~kris/9p

llm9p

ref: 0afa911aad2ddf1b824c5e829bd12541e622e09e llm9p/internal/llmfs/session_ask.go -rw-r--r-- 4.3 KiB
0afa911a — pdfinn 6 months ago
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>
a3dc06aa — pdfinn 7 months ago
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>
ed43a61b — pdfinn 7 months ago
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>
fa382007 — pdfinn 7 months ago
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>
054039ea — pdfinn 7 months ago
feat: Add CLI backend for Claude Max subscription

Add support for using Claude Code CLI as an alternative backend,
allowing users with Claude Max subscriptions to use llm9p without
API tokens.

New files:
- internal/llm/backend.go: Backend interface for swappable LLM providers
- internal/llm/cli_client.go: CLI-based client using `claude` command

Changes:
- Add -backend flag: 'api' (default) or 'cli'
- Refactor llmfs to use Backend interface instead of concrete Client
- Model names normalized for CLI (opus, sonnet, haiku)

Usage:
  ./llm9p -backend cli  # Uses Claude Max subscription
  ./llm9p -backend api  # Uses Anthropic API (default)

Limitations of CLI backend:
- Token counting not available (always 0)
- Streaming is simulated (full response as single chunk)
- Uses short model names (opus, sonnet, haiku)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
68199d2a — pdfinn 7 months ago
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>