@mcp-abap-adt/llm-agent-server-libs 18.1.2 → 19.1.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.
Files changed (101) hide show
  1. package/dist/generated/version.d.ts +1 -1
  2. package/dist/generated/version.js +1 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/legacy/dag.d.ts +4 -0
  8. package/dist/legacy/dag.d.ts.map +1 -0
  9. package/dist/legacy/dag.js +4 -0
  10. package/dist/legacy/dag.js.map +1 -0
  11. package/dist/legacy/flat.d.ts +2 -0
  12. package/dist/legacy/flat.d.ts.map +1 -0
  13. package/dist/legacy/flat.js +3 -0
  14. package/dist/legacy/flat.js.map +1 -0
  15. package/dist/legacy/linear.d.ts +3 -0
  16. package/dist/legacy/linear.d.ts.map +1 -0
  17. package/dist/legacy/linear.js +3 -0
  18. package/dist/legacy/linear.js.map +1 -0
  19. package/dist/legacy/stepper.d.ts +5 -0
  20. package/dist/legacy/stepper.d.ts.map +1 -0
  21. package/dist/legacy/stepper.js +5 -0
  22. package/dist/legacy/stepper.js.map +1 -0
  23. package/dist/pipelines/controller.d.ts +19 -0
  24. package/dist/pipelines/controller.d.ts.map +1 -0
  25. package/dist/pipelines/controller.js +100 -0
  26. package/dist/pipelines/controller.js.map +1 -0
  27. package/dist/pipelines/dag.d.ts +23 -0
  28. package/dist/pipelines/dag.d.ts.map +1 -0
  29. package/dist/pipelines/dag.js +46 -0
  30. package/dist/pipelines/dag.js.map +1 -0
  31. package/dist/pipelines/flat.d.ts +14 -0
  32. package/dist/pipelines/flat.d.ts.map +1 -0
  33. package/dist/pipelines/flat.js +18 -0
  34. package/dist/pipelines/flat.js.map +1 -0
  35. package/dist/pipelines/linear.d.ts +17 -0
  36. package/dist/pipelines/linear.d.ts.map +1 -0
  37. package/dist/pipelines/linear.js +26 -0
  38. package/dist/pipelines/linear.js.map +1 -0
  39. package/dist/pipelines/parsers.d.ts +5 -0
  40. package/dist/pipelines/parsers.d.ts.map +1 -0
  41. package/dist/pipelines/parsers.js +20 -0
  42. package/dist/pipelines/parsers.js.map +1 -0
  43. package/dist/pipelines/server-context.d.ts +53 -0
  44. package/dist/pipelines/server-context.d.ts.map +1 -0
  45. package/dist/pipelines/server-context.js +9 -0
  46. package/dist/pipelines/server-context.js.map +1 -0
  47. package/dist/pipelines/stepper.d.ts +23 -0
  48. package/dist/pipelines/stepper.d.ts.map +1 -0
  49. package/dist/pipelines/stepper.js +60 -0
  50. package/dist/pipelines/stepper.js.map +1 -0
  51. package/dist/smart-agent/config.d.ts +13 -4
  52. package/dist/smart-agent/config.d.ts.map +1 -1
  53. package/dist/smart-agent/config.js +137 -228
  54. package/dist/smart-agent/config.js.map +1 -1
  55. package/dist/smart-agent/controller/controller-coordinator-handler.d.ts +99 -0
  56. package/dist/smart-agent/controller/controller-coordinator-handler.d.ts.map +1 -0
  57. package/dist/smart-agent/controller/controller-coordinator-handler.js +627 -0
  58. package/dist/smart-agent/controller/controller-coordinator-handler.js.map +1 -0
  59. package/dist/smart-agent/controller/memorizer.d.ts +6 -0
  60. package/dist/smart-agent/controller/memorizer.d.ts.map +1 -0
  61. package/dist/smart-agent/controller/memorizer.js +5 -0
  62. package/dist/smart-agent/controller/memorizer.js.map +1 -0
  63. package/dist/smart-agent/controller/need-resolver.d.ts +3 -0
  64. package/dist/smart-agent/controller/need-resolver.d.ts.map +1 -0
  65. package/dist/smart-agent/controller/need-resolver.js +4 -0
  66. package/dist/smart-agent/controller/need-resolver.js.map +1 -0
  67. package/dist/smart-agent/controller/planner.d.ts +34 -0
  68. package/dist/smart-agent/controller/planner.d.ts.map +1 -0
  69. package/dist/smart-agent/controller/planner.js +247 -0
  70. package/dist/smart-agent/controller/planner.js.map +1 -0
  71. package/dist/smart-agent/controller/prompts.d.ts +17 -0
  72. package/dist/smart-agent/controller/prompts.d.ts.map +1 -0
  73. package/dist/smart-agent/controller/prompts.js +20 -0
  74. package/dist/smart-agent/controller/prompts.js.map +1 -0
  75. package/dist/smart-agent/controller/session-bundle.d.ts +15 -0
  76. package/dist/smart-agent/controller/session-bundle.d.ts.map +1 -0
  77. package/dist/smart-agent/controller/session-bundle.js +53 -0
  78. package/dist/smart-agent/controller/session-bundle.js.map +1 -0
  79. package/dist/smart-agent/controller/subagent-client.d.ts +7 -0
  80. package/dist/smart-agent/controller/subagent-client.d.ts.map +1 -0
  81. package/dist/smart-agent/controller/subagent-client.js +18 -0
  82. package/dist/smart-agent/controller/subagent-client.js.map +1 -0
  83. package/dist/smart-agent/controller/target-state.d.ts +28 -0
  84. package/dist/smart-agent/controller/target-state.d.ts.map +1 -0
  85. package/dist/smart-agent/controller/target-state.js +59 -0
  86. package/dist/smart-agent/controller/target-state.js.map +1 -0
  87. package/dist/smart-agent/controller/types.d.ts +121 -0
  88. package/dist/smart-agent/controller/types.d.ts.map +1 -0
  89. package/dist/smart-agent/controller/types.js +2 -0
  90. package/dist/smart-agent/controller/types.js.map +1 -0
  91. package/dist/smart-agent/resolve-agent-embedder.d.ts.map +1 -1
  92. package/dist/smart-agent/resolve-agent-embedder.js +8 -2
  93. package/dist/smart-agent/resolve-agent-embedder.js.map +1 -1
  94. package/dist/smart-agent/smart-server.d.ts +188 -31
  95. package/dist/smart-agent/smart-server.d.ts.map +1 -1
  96. package/dist/smart-agent/smart-server.js +809 -637
  97. package/dist/smart-agent/smart-server.js.map +1 -1
  98. package/dist/smart-agent/stepper-coordinator-handler.d.ts.map +1 -1
  99. package/dist/smart-agent/stepper-coordinator-handler.js +25 -11
  100. package/dist/smart-agent/stepper-coordinator-handler.js.map +1 -1
  101. package/package.json +43 -7
@@ -0,0 +1,6 @@
1
+ import type { IKnowledgeRagHandle, KnowledgeEntryMetadata } from '@mcp-abap-adt/llm-agent';
2
+ export interface Artifact extends KnowledgeEntryMetadata {
3
+ content: string;
4
+ }
5
+ export declare function writeArtifact(rag: IKnowledgeRagHandle, artifact: Artifact): Promise<void>;
6
+ //# sourceMappingURL=memorizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memorizer.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/controller/memorizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,QAAS,SAAQ,sBAAsB;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,mBAAmB,EACxB,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf"}
@@ -0,0 +1,5 @@
1
+ export async function writeArtifact(rag, artifact) {
2
+ const { content, ...metadata } = artifact;
3
+ await rag.write({ content, metadata });
4
+ }
5
+ //# sourceMappingURL=memorizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memorizer.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/memorizer.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAwB,EACxB,QAAkB;IAElB,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,QAAQ,CAAC;IAC1C,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { IKnowledgeRagHandle, KnowledgeEntry, KnowledgeFilter } from '@mcp-abap-adt/llm-agent';
2
+ export declare function resolveNeed(rag: IKnowledgeRagHandle, needText: string, k?: number, filter?: KnowledgeFilter): Promise<readonly KnowledgeEntry[]>;
3
+ //# sourceMappingURL=need-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"need-resolver.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/controller/need-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,eAAe,EAChB,MAAM,yBAAyB,CAAC;AAEjC,wBAAsB,WAAW,CAC/B,GAAG,EAAE,mBAAmB,EACxB,QAAQ,EAAE,MAAM,EAChB,CAAC,SAAI,EACL,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAEpC"}
@@ -0,0 +1,4 @@
1
+ export async function resolveNeed(rag, needText, k = 5, filter) {
2
+ return rag.query(needText, { k, filter });
3
+ }
4
+ //# sourceMappingURL=need-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"need-resolver.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/need-resolver.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAwB,EACxB,QAAgB,EAChB,CAAC,GAAG,CAAC,EACL,MAAwB;IAExB,OAAO,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { ISubagentClient } from './subagent-client.js';
2
+ import type { IControllerPlanner, NextStep, PlannerKind, PlannerNextInput, SessionBundle } from './types.js';
3
+ export declare class IncrementalPlanner implements IControllerPlanner {
4
+ private readonly planner;
5
+ /** Optional consumer domain hint appended to the agnostic planner prompt. */
6
+ private readonly hint?;
7
+ constructor(planner: ISubagentClient,
8
+ /** Optional consumer domain hint appended to the agnostic planner prompt. */
9
+ hint?: string | undefined);
10
+ next(input: PlannerNextInput): Promise<NextStep | null>;
11
+ }
12
+ export declare class AdaptivePlanner implements IControllerPlanner {
13
+ private readonly planner;
14
+ /** Optional consumer domain hint appended to every agnostic planner/
15
+ * create-plan/replan/finalize prompt this planner emits. */
16
+ private readonly hint?;
17
+ constructor(planner: ISubagentClient,
18
+ /** Optional consumer domain hint appended to every agnostic planner/
19
+ * create-plan/replan/finalize prompt this planner emits. */
20
+ hint?: string | undefined);
21
+ next(input: PlannerNextInput): Promise<NextStep | null>;
22
+ /** Commit the just-finished step's outcome so the advance is persisted with it.
23
+ * On success the cursor moves to the next step; a failure leaves the cursor so
24
+ * the next next() can replan from it. (No LLM call — pure bookkeeping.) */
25
+ commit(bundle: SessionBundle, outcome: 'advanced' | 'failed'): void;
26
+ /** Return the step at the cursor, or finalize → done when the plan is exhausted.
27
+ * Returns null when the finalizer call fails (error / unexpected tool_call) so
28
+ * the handler retries it (bounded by maxRetries) instead of emitting a fake
29
+ * "completed" answer. */
30
+ private stepAtCursor;
31
+ private callPlan;
32
+ }
33
+ export declare function makePlanner(kind: PlannerKind, planner: ISubagentClient, hint?: string): IControllerPlanner;
34
+ //# sourceMappingURL=planner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/controller/planner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EACV,kBAAkB,EAClB,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,aAAa,EAEd,MAAM,YAAY,CAAC;AAwBpB,qBAAa,kBAAmB,YAAW,kBAAkB;IAEzD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAFL,OAAO,EAAE,eAAe;IACzC,6EAA6E;IAC5D,IAAI,CAAC,EAAE,MAAM,YAAA;IAG1B,IAAI,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;CAiB9D;AAqFD,qBAAa,eAAgB,YAAW,kBAAkB;IAKtD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB;iEAC6D;IAC7D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAHL,OAAO,EAAE,eAAe;IACzC;iEAC6D;IAC5C,IAAI,CAAC,EAAE,MAAM,YAAA;IAG1B,IAAI,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IA8D7D;;gFAE4E;IAC5E,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI;IAMnE;;;8BAG0B;YACZ,YAAY;YAwBZ,QAAQ;CAgCvB;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,eAAe,EACxB,IAAI,CAAC,EAAE,MAAM,GACZ,kBAAkB,CAIpB"}
@@ -0,0 +1,247 @@
1
+ import { extractJsonObject, parseNextStep, } from './controller-coordinator-handler.js';
2
+ import { appendHint } from './prompts.js';
3
+ const PLANNER_SYSTEM = 'You are the planner. Given the goal and progress, return a SINGLE JSON ' +
4
+ 'object: {"kind":"next","step":{"name":...,"instructions":...}} to take the ' +
5
+ 'next step, {"kind":"done","result":...} when the goal is met, or ' +
6
+ '{"kind":"rewind","reason":...} to discard the current path. Output JSON only.\n' +
7
+ 'An executor carries out each step against the live target system using tools. ' +
8
+ 'Describe each step by INTENT — WHAT to fetch or do — in plain language. Do ' +
9
+ 'NOT choose, name, or assume a specific tool (no tool names in the step); the ' +
10
+ 'executor selects the right tool for the step. Any fact about the system MUST ' +
11
+ 'be obtained by planning a step that fetches it with a tool — do NOT answer ' +
12
+ 'from prior knowledge, and do NOT mark the goal "done" until the required data ' +
13
+ 'has actually been fetched (fetched results appear under Progress). Until then, ' +
14
+ 'return a concrete "next" fetch step. ' +
15
+ 'Keep each step MINIMAL and do NOT broaden the scope beyond what the goal asks, ' +
16
+ 'at the granularity it asks: a LIST/SHOW/find request is satisfied by the list ' +
17
+ 'itself — do NOT plan a step that fetches the full details of every listed item ' +
18
+ 'unless the goal explicitly asks for per-item details.';
19
+ const RETRY_HINT = '\nIMPORTANT: your previous reply was NOT valid JSON. Reply with ONLY the raw ' +
20
+ 'JSON object — no prose, no explanation, no markdown code fences.';
21
+ export class IncrementalPlanner {
22
+ planner;
23
+ hint;
24
+ constructor(planner,
25
+ /** Optional consumer domain hint appended to the agnostic planner prompt. */
26
+ hint) {
27
+ this.planner = planner;
28
+ this.hint = hint;
29
+ }
30
+ async next(input) {
31
+ const { bundle, prompt, retrying, logUsage } = input;
32
+ const res = await this.planner.send([
33
+ {
34
+ role: 'system',
35
+ content: appendHint(PLANNER_SYSTEM, this.hint) + (retrying ? RETRY_HINT : ''),
36
+ },
37
+ {
38
+ role: 'user',
39
+ content: `Goal: ${bundle.goal}\nProgress:${bundle.plannerPrivate}\nRequest: ${prompt}`,
40
+ },
41
+ ]);
42
+ logUsage?.('planner', res.usage);
43
+ if (res.kind !== 'content')
44
+ return null;
45
+ return parseNextStep(res.content);
46
+ }
47
+ }
48
+ const CREATE_PLAN_SYSTEM = 'You are the planner. Produce the COMPLETE, ordered plan that covers the ENTIRE ' +
49
+ 'goal NOW, as a SINGLE JSON object: {"plan":[{"name":...,"instructions":...}, ...]}. ' +
50
+ 'This is plan-once: there will be NO chance to add steps later (a replan happens ' +
51
+ 'only if a step FAILS), so the plan MUST already contain every step the goal ' +
52
+ 'needs from start to finish. Do NOT return a first-step-only or partial plan. ' +
53
+ 'Decompose the whole goal: if the request lists multiple actions (e.g. joined by ' +
54
+ '"then"/"and"/"also"/"потім"/"і"/commas), emit ONE step per action — a ' +
55
+ 'multi-action request MUST yield multiple steps (never a single step that lumps ' +
56
+ 'them together). ' +
57
+ 'Each step is ONE concrete action an executor performs against the live target ' +
58
+ 'system using tools. Describe each step by INTENT — WHAT to fetch or do — in ' +
59
+ 'plain language. Do NOT choose, name, or assume a specific tool (no tool names ' +
60
+ 'in the step instructions); the executor selects the right tool for the step. ' +
61
+ 'Any fact about the system MUST be fetched ' +
62
+ 'with a tool — plan fetch steps; never answer from prior knowledge. ' +
63
+ 'Keep it MINIMAL: one step per distinct piece of information the goal asks for; ' +
64
+ 'do NOT add exploratory or enrichment steps (extra metadata, sample/preview ' +
65
+ 'rows, recursive expansion) the goal did not request. ' +
66
+ 'Do NOT BROADEN the scope: answer exactly what the request asks, at the ' +
67
+ 'granularity it asks. In particular, do NOT add a "for each item, fetch its ' +
68
+ 'details" step unless the request explicitly asks for per-item details — a ' +
69
+ 'request to LIST/SHOW/find items is satisfied by the list itself; fetching the ' +
70
+ 'full details of every listed item is scope creep. ' +
71
+ 'Do NOT add a final step ' +
72
+ 'that summarizes, formats, or answers the user — a separate finalizer composes ' +
73
+ 'the answer from the fetched results, so the last step must be the last ' +
74
+ 'data-fetch/action the goal needs. Output JSON only.';
75
+ const REPLAN_SYSTEM = 'You are the planner. A step just FAILED. Given the goal, the progress so far ' +
76
+ '(fetched results + the failure), produce a REVISED, MINIMAL plan for the ' +
77
+ 'REMAINING work as {"plan":[{"name":...,"instructions":...}, ...]}. Plan only ' +
78
+ 'the data-fetch/action steps still required; describe each step by INTENT — do ' +
79
+ 'NOT name or choose a specific tool, the executor selects it. Do NOT add a ' +
80
+ 'final summarize/' +
81
+ 'answer step (a separate finalizer composes the answer). If the goal is ' +
82
+ 'already satisfied despite the failure, return {"plan":[]}. Output JSON only.';
83
+ const EXTERNAL_RESULT_REPLAN_SYSTEM = 'You are the planner. A NEW external tool result just arrived (see Progress) — ' +
84
+ 'this is NOT a failure. Given the goal and the progress (including the new ' +
85
+ 'result), produce a REVISED, MINIMAL plan for the REMAINING work as ' +
86
+ '{"plan":[{"name":...,"instructions":...}, ...]}. Plan only the data-fetch/' +
87
+ 'action steps still required; describe each step by INTENT — do NOT name or ' +
88
+ 'choose a specific tool, the executor selects it. Do NOT add a final summarize/' +
89
+ 'answer step (a ' +
90
+ 'separate finalizer composes the answer). If the goal is already satisfied by ' +
91
+ 'the result, return {"plan":[]}. Output JSON only.';
92
+ const FINALIZE_SYSTEM = 'All planned steps are complete. Using the progress below (the fetched results), ' +
93
+ 'write the final answer to the user request. Plain text, no JSON.';
94
+ /** Parse {"plan":[{name,instructions},...]} from a (possibly fenced) reply.
95
+ * Returns null on format failure: no `plan` array, OR ANY entry missing a valid
96
+ * name/instructions (so a half-formed step is a retryable format error, not a
97
+ * silently-dropped step). An explicitly empty `{"plan":[]}` is VALID (= nothing
98
+ * left to do — used by replan to signal completion). */
99
+ function parsePlan(content) {
100
+ const json = extractJsonObject(content);
101
+ if (json === null)
102
+ return null;
103
+ try {
104
+ const obj = JSON.parse(json);
105
+ if (!Array.isArray(obj.plan))
106
+ return null;
107
+ const steps = [];
108
+ for (const raw of obj.plan) {
109
+ const s = raw;
110
+ if (typeof s.name !== 'string' || typeof s.instructions !== 'string') {
111
+ return null; // malformed step → format failure (handler retries)
112
+ }
113
+ steps.push({
114
+ name: s.name,
115
+ instructions: s.instructions,
116
+ ...(s.type ? { type: s.type } : {}),
117
+ });
118
+ }
119
+ return steps;
120
+ }
121
+ catch {
122
+ return null;
123
+ }
124
+ }
125
+ export class AdaptivePlanner {
126
+ planner;
127
+ hint;
128
+ // No budget field: replans are bounded by the loop's maxSteps (a failed step
129
+ // bumps stepsUsed in runStep). Replan-specific budgeting is the deferred
130
+ // "limits as a selectable strategy" work.
131
+ constructor(planner,
132
+ /** Optional consumer domain hint appended to every agnostic planner/
133
+ * create-plan/replan/finalize prompt this planner emits. */
134
+ hint) {
135
+ this.planner = planner;
136
+ this.hint = hint;
137
+ }
138
+ async next(input) {
139
+ const { bundle, prompt, lastOutcome, resumedExternal, retrying, logUsage } = input;
140
+ // 1. No plan yet → create it.
141
+ if (!bundle.plan) {
142
+ const plan = await this.callPlan(CREATE_PLAN_SYSTEM, bundle, prompt, retrying, logUsage);
143
+ // An EMPTY plan from createPlan is invalid: it would skip straight to the
144
+ // finalizer and answer WITHOUT fetching the required data. Treat it as a
145
+ // format failure → handler re-asks (bounded by maxRetries). (An empty plan
146
+ // is only valid on REPLAN, where it means "remaining work is done".)
147
+ if (plan === null || plan.length === 0)
148
+ return null;
149
+ bundle.plan = plan;
150
+ bundle.planCursor = 0;
151
+ return this.stepAtCursor(bundle, prompt, logUsage);
152
+ }
153
+ // 2. Previous step failed, OR an external-tool result just arrived → replan
154
+ // the remainder from the cursor. The planner reads plannerPrivate (which
155
+ // now holds the failure/external result), so the revised plan incorporates
156
+ // it — no reliance on the executor seeing it. Use the matching prompt: an
157
+ // external result is NOT a failure, so it gets its own framing.
158
+ if (lastOutcome === 'failed' || resumedExternal) {
159
+ const system = resumedExternal
160
+ ? EXTERNAL_RESULT_REPLAN_SYSTEM
161
+ : REPLAN_SYSTEM;
162
+ const cursor = bundle.planCursor ?? 0;
163
+ // Steps before the cursor already ran successfully — pass them so the replan
164
+ // plans only the remaining work and never repeats a completed step.
165
+ const completed = bundle.plan.slice(0, cursor);
166
+ const rest = await this.callPlan(system, bundle, prompt, retrying, logUsage, completed);
167
+ if (rest === null)
168
+ return null;
169
+ bundle.plan = [...bundle.plan.slice(0, cursor), ...rest];
170
+ // The failure has now been consumed into the revised plan. Clear the durable
171
+ // failure marker BEFORE the (possible) finalize below, so that: a crash after
172
+ // this replan does NOT replan again on resume, and a finalizer error after an
173
+ // empty replan retries only the finalizer (not another replan).
174
+ bundle.lastOutcome = undefined;
175
+ return this.stepAtCursor(bundle, prompt, logUsage);
176
+ }
177
+ // 3. Otherwise emit the step at the cursor (or finalize). The cursor is
178
+ // advanced by commit() AFTER a step succeeds — NOT here — so the advance
179
+ // is persisted together with the step result (see Task 4), and a resume
180
+ // with lastOutcome=undefined continues from the next uncompleted step
181
+ // instead of repeating the last one.
182
+ return this.stepAtCursor(bundle, prompt, logUsage);
183
+ }
184
+ /** Commit the just-finished step's outcome so the advance is persisted with it.
185
+ * On success the cursor moves to the next step; a failure leaves the cursor so
186
+ * the next next() can replan from it. (No LLM call — pure bookkeeping.) */
187
+ commit(bundle, outcome) {
188
+ if (outcome === 'advanced') {
189
+ bundle.planCursor = (bundle.planCursor ?? 0) + 1;
190
+ }
191
+ }
192
+ /** Return the step at the cursor, or finalize → done when the plan is exhausted.
193
+ * Returns null when the finalizer call fails (error / unexpected tool_call) so
194
+ * the handler retries it (bounded by maxRetries) instead of emitting a fake
195
+ * "completed" answer. */
196
+ async stepAtCursor(bundle, prompt, logUsage) {
197
+ const plan = bundle.plan ?? [];
198
+ const cursor = bundle.planCursor ?? 0;
199
+ if (cursor >= plan.length) {
200
+ const res = await this.planner.send([
201
+ { role: 'system', content: appendHint(FINALIZE_SYSTEM, this.hint) },
202
+ {
203
+ role: 'user',
204
+ content: `Goal: ${bundle.goal}\nRequest: ${prompt}\nProgress:${bundle.plannerPrivate}`,
205
+ },
206
+ ]);
207
+ logUsage?.('finalizer', res.usage);
208
+ // Finalizer must produce content; an error or tool_call is NOT a successful
209
+ // answer → null so the handler re-asks rather than faking "completed".
210
+ if (res.kind !== 'content')
211
+ return null;
212
+ return { kind: 'done', result: res.content };
213
+ }
214
+ return { kind: 'next', step: plan[cursor] };
215
+ }
216
+ async callPlan(system, bundle, prompt, retrying, logUsage, completed = []) {
217
+ // On replan, the planner MUST know which steps already ran (their results are
218
+ // in Progress / the step-result collection) so it plans ONLY the remaining
219
+ // work and never re-executes a completed step.
220
+ const completedBlock = completed.length
221
+ ? `\nALREADY-EXECUTED steps — their results are in Progress above; do NOT plan or repeat these, plan only what is still missing:\n${completed.map((s) => `- ${s.name}`).join('\n')}`
222
+ : '';
223
+ const res = await this.planner.send([
224
+ {
225
+ role: 'system',
226
+ content: appendHint(system, this.hint) +
227
+ (retrying
228
+ ? '\nIMPORTANT: your previous reply was NOT valid JSON. Reply with ONLY the raw JSON object.'
229
+ : ''),
230
+ },
231
+ {
232
+ role: 'user',
233
+ content: `Goal: ${bundle.goal}\nProgress:${bundle.plannerPrivate}${completedBlock}\nRequest: ${prompt}`,
234
+ },
235
+ ]);
236
+ logUsage?.('planner', res.usage);
237
+ if (res.kind !== 'content')
238
+ return null;
239
+ return parsePlan(res.content);
240
+ }
241
+ }
242
+ export function makePlanner(kind, planner, hint) {
243
+ return kind === 'adaptive'
244
+ ? new AdaptivePlanner(planner, hint)
245
+ : new IncrementalPlanner(planner, hint);
246
+ }
247
+ //# sourceMappingURL=planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Append an optional per-role hint to a role's agnostic system prompt.
3
+ *
4
+ * The controller engine's role prompts (evaluator / planner / executor) are
5
+ * deliberately AGNOSTIC and concise. A deployment can append extra OPERATIONAL
6
+ * guidance for a role via `subagents.<role>.hint` — how to build the plan, how
7
+ * to execute a step, what to be strict about. Its main purpose is to scaffold
8
+ * WEAKER models: a capable model (Opus / Sonnet) usually needs none, while a
9
+ * smaller executor/planner model (e.g. gpt-4o-mini) may need the extra steering.
10
+ *
11
+ * A hint is NOT a domain description and must NOT name tools: the planner plans
12
+ * by intent (no tool catalog) and the executor selects the right tool per step;
13
+ * richer per-situation procedures belong to the skills RAG — a separate, dynamic
14
+ * mechanism. An absent or blank hint leaves the agnostic prompt untouched.
15
+ */
16
+ export declare function appendHint(system: string, hint?: string): string;
17
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/controller/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAGhE"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Append an optional per-role hint to a role's agnostic system prompt.
3
+ *
4
+ * The controller engine's role prompts (evaluator / planner / executor) are
5
+ * deliberately AGNOSTIC and concise. A deployment can append extra OPERATIONAL
6
+ * guidance for a role via `subagents.<role>.hint` — how to build the plan, how
7
+ * to execute a step, what to be strict about. Its main purpose is to scaffold
8
+ * WEAKER models: a capable model (Opus / Sonnet) usually needs none, while a
9
+ * smaller executor/planner model (e.g. gpt-4o-mini) may need the extra steering.
10
+ *
11
+ * A hint is NOT a domain description and must NOT name tools: the planner plans
12
+ * by intent (no tool catalog) and the executor selects the right tool per step;
13
+ * richer per-situation procedures belong to the skills RAG — a separate, dynamic
14
+ * mechanism. An absent or blank hint leaves the agnostic prompt untouched.
15
+ */
16
+ export function appendHint(system, hint) {
17
+ const h = hint?.trim();
18
+ return h ? `${system}\n\nAdditional guidance: ${h}` : system;
19
+ }
20
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,IAAa;IACtD,MAAM,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC;IACvB,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,4BAA4B,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { KnowledgeBackend } from '@mcp-abap-adt/llm-agent-libs';
2
+ import type { SessionBundle } from './types.js';
3
+ /**
4
+ * Durably persist the session bundle into the KnowledgeBackend, keyed by
5
+ * sessionId. Uses artifactType 'controller-bundle' as the discriminator.
6
+ * Required metadata fields are filled with deterministic synthetic values
7
+ * since this is an infrastructure record, not a turn-scoped artifact.
8
+ */
9
+ export declare function persistBundle(be: KnowledgeBackend, sessionId: string, bundle: SessionBundle): Promise<void>;
10
+ /**
11
+ * Retrieve the latest persisted bundle for a session. Returns a fresh empty
12
+ * bundle if none exists or if the stored content cannot be parsed.
13
+ */
14
+ export declare function hydrateBundle(be: KnowledgeBackend, sessionId: string): Promise<SessionBundle>;
15
+ //# sourceMappingURL=session-bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-bundle.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/controller/session-bundle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAkBhD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,gBAAgB,EACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,gBAAgB,EACpB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,CAAC,CAaxB"}
@@ -0,0 +1,53 @@
1
+ const BUNDLE_ARTIFACT_TYPE = 'controller-bundle';
2
+ const EMPTY_BUNDLE = {
3
+ goal: '',
4
+ plannerPrivate: '',
5
+ budgets: { stepsUsed: 0, rewindsUsed: 0 },
6
+ };
7
+ function emptyBundle() {
8
+ return {
9
+ goal: EMPTY_BUNDLE.goal,
10
+ plannerPrivate: EMPTY_BUNDLE.plannerPrivate,
11
+ budgets: { ...EMPTY_BUNDLE.budgets },
12
+ };
13
+ }
14
+ /**
15
+ * Durably persist the session bundle into the KnowledgeBackend, keyed by
16
+ * sessionId. Uses artifactType 'controller-bundle' as the discriminator.
17
+ * Required metadata fields are filled with deterministic synthetic values
18
+ * since this is an infrastructure record, not a turn-scoped artifact.
19
+ */
20
+ export async function persistBundle(be, sessionId, bundle) {
21
+ await be.put(sessionId, {
22
+ content: JSON.stringify(bundle),
23
+ metadata: {
24
+ traceId: sessionId,
25
+ turnId: sessionId,
26
+ stepperId: 'controller',
27
+ task: 'session-bundle',
28
+ artifactType: BUNDLE_ARTIFACT_TYPE,
29
+ createdAt: new Date().toISOString(),
30
+ },
31
+ });
32
+ }
33
+ /**
34
+ * Retrieve the latest persisted bundle for a session. Returns a fresh empty
35
+ * bundle if none exists or if the stored content cannot be parsed.
36
+ */
37
+ export async function hydrateBundle(be, sessionId) {
38
+ const entries = await be.scan(sessionId);
39
+ // Scan returns oldest-first; iterate in reverse so the latest bundle wins.
40
+ for (let i = entries.length - 1; i >= 0; i--) {
41
+ const entry = entries[i];
42
+ if (entry.metadata.artifactType !== BUNDLE_ARTIFACT_TYPE)
43
+ continue;
44
+ try {
45
+ return JSON.parse(entry.content);
46
+ }
47
+ catch {
48
+ // malformed entry — keep scanning backwards for a valid one
49
+ }
50
+ }
51
+ return emptyBundle();
52
+ }
53
+ //# sourceMappingURL=session-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-bundle.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/session-bundle.ts"],"names":[],"mappings":"AAGA,MAAM,oBAAoB,GAAG,mBAAmB,CAAC;AAEjD,MAAM,YAAY,GAAkB;IAClC,IAAI,EAAE,EAAE;IACR,cAAc,EAAE,EAAE;IAClB,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE;CAC1C,CAAC;AAEF,SAAS,WAAW;IAClB,OAAO;QACL,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,cAAc,EAAE,YAAY,CAAC,cAAc;QAC3C,OAAO,EAAE,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE;KACrC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAoB,EACpB,SAAiB,EACjB,MAAqB;IAErB,MAAM,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE;QACtB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;QAC/B,QAAQ,EAAE;YACR,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,YAAY;YACvB,IAAI,EAAE,gBAAgB;YACtB,YAAY,EAAE,oBAAoB;YAClC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAoB,EACpB,SAAiB;IAEjB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACzC,2EAA2E;IAC3E,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,KAAK,oBAAoB;YAAE,SAAS;QACnE,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAkB,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,4DAA4D;QAC9D,CAAC;IACH,CAAC;IACD,OAAO,WAAW,EAAE,CAAC;AACvB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ILlm, LlmTool, Message } from '@mcp-abap-adt/llm-agent';
2
+ import type { SubagentResult } from './types.js';
3
+ export interface ISubagentClient {
4
+ send(messages: Message[], tools?: LlmTool[]): Promise<SubagentResult>;
5
+ }
6
+ export declare function makeSubagentClient(llm: ILlm): ISubagentClient;
7
+ //# sourceMappingURL=subagent-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent-client.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/controller/subagent-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACvE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,GAAG,eAAe,CAgB7D"}
@@ -0,0 +1,18 @@
1
+ export function makeSubagentClient(llm) {
2
+ return {
3
+ async send(messages, tools) {
4
+ const r = await llm.chat(messages, tools);
5
+ if (!r.ok)
6
+ return {
7
+ kind: 'error',
8
+ error: r.error?.message ?? 'subagent llm error',
9
+ };
10
+ const v = r.value;
11
+ const usage = v.usage ? { usage: v.usage } : {};
12
+ if (v.toolCalls && v.toolCalls.length > 0)
13
+ return { kind: 'tool_call', toolCalls: v.toolCalls, ...usage };
14
+ return { kind: 'content', content: v.content ?? '', ...usage };
15
+ },
16
+ };
17
+ }
18
+ //# sourceMappingURL=subagent-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent-client.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/subagent-client.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,kBAAkB,CAAC,GAAS;IAC1C,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK;YACxB,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC1C,IAAI,CAAC,CAAC,CAAC,EAAE;gBACP,OAAO;oBACL,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,IAAI,oBAAoB;iBAChD,CAAC;YACJ,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YAClB,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;gBACvC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,GAAG,KAAK,EAAE,CAAC;YACjE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC;QACjE,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { CallOptions, IEmbedder, LlmUsage } from '@mcp-abap-adt/llm-agent';
2
+ import type { ISubagentClient } from './subagent-client.js';
3
+ import type { ControllerConfig } from './types.js';
4
+ export interface TargetStateDeps {
5
+ evaluator: ISubagentClient;
6
+ /** Required only for distance strategies (semantic-distance/auto). */
7
+ embedder?: IEmbedder;
8
+ }
9
+ /**
10
+ * Outcome of establishing the target state. `established` → the goal is settled
11
+ * and the loop proceeds. `needs-confirmation` → the coordinator must ask the
12
+ * consumer to confirm/refine `proposedTarget` (the marker carries it so a plain
13
+ * "yes" on resume commits the proposed target rather than the literal answer).
14
+ */
15
+ export type TargetStateOutcome = {
16
+ kind: 'established';
17
+ goal: string;
18
+ usage?: LlmUsage;
19
+ } | {
20
+ kind: 'needs-confirmation';
21
+ proposedTarget: string;
22
+ question: string;
23
+ usage?: LlmUsage;
24
+ };
25
+ export declare function establishTargetState(deps: TargetStateDeps, prompt: string, cfg: ControllerConfig['targetState'], options?: CallOptions,
26
+ /** Optional consumer domain hint appended to the agnostic evaluator prompt. */
27
+ hint?: string): Promise<TargetStateOutcome>;
28
+ //# sourceMappingURL=target-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-state.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/controller/target-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,eAAe,CAAC;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,QAAQ,CAAA;CAAE,GACvD;IACE,IAAI,EAAE,oBAAoB,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB,CAAC;AAgBN,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,gBAAgB,CAAC,aAAa,CAAC,EACpC,OAAO,CAAC,EAAE,WAAW;AACrB,+EAA+E;AAC/E,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,kBAAkB,CAAC,CAgD7B"}
@@ -0,0 +1,59 @@
1
+ import { appendHint } from './prompts.js';
2
+ function cosineDistance(a, b) {
3
+ const n = Math.min(a.length, b.length);
4
+ let dot = 0;
5
+ let na = 0;
6
+ let nb = 0;
7
+ for (let i = 0; i < n; i++) {
8
+ dot += a[i] * b[i];
9
+ na += a[i] * a[i];
10
+ nb += b[i] * b[i];
11
+ }
12
+ if (na === 0 || nb === 0)
13
+ return 1;
14
+ return 1 - dot / (Math.sqrt(na) * Math.sqrt(nb));
15
+ }
16
+ export async function establishTargetState(deps, prompt, cfg, options,
17
+ /** Optional consumer domain hint appended to the agnostic evaluator prompt. */
18
+ hint) {
19
+ const r = await deps.evaluator.send([
20
+ {
21
+ role: 'system',
22
+ content: appendHint('Restate the user request as a SHORT objective — the target state to ' +
23
+ 'achieve — in one or two sentences. Do NOT answer the request, and do ' +
24
+ 'NOT include any data, results, code, or explanations. Output only the ' +
25
+ 'objective.', hint),
26
+ },
27
+ { role: 'user', content: prompt },
28
+ ]);
29
+ const target = r.kind === 'content' ? r.content : '';
30
+ if (cfg.strategy === 'consumer-confirm') {
31
+ return {
32
+ kind: 'needs-confirmation',
33
+ proposedTarget: target,
34
+ question: `Confirm or refine the target state:\n${target}`,
35
+ usage: r.usage,
36
+ };
37
+ }
38
+ // MVP: 'auto' currently behaves as 'semantic-distance' (evaluator-self-judging is a follow-up).
39
+ if (cfg.strategy === 'semantic-distance' || cfg.strategy === 'auto') {
40
+ if (!deps.embedder) {
41
+ throw new Error(`target-state strategy '${cfg.strategy}' requires an embedder; configure rag.embedder or use strategy: consumer-confirm`);
42
+ }
43
+ const [te, pe] = await Promise.all([
44
+ deps.embedder.embed(target, options),
45
+ deps.embedder.embed(prompt, options),
46
+ ]);
47
+ const dist = cosineDistance(te.vector, pe.vector);
48
+ if (dist > cfg.distanceThreshold) {
49
+ return {
50
+ kind: 'needs-confirmation',
51
+ proposedTarget: target,
52
+ question: `The goal may be ambiguous (distance ${dist.toFixed(2)}). Confirm or refine:\n${target}`,
53
+ usage: r.usage,
54
+ };
55
+ }
56
+ }
57
+ return { kind: 'established', goal: target, usage: r.usage };
58
+ }
59
+ //# sourceMappingURL=target-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-state.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/target-state.ts"],"names":[],"mappings":"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"}