@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
@@ -1,14 +1,14 @@
1
- import { a as ChatEvent } from '../types-DRgd_9R7.cjs';
2
- export { B as BackendAdapterOptions, I as IChatBackend, d as IResumableBackend, i as isResumableBackend } from '../types-DRgd_9R7.cjs';
3
- export { B as BaseBackendAdapter, C as ClaudeChatAdapter, a as ClaudeChatAdapterOptions, b as CopilotChatAdapter, c as CopilotChatAdapterOptions, I as InProcessChatTransport, V as VercelAIChatAdapter, d as VercelAIChatAdapterOptions, W as WS_READY_STATE, e as WebSocketLike, f as WsChatTransport, g as WsTransportOptions } from '../in-process-transport-C7DSqPyX.cjs';
4
- import { I as IChatTransport } from '../transport-Cdh3M0tS.cjs';
5
- export { C as CloseDetectable, S as SSEChatTransport, a as SSETransportOptions, W as WritableResponse, s as streamToTransport } from '../transport-Cdh3M0tS.cjs';
6
- import '../agent-DxY68NZL.cjs';
1
+ import { a as ChatEvent } from '../types-DkSXALKg.cjs';
2
+ export { B as BackendAdapterOptions, I as IChatBackend, d as IResumableBackend, i as isResumableBackend } from '../types-DkSXALKg.cjs';
3
+ export { B as BaseBackendAdapter, C as ClaudeChatAdapter, a as ClaudeChatAdapterOptions, b as CopilotChatAdapter, c as CopilotChatAdapterOptions, I as InProcessChatTransport, M as MockLLMChatAdapter, d as MockLLMChatAdapterOptions, R as ResumableChatAdapter, V as VercelAIChatAdapter, e as VercelAIChatAdapterOptions, W as WS_READY_STATE, f as WebSocketLike, g as WsChatTransport, h as WsTransportOptions } from '../in-process-transport-Ct9YcX8I.cjs';
4
+ import { I as IChatTransport } from '../transport-DLWCN18G.cjs';
5
+ export { C as CloseDetectable, S as SSEChatTransport, a as SSETransportOptions, W as WritableResponse, s as streamToTransport } from '../transport-DLWCN18G.cjs';
6
+ import '../agent-C6H2CgJA.cjs';
7
7
  import 'zod';
8
8
  import '../errors-C-so0M4t.cjs';
9
9
  import '../types-4vbcmPTp.cjs';
10
10
  import '../errors-CmVvczxZ.cjs';
11
- import '../backends-BSrsBYFn.cjs';
11
+ import '../backends-Cno0gZjy.cjs';
12
12
 
13
13
  /**
14
14
  * @witqq/agent-sdk - Transport Interceptors
@@ -1,14 +1,14 @@
1
- import { a as ChatEvent } from '../types-ajANVzf7.js';
2
- export { B as BackendAdapterOptions, I as IChatBackend, d as IResumableBackend, i as isResumableBackend } from '../types-ajANVzf7.js';
3
- export { B as BaseBackendAdapter, C as ClaudeChatAdapter, a as ClaudeChatAdapterOptions, b as CopilotChatAdapter, c as CopilotChatAdapterOptions, I as InProcessChatTransport, V as VercelAIChatAdapter, d as VercelAIChatAdapterOptions, W as WS_READY_STATE, e as WebSocketLike, f as WsChatTransport, g as WsTransportOptions } from '../in-process-transport-C1JnJGVR.js';
4
- import { I as IChatTransport } from '../transport-Ciap4PWK.js';
5
- export { C as CloseDetectable, S as SSEChatTransport, a as SSETransportOptions, W as WritableResponse, s as streamToTransport } from '../transport-Ciap4PWK.js';
6
- import '../agent-CW9XbmG_.js';
1
+ import { a as ChatEvent } from '../types-DgtI1hzh.js';
2
+ export { B as BackendAdapterOptions, I as IChatBackend, d as IResumableBackend, i as isResumableBackend } from '../types-DgtI1hzh.js';
3
+ export { B as BaseBackendAdapter, C as ClaudeChatAdapter, a as ClaudeChatAdapterOptions, b as CopilotChatAdapter, c as CopilotChatAdapterOptions, I as InProcessChatTransport, M as MockLLMChatAdapter, d as MockLLMChatAdapterOptions, R as ResumableChatAdapter, V as VercelAIChatAdapter, e as VercelAIChatAdapterOptions, W as WS_READY_STATE, f as WebSocketLike, g as WsChatTransport, h as WsTransportOptions } from '../in-process-transport-7EIit9Xk.js';
4
+ import { I as IChatTransport } from '../transport-DsuS-GeM.js';
5
+ export { C as CloseDetectable, S as SSEChatTransport, a as SSETransportOptions, W as WritableResponse, s as streamToTransport } from '../transport-DsuS-GeM.js';
6
+ import '../agent-F7oB6eKp.js';
7
7
  import 'zod';
8
8
  import '../errors-C-so0M4t.js';
9
9
  import '../types-BxggH0Yh.js';
10
10
  import '../errors-CmVvczxZ.js';
11
- import '../backends-BSrsBYFn.js';
11
+ import '../backends-Cno0gZjy.js';
12
12
 
13
13
  /**
14
14
  * @witqq/agent-sdk - Transport Interceptors
@@ -722,17 +722,6 @@ function convertParameters(params) {
722
722
  }
723
723
  return params;
724
724
  }
725
- async function mapToolsToSDKAsync(tools) {
726
- return tools.map((tool) => ({
727
- name: tool.name,
728
- description: tool.description,
729
- parameters: convertParameters(tool.parameters),
730
- handler: async (args) => {
731
- const result = await tool.execute(args);
732
- return typeof result === "string" ? result : JSON.stringify(result);
733
- }
734
- }));
735
- }
736
725
  function buildPermissionHandler(config) {
737
726
  const onPermission = config.supervisor?.onPermission;
738
727
  if (!onPermission) {
@@ -970,15 +959,15 @@ var init_copilot = __esm({
970
959
  },
971
960
  onPermissionRequest: buildPermissionHandler(config),
972
961
  onUserInputRequest: buildUserInputHandler(config),
973
- ...config.availableTools?.length ? { availableTools: config.availableTools } : {}
962
+ ...config.availableTools ? { availableTools: config.availableTools } : {}
974
963
  };
975
964
  this._toolsReady = this._initToolsAsync(config);
976
965
  this._resumeSessionId = resumeSessionId;
977
966
  }
978
- /** Pre-convert Zod schemas to JSON Schema asynchronously.
967
+ /** Pre-convert Zod schemas to JSON Schema.
979
968
  * Updates sdkTools and sessionConfig.tools before first session creation. */
980
969
  async _initToolsAsync(config) {
981
- this.sdkTools = await mapToolsToSDKAsync(config.tools ?? []);
970
+ this.sdkTools = mapToolsToSDK(config.tools ?? []);
982
971
  this.sessionConfig.tools = this.sdkTools;
983
972
  }
984
973
  get sessionId() {
@@ -1269,7 +1258,11 @@ You MUST respond with ONLY valid JSON matching this schema:
1269
1258
  githubToken: this.options.githubToken,
1270
1259
  useLoggedInUser: this.options.useLoggedInUser ?? !this.options.githubToken,
1271
1260
  ...this.options.cliArgs ? { cliArgs: this.options.cliArgs } : {},
1272
- ...this.options.env ? { env: { ...process.env, ...this.options.env } } : {}
1261
+ env: {
1262
+ ...process.env,
1263
+ ...this.options.githubToken ? { GITHUB_TOKEN: this.options.githubToken } : {},
1264
+ ...this.options.env
1265
+ }
1273
1266
  });
1274
1267
  const startupTimeout = this.options.startupTimeoutMs ?? 3e4;
1275
1268
  await withTimeout(client.start(), startupTimeout, "CLI startup timed out");
@@ -2689,6 +2682,7 @@ var init_vercel_ai = __esm({
2689
2682
  }
2690
2683
  });
2691
2684
  let finalText = "";
2685
+ let lastFinishReason;
2692
2686
  try {
2693
2687
  for await (const part of result.fullStream) {
2694
2688
  if (signal.aborted) throw new AbortError();
@@ -2699,10 +2693,15 @@ var init_vercel_ai = __esm({
2699
2693
  }
2700
2694
  if (part.type === "finish-step") {
2701
2695
  const p = part;
2696
+ lastFinishReason = p.finishReason;
2702
2697
  if (p.finishReason === "tool-calls") {
2703
2698
  finalText = "";
2704
2699
  }
2705
2700
  }
2701
+ if (part.type === "finish") {
2702
+ const p = part;
2703
+ lastFinishReason = p.finishReason;
2704
+ }
2706
2705
  }
2707
2706
  const totalUsage = await result.totalUsage;
2708
2707
  yield {
@@ -2714,7 +2713,8 @@ var init_vercel_ai = __esm({
2714
2713
  yield {
2715
2714
  type: "done",
2716
2715
  finalOutput: hasStreamed ? null : finalText || null,
2717
- ...hasStreamed ? { streamed: true } : {}
2716
+ ...hasStreamed ? { streamed: true } : {},
2717
+ ...lastFinishReason ? { finishReason: lastFinishReason } : {}
2718
2718
  };
2719
2719
  } catch (e) {
2720
2720
  if (signal.aborted) throw new AbortError();
@@ -2879,8 +2879,9 @@ function agentEventToChatEvent(event, messageId) {
2879
2879
  case "ask_user":
2880
2880
  case "ask_user_response":
2881
2881
  case "session_info":
2882
- case "done":
2883
2882
  return null;
2883
+ case "done":
2884
+ return { type: "done", finalOutput: event.finalOutput ?? void 0, finishReason: event.finishReason };
2884
2885
  default:
2885
2886
  return null;
2886
2887
  }
@@ -2895,24 +2896,37 @@ async function* adaptAgentEvents(events, messageId) {
2895
2896
  }
2896
2897
 
2897
2898
  // src/chat/conversion.ts
2898
- function toAgentMessage(message) {
2899
+ function toAgentMessages(message) {
2899
2900
  const textContent = getMessageText(message);
2900
2901
  const toolCallParts = getMessageToolCalls(message);
2901
2902
  switch (message.role) {
2902
2903
  case "user":
2903
- return { role: "user", content: textContent };
2904
+ return [{ role: "user", content: textContent }];
2904
2905
  case "assistant": {
2905
2906
  const toolCalls = toolCallParts.length > 0 ? toolCallParts.map((p) => ({ id: p.toolCallId, name: p.name, args: p.args })) : void 0;
2906
- return {
2907
+ const assistantMsg = {
2907
2908
  role: "assistant",
2908
2909
  content: textContent,
2909
2910
  toolCalls
2910
2911
  };
2912
+ const toolResults = extractToolResults(message);
2913
+ if (toolResults.length > 0) {
2914
+ return [assistantMsg, { role: "tool", toolResults }];
2915
+ }
2916
+ return [assistantMsg];
2911
2917
  }
2912
2918
  case "system":
2913
- return { role: "system", content: textContent };
2919
+ return [{ role: "system", content: textContent }];
2914
2920
  }
2915
2921
  }
2922
+ function extractToolResults(message) {
2923
+ return getMessageToolCalls(message).filter((p) => p.result !== void 0).map((p) => ({
2924
+ toolCallId: p.toolCallId,
2925
+ name: p.name,
2926
+ result: p.result,
2927
+ isError: p.status === "error" ? true : void 0
2928
+ }));
2929
+ }
2916
2930
 
2917
2931
  // src/chat/errors.ts
2918
2932
  init_errors2();
@@ -3011,7 +3025,7 @@ var BaseBackendAdapter = class {
3011
3025
  async *streamMessage(session, message, options) {
3012
3026
  this.assertNotDisposed();
3013
3027
  const agent = this.getOrCreateAgent(options);
3014
- const messages = session.messages.map(toAgentMessage);
3028
+ const messages = session.messages.flatMap(toAgentMessages);
3015
3029
  messages.push({ role: "user", content: message });
3016
3030
  yield* this.streamAgentEvents(agent, messages, options);
3017
3031
  }
@@ -3088,7 +3102,8 @@ var BaseBackendAdapter = class {
3088
3102
  }
3089
3103
  const config = {
3090
3104
  ...this._agentConfig,
3091
- ...model !== void 0 && { model }
3105
+ ...model !== void 0 && { model },
3106
+ ...options?.tools?.length ? { tools: options.tools } : {}
3092
3107
  };
3093
3108
  const agent = this.agentService.createAgent(config);
3094
3109
  this._currentAgent = { instance: agent, model };
@@ -3103,21 +3118,15 @@ var BaseBackendAdapter = class {
3103
3118
  }
3104
3119
  };
3105
3120
 
3106
- // src/chat/backends/copilot.ts
3107
- var CopilotChatAdapter = class extends BaseBackendAdapter {
3121
+ // src/chat/backends/resumable.ts
3122
+ var ResumableChatAdapter = class extends BaseBackendAdapter {
3108
3123
  _backendSessionId = null;
3109
- _copilotOptions;
3110
- constructor(options) {
3124
+ constructor(name, options) {
3111
3125
  const agentConfig = {
3112
3126
  ...options.agentConfig,
3113
3127
  sessionMode: "persistent"
3114
3128
  };
3115
- super("copilot", { ...options, agentConfig });
3116
- this._copilotOptions = options.copilotOptions;
3117
- }
3118
- createService() {
3119
- const { createCopilotService: createCopilotService2 } = (init_copilot(), __toCommonJS(copilot_exports));
3120
- return createCopilotService2(this._copilotOptions || {});
3129
+ super(name, { ...options, agentConfig });
3121
3130
  }
3122
3131
  get backendSessionId() {
3123
3132
  return this._backendSessionId;
@@ -3146,7 +3155,7 @@ var CopilotChatAdapter = class extends BaseBackendAdapter {
3146
3155
  { code: "SESSION_EXPIRED" /* SESSION_EXPIRED */ }
3147
3156
  );
3148
3157
  }
3149
- const messages = session.messages.map(toAgentMessage);
3158
+ const messages = session.messages.flatMap(toAgentMessages);
3150
3159
  yield* this.streamAgentEvents(agent, messages, options);
3151
3160
  }
3152
3161
  captureSessionId(agent) {
@@ -3156,69 +3165,325 @@ var CopilotChatAdapter = class extends BaseBackendAdapter {
3156
3165
  }
3157
3166
  };
3158
3167
 
3168
+ // src/chat/backends/copilot.ts
3169
+ var CopilotChatAdapter = class extends ResumableChatAdapter {
3170
+ _copilotOptions;
3171
+ constructor(options) {
3172
+ super("copilot", options);
3173
+ this._copilotOptions = options.copilotOptions;
3174
+ }
3175
+ createService() {
3176
+ const { createCopilotService: createCopilotService2 } = (init_copilot(), __toCommonJS(copilot_exports));
3177
+ return createCopilotService2(this._copilotOptions || {});
3178
+ }
3179
+ };
3180
+
3159
3181
  // src/chat/backends/claude.ts
3160
- var ClaudeChatAdapter = class extends BaseBackendAdapter {
3161
- _backendSessionId = null;
3182
+ var ClaudeChatAdapter = class extends ResumableChatAdapter {
3162
3183
  _claudeOptions;
3163
3184
  constructor(options) {
3164
- const agentConfig = {
3165
- ...options.agentConfig,
3166
- sessionMode: "persistent"
3167
- };
3168
- super("claude", { ...options, agentConfig });
3185
+ super("claude", options);
3169
3186
  this._claudeOptions = options.claudeOptions;
3170
3187
  }
3171
3188
  createService() {
3172
3189
  const { createClaudeService: createClaudeService2 } = (init_claude(), __toCommonJS(claude_exports));
3173
3190
  return createClaudeService2(this._claudeOptions || {});
3174
3191
  }
3175
- get backendSessionId() {
3176
- return this._backendSessionId;
3192
+ };
3193
+
3194
+ // src/chat/backends/vercel-ai.ts
3195
+ var VercelAIChatAdapter = class extends BaseBackendAdapter {
3196
+ _vercelOptions;
3197
+ constructor(options) {
3198
+ super("vercel-ai", options);
3199
+ this._vercelOptions = options.vercelOptions;
3177
3200
  }
3178
- canResume() {
3179
- return this._backendSessionId !== null;
3201
+ createService() {
3202
+ const { createVercelAIService: createVercelAIService2 } = (init_vercel_ai(), __toCommonJS(vercel_ai_exports));
3203
+ return createVercelAIService2(this._vercelOptions || {});
3180
3204
  }
3181
- async *resume(session, backendSessionId, options) {
3182
- this.assertNotDisposed();
3183
- if (!backendSessionId) {
3184
- throw new ChatError("Backend session ID is required for resume", {
3185
- code: "INVALID_INPUT" /* INVALID_INPUT */
3205
+ captureSessionId(_agent) {
3206
+ }
3207
+ };
3208
+
3209
+ // src/backends/mock-llm.ts
3210
+ init_base_agent();
3211
+ init_errors2();
3212
+ function extractPrompt(messages) {
3213
+ for (let i = messages.length - 1; i >= 0; i--) {
3214
+ const msg = messages[i];
3215
+ if (msg.role === "user") {
3216
+ return typeof msg.content === "string" ? msg.content : msg.content.filter((p) => p.type === "text").map((p) => p.text).join("");
3217
+ }
3218
+ }
3219
+ return "";
3220
+ }
3221
+ function resolveResponse(mode, messages, callIndex) {
3222
+ switch (mode.type) {
3223
+ case "echo":
3224
+ return extractPrompt(messages);
3225
+ case "static":
3226
+ return mode.response;
3227
+ case "scripted": {
3228
+ if (mode.loop) {
3229
+ return mode.responses[callIndex % mode.responses.length];
3230
+ }
3231
+ if (callIndex < mode.responses.length) {
3232
+ return mode.responses[callIndex];
3233
+ }
3234
+ return mode.responses[mode.responses.length - 1];
3235
+ }
3236
+ case "error":
3237
+ throw new AgentSDKError(mode.error, {
3238
+ code: mode.code ?? "backend_error",
3239
+ retryable: mode.recoverable ?? false
3186
3240
  });
3241
+ }
3242
+ }
3243
+ async function applyLatency(latency, signal) {
3244
+ if (!latency) return;
3245
+ const ms = latency.type === "fixed" ? latency.ms : latency.minMs + Math.random() * (latency.maxMs - latency.minMs);
3246
+ if (ms <= 0) return;
3247
+ await new Promise((resolve, reject) => {
3248
+ const timer = setTimeout(resolve, ms);
3249
+ const onAbort = () => {
3250
+ clearTimeout(timer);
3251
+ reject(new Error("aborted"));
3252
+ };
3253
+ if (signal.aborted) {
3254
+ clearTimeout(timer);
3255
+ reject(new Error("aborted"));
3256
+ return;
3187
3257
  }
3188
- const agent = this.getOrCreateAgent(options);
3189
- const currentSessionId = agent.sessionId;
3190
- if (!currentSessionId) {
3191
- throw new ChatError(
3192
- `No active session to resume (requested: ${backendSessionId})`,
3193
- { code: "SESSION_NOT_FOUND" /* SESSION_NOT_FOUND */ }
3194
- );
3258
+ signal.addEventListener("abort", onAbort, { once: true });
3259
+ });
3260
+ }
3261
+ function chunkText(text, streaming) {
3262
+ if (streaming?.chunkSize && streaming.chunkSize > 0) {
3263
+ const chunks = [];
3264
+ for (let i = 0; i < text.length; i += streaming.chunkSize) {
3265
+ chunks.push(text.slice(i, i + streaming.chunkSize));
3195
3266
  }
3196
- if (currentSessionId !== backendSessionId) {
3197
- throw new ChatError(
3198
- `Session expired: expected ${backendSessionId}, got ${currentSessionId}`,
3199
- { code: "SESSION_EXPIRED" /* SESSION_EXPIRED */ }
3200
- );
3267
+ return chunks;
3268
+ }
3269
+ return text.split(/(\s+)/).filter(Boolean);
3270
+ }
3271
+ async function chunkDelay(streaming, signal) {
3272
+ const ms = streaming?.chunkDelayMs;
3273
+ if (!ms || ms <= 0) return;
3274
+ await new Promise((resolve, reject) => {
3275
+ const timer = setTimeout(resolve, ms);
3276
+ const onAbort = () => {
3277
+ clearTimeout(timer);
3278
+ reject(new Error("aborted"));
3279
+ };
3280
+ if (signal.aborted) {
3281
+ clearTimeout(timer);
3282
+ reject(new Error("aborted"));
3283
+ return;
3201
3284
  }
3202
- const messages = session.messages.map(toAgentMessage);
3203
- yield* this.streamAgentEvents(agent, messages, options);
3285
+ signal.addEventListener("abort", onAbort, { once: true });
3286
+ });
3287
+ }
3288
+ var MockLLMAgent = class extends BaseAgent {
3289
+ backendName = "mock-llm";
3290
+ mode;
3291
+ latency;
3292
+ streaming;
3293
+ finishReason;
3294
+ permissions;
3295
+ toolCallConfigs;
3296
+ configuredStructuredOutput;
3297
+ callIndex = 0;
3298
+ constructor(config, options) {
3299
+ super(config);
3300
+ this.mode = options.mode ?? { type: "echo" };
3301
+ this.latency = options.latency;
3302
+ this.streaming = options.streaming;
3303
+ this.finishReason = options.finishReason ?? "stop";
3304
+ this.permissions = options.permissions;
3305
+ this.toolCallConfigs = options.toolCalls ?? [];
3306
+ this.configuredStructuredOutput = options.structuredOutput;
3307
+ }
3308
+ async executeRun(messages, _options, signal) {
3309
+ this.checkAbort(signal);
3310
+ await applyLatency(this.latency, signal);
3311
+ this.checkAbort(signal);
3312
+ const idx = this.callIndex++;
3313
+ const output = resolveResponse(this.mode, messages, idx);
3314
+ const toolCalls = this.toolCallConfigs.map((tc) => ({
3315
+ toolName: tc.toolName,
3316
+ args: tc.args ?? {},
3317
+ result: tc.result ?? null,
3318
+ approved: true
3319
+ }));
3320
+ return {
3321
+ output,
3322
+ structuredOutput: void 0,
3323
+ toolCalls,
3324
+ messages: [
3325
+ ...messages,
3326
+ { role: "assistant", content: output }
3327
+ ],
3328
+ usage: { promptTokens: 10, completionTokens: output.length }
3329
+ };
3204
3330
  }
3205
- captureSessionId(agent) {
3206
- if (agent.sessionId) {
3207
- this._backendSessionId = agent.sessionId;
3331
+ async executeRunStructured(messages, _schema, _options, signal) {
3332
+ this.checkAbort(signal);
3333
+ await applyLatency(this.latency, signal);
3334
+ this.checkAbort(signal);
3335
+ const idx = this.callIndex++;
3336
+ const output = resolveResponse(this.mode, messages, idx);
3337
+ let parsed;
3338
+ if (this.configuredStructuredOutput !== void 0) {
3339
+ parsed = this.configuredStructuredOutput;
3340
+ } else {
3341
+ try {
3342
+ parsed = JSON.parse(output);
3343
+ } catch {
3344
+ parsed = output;
3345
+ }
3346
+ }
3347
+ return {
3348
+ output,
3349
+ structuredOutput: parsed,
3350
+ toolCalls: [],
3351
+ messages: [
3352
+ ...messages,
3353
+ { role: "assistant", content: output }
3354
+ ],
3355
+ usage: { promptTokens: 10, completionTokens: output.length }
3356
+ };
3357
+ }
3358
+ async *executeStream(messages, _options, signal) {
3359
+ this.checkAbort(signal);
3360
+ await applyLatency(this.latency, signal);
3361
+ this.checkAbort(signal);
3362
+ if (this.permissions) {
3363
+ yield* this.simulatePermissions(signal);
3364
+ }
3365
+ if (this.toolCallConfigs.length > 0) {
3366
+ yield* this.simulateToolCalls(signal);
3367
+ }
3368
+ const idx = this.callIndex++;
3369
+ const output = resolveResponse(this.mode, messages, idx);
3370
+ const chunks = chunkText(output, this.streaming);
3371
+ for (let i = 0; i < chunks.length; i++) {
3372
+ this.checkAbort(signal);
3373
+ if (i > 0) {
3374
+ await chunkDelay(this.streaming, signal);
3375
+ }
3376
+ yield { type: "text_delta", text: chunks[i] };
3377
+ }
3378
+ yield {
3379
+ type: "usage_update",
3380
+ promptTokens: 10,
3381
+ completionTokens: output.length
3382
+ };
3383
+ yield {
3384
+ type: "done",
3385
+ finalOutput: output,
3386
+ finishReason: this.finishReason
3387
+ };
3388
+ }
3389
+ async *simulateToolCalls(signal) {
3390
+ for (let i = 0; i < this.toolCallConfigs.length; i++) {
3391
+ this.checkAbort(signal);
3392
+ const tc = this.toolCallConfigs[i];
3393
+ const toolCallId = tc.toolCallId ?? `mock-tc-${i}`;
3394
+ yield {
3395
+ type: "tool_call_start",
3396
+ toolCallId,
3397
+ toolName: tc.toolName,
3398
+ args: tc.args ?? {}
3399
+ };
3400
+ yield {
3401
+ type: "tool_call_end",
3402
+ toolCallId,
3403
+ toolName: tc.toolName,
3404
+ result: tc.result ?? null
3405
+ };
3406
+ }
3407
+ }
3408
+ async *simulatePermissions(signal) {
3409
+ const perms = this.permissions;
3410
+ for (const toolName of perms.toolNames) {
3411
+ this.checkAbort(signal);
3412
+ const request = {
3413
+ toolName,
3414
+ toolArgs: {}
3415
+ };
3416
+ yield { type: "permission_request", request };
3417
+ if (perms.denyTools?.includes(toolName)) {
3418
+ yield {
3419
+ type: "permission_response",
3420
+ toolName,
3421
+ decision: { allowed: false, reason: "Denied by mock configuration" }
3422
+ };
3423
+ } else if (perms.autoApprove) {
3424
+ yield {
3425
+ type: "permission_response",
3426
+ toolName,
3427
+ decision: { allowed: true, scope: "once" }
3428
+ };
3429
+ } else {
3430
+ const supervisor = this.getConfig().supervisor;
3431
+ if (supervisor?.onPermission) {
3432
+ const decision = await supervisor.onPermission(request, signal);
3433
+ yield { type: "permission_response", toolName, decision };
3434
+ } else {
3435
+ yield {
3436
+ type: "permission_response",
3437
+ toolName,
3438
+ decision: { allowed: true, scope: "once" }
3439
+ };
3440
+ }
3441
+ }
3208
3442
  }
3209
3443
  }
3210
3444
  };
3445
+ var MockLLMService = class {
3446
+ name = "mock-llm";
3447
+ options;
3448
+ models;
3449
+ constructor(options = {}) {
3450
+ this.options = options;
3451
+ this.models = (options.models ?? [
3452
+ { id: "mock-fast", name: "Mock Fast" },
3453
+ { id: "mock-quality", name: "Mock Quality" }
3454
+ ]).map((m) => ({
3455
+ id: m.id,
3456
+ name: m.name,
3457
+ description: m.description
3458
+ }));
3459
+ }
3460
+ createAgent(config) {
3461
+ return new MockLLMAgent(config, this.options);
3462
+ }
3463
+ async listModels() {
3464
+ return this.models;
3465
+ }
3466
+ async validate() {
3467
+ return { valid: true, errors: [] };
3468
+ }
3469
+ async dispose() {
3470
+ }
3471
+ };
3472
+ function createMockLLMService(options = {}) {
3473
+ return new MockLLMService(options);
3474
+ }
3211
3475
 
3212
- // src/chat/backends/vercel-ai.ts
3213
- var VercelAIChatAdapter = class extends BaseBackendAdapter {
3214
- _vercelOptions;
3476
+ // src/chat/backends/mock-llm.ts
3477
+ var MockLLMChatAdapter = class extends BaseBackendAdapter {
3215
3478
  constructor(options) {
3216
- super("vercel-ai", options);
3217
- this._vercelOptions = options.vercelOptions;
3479
+ const mockOpts = options.mockOptions;
3480
+ super("mock-llm", {
3481
+ ...options,
3482
+ agentServiceFactory: () => createMockLLMService(mockOpts || {})
3483
+ });
3218
3484
  }
3219
3485
  createService() {
3220
- const { createVercelAIService: createVercelAIService2 } = (init_vercel_ai(), __toCommonJS(vercel_ai_exports));
3221
- return createVercelAIService2(this._vercelOptions || {});
3486
+ return createMockLLMService({});
3222
3487
  }
3223
3488
  captureSessionId(_agent) {
3224
3489
  }
@@ -3299,16 +3564,22 @@ var SSEChatTransport = class {
3299
3564
  };
3300
3565
  async function streamToTransport(events, transport) {
3301
3566
  try {
3302
- let accumulatedText = "";
3567
+ const textChunks = [];
3568
+ let finishReason;
3303
3569
  for await (const event of events) {
3304
3570
  if (!transport.isOpen) break;
3571
+ if (event.type === "done") {
3572
+ finishReason = event.finishReason;
3573
+ continue;
3574
+ }
3305
3575
  transport.send(event);
3306
3576
  if (event.type === "message:delta") {
3307
- accumulatedText += event.text;
3577
+ textChunks.push(event.text);
3308
3578
  }
3309
3579
  }
3310
3580
  if (transport.isOpen) {
3311
- transport.send({ type: "done", finalOutput: accumulatedText || void 0 });
3581
+ const finalOutput = textChunks.length > 0 ? textChunks.join("") : void 0;
3582
+ transport.send({ type: "done", finalOutput, finishReason });
3312
3583
  }
3313
3584
  transport.close();
3314
3585
  } catch (err) {
@@ -3507,6 +3778,6 @@ function withInterceptors(transport, interceptors) {
3507
3778
  return new InterceptedTransport(transport, interceptors);
3508
3779
  }
3509
3780
 
3510
- export { BaseBackendAdapter, ClaudeChatAdapter, CopilotChatAdapter, InProcessChatTransport, SSEChatTransport, VercelAIChatAdapter, WS_READY_STATE, WsChatTransport, isResumableBackend, streamToTransport, withInterceptors };
3781
+ export { BaseBackendAdapter, ClaudeChatAdapter, CopilotChatAdapter, InProcessChatTransport, MockLLMChatAdapter, ResumableChatAdapter, SSEChatTransport, VercelAIChatAdapter, WS_READY_STATE, WsChatTransport, isResumableBackend, streamToTransport, withInterceptors };
3511
3782
  //# sourceMappingURL=backends.js.map
3512
3783
  //# sourceMappingURL=backends.js.map