@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,106 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createDefaultCapabilityRegistry } from "../capability/registry.js";
|
|
4
|
+
import { createLocalExecutionEnv } from "../exec/index.js";
|
|
5
|
+
import { deriveEnforcement } from "../guardrails/index.js";
|
|
6
|
+
import { createDefaultProviderRegistry } from "../providers/index.js";
|
|
7
|
+
import { runAgent } from "../session/index.js";
|
|
8
|
+
import { createWrenNativeToolRegistry, resolveWrenBinary } from "../tools/index.js";
|
|
9
|
+
import { deriveAdapterSpec } from "./adapter-spec.js";
|
|
10
|
+
import { describeBundle } from "./describe.js";
|
|
11
|
+
import { buildHybridTierBinding, buildUniformTierBinding } from "./tier-binding.js";
|
|
12
|
+
const ANSWER_QUERY_AGENT_ID = "answer_query";
|
|
13
|
+
/** Operator-wide override for `resolveArtifactsDir`'s default, e.g. for a long-running BFF process. */
|
|
14
|
+
const ARTIFACTS_DIR_ENV_VAR = "WREN_HARNESS_ARTIFACTS_DIR";
|
|
15
|
+
/** Projects a bundle-wide validated map onto the component selected for one turn. */
|
|
16
|
+
export function filterTierBindingForAgent(agent, tierBinding) {
|
|
17
|
+
return Object.fromEntries([...new Set(agent.steps.map((step) => step.tier))]
|
|
18
|
+
.filter((tier) => tierBinding[tier] !== undefined)
|
|
19
|
+
.map((tier) => [tier, tierBinding[tier]]));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolves the `rootDir` the native `write_artifact` tool's
|
|
23
|
+
* `createLocalExecutionEnv` scope is rooted at. Precedence: an explicit
|
|
24
|
+
* `outDir` (per-call override, e.g. `InProcessOptions.outDir` /
|
|
25
|
+
* `WREN_HARNESS_OUT`) > the `WREN_HARNESS_ARTIFACTS_DIR` env var
|
|
26
|
+
* (operator-wide override) > a fixed `os.tmpdir()` subdirectory.
|
|
27
|
+
* Deliberately NEVER `process.cwd()` — that was the bug this fixes:
|
|
28
|
+
* `runInProcessDefault` used to call `createLocalExecutionEnv()` with no
|
|
29
|
+
* `rootDir` at all, which defaults to `process.cwd()` (`harness/exec/local.ts`)
|
|
30
|
+
* — for a live BFF process that's wherever this package's server process
|
|
31
|
+
* happens to be launched from, so every `write_artifact` call (from
|
|
32
|
+
* `explain_change`/`generate_dashboard`, both scoped-write-gated) dropped its
|
|
33
|
+
* output straight into whatever directory started the process.
|
|
34
|
+
*
|
|
35
|
+
* This is entirely independent of `projectDir` (`options.userProject`),
|
|
36
|
+
* which is the ONLY thing that governs the `query` tool's exec cwd (see
|
|
37
|
+
* `createWrenQueryTool` in `harness/tools/native.ts` — it takes `projectDir` as
|
|
38
|
+
* its `cwd` directly, never touching `env`'s own `rootDir`). Changing this
|
|
39
|
+
* default never changes where `query` runs.
|
|
40
|
+
*/
|
|
41
|
+
export function resolveArtifactsDir(outDir) {
|
|
42
|
+
return outDir ?? process.env[ARTIFACTS_DIR_ENV_VAR] ?? path.join(os.tmpdir(), "wren-harness-artifacts");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* In-process ("api-key" | "local" | "gateway"): compile the profile to a vercel
|
|
46
|
+
* bundle (unless `options.bundle` overrides it, for tests), resolve which
|
|
47
|
+
* compiled agent to run (`options.agentId`, defaulting to
|
|
48
|
+
* `ANSWER_QUERY_AGENT_ID` — intent routing picks this upstream in
|
|
49
|
+
* `server/turn.ts`, not here), assemble a `RunAgentContext` bound either to a
|
|
50
|
+
* single adapter covering every tier that agent uses (the default), or —
|
|
51
|
+
* when `options.tierBinding` is set ("hybrid" mode) — to that non-uniform
|
|
52
|
+
* per-tier map, validated via `buildHybridTierBinding`; wire its `query` tool
|
|
53
|
+
* to the real `wren` CLI against `options.userProject` (unless
|
|
54
|
+
* `options.mcpServers` overrides it, for tests), and run it in-process via
|
|
55
|
+
* `runAgent`.
|
|
56
|
+
*/
|
|
57
|
+
export async function runInProcessDefault(options) {
|
|
58
|
+
const bundle = options.bundle ?? (await describeBundle(options));
|
|
59
|
+
// Intent routing (server/turn.ts) picks the agent id when present; falls back to answer_query,
|
|
60
|
+
// the original default from before intent routing existed.
|
|
61
|
+
const agentId = options.agentId ?? ANSWER_QUERY_AGENT_ID;
|
|
62
|
+
const agent = bundle.agents.find((candidate) => candidate.id === agentId);
|
|
63
|
+
if (!agent) {
|
|
64
|
+
throw new Error(`compiled bundle has no "${agentId}" agent`);
|
|
65
|
+
}
|
|
66
|
+
// Runtime settings are validated against every tier declared by the
|
|
67
|
+
// compiled bundle, but one turn executes only one selected component. Keep
|
|
68
|
+
// that complete map at the server boundary and pass this agent's projection
|
|
69
|
+
// here; `buildHybridTierBinding` intentionally rejects tiers used solely by
|
|
70
|
+
// another component.
|
|
71
|
+
const agentTierBinding = options.tierBinding === undefined ? undefined : filterTierBindingForAgent(agent, options.tierBinding);
|
|
72
|
+
const binding = options.tierBinding !== undefined
|
|
73
|
+
? buildHybridTierBinding(agent, agentTierBinding)
|
|
74
|
+
: buildUniformTierBinding(agent, deriveAdapterSpec(options.authChoice, options.model !== undefined ? { model: options.model } : {}));
|
|
75
|
+
const registry = createDefaultProviderRegistry();
|
|
76
|
+
const capabilityRegistry = createDefaultCapabilityRegistry();
|
|
77
|
+
if (options.mcpServers !== undefined) {
|
|
78
|
+
return runAgent(bundle, agentId, options.question, {
|
|
79
|
+
binding,
|
|
80
|
+
registry,
|
|
81
|
+
capabilityRegistry,
|
|
82
|
+
mcpServers: options.mcpServers,
|
|
83
|
+
...(options.onEvent !== undefined ? { onEvent: options.onEvent } : {}),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// Preflight `wren` before wiring the native tool registry around
|
|
87
|
+
// it. Without this, a missing `wren` binary stayed invisible until the
|
|
88
|
+
// tool loop actually called `query` — surfacing as an opaque,
|
|
89
|
+
// indistinguishable-from-a-normal-failure exec result rather than a clear
|
|
90
|
+
// "wren is not installed" error at the point where it's actually
|
|
91
|
+
// diagnosable.
|
|
92
|
+
await resolveWrenBinary();
|
|
93
|
+
const policy = deriveEnforcement(agent);
|
|
94
|
+
// Scoped to an artifacts dir, never the default `process.cwd()`
|
|
95
|
+
// (see `resolveArtifactsDir`'s doc comment) — independent of `projectDir`
|
|
96
|
+
// below, which alone governs the `query` tool's exec cwd.
|
|
97
|
+
const env = createLocalExecutionEnv({ rootDir: resolveArtifactsDir(options.outDir) });
|
|
98
|
+
const nativeTools = createWrenNativeToolRegistry({ env, policy, projectDir: options.userProject });
|
|
99
|
+
return runAgent(bundle, agentId, options.question, {
|
|
100
|
+
binding,
|
|
101
|
+
registry,
|
|
102
|
+
capabilityRegistry,
|
|
103
|
+
nativeTools,
|
|
104
|
+
...(options.onEvent !== undefined ? { onEvent: options.onEvent } : {}),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { DEFAULT_LOCAL_ENDPOINT, DEFAULT_LOCAL_MODEL, deriveAdapterSpec } from "./adapter-spec.js";
|
|
2
|
+
export type { DeriveAdapterSpecOptions } from "./adapter-spec.js";
|
|
3
|
+
export { AgentSdkCliNotFoundError, resolveAgentSdkCli } from "./agent-sdk-cli.js";
|
|
4
|
+
export type { ResolvedCli } from "./agent-sdk-cli.js";
|
|
5
|
+
export { buildAgentSdkManifestArgs, runAgentSdkManifest } from "./agent-sdk-manifest.js";
|
|
6
|
+
export type { AgentSdkManifestCommand, BuildAgentSdkManifestArgsOptions } from "./agent-sdk-manifest.js";
|
|
7
|
+
export { describeBundle } from "./describe.js";
|
|
8
|
+
export type { DescribeBundleOptions } from "./describe.js";
|
|
9
|
+
export { resolveArtifactContent } from "./artifact-content.js";
|
|
10
|
+
export type { ArtifactContentDto, ArtifactContentUnavailableReason } from "./artifact-content.js";
|
|
11
|
+
export { buildAgentSdkChatArgs, DispatchedSessionError, runDispatchedDefault } from "./dispatched.js";
|
|
12
|
+
export type { AgentSdkChatCommand, BuildAgentSdkChatArgsOptions } from "./dispatched.js";
|
|
13
|
+
export { buildCodexAskArgs, runCodexAskDefault } from "./codex-ask.js";
|
|
14
|
+
export { CodexAskEventMapper } from "./codex-ask-events.js";
|
|
15
|
+
export { resolveArtifactsDir, runInProcessDefault } from "./in-process.js";
|
|
16
|
+
export { resolveDefaultEnrichIrPath, resolveDefaultProfileSource, resolveDefaultSetupIrPath } from "./profile-source.js";
|
|
17
|
+
export { route } from "./route.js";
|
|
18
|
+
export { buildHybridTierBinding, buildUniformTierBinding } from "./tier-binding.js";
|
|
19
|
+
export type { InProcessExecutor, InProcessOptions, CodexAskExecutor, CodexAskOptions, CodexAskResult, DispatchedExecutor, DispatchedOptions, DispatchedResult, RouteOptions, RouteResult, } from "./types.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { DEFAULT_LOCAL_ENDPOINT, DEFAULT_LOCAL_MODEL, deriveAdapterSpec } from "./adapter-spec.js";
|
|
2
|
+
export { AgentSdkCliNotFoundError, resolveAgentSdkCli } from "./agent-sdk-cli.js";
|
|
3
|
+
export { buildAgentSdkManifestArgs, runAgentSdkManifest } from "./agent-sdk-manifest.js";
|
|
4
|
+
export { describeBundle } from "./describe.js";
|
|
5
|
+
export { resolveArtifactContent } from "./artifact-content.js";
|
|
6
|
+
export { buildAgentSdkChatArgs, DispatchedSessionError, runDispatchedDefault } from "./dispatched.js";
|
|
7
|
+
export { buildCodexAskArgs, runCodexAskDefault } from "./codex-ask.js";
|
|
8
|
+
export { CodexAskEventMapper } from "./codex-ask-events.js";
|
|
9
|
+
export { resolveArtifactsDir, runInProcessDefault } from "./in-process.js";
|
|
10
|
+
export { resolveDefaultEnrichIrPath, resolveDefaultProfileSource, resolveDefaultSetupIrPath } from "./profile-source.js";
|
|
11
|
+
export { route } from "./route.js";
|
|
12
|
+
export { buildHybridTierBinding, buildUniformTierBinding } from "./tier-binding.js";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the v1 default profile (`profiles/genbi-default`). Callers that
|
|
3
|
+
* already have an explicit `--profile`/`profileSource` never call this.
|
|
4
|
+
* Throws (loud-fail) if this package's own profile tree is not present.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveDefaultProfileSource(): string;
|
|
7
|
+
/**
|
|
8
|
+
* Resolves the committed genbi-setup IR (`profiles/genbi-setup/ir.golden.json`)
|
|
9
|
+
* via the same walk as {@link resolveDefaultProfileSource}. Unlike that
|
|
10
|
+
* function, this one does NOT hard-fail when it is absent — only the setup
|
|
11
|
+
* wizard's agentic connect step needs this IR, so a bootstrap-mode BFF instance
|
|
12
|
+
* that never uses `/api/setup/connect` should still boot fine without it.
|
|
13
|
+
* Callers should surface a clear error at the point of actually dispatching a
|
|
14
|
+
* setup turn if this returns `undefined`, not at boot.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveDefaultSetupIrPath(): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the committed genbi-enrich-context IR
|
|
19
|
+
* (`profiles/genbi-enrich-context/ir.golden.json`) via the same walk as
|
|
20
|
+
* {@link resolveDefaultSetupIrPath}. This profile's `context_precondition`
|
|
21
|
+
* ("an existing pinned Wren project ... that parses and has a successful
|
|
22
|
+
* build proof") is a host runtime obligation, not something the compiled IR
|
|
23
|
+
* itself is validated against.
|
|
24
|
+
*
|
|
25
|
+
* This used to say the golden was "dispatched against whichever project is
|
|
26
|
+
* actually bound at runtime via --project". That was the bug: a golden is the
|
|
27
|
+
* profile compiled once against its own fixture binding, so dispatching it
|
|
28
|
+
* described the example project's schema to an agent working on someone
|
|
29
|
+
* else's. An enrichment draft now compiles against the bound project (see the
|
|
30
|
+
* runner's `profileSource`), and this path remains only as the prebuilt
|
|
31
|
+
* fallback for a caller that has no profile source. Does NOT hard-fail when it
|
|
32
|
+
* is absent — only an enrichment draft call needs this; a BFF instance that
|
|
33
|
+
* never starts an enrichment run should still boot fine without it. Callers
|
|
34
|
+
* should surface a clear error at the point of actually dispatching a draft
|
|
35
|
+
* turn if this returns `undefined`, not at boot.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveDefaultEnrichIrPath(): string | undefined;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
/**
|
|
5
|
+
* The GenBI profiles (`genbi-default`, `genbi-setup`, `genbi-enrich-context`,
|
|
6
|
+
* `genbi-monitor`) live in this package's own `profiles/` tree, alongside their
|
|
7
|
+
* committed `ir.golden.json`. The `warble` binary and its dispatchers still
|
|
8
|
+
* come from a sibling Warble checkout (see `harness/compile/resolve-binary.ts`);
|
|
9
|
+
* only the behavior source is ours.
|
|
10
|
+
*
|
|
11
|
+
* Resolution walks up from this module's own location looking for an ancestor
|
|
12
|
+
* that contains `profiles/<id>`, so it works both from the TypeScript sources
|
|
13
|
+
* (`harness/route/`) and from the built bundle (`dist-server/harness/route/`),
|
|
14
|
+
* whether the caller runs from the main checkout or a nested git worktree.
|
|
15
|
+
*/
|
|
16
|
+
function resolveProfileEntry(...segments) {
|
|
17
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const maxDepth = 10;
|
|
19
|
+
for (let i = 0; i < maxDepth; i += 1) {
|
|
20
|
+
const candidate = path.join(dir, "profiles", ...segments);
|
|
21
|
+
if (existsSync(candidate))
|
|
22
|
+
return candidate;
|
|
23
|
+
const parent = path.dirname(dir);
|
|
24
|
+
if (parent === dir)
|
|
25
|
+
break; // reached filesystem root
|
|
26
|
+
dir = parent;
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolves the v1 default profile (`profiles/genbi-default`). Callers that
|
|
32
|
+
* already have an explicit `--profile`/`profileSource` never call this.
|
|
33
|
+
* Throws (loud-fail) if this package's own profile tree is not present.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveDefaultProfileSource() {
|
|
36
|
+
const resolved = resolveProfileEntry("genbi-default");
|
|
37
|
+
if (resolved !== undefined)
|
|
38
|
+
return resolved;
|
|
39
|
+
throw new Error('no default profile source found (searched ancestors of this module for "<ancestor>/profiles/' +
|
|
40
|
+
'genbi-default"); pass --profile explicitly');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Resolves the committed genbi-setup IR (`profiles/genbi-setup/ir.golden.json`)
|
|
44
|
+
* via the same walk as {@link resolveDefaultProfileSource}. Unlike that
|
|
45
|
+
* function, this one does NOT hard-fail when it is absent — only the setup
|
|
46
|
+
* wizard's agentic connect step needs this IR, so a bootstrap-mode BFF instance
|
|
47
|
+
* that never uses `/api/setup/connect` should still boot fine without it.
|
|
48
|
+
* Callers should surface a clear error at the point of actually dispatching a
|
|
49
|
+
* setup turn if this returns `undefined`, not at boot.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveDefaultSetupIrPath() {
|
|
52
|
+
return resolveProfileEntry("genbi-setup", "ir.golden.json");
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolves the committed genbi-enrich-context IR
|
|
56
|
+
* (`profiles/genbi-enrich-context/ir.golden.json`) via the same walk as
|
|
57
|
+
* {@link resolveDefaultSetupIrPath}. This profile's `context_precondition`
|
|
58
|
+
* ("an existing pinned Wren project ... that parses and has a successful
|
|
59
|
+
* build proof") is a host runtime obligation, not something the compiled IR
|
|
60
|
+
* itself is validated against.
|
|
61
|
+
*
|
|
62
|
+
* This used to say the golden was "dispatched against whichever project is
|
|
63
|
+
* actually bound at runtime via --project". That was the bug: a golden is the
|
|
64
|
+
* profile compiled once against its own fixture binding, so dispatching it
|
|
65
|
+
* described the example project's schema to an agent working on someone
|
|
66
|
+
* else's. An enrichment draft now compiles against the bound project (see the
|
|
67
|
+
* runner's `profileSource`), and this path remains only as the prebuilt
|
|
68
|
+
* fallback for a caller that has no profile source. Does NOT hard-fail when it
|
|
69
|
+
* is absent — only an enrichment draft call needs this; a BFF instance that
|
|
70
|
+
* never starts an enrichment run should still boot fine without it. Callers
|
|
71
|
+
* should surface a clear error at the point of actually dispatching a draft
|
|
72
|
+
* turn if this returns `undefined`, not at boot.
|
|
73
|
+
*/
|
|
74
|
+
export function resolveDefaultEnrichIrPath() {
|
|
75
|
+
return resolveProfileEntry("genbi-enrich-context", "ir.golden.json");
|
|
76
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RouteOptions, RouteResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The single seam mapping a resolved `AuthChoice` to a back-end:
|
|
4
|
+
* Claude subscription -> dispatched (warble-agent-sdk), Codex subscription ->
|
|
5
|
+
* codex:local, everything else
|
|
6
|
+
* (`api-key`/`local`/`gateway`) -> in-process (compile to a vercel bundle and run
|
|
7
|
+
* In-process via `runAgent`). `inProcess`/`dispatched` are injectable so callers and
|
|
8
|
+
* tests can stub either back-end without touching the other or invoking any
|
|
9
|
+
* real compile/dispatch — this is the hook point later tickets (compliance
|
|
10
|
+
* gating, hybrid dispatch) attach to without needing to touch the CLI or
|
|
11
|
+
* either mode's internals.
|
|
12
|
+
*
|
|
13
|
+
* The compliance gate (`enforceCompliance`) runs first, before either
|
|
14
|
+
* back-end is invoked: a `subscription` `AuthChoice` used for a `"hosted"`
|
|
15
|
+
* deployment throws `ComplianceError` here, so no caller of `route()` can
|
|
16
|
+
* reach dispatched for a use the ToS doesn't allow, regardless of whether it
|
|
17
|
+
* came through the CLI's own (separate, warning-printing) check. The
|
|
18
|
+
* resulting `warnings` (e.g. `SUBSCRIPTION_TOS_WARNING`) are attached to the
|
|
19
|
+
* returned `RouteResult` so programmatic callers of `route()` see them too
|
|
20
|
+
* — the CLI additionally prints them to stderr from its own, separately
|
|
21
|
+
* timed `enforceCompliance` call (before `route()` is even invoked, so they
|
|
22
|
+
* print before the back-end runs rather than after `route()` resolves), but
|
|
23
|
+
* that's an independent concern from surfacing them on the result value
|
|
24
|
+
* here. `runDispatchedDefault` also re-runs this same gate as a belt for direct
|
|
25
|
+
* (non-`route()`) callers — see its doc comment.
|
|
26
|
+
*
|
|
27
|
+
* The per-tier "hybrid" override: `options.tierBinding` (in-process's per-tier override) and
|
|
28
|
+
* `options.modelsConfig` (dispatched's `--models-config` passthrough) are each
|
|
29
|
+
* meaningful for exactly one back-end. Rather than silently ignore one when
|
|
30
|
+
* the `authChoice` picks the other back-end, `route()` loud-fails — the
|
|
31
|
+
* same "no silent misrouting" posture as the existing dispatched provider guard.
|
|
32
|
+
*/
|
|
33
|
+
export declare function route(options: RouteOptions): Promise<RouteResult>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { enforceCompliance } from "../compliance/index.js";
|
|
2
|
+
import { runInProcessDefault } from "./in-process.js";
|
|
3
|
+
import { runDispatchedDefault } from "./dispatched.js";
|
|
4
|
+
import { runCodexAskDefault } from "./codex-ask.js";
|
|
5
|
+
/**
|
|
6
|
+
* The single seam mapping a resolved `AuthChoice` to a back-end:
|
|
7
|
+
* Claude subscription -> dispatched (warble-agent-sdk), Codex subscription ->
|
|
8
|
+
* codex:local, everything else
|
|
9
|
+
* (`api-key`/`local`/`gateway`) -> in-process (compile to a vercel bundle and run
|
|
10
|
+
* In-process via `runAgent`). `inProcess`/`dispatched` are injectable so callers and
|
|
11
|
+
* tests can stub either back-end without touching the other or invoking any
|
|
12
|
+
* real compile/dispatch — this is the hook point later tickets (compliance
|
|
13
|
+
* gating, hybrid dispatch) attach to without needing to touch the CLI or
|
|
14
|
+
* either mode's internals.
|
|
15
|
+
*
|
|
16
|
+
* The compliance gate (`enforceCompliance`) runs first, before either
|
|
17
|
+
* back-end is invoked: a `subscription` `AuthChoice` used for a `"hosted"`
|
|
18
|
+
* deployment throws `ComplianceError` here, so no caller of `route()` can
|
|
19
|
+
* reach dispatched for a use the ToS doesn't allow, regardless of whether it
|
|
20
|
+
* came through the CLI's own (separate, warning-printing) check. The
|
|
21
|
+
* resulting `warnings` (e.g. `SUBSCRIPTION_TOS_WARNING`) are attached to the
|
|
22
|
+
* returned `RouteResult` so programmatic callers of `route()` see them too
|
|
23
|
+
* — the CLI additionally prints them to stderr from its own, separately
|
|
24
|
+
* timed `enforceCompliance` call (before `route()` is even invoked, so they
|
|
25
|
+
* print before the back-end runs rather than after `route()` resolves), but
|
|
26
|
+
* that's an independent concern from surfacing them on the result value
|
|
27
|
+
* here. `runDispatchedDefault` also re-runs this same gate as a belt for direct
|
|
28
|
+
* (non-`route()`) callers — see its doc comment.
|
|
29
|
+
*
|
|
30
|
+
* The per-tier "hybrid" override: `options.tierBinding` (in-process's per-tier override) and
|
|
31
|
+
* `options.modelsConfig` (dispatched's `--models-config` passthrough) are each
|
|
32
|
+
* meaningful for exactly one back-end. Rather than silently ignore one when
|
|
33
|
+
* the `authChoice` picks the other back-end, `route()` loud-fails — the
|
|
34
|
+
* same "no silent misrouting" posture as the existing dispatched provider guard.
|
|
35
|
+
*/
|
|
36
|
+
export async function route(options) {
|
|
37
|
+
const runInProcess = options.inProcess ?? runInProcessDefault;
|
|
38
|
+
const runDispatched = options.dispatched ?? runDispatchedDefault;
|
|
39
|
+
const runCodexAsk = options.codexAsk ?? runCodexAskDefault;
|
|
40
|
+
const { authChoice } = options;
|
|
41
|
+
const deployment = options.deployment ?? "personal";
|
|
42
|
+
const { warnings } = enforceCompliance(authChoice, { deployment });
|
|
43
|
+
if (authChoice.mode === "subscription") {
|
|
44
|
+
if (options.tierBinding !== undefined) {
|
|
45
|
+
throw new Error("tierBinding (hybrid in-process per-tier routing) has no effect under a subscription " +
|
|
46
|
+
"authChoice — dispatched has no adapter/tier binding of its own; use modelsConfig instead " +
|
|
47
|
+
"(warble-agent-sdk's own --models-config per-step routing)");
|
|
48
|
+
}
|
|
49
|
+
if (authChoice.provider === "codex") {
|
|
50
|
+
if (options.modelsConfig !== undefined) {
|
|
51
|
+
throw new Error("modelsConfig applies only to the Claude subscription dispatcher, not codex:local Ask");
|
|
52
|
+
}
|
|
53
|
+
const result = await runCodexAsk({
|
|
54
|
+
authChoice: { ...authChoice, provider: "codex" },
|
|
55
|
+
profileSource: options.profileSource,
|
|
56
|
+
userProject: options.userProject,
|
|
57
|
+
question: options.question,
|
|
58
|
+
deployment,
|
|
59
|
+
...(options.warbleBin !== undefined ? { warbleBin: options.warbleBin } : {}),
|
|
60
|
+
...(options.workDir !== undefined ? { workDir: options.workDir } : {}),
|
|
61
|
+
...(options.onEvent !== undefined ? { onEvent: options.onEvent } : {}),
|
|
62
|
+
...(options.agentId !== undefined ? { agentId: options.agentId } : {}),
|
|
63
|
+
...(options.codexModels !== undefined ? { codexModels: options.codexModels } : {}),
|
|
64
|
+
...(options.codexHome !== undefined ? { codexHome: options.codexHome } : {}),
|
|
65
|
+
...(options.codexLocalBin !== undefined ? { codexLocalBin: options.codexLocalBin } : {}),
|
|
66
|
+
...(options.codexLocalCli !== undefined ? { codexLocalCli: options.codexLocalCli } : {}),
|
|
67
|
+
...(options.codexBin !== undefined ? { codexBin: options.codexBin } : {}),
|
|
68
|
+
...(options.codexMcpServer !== undefined ? { mcpServer: options.codexMcpServer } : {}),
|
|
69
|
+
...(options.chatTimeoutMs !== undefined ? { timeoutMs: options.chatTimeoutMs } : {}),
|
|
70
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
71
|
+
});
|
|
72
|
+
return { backend: "codex-local", warnings, ...result };
|
|
73
|
+
}
|
|
74
|
+
const result = await runDispatched({
|
|
75
|
+
authChoice,
|
|
76
|
+
profileSource: options.profileSource,
|
|
77
|
+
userProject: options.userProject,
|
|
78
|
+
question: options.question,
|
|
79
|
+
deployment,
|
|
80
|
+
...(options.warbleBin !== undefined ? { warbleBin: options.warbleBin } : {}),
|
|
81
|
+
...(options.agentSdkBin !== undefined ? { agentSdkBin: options.agentSdkBin } : {}),
|
|
82
|
+
...(options.outDir !== undefined ? { outDir: options.outDir } : {}),
|
|
83
|
+
...(options.workDir !== undefined ? { workDir: options.workDir } : {}),
|
|
84
|
+
...(options.modelsConfig !== undefined ? { modelsConfig: options.modelsConfig } : {}),
|
|
85
|
+
...(options.onEvent !== undefined ? { onEvent: options.onEvent } : {}),
|
|
86
|
+
...(options.agentId !== undefined ? { agentId: options.agentId } : {}),
|
|
87
|
+
...(options.chatTimeoutMs !== undefined ? { chatTimeoutMs: options.chatTimeoutMs } : {}),
|
|
88
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
89
|
+
});
|
|
90
|
+
return { backend: "agent-sdk", warnings, ...result };
|
|
91
|
+
}
|
|
92
|
+
if (options.modelsConfig !== undefined) {
|
|
93
|
+
throw new Error(`modelsConfig (hybrid dispatched --models-config passthrough) has no effect under a ` +
|
|
94
|
+
`"${authChoice.mode}" authChoice — that flag only reaches warble-agent-sdk's chat ` +
|
|
95
|
+
"invocation, which in-process never shells; use tierBinding instead (this harness's own " +
|
|
96
|
+
"per-tier adapter map)");
|
|
97
|
+
}
|
|
98
|
+
const result = await runInProcess({
|
|
99
|
+
authChoice,
|
|
100
|
+
profileSource: options.profileSource,
|
|
101
|
+
userProject: options.userProject,
|
|
102
|
+
question: options.question,
|
|
103
|
+
...(options.model !== undefined ? { model: options.model } : {}),
|
|
104
|
+
...(options.warbleBin !== undefined ? { warbleBin: options.warbleBin } : {}),
|
|
105
|
+
...(options.workDir !== undefined ? { workDir: options.workDir } : {}),
|
|
106
|
+
...(options.outDir !== undefined ? { outDir: options.outDir } : {}),
|
|
107
|
+
...(options.bundle !== undefined ? { bundle: options.bundle } : {}),
|
|
108
|
+
...(options.mcpServers !== undefined ? { mcpServers: options.mcpServers } : {}),
|
|
109
|
+
...(options.tierBinding !== undefined ? { tierBinding: options.tierBinding } : {}),
|
|
110
|
+
...(options.onEvent !== undefined ? { onEvent: options.onEvent } : {}),
|
|
111
|
+
...(options.agentId !== undefined ? { agentId: options.agentId } : {}),
|
|
112
|
+
});
|
|
113
|
+
return { backend: "agent", warnings, ...result };
|
|
114
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Agent } from "../bundle/schema.js";
|
|
2
|
+
import type { AdapterSpec, TierBinding } from "../providers/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Builds a `TierBinding` mapping every distinct `tier` name used by `agent`'s
|
|
5
|
+
* steps to the same `adapterSpec` — one model realizing every tier. Tier
|
|
6
|
+
* names are open strings owned by individual steps, not
|
|
7
|
+
* declared centrally on the agent, so a single-adapter run must enumerate
|
|
8
|
+
* them from the bundle itself rather than assuming fixed names like
|
|
9
|
+
* `cheap`/`strong`. This also covers the render envelope stage automatically:
|
|
10
|
+
* `renderEnvelope`'s default tier is always the tier of the agent's last
|
|
11
|
+
* `independent` step, which is necessarily one of the tiers already
|
|
12
|
+
* collected here.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildUniformTierBinding(agent: Agent, adapterSpec: AdapterSpec): TierBinding;
|
|
15
|
+
/**
|
|
16
|
+
* Builds a "hybrid" `TierBinding` — a NON-uniform map from `agent`'s
|
|
17
|
+
* tiers to independently-chosen `AdapterSpec`s (e.g. `cheap` on a free local
|
|
18
|
+
* model, `strong` on a paid cloud one). Unlike `buildUniformTierBinding`
|
|
19
|
+
* (which derives its single map from one `AdapterSpec`, so it can never be
|
|
20
|
+
* short a tier), this takes a caller-supplied per-tier map and must validate
|
|
21
|
+
* it against the agent's actual tiers before trusting it:
|
|
22
|
+
*
|
|
23
|
+
* - every tier `agent`'s steps use must have an entry in `tiers` — a step
|
|
24
|
+
* whose tier resolves to nothing would otherwise surface late, deep inside
|
|
25
|
+
* `resolveTierModel`, as a bare `UnknownTierError` with no hint that the
|
|
26
|
+
* hybrid map (not the agent) is what's incomplete.
|
|
27
|
+
* - every entry in `tiers` must name a tier `agent` actually uses — an entry
|
|
28
|
+
* for a typo'd or stale tier name would otherwise silently do nothing
|
|
29
|
+
* (the intended tier stays unbound) rather than fail at the point the typo
|
|
30
|
+
* was made.
|
|
31
|
+
*
|
|
32
|
+
* Both failure modes loud-fail here, before `runAgent` starts, naming the
|
|
33
|
+
* agent and every offending tier — mirroring this module's/`adapter-spec.ts`'s
|
|
34
|
+
* existing loud-fail style (e.g. `gateway` mode's missing `baseURL`/`model`).
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildHybridTierBinding(agent: Agent, tiers: Readonly<Record<string, AdapterSpec>>): TierBinding;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds a `TierBinding` mapping every distinct `tier` name used by `agent`'s
|
|
3
|
+
* steps to the same `adapterSpec` — one model realizing every tier. Tier
|
|
4
|
+
* names are open strings owned by individual steps, not
|
|
5
|
+
* declared centrally on the agent, so a single-adapter run must enumerate
|
|
6
|
+
* them from the bundle itself rather than assuming fixed names like
|
|
7
|
+
* `cheap`/`strong`. This also covers the render envelope stage automatically:
|
|
8
|
+
* `renderEnvelope`'s default tier is always the tier of the agent's last
|
|
9
|
+
* `independent` step, which is necessarily one of the tiers already
|
|
10
|
+
* collected here.
|
|
11
|
+
*/
|
|
12
|
+
export function buildUniformTierBinding(agent, adapterSpec) {
|
|
13
|
+
const tiers = {};
|
|
14
|
+
for (const step of agent.steps) {
|
|
15
|
+
tiers[step.tier] = adapterSpec;
|
|
16
|
+
}
|
|
17
|
+
return { tiers };
|
|
18
|
+
}
|
|
19
|
+
/** The distinct `tier` names `agent`'s steps use, in first-seen order. */
|
|
20
|
+
function agentTierNames(agent) {
|
|
21
|
+
const seen = new Set();
|
|
22
|
+
for (const step of agent.steps) {
|
|
23
|
+
seen.add(step.tier);
|
|
24
|
+
}
|
|
25
|
+
return [...seen];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Builds a "hybrid" `TierBinding` — a NON-uniform map from `agent`'s
|
|
29
|
+
* tiers to independently-chosen `AdapterSpec`s (e.g. `cheap` on a free local
|
|
30
|
+
* model, `strong` on a paid cloud one). Unlike `buildUniformTierBinding`
|
|
31
|
+
* (which derives its single map from one `AdapterSpec`, so it can never be
|
|
32
|
+
* short a tier), this takes a caller-supplied per-tier map and must validate
|
|
33
|
+
* it against the agent's actual tiers before trusting it:
|
|
34
|
+
*
|
|
35
|
+
* - every tier `agent`'s steps use must have an entry in `tiers` — a step
|
|
36
|
+
* whose tier resolves to nothing would otherwise surface late, deep inside
|
|
37
|
+
* `resolveTierModel`, as a bare `UnknownTierError` with no hint that the
|
|
38
|
+
* hybrid map (not the agent) is what's incomplete.
|
|
39
|
+
* - every entry in `tiers` must name a tier `agent` actually uses — an entry
|
|
40
|
+
* for a typo'd or stale tier name would otherwise silently do nothing
|
|
41
|
+
* (the intended tier stays unbound) rather than fail at the point the typo
|
|
42
|
+
* was made.
|
|
43
|
+
*
|
|
44
|
+
* Both failure modes loud-fail here, before `runAgent` starts, naming the
|
|
45
|
+
* agent and every offending tier — mirroring this module's/`adapter-spec.ts`'s
|
|
46
|
+
* existing loud-fail style (e.g. `gateway` mode's missing `baseURL`/`model`).
|
|
47
|
+
*/
|
|
48
|
+
export function buildHybridTierBinding(agent, tiers) {
|
|
49
|
+
const agentTiers = agentTierNames(agent);
|
|
50
|
+
const agentTierSet = new Set(agentTiers);
|
|
51
|
+
const boundTierSet = new Set(Object.keys(tiers));
|
|
52
|
+
const missing = agentTiers.filter((tier) => !boundTierSet.has(tier));
|
|
53
|
+
if (missing.length > 0) {
|
|
54
|
+
throw new Error(`hybrid tier binding is missing an adapter for tier(s): ${missing.join(", ")} — ` +
|
|
55
|
+
`agent "${agent.id}" uses tier(s): ${agentTiers.join(", ")}`);
|
|
56
|
+
}
|
|
57
|
+
const unknown = [...boundTierSet].filter((tier) => !agentTierSet.has(tier));
|
|
58
|
+
if (unknown.length > 0) {
|
|
59
|
+
throw new Error(`hybrid tier binding names unknown tier(s) not used by agent "${agent.id}": ${unknown.join(", ")} — ` +
|
|
60
|
+
`known tier(s): ${agentTiers.join(", ")}`);
|
|
61
|
+
}
|
|
62
|
+
return { tiers };
|
|
63
|
+
}
|