@agent-native/core 0.19.1 → 0.20.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 (167) hide show
  1. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  2. package/dist/agent/engine/builder-engine.js +12 -1
  3. package/dist/agent/engine/builder-engine.js.map +1 -1
  4. package/dist/agent/production-agent.d.ts.map +1 -1
  5. package/dist/agent/production-agent.js +5 -0
  6. package/dist/agent/production-agent.js.map +1 -1
  7. package/dist/agent/thread-data-builder.d.ts +17 -0
  8. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  9. package/dist/agent/thread-data-builder.js +210 -0
  10. package/dist/agent/thread-data-builder.js.map +1 -1
  11. package/dist/cli/code-agent-executor.d.ts +2 -0
  12. package/dist/cli/code-agent-executor.d.ts.map +1 -1
  13. package/dist/cli/code-agent-executor.js +39 -1
  14. package/dist/cli/code-agent-executor.js.map +1 -1
  15. package/dist/cli/code-agent-runs.d.ts +3 -0
  16. package/dist/cli/code-agent-runs.d.ts.map +1 -1
  17. package/dist/cli/code-agent-runs.js +3 -0
  18. package/dist/cli/code-agent-runs.js.map +1 -1
  19. package/dist/cli/connect.d.ts +3 -2
  20. package/dist/cli/connect.d.ts.map +1 -1
  21. package/dist/cli/connect.js +12 -8
  22. package/dist/cli/connect.js.map +1 -1
  23. package/dist/cli/mcp-config-writers.d.ts +3 -3
  24. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  25. package/dist/cli/mcp-config-writers.js +19 -8
  26. package/dist/cli/mcp-config-writers.js.map +1 -1
  27. package/dist/client/AgentPanel.d.ts.map +1 -1
  28. package/dist/client/AgentPanel.js +8 -3
  29. package/dist/client/AgentPanel.js.map +1 -1
  30. package/dist/client/AssistantChat.d.ts +58 -0
  31. package/dist/client/AssistantChat.d.ts.map +1 -1
  32. package/dist/client/AssistantChat.js +122 -50
  33. package/dist/client/AssistantChat.js.map +1 -1
  34. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  35. package/dist/client/agent-chat-adapter.js +172 -13
  36. package/dist/client/agent-chat-adapter.js.map +1 -1
  37. package/dist/client/agent-sidebar-state.d.ts +2 -0
  38. package/dist/client/agent-sidebar-state.d.ts.map +1 -1
  39. package/dist/client/agent-sidebar-state.js +32 -0
  40. package/dist/client/agent-sidebar-state.js.map +1 -1
  41. package/dist/client/code-agent-chat-adapter.d.ts +81 -0
  42. package/dist/client/code-agent-chat-adapter.d.ts.map +1 -0
  43. package/dist/client/code-agent-chat-adapter.js +297 -0
  44. package/dist/client/code-agent-chat-adapter.js.map +1 -0
  45. package/dist/client/composer/PromptComposer.d.ts +11 -0
  46. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  47. package/dist/client/composer/PromptComposer.js +7 -3
  48. package/dist/client/composer/PromptComposer.js.map +1 -1
  49. package/dist/client/composer/TiptapComposer.d.ts +12 -1
  50. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  51. package/dist/client/composer/TiptapComposer.js +16 -7
  52. package/dist/client/composer/TiptapComposer.js.map +1 -1
  53. package/dist/client/composer/index.d.ts +1 -0
  54. package/dist/client/composer/index.d.ts.map +1 -1
  55. package/dist/client/composer/index.js +1 -0
  56. package/dist/client/composer/index.js.map +1 -1
  57. package/dist/client/composer/prompt-attachments.d.ts +11 -0
  58. package/dist/client/composer/prompt-attachments.d.ts.map +1 -0
  59. package/dist/client/composer/prompt-attachments.js +45 -0
  60. package/dist/client/composer/prompt-attachments.js.map +1 -0
  61. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  62. package/dist/client/conversation/AgentConversation.js +124 -1
  63. package/dist/client/conversation/AgentConversation.js.map +1 -1
  64. package/dist/client/conversation/code-agent-transcript.d.ts +25 -0
  65. package/dist/client/conversation/code-agent-transcript.d.ts.map +1 -0
  66. package/dist/client/conversation/code-agent-transcript.js +200 -0
  67. package/dist/client/conversation/code-agent-transcript.js.map +1 -0
  68. package/dist/client/conversation/index.d.ts +2 -1
  69. package/dist/client/conversation/index.d.ts.map +1 -1
  70. package/dist/client/conversation/index.js +1 -0
  71. package/dist/client/conversation/index.js.map +1 -1
  72. package/dist/client/conversation/types.d.ts +8 -0
  73. package/dist/client/conversation/types.d.ts.map +1 -1
  74. package/dist/client/conversation/types.js.map +1 -1
  75. package/dist/client/conversation/use-near-bottom-autoscroll.d.ts.map +1 -1
  76. package/dist/client/conversation/use-near-bottom-autoscroll.js +26 -9
  77. package/dist/client/conversation/use-near-bottom-autoscroll.js.map +1 -1
  78. package/dist/client/index.d.ts +5 -2
  79. package/dist/client/index.d.ts.map +1 -1
  80. package/dist/client/index.js +5 -2
  81. package/dist/client/index.js.map +1 -1
  82. package/dist/client/settings/useBuilderStatus.d.ts +2 -0
  83. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  84. package/dist/client/settings/useBuilderStatus.js +21 -3
  85. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  86. package/dist/client/settings/useBuilderStatus.spec.js +16 -2
  87. package/dist/client/settings/useBuilderStatus.spec.js.map +1 -1
  88. package/dist/client/sse-event-processor.d.ts.map +1 -1
  89. package/dist/client/sse-event-processor.js +3 -0
  90. package/dist/client/sse-event-processor.js.map +1 -1
  91. package/dist/client/use-chat-models.d.ts +6 -1
  92. package/dist/client/use-chat-models.d.ts.map +1 -1
  93. package/dist/client/use-chat-models.js +7 -3
  94. package/dist/client/use-chat-models.js.map +1 -1
  95. package/dist/client/use-chat-models.spec.d.ts +2 -0
  96. package/dist/client/use-chat-models.spec.d.ts.map +1 -0
  97. package/dist/client/use-chat-models.spec.js +39 -0
  98. package/dist/client/use-chat-models.spec.js.map +1 -0
  99. package/dist/code-agents/background-controller.d.ts.map +1 -1
  100. package/dist/code-agents/background-controller.js +16 -0
  101. package/dist/code-agents/background-controller.js.map +1 -1
  102. package/dist/code-agents/index.d.ts +2 -0
  103. package/dist/code-agents/index.d.ts.map +1 -1
  104. package/dist/code-agents/index.js +2 -0
  105. package/dist/code-agents/index.js.map +1 -1
  106. package/dist/code-agents/prompt-attachments.d.ts +11 -0
  107. package/dist/code-agents/prompt-attachments.d.ts.map +1 -0
  108. package/dist/code-agents/prompt-attachments.js +23 -0
  109. package/dist/code-agents/prompt-attachments.js.map +1 -0
  110. package/dist/code-agents/transcript-normalizer.js +14 -5
  111. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  112. package/dist/code-agents/transcript-order.d.ts +16 -0
  113. package/dist/code-agents/transcript-order.d.ts.map +1 -0
  114. package/dist/code-agents/transcript-order.js +47 -0
  115. package/dist/code-agents/transcript-order.js.map +1 -0
  116. package/dist/extensions/routes.d.ts.map +1 -1
  117. package/dist/extensions/routes.js +18 -14
  118. package/dist/extensions/routes.js.map +1 -1
  119. package/dist/mcp/build-server.d.ts +33 -1
  120. package/dist/mcp/build-server.d.ts.map +1 -1
  121. package/dist/mcp/build-server.js +39 -12
  122. package/dist/mcp/build-server.js.map +1 -1
  123. package/dist/mcp/builtin-tools.d.ts +3 -1
  124. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  125. package/dist/mcp/builtin-tools.js +40 -10
  126. package/dist/mcp/builtin-tools.js.map +1 -1
  127. package/dist/mcp/connect-route.d.ts.map +1 -1
  128. package/dist/mcp/connect-route.js +299 -97
  129. package/dist/mcp/connect-route.js.map +1 -1
  130. package/dist/mcp/server.d.ts.map +1 -1
  131. package/dist/mcp/server.js +17 -3
  132. package/dist/mcp/server.js.map +1 -1
  133. package/dist/secrets/substitution.d.ts +18 -0
  134. package/dist/secrets/substitution.d.ts.map +1 -1
  135. package/dist/secrets/substitution.js +74 -0
  136. package/dist/secrets/substitution.js.map +1 -1
  137. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  138. package/dist/server/agent-chat-plugin.js +33 -0
  139. package/dist/server/agent-chat-plugin.js.map +1 -1
  140. package/dist/server/auth.d.ts +8 -0
  141. package/dist/server/auth.d.ts.map +1 -1
  142. package/dist/server/auth.js +8 -1
  143. package/dist/server/auth.js.map +1 -1
  144. package/dist/server/deep-link.d.ts +0 -18
  145. package/dist/server/deep-link.d.ts.map +1 -1
  146. package/dist/server/deep-link.js +2 -1
  147. package/dist/server/deep-link.js.map +1 -1
  148. package/dist/server/open-route.d.ts.map +1 -1
  149. package/dist/server/open-route.js +23 -4
  150. package/dist/server/open-route.js.map +1 -1
  151. package/dist/shared/agent-sidebar-url.d.ts +6 -0
  152. package/dist/shared/agent-sidebar-url.d.ts.map +1 -0
  153. package/dist/shared/agent-sidebar-url.js +37 -0
  154. package/dist/shared/agent-sidebar-url.js.map +1 -0
  155. package/dist/shared/index.d.ts +1 -0
  156. package/dist/shared/index.d.ts.map +1 -1
  157. package/dist/shared/index.js +1 -0
  158. package/dist/shared/index.js.map +1 -1
  159. package/dist/styles/agent-conversation.css +403 -0
  160. package/dist/styles/agent-native.css +2 -0
  161. package/dist/vite/client.d.ts.map +1 -1
  162. package/dist/vite/client.js +1 -0
  163. package/dist/vite/client.js.map +1 -1
  164. package/docs/content/external-agents.md +27 -6
  165. package/docs/content/mcp-clients.md +2 -0
  166. package/docs/content/mcp-protocol.md +4 -2
  167. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"agent-chat-adapter.d.ts","sourceRoot":"","sources":["../../src/client/agent-chat-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,qBAAqB,CAAC;AAehF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAKrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAsjB7D;;;;GAIG;AACH;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC3C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,SAAS,CAAA;KAAE,CAAC;IACrD,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,CAAA;KAAE,CAAC;CAC5D,GAAG,gBAAgB,CAw5BnB"}
1
+ {"version":3,"file":"agent-chat-adapter.d.ts","sourceRoot":"","sources":["../../src/client/agent-chat-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,qBAAqB,CAAC;AAehF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAKrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAutB7D;;;;GAIG;AACH;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC3C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,SAAS,CAAA;KAAE,CAAC;IACrD,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,CAAA;KAAE,CAAC;CAC5D,GAAG,gBAAgB,CAu9BnB"}
@@ -21,9 +21,16 @@ const MAX_STARTUP_RECOVERY_ATTEMPTS = 8;
21
21
  const MAX_STALE_RUN_CONTINUATIONS = 3;
22
22
  const MAX_STALLED_TRANSIENT_CONTINUATIONS = 8;
23
23
  const MAX_TOTAL_TRANSIENT_CONTINUATIONS = 32;
24
+ const MAX_EMPTY_TRANSIENT_CONTINUATIONS = 1;
24
25
  const RETRY_BASE_DELAY_MS = 500;
25
26
  const RETRY_MAX_DELAY_MS = 8_000;
26
27
  const MAX_HISTORY_ATTACHMENT_CHARS = 60_000;
28
+ const MAX_HISTORY_MESSAGES = 24;
29
+ const MAX_HISTORY_TOTAL_CHARS = 64_000;
30
+ const MAX_HISTORY_MESSAGE_CHARS = 12_000;
31
+ const MAX_HISTORY_TOOL_ARGS_CHARS = 8_000;
32
+ const MAX_HISTORY_TOOL_RESULT_CHARS = 12_000;
33
+ const STARTUP_RESPONSE_TIMEOUT_MS = 45_000;
27
34
  function normalizeMentions(text) {
28
35
  return text.replace(/@\[([^\]|]+)\|[^\]]+\]/g, "@$1");
29
36
  }
@@ -32,6 +39,12 @@ function truncateForContinuation(value, maxChars) {
32
39
  return value;
33
40
  return `${value.slice(0, maxChars)}\n\n...[truncated ${value.length - maxChars} chars from prior partial output]`;
34
41
  }
42
+ function truncateForHistory(value, maxChars, label) {
43
+ if (value.length <= maxChars)
44
+ return value;
45
+ const omitted = value.length - maxChars;
46
+ return `${value.slice(0, maxChars)}\n\n[${label} truncated after ${maxChars.toLocaleString()} characters; ${omitted.toLocaleString()} characters omitted from prior chat history. Read the current app/resource state with tools if exact content is needed.]`;
47
+ }
35
48
  function contentToContinuationHistory(content) {
36
49
  const chunks = [];
37
50
  for (const part of content) {
@@ -54,6 +67,33 @@ function contentToContinuationHistory(content) {
54
67
  return truncateForContinuation(chunks.join("\n\n"), 40_000).trim();
55
68
  }
56
69
  function messageTextFromContent(content) {
70
+ return truncateForHistory(content
71
+ .filter((p) => p.type === "text")
72
+ .map((p) => normalizeMentions(p.text))
73
+ .join("\n"), MAX_HISTORY_MESSAGE_CHARS, "Message");
74
+ }
75
+ function truncateToolArgsForHistory(args) {
76
+ if (!args || typeof args !== "object" || Array.isArray(args))
77
+ return {};
78
+ try {
79
+ const json = JSON.stringify(args);
80
+ if (json.length <= MAX_HISTORY_TOOL_ARGS_CHARS) {
81
+ return args;
82
+ }
83
+ return {
84
+ __agentNativeTruncated: true,
85
+ note: "Tool input was too large to resend in chat history. Use the current app/resource state as the source of truth if exact content is needed.",
86
+ preview: truncateForHistory(json, MAX_HISTORY_TOOL_ARGS_CHARS, "Tool input"),
87
+ };
88
+ }
89
+ catch {
90
+ return {
91
+ __agentNativeTruncated: true,
92
+ note: "Tool input could not be serialized for prior chat history.",
93
+ };
94
+ }
95
+ }
96
+ function messageTextFromContentRaw(content) {
57
97
  return content
58
98
  .filter((p) => p.type === "text")
59
99
  .map((p) => normalizeMentions(p.text))
@@ -164,11 +204,11 @@ function attachmentHistoryText(attachment) {
164
204
  return null;
165
205
  }
166
206
  function messageTextForHistory(message) {
167
- const text = messageTextFromContent(message.content);
207
+ const text = messageTextFromContentRaw(message.content);
168
208
  const attachments = extractAttachmentsFromMessage(message)
169
209
  .map(attachmentHistoryText)
170
210
  .filter((part) => !!part && part.trim().length > 0);
171
- return [text, ...attachments].filter((part) => part.trim()).join("\n\n");
211
+ return truncateForHistory([text, ...attachments].filter((part) => part.trim()).join("\n\n"), MAX_HISTORY_MESSAGE_CHARS, "Message");
172
212
  }
173
213
  function isToolCallContentPart(part) {
174
214
  return Boolean(part && typeof part === "object" && part.type === "tool-call");
@@ -183,10 +223,11 @@ function toolResultContent(result) {
183
223
  return String(result ?? "");
184
224
  }
185
225
  }
186
- function contentToStructuredMessages(content, nextToolCallId) {
226
+ function contentToStructuredMessages(content, nextToolCallId, options) {
187
227
  const messages = [];
188
228
  let assistantParts = [];
189
229
  let pendingToolResults = [];
230
+ const truncate = options?.truncateForHistory === true;
190
231
  const flushToolTurn = () => {
191
232
  if (pendingToolResults.length === 0)
192
233
  return;
@@ -202,7 +243,12 @@ function contentToStructuredMessages(content, nextToolCallId) {
202
243
  if (pendingToolResults.length > 0)
203
244
  flushToolTurn();
204
245
  if (part.text.trim()) {
205
- assistantParts.push({ type: "text", text: part.text });
246
+ assistantParts.push({
247
+ type: "text",
248
+ text: truncate
249
+ ? truncateForHistory(part.text, MAX_HISTORY_MESSAGE_CHARS, "Assistant text")
250
+ : part.text,
251
+ });
206
252
  }
207
253
  continue;
208
254
  }
@@ -212,14 +258,18 @@ function contentToStructuredMessages(content, nextToolCallId) {
212
258
  type: "tool-call",
213
259
  toolCallId,
214
260
  toolName: part.toolName,
215
- args: part.args ?? {},
261
+ args: truncate
262
+ ? truncateToolArgsForHistory(part.args ?? {})
263
+ : (part.args ?? {}),
216
264
  });
217
265
  if (part.result !== undefined) {
218
266
  pendingToolResults.push({
219
267
  type: "tool-result",
220
268
  toolCallId,
221
269
  toolName: part.toolName,
222
- content: toolResultContent(part.result),
270
+ content: truncate
271
+ ? truncateForHistory(toolResultContent(part.result), MAX_HISTORY_TOOL_RESULT_CHARS, "Tool result")
272
+ : toolResultContent(part.result),
223
273
  });
224
274
  }
225
275
  }
@@ -276,10 +326,36 @@ function assistantUiMessagesToStructuredHistory(messages) {
276
326
  });
277
327
  }
278
328
  }
279
- structured.push(...contentToStructuredMessages(content, nextToolCallId));
329
+ structured.push(...contentToStructuredMessages(content, nextToolCallId, {
330
+ truncateForHistory: true,
331
+ }));
280
332
  }
281
333
  return structured;
282
334
  }
335
+ function estimateHistoryMessageCost(message) {
336
+ return Math.max(1, messageTextForHistory(message).length);
337
+ }
338
+ function limitPriorMessagesForRequest(messages) {
339
+ const recent = messages.slice(-MAX_HISTORY_MESSAGES);
340
+ const kept = [];
341
+ let totalChars = 0;
342
+ for (let i = recent.length - 1; i >= 0; i--) {
343
+ const message = recent[i];
344
+ if (message.role !== "user" && message.role !== "assistant")
345
+ continue;
346
+ const cost = estimateHistoryMessageCost(message);
347
+ if (kept.length > 0 && totalChars + cost > MAX_HISTORY_TOTAL_CHARS) {
348
+ break;
349
+ }
350
+ kept.push(message);
351
+ totalChars += cost;
352
+ }
353
+ kept.reverse();
354
+ while (kept.length > 0 && kept[0].role !== "user") {
355
+ kept.shift();
356
+ }
357
+ return kept;
358
+ }
283
359
  function combineContinuationHistory(fragments) {
284
360
  return truncateForContinuation(fragments.filter(Boolean).join("\n\n"), 40_000).trim();
285
361
  }
@@ -317,6 +393,40 @@ function delay(ms, abortSignal) {
317
393
  }, { once: true });
318
394
  });
319
395
  }
396
+ class AgentStartupTimeoutError extends Error {
397
+ timeoutMs;
398
+ constructor(timeoutMs) {
399
+ super(`Agent chat did not start streaming within ${Math.round(timeoutMs / 1000)}s.`);
400
+ this.name = "AgentStartupTimeoutError";
401
+ this.timeoutMs = timeoutMs;
402
+ }
403
+ }
404
+ async function fetchWithStartupTimeout(input, init, timeoutMs, abortSignal) {
405
+ if (abortSignal.aborted) {
406
+ throw new DOMException("The operation was aborted.", "AbortError");
407
+ }
408
+ const controller = new AbortController();
409
+ let timedOut = false;
410
+ const timeout = setTimeout(() => {
411
+ timedOut = true;
412
+ controller.abort();
413
+ }, timeoutMs);
414
+ const abort = () => controller.abort();
415
+ abortSignal.addEventListener("abort", abort, { once: true });
416
+ try {
417
+ return await fetch(input, { ...init, signal: controller.signal });
418
+ }
419
+ catch (error) {
420
+ if (timedOut) {
421
+ throw new AgentStartupTimeoutError(timeoutMs);
422
+ }
423
+ throw error;
424
+ }
425
+ finally {
426
+ clearTimeout(timeout);
427
+ abortSignal.removeEventListener("abort", abort);
428
+ }
429
+ }
320
430
  function retryDelay(attempt, abortSignal) {
321
431
  const base = Math.min(RETRY_MAX_DELAY_MS, RETRY_BASE_DELAY_MS * Math.pow(2, attempt));
322
432
  const jitter = base * 0.2;
@@ -510,7 +620,7 @@ export function createAgentChatAdapter(options) {
510
620
  const userMessageText = rawMessageText.trim() || attachments.length === 0
511
621
  ? rawMessageText
512
622
  : "Use the attached context.";
513
- const priorMessages = messages.slice(0, -1); // exclude latest user message
623
+ const priorMessages = limitPriorMessagesForRequest(messages.slice(0, -1)); // exclude latest user message and cap resend size
514
624
  const history = priorMessages
515
625
  .filter((m) => m.role === "user" || m.role === "assistant")
516
626
  .map((m) => ({
@@ -564,6 +674,15 @@ export function createAgentChatAdapter(options) {
564
674
  .filter(Boolean)
565
675
  .join("\n");
566
676
  };
677
+ const exhaustedRecoveryMessage = (reason) => {
678
+ if (content.length === 0 &&
679
+ (reason === "run_timeout" ||
680
+ reason === "no_progress" ||
681
+ reason === "stream_ended")) {
682
+ return "The agent request started but did not produce any visible progress before timing out. I stopped the automatic retries so this chat would not stay stuck on Thinking.";
683
+ }
684
+ return "The agent connection kept failing after several automatic recovery attempts.";
685
+ };
567
686
  const dispatchAuthError = (reason) => {
568
687
  if (typeof window === "undefined")
569
688
  return;
@@ -788,11 +907,20 @@ export function createAgentChatAdapter(options) {
788
907
  const visibleContent = visibleContentForContinuation();
789
908
  const currentPartialHistory = contentToContinuationHistory(visibleContent);
790
909
  const madeProgress = hasContinuationProgress(visibleContent);
910
+ const madeVisibleProgress = visibleContent.length > 0;
791
911
  if (signal.reason === "loop_limit") {
792
912
  stalledTransientContinuationAttempts = 0;
793
913
  }
794
914
  else {
795
915
  totalTransientContinuationAttempts += 1;
916
+ if (!madeVisibleProgress && signal.reason === "run_timeout") {
917
+ return { ok: false, resetVisibleContent: false };
918
+ }
919
+ if (!madeVisibleProgress &&
920
+ totalTransientContinuationAttempts >
921
+ MAX_EMPTY_TRANSIENT_CONTINUATIONS) {
922
+ return { ok: false, resetVisibleContent: false };
923
+ }
796
924
  if (signal.reason === "stale_run") {
797
925
  staleRunContinuationAttempts += 1;
798
926
  if (staleRunContinuationAttempts > MAX_STALE_RUN_CONTINUATIONS) {
@@ -861,7 +989,7 @@ export function createAgentChatAdapter(options) {
861
989
  try {
862
990
  runId = null;
863
991
  lastSeq = -1;
864
- const res = await fetch(apiUrl, {
992
+ const res = await fetchWithStartupTimeout(apiUrl, {
865
993
  method: "POST",
866
994
  headers,
867
995
  body: JSON.stringify({
@@ -884,8 +1012,7 @@ export function createAgentChatAdapter(options) {
884
1012
  ? { references: runConfig.custom.references }
885
1013
  : {}),
886
1014
  }),
887
- signal: abortSignal,
888
- });
1015
+ }, STARTUP_RESPONSE_TIMEOUT_MS, abortSignal);
889
1016
  // Check for auth errors returned as 200 with JSON (common with middleware issues)
890
1017
  const contentType = res.headers.get("content-type") || "";
891
1018
  if (res.ok &&
@@ -1067,7 +1194,7 @@ export function createAgentChatAdapter(options) {
1067
1194
  }
1068
1195
  const continuation = prepareAutoContinuation(err);
1069
1196
  if (!continuation.ok) {
1070
- const message = "The agent connection kept failing after several automatic recovery attempts.";
1197
+ const message = exhaustedRecoveryMessage(err.reason);
1071
1198
  captureChatClientError(err, "auto-continuation-exhausted", {
1072
1199
  autoContinueReason: err.reason,
1073
1200
  });
@@ -1158,12 +1285,44 @@ export function createAgentChatAdapter(options) {
1158
1285
  const activeReconnected = yield* reconnectActiveRunForThread();
1159
1286
  if (activeReconnected)
1160
1287
  return;
1288
+ if (err instanceof AgentStartupTimeoutError) {
1289
+ const message = "The agent chat endpoint accepted the request but did not start streaming in time. This usually means prompt setup, the LLM gateway, or the provider is stalled.";
1290
+ captureChatClientError(err, "startup-timeout", {
1291
+ timeoutMs: err.timeoutMs,
1292
+ });
1293
+ const runError = {
1294
+ message,
1295
+ details: connectionRecoveryDetails(),
1296
+ errorCode: "startup_timeout",
1297
+ recoverable: true,
1298
+ ...(runId ? { runId } : {}),
1299
+ };
1300
+ if (typeof window !== "undefined") {
1301
+ window.dispatchEvent(new CustomEvent("agent-chat:run-error", {
1302
+ detail: { ...runError, tabId },
1303
+ }));
1304
+ }
1305
+ content.push({
1306
+ type: "text",
1307
+ text: `Something went wrong: ${message}`,
1308
+ });
1309
+ yield {
1310
+ content: [...content],
1311
+ status: {
1312
+ type: "incomplete",
1313
+ reason: "error",
1314
+ },
1315
+ metadata: { custom: { ...(runId ? { runId } : {}), runError } },
1316
+ };
1317
+ clearActiveRun();
1318
+ return;
1319
+ }
1161
1320
  // Reconnect failed or not possible — keep going from the partial
1162
1321
  // streamed content instead of surfacing a transient transport error.
1163
1322
  if (content.length > 0) {
1164
1323
  const continuation = prepareAutoContinuation(new AgentAutoContinueSignal({ reason: "stream_ended" }));
1165
1324
  if (!continuation.ok) {
1166
- const message = "The agent connection kept failing after several automatic recovery attempts.";
1325
+ const message = exhaustedRecoveryMessage("stream_ended");
1167
1326
  captureChatClientError(err, "recovery-exhausted");
1168
1327
  const runError = {
1169
1328
  message,