@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.
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/legacy/dag.d.ts +4 -0
- package/dist/legacy/dag.d.ts.map +1 -0
- package/dist/legacy/dag.js +4 -0
- package/dist/legacy/dag.js.map +1 -0
- package/dist/legacy/flat.d.ts +2 -0
- package/dist/legacy/flat.d.ts.map +1 -0
- package/dist/legacy/flat.js +3 -0
- package/dist/legacy/flat.js.map +1 -0
- package/dist/legacy/linear.d.ts +3 -0
- package/dist/legacy/linear.d.ts.map +1 -0
- package/dist/legacy/linear.js +3 -0
- package/dist/legacy/linear.js.map +1 -0
- package/dist/legacy/stepper.d.ts +5 -0
- package/dist/legacy/stepper.d.ts.map +1 -0
- package/dist/legacy/stepper.js +5 -0
- package/dist/legacy/stepper.js.map +1 -0
- package/dist/pipelines/controller.d.ts +19 -0
- package/dist/pipelines/controller.d.ts.map +1 -0
- package/dist/pipelines/controller.js +100 -0
- package/dist/pipelines/controller.js.map +1 -0
- package/dist/pipelines/dag.d.ts +23 -0
- package/dist/pipelines/dag.d.ts.map +1 -0
- package/dist/pipelines/dag.js +46 -0
- package/dist/pipelines/dag.js.map +1 -0
- package/dist/pipelines/flat.d.ts +14 -0
- package/dist/pipelines/flat.d.ts.map +1 -0
- package/dist/pipelines/flat.js +18 -0
- package/dist/pipelines/flat.js.map +1 -0
- package/dist/pipelines/linear.d.ts +17 -0
- package/dist/pipelines/linear.d.ts.map +1 -0
- package/dist/pipelines/linear.js +26 -0
- package/dist/pipelines/linear.js.map +1 -0
- package/dist/pipelines/parsers.d.ts +5 -0
- package/dist/pipelines/parsers.d.ts.map +1 -0
- package/dist/pipelines/parsers.js +20 -0
- package/dist/pipelines/parsers.js.map +1 -0
- package/dist/pipelines/server-context.d.ts +53 -0
- package/dist/pipelines/server-context.d.ts.map +1 -0
- package/dist/pipelines/server-context.js +9 -0
- package/dist/pipelines/server-context.js.map +1 -0
- package/dist/pipelines/stepper.d.ts +23 -0
- package/dist/pipelines/stepper.d.ts.map +1 -0
- package/dist/pipelines/stepper.js +60 -0
- package/dist/pipelines/stepper.js.map +1 -0
- package/dist/smart-agent/config.d.ts +13 -4
- package/dist/smart-agent/config.d.ts.map +1 -1
- package/dist/smart-agent/config.js +137 -228
- package/dist/smart-agent/config.js.map +1 -1
- package/dist/smart-agent/controller/controller-coordinator-handler.d.ts +99 -0
- package/dist/smart-agent/controller/controller-coordinator-handler.d.ts.map +1 -0
- package/dist/smart-agent/controller/controller-coordinator-handler.js +627 -0
- package/dist/smart-agent/controller/controller-coordinator-handler.js.map +1 -0
- package/dist/smart-agent/controller/memorizer.d.ts +6 -0
- package/dist/smart-agent/controller/memorizer.d.ts.map +1 -0
- package/dist/smart-agent/controller/memorizer.js +5 -0
- package/dist/smart-agent/controller/memorizer.js.map +1 -0
- package/dist/smart-agent/controller/need-resolver.d.ts +3 -0
- package/dist/smart-agent/controller/need-resolver.d.ts.map +1 -0
- package/dist/smart-agent/controller/need-resolver.js +4 -0
- package/dist/smart-agent/controller/need-resolver.js.map +1 -0
- package/dist/smart-agent/controller/planner.d.ts +34 -0
- package/dist/smart-agent/controller/planner.d.ts.map +1 -0
- package/dist/smart-agent/controller/planner.js +247 -0
- package/dist/smart-agent/controller/planner.js.map +1 -0
- package/dist/smart-agent/controller/prompts.d.ts +17 -0
- package/dist/smart-agent/controller/prompts.d.ts.map +1 -0
- package/dist/smart-agent/controller/prompts.js +20 -0
- package/dist/smart-agent/controller/prompts.js.map +1 -0
- package/dist/smart-agent/controller/session-bundle.d.ts +15 -0
- package/dist/smart-agent/controller/session-bundle.d.ts.map +1 -0
- package/dist/smart-agent/controller/session-bundle.js +53 -0
- package/dist/smart-agent/controller/session-bundle.js.map +1 -0
- package/dist/smart-agent/controller/subagent-client.d.ts +7 -0
- package/dist/smart-agent/controller/subagent-client.d.ts.map +1 -0
- package/dist/smart-agent/controller/subagent-client.js +18 -0
- package/dist/smart-agent/controller/subagent-client.js.map +1 -0
- package/dist/smart-agent/controller/target-state.d.ts +28 -0
- package/dist/smart-agent/controller/target-state.d.ts.map +1 -0
- package/dist/smart-agent/controller/target-state.js +59 -0
- package/dist/smart-agent/controller/target-state.js.map +1 -0
- package/dist/smart-agent/controller/types.d.ts +121 -0
- package/dist/smart-agent/controller/types.d.ts.map +1 -0
- package/dist/smart-agent/controller/types.js +2 -0
- package/dist/smart-agent/controller/types.js.map +1 -0
- package/dist/smart-agent/resolve-agent-embedder.d.ts.map +1 -1
- package/dist/smart-agent/resolve-agent-embedder.js +8 -2
- package/dist/smart-agent/resolve-agent-embedder.js.map +1 -1
- package/dist/smart-agent/smart-server.d.ts +188 -31
- package/dist/smart-agent/smart-server.d.ts.map +1 -1
- package/dist/smart-agent/smart-server.js +809 -637
- package/dist/smart-agent/smart-server.js.map +1 -1
- package/dist/smart-agent/stepper-coordinator-handler.d.ts.map +1 -1
- package/dist/smart-agent/stepper-coordinator-handler.js +25 -11
- package/dist/smart-agent/stepper-coordinator-handler.js.map +1 -1
- 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
|
|
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":"AAAA;;GAEG;AAIH,OAAO,KAAK,EACV,UAAU,EACV,IAAI,EACJ,uBAAuB,EACvB,sBAAsB,EACtB,QAAQ,EACT,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,cAAc,EAEd,eAAe,EAEf,qBAAqB,EAErB,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAGjB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EACV,iBAAiB,EACjB,oBAAoB,EAGrB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;AAChE,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,GAAG,YAAY,CAAC;AAmB7E;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,CAAC,EAAE,oBAAoB,GAAG,YAAY,GAC1C,gBAAgB,GAAG,SAAS,CAY9B;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,gBAAgB,GAAG,SAAS,EACjC,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,oBAAoB,GAAG,SAAS,CAGlC;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,gBAAgB,GAAG,SAAS,EACjC,IAAI,CAAC,EAAE,MAAM,EACb,gBAAgB,CAAC,EAAE,oBAAoB,GACtC,oBAAoB,GAAG,SAAS,CAIlC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EAChE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,MAAM,GAAG,SAAS,CAUpB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,UAAU,GAAG,iBAAiB,GAAG,aAAa,CAAC;IAC1D,QAAQ,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EACJ;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAA;KAAE,GAC7D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;KAC5C,CAAC;IACF,SAAS,CAAC,EAAE;QACV,IAAI,CAAC,EAAE,aAAa,GAAG,KAAK,GAAG,UAAU,CAAC;QAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,aAAa,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;
|
|
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
|
|
323
|
-
#
|
|
324
|
-
# pipeline:
|
|
325
|
-
#
|
|
326
|
-
#
|
|
327
|
-
#
|
|
328
|
-
#
|
|
329
|
-
#
|
|
330
|
-
#
|
|
331
|
-
#
|
|
332
|
-
#
|
|
333
|
-
#
|
|
334
|
-
#
|
|
335
|
-
#
|
|
336
|
-
#
|
|
337
|
-
#
|
|
338
|
-
#
|
|
339
|
-
#
|
|
340
|
-
#
|
|
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
|
-
#
|
|
410
|
-
#
|
|
411
|
-
#
|
|
412
|
-
#
|
|
413
|
-
#
|
|
414
|
-
#
|
|
415
|
-
#
|
|
416
|
-
#
|
|
417
|
-
#
|
|
418
|
-
#
|
|
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
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
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
|
-
//
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
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
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
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
|
-
|
|
608
|
-
|
|
609
|
-
|
|
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
|
-
|
|
671
|
-
|
|
672
|
-
|
|
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
|
-
|
|
700
|
-
|
|
701
|
-
|
|
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
|
-
|
|
881
|
-
|
|
882
|
-
|
|
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: {
|