@xalia/agent 0.6.4 → 0.6.6

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 (74) hide show
  1. package/dist/agent/src/agent/agent.js +12 -11
  2. package/dist/agent/src/agent/dummyLLM.js +24 -15
  3. package/dist/agent/src/agent/llm.js +0 -22
  4. package/dist/agent/src/agent/mcpServerManager.js +73 -15
  5. package/dist/agent/src/agent/openAI.js +32 -0
  6. package/dist/agent/src/agent/openAILLM.js +25 -1
  7. package/dist/agent/src/agent/openAILLMStreaming.js +8 -3
  8. package/dist/agent/src/agent/sudoMcpServerManager.js +22 -9
  9. package/dist/agent/src/chat/client/chatClient.js +2 -1
  10. package/dist/agent/src/chat/client/sessionClient.js +28 -3
  11. package/dist/agent/src/chat/data/dbSessionFileModels.js +10 -0
  12. package/dist/agent/src/chat/protocol/messages.js +1 -0
  13. package/dist/agent/src/chat/server/chatContextManager.js +4 -4
  14. package/dist/agent/src/chat/server/conversation.js +1 -1
  15. package/dist/agent/src/chat/server/imageGeneratorTools.js +7 -4
  16. package/dist/agent/src/chat/server/openSession.js +85 -12
  17. package/dist/agent/src/chat/server/sessionFileManager.js +17 -6
  18. package/dist/agent/src/chat/server/sessionRegistry.js +1 -1
  19. package/dist/agent/src/chat/server/tools.js +58 -10
  20. package/dist/agent/src/test/agent.test.js +26 -2
  21. package/dist/agent/src/test/chatContextManager.test.js +5 -5
  22. package/dist/agent/src/test/mcpServerManager.test.js +5 -1
  23. package/dist/agent/src/test/testTools.js +5 -2
  24. package/dist/agent/src/tool/chatMain.js +23 -3
  25. package/dist/agent/src/tool/files.js +0 -27
  26. package/package.json +3 -3
  27. package/scripts/test_chat +3 -1
  28. package/src/agent/agent.ts +53 -47
  29. package/src/agent/agentUtils.ts +7 -7
  30. package/src/agent/compressingContextManager.ts +4 -9
  31. package/src/agent/context.ts +28 -37
  32. package/src/agent/dummyLLM.ts +38 -28
  33. package/src/agent/iAgentEventHandler.ts +6 -9
  34. package/src/agent/imageGenLLM.ts +11 -5
  35. package/src/agent/llm.ts +41 -106
  36. package/src/agent/mcpServerManager.ts +145 -29
  37. package/src/agent/openAI.ts +123 -0
  38. package/src/agent/openAILLM.ts +52 -5
  39. package/src/agent/openAILLMStreaming.ts +36 -32
  40. package/src/agent/repeatLLM.ts +5 -6
  41. package/src/agent/sudoMcpServerManager.ts +48 -16
  42. package/src/agent/tools.ts +3 -5
  43. package/src/chat/client/chatClient.ts +3 -1
  44. package/src/chat/client/sessionClient.ts +47 -7
  45. package/src/chat/data/dataModels.ts +3 -3
  46. package/src/chat/data/dbSessionFileModels.ts +22 -0
  47. package/src/chat/protocol/messages.ts +39 -13
  48. package/src/chat/server/chatContextManager.ts +20 -24
  49. package/src/chat/server/conversation.ts +10 -10
  50. package/src/chat/server/imageGeneratorTools.ts +18 -9
  51. package/src/chat/server/openSession.ts +111 -22
  52. package/src/chat/server/sessionFileManager.ts +33 -10
  53. package/src/chat/server/sessionRegistry.ts +1 -1
  54. package/src/chat/server/tools.ts +77 -18
  55. package/src/chat/utils/approvalManager.ts +2 -2
  56. package/src/test/agent.test.ts +56 -31
  57. package/src/test/approvalManager.test.ts +2 -2
  58. package/src/test/chatContextManager.test.ts +11 -14
  59. package/src/test/compressingContextManager.test.ts +3 -3
  60. package/src/test/context.test.ts +3 -3
  61. package/src/test/conversation.test.ts +7 -7
  62. package/src/test/dbSessionMessages.test.ts +3 -3
  63. package/src/test/mcpServerManager.test.ts +10 -1
  64. package/src/test/testTools.ts +44 -33
  65. package/src/tool/agentChat.ts +10 -8
  66. package/src/tool/agentMain.ts +2 -2
  67. package/src/tool/chatMain.ts +38 -6
  68. package/src/tool/commandPrompt.ts +2 -4
  69. package/src/tool/files.ts +0 -34
  70. package/test_data/dummyllm_script_image_gen.json +27 -17
  71. package/test_data/dummyllm_script_invoke_image_gen_tool.json +9 -2
  72. package/test_data/dummyllm_script_render_tool.json +29 -0
  73. package/test_data/dummyllm_script_test_auto_approve.json +81 -0
  74. package/test_data/dummyllm_script_test_simplecalc_addition.json +29 -0
@@ -1,4 +1,3 @@
1
- import { OpenAI } from "openai";
2
1
  import { expect } from "vitest";
3
2
  import { strict as assert } from "assert";
4
3
 
@@ -12,10 +11,12 @@ import {
12
11
  completionToAssistantMessageParam,
13
12
  } from "../agent/agent";
14
13
  import {
15
- ChatCompletionAssistantMessageParam,
16
- ChatCompletionMessageParam,
17
- ChatCompletionMessageToolCall,
18
- ChatCompletionToolMessageParam,
14
+ AssistantMessageParam,
15
+ Choice,
16
+ MessageParam,
17
+ MessageToolCall,
18
+ ToolDescriptor,
19
+ ToolMessageParam,
19
20
  } from "../agent/llm";
20
21
  import { ContextManager } from "../agent/context";
21
22
  import { LOCAL_SERVER_URL, SkillManager } from "../agent/sudoMcpServerManager";
@@ -26,12 +27,13 @@ import {
26
27
  TestDummyLLM,
27
28
  TestErrorLLM,
28
29
  } from "./testTools";
30
+ import { DummyLLMScriptEntry } from "../agent/dummyLLM";
29
31
 
30
32
  function clone<T>(a: T): T {
31
33
  return JSON.parse(JSON.stringify(a)) as T;
32
34
  }
33
35
 
34
- const DUMMY_SCRIPT: OpenAI.Chat.Completions.ChatCompletion.Choice[] = [
36
+ const DUMMY_SCRIPT: Choice[] = [
35
37
  {
36
38
  index: 0,
37
39
  finish_reason: "stop",
@@ -59,13 +61,13 @@ function createCallTestToolScript(
59
61
  param1: string,
60
62
  param2: number
61
63
  ): {
62
- script: OpenAI.Chat.Completions.ChatCompletion.Choice[];
63
- expectCompletions: ChatCompletionAssistantMessageParam[];
64
+ script: Choice[];
65
+ expectCompletions: AssistantMessageParam[];
64
66
  expectAgentMessages: string[];
65
- expectToolResults: ChatCompletionToolMessageParam[];
66
- tool0_descriptor: OpenAI.ChatCompletionTool;
67
+ expectToolResults: ToolMessageParam[];
68
+ tool0_descriptor: ToolDescriptor;
67
69
  tool0_fn: (agent: Agent, args: unknown) => Promise<ToolCallResult>;
68
- test_tool_descriptor: OpenAI.ChatCompletionTool;
70
+ test_tool_descriptor: ToolDescriptor;
69
71
  test_tool_fn: (agent: Agent, args: unknown) => Promise<ToolCallResult>;
70
72
  } {
71
73
  // A tool with no args
@@ -75,7 +77,7 @@ function createCallTestToolScript(
75
77
  properties: {},
76
78
  };
77
79
 
78
- const tool0_descriptor: OpenAI.ChatCompletionTool = {
80
+ const tool0_descriptor: ToolDescriptor = {
79
81
  type: "function",
80
82
  function: {
81
83
  name: "tool0",
@@ -103,7 +105,7 @@ function createCallTestToolScript(
103
105
  required: ["param1", "param2"],
104
106
  };
105
107
 
106
- const test_tool_descriptor: OpenAI.ChatCompletionTool = {
108
+ const test_tool_descriptor: ToolDescriptor = {
107
109
  type: "function",
108
110
  function: {
109
111
  name: "test_tool",
@@ -120,13 +122,13 @@ function createCallTestToolScript(
120
122
  return new Promise((r) => {
121
123
  r({
122
124
  response: `tool_result: '${param1}' '${String(param2)}'`,
123
- metadata: { type: "text/plain" },
125
+ _meta: { type: "text/plain" },
124
126
  });
125
127
  });
126
128
  };
127
129
 
128
- const tool_calls: OpenAI.ChatCompletionMessageToolCall[] = [];
129
- const expectToolResults: ChatCompletionToolMessageParam[] = [];
130
+ const tool_calls: MessageToolCall[] = [];
131
+ const expectToolResults: ToolMessageParam[] = [];
130
132
 
131
133
  // First tool call (if requested) is test_tool
132
134
  if (tool_call_ids.length > 0) {
@@ -143,7 +145,7 @@ function createCallTestToolScript(
143
145
  content: `tool_result: '${param1}' '${String(param2)}'`,
144
146
  role: "tool",
145
147
  tool_call_id: id,
146
- metadata: { type: "text/plain" },
148
+ _meta: { type: "text/plain" },
147
149
  });
148
150
  }
149
151
 
@@ -172,7 +174,7 @@ function createCallTestToolScript(
172
174
 
173
175
  // A script that uses the tools
174
176
 
175
- const script: OpenAI.Chat.Completions.ChatCompletion.Choice[] = [
177
+ const script: Choice[] = [
176
178
  {
177
179
  index: 0,
178
180
  finish_reason: "tool_calls",
@@ -218,9 +220,7 @@ function createCallTestToolScript(
218
220
  }
219
221
 
220
222
  /// Return a dummy agent and a TestAgentEventHandler for tracking messages.
221
- async function createTestAgent(
222
- script: OpenAI.Chat.Completions.ChatCompletion.Choice[]
223
- ): Promise<{
223
+ async function createTestAgent(script: Choice[]): Promise<{
224
224
  agent: Agent;
225
225
  skillManager: SkillManager;
226
226
  eventHandler: TestAgentEventHandler;
@@ -423,8 +423,7 @@ describe("Agent", () => {
423
423
  // Take a copy of the script now, since this will be updated when the
424
424
  // tools redacted their args.
425
425
 
426
- const scriptCopy: OpenAI.Chat.Completions.ChatCompletion.Choice[] =
427
- clone(script);
426
+ const scriptCopy: Choice[] = clone(script);
428
427
 
429
428
  // Define the tool to update the arg. The transform is to up-case
430
429
  // `param1: string` and add 100 to `param2: number`.
@@ -455,9 +454,7 @@ describe("Agent", () => {
455
454
  // Check the event handler was called with all completions and tool
456
455
  // results, in the correct order.
457
456
 
458
- const transformToolCall = (
459
- toolCall: ChatCompletionMessageToolCall
460
- ): ChatCompletionMessageToolCall => {
457
+ const transformToolCall = (toolCall: MessageToolCall): MessageToolCall => {
461
458
  return {
462
459
  ...toolCall,
463
460
  function: {
@@ -476,7 +473,7 @@ describe("Agent", () => {
476
473
  ],
477
474
  });
478
475
 
479
- const allExpect: ChatCompletionMessageParam[] = [
476
+ const allExpect: MessageParam[] = [
480
477
  transformedFirstMsg,
481
478
  ...expectToolResults,
482
479
  completionToAssistantMessageParam(scriptCopy[1].message),
@@ -527,16 +524,17 @@ describe("Agent", () => {
527
524
  // Check the event handler was called with all completions and tool
528
525
  // results as expected.
529
526
 
530
- const expectToolCallResults: ChatCompletionMessageParam[] =
531
- expectToolResults.map((tr) => {
527
+ const expectToolCallResults: MessageParam[] = expectToolResults.map(
528
+ (tr) => {
532
529
  assert(typeof tr.content === "string");
533
530
  return {
534
531
  ...tr,
535
532
  content: transformResult(tr.content),
536
533
  };
537
- });
534
+ }
535
+ );
538
536
 
539
- const allExpect: ChatCompletionMessageParam[] = [
537
+ const allExpect: MessageParam[] = [
540
538
  completionToAssistantMessageParam(script[0].message),
541
539
  ...expectToolCallResults,
542
540
  completionToAssistantMessageParam(script[1].message),
@@ -561,4 +559,31 @@ describe("Agent", () => {
561
559
  // Check the Agent has not added the user messages.
562
560
  expect(ctxMgr.getLLMContext().length).eql(1);
563
561
  });
562
+
563
+ it("supports reasoning token callbacks", async function () {
564
+ const script: DummyLLMScriptEntry[] = [
565
+ {
566
+ finish_reason: "reasoning",
567
+ message: "Some reasoning tokens...",
568
+ },
569
+ {
570
+ index: 0,
571
+ finish_reason: "stop",
572
+ message: {
573
+ content: "Agent Message",
574
+ refusal: null,
575
+ role: "assistant",
576
+ },
577
+ logprobs: null,
578
+ },
579
+ ];
580
+
581
+ const llm = new TestDummyLLM(script);
582
+ const eventHandler = new TestAgentEventHandler();
583
+ const ctxMgr = new ContextManager("SYSTEM_PROMPT", []);
584
+ const agent = Agent.initializeWithLLM(eventHandler, llm, ctxMgr);
585
+
586
+ await agent.userMessageEx("user message 1");
587
+ expect(eventHandler.getReasoning()).eql([script[0].message, ""]);
588
+ });
564
589
  });
@@ -9,7 +9,7 @@ import {
9
9
  ServerToClient,
10
10
  } from "../chat/protocol/messages";
11
11
  import { ISessionMessageSender } from "../chat/server/openSessionMessageSender";
12
- import { ChatCompletionMessageToolCall } from "../agent/llm";
12
+ import { MessageToolCall } from "../agent/llm";
13
13
 
14
14
  export class TestAgentPreferencesWriter implements IAgentPreferencesWriter {
15
15
  public prefs: Record<string, AgentPreferences | undefined> = {};
@@ -41,7 +41,7 @@ export class TestMessageSender
41
41
  }
42
42
  }
43
43
 
44
- const tc: ChatCompletionMessageToolCall = {
44
+ const tc: MessageToolCall = {
45
45
  type: "function",
46
46
  id: "tool_call_0",
47
47
  function: { name: "fn0", arguments: "" },
@@ -7,10 +7,7 @@ import {
7
7
  resolveConversationWithCheckpoint,
8
8
  } from "../chat/server/chatContextManager";
9
9
  import { createUserMessageEnsure } from "../agent/agent";
10
- import {
11
- ChatCompletionAssistantMessageParam,
12
- ChatCompletionToolMessageParam,
13
- } from "../agent/llm";
10
+ import { AssistantMessageParam, ToolMessageParam } from "../agent/llm";
14
11
  import { createCheckpointMessage } from "../agent/compressingContextManager";
15
12
  import {
16
13
  MESSAGE_INDEX_FULL_INCREMENT,
@@ -58,7 +55,7 @@ const MESSAGES: SessionMessage[] = [
58
55
  role: "tool",
59
56
  content: "msg501",
60
57
  tool_call_id: "tool_call_0",
61
- metadata: { type: "text/plain" },
58
+ _meta: { type: "text/plain" },
62
59
  },
63
60
  },
64
61
  {
@@ -115,7 +112,7 @@ function testSuccessfulAgentLoop(cm: ChatContextManager, startIdx: number) {
115
112
  userMsgs.map((su) => {
116
113
  return {
117
114
  role: "user",
118
- name: su.user_nickname,
115
+ name: su.user_uuid,
119
116
  content: su.message,
120
117
  };
121
118
  })
@@ -142,7 +139,7 @@ function testSuccessfulAgentLoop(cm: ChatContextManager, startIdx: number) {
142
139
 
143
140
  // A full response (with toolcall) is returned
144
141
 
145
- const agentResponseWithToolCall: ChatCompletionAssistantMessageParam = {
142
+ const agentResponseWithToolCall: AssistantMessageParam = {
146
143
  role: "assistant",
147
144
  tool_calls: [
148
145
  {
@@ -188,7 +185,7 @@ function testSuccessfulAgentLoop(cm: ChatContextManager, startIdx: number) {
188
185
  // - 2*MESSAGE_INDEX_FULL_INCREMENT + 1*MESSAGE_INDEX_SUB_INCREMENT
189
186
  // - 2*MESSAGE_INDEX_FULL_INCREMENT + 2*MESSAGE_INDEX_SUB_INCREMENT
190
187
 
191
- const toolCallResults: ChatCompletionToolMessageParam[] = [
188
+ const toolCallResults: ToolMessageParam[] = [
192
189
  {
193
190
  role: "tool",
194
191
  tool_call_id: "tool_call_0",
@@ -218,7 +215,7 @@ function testSuccessfulAgentLoop(cm: ChatContextManager, startIdx: number) {
218
215
 
219
216
  // Final agent response
220
217
 
221
- const finalAgentResponse: ChatCompletionAssistantMessageParam = {
218
+ const finalAgentResponse: AssistantMessageParam = {
222
219
  role: "assistant",
223
220
  content: "AgentMessage2",
224
221
  };
@@ -246,7 +243,7 @@ function testSuccessfulAgentLoop(cm: ChatContextManager, startIdx: number) {
246
243
  content: createUserMessageEnsure(
247
244
  userMsgs[0].message,
248
245
  userMsgs[0].imageB64,
249
- "User0"
246
+ "user0"
250
247
  ),
251
248
  },
252
249
  {
@@ -256,7 +253,7 @@ function testSuccessfulAgentLoop(cm: ChatContextManager, startIdx: number) {
256
253
  content: createUserMessageEnsure(
257
254
  userMsgs[1].message,
258
255
  userMsgs[1].imageB64,
259
- "User1"
256
+ "user1"
260
257
  ),
261
258
  },
262
259
  // agent response with tool calls
@@ -448,14 +445,14 @@ describe("IndexingCompressingContextManager", () => {
448
445
  expect(llmUserMessages).eql([
449
446
  {
450
447
  role: "user",
451
- name: serverUserMessage0.user_nickname,
448
+ name: serverUserMessage0.user_uuid,
452
449
  content: serverUserMessage0.message,
453
450
  },
454
451
  ]);
455
452
 
456
453
  // A full response (with toolcall) is returned
457
454
 
458
- const agentResponseWithToolCall: ChatCompletionAssistantMessageParam = {
455
+ const agentResponseWithToolCall: AssistantMessageParam = {
459
456
  role: "assistant",
460
457
  tool_calls: [
461
458
  {
@@ -488,7 +485,7 @@ describe("IndexingCompressingContextManager", () => {
488
485
  // - 1*MESSAGE_INDEX_FULL_INCREMENT + 1*MESSAGE_INDEX_SUB_INCREMENT
489
486
  // - 1*MESSAGE_INDEX_FULL_INCREMENT + 2*MESSAGE_INDEX_SUB_INCREMENT
490
487
 
491
- const toolCallResults: ChatCompletionToolMessageParam[] = [
488
+ const toolCallResults: ToolMessageParam[] = [
492
489
  {
493
490
  role: "tool",
494
491
  tool_call_id: "tool_call_0",
@@ -4,9 +4,9 @@ import {
4
4
  CompressingContextManager,
5
5
  createCheckpointMessage,
6
6
  } from "../agent/compressingContextManager";
7
- import { ChatCompletionMessageParam } from "../agent/llm";
7
+ import { MessageParam } from "../agent/llm";
8
8
 
9
- const MESSAGES: ChatCompletionMessageParam[] = [
9
+ const MESSAGES: MessageParam[] = [
10
10
  { role: "user", content: "msg200" },
11
11
  { role: "assistant", content: "msg300" },
12
12
  { role: "user", content: "msg400" },
@@ -59,7 +59,7 @@ describe("Compression context", () => {
59
59
  // - new context is as expected
60
60
 
61
61
  const expectSummary = "Message number 0";
62
- const expectContext: ChatCompletionMessageParam[] = [
62
+ const expectContext: MessageParam[] = [
63
63
  {
64
64
  role: "system",
65
65
  content: "New system prompt",
@@ -3,11 +3,11 @@ import { strict as assert } from "assert";
3
3
 
4
4
  import { ContextManagerWithWorkspace } from "../agent/context";
5
5
  import { createUserMessage } from "../agent/agent";
6
- import { ChatCompletionMessageParam } from "../agent/llm";
6
+ import { MessageParam } from "../agent/llm";
7
7
  import { SystemPromptProvider } from "../agent/promptProvider";
8
8
 
9
9
  describe("ContextManagerWithWorkspace", () => {
10
- const msgs: ChatCompletionMessageParam[] = [
10
+ const msgs: MessageParam[] = [
11
11
  { role: "user", content: "message A" },
12
12
  { role: "assistant", content: "message B" },
13
13
  { role: "user", content: "message C" },
@@ -30,7 +30,7 @@ describe("ContextManagerWithWorkspace", () => {
30
30
  ]);
31
31
 
32
32
  // context with new message and workspace
33
- const lastMsg: ChatCompletionMessageParam = {
33
+ const lastMsg: MessageParam = {
34
34
  role: "user",
35
35
  content: "hello",
36
36
  };
@@ -1,8 +1,8 @@
1
1
  import { expect } from "vitest";
2
2
  import {
3
- ChatCompletionAssistantMessageParam,
4
- ChatCompletionMessageParam,
5
- ChatCompletionUserMessageParam,
3
+ AssistantMessageParam,
4
+ MessageParam,
5
+ UserMessageParam,
6
6
  } from "../agent/llm";
7
7
  import {
8
8
  MESSAGE_INDEX_FULL_INCREMENT,
@@ -13,13 +13,13 @@ import {
13
13
  import { SessionMessage } from "../chat/data/dataModels";
14
14
 
15
15
  // Fake conversation values.
16
- const AGENT: ChatCompletionAssistantMessageParam[] = [
16
+ const AGENT: AssistantMessageParam[] = [
17
17
  { role: "assistant", content: "Message 0" },
18
18
  { role: "assistant", content: "Message 1" },
19
19
  { role: "assistant", content: "Message 2" },
20
20
  ];
21
21
 
22
- const USER: ChatCompletionUserMessageParam[] = [
22
+ const USER: UserMessageParam[] = [
23
23
  { role: "user", content: "Message 0", name: "userA" },
24
24
  { role: "user", content: "Message 1", name: "userA" },
25
25
  { role: "user", content: "Message 2", name: "userA" },
@@ -45,7 +45,7 @@ describe("Conversation tools", () => {
45
45
  },
46
46
  {
47
47
  message_idx: 100,
48
- content: {} as unknown as ChatCompletionMessageParam,
48
+ content: {} as unknown as MessageParam,
49
49
  is_for_llm: false,
50
50
  },
51
51
  {
@@ -85,7 +85,7 @@ describe("Conversation tools", () => {
85
85
  },
86
86
  {
87
87
  message_idx: 5 * MESSAGE_INDEX_FULL_INCREMENT,
88
- content: {} as unknown as ChatCompletionMessageParam,
88
+ content: {} as unknown as MessageParam,
89
89
  is_for_llm: false,
90
90
  },
91
91
  {
@@ -1,7 +1,7 @@
1
1
  import { expect, beforeEach, afterEach, describe, it } from "vitest";
2
2
  import { Database } from "../chat/data/database";
3
3
  import { SessionMessage } from "../chat/data/dataModels";
4
- import { ChatCompletionMessageParam } from "../agent/llm";
4
+ import { MessageParam } from "../agent/llm";
5
5
  import {
6
6
  TestUserSpec,
7
7
  cleanupTestUser,
@@ -31,11 +31,11 @@ describe("DB Session Messages", () => {
31
31
  it("should update conversations", async () => {
32
32
  const { sessionId } = await createTestSession(db, testUsers[0]);
33
33
 
34
- const CONV_0: ChatCompletionMessageParam[] = [
34
+ const CONV_0: MessageParam[] = [
35
35
  { role: "user", content: "message 0" },
36
36
  { role: "assistant", content: "message 1" },
37
37
  ];
38
- const CONV_1: ChatCompletionMessageParam[] = [
38
+ const CONV_1: MessageParam[] = [
39
39
  { role: "user", content: "message 2" },
40
40
  { role: "assistant", content: "message 3" },
41
41
  ];
@@ -1,7 +1,10 @@
1
1
  /* eslint-disable @typescript-eslint/require-await */
2
2
  import { describe, it, expect, afterAll } from "vitest";
3
+ import { strict as assert } from "assert";
4
+
3
5
  import {
4
6
  computeQualifiedName,
7
+ isMcpServerToolCallMetaData,
5
8
  McpServerManager,
6
9
  splitQualifiedName,
7
10
  } from "../agent/mcpServerManager";
@@ -42,6 +45,7 @@ describe("McpServerManager", () => {
42
45
  expect(availableTools.length).toBeGreaterThan(0);
43
46
 
44
47
  // Initially, no tools are enabled.
48
+
45
49
  expect(tm.getOpenAITools().length).toBe(0);
46
50
 
47
51
  // Enable a tool and check we get a description for it.
@@ -59,7 +63,12 @@ describe("McpServerManager", () => {
59
63
  const r = await tm.invoke(
60
64
  tm.verifyToolCall(qualifiedName, { a: 1000, b: 10 })
61
65
  );
62
- console.log(`response: ${r}`);
66
+
67
+ assert(r._meta);
68
+ assert(isMcpServerToolCallMetaData(r._meta));
69
+ expect(r._meta["xalia/mcpServerName"]).eql("simplecalc");
70
+
71
+ console.log(`response: ${JSON.stringify(r)}`);
63
72
  }
64
73
 
65
74
  // Disable and check we don't get the spec anymore
@@ -1,14 +1,15 @@
1
- import { OpenAI } from "openai";
2
-
3
1
  import {
4
- ChatCompletionAssistantMessageParam,
5
- ChatCompletionMessageParam,
6
- ChatCompletionMessageToolCall,
7
- ChatCompletionToolMessageParam,
2
+ AssistantMessageParam,
3
+ MessageParam,
4
+ MessageToolCall,
5
+ ToolMessageParam,
6
+ ContentPartImage,
7
+ ToolDescriptor,
8
+ Completion,
8
9
  } from "../agent/llm";
9
10
  import { IAgentEventHandler } from "../agent/iAgentEventHandler";
10
11
  import { IPlatform } from "../agent/iplatform";
11
- import { DummyLLM } from "../agent/dummyLLM";
12
+ import { DummyLLM, DummyLLMScriptEntry } from "../agent/dummyLLM";
12
13
  import { ILLM } from "../agent/llm";
13
14
 
14
15
  export const DUMMY_PLATFORM: IPlatform = {
@@ -27,25 +28,25 @@ export const DUMMY_PLATFORM: IPlatform = {
27
28
  * IAgentEventHandler which records all calls, for testing.
28
29
  */
29
30
  export class TestAgentEventHandler implements IAgentEventHandler {
30
- private all: ChatCompletionMessageParam[] = [];
31
- private completions: ChatCompletionAssistantMessageParam[] = [];
32
- private images: OpenAI.Chat.Completions.ChatCompletionContentPartImage[] = [];
31
+ private all: MessageParam[] = [];
32
+ private completions: AssistantMessageParam[] = [];
33
+ private images: ContentPartImage[] = [];
33
34
  private agentMessages: string[] = [""];
34
35
  private reasoning: string[] = [""];
35
- private toolCalls: ChatCompletionMessageToolCall[] = [];
36
- private agentToolCalls: ChatCompletionMessageToolCall[] = [];
37
- private toolCallResults: OpenAI.ChatCompletionToolMessageParam[] = [];
36
+ private toolCalls: MessageToolCall[] = [];
37
+ private agentToolCalls: MessageToolCall[] = [];
38
+ private toolCallResults: ToolMessageParam[] = [];
38
39
 
39
- onCompletion(result: ChatCompletionAssistantMessageParam) {
40
+ onCompletion(result: AssistantMessageParam) {
40
41
  this.completions.push(result);
41
42
  this.all.push(result);
42
43
  }
43
44
 
44
- onImage(image: OpenAI.Chat.Completions.ChatCompletionContentPartImage) {
45
+ onImage(image: ContentPartImage) {
45
46
  this.images.push(image);
46
47
  }
47
48
 
48
- onToolCallResult(result: ChatCompletionToolMessageParam): void {
49
+ onToolCallResult(result: ToolMessageParam): void {
49
50
  this.toolCallResults.push(result);
50
51
  this.all.push(result);
51
52
  }
@@ -69,7 +70,7 @@ export class TestAgentEventHandler implements IAgentEventHandler {
69
70
  }
70
71
 
71
72
  onToolCall(
72
- toolCall: ChatCompletionMessageToolCall,
73
+ toolCall: MessageToolCall,
73
74
  isAgentTool: boolean
74
75
  ): Promise<boolean> {
75
76
  return new Promise<boolean>((r) => {
@@ -81,11 +82,11 @@ export class TestAgentEventHandler implements IAgentEventHandler {
81
82
  });
82
83
  }
83
84
 
84
- getAll(): ChatCompletionMessageParam[] {
85
+ getAll(): MessageParam[] {
85
86
  return this.all;
86
87
  }
87
88
 
88
- getCompletions(): ChatCompletionAssistantMessageParam[] {
89
+ getCompletions(): AssistantMessageParam[] {
89
90
  return this.completions;
90
91
  }
91
92
 
@@ -93,22 +94,26 @@ export class TestAgentEventHandler implements IAgentEventHandler {
93
94
  return this.agentMessages.slice(0, this.agentMessages.length - 1);
94
95
  }
95
96
 
96
- getToolCalls(): ChatCompletionMessageToolCall[] {
97
+ getToolCalls(): MessageToolCall[] {
97
98
  return this.toolCalls;
98
99
  }
99
100
 
100
- getAgentToolCalls(): ChatCompletionMessageToolCall[] {
101
+ getAgentToolCalls(): MessageToolCall[] {
101
102
  return this.agentToolCalls;
102
103
  }
103
104
 
104
- getToolCallResults(): OpenAI.ChatCompletionToolMessageParam[] {
105
+ getToolCallResults(): ToolMessageParam[] {
105
106
  return this.toolCallResults;
106
107
  }
108
+
109
+ getReasoning(): string[] {
110
+ return this.reasoning;
111
+ }
107
112
  }
108
113
 
109
114
  export type TestLLMRequest = {
110
- messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[];
111
- tools?: OpenAI.Chat.Completions.ChatCompletionTool[];
115
+ messages: MessageParam[];
116
+ tools?: ToolDescriptor[];
112
117
  };
113
118
 
114
119
  /**
@@ -118,18 +123,24 @@ export type TestLLMRequest = {
118
123
  export class TestDummyLLM extends DummyLLM {
119
124
  private readonly requests: TestLLMRequest[];
120
125
 
121
- constructor(script: OpenAI.Chat.Completions.ChatCompletion.Choice[]) {
126
+ constructor(script: DummyLLMScriptEntry[]) {
122
127
  super(script);
123
128
  this.requests = [];
124
129
  }
125
130
 
126
131
  override getConversationResponse(
127
- messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[],
128
- tools?: OpenAI.Chat.Completions.ChatCompletionTool[],
129
- onMessage?: (msg: string, end: boolean) => Promise<void>
130
- ): Promise<OpenAI.Chat.Completions.ChatCompletion> {
132
+ messages: MessageParam[],
133
+ tools?: ToolDescriptor[],
134
+ onMessage?: (msg: string, end: boolean) => Promise<void>,
135
+ onReasoning?: (reasoning: string) => Promise<void>
136
+ ): Promise<Completion> {
131
137
  this.requests.push({ messages, tools });
132
- return super.getConversationResponse(messages, tools, onMessage);
138
+ return super.getConversationResponse(
139
+ messages,
140
+ tools,
141
+ onMessage,
142
+ onReasoning
143
+ );
133
144
  }
134
145
 
135
146
  getRequests(): TestLLMRequest[] {
@@ -151,10 +162,10 @@ export class TestErrorLLM implements ILLM {
151
162
  throw new Error("cannot set model");
152
163
  }
153
164
  getConversationResponse(
154
- _messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[],
155
- _tools?: OpenAI.Chat.Completions.ChatCompletionTool[],
165
+ _messages: MessageParam[],
166
+ _tools?: ToolDescriptor[],
156
167
  _onMessage?: (msg: string, end: boolean) => Promise<void>
157
- ): Promise<OpenAI.Chat.Completions.ChatCompletion> {
168
+ ): Promise<Completion> {
158
169
  throw new Error("LLM test error");
159
170
  }
160
171
  }
@@ -1,6 +1,5 @@
1
1
  import yocto from "yocto-spinner";
2
2
  import { Spinner } from "yocto-spinner";
3
- import OpenAI from "openai";
4
3
  import chalk from "chalk";
5
4
 
6
5
  import { configuration, utils } from "@xalia/xmcp/tool";
@@ -15,7 +14,12 @@ import { NODE_PLATFORM } from "./nodePlatform";
15
14
  import { CommandPrompt } from "./commandPrompt";
16
15
  import { IPrompt, Prompt } from "./prompt";
17
16
  import { ContextManager } from "../agent/context";
18
- import { ChatCompletionMessageParam } from "../agent/llm";
17
+ import {
18
+ ContentPartImage,
19
+ MessageParam,
20
+ MessageToolCall,
21
+ ToolMessageParam,
22
+ } from "../agent/llm";
19
23
 
20
24
  const logger = getLogger();
21
25
 
@@ -37,7 +41,7 @@ async function write(msg: string): Promise<void> {
37
41
  export async function runChat(
38
42
  llmUrl: string,
39
43
  agentProfile: AgentProfile,
40
- conversation: ChatCompletionMessageParam[] | undefined,
44
+ conversation: MessageParam[] | undefined,
41
45
  prompt: string | undefined,
42
46
  image: string | undefined,
43
47
  llmApiKey: string | undefined,
@@ -89,7 +93,7 @@ export async function runChat(
89
93
  const cmdPrompt = new CommandPrompt(repl);
90
94
 
91
95
  let remainingApprovedToolCalls = approveToolsUpTo;
92
- const onToolCall = async (toolCall: OpenAI.ChatCompletionMessageToolCall) => {
96
+ const onToolCall = async (toolCall: MessageToolCall) => {
93
97
  if (remainingApprovedToolCalls !== 0) {
94
98
  --remainingApprovedToolCalls;
95
99
  return true;
@@ -101,14 +105,12 @@ export async function runChat(
101
105
  return result;
102
106
  };
103
107
 
104
- const onToolCallResult = (result: OpenAI.ChatCompletionToolMessageParam) => {
108
+ const onToolCallResult = (result: ToolMessageParam) => {
105
109
  // CLI doesn't need to display tool results - they're handled internally
106
110
  logger.debug(`Tool call result: ${JSON.stringify(result)}`);
107
111
  };
108
112
 
109
- const onImage = (
110
- image: OpenAI.Chat.Completions.ChatCompletionContentPartImage
111
- ) => {
113
+ const onImage = (image: ContentPartImage) => {
112
114
  const dataUrl = image.image_url.url;
113
115
  void NODE_PLATFORM.renderHTML(`<img src="${dataUrl}" />`);
114
116
  };