@justin06lee/yagami 0.4.1 → 0.6.0

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/dist/cli.js CHANGED
@@ -13,13 +13,13 @@ import {
13
13
  sessionCachePath,
14
14
  startYagami,
15
15
  writeServerState
16
- } from "./chunk-M5UHR273.js";
16
+ } from "./chunk-D2PNH6GV.js";
17
17
  import {
18
18
  VERSION,
19
19
  YagamiEngine,
20
20
  createProvider,
21
21
  detectProviders
22
- } from "./chunk-ASS6MJ7C.js";
22
+ } from "./chunk-ZYHC7PXX.js";
23
23
 
24
24
  // src/cli.ts
25
25
  import { spawn } from "child_process";
@@ -28,7 +28,7 @@ import * as path from "path";
28
28
  import { Command } from "commander";
29
29
  var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
30
30
  var program = new Command();
31
- program.name("yagami").description("Anthropic-compatible API served by your signed-in Claude Code CLI").version(VERSION);
31
+ program.name("yagami").description("Anthropic- and OpenAI-compatible API served by your signed-in coding-agent CLIs").version(VERSION);
32
32
  program.command("start", { isDefault: true }).description("start the yagami server").option("-p, --port <port>", "port to listen on").option("-H, --host <host>", "host to bind (default 127.0.0.1)").option("--claude <path>", "path to the claude executable").option("--provider <id>", "default provider for bare model ids (claude, codex, opencode, gemini, \u2026)").option("--cors", "enable permissive CORS (for browser clients)").option("--daemon", "run in the background (managed with `yagami stop`/`yagami status`)").option("--log <file>", "log file for --daemon mode (default ~/.config/yagami/yagami.log)").action(async (opts) => {
33
33
  const fileConfig = loadFileConfig();
34
34
  let freshKey;
@@ -78,17 +78,18 @@ program.command("start", { isDefault: true }).description("start the yagami serv
78
78
  console.log(` config ${configFilePath()}`);
79
79
  if (freshKey) {
80
80
  console.log(` api key ${freshKey}`);
81
- console.log(" (newly generated and saved \u2014 copy it now, it is shown in full only once)");
81
+ console.log(" (newly generated and saved \u2014 `yagami key` prints it again)");
82
82
  } else {
83
- console.log(` api keys ${running.config.apiKeys.map(maskKey).join(", ")}`);
83
+ console.log(` api keys ${running.config.apiKeys.map(maskKey).join(", ")} (\`yagami key\` prints them in full)`);
84
84
  }
85
85
  if (!["127.0.0.1", "localhost", "::1"].includes(running.config.host)) {
86
86
  console.log(
87
87
  ` \u26A0 bound to ${running.config.host} \u2014 reachable beyond this machine. Only do this on a network you trust.`
88
88
  );
89
89
  }
90
- console.log("\nPoint any Anthropic SDK at it:");
91
- console.log(` baseURL: "${running.url}" apiKey: <your yagami key>`);
90
+ console.log("\nConnect apps \u2014 either dialect, same key (`yagami key` prints ready-to-paste env exports):");
91
+ console.log(` Anthropic apps baseURL ${running.url} (ANTHROPIC_BASE_URL / ANTHROPIC_API_KEY)`);
92
+ console.log(` OpenAI apps baseURL ${running.url}/v1 (OPENAI_BASE_URL / OPENAI_API_KEY)`);
92
93
  } catch (err) {
93
94
  console.error(`yagami: ${err instanceof Error ? err.message : String(err)}`);
94
95
  process.exitCode = 1;
@@ -132,8 +133,9 @@ async function startDaemon(opts, freshKey) {
132
133
  console.log(` log ${logPath}`);
133
134
  if (freshKey) {
134
135
  console.log(` key ${freshKey}`);
135
- console.log(" (newly generated and saved \u2014 copy it now, it is shown in full only once)");
136
+ console.log(" (newly generated and saved \u2014 `yagami key` prints it again)");
136
137
  }
138
+ console.log(" `yagami key` prints the URL, key, and env exports for client apps");
137
139
  return;
138
140
  }
139
141
  await sleep(200);
@@ -194,6 +196,29 @@ program.command("keygen").description("generate an API key and add it to the con
194
196
  console.log(key);
195
197
  console.error(`saved to ${file} (${cfg.apiKeys.length} key${cfg.apiKeys.length === 1 ? "" : "s"} total)`);
196
198
  });
199
+ program.command("key").description("print the server URL, API key, and ready-to-paste env exports for client apps").action(() => {
200
+ const cfg = loadConfig();
201
+ const state = readServerState();
202
+ const live = state !== void 0 && isProcessAlive(state.pid);
203
+ const url = live ? state.url : `http://${cfg.host}:${cfg.port}`;
204
+ if (cfg.apiKeys.length === 0) {
205
+ console.error("no API keys configured \u2014 run `yagami start` (generates one) or `yagami keygen`");
206
+ process.exitCode = 1;
207
+ return;
208
+ }
209
+ const key = cfg.apiKeys[cfg.apiKeys.length - 1];
210
+ console.log(`url ${url}${live ? "" : " (server not running \u2014 this is where `yagami start` will listen)"}`);
211
+ console.log(`key ${key}`);
212
+ if (cfg.apiKeys.length > 1) {
213
+ console.log(` (newest of ${cfg.apiKeys.length} keys in ${configFilePath()})`);
214
+ }
215
+ console.log("\nAnthropic-dialect apps:");
216
+ console.log(` export ANTHROPIC_BASE_URL=${url}`);
217
+ console.log(` export ANTHROPIC_API_KEY=${key}`);
218
+ console.log("\nOpenAI-dialect apps:");
219
+ console.log(` export OPENAI_BASE_URL=${url}/v1`);
220
+ console.log(` export OPENAI_API_KEY=${key}`);
221
+ });
197
222
  program.command("doctor").description("check which coding-agent CLIs yagami can drive and whether they work").option("--live", "send one real (tiny) completion through the default provider").option("--provider <id>", "provider to use for --live (default: config/claude)").action(async (opts) => {
198
223
  let failed = false;
199
224
  const cfg = loadConfig();
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { spawn, spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { Command } from \"commander\";\nimport { YagamiEngine } from \"./core/engine.js\";\nimport { ClaudeProvider } from \"./core/providers/claude.js\";\nimport { createProvider, detectProviders } from \"./core/providers/registry.js\";\nimport { startYagami } from \"./server.js\";\nimport {\n clearServerState,\n configFilePath,\n generateApiKey,\n isProcessAlive,\n loadConfig,\n loadFileConfig,\n logFilePath,\n maskKey,\n readServerState,\n saveConfig,\n sessionCachePath,\n writeServerState,\n} from \"./server/config.js\";\nimport { VERSION } from \"./version.js\";\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst program = new Command();\n\nprogram\n .name(\"yagami\")\n .description(\"Anthropic-compatible API served by your signed-in Claude Code CLI\")\n .version(VERSION);\n\ninterface StartFlags {\n port?: string;\n host?: string;\n claude?: string;\n provider?: string;\n cors?: boolean;\n daemon?: boolean;\n log?: string;\n}\n\nprogram\n .command(\"start\", { isDefault: true })\n .description(\"start the yagami server\")\n .option(\"-p, --port <port>\", \"port to listen on\")\n .option(\"-H, --host <host>\", \"host to bind (default 127.0.0.1)\")\n .option(\"--claude <path>\", \"path to the claude executable\")\n .option(\"--provider <id>\", \"default provider for bare model ids (claude, codex, opencode, gemini, …)\")\n .option(\"--cors\", \"enable permissive CORS (for browser clients)\")\n .option(\"--daemon\", \"run in the background (managed with `yagami stop`/`yagami status`)\")\n .option(\"--log <file>\", \"log file for --daemon mode (default ~/.config/yagami/yagami.log)\")\n .action(async (opts: StartFlags) => {\n // First run: generate a key automatically so the endpoint is never open.\n const fileConfig = loadFileConfig();\n let freshKey: string | undefined;\n if (fileConfig.apiKeys.length === 0 && !process.env[\"YAGAMI_API_KEY\"]) {\n freshKey = generateApiKey();\n fileConfig.apiKeys.push(freshKey);\n saveConfig(fileConfig);\n }\n\n if (opts.daemon) {\n await startDaemon(opts, freshKey);\n return;\n }\n\n try {\n const running = await startYagami({\n port: opts.port !== undefined ? Number(opts.port) : undefined,\n host: opts.host,\n claudePath: opts.claude,\n defaultProvider: opts.provider,\n cors: opts.cors,\n });\n\n writeServerState({\n pid: process.pid,\n host: running.config.host,\n port: running.config.port,\n url: running.url,\n startedAt: new Date().toISOString(),\n version: VERSION,\n ...(process.env[\"YAGAMI_LOG_FILE\"] ? { log: process.env[\"YAGAMI_LOG_FILE\"] } : {}),\n });\n const shutdown = () => {\n running.sessionCache.persistNow();\n clearServerState(process.pid);\n void running.close().finally(() => process.exit(0));\n // Don't hang on a stuck in-flight response.\n setTimeout(() => process.exit(0), 3000).unref?.();\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n const engine = running.engine;\n const version = await engine.defaultProvider.version();\n const others = engine.providerIds.filter((id) => id !== engine.defaultProviderId);\n console.log(`yagami v${VERSION}`);\n console.log(` listening ${running.url}`);\n console.log(` provider ${engine.defaultProviderId} — ${engine.executable}${version ? ` (${version})` : \"\"}`);\n console.log(\n ` also ${others.length > 0 ? `${others.join(\", \")} (use model \"<provider>:<model>\")` : \"no other harness CLIs found — see `yagami doctor`\"}`,\n );\n console.log(` config ${configFilePath()}`);\n if (freshKey) {\n console.log(` api key ${freshKey}`);\n console.log(\" (newly generated and saved — copy it now, it is shown in full only once)\");\n } else {\n console.log(` api keys ${running.config.apiKeys.map(maskKey).join(\", \")}`);\n }\n if (![\"127.0.0.1\", \"localhost\", \"::1\"].includes(running.config.host)) {\n console.log(\n ` ⚠ bound to ${running.config.host} — reachable beyond this machine. Only do this on a network you trust.`,\n );\n }\n console.log(\"\\nPoint any Anthropic SDK at it:\");\n console.log(` baseURL: \"${running.url}\" apiKey: <your yagami key>`);\n } catch (err) {\n console.error(`yagami: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n }\n });\n\nasync function startDaemon(opts: StartFlags, freshKey: string | undefined): Promise<void> {\n const existing = readServerState();\n if (existing && isProcessAlive(existing.pid)) {\n console.error(`yagami is already running (pid ${existing.pid}, ${existing.url}) — \\`yagami stop\\` first`);\n process.exitCode = 1;\n return;\n }\n clearServerState();\n\n const logPath = opts.log ? path.resolve(opts.log) : logFilePath();\n fs.mkdirSync(path.dirname(logPath), { recursive: true });\n const fd = fs.openSync(logPath, \"a\");\n const args = [process.argv[1]!, \"start\"];\n if (opts.port !== undefined) args.push(\"-p\", opts.port);\n if (opts.host !== undefined) args.push(\"-H\", opts.host);\n if (opts.claude !== undefined) args.push(\"--claude\", opts.claude);\n if (opts.provider !== undefined) args.push(\"--provider\", opts.provider);\n if (opts.cors) args.push(\"--cors\");\n\n const child = spawn(process.execPath, args, {\n detached: true,\n stdio: [\"ignore\", fd, fd],\n env: { ...process.env, YAGAMI_LOG_FILE: logPath },\n });\n fs.closeSync(fd);\n let exitCode: number | null | undefined;\n child.on(\"exit\", (code) => {\n exitCode = code;\n });\n child.unref();\n\n const deadline = Date.now() + 15_000;\n while (Date.now() < deadline && exitCode === undefined) {\n const state = readServerState();\n if (state && state.pid === child.pid) {\n console.log(`yagami v${VERSION} running in the background`);\n console.log(` pid ${child.pid}`);\n console.log(` url ${state.url}`);\n console.log(` log ${logPath}`);\n if (freshKey) {\n console.log(` key ${freshKey}`);\n console.log(\" (newly generated and saved — copy it now, it is shown in full only once)\");\n }\n return;\n }\n await sleep(200);\n }\n console.error(\n exitCode !== undefined\n ? `yagami exited immediately (code ${exitCode}) — see ${logPath}`\n : `yagami did not report ready within 15s — see ${logPath}`,\n );\n process.exitCode = 1;\n}\n\nprogram\n .command(\"stop\")\n .description(\"stop a running yagami server\")\n .action(async () => {\n const state = readServerState();\n if (!state || !isProcessAlive(state.pid)) {\n if (state) clearServerState();\n console.log(\"yagami is not running\");\n return;\n }\n process.kill(state.pid, \"SIGTERM\");\n const deadline = Date.now() + 5_000;\n while (Date.now() < deadline) {\n if (!isProcessAlive(state.pid)) {\n clearServerState();\n console.log(`stopped yagami (pid ${state.pid})`);\n return;\n }\n await sleep(100);\n }\n console.error(`yagami (pid ${state.pid}) did not exit within 5s`);\n process.exitCode = 1;\n });\n\nprogram\n .command(\"status\")\n .description(\"show whether yagami is running, plus request/cost totals\")\n .action(async () => {\n const state = readServerState();\n if (!state || !isProcessAlive(state.pid)) {\n if (state) clearServerState();\n console.log(\"yagami is not running\");\n process.exitCode = 1;\n return;\n }\n console.log(`yagami running (pid ${state.pid})`);\n console.log(` url ${state.url}`);\n console.log(` since ${state.startedAt}`);\n if (state.log) console.log(` log ${state.log}`);\n try {\n const res = await fetch(`${state.url}/healthz`, { signal: AbortSignal.timeout(3000) });\n const body = (await res.json()) as {\n version?: string;\n claude?: string;\n requests?: number;\n total_cost_usd?: number;\n };\n console.log(` version ${body.version ?? \"?\"}`);\n console.log(` claude ${body.claude ?? \"?\"}`);\n console.log(` requests ${body.requests ?? 0}`);\n console.log(` cost $${(body.total_cost_usd ?? 0).toFixed(4)} (would-be API cost since start)`);\n } catch {\n console.log(` healthz unreachable — process is alive but ${state.url} is not answering`);\n }\n });\n\nprogram\n .command(\"keygen\")\n .description(\"generate an API key and add it to the config\")\n .action(() => {\n const cfg = loadFileConfig();\n const key = generateApiKey();\n cfg.apiKeys.push(key);\n const file = saveConfig(cfg);\n console.log(key);\n console.error(`saved to ${file} (${cfg.apiKeys.length} key${cfg.apiKeys.length === 1 ? \"\" : \"s\"} total)`);\n });\n\nprogram\n .command(\"doctor\")\n .description(\"check which coding-agent CLIs yagami can drive and whether they work\")\n .option(\"--live\", \"send one real (tiny) completion through the default provider\")\n .option(\"--provider <id>\", \"provider to use for --live (default: config/claude)\")\n .action(async (opts: { live?: boolean; provider?: string }) => {\n let failed = false;\n const cfg = loadConfig();\n const providerConfig = { ...cfg.providers };\n if (cfg.claudePath || cfg.claudeConfigDir) {\n providerConfig[\"claude\"] = {\n ...providerConfig[\"claude\"],\n ...(cfg.claudePath ? { path: cfg.claudePath } : {}),\n ...(cfg.claudeConfigDir ? { configDir: cfg.claudeConfigDir } : {}),\n };\n }\n const defaultProvider = opts.provider ?? cfg.defaultProvider ?? \"claude\";\n\n console.log(`node ${process.version}`);\n console.log(`config ${configFilePath()}${fs.existsSync(configFilePath()) ? \"\" : \" (not created yet)\"}`);\n console.log(`api keys ${cfg.apiKeys.length === 0 ? \"none — run `yagami keygen`\" : cfg.apiKeys.map(maskKey).join(\", \")}`);\n console.log(`bind ${cfg.host}:${cfg.port}`);\n console.log(`sessions ${sessionCachePath()}${fs.existsSync(sessionCachePath()) ? \"\" : \" (empty)\"}`);\n const state = readServerState();\n console.log(\n `server ${state && isProcessAlive(state.pid) ? `running (pid ${state.pid}, ${state.url})` : \"not running\"}`,\n );\n\n console.log(\"\\nproviders (model ids route as \\\"<provider>:<model>\\\"; bare ids go to the default)\");\n const detected = detectProviders(providerConfig);\n const installed = detected.filter((d) => d.installed);\n for (const d of detected) {\n const marker = d.id === defaultProvider ? \"*\" : \" \";\n if (!d.installed) {\n if (presetIsNiche(d.id)) continue; // keep the list readable\n console.log(` ${marker} ${d.id.padEnd(11)} not installed — ${d.installHint}`);\n continue;\n }\n let version: string | undefined;\n try {\n version = await createProvider(d.id, providerConfig[d.id] ?? {}, {}).version();\n } catch (err) {\n version = `✗ ${err instanceof Error ? err.message : String(err)}`;\n }\n console.log(` ${marker} ${d.id.padEnd(11)} ${d.path}${version ? ` (${version})` : \"\"}`);\n }\n const hidden = detected.filter((d) => !d.installed && presetIsNiche(d.id)).length;\n if (hidden > 0) console.log(` … ${hidden} more ACP presets not installed (see README for the full list)`);\n if (!installed.some((d) => d.id === defaultProvider)) {\n failed = true;\n console.log(` ✗ default provider \"${defaultProvider}\" is not installed`);\n }\n\n if (installed.some((d) => d.id === \"claude\")) {\n try {\n const claude = createProvider(\"claude\", providerConfig[\"claude\"] ?? {}, {}) as ClaudeProvider;\n const skew = await claude.versionSkew();\n if (skew) {\n console.log(`\\nagent sdk ${skew.sdkVersion} ↔ claude ${skew.binaryVersion} — ${skew.inSync ? \"in sync\" : `⚠ ${skew.note}`}`);\n }\n } catch {\n // skew check is advisory\n }\n }\n\n if (opts.live && !failed) {\n console.log(`\\nlive check: sending one tiny completion through ${defaultProvider}…`);\n try {\n const engine = new YagamiEngine({ providerConfig, defaultProvider, ...(cfg.defaultModel ? { defaultModel: cfg.defaultModel } : {}) });\n const started = Date.now();\n const result = await engine.complete({\n messages: [{ role: \"user\", content: \"Reply with exactly: pong\" }],\n max_tokens: 32,\n });\n const text = result.response.content\n .filter((b) => b.type === \"text\")\n .map((b) => b[\"text\"])\n .join(\"\");\n console.log(` reply ${JSON.stringify(text)}`);\n console.log(` model ${result.response.model}`);\n console.log(` latency ${((Date.now() - started) / 1000).toFixed(1)}s`);\n if (result.costUsd !== undefined) console.log(` cost $${result.costUsd.toFixed(6)}`);\n } catch (err) {\n failed = true;\n console.log(` ✗ ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n if (failed) process.exitCode = 1;\n });\n\n/** Presets most people won't have; hidden from doctor unless installed. */\nfunction presetIsNiche(id: string): boolean {\n return ![\"claude\", \"codex\", \"opencode\", \"gemini\", \"copilot\", \"cursor\", \"qwen\", \"goose\", \"kimi\"].includes(id);\n}\n\nprogram\n .command(\"models\")\n .description(\"list models across every installed provider (ids are ready to paste into requests)\")\n .option(\"--provider <id>\", \"only this provider\")\n .action(async (opts: { provider?: string }) => {\n const cfg = loadConfig();\n try {\n const engine = new YagamiEngine({\n ...(cfg.providers ? { providerConfig: cfg.providers } : {}),\n ...(cfg.defaultProvider ? { defaultProvider: cfg.defaultProvider } : {}),\n });\n const models = await engine.listModels();\n const byProvider = new Map<string, typeof models>();\n for (const m of models) {\n if (opts.provider && m.provider !== opts.provider) continue;\n if (!m.id.includes(\":\")) continue; // print the qualified form once\n const list = byProvider.get(m.provider ?? \"?\") ?? [];\n list.push(m);\n byProvider.set(m.provider ?? \"?\", list);\n }\n for (const [provider, list] of byProvider) {\n console.log(`${provider}${provider === engine.defaultProviderId ? \" (default — bare ids work too)\" : \"\"}`);\n for (const m of list) {\n console.log(` ${m.id.padEnd(40)} ${m.display_name}${m.resolved_model ? ` → ${m.resolved_model}` : \"\"}`);\n }\n }\n if (byProvider.size === 0) console.log(\"no models reported — run `yagami doctor`\");\n } catch (err) {\n console.error(`yagami: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n }\n });\n\nawait program.parseAsync(process.argv);\n"],"mappings":"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","names":["resolve"]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { spawn, spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { Command } from \"commander\";\nimport { YagamiEngine } from \"./core/engine.js\";\nimport { ClaudeProvider } from \"./core/providers/claude.js\";\nimport { createProvider, detectProviders } from \"./core/providers/registry.js\";\nimport { startYagami } from \"./server.js\";\nimport {\n clearServerState,\n configFilePath,\n generateApiKey,\n isProcessAlive,\n loadConfig,\n loadFileConfig,\n logFilePath,\n maskKey,\n readServerState,\n saveConfig,\n sessionCachePath,\n writeServerState,\n} from \"./server/config.js\";\nimport { VERSION } from \"./version.js\";\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst program = new Command();\n\nprogram\n .name(\"yagami\")\n .description(\"Anthropic- and OpenAI-compatible API served by your signed-in coding-agent CLIs\")\n .version(VERSION);\n\ninterface StartFlags {\n port?: string;\n host?: string;\n claude?: string;\n provider?: string;\n cors?: boolean;\n daemon?: boolean;\n log?: string;\n}\n\nprogram\n .command(\"start\", { isDefault: true })\n .description(\"start the yagami server\")\n .option(\"-p, --port <port>\", \"port to listen on\")\n .option(\"-H, --host <host>\", \"host to bind (default 127.0.0.1)\")\n .option(\"--claude <path>\", \"path to the claude executable\")\n .option(\"--provider <id>\", \"default provider for bare model ids (claude, codex, opencode, gemini, …)\")\n .option(\"--cors\", \"enable permissive CORS (for browser clients)\")\n .option(\"--daemon\", \"run in the background (managed with `yagami stop`/`yagami status`)\")\n .option(\"--log <file>\", \"log file for --daemon mode (default ~/.config/yagami/yagami.log)\")\n .action(async (opts: StartFlags) => {\n // First run: generate a key automatically so the endpoint is never open.\n const fileConfig = loadFileConfig();\n let freshKey: string | undefined;\n if (fileConfig.apiKeys.length === 0 && !process.env[\"YAGAMI_API_KEY\"]) {\n freshKey = generateApiKey();\n fileConfig.apiKeys.push(freshKey);\n saveConfig(fileConfig);\n }\n\n if (opts.daemon) {\n await startDaemon(opts, freshKey);\n return;\n }\n\n try {\n const running = await startYagami({\n port: opts.port !== undefined ? Number(opts.port) : undefined,\n host: opts.host,\n claudePath: opts.claude,\n defaultProvider: opts.provider,\n cors: opts.cors,\n });\n\n writeServerState({\n pid: process.pid,\n host: running.config.host,\n port: running.config.port,\n url: running.url,\n startedAt: new Date().toISOString(),\n version: VERSION,\n ...(process.env[\"YAGAMI_LOG_FILE\"] ? { log: process.env[\"YAGAMI_LOG_FILE\"] } : {}),\n });\n const shutdown = () => {\n running.sessionCache.persistNow();\n clearServerState(process.pid);\n void running.close().finally(() => process.exit(0));\n // Don't hang on a stuck in-flight response.\n setTimeout(() => process.exit(0), 3000).unref?.();\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n const engine = running.engine;\n const version = await engine.defaultProvider.version();\n const others = engine.providerIds.filter((id) => id !== engine.defaultProviderId);\n console.log(`yagami v${VERSION}`);\n console.log(` listening ${running.url}`);\n console.log(` provider ${engine.defaultProviderId} — ${engine.executable}${version ? ` (${version})` : \"\"}`);\n console.log(\n ` also ${others.length > 0 ? `${others.join(\", \")} (use model \"<provider>:<model>\")` : \"no other harness CLIs found — see `yagami doctor`\"}`,\n );\n console.log(` config ${configFilePath()}`);\n if (freshKey) {\n console.log(` api key ${freshKey}`);\n console.log(\" (newly generated and saved — `yagami key` prints it again)\");\n } else {\n console.log(` api keys ${running.config.apiKeys.map(maskKey).join(\", \")} (\\`yagami key\\` prints them in full)`);\n }\n if (![\"127.0.0.1\", \"localhost\", \"::1\"].includes(running.config.host)) {\n console.log(\n ` ⚠ bound to ${running.config.host} — reachable beyond this machine. Only do this on a network you trust.`,\n );\n }\n console.log(\"\\nConnect apps — either dialect, same key (`yagami key` prints ready-to-paste env exports):\");\n console.log(` Anthropic apps baseURL ${running.url} (ANTHROPIC_BASE_URL / ANTHROPIC_API_KEY)`);\n console.log(` OpenAI apps baseURL ${running.url}/v1 (OPENAI_BASE_URL / OPENAI_API_KEY)`);\n } catch (err) {\n console.error(`yagami: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n }\n });\n\nasync function startDaemon(opts: StartFlags, freshKey: string | undefined): Promise<void> {\n const existing = readServerState();\n if (existing && isProcessAlive(existing.pid)) {\n console.error(`yagami is already running (pid ${existing.pid}, ${existing.url}) — \\`yagami stop\\` first`);\n process.exitCode = 1;\n return;\n }\n clearServerState();\n\n const logPath = opts.log ? path.resolve(opts.log) : logFilePath();\n fs.mkdirSync(path.dirname(logPath), { recursive: true });\n const fd = fs.openSync(logPath, \"a\");\n const args = [process.argv[1]!, \"start\"];\n if (opts.port !== undefined) args.push(\"-p\", opts.port);\n if (opts.host !== undefined) args.push(\"-H\", opts.host);\n if (opts.claude !== undefined) args.push(\"--claude\", opts.claude);\n if (opts.provider !== undefined) args.push(\"--provider\", opts.provider);\n if (opts.cors) args.push(\"--cors\");\n\n const child = spawn(process.execPath, args, {\n detached: true,\n stdio: [\"ignore\", fd, fd],\n env: { ...process.env, YAGAMI_LOG_FILE: logPath },\n });\n fs.closeSync(fd);\n let exitCode: number | null | undefined;\n child.on(\"exit\", (code) => {\n exitCode = code;\n });\n child.unref();\n\n const deadline = Date.now() + 15_000;\n while (Date.now() < deadline && exitCode === undefined) {\n const state = readServerState();\n if (state && state.pid === child.pid) {\n console.log(`yagami v${VERSION} running in the background`);\n console.log(` pid ${child.pid}`);\n console.log(` url ${state.url}`);\n console.log(` log ${logPath}`);\n if (freshKey) {\n console.log(` key ${freshKey}`);\n console.log(\" (newly generated and saved — `yagami key` prints it again)\");\n }\n console.log(\" `yagami key` prints the URL, key, and env exports for client apps\");\n return;\n }\n await sleep(200);\n }\n console.error(\n exitCode !== undefined\n ? `yagami exited immediately (code ${exitCode}) — see ${logPath}`\n : `yagami did not report ready within 15s — see ${logPath}`,\n );\n process.exitCode = 1;\n}\n\nprogram\n .command(\"stop\")\n .description(\"stop a running yagami server\")\n .action(async () => {\n const state = readServerState();\n if (!state || !isProcessAlive(state.pid)) {\n if (state) clearServerState();\n console.log(\"yagami is not running\");\n return;\n }\n process.kill(state.pid, \"SIGTERM\");\n const deadline = Date.now() + 5_000;\n while (Date.now() < deadline) {\n if (!isProcessAlive(state.pid)) {\n clearServerState();\n console.log(`stopped yagami (pid ${state.pid})`);\n return;\n }\n await sleep(100);\n }\n console.error(`yagami (pid ${state.pid}) did not exit within 5s`);\n process.exitCode = 1;\n });\n\nprogram\n .command(\"status\")\n .description(\"show whether yagami is running, plus request/cost totals\")\n .action(async () => {\n const state = readServerState();\n if (!state || !isProcessAlive(state.pid)) {\n if (state) clearServerState();\n console.log(\"yagami is not running\");\n process.exitCode = 1;\n return;\n }\n console.log(`yagami running (pid ${state.pid})`);\n console.log(` url ${state.url}`);\n console.log(` since ${state.startedAt}`);\n if (state.log) console.log(` log ${state.log}`);\n try {\n const res = await fetch(`${state.url}/healthz`, { signal: AbortSignal.timeout(3000) });\n const body = (await res.json()) as {\n version?: string;\n claude?: string;\n requests?: number;\n total_cost_usd?: number;\n };\n console.log(` version ${body.version ?? \"?\"}`);\n console.log(` claude ${body.claude ?? \"?\"}`);\n console.log(` requests ${body.requests ?? 0}`);\n console.log(` cost $${(body.total_cost_usd ?? 0).toFixed(4)} (would-be API cost since start)`);\n } catch {\n console.log(` healthz unreachable — process is alive but ${state.url} is not answering`);\n }\n });\n\nprogram\n .command(\"keygen\")\n .description(\"generate an API key and add it to the config\")\n .action(() => {\n const cfg = loadFileConfig();\n const key = generateApiKey();\n cfg.apiKeys.push(key);\n const file = saveConfig(cfg);\n console.log(key);\n console.error(`saved to ${file} (${cfg.apiKeys.length} key${cfg.apiKeys.length === 1 ? \"\" : \"s\"} total)`);\n });\n\nprogram\n .command(\"key\")\n .description(\"print the server URL, API key, and ready-to-paste env exports for client apps\")\n .action(() => {\n const cfg = loadConfig();\n const state = readServerState();\n const live = state !== undefined && isProcessAlive(state.pid);\n const url = live ? state.url : `http://${cfg.host}:${cfg.port}`;\n if (cfg.apiKeys.length === 0) {\n console.error(\"no API keys configured — run `yagami start` (generates one) or `yagami keygen`\");\n process.exitCode = 1;\n return;\n }\n const key = cfg.apiKeys[cfg.apiKeys.length - 1]!;\n console.log(`url ${url}${live ? \"\" : \" (server not running — this is where `yagami start` will listen)\"}`);\n console.log(`key ${key}`);\n if (cfg.apiKeys.length > 1) {\n console.log(` (newest of ${cfg.apiKeys.length} keys in ${configFilePath()})`);\n }\n console.log(\"\\nAnthropic-dialect apps:\");\n console.log(` export ANTHROPIC_BASE_URL=${url}`);\n console.log(` export ANTHROPIC_API_KEY=${key}`);\n console.log(\"\\nOpenAI-dialect apps:\");\n console.log(` export OPENAI_BASE_URL=${url}/v1`);\n console.log(` export OPENAI_API_KEY=${key}`);\n });\n\nprogram\n .command(\"doctor\")\n .description(\"check which coding-agent CLIs yagami can drive and whether they work\")\n .option(\"--live\", \"send one real (tiny) completion through the default provider\")\n .option(\"--provider <id>\", \"provider to use for --live (default: config/claude)\")\n .action(async (opts: { live?: boolean; provider?: string }) => {\n let failed = false;\n const cfg = loadConfig();\n const providerConfig = { ...cfg.providers };\n if (cfg.claudePath || cfg.claudeConfigDir) {\n providerConfig[\"claude\"] = {\n ...providerConfig[\"claude\"],\n ...(cfg.claudePath ? { path: cfg.claudePath } : {}),\n ...(cfg.claudeConfigDir ? { configDir: cfg.claudeConfigDir } : {}),\n };\n }\n const defaultProvider = opts.provider ?? cfg.defaultProvider ?? \"claude\";\n\n console.log(`node ${process.version}`);\n console.log(`config ${configFilePath()}${fs.existsSync(configFilePath()) ? \"\" : \" (not created yet)\"}`);\n console.log(`api keys ${cfg.apiKeys.length === 0 ? \"none — run `yagami keygen`\" : cfg.apiKeys.map(maskKey).join(\", \")}`);\n console.log(`bind ${cfg.host}:${cfg.port}`);\n console.log(`sessions ${sessionCachePath()}${fs.existsSync(sessionCachePath()) ? \"\" : \" (empty)\"}`);\n const state = readServerState();\n console.log(\n `server ${state && isProcessAlive(state.pid) ? `running (pid ${state.pid}, ${state.url})` : \"not running\"}`,\n );\n\n console.log(\"\\nproviders (model ids route as \\\"<provider>:<model>\\\"; bare ids go to the default)\");\n const detected = detectProviders(providerConfig);\n const installed = detected.filter((d) => d.installed);\n for (const d of detected) {\n const marker = d.id === defaultProvider ? \"*\" : \" \";\n if (!d.installed) {\n if (presetIsNiche(d.id)) continue; // keep the list readable\n console.log(` ${marker} ${d.id.padEnd(11)} not installed — ${d.installHint}`);\n continue;\n }\n let version: string | undefined;\n try {\n version = await createProvider(d.id, providerConfig[d.id] ?? {}, {}).version();\n } catch (err) {\n version = `✗ ${err instanceof Error ? err.message : String(err)}`;\n }\n console.log(` ${marker} ${d.id.padEnd(11)} ${d.path}${version ? ` (${version})` : \"\"}`);\n }\n const hidden = detected.filter((d) => !d.installed && presetIsNiche(d.id)).length;\n if (hidden > 0) console.log(` … ${hidden} more ACP presets not installed (see README for the full list)`);\n if (!installed.some((d) => d.id === defaultProvider)) {\n failed = true;\n console.log(` ✗ default provider \"${defaultProvider}\" is not installed`);\n }\n\n if (installed.some((d) => d.id === \"claude\")) {\n try {\n const claude = createProvider(\"claude\", providerConfig[\"claude\"] ?? {}, {}) as ClaudeProvider;\n const skew = await claude.versionSkew();\n if (skew) {\n console.log(`\\nagent sdk ${skew.sdkVersion} ↔ claude ${skew.binaryVersion} — ${skew.inSync ? \"in sync\" : `⚠ ${skew.note}`}`);\n }\n } catch {\n // skew check is advisory\n }\n }\n\n if (opts.live && !failed) {\n console.log(`\\nlive check: sending one tiny completion through ${defaultProvider}…`);\n try {\n const engine = new YagamiEngine({ providerConfig, defaultProvider, ...(cfg.defaultModel ? { defaultModel: cfg.defaultModel } : {}) });\n const started = Date.now();\n const result = await engine.complete({\n messages: [{ role: \"user\", content: \"Reply with exactly: pong\" }],\n max_tokens: 32,\n });\n const text = result.response.content\n .filter((b) => b.type === \"text\")\n .map((b) => b[\"text\"])\n .join(\"\");\n console.log(` reply ${JSON.stringify(text)}`);\n console.log(` model ${result.response.model}`);\n console.log(` latency ${((Date.now() - started) / 1000).toFixed(1)}s`);\n if (result.costUsd !== undefined) console.log(` cost $${result.costUsd.toFixed(6)}`);\n } catch (err) {\n failed = true;\n console.log(` ✗ ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n if (failed) process.exitCode = 1;\n });\n\n/** Presets most people won't have; hidden from doctor unless installed. */\nfunction presetIsNiche(id: string): boolean {\n return ![\"claude\", \"codex\", \"opencode\", \"gemini\", \"copilot\", \"cursor\", \"qwen\", \"goose\", \"kimi\"].includes(id);\n}\n\nprogram\n .command(\"models\")\n .description(\"list models across every installed provider (ids are ready to paste into requests)\")\n .option(\"--provider <id>\", \"only this provider\")\n .action(async (opts: { provider?: string }) => {\n const cfg = loadConfig();\n try {\n const engine = new YagamiEngine({\n ...(cfg.providers ? { providerConfig: cfg.providers } : {}),\n ...(cfg.defaultProvider ? { defaultProvider: cfg.defaultProvider } : {}),\n });\n const models = await engine.listModels();\n const byProvider = new Map<string, typeof models>();\n for (const m of models) {\n if (opts.provider && m.provider !== opts.provider) continue;\n if (!m.id.includes(\":\")) continue; // print the qualified form once\n const list = byProvider.get(m.provider ?? \"?\") ?? [];\n list.push(m);\n byProvider.set(m.provider ?? \"?\", list);\n }\n for (const [provider, list] of byProvider) {\n console.log(`${provider}${provider === engine.defaultProviderId ? \" (default — bare ids work too)\" : \"\"}`);\n for (const m of list) {\n console.log(` ${m.id.padEnd(40)} ${m.display_name}${m.resolved_model ? ` → ${m.resolved_model}` : \"\"}`);\n }\n }\n if (byProvider.size === 0) console.log(\"no models reported — run `yagami doctor`\");\n } catch (err) {\n console.error(`yagami: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n }\n });\n\nawait program.parseAsync(process.argv);\n"],"mappings":"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","names":["resolve"]}
@@ -165,6 +165,92 @@ interface ModelRef {
165
165
  */
166
166
  declare function parseModelRef(model: string | undefined, providerIds: Iterable<string>): ModelRef;
167
167
  declare function qualifiedModel(providerId: string, model: string): string;
168
+ type SessionPermissionDecision = "allow" | "allow_always" | "deny" | "deny_always";
169
+ /** A harness asking the host whether a tool may run. */
170
+ interface SessionPermissionRequest {
171
+ provider: string;
172
+ sessionId?: string;
173
+ /** Tool name as the harness calls it (e.g. "Bash", "Edit", or an ACP title). */
174
+ tool: string;
175
+ /** Coarse category when known: read | edit | delete | execute | fetch | other … */
176
+ kind?: string;
177
+ title?: string;
178
+ input?: unknown;
179
+ /** Provider-native payload for hosts that want to go deep. */
180
+ raw?: unknown;
181
+ }
182
+ interface SessionPermissionHandler {
183
+ decide(req: SessionPermissionRequest, signal?: AbortSignal): Promise<SessionPermissionDecision>;
184
+ }
185
+ type AgentEvent = {
186
+ type: "session";
187
+ sessionId: string;
188
+ } | {
189
+ type: "text";
190
+ text: string;
191
+ } | {
192
+ type: "thinking";
193
+ text: string;
194
+ } | {
195
+ type: "tool_call";
196
+ id: string;
197
+ name: string;
198
+ status: "started" | "updated" | "completed" | "failed";
199
+ title?: string;
200
+ kind?: string;
201
+ input?: unknown;
202
+ output?: unknown;
203
+ } | {
204
+ type: "permission";
205
+ request: SessionPermissionRequest;
206
+ decision: SessionPermissionDecision;
207
+ } | {
208
+ type: "done";
209
+ usage?: Usage;
210
+ costUsd?: number;
211
+ stopReason?: string;
212
+ }
213
+ /** Anything the harness said that has no normalized shape. */
214
+ | {
215
+ type: "raw";
216
+ provider: string;
217
+ payload: unknown;
218
+ };
219
+ interface ProviderSessionOptions {
220
+ /** Project directory the agent works in. */
221
+ cwd: string;
222
+ model?: string;
223
+ /** Provider session id to continue. */
224
+ resume?: string;
225
+ /**
226
+ * "terminal" loads the same settings the interactive CLI would — user and
227
+ * project config, CLAUDE.md, skills, hooks, MCP servers. "isolated" loads
228
+ * none of it. Default "terminal", because that is the promise.
229
+ */
230
+ parity?: "terminal" | "isolated";
231
+ permissions: SessionPermissionHandler;
232
+ appName?: string;
233
+ effort?: string;
234
+ thinking?: ThinkingParam;
235
+ /** Override the harness's interactive system prompt. */
236
+ systemPrompt?: string;
237
+ /** Provider-specific escape hatch (Claude: Agent SDK Options; Codex: { sandbox }; ACP: { mode }). */
238
+ native?: Record<string, unknown>;
239
+ }
240
+ /** One live conversation with a harness: send turns, get normalized events. */
241
+ interface ProviderSession {
242
+ readonly provider: string;
243
+ /** Provider session id once known (use it to resume later). */
244
+ readonly id: string | undefined;
245
+ send(input: string | ContentBlockParam[]): AsyncGenerator<AgentEvent, void, undefined>;
246
+ interrupt(): Promise<void>;
247
+ close(): Promise<void>;
248
+ }
249
+ /** Providers that can host agentic sessions implement this too. */
250
+ interface SessionProvider extends Provider {
251
+ openSession(options: ProviderSessionOptions): ProviderSession;
252
+ }
253
+ declare function isSessionProvider(p: Provider): p is SessionProvider;
168
254
 
169
255
  type CodexSandboxMode = "read-only" | "workspace-write" | "danger-full-access";
170
256
  interface CodexProviderOptions {
@@ -177,7 +263,7 @@ interface CodexProviderOptions {
177
263
  env?: Record<string, string>;
178
264
  }
179
265
  /** OpenAI Codex CLI via `codex exec --json`, signed in with the user's ChatGPT account. */
180
- declare class CodexProvider implements Provider {
266
+ declare class CodexProvider implements SessionProvider {
181
267
  readonly id = "codex";
182
268
  readonly label = "Codex CLI";
183
269
  readonly executable: string;
@@ -190,6 +276,13 @@ declare class CodexProvider implements Provider {
190
276
  /** Build the `codex exec` argument list for a turn (exported for tests). */
191
277
  buildArgs(req: TurnRequest, imagePaths: string[]): string[];
192
278
  run(req: TurnRequest): AsyncGenerator<TurnEvent, void, undefined>;
279
+ /**
280
+ * A live, interactive Codex session (`codex app-server` — the TUI's own
281
+ * engine): streamed tool events, the user's config.toml verbatim, and
282
+ * approval requests forwarded to the host's permission handler. The
283
+ * completion-turn `run()` path above stays for API-style callers.
284
+ */
285
+ openSession(options: ProviderSessionOptions): ProviderSession;
193
286
  /** Ask the app-server protocol for the model catalog (no tokens spent). */
194
287
  listModels(): Promise<EngineModel[]>;
195
288
  version(): Promise<string | undefined>;
@@ -378,4 +471,23 @@ declare class YagamiEngine {
378
471
  private attemptStream;
379
472
  }
380
473
 
381
- export { ApiError as A, presetFor as B, CodexProvider as C, type DetectedProvider as D, type EngineModel as E, qualifiedModel as F, type LoadedProviders as L, type MessageParam as M, type Provider as P, SessionCache as S, type TurnRequest as T, type Usage as U, YagamiEngine as Y, type ProviderCapabilities as a, type TurnEvent as b, type ApiErrorType as c, type CodexProviderOptions as d, type CodexSandboxMode as e, type CompleteResult as f, type ContentBlock as g, type ContentBlockParam as h, type EngineOptions as i, type MessagesRequest as j, type MessagesResponse as k, type ModelRef as l, PROVIDER_PRESETS as m, type ProviderConfigEntry as n, type ProviderKind as o, type ProviderPreset as p, type SessionCacheOptions as q, type SseEvent as r, type StreamOptions as s, type StreamResultInfo as t, type StreamStart as u, type SystemParam as v, createProvider as w, detectProviders as x, loadProviders as y, parseModelRef as z };
474
+ /**
475
+ * The engine-relevant slice of the host's yagami config
476
+ * (~/.config/yagami/config.json + YAGAMI_* env) — what library mode reads so
477
+ * an embedded `Yagami` client automatically matches the `yagami` binary on
478
+ * the same machine: same providers, same paths, same defaults. Server-only
479
+ * fields (host, port, apiKeys) are ignored here on purpose.
480
+ */
481
+
482
+ declare function yagamiConfigDir(): string;
483
+ /** Engine options derivable from the host machine's yagami config. */
484
+ interface HostEngineConfig {
485
+ defaultProvider?: string;
486
+ defaultModel?: string;
487
+ providerConfig?: Record<string, ProviderConfigEntry>;
488
+ claudePath?: string;
489
+ claudeConfigDir?: string;
490
+ }
491
+ declare function loadHostEngineConfig(): HostEngineConfig;
492
+
493
+ export { ApiError as A, type StreamResultInfo as B, CodexProvider as C, type DetectedProvider as D, type EngineModel as E, type StreamStart as F, type SystemParam as G, type HostEngineConfig as H, createProvider as I, detectProviders as J, isSessionProvider as K, type LoadedProviders as L, type MessagesRequest as M, loadHostEngineConfig as N, loadProviders as O, type Provider as P, parseModelRef as Q, presetFor as R, type SseEvent as S, type TurnRequest as T, type Usage as U, qualifiedModel as V, yagamiConfigDir as W, YagamiEngine as Y, type MessagesResponse as a, type EngineOptions as b, type ProviderCapabilities as c, type TurnEvent as d, type SessionProvider as e, type ProviderSessionOptions as f, type ProviderSession as g, type AgentEvent as h, type ApiErrorType as i, type CodexProviderOptions as j, type CodexSandboxMode as k, type CompleteResult as l, type ContentBlock as m, type ContentBlockParam as n, type MessageParam as o, type ModelRef as p, PROVIDER_PRESETS as q, type ProviderConfigEntry as r, type ProviderKind as s, type ProviderPreset as t, SessionCache as u, type SessionCacheOptions as v, type SessionPermissionDecision as w, type SessionPermissionHandler as x, type SessionPermissionRequest as y, type StreamOptions as z };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,204 @@
1
- import { A as ApiError, P as Provider, a as ProviderCapabilities, T as TurnRequest, b as TurnEvent, E as EngineModel } from './engine-pmCK3S7z.js';
2
- export { c as ApiErrorType, C as CodexProvider, d as CodexProviderOptions, e as CodexSandboxMode, f as CompleteResult, g as ContentBlock, h as ContentBlockParam, D as DetectedProvider, i as EngineOptions, L as LoadedProviders, M as MessageParam, j as MessagesRequest, k as MessagesResponse, l as ModelRef, m as PROVIDER_PRESETS, n as ProviderConfigEntry, o as ProviderKind, p as ProviderPreset, S as SessionCache, q as SessionCacheOptions, r as SseEvent, s as StreamOptions, t as StreamResultInfo, u as StreamStart, v as SystemParam, U as Usage, Y as YagamiEngine, w as createProvider, x as detectProviders, y as loadProviders, z as parseModelRef, B as presetFor, F as qualifiedModel } from './engine-pmCK3S7z.js';
1
+ import { S as SseEvent, M as MessagesRequest, E as EngineModel, A as ApiError, a as MessagesResponse, Y as YagamiEngine, b as EngineOptions, P as Provider, c as ProviderCapabilities, T as TurnRequest, d as TurnEvent, e as SessionProvider, f as ProviderSessionOptions, g as ProviderSession } from './hostConfig-HmZ3z297.js';
2
+ export { h as AgentEvent, i as ApiErrorType, C as CodexProvider, j as CodexProviderOptions, k as CodexSandboxMode, l as CompleteResult, m as ContentBlock, n as ContentBlockParam, D as DetectedProvider, H as HostEngineConfig, L as LoadedProviders, o as MessageParam, p as ModelRef, q as PROVIDER_PRESETS, r as ProviderConfigEntry, s as ProviderKind, t as ProviderPreset, u as SessionCache, v as SessionCacheOptions, w as SessionPermissionDecision, x as SessionPermissionHandler, y as SessionPermissionRequest, z as StreamOptions, B as StreamResultInfo, F as StreamStart, G as SystemParam, U as Usage, I as createProvider, J as detectProviders, K as isSessionProvider, N as loadHostEngineConfig, O as loadProviders, Q as parseModelRef, R as presetFor, V as qualifiedModel, W as yagamiConfigDir } from './hostConfig-HmZ3z297.js';
3
3
  import { Options, SDKUserMessage, Query, SettingSource, PermissionUpdate, CanUseTool, PermissionResult, SDKMessage } from '@anthropic-ai/claude-agent-sdk';
4
4
  export { Options as AgentOptions, CanUseTool, PermissionMode, Query, SDKMessage, SDKUserMessage } from '@anthropic-ai/claude-agent-sdk';
5
5
  import { ClientSideConnection, InitializeResponse, SessionNotification, RequestPermissionRequest, RequestPermissionResponse } from '@agentclientprotocol/sdk';
6
6
 
7
+ /**
8
+ * OpenAI Chat Completions dialect: translation to and from the Anthropic
9
+ * Messages shapes the engine speaks. Pure functions — used by both the HTTP
10
+ * server (`POST /v1/chat/completions`) and the library client
11
+ * (`yagami.chat.completions.create`).
12
+ */
13
+
14
+ interface ChatMessageParam {
15
+ role: string;
16
+ content?: string | null | Array<{
17
+ type: string;
18
+ [key: string]: unknown;
19
+ }>;
20
+ [key: string]: unknown;
21
+ }
22
+ interface ChatCompletionsRequest {
23
+ model?: string;
24
+ messages: ChatMessageParam[];
25
+ stream?: boolean;
26
+ stream_options?: {
27
+ include_usage?: boolean;
28
+ };
29
+ max_tokens?: number;
30
+ max_completion_tokens?: number;
31
+ temperature?: number;
32
+ top_p?: number;
33
+ stop?: string | string[];
34
+ n?: number;
35
+ reasoning_effort?: string;
36
+ tools?: unknown;
37
+ tool_choice?: unknown;
38
+ functions?: unknown;
39
+ function_call?: unknown;
40
+ [key: string]: unknown;
41
+ }
42
+ interface ChatCompletionChoice {
43
+ index: number;
44
+ message: {
45
+ role: "assistant";
46
+ content: string;
47
+ /** Thinking output (DeepSeek-style extension; no standard OpenAI field exists). */
48
+ reasoning_content?: string;
49
+ refusal: null;
50
+ };
51
+ finish_reason: string;
52
+ logprobs: null;
53
+ }
54
+ interface ChatCompletion {
55
+ id: string;
56
+ object: "chat.completion";
57
+ created: number;
58
+ model: string;
59
+ choices: ChatCompletionChoice[];
60
+ usage: OpenAiUsage;
61
+ }
62
+ interface OpenAiUsage {
63
+ prompt_tokens: number;
64
+ completion_tokens: number;
65
+ total_tokens: number;
66
+ }
67
+ interface ChatCompletionChunk {
68
+ id: string;
69
+ object: "chat.completion.chunk";
70
+ created: number;
71
+ model: string;
72
+ choices: Array<{
73
+ index: number;
74
+ delta: {
75
+ role?: "assistant";
76
+ content?: string;
77
+ reasoning_content?: string;
78
+ };
79
+ finish_reason: string | null;
80
+ }>;
81
+ usage?: OpenAiUsage;
82
+ }
83
+ interface TranslatedChatRequest {
84
+ req: MessagesRequest;
85
+ /** OpenAI params yagami accepted but cannot honor (adds to x-yagami-ignored). */
86
+ extraIgnored: string[];
87
+ /** `stream_options.include_usage` — emit the trailing usage chunk. */
88
+ includeUsage: boolean;
89
+ }
90
+ /**
91
+ * Translate an OpenAI Chat Completions request into the Anthropic Messages
92
+ * request the engine runs. Tool calling is rejected (yagami is
93
+ * completions-only by design); knobs no CLI engine exposes are collected
94
+ * into `extraIgnored` instead of failing the request.
95
+ */
96
+ declare function chatToMessagesRequest(body: ChatCompletionsRequest): TranslatedChatRequest;
97
+ /** Anthropic Messages response → OpenAI chat.completion. */
98
+ declare function toChatCompletion(resp: MessagesResponse): ChatCompletion;
99
+ /** OpenAI-shaped error body (the OpenAI dialect's counterpart of ApiError.toBody). */
100
+ declare function openAiErrorBody(err: ApiError): {
101
+ error: {
102
+ message: string;
103
+ type: string;
104
+ param: null;
105
+ code: null;
106
+ };
107
+ };
108
+ /**
109
+ * Re-emits an Anthropic SSE event sequence as OpenAI chat.completion.chunk
110
+ * objects. Feed every engine event through `push`; the caller appends the
111
+ * `[DONE]` sentinel (HTTP mode) unless `errored`.
112
+ */
113
+ declare class ChatChunkTranslator {
114
+ private readonly includeUsage;
115
+ private id;
116
+ private model;
117
+ private created;
118
+ private stopReason;
119
+ private usage;
120
+ /** Set when the engine reported an error mid-stream (no [DONE] after). */
121
+ errored: boolean;
122
+ constructor(includeUsage: boolean);
123
+ private chunk;
124
+ /** Translate one engine SSE event into zero or more OpenAI chunk payloads. */
125
+ push(ev: SseEvent): unknown[];
126
+ }
127
+ /**
128
+ * Model list body served by GET /v1/models: Anthropic fields and OpenAI
129
+ * fields on the same objects, so both SDKs' `models.list()` parse it.
130
+ */
131
+ declare function modelListBody(models: EngineModel[]): {
132
+ object: "list";
133
+ data: Array<Record<string, unknown>>;
134
+ has_more: false;
135
+ first_id?: string;
136
+ last_id?: string;
137
+ };
138
+
139
+ /**
140
+ * `Yagami` — the zero-config library client. `new Yagami()` needs no URL and
141
+ * no API key: it finds the coding-agent CLIs already installed and signed in
142
+ * on this machine (the same T3-Code trick the server does) and mirrors the
143
+ * Anthropic and OpenAI SDK surfaces on top of them, so an app written
144
+ * against either SDK shape drops in with nothing to configure.
145
+ *
146
+ * By default it also reads the host's yagami config
147
+ * (~/.config/yagami/config.json), so an embedded client and the `yagami`
148
+ * binary on the same machine agree on providers, paths, and defaults.
149
+ */
150
+
151
+ interface YagamiOptions extends EngineOptions {
152
+ /**
153
+ * Merge the host machine's yagami config (providers, defaults) under any
154
+ * explicit options, so library and binary stay in sync. Default true;
155
+ * ignored when explicit `providers` instances are passed.
156
+ */
157
+ syncHostConfig?: boolean;
158
+ }
159
+ /** An Anthropic stream event's payload (`message_start`, `content_block_delta`, …). */
160
+ interface MessageStreamEvent {
161
+ type: string;
162
+ [key: string]: unknown;
163
+ }
164
+ interface YagamiMessages {
165
+ /** Anthropic-SDK-shaped: non-stream resolves to the message; `stream: true` yields stream events. */
166
+ create(req: MessagesRequest & {
167
+ stream: true;
168
+ }): AsyncGenerator<MessageStreamEvent, void, undefined>;
169
+ create(req: MessagesRequest & {
170
+ stream?: false | undefined;
171
+ }): Promise<MessagesResponse>;
172
+ /** Always-streaming variant (the SDK's `messages.stream`). */
173
+ stream(req: MessagesRequest): AsyncGenerator<MessageStreamEvent, void, undefined>;
174
+ }
175
+ interface YagamiChatCompletions {
176
+ /** OpenAI-SDK-shaped: non-stream resolves to a chat.completion; `stream: true` yields chunks. */
177
+ create(req: ChatCompletionsRequest & {
178
+ stream: true;
179
+ }): AsyncGenerator<ChatCompletionChunk, void, undefined>;
180
+ create(req: ChatCompletionsRequest & {
181
+ stream?: false | undefined;
182
+ }): Promise<ChatCompletion>;
183
+ }
184
+ declare class Yagami {
185
+ /** The underlying engine, for anything beyond the SDK-shaped surface. */
186
+ readonly engine: YagamiEngine;
187
+ constructor(options?: YagamiOptions);
188
+ readonly messages: YagamiMessages;
189
+ readonly chat: {
190
+ completions: YagamiChatCompletions;
191
+ };
192
+ readonly models: {
193
+ /** Both SDK shapes at once (Anthropic + OpenAI model-list fields). */
194
+ list: () => Promise<ReturnType<typeof modelListBody>>;
195
+ /** The engine's raw model list. */
196
+ raw: () => Promise<EngineModel[]>;
197
+ };
198
+ private streamMessageEvents;
199
+ private streamChatChunks;
200
+ }
201
+
7
202
  interface ClaudeSessionOptions {
8
203
  /** Path to the `claude` binary. Auto-resolved when omitted. */
9
204
  claudePath?: string;
@@ -276,7 +471,7 @@ interface AcpProviderOptions {
276
471
  * Gemini CLI, Copilot, Cursor, Qwen Code, Kimi, Goose, and anything in the
277
472
  * ACP registry. One adapter, many harnesses.
278
473
  */
279
- declare class AcpProvider implements Provider {
474
+ declare class AcpProvider implements SessionProvider {
280
475
  readonly id: string;
281
476
  readonly label: string;
282
477
  readonly executable: string;
@@ -292,6 +487,13 @@ declare class AcpProvider implements Provider {
292
487
  private spawnConnection;
293
488
  private classify;
294
489
  run(req: TurnRequest): AsyncGenerator<TurnEvent, void, undefined>;
490
+ /**
491
+ * A live, interactive ACP session: the agent runs warm in the project
492
+ * directory with ITS OWN defaults — no plan-mode hardening, no forced
493
+ * config. Tool calls stream as normalized events and permission requests
494
+ * go to the host's handler, exactly as the agent's own client would ask.
495
+ */
496
+ openSession(options: ProviderSessionOptions): ProviderSession;
295
497
  private selectModel;
296
498
  listModels(): Promise<EngineModel[]>;
297
499
  /**
@@ -323,6 +525,6 @@ declare function resolveExecutable(providerId: string, name: string, installHint
323
525
  */
324
526
  declare function resolveClaudeExecutable(explicit?: string): string;
325
527
 
326
- declare const VERSION = "0.4.1";
528
+ declare const VERSION = "0.5.0";
327
529
 
328
- export { type AcpConnection, AcpProvider, type AcpProviderOptions, AgentSession, type AgentSessionOptions, ApiError, AuthRequiredError, ClaudeProvider, type ClaudeProviderOptions, type ClaudeSessionOptions, EngineModel, type Parity, PermissionAdapter, type PermissionAdapterOptions, type PermissionDecision, type PermissionHandler, type PermissionRequest, Provider, ProviderCapabilities, ProviderError, ProviderNotInstalledError, TurnEvent, TurnRequest, VERSION, type VersionSkew, YagamiError, claudeCodeSession, findExecutable, resolveClaudeExecutable, resolveExecutable, settingSourcesFor, startAgentSession, toApiError };
530
+ export { type AcpConnection, AcpProvider, type AcpProviderOptions, AgentSession, type AgentSessionOptions, ApiError, AuthRequiredError, ChatChunkTranslator, type ChatCompletion, type ChatCompletionChunk, type ChatCompletionsRequest, type ChatMessageParam, ClaudeProvider, type ClaudeProviderOptions, type ClaudeSessionOptions, EngineModel, EngineOptions, type MessageStreamEvent, MessagesRequest, MessagesResponse, type OpenAiUsage, type Parity, PermissionAdapter, type PermissionAdapterOptions, type PermissionDecision, type PermissionHandler, type PermissionRequest, Provider, ProviderCapabilities, ProviderError, ProviderNotInstalledError, ProviderSession, ProviderSessionOptions, SessionProvider, SseEvent, type TranslatedChatRequest, TurnEvent, TurnRequest, VERSION, type VersionSkew, Yagami, type YagamiChatCompletions, YagamiEngine, YagamiError, type YagamiMessages, type YagamiOptions, chatToMessagesRequest, claudeCodeSession, findExecutable, modelListBody, openAiErrorBody, resolveClaudeExecutable, resolveExecutable, settingSourcesFor, startAgentSession, toApiError, toChatCompletion };