agentfootprint 9.18.0 → 9.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CLAUDE.md +4 -2
- package/README.md +2 -0
- package/ai-instructions/claude-code/SKILL.md +1 -1
- package/dist/core/Agent.js +71 -1
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +66 -1
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/buildAgentChart.js +19 -0
- package/dist/core/agent/buildAgentChart.js.map +1 -1
- package/dist/core/agent/buildDynamicAgentChart.js +42 -0
- package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/core/agent/skillBrains.js +216 -0
- package/dist/core/agent/skillBrains.js.map +1 -0
- package/dist/core/agent/stages/callLLM.js +29 -9
- package/dist/core/agent/stages/callLLM.js.map +1 -1
- package/dist/core/agent/stages/routeTurn.js +123 -3
- package/dist/core/agent/stages/routeTurn.js.map +1 -1
- package/dist/core/agent/stages/seed.js +9 -0
- package/dist/core/agent/stages/seed.js.map +1 -1
- package/dist/core/agent/stages/toolCalls.js +326 -8
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/agent/toolEffects.js +242 -0
- package/dist/core/agent/toolEffects.js.map +1 -0
- package/dist/esm/core/Agent.d.ts +6 -1
- package/dist/esm/core/Agent.js +71 -1
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.d.ts +43 -3
- package/dist/esm/core/agent/AgentBuilder.js +66 -1
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/buildAgentChart.d.ts +11 -0
- package/dist/esm/core/agent/buildAgentChart.js +19 -0
- package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
- package/dist/esm/core/agent/buildDynamicAgentChart.js +42 -0
- package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/esm/core/agent/skillBrains.d.ts +144 -0
- package/dist/esm/core/agent/skillBrains.js +209 -0
- package/dist/esm/core/agent/skillBrains.js.map +1 -0
- package/dist/esm/core/agent/stages/callLLM.d.ts +24 -0
- package/dist/esm/core/agent/stages/callLLM.js +29 -9
- package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
- package/dist/esm/core/agent/stages/routeTurn.d.ts +23 -0
- package/dist/esm/core/agent/stages/routeTurn.js +123 -3
- package/dist/esm/core/agent/stages/routeTurn.js.map +1 -1
- package/dist/esm/core/agent/stages/seed.d.ts +8 -0
- package/dist/esm/core/agent/stages/seed.js +9 -0
- package/dist/esm/core/agent/stages/seed.js.map +1 -1
- package/dist/esm/core/agent/stages/toolCalls.d.ts +33 -0
- package/dist/esm/core/agent/stages/toolCalls.js +326 -8
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/agent/toolEffects.d.ts +202 -0
- package/dist/esm/core/agent/toolEffects.js +234 -0
- package/dist/esm/core/agent/toolEffects.js.map +1 -0
- package/dist/esm/core/agent/types.d.ts +35 -0
- package/dist/esm/events/payloads.d.ts +123 -2
- package/dist/esm/events/registry.d.ts +5 -1
- package/dist/esm/events/registry.js +4 -0
- package/dist/esm/events/registry.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js +57 -1
- package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
- package/dist/esm/lib/injection-engine/constrainedEnumPick.d.ts +52 -0
- package/dist/esm/lib/injection-engine/constrainedEnumPick.js +101 -0
- package/dist/esm/lib/injection-engine/constrainedEnumPick.js.map +1 -0
- package/dist/esm/lib/injection-engine/evaluator.d.ts +7 -0
- package/dist/esm/lib/injection-engine/evaluator.js +16 -0
- package/dist/esm/lib/injection-engine/evaluator.js.map +1 -1
- package/dist/esm/lib/injection-engine/factories/defineSkill.d.ts +22 -0
- package/dist/esm/lib/injection-engine/factories/defineSkill.js +7 -0
- package/dist/esm/lib/injection-engine/factories/defineSkill.js.map +1 -1
- package/dist/esm/lib/injection-engine/index.d.ts +1 -0
- package/dist/esm/lib/injection-engine/index.js +3 -0
- package/dist/esm/lib/injection-engine/index.js.map +1 -1
- package/dist/esm/lib/injection-engine/llmClassifier.d.ts +11 -8
- package/dist/esm/lib/injection-engine/llmClassifier.js +27 -84
- package/dist/esm/lib/injection-engine/llmClassifier.js.map +1 -1
- package/dist/esm/lib/injection-engine/routingPolicy.d.ts +10 -3
- package/dist/esm/lib/injection-engine/routingPolicy.js.map +1 -1
- package/dist/esm/lib/injection-engine/skillGraph.d.ts +28 -3
- package/dist/esm/lib/injection-engine/skillGraph.js +80 -12
- package/dist/esm/lib/injection-engine/skillGraph.js.map +1 -1
- package/dist/esm/lib/injection-engine/types.d.ts +30 -0
- package/dist/esm/lib/injection-engine/types.js.map +1 -1
- package/dist/esm/recorders/observability/RouteRecorder.d.ts +6 -1
- package/dist/esm/recorders/observability/RouteRecorder.js +10 -0
- package/dist/esm/recorders/observability/RouteRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/commentary/commentaryTemplates.js +58 -0
- package/dist/esm/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
- package/dist/events/registry.js +4 -0
- package/dist/events/registry.js.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/injection-engine/buildInjectionEngineSubflow.js +57 -1
- package/dist/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
- package/dist/lib/injection-engine/constrainedEnumPick.js +105 -0
- package/dist/lib/injection-engine/constrainedEnumPick.js.map +1 -0
- package/dist/lib/injection-engine/evaluator.js +16 -0
- package/dist/lib/injection-engine/evaluator.js.map +1 -1
- package/dist/lib/injection-engine/factories/defineSkill.js +7 -0
- package/dist/lib/injection-engine/factories/defineSkill.js.map +1 -1
- package/dist/lib/injection-engine/index.js +5 -1
- package/dist/lib/injection-engine/index.js.map +1 -1
- package/dist/lib/injection-engine/llmClassifier.js +27 -84
- package/dist/lib/injection-engine/llmClassifier.js.map +1 -1
- package/dist/lib/injection-engine/routingPolicy.js.map +1 -1
- package/dist/lib/injection-engine/skillGraph.js +80 -12
- package/dist/lib/injection-engine/skillGraph.js.map +1 -1
- package/dist/lib/injection-engine/types.js.map +1 -1
- package/dist/recorders/observability/RouteRecorder.js +10 -0
- package/dist/recorders/observability/RouteRecorder.js.map +1 -1
- package/dist/recorders/observability/commentary/commentaryTemplates.js +58 -0
- package/dist/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
- package/dist/types/core/Agent.d.ts +6 -1
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +43 -3
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/buildAgentChart.d.ts +11 -0
- package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/skillBrains.d.ts +145 -0
- package/dist/types/core/agent/skillBrains.d.ts.map +1 -0
- package/dist/types/core/agent/stages/callLLM.d.ts +24 -0
- package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
- package/dist/types/core/agent/stages/routeTurn.d.ts +23 -0
- package/dist/types/core/agent/stages/routeTurn.d.ts.map +1 -1
- package/dist/types/core/agent/stages/seed.d.ts +8 -0
- package/dist/types/core/agent/stages/seed.d.ts.map +1 -1
- package/dist/types/core/agent/stages/toolCalls.d.ts +33 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/agent/toolEffects.d.ts +203 -0
- package/dist/types/core/agent/toolEffects.d.ts.map +1 -0
- package/dist/types/core/agent/types.d.ts +35 -0
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +123 -2
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/events/registry.d.ts +5 -1
- package/dist/types/events/registry.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/buildInjectionEngineSubflow.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/constrainedEnumPick.d.ts +53 -0
- package/dist/types/lib/injection-engine/constrainedEnumPick.d.ts.map +1 -0
- package/dist/types/lib/injection-engine/evaluator.d.ts +7 -0
- package/dist/types/lib/injection-engine/evaluator.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/factories/defineSkill.d.ts +22 -0
- package/dist/types/lib/injection-engine/factories/defineSkill.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/index.d.ts +1 -0
- package/dist/types/lib/injection-engine/index.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/llmClassifier.d.ts +11 -8
- package/dist/types/lib/injection-engine/llmClassifier.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/routingPolicy.d.ts +10 -3
- package/dist/types/lib/injection-engine/routingPolicy.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/skillGraph.d.ts +28 -3
- package/dist/types/lib/injection-engine/skillGraph.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/types.d.ts +30 -0
- package/dist/types/lib/injection-engine/types.d.ts.map +1 -1
- package/dist/types/recorders/observability/RouteRecorder.d.ts +6 -1
- package/dist/types/recorders/observability/RouteRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/commentary/commentaryTemplates.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* skillBrains — per-skill model switching (9.19.0). ONE owner of the brains
|
|
3
|
+
* fold: the declared shapes (`ProviderChoice`, `EscalationPolicy`), the
|
|
4
|
+
* build-time fold + check-up over BOTH declaration homes, and the runtime
|
|
5
|
+
* `brainFor` consult callLLM makes.
|
|
6
|
+
*
|
|
7
|
+
* "THE CURSOR PICKS THE BRAIN." A skill graph already decides WHERE the run
|
|
8
|
+
* is (the one cursor); this feature lets that same position decide WHO
|
|
9
|
+
* answers — a cheap triage skill on a small model, the refund skill on the
|
|
10
|
+
* strong one — with zero new stages: `callLLM` consults `brainFor(cursor,
|
|
11
|
+
* escalated)` once at the top and resolves field by field down the stated
|
|
12
|
+
* precedence chain:
|
|
13
|
+
*
|
|
14
|
+
* **escalation > per-skill brain > `.configure()` `resolvedModel` >
|
|
15
|
+
* build-time default** — the more specific context wins (evidence > node
|
|
16
|
+
* > run > build). Field-by-field at the call site: `provider =
|
|
17
|
+
* brain?.provider ?? deps.provider`; `model = brain?.model ??
|
|
18
|
+
* (runConfigured ? scope.resolvedModel : undefined) ?? deps.model`;
|
|
19
|
+
* `cacheStrategy = brain?.cacheStrategy ?? deps.cacheStrategy`. A brain
|
|
20
|
+
* naming only a MODEL inherits the agent's provider; a brain naming only a
|
|
21
|
+
* foreign PROVIDER may not inherit the agent's model id (that id belongs
|
|
22
|
+
* to another vendor's namespace and would fail mid-turn, on exactly the
|
|
23
|
+
* iteration the cursor enters the skill) — refused at build instead.
|
|
24
|
+
*
|
|
25
|
+
* TWO declaration homes, one meaning: `defineSkill({ provider, model })`
|
|
26
|
+
* keeps the choice beside the skill it serves; `SkillGraphOptions.providers`
|
|
27
|
+
* keeps a fleet's choices in one place at the mount. The same id declared in
|
|
28
|
+
* both with different choices is refused naming both homes — configuration
|
|
29
|
+
* that disagrees with itself must not pick a silent winner.
|
|
30
|
+
*
|
|
31
|
+
* ESCALATE-ON-EVIDENCE. `escalation: { provider, model?, afterRefusals: N }`
|
|
32
|
+
* — when the gate refuses N routing picks in ONE turn (`skill.rejected`,
|
|
33
|
+
* reachability or posture — real recorded refusals, never vibes), the rest
|
|
34
|
+
* of the turn runs on the escalation brain, `skill.escalated` goes on the
|
|
35
|
+
* record once, and the next turn's seed de-escalates. The loop the model is
|
|
36
|
+
* flubbing gets the bigger brain until the turn resolves.
|
|
37
|
+
*
|
|
38
|
+
* Vendor-neutral by construction: a brain is an `LLMProvider` OBJECT (any
|
|
39
|
+
* port implementation), never a vendor name this library resolves.
|
|
40
|
+
*/
|
|
41
|
+
import { getDefaultCacheStrategy } from '../../cache/strategyRegistry.js';
|
|
42
|
+
/** The per-skill brain declared on `defineSkill({ provider, model })`,
|
|
43
|
+
* read off the metadata bag (the engine-ignores-unknown precedent —
|
|
44
|
+
* `projectActiveInjection` never projects it, so the live provider object
|
|
45
|
+
* stays on the closure-held list and never crosses a scope boundary). */
|
|
46
|
+
export function skillBrainOf(injection) {
|
|
47
|
+
const meta = injection.metadata;
|
|
48
|
+
if (meta?.provider === undefined && meta?.model === undefined)
|
|
49
|
+
return undefined;
|
|
50
|
+
return {
|
|
51
|
+
// `model` alone is legal — the agent's own provider, another model.
|
|
52
|
+
...(meta.provider !== undefined && { provider: meta.provider }),
|
|
53
|
+
...(meta.model !== undefined && { model: meta.model }),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Fold both declaration homes into one frozen map, running every build-time
|
|
58
|
+
* refusal (the check-up). Returns `undefined` when nothing was declared —
|
|
59
|
+
* the zero-cost gate every caller branches on.
|
|
60
|
+
*/
|
|
61
|
+
export function foldSkillBrains(args) {
|
|
62
|
+
const fromOptions = new Map(Object.entries(args.providers ?? {}));
|
|
63
|
+
const fromSkills = new Map();
|
|
64
|
+
for (const inj of args.injections) {
|
|
65
|
+
if (inj.flavor !== 'skill')
|
|
66
|
+
continue;
|
|
67
|
+
const brain = skillBrainOf(inj);
|
|
68
|
+
if (brain)
|
|
69
|
+
fromSkills.set(inj.id, brain);
|
|
70
|
+
}
|
|
71
|
+
const declaredAnything = fromOptions.size > 0 ||
|
|
72
|
+
fromSkills.size > 0 ||
|
|
73
|
+
args.escalation !== undefined ||
|
|
74
|
+
args.decider !== undefined;
|
|
75
|
+
if (!declaredAnything)
|
|
76
|
+
return undefined;
|
|
77
|
+
// A brain with no cursor to pick it: "the cursor picks the brain", and an
|
|
78
|
+
// agent without a graph has no cursor. Refused rather than silently inert.
|
|
79
|
+
if (!args.graphMounted) {
|
|
80
|
+
const ids = [...new Set([...fromOptions.keys(), ...fromSkills.keys()])];
|
|
81
|
+
const what = ids.length > 0
|
|
82
|
+
? `per-skill brains (${ids.map((id) => `'${id}'`).join(', ')})`
|
|
83
|
+
: args.escalation !== undefined
|
|
84
|
+
? 'an escalation policy'
|
|
85
|
+
: 'a routing decider';
|
|
86
|
+
throw new Error(`Agent.build(): ${what} declared, but no skill graph is mounted — the cursor picks ` +
|
|
87
|
+
`the brain, and without .skillGraph() there is no cursor, so the declaration would ` +
|
|
88
|
+
`never serve a single call. Mount a graph, or drop the provider/model declarations.`);
|
|
89
|
+
}
|
|
90
|
+
if (args.nodeIds === undefined) {
|
|
91
|
+
throw new Error(`Agent.build(): per-skill brains / escalation / decider were declared, but the mounted ` +
|
|
92
|
+
`graph object carries no \`nodes\` — the brain check-up cannot tell a skill id from a ` +
|
|
93
|
+
`typo against it. Build the graph with this version's skillGraph() (every graph it ` +
|
|
94
|
+
`builds carries nodes), or drop the declarations.`);
|
|
95
|
+
}
|
|
96
|
+
// Foreign-provider-without-model: decidable at build, guaranteed wrong at
|
|
97
|
+
// run (the agent's model id belongs to another vendor's namespace).
|
|
98
|
+
const requireModelOnForeign = (choice, where) => {
|
|
99
|
+
if (choice.model !== undefined)
|
|
100
|
+
return;
|
|
101
|
+
if (choice.provider === undefined || choice.provider.name === args.agentProviderName)
|
|
102
|
+
return;
|
|
103
|
+
throw new Error(`Agent.build(): ${where} names provider '${choice.provider.name}' without a model. The ` +
|
|
104
|
+
`run's configured model belongs to '${args.agentProviderName}' and cannot be resolved ` +
|
|
105
|
+
`against a different provider — the call would fail mid-turn, on exactly the ` +
|
|
106
|
+
`iteration this brain first serves. Name the model for it (inheritance down the ` +
|
|
107
|
+
`chain stays legal when the provider matches the agent's).`);
|
|
108
|
+
};
|
|
109
|
+
// Merge the two homes. Same id + same choice = fine (one fact said twice);
|
|
110
|
+
// different choices = a disagreement no silent winner may resolve.
|
|
111
|
+
const bySkill = new Map();
|
|
112
|
+
for (const [skillId, choice] of fromSkills)
|
|
113
|
+
bySkill.set(skillId, choice);
|
|
114
|
+
for (const [skillId, choice] of fromOptions) {
|
|
115
|
+
const other = fromSkills.get(skillId);
|
|
116
|
+
if (other !== undefined) {
|
|
117
|
+
const sameProvider = other.provider === choice.provider;
|
|
118
|
+
const sameModel = other.model === choice.model;
|
|
119
|
+
if (!sameProvider || !sameModel) {
|
|
120
|
+
throw new Error(`Agent.build(): skill '${skillId}' declares a brain in BOTH homes with different ` +
|
|
121
|
+
`choices — defineSkill({ provider: ${describeChoice(other)} }) and ` +
|
|
122
|
+
`skillGraph options.providers['${skillId}'] = ${describeChoice(choice)}. Two ` +
|
|
123
|
+
`homes may repeat one choice; they may not disagree. Keep one declaration, or ` +
|
|
124
|
+
`make them identical.`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
bySkill.set(skillId, choice);
|
|
128
|
+
}
|
|
129
|
+
for (const [skillId, choice] of bySkill) {
|
|
130
|
+
if (!args.nodeIds.has(skillId)) {
|
|
131
|
+
throw new Error(`Agent.build(): a brain is declared for skill '${skillId}', but the mounted graph ` +
|
|
132
|
+
`has no node with that id — the cursor can never land there, so the brain would ` +
|
|
133
|
+
`never serve a call. Fix the id, wire the skill into the graph, or drop the ` +
|
|
134
|
+
`declaration.`);
|
|
135
|
+
}
|
|
136
|
+
// `model` alone (provider undefined in the defineSkill home) is the
|
|
137
|
+
// agent's own provider — nothing foreign to check.
|
|
138
|
+
if (choice.provider !== undefined) {
|
|
139
|
+
requireModelOnForeign(choice, `skill '${skillId}''s brain`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (args.escalation !== undefined) {
|
|
143
|
+
const n = args.escalation.afterRefusals;
|
|
144
|
+
if (!Number.isInteger(n) || n < 1) {
|
|
145
|
+
throw new Error(`Agent.build(): escalation.afterRefusals must be an integer ≥ 1 (got ${String(n)}). ` +
|
|
146
|
+
`It counts recorded gate refusals (skill.rejected) in one turn before the flip — ` +
|
|
147
|
+
`0 would mean "always escalated", which is not escalation but a different default ` +
|
|
148
|
+
`brain; declare that as the agent's provider/model instead.`);
|
|
149
|
+
}
|
|
150
|
+
requireModelOnForeign(args.escalation, 'the escalation brain');
|
|
151
|
+
}
|
|
152
|
+
if (args.decider !== undefined) {
|
|
153
|
+
requireModelOnForeign(args.decider, 'the routing decider');
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
bySkill,
|
|
157
|
+
...(args.escalation !== undefined && { escalation: args.escalation }),
|
|
158
|
+
...(args.decider !== undefined && { decider: args.decider }),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function describeChoice(c) {
|
|
162
|
+
const provider = c.provider !== undefined ? `provider '${c.provider.name}'` : 'agent provider';
|
|
163
|
+
return c.model !== undefined ? `${provider}, model '${c.model}'` : provider;
|
|
164
|
+
}
|
|
165
|
+
/** Build the runtime consult. See {@link BrainFor}. */
|
|
166
|
+
export function buildBrainFor(args) {
|
|
167
|
+
const strategyFor = (provider) => provider === undefined || provider.name === args.agentProviderName
|
|
168
|
+
? args.agentCacheStrategy
|
|
169
|
+
: getDefaultCacheStrategy(provider.name);
|
|
170
|
+
const bySkill = new Map();
|
|
171
|
+
for (const [skillId, choice] of args.brains.bySkill) {
|
|
172
|
+
bySkill.set(skillId, {
|
|
173
|
+
provider: choice.provider,
|
|
174
|
+
...(choice.model !== undefined && { model: choice.model }),
|
|
175
|
+
cacheStrategy: strategyFor(choice.provider),
|
|
176
|
+
via: 'skill',
|
|
177
|
+
skillId,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
const escalation = args.brains.escalation
|
|
181
|
+
? {
|
|
182
|
+
provider: args.brains.escalation.provider,
|
|
183
|
+
...(args.brains.escalation.model !== undefined && {
|
|
184
|
+
model: args.brains.escalation.model,
|
|
185
|
+
}),
|
|
186
|
+
cacheStrategy: strategyFor(args.brains.escalation.provider),
|
|
187
|
+
via: 'escalation',
|
|
188
|
+
}
|
|
189
|
+
: undefined;
|
|
190
|
+
return (activeCursor, escalated) => {
|
|
191
|
+
// Evidence outranks the node: once the turn escalated, EVERY remaining
|
|
192
|
+
// call of the turn runs on the escalation brain, whatever the cursor.
|
|
193
|
+
if (escalated && escalation !== undefined)
|
|
194
|
+
return escalation;
|
|
195
|
+
if (activeCursor === undefined)
|
|
196
|
+
return undefined;
|
|
197
|
+
return bySkill.get(activeCursor);
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/** Describe the brain that WOULD serve a cursor pre-escalation — the
|
|
201
|
+
* `skill.escalated` event's honest `from` field, resolved by the same
|
|
202
|
+
* precedence chain callLLM applies (skill brain > configured > default). */
|
|
203
|
+
export function describeServingBrain(args) {
|
|
204
|
+
const brain = args.cursor !== undefined ? args.brains.bySkill.get(args.cursor) : undefined;
|
|
205
|
+
const provider = brain?.provider?.name ?? args.agentProviderName;
|
|
206
|
+
const model = brain?.model ?? args.resolvedModel ?? args.defaultModel;
|
|
207
|
+
return { provider, model };
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=skillBrains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skillBrains.js","sourceRoot":"","sources":["../../../../src/core/agent/skillBrains.ts"],"names":[],"mappings":"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"}
|
|
@@ -90,6 +90,30 @@ export interface CallLLMStageDeps {
|
|
|
90
90
|
* product is the recording.
|
|
91
91
|
*/
|
|
92
92
|
readonly runConfigured?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* "The cursor picks the brain" (9.19.0). Consulted ONCE at the top of the
|
|
95
|
+
* stage with the ADVANCED cursor — `scope.nextSkillCursor ??
|
|
96
|
+
* scope.currentSkillId`, correct in BOTH chart shapes: inside
|
|
97
|
+
* `sf-llm-call` the boundary's `currentSkillId` is a readonly input still
|
|
98
|
+
* holding the previous iteration's cursor and the advanced one lives
|
|
99
|
+
* under `nextSkillCursor`; in the flat chart the engine's outputMapper
|
|
100
|
+
* has already written `currentSkillId` to the advanced value — and with
|
|
101
|
+
* the run's escalation flag (`scope.skillEscalated`, threaded across the
|
|
102
|
+
* `sf-llm-call` boundary by the grouped chart's mappers). The result
|
|
103
|
+
* resolves field by field down the STATED precedence chain:
|
|
104
|
+
*
|
|
105
|
+
* **escalation > per-skill brain > `.configure()` `resolvedModel` >
|
|
106
|
+
* build-time default** — `provider = brain?.provider ?? deps.provider`;
|
|
107
|
+
* `model = brain?.model ?? (runConfigured ? scope.resolvedModel :
|
|
108
|
+
* undefined) ?? deps.model`; `cacheStrategy = brain?.cacheStrategy ??
|
|
109
|
+
* deps.cacheStrategy`. A brain naming only a model inherits the agent's
|
|
110
|
+
* provider; a foreign provider without a model was refused at build.
|
|
111
|
+
*
|
|
112
|
+
* Undefined — no brain declared anywhere — and this stage reads no new
|
|
113
|
+
* scope key, resolves exactly as before, and `llm_start` keeps its exact
|
|
114
|
+
* bytes (the additive `brain` field appears only when a rung won).
|
|
115
|
+
*/
|
|
116
|
+
readonly brainFor?: import('../skillBrains.js').BrainFor;
|
|
93
117
|
}
|
|
94
118
|
/**
|
|
95
119
|
* Build the callLLM stage function. Captures the LLM provider + model
|
|
@@ -54,12 +54,24 @@ export function buildCallLLMStage(deps) {
|
|
|
54
54
|
// `scope.messagesInjections` is read by ContextRecorder for
|
|
55
55
|
// observability; the LLM-wire path now reads scope.history directly.
|
|
56
56
|
const iteration = scope.iteration;
|
|
57
|
+
// "The cursor picks the brain" (9.19.0) — ONE consult, at the top, with
|
|
58
|
+
// the advanced cursor and the escalation flag. Gated on `deps.brainFor`
|
|
59
|
+
// so an agent without brains reads no new scope key and resolves on the
|
|
60
|
+
// exact line it always did.
|
|
61
|
+
const brain = deps.brainFor
|
|
62
|
+
? deps.brainFor((scope.nextSkillCursor ?? scope.currentSkillId), scope.skillEscalated === true)
|
|
63
|
+
: undefined;
|
|
64
|
+
const provider = brain?.provider ?? deps.provider;
|
|
65
|
+
const cacheStrategy = brain?.cacheStrategy ?? deps.cacheStrategy;
|
|
57
66
|
// The model for this run. `.configure()` resolved it at seed and
|
|
58
67
|
// COMMITTED it to scope, so what gets called, what the `llm_start`
|
|
59
68
|
// event reports and what cost is priced against are all one value —
|
|
60
69
|
// the one the trace records. Without `.configure()` this is the
|
|
61
|
-
// build-time model and scope is never touched.
|
|
62
|
-
|
|
70
|
+
// build-time model and scope is never touched. A winning brain rung
|
|
71
|
+
// (9.19.0) outranks both — the stated precedence chain.
|
|
72
|
+
const model = brain?.model ??
|
|
73
|
+
(deps.runConfigured ? scope.resolvedModel : undefined) ??
|
|
74
|
+
deps.model;
|
|
63
75
|
// Per-iteration boundary marker (was a dedicated `IterationStart` stage —
|
|
64
76
|
// folded here since emitting is passive observability, not work that needs
|
|
65
77
|
// its own execution stage). Fires FIRST, before the LLM call, so recorders
|
|
@@ -102,11 +114,19 @@ export function buildCallLLMStage(deps) {
|
|
|
102
114
|
: registeredToolSchemas;
|
|
103
115
|
typedEmit(scope, 'agentfootprint.stream.llm_start', {
|
|
104
116
|
iteration,
|
|
105
|
-
provider:
|
|
117
|
+
provider: provider.name,
|
|
106
118
|
model,
|
|
107
119
|
systemPromptChars: systemPrompt.length,
|
|
108
120
|
messagesCount: messages.length,
|
|
109
121
|
toolsCount: activeToolSchemas.length,
|
|
122
|
+
// WHICH BRAIN answered (9.19.0) — stamped ONLY when a brain rung won,
|
|
123
|
+
// so configured/default runs keep byte-identical events.
|
|
124
|
+
...(brain !== undefined && {
|
|
125
|
+
brain: {
|
|
126
|
+
via: brain.via,
|
|
127
|
+
...(brain.skillId !== undefined && { skillId: brain.skillId }),
|
|
128
|
+
},
|
|
129
|
+
}),
|
|
110
130
|
...(activeToolSchemas.length > 0 && {
|
|
111
131
|
tools: activeToolSchemas.map((t) => ({
|
|
112
132
|
name: t.name,
|
|
@@ -135,7 +155,7 @@ export function buildCallLLMStage(deps) {
|
|
|
135
155
|
// and populated scope.cacheMarkers accordingly. Strategy.prepareRequest
|
|
136
156
|
// is a pass-through for empty markers.
|
|
137
157
|
const cacheMarkers = scope.cacheMarkers ?? [];
|
|
138
|
-
const cachePrepared = await
|
|
158
|
+
const cachePrepared = await cacheStrategy.prepareRequest(baseRequest, cacheMarkers, {
|
|
139
159
|
iteration,
|
|
140
160
|
iterationsRemaining: Math.max(0, deps.maxIterations - iteration),
|
|
141
161
|
recentHitRate: scope.recentHitRate,
|
|
@@ -167,8 +187,8 @@ export function buildCallLLMStage(deps) {
|
|
|
167
187
|
const singleProviderCall = async (req, hooks) => {
|
|
168
188
|
let resp;
|
|
169
189
|
let firstChunkFired = false;
|
|
170
|
-
if (
|
|
171
|
-
for await (const chunk of
|
|
190
|
+
if (provider.stream) {
|
|
191
|
+
for await (const chunk of provider.stream(req, providerHooks)) {
|
|
172
192
|
if (chunk.done) {
|
|
173
193
|
if (chunk.response)
|
|
174
194
|
resp = chunk.response;
|
|
@@ -182,7 +202,7 @@ export function buildCallLLMStage(deps) {
|
|
|
182
202
|
// with its own marker instead of `done: true`, which is why the
|
|
183
203
|
// refusal says what the terminal chunk looks like.
|
|
184
204
|
if (typeof chunk.content !== 'string') {
|
|
185
|
-
throw new TypeError(`provider '${
|
|
205
|
+
throw new TypeError(`provider '${provider.name}' yielded a stream chunk whose \`content\` is ` +
|
|
186
206
|
`${chunk.content === undefined ? 'missing' : `a ${typeof chunk.content}`}. ` +
|
|
187
207
|
`Every chunk from LLMProvider.stream() is ` +
|
|
188
208
|
`{ tokenIndex: number, content: string, done: boolean }, and the LAST one is ` +
|
|
@@ -213,7 +233,7 @@ export function buildCallLLMStage(deps) {
|
|
|
213
233
|
// those are two genuinely billed calls and collapsing them would
|
|
214
234
|
// hide real double-billing. (That this branch can re-call at all
|
|
215
235
|
// after a stream is a pre-existing quirk; see MENTAL_MODEL §14.)
|
|
216
|
-
resp = await
|
|
236
|
+
resp = await provider.complete(req, providerHooks);
|
|
217
237
|
}
|
|
218
238
|
// `'tool-forced'`: the answer arrived as the synthetic tool's ARGUMENTS,
|
|
219
239
|
// so it is moved into `content` and the call is taken off the list here,
|
|
@@ -276,7 +296,7 @@ export function buildCallLLMStage(deps) {
|
|
|
276
296
|
}
|
|
277
297
|
let response;
|
|
278
298
|
if (deps.reliability) {
|
|
279
|
-
response = await executeWithReliability(scope, llmRequest, deps.reliability,
|
|
299
|
+
response = await executeWithReliability(scope, llmRequest, deps.reliability, provider, provider.name, model, singleProviderCall, postValidate);
|
|
280
300
|
// `executeWithReliability` returns `undefined` when it took the
|
|
281
301
|
// fail-fast path. It already wrote scope state and called
|
|
282
302
|
// `$break(reason)` — `Agent.run()` translates the propagated
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callLLM.js","sourceRoot":"","sources":["../../../../../src/core/agent/stages/callLLM.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAYH,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAE7E,OAAO,EAAE,YAAY,EAA2B,MAAM,eAAe,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAA2B,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAElB,MAAM,2BAA2B,CAAC;AAGnC;;;;;;;GAOG;AACH,SAAS,oBAAoB,CAAC,QAA+B;IAC3D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IACvE,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACxB,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS;YAAE,OAAO,CAAC,CAAC;QACzC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;QAC3C,KAAK,OAAO,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;
|
|
1
|
+
{"version":3,"file":"callLLM.js","sourceRoot":"","sources":["../../../../../src/core/agent/stages/callLLM.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
* and the README names it.
|
|
48
48
|
*/
|
|
49
49
|
import type { TypedScope } from 'footprintjs';
|
|
50
|
+
import type { LLMProvider } from '../../../adapters/types.js';
|
|
50
51
|
import type { AgentState } from '../types.js';
|
|
51
52
|
import type { InjectionContext } from '../../../lib/injection-engine/types.js';
|
|
52
53
|
import type { EntryScoring } from '../../../lib/injection-engine/skillGraph.js';
|
|
@@ -69,5 +70,27 @@ export interface RouteTurnDeps {
|
|
|
69
70
|
/** Which skills the caller's role may not see (9.11.0) — excluded from
|
|
70
71
|
* candidates, scores, menus and the envelope. Fail-closed inside. */
|
|
71
72
|
readonly hiddenSkillIds?: () => Promise<readonly string[]> | readonly string[];
|
|
73
|
+
/**
|
|
74
|
+
* The tier-3 DECIDER (9.19.0) — an out-of-band constrained pick over an
|
|
75
|
+
* outstanding menu ∪ {stay}, resolved HERE, before the loop, with the
|
|
76
|
+
* `constrainedEnumPick` machinery (the `llmClassifier` discipline: forced
|
|
77
|
+
* tool on providers that constrain, strict parse + one re-ask + `'none'`
|
|
78
|
+
* everywhere else — ids never fabricated). A decisive pick starts the
|
|
79
|
+
* turn (`turn_routed { by: 'decider' }`, additive); `'stay'` holds the
|
|
80
|
+
* incumbent (`by: 'continuity'`, decider recorded); `'none'` / parse
|
|
81
|
+
* failure / a throw leaves the in-band envelope standing, decider
|
|
82
|
+
* recorded with `picked` absent. Rails × decider is ADMITTED — the
|
|
83
|
+
* decider is constrained, off-loop and recorded (a scorer in posture
|
|
84
|
+
* terms), which makes it the sanctioned resolver for rails menus.
|
|
85
|
+
* Undefined → every menu keeps its exact 9.17 behavior.
|
|
86
|
+
*/
|
|
87
|
+
readonly decider?: {
|
|
88
|
+
readonly provider: LLMProvider;
|
|
89
|
+
readonly model?: string;
|
|
90
|
+
/** The agent's build-time model — the chain's last rung. */
|
|
91
|
+
readonly defaultModel: string;
|
|
92
|
+
/** `.configure()` present — only then is `scope.resolvedModel` read. */
|
|
93
|
+
readonly runConfigured: boolean;
|
|
94
|
+
};
|
|
72
95
|
}
|
|
73
96
|
export declare function makeRouteTurnStage(deps: RouteTurnDeps): (scope: TypedScope<AgentState>) => Promise<void>;
|
|
@@ -49,7 +49,12 @@
|
|
|
49
49
|
import { isDevMode } from 'footprintjs';
|
|
50
50
|
import { validateIntentScores } from '../../../lib/injection-engine/intentScorer.js';
|
|
51
51
|
import { decideTier2, } from '../../../lib/injection-engine/routingPolicy.js';
|
|
52
|
+
import { constrainedEnumPick } from '../../../lib/injection-engine/constrainedEnumPick.js';
|
|
52
53
|
import { typedEmit } from '../../../recorders/core/typedEmit.js';
|
|
54
|
+
/** The decider's `'stay'` sentinel — first-class on mid-conversation menus. */
|
|
55
|
+
const DECIDER_STAY = 'stay';
|
|
56
|
+
/** The decider's decline sentinel (the enum machinery's fallback). */
|
|
57
|
+
const DECIDER_NONE = 'none';
|
|
53
58
|
export function makeRouteTurnStage(deps) {
|
|
54
59
|
const plan = deps.turnRouting;
|
|
55
60
|
return async (scope) => {
|
|
@@ -88,7 +93,7 @@ export function makeRouteTurnStage(deps) {
|
|
|
88
93
|
'Fix the resolver passed to hiddenSkillIds.');
|
|
89
94
|
}
|
|
90
95
|
const visibleEntryIds = plan.entryIds.filter((id) => !hidden.has(id));
|
|
91
|
-
|
|
96
|
+
let verdict = await runCascade(deps, plan, ctx, inherited, hidden, visibleEntryIds, env.signal);
|
|
92
97
|
if (verdict === undefined && droppedResume === undefined) {
|
|
93
98
|
// Cold start on a continuity graph with no tier 2 at all: the resolver's
|
|
94
99
|
// cold walk decides exactly as it always has — no verdict, no event.
|
|
@@ -100,6 +105,59 @@ export function makeRouteTurnStage(deps) {
|
|
|
100
105
|
scope.entryScores = verdict.scores;
|
|
101
106
|
scope.entryScorer = verdict.scorer;
|
|
102
107
|
}
|
|
108
|
+
// ── Tier-3 DECIDER (9.19.0) — the out-of-band menu resolver ────────
|
|
109
|
+
// Runs HERE, off the hot loop, only when a menu verdict is actually
|
|
110
|
+
// outstanding. A decisive pick starts the turn; 'stay' holds the
|
|
111
|
+
// incumbent; 'none'/parse-fail/throw leaves the in-band envelope
|
|
112
|
+
// standing. The consult is ALWAYS recorded on the event (`decider`),
|
|
113
|
+
// picked or not — a resolver that ran and said nothing is still a fact.
|
|
114
|
+
let deciderRecord;
|
|
115
|
+
/** Set when the decider RESOLVED the menu — the menu is then no longer
|
|
116
|
+
* outstanding, so the scope POJO carries no `offered` (the rails
|
|
117
|
+
* what-happened vs what-the-loop-may-act-on split, reused). */
|
|
118
|
+
let deciderResolved;
|
|
119
|
+
if (deps.decider !== undefined &&
|
|
120
|
+
verdict !== undefined &&
|
|
121
|
+
verdict.by === 'menu' &&
|
|
122
|
+
verdict.offered !== undefined &&
|
|
123
|
+
verdict.offered.length > 0) {
|
|
124
|
+
// The precedence chain's model rung, for the decider's own call:
|
|
125
|
+
// declared > `.configure()` resolvedModel > build-time default.
|
|
126
|
+
const deciderModel = deps.decider.model ??
|
|
127
|
+
(deps.decider.runConfigured ? scope.resolvedModel : undefined) ??
|
|
128
|
+
deps.decider.defaultModel;
|
|
129
|
+
const stayAllowed = verdict.stayOffered === true && inherited !== undefined;
|
|
130
|
+
const picked = await runDecider({
|
|
131
|
+
provider: deps.decider.provider,
|
|
132
|
+
model: deciderModel,
|
|
133
|
+
plan,
|
|
134
|
+
userMessage: ctx.userMessage,
|
|
135
|
+
offered: verdict.offered,
|
|
136
|
+
stayAllowed,
|
|
137
|
+
inherited,
|
|
138
|
+
signal: env.signal,
|
|
139
|
+
});
|
|
140
|
+
deciderRecord = {
|
|
141
|
+
provider: deps.decider.provider.name,
|
|
142
|
+
model: deciderModel,
|
|
143
|
+
...(picked !== undefined && { picked }),
|
|
144
|
+
};
|
|
145
|
+
if (picked !== undefined && picked !== DECIDER_STAY) {
|
|
146
|
+
// Decisive pick: the turn starts there. `offered` stays on the
|
|
147
|
+
// VERDICT (the event keeps the full menu); the POJO below drops it.
|
|
148
|
+
verdict = { ...verdict, by: 'decider', to: picked };
|
|
149
|
+
deciderResolved = 'move';
|
|
150
|
+
}
|
|
151
|
+
else if (picked === DECIDER_STAY) {
|
|
152
|
+
// STAY is a resolution too: the incumbent holds AND the menu closes
|
|
153
|
+
// — the scope TurnRoute carries no `offered` while the event keeps
|
|
154
|
+
// the full offered set (nice-6; guard's `menuOutstanding` then
|
|
155
|
+
// refuses late picks against a menu the decider already answered).
|
|
156
|
+
verdict = { ...verdict, by: 'continuity', to: inherited };
|
|
157
|
+
deciderResolved = 'stay';
|
|
158
|
+
}
|
|
159
|
+
// picked === undefined → the in-band envelope stands, decider recorded.
|
|
160
|
+
}
|
|
103
161
|
const policy = plan.policy;
|
|
104
162
|
const effectiveFloor = policy.floor ?? plan.scorer?.floor;
|
|
105
163
|
// Rails × menu: the model may not act on it — record the offer, act on none.
|
|
@@ -122,6 +180,7 @@ export function makeRouteTurnStage(deps) {
|
|
|
122
180
|
},
|
|
123
181
|
...(verdict?.window !== undefined && { window: verdict.window }),
|
|
124
182
|
...(droppedResume !== undefined && { droppedResume }),
|
|
183
|
+
...(deciderRecord !== undefined && { decider: { ...deciderRecord } }),
|
|
125
184
|
});
|
|
126
185
|
// The POJO the LOOP acts on — the resolver's iteration-1 input, the
|
|
127
186
|
// envelope's source, the guard gate's window. Under rails a menu carries
|
|
@@ -133,13 +192,23 @@ export function makeRouteTurnStage(deps) {
|
|
|
133
192
|
// untouched, or the drop would silently strand the turn on no entry.
|
|
134
193
|
if (verdict === undefined)
|
|
135
194
|
return;
|
|
195
|
+
// A decider-RESOLVED menu (move OR stay) is no longer outstanding: the
|
|
196
|
+
// POJO carries no `offered`, so the envelope composes none and `guard`'s
|
|
197
|
+
// `menuOutstanding` goes false — while the event above kept the full
|
|
198
|
+
// offered set. Same split rails ships; one more case earns it.
|
|
199
|
+
const menuStillOutstanding = deciderResolved === undefined;
|
|
136
200
|
const turnRoute = {
|
|
137
201
|
by: eventBy,
|
|
138
202
|
...(inherited !== undefined && { from: inherited }),
|
|
139
203
|
...(verdict.to !== undefined && { to: verdict.to }),
|
|
140
|
-
...(!rails && verdict.offered !== undefined && { offered: [...verdict.offered] }),
|
|
141
|
-
...(!rails && verdict.stayOffered !== undefined && { stayOffered: verdict.stayOffered }),
|
|
142
204
|
...(!rails &&
|
|
205
|
+
menuStillOutstanding &&
|
|
206
|
+
verdict.offered !== undefined && { offered: [...verdict.offered] }),
|
|
207
|
+
...(!rails &&
|
|
208
|
+
menuStillOutstanding &&
|
|
209
|
+
verdict.stayOffered !== undefined && { stayOffered: verdict.stayOffered }),
|
|
210
|
+
...(!rails &&
|
|
211
|
+
menuStillOutstanding &&
|
|
143
212
|
verdict.offered !== undefined &&
|
|
144
213
|
verdict.scores !== undefined && {
|
|
145
214
|
relevance: verdict.scores.map((s) => ({ id: s.id, relevance: s.relevance })),
|
|
@@ -292,6 +361,57 @@ function menuVerdict(offered, stayOffered, scorerName, window) {
|
|
|
292
361
|
...(window !== undefined && { window }),
|
|
293
362
|
};
|
|
294
363
|
}
|
|
364
|
+
/**
|
|
365
|
+
* The tier-3 decider's one constrained call (9.19.0). Candidates project
|
|
366
|
+
* from the offered entries' declared intents, else their descriptions —
|
|
367
|
+
* `plan.incumbentCandidate` is the one projection that already does exactly
|
|
368
|
+
* that, so ids are never fabricated. `'stay'` joins the enum only on a
|
|
369
|
+
* mid-conversation menu. Returns the picked id / `'stay'`, or `undefined`
|
|
370
|
+
* when the decider declined (`'none'`, a parse failure after the one
|
|
371
|
+
* re-ask, or a throw — dev-warned): a decider is a tier, never a
|
|
372
|
+
* correctness dependency, so the in-band envelope stands.
|
|
373
|
+
*/
|
|
374
|
+
async function runDecider(args) {
|
|
375
|
+
const lines = args.offered.map((id) => {
|
|
376
|
+
const candidate = args.plan.incumbentCandidate(id);
|
|
377
|
+
return `- ${candidate.id}: ${candidate.intent}`;
|
|
378
|
+
});
|
|
379
|
+
if (args.stayAllowed) {
|
|
380
|
+
lines.push(`- ${DECIDER_STAY}: continue the current skill '${args.inherited}'`);
|
|
381
|
+
}
|
|
382
|
+
const allowed = [...args.offered, ...(args.stayAllowed ? [DECIDER_STAY] : []), DECIDER_NONE];
|
|
383
|
+
const systemPrompt = `You route ONE user message to a skill from a fixed menu.\n` +
|
|
384
|
+
`Menu:\n${lines.join('\n')}\n\n` +
|
|
385
|
+
`Pick the single id that should handle the message. If genuinely none fits, pick ` +
|
|
386
|
+
`'${DECIDER_NONE}'. Never invent an id.`;
|
|
387
|
+
try {
|
|
388
|
+
const picked = await constrainedEnumPick({
|
|
389
|
+
provider: args.provider,
|
|
390
|
+
model: args.model,
|
|
391
|
+
systemPrompt,
|
|
392
|
+
messages: [{ role: 'user', content: args.userMessage }],
|
|
393
|
+
allowed,
|
|
394
|
+
fallback: DECIDER_NONE,
|
|
395
|
+
pickTool: {
|
|
396
|
+
name: 'pick_skill',
|
|
397
|
+
description: `Report which menu skill should handle the user's message ('${DECIDER_NONE}' if none).`,
|
|
398
|
+
argName: 'skill',
|
|
399
|
+
argDescription: 'The picked skill id.',
|
|
400
|
+
},
|
|
401
|
+
...(args.signal !== undefined && { signal: args.signal }),
|
|
402
|
+
});
|
|
403
|
+
return picked === DECIDER_NONE ? undefined : picked;
|
|
404
|
+
}
|
|
405
|
+
catch (err) {
|
|
406
|
+
if (isDevMode()) {
|
|
407
|
+
// eslint-disable-next-line no-console
|
|
408
|
+
console.warn(`agentfootprint RouteTurn: the routing decider threw — the menu stands and the ` +
|
|
409
|
+
`in-band envelope resolves it (recorded: turn_routed.decider with no pick). ` +
|
|
410
|
+
`${err instanceof Error ? err.message : String(err)}`);
|
|
411
|
+
}
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
295
415
|
/** The prior conversational turns a windowed scorer sees — user/assistant
|
|
296
416
|
* roles only, the CURRENT user message excluded, newest last. */
|
|
297
417
|
function recentTurnsOf(history, window) {
|