@mcp-abap-adt/llm-agent-server-libs 19.2.0 → 20.4.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 +57 -0
- package/dist/builders/controller-skill-pipeline-builder.d.ts.map +1 -0
- package/dist/builders/controller-skill-pipeline-builder.js +175 -0
- package/dist/builders/controller-skill-pipeline-builder.js.map +1 -0
- package/dist/factories/controller-factory.d.ts +2 -2
- package/dist/factories/controller-factory.d.ts.map +1 -1
- package/dist/factories/controller-factory.js +2 -1
- 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 +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/pipelines/controller.d.ts +4 -2
- package/dist/pipelines/controller.d.ts.map +1 -1
- package/dist/pipelines/controller.js +33 -8
- package/dist/pipelines/controller.js.map +1 -1
- package/dist/pipelines/coordinator-resolvers.d.ts +68 -0
- package/dist/pipelines/coordinator-resolvers.d.ts.map +1 -0
- package/dist/pipelines/coordinator-resolvers.js +97 -0
- package/dist/pipelines/coordinator-resolvers.js.map +1 -0
- package/dist/pipelines/dag.d.ts +2 -2
- package/dist/pipelines/dag.js +2 -2
- package/dist/pipelines/parsers.d.ts +1 -1
- package/dist/pipelines/parsers.d.ts.map +1 -1
- package/dist/pipelines/parsers.js +5 -4
- package/dist/pipelines/parsers.js.map +1 -1
- package/dist/pipelines/register-skill-sources.d.ts.map +1 -1
- package/dist/pipelines/register-skill-sources.js +5 -0
- package/dist/pipelines/register-skill-sources.js.map +1 -1
- package/dist/pipelines/stepper.d.ts +2 -2
- package/dist/pipelines/stepper.js +2 -2
- package/dist/smart-agent/build-stepper-root.d.ts +3 -2
- package/dist/smart-agent/build-stepper-root.d.ts.map +1 -1
- package/dist/smart-agent/build-stepper-root.js +2 -1
- package/dist/smart-agent/build-stepper-root.js.map +1 -1
- package/dist/smart-agent/config-reload-watcher.d.ts +30 -0
- package/dist/smart-agent/config-reload-watcher.d.ts.map +1 -0
- package/dist/smart-agent/config-reload-watcher.js +101 -0
- package/dist/smart-agent/config-reload-watcher.js.map +1 -0
- package/dist/smart-agent/config-validator.d.ts +21 -0
- package/dist/smart-agent/config-validator.d.ts.map +1 -0
- package/dist/smart-agent/config-validator.js +196 -0
- package/dist/smart-agent/config-validator.js.map +1 -0
- package/dist/smart-agent/config.d.ts +16 -254
- package/dist/smart-agent/config.d.ts.map +1 -1
- package/dist/smart-agent/config.js +17 -904
- package/dist/smart-agent/config.js.map +1 -1
- package/dist/smart-agent/controller/board.d.ts +6 -3
- package/dist/smart-agent/controller/board.d.ts.map +1 -1
- package/dist/smart-agent/controller/board.js +21 -0
- package/dist/smart-agent/controller/board.js.map +1 -1
- package/dist/smart-agent/controller/controller-coordinator-handler.d.ts +16 -50
- package/dist/smart-agent/controller/controller-coordinator-handler.d.ts.map +1 -1
- package/dist/smart-agent/controller/controller-coordinator-handler.js +83 -371
- package/dist/smart-agent/controller/controller-coordinator-handler.js.map +1 -1
- package/dist/smart-agent/controller/finalizer.d.ts +5 -0
- package/dist/smart-agent/controller/finalizer.d.ts.map +1 -1
- package/dist/smart-agent/controller/finalizer.js +12 -5
- package/dist/smart-agent/controller/finalizer.js.map +1 -1
- package/dist/smart-agent/controller/parser.d.ts +11 -0
- package/dist/smart-agent/controller/parser.d.ts.map +1 -0
- package/dist/smart-agent/controller/parser.js +77 -0
- package/dist/smart-agent/controller/parser.js.map +1 -0
- package/dist/smart-agent/controller/planner.d.ts +20 -16
- package/dist/smart-agent/controller/planner.d.ts.map +1 -1
- package/dist/smart-agent/controller/planner.js +58 -64
- package/dist/smart-agent/controller/planner.js.map +1 -1
- package/dist/smart-agent/controller/recall.d.ts +48 -0
- package/dist/smart-agent/controller/recall.d.ts.map +1 -0
- package/dist/smart-agent/controller/recall.js +196 -0
- package/dist/smart-agent/controller/recall.js.map +1 -0
- package/dist/smart-agent/controller/reviewer.d.ts.map +1 -1
- package/dist/smart-agent/controller/reviewer.js +1 -1
- package/dist/smart-agent/controller/reviewer.js.map +1 -1
- package/dist/smart-agent/controller/types.d.ts +8 -9
- package/dist/smart-agent/controller/types.d.ts.map +1 -1
- package/dist/smart-agent/controller/usage-logging.d.ts +16 -0
- package/dist/smart-agent/controller/usage-logging.d.ts.map +1 -0
- package/dist/smart-agent/controller/usage-logging.js +39 -0
- package/dist/smart-agent/controller/usage-logging.js.map +1 -0
- package/dist/smart-agent/http/adapter-route-handler.d.ts +13 -0
- package/dist/smart-agent/http/adapter-route-handler.d.ts.map +1 -0
- package/dist/smart-agent/http/adapter-route-handler.js +76 -0
- package/dist/smart-agent/http/adapter-route-handler.js.map +1 -0
- package/dist/smart-agent/http/chat-route-handler.d.ts +15 -0
- package/dist/smart-agent/http/chat-route-handler.d.ts.map +1 -0
- package/dist/smart-agent/http/chat-route-handler.js +327 -0
- package/dist/smart-agent/http/chat-route-handler.js.map +1 -0
- package/dist/smart-agent/http/config-route-handler.d.ts +21 -0
- package/dist/smart-agent/http/config-route-handler.d.ts.map +1 -0
- package/dist/smart-agent/http/config-route-handler.js +149 -0
- package/dist/smart-agent/http/config-route-handler.js.map +1 -0
- package/dist/smart-agent/http/health-route-handler.d.ts +12 -0
- package/dist/smart-agent/http/health-route-handler.d.ts.map +1 -0
- package/dist/smart-agent/http/health-route-handler.js +19 -0
- package/dist/smart-agent/http/health-route-handler.js.map +1 -0
- package/dist/smart-agent/http/models-route-handler.d.ts +17 -0
- package/dist/smart-agent/http/models-route-handler.d.ts.map +1 -0
- package/dist/smart-agent/http/models-route-handler.js +65 -0
- package/dist/smart-agent/http/models-route-handler.js.map +1 -0
- package/dist/smart-agent/http/response-helpers.d.ts +31 -0
- package/dist/smart-agent/http/response-helpers.d.ts.map +1 -0
- package/dist/smart-agent/http/response-helpers.js +59 -0
- package/dist/smart-agent/http/response-helpers.js.map +1 -0
- package/dist/smart-agent/http/route-table.d.ts +44 -0
- package/dist/smart-agent/http/route-table.d.ts.map +1 -0
- package/dist/smart-agent/http/route-table.js +35 -0
- package/dist/smart-agent/http/route-table.js.map +1 -0
- package/dist/smart-agent/http/session-cookie.d.ts +10 -0
- package/dist/smart-agent/http/session-cookie.d.ts.map +1 -0
- package/dist/smart-agent/http/session-cookie.js +16 -0
- package/dist/smart-agent/http/session-cookie.js.map +1 -0
- package/dist/smart-agent/http/sessions-route-handler.d.ts +8 -0
- package/dist/smart-agent/http/sessions-route-handler.d.ts.map +1 -0
- package/dist/smart-agent/http/sessions-route-handler.js +54 -0
- package/dist/smart-agent/http/sessions-route-handler.js.map +1 -0
- package/dist/smart-agent/http/usage-route-handler.d.ts +12 -0
- package/dist/smart-agent/http/usage-route-handler.d.ts.map +1 -0
- package/dist/smart-agent/http/usage-route-handler.js +28 -0
- package/dist/smart-agent/http/usage-route-handler.js.map +1 -0
- package/dist/smart-agent/knowledge/make-knowledge-backend.d.ts +13 -0
- package/dist/smart-agent/knowledge/make-knowledge-backend.d.ts.map +1 -0
- package/dist/smart-agent/knowledge/make-knowledge-backend.js +18 -0
- package/dist/smart-agent/knowledge/make-knowledge-backend.js.map +1 -0
- package/dist/smart-agent/llm/role-llm-resolver.d.ts +30 -0
- package/dist/smart-agent/llm/role-llm-resolver.d.ts.map +1 -0
- package/dist/smart-agent/llm/role-llm-resolver.js +44 -0
- package/dist/smart-agent/llm/role-llm-resolver.js.map +1 -0
- package/dist/smart-agent/llm-config-map.d.ts +38 -0
- package/dist/smart-agent/llm-config-map.d.ts.map +1 -0
- package/dist/smart-agent/llm-config-map.js +75 -0
- package/dist/smart-agent/llm-config-map.js.map +1 -0
- package/dist/smart-agent/mcp-readiness-monitor.d.ts +38 -0
- package/dist/smart-agent/mcp-readiness-monitor.d.ts.map +1 -0
- package/dist/smart-agent/mcp-readiness-monitor.js +81 -0
- package/dist/smart-agent/mcp-readiness-monitor.js.map +1 -0
- package/dist/smart-agent/mcp-readiness-registry.d.ts +37 -0
- package/dist/smart-agent/mcp-readiness-registry.d.ts.map +1 -0
- package/dist/smart-agent/mcp-readiness-registry.js +55 -0
- package/dist/smart-agent/mcp-readiness-registry.js.map +1 -0
- package/dist/smart-agent/resolve-config-sections.d.ts +15 -0
- package/dist/smart-agent/resolve-config-sections.d.ts.map +1 -0
- package/dist/smart-agent/resolve-config-sections.js +212 -0
- package/dist/smart-agent/resolve-config-sections.js.map +1 -0
- package/dist/smart-agent/session-lifecycle/index.d.ts +117 -0
- package/dist/smart-agent/session-lifecycle/index.d.ts.map +1 -0
- package/dist/smart-agent/session-lifecycle/index.js +152 -0
- package/dist/smart-agent/session-lifecycle/index.js.map +1 -0
- package/dist/smart-agent/skill-plugins-config.d.ts +9 -1
- package/dist/smart-agent/skill-plugins-config.d.ts.map +1 -1
- package/dist/smart-agent/skill-plugins-config.js +27 -1
- package/dist/smart-agent/skill-plugins-config.js.map +1 -1
- package/dist/smart-agent/skill-plugins-host-factory.d.ts +14 -2
- package/dist/smart-agent/skill-plugins-host-factory.d.ts.map +1 -1
- package/dist/smart-agent/skill-plugins-host-factory.js +16 -4
- package/dist/smart-agent/skill-plugins-host-factory.js.map +1 -1
- package/dist/smart-agent/smart-server.d.ts +151 -222
- package/dist/smart-agent/smart-server.d.ts.map +1 -1
- package/dist/smart-agent/smart-server.js +529 -1385
- package/dist/smart-agent/smart-server.js.map +1 -1
- package/dist/smart-agent/stepper-config.d.ts +138 -0
- package/dist/smart-agent/stepper-config.d.ts.map +1 -0
- package/dist/smart-agent/stepper-config.js +216 -0
- package/dist/smart-agent/stepper-config.js.map +1 -0
- package/dist/smart-agent/tools-rag-handle.d.ts +10 -0
- package/dist/smart-agent/tools-rag-handle.d.ts.map +1 -0
- package/dist/smart-agent/tools-rag-handle.js +76 -0
- package/dist/smart-agent/tools-rag-handle.js.map +1 -0
- package/dist/smart-agent/workers/worker-registry.d.ts +159 -0
- package/dist/smart-agent/workers/worker-registry.d.ts.map +1 -0
- package/dist/smart-agent/workers/worker-registry.js +203 -0
- package/dist/smart-agent/workers/worker-registry.js.map +1 -0
- package/dist/smart-agent/yaml-loader.d.ts +7 -0
- package/dist/smart-agent/yaml-loader.d.ts.map +1 -0
- package/dist/smart-agent/yaml-loader.js +146 -0
- package/dist/smart-agent/yaml-loader.js.map +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsonError } from './response-helpers.js';
|
|
2
|
+
import { resolveSessionCookie } from './session-cookie.js';
|
|
3
|
+
/**
|
|
4
|
+
* GET /v1/usage — return per-session token-usage summary.
|
|
5
|
+
*
|
|
6
|
+
* Body moved verbatim from `SmartServer._buildRouteTable` (route index 2).
|
|
7
|
+
* `rc.server._lifecycle` (private) is threaded as the `lifecycle` param so the
|
|
8
|
+
* free function compiles without accessing private class fields.
|
|
9
|
+
* The inline cookie block is replaced with `resolveSessionCookie(rc, lifecycle)`.
|
|
10
|
+
*/
|
|
11
|
+
export async function handleUsageRoute(rc, lifecycle) {
|
|
12
|
+
if (!lifecycle) {
|
|
13
|
+
rc.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
14
|
+
rc.res.end(jsonError('Session lifecycle not initialized', 'server_error'));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const resolved = resolveSessionCookie(rc, lifecycle);
|
|
18
|
+
const sessionId = resolved.identity.sessionId;
|
|
19
|
+
const graph = await lifecycle.acquire(sessionId);
|
|
20
|
+
try {
|
|
21
|
+
rc.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
22
|
+
rc.res.end(JSON.stringify(graph.logger.getSummary()));
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
lifecycle.release(sessionId, graph);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=usage-route-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-route-handler.js","sourceRoot":"","sources":["../../../src/smart-agent/http/usage-route-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAgB,EAChB,SAAuC;IAEvC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC9D,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,mCAAmC,EAAE,cAAc,CAAC,CAAC,CAAC;QAC3E,OAAO;IACT,CAAC;IACD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;IAC9C,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC9D,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IEmbedder } from '@mcp-abap-adt/llm-agent';
|
|
2
|
+
import { type KnowledgeBackend } from '@mcp-abap-adt/llm-agent-libs';
|
|
3
|
+
/**
|
|
4
|
+
* Build the ONE knowledge backend shared across all requests (JSONL when a
|
|
5
|
+
* logDir is set, else in-memory). When an embedder is provided, an
|
|
6
|
+
* embedder-backed semantic index is attached so recall ranks by meaning.
|
|
7
|
+
* Pure factory — no MCP dependency, safe to call before MCP resolves.
|
|
8
|
+
*/
|
|
9
|
+
export declare function makeKnowledgeBackend(input: {
|
|
10
|
+
logDir?: string;
|
|
11
|
+
embedder?: IEmbedder;
|
|
12
|
+
}): KnowledgeBackend;
|
|
13
|
+
//# sourceMappingURL=make-knowledge-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"make-knowledge-backend.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/knowledge/make-knowledge-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,8BAA8B,CAAC;AAItC;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,GAAG,gBAAgB,CAOnB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { InMemoryKnowledgeBackend, } from '@mcp-abap-adt/llm-agent-libs';
|
|
2
|
+
import { makeKnowledgeSemanticIndex } from '../embedder-knowledge-index.js';
|
|
3
|
+
import { JsonlKnowledgeBackend } from '../jsonl-knowledge-backend.js';
|
|
4
|
+
/**
|
|
5
|
+
* Build the ONE knowledge backend shared across all requests (JSONL when a
|
|
6
|
+
* logDir is set, else in-memory). When an embedder is provided, an
|
|
7
|
+
* embedder-backed semantic index is attached so recall ranks by meaning.
|
|
8
|
+
* Pure factory — no MCP dependency, safe to call before MCP resolves.
|
|
9
|
+
*/
|
|
10
|
+
export function makeKnowledgeBackend(input) {
|
|
11
|
+
const semantic = input.embedder
|
|
12
|
+
? makeKnowledgeSemanticIndex(input.embedder)
|
|
13
|
+
: undefined;
|
|
14
|
+
return input.logDir
|
|
15
|
+
? new JsonlKnowledgeBackend(input.logDir, semantic)
|
|
16
|
+
: new InMemoryKnowledgeBackend(semantic);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=make-knowledge-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"make-knowledge-backend.js","sourceRoot":"","sources":["../../../src/smart-agent/knowledge/make-knowledge-backend.ts"],"names":[],"mappings":"AACA,OAAO,EACL,wBAAwB,GAEzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEtE;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAGpC;IACC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ;QAC7B,CAAC,CAAC,0BAA0B,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC5C,CAAC,CAAC,SAAS,CAAC;IACd,OAAO,KAAK,CAAC,MAAM;QACjB,CAAC,CAAC,IAAI,qBAAqB,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC;QACnD,CAAC,CAAC,IAAI,wBAAwB,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ILlm } from '@mcp-abap-adt/llm-agent';
|
|
2
|
+
import { type NormalizedLlmMap } from '../config.js';
|
|
3
|
+
import type { SmartServerLlmConfig } from '../smart-server.js';
|
|
4
|
+
/** The real `makeLlm`-backed construction (the SmartServer seam's default). */
|
|
5
|
+
export declare function makeDefaultRoleLlm(lc: SmartServerLlmConfig, mainTemp: number | undefined): Promise<ILlm>;
|
|
6
|
+
export interface IRoleLlmResolver {
|
|
7
|
+
resolve(role: string): Promise<ILlm>;
|
|
8
|
+
makeLlm(lc: SmartServerLlmConfig): Promise<ILlm>;
|
|
9
|
+
}
|
|
10
|
+
export interface RoleLlmResolverDeps {
|
|
11
|
+
getMain(): ILlm | undefined;
|
|
12
|
+
getHelper(): ILlm | undefined;
|
|
13
|
+
getClassifier(): ILlm | undefined;
|
|
14
|
+
getLlmMap(): NormalizedLlmMap | undefined;
|
|
15
|
+
getPipelineFallback(): SmartServerLlmConfig | undefined;
|
|
16
|
+
makeLlm(lc: SmartServerLlmConfig): Promise<ILlm>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a per-role LLM through the normalized map → pipelineFallback chain.
|
|
20
|
+
* Reads the role LLM instances through LIVE accessors so a config-reload
|
|
21
|
+
* hot-swap of `main`/`helper`/`classifier` is observed transparently (the
|
|
22
|
+
* SmartServer keeps the fields as source-of-truth).
|
|
23
|
+
*/
|
|
24
|
+
export declare class RoleLlmResolver implements IRoleLlmResolver {
|
|
25
|
+
private readonly deps;
|
|
26
|
+
constructor(deps: RoleLlmResolverDeps);
|
|
27
|
+
makeLlm(lc: SmartServerLlmConfig): Promise<ILlm>;
|
|
28
|
+
resolve(role: string): Promise<ILlm>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=role-llm-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-llm-resolver.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/llm/role-llm-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAAE,KAAK,gBAAgB,EAAoB,MAAM,cAAc,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,oBAAoB,EACxB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,IAAI,IAAI,GAAG,SAAS,CAAC;IAC5B,SAAS,IAAI,IAAI,GAAG,SAAS,CAAC;IAC9B,aAAa,IAAI,IAAI,GAAG,SAAS,CAAC;IAClC,SAAS,IAAI,gBAAgB,GAAG,SAAS,CAAC;IAC1C,mBAAmB,IAAI,oBAAoB,GAAG,SAAS,CAAC;IACxD,OAAO,CAAC,EAAE,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,mBAAmB;IAEtD,OAAO,CAAC,EAAE,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAgB3C"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { makeLlm } from '@mcp-abap-adt/llm-agent-libs';
|
|
2
|
+
import { resolveLlmConfig } from '../config.js';
|
|
3
|
+
/** The real `makeLlm`-backed construction (the SmartServer seam's default). */
|
|
4
|
+
export function makeDefaultRoleLlm(lc, mainTemp) {
|
|
5
|
+
return makeLlm({
|
|
6
|
+
provider: lc.provider ?? 'deepseek',
|
|
7
|
+
apiKey: lc.apiKey,
|
|
8
|
+
baseURL: lc.url,
|
|
9
|
+
model: lc.model,
|
|
10
|
+
}, Number(lc.temperature ?? mainTemp ?? 0.7));
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a per-role LLM through the normalized map → pipelineFallback chain.
|
|
14
|
+
* Reads the role LLM instances through LIVE accessors so a config-reload
|
|
15
|
+
* hot-swap of `main`/`helper`/`classifier` is observed transparently (the
|
|
16
|
+
* SmartServer keeps the fields as source-of-truth).
|
|
17
|
+
*/
|
|
18
|
+
export class RoleLlmResolver {
|
|
19
|
+
deps;
|
|
20
|
+
constructor(deps) {
|
|
21
|
+
this.deps = deps;
|
|
22
|
+
}
|
|
23
|
+
makeLlm(lc) {
|
|
24
|
+
return this.deps.makeLlm(lc);
|
|
25
|
+
}
|
|
26
|
+
async resolve(role) {
|
|
27
|
+
const main = this.deps.getMain();
|
|
28
|
+
const helper = this.deps.getHelper();
|
|
29
|
+
const classifier = this.deps.getClassifier();
|
|
30
|
+
if (role === 'main' && main)
|
|
31
|
+
return main;
|
|
32
|
+
if ((role === 'helper' || role === 'planner') && helper)
|
|
33
|
+
return helper;
|
|
34
|
+
if (role === 'classifier' && classifier)
|
|
35
|
+
return classifier;
|
|
36
|
+
const cfg = resolveLlmConfig(this.deps.getLlmMap(), role, this.deps.getPipelineFallback());
|
|
37
|
+
if (cfg)
|
|
38
|
+
return this.deps.makeLlm(cfg);
|
|
39
|
+
if (main)
|
|
40
|
+
return main;
|
|
41
|
+
throw new Error(`cannot resolve LLM for role '${role}': no config`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=role-llm-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-llm-resolver.js","sourceRoot":"","sources":["../../../src/smart-agent/llm/role-llm-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAyB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGvE,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB,CAChC,EAAwB,EACxB,QAA4B;IAE5B,OAAO,OAAO,CACZ;QACE,QAAQ,EAAE,EAAE,CAAC,QAAQ,IAAI,UAAU;QACnC,MAAM,EAAE,EAAE,CAAC,MAAM;QACjB,OAAO,EAAE,EAAE,CAAC,GAAG;QACf,KAAK,EAAE,EAAE,CAAC,KAAK;KAChB,EACD,MAAM,CAAC,EAAE,CAAC,WAAW,IAAI,QAAQ,IAAI,GAAG,CAAC,CAC1C,CAAC;AACJ,CAAC;AAgBD;;;;;GAKG;AACH,MAAM,OAAO,eAAe;IACG;IAA7B,YAA6B,IAAyB;QAAzB,SAAI,GAAJ,IAAI,CAAqB;IAAG,CAAC;IAE1D,OAAO,CAAC,EAAwB;QAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAY;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QAC7C,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACzC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,SAAS,CAAC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QACvE,IAAI,IAAI,KAAK,YAAY,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;QAC3D,MAAM,GAAG,GAAG,gBAAgB,CAC1B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EACrB,IAAI,EACJ,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAChC,CAAC;QACF,IAAI,GAAG;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,cAAc,CAAC,CAAC;IACtE,CAAC;CACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { SmartServerLlmConfig } from './smart-server.js';
|
|
2
|
+
export type LlmConfigMap = Record<string, SmartServerLlmConfig>;
|
|
3
|
+
export type NormalizedLlmMap = {
|
|
4
|
+
main: SmartServerLlmConfig;
|
|
5
|
+
} & LlmConfigMap;
|
|
6
|
+
/**
|
|
7
|
+
* Normalize the optional top-level `llm:` block.
|
|
8
|
+
* - undefined → undefined (pipeline-only configs stay valid)
|
|
9
|
+
* - flat shape (has `provider` | `apiKey` | `model` | `url`) → { main: flat } (backward compat)
|
|
10
|
+
* - map shape → must include `main`; returned as NormalizedLlmMap
|
|
11
|
+
*/
|
|
12
|
+
export declare function normalizeLlmConfig(input?: SmartServerLlmConfig | LlmConfigMap): NormalizedLlmMap | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Strict lookup: returns map[name] if explicitly present, else undefined.
|
|
15
|
+
* Does NOT fall through to map.main. Use when the caller needs to
|
|
16
|
+
* detect explicit-presence (e.g. to decide between an alias and the
|
|
17
|
+
* named map entry).
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveLlmConfigStrict(map: NormalizedLlmMap | undefined, name: string | undefined): SmartServerLlmConfig | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Resolve a per-role LLM config by name from a normalized map.
|
|
22
|
+
* Lookup chain: map[name] → map.main → pipelineFallback.
|
|
23
|
+
* When map is undefined, falls back to pipelineFallback (so pipeline-only
|
|
24
|
+
* configs keep working with no top-level llm: block).
|
|
25
|
+
*
|
|
26
|
+
* The caller decides whether `undefined` is an error.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveLlmConfig(map: NormalizedLlmMap | undefined, name?: string, pipelineFallback?: SmartServerLlmConfig): SmartServerLlmConfig | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Read the reviewer block's LLM-name selector, accepting both the
|
|
31
|
+
* preferred `reviewerLlm` field and the deprecated `plannerLlm` alias.
|
|
32
|
+
* When the alias is used, calls `warn(message)`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveReviewerLlmName(block: {
|
|
35
|
+
reviewerLlm?: string;
|
|
36
|
+
plannerLlm?: string;
|
|
37
|
+
} | undefined, warn: (msg: string) => void): string | undefined;
|
|
38
|
+
//# sourceMappingURL=llm-config-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-config-map.d.ts","sourceRoot":"","sources":["../../src/smart-agent/llm-config-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect whether an object is a flat SmartServerLlmConfig shape.
|
|
3
|
+
* Flat shape is identified by the presence of ANY of the known flat-shape
|
|
4
|
+
* fields: `provider`, `apiKey`, `model`, or `url`. This covers keyless
|
|
5
|
+
* providers (Ollama, SAP AI Core) that omit `apiKey` — using `apiKey`-only
|
|
6
|
+
* detection silently misclassified those configs as a "map" shape.
|
|
7
|
+
*/
|
|
8
|
+
function isFlatLlmConfig(input) {
|
|
9
|
+
const flat = input;
|
|
10
|
+
return (typeof flat.provider === 'string' ||
|
|
11
|
+
typeof flat.apiKey === 'string' ||
|
|
12
|
+
typeof flat.model === 'string' ||
|
|
13
|
+
typeof flat.url === 'string');
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Normalize the optional top-level `llm:` block.
|
|
17
|
+
* - undefined → undefined (pipeline-only configs stay valid)
|
|
18
|
+
* - flat shape (has `provider` | `apiKey` | `model` | `url`) → { main: flat } (backward compat)
|
|
19
|
+
* - map shape → must include `main`; returned as NormalizedLlmMap
|
|
20
|
+
*/
|
|
21
|
+
export function normalizeLlmConfig(input) {
|
|
22
|
+
if (input === undefined)
|
|
23
|
+
return undefined;
|
|
24
|
+
if (isFlatLlmConfig(input)) {
|
|
25
|
+
return { main: input };
|
|
26
|
+
}
|
|
27
|
+
const map = input;
|
|
28
|
+
if (!map.main) {
|
|
29
|
+
throw new Error("llm: map must include a 'main' key (default LLM for unspecified roles)");
|
|
30
|
+
}
|
|
31
|
+
return map;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Strict lookup: returns map[name] if explicitly present, else undefined.
|
|
35
|
+
* Does NOT fall through to map.main. Use when the caller needs to
|
|
36
|
+
* detect explicit-presence (e.g. to decide between an alias and the
|
|
37
|
+
* named map entry).
|
|
38
|
+
*/
|
|
39
|
+
export function resolveLlmConfigStrict(map, name) {
|
|
40
|
+
if (!map || !name)
|
|
41
|
+
return undefined;
|
|
42
|
+
return map[name];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve a per-role LLM config by name from a normalized map.
|
|
46
|
+
* Lookup chain: map[name] → map.main → pipelineFallback.
|
|
47
|
+
* When map is undefined, falls back to pipelineFallback (so pipeline-only
|
|
48
|
+
* configs keep working with no top-level llm: block).
|
|
49
|
+
*
|
|
50
|
+
* The caller decides whether `undefined` is an error.
|
|
51
|
+
*/
|
|
52
|
+
export function resolveLlmConfig(map, name, pipelineFallback) {
|
|
53
|
+
if (!map)
|
|
54
|
+
return pipelineFallback;
|
|
55
|
+
if (!name || name === 'main')
|
|
56
|
+
return map.main;
|
|
57
|
+
return map[name] ?? map.main;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Read the reviewer block's LLM-name selector, accepting both the
|
|
61
|
+
* preferred `reviewerLlm` field and the deprecated `plannerLlm` alias.
|
|
62
|
+
* When the alias is used, calls `warn(message)`.
|
|
63
|
+
*/
|
|
64
|
+
export function resolveReviewerLlmName(block, warn) {
|
|
65
|
+
if (!block)
|
|
66
|
+
return undefined;
|
|
67
|
+
if (typeof block.reviewerLlm === 'string')
|
|
68
|
+
return block.reviewerLlm;
|
|
69
|
+
if (typeof block.plannerLlm === 'string') {
|
|
70
|
+
warn("coordinator.reviewer.plannerLlm is deprecated; rename to 'reviewerLlm'");
|
|
71
|
+
return block.plannerLlm;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=llm-config-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-config-map.js","sourceRoot":"","sources":["../../src/smart-agent/llm-config-map.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,KAA0C;IACjE,MAAM,IAAI,GAAG,KAAsC,CAAC;IACpD,OAAO,CACL,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ;QACjC,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;QAC/B,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;QAC9B,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,CAC7B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAA2C;IAE3C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,IAAI,EAAE,KAA6B,EAAsB,CAAC;IACrE,CAAC;IACD,MAAM,GAAG,GAAG,KAAqB,CAAC;IAClC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;IACJ,CAAC;IACD,OAAO,GAAuB,CAAC;AACjC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAiC,EACjC,IAAwB;IAExB,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IACpC,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAiC,EACjC,IAAa,EACb,gBAAuC;IAEvC,IAAI,CAAC,GAAG;QAAE,OAAO,gBAAgB,CAAC;IAClC,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC;IAC9C,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAgE,EAChE,IAA2B;IAE3B,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,WAAW,CAAC;IACpE,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACzC,IAAI,CACF,wEAAwE,CACzE,CAAC;QACF,OAAO,KAAK,CAAC,UAAU,CAAC;IAC1B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { IMcpClient } from '@mcp-abap-adt/llm-agent';
|
|
2
|
+
import type { McpReadinessRegistry } from './mcp-readiness-registry.js';
|
|
3
|
+
export interface McpReadinessMonitorDeps {
|
|
4
|
+
/** Lazily (re)connect a slot's opaque config to a live client. Throws if still
|
|
5
|
+
* down. */
|
|
6
|
+
connect: (config: unknown) => Promise<IMcpClient>;
|
|
7
|
+
/** Called after a GLOBAL slot transitions DOWN→UP, so the server can refresh the
|
|
8
|
+
* vectorized tool catalog (toolsRag) over the now-live clients. */
|
|
9
|
+
onGlobalRecovered?: () => Promise<void>;
|
|
10
|
+
/** Called after a WORKER slot transitions DOWN→UP, so the server can invalidate
|
|
11
|
+
* the worker cache (next session rebuild injects the recovered client). */
|
|
12
|
+
onWorkerRecovered?: (id: string) => void;
|
|
13
|
+
cooldownMs?: number;
|
|
14
|
+
intervalMs?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Periodic readiness probe over the SmartServer-owned MCP target registry. Drives
|
|
18
|
+
* the `_ready` signal: probes live clients via `healthCheck()` (→ `ping()`, a LIVE
|
|
19
|
+
* round-trip — never the cached `listTools()`), and lazily (re)connects DOWN targets
|
|
20
|
+
* on a cooldown. `tick()` is one pass; the timer just calls it on an interval so
|
|
21
|
+
* tests are deterministic.
|
|
22
|
+
*/
|
|
23
|
+
export declare class McpReadinessMonitor {
|
|
24
|
+
private readonly registry;
|
|
25
|
+
private readonly deps;
|
|
26
|
+
private timer?;
|
|
27
|
+
private readonly cooldownMs;
|
|
28
|
+
private readonly intervalMs;
|
|
29
|
+
constructor(registry: McpReadinessRegistry, deps: McpReadinessMonitorDeps);
|
|
30
|
+
isReady(): boolean;
|
|
31
|
+
/** One monitoring pass. The timer calls this; tests call it directly (passing an
|
|
32
|
+
* explicit `now` for deterministic cooldown). */
|
|
33
|
+
tick(now?: number): Promise<void>;
|
|
34
|
+
private _fireRecovered;
|
|
35
|
+
start(): void;
|
|
36
|
+
stop(): void;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=mcp-readiness-monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-readiness-monitor.d.ts","sourceRoot":"","sources":["../../src/smart-agent/mcp-readiness-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,MAAM,WAAW,uBAAuB;IACtC;gBACY;IACZ,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAClD;wEACoE;IACpE,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC;gFAC4E;IAC5E,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,qBAAa,mBAAmB;IAM5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IANvB,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAGjB,QAAQ,EAAE,oBAAoB,EAC9B,IAAI,EAAE,uBAAuB;IAMhD,OAAO,IAAI,OAAO;IAIlB;sDACkD;IAC5C,IAAI,CAAC,GAAG,SAAa,GAAG,OAAO,CAAC,IAAI,CAAC;YAsC7B,cAAc;IAQ5B,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;CAIb"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Periodic readiness probe over the SmartServer-owned MCP target registry. Drives
|
|
3
|
+
* the `_ready` signal: probes live clients via `healthCheck()` (→ `ping()`, a LIVE
|
|
4
|
+
* round-trip — never the cached `listTools()`), and lazily (re)connects DOWN targets
|
|
5
|
+
* on a cooldown. `tick()` is one pass; the timer just calls it on an interval so
|
|
6
|
+
* tests are deterministic.
|
|
7
|
+
*/
|
|
8
|
+
export class McpReadinessMonitor {
|
|
9
|
+
registry;
|
|
10
|
+
deps;
|
|
11
|
+
timer;
|
|
12
|
+
cooldownMs;
|
|
13
|
+
intervalMs;
|
|
14
|
+
constructor(registry, deps) {
|
|
15
|
+
this.registry = registry;
|
|
16
|
+
this.deps = deps;
|
|
17
|
+
this.cooldownMs = deps.cooldownMs ?? 30000;
|
|
18
|
+
this.intervalMs = deps.intervalMs ?? 10000;
|
|
19
|
+
}
|
|
20
|
+
isReady() {
|
|
21
|
+
return this.registry.allHealthy();
|
|
22
|
+
}
|
|
23
|
+
/** One monitoring pass. The timer calls this; tests call it directly (passing an
|
|
24
|
+
* explicit `now` for deterministic cooldown). */
|
|
25
|
+
async tick(now = Date.now()) {
|
|
26
|
+
for (const slot of this.registry.list()) {
|
|
27
|
+
const wasDown = !slot.healthy;
|
|
28
|
+
if (slot.client) {
|
|
29
|
+
// healthCheck is OPTIONAL on IMcpClient. A client WITHOUT it is ASSUMED
|
|
30
|
+
// healthy (per the interface contract) — never marked down on a missing
|
|
31
|
+
// probe, else a DI/plugin client without a probe wedges readiness down
|
|
32
|
+
// forever with no config to reconnect.
|
|
33
|
+
if (typeof slot.client.healthCheck !== 'function') {
|
|
34
|
+
this.registry.markHealthy(slot.id, slot.client);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const hc = await slot.client.healthCheck();
|
|
38
|
+
if (hc?.ok) {
|
|
39
|
+
this.registry.markHealthy(slot.id, slot.client);
|
|
40
|
+
if (wasDown)
|
|
41
|
+
await this._fireRecovered(slot.id, slot.scope);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
this.registry.markDown(slot.id);
|
|
45
|
+
// fall through to a reconnect attempt
|
|
46
|
+
}
|
|
47
|
+
if (!slot.healthy &&
|
|
48
|
+
slot.config !== undefined &&
|
|
49
|
+
now - slot.lastAttempt >= this.cooldownMs) {
|
|
50
|
+
slot.lastAttempt = now;
|
|
51
|
+
try {
|
|
52
|
+
const client = await this.deps.connect(slot.config);
|
|
53
|
+
this.registry.markHealthy(slot.id, client);
|
|
54
|
+
if (wasDown)
|
|
55
|
+
await this._fireRecovered(slot.id, slot.scope);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
this.registry.markDown(slot.id);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async _fireRecovered(id, scope) {
|
|
64
|
+
if (scope === 'global')
|
|
65
|
+
await this.deps.onGlobalRecovered?.();
|
|
66
|
+
else
|
|
67
|
+
this.deps.onWorkerRecovered?.(id);
|
|
68
|
+
}
|
|
69
|
+
start() {
|
|
70
|
+
if (this.timer)
|
|
71
|
+
return;
|
|
72
|
+
this.timer = setInterval(() => void this.tick(), this.intervalMs);
|
|
73
|
+
this.timer.unref?.();
|
|
74
|
+
}
|
|
75
|
+
stop() {
|
|
76
|
+
if (this.timer)
|
|
77
|
+
clearInterval(this.timer);
|
|
78
|
+
this.timer = undefined;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=mcp-readiness-monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-readiness-monitor.js","sourceRoot":"","sources":["../../src/smart-agent/mcp-readiness-monitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { IMcpClient } from '@mcp-abap-adt/llm-agent';
|
|
2
|
+
export type ReadinessScope = 'global' | 'worker';
|
|
3
|
+
export interface ReadinessSlot {
|
|
4
|
+
id: string;
|
|
5
|
+
scope: ReadinessScope;
|
|
6
|
+
/** Opaque MCP target config (the monitor's `connect` knows how to use it).
|
|
7
|
+
* Absent for DI-only live clients that have no reconnect config. */
|
|
8
|
+
config?: unknown;
|
|
9
|
+
client?: IMcpClient;
|
|
10
|
+
healthy: boolean;
|
|
11
|
+
lastAttempt: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Registry of configured MCP targets driving SmartServer readiness. A target with
|
|
15
|
+
* no healthy client ⇒ NOT ready. Built from CONFIG (not from successful connects),
|
|
16
|
+
* so a down-at-boot target is a DOWN slot, not a missing one — which is what makes
|
|
17
|
+
* "cold-MCP startup → NOT_READY (no throw), recover later" implementable.
|
|
18
|
+
*/
|
|
19
|
+
export declare class McpReadinessRegistry {
|
|
20
|
+
private readonly slots;
|
|
21
|
+
/** Register a configured target whose client may not be connected yet.
|
|
22
|
+
* Idempotent on `id` (the worker setup runs on both the primary build and the
|
|
23
|
+
* per-session rebuild — re-`addTarget` with the same id must keep ONE slot). */
|
|
24
|
+
addTarget(id: string, config: unknown, scope: ReadinessScope): void;
|
|
25
|
+
/** Register an already-live DI client (no lazy connect needed). */
|
|
26
|
+
addLiveClient(id: string, client: IMcpClient, scope: ReadinessScope): void;
|
|
27
|
+
markHealthy(id: string, client: IMcpClient): void;
|
|
28
|
+
markDown(id: string): void;
|
|
29
|
+
allHealthy(): boolean;
|
|
30
|
+
list(): ReadinessSlot[];
|
|
31
|
+
/** Live execution clients for GLOBAL targets — the source of truth `callMcp`
|
|
32
|
+
* reads so a monitor-recovered client is used without a restart. Worker targets
|
|
33
|
+
* are excluded: worker clients drive readiness + worker INJECTION (the worker
|
|
34
|
+
* hoist), not the top-level callMcp. */
|
|
35
|
+
liveClients(): IMcpClient[];
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=mcp-readiness-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-readiness-registry.d.ts","sourceRoot":"","sources":["../../src/smart-agent/mcp-readiness-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,cAAc,CAAC;IACtB;yEACqE;IACrE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoC;IAE1D;;qFAEiF;IACjF,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI;IAKnE,mEAAmE;IACnE,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI;IAI1E,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAQjD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK1B,UAAU,IAAI,OAAO;IAKrB,IAAI,IAAI,aAAa,EAAE;IAIvB;;;6CAGyC;IACzC,WAAW,IAAI,UAAU,EAAE;CAO5B"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry of configured MCP targets driving SmartServer readiness. A target with
|
|
3
|
+
* no healthy client ⇒ NOT ready. Built from CONFIG (not from successful connects),
|
|
4
|
+
* so a down-at-boot target is a DOWN slot, not a missing one — which is what makes
|
|
5
|
+
* "cold-MCP startup → NOT_READY (no throw), recover later" implementable.
|
|
6
|
+
*/
|
|
7
|
+
export class McpReadinessRegistry {
|
|
8
|
+
slots = new Map();
|
|
9
|
+
/** Register a configured target whose client may not be connected yet.
|
|
10
|
+
* Idempotent on `id` (the worker setup runs on both the primary build and the
|
|
11
|
+
* per-session rebuild — re-`addTarget` with the same id must keep ONE slot). */
|
|
12
|
+
addTarget(id, config, scope) {
|
|
13
|
+
if (this.slots.has(id))
|
|
14
|
+
return;
|
|
15
|
+
this.slots.set(id, { id, scope, config, healthy: false, lastAttempt: 0 });
|
|
16
|
+
}
|
|
17
|
+
/** Register an already-live DI client (no lazy connect needed). */
|
|
18
|
+
addLiveClient(id, client, scope) {
|
|
19
|
+
this.slots.set(id, { id, scope, client, healthy: true, lastAttempt: 0 });
|
|
20
|
+
}
|
|
21
|
+
markHealthy(id, client) {
|
|
22
|
+
const s = this.slots.get(id);
|
|
23
|
+
if (s) {
|
|
24
|
+
s.client = client;
|
|
25
|
+
s.healthy = true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
markDown(id) {
|
|
29
|
+
const s = this.slots.get(id);
|
|
30
|
+
if (s)
|
|
31
|
+
s.healthy = false;
|
|
32
|
+
}
|
|
33
|
+
allHealthy() {
|
|
34
|
+
for (const s of this.slots.values())
|
|
35
|
+
if (!s.healthy)
|
|
36
|
+
return false;
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
list() {
|
|
40
|
+
return [...this.slots.values()];
|
|
41
|
+
}
|
|
42
|
+
/** Live execution clients for GLOBAL targets — the source of truth `callMcp`
|
|
43
|
+
* reads so a monitor-recovered client is used without a restart. Worker targets
|
|
44
|
+
* are excluded: worker clients drive readiness + worker INJECTION (the worker
|
|
45
|
+
* hoist), not the top-level callMcp. */
|
|
46
|
+
liveClients() {
|
|
47
|
+
const out = [];
|
|
48
|
+
for (const s of this.slots.values()) {
|
|
49
|
+
if (s.scope === 'global' && s.healthy && s.client)
|
|
50
|
+
out.push(s.client);
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=mcp-readiness-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-readiness-registry.js","sourceRoot":"","sources":["../../src/smart-agent/mcp-readiness-registry.ts"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH,MAAM,OAAO,oBAAoB;IACd,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;IAE1D;;qFAEiF;IACjF,SAAS,CAAC,EAAU,EAAE,MAAe,EAAE,KAAqB;QAC1D,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO;QAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,mEAAmE;IACnE,aAAa,CAAC,EAAU,EAAE,MAAkB,EAAE,KAAqB;QACjE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,WAAW,CAAC,EAAU,EAAE,MAAkB;QACxC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE,CAAC;YACN,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC;YAClB,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;QACnB,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,EAAU;QACjB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,CAAC;YAAE,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC;IAC3B,CAAC;IAED,UAAU;QACR,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,IAAI,CAAC,CAAC,CAAC,OAAO;gBAAE,OAAO,KAAK,CAAC;QAClE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAClC,CAAC;IAED;;;6CAGyC;IACzC,WAAW;QACT,MAAM,GAAG,GAAiB,EAAE,CAAC;QAC7B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACpC,IAAI,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM;gBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-section config builders extracted from resolveSmartServerConfig.
|
|
3
|
+
* Internal module — not re-exported by the package barrel.
|
|
4
|
+
*/
|
|
5
|
+
import type { SmartServerAgentConfig, SmartServerConfig } from './smart-server.js';
|
|
6
|
+
import type { YamlConfig } from './yaml-loader.js';
|
|
7
|
+
export declare function resolveLlmSection(yaml: YamlConfig, apiKey: string): SmartServerConfig['llm'];
|
|
8
|
+
export declare function resolveRagSection(yaml: YamlConfig, args: Record<string, unknown>): SmartServerConfig['rag'];
|
|
9
|
+
export declare function resolveMcpSection(yaml: YamlConfig, args: Record<string, unknown>): SmartServerConfig['mcp'];
|
|
10
|
+
export declare function resolveAgentSection(yaml: YamlConfig, args: Record<string, unknown>): SmartServerAgentConfig;
|
|
11
|
+
export declare function resolvePromptsSection(yaml: YamlConfig): SmartServerConfig['prompts'];
|
|
12
|
+
export declare function resolvePipelineSelection(yaml: YamlConfig): {
|
|
13
|
+
pipeline?: SmartServerConfig['pipeline'];
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=resolve-config-sections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-config-sections.d.ts","sourceRoot":"","sources":["../../src/smart-agent/resolve-config-sections.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,sBAAsB,EACtB,iBAAiB,EAGlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,GACb,iBAAiB,CAAC,KAAK,CAAC,CAqB1B;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,iBAAiB,CAAC,KAAK,CAAC,CA+B1B;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,iBAAiB,CAAC,KAAK,CAAC,CAyC1B;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,sBAAsB,CAkIxB;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,UAAU,GACf,iBAAiB,CAAC,SAAS,CAAC,CA2B9B;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG;IAC1D,QAAQ,CAAC,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC;CAC1C,CAsBA"}
|