@mcp-abap-adt/llm-agent-server-libs 26.0.0 → 28.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builders/controller-skill-pipeline-builder.d.ts +6 -5
- package/dist/builders/controller-skill-pipeline-builder.d.ts.map +1 -1
- package/dist/builders/controller-skill-pipeline-builder.js +49 -54
- package/dist/builders/controller-skill-pipeline-builder.js.map +1 -1
- package/dist/factories/controller-factory.d.ts +13 -10
- package/dist/factories/controller-factory.d.ts.map +1 -1
- package/dist/factories/controller-factory.js +33 -12
- package/dist/factories/controller-factory.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/pipelines/controller-subagents.d.ts +11 -0
- package/dist/pipelines/controller-subagents.d.ts.map +1 -0
- package/dist/pipelines/controller-subagents.js +77 -0
- package/dist/pipelines/controller-subagents.js.map +1 -0
- package/dist/pipelines/controller.d.ts +11 -10
- package/dist/pipelines/controller.d.ts.map +1 -1
- package/dist/pipelines/controller.js +14 -65
- package/dist/pipelines/controller.js.map +1 -1
- package/dist/pipelines/coordinator-resolvers.d.ts +6 -11
- package/dist/pipelines/coordinator-resolvers.d.ts.map +1 -1
- package/dist/pipelines/coordinator-resolvers.js +7 -17
- package/dist/pipelines/coordinator-resolvers.js.map +1 -1
- package/dist/pipelines/dag.d.ts +9 -9
- package/dist/pipelines/dag.d.ts.map +1 -1
- package/dist/pipelines/dag.js +11 -22
- package/dist/pipelines/dag.js.map +1 -1
- package/dist/pipelines/flat.d.ts +4 -7
- package/dist/pipelines/flat.d.ts.map +1 -1
- package/dist/pipelines/flat.js +3 -8
- package/dist/pipelines/flat.js.map +1 -1
- package/dist/pipelines/linear.d.ts +8 -10
- package/dist/pipelines/linear.d.ts.map +1 -1
- package/dist/pipelines/linear.js +18 -11
- package/dist/pipelines/linear.js.map +1 -1
- package/dist/pipelines/parsers.d.ts +0 -3
- package/dist/pipelines/parsers.d.ts.map +1 -1
- package/dist/pipelines/parsers.js +4 -19
- package/dist/pipelines/parsers.js.map +1 -1
- package/dist/pipelines/server-context.d.ts +0 -5
- package/dist/pipelines/server-context.d.ts.map +1 -1
- package/dist/pipelines/server-context.js.map +1 -1
- package/dist/pipelines/stepper.d.ts +5 -4
- package/dist/pipelines/stepper.d.ts.map +1 -1
- package/dist/pipelines/stepper.js +5 -4
- package/dist/pipelines/stepper.js.map +1 -1
- package/dist/smart-agent/build-dag-coordinator-deps.d.ts +11 -22
- package/dist/smart-agent/build-dag-coordinator-deps.d.ts.map +1 -1
- package/dist/smart-agent/build-dag-coordinator-deps.js +21 -78
- package/dist/smart-agent/build-dag-coordinator-deps.js.map +1 -1
- package/dist/smart-agent/build-stepper-root.d.ts.map +1 -1
- package/dist/smart-agent/build-stepper-root.js +0 -1
- package/dist/smart-agent/build-stepper-root.js.map +1 -1
- package/dist/smart-agent/config-validator.d.ts +8 -1
- package/dist/smart-agent/config-validator.d.ts.map +1 -1
- package/dist/smart-agent/config-validator.js +200 -62
- package/dist/smart-agent/config-validator.js.map +1 -1
- package/dist/smart-agent/config.d.ts +7 -7
- package/dist/smart-agent/config.d.ts.map +1 -1
- package/dist/smart-agent/config.js +24 -11
- package/dist/smart-agent/config.js.map +1 -1
- package/dist/smart-agent/controller/types.d.ts +22 -15
- package/dist/smart-agent/controller/types.d.ts.map +1 -1
- package/dist/smart-agent/controller/types.js.map +1 -1
- package/dist/smart-agent/http/config-route-handler.d.ts +2 -0
- package/dist/smart-agent/http/config-route-handler.d.ts.map +1 -1
- package/dist/smart-agent/http/config-route-handler.js +20 -0
- package/dist/smart-agent/http/config-route-handler.js.map +1 -1
- package/dist/smart-agent/llm/role-llm-resolver.d.ts +23 -11
- package/dist/smart-agent/llm/role-llm-resolver.d.ts.map +1 -1
- package/dist/smart-agent/llm/role-llm-resolver.js +65 -37
- package/dist/smart-agent/llm/role-llm-resolver.js.map +1 -1
- package/dist/smart-agent/llm-config-map.d.ts +9 -1
- package/dist/smart-agent/llm-config-map.d.ts.map +1 -1
- package/dist/smart-agent/llm-config-map.js +27 -5
- package/dist/smart-agent/llm-config-map.js.map +1 -1
- package/dist/smart-agent/pipeline-settings.d.ts +50 -0
- package/dist/smart-agent/pipeline-settings.d.ts.map +1 -0
- package/dist/smart-agent/pipeline-settings.js +174 -0
- package/dist/smart-agent/pipeline-settings.js.map +1 -0
- package/dist/smart-agent/pipeline.d.ts +3 -63
- package/dist/smart-agent/pipeline.d.ts.map +1 -1
- package/dist/smart-agent/pipeline.js +3 -2
- package/dist/smart-agent/pipeline.js.map +1 -1
- package/dist/smart-agent/rag-config.d.ts +155 -0
- package/dist/smart-agent/rag-config.d.ts.map +1 -0
- package/dist/smart-agent/rag-config.js +62 -0
- package/dist/smart-agent/rag-config.js.map +1 -0
- package/dist/smart-agent/resolve-agent-embedder.d.ts +11 -10
- package/dist/smart-agent/resolve-agent-embedder.d.ts.map +1 -1
- package/dist/smart-agent/resolve-agent-embedder.js +37 -36
- package/dist/smart-agent/resolve-agent-embedder.js.map +1 -1
- package/dist/smart-agent/resolve-config-sections.d.ts +1 -1
- package/dist/smart-agent/resolve-config-sections.d.ts.map +1 -1
- package/dist/smart-agent/resolve-config-sections.js +124 -30
- package/dist/smart-agent/resolve-config-sections.js.map +1 -1
- package/dist/smart-agent/select-pipeline-plugin.d.ts +8 -0
- package/dist/smart-agent/select-pipeline-plugin.d.ts.map +1 -0
- package/dist/smart-agent/select-pipeline-plugin.js +26 -0
- package/dist/smart-agent/select-pipeline-plugin.js.map +1 -0
- package/dist/smart-agent/session-lifecycle/index.d.ts +38 -4
- package/dist/smart-agent/session-lifecycle/index.d.ts.map +1 -1
- package/dist/smart-agent/session-lifecycle/index.js +11 -1
- package/dist/smart-agent/session-lifecycle/index.js.map +1 -1
- package/dist/smart-agent/session-lifecycle/session-rag-registry.d.ts +39 -0
- package/dist/smart-agent/session-lifecycle/session-rag-registry.d.ts.map +1 -0
- package/dist/smart-agent/session-lifecycle/session-rag-registry.js +109 -0
- package/dist/smart-agent/session-lifecycle/session-rag-registry.js.map +1 -0
- package/dist/smart-agent/skill-plugins-config.d.ts +3 -2
- package/dist/smart-agent/skill-plugins-config.d.ts.map +1 -1
- package/dist/smart-agent/skill-plugins-config.js +12 -1
- package/dist/smart-agent/skill-plugins-config.js.map +1 -1
- package/dist/smart-agent/skill-plugins-host-factory.d.ts +9 -0
- package/dist/smart-agent/skill-plugins-host-factory.d.ts.map +1 -1
- package/dist/smart-agent/skill-plugins-host-factory.js +12 -6
- package/dist/smart-agent/skill-plugins-host-factory.js.map +1 -1
- package/dist/smart-agent/smart-server.d.ts +90 -78
- package/dist/smart-agent/smart-server.d.ts.map +1 -1
- package/dist/smart-agent/smart-server.js +201 -152
- package/dist/smart-agent/smart-server.js.map +1 -1
- package/dist/smart-agent/worker-llm.d.ts +18 -0
- package/dist/smart-agent/worker-llm.d.ts.map +1 -0
- package/dist/smart-agent/worker-llm.js +59 -0
- package/dist/smart-agent/worker-llm.js.map +1 -0
- package/dist/smart-agent/workers/worker-registry.d.ts +6 -14
- package/dist/smart-agent/workers/worker-registry.d.ts.map +1 -1
- package/dist/smart-agent/workers/worker-registry.js +2 -11
- package/dist/smart-agent/workers/worker-registry.js.map +1 -1
- package/dist/smart-agent/yaml-loader.d.ts +1 -1
- package/dist/smart-agent/yaml-loader.d.ts.map +1 -1
- package/dist/smart-agent/yaml-loader.js +20 -17
- package/dist/smart-agent/yaml-loader.js.map +1 -1
- package/package.json +9 -8
- package/dist/smart-agent/mcp/mcp-content.d.ts +0 -19
- package/dist/smart-agent/mcp/mcp-content.d.ts.map +0 -1
- package/dist/smart-agent/mcp/mcp-content.js +0 -31
- package/dist/smart-agent/mcp/mcp-content.js.map +0 -1
- package/dist/smart-agent/mcp/require-mcp-timeout.d.ts +0 -20
- package/dist/smart-agent/mcp/require-mcp-timeout.d.ts.map +0 -1
- package/dist/smart-agent/mcp/require-mcp-timeout.js +0 -23
- package/dist/smart-agent/mcp/require-mcp-timeout.js.map +0 -1
- package/dist/smart-agent/mcp-readiness-monitor.d.ts +0 -38
- package/dist/smart-agent/mcp-readiness-monitor.d.ts.map +0 -1
- package/dist/smart-agent/mcp-readiness-monitor.js +0 -81
- package/dist/smart-agent/mcp-readiness-monitor.js.map +0 -1
- package/dist/smart-agent/mcp-readiness-registry.d.ts +0 -37
- package/dist/smart-agent/mcp-readiness-registry.d.ts.map +0 -1
- package/dist/smart-agent/mcp-readiness-registry.js +0 -55
- package/dist/smart-agent/mcp-readiness-registry.js.map +0 -1
- package/dist/smart-agent/skill-plugins-config.test.d.ts +0 -2
- package/dist/smart-agent/skill-plugins-config.test.d.ts.map +0 -1
- package/dist/smart-agent/skill-plugins-config.test.js.map +0 -1
- package/dist/smart-agent/skill-plugins-host-factory.test.d.ts +0 -2
- package/dist/smart-agent/skill-plugins-host-factory.test.d.ts.map +0 -1
- package/dist/smart-agent/skill-plugins-host-factory.test.js.map +0 -1
|
@@ -6,10 +6,10 @@ import http from 'node:http';
|
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
7
7
|
import { resolve as pathResolve } from 'node:path';
|
|
8
8
|
import { pathToFileURL } from 'node:url';
|
|
9
|
-
import { buildNamespacedTools, defaultToolNamespace, isReadinessReporter, } from '@mcp-abap-adt/llm-agent';
|
|
10
|
-
import { ClaudeSkillManager, CodexSkillManager, FileSystemPluginLoader, FileSystemSkillManager, getDefaultPluginDirs, HealthChecker, InMemoryKnowledgeBackend, KnowledgeRag,
|
|
9
|
+
import { buildNamespacedTools, defaultToolNamespace, isReadinessReporter, SimpleRagProviderRegistry, } from '@mcp-abap-adt/llm-agent';
|
|
10
|
+
import { ClaudeSkillManager, CodexSkillManager, FileSystemPluginLoader, FileSystemSkillManager, getDefaultPluginDirs, HealthChecker, InMemoryKnowledgeBackend, KnowledgeRag, mergePluginExports, SessionRequestLogger, SmartAgentBuilder, SmartAgentSubAgent, WindowContextStrategy, } from '@mcp-abap-adt/llm-agent-libs';
|
|
11
11
|
import { DefaultMcpFailureClassifier, MCPClientWrapper, McpClientAdapter, } from '@mcp-abap-adt/llm-agent-mcp';
|
|
12
|
-
import {
|
|
12
|
+
import { prefetchEmbedderFactories } from '@mcp-abap-adt/llm-agent-rag';
|
|
13
13
|
import { PACKAGE_VERSION } from '../generated/version.js';
|
|
14
14
|
import { ConfigReloadWatcher } from './config-reload-watcher.js';
|
|
15
15
|
import { handleAdapterRequest } from './http/adapter-route-handler.js';
|
|
@@ -21,9 +21,11 @@ import { CORS_HEADERS, jsonError, writeNotReady, } from './http/response-helpers
|
|
|
21
21
|
import { HttpRouteTable } from './http/route-table.js';
|
|
22
22
|
import { handleSessionDelete, handleSessionResume, handleSessionsList, } from './http/sessions-route-handler.js';
|
|
23
23
|
import { handleUsageRoute } from './http/usage-route-handler.js';
|
|
24
|
-
import {
|
|
24
|
+
import { RoleLlmResolver, } from './llm/role-llm-resolver.js';
|
|
25
|
+
import { assertRagConfigShape, embedderSectionFor, toMakeRagInput, } from './rag-config.js';
|
|
25
26
|
import { resolveAgentEmbedder } from './resolve-agent-embedder.js';
|
|
26
27
|
import { makeToolsRagHandle } from './tools-rag-handle.js';
|
|
28
|
+
import { assertWorkerLlmConfig, parseWorkerLlm } from './worker-llm.js';
|
|
27
29
|
export { writeNotReady } from './http/response-helpers.js';
|
|
28
30
|
// ---------------------------------------------------------------------------
|
|
29
31
|
// Helpers
|
|
@@ -56,9 +58,12 @@ import { createServerPipelineContext, } from '../pipelines/server-context.js';
|
|
|
56
58
|
import { StepperPipelinePlugin } from '../pipelines/stepper.js';
|
|
57
59
|
import { normalizeLlmConfig, resolveLlmConfig, resolveLlmConfigStrict, resolveToolSelectionStrategy, } from './config.js';
|
|
58
60
|
import { makeKnowledgeBackend } from './knowledge/make-knowledge-backend.js';
|
|
61
|
+
import { llmKeySet } from './llm-config-map.js';
|
|
59
62
|
import { buildSessionMcpClients, serverOwnsMcpConnection, shouldIsolateMcpPerSession, } from './mcp/build-session-mcp-clients.js';
|
|
60
63
|
import { buildNamespacedMcpBridge, rebindProvenanceToClients, } from './mcp/namespaced-bridge.js';
|
|
61
64
|
import { makePgPool, makePgReadPool } from './pg-pool.js';
|
|
65
|
+
import { assertNamedLlmKeys, dagNamedLlmKeys, parseControllerSettings, parseDagSettings, parseLinearSettings, parseStepperSettings, } from './pipeline-settings.js';
|
|
66
|
+
import { selectPipelinePlugin } from './select-pipeline-plugin.js';
|
|
62
67
|
import { InMemorySessionMetaStore } from './session-meta-store.js';
|
|
63
68
|
import { buildSkillHostFromConfig, initSkillHost, } from './skill-plugins-host-factory.js';
|
|
64
69
|
export { generateConfigTemplate, loadYamlConfig, resolveCoordinatorActivation, resolveCoordinatorDispatch, resolveCoordinatorPlanning, resolveEnvVars, resolveSmartServerConfig, resolveToolSelectionStrategy, YAML_TEMPLATE, } from './config.js';
|
|
@@ -75,8 +80,8 @@ import { backfillWorkerCacheFromHandle, resolveWorkerLlmSet, WorkerRegistry, } f
|
|
|
75
80
|
// Internal callers (SmartServer methods) import the value symbols they call;
|
|
76
81
|
// re-export the full public surface for the package barrel.
|
|
77
82
|
// ---------------------------------------------------------------------------
|
|
78
|
-
import { buildSessionLifecycle, recordSessionEnd, recordSessionStart, resolveSubAgentRagRegistry, seedSessionKnowledge, } from './session-lifecycle/index.js';
|
|
79
|
-
export { buildSessionLifecycle, handleDeleteSession, handleListSessions, handleResumeSession, recordSessionEnd, recordSessionStart, resolveSubAgentRagRegistry, seedSessionKnowledge, } from './session-lifecycle/index.js';
|
|
83
|
+
import { buildSessionLifecycle, buildSessionRagRegistry, recordSessionEnd, recordSessionStart, resolveSubAgentRagRegistry, seedSessionKnowledge, } from './session-lifecycle/index.js';
|
|
84
|
+
export { buildSessionLifecycle, buildSessionRagRegistry, handleDeleteSession, handleListSessions, handleResumeSession, recordSessionEnd, recordSessionStart, resolveSubAgentRagRegistry, seedSessionKnowledge, } from './session-lifecycle/index.js';
|
|
80
85
|
// ---------------------------------------------------------------------------
|
|
81
86
|
// MCP bridge for the Stepper path (B-1)
|
|
82
87
|
// ---------------------------------------------------------------------------
|
|
@@ -191,6 +196,25 @@ export function buildMcpBridge(clients, classifier = new DefaultMcpFailureClassi
|
|
|
191
196
|
return { text: `Tool not found: ${name}`, isError: true };
|
|
192
197
|
};
|
|
193
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* The seams the library no longer defaults. The type already makes them required;
|
|
201
|
+
* this runs for callers with no types to check, so a plain-JS embedder of
|
|
202
|
+
* SmartServer is told at construction instead of starting without an LLM.
|
|
203
|
+
*/
|
|
204
|
+
const REQUIRED_CONSTRUCTION_SEAMS = [
|
|
205
|
+
'makeLlm',
|
|
206
|
+
'resolveEmbedder',
|
|
207
|
+
'makeRag',
|
|
208
|
+
];
|
|
209
|
+
function assertConstructionSeams(deps) {
|
|
210
|
+
const missing = REQUIRED_CONSTRUCTION_SEAMS.filter((k) => typeof deps?.[k] !== 'function');
|
|
211
|
+
if (missing.length === 0)
|
|
212
|
+
return;
|
|
213
|
+
throw new Error(`${missing.map((k) => `BuildAgentDeps.${k}`).join(', ')} ` +
|
|
214
|
+
`${missing.length > 1 ? 'are' : 'is'} required: the library constructs no ` +
|
|
215
|
+
'LLM, embedder or store from configuration, because doing so meant carrying ' +
|
|
216
|
+
'a secret through a framework config. Supply them from your composition root.');
|
|
217
|
+
}
|
|
194
218
|
export class SmartServer {
|
|
195
219
|
cfg;
|
|
196
220
|
noop = () => { };
|
|
@@ -238,7 +262,6 @@ export class SmartServer {
|
|
|
238
262
|
* `start()` so buildServerCtx can hand the raw role-LLM materials to the
|
|
239
263
|
* context factory (mirrors the inline DAG/linear resolution). */
|
|
240
264
|
_llmMap;
|
|
241
|
-
_pipelineFallback;
|
|
242
265
|
_mainTemp;
|
|
243
266
|
_roleLlm;
|
|
244
267
|
_requestLogger;
|
|
@@ -253,6 +276,21 @@ export class SmartServer {
|
|
|
253
276
|
* (the stepper catalog handle), which falls back to catalog order regardless.
|
|
254
277
|
*/
|
|
255
278
|
_toolsRag;
|
|
279
|
+
/**
|
|
280
|
+
* The providers every build of this server creates through, and the catalogs
|
|
281
|
+
* a session registry is hydrated from. One object, handed to every build:
|
|
282
|
+
* without it each session build replaced the registry's provider registry
|
|
283
|
+
* with a fresh empty one.
|
|
284
|
+
*/
|
|
285
|
+
_ragProviderRegistry = new SimpleRagProviderRegistry();
|
|
286
|
+
/**
|
|
287
|
+
* Catalog findings (rejected rows, skipped globals) already logged by one of
|
|
288
|
+
* this server's sessions, so the next session does not repeat them. One per
|
|
289
|
+
* server, never module-global: see SessionRagRegistryInput.reported.
|
|
290
|
+
*/
|
|
291
|
+
_reportedCatalogFindings = new Set();
|
|
292
|
+
/** The deployment's registry, whose globals every session registry holds. */
|
|
293
|
+
_globalRagRegistry;
|
|
256
294
|
/**
|
|
257
295
|
* MCP clients connected for the Stepper path from the YAML `mcp:` config
|
|
258
296
|
* block. These are connected ONCE in `start()` (lazily resolved by
|
|
@@ -335,12 +373,12 @@ export class SmartServer {
|
|
|
335
373
|
*/
|
|
336
374
|
_sessionMetaStore = new InMemorySessionMetaStore();
|
|
337
375
|
/**
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
* `
|
|
341
|
-
* `buildPipelineInstance`
|
|
376
|
+
* The ONE pipeline plugin this server runs: its factory was selected by
|
|
377
|
+
* `cfg.pipeline.name` (default 'flat') and called once in `_buildInfra`, with
|
|
378
|
+
* `cfg.pipeline.config` parsed by the server (built-ins) or by the plugin author's
|
|
379
|
+
* factory (dynamic). `buildPipelineInstance` only builds it per session.
|
|
342
380
|
*/
|
|
343
|
-
|
|
381
|
+
_pipelinePlugin;
|
|
344
382
|
/**
|
|
345
383
|
* Per-session `IPipelineInstance.close()` hooks, keyed by sessionId. Populated
|
|
346
384
|
* by `buildPipelineInstance` (via `buildSessionAgent`) and invoked from the
|
|
@@ -374,8 +412,13 @@ export class SmartServer {
|
|
|
374
412
|
* and `embedder` stay optional (present only when injected).
|
|
375
413
|
*/
|
|
376
414
|
_deps;
|
|
377
|
-
constructor(config, deps
|
|
415
|
+
constructor(config, deps) {
|
|
416
|
+
assertConstructionSeams(deps);
|
|
378
417
|
this.cfg = config;
|
|
418
|
+
assertRagConfigShape(config.rag, 'rag');
|
|
419
|
+
for (const sub of config.subAgentConfigs ?? []) {
|
|
420
|
+
assertRagConfigShape(sub.config.rag, `subagent '${sub.name}' rag`);
|
|
421
|
+
}
|
|
379
422
|
this._mcpSeamInjected =
|
|
380
423
|
deps.mcpClients !== undefined ||
|
|
381
424
|
deps.connectMcp !== undefined ||
|
|
@@ -398,8 +441,9 @@ export class SmartServer {
|
|
|
398
441
|
this._waitStrategy = deps.waitStrategy;
|
|
399
442
|
this._toolNamespace = deps.toolNamespace ?? defaultToolNamespace;
|
|
400
443
|
this._deps = {
|
|
401
|
-
makeLlm: deps.makeLlm
|
|
402
|
-
resolveEmbedder: deps.resolveEmbedder
|
|
444
|
+
makeLlm: deps.makeLlm,
|
|
445
|
+
resolveEmbedder: deps.resolveEmbedder,
|
|
446
|
+
makeRag: deps.makeRag,
|
|
403
447
|
prefetchEmbedderFactories: deps.prefetchEmbedderFactories ?? prefetchEmbedderFactories,
|
|
404
448
|
buildSkillHost: deps.buildSkillHost ?? buildSkillHostFromConfig,
|
|
405
449
|
connectMcp: deps.connectMcp ?? connectMcpClientsFromConfig,
|
|
@@ -452,26 +496,24 @@ export class SmartServer {
|
|
|
452
496
|
};
|
|
453
497
|
this._fileLogger = fileLogger;
|
|
454
498
|
// ---- Composition root: resolve config → interfaces --------------------
|
|
455
|
-
// LLM resolution — normalize the flat/map top-level `llm:` block.
|
|
456
|
-
// per-pipeline `pipeline.llm.*` override is gone; role LLMs derive entirely
|
|
457
|
-
// from the top-level map (resolveLlmConfig falls back to map.main), so the
|
|
458
|
-
// pipelineFallback chain is no longer fed a separate config — it stays
|
|
459
|
-
// undefined and the map.main fallback in resolveLlmConfig covers it.
|
|
499
|
+
// LLM resolution — normalize the flat/map top-level `llm:` block.
|
|
460
500
|
const llmMap = normalizeLlmConfig(this.cfg.llm);
|
|
461
|
-
const
|
|
462
|
-
const topMain = resolveLlmConfig(llmMap, 'main', pipelineFallback);
|
|
501
|
+
const topMain = resolveLlmConfig(llmMap, 'main');
|
|
463
502
|
const mainTemp = Number(topMain?.temperature ?? 0.7);
|
|
464
503
|
const mainLlm = topMain
|
|
465
504
|
? await this._deps.makeLlm({ ...topMain, temperature: mainTemp })
|
|
466
505
|
: (() => {
|
|
467
506
|
throw new Error('no LLM configured: provide top-level llm.main');
|
|
468
507
|
})();
|
|
508
|
+
const classifierEntry = resolveLlmConfigStrict(llmMap, 'classifier');
|
|
469
509
|
const classifierTemp = Number(topMain?.classifierTemperature ?? 0.1);
|
|
470
|
-
const classifierLlm =
|
|
471
|
-
? await this._deps.makeLlm(
|
|
472
|
-
:
|
|
473
|
-
|
|
474
|
-
|
|
510
|
+
const classifierLlm = classifierEntry
|
|
511
|
+
? await this._deps.makeLlm(classifierEntry)
|
|
512
|
+
: topMain
|
|
513
|
+
? await this._deps.makeLlm({ ...topMain, temperature: classifierTemp })
|
|
514
|
+
: (() => {
|
|
515
|
+
throw new Error('no LLM configured: provide top-level llm.main');
|
|
516
|
+
})();
|
|
475
517
|
// A 'helper' role LLM derives from the top-level `llm:` map when present
|
|
476
518
|
// (built only when an explicit map entry exists).
|
|
477
519
|
const helperCfg = resolveLlmConfigStrict(llmMap, 'helper');
|
|
@@ -485,16 +527,17 @@ export class SmartServer {
|
|
|
485
527
|
this._classifierLlm = classifierLlm;
|
|
486
528
|
this._helperLlm = helperLlm;
|
|
487
529
|
this._llmMap = llmMap;
|
|
488
|
-
this._pipelineFallback = pipelineFallback;
|
|
489
530
|
this._mainTemp = mainTemp;
|
|
490
531
|
this._roleLlm = new RoleLlmResolver({
|
|
491
532
|
getMain: () => this._mainLlm,
|
|
492
533
|
getHelper: () => this._helperLlm,
|
|
493
534
|
getClassifier: () => this._classifierLlm,
|
|
494
535
|
getLlmMap: () => this._llmMap,
|
|
495
|
-
|
|
496
|
-
makeLlm: (lc) => this._deps.makeLlm(lc),
|
|
536
|
+
build: (entry) => this._deps.makeLlm(entry),
|
|
497
537
|
});
|
|
538
|
+
// The programmatic subAgentConfigs path never passed the YAML check, so a
|
|
539
|
+
// worker's named keys are checked here too (§4.6.7): startup fails loudly.
|
|
540
|
+
assertWorkerLlmConfig(this.cfg.subAgentConfigs, llmMap);
|
|
498
541
|
// ---- Plugin loader -------------------------------------------------------
|
|
499
542
|
const pluginLoader = this.cfg.pluginLoader ??
|
|
500
543
|
(() => {
|
|
@@ -542,34 +585,53 @@ export class SmartServer {
|
|
|
542
585
|
const registered = mergePluginExports(plugins, mod, spec);
|
|
543
586
|
log({ event: 'plugin_specifier_loaded', spec, registered });
|
|
544
587
|
}
|
|
545
|
-
// ---- Pipeline-plugin registry (
|
|
546
|
-
//
|
|
547
|
-
//
|
|
548
|
-
//
|
|
549
|
-
//
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
new FlatPipelinePlugin(),
|
|
553
|
-
new LinearPipelinePlugin(),
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
588
|
+
// ---- Pipeline-plugin registry: factories (§4.6.7) -------------------
|
|
589
|
+
// Built-ins are server code — parse, validate, construct with typed settings.
|
|
590
|
+
// A dynamic instance export is registered as a factory that ignores its
|
|
591
|
+
// section; a dynamic factory is the plugin author's parser. Only the selected
|
|
592
|
+
// entry is ever called, once, below.
|
|
593
|
+
const warn = (m) => this.warn(m);
|
|
594
|
+
const pipelineRegistry = new Map([
|
|
595
|
+
['flat', () => new FlatPipelinePlugin()],
|
|
596
|
+
['linear', (s) => new LinearPipelinePlugin(parseLinearSettings(s))],
|
|
597
|
+
[
|
|
598
|
+
'dag',
|
|
599
|
+
(s) => {
|
|
600
|
+
const settings = parseDagSettings(s, warn);
|
|
601
|
+
assertNamedLlmKeys(dagNamedLlmKeys(settings), this._llmMap, "pipeline 'dag'");
|
|
602
|
+
return new DagPipelinePlugin(settings);
|
|
603
|
+
},
|
|
604
|
+
],
|
|
605
|
+
['stepper', (s) => new StepperPipelinePlugin(parseStepperSettings(s))],
|
|
606
|
+
[
|
|
607
|
+
'controller',
|
|
608
|
+
(s) => new ControllerPipelinePlugin('controller', 'smart-executor', parseControllerSettings(s, llmKeySet(this._llmMap))),
|
|
609
|
+
],
|
|
610
|
+
[
|
|
611
|
+
'controller-weak',
|
|
612
|
+
(s) => new ControllerPipelinePlugin('controller-weak', 'weak-executor', parseControllerSettings(s, llmKeySet(this._llmMap))),
|
|
613
|
+
],
|
|
614
|
+
]);
|
|
615
|
+
const pipelineSources = new Map([...pipelineRegistry.keys()].map((k) => [k, 'built-in']));
|
|
616
|
+
const registerPipeline = (name, factory) => {
|
|
617
|
+
const source = plugins.pipelinePluginSources.get(name) ?? 'unknown';
|
|
562
618
|
if (pipelineRegistry.has(name)) {
|
|
563
619
|
throw new Error(`pipeline plugin name collision: '${name}' is already registered ` +
|
|
564
|
-
|
|
620
|
+
`(built-in or another plugin) — '${source}' against '${pipelineSources.get(name)}'`);
|
|
565
621
|
}
|
|
566
|
-
pipelineRegistry.set(name,
|
|
622
|
+
pipelineRegistry.set(name, factory);
|
|
623
|
+
pipelineSources.set(name, source);
|
|
624
|
+
};
|
|
625
|
+
for (const [name, plugin] of plugins.pipelinePlugins)
|
|
626
|
+
registerPipeline(name, () => plugin);
|
|
627
|
+
for (const [name, factory] of plugins.pipelinePluginFactories ?? []) {
|
|
628
|
+
registerPipeline(name, factory);
|
|
567
629
|
}
|
|
568
|
-
this._pipelineRegistry = pipelineRegistry;
|
|
569
630
|
log({
|
|
570
631
|
event: 'pipeline_registry_loaded',
|
|
571
632
|
pipelines: [...pipelineRegistry.keys()],
|
|
572
633
|
});
|
|
634
|
+
this._pipelinePlugin = selectPipelinePlugin(pipelineRegistry, pipelineSources, this.cfg.pipeline?.name ?? 'flat', this.cfg.pipeline?.config ?? {});
|
|
573
635
|
// Merge plugin embedder factories with config-provided ones
|
|
574
636
|
const mergedEmbedderFactories = {
|
|
575
637
|
...plugins.embedderFactories,
|
|
@@ -588,7 +650,7 @@ export class SmartServer {
|
|
|
588
650
|
});
|
|
589
651
|
// Resolve the embedder ONCE so the same instance feeds both makeRag and the
|
|
590
652
|
// subagent context-builder's toolSource (#137). See resolve-agent-embedder.
|
|
591
|
-
const resolvedEmbedder = await resolveAgentEmbedder(this.cfg.rag, this._deps.embedder ?? this.cfg.embedder, mergedEmbedderFactories, this._fileLogger);
|
|
653
|
+
const resolvedEmbedder = await resolveAgentEmbedder(this.cfg.rag, this._deps.embedder ?? this.cfg.embedder, this._deps.resolveEmbedder, mergedEmbedderFactories, this._fileLogger);
|
|
592
654
|
// Hold the resolved embedder so buildServerCtx can thread it onto every
|
|
593
655
|
// pipeline context (the controller pipeline needs it for target-state).
|
|
594
656
|
this._resolvedEmbedder = resolvedEmbedder;
|
|
@@ -607,9 +669,10 @@ export class SmartServer {
|
|
|
607
669
|
// Prefetch the named embedder factory only when we will actually build a
|
|
608
670
|
// dedicated one (the agent embedder is already prefetched + wrapped).
|
|
609
671
|
if (!reuseAgentEmbedder) {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
672
|
+
const section = embedderSectionFor(skillCfg.embedder?.provider);
|
|
673
|
+
if (section.factory === undefined) {
|
|
674
|
+
await this._deps.prefetchEmbedderFactories([section.provider]);
|
|
675
|
+
}
|
|
613
676
|
}
|
|
614
677
|
// Build → load → validate as one fail-fast unit. If ANY step throws, the
|
|
615
678
|
// captured pg pools are ended INSIDE initSkillHost (the later closeFns
|
|
@@ -620,9 +683,7 @@ export class SmartServer {
|
|
|
620
683
|
: () => this._deps.buildSkillHost(skillCfg, {
|
|
621
684
|
resolveEmbedder: (ec) => reuseAgentEmbedder
|
|
622
685
|
? (injectedEmbedder ?? resolvedEmbedder)
|
|
623
|
-
: this._deps.resolveEmbedder(ec, {
|
|
624
|
-
extraFactories: mergedEmbedderFactories,
|
|
625
|
-
}),
|
|
686
|
+
: this._deps.resolveEmbedder(embedderSectionFor(ec.embedder, ec.model), { extraFactories: mergedEmbedderFactories }),
|
|
626
687
|
// Real pg `Pool` provider for a `postgres` catalog (qdrant
|
|
627
688
|
// deployment). Lazily imports `pg` and ensures the catalog table
|
|
628
689
|
// exists on first use; pass the configured table so the DDL targets
|
|
@@ -654,12 +715,12 @@ export class SmartServer {
|
|
|
654
715
|
let historyRag;
|
|
655
716
|
const ragCollections = [];
|
|
656
717
|
if (this.cfg.rag) {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
toolsRag = await
|
|
662
|
-
historyRag = await
|
|
718
|
+
// The embedder was resolved through the seam above; the store is built
|
|
719
|
+
// through its own. Two calls, two stores — the history store never shared
|
|
720
|
+
// the tools store's instance.
|
|
721
|
+
const input = toMakeRagInput(this.cfg.rag.store, resolvedEmbedder, 'rag');
|
|
722
|
+
toolsRag = await this._deps.makeRag(input);
|
|
723
|
+
historyRag = await this._deps.makeRag(input);
|
|
663
724
|
}
|
|
664
725
|
// Capture the tools store for the flat/smart pipeline's ToolSelectHandler
|
|
665
726
|
// (and white-box vectorization assertions). See field doc.
|
|
@@ -810,6 +871,15 @@ export class SmartServer {
|
|
|
810
871
|
const agentHandle = await builder.build();
|
|
811
872
|
const { agent: smartAgent, chat, streamChat, close: closeAgent, circuitBreakers, ragStores, modelProvider, } = agentHandle;
|
|
812
873
|
const { ragRegistry: globalRagRegistry, mcpClients: globalMcpClients } = agentHandle;
|
|
874
|
+
this._globalRagRegistry = globalRagRegistry;
|
|
875
|
+
// Two limits of this server, stated rather than fixed (§6.4): it registers
|
|
876
|
+
// no RAG providers, so no session registry has a catalog to hydrate from —
|
|
877
|
+
// each holds only the deployment's globals; and its sessions carry a
|
|
878
|
+
// sessionId and no userId (llm-agent-libs session-registry.ts builds them
|
|
879
|
+
// from { sessionId }), so user collections are neither hydrated nor
|
|
880
|
+
// creatable through it. Not logged: in today's default deployment it would
|
|
881
|
+
// fire at every start, and an expected warning trains readers to skip the
|
|
882
|
+
// real ones — the limits are stated here, in the CHANGELOG and in the docs.
|
|
813
883
|
// ---- Authoritative namespaced snapshot — yaml-builder path (#244) --------
|
|
814
884
|
// The startup builder computes `namespacedTools`/`toolProvenance` (+ the
|
|
815
885
|
// descriptors backing them) ONLY when it owns the connection itself (the
|
|
@@ -903,7 +973,13 @@ export class SmartServer {
|
|
|
903
973
|
// `this._toolsRag` === the `toolsRag` local captured in start(); reference
|
|
904
974
|
// the field as the single source of truth for the tools store.
|
|
905
975
|
toolsRag: this._toolsRag,
|
|
906
|
-
|
|
976
|
+
// A registry per session, seeded with the deployment's globals and
|
|
977
|
+
// hydrated for its identity (§6.4). Never the shared one: collections are
|
|
978
|
+
// addressed by name, so sharing it would put every session's collections
|
|
979
|
+
// in every session's address space. Hydration finds nothing until a
|
|
980
|
+
// provider is registered, and no user collection while sessions carry no
|
|
981
|
+
// userId — see the limits stated above.
|
|
982
|
+
ragRegistryFactory: (identity) => this._sessionRagRegistry(identity),
|
|
907
983
|
buildAgent: (parts) => this.buildSessionAgent(parts),
|
|
908
984
|
logger: fileLogger,
|
|
909
985
|
// Per-session pipeline teardown: run the IPipelineInstance.close captured
|
|
@@ -1129,18 +1205,16 @@ export class SmartServer {
|
|
|
1129
1205
|
* always undefined here.
|
|
1130
1206
|
*/
|
|
1131
1207
|
async buildSubAgent(name, subCfg, parentLogger, embedderFactories, injected) {
|
|
1132
|
-
//
|
|
1133
|
-
//
|
|
1134
|
-
//
|
|
1135
|
-
|
|
1136
|
-
const
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
// The subagent's helper role derives from its own top-level `llm:` map.
|
|
1143
|
-
const subHelperCfg = resolveLlmConfigStrict(subLlmMap, 'helper');
|
|
1208
|
+
// A worker's three LLM slots come from the SAME resolver as the pipeline's
|
|
1209
|
+
// (§4.6.7): a named key resolves strictly, an omitted role as that name
|
|
1210
|
+
// does for the pipeline. Instances are held by the resolver, so nothing is
|
|
1211
|
+
// built per session and a PUT /v1/config swap reaches workers too.
|
|
1212
|
+
const keys = parseWorkerLlm(name, subCfg.llm);
|
|
1213
|
+
const [mainLlm, classifierLlm, helperLlm] = await Promise.all([
|
|
1214
|
+
this.resolveWorkerRoleLlm(keys.main, 'main'),
|
|
1215
|
+
this.resolveWorkerRoleLlm(keys.classifier, 'classifier'),
|
|
1216
|
+
this.resolveWorkerRoleLlm(keys.helper, 'helper'),
|
|
1217
|
+
]);
|
|
1144
1218
|
// LLM/embedder clients: when the per-session re-wire injected them, use
|
|
1145
1219
|
// those cached instances by reference (NEVER reconstruct). Otherwise (the
|
|
1146
1220
|
// primary build()), build-once via the cache so the global agent build
|
|
@@ -1148,58 +1222,24 @@ export class SmartServer {
|
|
|
1148
1222
|
// instances.
|
|
1149
1223
|
// Note: a per-worker embedder slot is carried in WorkerLlmSet and the
|
|
1150
1224
|
// injected record for forward-compat with Task A8/A10 per-session wiring.
|
|
1151
|
-
//
|
|
1152
|
-
//
|
|
1153
|
-
//
|
|
1154
|
-
// Resolve (build-once or load from cache) the worker's own LLMs +
|
|
1225
|
+
// The worker's embedder is resolved through `BuildAgentDeps.resolveEmbedder`
|
|
1226
|
+
// inside the factories below (`_workerRagInput`), not separately here.
|
|
1227
|
+
// Resolve (build-once or load from cache) the worker's own
|
|
1155
1228
|
// toolsRag/historyRag/mcpClients. The cache is keyed by worker name; the
|
|
1156
1229
|
// primary build() populates it (no `injected` arg), and per-session
|
|
1157
1230
|
// re-wires (`injected` set) read from it via the same call below — the
|
|
1158
1231
|
// cache hit short-circuits all factories. This keeps the worker's
|
|
1159
1232
|
// declared RAG/MCP intact across per-session re-wires (review HIGH #1).
|
|
1160
|
-
const subFlatLlm = subLlmMain;
|
|
1161
|
-
const mainTemp = Number(subFlatLlm?.temperature ?? 0.7);
|
|
1162
|
-
const classifierTemp = Number(subFlatLlm?.classifierTemperature ?? 0.1);
|
|
1163
1233
|
const cached = await resolveWorkerLlmSet({
|
|
1164
1234
|
name,
|
|
1165
1235
|
cache: this._workers.cache,
|
|
1166
|
-
// Preserve the existing makeLlm derivation exactly.
|
|
1167
|
-
makeMain: () => makeLlm({
|
|
1168
|
-
// ?? 'deepseek' is a TS type-narrowing net only; the config
|
|
1169
|
-
// validator rejects a missing flat-schema provider before
|
|
1170
|
-
// this runs.
|
|
1171
|
-
provider: subFlatLlm?.provider ?? 'deepseek',
|
|
1172
|
-
apiKey: subFlatLlm?.apiKey ?? '',
|
|
1173
|
-
baseURL: subFlatLlm?.url,
|
|
1174
|
-
model: subFlatLlm?.model,
|
|
1175
|
-
}, mainTemp),
|
|
1176
|
-
makeClassifier: () => makeLlm({
|
|
1177
|
-
provider: subFlatLlm?.provider ?? 'deepseek',
|
|
1178
|
-
apiKey: subFlatLlm?.apiKey ?? '',
|
|
1179
|
-
baseURL: subFlatLlm?.url,
|
|
1180
|
-
model: subFlatLlm?.model,
|
|
1181
|
-
}, classifierTemp),
|
|
1182
|
-
makeHelper: subHelperCfg
|
|
1183
|
-
? ((h) => () => makeLlm({
|
|
1184
|
-
provider: h.provider ?? 'deepseek',
|
|
1185
|
-
apiKey: h.apiKey,
|
|
1186
|
-
baseURL: h.url,
|
|
1187
|
-
model: h.model,
|
|
1188
|
-
}, Number(h.temperature ?? 0.1)))(subHelperCfg)
|
|
1189
|
-
: undefined,
|
|
1190
1236
|
// Worker-OWN tools RAG (from subCfg.rag, if declared). Built once;
|
|
1191
1237
|
// re-wired per-session by reference — never re-vectorized.
|
|
1192
1238
|
makeToolsRag: subCfg.rag
|
|
1193
|
-
? () => makeRag(subCfg.rag,
|
|
1194
|
-
injectedEmbedder: subCfg.embedder,
|
|
1195
|
-
extraFactories: embedderFactories,
|
|
1196
|
-
})
|
|
1239
|
+
? async () => this._deps.makeRag(await this._workerRagInput(name, subCfg.rag, subCfg.embedder, embedderFactories))
|
|
1197
1240
|
: undefined,
|
|
1198
1241
|
makeHistoryRag: subCfg.rag
|
|
1199
|
-
? () => makeRag(
|
|
1200
|
-
injectedEmbedder: subCfg.embedder,
|
|
1201
|
-
extraFactories: embedderFactories,
|
|
1202
|
-
})
|
|
1242
|
+
? async () => this._deps.makeRag(await this._workerRagInput(name, subCfg.rag, subCfg.embedder, embedderFactories))
|
|
1203
1243
|
: undefined,
|
|
1204
1244
|
// Worker-OWN MCP clients. DI list (subCfg.mcpClients) wins; otherwise
|
|
1205
1245
|
// SmartAgentBuilder's own MCP-connect path handles `subCfg.mcp` — we
|
|
@@ -1209,9 +1249,6 @@ export class SmartServer {
|
|
|
1209
1249
|
? async () => subCfg.mcpClients
|
|
1210
1250
|
: undefined,
|
|
1211
1251
|
});
|
|
1212
|
-
const mainLlm = cached.mainLlm;
|
|
1213
|
-
const classifierLlm = cached.classifierLlm;
|
|
1214
|
-
const helperLlm = cached.helperLlm;
|
|
1215
1252
|
let subBuilder = new SmartAgentBuilder({
|
|
1216
1253
|
mcp: subCfg.mcp,
|
|
1217
1254
|
agent: subCfg.agent,
|
|
@@ -1222,9 +1259,7 @@ export class SmartServer {
|
|
|
1222
1259
|
.withClassifierLlm(classifierLlm)
|
|
1223
1260
|
.withLogger(parentLogger)
|
|
1224
1261
|
.withMode(subCfg.mode ?? 'smart');
|
|
1225
|
-
|
|
1226
|
-
subBuilder = subBuilder.withHelperLlm(helperLlm);
|
|
1227
|
-
}
|
|
1262
|
+
subBuilder = subBuilder.withHelperLlm(helperLlm);
|
|
1228
1263
|
// SHARE the parent RAG registry + session logger when injected (per-session
|
|
1229
1264
|
// worker re-wire). The per-call scope filter isolates by ctx.sessionId.
|
|
1230
1265
|
const sharedReg = resolveSubAgentRagRegistry({
|
|
@@ -1280,24 +1315,31 @@ export class SmartServer {
|
|
|
1280
1315
|
}
|
|
1281
1316
|
// -- Pipeline-context dep sources (promoted from the inline coordinator-gate
|
|
1282
1317
|
// closures; consumed by buildServerCtx, which later tasks call) ----------
|
|
1283
|
-
/**
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
return this._deps.makeLlm(lc);
|
|
1288
|
-
}
|
|
1289
|
-
/** The real `makeLlm`-backed construction (the seam's default). */
|
|
1290
|
-
_makeLlmDefault(lc) {
|
|
1291
|
-
return makeDefaultRoleLlm(lc, this._mainTemp);
|
|
1318
|
+
/** A worker's own store input: its embedder through the seam, then paired. */
|
|
1319
|
+
async _workerRagInput(name, rag, diEmbedder, extraFactories) {
|
|
1320
|
+
const embedder = await resolveAgentEmbedder(rag, diEmbedder, this._deps.resolveEmbedder, extraFactories, this._fileLogger);
|
|
1321
|
+
return toMakeRagInput(rag.store, embedder, `subagent '${name}' rag`);
|
|
1292
1322
|
}
|
|
1293
|
-
/**
|
|
1294
|
-
* 'main' returns the captured mainLlm; 'helper'/'classifier' return the
|
|
1295
|
-
* prebuilt instances when present; otherwise the map/fallback config is built. */
|
|
1323
|
+
/** `ctx.resolveLlm(role)` — the role's default, through the held role map. */
|
|
1296
1324
|
async resolveRoleLlm(role) {
|
|
1325
|
+
return this.roleLlm().resolve(role);
|
|
1326
|
+
}
|
|
1327
|
+
/** `ctx.resolveNamedLlm(key)` — strict: an `llm:` entry of exactly that name. */
|
|
1328
|
+
async resolveNamedRoleLlm(key) {
|
|
1329
|
+
return this.roleLlm().resolveNamed(key);
|
|
1330
|
+
}
|
|
1331
|
+
/** A worker role's LLM: its named key strictly, else the role's own name —
|
|
1332
|
+
* the same resolver the pipeline reads, so instances are shared (§4.6.7). */
|
|
1333
|
+
async resolveWorkerRoleLlm(key, role) {
|
|
1334
|
+
return key !== undefined
|
|
1335
|
+
? this.roleLlm().resolveNamed(key)
|
|
1336
|
+
: this.roleLlm().resolve(role);
|
|
1337
|
+
}
|
|
1338
|
+
roleLlm() {
|
|
1297
1339
|
if (!this._roleLlm) {
|
|
1298
|
-
throw new Error('
|
|
1340
|
+
throw new Error('role LLM lookup invoked before _buildInfra built the resolver');
|
|
1299
1341
|
}
|
|
1300
|
-
return this._roleLlm
|
|
1342
|
+
return this._roleLlm;
|
|
1301
1343
|
}
|
|
1302
1344
|
/**
|
|
1303
1345
|
* Session-scoped knowledge RAG over the shared knowledge backend (built
|
|
@@ -1544,22 +1586,13 @@ export class SmartServer {
|
|
|
1544
1586
|
: undefined);
|
|
1545
1587
|
}
|
|
1546
1588
|
/**
|
|
1547
|
-
* Build the per-session pipeline instance from the
|
|
1548
|
-
*
|
|
1549
|
-
*
|
|
1550
|
-
*
|
|
1551
|
-
* `agent`; `buildSessionAgent` registers `close` into the session-dispose path.
|
|
1589
|
+
* Build the per-session pipeline instance from the plugin selected at startup,
|
|
1590
|
+
* against a session-scoped pipeline context. The returned `IPipelineInstance`
|
|
1591
|
+
* carries `{ agent, close }`; `buildSessionAgent` registers `close` into the
|
|
1592
|
+
* session-dispose path.
|
|
1552
1593
|
*/
|
|
1553
1594
|
async buildPipelineInstance(scope) {
|
|
1554
|
-
|
|
1555
|
-
const plugin = this._pipelineRegistry.get(name);
|
|
1556
|
-
if (!plugin) {
|
|
1557
|
-
throw new Error(`unknown pipeline '${name}'; available: ${[
|
|
1558
|
-
...this._pipelineRegistry.keys(),
|
|
1559
|
-
].join(', ')}`);
|
|
1560
|
-
}
|
|
1561
|
-
const cfg = plugin.parseConfig(this.cfg.pipeline?.config ?? {});
|
|
1562
|
-
return plugin.build(cfg, await this.buildServerCtx(scope));
|
|
1595
|
+
return this._pipelinePlugin.build(await this.buildServerCtx(scope));
|
|
1563
1596
|
}
|
|
1564
1597
|
warn(msg) {
|
|
1565
1598
|
(this.cfg.log ?? this.noop)({ event: 'config_warning', message: msg });
|
|
@@ -1636,6 +1669,7 @@ export class SmartServer {
|
|
|
1636
1669
|
: undefined;
|
|
1637
1670
|
return createServerPipelineContext({
|
|
1638
1671
|
resolveLlm: (role) => this.resolveRoleLlm(role),
|
|
1672
|
+
resolveNamedLlm: (key) => this.resolveNamedRoleLlm(key),
|
|
1639
1673
|
knowledgeRagFor: (sid) => this.knowledgeRagFor(sid),
|
|
1640
1674
|
// Durable backend + resolved embedder shared with every pipeline; the
|
|
1641
1675
|
// controller pipeline consumes both (session-bundle persistence +
|
|
@@ -1699,9 +1733,6 @@ export class SmartServer {
|
|
|
1699
1733
|
logger: this._fileLogger,
|
|
1700
1734
|
logLlmCall: (e) => requestLogger?.logLlmCall?.(e),
|
|
1701
1735
|
createAgentBuilder: () => this.buildBaseBuilder(this.partsToBaseInput(scope.parts, workerRegistry, extras)),
|
|
1702
|
-
makeLlm: (c) => this._makeLlm(c),
|
|
1703
|
-
llmMap: this._llmMap,
|
|
1704
|
-
pipelineFallback: this._pipelineFallback,
|
|
1705
1736
|
mainLlm: this._mainLlm,
|
|
1706
1737
|
helperLlm: this._helperLlm,
|
|
1707
1738
|
mainTemp: this._mainTemp ?? 0.7,
|
|
@@ -1756,6 +1787,10 @@ export class SmartServer {
|
|
|
1756
1787
|
if (parts.ragRegistry) {
|
|
1757
1788
|
builder = builder.setRagRegistry(parts.ragRegistry);
|
|
1758
1789
|
}
|
|
1790
|
+
// The server's one provider registry: without it build() substitutes an
|
|
1791
|
+
// empty one and sets it on the session's registry, and an adopted
|
|
1792
|
+
// collection's delete then reaches no provider.
|
|
1793
|
+
builder = builder.setRagProviderRegistry(this._ragProviderRegistry);
|
|
1759
1794
|
if (parts.requestLogger) {
|
|
1760
1795
|
builder = builder.withRequestLogger(parts.requestLogger);
|
|
1761
1796
|
}
|
|
@@ -1836,6 +1871,19 @@ export class SmartServer {
|
|
|
1836
1871
|
(() => new WindowContextStrategy()));
|
|
1837
1872
|
return builder;
|
|
1838
1873
|
}
|
|
1874
|
+
/** The registry one session owns; see buildSessionRagRegistry. */
|
|
1875
|
+
_sessionRagRegistry(identity) {
|
|
1876
|
+
if (!this._globalRagRegistry) {
|
|
1877
|
+
throw new Error('A session RAG registry was requested before the server infra was built');
|
|
1878
|
+
}
|
|
1879
|
+
return buildSessionRagRegistry({
|
|
1880
|
+
identity,
|
|
1881
|
+
globals: this._globalRagRegistry,
|
|
1882
|
+
providers: this._ragProviderRegistry,
|
|
1883
|
+
logger: this._fileLogger,
|
|
1884
|
+
reported: this._reportedCatalogFindings,
|
|
1885
|
+
});
|
|
1886
|
+
}
|
|
1839
1887
|
/**
|
|
1840
1888
|
* Builds the per-session SmartAgent by routing through the selected pipeline
|
|
1841
1889
|
* plugin (`buildPipelineInstance`). The pipeline owns coordinator wiring; the
|
|
@@ -2081,6 +2129,7 @@ export class SmartServer {
|
|
|
2081
2129
|
_configUpdateTarget() {
|
|
2082
2130
|
return {
|
|
2083
2131
|
modelResolver: this.cfg.modelResolver,
|
|
2132
|
+
skipModelValidation: this.cfg.skipModelValidation === true,
|
|
2084
2133
|
setMainLlm: (llm) => {
|
|
2085
2134
|
this._mainLlm = llm;
|
|
2086
2135
|
},
|