@lssm/lib.ai-agent 1.41.0 → 1.42.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/dist/agent/agent-factory.d.ts +104 -0
  4. package/dist/agent/agent-factory.d.ts.map +1 -0
  5. package/dist/agent/agent-factory.js +103 -1
  6. package/dist/agent/agent-factory.js.map +1 -0
  7. package/dist/agent/contract-spec-agent.d.ts +75 -0
  8. package/dist/agent/contract-spec-agent.d.ts.map +1 -0
  9. package/dist/agent/contract-spec-agent.js +148 -1
  10. package/dist/agent/contract-spec-agent.js.map +1 -0
  11. package/dist/agent/index.d.ts +3 -0
  12. package/dist/agent/index.js +4 -1
  13. package/dist/approval/index.d.ts +2 -0
  14. package/dist/approval/index.js +3 -1
  15. package/dist/approval/workflow.d.ts +156 -0
  16. package/dist/approval/workflow.d.ts.map +1 -0
  17. package/dist/approval/workflow.js +160 -1
  18. package/dist/approval/workflow.js.map +1 -0
  19. package/dist/index.d.ts +23 -0
  20. package/dist/index.js +21 -1
  21. package/dist/knowledge/index.d.ts +2 -0
  22. package/dist/knowledge/index.js +3 -1
  23. package/dist/knowledge/injector.d.ts +38 -0
  24. package/dist/knowledge/injector.d.ts.map +1 -0
  25. package/dist/knowledge/injector.js +50 -5
  26. package/dist/knowledge/injector.js.map +1 -0
  27. package/dist/memory/in-memory.d.ts +22 -0
  28. package/dist/memory/in-memory.d.ts.map +1 -0
  29. package/dist/memory/in-memory.js +48 -2
  30. package/dist/memory/in-memory.js.map +1 -0
  31. package/dist/memory/index.d.ts +3 -0
  32. package/dist/memory/index.js +4 -1
  33. package/dist/memory/manager.d.ts +42 -0
  34. package/dist/memory/manager.d.ts.map +1 -0
  35. package/dist/memory/manager.js +80 -1
  36. package/dist/memory/manager.js.map +1 -0
  37. package/dist/schema/index.d.ts +3 -0
  38. package/dist/schema/index.js +4 -1
  39. package/dist/schema/json-schema-to-zod.d.ts +55 -0
  40. package/dist/schema/json-schema-to-zod.d.ts.map +1 -0
  41. package/dist/schema/json-schema-to-zod.js +124 -1
  42. package/dist/schema/json-schema-to-zod.js.map +1 -0
  43. package/dist/schema/schema-output.d.ts +77 -0
  44. package/dist/schema/schema-output.d.ts.map +1 -0
  45. package/dist/schema/schema-output.js +65 -1
  46. package/dist/schema/schema-output.js.map +1 -0
  47. package/dist/session/index.d.ts +2 -0
  48. package/dist/session/index.js +3 -1
  49. package/dist/session/store.d.ts +74 -0
  50. package/dist/session/store.d.ts.map +1 -0
  51. package/dist/session/store.js +79 -1
  52. package/dist/session/store.js.map +1 -0
  53. package/dist/spec/index.d.ts +3 -0
  54. package/dist/spec/index.js +4 -1
  55. package/dist/spec/registry.d.ts +78 -0
  56. package/dist/spec/registry.d.ts.map +1 -0
  57. package/dist/spec/registry.js +117 -1
  58. package/dist/spec/registry.js.map +1 -0
  59. package/dist/spec/spec.d.ts +127 -0
  60. package/dist/spec/spec.d.ts.map +1 -0
  61. package/dist/spec/spec.js +30 -1
  62. package/dist/spec/spec.js.map +1 -0
  63. package/dist/telemetry/adapter.d.ts +73 -0
  64. package/dist/telemetry/adapter.d.ts.map +1 -0
  65. package/dist/telemetry/adapter.js +103 -1
  66. package/dist/telemetry/adapter.js.map +1 -0
  67. package/dist/telemetry/index.d.ts +2 -0
  68. package/dist/telemetry/index.js +3 -1
  69. package/dist/tools/index.d.ts +5 -0
  70. package/dist/tools/index.js +6 -1
  71. package/dist/tools/knowledge-tool.d.ts +21 -0
  72. package/dist/tools/knowledge-tool.d.ts.map +1 -0
  73. package/dist/tools/knowledge-tool.js +51 -6
  74. package/dist/tools/knowledge-tool.js.map +1 -0
  75. package/dist/tools/mcp-client.d.ts +59 -0
  76. package/dist/tools/mcp-client.d.ts.map +1 -0
  77. package/dist/tools/mcp-client.js +58 -1
  78. package/dist/tools/mcp-client.js.map +1 -0
  79. package/dist/tools/mcp-server.d.ts +46 -0
  80. package/dist/tools/mcp-server.d.ts.map +1 -0
  81. package/dist/tools/mcp-server.js +69 -1
  82. package/dist/tools/mcp-server.js.map +1 -0
  83. package/dist/tools/tool-adapter.d.ts +50 -0
  84. package/dist/tools/tool-adapter.d.ts.map +1 -0
  85. package/dist/tools/tool-adapter.js +80 -1
  86. package/dist/tools/tool-adapter.js.map +1 -0
  87. package/dist/types.d.ts +146 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/package.json +49 -40
@@ -1 +1,103 @@
1
- function e(e){let t=e.match(/^(.+)\.v(\d+)$/);return t?{name:t[1],version:parseInt(t[2],10)}:{name:e,version:1}}async function t(t,n,r,i){let{name:a,version:o}=e(n);for(let e of r.toolCalls??[]){let s={operation:{name:`${a}.${e.toolName}`,version:o},durationMs:i??0,success:r.toolResults?.some(t=>t.toolCallId===e.toolCallId&&t.output!==void 0)??!1,timestamp:new Date,metadata:{agentId:n,toolName:e.toolName,finishReason:r.finishReason}};await t.collect(s)}let s={operation:{name:a,version:o},durationMs:i??0,success:r.finishReason!==`error`,timestamp:new Date,metadata:{agentId:n,finishReason:r.finishReason,tokenUsage:r.usage,toolCallCount:r.toolCalls?.length??0}};await t.collect(s)}var n=class{samples=[];async collect(e){this.samples.push(e)}getSamples(){return[...this.samples]}getSamplesForOperation(e){return this.samples.filter(t=>t.operation.name===e)}clear(){this.samples.length=0}};function r(){return new n}const i={collect:async()=>{}};export{n as InMemoryTelemetryCollector,r as createInMemoryTelemetryCollector,i as noopTelemetryCollector,t as trackAgentStep};
1
+ //#region src/telemetry/adapter.ts
2
+ /**
3
+ * Parse agent ID into name and version.
4
+ */
5
+ function parseAgentId(agentId) {
6
+ const match = agentId.match(/^(.+)\.v(\d+)$/);
7
+ if (match) return {
8
+ name: match[1],
9
+ version: parseInt(match[2], 10)
10
+ };
11
+ return {
12
+ name: agentId,
13
+ version: 1
14
+ };
15
+ }
16
+ /**
17
+ * Track an agent step for telemetry.
18
+ *
19
+ * Called from ContractSpecAgent.onStepFinish to feed metrics
20
+ * to the evolution engine.
21
+ *
22
+ * @param collector - Telemetry collector
23
+ * @param agentId - Agent identifier (e.g., "support.bot.v1")
24
+ * @param step - AI SDK step result
25
+ * @param durationMs - Optional step duration in milliseconds
26
+ */
27
+ async function trackAgentStep(collector, agentId, step, durationMs) {
28
+ const { name, version } = parseAgentId(agentId);
29
+ for (const toolCall of step.toolCalls ?? []) {
30
+ const toolSample = {
31
+ operation: {
32
+ name: `${name}.${toolCall.toolName}`,
33
+ version
34
+ },
35
+ durationMs: durationMs ?? 0,
36
+ success: step.toolResults?.some((r) => r.toolCallId === toolCall.toolCallId && r.output !== void 0) ?? false,
37
+ timestamp: /* @__PURE__ */ new Date(),
38
+ metadata: {
39
+ agentId,
40
+ toolName: toolCall.toolName,
41
+ finishReason: step.finishReason
42
+ }
43
+ };
44
+ await collector.collect(toolSample);
45
+ }
46
+ const stepSample = {
47
+ operation: {
48
+ name,
49
+ version
50
+ },
51
+ durationMs: durationMs ?? 0,
52
+ success: step.finishReason !== "error",
53
+ timestamp: /* @__PURE__ */ new Date(),
54
+ metadata: {
55
+ agentId,
56
+ finishReason: step.finishReason,
57
+ tokenUsage: step.usage,
58
+ toolCallCount: step.toolCalls?.length ?? 0
59
+ }
60
+ };
61
+ await collector.collect(stepSample);
62
+ }
63
+ /**
64
+ * In-memory telemetry collector for testing.
65
+ */
66
+ var InMemoryTelemetryCollector = class {
67
+ samples = [];
68
+ async collect(sample) {
69
+ this.samples.push(sample);
70
+ }
71
+ /**
72
+ * Get all collected samples.
73
+ */
74
+ getSamples() {
75
+ return [...this.samples];
76
+ }
77
+ /**
78
+ * Get samples for a specific operation.
79
+ */
80
+ getSamplesForOperation(operationName) {
81
+ return this.samples.filter((s) => s.operation.name === operationName);
82
+ }
83
+ /**
84
+ * Clear all samples.
85
+ */
86
+ clear() {
87
+ this.samples.length = 0;
88
+ }
89
+ };
90
+ /**
91
+ * Create an in-memory telemetry collector.
92
+ */
93
+ function createInMemoryTelemetryCollector() {
94
+ return new InMemoryTelemetryCollector();
95
+ }
96
+ /**
97
+ * No-op telemetry collector that discards all metrics.
98
+ */
99
+ const noopTelemetryCollector = { collect: async () => {} };
100
+
101
+ //#endregion
102
+ export { InMemoryTelemetryCollector, createInMemoryTelemetryCollector, noopTelemetryCollector, trackAgentStep };
103
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","names":["toolSample: OperationMetricSample","stepSample: OperationMetricSample","noopTelemetryCollector: TelemetryCollector"],"sources":["../../src/telemetry/adapter.ts"],"sourcesContent":["import type { StepResult, ToolSet } from 'ai';\n\n/**\n * Metric sample compatible with @lssm/lib.evolution OperationMetricSample.\n */\nexport interface OperationMetricSample {\n operation: { name: string; version: number };\n durationMs: number;\n success: boolean;\n timestamp: Date;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Interface for collecting telemetry metrics.\n *\n * Implementations can send metrics to:\n * - @lssm/lib.evolution for self-improvement\n * - PostHog for analytics\n * - Custom monitoring systems\n */\nexport interface TelemetryCollector {\n /**\n * Collect a metric sample.\n */\n collect(sample: OperationMetricSample): Promise<void>;\n}\n\n/**\n * Parse agent ID into name and version.\n */\nfunction parseAgentId(agentId: string): { name: string; version: number } {\n const match = agentId.match(/^(.+)\\.v(\\d+)$/);\n if (match) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return { name: match[1]!, version: parseInt(match[2]!, 10) };\n }\n return { name: agentId, version: 1 };\n}\n\n/**\n * Track an agent step for telemetry.\n *\n * Called from ContractSpecAgent.onStepFinish to feed metrics\n * to the evolution engine.\n *\n * @param collector - Telemetry collector\n * @param agentId - Agent identifier (e.g., \"support.bot.v1\")\n * @param step - AI SDK step result\n * @param durationMs - Optional step duration in milliseconds\n */\nexport async function trackAgentStep(\n collector: TelemetryCollector,\n agentId: string,\n step: StepResult<ToolSet>,\n durationMs?: number\n): Promise<void> {\n const { name, version } = parseAgentId(agentId);\n\n // Track tool invocations\n for (const toolCall of step.toolCalls ?? []) {\n const toolSample: OperationMetricSample = {\n operation: { name: `${name}.${toolCall.toolName}`, version },\n durationMs: durationMs ?? 0,\n success:\n step.toolResults?.some(\n (r) => r.toolCallId === toolCall.toolCallId && r.output !== undefined\n ) ?? false,\n timestamp: new Date(),\n metadata: {\n agentId,\n toolName: toolCall.toolName,\n finishReason: step.finishReason,\n },\n };\n await collector.collect(toolSample);\n }\n\n // Track overall step\n const stepSample: OperationMetricSample = {\n operation: { name, version },\n durationMs: durationMs ?? 0,\n success: step.finishReason !== 'error',\n timestamp: new Date(),\n metadata: {\n agentId,\n finishReason: step.finishReason,\n tokenUsage: step.usage,\n toolCallCount: step.toolCalls?.length ?? 0,\n },\n };\n await collector.collect(stepSample);\n}\n\n/**\n * In-memory telemetry collector for testing.\n */\nexport class InMemoryTelemetryCollector implements TelemetryCollector {\n private readonly samples: OperationMetricSample[] = [];\n\n async collect(sample: OperationMetricSample): Promise<void> {\n this.samples.push(sample);\n }\n\n /**\n * Get all collected samples.\n */\n getSamples(): OperationMetricSample[] {\n return [...this.samples];\n }\n\n /**\n * Get samples for a specific operation.\n */\n getSamplesForOperation(operationName: string): OperationMetricSample[] {\n return this.samples.filter((s) => s.operation.name === operationName);\n }\n\n /**\n * Clear all samples.\n */\n clear(): void {\n this.samples.length = 0;\n }\n}\n\n/**\n * Create an in-memory telemetry collector.\n */\nexport function createInMemoryTelemetryCollector(): InMemoryTelemetryCollector {\n return new InMemoryTelemetryCollector();\n}\n\n/**\n * No-op telemetry collector that discards all metrics.\n */\nexport const noopTelemetryCollector: TelemetryCollector = {\n collect: async () => {\n /* noop */\n },\n};\n"],"mappings":";;;;AA+BA,SAAS,aAAa,SAAoD;CACxE,MAAM,QAAQ,QAAQ,MAAM,iBAAiB;AAC7C,KAAI,MAEF,QAAO;EAAE,MAAM,MAAM;EAAK,SAAS,SAAS,MAAM,IAAK,GAAG;EAAE;AAE9D,QAAO;EAAE,MAAM;EAAS,SAAS;EAAG;;;;;;;;;;;;;AActC,eAAsB,eACpB,WACA,SACA,MACA,YACe;CACf,MAAM,EAAE,MAAM,YAAY,aAAa,QAAQ;AAG/C,MAAK,MAAM,YAAY,KAAK,aAAa,EAAE,EAAE;EAC3C,MAAMA,aAAoC;GACxC,WAAW;IAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAAY;IAAS;GAC5D,YAAY,cAAc;GAC1B,SACE,KAAK,aAAa,MACf,MAAM,EAAE,eAAe,SAAS,cAAc,EAAE,WAAW,OAC7D,IAAI;GACP,2BAAW,IAAI,MAAM;GACrB,UAAU;IACR;IACA,UAAU,SAAS;IACnB,cAAc,KAAK;IACpB;GACF;AACD,QAAM,UAAU,QAAQ,WAAW;;CAIrC,MAAMC,aAAoC;EACxC,WAAW;GAAE;GAAM;GAAS;EAC5B,YAAY,cAAc;EAC1B,SAAS,KAAK,iBAAiB;EAC/B,2BAAW,IAAI,MAAM;EACrB,UAAU;GACR;GACA,cAAc,KAAK;GACnB,YAAY,KAAK;GACjB,eAAe,KAAK,WAAW,UAAU;GAC1C;EACF;AACD,OAAM,UAAU,QAAQ,WAAW;;;;;AAMrC,IAAa,6BAAb,MAAsE;CACpE,AAAiB,UAAmC,EAAE;CAEtD,MAAM,QAAQ,QAA8C;AAC1D,OAAK,QAAQ,KAAK,OAAO;;;;;CAM3B,aAAsC;AACpC,SAAO,CAAC,GAAG,KAAK,QAAQ;;;;;CAM1B,uBAAuB,eAAgD;AACrE,SAAO,KAAK,QAAQ,QAAQ,MAAM,EAAE,UAAU,SAAS,cAAc;;;;;CAMvE,QAAc;AACZ,OAAK,QAAQ,SAAS;;;;;;AAO1B,SAAgB,mCAA+D;AAC7E,QAAO,IAAI,4BAA4B;;;;;AAMzC,MAAaC,yBAA6C,EACxD,SAAS,YAAY,IAGtB"}
@@ -0,0 +1,2 @@
1
+ import { InMemoryTelemetryCollector, OperationMetricSample, TelemetryCollector, createInMemoryTelemetryCollector, noopTelemetryCollector, trackAgentStep } from "./adapter.js";
2
+ export { InMemoryTelemetryCollector, OperationMetricSample, TelemetryCollector, createInMemoryTelemetryCollector, noopTelemetryCollector, trackAgentStep };
@@ -1 +1,3 @@
1
- import{InMemoryTelemetryCollector as e,createInMemoryTelemetryCollector as t,noopTelemetryCollector as n,trackAgentStep as r}from"./adapter.js";export{e as InMemoryTelemetryCollector,t as createInMemoryTelemetryCollector,n as noopTelemetryCollector,r as trackAgentStep};
1
+ import { InMemoryTelemetryCollector, createInMemoryTelemetryCollector, noopTelemetryCollector, trackAgentStep } from "./adapter.js";
2
+
3
+ export { InMemoryTelemetryCollector, createInMemoryTelemetryCollector, noopTelemetryCollector, trackAgentStep };
@@ -0,0 +1,5 @@
1
+ import { buildToolHandlers, createToolHandler, specToolToAISDKTool, specToolsToAISDKTools } from "./tool-adapter.js";
2
+ import { createKnowledgeQueryTool } from "./knowledge-tool.js";
3
+ import { McpClientConfig, McpClientResult, createMcpToolsets, mcpServerToTools } from "./mcp-client.js";
4
+ import { AgentMcpServerConfig, agentToMcpServer, createAgentMcpServer } from "./mcp-server.js";
5
+ export { AgentMcpServerConfig, McpClientConfig, McpClientResult, agentToMcpServer, buildToolHandlers, createAgentMcpServer, createKnowledgeQueryTool, createMcpToolsets, createToolHandler, mcpServerToTools, specToolToAISDKTool, specToolsToAISDKTools };
@@ -1 +1,6 @@
1
- import{buildToolHandlers as e,createToolHandler as t,specToolToAISDKTool as n,specToolsToAISDKTools as r}from"./tool-adapter.js";import{createKnowledgeQueryTool as i}from"./knowledge-tool.js";import{createMcpToolsets as a,mcpServerToTools as o}from"./mcp-client.js";import{agentToMcpServer as s,createAgentMcpServer as c}from"./mcp-server.js";export{s as agentToMcpServer,e as buildToolHandlers,c as createAgentMcpServer,i as createKnowledgeQueryTool,a as createMcpToolsets,t as createToolHandler,o as mcpServerToTools,n as specToolToAISDKTool,r as specToolsToAISDKTools};
1
+ import { buildToolHandlers, createToolHandler, specToolToAISDKTool, specToolsToAISDKTools } from "./tool-adapter.js";
2
+ import { createKnowledgeQueryTool } from "./knowledge-tool.js";
3
+ import { createMcpToolsets, mcpServerToTools } from "./mcp-client.js";
4
+ import { agentToMcpServer, createAgentMcpServer } from "./mcp-server.js";
5
+
6
+ export { agentToMcpServer, buildToolHandlers, createAgentMcpServer, createKnowledgeQueryTool, createMcpToolsets, createToolHandler, mcpServerToTools, specToolToAISDKTool, specToolsToAISDKTools };
@@ -0,0 +1,21 @@
1
+ import { AgentKnowledgeRef } from "../spec/spec.js";
2
+ import { Tool } from "ai";
3
+ import { KnowledgeRetriever } from "@lssm/lib.knowledge/retriever";
4
+
5
+ //#region src/tools/knowledge-tool.d.ts
6
+
7
+ /**
8
+ * Create a knowledge query tool for dynamic RAG.
9
+ *
10
+ * This tool allows the agent to query optional knowledge spaces
11
+ * at runtime. Required knowledge is injected statically via
12
+ * the knowledge injector.
13
+ *
14
+ * @param retriever - The knowledge retriever to use
15
+ * @param knowledgeRefs - Knowledge references from the agent spec
16
+ * @returns AI SDK CoreTool for knowledge queries
17
+ */
18
+ declare function createKnowledgeQueryTool(retriever: KnowledgeRetriever, knowledgeRefs: AgentKnowledgeRef[]): Tool<any, any> | null;
19
+ //#endregion
20
+ export { createKnowledgeQueryTool };
21
+ //# sourceMappingURL=knowledge-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge-tool.d.ts","names":[],"sources":["../../src/tools/knowledge-tool.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAgBA;;;;;;;;;iBAAgB,wBAAA,YACH,mCACI,sBAEd"}
@@ -1,9 +1,54 @@
1
- import{tool as e}from"ai";import*as t from"zod";function n(n,r){let i=r.filter(e=>!e.required).map(e=>e.key).filter(e=>n.supportsSpace(e));return i.length===0?null:e({description:`Query knowledge bases for relevant information. Use this tool when you need to look up specific information that may not be in your context.
1
+ import { tool } from "ai";
2
+ import * as z$1 from "zod";
2
3
 
3
- Available knowledge spaces:
4
- ${r.filter(e=>!e.required&&n.supportsSpace(e.key)).map(e=>`- ${e.key}: ${e.instructions??`Knowledge space`}`).join(`
5
- `)}`,inputSchema:t.object({query:t.string().describe(`The question or search query to find relevant information`),spaceKey:t.enum(i).optional().describe(`Specific knowledge space to query. If omitted, searches all available spaces.`),topK:t.number().optional().default(5).describe(`Maximum number of results to return`)}),execute:async({query:e,spaceKey:t,topK:r})=>{let a=t?[t]:i,o=[];for(let t of a)try{let i=await n.retrieve(e,{spaceKey:t,topK:r??5});for(let e of i)o.push({space:t,content:e.content,score:e.score})}catch(e){console.warn(`Failed to query knowledge space ${t}:`,e)}return o.length===0?`No relevant information found in the knowledge bases.`:(o.sort((e,t)=>t.score-e.score),o.slice(0,r??5).map((e,t)=>`[Source ${t+1} - ${e.space}] (relevance: ${(e.score*100).toFixed(0)}%)\n${e.content}`).join(`
4
+ //#region src/tools/knowledge-tool.ts
5
+ /**
6
+ * Create a knowledge query tool for dynamic RAG.
7
+ *
8
+ * This tool allows the agent to query optional knowledge spaces
9
+ * at runtime. Required knowledge is injected statically via
10
+ * the knowledge injector.
11
+ *
12
+ * @param retriever - The knowledge retriever to use
13
+ * @param knowledgeRefs - Knowledge references from the agent spec
14
+ * @returns AI SDK CoreTool for knowledge queries
15
+ */
16
+ function createKnowledgeQueryTool(retriever, knowledgeRefs) {
17
+ const optionalSpaces = knowledgeRefs.filter((k) => !k.required).map((k) => k.key).filter((key) => retriever.supportsSpace(key));
18
+ if (optionalSpaces.length === 0) return null;
19
+ return tool({
20
+ description: `Query knowledge bases for relevant information. Use this tool when you need to look up specific information that may not be in your context.
6
21
 
7
- ---
22
+ Available knowledge spaces:
23
+ ${knowledgeRefs.filter((k) => !k.required && retriever.supportsSpace(k.key)).map((k) => `- ${k.key}: ${k.instructions ?? "Knowledge space"}`).join("\n")}`,
24
+ inputSchema: z$1.object({
25
+ query: z$1.string().describe("The question or search query to find relevant information"),
26
+ spaceKey: z$1.enum(optionalSpaces).optional().describe("Specific knowledge space to query. If omitted, searches all available spaces."),
27
+ topK: z$1.number().optional().default(5).describe("Maximum number of results to return")
28
+ }),
29
+ execute: async ({ query, spaceKey, topK }) => {
30
+ const spacesToSearch = spaceKey ? [spaceKey] : optionalSpaces;
31
+ const allResults = [];
32
+ for (const space of spacesToSearch) try {
33
+ const results = await retriever.retrieve(query, {
34
+ spaceKey: space,
35
+ topK: topK ?? 5
36
+ });
37
+ for (const result of results) allResults.push({
38
+ space,
39
+ content: result.content,
40
+ score: result.score
41
+ });
42
+ } catch (error) {
43
+ console.warn(`Failed to query knowledge space ${space}:`, error);
44
+ }
45
+ if (allResults.length === 0) return "No relevant information found in the knowledge bases.";
46
+ allResults.sort((a, b) => b.score - a.score);
47
+ return allResults.slice(0, topK ?? 5).map((r, i) => `[Source ${i + 1} - ${r.space}] (relevance: ${(r.score * 100).toFixed(0)}%)\n${r.content}`).join("\n\n---\n\n");
48
+ }
49
+ });
50
+ }
8
51
 
9
- `))}})}export{n as createKnowledgeQueryTool};
52
+ //#endregion
53
+ export { createKnowledgeQueryTool };
54
+ //# sourceMappingURL=knowledge-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge-tool.js","names":["z","allResults: { space: string; content: string; score: number }[]"],"sources":["../../src/tools/knowledge-tool.ts"],"sourcesContent":["import { tool, type Tool } from 'ai';\nimport * as z from 'zod';\nimport type { KnowledgeRetriever } from '@lssm/lib.knowledge/retriever';\nimport type { AgentKnowledgeRef } from '../spec/spec';\n\n/**\n * Create a knowledge query tool for dynamic RAG.\n *\n * This tool allows the agent to query optional knowledge spaces\n * at runtime. Required knowledge is injected statically via\n * the knowledge injector.\n *\n * @param retriever - The knowledge retriever to use\n * @param knowledgeRefs - Knowledge references from the agent spec\n * @returns AI SDK CoreTool for knowledge queries\n */\nexport function createKnowledgeQueryTool(\n retriever: KnowledgeRetriever,\n knowledgeRefs: AgentKnowledgeRef[]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): Tool<any, any> | null {\n // Only include optional (non-required) knowledge spaces\n const optionalSpaces = knowledgeRefs\n .filter((k) => !k.required)\n .map((k) => k.key)\n .filter((key) => retriever.supportsSpace(key));\n\n if (optionalSpaces.length === 0) {\n return null;\n }\n\n // Build space descriptions for the tool\n const spaceDescriptions = knowledgeRefs\n .filter((k) => !k.required && retriever.supportsSpace(k.key))\n .map((k) => `- ${k.key}: ${k.instructions ?? 'Knowledge space'}`)\n .join('\\n');\n\n return tool({\n description: `Query knowledge bases for relevant information. Use this tool when you need to look up specific information that may not be in your context.\n\nAvailable knowledge spaces:\n${spaceDescriptions}`,\n // AI SDK v6 uses inputSchema instead of parameters\n inputSchema: z.object({\n query: z\n .string()\n .describe('The question or search query to find relevant information'),\n spaceKey: z\n .enum(optionalSpaces as [string, ...string[]])\n .optional()\n .describe(\n 'Specific knowledge space to query. If omitted, searches all available spaces.'\n ),\n topK: z\n .number()\n .optional()\n .default(5)\n .describe('Maximum number of results to return'),\n }),\n execute: async ({ query, spaceKey, topK }) => {\n const spacesToSearch = spaceKey ? [spaceKey] : optionalSpaces;\n const allResults: { space: string; content: string; score: number }[] =\n [];\n\n for (const space of spacesToSearch) {\n try {\n const results = await retriever.retrieve(query, {\n spaceKey: space,\n topK: topK ?? 5,\n });\n\n for (const result of results) {\n allResults.push({\n space,\n content: result.content,\n score: result.score,\n });\n }\n } catch (error) {\n // Log but don't fail on individual space errors\n console.warn(`Failed to query knowledge space ${space}:`, error);\n }\n }\n\n if (allResults.length === 0) {\n return 'No relevant information found in the knowledge bases.';\n }\n\n // Sort by score and format results\n allResults.sort((a, b) => b.score - a.score);\n const topResults = allResults.slice(0, topK ?? 5);\n\n return topResults\n .map(\n (r, i) =>\n `[Source ${i + 1} - ${r.space}] (relevance: ${(r.score * 100).toFixed(0)}%)\\n${r.content}`\n )\n .join('\\n\\n---\\n\\n');\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,SAAgB,yBACd,WACA,eAEuB;CAEvB,MAAM,iBAAiB,cACpB,QAAQ,MAAM,CAAC,EAAE,SAAS,CAC1B,KAAK,MAAM,EAAE,IAAI,CACjB,QAAQ,QAAQ,UAAU,cAAc,IAAI,CAAC;AAEhD,KAAI,eAAe,WAAW,EAC5B,QAAO;AAST,QAAO,KAAK;EACV,aAAa;;;EANW,cACvB,QAAQ,MAAM,CAAC,EAAE,YAAY,UAAU,cAAc,EAAE,IAAI,CAAC,CAC5D,KAAK,MAAM,KAAK,EAAE,IAAI,IAAI,EAAE,gBAAgB,oBAAoB,CAChE,KAAK,KAAK;EAQX,aAAaA,IAAE,OAAO;GACpB,OAAOA,IACJ,QAAQ,CACR,SAAS,4DAA4D;GACxE,UAAUA,IACP,KAAK,eAAwC,CAC7C,UAAU,CACV,SACC,gFACD;GACH,MAAMA,IACH,QAAQ,CACR,UAAU,CACV,QAAQ,EAAE,CACV,SAAS,sCAAsC;GACnD,CAAC;EACF,SAAS,OAAO,EAAE,OAAO,UAAU,WAAW;GAC5C,MAAM,iBAAiB,WAAW,CAAC,SAAS,GAAG;GAC/C,MAAMC,aACJ,EAAE;AAEJ,QAAK,MAAM,SAAS,eAClB,KAAI;IACF,MAAM,UAAU,MAAM,UAAU,SAAS,OAAO;KAC9C,UAAU;KACV,MAAM,QAAQ;KACf,CAAC;AAEF,SAAK,MAAM,UAAU,QACnB,YAAW,KAAK;KACd;KACA,SAAS,OAAO;KAChB,OAAO,OAAO;KACf,CAAC;YAEG,OAAO;AAEd,YAAQ,KAAK,mCAAmC,MAAM,IAAI,MAAM;;AAIpE,OAAI,WAAW,WAAW,EACxB,QAAO;AAIT,cAAW,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;AAG5C,UAFmB,WAAW,MAAM,GAAG,QAAQ,EAAE,CAG9C,KACE,GAAG,MACF,WAAW,IAAI,EAAE,KAAK,EAAE,MAAM,iBAAiB,EAAE,QAAQ,KAAK,QAAQ,EAAE,CAAC,MAAM,EAAE,UACpF,CACA,KAAK,cAAc;;EAEzB,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { Tool } from "ai";
2
+
3
+ //#region src/tools/mcp-client.d.ts
4
+
5
+ /**
6
+ * Configuration for connecting to an MCP server.
7
+ */
8
+ interface McpClientConfig {
9
+ /** Display name for the MCP server */
10
+ name: string;
11
+ /** Command to spawn the MCP server process */
12
+ command: string;
13
+ /** Arguments to pass to the command */
14
+ args?: string[];
15
+ /** Environment variables for the process */
16
+ env?: Record<string, string>;
17
+ }
18
+ /**
19
+ * Result of creating an MCP client with tools.
20
+ */
21
+ interface McpClientResult {
22
+ /** AI SDK tools from the MCP server */
23
+ tools: Record<string, Tool<unknown, unknown>>;
24
+ /** Cleanup function to close the connection */
25
+ cleanup: () => Promise<void>;
26
+ }
27
+ /**
28
+ * Create AI SDK tools from an MCP server.
29
+ *
30
+ * This adapter allows ContractSpec agents to consume tools
31
+ * from external MCP servers (e.g., filesystem, database, etc.).
32
+ *
33
+ * @param config - MCP server configuration
34
+ * @returns Tools and cleanup function
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const { tools, cleanup } = await mcpServerToTools({
39
+ * name: 'filesystem',
40
+ * command: 'npx',
41
+ * args: ['-y', '@modelcontextprotocol/server-filesystem', '/path'],
42
+ * });
43
+ *
44
+ * // Use tools in agent...
45
+ *
46
+ * await cleanup();
47
+ * ```
48
+ */
49
+ declare function mcpServerToTools(config: McpClientConfig): Promise<McpClientResult>;
50
+ /**
51
+ * Create multiple MCP tool sets from configurations.
52
+ *
53
+ * @param configs - Array of MCP server configurations
54
+ * @returns Combined tools and cleanup function
55
+ */
56
+ declare function createMcpToolsets(configs: McpClientConfig[]): Promise<McpClientResult>;
57
+ //#endregion
58
+ export { McpClientConfig, McpClientResult, createMcpToolsets, mcpServerToTools };
59
+ //# sourceMappingURL=mcp-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client.d.ts","names":[],"sources":["../../src/tools/mcp-client.ts"],"sourcesContent":[],"mappings":";;;;;;AAOA;AAciB,UAdA,eAAA,CAce;EAER;EAAf,IAAA,EAAA,MAAA;EAEQ;EAAO,OAAA,EAAA,MAAA;EAyBF;EACZ,IAAA,CAAA,EAAA,MAAA,EAAA;EACC;EAAR,GAAA,CAAA,EArCK,MAqCL,CAAA,MAAA,EAAA,MAAA,CAAA;;AAsBH;;;AAEG,UAvDc,eAAA,CAuDd;EAAO;SArDD,eAAe;;iBAEP;;;;;;;;;;;;;;;;;;;;;;;;iBAyBK,gBAAA,SACZ,kBACP,QAAQ;;;;;;;iBAsBW,iBAAA,UACX,oBACR,QAAQ"}
@@ -1 +1,58 @@
1
- import{experimental_createMCPClient as e}from"@ai-sdk/mcp";import{Experimental_StdioMCPTransport as t}from"@ai-sdk/mcp/mcp-stdio";async function n(n){let r=await e({transport:new t({command:n.command,args:n.args,env:n.env})});return{tools:await r.tools(),cleanup:()=>r.close()}}async function r(e){let t=await Promise.all(e.map(n)),r={};for(let e of t)Object.assign(r,e.tools);return{tools:r,cleanup:async()=>{await Promise.all(t.map(e=>e.cleanup()))}}}export{r as createMcpToolsets,n as mcpServerToTools};
1
+ import { experimental_createMCPClient } from "@ai-sdk/mcp";
2
+ import { Experimental_StdioMCPTransport } from "@ai-sdk/mcp/mcp-stdio";
3
+
4
+ //#region src/tools/mcp-client.ts
5
+ /**
6
+ * Create AI SDK tools from an MCP server.
7
+ *
8
+ * This adapter allows ContractSpec agents to consume tools
9
+ * from external MCP servers (e.g., filesystem, database, etc.).
10
+ *
11
+ * @param config - MCP server configuration
12
+ * @returns Tools and cleanup function
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const { tools, cleanup } = await mcpServerToTools({
17
+ * name: 'filesystem',
18
+ * command: 'npx',
19
+ * args: ['-y', '@modelcontextprotocol/server-filesystem', '/path'],
20
+ * });
21
+ *
22
+ * // Use tools in agent...
23
+ *
24
+ * await cleanup();
25
+ * ```
26
+ */
27
+ async function mcpServerToTools(config) {
28
+ const client = await experimental_createMCPClient({ transport: new Experimental_StdioMCPTransport({
29
+ command: config.command,
30
+ args: config.args,
31
+ env: config.env
32
+ }) });
33
+ return {
34
+ tools: await client.tools(),
35
+ cleanup: () => client.close()
36
+ };
37
+ }
38
+ /**
39
+ * Create multiple MCP tool sets from configurations.
40
+ *
41
+ * @param configs - Array of MCP server configurations
42
+ * @returns Combined tools and cleanup function
43
+ */
44
+ async function createMcpToolsets(configs) {
45
+ const results = await Promise.all(configs.map(mcpServerToTools));
46
+ const combinedTools = {};
47
+ for (const result of results) Object.assign(combinedTools, result.tools);
48
+ return {
49
+ tools: combinedTools,
50
+ cleanup: async () => {
51
+ await Promise.all(results.map((r) => r.cleanup()));
52
+ }
53
+ };
54
+ }
55
+
56
+ //#endregion
57
+ export { createMcpToolsets, mcpServerToTools };
58
+ //# sourceMappingURL=mcp-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client.js","names":["StdioClientTransport","combinedTools: Record<string, Tool<unknown, unknown>>"],"sources":["../../src/tools/mcp-client.ts"],"sourcesContent":["import { experimental_createMCPClient } from '@ai-sdk/mcp';\nimport { Experimental_StdioMCPTransport as StdioClientTransport } from '@ai-sdk/mcp/mcp-stdio';\nimport type { Tool } from 'ai';\n\n/**\n * Configuration for connecting to an MCP server.\n */\nexport interface McpClientConfig {\n /** Display name for the MCP server */\n name: string;\n /** Command to spawn the MCP server process */\n command: string;\n /** Arguments to pass to the command */\n args?: string[];\n /** Environment variables for the process */\n env?: Record<string, string>;\n}\n\n/**\n * Result of creating an MCP client with tools.\n */\nexport interface McpClientResult {\n /** AI SDK tools from the MCP server */\n tools: Record<string, Tool<unknown, unknown>>;\n /** Cleanup function to close the connection */\n cleanup: () => Promise<void>;\n}\n\n/**\n * Create AI SDK tools from an MCP server.\n *\n * This adapter allows ContractSpec agents to consume tools\n * from external MCP servers (e.g., filesystem, database, etc.).\n *\n * @param config - MCP server configuration\n * @returns Tools and cleanup function\n *\n * @example\n * ```typescript\n * const { tools, cleanup } = await mcpServerToTools({\n * name: 'filesystem',\n * command: 'npx',\n * args: ['-y', '@modelcontextprotocol/server-filesystem', '/path'],\n * });\n *\n * // Use tools in agent...\n *\n * await cleanup();\n * ```\n */\nexport async function mcpServerToTools(\n config: McpClientConfig\n): Promise<McpClientResult> {\n const transport = new StdioClientTransport({\n command: config.command,\n args: config.args,\n env: config.env,\n });\n\n const client = await experimental_createMCPClient({ transport });\n const tools = await client.tools();\n\n return {\n tools: tools as Record<string, Tool<unknown, unknown>>,\n cleanup: () => client.close(),\n };\n}\n\n/**\n * Create multiple MCP tool sets from configurations.\n *\n * @param configs - Array of MCP server configurations\n * @returns Combined tools and cleanup function\n */\nexport async function createMcpToolsets(\n configs: McpClientConfig[]\n): Promise<McpClientResult> {\n const results = await Promise.all(configs.map(mcpServerToTools));\n\n const combinedTools: Record<string, Tool<unknown, unknown>> = {};\n for (const result of results) {\n Object.assign(combinedTools, result.tools);\n }\n\n return {\n tools: combinedTools,\n cleanup: async () => {\n await Promise.all(results.map((r) => r.cleanup()));\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,eAAsB,iBACpB,QAC0B;CAO1B,MAAM,SAAS,MAAM,6BAA6B,EAAE,WANlC,IAAIA,+BAAqB;EACzC,SAAS,OAAO;EAChB,MAAM,OAAO;EACb,KAAK,OAAO;EACb,CAAC,EAE6D,CAAC;AAGhE,QAAO;EACL,OAHY,MAAM,OAAO,OAAO;EAIhC,eAAe,OAAO,OAAO;EAC9B;;;;;;;;AASH,eAAsB,kBACpB,SAC0B;CAC1B,MAAM,UAAU,MAAM,QAAQ,IAAI,QAAQ,IAAI,iBAAiB,CAAC;CAEhE,MAAMC,gBAAwD,EAAE;AAChE,MAAK,MAAM,UAAU,QACnB,QAAO,OAAO,eAAe,OAAO,MAAM;AAG5C,QAAO;EACL,OAAO;EACP,SAAS,YAAY;AACnB,SAAM,QAAQ,IAAI,QAAQ,KAAK,MAAM,EAAE,SAAS,CAAC,CAAC;;EAErD"}
@@ -0,0 +1,46 @@
1
+ import { AgentSpec } from "../spec/spec.js";
2
+ import { ContractSpecAgent } from "../agent/contract-spec-agent.js";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+
5
+ //#region src/tools/mcp-server.d.ts
6
+
7
+ /**
8
+ * Generate an MCP server that exposes a ContractSpec agent as a tool.
9
+ *
10
+ * This allows other AI agents (e.g., Claude Desktop, Cursor) to use
11
+ * your ContractSpec agents as tools, enabling agent-to-agent composition.
12
+ *
13
+ * @param agent - The ContractSpec agent to expose
14
+ * @param spec - The agent specification
15
+ * @returns MCP Server instance
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const server = agentToMcpServer(myAgent, myAgentSpec);
20
+ *
21
+ * // Run via stdio transport
22
+ * const transport = new StdioServerTransport();
23
+ * await server.connect(transport);
24
+ * ```
25
+ */
26
+ declare function agentToMcpServer(agent: ContractSpecAgent, spec: AgentSpec): McpServer;
27
+ /**
28
+ * Configuration for running an agent as an MCP server.
29
+ */
30
+ interface AgentMcpServerConfig {
31
+ /** The agent to expose */
32
+ agent: ContractSpecAgent;
33
+ /** The agent specification */
34
+ spec: AgentSpec;
35
+ /** Optional server name override */
36
+ name?: string;
37
+ /** Optional version override */
38
+ version?: string;
39
+ }
40
+ /**
41
+ * Create an MCP server from configuration.
42
+ */
43
+ declare function createAgentMcpServer(config: AgentMcpServerConfig): McpServer;
44
+ //#endregion
45
+ export { AgentMcpServerConfig, agentToMcpServer, createAgentMcpServer };
46
+ //# sourceMappingURL=mcp-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.d.ts","names":[],"sources":["../../src/tools/mcp-server.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAyBA;;;;;AA+EA;AAcA;;;;;;;;;;;iBA7FgB,gBAAA,QACP,yBACD,YACL;;;;UA4Ec,oBAAA;;SAER;;QAED;;;;;;;;;iBAUQ,oBAAA,SAA6B,uBAAuB"}
@@ -1 +1,69 @@
1
- import{jsonSchemaToZodSafe as e}from"../schema/json-schema-to-zod.js";import*as t from"zod";import{McpServer as n}from"@modelcontextprotocol/sdk/server/mcp.js";function r(r,i){let a=new n({name:i.meta.name,version:`${i.meta.version}`});a.registerTool(i.meta.name,{description:i.description??`Interact with ${i.meta.name} agent`,inputSchema:t.object({message:t.string().describe(`The message or query to send to the agent`),sessionId:t.string().optional().describe(`Optional session ID to continue a conversation`)})},async e=>{let{message:t,sessionId:n}=e;return{content:[{type:`text`,text:(await r.generate({prompt:t,options:{sessionId:n}})).text}]}});for(let n of i.tools){let o=n.schema?e(n.schema):t.object({});a.registerTool(`${i.meta.name}.${n.name}`,{description:n.description??`Execute ${n.name} tool`,inputSchema:o},async e=>({content:[{type:`text`,text:(await r.generate({prompt:`Execute the ${n.name} tool with the following arguments: ${JSON.stringify(e)}`})).text}]}))}return a}function i(e){return r(e.agent,e.spec)}export{r as agentToMcpServer,i as createAgentMcpServer};
1
+ import { jsonSchemaToZodSafe } from "../schema/json-schema-to-zod.js";
2
+ import * as z$1 from "zod";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+
5
+ //#region src/tools/mcp-server.ts
6
+ /**
7
+ * Generate an MCP server that exposes a ContractSpec agent as a tool.
8
+ *
9
+ * This allows other AI agents (e.g., Claude Desktop, Cursor) to use
10
+ * your ContractSpec agents as tools, enabling agent-to-agent composition.
11
+ *
12
+ * @param agent - The ContractSpec agent to expose
13
+ * @param spec - The agent specification
14
+ * @returns MCP Server instance
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const server = agentToMcpServer(myAgent, myAgentSpec);
19
+ *
20
+ * // Run via stdio transport
21
+ * const transport = new StdioServerTransport();
22
+ * await server.connect(transport);
23
+ * ```
24
+ */
25
+ function agentToMcpServer(agent, spec) {
26
+ const server = new McpServer({
27
+ name: spec.meta.key,
28
+ version: `${spec.meta.version}`
29
+ });
30
+ server.registerTool(spec.meta.key, {
31
+ description: spec.description ?? `Interact with ${spec.meta.key} agent`,
32
+ inputSchema: z$1.object({
33
+ message: z$1.string().describe("The message or query to send to the agent"),
34
+ sessionId: z$1.string().optional().describe("Optional session ID to continue a conversation")
35
+ })
36
+ }, async (args) => {
37
+ const { message, sessionId } = args;
38
+ return { content: [{
39
+ type: "text",
40
+ text: (await agent.generate({
41
+ prompt: message,
42
+ options: { sessionId }
43
+ })).text
44
+ }] };
45
+ });
46
+ for (const toolConfig of spec.tools) {
47
+ const inputSchema = toolConfig.schema ? jsonSchemaToZodSafe(toolConfig.schema) : z$1.object({});
48
+ server.registerTool(`${spec.meta.key}.${toolConfig.name}`, {
49
+ description: toolConfig.description ?? `Execute ${toolConfig.name} tool`,
50
+ inputSchema
51
+ }, async (args) => {
52
+ return { content: [{
53
+ type: "text",
54
+ text: (await agent.generate({ prompt: `Execute the ${toolConfig.name} tool with the following arguments: ${JSON.stringify(args)}` })).text
55
+ }] };
56
+ });
57
+ }
58
+ return server;
59
+ }
60
+ /**
61
+ * Create an MCP server from configuration.
62
+ */
63
+ function createAgentMcpServer(config) {
64
+ return agentToMcpServer(config.agent, config.spec);
65
+ }
66
+
67
+ //#endregion
68
+ export { agentToMcpServer, createAgentMcpServer };
69
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","names":["z"],"sources":["../../src/tools/mcp-server.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport * as z from 'zod';\nimport type { AgentSpec } from '../spec/spec';\nimport type { ContractSpecAgent } from '../agent/contract-spec-agent';\nimport { jsonSchemaToZodSafe } from '../schema/json-schema-to-zod';\n\n/**\n * Generate an MCP server that exposes a ContractSpec agent as a tool.\n *\n * This allows other AI agents (e.g., Claude Desktop, Cursor) to use\n * your ContractSpec agents as tools, enabling agent-to-agent composition.\n *\n * @param agent - The ContractSpec agent to expose\n * @param spec - The agent specification\n * @returns MCP Server instance\n *\n * @example\n * ```typescript\n * const server = agentToMcpServer(myAgent, myAgentSpec);\n *\n * // Run via stdio transport\n * const transport = new StdioServerTransport();\n * await server.connect(transport);\n * ```\n */\nexport function agentToMcpServer(\n agent: ContractSpecAgent,\n spec: AgentSpec\n): McpServer {\n const server = new McpServer({\n name: spec.meta.key,\n version: `${spec.meta.version}`,\n });\n\n // Expose agent as a conversational tool using registerTool\n server.registerTool(\n spec.meta.key,\n {\n description: spec.description ?? `Interact with ${spec.meta.key} agent`,\n inputSchema: z.object({\n message: z\n .string()\n .describe('The message or query to send to the agent'),\n sessionId: z\n .string()\n .optional()\n .describe('Optional session ID to continue a conversation'),\n }),\n },\n async (args) => {\n const { message, sessionId } = args;\n\n const result = await agent.generate({\n prompt: message,\n options: { sessionId },\n });\n\n return {\n content: [\n {\n type: 'text',\n text: result.text,\n },\n ],\n };\n }\n );\n\n // Expose individual tools from the agent spec\n for (const toolConfig of spec.tools) {\n const inputSchema = toolConfig.schema\n ? jsonSchemaToZodSafe(toolConfig.schema)\n : z.object({});\n\n server.registerTool(\n `${spec.meta.key}.${toolConfig.name}`,\n {\n description:\n toolConfig.description ?? `Execute ${toolConfig.name} tool`,\n inputSchema,\n },\n async (args) => {\n const result = await agent.generate({\n prompt: `Execute the ${toolConfig.name} tool with the following arguments: ${JSON.stringify(args)}`,\n });\n\n return {\n content: [\n {\n type: 'text',\n text: result.text,\n },\n ],\n };\n }\n );\n }\n\n return server;\n}\n\n/**\n * Configuration for running an agent as an MCP server.\n */\nexport interface AgentMcpServerConfig {\n /** The agent to expose */\n agent: ContractSpecAgent;\n /** The agent specification */\n spec: AgentSpec;\n /** Optional server name override */\n name?: string;\n /** Optional version override */\n version?: string;\n}\n\n/**\n * Create an MCP server from configuration.\n */\nexport function createAgentMcpServer(config: AgentMcpServerConfig): McpServer {\n return agentToMcpServer(config.agent, config.spec);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,iBACd,OACA,MACW;CACX,MAAM,SAAS,IAAI,UAAU;EAC3B,MAAM,KAAK,KAAK;EAChB,SAAS,GAAG,KAAK,KAAK;EACvB,CAAC;AAGF,QAAO,aACL,KAAK,KAAK,KACV;EACE,aAAa,KAAK,eAAe,iBAAiB,KAAK,KAAK,IAAI;EAChE,aAAaA,IAAE,OAAO;GACpB,SAASA,IACN,QAAQ,CACR,SAAS,4CAA4C;GACxD,WAAWA,IACR,QAAQ,CACR,UAAU,CACV,SAAS,iDAAiD;GAC9D,CAAC;EACH,EACD,OAAO,SAAS;EACd,MAAM,EAAE,SAAS,cAAc;AAO/B,SAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,OATS,MAAM,MAAM,SAAS;IAClC,QAAQ;IACR,SAAS,EAAE,WAAW;IACvB,CAAC,EAMiB;GACd,CACF,EACF;GAEJ;AAGD,MAAK,MAAM,cAAc,KAAK,OAAO;EACnC,MAAM,cAAc,WAAW,SAC3B,oBAAoB,WAAW,OAAO,GACtCA,IAAE,OAAO,EAAE,CAAC;AAEhB,SAAO,aACL,GAAG,KAAK,KAAK,IAAI,GAAG,WAAW,QAC/B;GACE,aACE,WAAW,eAAe,WAAW,WAAW,KAAK;GACvD;GACD,EACD,OAAO,SAAS;AAKd,UAAO,EACL,SAAS,CACP;IACE,MAAM;IACN,OARS,MAAM,MAAM,SAAS,EAClC,QAAQ,eAAe,WAAW,KAAK,sCAAsC,KAAK,UAAU,KAAK,IAClG,CAAC,EAMiB;IACd,CACF,EACF;IAEJ;;AAGH,QAAO;;;;;AAoBT,SAAgB,qBAAqB,QAAyC;AAC5E,QAAO,iBAAiB,OAAO,OAAO,OAAO,KAAK"}
@@ -0,0 +1,50 @@
1
+ import { AgentToolConfig } from "../spec/spec.js";
2
+ import { ToolExecutionContext, ToolHandler } from "../types.js";
3
+ import { Tool } from "ai";
4
+
5
+ //#region src/tools/tool-adapter.d.ts
6
+
7
+ /**
8
+ * Convert ContractSpec AgentToolConfig to AI SDK CoreTool.
9
+ *
10
+ * @param specTool - The tool configuration from AgentSpec
11
+ * @param handler - The handler function for the tool
12
+ * @param context - Partial context to inject into handler calls
13
+ * @returns AI SDK CoreTool
14
+ */
15
+ declare function specToolToAISDKTool(specTool: AgentToolConfig, handler: ToolHandler, context?: Partial<ToolExecutionContext>): Tool<any, any>;
16
+ /**
17
+ * Convert multiple ContractSpec tool configs to AI SDK tools.
18
+ *
19
+ * @param specTools - Array of tool configurations
20
+ * @param handlers - Map of tool name to handler function
21
+ * @param context - Partial context to inject into handler calls
22
+ * @returns Record of AI SDK tools keyed by name
23
+ */
24
+ declare function specToolsToAISDKTools(specTools: AgentToolConfig[], handlers: Map<string, ToolHandler>, context?: Partial<ToolExecutionContext>): Record<string, Tool<any, any>>;
25
+ /**
26
+ * Type-safe tool handler builder.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const handler = createToolHandler<{ query: string }>((input, ctx) => {
31
+ * return `Searched for: ${input.query}`;
32
+ * });
33
+ * ```
34
+ */
35
+ declare function createToolHandler<TInput = unknown, TOutput = string>(handler: (input: TInput, context: ToolExecutionContext) => Promise<TOutput> | TOutput): ToolHandler<TInput, TOutput>;
36
+ /**
37
+ * Build a tool handlers map from an object.
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * const handlers = buildToolHandlers({
42
+ * search: async (input: { query: string }) => `Found: ${input.query}`,
43
+ * calculate: async (input: { a: number, b: number }) => `${input.a + input.b}`,
44
+ * });
45
+ * ```
46
+ */
47
+ declare function buildToolHandlers(handlersObj: Record<string, ToolHandler>): Map<string, ToolHandler>;
48
+ //#endregion
49
+ export { buildToolHandlers, createToolHandler, specToolToAISDKTool, specToolsToAISDKTools };
50
+ //# sourceMappingURL=tool-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-adapter.d.ts","names":[],"sources":["../../src/tools/tool-adapter.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAcA;;;;;;AAIO,iBAJS,mBAAA,CAIT,QAAA,EAHK,eAGL,EAAA,OAAA,EAFI,WAEJ,EAAA,OAAA,CAAA,EADI,OACJ,CADY,oBACZ,CAAA,CAAA,EAAJ,IAAI,CAAA,GAAA,EAAA,GAAA,CAAA;AA6BP;;;;;;;;AAIS,iBAJO,qBAAA,CAIP,SAAA,EAHI,eAGJ,EAAA,EAAA,QAAA,EAFG,GAEH,CAAA,MAAA,EAFe,WAEf,CAAA,EAAA,OAAA,CAAA,EADE,OACF,CADU,oBACV,CAAA,CAAA,EAAN,MAAM,CAAA,MAAA,EAAS,IAAT,CAAA,GAAA,EAAA,GAAA,CAAA,CAAA;AAyBT;;;;;;;;;;AAsBgB,iBAtBA,iBAsBiB,CAAA,SAAA,OAAA,EAAA,UAAA,MAAA,CAAA,CAAA,OAAA,EAAA,CAAA,KAAA,EApBtB,MAoBsB,EAAA,OAAA,EAnBpB,oBAmBoB,EAAA,GAlB1B,OAkB0B,CAlBlB,OAkBkB,CAAA,GAlBP,OAkBO,CAAA,EAjB9B,WAiB8B,CAjBlB,MAiBkB,EAjBV,OAiBU,CAAA;;;;;;;;;;;;iBAAjB,iBAAA,cACD,eAAe,eAC3B,YAAY"}
@@ -1 +1,80 @@
1
- import{jsonSchemaToZodSafe as e}from"../schema/json-schema-to-zod.js";import{tool as t}from"ai";function n(n,r,i={}){return t({description:n.description??n.name,inputSchema:e(n.schema),needsApproval:n.requiresApproval??!n.automationSafe,execute:async e=>{let t=await r(e,{agentId:i.agentId??`unknown`,sessionId:i.sessionId??`unknown`,tenantId:i.tenantId,actorId:i.actorId,metadata:i.metadata,signal:i.signal});return typeof t==`string`?t:JSON.stringify(t)}})}function r(e,t,r={}){let i={};for(let a of e){let e=t.get(a.name);if(!e)throw Error(`Missing handler for tool: ${a.name}`);i[a.name]=n(a,e,r)}return i}function i(e){return async(t,n)=>e(t,n)}function a(e){return new Map(Object.entries(e))}export{a as buildToolHandlers,i as createToolHandler,n as specToolToAISDKTool,r as specToolsToAISDKTools};
1
+ import { jsonSchemaToZodSafe } from "../schema/json-schema-to-zod.js";
2
+ import { tool } from "ai";
3
+
4
+ //#region src/tools/tool-adapter.ts
5
+ /**
6
+ * Convert ContractSpec AgentToolConfig to AI SDK CoreTool.
7
+ *
8
+ * @param specTool - The tool configuration from AgentSpec
9
+ * @param handler - The handler function for the tool
10
+ * @param context - Partial context to inject into handler calls
11
+ * @returns AI SDK CoreTool
12
+ */
13
+ function specToolToAISDKTool(specTool, handler, context = {}) {
14
+ return tool({
15
+ description: specTool.description ?? specTool.name,
16
+ inputSchema: jsonSchemaToZodSafe(specTool.schema),
17
+ needsApproval: specTool.requiresApproval ?? !specTool.automationSafe,
18
+ execute: async (input) => {
19
+ const result = await handler(input, {
20
+ agentId: context.agentId ?? "unknown",
21
+ sessionId: context.sessionId ?? "unknown",
22
+ tenantId: context.tenantId,
23
+ actorId: context.actorId,
24
+ metadata: context.metadata,
25
+ signal: context.signal
26
+ });
27
+ return typeof result === "string" ? result : JSON.stringify(result);
28
+ }
29
+ });
30
+ }
31
+ /**
32
+ * Convert multiple ContractSpec tool configs to AI SDK tools.
33
+ *
34
+ * @param specTools - Array of tool configurations
35
+ * @param handlers - Map of tool name to handler function
36
+ * @param context - Partial context to inject into handler calls
37
+ * @returns Record of AI SDK tools keyed by name
38
+ */
39
+ function specToolsToAISDKTools(specTools, handlers, context = {}) {
40
+ const tools = {};
41
+ for (const specTool of specTools) {
42
+ const handler = handlers.get(specTool.name);
43
+ if (!handler) throw new Error(`Missing handler for tool: ${specTool.name}`);
44
+ tools[specTool.name] = specToolToAISDKTool(specTool, handler, context);
45
+ }
46
+ return tools;
47
+ }
48
+ /**
49
+ * Type-safe tool handler builder.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const handler = createToolHandler<{ query: string }>((input, ctx) => {
54
+ * return `Searched for: ${input.query}`;
55
+ * });
56
+ * ```
57
+ */
58
+ function createToolHandler(handler) {
59
+ return async (input, context) => {
60
+ return handler(input, context);
61
+ };
62
+ }
63
+ /**
64
+ * Build a tool handlers map from an object.
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * const handlers = buildToolHandlers({
69
+ * search: async (input: { query: string }) => `Found: ${input.query}`,
70
+ * calculate: async (input: { a: number, b: number }) => `${input.a + input.b}`,
71
+ * });
72
+ * ```
73
+ */
74
+ function buildToolHandlers(handlersObj) {
75
+ return new Map(Object.entries(handlersObj));
76
+ }
77
+
78
+ //#endregion
79
+ export { buildToolHandlers, createToolHandler, specToolToAISDKTool, specToolsToAISDKTools };
80
+ //# sourceMappingURL=tool-adapter.js.map