@wrenai/genbi 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +141 -0
- package/bin/genbi.mjs +31 -0
- package/dist/assets/echarts-LTFC-ysd.js +40 -0
- package/dist/assets/index-Bo--QMUN.js +441 -0
- package/dist/assets/index-Xs4q7pNo.css +1 -0
- package/dist/index.html +14 -0
- package/dist/wrenai_logo.png +0 -0
- package/dist/wrenai_logo_white.png +0 -0
- package/dist-server/harness/auth/detect.d.ts +18 -0
- package/dist-server/harness/auth/detect.js +37 -0
- package/dist-server/harness/auth/index.d.ts +4 -0
- package/dist-server/harness/auth/index.js +2 -0
- package/dist-server/harness/auth/probe.d.ts +18 -0
- package/dist-server/harness/auth/probe.js +52 -0
- package/dist-server/harness/auth/types.d.ts +42 -0
- package/dist-server/harness/auth/types.js +9 -0
- package/dist-server/harness/bundle/loader.d.ts +32 -0
- package/dist-server/harness/bundle/loader.js +43 -0
- package/dist-server/harness/bundle/schema.d.ts +199 -0
- package/dist-server/harness/bundle/schema.js +127 -0
- package/dist-server/harness/bundle/version.d.ts +10 -0
- package/dist-server/harness/bundle/version.js +43 -0
- package/dist-server/harness/capability/gate.d.ts +6 -0
- package/dist-server/harness/capability/gate.js +29 -0
- package/dist-server/harness/capability/registry.d.ts +6 -0
- package/dist-server/harness/capability/registry.js +17 -0
- package/dist-server/harness/cli-args.d.ts +123 -0
- package/dist-server/harness/cli-args.js +247 -0
- package/dist-server/harness/cli.d.ts +2 -0
- package/dist-server/harness/cli.js +151 -0
- package/dist-server/harness/compile/cache.d.ts +23 -0
- package/dist-server/harness/compile/cache.js +109 -0
- package/dist-server/harness/compile/compose-profile.d.ts +34 -0
- package/dist-server/harness/compile/compose-profile.js +95 -0
- package/dist-server/harness/compile/errors.d.ts +22 -0
- package/dist-server/harness/compile/errors.js +41 -0
- package/dist-server/harness/compile/fingerprint.d.ts +22 -0
- package/dist-server/harness/compile/fingerprint.js +84 -0
- package/dist-server/harness/compile/index.d.ts +8 -0
- package/dist-server/harness/compile/index.js +7 -0
- package/dist-server/harness/compile/pipeline.d.ts +66 -0
- package/dist-server/harness/compile/pipeline.js +176 -0
- package/dist-server/harness/compile/resolve-binary.d.ts +55 -0
- package/dist-server/harness/compile/resolve-binary.js +133 -0
- package/dist-server/harness/compile/types.d.ts +107 -0
- package/dist-server/harness/compile/types.js +1 -0
- package/dist-server/harness/compile/warble-identity.d.ts +12 -0
- package/dist-server/harness/compile/warble-identity.js +33 -0
- package/dist-server/harness/compliance/gate.d.ts +35 -0
- package/dist-server/harness/compliance/gate.js +48 -0
- package/dist-server/harness/compliance/index.d.ts +2 -0
- package/dist-server/harness/compliance/index.js +1 -0
- package/dist-server/harness/compliance/types.d.ts +16 -0
- package/dist-server/harness/compliance/types.js +1 -0
- package/dist-server/harness/events/emitter.d.ts +34 -0
- package/dist-server/harness/events/emitter.js +25 -0
- package/dist-server/harness/events/index.d.ts +4 -0
- package/dist-server/harness/events/index.js +2 -0
- package/dist-server/harness/events/sse.d.ts +20 -0
- package/dist-server/harness/events/sse.js +48 -0
- package/dist-server/harness/events/types.d.ts +131 -0
- package/dist-server/harness/events/types.js +1 -0
- package/dist-server/harness/exec/errors.d.ts +16 -0
- package/dist-server/harness/exec/errors.js +29 -0
- package/dist-server/harness/exec/index.d.ts +5 -0
- package/dist-server/harness/exec/index.js +2 -0
- package/dist-server/harness/exec/local.d.ts +32 -0
- package/dist-server/harness/exec/local.js +134 -0
- package/dist-server/harness/exec/policy.d.ts +12 -0
- package/dist-server/harness/exec/policy.js +1 -0
- package/dist-server/harness/exec/types.d.ts +63 -0
- package/dist-server/harness/exec/types.js +1 -0
- package/dist-server/harness/guardrails/index.d.ts +2 -0
- package/dist-server/harness/guardrails/index.js +1 -0
- package/dist-server/harness/guardrails/policy.d.ts +45 -0
- package/dist-server/harness/guardrails/policy.js +57 -0
- package/dist-server/harness/index.d.ts +37 -0
- package/dist-server/harness/index.js +19 -0
- package/dist-server/harness/loop/errors.d.ts +53 -0
- package/dist-server/harness/loop/errors.js +72 -0
- package/dist-server/harness/loop/executor.d.ts +123 -0
- package/dist-server/harness/loop/executor.js +380 -0
- package/dist-server/harness/loop/guard.d.ts +16 -0
- package/dist-server/harness/loop/guard.js +1 -0
- package/dist-server/harness/loop/index.d.ts +5 -0
- package/dist-server/harness/loop/index.js +3 -0
- package/dist-server/harness/native-producer/index.d.ts +109 -0
- package/dist-server/harness/native-producer/index.js +302 -0
- package/dist-server/harness/npm-package-resolve.d.ts +28 -0
- package/dist-server/harness/npm-package-resolve.js +47 -0
- package/dist-server/harness/providers/adapters/anthropic.d.ts +7 -0
- package/dist-server/harness/providers/adapters/anthropic.js +6 -0
- package/dist-server/harness/providers/adapters/mock.d.ts +4 -0
- package/dist-server/harness/providers/adapters/mock.js +5 -0
- package/dist-server/harness/providers/adapters/openai-compatible.d.ts +10 -0
- package/dist-server/harness/providers/adapters/openai-compatible.js +10 -0
- package/dist-server/harness/providers/binding.d.ts +23 -0
- package/dist-server/harness/providers/binding.js +13 -0
- package/dist-server/harness/providers/errors.d.ts +6 -0
- package/dist-server/harness/providers/errors.js +12 -0
- package/dist-server/harness/providers/index.d.ts +18 -0
- package/dist-server/harness/providers/index.js +22 -0
- package/dist-server/harness/providers/registry.d.ts +16 -0
- package/dist-server/harness/providers/registry.js +24 -0
- package/dist-server/harness/render/envelope.d.ts +145 -0
- package/dist-server/harness/render/envelope.js +428 -0
- package/dist-server/harness/render/errors.d.ts +33 -0
- package/dist-server/harness/render/errors.js +46 -0
- package/dist-server/harness/render/index.d.ts +5 -0
- package/dist-server/harness/render/index.js +3 -0
- package/dist-server/harness/render/validate.d.ts +13 -0
- package/dist-server/harness/render/validate.js +88 -0
- package/dist-server/harness/route/adapter-spec.d.ts +40 -0
- package/dist-server/harness/route/adapter-spec.js +61 -0
- package/dist-server/harness/route/agent-sdk-cli.d.ts +30 -0
- package/dist-server/harness/route/agent-sdk-cli.js +86 -0
- package/dist-server/harness/route/agent-sdk-manifest.d.ts +31 -0
- package/dist-server/harness/route/agent-sdk-manifest.js +56 -0
- package/dist-server/harness/route/artifact-content.d.ts +53 -0
- package/dist-server/harness/route/artifact-content.js +83 -0
- package/dist-server/harness/route/chat-event-mapper.d.ts +95 -0
- package/dist-server/harness/route/chat-event-mapper.js +164 -0
- package/dist-server/harness/route/codex-ask-events.d.ts +25 -0
- package/dist-server/harness/route/codex-ask-events.js +395 -0
- package/dist-server/harness/route/codex-ask.d.ts +15 -0
- package/dist-server/harness/route/codex-ask.js +242 -0
- package/dist-server/harness/route/codex-local-cli.d.ts +20 -0
- package/dist-server/harness/route/codex-local-cli.js +78 -0
- package/dist-server/harness/route/codex-local-manifest.d.ts +22 -0
- package/dist-server/harness/route/codex-local-manifest.js +180 -0
- package/dist-server/harness/route/describe.d.ts +54 -0
- package/dist-server/harness/route/describe.js +84 -0
- package/dist-server/harness/route/dispatched.d.ts +138 -0
- package/dist-server/harness/route/dispatched.js +339 -0
- package/dist-server/harness/route/in-process.d.ts +43 -0
- package/dist-server/harness/route/in-process.js +106 -0
- package/dist-server/harness/route/index.d.ts +19 -0
- package/dist-server/harness/route/index.js +12 -0
- package/dist-server/harness/route/profile-source.d.ts +37 -0
- package/dist-server/harness/route/profile-source.js +76 -0
- package/dist-server/harness/route/route.d.ts +33 -0
- package/dist-server/harness/route/route.js +114 -0
- package/dist-server/harness/route/tier-binding.d.ts +36 -0
- package/dist-server/harness/route/tier-binding.js +63 -0
- package/dist-server/harness/route/types.d.ts +286 -0
- package/dist-server/harness/route/types.js +1 -0
- package/dist-server/harness/session/errors.d.ts +4 -0
- package/dist-server/harness/session/errors.js +7 -0
- package/dist-server/harness/session/gate.d.ts +11 -0
- package/dist-server/harness/session/gate.js +13 -0
- package/dist-server/harness/session/index.d.ts +5 -0
- package/dist-server/harness/session/index.js +3 -0
- package/dist-server/harness/session/run.d.ts +60 -0
- package/dist-server/harness/session/run.js +333 -0
- package/dist-server/harness/session/types.d.ts +29 -0
- package/dist-server/harness/session/types.js +1 -0
- package/dist-server/harness/setup/codex-events.d.ts +12 -0
- package/dist-server/harness/setup/codex-events.js +108 -0
- package/dist-server/harness/setup/runner.d.ts +497 -0
- package/dist-server/harness/setup/runner.js +1314 -0
- package/dist-server/harness/tools/errors.d.ts +107 -0
- package/dist-server/harness/tools/errors.js +141 -0
- package/dist-server/harness/tools/index.d.ts +13 -0
- package/dist-server/harness/tools/index.js +8 -0
- package/dist-server/harness/tools/mcp.d.ts +26 -0
- package/dist-server/harness/tools/mcp.js +15 -0
- package/dist-server/harness/tools/native.d.ts +179 -0
- package/dist-server/harness/tools/native.js +322 -0
- package/dist-server/harness/tools/parse.d.ts +14 -0
- package/dist-server/harness/tools/parse.js +18 -0
- package/dist-server/harness/tools/resolve-wren-binary.d.ts +12 -0
- package/dist-server/harness/tools/resolve-wren-binary.js +21 -0
- package/dist-server/harness/tools/resolve.d.ts +51 -0
- package/dist-server/harness/tools/resolve.js +79 -0
- package/dist-server/harness/tools/setup-native.d.ts +84 -0
- package/dist-server/harness/tools/setup-native.js +353 -0
- package/dist-server/harness/tools/wiring.d.ts +10 -0
- package/dist-server/harness/tools/wiring.js +16 -0
- package/dist-server/providers/setup.provider.yaml +31 -0
- package/dist-server/providers/wren.provider.yaml +33 -0
- package/dist-server/server/adopt.d.ts +87 -0
- package/dist-server/server/adopt.js +263 -0
- package/dist-server/server/app.d.ts +6 -0
- package/dist-server/server/app.js +2521 -0
- package/dist-server/server/auth-choice.d.ts +16 -0
- package/dist-server/server/auth-choice.js +36 -0
- package/dist-server/server/bin.d.ts +2 -0
- package/dist-server/server/bin.js +601 -0
- package/dist-server/server/bootstrap-project-binding.d.ts +31 -0
- package/dist-server/server/bootstrap-project-binding.js +71 -0
- package/dist-server/server/clarify.d.ts +10 -0
- package/dist-server/server/clarify.js +17 -0
- package/dist-server/server/codex-setup-mcp.d.ts +2 -0
- package/dist-server/server/codex-setup-mcp.js +147 -0
- package/dist-server/server/compose.d.ts +89 -0
- package/dist-server/server/compose.js +271 -0
- package/dist-server/server/conn-config.d.ts +30 -0
- package/dist-server/server/conn-config.js +253 -0
- package/dist-server/server/context-files.d.ts +12 -0
- package/dist-server/server/context-files.js +117 -0
- package/dist-server/server/context-map.d.ts +30 -0
- package/dist-server/server/context-map.js +95 -0
- package/dist-server/server/context-source.d.ts +68 -0
- package/dist-server/server/context-source.js +85 -0
- package/dist-server/server/db.d.ts +862 -0
- package/dist-server/server/db.js +1839 -0
- package/dist-server/server/enrichment-runner.d.ts +184 -0
- package/dist-server/server/enrichment-runner.js +213 -0
- package/dist-server/server/enrichment-verify.d.ts +73 -0
- package/dist-server/server/enrichment-verify.js +290 -0
- package/dist-server/server/enrichment.d.ts +232 -0
- package/dist-server/server/enrichment.js +199 -0
- package/dist-server/server/env-detect.d.ts +8 -0
- package/dist-server/server/env-detect.js +17 -0
- package/dist-server/server/env-field-hints.d.ts +46 -0
- package/dist-server/server/env-field-hints.js +48 -0
- package/dist-server/server/fold.d.ts +133 -0
- package/dist-server/server/fold.js +407 -0
- package/dist-server/server/harness-profile-sources.d.ts +3 -0
- package/dist-server/server/harness-profile-sources.js +24 -0
- package/dist-server/server/harness.d.ts +19 -0
- package/dist-server/server/harness.js +439 -0
- package/dist-server/server/impact.d.ts +18 -0
- package/dist-server/server/impact.js +85 -0
- package/dist-server/server/interactive-terminal.d.ts +175 -0
- package/dist-server/server/interactive-terminal.js +336 -0
- package/dist-server/server/native-artifacts.d.ts +1004 -0
- package/dist-server/server/native-artifacts.js +564 -0
- package/dist-server/server/native-dispatch-registry.d.ts +42 -0
- package/dist-server/server/native-dispatch-registry.js +45 -0
- package/dist-server/server/native-producer-fence.d.ts +14 -0
- package/dist-server/server/native-producer-fence.js +48 -0
- package/dist-server/server/native-session-resume.d.ts +6 -0
- package/dist-server/server/native-session-resume.js +103 -0
- package/dist-server/server/native-session-workspace.d.ts +40 -0
- package/dist-server/server/native-session-workspace.js +175 -0
- package/dist-server/server/native-sessions.d.ts +374 -0
- package/dist-server/server/native-sessions.js +1517 -0
- package/dist-server/server/native-wren-runtime.d.ts +20 -0
- package/dist-server/server/native-wren-runtime.js +259 -0
- package/dist-server/server/node-pty-host.d.ts +31 -0
- package/dist-server/server/node-pty-host.js +100 -0
- package/dist-server/server/route-intent.d.ts +40 -0
- package/dist-server/server/route-intent.js +23 -0
- package/dist-server/server/runtime-binding.d.ts +52 -0
- package/dist-server/server/runtime-binding.js +258 -0
- package/dist-server/server/source-catalog.d.ts +84 -0
- package/dist-server/server/source-catalog.js +221 -0
- package/dist-server/server/source-driver.d.ts +35 -0
- package/dist-server/server/source-driver.js +124 -0
- package/dist-server/server/spa.d.ts +2 -0
- package/dist-server/server/spa.js +51 -0
- package/dist-server/server/subscription-model-catalog.d.ts +27 -0
- package/dist-server/server/subscription-model-catalog.js +203 -0
- package/dist-server/server/turn.d.ts +249 -0
- package/dist-server/server/turn.js +1074 -0
- package/dist-server/server/wire-types.d.ts +799 -0
- package/dist-server/server/wire-types.js +1 -0
- package/dist-server/server/wren-home.d.ts +19 -0
- package/dist-server/server/wren-home.js +33 -0
- package/dist-server/server/wren-profiles.d.ts +43 -0
- package/dist-server/server/wren-profiles.js +123 -0
- package/package.json +93 -0
- package/profiles/genbi-default/context/binding.yml +9 -0
- package/profiles/genbi-default/ir.golden.json +506 -0
- package/profiles/genbi-default/profile.yml +16 -0
- package/profiles/genbi-enrich-context/components/apply_enrichment/component.yml +42 -0
- package/profiles/genbi-enrich-context/components/draft_enrichment/component.yml +30 -0
- package/profiles/genbi-enrich-context/components/draft_enrichment/steps/draft.md +34 -0
- package/profiles/genbi-enrich-context/components/inspect_context/component.yml +32 -0
- package/profiles/genbi-enrich-context/components/inspect_context/steps/inspect.md +13 -0
- package/profiles/genbi-enrich-context/context/binding.yml +4 -0
- package/profiles/genbi-enrich-context/ir.golden.json +302 -0
- package/profiles/genbi-enrich-context/profile.yml +15 -0
- package/profiles/genbi-monitor/context/binding.yml +7 -0
- package/profiles/genbi-monitor/ir.golden.json +188 -0
- package/profiles/genbi-monitor/profile.yml +27 -0
- package/profiles/genbi-setup/components/build_context/component.yml +44 -0
- package/profiles/genbi-setup/components/build_context/steps/build.md +14 -0
- package/profiles/genbi-setup/components/connect_source/component.yml +51 -0
- package/profiles/genbi-setup/components/connect_source/steps/connect.md +23 -0
- package/profiles/genbi-setup/context/binding.yml +8 -0
- package/profiles/genbi-setup/ir.golden.json +140 -0
- package/profiles/genbi-setup/profile.yml +18 -0
- package/profiles/genbi-setup/raw/schema.json +5 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { accessSync, constants as fsConstants } from "node:fs";
|
|
3
|
+
import { createInterface } from "node:readline";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { enforceCompliance } from "../compliance/index.js";
|
|
6
|
+
import { compileProfile } from "../compile/pipeline.js";
|
|
7
|
+
import { createAgentEventEmitter } from "../events/index.js";
|
|
8
|
+
import { CodexAskEventMapper } from "./codex-ask-events.js";
|
|
9
|
+
import { resolveCodexLocalCli } from "./codex-local-cli.js";
|
|
10
|
+
import { CODEX_ASK_COMPONENTS, } from "./codex-local-manifest.js";
|
|
11
|
+
const CODEX_BILLING_ENV_KEYS = new Set([
|
|
12
|
+
"OPENAI_API_KEY",
|
|
13
|
+
"CODEX_API_KEY",
|
|
14
|
+
"AZURE_OPENAI_API_KEY",
|
|
15
|
+
"OPENAI_ORGANIZATION",
|
|
16
|
+
"OPENAI_ORG_ID",
|
|
17
|
+
"OPENAI_PROJECT",
|
|
18
|
+
"OPENAI_PROJECT_ID",
|
|
19
|
+
]);
|
|
20
|
+
const DEFAULT_CODEX_ASK_TIMEOUT_MS = 10 * 60 * 1000;
|
|
21
|
+
export function buildCodexAskArgs(cli, options) {
|
|
22
|
+
if (!options.question.trim())
|
|
23
|
+
throw new Error("Codex Ask question must not be empty");
|
|
24
|
+
return [
|
|
25
|
+
...cli.prefixArgs,
|
|
26
|
+
"dispatch",
|
|
27
|
+
options.irPath,
|
|
28
|
+
options.question,
|
|
29
|
+
"--component",
|
|
30
|
+
options.component ?? "answer_query",
|
|
31
|
+
"--project",
|
|
32
|
+
options.userProject,
|
|
33
|
+
"--codex-home",
|
|
34
|
+
options.codexHome,
|
|
35
|
+
"--orchestrator-model",
|
|
36
|
+
options.models.orchestrator,
|
|
37
|
+
"--cheap-model",
|
|
38
|
+
options.models.cheap,
|
|
39
|
+
"--strong-model",
|
|
40
|
+
options.models.strong,
|
|
41
|
+
"--server",
|
|
42
|
+
"wren",
|
|
43
|
+
"--server-command",
|
|
44
|
+
options.mcpServer.command,
|
|
45
|
+
...options.mcpServer.prefixArgs.flatMap((arg) => arg.startsWith("-") ? [`--server-arg=${arg}`] : ["--server-arg", arg]),
|
|
46
|
+
"--server-arg",
|
|
47
|
+
"serve",
|
|
48
|
+
"--server-arg",
|
|
49
|
+
"mcp",
|
|
50
|
+
"--server-arg=--project",
|
|
51
|
+
"--server-arg",
|
|
52
|
+
options.userProject,
|
|
53
|
+
"--server-arg=--quiet",
|
|
54
|
+
"--inspect-tool",
|
|
55
|
+
"get_context",
|
|
56
|
+
"--query-tool",
|
|
57
|
+
"run_sql",
|
|
58
|
+
"--timeout",
|
|
59
|
+
String(options.timeoutMs),
|
|
60
|
+
...(options.codexBin ? ["--codex-bin", options.codexBin] : []),
|
|
61
|
+
"--stream-json",
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
export async function runCodexAskDefault(options) {
|
|
65
|
+
enforceCompliance(options.authChoice, { deployment: options.deployment ?? "personal" });
|
|
66
|
+
if (options.authChoice.provider !== "codex") {
|
|
67
|
+
throw new Error("Codex Ask runner requires a Codex subscription auth choice");
|
|
68
|
+
}
|
|
69
|
+
const agentId = options.agentId ?? "answer_query";
|
|
70
|
+
if (!CODEX_ASK_COMPONENTS.includes(agentId)) {
|
|
71
|
+
throw new Error(`codex:local Ask does not support the "${agentId}" component`);
|
|
72
|
+
}
|
|
73
|
+
const component = agentId;
|
|
74
|
+
const models = resolveModels(options.codexModels);
|
|
75
|
+
const codexHome = options.codexHome?.trim();
|
|
76
|
+
if (!codexHome || !path.isAbsolute(codexHome)) {
|
|
77
|
+
throw new Error("Codex Ask requires an absolute WREN_HARNESS_CODEX_HOME for its dedicated authenticated session home");
|
|
78
|
+
}
|
|
79
|
+
if (options.signal?.aborted)
|
|
80
|
+
throw new Error("warble-codex-local Ask was cancelled before start");
|
|
81
|
+
const emitter = createAgentEventEmitter(options.onEvent);
|
|
82
|
+
emitter.emit({ kind: "run.start", mode: "B", agentId: component });
|
|
83
|
+
try {
|
|
84
|
+
const irPath = options.irPath ?? (await compileProfile({
|
|
85
|
+
profileSource: options.profileSource,
|
|
86
|
+
userProject: options.userProject,
|
|
87
|
+
mode: "native",
|
|
88
|
+
...(options.warbleBin !== undefined ? { warbleBin: options.warbleBin } : {}),
|
|
89
|
+
...(options.workDir !== undefined ? { workDir: options.workDir } : {}),
|
|
90
|
+
})).irPath;
|
|
91
|
+
if (options.signal?.aborted)
|
|
92
|
+
throw new Error("warble-codex-local Ask was cancelled during preparation");
|
|
93
|
+
const cli = options.codexLocalCli ?? (await resolveCodexLocalCli(options.codexLocalBin));
|
|
94
|
+
if (options.signal?.aborted)
|
|
95
|
+
throw new Error("warble-codex-local Ask was cancelled during preparation");
|
|
96
|
+
const mcpServer = options.mcpServer ?? { command: resolveExecutableOnPath("wren"), prefixArgs: [] };
|
|
97
|
+
if (options.signal?.aborted)
|
|
98
|
+
throw new Error("warble-codex-local Ask was cancelled during preparation");
|
|
99
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_CODEX_ASK_TIMEOUT_MS;
|
|
100
|
+
const args = buildCodexAskArgs(cli, {
|
|
101
|
+
irPath,
|
|
102
|
+
question: options.question,
|
|
103
|
+
userProject: options.userProject,
|
|
104
|
+
codexHome,
|
|
105
|
+
models,
|
|
106
|
+
mcpServer,
|
|
107
|
+
timeoutMs,
|
|
108
|
+
component,
|
|
109
|
+
...(options.codexBin !== undefined ? { codexBin: options.codexBin } : {}),
|
|
110
|
+
});
|
|
111
|
+
const mapper = new CodexAskEventMapper(models, component);
|
|
112
|
+
const finalText = await spawnCodexAsk(cli.command, args, mapper, emitter.emit, options.processTimeoutMs ?? timeoutMs + 5_000, options.signal);
|
|
113
|
+
emitter.emit({ kind: "run.finish", status: "answer" });
|
|
114
|
+
return { finalText };
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
118
|
+
emitter.emit({ kind: "error", message });
|
|
119
|
+
emitter.emit({ kind: "run.finish", status: "error" });
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function resolveModels(value) {
|
|
124
|
+
const models = typeof value === "function" ? value() : value;
|
|
125
|
+
if (!models || !models.orchestrator.trim() || !models.cheap.trim() || !models.strong.trim()) {
|
|
126
|
+
throw new Error("Codex Ask requires orchestrator, cheap, and strong model bindings");
|
|
127
|
+
}
|
|
128
|
+
return models;
|
|
129
|
+
}
|
|
130
|
+
function resolveExecutableOnPath(name) {
|
|
131
|
+
for (const directory of (process.env.PATH ?? "").split(path.delimiter)) {
|
|
132
|
+
if (!directory)
|
|
133
|
+
continue;
|
|
134
|
+
const candidate = path.join(directory, name);
|
|
135
|
+
try {
|
|
136
|
+
accessSync(candidate, fsConstants.X_OK);
|
|
137
|
+
return candidate;
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Keep searching.
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
throw new Error(`could not find the "${name}" executable on PATH`);
|
|
144
|
+
}
|
|
145
|
+
function sanitizedCodexEnvironment() {
|
|
146
|
+
return Object.fromEntries(Object.entries(process.env).filter(([key, value]) => value !== undefined && !CODEX_BILLING_ENV_KEYS.has(key.toUpperCase())));
|
|
147
|
+
}
|
|
148
|
+
function spawnCodexAsk(command, args, mapper, emit, timeoutMs, signal) {
|
|
149
|
+
return new Promise((resolve, reject) => {
|
|
150
|
+
if (signal?.aborted) {
|
|
151
|
+
reject(new Error("warble-codex-local Ask was cancelled before spawn"));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const child = spawn(command, [...args], {
|
|
155
|
+
env: sanitizedCodexEnvironment(),
|
|
156
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
157
|
+
detached: process.platform !== "win32",
|
|
158
|
+
});
|
|
159
|
+
let stderr = "";
|
|
160
|
+
let settled = false;
|
|
161
|
+
let stopReason;
|
|
162
|
+
let killTimer;
|
|
163
|
+
const terminate = (childSignal) => {
|
|
164
|
+
if (child.pid !== undefined && process.platform !== "win32") {
|
|
165
|
+
try {
|
|
166
|
+
process.kill(-child.pid, childSignal);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// Fall through to the direct child.
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
child.kill(childSignal);
|
|
174
|
+
};
|
|
175
|
+
const stop = (reason) => {
|
|
176
|
+
if (settled || stopReason !== undefined)
|
|
177
|
+
return;
|
|
178
|
+
stopReason = reason;
|
|
179
|
+
terminate("SIGTERM");
|
|
180
|
+
killTimer = setTimeout(() => terminate("SIGKILL"), 1_000);
|
|
181
|
+
};
|
|
182
|
+
const timer = setTimeout(() => stop("timeout"), timeoutMs);
|
|
183
|
+
const cancel = () => stop("cancelled");
|
|
184
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
185
|
+
const lines = createInterface({ input: child.stdout, crlfDelay: Infinity });
|
|
186
|
+
lines.on("line", (line) => {
|
|
187
|
+
if (settled || !line.trim())
|
|
188
|
+
return;
|
|
189
|
+
try {
|
|
190
|
+
for (const event of mapper.nextLine(line))
|
|
191
|
+
emit(event);
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
settled = true;
|
|
195
|
+
clearTimeout(timer);
|
|
196
|
+
signal?.removeEventListener("abort", cancel);
|
|
197
|
+
terminate("SIGTERM");
|
|
198
|
+
killTimer = setTimeout(() => terminate("SIGKILL"), 1_000);
|
|
199
|
+
reject(error);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
child.stderr.on("data", (chunk) => {
|
|
203
|
+
if (stderr.length < 8_192)
|
|
204
|
+
stderr += chunk.toString("utf8");
|
|
205
|
+
});
|
|
206
|
+
child.on("error", (error) => {
|
|
207
|
+
if (settled)
|
|
208
|
+
return;
|
|
209
|
+
settled = true;
|
|
210
|
+
clearTimeout(timer);
|
|
211
|
+
if (killTimer)
|
|
212
|
+
clearTimeout(killTimer);
|
|
213
|
+
signal?.removeEventListener("abort", cancel);
|
|
214
|
+
reject(new Error(`warble-codex-local Ask failed to start: ${error.message}`));
|
|
215
|
+
});
|
|
216
|
+
child.on("close", (code, childSignal) => {
|
|
217
|
+
clearTimeout(timer);
|
|
218
|
+
signal?.removeEventListener("abort", cancel);
|
|
219
|
+
lines.close();
|
|
220
|
+
if (settled)
|
|
221
|
+
return;
|
|
222
|
+
settled = true;
|
|
223
|
+
if (stopReason === "timeout") {
|
|
224
|
+
reject(new Error(`warble-codex-local Ask timed out after ${timeoutMs}ms`));
|
|
225
|
+
}
|
|
226
|
+
else if (stopReason === "cancelled") {
|
|
227
|
+
reject(new Error("warble-codex-local Ask was cancelled"));
|
|
228
|
+
}
|
|
229
|
+
else if (code !== 0) {
|
|
230
|
+
reject(new Error(`warble-codex-local Ask exited with ${code ?? childSignal ?? "unknown"}: ${stderr.trim()}`));
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
try {
|
|
234
|
+
resolve(mapper.result());
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
reject(error);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ResolvedCli } from "./agent-sdk-cli.js";
|
|
2
|
+
export declare class CodexLocalCliNotFoundError extends Error {
|
|
3
|
+
constructor(attempts: readonly string[]);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the warble `codex-local` dispatcher CLI in four tiers, mirroring
|
|
7
|
+
* `resolveAgentSdkCli`/`resolveWarbleBinary`:
|
|
8
|
+
*
|
|
9
|
+
* 1. `explicit` — trusted as-is, no existence check.
|
|
10
|
+
* 2. The pinned `@warble/codex-local` npm package this workspace depends on, run via
|
|
11
|
+
* `node <dist/cli.js>`.
|
|
12
|
+
* 3. `PATH` — a `warble-codex-local` executable found by walking `PATH` directly (this resolver's
|
|
13
|
+
* existing convention, unlike `resolveAgentSdkCli`'s `--help` probe).
|
|
14
|
+
* 4. A sibling `warble` repo's dev-mode invocation, gated behind the explicit
|
|
15
|
+
* `WREN_HARNESS_ALLOW_WARBLE_SIBLING_CHECKOUT=1` opt-in — must not silently win over the pinned
|
|
16
|
+
* package now that tier 2 exists.
|
|
17
|
+
*
|
|
18
|
+
* Throws {@link CodexLocalCliNotFoundError} (loud-fail) if none of the four work.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveCodexLocalCli(explicit?: string): Promise<ResolvedCli>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { accessSync, constants as fsConstants, existsSync } from "node:fs";
|
|
2
|
+
import { delimiter, dirname, join, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { isWarbleSiblingCheckoutDevModeEnabled, resolveInstalledPackageBin } from "../npm-package-resolve.js";
|
|
5
|
+
export class CodexLocalCliNotFoundError extends Error {
|
|
6
|
+
constructor(attempts) {
|
|
7
|
+
super(`could not resolve the warble-codex-local CLI:\n${attempts.map((attempt) => ` - ${attempt}`).join("\n")}`);
|
|
8
|
+
this.name = "CodexLocalCliNotFoundError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolves the warble `codex-local` dispatcher CLI in four tiers, mirroring
|
|
13
|
+
* `resolveAgentSdkCli`/`resolveWarbleBinary`:
|
|
14
|
+
*
|
|
15
|
+
* 1. `explicit` — trusted as-is, no existence check.
|
|
16
|
+
* 2. The pinned `@warble/codex-local` npm package this workspace depends on, run via
|
|
17
|
+
* `node <dist/cli.js>`.
|
|
18
|
+
* 3. `PATH` — a `warble-codex-local` executable found by walking `PATH` directly (this resolver's
|
|
19
|
+
* existing convention, unlike `resolveAgentSdkCli`'s `--help` probe).
|
|
20
|
+
* 4. A sibling `warble` repo's dev-mode invocation, gated behind the explicit
|
|
21
|
+
* `WREN_HARNESS_ALLOW_WARBLE_SIBLING_CHECKOUT=1` opt-in — must not silently win over the pinned
|
|
22
|
+
* package now that tier 2 exists.
|
|
23
|
+
*
|
|
24
|
+
* Throws {@link CodexLocalCliNotFoundError} (loud-fail) if none of the four work.
|
|
25
|
+
*/
|
|
26
|
+
export async function resolveCodexLocalCli(explicit) {
|
|
27
|
+
if (explicit !== undefined)
|
|
28
|
+
return { command: explicit, prefixArgs: [] };
|
|
29
|
+
const attempts = [];
|
|
30
|
+
const packageBin = resolveInstalledPackageBin("@warble/codex-local", "warble-codex-local");
|
|
31
|
+
if (packageBin !== undefined)
|
|
32
|
+
return { command: process.execPath, prefixArgs: [packageBin] };
|
|
33
|
+
attempts.push(`"@warble/codex-local" is not installed (or declares no "warble-codex-local" bin) in this workspace`);
|
|
34
|
+
const fromPath = resolveOnPath("warble-codex-local");
|
|
35
|
+
if (fromPath !== undefined)
|
|
36
|
+
return { command: fromPath, prefixArgs: [] };
|
|
37
|
+
attempts.push('not found on PATH as "warble-codex-local"');
|
|
38
|
+
if (isWarbleSiblingCheckoutDevModeEnabled()) {
|
|
39
|
+
const sibling = findSiblingDevInvocation();
|
|
40
|
+
if (sibling !== undefined)
|
|
41
|
+
return sibling;
|
|
42
|
+
attempts.push('no sibling "warble/dispatcher/codex-local" package with a tsx dev entry was found');
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
attempts.push(`sibling "warble" checkout dev mode is disabled (set WREN_HARNESS_ALLOW_WARBLE_SIBLING_CHECKOUT=1 to enable it)`);
|
|
46
|
+
}
|
|
47
|
+
throw new CodexLocalCliNotFoundError(attempts);
|
|
48
|
+
}
|
|
49
|
+
function resolveOnPath(binaryName) {
|
|
50
|
+
for (const dir of (process.env.PATH ?? "").split(delimiter)) {
|
|
51
|
+
if (!dir)
|
|
52
|
+
continue;
|
|
53
|
+
const candidate = join(dir, binaryName);
|
|
54
|
+
try {
|
|
55
|
+
accessSync(candidate, fsConstants.X_OK);
|
|
56
|
+
return candidate;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Keep searching.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
function findSiblingDevInvocation() {
|
|
65
|
+
let dir = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
66
|
+
for (let i = 0; i < 10; i += 1) {
|
|
67
|
+
const parent = dirname(dir);
|
|
68
|
+
const pkgDir = join(parent, "warble", "dispatcher", "codex-local");
|
|
69
|
+
const tsx = join(pkgDir, "node_modules", ".bin", "tsx");
|
|
70
|
+
const entry = join(pkgDir, "src", "cli.ts");
|
|
71
|
+
if (existsSync(tsx) && existsSync(entry))
|
|
72
|
+
return { command: tsx, prefixArgs: [entry] };
|
|
73
|
+
if (parent === dir)
|
|
74
|
+
break;
|
|
75
|
+
dir = parent;
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Bundle } from "../bundle/schema.js";
|
|
2
|
+
import type { ResolvedCli } from "./agent-sdk-cli.js";
|
|
3
|
+
export interface CodexManifestModels {
|
|
4
|
+
readonly orchestrator: string;
|
|
5
|
+
readonly cheap: string;
|
|
6
|
+
readonly strong: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const CODEX_ASK_COMPONENTS: readonly ["answer_query", "generate_dashboard"];
|
|
9
|
+
export type CodexAskComponent = (typeof CODEX_ASK_COMPONENTS)[number];
|
|
10
|
+
export declare const CODEX_ENRICH_COMPONENTS: readonly ["inspect_context", "draft_enrichment"];
|
|
11
|
+
export type CodexManifestPurpose = "analysis" | "setup" | "context_enrichment";
|
|
12
|
+
export declare function buildCodexAskManifestArgs(cli: ResolvedCli, irPath: string, models: CodexManifestModels, component?: CodexAskComponent): readonly string[];
|
|
13
|
+
export declare function buildCodexBootstrapManifestArgs(cli: ResolvedCli, irPath: string): readonly string[];
|
|
14
|
+
export declare function buildCodexEnrichmentManifestArgs(cli: ResolvedCli, irPath: string, models: CodexManifestModels, component: (typeof CODEX_ENRICH_COMPONENTS)[number]): readonly string[];
|
|
15
|
+
export declare function describeCodexAskManifest(cli: ResolvedCli, irPath: string, models: CodexManifestModels): Promise<Bundle>;
|
|
16
|
+
/**
|
|
17
|
+
* Setup is a raw/bootstrap profile, not an Ask profile. Its dispatcher has a
|
|
18
|
+
* dedicated whole-profile `manifest` command that neither needs nor accepts a
|
|
19
|
+
* bound Wren project, so never route it through the Ask-only component list.
|
|
20
|
+
*/
|
|
21
|
+
export declare function describeCodexBootstrapManifest(cli: ResolvedCli, irPath: string): Promise<Bundle>;
|
|
22
|
+
export declare function describeCodexEnrichmentManifest(cli: ResolvedCli, irPath: string, models: CodexManifestModels): Promise<Bundle>;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { loadBundle } from "../bundle/loader.js";
|
|
4
|
+
export const CODEX_ASK_COMPONENTS = ["answer_query", "generate_dashboard"];
|
|
5
|
+
export const CODEX_ENRICH_COMPONENTS = ["inspect_context", "draft_enrichment"];
|
|
6
|
+
export function buildCodexAskManifestArgs(cli, irPath, models, component = "answer_query") {
|
|
7
|
+
return [
|
|
8
|
+
...cli.prefixArgs,
|
|
9
|
+
"manifest",
|
|
10
|
+
irPath,
|
|
11
|
+
"--component",
|
|
12
|
+
component,
|
|
13
|
+
"--orchestrator-model",
|
|
14
|
+
models.orchestrator,
|
|
15
|
+
"--cheap-model",
|
|
16
|
+
models.cheap,
|
|
17
|
+
"--strong-model",
|
|
18
|
+
models.strong,
|
|
19
|
+
// Manifest preparation validates an absolute MCP command but does not
|
|
20
|
+
// spawn it; the runtime binds the real Wren MCP command separately.
|
|
21
|
+
"--server-command",
|
|
22
|
+
process.execPath,
|
|
23
|
+
"--inspect-tool",
|
|
24
|
+
"get_context",
|
|
25
|
+
"--query-tool",
|
|
26
|
+
"run_sql",
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
export function buildCodexBootstrapManifestArgs(cli, irPath) {
|
|
30
|
+
return [
|
|
31
|
+
...cli.prefixArgs,
|
|
32
|
+
"manifest",
|
|
33
|
+
irPath,
|
|
34
|
+
"--server-command",
|
|
35
|
+
process.execPath,
|
|
36
|
+
"--source-tool",
|
|
37
|
+
"setup_execution",
|
|
38
|
+
"--context-tool",
|
|
39
|
+
"setup_execution",
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
export function buildCodexEnrichmentManifestArgs(cli, irPath, models, component) {
|
|
43
|
+
return [
|
|
44
|
+
...cli.prefixArgs,
|
|
45
|
+
"manifest",
|
|
46
|
+
irPath,
|
|
47
|
+
"--component",
|
|
48
|
+
component,
|
|
49
|
+
"--model",
|
|
50
|
+
component === "inspect_context" ? models.cheap : models.strong,
|
|
51
|
+
"--server-command",
|
|
52
|
+
process.execPath,
|
|
53
|
+
"--semantic-tool",
|
|
54
|
+
"get_context",
|
|
55
|
+
"--raw-material-tool",
|
|
56
|
+
"get_context",
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
async function describeCodexComponentManifests(cli, irPath, components, argsFor) {
|
|
60
|
+
const ir = JSON.parse(await readFile(irPath, "utf8"));
|
|
61
|
+
const bundles = await Promise.all(components.map(async (component) => {
|
|
62
|
+
const stdout = await execCodexManifest(cli.command, argsFor(component));
|
|
63
|
+
return normalizeCodexManifest(JSON.parse(stdout), ir);
|
|
64
|
+
}));
|
|
65
|
+
const primary = bundles[0];
|
|
66
|
+
for (const bundle of bundles.slice(1)) {
|
|
67
|
+
if (bundle.manifest_version !== primary.manifest_version ||
|
|
68
|
+
JSON.stringify(bundle.compat) !== JSON.stringify(primary.compat) ||
|
|
69
|
+
bundle.profile !== primary.profile ||
|
|
70
|
+
bundle.target !== primary.target) {
|
|
71
|
+
throw new Error("Codex component manifests disagree on their target identity");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return loadBundle({ ...primary, agents: bundles.flatMap((bundle) => bundle.agents) });
|
|
75
|
+
}
|
|
76
|
+
export async function describeCodexAskManifest(cli, irPath, models) {
|
|
77
|
+
return describeCodexComponentManifests(cli, irPath, CODEX_ASK_COMPONENTS, (component) => buildCodexAskManifestArgs(cli, irPath, models, component));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Setup is a raw/bootstrap profile, not an Ask profile. Its dispatcher has a
|
|
81
|
+
* dedicated whole-profile `manifest` command that neither needs nor accepts a
|
|
82
|
+
* bound Wren project, so never route it through the Ask-only component list.
|
|
83
|
+
*/
|
|
84
|
+
export async function describeCodexBootstrapManifest(cli, irPath) {
|
|
85
|
+
const ir = JSON.parse(await readFile(irPath, "utf8"));
|
|
86
|
+
const stdout = await execCodexManifest(cli.command, buildCodexBootstrapManifestArgs(cli, irPath));
|
|
87
|
+
return normalizeCodexManifest(JSON.parse(stdout), ir);
|
|
88
|
+
}
|
|
89
|
+
export async function describeCodexEnrichmentManifest(cli, irPath, models) {
|
|
90
|
+
return describeCodexComponentManifests(cli, irPath, CODEX_ENRICH_COMPONENTS, (component) => buildCodexEnrichmentManifestArgs(cli, irPath, models, component));
|
|
91
|
+
}
|
|
92
|
+
function execCodexManifest(command, args) {
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
execFile(command, [...args], { maxBuffer: 32 * 1024 * 1024, timeout: 120_000 }, (error, stdout, stderr) => {
|
|
95
|
+
if (error) {
|
|
96
|
+
reject(new Error(`warble-codex-local manifest failed: ${stderr || error.message}`));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
resolve(stdout);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function records(value) {
|
|
104
|
+
return Array.isArray(value)
|
|
105
|
+
? value.filter((entry) => typeof entry === "object" && entry !== null)
|
|
106
|
+
: [];
|
|
107
|
+
}
|
|
108
|
+
function normalizeCodexManifest(manifest, ir) {
|
|
109
|
+
const irComponents = records(ir["components"]);
|
|
110
|
+
const agents = records(manifest["agents"]).map((agent) => {
|
|
111
|
+
const id = String(agent["id"] ?? "");
|
|
112
|
+
const component = irComponents.find((candidate) => candidate["id"] === id);
|
|
113
|
+
if (!component)
|
|
114
|
+
throw new Error(`Codex manifest component "${id}" is absent from compiled IR`);
|
|
115
|
+
const irSteps = records(component["llm_calls"]);
|
|
116
|
+
const irGuards = records(component["guardrails"]);
|
|
117
|
+
const renderBlocks = records(component["effect"]?.["render_blocks"]);
|
|
118
|
+
const manifestGuards = (agent["guardrails"] ?? {});
|
|
119
|
+
return {
|
|
120
|
+
id,
|
|
121
|
+
verb: String(agent["verb"] ?? component["verb"] ?? id),
|
|
122
|
+
component_type: String(agent["component_type"] ?? component["type"] ?? "analytical"),
|
|
123
|
+
realization_kind: String(agent["realization_kind"] ?? component["realization_kind"] ?? "skill"),
|
|
124
|
+
trigger: String(agent["trigger"] ?? component["trigger"]?.["kind"] ?? "one_shot"),
|
|
125
|
+
outcome: String(agent["outcome"] ?? component["effect"]?.["outcome"] ?? "none"),
|
|
126
|
+
steps: records(agent["steps"]).map((step) => {
|
|
127
|
+
const name = String(step["name"] ?? "");
|
|
128
|
+
const source = irSteps.find((candidate) => candidate["name"] === name) ?? {};
|
|
129
|
+
const when = source["when"];
|
|
130
|
+
return {
|
|
131
|
+
name,
|
|
132
|
+
tier: String(step["tier"] ?? source["tier"] ?? "strong"),
|
|
133
|
+
consumes: Array.isArray(step["consumes"]) ? step["consumes"].map(String) : [],
|
|
134
|
+
produces: String(step["produces"] ?? source["produces"] ?? "result"),
|
|
135
|
+
prompt: String(source["prompt"] ?? ""),
|
|
136
|
+
realization: when
|
|
137
|
+
? { kind: "repair_fold", fold_into: String(when["target"] ?? ""), max_attempts: 1 }
|
|
138
|
+
: { kind: "independent" },
|
|
139
|
+
...(when ? { when: { guard: String(when["guard"] ?? ""), target: String(when["target"] ?? "") } } : {}),
|
|
140
|
+
};
|
|
141
|
+
}),
|
|
142
|
+
guardrails: Object.fromEntries(irGuards.map((guard) => {
|
|
143
|
+
const name = String(guard["name"] ?? "");
|
|
144
|
+
const described = manifestGuards[name] ?? {};
|
|
145
|
+
return [
|
|
146
|
+
name,
|
|
147
|
+
{
|
|
148
|
+
enforcement: String(described["enforcement"] ?? "codex-local"),
|
|
149
|
+
locked: Boolean(guard["locked"]),
|
|
150
|
+
...(typeof guard["threshold"] === "number" ? { threshold: guard["threshold"] } : {}),
|
|
151
|
+
...(typeof guard["scope"] === "string" ? { scope: guard["scope"] } : {}),
|
|
152
|
+
},
|
|
153
|
+
];
|
|
154
|
+
})),
|
|
155
|
+
tools: records(agent["tools"]).map((tool) => ({ name: String(tool["name"] ?? ""), source: String(tool["source"] ?? "") })),
|
|
156
|
+
output_schema: {
|
|
157
|
+
properties: {
|
|
158
|
+
blocks: {
|
|
159
|
+
items: {
|
|
160
|
+
anyOf: renderBlocks.map((block) => ({ properties: { type: { const: String(block["type"] ?? "") } } })),
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
capabilities: records(agent["capabilities"]).map((capability) => ({
|
|
166
|
+
capability: String(capability["capability"] ?? ""),
|
|
167
|
+
outcome: String(capability["outcome"] ?? "native"),
|
|
168
|
+
provided_by: typeof capability["via"] === "string" ? capability["via"] : "codex-local",
|
|
169
|
+
criticality: "required",
|
|
170
|
+
})),
|
|
171
|
+
};
|
|
172
|
+
});
|
|
173
|
+
return loadBundle({
|
|
174
|
+
manifest_version: manifest["manifest_version"],
|
|
175
|
+
compat: manifest["compat"],
|
|
176
|
+
profile: manifest["profile"],
|
|
177
|
+
target: manifest["target"],
|
|
178
|
+
agents,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { AuthChoice } from "../auth/index.js";
|
|
2
|
+
import type { Bundle } from "../bundle/schema.js";
|
|
3
|
+
import { type CodexManifestModels, type CodexManifestPurpose } from "./codex-local-manifest.js";
|
|
4
|
+
/**
|
|
5
|
+
* The subset of `RouteOptions`/`InProcessOptions` needed to describe how a
|
|
6
|
+
* profile is CURRENTLY realized. `authChoice` is required (not optional)
|
|
7
|
+
* because it's the discriminator `describeBundle` branches on — see below —
|
|
8
|
+
* unlike `question`/`onEvent`/model-routing options, which don't affect what
|
|
9
|
+
* gets described.
|
|
10
|
+
*/
|
|
11
|
+
interface DescribeBundleBaseOptions {
|
|
12
|
+
readonly authChoice: AuthChoice;
|
|
13
|
+
readonly profileSource: string;
|
|
14
|
+
readonly warbleBin?: string;
|
|
15
|
+
readonly agentSdkBin?: string;
|
|
16
|
+
readonly codexLocalBin?: string;
|
|
17
|
+
readonly codexModels?: CodexManifestModels;
|
|
18
|
+
readonly workDir?: string;
|
|
19
|
+
/** Selects the executable component family shown by the purpose-scoped Harness. */
|
|
20
|
+
readonly codexManifestPurpose?: CodexManifestPurpose;
|
|
21
|
+
}
|
|
22
|
+
/** A profile whose context must be rebound to the currently bound project. */
|
|
23
|
+
export interface BoundDescribeBundleOptions extends DescribeBundleBaseOptions {
|
|
24
|
+
/** Omitted by legacy bound callers; bootstrap must always be explicit. */
|
|
25
|
+
readonly context?: "bound_project";
|
|
26
|
+
readonly userProject: string;
|
|
27
|
+
}
|
|
28
|
+
/** A profile that owns its authored raw/bootstrap context and has no user project. */
|
|
29
|
+
export interface BootstrapDescribeBundleOptions extends DescribeBundleBaseOptions {
|
|
30
|
+
readonly context: "bootstrap";
|
|
31
|
+
}
|
|
32
|
+
export type DescribeBundleOptions = BoundDescribeBundleOptions | BootstrapDescribeBundleOptions;
|
|
33
|
+
/**
|
|
34
|
+
* Describes whichever back-end will ACTUALLY run a turn for
|
|
35
|
+
* `options.authChoice` — the invariant this maintains is: Harness-shown
|
|
36
|
+
* target == `runtimeDispatcher`'s prediction (`server/harness.ts`)
|
|
37
|
+
* == what `route()` really dispatches to. The IR itself stays target-neutral
|
|
38
|
+
* either way; only the DISPLAY artifact this function loads differs:
|
|
39
|
+
*
|
|
40
|
+
* - `authChoice.mode === "subscription"` (dispatched): compiles IR only
|
|
41
|
+
* (`mode: "native"`, reusing `compileProfile`'s cache) — no vercel bundle
|
|
42
|
+
* is produced on this path at all — then sources the display from the
|
|
43
|
+
* claude-agent-sdk dispatcher's OWN `manifest` subcommand, which reads
|
|
44
|
+
* that same IR and emits a structurally-identical-to-the-vercel-bundle
|
|
45
|
+
* JSON (`target: "claude-agent-sdk:local"`) to stdout. This is genuinely
|
|
46
|
+
* what dispatched runs — `runDispatchedDefault` (`./dispatched.js`) shells this same
|
|
47
|
+
* dispatcher's `chat` subcommand against the same IR.
|
|
48
|
+
* - every other `authChoice.mode` (in-process: api-key/local/gateway): compiles
|
|
49
|
+
* to a vercel bundle (`mode: "agnostic"`, `warble dispatch --target
|
|
50
|
+
* vercel`) — unchanged pre-existing behavior; `runInProcessDefault`
|
|
51
|
+
* (`./in-process.js`) calls this too rather than keeping its own copy.
|
|
52
|
+
*/
|
|
53
|
+
export declare function describeBundle(options: DescribeBundleOptions): Promise<Bundle>;
|
|
54
|
+
export {};
|