LOGS_SQL and LOGS_SQL_SEARCH left join the calls table on responses.id
(they share ids by construction). --json output now includes
head_input_message_id and head_output_message_id.
Rows that predate the DAG schema — or historical fixtures that only
wrote to responses — get NULL for those columns, so existing tests
are unaffected. Two new tests cover both cases: real prompt round-trip
(fields populated) and legacy-shape rows (fields NULL).
This is the minimum hook from the Deferred list in plans/dag-schema.md.
Union-read (prefer calls over responses, reconstruct prompt/response
from the DAG) is still deferred — a follow-up once there are calls
rows without matching responses rows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- MessageStore.fork(source_message_id, name=, model=) creates a new
conversation rooted at an existing message. The shared prefix is
reused in place; only one conversations row is written.
- Model defaults to whatever most recently wrote a call touching the
source message; can be overridden. Raises ValueError if the message
doesn't exist or no model can be inferred.
- New `llm fork <message_id>` CLI prints the new conversation id.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Accept messages= alongside the existing parts= parameter.
Conversation/AsyncConversation/Model/AsyncModel prompt() forward it to
Prompt, which stores it as prompt.messages.
OpenAI adapter gains _append_message_from_message which translates one
llm.Message into the correct OpenAI message dict(s), including the
parallel-tool-calls case (one assistant message with multiple
ToolCallParts becomes one OpenAI message with a tool_calls array).
Legacy paths untouched: parts=, prompt=, system=, attachments=, and
tool_results= still work when messages= is not set.
display_stream_events() helper handles writing text to stdout and
reasoning to stderr with proper newlines at each reasoning-to-text
transition. Used by sync prompt and chat streaming loops. Async prompt
loop has the same logic inline.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Streaming loops in prompt and chat commands now use stream_events()
instead of __iter__. Reasoning events are displayed on stderr in
dim text. Text events go to stdout as before.
New flags:
-R / --no-reasoning Suppress reasoning output on stderr
-S / --no-stream (shortcut for existing --no-stream)
-L (shortcut for existing -n/--no-log)
ChainResponse.stream_events() and AsyncChainResponse.astream_events()
added so tool-calling flows also surface reasoning events.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Closes#1014
- llm.ToolOutput(output='...', attachments=[...]) for tools to return attachments
- New table: `tool_results_attachments`
- Table is populated when tools return attachments
- llm --tools-debug shows attachments returned by tools
- llm logs shows attachments returned by tools
* add vscode and uv artifacts to gitignore
* !fragment feature
* Update fragment command to accept multiple fragments
* Add support for multiple fragments in !fragment command, factor out fragment processing
* Add support for fragment/system fragment arguments in chat command
* update docs
---------
Co-authored-by: Simon Willison <swillison@gmail.com>