@witqq/agent-sdk 0.6.0 → 0.7.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 (122) hide show
  1. package/README.md +433 -6
  2. package/dist/auth/index.cjs +188 -1
  3. package/dist/auth/index.cjs.map +1 -1
  4. package/dist/auth/index.d.cts +154 -138
  5. package/dist/auth/index.d.ts +154 -138
  6. package/dist/auth/index.js +188 -2
  7. package/dist/auth/index.js.map +1 -1
  8. package/dist/backends/claude.cjs +341 -22
  9. package/dist/backends/claude.cjs.map +1 -1
  10. package/dist/backends/claude.d.cts +2 -1
  11. package/dist/backends/claude.d.ts +2 -1
  12. package/dist/backends/claude.js +341 -22
  13. package/dist/backends/claude.js.map +1 -1
  14. package/dist/backends/copilot.cjs +133 -25
  15. package/dist/backends/copilot.cjs.map +1 -1
  16. package/dist/backends/copilot.d.cts +2 -1
  17. package/dist/backends/copilot.d.ts +2 -1
  18. package/dist/backends/copilot.js +133 -25
  19. package/dist/backends/copilot.js.map +1 -1
  20. package/dist/backends/vercel-ai.cjs +66 -19
  21. package/dist/backends/vercel-ai.cjs.map +1 -1
  22. package/dist/backends/vercel-ai.d.cts +1 -1
  23. package/dist/backends/vercel-ai.d.ts +1 -1
  24. package/dist/backends/vercel-ai.js +66 -19
  25. package/dist/backends/vercel-ai.js.map +1 -1
  26. package/dist/chat/accumulator.cjs +147 -0
  27. package/dist/chat/accumulator.cjs.map +1 -0
  28. package/dist/chat/accumulator.d.cts +61 -0
  29. package/dist/chat/accumulator.d.ts +61 -0
  30. package/dist/chat/accumulator.js +145 -0
  31. package/dist/chat/accumulator.js.map +1 -0
  32. package/dist/chat/backends.cjs +3534 -0
  33. package/dist/chat/backends.cjs.map +1 -0
  34. package/dist/chat/backends.d.cts +62 -0
  35. package/dist/chat/backends.d.ts +62 -0
  36. package/dist/chat/backends.js +3501 -0
  37. package/dist/chat/backends.js.map +1 -0
  38. package/dist/chat/context.cjs +230 -0
  39. package/dist/chat/context.cjs.map +1 -0
  40. package/dist/chat/context.d.cts +167 -0
  41. package/dist/chat/context.d.ts +167 -0
  42. package/dist/chat/context.js +227 -0
  43. package/dist/chat/context.js.map +1 -0
  44. package/dist/chat/core.cjs +282 -0
  45. package/dist/chat/core.cjs.map +1 -0
  46. package/dist/chat/core.d.cts +435 -0
  47. package/dist/chat/core.d.ts +435 -0
  48. package/dist/chat/core.js +261 -0
  49. package/dist/chat/core.js.map +1 -0
  50. package/dist/chat/errors.cjs +251 -0
  51. package/dist/chat/errors.cjs.map +1 -0
  52. package/dist/chat/errors.d.cts +122 -0
  53. package/dist/chat/errors.d.ts +122 -0
  54. package/dist/chat/errors.js +243 -0
  55. package/dist/chat/errors.js.map +1 -0
  56. package/dist/chat/events.cjs +203 -0
  57. package/dist/chat/events.cjs.map +1 -0
  58. package/dist/chat/events.d.cts +241 -0
  59. package/dist/chat/events.d.ts +241 -0
  60. package/dist/chat/events.js +196 -0
  61. package/dist/chat/events.js.map +1 -0
  62. package/dist/chat/index.cjs +5359 -0
  63. package/dist/chat/index.cjs.map +1 -0
  64. package/dist/chat/index.d.cts +52 -0
  65. package/dist/chat/index.d.ts +52 -0
  66. package/dist/chat/index.js +5296 -0
  67. package/dist/chat/index.js.map +1 -0
  68. package/dist/chat/react.cjs +2739 -0
  69. package/dist/chat/react.cjs.map +1 -0
  70. package/dist/chat/react.d.cts +619 -0
  71. package/dist/chat/react.d.ts +619 -0
  72. package/dist/chat/react.js +2714 -0
  73. package/dist/chat/react.js.map +1 -0
  74. package/dist/chat/runtime.cjs +1030 -0
  75. package/dist/chat/runtime.cjs.map +1 -0
  76. package/dist/chat/runtime.d.cts +118 -0
  77. package/dist/chat/runtime.d.ts +118 -0
  78. package/dist/chat/runtime.js +1028 -0
  79. package/dist/chat/runtime.js.map +1 -0
  80. package/dist/chat/server.cjs +643 -0
  81. package/dist/chat/server.cjs.map +1 -0
  82. package/dist/chat/server.d.cts +287 -0
  83. package/dist/chat/server.d.ts +287 -0
  84. package/dist/chat/server.js +617 -0
  85. package/dist/chat/server.js.map +1 -0
  86. package/dist/chat/sessions.cjs +398 -0
  87. package/dist/chat/sessions.cjs.map +1 -0
  88. package/dist/chat/sessions.d.cts +239 -0
  89. package/dist/chat/sessions.d.ts +239 -0
  90. package/dist/chat/sessions.js +394 -0
  91. package/dist/chat/sessions.js.map +1 -0
  92. package/dist/chat/state.cjs +177 -0
  93. package/dist/chat/state.cjs.map +1 -0
  94. package/dist/chat/state.d.cts +92 -0
  95. package/dist/chat/state.d.ts +92 -0
  96. package/dist/chat/state.js +167 -0
  97. package/dist/chat/state.js.map +1 -0
  98. package/dist/chat/storage.cjs +240 -0
  99. package/dist/chat/storage.cjs.map +1 -0
  100. package/dist/chat/storage.d.cts +191 -0
  101. package/dist/chat/storage.d.ts +191 -0
  102. package/dist/chat/storage.js +236 -0
  103. package/dist/chat/storage.js.map +1 -0
  104. package/dist/errors-BDLbNu9w.d.cts +13 -0
  105. package/dist/errors-BDLbNu9w.d.ts +13 -0
  106. package/dist/in-process-transport-C2oPTYs6.d.ts +223 -0
  107. package/dist/in-process-transport-DG-w5G6k.d.cts +223 -0
  108. package/dist/index.cjs +25 -13
  109. package/dist/index.cjs.map +1 -1
  110. package/dist/index.d.cts +32 -4
  111. package/dist/index.d.ts +32 -4
  112. package/dist/index.js +25 -13
  113. package/dist/index.js.map +1 -1
  114. package/dist/transport-D1OaUgRk.d.ts +67 -0
  115. package/dist/transport-DX1Nhm4N.d.cts +67 -0
  116. package/dist/types-Bh5AhqD-.d.ts +141 -0
  117. package/dist/types-CGF7AEX1.d.cts +141 -0
  118. package/dist/{types-BvwNzZCj.d.cts → types-CqvUAYxt.d.cts} +21 -3
  119. package/dist/{types-BvwNzZCj.d.ts → types-CqvUAYxt.d.ts} +21 -3
  120. package/dist/types-DLZzlJxt.d.ts +39 -0
  121. package/dist/types-tE0CXwBl.d.cts +39 -0
  122. package/package.json +149 -2
@@ -8,10 +8,16 @@ function getTextContent(content) {
8
8
 
9
9
  // src/errors.ts
10
10
  var AgentSDKError = class extends Error {
11
+ /** @internal Marker for cross-bundle identity checks */
12
+ _agentSDKError = true;
11
13
  constructor(message, options) {
12
14
  super(message, options);
13
15
  this.name = "AgentSDKError";
14
16
  }
17
+ /** Check if an error is an AgentSDKError (works across bundled copies) */
18
+ static is(error) {
19
+ return error instanceof Error && "_agentSDKError" in error && error._agentSDKError === true;
20
+ }
15
21
  };
16
22
  var ReentrancyError = class extends AgentSDKError {
17
23
  constructor() {
@@ -43,6 +49,7 @@ var BaseAgent = class {
43
49
  state = "idle";
44
50
  abortController = null;
45
51
  config;
52
+ _cleanupExternalSignal = null;
46
53
  /** CLI session ID for persistent mode. Override in backends that support it. */
47
54
  get sessionId() {
48
55
  return void 0;
@@ -62,8 +69,7 @@ var BaseAgent = class {
62
69
  this.enrichAndNotifyUsage(result);
63
70
  return result;
64
71
  } finally {
65
- this.state = "idle";
66
- this.abortController = null;
72
+ this.cleanupRun();
67
73
  }
68
74
  }
69
75
  async runWithContext(messages, options) {
@@ -76,8 +82,7 @@ var BaseAgent = class {
76
82
  this.enrichAndNotifyUsage(result);
77
83
  return result;
78
84
  } finally {
79
- this.state = "idle";
80
- this.abortController = null;
85
+ this.cleanupRun();
81
86
  }
82
87
  }
83
88
  async runStructured(prompt, schema, options) {
@@ -96,8 +101,7 @@ var BaseAgent = class {
96
101
  this.enrichAndNotifyUsage(result);
97
102
  return result;
98
103
  } finally {
99
- this.state = "idle";
100
- this.abortController = null;
104
+ this.cleanupRun();
101
105
  }
102
106
  }
103
107
  async *stream(prompt, options) {
@@ -110,8 +114,7 @@ var BaseAgent = class {
110
114
  const enriched = this.enrichStream(this.executeStream(messages, options, ac.signal));
111
115
  yield* this.heartbeatStream(enriched);
112
116
  } finally {
113
- this.state = "idle";
114
- this.abortController = null;
117
+ this.cleanupRun();
115
118
  }
116
119
  }
117
120
  async *streamWithContext(messages, options) {
@@ -123,8 +126,7 @@ var BaseAgent = class {
123
126
  const enriched = this.enrichStream(this.executeStream(messages, options, ac.signal));
124
127
  yield* this.heartbeatStream(enriched);
125
128
  } finally {
126
- this.state = "idle";
127
- this.abortController = null;
129
+ this.cleanupRun();
128
130
  }
129
131
  }
130
132
  abort() {
@@ -144,6 +146,8 @@ var BaseAgent = class {
144
146
  }
145
147
  /** Mark agent as disposed. Override to add cleanup. */
146
148
  dispose() {
149
+ this._cleanupExternalSignal?.();
150
+ this._cleanupExternalSignal = null;
147
151
  this.abort();
148
152
  this.state = "disposed";
149
153
  }
@@ -254,16 +258,24 @@ var BaseAgent = class {
254
258
  }
255
259
  }
256
260
  // ─── Internal Helpers ─────────────────────────────────────────
261
+ /** Clean up after a run completes (success, error, or abort). */
262
+ cleanupRun() {
263
+ this._cleanupExternalSignal?.();
264
+ this._cleanupExternalSignal = null;
265
+ this.state = "idle";
266
+ this.abortController = null;
267
+ }
257
268
  createAbortController(externalSignal) {
258
269
  const ac = new AbortController();
259
270
  this.abortController = ac;
271
+ this._cleanupExternalSignal = null;
260
272
  if (externalSignal) {
261
273
  if (externalSignal.aborted) {
262
274
  ac.abort();
263
275
  } else {
264
- externalSignal.addEventListener("abort", () => ac.abort(), {
265
- once: true
266
- });
276
+ const listener = () => ac.abort();
277
+ externalSignal.addEventListener("abort", listener, { once: true });
278
+ this._cleanupExternalSignal = () => externalSignal.removeEventListener("abort", listener);
267
279
  }
268
280
  }
269
281
  return ac;
@@ -349,9 +361,25 @@ function mapToolsToSDK(tools) {
349
361
  return tools.map((tool) => ({
350
362
  name: tool.name,
351
363
  description: tool.description,
352
- // Pass Zod schema directly — Copilot SDK accepts ZodSchema natively
353
- // and handles conversion internally, avoiding potential schema format issues.
354
- parameters: tool.parameters,
364
+ parameters: convertParameters(tool.parameters),
365
+ handler: async (args) => {
366
+ const result = await tool.execute(args);
367
+ return typeof result === "string" ? result : JSON.stringify(result);
368
+ }
369
+ }));
370
+ }
371
+ function convertParameters(params) {
372
+ if (!params) return void 0;
373
+ if (params && typeof params === "object" && "_def" in params) {
374
+ return zodToJsonSchema(params);
375
+ }
376
+ return params;
377
+ }
378
+ async function mapToolsToSDKAsync(tools) {
379
+ return tools.map((tool) => ({
380
+ name: tool.name,
381
+ description: tool.description,
382
+ parameters: convertParameters(tool.parameters),
355
383
  handler: async (args) => {
356
384
  const result = await tool.execute(args);
357
385
  return typeof result === "string" ? result : JSON.stringify(result);
@@ -522,7 +550,7 @@ function mapSessionEvent(event, tracker, thinkingTracker) {
522
550
  case "assistant.message": {
523
551
  const doneEvent = {
524
552
  type: "done",
525
- finalOutput: String(data.content ?? "")
553
+ finalOutput: data.content ? String(data.content) : null
526
554
  };
527
555
  if (thinkingTracker.endThinking()) {
528
556
  return [{ type: "thinking_end" }, doneEvent];
@@ -543,12 +571,14 @@ var CopilotAgent = class extends BaseAgent {
543
571
  persistentSession = null;
544
572
  _sessionId;
545
573
  activeSession = null;
546
- constructor(config, getClient, sendAndWaitTimeout) {
574
+ _resumeSessionId;
575
+ _toolsReady = null;
576
+ constructor(config, getClient, sendAndWaitTimeout, resumeSessionId) {
547
577
  super(config);
548
578
  this.getClient = getClient;
549
579
  this.sendAndWaitTimeout = sendAndWaitTimeout;
550
580
  this.isPersistent = config.sessionMode === "persistent";
551
- this.sdkTools = mapToolsToSDK(config.tools);
581
+ this.sdkTools = mapToolsToSDK(config.tools ?? []);
552
582
  this.sessionConfig = {
553
583
  model: config.model,
554
584
  tools: this.sdkTools,
@@ -558,8 +588,16 @@ var CopilotAgent = class extends BaseAgent {
558
588
  },
559
589
  onPermissionRequest: buildPermissionHandler(config),
560
590
  onUserInputRequest: buildUserInputHandler(config),
561
- ...config.availableTools ? { availableTools: config.availableTools } : {}
591
+ ...config.availableTools?.length ? { availableTools: config.availableTools } : {}
562
592
  };
593
+ this._toolsReady = this._initToolsAsync(config);
594
+ this._resumeSessionId = resumeSessionId;
595
+ }
596
+ /** Pre-convert Zod schemas to JSON Schema asynchronously.
597
+ * Updates sdkTools and sessionConfig.tools before first session creation. */
598
+ async _initToolsAsync(config) {
599
+ this.sdkTools = await mapToolsToSDKAsync(config.tools ?? []);
600
+ this.sessionConfig.tools = this.sdkTools;
563
601
  }
564
602
  get sessionId() {
565
603
  return this._sessionId;
@@ -588,7 +626,27 @@ var CopilotAgent = class extends BaseAgent {
588
626
  if (this.isPersistent && this.persistentSession) {
589
627
  return { session: this.persistentSession, isNew: false };
590
628
  }
629
+ if (this._toolsReady) {
630
+ await this._toolsReady;
631
+ this._toolsReady = null;
632
+ }
591
633
  const client = await this.getClient();
634
+ if (this._resumeSessionId) {
635
+ const storedId = this._resumeSessionId;
636
+ this._resumeSessionId = void 0;
637
+ try {
638
+ const session2 = await client.resumeSession(storedId, {
639
+ ...this.sessionConfig,
640
+ streaming: this.isPersistent ? true : streaming
641
+ });
642
+ if (this.isPersistent) {
643
+ this.persistentSession = session2;
644
+ this._sessionId = session2.sessionId;
645
+ }
646
+ return { session: session2, isNew: false };
647
+ } catch {
648
+ }
649
+ }
592
650
  const session = await client.createSession({
593
651
  ...this.sessionConfig,
594
652
  streaming: this.isPersistent ? true : streaming
@@ -796,13 +854,43 @@ function extractLastUserPrompt(messages) {
796
854
  }
797
855
  return "";
798
856
  }
857
+ function serializeToolCall(tc) {
858
+ const args = typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args);
859
+ return ` Tool call: ${tc.name}(${args})`;
860
+ }
861
+ function serializeToolResult(tr) {
862
+ const result = typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result);
863
+ const prefix = tr.isError ? "[ERROR] " : "";
864
+ return ` ${tr.name} \u2192 ${prefix}${result}`;
865
+ }
799
866
  function buildContextualPrompt(messages) {
800
867
  if (messages.length <= 1) {
801
868
  return extractLastUserPrompt(messages);
802
869
  }
803
870
  const history = messages.slice(0, -1).map((msg) => {
871
+ if (msg.role === "user") {
872
+ return `User: ${msg.content ? getTextContent(msg.content) : ""}`;
873
+ }
874
+ if (msg.role === "tool" && msg.toolResults) {
875
+ const results = msg.toolResults.map(serializeToolResult).join("\n");
876
+ return `Tool results:
877
+ ${results}`;
878
+ }
879
+ if (msg.role === "assistant") {
880
+ const parts = [];
881
+ const thinking = msg.thinking;
882
+ if (thinking) {
883
+ parts.push(`[reasoning: ${thinking}]`);
884
+ }
885
+ const text2 = msg.content ? getTextContent(msg.content) : "";
886
+ if (text2) parts.push(text2);
887
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
888
+ parts.push(msg.toolCalls.map(serializeToolCall).join("\n"));
889
+ }
890
+ return `Assistant: ${parts.join("\n")}`;
891
+ }
804
892
  const text = msg.content ? getTextContent(msg.content) : "";
805
- return msg.role === "user" ? `User: ${text}` : `Assistant: ${text}`;
893
+ return `${msg.role}: ${text}`;
806
894
  }).join("\n");
807
895
  const lastPrompt = extractLastUserPrompt(messages);
808
896
  return `Conversation history:
@@ -810,6 +898,21 @@ ${history}
810
898
 
811
899
  User: ${lastPrompt}`;
812
900
  }
901
+ function withTimeout(promise, ms, message) {
902
+ return new Promise((resolve, reject) => {
903
+ const timer = setTimeout(() => reject(new SubprocessError(message)), ms);
904
+ promise.then(
905
+ (val) => {
906
+ clearTimeout(timer);
907
+ resolve(val);
908
+ },
909
+ (err) => {
910
+ clearTimeout(timer);
911
+ reject(err);
912
+ }
913
+ );
914
+ });
915
+ }
813
916
  var CopilotAgentService = class {
814
917
  name = "copilot";
815
918
  client = null;
@@ -834,12 +937,17 @@ var CopilotAgentService = class {
834
937
  autoRestart: true,
835
938
  logLevel: "error",
836
939
  githubToken: this.options.githubToken,
837
- useLoggedInUser: this.options.useLoggedInUser ?? true,
940
+ useLoggedInUser: this.options.useLoggedInUser ?? !this.options.githubToken,
838
941
  ...this.options.cliArgs ? { cliArgs: this.options.cliArgs } : {},
839
942
  ...this.options.env ? { env: { ...process.env, ...this.options.env } } : {}
840
943
  });
841
- await client.start();
842
- const auth = await client.getAuthStatus();
944
+ const startupTimeout = this.options.startupTimeoutMs ?? 3e4;
945
+ await withTimeout(client.start(), startupTimeout, "CLI startup timed out");
946
+ const auth = await withTimeout(
947
+ client.getAuthStatus(),
948
+ startupTimeout,
949
+ "Auth status check timed out \u2014 token may be expired"
950
+ );
843
951
  if (!auth.isAuthenticated) {
844
952
  await client.stop();
845
953
  throw new SubprocessError(
@@ -857,7 +965,7 @@ var CopilotAgentService = class {
857
965
  }
858
966
  createAgent(config) {
859
967
  if (this.disposed) throw new DisposedError("CopilotAgentService");
860
- return new CopilotAgent(config, () => this.ensureClient(), this.options.timeout);
968
+ return new CopilotAgent(config, () => this.ensureClient(), this.options.timeout, this.options.resumeSessionId);
861
969
  }
862
970
  async listModels() {
863
971
  const client = await this.ensureClient();