feat(llmfs): native Anthropic tool_use protocol support
Add structured tool_use protocol to llm9p, enabling Veltro to use
Claude's native JSON tool invocation instead of text-based parsing.
New types (backend.go):
- AskResponse: carries Response, StructuredJSON, and Tokens — replaces
the old (string, int, error) return from AskWithRequest
- ToolDef: tool definition passed to Anthropic tools API
- ToolResult: tool execution result for submission to the LLM
- Backend.AskWithRequest() now returns (AskResponse, error)
client.go:
- Message.StructuredContent: stores JSON content blocks for correct
history replay of tool_use and tool_result turns
- AskWithRequest(): when ToolDefs non-nil, passes tools to API and
returns STOP:/TOOL: formatted response for Limbo parsing
Format: "STOP:tool_use\nTOOL:<id>:<name>:<args>\n<text>" or
"STOP:end_turn\n<text>" or plain text (no tools)
- AskWithToolResults(): submits tool results as a new user turn
- Helpers: buildMessageParam(), buildToolParams(), extractToolArgs(),
jsonEscapeString()
session.go:
- Session.tools field + SetTools/Tools methods
- Session.AddStructuredMessage() for storing structured content blocks
- AskRequest extended with ToolDefs and ToolResults fields
- SessionManager.Ask(): includes tools, stores structured JSON in history
- SessionManager.AskWithToolResults(): new method for tool result turns
- Fix Compact() for new AskResponse return type
- Helpers: extractTextContent(), buildToolResultsJSON()
cli_client.go: update AskWithRequest() to return AskResponse (no tools
support; StructuredJSON always empty)
session_tools.go (new): /n/llm/{id}/tools write-only file
- Write JSON array of ToolDef to enable native tool_use protocol
- Empty write clears tools (returns session to text-only mode)
session_ask.go:
- Detect TOOL_RESULTS\n prefix in Write() → parseToolResults() → AskWithToolResults()
- TOOL_RESULTS format: "TOOL_RESULTS\n<id>\n<content>\n---\n..."
session_dir.go: add tools file to Children() and Lookup()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(llm9p): Implement clone-based session architecture
Replace per-fid session model with Plan 9 clone pattern:
- Reading /n/llm/new creates a session and returns its ID
- Each session gets its own directory: /n/llm/<id>/
- Per-session files: ask, ctl, model, system, thinking, context, metrics
- AskWithRequest method for stateless CSP-style LLM calls
- Session settings (model, temperature, thinking) are per-session
- Remove old ask.go, context.go in favor of session-scoped files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat(llm9p): Add per-fid session isolation and prefill support
- Add SessionManager for per-fid conversation isolation
- Each 9P fid now gets its own conversation history
- Add FidAwareFile interface for files needing fid context
- Add /n/llm/prefill file for assistant response prefill
- Prefill helps keep model in character (e.g., "[Veltro]")
- Update ask, new, context files to use session manager
- Fix context contamination between parent and subagent
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat(llm): Add extended thinking support and usage tracking
- Add thinking token control via /n/llm/thinking file (max/off/number)
- CLI backend sets MAX_THINKING_TOKENS env var for Claude CLI
- Default to max thinking (31999 tokens) for CLI backend
- Add /n/llm/usage file for token usage monitoring
- Add /n/llm/compact file for conversation summarization
- Extend Backend interface with ThinkingTokens, TotalTokens, ContextLimit, Compact
- Add true streaming support for CLI backend with line-by-line output
- Update example file with thinking documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat: Add system prompt file for persistent persona configuration
- Add system file (read/write) to set system prompt
- System prompt persists across conversation resets
- Add SystemPrompt() and SetSystemPrompt() to Backend interface
- Update both API and CLI clients to support dedicated system prompt
- Update documentation and examples
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat: Initial implementation of llm9p - LLM as 9P filesystem
Exposes Claude as a 9P filesystem, enabling interaction through
standard file operations:
- ask: write prompt, read response (shim pattern)
- model: read/write current model name
- temperature: read/write sampling temperature
- tokens: read-only token count from last response
- new: write to reset conversation
- context: read JSON history, write to add system message
- _example: usage documentation
- stream/chunk: blocking read for streaming responses
Includes:
- Full 9P2000 protocol implementation (stdlib only)
- Anthropic SDK integration with conversation state
- Streaming support
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>