@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.
Files changed (112) hide show
  1. package/dist/factories/controller-factory.d.ts +20 -6
  2. package/dist/factories/controller-factory.d.ts.map +1 -1
  3. package/dist/factories/controller-factory.js +52 -11
  4. package/dist/factories/controller-factory.js.map +1 -1
  5. package/dist/generated/version.d.ts +1 -1
  6. package/dist/generated/version.js +1 -1
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +1 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/pipelines/controller.d.ts +4 -2
  12. package/dist/pipelines/controller.d.ts.map +1 -1
  13. package/dist/pipelines/controller.js +55 -5
  14. package/dist/pipelines/controller.js.map +1 -1
  15. package/dist/pipelines/dag.d.ts +2 -2
  16. package/dist/pipelines/dag.d.ts.map +1 -1
  17. package/dist/pipelines/dag.js +4 -3
  18. package/dist/pipelines/dag.js.map +1 -1
  19. package/dist/pipelines/flat.d.ts.map +1 -1
  20. package/dist/pipelines/flat.js +2 -1
  21. package/dist/pipelines/flat.js.map +1 -1
  22. package/dist/pipelines/linear.d.ts.map +1 -1
  23. package/dist/pipelines/linear.js +2 -1
  24. package/dist/pipelines/linear.js.map +1 -1
  25. package/dist/pipelines/register-skill-sources.d.ts +21 -0
  26. package/dist/pipelines/register-skill-sources.d.ts.map +1 -0
  27. package/dist/pipelines/register-skill-sources.js +57 -0
  28. package/dist/pipelines/register-skill-sources.js.map +1 -0
  29. package/dist/pipelines/server-context.d.ts +37 -1
  30. package/dist/pipelines/server-context.d.ts.map +1 -1
  31. package/dist/pipelines/server-context.js.map +1 -1
  32. package/dist/pipelines/stepper.d.ts +2 -2
  33. package/dist/pipelines/stepper.js +2 -2
  34. package/dist/smart-agent/config.d.ts +1 -1
  35. package/dist/smart-agent/config.d.ts.map +1 -1
  36. package/dist/smart-agent/config.js +7 -3
  37. package/dist/smart-agent/config.js.map +1 -1
  38. package/dist/smart-agent/controller/artifacts.d.ts +116 -0
  39. package/dist/smart-agent/controller/artifacts.d.ts.map +1 -0
  40. package/dist/smart-agent/controller/artifacts.js +192 -0
  41. package/dist/smart-agent/controller/artifacts.js.map +1 -0
  42. package/dist/smart-agent/controller/board.d.ts +73 -0
  43. package/dist/smart-agent/controller/board.d.ts.map +1 -0
  44. package/dist/smart-agent/controller/board.js +233 -0
  45. package/dist/smart-agent/controller/board.js.map +1 -0
  46. package/dist/smart-agent/controller/controller-coordinator-handler.d.ts +75 -7
  47. package/dist/smart-agent/controller/controller-coordinator-handler.d.ts.map +1 -1
  48. package/dist/smart-agent/controller/controller-coordinator-handler.js +929 -66
  49. package/dist/smart-agent/controller/controller-coordinator-handler.js.map +1 -1
  50. package/dist/smart-agent/controller/finalizer.d.ts +48 -0
  51. package/dist/smart-agent/controller/finalizer.d.ts.map +1 -0
  52. package/dist/smart-agent/controller/finalizer.js +126 -0
  53. package/dist/smart-agent/controller/finalizer.js.map +1 -0
  54. package/dist/smart-agent/controller/memorizer.d.ts +2 -2
  55. package/dist/smart-agent/controller/memorizer.d.ts.map +1 -1
  56. package/dist/smart-agent/controller/memorizer.js +2 -2
  57. package/dist/smart-agent/controller/memorizer.js.map +1 -1
  58. package/dist/smart-agent/controller/outcome.d.ts +28 -0
  59. package/dist/smart-agent/controller/outcome.d.ts.map +1 -0
  60. package/dist/smart-agent/controller/outcome.js +30 -0
  61. package/dist/smart-agent/controller/outcome.js.map +1 -0
  62. package/dist/smart-agent/controller/planner.d.ts +41 -14
  63. package/dist/smart-agent/controller/planner.d.ts.map +1 -1
  64. package/dist/smart-agent/controller/planner.js +149 -73
  65. package/dist/smart-agent/controller/planner.js.map +1 -1
  66. package/dist/smart-agent/controller/reviewer.d.ts +48 -0
  67. package/dist/smart-agent/controller/reviewer.d.ts.map +1 -0
  68. package/dist/smart-agent/controller/reviewer.js +116 -0
  69. package/dist/smart-agent/controller/reviewer.js.map +1 -0
  70. package/dist/smart-agent/controller/run-scope.d.ts +50 -0
  71. package/dist/smart-agent/controller/run-scope.d.ts.map +1 -0
  72. package/dist/smart-agent/controller/run-scope.js +99 -0
  73. package/dist/smart-agent/controller/run-scope.js.map +1 -0
  74. package/dist/smart-agent/controller/session-bundle.d.ts +5 -0
  75. package/dist/smart-agent/controller/session-bundle.d.ts.map +1 -1
  76. package/dist/smart-agent/controller/session-bundle.js +27 -0
  77. package/dist/smart-agent/controller/session-bundle.js.map +1 -1
  78. package/dist/smart-agent/controller/types.d.ts +124 -15
  79. package/dist/smart-agent/controller/types.d.ts.map +1 -1
  80. package/dist/smart-agent/controller/types.js +30 -1
  81. package/dist/smart-agent/controller/types.js.map +1 -1
  82. package/dist/smart-agent/embedder-knowledge-index.d.ts +28 -0
  83. package/dist/smart-agent/embedder-knowledge-index.d.ts.map +1 -0
  84. package/dist/smart-agent/embedder-knowledge-index.js +71 -0
  85. package/dist/smart-agent/embedder-knowledge-index.js.map +1 -0
  86. package/dist/smart-agent/jsonl-knowledge-backend.d.ts +26 -10
  87. package/dist/smart-agent/jsonl-knowledge-backend.d.ts.map +1 -1
  88. package/dist/smart-agent/jsonl-knowledge-backend.js +81 -9
  89. package/dist/smart-agent/jsonl-knowledge-backend.js.map +1 -1
  90. package/dist/smart-agent/pg-pool.d.ts +58 -0
  91. package/dist/smart-agent/pg-pool.d.ts.map +1 -0
  92. package/dist/smart-agent/pg-pool.js +149 -0
  93. package/dist/smart-agent/pg-pool.js.map +1 -0
  94. package/dist/smart-agent/skill-plugins-config.d.ts +97 -0
  95. package/dist/smart-agent/skill-plugins-config.d.ts.map +1 -0
  96. package/dist/smart-agent/skill-plugins-config.js +318 -0
  97. package/dist/smart-agent/skill-plugins-config.js.map +1 -0
  98. package/dist/smart-agent/skill-plugins-config.test.d.ts +2 -0
  99. package/dist/smart-agent/skill-plugins-config.test.d.ts.map +1 -0
  100. package/dist/smart-agent/skill-plugins-config.test.js.map +1 -0
  101. package/dist/smart-agent/skill-plugins-host-factory.d.ts +98 -0
  102. package/dist/smart-agent/skill-plugins-host-factory.d.ts.map +1 -0
  103. package/dist/smart-agent/skill-plugins-host-factory.js +284 -0
  104. package/dist/smart-agent/skill-plugins-host-factory.js.map +1 -0
  105. package/dist/smart-agent/skill-plugins-host-factory.test.d.ts +2 -0
  106. package/dist/smart-agent/skill-plugins-host-factory.test.d.ts.map +1 -0
  107. package/dist/smart-agent/skill-plugins-host-factory.test.js.map +1 -0
  108. package/dist/smart-agent/smart-server.d.ts +25 -0
  109. package/dist/smart-agent/smart-server.d.ts.map +1 -1
  110. package/dist/smart-agent/smart-server.js +141 -7
  111. package/dist/smart-agent/smart-server.js.map +1 -1
  112. package/package.json +9 -7
@@ -1,51 +1,35 @@
1
- import { extractJsonObject, parseNextStep, } from './controller-coordinator-handler.js';
1
+ import { mintCreateStepIds, mintReplanStepIds, } from './artifacts.js';
2
+ import { extractJsonObject } from './controller-coordinator-handler.js';
2
3
  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
- }
4
+ import { MAX_REQUIRE_CHARS, MAX_REQUIRES, validateRequires, } from './types.js';
5
+ // Built from the validation constants so the prompt cap can NEVER drift from what
6
+ // the parser enforces (no duplicated literals). Appended to EVERY planner/replan
7
+ // prompt as a HARD invariant so step instructions/requires are English (stable
8
+ // tool selection against the English-translated catalog) and the requires count is
9
+ // bounded.
10
+ export const ENGLISH_INSTRUCTIONS_RULE = ' Step `instructions` AND `requires` references MUST be written in English — ' +
11
+ "always, regardless of the language of the user's request. This is a hard " +
12
+ 'contract: the executor selects tools by semantic match against an ' +
13
+ 'English-translated catalog, and the reviewer matches `requires` against stored ' +
14
+ 'artifacts — so non-English instructions/requires break both. ' +
15
+ `List at MOST ${MAX_REQUIRES} \`requires\`, each a SHORT reference (a few words, ` +
16
+ `≤ ${MAX_REQUIRE_CHARS} chars) — not pasted content. (The user-facing answer is ` +
17
+ "composed separately in the user's language.)";
18
+ /** Append a non-empty recall block to a user message, preserving the agnostic
19
+ * message byte-for-byte when the block is empty. */
20
+ function withSkillsBlock(userContent, block) {
21
+ return block ? `${userContent}\n\n${block}` : userContent;
22
+ }
23
+ /** The planner's progress context. With a live board, render the AUTHORITATIVE
24
+ * structured board AND the plannerPrivate tail — the latter carries non-board
25
+ * deltas the planner still needs (clarify answers, legacy external-tool result).
26
+ * An empty board → plannerPrivate alone, byte-identical to the legacy prompt. */
27
+ function progressBlock(bundle, boardText) {
28
+ return boardText && boardText.length > 0
29
+ ? `${boardText}\n${bundle.plannerPrivate}`
30
+ : bundle.plannerPrivate;
47
31
  }
48
- const CREATE_PLAN_SYSTEM = 'You are the planner. Produce the COMPLETE, ordered plan that covers the ENTIRE ' +
32
+ export const CREATE_PLAN_SYSTEM = 'You are the planner. Produce the COMPLETE, ordered plan that covers the ENTIRE ' +
49
33
  'goal NOW, as a SINGLE JSON object: {"plan":[{"name":...,"instructions":...}, ...]}. ' +
50
34
  'This is plan-once: there will be NO chance to add steps later (a replan happens ' +
51
35
  'only if a step FAILS), so the plan MUST already contain every step the goal ' +
@@ -71,16 +55,18 @@ const CREATE_PLAN_SYSTEM = 'You are the planner. Produce the COMPLETE, ordered p
71
55
  'Do NOT add a final step ' +
72
56
  'that summarizes, formats, or answers the user — a separate finalizer composes ' +
73
57
  '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 ' +
58
+ 'data-fetch/action the goal needs. Output JSON only.' +
59
+ ENGLISH_INSTRUCTIONS_RULE;
60
+ export const REPLAN_SYSTEM = 'You are the planner. A step just FAILED. Given the goal, the progress so far ' +
76
61
  '(fetched results + the failure), produce a REVISED, MINIMAL plan for the ' +
77
62
  'REMAINING work as {"plan":[{"name":...,"instructions":...}, ...]}. Plan only ' +
78
63
  'the data-fetch/action steps still required; describe each step by INTENT — do ' +
79
64
  'NOT name or choose a specific tool, the executor selects it. Do NOT add a ' +
80
65
  'final summarize/' +
81
66
  '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) — ' +
67
+ 'already satisfied despite the failure, return {"plan":[]}. Output JSON only.' +
68
+ ENGLISH_INSTRUCTIONS_RULE;
69
+ export const EXTERNAL_RESULT_REPLAN_SYSTEM = 'You are the planner. A NEW external tool result just arrived (see Progress) — ' +
84
70
  'this is NOT a failure. Given the goal and the progress (including the new ' +
85
71
  'result), produce a REVISED, MINIMAL plan for the REMAINING work as ' +
86
72
  '{"plan":[{"name":...,"instructions":...}, ...]}. Plan only the data-fetch/' +
@@ -88,7 +74,32 @@ const EXTERNAL_RESULT_REPLAN_SYSTEM = 'You are the planner. A NEW external tool
88
74
  'choose a specific tool, the executor selects it. Do NOT add a final summarize/' +
89
75
  'answer step (a ' +
90
76
  'separate finalizer composes the answer). If the goal is already satisfied by ' +
91
- 'the result, return {"plan":[]}. Output JSON only.';
77
+ 'the result, return {"plan":[]}. Output JSON only.' +
78
+ ENGLISH_INSTRUCTIONS_RULE;
79
+ /** Smart-executor granularity clause (§C). A capable executor can self-expand a
80
+ * coarse step inside its own tool-loop, so the planner MAY plan coarse. Clarifies
81
+ * that the base's "one concrete action" means one INTENT — a coarse batch step is
82
+ * one intent, not a planner-side per-item fan-out. AGNOSTIC: no tool names. */
83
+ const SMART_GRANULARITY = ' GRANULARITY (smart executor): a step MAY be COARSE — a single intent that ' +
84
+ 'covers a set of related items (e.g. "read every item referenced by the prior ' +
85
+ 'result"); a capable executor enumerates and processes each item WITHIN ITS OWN ' +
86
+ 'tool-loop, and control returns to the reviewer after the coarse step. This does ' +
87
+ 'NOT violate "one concrete action": a coarse batch is ONE intent. PREFER fewer ' +
88
+ 'coarse steps over enumerating items yourself.';
89
+ /** Weak-executor granularity clause (§C). A weak executor cannot be trusted to
90
+ * self-expand, so every step is exactly one atomic action. (Deferred discovery
91
+ * fan-out for plan-time-unknowable batches — §D — is Phase 4; in Phase 3 the weak
92
+ * planner just plans the finest grain it can.) AGNOSTIC: no tool names. */
93
+ const WEAK_GRANULARITY = ' GRANULARITY (weak executor): each step is EXACTLY ONE ATOMIC action the ' +
94
+ 'executor performs in a SINGLE tool use. NEVER emit a coarse/batch step and ' +
95
+ 'NEVER rely on the executor to self-expand a step — the executor handles one ' +
96
+ 'action at a time; if work spans several actions, emit that many steps.';
97
+ export const SMART_CREATE_PLAN_SYSTEM = CREATE_PLAN_SYSTEM + SMART_GRANULARITY;
98
+ export const SMART_REPLAN_SYSTEM = REPLAN_SYSTEM + SMART_GRANULARITY;
99
+ export const SMART_EXTERNAL_RESULT_REPLAN_SYSTEM = EXTERNAL_RESULT_REPLAN_SYSTEM + SMART_GRANULARITY;
100
+ export const WEAK_CREATE_PLAN_SYSTEM = CREATE_PLAN_SYSTEM + WEAK_GRANULARITY;
101
+ export const WEAK_REPLAN_SYSTEM = REPLAN_SYSTEM + WEAK_GRANULARITY;
102
+ export const WEAK_EXTERNAL_RESULT_REPLAN_SYSTEM = EXTERNAL_RESULT_REPLAN_SYSTEM + WEAK_GRANULARITY;
92
103
  const FINALIZE_SYSTEM = 'All planned steps are complete. Using the progress below (the fetched results), ' +
93
104
  'write the final answer to the user request. Plain text, no JSON.';
94
105
  /** Parse {"plan":[{name,instructions},...]} from a (possibly fenced) reply.
@@ -110,10 +121,14 @@ function parsePlan(content) {
110
121
  if (typeof s.name !== 'string' || typeof s.instructions !== 'string') {
111
122
  return null; // malformed step → format failure (handler retries)
112
123
  }
124
+ const req = validateRequires(raw.requires);
125
+ if (req === false)
126
+ return null; // malformed requires → format failure → retry
113
127
  steps.push({
114
128
  name: s.name,
115
129
  instructions: s.instructions,
116
130
  ...(s.type ? { type: s.type } : {}),
131
+ ...(req ? { requires: req } : {}),
117
132
  });
118
133
  }
119
134
  return steps;
@@ -122,70 +137,111 @@ function parsePlan(content) {
122
137
  return null;
123
138
  }
124
139
  }
125
- export class AdaptivePlanner {
140
+ /** Queue a plan decision for the controller to persist (§A boundary: the planner
141
+ * CONSTRUCTS the decision; the controller does the durable write). */
142
+ function recordDecision(bundle, decision) {
143
+ if (!bundle.pendingPlanDecisions)
144
+ bundle.pendingPlanDecisions = [];
145
+ bundle.pendingPlanDecisions.push(decision);
146
+ }
147
+ export class SmartExecutorPlanner {
126
148
  planner;
127
149
  hint;
150
+ skillsRecall;
128
151
  // No budget field: replans are bounded by the loop's maxSteps (a failed step
129
152
  // bumps stepsUsed in runStep). Replan-specific budgeting is the deferred
130
153
  // "limits as a selectable strategy" work.
131
154
  constructor(planner,
132
155
  /** Optional consumer domain hint appended to every agnostic planner/
133
156
  * create-plan/replan/finalize prompt this planner emits. */
134
- hint) {
157
+ hint,
158
+ /** Optional controller-own skills recall hook (B4). Queried before each
159
+ * create-plan/replan; its block is injected into the user message. */
160
+ skillsRecall) {
135
161
  this.planner = planner;
136
162
  this.hint = hint;
163
+ this.skillsRecall = skillsRecall;
164
+ }
165
+ /** Prompt seam — overridden by WeakExecutorPlanner for atomic granularity (§C). */
166
+ get createPlanSystem() {
167
+ return SMART_CREATE_PLAN_SYSTEM;
168
+ }
169
+ get replanSystem() {
170
+ return SMART_REPLAN_SYSTEM;
171
+ }
172
+ get externalResultReplanSystem() {
173
+ return SMART_EXTERNAL_RESULT_REPLAN_SYSTEM;
137
174
  }
138
175
  async next(input) {
139
- const { bundle, prompt, lastOutcome, resumedExternal, retrying, logUsage } = input;
176
+ const { bundle, prompt, lastOutcome, resumedExternal, retrying, logUsage, options, boardText, } = input;
140
177
  // 1. No plan yet → create it.
141
178
  if (!bundle.plan) {
142
- const plan = await this.callPlan(CREATE_PLAN_SYSTEM, bundle, prompt, retrying, logUsage);
179
+ const plan = await this.callPlan(this.createPlanSystem, bundle, prompt, retrying, logUsage, [], options, boardText);
143
180
  // An EMPTY plan from createPlan is invalid: it would skip straight to the
144
181
  // finalizer and answer WITHOUT fetching the required data. Treat it as a
145
182
  // format failure → handler re-asks (bounded by maxRetries). (An empty plan
146
183
  // is only valid on REPLAN, where it means "remaining work is done".)
147
184
  if (plan === null || plan.length === 0)
148
185
  return null;
149
- bundle.plan = plan;
186
+ const minted = mintCreateStepIds(plan, bundle.runId ?? '');
187
+ bundle.plan = minted;
150
188
  bundle.planCursor = 0;
151
- return this.stepAtCursor(bundle, prompt, logUsage);
189
+ recordDecision(bundle, {
190
+ kind: 'create',
191
+ runId: bundle.runId ?? '',
192
+ steps: minted,
193
+ });
194
+ return this.stepAtCursor(bundle, prompt, logUsage, boardText);
152
195
  }
153
196
  // 2. Previous step failed, OR an external-tool result just arrived → replan
154
197
  // the remainder from the cursor. The planner reads plannerPrivate (which
155
198
  // now holds the failure/external result), so the revised plan incorporates
156
199
  // it — no reliance on the executor seeing it. Use the matching prompt: an
157
200
  // external result is NOT a failure, so it gets its own framing.
158
- if (lastOutcome === 'failed' || resumedExternal) {
201
+ if (lastOutcome === 'failed' ||
202
+ lastOutcome === 'partial' ||
203
+ resumedExternal) {
159
204
  const system = resumedExternal
160
- ? EXTERNAL_RESULT_REPLAN_SYSTEM
161
- : REPLAN_SYSTEM;
205
+ ? this.externalResultReplanSystem
206
+ : this.replanSystem;
162
207
  const cursor = bundle.planCursor ?? 0;
163
208
  // Steps before the cursor already ran successfully — pass them so the replan
164
209
  // plans only the remaining work and never repeats a completed step.
165
210
  const completed = bundle.plan.slice(0, cursor);
166
- const rest = await this.callPlan(system, bundle, prompt, retrying, logUsage, completed);
211
+ const rest = await this.callPlan(system, bundle, prompt, retrying, logUsage, completed, options, boardText);
167
212
  if (rest === null)
168
213
  return null;
169
- bundle.plan = [...bundle.plan.slice(0, cursor), ...rest];
214
+ const anchor = bundle.plan[cursor]?.stepId ?? '';
215
+ const mintedRest = mintReplanStepIds(rest, bundle.runId ?? '', anchor);
216
+ bundle.plan = [...bundle.plan.slice(0, cursor), ...mintedRest];
217
+ recordDecision(bundle, {
218
+ kind: 'replan',
219
+ runId: bundle.runId ?? '',
220
+ anchor,
221
+ steps: mintedRest,
222
+ });
170
223
  // The failure has now been consumed into the revised plan. Clear the durable
171
224
  // failure marker BEFORE the (possible) finalize below, so that: a crash after
172
225
  // this replan does NOT replan again on resume, and a finalizer error after an
173
226
  // empty replan retries only the finalizer (not another replan).
174
227
  bundle.lastOutcome = undefined;
175
- return this.stepAtCursor(bundle, prompt, logUsage);
228
+ return this.stepAtCursor(bundle, prompt, logUsage, boardText);
176
229
  }
177
230
  // 3. Otherwise emit the step at the cursor (or finalize). The cursor is
178
231
  // advanced by commit() AFTER a step succeeds — NOT here — so the advance
179
232
  // is persisted together with the step result (see Task 4), and a resume
180
233
  // with lastOutcome=undefined continues from the next uncompleted step
181
234
  // instead of repeating the last one.
182
- return this.stepAtCursor(bundle, prompt, logUsage);
235
+ return this.stepAtCursor(bundle, prompt, logUsage, boardText);
183
236
  }
184
237
  /** Commit the just-finished step's outcome so the advance is persisted with it.
185
238
  * On success the cursor moves to the next step; a failure leaves the cursor so
186
239
  * the next next() can replan from it. (No LLM call — pure bookkeeping.) */
187
240
  commit(bundle, outcome) {
188
- if (outcome === 'advanced') {
241
+ // 'advanced' and 'partial' both advance the cursor: the accepted part of a
242
+ // partial is committed and must not be re-run (the remainder is replanned at
243
+ // the next cursor). 'failed' leaves the cursor for next()'s replan.
244
+ if (outcome === 'advanced' || outcome === 'partial') {
189
245
  bundle.planCursor = (bundle.planCursor ?? 0) + 1;
190
246
  }
191
247
  }
@@ -193,7 +249,7 @@ export class AdaptivePlanner {
193
249
  * Returns null when the finalizer call fails (error / unexpected tool_call) so
194
250
  * the handler retries it (bounded by maxRetries) instead of emitting a fake
195
251
  * "completed" answer. */
196
- async stepAtCursor(bundle, prompt, logUsage) {
252
+ async stepAtCursor(bundle, prompt, logUsage, boardText) {
197
253
  const plan = bundle.plan ?? [];
198
254
  const cursor = bundle.planCursor ?? 0;
199
255
  if (cursor >= plan.length) {
@@ -201,7 +257,7 @@ export class AdaptivePlanner {
201
257
  { role: 'system', content: appendHint(FINALIZE_SYSTEM, this.hint) },
202
258
  {
203
259
  role: 'user',
204
- content: `Goal: ${bundle.goal}\nRequest: ${prompt}\nProgress:${bundle.plannerPrivate}`,
260
+ content: `Goal: ${bundle.goal}\nRequest: ${prompt}\nProgress:${progressBlock(bundle, boardText)}`,
205
261
  },
206
262
  ]);
207
263
  logUsage?.('finalizer', res.usage);
@@ -213,13 +269,19 @@ export class AdaptivePlanner {
213
269
  }
214
270
  return { kind: 'next', step: plan[cursor] };
215
271
  }
216
- async callPlan(system, bundle, prompt, retrying, logUsage, completed = []) {
272
+ async callPlan(system, bundle, prompt, retrying, logUsage, completed = [], options, boardText) {
217
273
  // On replan, the planner MUST know which steps already ran (their results are
218
274
  // in Progress / the step-result collection) so it plans ONLY the remaining
219
275
  // work and never re-executes a completed step.
220
276
  const completedBlock = completed.length
221
277
  ? `\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
278
  : '';
279
+ // Recall the configured controller skill group BEFORE the LLM call and inject
280
+ // its bounded block. When the hook is absent OR returns '' the user message is
281
+ // byte-identical to the agnostic prompt (the measurement toggle).
282
+ const skillsBlock = this.skillsRecall
283
+ ? await this.skillsRecall(bundle.goal, options)
284
+ : '';
223
285
  const res = await this.planner.send([
224
286
  {
225
287
  role: 'system',
@@ -230,7 +292,7 @@ export class AdaptivePlanner {
230
292
  },
231
293
  {
232
294
  role: 'user',
233
- content: `Goal: ${bundle.goal}\nProgress:${bundle.plannerPrivate}${completedBlock}\nRequest: ${prompt}`,
295
+ content: withSkillsBlock(`Goal: ${bundle.goal}\nProgress:${progressBlock(bundle, boardText)}${completedBlock}\nRequest: ${prompt}`, skillsBlock),
234
296
  },
235
297
  ]);
236
298
  logUsage?.('planner', res.usage);
@@ -239,9 +301,23 @@ export class AdaptivePlanner {
239
301
  return parsePlan(res.content);
240
302
  }
241
303
  }
242
- export function makePlanner(kind, planner, hint) {
243
- return kind === 'adaptive'
244
- ? new AdaptivePlanner(planner, hint)
245
- : new IncrementalPlanner(planner, hint);
304
+ /** Weak-executor planner (§C): the same plan-first engine as SmartExecutorPlanner,
305
+ * but with the finest-grain create/replan prompts (one action per step). Phase 4
306
+ * adds deferred discovery expansion to this class; Phase 3 differs only by prompt. */
307
+ export class WeakExecutorPlanner extends SmartExecutorPlanner {
308
+ get createPlanSystem() {
309
+ return WEAK_CREATE_PLAN_SYSTEM;
310
+ }
311
+ get replanSystem() {
312
+ return WEAK_REPLAN_SYSTEM;
313
+ }
314
+ get externalResultReplanSystem() {
315
+ return WEAK_EXTERNAL_RESULT_REPLAN_SYSTEM;
316
+ }
317
+ }
318
+ export function makeControllerPlanner(kind, planner, hint, skillsRecall) {
319
+ return kind === 'weak-executor'
320
+ ? new WeakExecutorPlanner(planner, hint, skillsRecall)
321
+ : new SmartExecutorPlanner(planner, hint, skillsRecall);
246
322
  }
247
323
  //# sourceMappingURL=planner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/planner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { LlmUsage } from '@mcp-abap-adt/llm-agent';
2
+ import type { ReviewOutcome } from './outcome.js';
3
+ import type { ISubagentClient } from './subagent-client.js';
4
+ import type { Step } from './types.js';
5
+ /** One reference's evidence: the closest stored artifact's content (or none). */
6
+ export interface Evidence {
7
+ ref: string;
8
+ hit: boolean;
9
+ topArtifact?: string;
10
+ }
11
+ export interface ReviewOpts {
12
+ hint?: string;
13
+ logUsage?: (role: string, u?: LlmUsage) => void;
14
+ /** Defensive cap on the returned `digest` (§B). Defaults to 500 when omitted. */
15
+ maxDigestChars?: number;
16
+ }
17
+ /** The reviewer's return: EITHER an authoritative step Outcome (incl. a genuine
18
+ * `failed` verdict → step replan), OR a judge-failure — the reviewer could not
19
+ * produce ANY usable verdict (provider/transport error, unparsable JSON, or a
20
+ * missing/invalid status). The controller re-asks a judge-failure within
21
+ * `maxReviewRetries` and, on exhaustion, DEGRADES it to a failed step (→ replan),
22
+ * bounded by `maxStepAttempts`/`maxSteps` — it does NOT abort the run. (A
23
+ * well-formed but contradictory verdict — ok/exists/partial with empty `approved` —
24
+ * is coerced to a `failed` Outcome in `parseReview`, NOT a judge-failure.) */
25
+ export type ReviewResult = {
26
+ kind: 'outcome';
27
+ outcome: ReviewOutcome;
28
+ } | {
29
+ kind: 'judge-failure';
30
+ reason: string;
31
+ };
32
+ /** Separate judging role. The controller depends ONLY on this; `status` always
33
+ * comes through a well-formed Outcome. Default impl is LLM-backed; swappable. */
34
+ export interface IReviewer {
35
+ review(step: Step, evidence: readonly Evidence[], executorResult: string, opts: ReviewOpts): Promise<ReviewResult>;
36
+ }
37
+ export declare class LlmReviewer implements IReviewer {
38
+ private readonly client;
39
+ constructor(client: ISubagentClient);
40
+ review(step: Step, evidence: readonly Evidence[], executorResult: string, opts: ReviewOpts): Promise<ReviewResult>;
41
+ }
42
+ /** Parse a reviewer reply into a ReviewResult. A well-formed verdict (any of
43
+ * ok/exists/partial/failed) is an `outcome`; ok/exists/partial with EMPTY approved
44
+ * is coerced to a `failed` outcome (contradictory → replan, not abort). Only a
45
+ * truly unusable reply — unparsable JSON or missing/invalid status — is a
46
+ * `judge-failure` (re-ask within budget, then degrade to a failed step). */
47
+ export declare function parseReview(content: string, maxDigestChars?: number): ReviewResult;
48
+ //# sourceMappingURL=reviewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewer.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/controller/reviewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,iFAAiF;AACjF,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,OAAO,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC;IAChD,iFAAiF;IACjF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;+EAO+E;AAC/E,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,aAAa,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9C;kFACkF;AAClF,MAAM,WAAW,SAAS;IACxB,MAAM,CACJ,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,SAAS,QAAQ,EAAE,EAC7B,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,YAAY,CAAC,CAAC;CAC1B;AAwBD,qBAAa,WAAY,YAAW,SAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,eAAe;IAE9C,MAAM,CACV,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,SAAS,QAAQ,EAAE,EAC7B,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,YAAY,CAAC;CA8BzB;AAED;;;;6EAI6E;AAC7E,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,cAAc,SAAM,GACnB,YAAY,CAyDd"}
@@ -0,0 +1,116 @@
1
+ import { extractJsonObject } from './controller-coordinator-handler.js';
2
+ import { appendHint } from './prompts.js';
3
+ const REVIEWER_SYSTEM = 'You are the reviewer. You did NOT do the work — you JUDGE it. Given the ' +
4
+ "step intent, the per-reference evidence, and the executor's result, decide " +
5
+ 'the authoritative outcome and return a SINGLE JSON object: ' +
6
+ '{"status":"ok"|"exists"|"failed"|"partial","approved":<content to keep>,' +
7
+ '"remainder":<what is still missing>,"note":<short reason>,' +
8
+ '"digest":<a SHORT plain-text extract of what this step established that the ' +
9
+ 'PLANNER needs to decide the next step — e.g. the key names/ids/outcome, NOT ' +
10
+ 'the full content>}. ' +
11
+ 'Use "ok" when the step is fully satisfied, "exists" when the target already ' +
12
+ 'existed (idempotent no-op success), "partial" when only part is done (put the ' +
13
+ 'accepted content in "approved" and what remains in "remainder"), "failed" when ' +
14
+ 'the result does not satisfy the step. "approved" MUST be non-empty for ok/' +
15
+ 'exists/partial. Judge ONLY from the evidence + result; do NOT invent facts. ' +
16
+ 'The evidence lists, per required reference, the CLOSEST stored artifact (or ' +
17
+ 'MISSING). Decide for YOURSELF whether that artifact actually satisfies the ' +
18
+ 'reference — a closest-match artifact may be irrelevant; treat an unsatisfied or ' +
19
+ 'missing required reference as "failed" (note: "missing input: <ref>"). ' +
20
+ 'The "digest" is REQUIRED and MUST be a non-empty plain-text string (keep it ' +
21
+ 'brief — the full result is stored separately). ' +
22
+ 'Output JSON only.';
23
+ export class LlmReviewer {
24
+ client;
25
+ constructor(client) {
26
+ this.client = client;
27
+ }
28
+ async review(step, evidence, executorResult, opts) {
29
+ const evidenceBlock = evidence
30
+ .map((e) => e.topArtifact
31
+ ? // topArtifact is already a relevance-oriented, bounded extract.
32
+ `- ${e.ref}: closest artifact →\n${e.topArtifact}`
33
+ : `- ${e.ref}: MISSING (no artifact found)`)
34
+ .join('\n');
35
+ const res = await this.client.send([
36
+ { role: 'system', content: appendHint(REVIEWER_SYSTEM, opts.hint) },
37
+ {
38
+ role: 'user',
39
+ content: `Step: ${step.name}\nIntent: ${step.instructions}\n` +
40
+ `Evidence:\n${evidenceBlock || '(none)'}\n` +
41
+ `Executor result:\n${executorResult}`,
42
+ },
43
+ ]);
44
+ opts.logUsage?.('reviewer', res.usage);
45
+ if (res.kind !== 'content') {
46
+ // Provider/transport error → JUDGE failure (the verdict is unknown), NOT a
47
+ // step failure.
48
+ return {
49
+ kind: 'judge-failure',
50
+ reason: `reviewer error: ${res.kind === 'error' ? res.error : res.kind}`,
51
+ };
52
+ }
53
+ return parseReview(res.content, opts.maxDigestChars ?? 500);
54
+ }
55
+ }
56
+ /** Parse a reviewer reply into a ReviewResult. A well-formed verdict (any of
57
+ * ok/exists/partial/failed) is an `outcome`; ok/exists/partial with EMPTY approved
58
+ * is coerced to a `failed` outcome (contradictory → replan, not abort). Only a
59
+ * truly unusable reply — unparsable JSON or missing/invalid status — is a
60
+ * `judge-failure` (re-ask within budget, then degrade to a failed step). */
61
+ export function parseReview(content, maxDigestChars = 500) {
62
+ const json = extractJsonObject(content);
63
+ if (json === null)
64
+ return { kind: 'judge-failure', reason: 'unparsable reviewer reply' };
65
+ try {
66
+ const o = JSON.parse(json);
67
+ const status = o.status;
68
+ const approved = typeof o.approved === 'string' ? o.approved : '';
69
+ const remainder = typeof o.remainder === 'string' ? o.remainder : '';
70
+ const note = typeof o.note === 'string' ? o.note : '';
71
+ const rawDigest = typeof o.digest === 'string' ? o.digest : '';
72
+ if (status !== 'ok' &&
73
+ status !== 'exists' &&
74
+ status !== 'failed' &&
75
+ status !== 'partial') {
76
+ return { kind: 'judge-failure', reason: 'missing/invalid status' };
77
+ }
78
+ // Digest is REQUIRED on every settle (it is the planner's board content). A
79
+ // missing/empty digest is a judge-failure (re-ask), distinct from a real
80
+ // verdict. Bound it defensively (the full result is in RAG regardless).
81
+ if (rawDigest.trim().length === 0) {
82
+ return { kind: 'judge-failure', reason: 'missing digest' };
83
+ }
84
+ const digest = rawDigest.slice(0, maxDigestChars);
85
+ if ((status === 'ok' || status === 'exists' || status === 'partial') &&
86
+ approved.length === 0) {
87
+ const coercedNote = note
88
+ ? `${note} [coerced: reviewer returned ${status} with empty approved]`
89
+ : `reviewer returned ${status} with empty approved`;
90
+ return {
91
+ kind: 'outcome',
92
+ outcome: {
93
+ status: 'failed',
94
+ approved: '',
95
+ remainder: remainder || approved,
96
+ note: coercedNote,
97
+ digest: (note || coercedNote).slice(0, maxDigestChars),
98
+ },
99
+ };
100
+ }
101
+ if (status === 'partial' && remainder.trim().length === 0) {
102
+ return {
103
+ kind: 'outcome',
104
+ outcome: { status: 'ok', approved, remainder: '', note, digest },
105
+ };
106
+ }
107
+ return {
108
+ kind: 'outcome',
109
+ outcome: { status, approved, remainder, note, digest },
110
+ };
111
+ }
112
+ catch {
113
+ return { kind: 'judge-failure', reason: 'unparsable reviewer reply' };
114
+ }
115
+ }
116
+ //# sourceMappingURL=reviewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewer.js","sourceRoot":"","sources":["../../../src/smart-agent/controller/reviewer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { KnowledgeBackend } from '@mcp-abap-adt/llm-agent-libs';
2
+ import type { SessionBundle } from './types.js';
3
+ /** Injectable runId minter (matches the existing id-minter pattern); tests pass a
4
+ * deterministic counter. Default is time+random based. */
5
+ export type RunIdMinter = () => string;
6
+ /** Canonical identity fingerprint of a request: a hash of the NORMALIZED text
7
+ * (trimmed, internal whitespace collapsed). Used only for identity comparison —
8
+ * the verbatim request is kept separately for the finalizer. */
9
+ export declare function fingerprintRequest(request: string): string;
10
+ export type TerminalOutcome = {
11
+ kind: 'success';
12
+ answer: string;
13
+ } | {
14
+ kind: 'error';
15
+ error: string;
16
+ };
17
+ /** Persist a terminal outcome keyed by runId with a TTL. Written into the same
18
+ * KnowledgeBackend as the bundle but under a distinct artifactType so it
19
+ * survives the next run's bundle reset (the TTL promise). `nowIso` is passed so
20
+ * the caller controls time. */
21
+ export declare function writeTerminal(be: KnowledgeBackend, sessionId: string, runId: string, terminalOutcome: TerminalOutcome, ttlMs: number, nowIso: string): Promise<void>;
22
+ /** Read the latest non-expired terminal outcome for runId, or undefined. */
23
+ export declare function readTerminal(be: KnowledgeBackend, sessionId: string, runId: string, nowIso: string): Promise<TerminalOutcome | undefined>;
24
+ /** The runIds whose terminal entries are expired as of nowIso (backends without
25
+ * delete simply ignore stale rows on read). */
26
+ export declare function gcTerminal(be: KnowledgeBackend, sessionId: string, nowIso: string): Promise<string[]>;
27
+ export type Classification = {
28
+ kind: 'fresh';
29
+ } | {
30
+ kind: 'resume';
31
+ } | {
32
+ kind: 'replay';
33
+ runId: string;
34
+ } | {
35
+ kind: 'not-found';
36
+ };
37
+ export interface ClassifyInput {
38
+ bundle: SessionBundle;
39
+ incomingRequest: string;
40
+ /** Explicit idempotency key / runId supplied by the caller (if any). */
41
+ explicitKey?: string;
42
+ /** True when the consumer set the newRun flag for THIS request. */
43
+ newRun?: boolean;
44
+ /** Whether `explicitKey` (or, for fingerprint matches, the current bundle's
45
+ * runId) has a non-expired terminal-store entry. */
46
+ terminalExists: boolean;
47
+ }
48
+ /** Strict ordered request classification. First matching branch wins. */
49
+ export declare function classifyRequest(input: ClassifyInput): Classification;
50
+ //# sourceMappingURL=run-scope.d.ts.map