@justin06lee/yagami 0.6.1 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,7 +32,7 @@ yagami start # first run generates + saves an API key and prints it
32
32
  `make update` stops any running yagami server, rebuilds, reinstalls, and restarts it. Or install from npm: `bun add -g @justin06lee/yagami`.
33
33
 
34
34
  ```
35
- yagami v0.5.0
35
+ yagami v0.7.0
36
36
  listening http://127.0.0.1:8787
37
37
  provider claude — /Users/you/.local/bin/claude (2.1.238 (Claude Code))
38
38
  also codex, opencode (use model "<provider>:<model>")
@@ -74,6 +74,20 @@ curl http://127.0.0.1:8787/v1/chat/completions \
74
74
  -d '{"model":"codex","messages":[{"role":"user","content":"ping"}]}'
75
75
  ```
76
76
 
77
+ ### Web search and fetch
78
+
79
+ `/v1/messages` accepts Anthropic's **server tools**, so a client can ask the engine to go look something up before it answers:
80
+
81
+ ```sh
82
+ curl http://127.0.0.1:8787/v1/messages \
83
+ -H "x-api-key: ygm_..." -H "content-type: application/json" \
84
+ -d '{"model":"sonnet","max_tokens":600,
85
+ "tools":[{"type":"web_search_20260209","name":"web_search"}],
86
+ "messages":[{"role":"user","content":"What is the current stable Rust version?"}]}'
87
+ ```
88
+
89
+ Server tools run *inside* the engine — they map onto the CLI's own `WebSearch` and `WebFetch`, and the results are folded into the reply. Nothing changes about the endpoint's contract: it still never emits a `tool_use` block for you to execute. Every dated variant of a type works (`web_search_20250305`, `web_search_20260209`, …), `tool_choice` may be `auto` or `none`, and any other tool in the array is rejected — a custom tool would have to run on your side, and there is no round trip here to run it on. Only the claude provider serves them; asking codex or an ACP agent for them fails loudly rather than quietly answering without the lookup.
90
+
77
91
  One caveat for OpenAI-dialect apps: the `model` field still routes through yagami's providers — set it to a model your CLIs actually serve (`sonnet`, `codex:gpt-5.6-sol`, `opencode:…`), not whatever `gpt-*` id the app defaults to.
78
92
 
79
93
  ## Library mode
@@ -112,7 +126,7 @@ Every provider implements one small `Provider` contract (`run(turn)` → normali
112
126
 
113
127
  ### Building a UI on Claude Code
114
128
 
115
- `Yagami`/`YagamiEngine` are completions-only by design. To build an actual coding UI — tools, permissions, plan mode, a warm session across turns — use `AgentSession`, which wraps the full Claude Code agent with the lifecycle the interactive terminal gives you for free:
129
+ `Yagami`/`YagamiEngine` are completions-only by design (server tools aside, they never hand you a tool call to run). To build an actual coding UI — tools, permissions, plan mode, a warm session across turns — use `AgentSession`, which wraps the full Claude Code agent with the lifecycle the interactive terminal gives you for free:
116
130
 
117
131
  ```ts
118
132
  import { AgentSession } from "@justin06lee/yagami";
@@ -161,10 +175,16 @@ if (isSessionProvider(codex)) {
161
175
  permissions: {
162
176
  decide: async (req) => (await showDialog(req.tool, req.input)) ? "allow" : "deny",
163
177
  }, // "allow_always" answers like the TUI's "don't ask again"
178
+ input: {
179
+ // Codex request_user_input and MCP/ACP form or URL elicitations all
180
+ // arrive in this provider-neutral shape. Throwing safely cancels it.
181
+ respond: async (request) => renderInput(request),
182
+ },
164
183
  });
165
184
  for await (const ev of session.send("fix the failing test")) {
166
- // normalized AgentEvents: text / thinking / tool_call (started→completed,
167
- // with inputs and outputs) / permission / done (usage, stop reason)
185
+ // normalized AgentEvents: session / turn / text / thinking / tool_call
186
+ // (started→completed, including Codex multi-agent operations) / permission
187
+ // / plan / done
168
188
  }
169
189
  session.send("now add a test"); // same warm thread, context carries
170
190
  await session.interrupt();
@@ -172,7 +192,7 @@ if (isSessionProvider(codex)) {
172
192
  }
173
193
  ```
174
194
 
175
- `ProviderSessionOptions` takes `cwd`, `model`, `resume`, `effort`, `systemPrompt` (extra developer instructions where the harness supports them), and a `native` escape hatch (Codex: `{ sandbox, approvalPolicy, config }`; ACP: `{ mode }`). The completion-turn `run()` path stays for API-style callers; sessions are for hosts that want the real interactive agent.
195
+ `ProviderSessionOptions` takes `cwd`, `model`, `resume`, `effort`, `systemPrompt` (extra developer instructions where the harness supports them), `permissions`, optional `input`, and a `native` escape hatch (Codex: `{ sandbox, approvalPolicy, config }`; ACP: `{ mode }`). A session provider reports `sessionCapabilities.fork`; when true, `{ resume, fork: true }` branches at the tip and `{ resume, forkAt: turnId }` branches through an exact `turn` event without mutating the source conversation. Input fields preserve labels, options, required/secret flags, primitive constraints, and URLs; omitting the handler declines safely instead of hanging a turn. ACP sessions also map `effort` onto the agent's `thought_level` option when it exposes one. The completion-turn `run()` path stays for API-style callers; sessions are for hosts that want the real interactive agent.
176
196
 
177
197
  The server is also embeddable: `import { startYagami } from "@justin06lee/yagami/server"`.
178
198
 
@@ -184,7 +204,7 @@ A bare model id goes to the **default provider** (Claude Code unless you change
184
204
  |---|---|---|---|---|---|
185
205
  | `claude` — Claude Code | Agent SDK → your `claude` binary | yes, forking | yes (+ documents) | native | native |
186
206
  | `codex` — Codex CLI | `codex exec --json` (read-only sandbox) | yes | yes | emulated | effort only |
187
- | `opencode`, `gemini`, `copilot`, `cursor`, `qwen`, `goose`, `kimi`, `kilo`, `cline`, `auggie`, `amp`, `grok`, `droid`, `codex-acp`, `claude-acp` | Agent Client Protocol over stdio | if the agent supports it | if the agent supports it | emulated | |
207
+ | `opencode`, `gemini`, `copilot`, `cursor`, `qwen`, `goose`, `kimi`, `kilo`, `cline`, `auggie`, `amp`, `grok`, `droid`, `codex-acp`, `claude-acp` | Agent Client Protocol over stdio | if the agent supports it | if the agent supports it | emulated | `thought_level` when exposed |
188
208
 
189
209
  "Emulated" means the system prompt is folded into the user turn as a `<system>` block; unsupported `thinking`/`effort` are accepted and reported in `x-yagami-ignored` rather than rejected. Without native forking, a resumed session is single-use: a sibling branch of the same conversation falls back to transcript replay instead of corrupting the shared session.
190
210
 
@@ -242,7 +262,7 @@ Env overrides: `YAGAMI_HOST`, `YAGAMI_PORT`, `YAGAMI_API_KEY`, `YAGAMI_PROVIDER`
242
262
  - **Dialects**: `POST /v1/messages` is native. `POST /v1/chat/completions` translates OpenAI shapes at the edge — system/developer messages fold into `system`, `image_url` parts become image blocks, streams are re-emitted as `chat.completion.chunk` events ending in `[DONE]`, and thinking output rides along as `reasoning_content`. Errors on that path come back OpenAI-shaped too. `GET /v1/models` serves one merged shape both SDKs parse.
243
263
  - **Multi-turn**: the Messages API is stateless but harness sessions aren't. yagami hashes each conversation prefix (per provider) and remembers which session produced it; a follow-up request resumes that session and sends only the new user message. Unmatched histories fall back to replaying the transcript in a single prompt, and if a cached session turns out to be gone, the stale mapping is dropped and the request transparently retries via replay. The cache persists across restarts at `~/.config/yagami/sessions.json`.
244
264
  - **Streaming**: every harness's output is normalized into deltas and re-emitted as a proper Anthropic SSE sequence — `message_start` → thinking/text content blocks → `message_delta` → `message_stop` (or the OpenAI chunk sequence on the chat-completions path). Claude and ACP agents stream tokens; Codex streams per message part.
245
- - **Models**: `GET /v1/models` asks each installed CLI what it supports (Claude via the SDK, Codex via its app-server protocol, ACP agents via their session config) — probed once per process, then cached. Failed probes are skipped and retried next time; a static fallback list is served only if nothing answers (`x-yagami-models-source` says which).
265
+ - **Models**: `GET /v1/models` asks each installed CLI what it supports (Claude via the SDK, Codex via its app-server protocol, ACP agents via their session config) — probed once per process, then cached. Library callers also receive native model metadata when reported: reasoning levels/default, input modalities, fast/auto/adaptive-thinking flags, personality and multi-agent support, service tiers, and the provider's default model. Failed probes are skipped and retried next time; a static fallback list is served only if nothing answers (`x-yagami-models-source` says which).
246
266
  - **Auth**: `x-api-key` or `Authorization: Bearer`, compared in constant time. Binds to `127.0.0.1` by default and warns loudly on anything else.
247
267
 
248
268
  Extra response headers: `x-yagami-provider`, `x-yagami-cost-usd` (what the turn would have cost at API prices, when the harness reports it), `x-yagami-session`, `x-yagami-ignored` (accepted-but-unsupported params). `/healthz` (unauthenticated) reports the default provider, installed providers, uptime, request count, and the cumulative would-be cost — `yagami status` shows the same.
@@ -264,3 +284,5 @@ bun run smoke # live end-to-end through your real Claude C
264
284
  bun run live:providers # live check across every installed harness (tiny token cost each)
265
285
  make build # build dist/ only
266
286
  ```
287
+
288
+ Codex sessions preserve proposed plan documents and stream reasoning summaries as they arrive, and completed items only fill missing text. A failed resume is reported as an error; it never silently opens an empty conversation. Only one send can run at a time, including during startup. Input and permission handlers receive an abort signal when the server resolves their request, their turn stops, or the session closes; hosts should dismiss the corresponding prompt. Close and reopen a failed session with its last ID to retry.
@@ -10,7 +10,7 @@ import {
10
10
  toApiError,
11
11
  toChatCompletion,
12
12
  yagamiConfigDir
13
- } from "./chunk-ZYHC7PXX.js";
13
+ } from "./chunk-U3RFT7QV.js";
14
14
 
15
15
  // src/server.ts
16
16
  import { serve } from "@hono/node-server";
@@ -374,4 +374,4 @@ export {
374
374
  maskKey,
375
375
  startYagami
376
376
  };
377
- //# sourceMappingURL=chunk-D2PNH6GV.js.map
377
+ //# sourceMappingURL=chunk-4S5QNDQK.js.map