@xalia/agent 0.6.9 → 0.6.10

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 (127) hide show
  1. package/.env.development +6 -1
  2. package/.env.test +7 -0
  3. package/README.md +11 -0
  4. package/context_system.md +498 -0
  5. package/dist/agent/src/agent/agent.js +77 -18
  6. package/dist/agent/src/agent/agentUtils.js +3 -2
  7. package/dist/agent/src/agent/documentSummarizer.js +126 -0
  8. package/dist/agent/src/agent/dummyLLM.js +25 -22
  9. package/dist/agent/src/agent/imageGenLLM.js +22 -19
  10. package/dist/agent/src/agent/llm.js +1 -1
  11. package/dist/agent/src/agent/openAILLM.js +15 -12
  12. package/dist/agent/src/agent/openAILLMStreaming.js +68 -37
  13. package/dist/agent/src/agent/repeatLLM.js +16 -7
  14. package/dist/agent/src/agent/tokenCounter.js +390 -0
  15. package/dist/agent/src/agent/tokenCounter.test.js +206 -0
  16. package/dist/agent/src/agent/toolSettings.js +17 -0
  17. package/dist/agent/src/agent/tools/calculatorTool.js +45 -0
  18. package/dist/agent/src/agent/tools/contentExtractors/pdfToText.js +55 -0
  19. package/dist/agent/src/agent/tools/datetimeTool.js +38 -0
  20. package/dist/agent/src/agent/tools/fileManager/fileManagerTool.js +156 -0
  21. package/dist/agent/src/agent/tools/fileManager/index.js +31 -0
  22. package/dist/agent/src/agent/tools/fileManager/memoryFileManager.js +102 -0
  23. package/dist/agent/src/{chat/data → agent/tools/fileManager}/mimeTypes.js +3 -1
  24. package/dist/agent/src/agent/tools/fileManager/prompt.js +33 -0
  25. package/dist/agent/src/{chat/data/dbSessionFileModels.js → agent/tools/fileManager/types.js} +7 -0
  26. package/dist/agent/src/agent/tools/index.js +64 -0
  27. package/dist/agent/src/agent/tools/openUrlTool.js +57 -0
  28. package/dist/agent/src/agent/tools/renderTool.js +89 -0
  29. package/dist/agent/src/agent/tools/utils.js +61 -0
  30. package/dist/agent/src/{chat/utils/search.js → agent/tools/webSearch.js} +1 -2
  31. package/dist/agent/src/agent/tools/webSearchTool.js +40 -0
  32. package/dist/agent/src/chat/client/chatClient.js +28 -0
  33. package/dist/agent/src/chat/client/index.js +4 -1
  34. package/dist/agent/src/chat/client/sessionClient.js +28 -2
  35. package/dist/agent/src/chat/constants.js +8 -0
  36. package/dist/agent/src/chat/data/dbSessionFiles.js +11 -6
  37. package/dist/agent/src/chat/protocol/messages.js +5 -0
  38. package/dist/agent/src/chat/server/chatContextManager.js +45 -25
  39. package/dist/agent/src/chat/server/conversation.js +3 -0
  40. package/dist/agent/src/chat/server/imageGeneratorTools.js +20 -8
  41. package/dist/agent/src/chat/server/openAIRouterLLM.js +0 -3
  42. package/dist/agent/src/chat/server/openSession.js +218 -55
  43. package/dist/agent/src/chat/server/promptRefiner.js +86 -0
  44. package/dist/agent/src/chat/server/server.js +5 -1
  45. package/dist/agent/src/chat/server/sessionFileManager.js +22 -221
  46. package/dist/agent/src/chat/server/sessionRegistry.js +87 -0
  47. package/dist/agent/src/chat/server/titleGenerator.js +112 -0
  48. package/dist/agent/src/chat/server/titleGenerator.test.js +113 -0
  49. package/dist/agent/src/chat/server/tools.js +63 -287
  50. package/dist/agent/src/chat/utils/approvalManager.js +6 -3
  51. package/dist/agent/src/chat/utils/multiAsyncQueue.js +3 -0
  52. package/dist/agent/src/test/agent.test.js +16 -17
  53. package/dist/agent/src/test/chatContextManager.test.js +15 -3
  54. package/dist/agent/src/test/dbMcpServerConfigs.test.js +4 -4
  55. package/dist/agent/src/test/dbSessionFiles.test.js +17 -17
  56. package/dist/agent/src/test/testTools.js +6 -1
  57. package/dist/agent/src/test/tools.test.js +27 -9
  58. package/dist/agent/src/tool/agentChat.js +5 -2
  59. package/dist/agent/src/tool/chatMain.js +34 -7
  60. package/dist/agent/src/tool/commandPrompt.js +2 -2
  61. package/dist/agent/src/tool/files.js +7 -8
  62. package/package.json +4 -1
  63. package/scripts/test_chat +195 -176
  64. package/src/agent/agent.ts +98 -23
  65. package/src/agent/agentUtils.ts +3 -2
  66. package/src/agent/documentSummarizer.ts +157 -0
  67. package/src/agent/dummyLLM.ts +27 -23
  68. package/src/agent/imageGenLLM.ts +28 -24
  69. package/src/agent/llm.ts +2 -2
  70. package/src/agent/openAILLM.ts +17 -13
  71. package/src/agent/openAILLMStreaming.ts +80 -41
  72. package/src/agent/repeatLLM.ts +19 -7
  73. package/src/agent/test_data/harrypotter.txt +6065 -0
  74. package/src/agent/tokenCounter.test.ts +243 -0
  75. package/src/agent/tokenCounter.ts +483 -0
  76. package/src/agent/toolSettings.ts +24 -0
  77. package/src/agent/tools/calculatorTool.ts +50 -0
  78. package/src/agent/tools/contentExtractors/pdfToText.ts +60 -0
  79. package/src/agent/tools/datetimeTool.ts +41 -0
  80. package/src/agent/tools/fileManager/fileManagerTool.ts +199 -0
  81. package/src/agent/tools/fileManager/index.ts +50 -0
  82. package/src/agent/tools/fileManager/memoryFileManager.ts +120 -0
  83. package/src/{chat/data → agent/tools/fileManager}/mimeTypes.ts +3 -1
  84. package/src/agent/tools/fileManager/prompt.ts +38 -0
  85. package/src/{chat/data/dbSessionFileModels.ts → agent/tools/fileManager/types.ts} +76 -0
  86. package/src/agent/tools/index.ts +49 -0
  87. package/src/agent/tools/openUrlTool.ts +62 -0
  88. package/src/agent/tools/renderTool.ts +92 -0
  89. package/src/agent/tools/utils.ts +74 -0
  90. package/src/{chat/utils/search.ts → agent/tools/webSearch.ts} +0 -1
  91. package/src/agent/tools/webSearchTool.ts +44 -0
  92. package/src/chat/client/chatClient.ts +45 -0
  93. package/src/chat/client/index.ts +3 -0
  94. package/src/chat/client/sessionClient.ts +40 -3
  95. package/src/chat/client/sessionFiles.ts +1 -1
  96. package/src/chat/constants.ts +6 -0
  97. package/src/chat/data/dataModels.ts +6 -0
  98. package/src/chat/data/dbSessionFiles.ts +12 -4
  99. package/src/chat/protocol/messages.ts +60 -7
  100. package/src/chat/server/chatContextManager.ts +58 -37
  101. package/src/chat/server/conversation.ts +3 -0
  102. package/src/chat/server/imageGeneratorTools.ts +31 -12
  103. package/src/chat/server/openAIRouterLLM.ts +1 -4
  104. package/src/chat/server/openSession.ts +323 -67
  105. package/src/chat/server/promptRefiner.ts +106 -0
  106. package/src/chat/server/server.ts +4 -1
  107. package/src/chat/server/sessionFileManager.ts +35 -306
  108. package/src/chat/server/sessionRegistry.ts +128 -0
  109. package/src/chat/server/titleGenerator.test.ts +103 -0
  110. package/src/chat/server/titleGenerator.ts +143 -0
  111. package/src/chat/server/tools.ts +77 -304
  112. package/src/chat/utils/approvalManager.ts +9 -3
  113. package/src/chat/utils/multiAsyncQueue.ts +4 -0
  114. package/src/test/agent.test.ts +17 -23
  115. package/src/test/chatContextManager.test.ts +29 -4
  116. package/src/test/dbMcpServerConfigs.test.ts +4 -4
  117. package/src/test/dbSessionFiles.test.ts +16 -16
  118. package/src/test/testTools.ts +8 -3
  119. package/src/test/tools.test.ts +30 -5
  120. package/src/tool/agentChat.ts +12 -3
  121. package/src/tool/chatMain.ts +33 -6
  122. package/src/tool/commandPrompt.ts +2 -2
  123. package/src/tool/files.ts +1 -3
  124. package/dist/agent/src/agent/tools.js +0 -44
  125. package/src/agent/tools.ts +0 -57
  126. /package/dist/agent/src/{chat/utils → agent/tools/contentExtractors}/htmlToText.js +0 -0
  127. /package/src/{chat/utils → agent/tools/contentExtractors}/htmlToText.ts +0 -0
@@ -34,15 +34,14 @@ import {
34
34
  ISessionFileManager,
35
35
  ISessionFileManagerEventHandler,
36
36
  createSessionFilesManagerPrompt,
37
- } from "./sessionFileManager";
38
- import {
39
37
  SessionFileDescriptor,
40
38
  SessionFileEntry,
41
- } from "../data/dbSessionFileModels";
39
+ } from "../../agent/tools/fileManager";
42
40
  // eslint-disable-next-line max-len
43
41
  import { ContextTransactionWithWorkspace } from "../../agent/contextWithWorkspace";
44
42
  import { getErrorString } from "./errorUtils";
45
43
  import { createUserMessage } from "../../agent/agent";
44
+ import { TokenCounter } from "../../agent/tokenCounter";
46
45
 
47
46
  const logger = getLogger();
48
47
 
@@ -64,7 +63,8 @@ export interface ICheckpointWriter {
64
63
  export class ChatContextTransaction implements IContextTransaction {
65
64
  private readonly baseTx: ContextTransactionWithWorkspace;
66
65
  private readonly sessionUUID: string;
67
- /// Index of final message in the committed context
66
+ /// Index of final message in the committed context. If this has changed
67
+ /// before we try to commit this tx, the commit will fail.
68
68
  private readonly baseMsgIdx: number | undefined;
69
69
  private readonly startingLLMContextLength: number;
70
70
  private readonly pendingMessages: ConversationMessage[];
@@ -216,7 +216,6 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
216
216
  private readonly llmContext: CompressingContextManager;
217
217
 
218
218
  private nextMessageIdx: number;
219
- private pendingUserMessages: ServerUserMessage[];
220
219
 
221
220
  // Compression state
222
221
  private readonly checkpointWriter: ICheckpointWriter;
@@ -226,6 +225,10 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
226
225
  private readonly fileManager: ISessionFileManager;
227
226
  private fileManagerDescriptionsDirty: boolean;
228
227
 
228
+ // LLM and token counting
229
+ private readonly llm: ILLM;
230
+ private tokenCounter: TokenCounter;
231
+
229
232
  constructor(
230
233
  systemPrompt: string,
231
234
  sessionMessages: SessionMessage[],
@@ -254,7 +257,6 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
254
257
  defaultUserName,
255
258
  sessionUUID
256
259
  );
257
- this.pendingUserMessages = [];
258
260
  this.llmContext = new CompressingContextManager(
259
261
  systemPrompt,
260
262
  llmMessages,
@@ -266,13 +268,14 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
266
268
  this.fileManager = fileManager;
267
269
  fileManager.addEventHandler(this);
268
270
  this.fileManagerDescriptionsDirty = true;
271
+ this.llm = llm;
272
+ this.tokenCounter = new TokenCounter(llm.getModel());
269
273
  }
270
274
 
271
275
  // IContextManager.getLLMContext
272
276
  getLLMContext(): MessageParam[] {
273
277
  if (this.fileManagerDescriptionsDirty) {
274
278
  const prompt = createSessionFilesManagerPrompt(this.fileManager);
275
- logger.debug(`[ChatContextManager] filemanager prompt:\n${prompt}`);
276
279
  this.llmContext.setPromptFragment("file_manager", prompt);
277
280
  this.fileManagerDescriptionsDirty = false;
278
281
  }
@@ -324,7 +327,22 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
324
327
 
325
328
  // Get the conversation (to send to clients)
326
329
  getConversationMessages(): ConversationMessage[] {
327
- return this.conversationMessages.concat(this.pendingUserMessages);
330
+ return this.conversationMessages;
331
+ }
332
+
333
+ // Get current context usage (tokens)
334
+ getContextUsage(): { used: number; max: number } {
335
+ // Update tokenCounter if model changed
336
+ const currentModel = this.llm.getModel();
337
+ if (this.tokenCounter.getModel() !== currentModel) {
338
+ this.tokenCounter.free();
339
+ this.tokenCounter = new TokenCounter(currentModel);
340
+ }
341
+
342
+ const messages = this.getLLMContext();
343
+ const used = this.tokenCounter.countMessagesTokens(messages);
344
+ const max = this.tokenCounter.getContextWindow();
345
+ return { used, max };
328
346
  }
329
347
 
330
348
  processUserMessage(
@@ -336,7 +354,11 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
336
354
  // pass in our generated messages back into `startAgentResponse`.
337
355
 
338
356
  // Filter out null messages immediately.
339
- if (!msg.imageB64 && !msg.message) {
357
+ if (
358
+ !msg.imageB64 &&
359
+ !msg.message &&
360
+ (!msg.attachedFiles || msg.attachedFiles.length === 0)
361
+ ) {
340
362
  return undefined;
341
363
  }
342
364
 
@@ -352,8 +374,13 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
352
374
  if (msg.imageB64) {
353
375
  userMessage.imageB64 = msg.imageB64;
354
376
  }
377
+ if (msg.attachedFiles) {
378
+ userMessage.attachedFiles = msg.attachedFiles;
379
+ }
380
+ if (msg.race_mode) {
381
+ userMessage.race_mode = msg.race_mode;
382
+ }
355
383
 
356
- this.pendingUserMessages.push(userMessage);
357
384
  return userMessage;
358
385
  }
359
386
 
@@ -373,32 +400,18 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
373
400
  // Sanity check the state - the incoming user messages should match the
374
401
  // pending user messages.
375
402
 
376
- const numMessages = this.pendingUserMessages.length;
377
- assert(numMessages > 0);
378
- if (msgs.length !== this.pendingUserMessages.length) {
379
- throw new Error(
380
- `length mismatch: msgs: ${JSON.stringify(msgs)}, ` +
381
- `this.pendingUserMsgs: ${JSON.stringify(this.pendingUserMessages)}`
382
- );
383
- }
384
- assert(msgs[0].message_idx === this.pendingUserMessages[0].message_idx);
385
- assert(
386
- msgs[numMessages - 1].message_idx ===
387
- this.pendingUserMessages[numMessages - 1].message_idx
388
- );
389
-
403
+ const numMessages = msgs.length;
404
+ assert(numMessages > 0, "no messages");
390
405
  // Collect the pending user messages and allocate a starting index for
391
406
  // agent messages and tool calls.
392
407
 
393
- const pendingUserMessages = this.pendingUserMessages;
394
- const baseMsgIdx = this.lastMessageIdx();
408
+ const baseMsgIdx = this.lastCommittedMessageIdx();
395
409
  const curAgentMsgIdx = this.getNextMessageIdx();
396
- this.pendingUserMessages = [];
397
410
 
398
411
  // Compute the new llm messages
399
412
 
400
413
  const llmUserMessages: UserMessageParam[] = [];
401
- for (const msg of pendingUserMessages) {
414
+ for (const msg of msgs) {
402
415
  const userMsg = createUserMessage(
403
416
  msg.message,
404
417
  msg.imageB64,
@@ -419,12 +432,19 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
419
432
  end: false,
420
433
  };
421
434
 
435
+ // Update file manager fragment BEFORE starting the transaction
436
+ if (this.fileManagerDescriptionsDirty) {
437
+ const prompt = createSessionFilesManagerPrompt(this.fileManager);
438
+ this.llmContext.setPromptFragment("file_manager", prompt);
439
+ this.fileManagerDescriptionsDirty = false;
440
+ }
441
+
422
442
  const baseTx = await this.llmContext.startTx(llmUserMessages);
423
443
  const contextTx = new ChatContextTransaction(
424
444
  baseTx,
425
445
  this.sessionUUID,
426
446
  baseMsgIdx,
427
- pendingUserMessages,
447
+ msgs,
428
448
  curAgentMsgIdx
429
449
  );
430
450
  return { agentFirstChunk, contextTx };
@@ -432,7 +452,7 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
432
452
 
433
453
  async endAgentResponse(tx: IContextTransaction): Promise<SessionMessage[]> {
434
454
  assert(tx instanceof ChatContextTransaction);
435
- if (tx.baseMessageIdx() !== this.lastMessageIdx()) {
455
+ if (tx.baseMessageIdx() !== this.lastCommittedMessageIdx()) {
436
456
  throw new Error(
437
457
  `Tx stale? tx.baseMessageIdx=${String(tx.baseMessageIdx())}, ` +
438
458
  `this.conv: ${JSON.stringify(this.conversationMessages)}`
@@ -449,12 +469,13 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
449
469
  const newLLMMessages = tx.newMessages();
450
470
 
451
471
  const messageListError = (error: string) => {
452
- throw new Error(
453
- `${error}:` +
454
- `\n newSessionMessages: ${JSON.stringify(newSessionMessages)}` +
455
- `\n pending: ${JSON.stringify(pending)}` +
456
- `\n newLLMMessages: ${JSON.stringify(newLLMMessages)}`
457
- );
472
+ const fullError =
473
+ `[endAgentResponse] Message list validation failed - ${error}:` +
474
+ `\n newSessionMessages: ${JSON.stringify(newSessionMessages)}` +
475
+ `\n pending: ${JSON.stringify(pending)}` +
476
+ `\n newLLMMessages: ${JSON.stringify(newLLMMessages)}`;
477
+ logger.error(fullError);
478
+ throw new Error(fullError);
458
479
  };
459
480
 
460
481
  if (newSessionMessages.length !== numPending) {
@@ -506,7 +527,7 @@ export class ChatContextManager implements ISessionFileManagerEventHandler {
506
527
  return newSessionMessages;
507
528
  }
508
529
 
509
- private lastMessageIdx(): number | undefined {
530
+ private lastCommittedMessageIdx(): number | undefined {
510
531
  const numMsgs = this.conversationMessages.length;
511
532
  if (numMsgs > 0) {
512
533
  return this.conversationMessages[numMsgs - 1].message_idx;
@@ -127,6 +127,9 @@ export function userMessageToConversationMessage(
127
127
  if (userMsgData.imageB64) {
128
128
  msg.imageB64 = userMsgData.imageB64;
129
129
  }
130
+ if (userMsgData.attachedFiles) {
131
+ msg.attachedFiles = userMsgData.attachedFiles;
132
+ }
130
133
  return msg;
131
134
  }
132
135
 
@@ -4,15 +4,16 @@ import { AgentEx, IAgentToolProvider, ToolCallResult } from "../../agent/agent";
4
4
  import { ToolDescriptor } from "../../agent/llm";
5
5
  import { ImageGenerator } from "../../agent/imageGenerator";
6
6
  import {
7
- ChatSessionFileManager,
7
+ ISessionFileManager,
8
8
  ToolCallResultWithFileRef,
9
- } from "./sessionFileManager";
10
- import { makeParseArgsFn } from "./tools";
11
- import { getSessionFileMimeTypeFromDataUrl } from "../data/dbSessionFileModels";
9
+ getSessionFileMimeTypeFromDataUrl,
10
+ makeParseArgsFn,
11
+ } from "../../agent/tools";
12
12
  import { getOpenAIClientParams } from "./openAIRouterLLM";
13
13
  import { DEFAULT_IMAGE_GEN_MODEL, ImageGenLLM } from "../../agent/imageGenLLM";
14
14
  import { createSpecializedLLM } from "../../agent/agentUtils";
15
15
  import { IPlatform } from "../../agent/iplatform";
16
+ import { CANVAS_WORKSPACE_FILENAME } from "../constants";
16
17
 
17
18
  const logger = getLogger();
18
19
 
@@ -95,13 +96,17 @@ export async function genImageTool(
95
96
 
96
97
  export async function genImageFileTool(
97
98
  platform: IPlatform,
98
- fileManager: ChatSessionFileManager
99
+ fileManager: ISessionFileManager
99
100
  ): Promise<IAgentToolProvider> {
100
101
  const GEN_IMAGE_FILE_DESC: ToolDescriptor = {
101
102
  type: "function",
102
103
  function: {
103
104
  name: "gen_image_file",
104
- description: "Generate image (into session file manager)",
105
+ description:
106
+ "Generate or edit an image. Saves result to file manager. " +
107
+ `Canvas workspace is '${CANVAS_WORKSPACE_FILENAME}'. ` +
108
+ "When editing canvas images, set add_to_canvas=true to " +
109
+ "place the result back onto the canvas.",
105
110
  parameters: {
106
111
  type: "object",
107
112
  properties: {
@@ -119,7 +124,14 @@ export async function genImageFileTool(
119
124
  },
120
125
  input_name: {
121
126
  type: "string",
122
- description: "(Optional) input image filename",
127
+ description:
128
+ "(Optional) input image filename. " +
129
+ `Use '${CANVAS_WORKSPACE_FILENAME}' for canvas edits.`,
130
+ },
131
+ add_to_canvas: {
132
+ type: "boolean",
133
+ description:
134
+ "Set true to place result on canvas (use when editing canvas)",
123
135
  },
124
136
  },
125
137
  required: ["prompt", "name", "summary"],
@@ -128,26 +140,33 @@ export async function genImageFileTool(
128
140
  } as const;
129
141
 
130
142
  const imageGenerator = await createImageGenerator(platform);
131
- const getPromptNameSummary = makeParseArgsFn(
143
+ const getArgs = makeParseArgsFn(
132
144
  ["prompt", "name", "summary"] as const,
133
- ["input_name"] as const
145
+ ["input_name"] as const,
146
+ ["add_to_canvas"] as const
134
147
  );
135
148
  const toolFn = async (
136
149
  _: AgentEx,
137
150
  args: unknown
138
151
  ): Promise<ToolCallResultWithFileRef> => {
139
- const { prompt, name, summary, input_name } = getPromptNameSummary(args);
152
+ const { prompt, name, summary, input_name, add_to_canvas } = getArgs(args);
153
+ const addToCanvas = add_to_canvas ?? false;
154
+
140
155
  const input_image = input_name
141
156
  ? await fileManager.getFileContent(input_name)
142
157
  : undefined;
143
158
 
144
159
  const image = await imageGenerator.generate(prompt, input_image);
145
- const mimeType = getSessionFileMimeTypeFromDataUrl(image);
146
160
  await fileManager.putFileContent(name, summary, image);
147
161
  const uri = fileManager.getSessionFileRelativeUrl(name);
162
+
148
163
  return {
149
164
  response: uri,
150
- _meta: { "xalia/fileUri": uri, "xalia/fileMimeType": mimeType },
165
+ _meta: {
166
+ "xalia/fileUri": uri,
167
+ "xalia/fileMimeType": getSessionFileMimeTypeFromDataUrl(image),
168
+ ...(addToCanvas && { "xalia/addToCanvas": "true" }),
169
+ },
151
170
  };
152
171
  };
153
172
 
@@ -20,7 +20,6 @@ const DEFAULT_PROVIDER_URLS: Record<string, string | undefined> = {
20
20
  openrouter: "https://openrouter.ai/api/v1",
21
21
  openai: "https://api.openai.com/v1",
22
22
  anthropic: "https://api.anthropic.com/v1",
23
- together: "https://api.together.xyz/v1",
24
23
  };
25
24
 
26
25
  const DEFAULT_MODEL_MAP: Record<string, string | undefined> = {
@@ -35,8 +34,6 @@ const DEFAULT_MODEL_MAP: Record<string, string | undefined> = {
35
34
  "anthropic/claude-sonnet-4": "openrouter",
36
35
  "anthropic/claude-sonnet-4.5": "openrouter",
37
36
  "claude-3-7-sonnet-20250219": "anthropic",
38
- "arcee-ai/AFM-4.5B-Preview": "together",
39
- "meta-llama/Llama-3.3-70B-Instruct-Turbo-Free": "together",
40
37
  };
41
38
 
42
39
  type CachedMaps = {
@@ -158,7 +155,7 @@ export class OpenAIRouterLLM implements ILLM {
158
155
  tools?: ToolDescriptor[],
159
156
  onMessage?: (msg: string, end: boolean) => Promise<void>,
160
157
  onReasoning?: (reasoning: string) => Promise<void>
161
- ): Promise<Completion> {
158
+ ): Promise<{ stop: (msg: string) => void; completion: Promise<Completion> }> {
162
159
  return OpenAILLMStreaming.makeRequest(
163
160
  this.openai,
164
161
  this.model,