@xalia/agent 0.6.10 → 0.6.11

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 (161) hide show
  1. package/package.json +5 -2
  2. package/.env.development +0 -6
  3. package/.env.test +0 -7
  4. package/.prettierrc.json +0 -11
  5. package/context_system.md +0 -498
  6. package/eslint.config.mjs +0 -38
  7. package/scripts/chat_server +0 -8
  8. package/scripts/git_message +0 -31
  9. package/scripts/git_wip +0 -21
  10. package/scripts/pr_message +0 -18
  11. package/scripts/pr_review +0 -16
  12. package/scripts/setup_chat +0 -90
  13. package/scripts/shutdown_chat_server +0 -42
  14. package/scripts/start_chat_server +0 -24
  15. package/scripts/sudomcp_import +0 -23
  16. package/scripts/test_chat +0 -327
  17. package/src/agent/agent.ts +0 -699
  18. package/src/agent/agentUtils.ts +0 -286
  19. package/src/agent/compressingContextManager.ts +0 -129
  20. package/src/agent/context.ts +0 -265
  21. package/src/agent/contextWithWorkspace.ts +0 -162
  22. package/src/agent/documentSummarizer.ts +0 -157
  23. package/src/agent/dummyLLM.ts +0 -130
  24. package/src/agent/iAgentEventHandler.ts +0 -64
  25. package/src/agent/imageGenLLM.ts +0 -101
  26. package/src/agent/imageGenerator.ts +0 -45
  27. package/src/agent/iplatform.ts +0 -18
  28. package/src/agent/llm.ts +0 -74
  29. package/src/agent/mcpServerManager.ts +0 -541
  30. package/src/agent/nullAgentEventHandler.ts +0 -26
  31. package/src/agent/nullPlatform.ts +0 -13
  32. package/src/agent/openAI.ts +0 -123
  33. package/src/agent/openAILLM.ts +0 -99
  34. package/src/agent/openAILLMStreaming.ts +0 -648
  35. package/src/agent/promptProvider.ts +0 -87
  36. package/src/agent/repeatLLM.ts +0 -62
  37. package/src/agent/sudoMcpServerManager.ts +0 -361
  38. package/src/agent/test_data/harrypotter.txt +0 -6065
  39. package/src/agent/tokenAuth.ts +0 -50
  40. package/src/agent/tokenCounter.test.ts +0 -243
  41. package/src/agent/tokenCounter.ts +0 -483
  42. package/src/agent/toolSettings.ts +0 -24
  43. package/src/agent/tools/calculatorTool.ts +0 -50
  44. package/src/agent/tools/contentExtractors/htmlToText.ts +0 -61
  45. package/src/agent/tools/contentExtractors/pdfToText.ts +0 -60
  46. package/src/agent/tools/datetimeTool.ts +0 -41
  47. package/src/agent/tools/fileManager/fileManagerTool.ts +0 -199
  48. package/src/agent/tools/fileManager/index.ts +0 -50
  49. package/src/agent/tools/fileManager/memoryFileManager.ts +0 -120
  50. package/src/agent/tools/fileManager/mimeTypes.ts +0 -60
  51. package/src/agent/tools/fileManager/prompt.ts +0 -38
  52. package/src/agent/tools/fileManager/types.ts +0 -189
  53. package/src/agent/tools/index.ts +0 -49
  54. package/src/agent/tools/openUrlTool.ts +0 -62
  55. package/src/agent/tools/renderTool.ts +0 -92
  56. package/src/agent/tools/utils.ts +0 -74
  57. package/src/agent/tools/webSearch.ts +0 -138
  58. package/src/agent/tools/webSearchTool.ts +0 -44
  59. package/src/chat/client/chatClient.ts +0 -967
  60. package/src/chat/client/connection.test.ts +0 -241
  61. package/src/chat/client/connection.ts +0 -286
  62. package/src/chat/client/constants.ts +0 -1
  63. package/src/chat/client/index.ts +0 -21
  64. package/src/chat/client/interfaces.ts +0 -34
  65. package/src/chat/client/sessionClient.ts +0 -574
  66. package/src/chat/client/sessionFiles.ts +0 -142
  67. package/src/chat/client/teamManager.ts +0 -29
  68. package/src/chat/constants.ts +0 -6
  69. package/src/chat/data/apiKeyManager.ts +0 -76
  70. package/src/chat/data/dataModels.ts +0 -107
  71. package/src/chat/data/database.ts +0 -997
  72. package/src/chat/data/dbMcpServerConfigs.ts +0 -59
  73. package/src/chat/data/dbSessionFiles.ts +0 -107
  74. package/src/chat/data/dbSessionMessages.ts +0 -102
  75. package/src/chat/protocol/connectionMessages.ts +0 -49
  76. package/src/chat/protocol/constants.ts +0 -55
  77. package/src/chat/protocol/errors.ts +0 -16
  78. package/src/chat/protocol/messages.ts +0 -899
  79. package/src/chat/server/README.md +0 -127
  80. package/src/chat/server/chatContextManager.ts +0 -660
  81. package/src/chat/server/connectionManager.test.ts +0 -246
  82. package/src/chat/server/connectionManager.ts +0 -506
  83. package/src/chat/server/conversation.ts +0 -319
  84. package/src/chat/server/errorUtils.ts +0 -28
  85. package/src/chat/server/imageGeneratorTools.ts +0 -179
  86. package/src/chat/server/openAIRouterLLM.ts +0 -168
  87. package/src/chat/server/openSession.ts +0 -1945
  88. package/src/chat/server/openSessionMessageSender.ts +0 -4
  89. package/src/chat/server/promptRefiner.ts +0 -106
  90. package/src/chat/server/server.ts +0 -178
  91. package/src/chat/server/sessionFileManager.ts +0 -151
  92. package/src/chat/server/sessionRegistry.test.ts +0 -137
  93. package/src/chat/server/sessionRegistry.ts +0 -1553
  94. package/src/chat/server/test-utils/mockFactories.ts +0 -422
  95. package/src/chat/server/titleGenerator.test.ts +0 -103
  96. package/src/chat/server/titleGenerator.ts +0 -143
  97. package/src/chat/server/tools.ts +0 -170
  98. package/src/chat/utils/agentSessionMap.ts +0 -76
  99. package/src/chat/utils/approvalManager.ts +0 -189
  100. package/src/chat/utils/asyncLock.ts +0 -43
  101. package/src/chat/utils/asyncQueue.ts +0 -62
  102. package/src/chat/utils/multiAsyncQueue.ts +0 -66
  103. package/src/chat/utils/responseAwaiter.ts +0 -181
  104. package/src/chat/utils/userResolver.ts +0 -48
  105. package/src/chat/utils/websocket.ts +0 -16
  106. package/src/index.ts +0 -0
  107. package/src/test/agent.test.ts +0 -584
  108. package/src/test/approvalManager.test.ts +0 -141
  109. package/src/test/chatContextManager.test.ts +0 -552
  110. package/src/test/clientServerConnection.test.ts +0 -205
  111. package/src/test/compressingContextManager.test.ts +0 -77
  112. package/src/test/context.test.ts +0 -150
  113. package/src/test/contextTestTools.ts +0 -95
  114. package/src/test/conversation.test.ts +0 -109
  115. package/src/test/db.test.ts +0 -363
  116. package/src/test/dbMcpServerConfigs.test.ts +0 -112
  117. package/src/test/dbSessionFiles.test.ts +0 -258
  118. package/src/test/dbSessionMessages.test.ts +0 -85
  119. package/src/test/dbTestTools.ts +0 -157
  120. package/src/test/imageLoad.test.ts +0 -15
  121. package/src/test/mcpServerManager.test.ts +0 -114
  122. package/src/test/multiAsyncQueue.test.ts +0 -183
  123. package/src/test/openaiStreaming.test.ts +0 -177
  124. package/src/test/prompt.test.ts +0 -27
  125. package/src/test/promptProvider.test.ts +0 -33
  126. package/src/test/responseAwaiter.test.ts +0 -103
  127. package/src/test/sudoMcpServerManager.test.ts +0 -63
  128. package/src/test/testTools.ts +0 -176
  129. package/src/test/tools.test.ts +0 -64
  130. package/src/tool/agentChat.ts +0 -203
  131. package/src/tool/agentMain.ts +0 -180
  132. package/src/tool/chatMain.ts +0 -621
  133. package/src/tool/commandPrompt.ts +0 -264
  134. package/src/tool/files.ts +0 -82
  135. package/src/tool/main.ts +0 -25
  136. package/src/tool/nodePlatform.ts +0 -73
  137. package/src/tool/options.ts +0 -144
  138. package/src/tool/prompt.ts +0 -101
  139. package/test_data/background_test_profile.json +0 -6
  140. package/test_data/background_test_script.json +0 -11
  141. package/test_data/dummyllm_script_crash.json +0 -32
  142. package/test_data/dummyllm_script_image_gen.json +0 -19
  143. package/test_data/dummyllm_script_image_gen_fe.json +0 -29
  144. package/test_data/dummyllm_script_invoke_image_gen_tool.json +0 -37
  145. package/test_data/dummyllm_script_render_tool.json +0 -29
  146. package/test_data/dummyllm_script_simplecalc.json +0 -28
  147. package/test_data/dummyllm_script_test_auto_approve.json +0 -81
  148. package/test_data/dummyllm_script_test_simplecalc_addition.json +0 -29
  149. package/test_data/frog.png +0 -0
  150. package/test_data/frog.png.b64 +0 -1
  151. package/test_data/git_message_profile.json +0 -4
  152. package/test_data/git_wip_system.txt +0 -5
  153. package/test_data/image_gen_test_profile.json +0 -5
  154. package/test_data/pr_message_profile.json +0 -4
  155. package/test_data/pr_review_profile.json +0 -4
  156. package/test_data/prompt_simplecalc.txt +0 -1
  157. package/test_data/simplecalc_profile.json +0 -4
  158. package/test_data/sudomcp_import_profile.json +0 -4
  159. package/test_data/test_script_profile.json +0 -8
  160. package/tsconfig.json +0 -13
  161. package/vitest.config.ts +0 -39
package/src/agent/llm.ts DELETED
@@ -1,74 +0,0 @@
1
- import * as openai from "./openAI";
2
- import { OpenAI } from "openai";
3
-
4
- export const XALIA_APP_HEADER = {
5
- "HTTP-Referer": "https://xalia.ai",
6
- "X-Title": "Xalia",
7
- };
8
-
9
- export type ContentPartImage = openai.ChatCompletionContentPartImage;
10
-
11
- // For now, internally we only support "function" tool call requests, not
12
- // "custom" (impacts AssistantMessageParam).
13
- export type MessageToolCall = OpenAI.ChatCompletionMessageFunctionToolCall;
14
-
15
- // ChatCompletionAssistantMessageParam, but with only "function" tool calls.
16
- export interface AssistantMessageParam
17
- extends openai.ChatCompletionAssistantMessageParam {
18
- tool_calls?: Array<MessageToolCall>;
19
- }
20
-
21
- export type UserMessageParam = openai.ChatCompletionUserMessageParam;
22
-
23
- // Tool call results `ToolMessageParam` are only "function" results for now
24
- export interface ToolMessageParam
25
- extends OpenAI.ChatCompletionToolMessageParam {
26
- _meta?: Record<string, string>;
27
- structuredContent?: unknown;
28
- }
29
-
30
- export type MessageParam =
31
- | OpenAI.Chat.Completions.ChatCompletionSystemMessageParam
32
- | AssistantMessageParam
33
- | UserMessageParam
34
- | ToolMessageParam;
35
-
36
- // The tool description type
37
-
38
- export type ToolDescriptor = OpenAI.Chat.Completions.ChatCompletionFunctionTool;
39
-
40
- /**
41
- *
42
- */
43
- export interface Message /* WithReasoning */
44
- extends openai.ChatCompletionMessage {
45
- reasoning?: string;
46
- tool_calls?: Array<MessageToolCall>;
47
- }
48
-
49
- // export interface Message extends MessageWithReasoning {}
50
-
51
- // Extend ChatCompletionChoice to only hold function tool calls
52
- export interface Choice extends openai.ChatCompletionChoice {
53
- message: Message;
54
- }
55
-
56
- // Extends ChatCompletion to only hold function tool calls.
57
- export interface Completion extends openai.ChatCompletion {
58
- choices: Array<Choice>;
59
- }
60
-
61
- export interface ILLM {
62
- getModel(): string;
63
-
64
- getUrl(): string;
65
-
66
- getConversationResponse(
67
- messages: MessageParam[],
68
- tools?: ToolDescriptor[],
69
- onMessage?: (msg: string, end: boolean) => Promise<void>,
70
- onReasoning?: (reasoning: string) => Promise<void>
71
- ): Promise<{ stop: (msg: string) => void; completion: Promise<Completion> }>;
72
-
73
- setModel(model: string): void;
74
- }
@@ -1,541 +0,0 @@
1
- import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
2
- import {
3
- SSEClientTransport,
4
- SSEClientTransportOptions,
5
- } from "@modelcontextprotocol/sdk/client/sse.js";
6
- import {
7
- StreamableHTTPClientTransport,
8
- StreamableHTTPClientTransportOptions,
9
- } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
10
- import { Client as McpClient } from "@modelcontextprotocol/sdk/client/index.js";
11
- import { Tool, Resource } from "@modelcontextprotocol/sdk/types.js";
12
-
13
- import { McpServerSettings, getLogger } from "@xalia/xmcp/sdk";
14
- export type { McpServerSettings } from "@xalia/xmcp/sdk";
15
-
16
- import { TokenAuth } from "./tokenAuth";
17
- import { strict as assert } from "assert";
18
- import { ToolDescriptor } from "./llm";
19
- import { ToolCallResult } from "./agent";
20
-
21
- const logger = getLogger();
22
-
23
- export type McpServerToolCallMetaData = {
24
- "xalia/mcpServerName": string;
25
- };
26
-
27
- const mcpServerToolCallMetaKeys: (keyof McpServerToolCallMetaData)[] = [
28
- "xalia/mcpServerName",
29
- ];
30
-
31
- export function isMcpServerToolCallMetaData(
32
- meta: unknown
33
- ): meta is McpServerToolCallMetaData {
34
- return (
35
- !!meta &&
36
- typeof meta === "object" &&
37
- mcpServerToolCallMetaKeys.every((k) => k in meta)
38
- );
39
- }
40
-
41
- export type McpServerToolCallResult = ToolCallResult<McpServerToolCallMetaData>;
42
-
43
- export type VerifiedMcpToolCall = {
44
- mcpServerName: string;
45
- toolName: string;
46
- args: unknown;
47
- };
48
-
49
- export type ResourceContent = {
50
- _meta?: Record<string, unknown>;
51
- uri: string;
52
- mimeType?: string;
53
- text?: string;
54
- blob?: string;
55
- };
56
-
57
- /// Callback into an Mcp server
58
- export type McpCallback = { (args: string): Promise<McpServerToolCallResult> };
59
-
60
- /// Map of tool name to callback
61
- export type McpCallbacks = Map<string, McpCallback>;
62
-
63
- /// List of tool names that are enabled. We keep it as a map in the runtime
64
- /// object, so that we can quickly add and remove arbitrary entries. (The
65
- /// AgentProfile keeps this as a flat list).
66
- export type EnabledToolsMap = Map<string, boolean>;
67
-
68
- /**
69
- * The (read-only) McpServerInfo to expose to external classes. Callers
70
- * should not modify this data directly. Only through the McpServerManager
71
- * class.
72
- */
73
- export class McpServerInfo {
74
- private readonly name: string;
75
- private readonly tools: Tool[]; // TODO: May not need both tools and toolsMap
76
- private readonly resources: Resource[];
77
- private readonly toolsMap: { [toolName: string]: Tool };
78
- protected enabledToolsMap: EnabledToolsMap;
79
-
80
- constructor(name: string, tools: Tool[], resources: Resource[]) {
81
- const toolsMap: { [toolName: string]: Tool } = {};
82
-
83
- for (const mcpTool of tools) {
84
- const toolName = mcpTool.name;
85
- toolsMap[toolName] = mcpTool;
86
- }
87
-
88
- this.name = name;
89
- this.tools = tools;
90
- this.resources = resources;
91
- this.toolsMap = toolsMap;
92
- this.enabledToolsMap = new Map();
93
- }
94
-
95
- public getName(): string {
96
- return this.name;
97
- }
98
-
99
- public getEnabledTools(): EnabledToolsMap {
100
- return this.enabledToolsMap;
101
- }
102
-
103
- public getTools(): Tool[] {
104
- return this.tools;
105
- }
106
-
107
- public getResources(): Resource[] {
108
- return this.resources;
109
- }
110
-
111
- public getTool(toolName: string): Tool | undefined {
112
- return this.toolsMap[toolName];
113
- }
114
- }
115
-
116
- /**
117
- * Instance of McpServerInfo which supports setting tool state. Intended for
118
- * IMcpServerManager implementations, not for client code.
119
- */
120
- export class McpServerInfoRW extends McpServerInfo {
121
- public enableTool(toolName: string) {
122
- this.enabledToolsMap.set(toolName, true);
123
- }
124
-
125
- public disableTool(toolName: string) {
126
- this.enabledToolsMap.delete(toolName);
127
- }
128
- }
129
-
130
- /**
131
- * The internal class holds server info and allows it to be updated. Managed
132
- * by McpServerManager. Do not access these methods except via the
133
- * McpServerManager.
134
- */
135
- class McpServerInfoInternal extends McpServerInfoRW {
136
- private readonly client: McpClient;
137
- private readonly callbacks: McpCallbacks;
138
-
139
- constructor(
140
- name: string,
141
- client: McpClient,
142
- tools: Tool[],
143
- resources: Resource[]
144
- ) {
145
- super(name, tools, resources);
146
-
147
- logger.debug(`[McpServerInfoInternal] tools: ${JSON.stringify(tools)}`);
148
-
149
- const callbacks: McpCallbacks = new Map();
150
-
151
- for (const mcpTool of tools) {
152
- const toolName = mcpTool.name;
153
-
154
- // Create callback
155
- const callback = async (
156
- argStr: string
157
- ): Promise<McpServerToolCallResult> => {
158
- logger.debug(
159
- `cb for ${toolName} invoked with args (${typeof argStr}): ` +
160
- JSON.stringify(argStr)
161
- );
162
-
163
- const argsObj: unknown = JSON.parse(argStr);
164
- const toolResult = await client.callTool({
165
- name: toolName,
166
- arguments: argsObj as Record<string, unknown>,
167
- });
168
- logger.debug(
169
- `cb for ${toolName} returned: ${JSON.stringify(toolResult)}`
170
- );
171
-
172
- assert(typeof toolResult === "object");
173
- const content = toolResult.content as { [a: number]: unknown };
174
- assert(typeof content === "object");
175
- assert(content);
176
- const content0 = content[0] as { text: string };
177
- assert(typeof content0 === "object");
178
- const content0Text = content0.text;
179
- assert(typeof content0Text === "string");
180
-
181
- const meta: Record<string, string> = (toolResult._meta ||
182
- {}) as McpServerToolCallMetaData;
183
- meta["xalia/mcpServerName"] = this.getName();
184
- assert(isMcpServerToolCallMetaData(meta));
185
-
186
- return {
187
- response: content0Text,
188
- _meta: meta,
189
- ...(toolResult.structuredContent
190
- ? { structuredContent: toolResult.structuredContent }
191
- : {}),
192
- };
193
- };
194
-
195
- callbacks.set(toolName, callback);
196
- }
197
-
198
- this.client = client;
199
- this.callbacks = callbacks;
200
- }
201
-
202
- public async shutdown(): Promise<void> {
203
- await this.client.close();
204
- }
205
-
206
- public getCallback(toolName: string): McpCallback | undefined {
207
- return this.callbacks.get(toolName);
208
- }
209
-
210
- public async readResource(uri: string): Promise<ResourceContent[]> {
211
- const res = await this.client.readResource({
212
- uri,
213
- });
214
-
215
- logger.info(`readResource: got: ${JSON.stringify(res)}`);
216
- return res.contents;
217
- }
218
- }
219
-
220
- /**
221
- * The client's interface to a manager which has mcp servers assigned to it,
222
- * and can then query them for their tools, enable/disbale spercific tools and
223
- * remove servers completely.
224
- *
225
- * This interface says nothing about communication with a specific agent. It
226
- * only defines the client-facing interactions.
227
- */
228
- export interface IMcpServerManager {
229
- hasMcpServer(mcpServerName: string): boolean;
230
- getMcpServerNames(): string[];
231
- getMcpServer(mcpServerName: string): McpServerInfo;
232
-
233
- removeMcpServer(mcpServerName: string): Promise<void>;
234
- enableAllTools(mcpServerName: string): void;
235
- disableAllTools(mcpServerName: string): void;
236
- enableTool(mcpServerName: string, toolName: string): void;
237
- disableTool(mcpServerName: string, toolName: string): void;
238
-
239
- shutdown(): Promise<void>;
240
- }
241
-
242
- /**
243
- * Manage a set of MCP servers, where the tools for each server have an
244
- * 'enabled' flag. Tools are disabled by default. The set of enabled tools
245
- * over all servers is exposed as a single list of OpenAI functions.
246
- */
247
- export class McpServerManager implements IMcpServerManager {
248
- private mcpServers = new Map<string, McpServerInfoInternal>();
249
- private enabledToolsDirty: boolean = true;
250
- private enabledOpenAITools: ToolDescriptor[] = [];
251
-
252
- public async shutdown() {
253
- await Promise.all(
254
- Array.from(this.mcpServers.entries()).map(([name, server]) => {
255
- logger.debug(`shutting down: ${name}...`);
256
- return server.shutdown();
257
- })
258
- );
259
-
260
- this.mcpServers.clear();
261
- }
262
-
263
- public hasMcpServer(mcpServerName: string): boolean {
264
- return this.mcpServers.has(mcpServerName);
265
- }
266
-
267
- public getMcpServerNames(): string[] {
268
- return Array.from(this.mcpServers.keys());
269
- }
270
-
271
- public getMcpServer(mcpServerName: string): McpServerInfo {
272
- return this.getMcpServerInternal(mcpServerName);
273
- }
274
-
275
- public async addMcpServerWithTransport(
276
- mcpServerName: string,
277
- transport: Transport,
278
- tools?: Tool[]
279
- ): Promise<void> {
280
- const client = new McpClient({
281
- name: "@xalia/agent",
282
- version: "1.0.0",
283
- });
284
-
285
- try {
286
- await client.connect(transport);
287
- } catch (e) {
288
- // Ensure the socket is closed so the process can exit if there is an
289
- // error at connection time.
290
- await client.close();
291
- throw e;
292
- }
293
- await this.addMcpServerWithClient(client, mcpServerName, tools);
294
- }
295
-
296
- public async addMcpServerWithSSEUrl(
297
- mcpServerName: string,
298
- url: string,
299
- apiKey?: string,
300
- tools?: Tool[]
301
- ): Promise<void> {
302
- logger.debug(`Adding mcp server ${mcpServerName}: ${url}`);
303
- const sseTransportOptions: SSEClientTransportOptions = {};
304
- if (apiKey) {
305
- sseTransportOptions.authProvider = new TokenAuth(apiKey);
306
- }
307
- const urlO = new URL(url);
308
- const transport = new SSEClientTransport(urlO, sseTransportOptions);
309
- return this.addMcpServerWithTransport(mcpServerName, transport, tools);
310
- }
311
-
312
- public async addMcpServerWithStreamableHTTPUrl(
313
- mcpServerName: string,
314
- url: string,
315
- apiKey?: string
316
- ): Promise<void> {
317
- logger.debug(`Adding mcp (s-http) server ${mcpServerName}: ${url}`);
318
- const transportOptions: StreamableHTTPClientTransportOptions = {};
319
- if (apiKey) {
320
- transportOptions.authProvider = new TokenAuth(apiKey);
321
- }
322
- const urlO = new URL(url);
323
- const transport = new StreamableHTTPClientTransport(urlO, transportOptions);
324
- return this.addMcpServerWithTransport(mcpServerName, transport);
325
- }
326
-
327
- /**
328
- * Add MCP server from an already connected McpClient.
329
- */
330
- public async addMcpServerWithClient(
331
- client: McpClient,
332
- mcpServerName: string,
333
- tools?: Tool[]
334
- ): Promise<void> {
335
- try {
336
- // TODO: require the tools to be passed in.
337
-
338
- const resourcesP = client.listResources().catch((err: unknown) => {
339
- logger.warn(
340
- `resources ${mcpServerName}: ${JSON.stringify(err)} ${String(err)}`
341
- );
342
- return { resources: [] };
343
- });
344
- if (!tools) {
345
- const mcpTools = await client.listTools();
346
- tools = mcpTools.tools;
347
- }
348
-
349
- const resources: Resource[] = (await resourcesP).resources;
350
- this.mcpServers.set(
351
- mcpServerName,
352
- new McpServerInfoInternal(mcpServerName, client, tools, resources)
353
- );
354
- } catch (e) {
355
- await client.close();
356
- throw e;
357
- }
358
- }
359
-
360
- public async removeMcpServer(mcpServerName: string): Promise<void> {
361
- const server = this.getMcpServerInternal(mcpServerName);
362
- this.mcpServers.delete(mcpServerName);
363
- await server.shutdown();
364
- this.enabledToolsDirty = true;
365
- }
366
-
367
- public enableAllTools(mcpServerName: string) {
368
- logger.debug(`enableAllTools: ${mcpServerName}`);
369
- const server = this.getMcpServerInternal(mcpServerName);
370
- for (const tool of server.getTools()) {
371
- logger.debug(`enable: ${tool.name}`);
372
- server.enableTool(tool.name);
373
- }
374
- this.enabledToolsDirty = true;
375
- }
376
-
377
- public disableAllTools(mcpServerName: string) {
378
- logger.debug(`disableAllTools: ${mcpServerName}`);
379
- const server = this.getMcpServerInternal(mcpServerName);
380
- for (const tool of server.getTools()) {
381
- logger.debug(`disable: ${tool.name}`);
382
- server.disableTool(tool.name);
383
- }
384
- this.enabledToolsDirty = true;
385
- }
386
-
387
- public enableTool(mcpServerName: string, toolName: string) {
388
- logger.debug(`enableTool: ${mcpServerName} ${toolName}`);
389
- const server = this.getMcpServerInternal(mcpServerName);
390
- server.enableTool(toolName);
391
- this.enabledToolsDirty = true;
392
- }
393
-
394
- public disableTool(mcpServerName: string, toolName: string) {
395
- const server = this.getMcpServerInternal(mcpServerName);
396
- server.disableTool(toolName);
397
- this.enabledToolsDirty = true;
398
- }
399
-
400
- public getOpenAITools(): ToolDescriptor[] {
401
- if (this.enabledToolsDirty) {
402
- this.enabledOpenAITools = computeOpenAIToolList(this.mcpServers);
403
- this.enabledToolsDirty = false;
404
- }
405
-
406
- return this.enabledOpenAITools;
407
- }
408
-
409
- public verifyToolCall(
410
- qualifiedToolName: string,
411
- args: unknown
412
- ): VerifiedMcpToolCall {
413
- const [mcpServerName, toolName] = splitQualifiedName(qualifiedToolName);
414
- logger.debug(`invoke: qualified: ${qualifiedToolName}`);
415
- logger.debug(
416
- `invoke: mcpServerName: ${mcpServerName}, toolName: ${toolName}`
417
- );
418
- logger.debug(`invoke: args: ${JSON.stringify(args)}`);
419
-
420
- const server = this.getMcpServerInternal(mcpServerName);
421
- const cb = server.getCallback(toolName);
422
- if (!cb) {
423
- throw new Error(`Unknown tool ${qualifiedToolName}`);
424
- }
425
- return {
426
- mcpServerName,
427
- toolName,
428
- args,
429
- };
430
- }
431
-
432
- /**
433
- * Note the `qualifiedToolName` is the full `{mcpServerName}/{toolName}` as
434
- * in the openai spec.
435
- */
436
- public async invoke(toolCall: VerifiedMcpToolCall): Promise<ToolCallResult> {
437
- const server = this.getMcpServerInternal(toolCall.mcpServerName);
438
- const cb = server.getCallback(toolCall.toolName);
439
- if (!cb) {
440
- throw new Error(`Unknown tool ${toolCall.toolName}`);
441
- }
442
-
443
- return cb(JSON.stringify(toolCall.args));
444
- }
445
-
446
- public async getResource(
447
- serverName: string,
448
- uri: string
449
- ): Promise<ResourceContent[]> {
450
- const server = this.getMcpServerInternal(serverName);
451
- return server.readResource(uri);
452
- }
453
-
454
- /**
455
- * "Settings" refers to the set of added servers and enabled tools.
456
- */
457
- public getMcpServerSettings(): McpServerSettings {
458
- const config: McpServerSettings = {};
459
-
460
- // NOTE: on load, entries of the form:
461
- //
462
- // <server>: []
463
- //
464
- // may be interpreted as "all tools for <server>". If the client has left
465
- // a server with no tools enabled, we mark it as disabled.
466
-
467
- for (const [serverName, server] of this.mcpServers) {
468
- const tools = Array.from(server.getEnabledTools().keys());
469
- if (tools.length > 0) {
470
- config[serverName] = tools;
471
- }
472
- }
473
-
474
- return config;
475
- }
476
-
477
- private getMcpServerInternal(mcpServerName: string): McpServerInfoInternal {
478
- const server = this.mcpServers.get(mcpServerName);
479
- if (server) {
480
- return server;
481
- }
482
- throw Error(`[getMcpServerInternal] unknown server ${mcpServerName}`);
483
- }
484
- }
485
-
486
- export function computeQualifiedName(
487
- mcpServerName: string,
488
- toolName: string
489
- ): string {
490
- return `${mcpServerName}__${toolName}`;
491
- }
492
-
493
- export function splitQualifiedName(
494
- qualifiedToolName: string
495
- ): [string, string] {
496
- const delimIdx = qualifiedToolName.indexOf("__");
497
- if (delimIdx < 0) {
498
- throw Error(`invalid qualified name: ${qualifiedToolName}`);
499
- }
500
-
501
- return [
502
- qualifiedToolName.slice(0, delimIdx),
503
- qualifiedToolName.slice(delimIdx + 2),
504
- ];
505
- }
506
-
507
- export function computeOpenAIToolList(
508
- mcpServers: Map<string, McpServerInfoInternal>
509
- ): ToolDescriptor[] {
510
- const openaiTools: ToolDescriptor[] = [];
511
-
512
- for (const [mcpServerName, mcpServer] of mcpServers) {
513
- const tools = mcpServer.getTools();
514
- const enabled = mcpServer.getEnabledTools();
515
-
516
- for (const mcpTool of tools) {
517
- const toolName = mcpTool.name;
518
- if (enabled.get(toolName)) {
519
- const qualifiedName = computeQualifiedName(mcpServerName, toolName);
520
- const openaiTool = mcpToolToOpenAITool(mcpTool, qualifiedName);
521
- openaiTools.push(openaiTool);
522
- }
523
- }
524
- }
525
-
526
- return openaiTools;
527
- }
528
-
529
- export function mcpToolToOpenAITool(
530
- tool: Tool,
531
- qualifiedName?: string
532
- ): ToolDescriptor {
533
- return {
534
- type: "function",
535
- function: {
536
- name: qualifiedName || tool.name,
537
- description: tool.description,
538
- parameters: tool.inputSchema,
539
- },
540
- };
541
- }
@@ -1,26 +0,0 @@
1
- import { IAgentEventHandler } from "./iAgentEventHandler";
2
-
3
- /**
4
- * Trivial IAgentEventHandler implementation which does not track any messages
5
- * and does not allow tool calls.
6
- */
7
- export const NULL_AGENT_EVENT_HANDLER: IAgentEventHandler = {
8
- onCompletion: (): void => {},
9
- onImage: (): void => {},
10
- onToolCallResult: (): void => {},
11
- onAgentMessage: (): Promise<void> => {
12
- return new Promise<void>((r) => {
13
- r();
14
- });
15
- },
16
- onReasoning: (): Promise<void> => {
17
- return new Promise<void>((r) => {
18
- r();
19
- });
20
- },
21
- onToolCall: (): Promise<boolean> => {
22
- return new Promise((r) => {
23
- r(false);
24
- });
25
- },
26
- };
@@ -1,13 +0,0 @@
1
- import { IPlatform } from "../agent/iplatform";
2
-
3
- export const NULL_PLATFORM: IPlatform = {
4
- openUrl: () => {
5
- throw new Error("null_platform openUrl called");
6
- },
7
- load: (): Promise<string> => {
8
- throw new Error("null_platform load called");
9
- },
10
- renderHTML: (): Promise<void> => {
11
- throw new Error("null_platform renderHTML called");
12
- },
13
- };