Metadata-Version: 2.4
Name: llmsurgery
Version: 0.0.4
Summary: LLM Surgery
Author-email: Jeremy Howard <info@fast.ai>
License: Apache-2.0
Project-URL: Repository, https://github.com/AnswerDotAI/llmsurgery
Project-URL: Documentation, https://AnswerDotAI.github.io/llmsurgery/
Keywords: nbdev
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: nbformat
Requires-Dist: fastcore>=2.1.3
Requires-Dist: python-fastllm>=0.0.28
Requires-Dist: json5
Requires-Dist: claude-agent-sdk
Provides-Extra: dev
Requires-Dist: exhash; extra == "dev"
Dynamic: license-file

# llmsurgery


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

## Install

``` sh
pip install llmsurgery
```

## What’s here

Dialogs are LLM conversations kept as Jupyter notebooks: notes, runnable code with outputs, and prompt/reply pairs in one editable, diffable document. This library is the data model and surgery toolkit for them, consisting of:

- `llmsurgery.dialog`: [`Message`](https://AnswerDotAI.github.io/llmsurgery/dialog.html#message), [`Dialog`](https://AnswerDotAI.github.io/llmsurgery/dialog.html#dialog), and [`Attachment`](https://AnswerDotAI.github.io/llmsurgery/dialog.html#attachment) — a message carries exactly what the ipynb spec provides (content, output, type, id, attachments) plus a verbatim metadata dict, so host annotations round-trip untouched; hosts declare their own fields via `meta_attrs` and inject their subclasses through `msg_cls` and `read_ipynb(cls=)`.
- `llmsurgery.ipynb`: reading and writing dialogs as `.ipynb` files.
- `llmsurgery.hist`: converting dialogs to LLM chat history, including recovering tool calls from replies as structured messages. Rendering defaults are deliberately unopinionated (bare prompts, pass-through media, verbatim latex); hosts install their policies as class members (`prompt_txt`, `prep_img`, `media_extra`, `ai_renderers`, `UNSUPPORTED_MSG`).
- `llmsurgery.ant`: Claude Code session transcripts: read, write, search, curate, and build them from dialogs, so `claude --resume` opens an authored conversation.
- `llmsurgery.oai`: Codex threads: drive `codex app-server` to inject authored histories, ready for `codex resume`.

## The theory

A dialog is a conversation between a human, an AI, and an interpreter. Each message type addresses one of them and expects a certain kind of answer:

- A **prompt** asks the AI a question and holds its reply.
- A **code** message gives the interpreter source and holds its outputs.
- A **note** is read by everyone and answered by nobody.
- A **raw** message addresses no one. It is inert matter the conversation carries along.

A reply may itself contain runnable code with results, so a whole dialog can live inside one message. [`reply2dlg`](https://AnswerDotAI.github.io/llmsurgery/hist.html#reply2dlg) opens a reply up as a dialog and [`dlg2reply`](https://AnswerDotAI.github.io/llmsurgery/hist.html#dlg2reply) puts it back.

Dialogs and Jupyter notebooks both serialize to the ipynb format, but they are not the same thing. A notebook has cells. A dialog has messages. Messages can be *prompts*, which notebooks cannot express, and they make structure explicit that notebooks leave implicit. E.g a heading opens a section that runs to the next heading of the same level; an export directive marks the code that belongs to a module. The shared file format means the same tools read both. The word tells you which layer you are on. File-level tools such as `fastcore.nbio` and `exhash` speak of cells and notebooks. Everything in this library speaks of messages and dialogs.

The [`Dialog`](https://AnswerDotAI.github.io/llmsurgery/dialog.html#dialog) is the center of the library. Everything else is a projection of it. A storage projection must preserve everything that means something. What it does not understand it carries verbatim in metadata, and what is broken it heals rather than rejects. A transmission projection normalizes on purpose, and what it drops is written into its contract. A display projection only goes one way. The rule is to convert in, edit at the center, and project out. The function names say the same thing. Every converter has `dlg` on exactly one side.

| projection | contract | in | out |
|----|----|----|----|
| ipynb file | storage, pragmatically lossless | [`read_ipynb`](https://AnswerDotAI.github.io/llmsurgery/ipynb.html#read_ipynb) | [`write_ipynb`](https://AnswerDotAI.github.io/llmsurgery/ipynb.html#write_ipynb) |
| Claude Code session | storage | [`sess2dlg`](https://AnswerDotAI.github.io/llmsurgery/ant.html#sess2dlg) | [`dlg2sess`](https://AnswerDotAI.github.io/llmsurgery/ant.html#dlg2sess) |
| Codex thread | storage (write-only so far) |  | [`dlg2thread`](https://AnswerDotAI.github.io/llmsurgery/oai.html#dlg2thread) |
| fastllm chat (`Msg`/`Part`) | transmission, normalizing | [`chat2dlg`](https://AnswerDotAI.github.io/llmsurgery/ant.html#chat2dlg) | [`dlg2chat`](https://AnswerDotAI.github.io/llmsurgery/hist.html#dlg2chat) |
| fastllm hist (live call input) | transmission, one-way |  | [`dlg2hist`](https://AnswerDotAI.github.io/llmsurgery/hist.html#dlg2hist) |
| a prompt’s reply | self-similar | [`reply2dlg`](https://AnswerDotAI.github.io/llmsurgery/hist.html#reply2dlg) | [`dlg2reply`](https://AnswerDotAI.github.io/llmsurgery/hist.html#dlg2reply) |
| XML views | display, one-way |  | [`view_dlg`](https://AnswerDotAI.github.io/llmsurgery/dlgskill.html#view_dlg), [`msg2xml`](https://AnswerDotAI.github.io/llmsurgery/dlgskill.html#msg2xml) |

The session codecs route through chat on their way to the wire: ant’s [`dlg2msgs`](https://AnswerDotAI.github.io/llmsurgery/ant.html#dlg2msgs) and oai’s [`dlg2items`](https://AnswerDotAI.github.io/llmsurgery/oai.html#dlg2items) are each `denorm_msgs(dlg2chat(...))`.
