@witqq/agent-sdk 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/dist/{agent-DxY68NZL.d.cts → agent-C6H2CgJA.d.cts} +2 -0
  2. package/dist/{agent-CW9XbmG_.d.ts → agent-F7oB6eKp.d.ts} +2 -0
  3. package/dist/backends/claude.cjs.map +1 -1
  4. package/dist/backends/claude.d.cts +2 -2
  5. package/dist/backends/claude.d.ts +2 -2
  6. package/dist/backends/claude.js.map +1 -1
  7. package/dist/backends/copilot.cjs +8 -15
  8. package/dist/backends/copilot.cjs.map +1 -1
  9. package/dist/backends/copilot.d.cts +2 -2
  10. package/dist/backends/copilot.d.ts +2 -2
  11. package/dist/backends/copilot.js +8 -15
  12. package/dist/backends/copilot.js.map +1 -1
  13. package/dist/backends/mock-llm.cjs +719 -0
  14. package/dist/backends/mock-llm.cjs.map +1 -0
  15. package/dist/backends/mock-llm.d.cts +37 -0
  16. package/dist/backends/mock-llm.d.ts +37 -0
  17. package/dist/backends/mock-llm.js +717 -0
  18. package/dist/backends/mock-llm.js.map +1 -0
  19. package/dist/backends/vercel-ai.cjs +8 -1
  20. package/dist/backends/vercel-ai.cjs.map +1 -1
  21. package/dist/backends/vercel-ai.d.cts +2 -2
  22. package/dist/backends/vercel-ai.d.ts +2 -2
  23. package/dist/backends/vercel-ai.js +8 -1
  24. package/dist/backends/vercel-ai.js.map +1 -1
  25. package/dist/backends-Cno0gZjy.d.cts +114 -0
  26. package/dist/backends-Cno0gZjy.d.ts +114 -0
  27. package/dist/chat/accumulator.cjs.map +1 -1
  28. package/dist/chat/accumulator.d.cts +2 -2
  29. package/dist/chat/accumulator.d.ts +2 -2
  30. package/dist/chat/accumulator.js.map +1 -1
  31. package/dist/chat/backends.cjs +350 -77
  32. package/dist/chat/backends.cjs.map +1 -1
  33. package/dist/chat/backends.d.cts +7 -7
  34. package/dist/chat/backends.d.ts +7 -7
  35. package/dist/chat/backends.js +349 -78
  36. package/dist/chat/backends.js.map +1 -1
  37. package/dist/chat/context.d.cts +2 -2
  38. package/dist/chat/context.d.ts +2 -2
  39. package/dist/chat/core.cjs +35 -25
  40. package/dist/chat/core.cjs.map +1 -1
  41. package/dist/chat/core.d.cts +15 -5
  42. package/dist/chat/core.d.ts +15 -5
  43. package/dist/chat/core.js +35 -26
  44. package/dist/chat/core.js.map +1 -1
  45. package/dist/chat/events.d.cts +2 -2
  46. package/dist/chat/events.d.ts +2 -2
  47. package/dist/chat/index.cjs +418 -122
  48. package/dist/chat/index.cjs.map +1 -1
  49. package/dist/chat/index.d.cts +7 -7
  50. package/dist/chat/index.d.ts +7 -7
  51. package/dist/chat/index.js +418 -124
  52. package/dist/chat/index.js.map +1 -1
  53. package/dist/chat/react.cjs +216 -12
  54. package/dist/chat/react.cjs.map +1 -1
  55. package/dist/chat/react.d.cts +78 -4
  56. package/dist/chat/react.d.ts +78 -4
  57. package/dist/chat/react.js +215 -13
  58. package/dist/chat/react.js.map +1 -1
  59. package/dist/chat/runtime.cjs +6 -2
  60. package/dist/chat/runtime.cjs.map +1 -1
  61. package/dist/chat/runtime.d.cts +2 -2
  62. package/dist/chat/runtime.d.ts +2 -2
  63. package/dist/chat/runtime.js +6 -2
  64. package/dist/chat/runtime.js.map +1 -1
  65. package/dist/chat/server.cjs +15 -5
  66. package/dist/chat/server.cjs.map +1 -1
  67. package/dist/chat/server.d.cts +3 -3
  68. package/dist/chat/server.d.ts +3 -3
  69. package/dist/chat/server.js +15 -5
  70. package/dist/chat/server.js.map +1 -1
  71. package/dist/chat/sessions.cjs +39 -23
  72. package/dist/chat/sessions.cjs.map +1 -1
  73. package/dist/chat/sessions.d.cts +2 -2
  74. package/dist/chat/sessions.d.ts +2 -2
  75. package/dist/chat/sessions.js +40 -24
  76. package/dist/chat/sessions.js.map +1 -1
  77. package/dist/chat/sqlite.cjs +95 -0
  78. package/dist/chat/sqlite.cjs.map +1 -1
  79. package/dist/chat/sqlite.d.cts +39 -3
  80. package/dist/chat/sqlite.d.ts +39 -3
  81. package/dist/chat/sqlite.js +93 -1
  82. package/dist/chat/sqlite.js.map +1 -1
  83. package/dist/chat/state.d.cts +2 -2
  84. package/dist/chat/state.d.ts +2 -2
  85. package/dist/chat/storage.cjs +39 -23
  86. package/dist/chat/storage.cjs.map +1 -1
  87. package/dist/chat/storage.d.cts +7 -3
  88. package/dist/chat/storage.d.ts +7 -3
  89. package/dist/chat/storage.js +40 -24
  90. package/dist/chat/storage.js.map +1 -1
  91. package/dist/{in-process-transport-C1JnJGVR.d.ts → in-process-transport-7EIit9Xk.d.ts} +51 -17
  92. package/dist/{in-process-transport-C7DSqPyX.d.cts → in-process-transport-Ct9YcX8I.d.cts} +51 -17
  93. package/dist/index.cjs +14 -14
  94. package/dist/index.cjs.map +1 -1
  95. package/dist/index.d.cts +4 -2
  96. package/dist/index.d.ts +4 -2
  97. package/dist/index.js +13 -13
  98. package/dist/index.js.map +1 -1
  99. package/dist/testing.cjs +724 -0
  100. package/dist/testing.cjs.map +1 -1
  101. package/dist/testing.d.cts +14 -2
  102. package/dist/testing.d.ts +14 -2
  103. package/dist/testing.js +724 -0
  104. package/dist/testing.js.map +1 -1
  105. package/dist/{transport-Cdh3M0tS.d.cts → transport-DLWCN18G.d.cts} +1 -1
  106. package/dist/{transport-Ciap4PWK.d.ts → transport-DsuS-GeM.d.ts} +1 -1
  107. package/dist/{types-ajANVzf7.d.ts → types-DgtI1hzh.d.ts} +2 -1
  108. package/dist/{types-DRgd_9R7.d.cts → types-DkSXALKg.d.cts} +2 -1
  109. package/package.json +18 -7
  110. package/LICENSE +0 -21
  111. package/README.md +0 -1054
  112. package/dist/backends-BSrsBYFn.d.cts +0 -39
  113. package/dist/backends-BSrsBYFn.d.ts +0 -39
@@ -724,17 +724,6 @@ function convertParameters(params) {
724
724
  }
725
725
  return params;
726
726
  }
727
- async function mapToolsToSDKAsync(tools) {
728
- return tools.map((tool) => ({
729
- name: tool.name,
730
- description: tool.description,
731
- parameters: convertParameters(tool.parameters),
732
- handler: async (args) => {
733
- const result = await tool.execute(args);
734
- return typeof result === "string" ? result : JSON.stringify(result);
735
- }
736
- }));
737
- }
738
727
  function buildPermissionHandler(config) {
739
728
  const onPermission = config.supervisor?.onPermission;
740
729
  if (!onPermission) {
@@ -972,15 +961,15 @@ var init_copilot = __esm({
972
961
  },
973
962
  onPermissionRequest: buildPermissionHandler(config),
974
963
  onUserInputRequest: buildUserInputHandler(config),
975
- ...config.availableTools?.length ? { availableTools: config.availableTools } : {}
964
+ ...config.availableTools ? { availableTools: config.availableTools } : {}
976
965
  };
977
966
  this._toolsReady = this._initToolsAsync(config);
978
967
  this._resumeSessionId = resumeSessionId;
979
968
  }
980
- /** Pre-convert Zod schemas to JSON Schema asynchronously.
969
+ /** Pre-convert Zod schemas to JSON Schema.
981
970
  * Updates sdkTools and sessionConfig.tools before first session creation. */
982
971
  async _initToolsAsync(config) {
983
- this.sdkTools = await mapToolsToSDKAsync(config.tools ?? []);
972
+ this.sdkTools = mapToolsToSDK(config.tools ?? []);
984
973
  this.sessionConfig.tools = this.sdkTools;
985
974
  }
986
975
  get sessionId() {
@@ -1271,7 +1260,11 @@ You MUST respond with ONLY valid JSON matching this schema:
1271
1260
  githubToken: this.options.githubToken,
1272
1261
  useLoggedInUser: this.options.useLoggedInUser ?? !this.options.githubToken,
1273
1262
  ...this.options.cliArgs ? { cliArgs: this.options.cliArgs } : {},
1274
- ...this.options.env ? { env: { ...process.env, ...this.options.env } } : {}
1263
+ env: {
1264
+ ...process.env,
1265
+ ...this.options.githubToken ? { GITHUB_TOKEN: this.options.githubToken } : {},
1266
+ ...this.options.env
1267
+ }
1275
1268
  });
1276
1269
  const startupTimeout = this.options.startupTimeoutMs ?? 3e4;
1277
1270
  await withTimeout(client.start(), startupTimeout, "CLI startup timed out");
@@ -2691,6 +2684,7 @@ var init_vercel_ai = __esm({
2691
2684
  }
2692
2685
  });
2693
2686
  let finalText = "";
2687
+ let lastFinishReason;
2694
2688
  try {
2695
2689
  for await (const part of result.fullStream) {
2696
2690
  if (signal.aborted) throw new AbortError();
@@ -2701,10 +2695,15 @@ var init_vercel_ai = __esm({
2701
2695
  }
2702
2696
  if (part.type === "finish-step") {
2703
2697
  const p = part;
2698
+ lastFinishReason = p.finishReason;
2704
2699
  if (p.finishReason === "tool-calls") {
2705
2700
  finalText = "";
2706
2701
  }
2707
2702
  }
2703
+ if (part.type === "finish") {
2704
+ const p = part;
2705
+ lastFinishReason = p.finishReason;
2706
+ }
2708
2707
  }
2709
2708
  const totalUsage = await result.totalUsage;
2710
2709
  yield {
@@ -2716,7 +2715,8 @@ var init_vercel_ai = __esm({
2716
2715
  yield {
2717
2716
  type: "done",
2718
2717
  finalOutput: hasStreamed ? null : finalText || null,
2719
- ...hasStreamed ? { streamed: true } : {}
2718
+ ...hasStreamed ? { streamed: true } : {},
2719
+ ...lastFinishReason ? { finishReason: lastFinishReason } : {}
2720
2720
  };
2721
2721
  } catch (e) {
2722
2722
  if (signal.aborted) throw new AbortError();
@@ -2881,8 +2881,9 @@ function agentEventToChatEvent(event, messageId) {
2881
2881
  case "ask_user":
2882
2882
  case "ask_user_response":
2883
2883
  case "session_info":
2884
- case "done":
2885
2884
  return null;
2885
+ case "done":
2886
+ return { type: "done", finalOutput: event.finalOutput ?? void 0, finishReason: event.finishReason };
2886
2887
  default:
2887
2888
  return null;
2888
2889
  }
@@ -2897,24 +2898,37 @@ async function* adaptAgentEvents(events, messageId) {
2897
2898
  }
2898
2899
 
2899
2900
  // src/chat/conversion.ts
2900
- function toAgentMessage(message) {
2901
+ function toAgentMessages(message) {
2901
2902
  const textContent = getMessageText(message);
2902
2903
  const toolCallParts = getMessageToolCalls(message);
2903
2904
  switch (message.role) {
2904
2905
  case "user":
2905
- return { role: "user", content: textContent };
2906
+ return [{ role: "user", content: textContent }];
2906
2907
  case "assistant": {
2907
2908
  const toolCalls = toolCallParts.length > 0 ? toolCallParts.map((p) => ({ id: p.toolCallId, name: p.name, args: p.args })) : void 0;
2908
- return {
2909
+ const assistantMsg = {
2909
2910
  role: "assistant",
2910
2911
  content: textContent,
2911
2912
  toolCalls
2912
2913
  };
2914
+ const toolResults = extractToolResults(message);
2915
+ if (toolResults.length > 0) {
2916
+ return [assistantMsg, { role: "tool", toolResults }];
2917
+ }
2918
+ return [assistantMsg];
2913
2919
  }
2914
2920
  case "system":
2915
- return { role: "system", content: textContent };
2921
+ return [{ role: "system", content: textContent }];
2916
2922
  }
2917
2923
  }
2924
+ function extractToolResults(message) {
2925
+ return getMessageToolCalls(message).filter((p) => p.result !== void 0).map((p) => ({
2926
+ toolCallId: p.toolCallId,
2927
+ name: p.name,
2928
+ result: p.result,
2929
+ isError: p.status === "error" ? true : void 0
2930
+ }));
2931
+ }
2918
2932
 
2919
2933
  // src/chat/errors.ts
2920
2934
  init_errors2();
@@ -3013,7 +3027,7 @@ var BaseBackendAdapter = class {
3013
3027
  async *streamMessage(session, message, options) {
3014
3028
  this.assertNotDisposed();
3015
3029
  const agent = this.getOrCreateAgent(options);
3016
- const messages = session.messages.map(toAgentMessage);
3030
+ const messages = session.messages.flatMap(toAgentMessages);
3017
3031
  messages.push({ role: "user", content: message });
3018
3032
  yield* this.streamAgentEvents(agent, messages, options);
3019
3033
  }
@@ -3090,7 +3104,8 @@ var BaseBackendAdapter = class {
3090
3104
  }
3091
3105
  const config = {
3092
3106
  ...this._agentConfig,
3093
- ...model !== void 0 && { model }
3107
+ ...model !== void 0 && { model },
3108
+ ...options?.tools?.length ? { tools: options.tools } : {}
3094
3109
  };
3095
3110
  const agent = this.agentService.createAgent(config);
3096
3111
  this._currentAgent = { instance: agent, model };
@@ -3105,21 +3120,15 @@ var BaseBackendAdapter = class {
3105
3120
  }
3106
3121
  };
3107
3122
 
3108
- // src/chat/backends/copilot.ts
3109
- var CopilotChatAdapter = class extends BaseBackendAdapter {
3123
+ // src/chat/backends/resumable.ts
3124
+ var ResumableChatAdapter = class extends BaseBackendAdapter {
3110
3125
  _backendSessionId = null;
3111
- _copilotOptions;
3112
- constructor(options) {
3126
+ constructor(name, options) {
3113
3127
  const agentConfig = {
3114
3128
  ...options.agentConfig,
3115
3129
  sessionMode: "persistent"
3116
3130
  };
3117
- super("copilot", { ...options, agentConfig });
3118
- this._copilotOptions = options.copilotOptions;
3119
- }
3120
- createService() {
3121
- const { createCopilotService: createCopilotService2 } = (init_copilot(), __toCommonJS(copilot_exports));
3122
- return createCopilotService2(this._copilotOptions || {});
3131
+ super(name, { ...options, agentConfig });
3123
3132
  }
3124
3133
  get backendSessionId() {
3125
3134
  return this._backendSessionId;
@@ -3148,7 +3157,7 @@ var CopilotChatAdapter = class extends BaseBackendAdapter {
3148
3157
  { code: "SESSION_EXPIRED" /* SESSION_EXPIRED */ }
3149
3158
  );
3150
3159
  }
3151
- const messages = session.messages.map(toAgentMessage);
3160
+ const messages = session.messages.flatMap(toAgentMessages);
3152
3161
  yield* this.streamAgentEvents(agent, messages, options);
3153
3162
  }
3154
3163
  captureSessionId(agent) {
@@ -3158,69 +3167,325 @@ var CopilotChatAdapter = class extends BaseBackendAdapter {
3158
3167
  }
3159
3168
  };
3160
3169
 
3170
+ // src/chat/backends/copilot.ts
3171
+ var CopilotChatAdapter = class extends ResumableChatAdapter {
3172
+ _copilotOptions;
3173
+ constructor(options) {
3174
+ super("copilot", options);
3175
+ this._copilotOptions = options.copilotOptions;
3176
+ }
3177
+ createService() {
3178
+ const { createCopilotService: createCopilotService2 } = (init_copilot(), __toCommonJS(copilot_exports));
3179
+ return createCopilotService2(this._copilotOptions || {});
3180
+ }
3181
+ };
3182
+
3161
3183
  // src/chat/backends/claude.ts
3162
- var ClaudeChatAdapter = class extends BaseBackendAdapter {
3163
- _backendSessionId = null;
3184
+ var ClaudeChatAdapter = class extends ResumableChatAdapter {
3164
3185
  _claudeOptions;
3165
3186
  constructor(options) {
3166
- const agentConfig = {
3167
- ...options.agentConfig,
3168
- sessionMode: "persistent"
3169
- };
3170
- super("claude", { ...options, agentConfig });
3187
+ super("claude", options);
3171
3188
  this._claudeOptions = options.claudeOptions;
3172
3189
  }
3173
3190
  createService() {
3174
3191
  const { createClaudeService: createClaudeService2 } = (init_claude(), __toCommonJS(claude_exports));
3175
3192
  return createClaudeService2(this._claudeOptions || {});
3176
3193
  }
3177
- get backendSessionId() {
3178
- return this._backendSessionId;
3194
+ };
3195
+
3196
+ // src/chat/backends/vercel-ai.ts
3197
+ var VercelAIChatAdapter = class extends BaseBackendAdapter {
3198
+ _vercelOptions;
3199
+ constructor(options) {
3200
+ super("vercel-ai", options);
3201
+ this._vercelOptions = options.vercelOptions;
3179
3202
  }
3180
- canResume() {
3181
- return this._backendSessionId !== null;
3203
+ createService() {
3204
+ const { createVercelAIService: createVercelAIService2 } = (init_vercel_ai(), __toCommonJS(vercel_ai_exports));
3205
+ return createVercelAIService2(this._vercelOptions || {});
3182
3206
  }
3183
- async *resume(session, backendSessionId, options) {
3184
- this.assertNotDisposed();
3185
- if (!backendSessionId) {
3186
- throw new ChatError("Backend session ID is required for resume", {
3187
- code: "INVALID_INPUT" /* INVALID_INPUT */
3207
+ captureSessionId(_agent) {
3208
+ }
3209
+ };
3210
+
3211
+ // src/backends/mock-llm.ts
3212
+ init_base_agent();
3213
+ init_errors2();
3214
+ function extractPrompt(messages) {
3215
+ for (let i = messages.length - 1; i >= 0; i--) {
3216
+ const msg = messages[i];
3217
+ if (msg.role === "user") {
3218
+ return typeof msg.content === "string" ? msg.content : msg.content.filter((p) => p.type === "text").map((p) => p.text).join("");
3219
+ }
3220
+ }
3221
+ return "";
3222
+ }
3223
+ function resolveResponse(mode, messages, callIndex) {
3224
+ switch (mode.type) {
3225
+ case "echo":
3226
+ return extractPrompt(messages);
3227
+ case "static":
3228
+ return mode.response;
3229
+ case "scripted": {
3230
+ if (mode.loop) {
3231
+ return mode.responses[callIndex % mode.responses.length];
3232
+ }
3233
+ if (callIndex < mode.responses.length) {
3234
+ return mode.responses[callIndex];
3235
+ }
3236
+ return mode.responses[mode.responses.length - 1];
3237
+ }
3238
+ case "error":
3239
+ throw new AgentSDKError(mode.error, {
3240
+ code: mode.code ?? "backend_error",
3241
+ retryable: mode.recoverable ?? false
3188
3242
  });
3243
+ }
3244
+ }
3245
+ async function applyLatency(latency, signal) {
3246
+ if (!latency) return;
3247
+ const ms = latency.type === "fixed" ? latency.ms : latency.minMs + Math.random() * (latency.maxMs - latency.minMs);
3248
+ if (ms <= 0) return;
3249
+ await new Promise((resolve, reject) => {
3250
+ const timer = setTimeout(resolve, ms);
3251
+ const onAbort = () => {
3252
+ clearTimeout(timer);
3253
+ reject(new Error("aborted"));
3254
+ };
3255
+ if (signal.aborted) {
3256
+ clearTimeout(timer);
3257
+ reject(new Error("aborted"));
3258
+ return;
3189
3259
  }
3190
- const agent = this.getOrCreateAgent(options);
3191
- const currentSessionId = agent.sessionId;
3192
- if (!currentSessionId) {
3193
- throw new ChatError(
3194
- `No active session to resume (requested: ${backendSessionId})`,
3195
- { code: "SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */ }
3196
- );
3260
+ signal.addEventListener("abort", onAbort, { once: true });
3261
+ });
3262
+ }
3263
+ function chunkText(text, streaming) {
3264
+ if (streaming?.chunkSize && streaming.chunkSize > 0) {
3265
+ const chunks = [];
3266
+ for (let i = 0; i < text.length; i += streaming.chunkSize) {
3267
+ chunks.push(text.slice(i, i + streaming.chunkSize));
3197
3268
  }
3198
- if (currentSessionId !== backendSessionId) {
3199
- throw new ChatError(
3200
- `Session expired: expected ${backendSessionId}, got ${currentSessionId}`,
3201
- { code: "SESSION_EXPIRED" /* SESSION_EXPIRED */ }
3202
- );
3269
+ return chunks;
3270
+ }
3271
+ return text.split(/(\s+)/).filter(Boolean);
3272
+ }
3273
+ async function chunkDelay(streaming, signal) {
3274
+ const ms = streaming?.chunkDelayMs;
3275
+ if (!ms || ms <= 0) return;
3276
+ await new Promise((resolve, reject) => {
3277
+ const timer = setTimeout(resolve, ms);
3278
+ const onAbort = () => {
3279
+ clearTimeout(timer);
3280
+ reject(new Error("aborted"));
3281
+ };
3282
+ if (signal.aborted) {
3283
+ clearTimeout(timer);
3284
+ reject(new Error("aborted"));
3285
+ return;
3203
3286
  }
3204
- const messages = session.messages.map(toAgentMessage);
3205
- yield* this.streamAgentEvents(agent, messages, options);
3287
+ signal.addEventListener("abort", onAbort, { once: true });
3288
+ });
3289
+ }
3290
+ var MockLLMAgent = class extends BaseAgent {
3291
+ backendName = "mock-llm";
3292
+ mode;
3293
+ latency;
3294
+ streaming;
3295
+ finishReason;
3296
+ permissions;
3297
+ toolCallConfigs;
3298
+ configuredStructuredOutput;
3299
+ callIndex = 0;
3300
+ constructor(config, options) {
3301
+ super(config);
3302
+ this.mode = options.mode ?? { type: "echo" };
3303
+ this.latency = options.latency;
3304
+ this.streaming = options.streaming;
3305
+ this.finishReason = options.finishReason ?? "stop";
3306
+ this.permissions = options.permissions;
3307
+ this.toolCallConfigs = options.toolCalls ?? [];
3308
+ this.configuredStructuredOutput = options.structuredOutput;
3309
+ }
3310
+ async executeRun(messages, _options, signal) {
3311
+ this.checkAbort(signal);
3312
+ await applyLatency(this.latency, signal);
3313
+ this.checkAbort(signal);
3314
+ const idx = this.callIndex++;
3315
+ const output = resolveResponse(this.mode, messages, idx);
3316
+ const toolCalls = this.toolCallConfigs.map((tc) => ({
3317
+ toolName: tc.toolName,
3318
+ args: tc.args ?? {},
3319
+ result: tc.result ?? null,
3320
+ approved: true
3321
+ }));
3322
+ return {
3323
+ output,
3324
+ structuredOutput: void 0,
3325
+ toolCalls,
3326
+ messages: [
3327
+ ...messages,
3328
+ { role: "assistant", content: output }
3329
+ ],
3330
+ usage: { promptTokens: 10, completionTokens: output.length }
3331
+ };
3206
3332
  }
3207
- captureSessionId(agent) {
3208
- if (agent.sessionId) {
3209
- this._backendSessionId = agent.sessionId;
3333
+ async executeRunStructured(messages, _schema, _options, signal) {
3334
+ this.checkAbort(signal);
3335
+ await applyLatency(this.latency, signal);
3336
+ this.checkAbort(signal);
3337
+ const idx = this.callIndex++;
3338
+ const output = resolveResponse(this.mode, messages, idx);
3339
+ let parsed;
3340
+ if (this.configuredStructuredOutput !== void 0) {
3341
+ parsed = this.configuredStructuredOutput;
3342
+ } else {
3343
+ try {
3344
+ parsed = JSON.parse(output);
3345
+ } catch {
3346
+ parsed = output;
3347
+ }
3348
+ }
3349
+ return {
3350
+ output,
3351
+ structuredOutput: parsed,
3352
+ toolCalls: [],
3353
+ messages: [
3354
+ ...messages,
3355
+ { role: "assistant", content: output }
3356
+ ],
3357
+ usage: { promptTokens: 10, completionTokens: output.length }
3358
+ };
3359
+ }
3360
+ async *executeStream(messages, _options, signal) {
3361
+ this.checkAbort(signal);
3362
+ await applyLatency(this.latency, signal);
3363
+ this.checkAbort(signal);
3364
+ if (this.permissions) {
3365
+ yield* this.simulatePermissions(signal);
3366
+ }
3367
+ if (this.toolCallConfigs.length > 0) {
3368
+ yield* this.simulateToolCalls(signal);
3369
+ }
3370
+ const idx = this.callIndex++;
3371
+ const output = resolveResponse(this.mode, messages, idx);
3372
+ const chunks = chunkText(output, this.streaming);
3373
+ for (let i = 0; i < chunks.length; i++) {
3374
+ this.checkAbort(signal);
3375
+ if (i > 0) {
3376
+ await chunkDelay(this.streaming, signal);
3377
+ }
3378
+ yield { type: "text_delta", text: chunks[i] };
3379
+ }
3380
+ yield {
3381
+ type: "usage_update",
3382
+ promptTokens: 10,
3383
+ completionTokens: output.length
3384
+ };
3385
+ yield {
3386
+ type: "done",
3387
+ finalOutput: output,
3388
+ finishReason: this.finishReason
3389
+ };
3390
+ }
3391
+ async *simulateToolCalls(signal) {
3392
+ for (let i = 0; i < this.toolCallConfigs.length; i++) {
3393
+ this.checkAbort(signal);
3394
+ const tc = this.toolCallConfigs[i];
3395
+ const toolCallId = tc.toolCallId ?? `mock-tc-${i}`;
3396
+ yield {
3397
+ type: "tool_call_start",
3398
+ toolCallId,
3399
+ toolName: tc.toolName,
3400
+ args: tc.args ?? {}
3401
+ };
3402
+ yield {
3403
+ type: "tool_call_end",
3404
+ toolCallId,
3405
+ toolName: tc.toolName,
3406
+ result: tc.result ?? null
3407
+ };
3408
+ }
3409
+ }
3410
+ async *simulatePermissions(signal) {
3411
+ const perms = this.permissions;
3412
+ for (const toolName of perms.toolNames) {
3413
+ this.checkAbort(signal);
3414
+ const request = {
3415
+ toolName,
3416
+ toolArgs: {}
3417
+ };
3418
+ yield { type: "permission_request", request };
3419
+ if (perms.denyTools?.includes(toolName)) {
3420
+ yield {
3421
+ type: "permission_response",
3422
+ toolName,
3423
+ decision: { allowed: false, reason: "Denied by mock configuration" }
3424
+ };
3425
+ } else if (perms.autoApprove) {
3426
+ yield {
3427
+ type: "permission_response",
3428
+ toolName,
3429
+ decision: { allowed: true, scope: "once" }
3430
+ };
3431
+ } else {
3432
+ const supervisor = this.getConfig().supervisor;
3433
+ if (supervisor?.onPermission) {
3434
+ const decision = await supervisor.onPermission(request, signal);
3435
+ yield { type: "permission_response", toolName, decision };
3436
+ } else {
3437
+ yield {
3438
+ type: "permission_response",
3439
+ toolName,
3440
+ decision: { allowed: true, scope: "once" }
3441
+ };
3442
+ }
3443
+ }
3210
3444
  }
3211
3445
  }
3212
3446
  };
3447
+ var MockLLMService = class {
3448
+ name = "mock-llm";
3449
+ options;
3450
+ models;
3451
+ constructor(options = {}) {
3452
+ this.options = options;
3453
+ this.models = (options.models ?? [
3454
+ { id: "mock-fast", name: "Mock Fast" },
3455
+ { id: "mock-quality", name: "Mock Quality" }
3456
+ ]).map((m) => ({
3457
+ id: m.id,
3458
+ name: m.name,
3459
+ description: m.description
3460
+ }));
3461
+ }
3462
+ createAgent(config) {
3463
+ return new MockLLMAgent(config, this.options);
3464
+ }
3465
+ async listModels() {
3466
+ return this.models;
3467
+ }
3468
+ async validate() {
3469
+ return { valid: true, errors: [] };
3470
+ }
3471
+ async dispose() {
3472
+ }
3473
+ };
3474
+ function createMockLLMService(options = {}) {
3475
+ return new MockLLMService(options);
3476
+ }
3213
3477
 
3214
- // src/chat/backends/vercel-ai.ts
3215
- var VercelAIChatAdapter = class extends BaseBackendAdapter {
3216
- _vercelOptions;
3478
+ // src/chat/backends/mock-llm.ts
3479
+ var MockLLMChatAdapter = class extends BaseBackendAdapter {
3217
3480
  constructor(options) {
3218
- super("vercel-ai", options);
3219
- this._vercelOptions = options.vercelOptions;
3481
+ const mockOpts = options.mockOptions;
3482
+ super("mock-llm", {
3483
+ ...options,
3484
+ agentServiceFactory: () => createMockLLMService(mockOpts || {})
3485
+ });
3220
3486
  }
3221
3487
  createService() {
3222
- const { createVercelAIService: createVercelAIService2 } = (init_vercel_ai(), __toCommonJS(vercel_ai_exports));
3223
- return createVercelAIService2(this._vercelOptions || {});
3488
+ return createMockLLMService({});
3224
3489
  }
3225
3490
  captureSessionId(_agent) {
3226
3491
  }
@@ -3301,16 +3566,22 @@ var SSEChatTransport = class {
3301
3566
  };
3302
3567
  async function streamToTransport(events, transport) {
3303
3568
  try {
3304
- let accumulatedText = "";
3569
+ const textChunks = [];
3570
+ let finishReason;
3305
3571
  for await (const event of events) {
3306
3572
  if (!transport.isOpen) break;
3573
+ if (event.type === "done") {
3574
+ finishReason = event.finishReason;
3575
+ continue;
3576
+ }
3307
3577
  transport.send(event);
3308
3578
  if (event.type === "message:delta") {
3309
- accumulatedText += event.text;
3579
+ textChunks.push(event.text);
3310
3580
  }
3311
3581
  }
3312
3582
  if (transport.isOpen) {
3313
- transport.send({ type: "done", finalOutput: accumulatedText || void 0 });
3583
+ const finalOutput = textChunks.length > 0 ? textChunks.join("") : void 0;
3584
+ transport.send({ type: "done", finalOutput, finishReason });
3314
3585
  }
3315
3586
  transport.close();
3316
3587
  } catch (err) {
@@ -3513,6 +3784,8 @@ exports.BaseBackendAdapter = BaseBackendAdapter;
3513
3784
  exports.ClaudeChatAdapter = ClaudeChatAdapter;
3514
3785
  exports.CopilotChatAdapter = CopilotChatAdapter;
3515
3786
  exports.InProcessChatTransport = InProcessChatTransport;
3787
+ exports.MockLLMChatAdapter = MockLLMChatAdapter;
3788
+ exports.ResumableChatAdapter = ResumableChatAdapter;
3516
3789
  exports.SSEChatTransport = SSEChatTransport;
3517
3790
  exports.VercelAIChatAdapter = VercelAIChatAdapter;
3518
3791
  exports.WS_READY_STATE = WS_READY_STATE;