@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,60 @@
1
+ import { CyclicFactory, DeepStepperFactory, PlannedFactory, } from '../factories/index.js';
2
+ import { parseStepperCoordinatorConfig, } from './parsers.js';
3
+ /**
4
+ * Built-in `stepper` pipeline plugin. Parses the coordinator config dialect,
5
+ * picks the matching builder-factory by `mode`, builds the coordinator stage
6
+ * handler, registers it on a fresh agent builder, and returns the runnable
7
+ * agent plus a disposal hook.
8
+ *
9
+ * @deprecated Legacy pipeline. `stepper` runs on its own legacy composition
10
+ * step-interpreter and stays selectable only for backward compatibility — it is
11
+ * not the active development path. The newer `controller` pipeline (incremental
12
+ * / adaptive planner) is the maintained interpreter; new deployments should use
13
+ * it. The controller interpreter was not designed to drive the legacy stepper
14
+ * flow, so do not migrate a `stepper` config onto it. May be removed in a future
15
+ * major.
16
+ */
17
+ export class StepperPipelinePlugin {
18
+ name = 'stepper';
19
+ parseConfig(raw) {
20
+ return parseStepperCoordinatorConfig((raw ?? {}));
21
+ }
22
+ async build(cfg, ctx) {
23
+ const spec = {
24
+ granularity: cfg.flow.granularity,
25
+ finalizer: cfg.flow.finalizer,
26
+ plannerSystemPrompt: cfg.flow.plannerSystemPrompt,
27
+ executorSystemPrompt: cfg.flow.executorSystemPrompt,
28
+ evaluatorEnabled: cfg.flow.evaluatorEnabled,
29
+ evaluatorAtDepths: cfg.flow.evaluatorAtDepths,
30
+ evaluatorSystemPrompt: cfg.flow.evaluatorSystemPrompt,
31
+ reviewerAtDepths: cfg.reviewerAtDepths,
32
+ maxParallelSteps: cfg.maxParallelSteps,
33
+ maxDepth: cfg.maxDepth,
34
+ tokenBudget: cfg.tokenBudget,
35
+ formalizeTask: cfg.formalizeTask,
36
+ plan: cfg.flow.plan,
37
+ nodes: cfg.flow.nodes,
38
+ };
39
+ const deps = {
40
+ makeRoleLlm: (role) => ctx.resolveLlm(role),
41
+ callMcp: (n, a, s) => ctx.callMcp(n, a, s).then(String),
42
+ // ctx.knowledgeRagFor is MaybePromise; StepperFactoryDeps wants Promise.
43
+ knowledgeRagFor: async (sid) => ctx.knowledgeRagFor(sid),
44
+ toolsRag: ctx.toolsRag,
45
+ mintStepperId: () => ctx.mintStepperId(),
46
+ mintTurnId: () => ctx.mintTurnId(),
47
+ subagents: ctx.subagents,
48
+ };
49
+ const factory = cfg.mode === 'cyclic-react'
50
+ ? new CyclicFactory()
51
+ : cfg.mode === 'deep-stepper'
52
+ ? new DeepStepperFactory()
53
+ : new PlannedFactory();
54
+ const { handler } = await factory.build(spec, deps);
55
+ const builder = await ctx.createAgentBuilder();
56
+ const handle = await builder.withStepperCoordinator(handler).build();
57
+ return { agent: handle.agent, close: () => handle.close() };
58
+ }
59
+ }
60
+ //# sourceMappingURL=stepper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepper.js","sourceRoot":"","sources":["../../src/pipelines/stepper.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,cAAc,GAGf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,6BAA6B,GAE9B,MAAM,cAAc,CAAC;AAGtB;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,qBAAqB;IAGvB,IAAI,GAAG,SAAS,CAAC;IAE1B,WAAW,CAAC,GAAY;QACtB,OAAO,6BAA6B,CAClC,CAAC,GAAG,IAAI,EAAE,CAA4B,CACvC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK,CACT,GAA6B,EAC7B,GAA2B;QAE3B,MAAM,IAAI,GAAyB;YACjC,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW;YACjC,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS;YAC7B,mBAAmB,EAAE,GAAG,CAAC,IAAI,CAAC,mBAAmB;YACjD,oBAAoB,EAAE,GAAG,CAAC,IAAI,CAAC,oBAAoB;YACnD,gBAAgB,EAAE,GAAG,CAAC,IAAI,CAAC,gBAAgB;YAC3C,iBAAiB,EAAE,GAAG,CAAC,IAAI,CAAC,iBAAiB;YAC7C,qBAAqB,EAAE,GAAG,CAAC,IAAI,CAAC,qBAAqB;YACrD,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;YACtC,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;YACtC,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI;YACnB,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;SACtB,CAAC;QACF,MAAM,IAAI,GAAuB;YAC/B,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;YAC3C,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;YACvD,yEAAyE;YACzE,eAAe,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;YACxD,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,aAAa,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,EAAE;YACxC,UAAU,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE;YAClC,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC;QACF,MAAM,OAAO,GACX,GAAG,CAAC,IAAI,KAAK,cAAc;YACzB,CAAC,CAAC,IAAI,aAAa,EAAE;YACrB,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc;gBAC3B,CAAC,CAAC,IAAI,kBAAkB,EAAE;gBAC1B,CAAC,CAAC,IAAI,cAAc,EAAE,CAAC;QAC7B,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,kBAAkB,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC;QACrE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;IAC9D,CAAC;CACF"}
@@ -73,9 +73,6 @@ export interface YamlCoordinator {
73
73
  stateOracle?: string;
74
74
  maxRoundTrips?: number;
75
75
  }
76
- /** Fail-loud guard: a coordinator block is either DAG (has `planner`) or linear,
77
- * never mixed. `activation` is shared and always allowed. */
78
- export declare function assertCoordinatorConfigShape(coord: Record<string, unknown>): void;
79
76
  export declare function resolveCoordinatorPlanning(name: string, plannerLlm: ILlm): OneShotPlanning | ReplanOnErrorPlanning | SkillStepsPlanning;
80
77
  /**
81
78
  * Default coordinator dispatch kind. Omitted → 'hybrid' for ALL planning kinds:
@@ -117,7 +114,7 @@ export interface ResolveConfigArgs {
117
114
  'plugin-dir'?: string;
118
115
  mode?: string | boolean;
119
116
  }
120
- export declare const YAML_TEMPLATE = "port: 4004\nhost: 0.0.0.0\n\n# Request routing mode:\n# hard \u2014 Fully managed context. Ignores client history/system prompt. Uses RAG + internal MCP tools only.\n# pass \u2014 Transparent proxy. Logs everything but modifies nothing.\n# smart \u2014 Hybrid. Preserves client history but enriches it with RAG context and MCP tools based on analysis. (default)\nmode: smart\n\nllm:\n provider: deepseek # deepseek | openai | anthropic | sap-ai-sdk | ollama\n apiKey: ${DEEPSEEK_API_KEY} # not required for ollama / sap-ai-sdk\n model: deepseek-chat\n temperature: 0.7\n classifierTemperature: 0.1\n\nrag:\n type: in-memory # in-memory | qdrant | hana-vector | pg-vector\n embedder: ollama # Embedder to use: ollama | openai | sap-ai-core | <custom>\n url: http://localhost:11434\n model: bge-m3\n # resourceGroup: default # SAP AI Core resource group (sap-ai-core embedder)\n # scenario: orchestration # SAP AI Core scenario: orchestration (default) | foundation-models\n # collectionName: llm-agent # Collection/table name (qdrant | hana-vector | pg-vector)\n dedupThreshold: 0.92\n vectorWeight: 0.7 # Semantic similarity weight (0..1)\n keywordWeight: 0.3 # Lexical matching weight (0..1)\n\nmcp:\n # type: none | http | stdio\n # To disable MCP, set type to 'none'\n type: http\n url: http://localhost:3001/mcp/stream/http\n\nagent:\n externalToolsValidationMode: permissive # permissive | strict\n maxIterations: 10\n maxToolCalls: 30\n toolUnavailableTtlMs: 600000 # Temporary tool blacklist TTL (ms)\n ragQueryK: 10\n # contextBudgetTokens: 4000 # Max tokens for RAG context in system prompt (0 = no limit)\n # semanticHistoryEnabled: false # Enable semantic history via RAG\n # historyRecencyWindow: 4 # Last N messages from client history in LLM context\n # historyTurnSummaryPrompt: \"...\" # LLM prompt for turn summarization\n showReasoning: false # Explain strategy at start of response\n historyAutoSummarizeLimit: 10 # History length to trigger compression\n queryExpansionEnabled: false # Expand RAG queries with LLM-generated synonyms\n toolResultCacheTtlMs: 300000 # Tool result cache TTL (ms); 0 to disable\n sessionTokenBudget: 0 # Multi-turn token budget; 0 to disable\n # ragTranslateEnabled: true # Translate non-ASCII RAG queries to English (default: true)\n # classificationEnabled: false # Enable for custom pipelines with multi-store routing\n # toolReselectPerIteration: false # Re-select tools via RAG on each tool-loop iteration\n # llmCallStrategy: streaming # streaming | non-streaming | fallback\n # streamMode: full # full | final \u2014 streaming behavior for tool loops\n # heartbeatIntervalMs: 5000 # SSE heartbeat interval during tool execution (ms)\n # healthTimeoutMs: 5000 # Health check probe timeout (ms); increase for slow providers (SAP AI Core: 15000)\n # retry: # LLM retry config for 429/5xx errors\n # maxAttempts: 3\n # backoffMs: 1000\n # retryOn: [429, 500, 502, 503]\n # retryOnMidStream: ['SSE stream'] # Substrings triggering mid-stream retry\n\n# --- Advanced Multi-Model Pipeline (optional) -------------------------------\n# Use this section to assign different models for different internal tasks.\n# pipeline:\n# llm:\n# main:\n# provider: deepseek # deepseek | openai | anthropic | sap-ai-sdk\n# apiKey: ${DEEPSEEK_API_KEY}\n# model: deepseek-chat\n# temperature: 0.7\n# streaming: true # false to disable streaming for this provider\n# classifier: # optional; if absent, main config is reused\n# provider: deepseek\n# apiKey: ${DEEPSEEK_API_KEY}\n# model: deepseek-chat\n# temperature: 0.1\n# helper: # optional; if absent, main config is reused\n# provider: deepseek\n# apiKey: ${DEEPSEEK_API_KEY}\n# model: deepseek-chat\n# temperature: 0.1\n#\n# rag:\n# tools:\n# type: qdrant\n# url: http://qdrant:6333\n# embedder: openai # ollama | openai | <custom registered name>\n# model: text-embedding-3-small\n# apiKey: ${OPENAI_API_KEY}\n# history:\n# type: in-memory\n#\n# mcp:\n# - type: http\n# url: http://localhost:3001/mcp/stream/http\n\n# --- Structured Pipeline (optional) -------------------------------------------\n# Replaces the hardcoded orchestration flow with a YAML-defined stage tree.\n# When absent, the default flow runs unchanged (full backwards compatibility).\n#\n# pipeline:\n# version: \"1\"\n# stages:\n# - id: classify\n# type: classify\n# - id: summarize\n# type: summarize\n# - id: rag-retrieval\n# type: parallel\n# when: \"shouldRetrieve\"\n# stages:\n# - { id: translate, type: translate }\n# - { id: expand, type: expand }\n# after:\n# - id: rag-queries\n# type: parallel\n# stages:\n# - { id: tools, type: rag-query, config: { store: tools, k: 10 } }\n# - { id: history, type: rag-query, config: { store: history, k: 5 } }\n# - { id: rerank, type: rerank }\n# - { id: tool-select, type: tool-select }\n# - id: assemble\n# type: assemble\n# - id: tool-loop\n# type: tool-loop\n\n# prompts:\n# system: \"You are a helpful assistant specialized in SAP ABAP development.\"\n# classifier: |\n# You are an intent classifier... (see source for full default prompt)\n# reasoning: |\n# IMPORTANT: Always start your response with a brief <reasoning> block...\n# ragTranslate: |\n# Translate the user request to English for search purposes...\n# historySummary: |\n# Summarize the conversation so far...\n\nlog: smart-server.log # path to log file; omit for stdout\n# logDir: sessions # Directory for detailed session debug logs\n# pluginDir: ./my-plugins # Additional plugin directory (loaded after defaults)\n\n# subagents: # Optional: nested agents callable from pipeline\n# - name: code-reviewer # Used as stage config: { agent: code-reviewer }\n# description: | # Optional. Shown to the Coordinator planner LLM\n# Reviews code and returns # so it can pick this agent for the right step.\n# structured JSON.\n# config: ./agents/code-reviewer.yaml\n\n# coordinator: # Optional: enable autonomous plan-execute loop\n# planning: one-shot # one-shot | replan-on-error | skill-steps\n# dispatch: subagent # subagent | self | hybrid\n# activation: explicit # explicit (default) | auto\n# plannerLlm: main # main | planner | helper (unused by skill-steps)\n# maxSteps: 12\n# maxRetriesPerStep: 1\n# failPolicy: abort # abort | continue\n# maxLayer: 1 # DEPRECATED \u2014 accepted but ignored (nested\n# # dispatch removed; subagents are leaves)\n";
117
+ export declare const YAML_TEMPLATE = "port: 4004\nhost: 0.0.0.0\n\n# Request routing mode:\n# hard \u2014 Fully managed context. Ignores client history/system prompt. Uses RAG + internal MCP tools only.\n# pass \u2014 Transparent proxy. Logs everything but modifies nothing.\n# smart \u2014 Hybrid. Preserves client history but enriches it with RAG context and MCP tools based on analysis. (default)\nmode: smart\n\nllm:\n provider: deepseek # deepseek | openai | anthropic | sap-ai-sdk | ollama\n apiKey: ${DEEPSEEK_API_KEY} # not required for ollama / sap-ai-sdk\n model: deepseek-chat\n temperature: 0.7\n classifierTemperature: 0.1\n\nrag:\n type: in-memory # in-memory | qdrant | hana-vector | pg-vector\n embedder: ollama # Embedder to use: ollama | openai | sap-ai-core | <custom>\n url: http://localhost:11434\n model: bge-m3\n # resourceGroup: default # SAP AI Core resource group (sap-ai-core embedder)\n # scenario: orchestration # SAP AI Core scenario: orchestration (default) | foundation-models\n # collectionName: llm-agent # Collection/table name (qdrant | hana-vector | pg-vector)\n dedupThreshold: 0.92\n vectorWeight: 0.7 # Semantic similarity weight (0..1)\n keywordWeight: 0.3 # Lexical matching weight (0..1)\n\nmcp:\n # type: none | http | stdio\n # To disable MCP, set type to 'none'\n type: http\n url: http://localhost:3001/mcp/stream/http\n\nagent:\n externalToolsValidationMode: permissive # permissive | strict\n maxIterations: 10\n maxToolCalls: 30\n toolUnavailableTtlMs: 600000 # Temporary tool blacklist TTL (ms)\n ragQueryK: 10\n # contextBudgetTokens: 4000 # Max tokens for RAG context in system prompt (0 = no limit)\n # semanticHistoryEnabled: false # Enable semantic history via RAG\n # historyRecencyWindow: 4 # Last N messages from client history in LLM context\n # historyTurnSummaryPrompt: \"...\" # LLM prompt for turn summarization\n showReasoning: false # Explain strategy at start of response\n historyAutoSummarizeLimit: 10 # History length to trigger compression\n queryExpansionEnabled: false # Expand RAG queries with LLM-generated synonyms\n toolResultCacheTtlMs: 300000 # Tool result cache TTL (ms); 0 to disable\n sessionTokenBudget: 0 # Multi-turn token budget; 0 to disable\n # ragTranslateEnabled: true # Translate non-ASCII RAG queries to English (default: true)\n # classificationEnabled: false # Enable for custom pipelines with multi-store routing\n # toolReselectPerIteration: false # Re-select tools via RAG on each tool-loop iteration\n # llmCallStrategy: streaming # streaming | non-streaming | fallback\n # streamMode: full # full | final \u2014 streaming behavior for tool loops\n # heartbeatIntervalMs: 5000 # SSE heartbeat interval during tool execution (ms)\n # healthTimeoutMs: 5000 # Health check probe timeout (ms); increase for slow providers (SAP AI Core: 15000)\n # retry: # LLM retry config for 429/5xx errors\n # maxAttempts: 3\n # backoffMs: 1000\n # retryOn: [429, 500, 502, 503]\n # retryOnMidStream: ['SSE stream'] # Substrings triggering mid-stream retry\n\n# --- Advanced Multi-Model LLM (optional) ------------------------------------\n# Assign different models for different internal roles via a top-level llm: map.\n# (The legacy pipeline.llm override was removed \u2014 use the top-level llm: map now.)\n# llm:\n# main:\n# provider: deepseek # deepseek | openai | anthropic | sap-ai-sdk\n# apiKey: ${DEEPSEEK_API_KEY}\n# model: deepseek-chat\n# temperature: 0.7\n# classifier: # optional; if absent, main config is reused\n# provider: deepseek\n# apiKey: ${DEEPSEEK_API_KEY}\n# model: deepseek-chat\n# temperature: 0.1\n# helper: # optional; if absent, main config is reused\n# provider: deepseek\n# apiKey: ${DEEPSEEK_API_KEY}\n# model: deepseek-chat\n# temperature: 0.1\n\n# prompts:\n# system: \"You are a helpful assistant specialized in SAP ABAP development.\"\n# classifier: |\n# You are an intent classifier... (see source for full default prompt)\n# reasoning: |\n# IMPORTANT: Always start your response with a brief <reasoning> block...\n# ragTranslate: |\n# Translate the user request to English for search purposes...\n# historySummary: |\n# Summarize the conversation so far...\n\nlog: smart-server.log # path to log file; omit for stdout\n# logDir: sessions # Directory for detailed session debug logs\n# pluginDir: ./my-plugins # Additional plugin directory (loaded after defaults)\n# plugins: # Explicit plugin module specifiers (npm packages or paths)\n# - \"@scope/my-pipeline-plugin\" # bare specifier resolved from cwd\n# - ./local-plugin.mjs # relative path resolved against cwd\n\n# subagents: # Optional: nested agents callable from pipeline\n# - name: code-reviewer # Used as stage config: { agent: code-reviewer }\n# description: | # Optional. Shown to the Coordinator planner LLM\n# Reviews code and returns # so it can pick this agent for the right step.\n# structured JSON.\n# config: ./agents/code-reviewer.yaml\n\n# pipeline: # Optional: select the request pipeline.\n# name: flat # flat (default) | linear | dag | stepper | <plugin>\n# config: # Opaque per-pipeline dialect (validated by the plugin)\n# mode: planned-react # e.g. stepper: cyclic-react | planned-react | deep-stepper\n# knowledgeSeed: [] # stepper: deployment-supplied tool guidance\n#\n# NOTE: the legacy 'coordinator:' block and the old 'pipeline:' shape\n# (mcp/rag/stages/llm overrides) were REMOVED in this major. A config that\n# still uses them fails loud at startup. Top-level 'llm:', 'mcp:', 'rag:' now\n# own those concerns; pipeline behavior moves under 'pipeline.config'.\n";
121
118
  export declare function resolveEnvVars(value: unknown, env?: NodeJS.ProcessEnv): unknown;
122
119
  export declare function loadYamlConfig(filePath: string, env?: NodeJS.ProcessEnv): YamlConfig;
123
120
  export declare function generateConfigTemplate(outputPath: string): void;
@@ -138,6 +135,18 @@ export type FinalizerYaml = {
138
135
  * `type: template` → TemplateFinalizer.
139
136
  */
140
137
  export declare function buildFinalizer(cfg: FinalizerYaml | undefined, llmMap: NormalizedLlmMap | undefined, pipelineFallback: SmartServerLlmConfig | undefined, makeLlm: (config: SmartServerLlmConfig) => Promise<ILlm>): Promise<IFinalizer>;
138
+ /**
139
+ * Fail-loud migration guard for the clean break to `pipeline: { name, config }`.
140
+ *
141
+ * Throws when the raw YAML still carries either:
142
+ * - a `coordinator:` block (the old runtime dispatch, removed in this major), OR
143
+ * - a `pipeline:` value in the LEGACY PipelineConfig shape — an object that
144
+ * carries `mcp`/`rag`/`stages`/`llm` but NO `name`.
145
+ *
146
+ * A new `pipeline: { name, ... }` object or a bare string shorthand
147
+ * (`pipeline: stepper`) passes untouched.
148
+ */
149
+ export declare function assertNoLegacyPipelineConfig(yaml: YamlConfig): void;
141
150
  export interface ResolveSmartServerConfigOptions {
142
151
  /**
143
152
  * Filesystem path of the YAML config that produced `yaml`. Required for
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/smart-agent/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/smart-agent/config.ts"],"names":[],"mappings":"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"}
@@ -79,96 +79,6 @@ export function resolveReviewerLlmName(block, warn) {
79
79
  }
80
80
  return undefined;
81
81
  }
82
- const LINEAR_ONLY = [
83
- 'planning',
84
- 'dispatch',
85
- 'maxSteps',
86
- 'maxRetriesPerStep',
87
- 'failPolicy',
88
- 'maxLayer',
89
- 'plannerLlm',
90
- ];
91
- const DAG_ONLY = [
92
- 'planner',
93
- 'interpreter',
94
- 'reviewer',
95
- 'errorStrategy',
96
- 'finalizer',
97
- 'stateOracle',
98
- 'maxRoundTrips',
99
- ];
100
- /** Validate a coordinator role block shape. */
101
- function assertLlmRoleShape(label, role) {
102
- if (typeof role !== 'object' || role === null || Array.isArray(role)) {
103
- throw new Error(`coordinator.${label} must be an object (e.g. { type: llm }), got: ${JSON.stringify(role)}`);
104
- }
105
- const kind = role.type;
106
- if (kind !== undefined &&
107
- kind !== 'llm' &&
108
- !(label === 'finalizer' && (kind === 'passthrough' || kind === 'template'))) {
109
- throw new Error(`coordinator.${label}: unknown type '${String(kind)}'`);
110
- }
111
- for (const field of ['plannerLlm', 'reviewerLlm', 'finalizerLlm']) {
112
- const sel = role[field];
113
- if (sel !== undefined && typeof sel !== 'string') {
114
- throw new Error(`coordinator.${label}.${field} must be a string referencing an llm.* key, got: ${String(sel)}`);
115
- }
116
- }
117
- const sp = role.systemPrompt;
118
- if (sp !== undefined && typeof sp !== 'string') {
119
- throw new Error(`coordinator.${label}.systemPrompt must be a string, got: ${String(sp)}`);
120
- }
121
- }
122
- function assertErrorStrategyShape(es) {
123
- if (typeof es !== 'object' || es === null || Array.isArray(es)) {
124
- throw new Error(`coordinator.errorStrategy must be an object (e.g. { type: replan }), got: ${JSON.stringify(es)}`);
125
- }
126
- const type = es.type;
127
- if (type !== undefined && type !== 'abort' && type !== 'replan') {
128
- throw new Error(`coordinator.errorStrategy: unknown type '${String(type)}' (only 'abort' | 'replan')`);
129
- }
130
- const mr = es.maxReplans;
131
- if (mr !== undefined && (typeof mr !== 'number' || mr < 0)) {
132
- throw new Error(`coordinator.errorStrategy.maxReplans must be a non-negative number, got: ${String(mr)}`);
133
- }
134
- }
135
- /** Fail-loud guard: a coordinator block is either DAG (has `planner`) or linear,
136
- * never mixed. `activation` is shared and always allowed. */
137
- export function assertCoordinatorConfigShape(coord) {
138
- const isDag = coord.planner !== undefined;
139
- if (isDag) {
140
- assertLlmRoleShape('planner', coord.planner);
141
- if (coord.reviewer !== undefined) {
142
- assertLlmRoleShape('reviewer', coord.reviewer);
143
- }
144
- if (coord.finalizer !== undefined) {
145
- assertLlmRoleShape('finalizer', coord.finalizer);
146
- }
147
- if (coord.errorStrategy !== undefined) {
148
- assertErrorStrategyShape(coord.errorStrategy);
149
- }
150
- if (coord.stateOracle !== undefined &&
151
- typeof coord.stateOracle !== 'string') {
152
- throw new Error(`coordinator.stateOracle must be a string (a declared subagent name), got: ${JSON.stringify(coord.stateOracle)}`);
153
- }
154
- if (coord.maxRoundTrips !== undefined &&
155
- (typeof coord.maxRoundTrips !== 'number' || coord.maxRoundTrips < 0)) {
156
- throw new Error(`coordinator.maxRoundTrips must be a non-negative number, got: ${String(coord.maxRoundTrips)}`);
157
- }
158
- for (const f of LINEAR_ONLY) {
159
- if (coord[f] !== undefined) {
160
- throw new Error(`coordinator: '${f}' is a linear-only field and cannot be combined with 'planner' (DAG mode)`);
161
- }
162
- }
163
- }
164
- else {
165
- for (const f of DAG_ONLY) {
166
- if (coord[f] !== undefined) {
167
- throw new Error(`coordinator: '${f}' is a DAG-only field; a linear coordinator uses 'planning'/'dispatch'`);
168
- }
169
- }
170
- }
171
- }
172
82
  export function resolveCoordinatorPlanning(name, plannerLlm) {
173
83
  switch (name) {
174
84
  case 'one-shot':
@@ -319,70 +229,25 @@ agent:
319
229
  # retryOn: [429, 500, 502, 503]
320
230
  # retryOnMidStream: ['SSE stream'] # Substrings triggering mid-stream retry
321
231
 
322
- # --- Advanced Multi-Model Pipeline (optional) -------------------------------
323
- # Use this section to assign different models for different internal tasks.
324
- # pipeline:
325
- # llm:
326
- # main:
327
- # provider: deepseek # deepseek | openai | anthropic | sap-ai-sdk
328
- # apiKey: \${DEEPSEEK_API_KEY}
329
- # model: deepseek-chat
330
- # temperature: 0.7
331
- # streaming: true # false to disable streaming for this provider
332
- # classifier: # optional; if absent, main config is reused
333
- # provider: deepseek
334
- # apiKey: \${DEEPSEEK_API_KEY}
335
- # model: deepseek-chat
336
- # temperature: 0.1
337
- # helper: # optional; if absent, main config is reused
338
- # provider: deepseek
339
- # apiKey: \${DEEPSEEK_API_KEY}
340
- # model: deepseek-chat
341
- # temperature: 0.1
342
- #
343
- # rag:
344
- # tools:
345
- # type: qdrant
346
- # url: http://qdrant:6333
347
- # embedder: openai # ollama | openai | <custom registered name>
348
- # model: text-embedding-3-small
349
- # apiKey: \${OPENAI_API_KEY}
350
- # history:
351
- # type: in-memory
352
- #
353
- # mcp:
354
- # - type: http
355
- # url: http://localhost:3001/mcp/stream/http
356
-
357
- # --- Structured Pipeline (optional) -------------------------------------------
358
- # Replaces the hardcoded orchestration flow with a YAML-defined stage tree.
359
- # When absent, the default flow runs unchanged (full backwards compatibility).
360
- #
361
- # pipeline:
362
- # version: "1"
363
- # stages:
364
- # - id: classify
365
- # type: classify
366
- # - id: summarize
367
- # type: summarize
368
- # - id: rag-retrieval
369
- # type: parallel
370
- # when: "shouldRetrieve"
371
- # stages:
372
- # - { id: translate, type: translate }
373
- # - { id: expand, type: expand }
374
- # after:
375
- # - id: rag-queries
376
- # type: parallel
377
- # stages:
378
- # - { id: tools, type: rag-query, config: { store: tools, k: 10 } }
379
- # - { id: history, type: rag-query, config: { store: history, k: 5 } }
380
- # - { id: rerank, type: rerank }
381
- # - { id: tool-select, type: tool-select }
382
- # - id: assemble
383
- # type: assemble
384
- # - id: tool-loop
385
- # type: tool-loop
232
+ # --- Advanced Multi-Model LLM (optional) ------------------------------------
233
+ # Assign different models for different internal roles via a top-level llm: map.
234
+ # (The legacy pipeline.llm override was removed — use the top-level llm: map now.)
235
+ # llm:
236
+ # main:
237
+ # provider: deepseek # deepseek | openai | anthropic | sap-ai-sdk
238
+ # apiKey: \${DEEPSEEK_API_KEY}
239
+ # model: deepseek-chat
240
+ # temperature: 0.7
241
+ # classifier: # optional; if absent, main config is reused
242
+ # provider: deepseek
243
+ # apiKey: \${DEEPSEEK_API_KEY}
244
+ # model: deepseek-chat
245
+ # temperature: 0.1
246
+ # helper: # optional; if absent, main config is reused
247
+ # provider: deepseek
248
+ # apiKey: \${DEEPSEEK_API_KEY}
249
+ # model: deepseek-chat
250
+ # temperature: 0.1
386
251
 
387
252
  # prompts:
388
253
  # system: "You are a helpful assistant specialized in SAP ABAP development."
@@ -398,6 +263,9 @@ agent:
398
263
  log: smart-server.log # path to log file; omit for stdout
399
264
  # logDir: sessions # Directory for detailed session debug logs
400
265
  # pluginDir: ./my-plugins # Additional plugin directory (loaded after defaults)
266
+ # plugins: # Explicit plugin module specifiers (npm packages or paths)
267
+ # - "@scope/my-pipeline-plugin" # bare specifier resolved from cwd
268
+ # - ./local-plugin.mjs # relative path resolved against cwd
401
269
 
402
270
  # subagents: # Optional: nested agents callable from pipeline
403
271
  # - name: code-reviewer # Used as stage config: { agent: code-reviewer }
@@ -406,16 +274,16 @@ log: smart-server.log # path to log file; omit for stdout
406
274
  # structured JSON.
407
275
  # config: ./agents/code-reviewer.yaml
408
276
 
409
- # coordinator: # Optional: enable autonomous plan-execute loop
410
- # planning: one-shot # one-shot | replan-on-error | skill-steps
411
- # dispatch: subagent # subagent | self | hybrid
412
- # activation: explicit # explicit (default) | auto
413
- # plannerLlm: main # main | planner | helper (unused by skill-steps)
414
- # maxSteps: 12
415
- # maxRetriesPerStep: 1
416
- # failPolicy: abort # abort | continue
417
- # maxLayer: 1 # DEPRECATED — accepted but ignored (nested
418
- # # dispatch removed; subagents are leaves)
277
+ # pipeline: # Optional: select the request pipeline.
278
+ # name: flat # flat (default) | linear | dag | stepper | <plugin>
279
+ # config: # Opaque per-pipeline dialect (validated by the plugin)
280
+ # mode: planned-react # e.g. stepper: cyclic-react | planned-react | deep-stepper
281
+ # knowledgeSeed: [] # stepper: deployment-supplied tool guidance
282
+ #
283
+ # NOTE: the legacy 'coordinator:' block and the old 'pipeline:' shape
284
+ # (mcp/rag/stages/llm overrides) were REMOVED in this major. A config that
285
+ # still uses them fails loud at startup. Top-level 'llm:', 'mcp:', 'rag:' now
286
+ # own those concerns; pipeline behavior moves under 'pipeline.config'.
419
287
  `;
420
288
  export function resolveEnvVars(value, env = process.env) {
421
289
  if (typeof value === 'string')
@@ -539,47 +407,73 @@ function checkRagStore(label, store, issues) {
539
407
  function validateLlmEntry(label, cfg, required, env, issues) {
540
408
  checkLlmRole(label, cfg, required, env, issues);
541
409
  }
410
+ /**
411
+ * Fail-loud migration guard for the clean break to `pipeline: { name, config }`.
412
+ *
413
+ * Throws when the raw YAML still carries either:
414
+ * - a `coordinator:` block (the old runtime dispatch, removed in this major), OR
415
+ * - a `pipeline:` value in the LEGACY PipelineConfig shape — an object that
416
+ * carries `mcp`/`rag`/`stages`/`llm` but NO `name`.
417
+ *
418
+ * A new `pipeline: { name, ... }` object or a bare string shorthand
419
+ * (`pipeline: stepper`) passes untouched.
420
+ */
421
+ export function assertNoLegacyPipelineConfig(yaml) {
422
+ const hasCoordinator = yaml.coordinator !== undefined;
423
+ const rawPipeline = yaml.pipeline;
424
+ const isLegacyPipeline = rawPipeline !== undefined &&
425
+ rawPipeline !== null &&
426
+ typeof rawPipeline === 'object' &&
427
+ !Array.isArray(rawPipeline) &&
428
+ typeof rawPipeline.name !== 'string' &&
429
+ ['mcp', 'rag', 'stages', 'llm'].some((k) => rawPipeline[k] !== undefined);
430
+ if (hasCoordinator || isLegacyPipeline) {
431
+ throw new Error("Legacy 'coordinator:' / 'pipeline:' config is no longer supported (removed in this major). " +
432
+ 'Migrate to: pipeline: { name: <flat|linear|dag|stepper>, config: { ... } }. ' +
433
+ "(Stepper's knowledgeSeed moves under pipeline.config.knowledgeSeed.) " +
434
+ 'Pin a version <= 18 for the old behavior.');
435
+ }
436
+ }
542
437
  function validateResolvedConfig(_resolved, yaml, env) {
543
438
  const issues = [];
544
- const usingPipeline = !!get(yaml, 'pipeline', 'llm', 'main');
545
- if (usingPipeline) {
546
- const llmCfg = get(yaml, 'pipeline', 'llm');
547
- checkLlmRole('pipeline.llm.main', llmCfg?.main, true, env, issues);
548
- if (llmCfg?.classifier) {
549
- checkLlmRole('pipeline.llm.classifier', llmCfg.classifier, false, env, issues);
550
- }
551
- if (llmCfg?.helper) {
552
- checkLlmRole('pipeline.llm.helper', llmCfg.helper, false, env, issues);
553
- }
439
+ // LLM is always sourced from the top-level `llm:` block now — the legacy
440
+ // `pipeline.llm.*` override has been removed with the `pipeline: {name,config}`
441
+ // migration. Read from the raw YAML so we can distinguish flat vs map shape.
442
+ // `resolved.llm` is always constructed as a flat object by
443
+ // resolveSmartServerConfig, so it cannot be used to detect the map shape.
444
+ const rawLlm = get(yaml, 'llm');
445
+ if (rawLlm === undefined) {
446
+ issues.push('llm: required (top-level llm.main or a flat llm block)');
447
+ }
448
+ else if (typeof rawLlm.provider === 'string') {
449
+ // Flat shape — existing behaviour.
450
+ validateLlmEntry('llm', rawLlm, true, env, issues);
554
451
  }
555
452
  else {
556
- // Read from the raw YAML so we can distinguish flat vs map shape.
557
- // `resolved.llm` is always constructed as a flat object by resolveSmartServerConfig,
558
- // so it cannot be used to detect the map shape.
559
- const rawLlm = get(yaml, 'llm');
560
- if (rawLlm === undefined) {
561
- // No top-level llm: AND no pipeline.llm.main → would have been caught
562
- // by `usingPipeline` branch. Defensive: surface a clear issue.
563
- issues.push('llm: required when pipeline.llm.main is not configured');
564
- }
565
- else if (typeof rawLlm.provider === 'string') {
566
- // Flat shape — existing behaviour.
567
- validateLlmEntry('llm', rawLlm, true, env, issues);
453
+ // Map shape — llm.main is required; every named entry is validated.
454
+ const map = rawLlm;
455
+ if (!map.main) {
456
+ issues.push("llm.main: required when 'llm' is a named map");
568
457
  }
569
458
  else {
570
- // Map shape — llm.main is required; every named entry is validated.
571
- const map = rawLlm;
572
- if (!map.main) {
573
- issues.push("llm.main: required when 'llm' is a named map");
574
- }
575
- else {
576
- validateLlmEntry('llm.main', map.main, true, env, issues);
577
- }
578
- for (const [name, entry] of Object.entries(map)) {
579
- if (name === 'main')
580
- continue;
581
- validateLlmEntry(`llm.${name}`, entry, true, env, issues);
582
- }
459
+ validateLlmEntry('llm.main', map.main, true, env, issues);
460
+ }
461
+ for (const [name, entry] of Object.entries(map)) {
462
+ if (name === 'main')
463
+ continue;
464
+ validateLlmEntry(`llm.${name}`, entry, true, env, issues);
465
+ }
466
+ }
467
+ // Pipeline selection shape: `pipeline:` must name a pipeline (string or
468
+ // { name } object). The plugin validates its own `config` dialect at build
469
+ // time — we only enforce the presence of a name here.
470
+ const rawPipeline = yaml.pipeline;
471
+ if (rawPipeline !== undefined && rawPipeline !== null) {
472
+ const ok = typeof rawPipeline === 'string' ||
473
+ (typeof rawPipeline === 'object' &&
474
+ typeof rawPipeline.name === 'string');
475
+ if (!ok) {
476
+ issues.push("pipeline: requires a 'name' (string, or { name, config }); built-ins: flat, linear, dag, stepper");
583
477
  }
584
478
  }
585
479
  if (get(yaml, 'mcp')) {
@@ -604,12 +498,9 @@ function validateResolvedConfig(_resolved, yaml, env) {
604
498
  if (get(yaml, 'rag')) {
605
499
  checkRagStore('rag', get(yaml, 'rag'), issues);
606
500
  }
607
- const pipelineRag = get(yaml, 'pipeline', 'rag');
608
- if (pipelineRag) {
609
- for (const [name, store] of Object.entries(pipelineRag)) {
610
- checkRagStore(`pipeline.rag.${name}`, store, issues);
611
- }
612
- }
501
+ // NOTE: the legacy `pipeline.rag.{name}` multistore was removed with the
502
+ // `pipeline: {name,config}` migration; the top-level `rag:` block is the sole
503
+ // RAG source, validated above.
613
504
  if (issues.length > 0)
614
505
  throw new ConfigValidationError([...new Set(issues)]);
615
506
  }
@@ -661,28 +552,18 @@ function parseSubAgents(yaml, configPath, args, env) {
661
552
  if (subYaml.pluginDir !== undefined) {
662
553
  unsupported.push('pluginDir');
663
554
  }
555
+ if (subYaml.plugins !== undefined) {
556
+ unsupported.push('plugins');
557
+ }
664
558
  if (subYaml.clientAdapter !== undefined) {
665
559
  unsupported.push('clientAdapter');
666
560
  }
667
561
  if (subYaml.circuitBreaker !== undefined) {
668
562
  unsupported.push('circuitBreaker');
669
563
  }
670
- const subPipeline = subYaml.pipeline;
671
- if (subPipeline && typeof subPipeline === 'object') {
672
- const p = subPipeline;
673
- if (p.reranker !== undefined)
674
- unsupported.push('pipeline.reranker');
675
- if (p.queryExpander !== undefined)
676
- unsupported.push('pipeline.queryExpander');
677
- if (p.outputValidator !== undefined)
678
- unsupported.push('pipeline.outputValidator');
679
- if (p.rag !== undefined &&
680
- p.rag !== null &&
681
- typeof p.rag === 'object' &&
682
- !Array.isArray(p.rag)) {
683
- unsupported.push('pipeline.rag');
684
- }
685
- }
564
+ // A subagent's `pipeline:` (if present) is the new `{name, config}` shape;
565
+ // there are no per-subagent reranker/queryExpander/outputValidator/rag
566
+ // overrides to reject anymore (they were tied to the removed legacy shape).
686
567
  if (unsupported.length > 0) {
687
568
  throw new Error(`subagent '${name}': unsupported fields [${unsupported.join(', ')}]`);
688
569
  }
@@ -696,9 +577,13 @@ function parseSubAgents(yaml, configPath, args, env) {
696
577
  return out;
697
578
  }
698
579
  export function resolveSmartServerConfig(args = {}, yaml = {}, env = process.env, options = {}) {
699
- const flatApiKey = get(yaml, 'llm', 'apiKey') ?? '';
700
- const pipelineApiKey = get(yaml, 'pipeline', 'llm', 'main', 'apiKey');
701
- const apiKey = flatApiKey || pipelineApiKey || '';
580
+ // Clean-break migration guard FIRST — before any pipeline-shape parsing — so a
581
+ // legacy `coordinator:`/`pipeline:` config gets the actionable migration error
582
+ // rather than the generic "pipeline requires a name" diagnostic.
583
+ assertNoLegacyPipelineConfig(yaml);
584
+ // API key derives solely from the top-level `llm:` block now (the legacy
585
+ // `pipeline.llm.main.apiKey` override was removed with the schema migration).
586
+ const apiKey = get(yaml, 'llm', 'apiKey') ?? '';
702
587
  const rawMcp = yaml.mcp;
703
588
  const mcpIsArray = Array.isArray(rawMcp);
704
589
  const mcpUrl = get(yaml, 'mcp', 'url');
@@ -872,16 +757,40 @@ export function resolveSmartServerConfig(args = {}, yaml = {}, env = process.env
872
757
  mode: get(yaml, 'mode') ?? undefined,
873
758
  logDir: args['log-dir'] ?? get(yaml, 'logDir') ?? null,
874
759
  pluginDir: args['plugin-dir'] ?? get(yaml, 'pluginDir') ?? undefined,
760
+ plugins: (() => {
761
+ const raw = get(yaml, 'plugins');
762
+ if (!Array.isArray(raw))
763
+ return undefined;
764
+ const specs = raw.filter((s) => typeof s === 'string');
765
+ return specs.length > 0 ? specs : undefined;
766
+ })(),
875
767
  ...(() => {
876
768
  const subAgentConfigs = parseSubAgents(yaml, options.configPath, args, env);
877
769
  return subAgentConfigs ? { subAgentConfigs } : {};
878
770
  })(),
879
771
  ...(() => {
880
- const coordinatorYaml = yaml
881
- .coordinator;
882
- return coordinatorYaml ? { coordinatorYaml } : {};
772
+ // Pipeline selection: `pipeline: { name, config }`. `name` is required;
773
+ // `config` is the plugin's opaque dialect (validated by the plugin's
774
+ // parseConfig at build time). A bare string (`pipeline: stepper`) is
775
+ // accepted as shorthand for `{ name: <string> }`.
776
+ const raw = yaml.pipeline;
777
+ if (raw === undefined || raw === null)
778
+ return {};
779
+ if (typeof raw === 'string')
780
+ return { pipeline: { name: raw } };
781
+ const obj = raw;
782
+ if (typeof obj.name !== 'string') {
783
+ throw new Error("pipeline: requires a 'name' (one of: flat, linear, dag, stepper, or a registered plugin)");
784
+ }
785
+ return {
786
+ pipeline: {
787
+ name: obj.name,
788
+ ...(obj.config && typeof obj.config === 'object'
789
+ ? { config: obj.config }
790
+ : {}),
791
+ },
792
+ };
883
793
  })(),
884
- ...(yaml.pipeline ? { pipeline: yaml.pipeline } : {}),
885
794
  ...(yaml.skills
886
795
  ? {
887
796
  skills: {