chorus-codes 0.7.0 → 0.7.2
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/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/cache/.previewinfo +1 -1
- package/.next/cache/.rscinfo +1 -1
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/new.html +1 -1
- package/.next/server/app/new.rsc +1 -1
- package/.next/server/app/new.segments/_full.segment.rsc +1 -1
- package/.next/server/app/new.segments/_head.segment.rsc +1 -1
- package/.next/server/app/new.segments/_index.segment.rsc +1 -1
- package/.next/server/app/new.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/new.segments/new/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/new.segments/new.segment.rsc +1 -1
- package/.next/server/app/onboarding.html +1 -1
- package/.next/server/app/onboarding.rsc +1 -1
- package/.next/server/app/onboarding.segments/_full.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/_index.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
- package/.next/server/app/personas.html +1 -1
- package/.next/server/app/personas.rsc +1 -1
- package/.next/server/app/personas.segments/_full.segment.rsc +1 -1
- package/.next/server/app/personas.segments/_head.segment.rsc +1 -1
- package/.next/server/app/personas.segments/_index.segment.rsc +1 -1
- package/.next/server/app/personas.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/personas.segments/personas/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/personas.segments/personas.segment.rsc +1 -1
- package/.next/server/app/settings.html +1 -1
- package/.next/server/app/settings.rsc +1 -1
- package/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/app/templates.html +1 -1
- package/.next/server/app/templates.rsc +1 -1
- package/.next/server/app/templates.segments/_full.segment.rsc +1 -1
- package/.next/server/app/templates.segments/_head.segment.rsc +1 -1
- package/.next/server/app/templates.segments/_index.segment.rsc +1 -1
- package/.next/server/app/templates.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/templates.segments/templates/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/templates.segments/templates.segment.rsc +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/trace +1 -1
- package/.next/trace-build +1 -1
- package/README.md +38 -15
- package/dist/cli/commands/doctor.js +116 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.js +211 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/start.js +298 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.js +54 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stop.js +97 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/connect.js +108 -0
- package/dist/cli/connect.js.map +1 -0
- package/dist/cli/index.js +99 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/port-utils.js +260 -0
- package/dist/cli/port-utils.js.map +1 -0
- package/dist/cli/runtime-env.js +60 -0
- package/dist/cli/runtime-env.js.map +1 -0
- package/dist/cli/shared.js +54 -0
- package/dist/cli/shared.js.map +1 -0
- package/dist/cli/ui.js +60 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/daemon/agents/claude.js +98 -0
- package/dist/daemon/agents/claude.js.map +1 -0
- package/dist/daemon/agents/codex.js +160 -0
- package/dist/daemon/agents/codex.js.map +1 -0
- package/dist/daemon/agents/gemini.js +111 -0
- package/dist/daemon/agents/gemini.js.map +1 -0
- package/dist/daemon/agents/index.js +59 -0
- package/dist/daemon/agents/index.js.map +1 -0
- package/dist/daemon/agents/kimi.js +206 -0
- package/dist/daemon/agents/kimi.js.map +1 -0
- package/dist/daemon/agents/opencode.js +228 -0
- package/dist/daemon/agents/opencode.js.map +1 -0
- package/dist/daemon/agents/openrouter.js +274 -0
- package/dist/daemon/agents/openrouter.js.map +1 -0
- package/dist/daemon/agents/parsers/claude.js +63 -0
- package/dist/daemon/agents/parsers/claude.js.map +1 -0
- package/dist/daemon/agents/parsers/codex.js +51 -0
- package/dist/daemon/agents/parsers/codex.js.map +1 -0
- package/dist/daemon/agents/parsers/gemini.js +144 -0
- package/dist/daemon/agents/parsers/gemini.js.map +1 -0
- package/dist/daemon/agents/parsers/index.js +31 -0
- package/dist/daemon/agents/parsers/index.js.map +1 -0
- package/dist/daemon/agents/parsers/kimi.js +8 -0
- package/dist/daemon/agents/parsers/kimi.js.map +1 -0
- package/dist/daemon/agents/parsers/opencode.js +105 -0
- package/dist/daemon/agents/parsers/opencode.js.map +1 -0
- package/dist/daemon/agents/parsers/openrouter.js +69 -0
- package/dist/daemon/agents/parsers/openrouter.js.map +1 -0
- package/dist/daemon/agents/parsers/shared.js +17 -0
- package/dist/daemon/agents/parsers/shared.js.map +1 -0
- package/dist/daemon/agents/preflight.js +83 -0
- package/dist/daemon/agents/preflight.js.map +1 -0
- package/dist/daemon/agents/quote.js +45 -0
- package/dist/daemon/agents/quote.js.map +1 -0
- package/dist/daemon/agents/sandbox-guard.js +69 -0
- package/dist/daemon/agents/sandbox-guard.js.map +1 -0
- package/dist/daemon/agents/types.js +6 -0
- package/dist/daemon/agents/types.js.map +1 -0
- package/dist/daemon/api-response.js +65 -0
- package/dist/daemon/api-response.js.map +1 -0
- package/dist/daemon/error-detector.js +329 -0
- package/dist/daemon/error-detector.js.map +1 -0
- package/dist/daemon/headless.js +533 -0
- package/dist/daemon/headless.js.map +1 -0
- package/dist/daemon/index.js +333 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/openrouter.js +192 -0
- package/dist/daemon/openrouter.js.map +1 -0
- package/dist/daemon/orchestrators/claude.js +163 -0
- package/dist/daemon/orchestrators/claude.js.map +1 -0
- package/dist/daemon/orchestrators/codex.js +101 -0
- package/dist/daemon/orchestrators/codex.js.map +1 -0
- package/dist/daemon/orchestrators/cursor-windsurf.js +118 -0
- package/dist/daemon/orchestrators/cursor-windsurf.js.map +1 -0
- package/dist/daemon/orchestrators/gemini.js +108 -0
- package/dist/daemon/orchestrators/gemini.js.map +1 -0
- package/dist/daemon/orchestrators/index.js +90 -0
- package/dist/daemon/orchestrators/index.js.map +1 -0
- package/dist/daemon/orchestrators/kimi.js +108 -0
- package/dist/daemon/orchestrators/kimi.js.map +1 -0
- package/dist/daemon/orchestrators/opencode.js +152 -0
- package/dist/daemon/orchestrators/opencode.js.map +1 -0
- package/dist/daemon/orchestrators/shared.js +60 -0
- package/dist/daemon/orchestrators/shared.js.map +1 -0
- package/dist/daemon/output-watcher.js +131 -0
- package/dist/daemon/output-watcher.js.map +1 -0
- package/dist/daemon/participant-aborts.js +123 -0
- package/dist/daemon/participant-aborts.js.map +1 -0
- package/dist/daemon/reaper.js +46 -0
- package/dist/daemon/reaper.js.map +1 -0
- package/dist/daemon/routes/chats-events.js +62 -0
- package/dist/daemon/routes/chats-events.js.map +1 -0
- package/dist/daemon/routes/chats-stream.js +241 -0
- package/dist/daemon/routes/chats-stream.js.map +1 -0
- package/dist/daemon/routes/chats-validation.js +13 -0
- package/dist/daemon/routes/chats-validation.js.map +1 -0
- package/dist/daemon/routes/chats.js +545 -0
- package/dist/daemon/routes/chats.js.map +1 -0
- package/dist/daemon/routes/openrouter.js +103 -0
- package/dist/daemon/routes/openrouter.js.map +1 -0
- package/dist/daemon/routes/settings.js +199 -0
- package/dist/daemon/routes/settings.js.map +1 -0
- package/dist/daemon/routes/stats.js +155 -0
- package/dist/daemon/routes/stats.js.map +1 -0
- package/dist/daemon/routes/system.js +208 -0
- package/dist/daemon/routes/system.js.map +1 -0
- package/dist/daemon/routes/templates-personas.js +254 -0
- package/dist/daemon/routes/templates-personas.js.map +1 -0
- package/dist/daemon/routes/voices.js +139 -0
- package/dist/daemon/routes/voices.js.map +1 -0
- package/dist/daemon/runner/doer-driver.js +346 -0
- package/dist/daemon/runner/doer-driver.js.map +1 -0
- package/dist/daemon/runner/doer.js +336 -0
- package/dist/daemon/runner/doer.js.map +1 -0
- package/dist/daemon/runner/prior-round.js +140 -0
- package/dist/daemon/runner/prior-round.js.map +1 -0
- package/dist/daemon/runner/prompt-builder.js +292 -0
- package/dist/daemon/runner/prompt-builder.js.map +1 -0
- package/dist/daemon/runner/review-only-phase.js +103 -0
- package/dist/daemon/runner/review-only-phase.js.map +1 -0
- package/dist/daemon/runner/reviewer-driver.js +410 -0
- package/dist/daemon/runner/reviewer-driver.js.map +1 -0
- package/dist/daemon/runner/reviewer.js +384 -0
- package/dist/daemon/runner/reviewer.js.map +1 -0
- package/dist/daemon/runner/run-with-fallback.js +56 -0
- package/dist/daemon/runner/run-with-fallback.js.map +1 -0
- package/dist/daemon/runner/sanitize-name.js +8 -0
- package/dist/daemon/runner/sanitize-name.js.map +1 -0
- package/dist/daemon/runner/stream-file-writer.js +116 -0
- package/dist/daemon/runner/stream-file-writer.js.map +1 -0
- package/dist/daemon/runner/swap-sidecar.js +102 -0
- package/dist/daemon/runner/swap-sidecar.js.map +1 -0
- package/dist/daemon/runner/template-fallback.js +119 -0
- package/dist/daemon/runner/template-fallback.js.map +1 -0
- package/dist/daemon/runner/types.js +3 -0
- package/dist/daemon/runner/types.js.map +1 -0
- package/dist/daemon/runner/verdict.js +51 -0
- package/dist/daemon/runner/verdict.js.map +1 -0
- package/dist/daemon/runner-multiplex.js +364 -0
- package/dist/daemon/runner-multiplex.js.map +1 -0
- package/dist/daemon/runner.js +427 -0
- package/dist/daemon/runner.js.map +1 -0
- package/dist/daemon/ship.js +340 -0
- package/dist/daemon/ship.js.map +1 -0
- package/dist/daemon/template-cache.js +37 -0
- package/dist/daemon/template-cache.js.map +1 -0
- package/dist/daemon/tmux-types.js +9 -0
- package/dist/daemon/tmux-types.js.map +1 -0
- package/dist/daemon/tmux.js +341 -0
- package/dist/daemon/tmux.js.map +1 -0
- package/dist/lib/atomic-write.js +55 -0
- package/dist/lib/atomic-write.js.map +1 -0
- package/dist/lib/chat-events-bus.js +27 -0
- package/dist/lib/chat-events-bus.js.map +1 -0
- package/dist/lib/chat-slug.js +105 -0
- package/dist/lib/chat-slug.js.map +1 -0
- package/dist/lib/cli-detect.js +388 -0
- package/dist/lib/cli-detect.js.map +1 -0
- package/dist/lib/cli-health.js +156 -0
- package/dist/lib/cli-health.js.map +1 -0
- package/dist/lib/cli-paths.js +113 -0
- package/dist/lib/cli-paths.js.map +1 -0
- package/dist/lib/cli-precheck.js +141 -0
- package/dist/lib/cli-precheck.js.map +1 -0
- package/dist/lib/db/chats.js +244 -0
- package/dist/lib/db/chats.js.map +1 -0
- package/dist/lib/db/connection.js +254 -0
- package/dist/lib/db/connection.js.map +1 -0
- package/dist/lib/db/index.js +34 -0
- package/dist/lib/db/index.js.map +1 -0
- package/dist/lib/db/personas.js +65 -0
- package/dist/lib/db/personas.js.map +1 -0
- package/dist/lib/db/phase-events.js +172 -0
- package/dist/lib/db/phase-events.js.map +1 -0
- package/dist/lib/db/secrets.js +53 -0
- package/dist/lib/db/secrets.js.map +1 -0
- package/dist/lib/db/settings.js +47 -0
- package/dist/lib/db/settings.js.map +1 -0
- package/dist/lib/db/templates.js +75 -0
- package/dist/lib/db/templates.js.map +1 -0
- package/dist/lib/db/voices.js +184 -0
- package/dist/lib/db/voices.js.map +1 -0
- package/dist/lib/lineage-maps.js +200 -0
- package/dist/lib/lineage-maps.js.map +1 -0
- package/dist/lib/logger.js +186 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/personas.js +117 -0
- package/dist/lib/personas.js.map +1 -0
- package/dist/lib/runtime-path.js +222 -0
- package/dist/lib/runtime-path.js.map +1 -0
- package/dist/lib/settings/billing.js +58 -0
- package/dist/lib/settings/billing.js.map +1 -0
- package/dist/lib/settings/permissions.js +81 -0
- package/dist/lib/settings/permissions.js.map +1 -0
- package/dist/lib/settings/transport.js +113 -0
- package/dist/lib/settings/transport.js.map +1 -0
- package/dist/lib/telemetry.js +290 -0
- package/dist/lib/telemetry.js.map +1 -0
- package/dist/lib/template-schema.js +319 -0
- package/dist/lib/template-schema.js.map +1 -0
- package/dist/lib/template-validation.js +82 -0
- package/dist/lib/template-validation.js.map +1 -0
- package/dist/lib/voices.js +533 -0
- package/dist/lib/voices.js.map +1 -0
- package/dist/mcp/client.js +138 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/index.js +178 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/tools.js +355 -0
- package/dist/mcp/tools.js.map +1 -0
- package/package.json +2 -1
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js +0 -6077
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js.map +0 -69
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js +0 -6318
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js.map +0 -71
- package/.next/dev/types/cache-life.d.ts +0 -145
- package/.next/dev/types/routes.d.ts +0 -84
- package/.next/dev/types/validator.ts +0 -178
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_buildManifest.js +0 -0
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenRouter HTTP shim — dispatches chat completions over `/api/v1/chat/completions`
|
|
4
|
+
* with `stream=true` and parses the resulting SSE into AgentEvents.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists: PR #27 shipped the inline catalog/voice-insert flow but
|
|
7
|
+
* left runtime dispatch as a follow-up. This module is the follow-up. With
|
|
8
|
+
* it, an `openrouter:<model-id>` voice referenced from a template actually
|
|
9
|
+
* runs (instead of falling through to the wrong CLI shim or erroring).
|
|
10
|
+
*
|
|
11
|
+
* Lineage tag is `'any'` because OpenRouter spans every lineage we score
|
|
12
|
+
* (anthropic / openai / google / meta / moonshot / deepseek / mistral / xai).
|
|
13
|
+
* The voice's REAL lineage lives on the voices table row (set by
|
|
14
|
+
* classifyOpencodeModel during voices.upsert) and is what the runner uses
|
|
15
|
+
* for diversity scoring — picking this shim does not collapse diversity.
|
|
16
|
+
*
|
|
17
|
+
* Dispatch: see `pickShimForVoice` in `agents/index.ts`. When the model id
|
|
18
|
+
* starts with `openrouter:`, the runner picks this shim regardless of
|
|
19
|
+
* `phase.doer.lineage`. Precheck (CLI credential file + quota) is skipped
|
|
20
|
+
* — this shim's auth is the OpenRouter key in the secrets table.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.openrouterShim = void 0;
|
|
24
|
+
const index_js_1 = require("../../lib/db/index.js");
|
|
25
|
+
const cli_health_js_1 = require("../../lib/cli-health.js");
|
|
26
|
+
const index_js_2 = require("./parsers/index.js");
|
|
27
|
+
const OPENROUTER_BASE = 'https://openrouter.ai/api/v1';
|
|
28
|
+
const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
|
|
29
|
+
/**
|
|
30
|
+
* Strip the `openrouter:` voice-id prefix if present. The voices table stores
|
|
31
|
+
* ids like `openrouter:anthropic/claude-3.5-sonnet`; OpenRouter's API expects
|
|
32
|
+
* the bare model id `anthropic/claude-3.5-sonnet`.
|
|
33
|
+
*/
|
|
34
|
+
function stripOpenRouterPrefix(model) {
|
|
35
|
+
return model.startsWith('openrouter:') ? model.slice('openrouter:'.length) : model;
|
|
36
|
+
}
|
|
37
|
+
exports.openrouterShim = {
|
|
38
|
+
lineage: 'any',
|
|
39
|
+
name: 'openrouter',
|
|
40
|
+
buildLaunchCommand(_opts) {
|
|
41
|
+
// OpenRouter is HTTP-only; there is no tmux launch path. The runner must
|
|
42
|
+
// route through `runHeadless`. This stub exists only because the shim
|
|
43
|
+
// contract requires it; calling it indicates a routing bug upstream.
|
|
44
|
+
throw new Error('openrouterShim has no tmux launch path — runner must use runHeadless');
|
|
45
|
+
},
|
|
46
|
+
formatPrompt(_opts) {
|
|
47
|
+
// Same — no file-based prompt nudging. The full prompt flows directly
|
|
48
|
+
// through the chat-completions request body.
|
|
49
|
+
throw new Error('openrouterShim does not use file-based prompt nudging — runHeadless ' +
|
|
50
|
+
'passes promptText into the request body directly');
|
|
51
|
+
},
|
|
52
|
+
runHeadless(opts) {
|
|
53
|
+
return runOpenRouterStream(opts);
|
|
54
|
+
},
|
|
55
|
+
estimateCostUsd(_input, _output, _model) {
|
|
56
|
+
// The shim emits actual cost from OpenRouter's `usage.cost` on the final
|
|
57
|
+
// SSE chunk, so estimation here returns 0. Cost preview UX (cost-before-
|
|
58
|
+
// run) should consult voices.input_cost_per_mtok directly rather than
|
|
59
|
+
// this method.
|
|
60
|
+
return 0;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Generator that wraps the fetch + SSE loop. Honours abortSignal and a
|
|
65
|
+
* hard timeoutMs (defaults to spawnHeadless's 10-min budget). The model id
|
|
66
|
+
* is auto-stripped of any `openrouter:` prefix.
|
|
67
|
+
*
|
|
68
|
+
* Failure modes mapped to AgentEvents:
|
|
69
|
+
* - missing API key → `error{kind:'auth_missing'}`
|
|
70
|
+
* - non-2xx HTTP → `error{kind:'openrouter_<status>'}`
|
|
71
|
+
* - aborted / timed out → `error{kind:'aborted'|'timeout'}`
|
|
72
|
+
* - upstream stream error envelope → forwarded with its own kind
|
|
73
|
+
*/
|
|
74
|
+
async function* runOpenRouterStream(opts) {
|
|
75
|
+
const stored = await index_js_1.secrets.get('openrouter');
|
|
76
|
+
const apiKey = stored?.value;
|
|
77
|
+
if (!apiKey) {
|
|
78
|
+
yield {
|
|
79
|
+
type: 'error',
|
|
80
|
+
kind: 'auth_missing',
|
|
81
|
+
message: 'No OpenRouter API key in secrets. Save one via Settings → OpenRouter ' +
|
|
82
|
+
'before using openrouter:* voices.',
|
|
83
|
+
};
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const rawModel = opts.model;
|
|
87
|
+
if (!rawModel) {
|
|
88
|
+
yield {
|
|
89
|
+
type: 'error',
|
|
90
|
+
kind: 'validation',
|
|
91
|
+
message: 'OpenRouter dispatch requires an explicit model — none supplied.',
|
|
92
|
+
};
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const model = stripOpenRouterPrefix(rawModel);
|
|
96
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
97
|
+
// Compose the abort source: outer cancel (chat cancel button, daemon
|
|
98
|
+
// shutdown) AND inner timeout. Either firing cancels the fetch + closes
|
|
99
|
+
// the stream reader. Node's AbortSignal.any was added in 20.3 — chorus
|
|
100
|
+
// engines field already requires Node 20+.
|
|
101
|
+
const timeoutCtl = new AbortController();
|
|
102
|
+
const timeoutHandle = setTimeout(() => timeoutCtl.abort('timeout'), timeoutMs);
|
|
103
|
+
const signals = [timeoutCtl.signal];
|
|
104
|
+
if (opts.abortSignal)
|
|
105
|
+
signals.push(opts.abortSignal);
|
|
106
|
+
const composed = AbortSignal.any(signals);
|
|
107
|
+
let accumulated = '';
|
|
108
|
+
let usage;
|
|
109
|
+
let finishedNaturally = false;
|
|
110
|
+
try {
|
|
111
|
+
const res = await fetch(`${OPENROUTER_BASE}/chat/completions`, {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
headers: {
|
|
114
|
+
'Content-Type': 'application/json',
|
|
115
|
+
Authorization: `Bearer ${apiKey}`,
|
|
116
|
+
// OpenRouter recommends a referer / X-Title for ranking + analytics.
|
|
117
|
+
// Self-attributing keeps chorus calls grouped on the user's dashboard.
|
|
118
|
+
'HTTP-Referer': 'https://chorus.codes',
|
|
119
|
+
'X-Title': 'Chorus',
|
|
120
|
+
},
|
|
121
|
+
body: JSON.stringify({
|
|
122
|
+
model,
|
|
123
|
+
messages: [{ role: 'user', content: opts.promptText }],
|
|
124
|
+
stream: true,
|
|
125
|
+
// Forces the terminal usage chunk so we get prompt/completion/cost
|
|
126
|
+
// attribution. Without this, OpenRouter omits usage from the stream.
|
|
127
|
+
stream_options: { include_usage: true },
|
|
128
|
+
}),
|
|
129
|
+
signal: composed,
|
|
130
|
+
});
|
|
131
|
+
if (!res.ok) {
|
|
132
|
+
// Try to lift a structured error from the body before falling back to
|
|
133
|
+
// the raw status code. Body is small for error responses.
|
|
134
|
+
let errMessage = `OpenRouter returned ${res.status}`;
|
|
135
|
+
try {
|
|
136
|
+
const text = await res.text();
|
|
137
|
+
const parsed = JSON.parse(text);
|
|
138
|
+
if (parsed.error?.message)
|
|
139
|
+
errMessage = parsed.error.message;
|
|
140
|
+
else if (text.length > 0 && text.length < 500)
|
|
141
|
+
errMessage = text;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
/* keep status-code message */
|
|
145
|
+
}
|
|
146
|
+
yield {
|
|
147
|
+
type: 'error',
|
|
148
|
+
kind: `openrouter_${res.status}`,
|
|
149
|
+
message: errMessage,
|
|
150
|
+
};
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (!res.body) {
|
|
154
|
+
yield {
|
|
155
|
+
type: 'error',
|
|
156
|
+
kind: 'openrouter_no_body',
|
|
157
|
+
message: 'OpenRouter response had no body — cannot stream.',
|
|
158
|
+
};
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// SSE parsing: split on `\n\n` event boundaries, strip the `data: `
|
|
162
|
+
// prefix, hand each payload to parseOpenRouterSSE. Buffer carries
|
|
163
|
+
// partial events across chunk boundaries.
|
|
164
|
+
const reader = res.body.getReader();
|
|
165
|
+
const decoder = new TextDecoder();
|
|
166
|
+
let buffer = '';
|
|
167
|
+
while (true) {
|
|
168
|
+
const { value, done } = await reader.read();
|
|
169
|
+
if (done)
|
|
170
|
+
break;
|
|
171
|
+
buffer += decoder.decode(value, { stream: true });
|
|
172
|
+
// Drain complete events from buffer. SSE delimiter is a blank line
|
|
173
|
+
// (\n\n). Some servers use \r\n\r\n — handle both.
|
|
174
|
+
let boundary;
|
|
175
|
+
while ((boundary = findEventBoundary(buffer)) !== -1) {
|
|
176
|
+
const rawEvent = buffer.slice(0, boundary);
|
|
177
|
+
buffer = buffer.slice(boundary).replace(/^[\r\n]+/, '');
|
|
178
|
+
// An event may contain multiple `data:` lines (per SSE spec these
|
|
179
|
+
// concatenate with `\n`). For chat-completions chunks each event is
|
|
180
|
+
// a single data line, but be defensive.
|
|
181
|
+
const dataLines = rawEvent
|
|
182
|
+
.split('\n')
|
|
183
|
+
.filter((l) => l.startsWith('data:'))
|
|
184
|
+
.map((l) => l.slice('data:'.length).replace(/^ /, ''));
|
|
185
|
+
const payload = dataLines.join('\n');
|
|
186
|
+
if (payload.length === 0)
|
|
187
|
+
continue;
|
|
188
|
+
for (const ev of (0, index_js_2.parseOpenRouterSSE)(payload)) {
|
|
189
|
+
if (ev.type === 'text_delta') {
|
|
190
|
+
accumulated += ev.text;
|
|
191
|
+
yield ev;
|
|
192
|
+
}
|
|
193
|
+
else if (ev.type === 'message_done') {
|
|
194
|
+
// Parser emits this only for usage-bearing chunks. Capture the
|
|
195
|
+
// usage; the real terminal message_done with finalText is
|
|
196
|
+
// emitted at end-of-stream so the runner sees one consolidated
|
|
197
|
+
// event with both finalText AND usage.
|
|
198
|
+
usage = ev.usage;
|
|
199
|
+
}
|
|
200
|
+
else if (ev.type === 'error') {
|
|
201
|
+
yield ev;
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
yield ev;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
finishedNaturally = true;
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
const aborted = composed.aborted;
|
|
214
|
+
const reason = composed.aborted ? composed.reason : undefined;
|
|
215
|
+
if (aborted && reason === 'timeout') {
|
|
216
|
+
yield {
|
|
217
|
+
type: 'error',
|
|
218
|
+
kind: 'timeout',
|
|
219
|
+
message: `OpenRouter dispatch exceeded ${Math.round(timeoutMs / 1000)}s.`,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
else if (aborted) {
|
|
223
|
+
yield {
|
|
224
|
+
type: 'error',
|
|
225
|
+
kind: 'aborted',
|
|
226
|
+
message: 'OpenRouter dispatch was cancelled.',
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
231
|
+
yield {
|
|
232
|
+
type: 'error',
|
|
233
|
+
kind: 'openrouter_fetch_failed',
|
|
234
|
+
message: `Network error: ${message}`,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
clearTimeout(timeoutHandle);
|
|
241
|
+
}
|
|
242
|
+
if (finishedNaturally) {
|
|
243
|
+
// Clear any stale auth/quota/rate-limit state — the dispatch just
|
|
244
|
+
// succeeded, so any prior badge on the home OpenRouter card no
|
|
245
|
+
// longer reflects reality. Best-effort.
|
|
246
|
+
(0, cli_health_js_1.recordHealth)({
|
|
247
|
+
lineage: 'openrouter',
|
|
248
|
+
status: 'healthy',
|
|
249
|
+
}).catch(() => {
|
|
250
|
+
/* health write is informational; ignore */
|
|
251
|
+
});
|
|
252
|
+
yield {
|
|
253
|
+
type: 'message_done',
|
|
254
|
+
finalText: accumulated,
|
|
255
|
+
...(usage ? { usage } : {}),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Find the next event boundary in the SSE buffer (`\n\n` or `\r\n\r\n`),
|
|
261
|
+
* returning the index AT the boundary (caller slices [0, boundary] to
|
|
262
|
+
* extract the event, then advances past the boundary's newlines). Returns
|
|
263
|
+
* -1 when no complete event is buffered.
|
|
264
|
+
*/
|
|
265
|
+
function findEventBoundary(buf) {
|
|
266
|
+
const lf = buf.indexOf('\n\n');
|
|
267
|
+
const crlf = buf.indexOf('\r\n\r\n');
|
|
268
|
+
if (lf === -1)
|
|
269
|
+
return crlf;
|
|
270
|
+
if (crlf === -1)
|
|
271
|
+
return lf;
|
|
272
|
+
return Math.min(lf, crlf);
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=openrouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../../src/daemon/agents/openrouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseClaude = parseClaude;
|
|
4
|
+
const shared_js_1 = require("./shared.js");
|
|
5
|
+
function parseClaude(line) {
|
|
6
|
+
const obj = (0, shared_js_1.tryJson)(line);
|
|
7
|
+
if (!obj || typeof obj !== 'object')
|
|
8
|
+
return [];
|
|
9
|
+
const t = obj.type;
|
|
10
|
+
// Final result line — emit message_done with the assembled text.
|
|
11
|
+
if (t === 'result') {
|
|
12
|
+
const subtype = obj.subtype;
|
|
13
|
+
const isError = obj.is_error;
|
|
14
|
+
if (subtype === 'success' && !isError) {
|
|
15
|
+
return [{ type: 'message_done', finalText: String(obj.result ?? '') }];
|
|
16
|
+
}
|
|
17
|
+
return [
|
|
18
|
+
{
|
|
19
|
+
type: 'error',
|
|
20
|
+
kind: 'claude_result_error',
|
|
21
|
+
message: String(obj.result ?? obj.api_error_status ?? 'Claude reported error'),
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
if (t === 'stream_event') {
|
|
26
|
+
const event = obj.event ?? {};
|
|
27
|
+
const eventType = event.type;
|
|
28
|
+
if (eventType === 'content_block_delta') {
|
|
29
|
+
const delta = event.delta ?? {};
|
|
30
|
+
if (delta.type === 'text_delta' && typeof delta.text === 'string') {
|
|
31
|
+
return [{ type: 'text_delta', text: delta.text }];
|
|
32
|
+
}
|
|
33
|
+
// Tool input deltas (input_json_delta) aren't surfaced — the
|
|
34
|
+
// tool_call_start carries the initial input snapshot which is
|
|
35
|
+
// enough for UI ("called Read on /path/x.ts").
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
if (eventType === 'content_block_start') {
|
|
39
|
+
const block = event.content_block ?? {};
|
|
40
|
+
if (block.type === 'tool_use') {
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
type: 'tool_call_start',
|
|
44
|
+
tool: typeof block.name === 'string' ? block.name : 'unknown',
|
|
45
|
+
input: block.input,
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
// We don't emit tool_call_end from Claude's stream — Claude emits a
|
|
52
|
+
// tool_result message later that we'd need to track separately.
|
|
53
|
+
// Skipping for now; UI shows tool_call_start in the trace, which is
|
|
54
|
+
// enough for live progress.
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
// System (init, hook events, status), assistant (assembled message),
|
|
58
|
+
// rate_limit_event — silently ignored. Future: surface
|
|
59
|
+
// rate_limit_event into the cli-health module so cockpit can show
|
|
60
|
+
// "Claude resets at <time>" without waiting for a quota_exhausted.
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../../src/daemon/agents/parsers/claude.ts"],"names":[],"mappings":";;AAmBA,kCA+DC;AAjED,2CAAsC;AAEtC,SAAgB,WAAW,CAAC,IAAY;IACtC,MAAM,GAAG,GAAG,IAAA,mBAAO,EAAC,IAAI,CAAwC,CAAC;IACjE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAE/C,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC;IAEnB,iEAAiE;IACjE,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,GAAG,CAAC,OAA6B,CAAC;QAClD,MAAM,OAAO,GAAG,GAAG,CAAC,QAA+B,CAAC;QACpD,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;YACtC,OAAO,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,OAAO;YACL;gBACE,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,qBAAqB;gBAC3B,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,gBAAgB,IAAI,uBAAuB,CAAC;aAC/E;SACF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAK,cAAc,EAAE,CAAC;QACzB,MAAM,KAAK,GAAI,GAAG,CAAC,KAA6C,IAAI,EAAE,CAAC;QACvE,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC;QAE7B,IAAI,SAAS,KAAK,qBAAqB,EAAE,CAAC;YACxC,MAAM,KAAK,GAAI,KAAK,CAAC,KAA6C,IAAI,EAAE,CAAC;YACzE,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAClE,OAAO,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,6DAA6D;YAC7D,8DAA8D;YAC9D,+CAA+C;YAC/C,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,SAAS,KAAK,qBAAqB,EAAE,CAAC;YACxC,MAAM,KAAK,GAAI,KAAK,CAAC,aAAqD,IAAI,EAAE,CAAC;YACjF,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,OAAO;oBACL;wBACE,IAAI,EAAE,iBAAiB;wBACvB,IAAI,EAAE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;wBAC7D,KAAK,EAAE,KAAK,CAAC,KAAK;qBACnB;iBACF,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,oEAAoE;QACpE,gEAAgE;QAChE,oEAAoE;QACpE,4BAA4B;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,qEAAqE;IACrE,uDAAuD;IACvD,kEAAkE;IAClE,mEAAmE;IACnE,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseCodex = parseCodex;
|
|
4
|
+
exports.parseCodexExit = parseCodexExit;
|
|
5
|
+
// Anchored to the literal `ERROR:` prefix codex emits. The loose
|
|
6
|
+
// alternation /upgrade to plus/i / /try again at/i without an anchor
|
|
7
|
+
// would false-match prompts that legitimately echo those phrases (codex
|
|
8
|
+
// `exec` echoes the user prompt back into stderr, so a code review brief
|
|
9
|
+
// mentioning "try again at midnight" was a real hazard). Round-1
|
|
10
|
+
// review-only dogfood (PR #9) flagged this.
|
|
11
|
+
const CODEX_QUOTA_LINE = /ERROR:[^\n]*(usage limit|upgrade to plus|try again at)/i;
|
|
12
|
+
function looksLikeCodexQuota(text) {
|
|
13
|
+
return CODEX_QUOTA_LINE.test(text);
|
|
14
|
+
}
|
|
15
|
+
function parseCodex(_line) {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
function parseCodexExit(fullStdout, fullStderr = '', code = 0) {
|
|
19
|
+
const stdoutTrimmed = fullStdout.trim();
|
|
20
|
+
if (code === 0 && stdoutTrimmed.length > 0) {
|
|
21
|
+
return [{ type: 'message_done', finalText: fullStdout }];
|
|
22
|
+
}
|
|
23
|
+
if (looksLikeCodexQuota(fullStderr) || looksLikeCodexQuota(fullStdout)) {
|
|
24
|
+
// Pull the literal ERROR line for a usable message; fall back to a
|
|
25
|
+
// truncated tail so we never lose the signal.
|
|
26
|
+
const errorLine = [fullStderr, fullStdout]
|
|
27
|
+
.flatMap((s) => s.split('\n'))
|
|
28
|
+
.find((l) => /ERROR:.*usage limit/i.test(l))
|
|
29
|
+
?.trim() ?? 'codex usage limit reached';
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
type: 'error',
|
|
33
|
+
kind: 'quota_exhausted',
|
|
34
|
+
message: errorLine,
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
if (code !== null && code !== 0) {
|
|
39
|
+
const tail = (fullStderr.trim() || fullStdout.trim()).slice(-300);
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
type: 'error',
|
|
43
|
+
kind: 'cli_error',
|
|
44
|
+
message: tail.length > 0 ? tail : `codex exited ${code} with no output`,
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
// code===0 + empty stdout — preserve old "emit nothing" behavior.
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../../src/daemon/agents/parsers/codex.ts"],"names":[],"mappings":";;AA6BA,gCAEC;AAED,wCAyCC;AAzDD,iEAAiE;AACjE,qEAAqE;AACrE,wEAAwE;AACxE,yEAAyE;AACzE,iEAAiE;AACjE,4CAA4C;AAC5C,MAAM,gBAAgB,GAAG,yDAAyD,CAAC;AAEnF,SAAS,mBAAmB,CAAC,IAAY;IACvC,OAAO,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,SAAgB,UAAU,CAAC,KAAa;IACtC,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAgB,cAAc,CAC5B,UAAkB,EAClB,UAAU,GAAG,EAAE,EACf,OAAsB,CAAC;IAEvB,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAExC,IAAI,IAAI,KAAK,CAAC,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,OAAO,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,mBAAmB,CAAC,UAAU,CAAC,IAAI,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC;QACvE,mEAAmE;QACnE,8CAA8C;QAC9C,MAAM,SAAS,GACb,CAAC,UAAU,EAAE,UAAU,CAAC;aACrB,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;aAC7B,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC5C,EAAE,IAAI,EAAE,IAAI,2BAA2B,CAAC;QAC5C,OAAO;YACL;gBACE,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,SAAS;aACnB;SACF,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;QAClE,OAAO;YACL;gBACE,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,IAAI,iBAAiB;aACxE;SACF,CAAC;IACJ,CAAC;IAED,kEAAkE;IAClE,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseGemini = parseGemini;
|
|
4
|
+
exports.parseGeminiExit = parseGeminiExit;
|
|
5
|
+
const shared_js_1 = require("./shared.js");
|
|
6
|
+
function parseGemini(line) {
|
|
7
|
+
const obj = (0, shared_js_1.tryJson)(line);
|
|
8
|
+
if (!obj)
|
|
9
|
+
return [];
|
|
10
|
+
const t = obj.type;
|
|
11
|
+
if (t === 'message' && obj.role === 'assistant' && obj.delta === true) {
|
|
12
|
+
if (typeof obj.content === 'string' && obj.content.length > 0) {
|
|
13
|
+
return [{ type: 'text_delta', text: obj.content }];
|
|
14
|
+
}
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
// Tool calls (functionCall). Best-effort detection on common shape variants.
|
|
18
|
+
if (t === 'message' && obj.functionCall) {
|
|
19
|
+
const fc = obj.functionCall;
|
|
20
|
+
return [
|
|
21
|
+
{
|
|
22
|
+
type: 'tool_call_start',
|
|
23
|
+
tool: typeof fc.name === 'string' ? fc.name : 'unknown',
|
|
24
|
+
input: fc.args,
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
if (t === 'result') {
|
|
29
|
+
const status = obj.status;
|
|
30
|
+
if (status === 'success') {
|
|
31
|
+
return [{ type: 'message_done', finalText: '' }];
|
|
32
|
+
}
|
|
33
|
+
const message = extractGeminiErrorMessage(obj, status);
|
|
34
|
+
// Quota exhaustion is the single most common gemini failure on a
|
|
35
|
+
// free or low-tier account (we hit it ourselves during dogfood).
|
|
36
|
+
// Promote it from the generic "gemini_result_error" to a dedicated
|
|
37
|
+
// kind so the cockpit can render a useful card — including the
|
|
38
|
+
// "resets in Nh Nm" hint we extract below.
|
|
39
|
+
if (looksLikeQuotaExhausted(message) || looksLikeQuotaExhausted(JSON.stringify(obj))) {
|
|
40
|
+
const reset = extractResetWindow(message) ?? extractResetWindow(JSON.stringify(obj));
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
type: 'error',
|
|
44
|
+
kind: 'quota_exhausted',
|
|
45
|
+
message: reset
|
|
46
|
+
? `Gemini quota exhausted — resets in ${reset}.`
|
|
47
|
+
: `Gemini quota exhausted.${message ? ` ${message}` : ''}`,
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
return [
|
|
52
|
+
{
|
|
53
|
+
type: 'error',
|
|
54
|
+
kind: 'gemini_result_error',
|
|
55
|
+
message,
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
// init, user-echo message, anything else — silently ignore.
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Pull a human-readable error message out of gemini's `result` line.
|
|
64
|
+
*
|
|
65
|
+
* The CLI nests the actual upstream API error a few layers deep:
|
|
66
|
+
* { type: 'result', status: 'error',
|
|
67
|
+
* error: { message: '...', cause: { message: '...', code: 429 } } }
|
|
68
|
+
* — but older builds put it at `obj.error` (string) or `obj.message`
|
|
69
|
+
* (string). Walk the common shapes in order of specificity.
|
|
70
|
+
*
|
|
71
|
+
* Pre-fix this function returned the bare "Gemini result status=error"
|
|
72
|
+
* string for every quota / 5xx / 4xx — useless to the user. Now it
|
|
73
|
+
* returns the actual upstream message when present.
|
|
74
|
+
*/
|
|
75
|
+
function extractGeminiErrorMessage(obj, status) {
|
|
76
|
+
if (typeof obj.error === 'string')
|
|
77
|
+
return obj.error;
|
|
78
|
+
if (typeof obj.message === 'string')
|
|
79
|
+
return obj.message;
|
|
80
|
+
const err = obj.error;
|
|
81
|
+
if (err && typeof err === 'object') {
|
|
82
|
+
const e = err;
|
|
83
|
+
if (typeof e.message === 'string' && e.message.length > 0)
|
|
84
|
+
return e.message;
|
|
85
|
+
const cause = e.cause;
|
|
86
|
+
if (cause && typeof cause === 'object') {
|
|
87
|
+
const c = cause;
|
|
88
|
+
if (typeof c.message === 'string' && c.message.length > 0)
|
|
89
|
+
return c.message;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return `Gemini result status=${status ?? 'unknown'}`;
|
|
93
|
+
}
|
|
94
|
+
function looksLikeQuotaExhausted(s) {
|
|
95
|
+
if (!s)
|
|
96
|
+
return false;
|
|
97
|
+
return /quota|exhausted|429|capacity|rate.?limit|QUOTA_EXHAUSTED/i.test(s);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Extract a "Nh Nm Ns" reset window from gemini's quota error string
|
|
101
|
+
* (formats seen in practice: "resets after 8h14m16s", "in 23m", "1d
|
|
102
|
+
* 2h"). Returns the matched substring or null. Best-effort — when the
|
|
103
|
+
* upstream message format changes we fall through to the generic
|
|
104
|
+
* "quota exhausted" message.
|
|
105
|
+
*/
|
|
106
|
+
function extractResetWindow(s) {
|
|
107
|
+
if (!s)
|
|
108
|
+
return null;
|
|
109
|
+
const m = s.match(/(?:reset|resets|in)\s*(?:after|in)?\s*(\d+\s*(?:d|h|m|s)\s*)+/i);
|
|
110
|
+
if (!m)
|
|
111
|
+
return null;
|
|
112
|
+
return m[0]
|
|
113
|
+
.replace(/^(?:reset|resets|in)\s*(?:after|in)?\s*/i, '')
|
|
114
|
+
.trim();
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* On-exit hook for the gemini shim. Scans stderr for quota messages
|
|
118
|
+
* the JSON result line doesn't carry — gemini-cli logs the upstream
|
|
119
|
+
* 429 to stderr only when its underlying SDK throws (verified by the
|
|
120
|
+
* stack trace seen in dogfood). Without this the user sees just
|
|
121
|
+
* "Gemini result status=error" and has no idea the issue is
|
|
122
|
+
* "wait 8h for the quota to reset."
|
|
123
|
+
*
|
|
124
|
+
* Returns at most one event. Falls through to no-op when stderr
|
|
125
|
+
* doesn't match — the existing `cli_failed` branch in headless.ts
|
|
126
|
+
* still surfaces the raw tail so we never silently swallow info.
|
|
127
|
+
*/
|
|
128
|
+
function parseGeminiExit(_fullStdout, fullStderr, _code) {
|
|
129
|
+
if (!fullStderr)
|
|
130
|
+
return [];
|
|
131
|
+
if (!looksLikeQuotaExhausted(fullStderr))
|
|
132
|
+
return [];
|
|
133
|
+
const reset = extractResetWindow(fullStderr);
|
|
134
|
+
return [
|
|
135
|
+
{
|
|
136
|
+
type: 'error',
|
|
137
|
+
kind: 'quota_exhausted',
|
|
138
|
+
message: reset
|
|
139
|
+
? `Gemini quota exhausted — resets in ${reset}.`
|
|
140
|
+
: `Gemini quota exhausted (Google API returned 429).`,
|
|
141
|
+
},
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../../src/daemon/agents/parsers/gemini.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Per-CLI stream-json parsers — barrel re-exports.
|
|
4
|
+
*
|
|
5
|
+
* Each parser is a pure function: takes a single line of stdout (or, for
|
|
6
|
+
* codex/opencode-exit, the whole stdout once), returns zero or more
|
|
7
|
+
* AgentEvents. No I/O, no state — unit-testable in isolation from the
|
|
8
|
+
* spawn/transport layer.
|
|
9
|
+
*
|
|
10
|
+
* To add a new CLI: capture sample output, write the parser in its own
|
|
11
|
+
* file under `parsers/`, add a vitest fixture under `tests/`, then have
|
|
12
|
+
* the shim call `spawnHeadless({ parseLine: parseX })`.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.parseOpenRouterSSE = exports.parseCodexExit = exports.parseCodex = exports.parseOpencodeExit = exports.parseOpencode = exports.parseKimi = exports.parseGeminiExit = exports.parseGemini = exports.parseClaude = void 0;
|
|
16
|
+
var claude_js_1 = require("./claude.js");
|
|
17
|
+
Object.defineProperty(exports, "parseClaude", { enumerable: true, get: function () { return claude_js_1.parseClaude; } });
|
|
18
|
+
var gemini_js_1 = require("./gemini.js");
|
|
19
|
+
Object.defineProperty(exports, "parseGemini", { enumerable: true, get: function () { return gemini_js_1.parseGemini; } });
|
|
20
|
+
Object.defineProperty(exports, "parseGeminiExit", { enumerable: true, get: function () { return gemini_js_1.parseGeminiExit; } });
|
|
21
|
+
var kimi_js_1 = require("./kimi.js");
|
|
22
|
+
Object.defineProperty(exports, "parseKimi", { enumerable: true, get: function () { return kimi_js_1.parseKimi; } });
|
|
23
|
+
var opencode_js_1 = require("./opencode.js");
|
|
24
|
+
Object.defineProperty(exports, "parseOpencode", { enumerable: true, get: function () { return opencode_js_1.parseOpencode; } });
|
|
25
|
+
Object.defineProperty(exports, "parseOpencodeExit", { enumerable: true, get: function () { return opencode_js_1.parseOpencodeExit; } });
|
|
26
|
+
var codex_js_1 = require("./codex.js");
|
|
27
|
+
Object.defineProperty(exports, "parseCodex", { enumerable: true, get: function () { return codex_js_1.parseCodex; } });
|
|
28
|
+
Object.defineProperty(exports, "parseCodexExit", { enumerable: true, get: function () { return codex_js_1.parseCodexExit; } });
|
|
29
|
+
var openrouter_js_1 = require("./openrouter.js");
|
|
30
|
+
Object.defineProperty(exports, "parseOpenRouterSSE", { enumerable: true, get: function () { return openrouter_js_1.parseOpenRouterSSE; } });
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/daemon/agents/parsers/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAEH,yCAA0C;AAAjC,wGAAA,WAAW,OAAA;AACpB,yCAA2D;AAAlD,wGAAA,WAAW,OAAA;AAAE,4GAAA,eAAe,OAAA;AACrC,qCAAsC;AAA7B,oGAAA,SAAS,OAAA;AAClB,6CAAiE;AAAxD,4GAAA,aAAa,OAAA;AAAE,gHAAA,iBAAiB,OAAA;AACzC,uCAAwD;AAA/C,sGAAA,UAAU,OAAA;AAAE,0GAAA,cAAc,OAAA;AACnC,iDAAqD;AAA5C,mHAAA,kBAAkB,OAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseKimi = parseKimi;
|
|
4
|
+
const claude_js_1 = require("./claude.js");
|
|
5
|
+
function parseKimi(line) {
|
|
6
|
+
return (0, claude_js_1.parseClaude)(line);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=kimi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kimi.js","sourceRoot":"","sources":["../../../../src/daemon/agents/parsers/kimi.ts"],"names":[],"mappings":";;AASA,8BAEC;AAJD,2CAA0C;AAE1C,SAAgB,SAAS,CAAC,IAAY;IACpC,OAAO,IAAA,uBAAW,EAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
|