@agent-native/core 0.84.32 → 0.84.35

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 (81) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +20 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/a2a/response-text.ts +10 -1
  5. package/corpus/core/src/agent/production-agent.ts +23 -20
  6. package/corpus/core/src/agent/run-manager.ts +46 -1
  7. package/corpus/core/src/agent/thread-data-builder.ts +15 -2
  8. package/corpus/core/src/client/code-agent-chat-adapter.ts +8 -1
  9. package/corpus/core/src/client/sse-event-processor.ts +21 -3
  10. package/corpus/core/src/client/use-action.ts +5 -1
  11. package/corpus/core/src/code-agents/transcript-normalizer.ts +31 -0
  12. package/corpus/core/src/server/agent-chat-plugin.ts +8 -2
  13. package/corpus/core/src/server/agent-teams.ts +24 -2
  14. package/corpus/core/src/server/ssr-handler.ts +12 -0
  15. package/corpus/core/src/vite/action-types-plugin.ts +6 -2
  16. package/corpus/core/src/vite/client.ts +152 -17
  17. package/corpus/templates/analytics/changelog/2026-07-01-smoother-chat-streaming.md +6 -0
  18. package/corpus/templates/design/actions/import-design-source.ts +158 -0
  19. package/corpus/templates/design/actions/navigate.ts +3 -2
  20. package/corpus/templates/design/actions/view-screen.ts +1 -1
  21. package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +519 -0
  22. package/corpus/templates/design/app/hooks/use-navigation-state.ts +28 -5
  23. package/corpus/templates/design/app/i18n/zh-TW.ts +40 -0
  24. package/corpus/templates/design/app/i18n-data.ts +508 -0
  25. package/corpus/templates/design/app/pages/DesignEditor.tsx +27 -0
  26. package/corpus/templates/design/changelog/2026-07-01-design-can-import-figma-paste-fig-files-and-standalone-html.md +6 -0
  27. package/corpus/templates/design/package.json +3 -0
  28. package/corpus/templates/design/server/handlers/import-design-file.ts +168 -0
  29. package/corpus/templates/design/server/lib/figma-import/clipboard.ts +122 -0
  30. package/corpus/templates/design/server/lib/figma-import/decode.ts +455 -0
  31. package/corpus/templates/design/server/lib/figma-import/processor.ts +116 -0
  32. package/corpus/templates/design/server/lib/figma-import/render-html.ts +397 -0
  33. package/corpus/templates/design/server/lib/figma-import/types.ts +60 -0
  34. package/corpus/templates/design/server/lib/import-design-files.ts +314 -0
  35. package/corpus/templates/design/server/routes/api/import-design-file.post.ts +1 -0
  36. package/dist/a2a/response-text.d.ts +1 -0
  37. package/dist/a2a/response-text.d.ts.map +1 -1
  38. package/dist/a2a/response-text.js +8 -2
  39. package/dist/a2a/response-text.js.map +1 -1
  40. package/dist/agent/production-agent.d.ts.map +1 -1
  41. package/dist/agent/production-agent.js +31 -27
  42. package/dist/agent/production-agent.js.map +1 -1
  43. package/dist/agent/run-manager.d.ts +12 -0
  44. package/dist/agent/run-manager.d.ts.map +1 -1
  45. package/dist/agent/run-manager.js +32 -1
  46. package/dist/agent/run-manager.js.map +1 -1
  47. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  48. package/dist/agent/thread-data-builder.js +15 -2
  49. package/dist/agent/thread-data-builder.js.map +1 -1
  50. package/dist/client/code-agent-chat-adapter.d.ts.map +1 -1
  51. package/dist/client/code-agent-chat-adapter.js +5 -1
  52. package/dist/client/code-agent-chat-adapter.js.map +1 -1
  53. package/dist/client/sse-event-processor.d.ts.map +1 -1
  54. package/dist/client/sse-event-processor.js +21 -3
  55. package/dist/client/sse-event-processor.js.map +1 -1
  56. package/dist/client/use-action.d.ts +5 -1
  57. package/dist/client/use-action.d.ts.map +1 -1
  58. package/dist/client/use-action.js.map +1 -1
  59. package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
  60. package/dist/code-agents/transcript-normalizer.js +24 -0
  61. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  62. package/dist/collab/routes.d.ts +1 -1
  63. package/dist/observability/routes.d.ts +3 -3
  64. package/dist/resources/handlers.d.ts +2 -2
  65. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  66. package/dist/server/agent-chat-plugin.js +2 -3
  67. package/dist/server/agent-chat-plugin.js.map +1 -1
  68. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  69. package/dist/server/agent-teams.d.ts.map +1 -1
  70. package/dist/server/agent-teams.js +17 -2
  71. package/dist/server/agent-teams.js.map +1 -1
  72. package/dist/server/ssr-handler.d.ts.map +1 -1
  73. package/dist/server/ssr-handler.js +7 -0
  74. package/dist/server/ssr-handler.js.map +1 -1
  75. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  76. package/dist/vite/action-types-plugin.js +6 -2
  77. package/dist/vite/action-types-plugin.js.map +1 -1
  78. package/dist/vite/client.d.ts.map +1 -1
  79. package/dist/vite/client.js +132 -11
  80. package/dist/vite/client.js.map +1 -1
  81. package/package.json +1 -1
package/corpus/README.md CHANGED
@@ -28,4 +28,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
28
28
  ## Generated Counts
29
29
 
30
30
  - core files: 2043
31
- - template files: 4983
31
+ - template files: 4995
@@ -1,5 +1,25 @@
1
1
  # @agent-native/core
2
2
 
3
+ ## 0.84.35
4
+
5
+ ### Patch Changes
6
+
7
+ - 3dea26c: Fix hosted Google Analytics / Tag Manager injection by baking the measurement id into Nitro server bundles and merging the required GA/GTM script, connect, and image hosts into existing stricter document CSPs.
8
+ - 3dea26c: Improve chat tool-preparation UX by hiding zero-byte progress, using clearer preparation/writing copy, and showing a delayed long-running update hint.
9
+ - 3dea26c: Improve background chat streaming smoothness by streaming guarded final text live and using adaptive SQL polling while run events are actively arriving.
10
+
11
+ ## 0.84.34
12
+
13
+ ### Patch Changes
14
+
15
+ - 56f3d91: Fix hosted Google Analytics / Tag Manager injection by baking the measurement id into Nitro server bundles and merging the required GA/GTM script, connect, and image hosts into existing stricter document CSPs.
16
+
17
+ ## 0.84.33
18
+
19
+ ### Patch Changes
20
+
21
+ - 8cc9620: Keep Nitro/Vite dev servers responsive when native file watchers hit EMFILE or ENOSPC by falling back to polling instead of replacing failed watches with no-ops.
22
+
3
23
  ## 0.84.32
4
24
 
5
25
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.84.32",
3
+ "version": "0.84.35",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -4,6 +4,15 @@ export interface CollectFinalResponseTextOptions {
4
4
  fallbackToPreToolText?: boolean;
5
5
  }
6
6
 
7
+ export function applyAgentTextEventToBuffer(
8
+ currentText: string,
9
+ event: AgentChatEvent,
10
+ ): string {
11
+ if (event.type === "clear") return "";
12
+ if (event.type === "text") return currentText + event.text;
13
+ return currentText;
14
+ }
15
+
7
16
  export function collectFinalResponseTextFromAgentEvents(
8
17
  events: readonly AgentChatEvent[],
9
18
  options: CollectFinalResponseTextOptions = {},
@@ -38,7 +47,7 @@ function collectTextEvents(
38
47
  let text = "";
39
48
  for (let i = startIdx; i < events.length; i++) {
40
49
  const event = events[i];
41
- if (event.type === "text") text += event.text;
50
+ text = applyAgentTextEventToBuffer(text, event);
42
51
  }
43
52
  return text;
44
53
  }
@@ -2670,7 +2670,6 @@ export async function runAgentLoop(opts: {
2670
2670
  }
2671
2671
  }
2672
2672
 
2673
- const bufferTextUntilFinalGuard = Boolean(opts.finalResponseGuard);
2674
2673
  let finalGuardRetries = 0;
2675
2674
  let iterations = 0;
2676
2675
 
@@ -2700,7 +2699,7 @@ export async function runAgentLoop(opts: {
2700
2699
  }
2701
2700
 
2702
2701
  let assistantContent: EngineContentPart[] | undefined;
2703
- let bufferedAssistantText = "";
2702
+ let streamedAssistantText = "";
2704
2703
  let terminalStopReason:
2705
2704
  | Extract<EngineEvent, { type: "stop" }>["reason"]
2706
2705
  | undefined;
@@ -2768,7 +2767,7 @@ export async function runAgentLoop(opts: {
2768
2767
 
2769
2768
  for (let retry = 0; ; retry++) {
2770
2769
  assistantContent = undefined;
2771
- bufferedAssistantText = "";
2770
+ streamedAssistantText = "";
2772
2771
  terminalStopReason = undefined;
2773
2772
  toolCallErrors.clear();
2774
2773
  try {
@@ -2833,11 +2832,8 @@ export async function runAgentLoop(opts: {
2833
2832
  }
2834
2833
  }
2835
2834
  if (event.type === "text-delta") {
2836
- if (bufferTextUntilFinalGuard) {
2837
- bufferedAssistantText += event.text;
2838
- } else {
2839
- send({ type: "text", text: event.text });
2840
- }
2835
+ streamedAssistantText += event.text;
2836
+ send({ type: "text", text: event.text });
2841
2837
  } else if (event.type === "thinking-delta") {
2842
2838
  thinkingBuffer += event.text;
2843
2839
  // Forward thinking deltas as a distinct event type so the UI
@@ -3007,21 +3003,22 @@ export async function runAgentLoop(opts: {
3007
3003
  }
3008
3004
  }
3009
3005
 
3010
- const flushBufferedAssistantText = () => {
3011
- if (!bufferTextUntilFinalGuard) return;
3012
- const text =
3013
- bufferedAssistantText || collectTextParts(assistantContentForHistory);
3006
+ const flushUnstreamedAssistantText = () => {
3007
+ if (streamedAssistantText) return;
3008
+ const text = collectTextParts(assistantContentForHistory);
3014
3009
  if (text) send({ type: "text", text });
3015
3010
  };
3016
3011
 
3017
3012
  if (toolCallParts.length === 0) {
3018
3013
  if (terminalStopReason === "max_tokens") {
3019
- flushBufferedAssistantText();
3014
+ flushUnstreamedAssistantText();
3020
3015
  appendAgentLoopContinuation(messages, "max_tokens");
3021
3016
  continue;
3022
3017
  }
3023
- const guard = opts.finalResponseGuard
3024
- ? await opts.finalResponseGuard({
3018
+ let guard: Awaited<ReturnType<AgentLoopFinalResponseGuard>> | null = null;
3019
+ if (opts.finalResponseGuard) {
3020
+ try {
3021
+ guard = await opts.finalResponseGuard({
3025
3022
  messages,
3026
3023
  assistantContent: assistantContentForHistory,
3027
3024
  text: collectTextParts(assistantContentForHistory),
@@ -3029,8 +3026,12 @@ export async function runAgentLoop(opts: {
3029
3026
  toolResults: [...toolResultHistory],
3030
3027
  retryCount: finalGuardRetries,
3031
3028
  executionMode: opts.executionMode ?? "act",
3032
- })
3033
- : null;
3029
+ });
3030
+ } catch (err) {
3031
+ send({ type: "clear" });
3032
+ throw err;
3033
+ }
3034
+ }
3034
3035
  let guardEmittedFallback = false;
3035
3036
  if (guard) {
3036
3037
  const retryMessage =
@@ -3039,16 +3040,18 @@ export async function runAgentLoop(opts: {
3039
3040
  typeof guard === "string" ? guard : guard.fallbackMessage;
3040
3041
  if (finalGuardRetries < 1) {
3041
3042
  finalGuardRetries += 1;
3043
+ send({ type: "clear" });
3042
3044
  messages.push({
3043
3045
  role: "user",
3044
3046
  content: [{ type: "text", text: retryMessage }],
3045
3047
  });
3046
3048
  continue;
3047
3049
  }
3050
+ send({ type: "clear" });
3048
3051
  send({ type: "text", text: fallbackMessage ?? retryMessage });
3049
3052
  guardEmittedFallback = true;
3050
3053
  } else {
3051
- flushBufferedAssistantText();
3054
+ flushUnstreamedAssistantText();
3052
3055
  }
3053
3056
  // Some providers (notably OpenAI Responses for gpt-5+) can stream a
3054
3057
  // successful turn that contains only reasoning content and zero output
@@ -3059,7 +3062,7 @@ export async function runAgentLoop(opts: {
3059
3062
  if (
3060
3063
  !guardEmittedFallback &&
3061
3064
  collectTextParts(assistantContentForHistory).trim().length === 0 &&
3062
- bufferedAssistantText.trim().length === 0
3065
+ streamedAssistantText.trim().length === 0
3063
3066
  ) {
3064
3067
  send({
3065
3068
  type: "text",
@@ -3076,7 +3079,7 @@ export async function runAgentLoop(opts: {
3076
3079
  // permanently disabled for the rest of a long multi-step run.
3077
3080
  finalGuardRetries = 0;
3078
3081
 
3079
- flushBufferedAssistantText();
3082
+ flushUnstreamedAssistantText();
3080
3083
 
3081
3084
  let requestedActionStop: { message: string; errorCode?: string } | null =
3082
3085
  null;
@@ -124,6 +124,30 @@ export const DEFAULT_ERRORED_RUN_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
124
124
  */
125
125
  export const TERMINAL_RUN_RECONNECT_WINDOW_MS = 10 * 60 * 1000;
126
126
 
127
+ /** Fast poll cadence while a SQL-backed SSE subscription is actively receiving rows. */
128
+ export const SQL_SUBSCRIPTION_ACTIVE_POLL_MS = 125;
129
+
130
+ /** Baseline SQL-backed SSE poll cadence when the run is idle. */
131
+ export const SQL_SUBSCRIPTION_IDLE_POLL_MS = 500;
132
+
133
+ /**
134
+ * Keep briefly polling quickly after rows arrive so token streams stay smooth,
135
+ * then back off to the idle cadence if the producer goes quiet.
136
+ */
137
+ export const SQL_SUBSCRIPTION_ACTIVE_GRACE_MS = 2_000;
138
+
139
+ /** Keep terminal/status probes at the historical cadence to bound DB work. */
140
+ export const SQL_SUBSCRIPTION_STATUS_POLL_MS = 500;
141
+
142
+ export function resolveSqlSubscriptionPollMs(
143
+ now: number,
144
+ activePollUntil: number,
145
+ ): number {
146
+ return now < activePollUntil
147
+ ? SQL_SUBSCRIPTION_ACTIVE_POLL_MS
148
+ : SQL_SUBSCRIPTION_IDLE_POLL_MS;
149
+ }
150
+
127
151
  const PROVIDER_RATE_LIMITED_ERROR_CODE = "provider_rate_limited";
128
152
 
129
153
  function isPreparingActionActivityEvent(event: AgentChatEvent): boolean {
@@ -960,6 +984,8 @@ function subscribeFromSQL(
960
984
  return new ReadableStream({
961
985
  async start(controller) {
962
986
  let lastSeq = fromSeq;
987
+ let activePollUntil = 0;
988
+ let lastStatusCheckAt = 0;
963
989
  const ping = () => {
964
990
  try {
965
991
  controller.enqueue(encoder.encode(`: ping ${Date.now()}\n\n`));
@@ -976,6 +1002,9 @@ function subscribeFromSQL(
976
1002
  try {
977
1003
  // Read new events from SQL
978
1004
  const events = await getRunEventsSince(runId, lastSeq);
1005
+ if (events.length > 0) {
1006
+ activePollUntil = Date.now() + SQL_SUBSCRIPTION_ACTIVE_GRACE_MS;
1007
+ }
979
1008
  for (const { seq, eventData } of events) {
980
1009
  // Advance the cursor first, before any parse/enqueue branch can
981
1010
  // `continue`/`return`. Otherwise a single corrupt (unparseable)
@@ -1009,6 +1038,18 @@ function subscribeFromSQL(
1009
1038
 
1010
1039
  // Check if run completed (no terminal event but status changed)
1011
1040
  if (events.length === 0) {
1041
+ const now = Date.now();
1042
+ if (now - lastStatusCheckAt < SQL_SUBSCRIPTION_STATUS_POLL_MS) {
1043
+ if (!cancelled) {
1044
+ const pollMs = resolveSqlSubscriptionPollMs(
1045
+ now,
1046
+ activePollUntil,
1047
+ );
1048
+ pollTimer = setTimeout(poll, pollMs);
1049
+ }
1050
+ return;
1051
+ }
1052
+ lastStatusCheckAt = now;
1012
1053
  // Opportunistically reap a stale producer before trusting SQL's
1013
1054
  // "running" status — otherwise a crashed server leaves us polling
1014
1055
  // forever.
@@ -1099,7 +1140,11 @@ function subscribeFromSQL(
1099
1140
 
1100
1141
  // Schedule next poll
1101
1142
  if (!cancelled) {
1102
- pollTimer = setTimeout(poll, 500);
1143
+ const pollMs = resolveSqlSubscriptionPollMs(
1144
+ Date.now(),
1145
+ activePollUntil,
1146
+ );
1147
+ pollTimer = setTimeout(poll, pollMs);
1103
1148
  }
1104
1149
  } catch {
1105
1150
  // SQL error — close stream
@@ -126,8 +126,7 @@ export function buildAssistantMessage(
126
126
 
127
127
  for (const { event } of events) {
128
128
  if (event.type === "clear") {
129
- content.length = 0;
130
- toolCallCounter = 0;
129
+ clearAssistantDraftContent(content);
131
130
  continue;
132
131
  }
133
132
 
@@ -252,6 +251,20 @@ export function buildAssistantMessage(
252
251
  };
253
252
  }
254
253
 
254
+ function clearAssistantDraftContent(content: ContentPart[]): void {
255
+ for (let index = content.length - 1; index >= 0; index--) {
256
+ const part = content[index];
257
+ if (!part) continue;
258
+ if (part.type === "text") {
259
+ content.splice(index, 1);
260
+ continue;
261
+ }
262
+ if (part.type === "tool-call" && part.result === undefined) {
263
+ content.splice(index, 1);
264
+ }
265
+ }
266
+ }
267
+
255
268
  function getStoredMessage(entry: any): any {
256
269
  return entry?.message ?? entry;
257
270
  }
@@ -180,7 +180,8 @@ export function createCodeAgentChatAdapter(
180
180
  }
181
181
 
182
182
  const content = codeAgentTranscriptEventsToContent(tailedEvents);
183
- if (content.length > 0 && nextEvents.length > 0) {
183
+ const sawClear = nextEvents.some(isAgentChatClearTranscriptEvent);
184
+ if ((content.length > 0 || sawClear) && nextEvents.length > 0) {
184
185
  yieldedContent = true;
185
186
  yield withRunMetadata({ content: [...content] }, runId);
186
187
  }
@@ -249,6 +250,12 @@ export function codeAgentTranscriptEventsToContent(
249
250
  return content;
250
251
  }
251
252
 
253
+ function isAgentChatClearTranscriptEvent(
254
+ event: CodeAgentChatTranscriptEvent | undefined,
255
+ ): boolean {
256
+ return event?.metadata?.agentChatEventType === "clear";
257
+ }
258
+
252
259
  function latestUserMessage(
253
260
  messages: ChatModelRunOptions["messages"],
254
261
  ): ChatModelRunOptions["messages"][number] | undefined {
@@ -698,11 +698,15 @@ export function processEvent(
698
698
  };
699
699
  } {
700
700
  if (ev.type === "clear") {
701
- // Server is retrying — discard partial text/tool output from the failed attempt
702
- content.length = 0;
701
+ // Server is retrying — discard rejected draft text and unfinished tool
702
+ // output while keeping completed tool results visible.
703
+ clearAssistantDraftContent(content);
703
704
  resetProcessEventState(state);
704
705
  dispatchActivityClear(tabId);
705
- return { action: "continue" };
706
+ return {
707
+ action: "yield",
708
+ result: { content: contentSnapshot(content) } as ChatModelRunResult,
709
+ };
706
710
  }
707
711
 
708
712
  if (ev.type === "text") {
@@ -1159,6 +1163,20 @@ export function processEvent(
1159
1163
  return { action: "continue" };
1160
1164
  }
1161
1165
 
1166
+ function clearAssistantDraftContent(content: ContentPart[]): void {
1167
+ for (let index = content.length - 1; index >= 0; index--) {
1168
+ const part = content[index];
1169
+ if (!part) continue;
1170
+ if (part.type === "text") {
1171
+ content.splice(index, 1);
1172
+ continue;
1173
+ }
1174
+ if (part.type === "tool-call" && part.result === undefined) {
1175
+ content.splice(index, 1);
1176
+ }
1177
+ }
1178
+ }
1179
+
1162
1180
  /**
1163
1181
  * Read and process SSE events from a ReadableStream response body.
1164
1182
  * Yields ChatModelRunResult for each meaningful event.
@@ -60,7 +60,11 @@ function defaultActionQueryRetry(
60
60
  * it maps action names to their parameter and return types, enabling
61
61
  * end-to-end type safety for `useActionQuery` and `useActionMutation`.
62
62
  */
63
- export interface ActionRegistry {}
63
+ declare global {
64
+ interface AgentNativeActionRegistry {}
65
+ }
66
+
67
+ export interface ActionRegistry extends AgentNativeActionRegistry {}
64
68
 
65
69
  /** Resolves to the union of registered action names, or `string` if no registry exists. */
66
70
  type ActionName = keyof ActionRegistry extends never
@@ -92,6 +92,12 @@ export function normalizeCodeAgentTranscript(
92
92
 
93
93
  for (const event of events) {
94
94
  const currentTurnIndex = Math.max(turnIndex, 0);
95
+ if (isAgentChatClearEvent(event)) {
96
+ clearNormalizedAgentDraftItems(items, currentTurnIndex);
97
+ hiddenEvents.push(event);
98
+ continue;
99
+ }
100
+
95
101
  if (event.kind === "user") {
96
102
  turnIndex = turnIndex < 0 ? (items.length === 0 ? 0 : 1) : turnIndex + 1;
97
103
  items.push(createUserTurn(event, turnIndex));
@@ -359,6 +365,31 @@ function findOpenToolEvent(
359
365
  return null;
360
366
  }
361
367
 
368
+ function isAgentChatClearEvent(event: CodeAgentTranscriptEvent): boolean {
369
+ return stringMetadata(event.metadata, "agentChatEventType") === "clear";
370
+ }
371
+
372
+ function clearNormalizedAgentDraftItems(
373
+ items: NormalizedCodeAgentTranscriptItem[],
374
+ turnIndex: number,
375
+ ): void {
376
+ for (let index = items.length - 1; index >= 0; index--) {
377
+ const item = items[index];
378
+ if (!item || item.turnIndex !== turnIndex) continue;
379
+ if (
380
+ item.type === "assistant" ||
381
+ item.type === "thinking" ||
382
+ item.type === "status"
383
+ ) {
384
+ items.splice(index, 1);
385
+ continue;
386
+ }
387
+ if (item.type === "tool" && item.state !== "completed") {
388
+ items.splice(index, 1);
389
+ }
390
+ }
391
+ }
392
+
362
393
  function suppressDuplicateFinalAssistantText(
363
394
  items: readonly NormalizedCodeAgentTranscriptItem[],
364
395
  hiddenEvents: CodeAgentTranscriptEvent[],
@@ -21,7 +21,10 @@ import {
21
21
  hasConfiguredA2ASecret,
22
22
  isA2AProductionRuntime,
23
23
  } from "../a2a/auth-policy.js";
24
- import { collectFinalResponseTextFromAgentEvents } from "../a2a/response-text.js";
24
+ import {
25
+ applyAgentTextEventToBuffer,
26
+ collectFinalResponseTextFromAgentEvents,
27
+ } from "../a2a/response-text.js";
25
28
  import { updateTaskStatusMessage } from "../a2a/task-store.js";
26
29
  import { ACTION_CHAT_UI_DATA_WIDGET_RENDERER } from "../action-ui.js";
27
30
  import type { ActionHttpConfig } from "../action.js";
@@ -5179,7 +5182,10 @@ export function createAgentChatPlugin(
5179
5182
  ],
5180
5183
  actions: mcpActions,
5181
5184
  send: (event) => {
5182
- if (event.type === "text") accumulatedText += event.text;
5185
+ accumulatedText = applyAgentTextEventToBuffer(
5186
+ accumulatedText,
5187
+ event,
5188
+ );
5183
5189
  },
5184
5190
  signal: controller.signal,
5185
5191
  },
@@ -17,6 +17,7 @@
17
17
 
18
18
  import { AsyncLocalStorage } from "node:async_hooks";
19
19
 
20
+ import { applyAgentTextEventToBuffer } from "../a2a/response-text.js";
20
21
  import type { AgentEngine, EngineMessage } from "../agent/engine/types.js";
21
22
  import type {
22
23
  ActionEntry,
@@ -1158,7 +1159,11 @@ function summarizeAgentChatEvent(event: RunEvent): {
1158
1159
  metadata: { reason: payload.reason },
1159
1160
  };
1160
1161
  case "clear":
1161
- return null;
1162
+ return {
1163
+ kind: "status",
1164
+ message: "",
1165
+ metadata: { agentChatEventType: "clear" },
1166
+ };
1162
1167
  case "agent_call":
1163
1168
  return {
1164
1169
  kind: "status",
@@ -1759,7 +1764,10 @@ export async function processAgentTeamRun(
1759
1764
  const wrappedSend = (event: AgentChatEvent) => {
1760
1765
  send(event);
1761
1766
  if (event.type === "text") {
1762
- accumulatedText += event.text;
1767
+ accumulatedText = applyAgentTextEventToBuffer(
1768
+ accumulatedText,
1769
+ event,
1770
+ );
1763
1771
  task.preview = accumulatedText.slice(-800);
1764
1772
  const now = Date.now();
1765
1773
  if (now - lastProgressSent >= PROGRESS_INTERVAL_MS) {
@@ -1772,6 +1780,20 @@ export async function processAgentTeamRun(
1772
1780
  });
1773
1781
  if (ownerEmail) void updateTaskProgressRun(task, ownerEmail);
1774
1782
  }
1783
+ } else if (event.type === "clear") {
1784
+ accumulatedText = applyAgentTextEventToBuffer(
1785
+ accumulatedText,
1786
+ event,
1787
+ );
1788
+ task.preview = "";
1789
+ lastProgressSent = Date.now();
1790
+ saveTask(task).catch((err) => {
1791
+ console.warn(
1792
+ `[agent-teams] clear save failed for task ${task.taskId}:`,
1793
+ describeDbError(err),
1794
+ );
1795
+ });
1796
+ if (ownerEmail) void updateTaskProgressRun(task, ownerEmail);
1775
1797
  } else if (event.type === "tool_start") {
1776
1798
  task.currentStep = `Running ${event.tool}...`;
1777
1799
  } else if (event.type === "tool_done") {
@@ -402,6 +402,15 @@ function appendToExistingCspDirective(
402
402
  existing.tokens = appendCspTokens(existing.tokens, additions);
403
403
  }
404
404
 
405
+ function ensureCspDirective(
406
+ directives: CspDirective[],
407
+ name: string,
408
+ tokens: readonly string[],
409
+ ): void {
410
+ if (findCspDirective(directives, name)) return;
411
+ directives.push({ name, tokens: [...tokens] });
412
+ }
413
+
405
414
  function hasStrictNonceScriptPolicy(tokens: readonly string[]): boolean {
406
415
  return tokens.some(
407
416
  (token) => token === "'strict-dynamic'" || token.startsWith("'nonce-"),
@@ -480,6 +489,9 @@ function augmentExistingEnforcedCspForFrameworkScripts(
480
489
  }
481
490
  }
482
491
 
492
+ ensureCspDirective(directives, "object-src", ["'none'"]);
493
+ ensureCspDirective(directives, "base-uri", ["'self'"]);
494
+
483
495
  return serializeCsp(directives);
484
496
  }
485
497
 
@@ -280,12 +280,16 @@ type ActionEntry<T> = T extends { default: { run: (...args: infer A) => infer R
280
280
  }
281
281
  : { result: any; params: Record<string, any> };
282
282
 
283
- declare module "@agent-native/core/client" {
284
- interface ActionRegistry {
283
+ declare global {
284
+ interface AgentNativeActionRegistry {
285
285
  ${typeEntries.join("\n")}
286
286
  }
287
287
  }
288
288
 
289
+ declare module "@agent-native/core/client" {
290
+ interface ActionRegistry extends AgentNativeActionRegistry {}
291
+ }
292
+
289
293
  export {};
290
294
  `;
291
295