@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,380 @@
|
|
|
1
|
+
import { generateText, isStepCount, ToolLoopAgent } from "ai";
|
|
2
|
+
import { resolveStepModel } from "../providers/index.js";
|
|
3
|
+
import { WRITE_ARTIFACT_TOOL_NAME } from "../tools/index.js";
|
|
4
|
+
import { AgentScopeError, InvalidRepairFoldError, RepairExhaustedError, StepBudgetExhaustedError } from "./errors.js";
|
|
5
|
+
import { passthroughGuardEvaluator } from "./guard.js";
|
|
6
|
+
const SUPPORTED_COMPONENT_TYPE = "analytical";
|
|
7
|
+
const SUPPORTED_TRIGGER = "one_shot";
|
|
8
|
+
const SUPPORTED_OUTCOME = "none";
|
|
9
|
+
/**
|
|
10
|
+
* Runs an agent's `steps[]` over a dataflow artifact state (option (b)):
|
|
11
|
+
* a step becomes runnable once every artifact it `consumes` is present, and
|
|
12
|
+
* on completion it stores its `produces` artifact. Step order is *derived*
|
|
13
|
+
* from consumes/produces satisfaction, not from the array's emergent index.
|
|
14
|
+
*
|
|
15
|
+
* Tool granularity is agent-level in the bundle, not per-step: if the agent
|
|
16
|
+
* declares `tools`, every (non-repair_fold) step runs as a `ToolLoopAgent`
|
|
17
|
+
* turn with the injected tool set (tool calls are emergent — a given step
|
|
18
|
+
* may make zero); otherwise every step is a single `generateText` call.
|
|
19
|
+
* A future milestone may refine this to scope tools per step.
|
|
20
|
+
*
|
|
21
|
+
* `realization.kind: "repair_fold"` steps are recognized but never run as
|
|
22
|
+
* independent top-level steps — instead each one folds into its
|
|
23
|
+
* `fold_into` target's tool-loop as a bounded error-recovery turn: when the
|
|
24
|
+
* target step's most recent turn surfaces a tool-execution error, the next
|
|
25
|
+
* turn's model and instructions swap to the repair step's, bounded by
|
|
26
|
+
* `max_attempts`. The DAG stays acyclic — this is a loop-internal retry, not
|
|
27
|
+
* a dataflow back-edge — and exhaustion is a loud failure
|
|
28
|
+
* ({@link RepairExhaustedError}), never a silent swallow or infinite retry.
|
|
29
|
+
*
|
|
30
|
+
* Returns the final dataflow artifact state — not a render envelope
|
|
31
|
+
* (the two-stage structured-output envelope is built in `harness/render/`).
|
|
32
|
+
*/
|
|
33
|
+
export async function executeAgent(agent, ctx) {
|
|
34
|
+
assertV1Scope(agent);
|
|
35
|
+
const artifacts = new Map();
|
|
36
|
+
const evaluateGuard = ctx.evaluateGuard ?? passthroughGuardEvaluator;
|
|
37
|
+
// Tool granularity is agent-level in the bundle (`agent.tools[]`), not
|
|
38
|
+
// per-step — so gate the ToolLoopAgent-vs-generateText choice on the
|
|
39
|
+
// bundle's declaration, not on whatever happens to be in the injected
|
|
40
|
+
// tool set (which the caller may size differently today, since real
|
|
41
|
+
// `agent.tools[]` -> AI SDK tool resolution happens elsewhere).
|
|
42
|
+
const hasTools = agent.tools.length > 0;
|
|
43
|
+
// repair_fold steps never run as independent top-level steps — they're
|
|
44
|
+
// consumed by the fold-into-loop logic below, keyed by their fold_into
|
|
45
|
+
// target's step name.
|
|
46
|
+
const repairByTarget = buildRepairFoldMap(agent, hasTools);
|
|
47
|
+
const pending = agent.steps.filter((step) => step.realization.kind !== "repair_fold");
|
|
48
|
+
while (pending.length > 0) {
|
|
49
|
+
const readyIndex = pending.findIndex((step) => isConsumesSatisfied(step, artifacts));
|
|
50
|
+
if (readyIndex === -1) {
|
|
51
|
+
// No remaining step's consumes can ever be satisfied — e.g. its sole
|
|
52
|
+
// producer is a repair_fold step, which never runs as a top-level step.
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
const [step] = pending.splice(readyIndex, 1);
|
|
56
|
+
if (!step)
|
|
57
|
+
break;
|
|
58
|
+
if (!evaluateGuard({ step, artifacts })) {
|
|
59
|
+
// A real guard would skip this step's execution and leave
|
|
60
|
+
// its `produces` artifact absent. The default guard used here never does this.
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const prompt = renderStepPrompt(step, ctx.userInput, artifacts);
|
|
64
|
+
const model = resolveStepModel(step, ctx.binding, ctx.registry);
|
|
65
|
+
const repairStep = repairByTarget.get(step.name);
|
|
66
|
+
const stepId = step.name;
|
|
67
|
+
// `step.start`/`step.finish` bracket each bundle step.
|
|
68
|
+
// In-process has no sub-agent/Task mechanism, so `depth` is always 0 and
|
|
69
|
+
// `parent` is never set here (see `ExecuteAgentContext.onEvent`'s doc
|
|
70
|
+
// comment).
|
|
71
|
+
ctx.onEvent?.({ kind: "step.start", stepId, name: step.name, tier: step.tier, depth: 0 });
|
|
72
|
+
let text;
|
|
73
|
+
let repaired = false;
|
|
74
|
+
try {
|
|
75
|
+
if (repairStep) {
|
|
76
|
+
// Validated up front in buildRepairFoldMap: a repair_fold target is
|
|
77
|
+
// always a tools-bearing step, so hasTools is guaranteed true here.
|
|
78
|
+
const result = await runToolLoopStepWithRepair(model, ctx.tools, prompt, repairStep, ctx.binding, ctx.registry, stepId, ctx.onToolCallOutcome, ctx.onEvent, ctx.maxSteps);
|
|
79
|
+
if (result.exhausted) {
|
|
80
|
+
throw new StepBudgetExhaustedError(stepId, ctx.maxSteps, artifacts.size);
|
|
81
|
+
}
|
|
82
|
+
text = result.text;
|
|
83
|
+
repaired = result.repaired;
|
|
84
|
+
}
|
|
85
|
+
else if (hasTools) {
|
|
86
|
+
const result = await runToolLoopStep(model, ctx.tools, prompt, stepId, ctx.onToolCallOutcome, ctx.onEvent, ctx.maxSteps);
|
|
87
|
+
if (result.exhausted) {
|
|
88
|
+
throw new StepBudgetExhaustedError(stepId, ctx.maxSteps, artifacts.size);
|
|
89
|
+
}
|
|
90
|
+
text = result.text;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
text = await runSingleGenerateStep(model, prompt);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
ctx.onEvent?.({ kind: "step.finish", stepId, name: step.name, status: "error", detail: describeError(error) });
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
artifacts.set(step.produces, text);
|
|
101
|
+
// Surface the step's own reasoning/output — the text it just
|
|
102
|
+
// produced (already about to be stored as `step.produces`'s artifact) —
|
|
103
|
+
// bounded via the same `summarizeToolOutput` truncation a tool result
|
|
104
|
+
// uses, so a long LLM step's output doesn't blow up the work-log frame.
|
|
105
|
+
const detail = summarizeToolOutput(text);
|
|
106
|
+
ctx.onEvent?.({
|
|
107
|
+
kind: "step.finish",
|
|
108
|
+
stepId,
|
|
109
|
+
name: step.name,
|
|
110
|
+
status: "ok",
|
|
111
|
+
...(detail !== undefined ? { detail } : {}),
|
|
112
|
+
});
|
|
113
|
+
// The repair step's own `produces` artifact only appears when a repair
|
|
114
|
+
// turn actually ran — never on the ordinary success path (see the
|
|
115
|
+
// `repaired_result` absence assertion).
|
|
116
|
+
if (repairStep && repaired) {
|
|
117
|
+
artifacts.set(repairStep.produces, text);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return artifacts;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Validates and indexes every `repair_fold` step by its `fold_into` target
|
|
124
|
+
* step name. The fold-into-loop contract is closed: `when` must be exactly
|
|
125
|
+
* `{ guard: "on_failure", target: <fold_into> }`, the target must exist
|
|
126
|
+
* among the agent's steps, at most one repair may bind to a given target,
|
|
127
|
+
* and — since this mechanism only ever detects failure via a tool-error content part on
|
|
128
|
+
* the target's tool-loop turn — the target must be a tools-bearing step.
|
|
129
|
+
* Any violation is a loud `InvalidRepairFoldError` at agent-start, not a
|
|
130
|
+
* silent fall-back to skipping the repair step.
|
|
131
|
+
*/
|
|
132
|
+
function buildRepairFoldMap(agent, hasTools) {
|
|
133
|
+
const map = new Map();
|
|
134
|
+
const stepNames = new Set(agent.steps.map((step) => step.name));
|
|
135
|
+
for (const step of agent.steps) {
|
|
136
|
+
if (step.realization.kind !== "repair_fold")
|
|
137
|
+
continue;
|
|
138
|
+
const foldInto = step.realization.fold_into;
|
|
139
|
+
if (!foldInto) {
|
|
140
|
+
throw new InvalidRepairFoldError(step.name, "realization.fold_into is required");
|
|
141
|
+
}
|
|
142
|
+
if (!stepNames.has(foldInto)) {
|
|
143
|
+
throw new InvalidRepairFoldError(step.name, `fold_into target "${foldInto}" is not a step on this agent`);
|
|
144
|
+
}
|
|
145
|
+
if (!step.when || step.when.guard !== "on_failure" || step.when.target !== foldInto) {
|
|
146
|
+
throw new InvalidRepairFoldError(step.name, `expected when = { guard: "on_failure", target: "${foldInto}" }`);
|
|
147
|
+
}
|
|
148
|
+
if (map.has(foldInto)) {
|
|
149
|
+
throw new InvalidRepairFoldError(step.name, `step "${foldInto}" already has a repair_fold bound to it`);
|
|
150
|
+
}
|
|
151
|
+
if (!hasTools) {
|
|
152
|
+
throw new InvalidRepairFoldError(step.name, `fold_into target "${foldInto}" must be a tools-bearing step (the fold-into-loop mechanism detects failure via a tool-error)`);
|
|
153
|
+
}
|
|
154
|
+
map.set(foldInto, step);
|
|
155
|
+
}
|
|
156
|
+
return map;
|
|
157
|
+
}
|
|
158
|
+
function assertV1Scope(agent) {
|
|
159
|
+
if (agent.component_type !== SUPPORTED_COMPONENT_TYPE ||
|
|
160
|
+
agent.trigger !== SUPPORTED_TRIGGER ||
|
|
161
|
+
agent.outcome !== SUPPORTED_OUTCOME) {
|
|
162
|
+
throw new AgentScopeError(agent.id, agent.component_type, agent.trigger, agent.outcome);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function isConsumesSatisfied(step, artifacts) {
|
|
166
|
+
return step.consumes.every((artifactName) => artifacts.has(artifactName));
|
|
167
|
+
}
|
|
168
|
+
async function runSingleGenerateStep(model, prompt) {
|
|
169
|
+
const result = await generateText({ model, prompt });
|
|
170
|
+
return result.text;
|
|
171
|
+
}
|
|
172
|
+
async function runToolLoopStep(model, tools, prompt, stepId, onToolCallOutcome, onEvent, maxSteps) {
|
|
173
|
+
const agentRunner = new ToolLoopAgent({
|
|
174
|
+
model,
|
|
175
|
+
tools,
|
|
176
|
+
...(maxSteps !== undefined ? { stopWhen: isStepCount(maxSteps) } : {}),
|
|
177
|
+
});
|
|
178
|
+
const result = await agentRunner.generate({ prompt });
|
|
179
|
+
reportToolCallOutcomes(result.steps, stepId, onToolCallOutcome, onEvent);
|
|
180
|
+
return { text: result.text, exhausted: isBudgetExhausted(result, maxSteps) };
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* The fold-into-loop mechanism: runs `prompt` as a `ToolLoopAgent` turn
|
|
184
|
+
* exactly like {@link runToolLoopStep}, except `prepareStep` inspects the
|
|
185
|
+
* immediately-preceding turn for a tool-execution error (a `type:
|
|
186
|
+
* "tool-error"` content part — the shape the AI SDK gives a caught tool
|
|
187
|
+
* `execute` rejection, confirmed against `@ai-sdk/mcp`'s JSON-RPC error
|
|
188
|
+
* path). On error, the *next* turn's model and instructions are swapped to
|
|
189
|
+
* the repair step's (its `tier` resolved the same way any step's tier is),
|
|
190
|
+
* folding the repair in as a bounded error-recovery turn rather than a
|
|
191
|
+
* separate top-level step. Bounded by `repairStep.realization.max_attempts`
|
|
192
|
+
* (default 1); once exhausted, a further tool-error throws
|
|
193
|
+
* {@link RepairExhaustedError} instead of retrying again.
|
|
194
|
+
*/
|
|
195
|
+
async function runToolLoopStepWithRepair(model, tools, prompt, repairStep, binding, registry, stepId, onToolCallOutcome, onEvent, maxSteps) {
|
|
196
|
+
const maxAttempts = repairStep.realization.max_attempts ?? 1;
|
|
197
|
+
const repairModel = resolveStepModel(repairStep, binding, registry);
|
|
198
|
+
const foldTarget = repairStep.realization.fold_into ?? repairStep.name;
|
|
199
|
+
let attemptsUsed = 0;
|
|
200
|
+
let repaired = false;
|
|
201
|
+
const agentRunner = new ToolLoopAgent({
|
|
202
|
+
model,
|
|
203
|
+
tools,
|
|
204
|
+
...(maxSteps !== undefined ? { stopWhen: isStepCount(maxSteps) } : {}),
|
|
205
|
+
prepareStep: ({ steps }) => {
|
|
206
|
+
const lastStep = steps[steps.length - 1];
|
|
207
|
+
if (!lastStep || !stepHasToolError(lastStep)) {
|
|
208
|
+
return {};
|
|
209
|
+
}
|
|
210
|
+
if (attemptsUsed >= maxAttempts) {
|
|
211
|
+
throw new RepairExhaustedError(foldTarget, repairStep.name, maxAttempts);
|
|
212
|
+
}
|
|
213
|
+
attemptsUsed += 1;
|
|
214
|
+
repaired = true;
|
|
215
|
+
return { model: repairModel, instructions: repairStep.prompt };
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
const result = await agentRunner.generate({ prompt });
|
|
219
|
+
reportToolCallOutcomes(result.steps, stepId, onToolCallOutcome, onEvent);
|
|
220
|
+
return { text: result.text, repaired, exhausted: isBudgetExhausted(result, maxSteps) };
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Detects whether a completed `ToolLoopAgent` turn was cut off by its
|
|
224
|
+
* configured step budget rather than finishing on its own. `isStepCount`'s
|
|
225
|
+
* own stop condition is an exact-equality check (`steps.length ===
|
|
226
|
+
* stepCount`, `ai`'s `stop-condition.ts`) — indistinguishable, by step count
|
|
227
|
+
* alone, from a model that happens to finish naturally on exactly the
|
|
228
|
+
* budget's last step. `finishReason` disambiguates: a clean finish sets it to
|
|
229
|
+
* `"stop"` (`generate-text.ts`'s main loop only resolves output when
|
|
230
|
+
* `lastStep.finishReason === "stop"`); a turn cut off mid-flight — the model
|
|
231
|
+
* still had a tool call queued when the budget's step count was hit — never
|
|
232
|
+
* reaches that state, so its last step's `finishReason` is something else
|
|
233
|
+
* (typically `"tool-calls"`). Always `false` when no budget was configured
|
|
234
|
+
* (`maxSteps === undefined`), so a caller that never opts in (the Ask path)
|
|
235
|
+
* can never see this heuristic fire.
|
|
236
|
+
*/
|
|
237
|
+
function isBudgetExhausted(result, maxSteps) {
|
|
238
|
+
if (maxSteps === undefined)
|
|
239
|
+
return false;
|
|
240
|
+
return result.steps.length >= maxSteps && result.finishReason !== "stop";
|
|
241
|
+
}
|
|
242
|
+
function stepHasToolError(step) {
|
|
243
|
+
return step.content.some((part) => part.type === "tool-error");
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* This function, widened for the live-event layer: walks every step's content parts from a
|
|
247
|
+
* completed `ToolLoopAgent` turn and reports each outcome to
|
|
248
|
+
* `onToolCallOutcome` ({@link ToolCallOutcome}) — this is the sole place
|
|
249
|
+
* tool-call outcomes are observed, so the deterministic gate and the
|
|
250
|
+
* FLOOR `StepTrace` both see outcomes from ordinary steps and from
|
|
251
|
+
* repair-folded turns alike. A no-op for a given concern when neither
|
|
252
|
+
* `onToolCallOutcome` nor `onEvent` is registered.
|
|
253
|
+
*
|
|
254
|
+
* Also emits, when `onEvent` is set: a `tool.call` for every `tool-call`
|
|
255
|
+
* part (before its outcome is known — `status: "running"`), a `tool.result`
|
|
256
|
+
* for every `tool-result`/`tool-error` part, and — best-effort, since the
|
|
257
|
+
* bundle's native `write_artifact` tool has no `artifactKind` field of its
|
|
258
|
+
* own (input is just `{path, content}`) — an `artifact` event defaulting
|
|
259
|
+
* `artifactKind` to `"report"` whenever that tool call succeeds. This is a
|
|
260
|
+
* documented limitation, not a real classification signal.
|
|
261
|
+
*/
|
|
262
|
+
function reportToolCallOutcomes(steps, stepId, onToolCallOutcome, onEvent) {
|
|
263
|
+
if (!onToolCallOutcome && !onEvent)
|
|
264
|
+
return;
|
|
265
|
+
for (const step of steps) {
|
|
266
|
+
for (const part of step.content) {
|
|
267
|
+
if (part.type === "tool-call") {
|
|
268
|
+
onEvent?.({
|
|
269
|
+
kind: "tool.call",
|
|
270
|
+
stepId,
|
|
271
|
+
callId: part.toolCallId,
|
|
272
|
+
tool: part.toolName,
|
|
273
|
+
...(part.input !== undefined ? { input: part.input } : {}),
|
|
274
|
+
depth: 0,
|
|
275
|
+
status: "running",
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
else if (part.type === "tool-result") {
|
|
279
|
+
onToolCallOutcome?.({
|
|
280
|
+
tool: part.toolName,
|
|
281
|
+
outcome: "success",
|
|
282
|
+
callId: part.toolCallId,
|
|
283
|
+
...(part.input !== undefined ? { input: part.input } : {}),
|
|
284
|
+
...(part.output !== undefined ? { output: part.output } : {}),
|
|
285
|
+
});
|
|
286
|
+
const summary = summarizeToolOutput(part.output);
|
|
287
|
+
onEvent?.({
|
|
288
|
+
kind: "tool.result",
|
|
289
|
+
stepId,
|
|
290
|
+
callId: part.toolCallId,
|
|
291
|
+
tool: part.toolName,
|
|
292
|
+
status: "success",
|
|
293
|
+
...(summary !== undefined ? { summary } : {}),
|
|
294
|
+
});
|
|
295
|
+
if (part.toolName === WRITE_ARTIFACT_TOOL_NAME) {
|
|
296
|
+
const location = extractArtifactPath(part.input);
|
|
297
|
+
if (location !== undefined) {
|
|
298
|
+
onEvent?.({
|
|
299
|
+
kind: "artifact",
|
|
300
|
+
// Best-effort default — the native `write_artifact` tool has
|
|
301
|
+
// no `artifactKind` concept in its input/output schema (see
|
|
302
|
+
// this function's doc comment).
|
|
303
|
+
name: basenameOf(location),
|
|
304
|
+
artifactKind: "report",
|
|
305
|
+
location,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
else if (part.type === "tool-error") {
|
|
311
|
+
const error = describeError(part.error);
|
|
312
|
+
onToolCallOutcome?.({
|
|
313
|
+
tool: part.toolName,
|
|
314
|
+
outcome: "error",
|
|
315
|
+
callId: part.toolCallId,
|
|
316
|
+
...(part.input !== undefined ? { input: part.input } : {}),
|
|
317
|
+
error,
|
|
318
|
+
});
|
|
319
|
+
onEvent?.({
|
|
320
|
+
kind: "tool.result",
|
|
321
|
+
stepId,
|
|
322
|
+
callId: part.toolCallId,
|
|
323
|
+
tool: part.toolName,
|
|
324
|
+
status: "error",
|
|
325
|
+
error,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Best-effort, bounded-length human summary of a tool's `output`, for
|
|
333
|
+
* `ToolResultEvent.summary`. Exported so `harness/session/run.ts` can build a
|
|
334
|
+
* `TraceStep.detail` for a successful outcome from the same seam, without
|
|
335
|
+
* duplicating the truncation logic.
|
|
336
|
+
*/
|
|
337
|
+
export function summarizeToolOutput(output) {
|
|
338
|
+
if (output === undefined)
|
|
339
|
+
return undefined;
|
|
340
|
+
const text = typeof output === "string" ? output : JSON.stringify(output);
|
|
341
|
+
const MAX_LENGTH = 200;
|
|
342
|
+
return text.length > MAX_LENGTH ? `${text.slice(0, MAX_LENGTH)}…` : text;
|
|
343
|
+
}
|
|
344
|
+
function describeError(error) {
|
|
345
|
+
const text = error instanceof Error ? error.message : typeof error === "string" ? error : JSON.stringify(error);
|
|
346
|
+
// Bounded like summarizeToolOutput: this string is now persisted into the
|
|
347
|
+
// display worklog's `detail` (via the tool.result/step.finish events), so a
|
|
348
|
+
// pathological huge error message must not bloat trace_json.
|
|
349
|
+
const MAX_LENGTH = 200;
|
|
350
|
+
return text.length > MAX_LENGTH ? `${text.slice(0, MAX_LENGTH)}…` : text;
|
|
351
|
+
}
|
|
352
|
+
function extractArtifactPath(input) {
|
|
353
|
+
if (typeof input !== "object" || input === null)
|
|
354
|
+
return undefined;
|
|
355
|
+
const path = input.path;
|
|
356
|
+
return typeof path === "string" ? path : undefined;
|
|
357
|
+
}
|
|
358
|
+
function basenameOf(filePath) {
|
|
359
|
+
const segments = filePath.split(/[/\\]/);
|
|
360
|
+
return segments[segments.length - 1] || filePath;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Builds the message sent for a step: the user's question (always present,
|
|
364
|
+
* so steps with `consumes: []` like `resolve_intent` can still see it),
|
|
365
|
+
* the step's own prompt, and the resolved values of every artifact it
|
|
366
|
+
* consumes.
|
|
367
|
+
*/
|
|
368
|
+
function renderStepPrompt(step, userInput, artifacts) {
|
|
369
|
+
const sections = [`User's question: ${userInput}`, step.prompt];
|
|
370
|
+
if (step.consumes.length > 0) {
|
|
371
|
+
const consumedSection = step.consumes
|
|
372
|
+
.map((name) => `${name}: ${formatArtifactValue(artifacts.get(name))}`)
|
|
373
|
+
.join("\n");
|
|
374
|
+
sections.push(`Consumed artifacts:\n${consumedSection}`);
|
|
375
|
+
}
|
|
376
|
+
return sections.join("\n\n");
|
|
377
|
+
}
|
|
378
|
+
function formatArtifactValue(value) {
|
|
379
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
380
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Step } from "../bundle/schema.js";
|
|
2
|
+
/** Snapshot handed to a guard evaluator immediately before a step would run. */
|
|
3
|
+
export interface StepGuardContext {
|
|
4
|
+
readonly step: Step;
|
|
5
|
+
readonly artifacts: ReadonlyMap<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Decides whether a runnable step should actually execute. This is the seam
|
|
9
|
+
* reserved for `when` guard semantics (`on_failure` folds into the repair-fold
|
|
10
|
+
* retry turn; `on_flag` / `on_missing` drive a guarded-skip) — both are not
|
|
11
|
+
* yet implemented. The executor always calls this hook before
|
|
12
|
+
* running a step; the default implementation here is a pass-through no-op so
|
|
13
|
+
* the seam exists without any guard behavior attached to it yet.
|
|
14
|
+
*/
|
|
15
|
+
export type GuardEvaluator = (ctx: StepGuardContext) => boolean;
|
|
16
|
+
export declare const passthroughGuardEvaluator: GuardEvaluator;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const passthroughGuardEvaluator = () => true;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { executeAgent, summarizeToolOutput } from "./executor.js";
|
|
2
|
+
export type { DataflowArtifacts, ExecuteAgentContext, ToolCallOutcome, ToolCallOutcomeListener } from "./executor.js";
|
|
3
|
+
export { AgentScopeError, InvalidRepairFoldError, RepairExhaustedError, StepBudgetExhaustedError } from "./errors.js";
|
|
4
|
+
export { passthroughGuardEvaluator } from "./guard.js";
|
|
5
|
+
export type { GuardEvaluator, StepGuardContext } from "./guard.js";
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { AgentEvent, RouteOptions, RouteResult } from "../index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Host-owned contract for deterministic, noninteractive dispatch. This is
|
|
4
|
+
* intentionally not the interactive terminal protocol: it contains no bytes
|
|
5
|
+
* from a PTY, dispatcher stream, prompt, tool input/output, or credential.
|
|
6
|
+
*/
|
|
7
|
+
export declare const NATIVE_PRODUCER_VERSION: "1";
|
|
8
|
+
export type NativeProducerVendor = "claude" | "codex";
|
|
9
|
+
export type NativeProducerErrorCode = "unsupported_version" | "scope_mismatch" | "invalid_request" | "malformed_output" | "missing_replay" | "timeout" | "cancelled" | "producer_failed";
|
|
10
|
+
export interface NativeProducerScope {
|
|
11
|
+
readonly bindingDigest: string;
|
|
12
|
+
}
|
|
13
|
+
export interface NativeProducerRequest {
|
|
14
|
+
readonly version: typeof NATIVE_PRODUCER_VERSION;
|
|
15
|
+
readonly vendor: NativeProducerVendor;
|
|
16
|
+
readonly agentId: string;
|
|
17
|
+
readonly input: string;
|
|
18
|
+
readonly scope: NativeProducerScope;
|
|
19
|
+
/** Host-selected idempotency key; never derived from prompt text. */
|
|
20
|
+
readonly idempotencyKey: string;
|
|
21
|
+
}
|
|
22
|
+
/** A bounded, host-validated artifact pointer; never a local filesystem path. */
|
|
23
|
+
export interface NativeProducerArtifactReference {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly kind: "dashboard" | "report" | "chart";
|
|
26
|
+
readonly digest: string;
|
|
27
|
+
readonly idempotencyKey: string;
|
|
28
|
+
}
|
|
29
|
+
export type NativeProducerLifecycleState = "accepted" | "running" | "completed" | "failed";
|
|
30
|
+
export interface NativeProducerLifecycle {
|
|
31
|
+
readonly state: NativeProducerLifecycleState;
|
|
32
|
+
}
|
|
33
|
+
export interface NativeProducerSuccess {
|
|
34
|
+
readonly version: typeof NATIVE_PRODUCER_VERSION;
|
|
35
|
+
readonly status: "completed";
|
|
36
|
+
readonly lifecycle: readonly NativeProducerLifecycle[];
|
|
37
|
+
/** Sanitized final result only; never an unparsed dispatcher stream. */
|
|
38
|
+
readonly result: {
|
|
39
|
+
readonly text: string;
|
|
40
|
+
};
|
|
41
|
+
readonly artifacts: readonly NativeProducerArtifactReference[];
|
|
42
|
+
}
|
|
43
|
+
export interface NativeProducerFailure {
|
|
44
|
+
readonly version: typeof NATIVE_PRODUCER_VERSION;
|
|
45
|
+
readonly status: "failed";
|
|
46
|
+
readonly lifecycle: readonly NativeProducerLifecycle[];
|
|
47
|
+
/** Stable category only. Raw subprocess errors are intentionally not surfaced. */
|
|
48
|
+
readonly error: {
|
|
49
|
+
readonly code: NativeProducerErrorCode;
|
|
50
|
+
};
|
|
51
|
+
readonly artifacts: readonly [];
|
|
52
|
+
}
|
|
53
|
+
export type NativeProducerResponse = NativeProducerSuccess | NativeProducerFailure;
|
|
54
|
+
export interface NativeProducerDispatchInput {
|
|
55
|
+
readonly vendor: NativeProducerVendor;
|
|
56
|
+
readonly agentId: string;
|
|
57
|
+
readonly input: string;
|
|
58
|
+
readonly scope: NativeProducerScope;
|
|
59
|
+
readonly idempotencyKey: string;
|
|
60
|
+
readonly signal: AbortSignal;
|
|
61
|
+
readonly fence: NativeProducerHostFence;
|
|
62
|
+
/** Events are available only for local bookkeeping; they never cross this contract. */
|
|
63
|
+
readonly onEvent: (event: AgentEvent) => void;
|
|
64
|
+
}
|
|
65
|
+
/** Host-only bridge to durable session, binding, and artifact state. */
|
|
66
|
+
export interface NativeProducerHostFence {
|
|
67
|
+
readonly bindingDigest: string;
|
|
68
|
+
validateRun(request: NativeProducerRequest): boolean;
|
|
69
|
+
validateRoute(request: NativeProducerRequest, userProject: string): boolean;
|
|
70
|
+
validateArtifact(reference: NativeProducerArtifactReference, request: NativeProducerRequest): boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface NativeProducerDispatchResult {
|
|
73
|
+
readonly text: string;
|
|
74
|
+
readonly artifacts?: readonly NativeProducerArtifactReference[];
|
|
75
|
+
}
|
|
76
|
+
export type NativeProducerDispatch = (input: NativeProducerDispatchInput) => Promise<NativeProducerDispatchResult>;
|
|
77
|
+
export interface NativeProducerOptions {
|
|
78
|
+
readonly fence: NativeProducerHostFence;
|
|
79
|
+
readonly dispatch: NativeProducerDispatch;
|
|
80
|
+
readonly timeoutMs?: number;
|
|
81
|
+
/** Host cancellation; it aborts only this producer's selected dispatcher. */
|
|
82
|
+
readonly signal?: AbortSignal;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A deterministic record of an already-sanitized producer response. It is
|
|
86
|
+
* deliberately independent of the raw dispatcher cassette format: callers
|
|
87
|
+
* replay a stable host contract, not a vendor's opaque wire bytes.
|
|
88
|
+
*/
|
|
89
|
+
export interface NativeProducerCassette {
|
|
90
|
+
readonly version: typeof NATIVE_PRODUCER_VERSION;
|
|
91
|
+
readonly key: string;
|
|
92
|
+
readonly vendor: NativeProducerVendor;
|
|
93
|
+
readonly agentId: string;
|
|
94
|
+
readonly scope: NativeProducerScope;
|
|
95
|
+
readonly response: NativeProducerResponse;
|
|
96
|
+
}
|
|
97
|
+
/** Stable, prompt-free cassette selector for one host-owned idempotent run. */
|
|
98
|
+
export declare function nativeProducerCassetteKey(request: NativeProducerRequest): string;
|
|
99
|
+
/** Runs one noninteractive dispatch and always returns a typed, fail-closed response. */
|
|
100
|
+
export declare function produceNoninteractiveNative(request: unknown, options: NativeProducerOptions): Promise<NativeProducerResponse>;
|
|
101
|
+
/** Replays a sanitized producer cassette; absence, drift, and scope changes fail closed. */
|
|
102
|
+
export declare function replayNoninteractiveNative(request: unknown, cassette: unknown, fence: NativeProducerHostFence): NativeProducerResponse;
|
|
103
|
+
/** Creates a checked-in/replayable record only from an already-safe response. */
|
|
104
|
+
export declare function createNativeProducerCassette(key: string, request: unknown, response: unknown, fence: NativeProducerHostFence): NativeProducerCassette;
|
|
105
|
+
/**
|
|
106
|
+
* Adapts existing subscription dispatchers without widening their protocol.
|
|
107
|
+
* The native producer only admits the vendor selected by the route options.
|
|
108
|
+
*/
|
|
109
|
+
export declare function createRouteNativeProducer(route: (options: RouteOptions) => Promise<RouteResult>, baseOptions: Omit<RouteOptions, "question" | "agentId" | "onEvent" | "signal">): NativeProducerDispatch;
|