@mcp-abap-adt/llm-agent-server-libs 19.1.2 → 20.0.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/dist/factories/controller-factory.d.ts +20 -6
- package/dist/factories/controller-factory.d.ts.map +1 -1
- package/dist/factories/controller-factory.js +52 -11
- package/dist/factories/controller-factory.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/pipelines/controller.d.ts +4 -2
- package/dist/pipelines/controller.d.ts.map +1 -1
- package/dist/pipelines/controller.js +55 -5
- package/dist/pipelines/controller.js.map +1 -1
- package/dist/pipelines/dag.d.ts +2 -2
- package/dist/pipelines/dag.d.ts.map +1 -1
- package/dist/pipelines/dag.js +4 -3
- package/dist/pipelines/dag.js.map +1 -1
- package/dist/pipelines/flat.d.ts.map +1 -1
- package/dist/pipelines/flat.js +2 -1
- package/dist/pipelines/flat.js.map +1 -1
- package/dist/pipelines/linear.d.ts.map +1 -1
- package/dist/pipelines/linear.js +2 -1
- package/dist/pipelines/linear.js.map +1 -1
- package/dist/pipelines/register-skill-sources.d.ts +21 -0
- package/dist/pipelines/register-skill-sources.d.ts.map +1 -0
- package/dist/pipelines/register-skill-sources.js +57 -0
- package/dist/pipelines/register-skill-sources.js.map +1 -0
- package/dist/pipelines/server-context.d.ts +37 -1
- package/dist/pipelines/server-context.d.ts.map +1 -1
- package/dist/pipelines/server-context.js.map +1 -1
- package/dist/pipelines/stepper.d.ts +2 -2
- package/dist/pipelines/stepper.js +2 -2
- package/dist/smart-agent/config.d.ts +1 -1
- package/dist/smart-agent/config.d.ts.map +1 -1
- package/dist/smart-agent/config.js +7 -3
- package/dist/smart-agent/config.js.map +1 -1
- package/dist/smart-agent/controller/artifacts.d.ts +116 -0
- package/dist/smart-agent/controller/artifacts.d.ts.map +1 -0
- package/dist/smart-agent/controller/artifacts.js +192 -0
- package/dist/smart-agent/controller/artifacts.js.map +1 -0
- package/dist/smart-agent/controller/board.d.ts +73 -0
- package/dist/smart-agent/controller/board.d.ts.map +1 -0
- package/dist/smart-agent/controller/board.js +233 -0
- package/dist/smart-agent/controller/board.js.map +1 -0
- package/dist/smart-agent/controller/controller-coordinator-handler.d.ts +75 -7
- package/dist/smart-agent/controller/controller-coordinator-handler.d.ts.map +1 -1
- package/dist/smart-agent/controller/controller-coordinator-handler.js +929 -66
- package/dist/smart-agent/controller/controller-coordinator-handler.js.map +1 -1
- package/dist/smart-agent/controller/finalizer.d.ts +48 -0
- package/dist/smart-agent/controller/finalizer.d.ts.map +1 -0
- package/dist/smart-agent/controller/finalizer.js +126 -0
- package/dist/smart-agent/controller/finalizer.js.map +1 -0
- package/dist/smart-agent/controller/memorizer.d.ts +2 -2
- package/dist/smart-agent/controller/memorizer.d.ts.map +1 -1
- package/dist/smart-agent/controller/memorizer.js +2 -2
- package/dist/smart-agent/controller/memorizer.js.map +1 -1
- package/dist/smart-agent/controller/outcome.d.ts +28 -0
- package/dist/smart-agent/controller/outcome.d.ts.map +1 -0
- package/dist/smart-agent/controller/outcome.js +30 -0
- package/dist/smart-agent/controller/outcome.js.map +1 -0
- package/dist/smart-agent/controller/planner.d.ts +41 -14
- package/dist/smart-agent/controller/planner.d.ts.map +1 -1
- package/dist/smart-agent/controller/planner.js +149 -73
- package/dist/smart-agent/controller/planner.js.map +1 -1
- package/dist/smart-agent/controller/reviewer.d.ts +48 -0
- package/dist/smart-agent/controller/reviewer.d.ts.map +1 -0
- package/dist/smart-agent/controller/reviewer.js +116 -0
- package/dist/smart-agent/controller/reviewer.js.map +1 -0
- package/dist/smart-agent/controller/run-scope.d.ts +50 -0
- package/dist/smart-agent/controller/run-scope.d.ts.map +1 -0
- package/dist/smart-agent/controller/run-scope.js +99 -0
- package/dist/smart-agent/controller/run-scope.js.map +1 -0
- package/dist/smart-agent/controller/session-bundle.d.ts +5 -0
- package/dist/smart-agent/controller/session-bundle.d.ts.map +1 -1
- package/dist/smart-agent/controller/session-bundle.js +27 -0
- package/dist/smart-agent/controller/session-bundle.js.map +1 -1
- package/dist/smart-agent/controller/types.d.ts +124 -15
- package/dist/smart-agent/controller/types.d.ts.map +1 -1
- package/dist/smart-agent/controller/types.js +30 -1
- package/dist/smart-agent/controller/types.js.map +1 -1
- package/dist/smart-agent/embedder-knowledge-index.d.ts +28 -0
- package/dist/smart-agent/embedder-knowledge-index.d.ts.map +1 -0
- package/dist/smart-agent/embedder-knowledge-index.js +71 -0
- package/dist/smart-agent/embedder-knowledge-index.js.map +1 -0
- package/dist/smart-agent/jsonl-knowledge-backend.d.ts +26 -10
- package/dist/smart-agent/jsonl-knowledge-backend.d.ts.map +1 -1
- package/dist/smart-agent/jsonl-knowledge-backend.js +81 -9
- package/dist/smart-agent/jsonl-knowledge-backend.js.map +1 -1
- package/dist/smart-agent/pg-pool.d.ts +58 -0
- package/dist/smart-agent/pg-pool.d.ts.map +1 -0
- package/dist/smart-agent/pg-pool.js +149 -0
- package/dist/smart-agent/pg-pool.js.map +1 -0
- package/dist/smart-agent/skill-plugins-config.d.ts +97 -0
- package/dist/smart-agent/skill-plugins-config.d.ts.map +1 -0
- package/dist/smart-agent/skill-plugins-config.js +318 -0
- package/dist/smart-agent/skill-plugins-config.js.map +1 -0
- package/dist/smart-agent/skill-plugins-config.test.d.ts +2 -0
- package/dist/smart-agent/skill-plugins-config.test.d.ts.map +1 -0
- package/dist/smart-agent/skill-plugins-config.test.js.map +1 -0
- package/dist/smart-agent/skill-plugins-host-factory.d.ts +98 -0
- package/dist/smart-agent/skill-plugins-host-factory.d.ts.map +1 -0
- package/dist/smart-agent/skill-plugins-host-factory.js +284 -0
- package/dist/smart-agent/skill-plugins-host-factory.js.map +1 -0
- package/dist/smart-agent/skill-plugins-host-factory.test.d.ts +2 -0
- package/dist/smart-agent/skill-plugins-host-factory.test.d.ts.map +1 -0
- package/dist/smart-agent/skill-plugins-host-factory.test.js.map +1 -0
- package/dist/smart-agent/smart-server.d.ts +25 -0
- package/dist/smart-agent/smart-server.d.ts.map +1 -1
- package/dist/smart-agent/smart-server.js +141 -7
- package/dist/smart-agent/smart-server.js.map +1 -1
- package/package.json +9 -7
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
/** Deterministic content-hash id (the spec's `uuidv5(...)` realised without a
|
|
3
|
+
* new dependency - matches run-scope.ts's createHash usage). Segments are
|
|
4
|
+
* length-prefixed so no concatenation collision is possible
|
|
5
|
+
* (['a','bc'] and ['ab','c'] hash differently). */
|
|
6
|
+
export function deterministicId(...segments) {
|
|
7
|
+
const h = createHash('sha256');
|
|
8
|
+
for (const s of segments) {
|
|
9
|
+
const str = String(s);
|
|
10
|
+
h.update(String(str.length));
|
|
11
|
+
h.update(' ');
|
|
12
|
+
h.update(str);
|
|
13
|
+
}
|
|
14
|
+
return h.digest('hex');
|
|
15
|
+
}
|
|
16
|
+
/** Slot the decision occupies (one winner per slot, §F). */
|
|
17
|
+
export function decisionSlotId(k) {
|
|
18
|
+
switch (k.kind) {
|
|
19
|
+
case 'create':
|
|
20
|
+
return deterministicId(k.runId, 'create');
|
|
21
|
+
case 'replan':
|
|
22
|
+
return 'anchor' in k
|
|
23
|
+
? deterministicId(k.runId, 'replan', 'anchor', k.anchor)
|
|
24
|
+
: deterministicId(k.runId, 'replan', 'trigger', k.triggerId);
|
|
25
|
+
case 'expand':
|
|
26
|
+
return deterministicId(k.runId, 'expand', k.discoveryStepId, k.offset);
|
|
27
|
+
case 'page':
|
|
28
|
+
return deterministicId(k.runId, 'page', k.discoveryChainId, k.pageIndex);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Content-hash decision id. LLM-authored kinds fold `plannerOutput` (identical
|
|
32
|
+
* output → identical id → dedup; differing → different id). The controller-
|
|
33
|
+
* authored `page` is deterministic from its key fields + tokenHash (no
|
|
34
|
+
* plannerOutput). (§F: at-least-once invocation, exactly-once applied effect.) */
|
|
35
|
+
export function decisionId(k, plannerOutput) {
|
|
36
|
+
switch (k.kind) {
|
|
37
|
+
case 'create':
|
|
38
|
+
return deterministicId(k.runId, 'create', plannerOutput);
|
|
39
|
+
case 'replan':
|
|
40
|
+
return 'anchor' in k
|
|
41
|
+
? deterministicId(k.runId, 'replan', 'anchor', k.anchor, plannerOutput)
|
|
42
|
+
: deterministicId(k.runId, 'replan', 'trigger', k.triggerId, plannerOutput);
|
|
43
|
+
case 'expand':
|
|
44
|
+
return deterministicId(k.runId, 'expand', k.discoveryStepId, k.offset, plannerOutput);
|
|
45
|
+
case 'page':
|
|
46
|
+
return deterministicId(k.runId, 'page', k.discoveryChainId, k.pageIndex, k.tokenHash);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export const PLAN_DECISION_ARTIFACT = 'plan-decision';
|
|
50
|
+
/** The DecisionKey for slot/id computation. Fail-loud: a malformed decision
|
|
51
|
+
* (e.g. a `page` with no `tokenHash`) throws rather than hashing a '' field. */
|
|
52
|
+
function keyOf(d) {
|
|
53
|
+
switch (d.kind) {
|
|
54
|
+
case 'create':
|
|
55
|
+
return { kind: 'create', runId: d.runId };
|
|
56
|
+
case 'replan':
|
|
57
|
+
if ('anchor' in d)
|
|
58
|
+
return { kind: 'replan', runId: d.runId, anchor: d.anchor };
|
|
59
|
+
if ('triggerId' in d)
|
|
60
|
+
return { kind: 'replan', runId: d.runId, triggerId: d.triggerId };
|
|
61
|
+
throw new Error('plan-decision replan requires anchor or triggerId');
|
|
62
|
+
case 'expand':
|
|
63
|
+
if (d.discoveryStepId === undefined || d.offset === undefined)
|
|
64
|
+
throw new Error('plan-decision expand requires discoveryStepId + offset');
|
|
65
|
+
return {
|
|
66
|
+
kind: 'expand',
|
|
67
|
+
runId: d.runId,
|
|
68
|
+
discoveryStepId: d.discoveryStepId,
|
|
69
|
+
offset: d.offset,
|
|
70
|
+
};
|
|
71
|
+
case 'page':
|
|
72
|
+
if (!d.tokenHash)
|
|
73
|
+
throw new Error('plan-decision page requires tokenHash');
|
|
74
|
+
return {
|
|
75
|
+
kind: 'page',
|
|
76
|
+
runId: d.runId,
|
|
77
|
+
discoveryChainId: d.discoveryChainId,
|
|
78
|
+
pageIndex: d.pageIndex,
|
|
79
|
+
tokenHash: d.tokenHash,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export async function writePlanDecision(be, sessionId, d, plannerOutput, nowIso, writeOrdinal) {
|
|
84
|
+
const k = keyOf(d);
|
|
85
|
+
await be.put(sessionId, {
|
|
86
|
+
content: JSON.stringify({ steps: d.steps }),
|
|
87
|
+
metadata: {
|
|
88
|
+
traceId: sessionId,
|
|
89
|
+
turnId: sessionId,
|
|
90
|
+
stepperId: 'controller',
|
|
91
|
+
task: 'controller',
|
|
92
|
+
artifactType: PLAN_DECISION_ARTIFACT,
|
|
93
|
+
runId: d.runId,
|
|
94
|
+
kind: d.kind,
|
|
95
|
+
slotId: decisionSlotId(k),
|
|
96
|
+
decisionId: decisionId(k, plannerOutput),
|
|
97
|
+
createdAt: nowIso,
|
|
98
|
+
writeOrdinal,
|
|
99
|
+
...(d.kind === 'replan' && 'anchor' in d
|
|
100
|
+
? { supersedesStepId: d.anchor }
|
|
101
|
+
: {}),
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
export async function readPlanDecisions(rag, runId) {
|
|
106
|
+
const list = await rag.list({ runId, artifactType: PLAN_DECISION_ARTIFACT });
|
|
107
|
+
return list.map((e) => ({
|
|
108
|
+
runId,
|
|
109
|
+
kind: (e.metadata.kind ?? 'create'),
|
|
110
|
+
decisionId: e.metadata.decisionId,
|
|
111
|
+
slotId: e.metadata.slotId,
|
|
112
|
+
steps: JSON.parse(e.content).steps,
|
|
113
|
+
writeOrdinal: e.metadata.writeOrdinal ?? 0,
|
|
114
|
+
anchorStepId: e.metadata.supersedesStepId,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
export const STEP_START_ARTIFACT = 'step-start';
|
|
118
|
+
export async function writeStepStartClaim(be, sessionId,
|
|
119
|
+
// `writeOrdinal` is supplied as a separate arg (the value WRITTEN to metadata),
|
|
120
|
+
// so the claim INPUT omits it; `StepStartClaim` stays the read/persisted shape.
|
|
121
|
+
c, nowIso, writeOrdinal) {
|
|
122
|
+
await be.put(sessionId, {
|
|
123
|
+
content: '',
|
|
124
|
+
metadata: {
|
|
125
|
+
traceId: sessionId,
|
|
126
|
+
turnId: sessionId,
|
|
127
|
+
stepperId: 'controller',
|
|
128
|
+
task: 'controller',
|
|
129
|
+
artifactType: STEP_START_ARTIFACT,
|
|
130
|
+
runId: c.runId,
|
|
131
|
+
slotId: c.slotId,
|
|
132
|
+
stepId: c.stepId,
|
|
133
|
+
seq: c.seq,
|
|
134
|
+
attempt: c.attempt,
|
|
135
|
+
decisionId: c.decisionId,
|
|
136
|
+
createdAt: nowIso,
|
|
137
|
+
writeOrdinal,
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
export async function readClaims(rag, runId) {
|
|
142
|
+
const list = await rag.list({ runId, artifactType: STEP_START_ARTIFACT });
|
|
143
|
+
// A persisted claim ALWAYS has a writeOrdinal (writeStepStartClaim sets it).
|
|
144
|
+
// Drop any claim missing it (malformed/foreign row) rather than defaulting to
|
|
145
|
+
// 0, which would make ordering input-dependent.
|
|
146
|
+
return list.flatMap((e) => {
|
|
147
|
+
if (typeof e.metadata.writeOrdinal !== 'number')
|
|
148
|
+
return [];
|
|
149
|
+
return [
|
|
150
|
+
{
|
|
151
|
+
runId,
|
|
152
|
+
slotId: e.metadata.slotId ?? '',
|
|
153
|
+
stepId: e.metadata.stepId ?? '',
|
|
154
|
+
seq: e.metadata.seq ?? 0,
|
|
155
|
+
attempt: e.metadata.attempt ?? 0,
|
|
156
|
+
decisionId: e.metadata.decisionId ?? '',
|
|
157
|
+
writeOrdinal: e.metadata.writeOrdinal,
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
/** The decision that owns a slot = the FIRST claim for it, by ascending
|
|
163
|
+
* `writeOrdinal` (monotonic per run ⇒ unique ⇒ a total, input-order-independent
|
|
164
|
+
* order). Attempt-independent: a retry never changes which decision owns the
|
|
165
|
+
* slot (§F). */
|
|
166
|
+
export function decisionWinner(claims, slotId) {
|
|
167
|
+
const forSlot = claims.filter((c) => c.slotId === slotId);
|
|
168
|
+
if (forSlot.length === 0)
|
|
169
|
+
return undefined;
|
|
170
|
+
forSlot.sort((a, b) => a.writeOrdinal - b.writeOrdinal);
|
|
171
|
+
return forSlot[0].decisionId;
|
|
172
|
+
}
|
|
173
|
+
/** Mint stable plan-time stepIds for a freshly created plan (§F). Pure: returns
|
|
174
|
+
* NEW step objects (does not mutate the input). `deterministicId(runId,'create',i)`
|
|
175
|
+
* is replay-stable — an at-least-once planner re-call produces identical ids. */
|
|
176
|
+
export function mintCreateStepIds(steps, runId) {
|
|
177
|
+
return steps.map((s, i) => ({
|
|
178
|
+
...s,
|
|
179
|
+
stepId: deterministicId(runId, 'create', i),
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
/** Mint stepIds for a replan's replacement tail (§F). Each replacement gets a NEW
|
|
183
|
+
* stepId keyed by the superseded anchor; the FIRST replacement carries
|
|
184
|
+
* `supersedesStepId = anchorStepId` (it replaces the failed step). Pure. */
|
|
185
|
+
export function mintReplanStepIds(steps, runId, anchorStepId) {
|
|
186
|
+
return steps.map((s, i) => ({
|
|
187
|
+
...s,
|
|
188
|
+
stepId: deterministicId(runId, 'replan', anchorStepId, i),
|
|
189
|
+
...(i === 0 ? { supersedesStepId: anchorStepId } : {}),
|
|
190
|
+
}));
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { KnowledgeEntry } from '@mcp-abap-adt/llm-agent';
|
|
2
|
+
import type { PlanDecisionRecord, StepStartClaim } from './artifacts.js';
|
|
3
|
+
import type { InFlightStep, PendingMarker, Step } from './types.js';
|
|
4
|
+
export type StepState = 'planned' | 'executing' | 'awaiting-external' | 'done' | 'partial' | 'failed';
|
|
5
|
+
export interface BoardEntry {
|
|
6
|
+
stepId: string;
|
|
7
|
+
name: string;
|
|
8
|
+
instructions: string;
|
|
9
|
+
state: StepState;
|
|
10
|
+
digest?: string;
|
|
11
|
+
seq?: number;
|
|
12
|
+
attempt?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface BoardInputs {
|
|
15
|
+
structure: PlanDecisionRecord[];
|
|
16
|
+
stepResults: readonly KnowledgeEntry[];
|
|
17
|
+
claims: StepStartClaim[];
|
|
18
|
+
inFlight?: InFlightStep;
|
|
19
|
+
/** The run-level pending marker — it lives on the SessionBundle, NOT on
|
|
20
|
+
* InFlightStep. Passed in so the board can refine the current in-flight step's
|
|
21
|
+
* transient state to `awaiting-external` when the run is suspended on an
|
|
22
|
+
* external tool. */
|
|
23
|
+
pending?: PendingMarker;
|
|
24
|
+
}
|
|
25
|
+
/** Replay create/replan decisions (writeOrdinal order) into the canonical CURRENT
|
|
26
|
+
* plan (§F arbitration): a later `create` (a crash-retry of a not-yet-persisted
|
|
27
|
+
* plan) REPLACES the earlier one; a `replan` replaces the plan tail from its
|
|
28
|
+
* superseded anchor (steps[0].supersedesStepId) onward. Steps dropped by a
|
|
29
|
+
* replacement therefore never appear as phantom `planned` entries. */
|
|
30
|
+
export declare function reconstructPlanStructure(decisions: PlanDecisionRecord[]): Step[];
|
|
31
|
+
/** Rebuild the step-state board from artifacts (§F), sources 1–3. */
|
|
32
|
+
export declare function reconstructBoard(input: BoardInputs): Map<string, BoardEntry>;
|
|
33
|
+
/** Thrown by renderBoard when the protected (uncompactable) content still exceeds
|
|
34
|
+
* maxBoardChars (§B): the controller catches it and fails loud / suspends BEFORE
|
|
35
|
+
* the planner call rather than feeding a lossy board. */
|
|
36
|
+
export declare class BoardOverBudgetError extends Error {
|
|
37
|
+
readonly rendered: number;
|
|
38
|
+
readonly cap: number;
|
|
39
|
+
constructor(rendered: number, cap: number);
|
|
40
|
+
}
|
|
41
|
+
/** Board render budget (§B). All bounds are REQUIRED so the cap is guaranteed. */
|
|
42
|
+
export interface BoardBudget {
|
|
43
|
+
/** Cap on a non-discovery free-text digest (terminal entries). */
|
|
44
|
+
maxDigestChars: number;
|
|
45
|
+
/** Cap on an actionable entry's rendered intent (never dropped, only trimmed). */
|
|
46
|
+
maxIntentChars: number;
|
|
47
|
+
/** Bound on simultaneously-actionable entries (the §D capacity gate enforces it;
|
|
48
|
+
* here it sizes the load-time invariant). */
|
|
49
|
+
maxActiveSteps: number;
|
|
50
|
+
/** Hard cap on the whole rendered board. */
|
|
51
|
+
maxBoardChars: number;
|
|
52
|
+
/** Number of most-recent terminal digests kept in full before compaction. */
|
|
53
|
+
keepRecentDigests: number;
|
|
54
|
+
}
|
|
55
|
+
/** Validate the board budget at load (§B fail-loud invariant): all knobs are
|
|
56
|
+
* non-negative integers, and the worst-case actionable block + the kept digests +
|
|
57
|
+
* headroom fit `maxBoardChars`. A fixed per-line overhead (~24 chars: `[`, stepId8,
|
|
58
|
+
* space, state, `] `, newline) is folded into the estimate.
|
|
59
|
+
*
|
|
60
|
+
* The `maxActiveSteps` term is the §D-capacity-gated worst case (fan-out ≤
|
|
61
|
+
* maxFanOut, one window at a time). In Phase 2 (no §D gate) the actionable count is
|
|
62
|
+
* NOT bounded by maxActiveSteps — a one-shot plan materialises every future step as
|
|
63
|
+
* `planned`. So this check is the load-time sizing guide; the HARD runtime
|
|
64
|
+
* guarantee that the board never exceeds the cap is `renderBoard`'s
|
|
65
|
+
* `BoardOverBudgetError` throw (the controller catches it → fail-loud). */
|
|
66
|
+
export declare function validateBoardBudget(b: BoardBudget): void;
|
|
67
|
+
/** Render the reconstructed board to ONE bounded text block (§B). Deterministic:
|
|
68
|
+
* same board ⇒ same output. Actionable (not-terminal) entries are always rendered
|
|
69
|
+
* individually (stepId + state + bounded intent); terminal entries keep the most
|
|
70
|
+
* recent K digests in full and compact older ones oldest-first, dropping to an
|
|
71
|
+
* "omitted" marker if the cap is still exceeded. */
|
|
72
|
+
export declare function renderBoard(board: Map<string, BoardEntry>, budget: BoardBudget): string;
|
|
73
|
+
//# sourceMappingURL=board.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/controller/board.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGzE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,WAAW,GACX,mBAAmB,GACnB,MAAM,GACN,SAAS,GACT,QAAQ,CAAC;AAEb,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,WAAW,EAAE,SAAS,cAAc,EAAE,CAAC;IACvC,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;yBAGqB;IACrB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED;;;;uEAIuE;AACvE,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,kBAAkB,EAAE,GAC9B,IAAI,EAAE,CAmBR;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAiI5E;AAED;;0DAE0D;AAC1D,qBAAa,oBAAqB,SAAQ,KAAK;IAE3C,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM;gBADX,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM;CAKvB;AAED,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,cAAc,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,cAAc,EAAE,MAAM,CAAC;IACvB;kDAC8C;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAID;;;;;;;;;;4EAU4E;AAC5E,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,CAsBxD;AAED;;;;qDAIqD;AACrD,wBAAgB,WAAW,CACzB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAC9B,MAAM,EAAE,WAAW,GAClB,MAAM,CAwDR"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { projectStepState, resolveByPrecedence } from './outcome.js';
|
|
2
|
+
/** Replay create/replan decisions (writeOrdinal order) into the canonical CURRENT
|
|
3
|
+
* plan (§F arbitration): a later `create` (a crash-retry of a not-yet-persisted
|
|
4
|
+
* plan) REPLACES the earlier one; a `replan` replaces the plan tail from its
|
|
5
|
+
* superseded anchor (steps[0].supersedesStepId) onward. Steps dropped by a
|
|
6
|
+
* replacement therefore never appear as phantom `planned` entries. */
|
|
7
|
+
export function reconstructPlanStructure(decisions) {
|
|
8
|
+
const ordered = [...decisions].sort((a, b) => a.writeOrdinal - b.writeOrdinal);
|
|
9
|
+
let plan = [];
|
|
10
|
+
for (const dec of ordered) {
|
|
11
|
+
if (dec.kind === 'create') {
|
|
12
|
+
plan = dec.steps;
|
|
13
|
+
}
|
|
14
|
+
else if (dec.kind === 'replan') {
|
|
15
|
+
const anchor = dec.anchorStepId ?? dec.steps[0]?.supersedesStepId;
|
|
16
|
+
const idx = anchor ? plan.findIndex((s) => s.stepId === anchor) : -1;
|
|
17
|
+
plan =
|
|
18
|
+
idx >= 0
|
|
19
|
+
? [...plan.slice(0, idx), ...dec.steps]
|
|
20
|
+
: [...plan, ...dec.steps];
|
|
21
|
+
}
|
|
22
|
+
// expand/page kinds are not produced in Phase 2 — ignored (later-phase concern).
|
|
23
|
+
}
|
|
24
|
+
return plan;
|
|
25
|
+
}
|
|
26
|
+
/** Rebuild the step-state board from artifacts (§F), sources 1–3. */
|
|
27
|
+
export function reconstructBoard(input) {
|
|
28
|
+
const board = new Map();
|
|
29
|
+
// (1) Structure ← the canonical replayed plan (§F arbitration): a stale create or
|
|
30
|
+
// a replan-dropped tail never becomes a phantom `planned` entry.
|
|
31
|
+
const canonical = reconstructPlanStructure(input.structure);
|
|
32
|
+
// Lookup over EVERY step ever decided — used to resurrect executed-but-dropped steps.
|
|
33
|
+
const everDecided = new Map();
|
|
34
|
+
for (const dec of input.structure) {
|
|
35
|
+
for (const s of dec.steps) {
|
|
36
|
+
if (s.stepId)
|
|
37
|
+
everDecided.set(s.stepId, s);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (const s of canonical) {
|
|
41
|
+
if (!s.stepId)
|
|
42
|
+
continue;
|
|
43
|
+
board.set(s.stepId, {
|
|
44
|
+
stepId: s.stepId,
|
|
45
|
+
name: s.name,
|
|
46
|
+
instructions: s.instructions,
|
|
47
|
+
state: 'planned',
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// (1b) Resurrect EXECUTED steps a replacement dropped from the canonical plan: an
|
|
51
|
+
// executed step is immutable history (§F) and must stay on the board with its
|
|
52
|
+
// terminal state; an UNEXECUTED dropped step is a phantom and stays out.
|
|
53
|
+
for (const e of input.stepResults) {
|
|
54
|
+
if (e.metadata.artifactType !== 'step-result')
|
|
55
|
+
continue;
|
|
56
|
+
const id = e.metadata.stepId;
|
|
57
|
+
if (!id || board.has(id))
|
|
58
|
+
continue;
|
|
59
|
+
const s = everDecided.get(id);
|
|
60
|
+
if (s) {
|
|
61
|
+
board.set(id, {
|
|
62
|
+
stepId: id,
|
|
63
|
+
name: s.name,
|
|
64
|
+
instructions: s.instructions,
|
|
65
|
+
state: 'planned',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const resultsByStep = new Map();
|
|
70
|
+
for (const e of input.stepResults) {
|
|
71
|
+
if (e.metadata.artifactType !== 'step-result')
|
|
72
|
+
continue;
|
|
73
|
+
const id = e.metadata.stepId;
|
|
74
|
+
if (!id)
|
|
75
|
+
continue;
|
|
76
|
+
const bucket = resultsByStep.get(id);
|
|
77
|
+
if (bucket)
|
|
78
|
+
bucket.push(e);
|
|
79
|
+
else
|
|
80
|
+
resultsByStep.set(id, [e]);
|
|
81
|
+
}
|
|
82
|
+
const claimsByStep = new Map();
|
|
83
|
+
for (const c of input.claims) {
|
|
84
|
+
const bucket = claimsByStep.get(c.stepId);
|
|
85
|
+
if (bucket)
|
|
86
|
+
bucket.push(c);
|
|
87
|
+
else
|
|
88
|
+
claimsByStep.set(c.stepId, [c]);
|
|
89
|
+
}
|
|
90
|
+
// (2)+(3) Terminal / transient state, attempt-scoped (§F).
|
|
91
|
+
for (const [stepId, entry] of board) {
|
|
92
|
+
const results = resultsByStep.get(stepId) ?? [];
|
|
93
|
+
const claims = claimsByStep.get(stepId) ?? [];
|
|
94
|
+
const maxResultAttempt = results.reduce((m, e) => Math.max(m, e.metadata.attempt ?? 0), -1);
|
|
95
|
+
const maxClaimAttempt = claims.reduce((m, c) => Math.max(m, c.attempt), -1);
|
|
96
|
+
const inFlightForStep = input.inFlight && input.inFlight.step?.stepId === stepId
|
|
97
|
+
? input.inFlight
|
|
98
|
+
: undefined;
|
|
99
|
+
const maxAttempt = Math.max(maxResultAttempt, maxClaimAttempt, inFlightForStep ? inFlightForStep.attempt : -1);
|
|
100
|
+
if (maxAttempt < 0)
|
|
101
|
+
continue; // never started → stays 'planned'
|
|
102
|
+
const settledForCurrent = results.filter((e) => (e.metadata.attempt ?? 0) === maxAttempt);
|
|
103
|
+
if (settledForCurrent.length === 0) {
|
|
104
|
+
entry.state =
|
|
105
|
+
inFlightForStep?.phase === 'executing' &&
|
|
106
|
+
input.pending?.kind === 'external-tool'
|
|
107
|
+
? 'awaiting-external'
|
|
108
|
+
: 'executing';
|
|
109
|
+
entry.attempt = maxAttempt;
|
|
110
|
+
// Populate seq from the in-flight step first; fall back to the max-attempt claim.
|
|
111
|
+
const maxAttemptClaim = claims.reduce((best, c) => c.attempt === maxAttempt &&
|
|
112
|
+
(!best || c.writeOrdinal >= best.writeOrdinal)
|
|
113
|
+
? c
|
|
114
|
+
: best, undefined);
|
|
115
|
+
entry.seq = inFlightForStep?.seq ?? maxAttemptClaim?.seq;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const outcomes = settledForCurrent
|
|
119
|
+
.slice()
|
|
120
|
+
.sort((a, b) => (a.metadata.writeOrdinal ?? 0) - (b.metadata.writeOrdinal ?? 0))
|
|
121
|
+
.map((e) => ({
|
|
122
|
+
status: (e.metadata.status ?? 'failed'),
|
|
123
|
+
approved: e.content,
|
|
124
|
+
remainder: e.metadata.remainder ?? '',
|
|
125
|
+
note: e.metadata.note ?? '',
|
|
126
|
+
}));
|
|
127
|
+
const resolved = resolveByPrecedence(outcomes);
|
|
128
|
+
if (!resolved)
|
|
129
|
+
continue;
|
|
130
|
+
entry.state = projectStepState(resolved.status);
|
|
131
|
+
entry.attempt = maxAttempt;
|
|
132
|
+
const winner = settledForCurrent
|
|
133
|
+
.filter((e) => (e.metadata.status ?? 'failed') === resolved.status)
|
|
134
|
+
.reduce((best, e) => !best ||
|
|
135
|
+
(e.metadata.writeOrdinal ?? 0) >= (best.metadata.writeOrdinal ?? 0)
|
|
136
|
+
? e
|
|
137
|
+
: best, undefined);
|
|
138
|
+
entry.digest = winner?.metadata.digest;
|
|
139
|
+
entry.seq = winner?.metadata.seq;
|
|
140
|
+
}
|
|
141
|
+
return board;
|
|
142
|
+
}
|
|
143
|
+
/** Thrown by renderBoard when the protected (uncompactable) content still exceeds
|
|
144
|
+
* maxBoardChars (§B): the controller catches it and fails loud / suspends BEFORE
|
|
145
|
+
* the planner call rather than feeding a lossy board. */
|
|
146
|
+
export class BoardOverBudgetError extends Error {
|
|
147
|
+
rendered;
|
|
148
|
+
cap;
|
|
149
|
+
constructor(rendered, cap) {
|
|
150
|
+
super(`rendered board (${rendered} chars) exceeds maxBoardChars (${cap})`);
|
|
151
|
+
this.rendered = rendered;
|
|
152
|
+
this.cap = cap;
|
|
153
|
+
this.name = 'BoardOverBudgetError';
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const TERMINAL = new Set(['done', 'partial', 'failed']);
|
|
157
|
+
/** Validate the board budget at load (§B fail-loud invariant): all knobs are
|
|
158
|
+
* non-negative integers, and the worst-case actionable block + the kept digests +
|
|
159
|
+
* headroom fit `maxBoardChars`. A fixed per-line overhead (~24 chars: `[`, stepId8,
|
|
160
|
+
* space, state, `] `, newline) is folded into the estimate.
|
|
161
|
+
*
|
|
162
|
+
* The `maxActiveSteps` term is the §D-capacity-gated worst case (fan-out ≤
|
|
163
|
+
* maxFanOut, one window at a time). In Phase 2 (no §D gate) the actionable count is
|
|
164
|
+
* NOT bounded by maxActiveSteps — a one-shot plan materialises every future step as
|
|
165
|
+
* `planned`. So this check is the load-time sizing guide; the HARD runtime
|
|
166
|
+
* guarantee that the board never exceeds the cap is `renderBoard`'s
|
|
167
|
+
* `BoardOverBudgetError` throw (the controller catches it → fail-loud). */
|
|
168
|
+
export function validateBoardBudget(b) {
|
|
169
|
+
for (const [k, v] of Object.entries(b)) {
|
|
170
|
+
if (!Number.isInteger(v) || v < 0) {
|
|
171
|
+
throw new Error(`BoardBudget.${k} must be a non-negative integer (got ${v})`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const PER_LINE_OVERHEAD = 24;
|
|
175
|
+
const actionableWorstCase = b.maxActiveSteps * (PER_LINE_OVERHEAD + b.maxIntentChars);
|
|
176
|
+
const digestsWorstCase = b.keepRecentDigests * (PER_LINE_OVERHEAD + b.maxDigestChars);
|
|
177
|
+
const headroom = 256;
|
|
178
|
+
const needed = actionableWorstCase + digestsWorstCase + headroom;
|
|
179
|
+
if (needed > b.maxBoardChars) {
|
|
180
|
+
throw new Error(`BoardBudget invariant violated: worst-case board (${needed}) exceeds ` +
|
|
181
|
+
`maxBoardChars (${b.maxBoardChars}). Increase maxBoardChars or reduce ` +
|
|
182
|
+
`maxActiveSteps/maxIntentChars/keepRecentDigests/maxDigestChars.`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/** Render the reconstructed board to ONE bounded text block (§B). Deterministic:
|
|
186
|
+
* same board ⇒ same output. Actionable (not-terminal) entries are always rendered
|
|
187
|
+
* individually (stepId + state + bounded intent); terminal entries keep the most
|
|
188
|
+
* recent K digests in full and compact older ones oldest-first, dropping to an
|
|
189
|
+
* "omitted" marker if the cap is still exceeded. */
|
|
190
|
+
export function renderBoard(board, budget) {
|
|
191
|
+
const entries = [...board.values()];
|
|
192
|
+
if (entries.length === 0)
|
|
193
|
+
return '';
|
|
194
|
+
const short = (id) => id.slice(0, 8);
|
|
195
|
+
const actionable = entries
|
|
196
|
+
.filter((e) => !TERMINAL.has(e.state))
|
|
197
|
+
.sort((a, b) => (a.seq ?? Number.POSITIVE_INFINITY) -
|
|
198
|
+
(b.seq ?? Number.POSITIVE_INFINITY) ||
|
|
199
|
+
a.stepId.localeCompare(b.stepId))
|
|
200
|
+
.map((e) => `[${short(e.stepId)} ${e.state}] ${e.instructions.slice(0, budget.maxIntentChars)}`);
|
|
201
|
+
const terminals = entries
|
|
202
|
+
.filter((e) => TERMINAL.has(e.state))
|
|
203
|
+
.sort((a, b) => (a.seq ?? 0) - (b.seq ?? 0));
|
|
204
|
+
const cutoff = Math.max(0, terminals.length - budget.keepRecentDigests);
|
|
205
|
+
const recentLines = terminals
|
|
206
|
+
.slice(cutoff)
|
|
207
|
+
.map((e) => `[seq ${e.seq ?? 0} ${e.name} ${e.state}] ${(e.digest ?? '').slice(0, budget.maxDigestChars)}`);
|
|
208
|
+
let olderLines = terminals
|
|
209
|
+
.slice(0, cutoff)
|
|
210
|
+
.map((e) => `[seq ${e.seq ?? 0} ${e.name} ${e.state}]`);
|
|
211
|
+
const assemble = (older, omitted) => [
|
|
212
|
+
...actionable,
|
|
213
|
+
...(omitted > 0 ? [`… ${omitted} earlier steps omitted`] : []),
|
|
214
|
+
...older,
|
|
215
|
+
...recentLines,
|
|
216
|
+
].join('\n');
|
|
217
|
+
let text = assemble(olderLines, 0);
|
|
218
|
+
let omitted = 0;
|
|
219
|
+
while (text.length > budget.maxBoardChars && olderLines.length > 0) {
|
|
220
|
+
olderLines = olderLines.slice(1);
|
|
221
|
+
omitted++;
|
|
222
|
+
text = assemble(olderLines, omitted);
|
|
223
|
+
}
|
|
224
|
+
// GUARANTEED cap (§B): older summaries are now exhausted. The remaining content
|
|
225
|
+
// (protected actionable block + K recent digests + omitted marker) is
|
|
226
|
+
// uncompactable — if it STILL exceeds the cap, do NOT return a lossy board; throw
|
|
227
|
+
// so the controller fails loud / suspends BEFORE the planner call.
|
|
228
|
+
if (text.length > budget.maxBoardChars) {
|
|
229
|
+
throw new BoardOverBudgetError(text.length, budget.maxBoardChars);
|
|
230
|
+
}
|
|
231
|
+
return text;
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=board.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/board.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAiCrE;;;;uEAIuE;AACvE,MAAM,UAAU,wBAAwB,CACtC,SAA+B;IAE/B,MAAM,OAAO,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CACjC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAC1C,CAAC;IACF,IAAI,IAAI,GAAW,EAAE,CAAC;IACtB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC;QACnB,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC;YAClE,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrE,IAAI;gBACF,GAAG,IAAI,CAAC;oBACN,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC;oBACvC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,iFAAiF;IACnF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,gBAAgB,CAAC,KAAkB;IACjD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE5C,kFAAkF;IAClF,qEAAqE;IACrE,MAAM,SAAS,GAAG,wBAAwB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC5D,sFAAsF;IACtF,MAAM,WAAW,GAAG,IAAI,GAAG,EAAgB,CAAC;IAC5C,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QAClC,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,CAAC,MAAM;gBAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,CAAC,MAAM;YAAE,SAAS;QACxB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE;YAClB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,YAAY,EAAE,CAAC,CAAC,YAAY;YAC5B,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;IACL,CAAC;IACD,kFAAkF;IAClF,mFAAmF;IACnF,8EAA8E;IAC9E,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QAClC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,KAAK,aAAa;YAAE,SAAS;QACxD,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,EAAE,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,SAAS;QACnC,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,EAAE,CAAC;YACN,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE;gBACZ,MAAM,EAAE,EAAE;gBACV,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,YAAY,EAAE,CAAC,CAAC,YAAY;gBAC5B,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,GAAG,EAA4B,CAAC;IAC1D,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QAClC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,KAAK,aAAa;YAAE,SAAS;QACxD,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,EAAE;YAAE,SAAS;QAClB,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;YACtB,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,GAAG,EAA4B,CAAC;IACzD,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;YACtB,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,2DAA2D;IAC3D,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9C,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CACrC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC,EAC9C,CAAC,CAAC,CACH,CAAC;QACF,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5E,MAAM,eAAe,GACnB,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;YACtD,CAAC,CAAC,KAAK,CAAC,QAAQ;YAChB,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CACzB,gBAAgB,EAChB,eAAe,EACf,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAC/C,CAAC;QAEF,IAAI,UAAU,GAAG,CAAC;YAAE,SAAS,CAAC,kCAAkC;QAEhE,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CACtC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,UAAU,CAChD,CAAC;QACF,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,KAAK,CAAC,KAAK;gBACT,eAAe,EAAE,KAAK,KAAK,WAAW;oBACtC,KAAK,CAAC,OAAO,EAAE,IAAI,KAAK,eAAe;oBACrC,CAAC,CAAC,mBAAmB;oBACrB,CAAC,CAAC,WAAW,CAAC;YAClB,KAAK,CAAC,OAAO,GAAG,UAAU,CAAC;YAC3B,kFAAkF;YAClF,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CACnC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CACV,CAAC,CAAC,OAAO,KAAK,UAAU;gBACxB,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC;gBAC5C,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,IAAI,EACV,SAAS,CACV,CAAC;YACF,KAAK,CAAC,GAAG,GAAG,eAAe,EAAE,GAAG,IAAI,eAAe,EAAE,GAAG,CAAC;YACzD,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAc,iBAAiB;aAC1C,KAAK,EAAE;aACP,IAAI,CACH,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,IAAI,CAAC,CAAC,CAClE;aACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAsB;YAC5D,QAAQ,EAAE,CAAC,CAAC,OAAO;YACnB,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE;YACrC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE;SAC5B,CAAC,CAAC,CAAC;QACN,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ;YAAE,SAAS;QACxB,KAAK,CAAC,KAAK,GAAG,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAChD,KAAK,CAAC,OAAO,GAAG,UAAU,CAAC;QAC3B,MAAM,MAAM,GAAG,iBAAiB;aAC7B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,KAAK,QAAQ,CAAC,MAAM,CAAC;aAClE,MAAM,CACL,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CACV,CAAC,IAAI;YACL,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,IAAI,CAAC,CAAC;YACjE,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,IAAI,EACV,SAAS,CACV,CAAC;QACJ,KAAK,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;QACvC,KAAK,CAAC,GAAG,GAAG,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC;IACnC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;0DAE0D;AAC1D,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAElC;IACA;IAFX,YACW,QAAgB,EAChB,GAAW;QAEpB,KAAK,CAAC,mBAAmB,QAAQ,kCAAkC,GAAG,GAAG,CAAC,CAAC;QAHlE,aAAQ,GAAR,QAAQ,CAAQ;QAChB,QAAG,GAAH,GAAG,CAAQ;QAGpB,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAiBD,MAAM,QAAQ,GAA2B,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEhF;;;;;;;;;;4EAU4E;AAC5E,MAAM,UAAU,mBAAmB,CAAC,CAAc;IAChD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CACb,eAAe,CAAC,wCAAwC,CAAC,GAAG,CAC7D,CAAC;QACJ,CAAC;IACH,CAAC;IACD,MAAM,iBAAiB,GAAG,EAAE,CAAC;IAC7B,MAAM,mBAAmB,GACvB,CAAC,CAAC,cAAc,GAAG,CAAC,iBAAiB,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC;IAC5D,MAAM,gBAAgB,GACpB,CAAC,CAAC,iBAAiB,GAAG,CAAC,iBAAiB,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,GAAG,CAAC;IACrB,MAAM,MAAM,GAAG,mBAAmB,GAAG,gBAAgB,GAAG,QAAQ,CAAC;IACjE,IAAI,MAAM,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,qDAAqD,MAAM,YAAY;YACrE,kBAAkB,CAAC,CAAC,aAAa,sCAAsC;YACvE,iEAAiE,CACpE,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;qDAIqD;AACrD,MAAM,UAAU,WAAW,CACzB,KAA8B,EAC9B,MAAmB;IAEnB,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE7C,MAAM,UAAU,GAAG,OAAO;SACvB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;SACrC,IAAI,CACH,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,iBAAiB,CAAC;QACjC,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,iBAAiB,CAAC;QACrC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CACnC;SACA,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,EAAE,CACtF,CAAC;IAEJ,MAAM,SAAS,GAAG,OAAO;SACtB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;SACpC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAE/C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACxE,MAAM,WAAW,GAAG,SAAS;SAC1B,KAAK,CAAC,MAAM,CAAC;SACb,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,EAAE,CACjG,CAAC;IACJ,IAAI,UAAU,GAAG,SAAS;SACvB,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC;SAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;IAE1D,MAAM,QAAQ,GAAG,CAAC,KAAe,EAAE,OAAe,EAAU,EAAE,CAC5D;QACE,GAAG,UAAU;QACb,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,wBAAwB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,GAAG,KAAK;QACR,GAAG,WAAW;KACf,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEf,IAAI,IAAI,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACnC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAO,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnE,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACjC,OAAO,EAAE,CAAC;QACV,IAAI,GAAG,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,gFAAgF;IAChF,sEAAsE;IACtE,kFAAkF;IAClF,mEAAmE;IACnE,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;QACvC,MAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { type CallOptions, type IEmbedder, type IKnowledgeRagHandle, type IRequestLogger, type IStageHandler, type LlmTool, type LlmUsage, type ModelUsageEntry } from '@mcp-abap-adt/llm-agent';
|
|
1
|
+
import { type CallOptions, type IEmbedder, type IKnowledgeRagHandle, type IRequestLogger, type IStageHandler, type KnowledgeEntry, type LlmTool, type LlmUsage, type ModelUsageEntry } from '@mcp-abap-adt/llm-agent';
|
|
2
2
|
import { type KnowledgeBackend, type PipelineContext } from '@mcp-abap-adt/llm-agent-libs';
|
|
3
|
+
import type { IFinalizer } from './finalizer.js';
|
|
4
|
+
import type { IReviewer } from './reviewer.js';
|
|
5
|
+
import type { RunIdMinter } from './run-scope.js';
|
|
3
6
|
import type { ISubagentClient } from './subagent-client.js';
|
|
4
|
-
import type
|
|
7
|
+
import { type ControllerConfig, type IControllerPlanner, type NextStep, type PlannerKind } from './types.js';
|
|
5
8
|
/** Flat usage triple + per-model breakdown — the canonical terminal-chunk shape. */
|
|
6
9
|
export type TerminalUsage = LlmUsage & {
|
|
7
10
|
models?: Record<string, ModelUsageEntry>;
|
|
@@ -17,6 +20,8 @@ export declare function makeLogUsage(requestLogger: IRequestLogger, requestId: s
|
|
|
17
20
|
evaluator: string;
|
|
18
21
|
planner: string;
|
|
19
22
|
executor: string;
|
|
23
|
+
reviewer?: string;
|
|
24
|
+
finalizer?: string;
|
|
20
25
|
}): (role: string, u?: LlmUsage) => void;
|
|
21
26
|
export interface ControllerHandlerDeps {
|
|
22
27
|
evaluator: ISubagentClient;
|
|
@@ -44,13 +49,43 @@ export interface ControllerHandlerDeps {
|
|
|
44
49
|
*/
|
|
45
50
|
isExternalTool?: (toolName: string) => boolean;
|
|
46
51
|
config: ControllerConfig;
|
|
47
|
-
/** Resolved model id per subagent role, for usage attribution
|
|
48
|
-
* the planner model
|
|
52
|
+
/** Resolved model id per subagent role, for usage attribution. reviewer/finalizer
|
|
53
|
+
* fall back to the planner model when their subagent config is absent. */
|
|
49
54
|
models: {
|
|
50
55
|
evaluator: string;
|
|
51
56
|
planner: string;
|
|
52
57
|
executor: string;
|
|
58
|
+
reviewer?: string;
|
|
59
|
+
finalizer?: string;
|
|
53
60
|
};
|
|
61
|
+
/** Judge role. Optional; when absent the handler uses a built-in
|
|
62
|
+
* approve-content reviewer (legacy behaviour — every content result is 'ok')
|
|
63
|
+
* so pre-reviewer callers keep working. The factory injects LlmReviewer. */
|
|
64
|
+
reviewer?: IReviewer;
|
|
65
|
+
/** Finalizer role. Optional; when absent the plan-first planner's own finalize is
|
|
66
|
+
* used and a planner without finalize support uses the planner's `done.result` as the answer (legacy). */
|
|
67
|
+
finalizer?: IFinalizer;
|
|
68
|
+
/** Injectable runId minter (tests pass a deterministic counter). */
|
|
69
|
+
runIdMinter?: RunIdMinter;
|
|
70
|
+
/** Clock seam (ISO now). Defaults to () => new Date().toISOString(). */
|
|
71
|
+
now?: () => string;
|
|
72
|
+
/** Terminal-store TTL in ms (default 24h). */
|
|
73
|
+
terminalTtlMs?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Optional controller-own skills recall hook. When present it is threaded into
|
|
76
|
+
* the planner, which queries it before each create-plan/replan and injects a
|
|
77
|
+
* bounded "Relevant skills" block into the prompt. Absent → the planner prompt
|
|
78
|
+
* is byte-identical to the agnostic path.
|
|
79
|
+
*/
|
|
80
|
+
skillsRecall?: (goal: string, options?: CallOptions) => Promise<string>;
|
|
81
|
+
/** Capability kind chosen by the PRESET (composition code), not user config.
|
|
82
|
+
* Selects the planner implementation. Defaults to 'smart-executor' when absent
|
|
83
|
+
* (a consumer building the handler directly without a preset). */
|
|
84
|
+
plannerKind?: PlannerKind;
|
|
85
|
+
/** Test/composition seam: a pre-built planner used verbatim instead of
|
|
86
|
+
* makeControllerPlanner(...). Lets a test/consumer supply an IControllerPlanner
|
|
87
|
+
* that emits behaviours the default smart/weak planners do not (e.g. rewind). */
|
|
88
|
+
controllerPlanner?: IControllerPlanner;
|
|
54
89
|
}
|
|
55
90
|
/**
|
|
56
91
|
* Controller coordinator boundary. Runs a deterministic loop delegating to
|
|
@@ -77,11 +112,22 @@ export declare class ControllerCoordinatorHandler implements IStageHandler {
|
|
|
77
112
|
constructor(deps: ControllerHandlerDeps);
|
|
78
113
|
execute(ctx: PipelineContext, _config: Record<string, unknown>, _span: unknown): Promise<boolean>;
|
|
79
114
|
/** Returns 'advanced' (step succeeded — continue loop), 'failed' (retries/
|
|
80
|
-
* tool-call budget exhausted; the failure note
|
|
81
|
-
* planner can replan),
|
|
82
|
-
*
|
|
115
|
+
* tool-call budget OR reviewer-unverifiable budget exhausted; the failure note
|
|
116
|
+
* is in plannerPrivate so the planner can replan), 'partial' (reviewer approved
|
|
117
|
+
* part, remainder replans), or 'suspended' (external round-trip surfaced — caller
|
|
118
|
+
* must return true). ('aborted' remains in the return union for the caller's
|
|
119
|
+
* guard but is no longer produced here — a judge-failure now degrades to 'failed'
|
|
120
|
+
* rather than aborting the run.) */
|
|
83
121
|
private runStep;
|
|
84
122
|
private escalate;
|
|
123
|
+
/** Store-first terminal ERROR: write the terminal outcome to the TTL store
|
|
124
|
+
* FIRST (keyed by runId), THEN flip the bundle terminal and surface the error.
|
|
125
|
+
* Store-first makes the abort idempotent across a crash between the two writes. */
|
|
126
|
+
private abortTerminal;
|
|
127
|
+
private finalize;
|
|
128
|
+
/** Store-first terminal SUCCESS: write the terminal store FIRST, then flip the
|
|
129
|
+
* bundle to terminal and surface the answer (mirror of abortTerminal). */
|
|
130
|
+
private commitTerminalSuccess;
|
|
85
131
|
private surfaceClarify;
|
|
86
132
|
private surfaceFinal;
|
|
87
133
|
private surfaceToolCall;
|
|
@@ -96,4 +142,26 @@ export declare function parseNextStep(content: string): NextStep | null;
|
|
|
96
142
|
* fences and prose around it. String-aware (braces inside strings don't count).
|
|
97
143
|
* Returns null if no balanced object is present. */
|
|
98
144
|
export declare function extractJsonObject(raw: string): string | null;
|
|
145
|
+
/** The ONE run-scoped results-RAG recall primitive — used by BOTH the whole-step
|
|
146
|
+
* recall AND the per-`requires` evidence. EMBEDDING-based similarity via the
|
|
147
|
+
* backend's semantic query (NO homemade lexical scoring): the backend embeds the
|
|
148
|
+
* query + ranks by vector similarity, with the `runId` filter applied PRE-cap.
|
|
149
|
+
* Over-fetch `kPrime` (caller-supplied so the duplication bound is justified PER
|
|
150
|
+
* KIND), then dedup and cap to `k`. Dedup: step-results (have `seq`) →
|
|
151
|
+
* precedence-winner per seq; mcp-results → by `identityKey`. Embedding rank order
|
|
152
|
+
* is preserved through the dedup.
|
|
153
|
+
* `options` is forwarded into the embedder so recall-time embeds are metered. */
|
|
154
|
+
export declare function runScopedRecall(rag: IKnowledgeRagHandle, text: string, k: number, runId: string | undefined, kPrime: number, artifactType: readonly string[], options?: CallOptions): Promise<readonly KnowledgeEntry[]>;
|
|
155
|
+
/** Return the ≤`maxChars` fragment of `content` most similar to `ref` by EMBEDDING
|
|
156
|
+
* (NOT ASCII lexical overlap). DIRECT single-pass ranking: every candidate is
|
|
157
|
+
* scored on its own. The SCORED window IS the RETURNED body: candidates are
|
|
158
|
+
* `body = maxChars - 2` chars (head+tail '…' reserved up front), so the
|
|
159
|
+
* highest-scoring fragment is never truncated by the markers. Stride is 50%
|
|
160
|
+
* overlap, widened to span the whole content within MAX_EXTRACT_WINDOWS windows
|
|
161
|
+
* (point coverage for content ≤ MAX_EXTRACT_WINDOWS×maxChars; larger thins to
|
|
162
|
+
* non-overlapping, best-effort). Embeds are SEQUENTIAL and BOUNDED to ≤
|
|
163
|
+
* MAX_EXTRACT_WINDOWS + 1 — touches NO public embedder API (batch is a deferred
|
|
164
|
+
* optimization). Result STRICTLY ≤ maxChars; tiny maxChars (< 3) → bare slice.
|
|
165
|
+
* The `requires` ref is English (planner invariant) → a normal embedder suffices. */
|
|
166
|
+
export declare function relevantExtract(content: string, ref: string, maxChars: number, embedder: IEmbedder, options?: CallOptions): Promise<string>;
|
|
99
167
|
//# sourceMappingURL=controller-coordinator-handler.d.ts.map
|