@agent-native/core 0.84.23 → 0.84.25

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 (66) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +12 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/agent/production-agent.ts +8 -6
  5. package/corpus/core/src/agent/run-manager.ts +57 -6
  6. package/corpus/core/src/client/AssistantChat.tsx +82 -15
  7. package/corpus/core/src/client/active-run-state.ts +22 -0
  8. package/corpus/core/src/client/chat/message-components.tsx +2 -1
  9. package/corpus/core/src/client/chat/tool-call-display.tsx +18 -2
  10. package/corpus/core/src/client/sse-event-processor.ts +196 -51
  11. package/corpus/core/src/client/tool-display.ts +1 -1
  12. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +15 -13
  13. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +4 -2
  14. package/corpus/templates/clips/app/components/player/share-dialog.tsx +11 -2
  15. package/corpus/templates/clips/app/i18n/ar-SA.ts +4 -0
  16. package/corpus/templates/clips/app/i18n/de-DE.ts +4 -0
  17. package/corpus/templates/clips/app/i18n/en-US.ts +4 -0
  18. package/corpus/templates/clips/app/i18n/es-ES.ts +4 -0
  19. package/corpus/templates/clips/app/i18n/fr-FR.ts +4 -0
  20. package/corpus/templates/clips/app/i18n/hi-IN.ts +4 -0
  21. package/corpus/templates/clips/app/i18n/ja-JP.ts +4 -0
  22. package/corpus/templates/clips/app/i18n/ko-KR.ts +4 -0
  23. package/corpus/templates/clips/app/i18n/pt-BR.ts +4 -0
  24. package/corpus/templates/clips/app/i18n/zh-CN.ts +4 -0
  25. package/corpus/templates/clips/app/i18n/zh-TW.ts +4 -0
  26. package/corpus/templates/clips/app/routes/embed.$shareId.tsx +31 -3
  27. package/corpus/templates/clips/changelog/2026-07-01-clip-embeds-now-render-as-a-clean-video-only-player-without-.md +6 -0
  28. package/corpus/templates/clips/changelog/2026-07-01-shared-clips-can-now-copy-a-ready-to-send-prompt-that-tells-.md +6 -0
  29. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
  30. package/corpus/templates/clips/chrome-extension/src/github-preview-content.ts +2 -2
  31. package/corpus/templates/clips/chrome-extension/src/github-preview.ts +41 -31
  32. package/dist/agent/production-agent.d.ts.map +1 -1
  33. package/dist/agent/production-agent.js +8 -6
  34. package/dist/agent/production-agent.js.map +1 -1
  35. package/dist/agent/run-manager.d.ts.map +1 -1
  36. package/dist/agent/run-manager.js +56 -4
  37. package/dist/agent/run-manager.js.map +1 -1
  38. package/dist/client/AssistantChat.d.ts +2 -1
  39. package/dist/client/AssistantChat.d.ts.map +1 -1
  40. package/dist/client/AssistantChat.js +74 -18
  41. package/dist/client/AssistantChat.js.map +1 -1
  42. package/dist/client/active-run-state.d.ts +2 -0
  43. package/dist/client/active-run-state.d.ts.map +1 -1
  44. package/dist/client/active-run-state.js +17 -0
  45. package/dist/client/active-run-state.js.map +1 -1
  46. package/dist/client/chat/message-components.d.ts.map +1 -1
  47. package/dist/client/chat/message-components.js +3 -1
  48. package/dist/client/chat/message-components.js.map +1 -1
  49. package/dist/client/chat/tool-call-display.d.ts +3 -1
  50. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  51. package/dist/client/chat/tool-call-display.js +8 -8
  52. package/dist/client/chat/tool-call-display.js.map +1 -1
  53. package/dist/client/sse-event-processor.d.ts +1 -0
  54. package/dist/client/sse-event-processor.d.ts.map +1 -1
  55. package/dist/client/sse-event-processor.js +163 -45
  56. package/dist/client/sse-event-processor.js.map +1 -1
  57. package/dist/client/tool-display.js +1 -1
  58. package/dist/client/tool-display.js.map +1 -1
  59. package/dist/collab/awareness.d.ts +2 -2
  60. package/dist/collab/awareness.d.ts.map +1 -1
  61. package/dist/collab/routes.d.ts +1 -1
  62. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  63. package/dist/notifications/routes.d.ts +3 -3
  64. package/dist/observability/routes.d.ts +6 -6
  65. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  66. package/package.json +1 -1
@@ -4,7 +4,7 @@ import { CompositeAttachmentAdapter } from "@assistant-ui/react";
4
4
  import { IconMessage, IconX, IconPlayerStop, IconChevronDown, IconTerminal, IconAlertTriangle, IconRefresh, } from "@tabler/icons-react";
5
5
  import { useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect, forwardRef, useImperativeHandle, } from "react";
6
6
  import { LLM_MISSING_CREDENTIALS_MESSAGE } from "../agent/engine/credential-errors.js";
7
- import { getActiveRunActivityTool, getActiveRun, resolveReconnectAfterSeq, setActiveRun, updateActiveRunActivity, updateActiveRunSeq, } from "./active-run-state.js";
7
+ import { ACTIVE_RUN_STATE_EVENT, clearActiveRunIfMatches, getActiveRunActivityTool, getActiveRun, resolveReconnectAfterSeq, setActiveRun, updateActiveRunActivity, updateActiveRunSeq, } from "./active-run-state.js";
8
8
  import { createAgentChatAdapter, } from "./agent-chat-adapter.js";
9
9
  import { appendAgentChatContextToMessage, formatAgentChatContextItemsForPrompt, getAgentChatContextState, normalizeAgentChatContextItem, publishAgentChatContextItems, refreshAgentChatContext, subscribeAgentChatContext, } from "./agent-chat.js";
10
10
  import { captureError } from "./analytics.js";
@@ -96,6 +96,9 @@ export function reconnectProgressTimedOut(args) {
96
96
  const threshold = args.thresholdMs ?? ACTIVE_RUN_STUCK_THRESHOLD_MS;
97
97
  return args.now - args.lastProgressAt >= threshold;
98
98
  }
99
+ function activeRunMatchesThread(state, threadId) {
100
+ return Boolean(threadId && state?.threadId === threadId && state.runId);
101
+ }
99
102
  function isAssistantUiDuplicateMessageIdError(error) {
100
103
  const message = error instanceof Error ? error.message : String(error ?? "");
101
104
  return (message.includes("MessageRepository") &&
@@ -305,8 +308,12 @@ export function resolveAssistantChatSubmitIntent({ isRunning, requestedIntent, }
305
308
  return "queued";
306
309
  return requestedIntent ?? "immediate";
307
310
  }
308
- export function resolveAssistantChatRunningState({ forceStopped, isRuntimeRunning, isReconnecting, optimisticRunning, isAutoResuming, }) {
309
- const isRunning = !forceStopped && (isRuntimeRunning || isReconnecting || optimisticRunning);
311
+ export function resolveAssistantChatRunningState({ forceStopped, isRuntimeRunning, isReconnecting, optimisticRunning, isAutoResuming, hasActiveServerRun, }) {
312
+ const isRunning = !forceStopped &&
313
+ (isRuntimeRunning ||
314
+ isReconnecting ||
315
+ optimisticRunning ||
316
+ Boolean(hasActiveServerRun));
310
317
  return {
311
318
  isRunning,
312
319
  // During auto-continuation, assistant-ui can briefly mark the message done
@@ -771,13 +778,32 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
771
778
  // When stop is clicked during reconnect, keep content visible (don't wipe it)
772
779
  const [reconnectFrozen, setReconnectFrozen] = useState(false);
773
780
  const reconnectRunIdRef = useRef(null);
774
- const [reconnectAfterSeq, setReconnectAfterSeq] = useState(0);
781
+ const reconnectCanMaterializeRef = useRef(false);
775
782
  const reconnectAbortRef = useRef(null);
776
783
  // Nuclear stop: user clicked stop. Clears the stop button/indicator AND
777
784
  // lets new submissions go through immediately — prevents the "stuck
778
785
  // queueing forever" state where isReconnecting or isRuntimeRunning gets
779
786
  // wedged (e.g. after a tab refresh + stop during reconnect).
780
787
  const [forceStopped, setForceStopped] = useState(false);
788
+ const [hasActiveServerRun, setHasActiveServerRun] = useState(() => activeRunMatchesThread(getActiveRun(), threadId));
789
+ useEffect(() => {
790
+ const syncActiveRun = (state = getActiveRun()) => {
791
+ setHasActiveServerRun(activeRunMatchesThread(state, threadId));
792
+ };
793
+ syncActiveRun();
794
+ const handler = (event) => {
795
+ const state = event
796
+ .detail?.state;
797
+ syncActiveRun(state ?? null);
798
+ };
799
+ const storageHandler = () => syncActiveRun();
800
+ window.addEventListener(ACTIVE_RUN_STATE_EVENT, handler);
801
+ window.addEventListener("storage", storageHandler);
802
+ return () => {
803
+ window.removeEventListener(ACTIVE_RUN_STATE_EVENT, handler);
804
+ window.removeEventListener("storage", storageHandler);
805
+ };
806
+ }, [threadId]);
781
807
  // Real running state drives submission/queue gating; UI running also covers
782
808
  // short auto-continuation gaps so the latest assistant message does not flash
783
809
  // into a done state while the agent is still working.
@@ -787,14 +813,14 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
787
813
  isReconnecting,
788
814
  optimisticRunning,
789
815
  isAutoResuming,
816
+ hasActiveServerRun,
790
817
  });
791
818
  const textStreaming = showRunningInUI || externalStreaming;
792
819
  // A revealed activity label wins; otherwise stay a steady "Thinking" by
793
820
  // default. We only surface "Reconnecting" while we are actively replaying
794
821
  // recovered content (reconnectContent populated). A bare reconnect with no
795
- // replayed content e.g. a tail-resume after the serverless wall, where
796
- // `scheduleUpdate` intentionally leaves reconnectContent empty — is normal
797
- // ongoing work, so it must read as "Thinking", never a perpetual "Working".
822
+ // replayed content is normal ongoing work, so it must read as "Thinking",
823
+ // never a perpetual "Working".
798
824
  const runningStatusLabel = runningActivityLabel
799
825
  ? runningActivityLabel
800
826
  : isAutoResuming
@@ -1033,9 +1059,9 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1033
1059
  return true;
1034
1060
  reconnectRunIdRef.current = runId;
1035
1061
  const afterSeq = resolveReconnectAfterSeq(threadId, runId);
1062
+ reconnectCanMaterializeRef.current = afterSeq === 0;
1036
1063
  const storedActivityTool = getActiveRunActivityTool(threadId, runId);
1037
1064
  setRunningActivityTool(storedActivityTool);
1038
- setReconnectAfterSeq(afterSeq);
1039
1065
  setActiveRun({
1040
1066
  threadId,
1041
1067
  runId,
@@ -1112,8 +1138,6 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1112
1138
  let rafPending = false;
1113
1139
  let latestSnapshot = [];
1114
1140
  const scheduleUpdate = (snapshot) => {
1115
- if (afterSeq > 0)
1116
- return;
1117
1141
  latestSnapshot = snapshot;
1118
1142
  if (rafPending)
1119
1143
  return;
@@ -1185,6 +1209,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1185
1209
  settleInterruptedToolCalls(latestContent);
1186
1210
  setReconnectContent([...latestContent]);
1187
1211
  setReconnectFrozen(latestContent.length > 0);
1212
+ reconnectCanMaterializeRef.current = latestContent.length > 0;
1188
1213
  }
1189
1214
  setRunErrorInfo({
1190
1215
  message: "The previous agent run stopped producing visible progress while reconnecting, so it was stopped before it could keep looping.",
@@ -1193,16 +1218,19 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1193
1218
  runId,
1194
1219
  });
1195
1220
  setDismissedRunErrorKey(null);
1221
+ clearActiveRunIfMatches(threadId, runId);
1196
1222
  reconnectAbortRef.current = null;
1197
1223
  setIsReconnecting(false);
1198
1224
  reconnectRunIdRef.current = null;
1199
- setReconnectAfterSeq(0);
1225
+ if (afterSeq > 0) {
1226
+ reconnectCanMaterializeRef.current = false;
1227
+ }
1200
1228
  window.dispatchEvent(new CustomEvent("agentNative.chatRunning", {
1201
1229
  detail: { isRunning: false, tabId: tabId || threadId },
1202
1230
  }));
1203
1231
  return;
1204
1232
  }
1205
- setReconnectFrozen(true);
1233
+ setReconnectFrozen(afterSeq === 0);
1206
1234
  let loaded = false;
1207
1235
  for (let attempt = 0; attempt < 10; attempt++) {
1208
1236
  await new Promise((r) => setTimeout(r, 500));
@@ -1212,21 +1240,34 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1212
1240
  if (repoHasAssistantMessage(repo)) {
1213
1241
  setReconnectContent([]);
1214
1242
  setReconnectFrozen(false);
1243
+ reconnectCanMaterializeRef.current = false;
1215
1244
  loaded = true;
1216
1245
  break;
1217
1246
  }
1218
1247
  }
1219
1248
  if (reconnectRunIdRef.current === runId) {
1249
+ if (afterSeq > 0) {
1250
+ setReconnectContent([]);
1251
+ setReconnectFrozen(false);
1252
+ }
1253
+ clearActiveRunIfMatches(threadId, runId);
1220
1254
  reconnectAbortRef.current = null;
1221
1255
  setIsReconnecting(false);
1222
1256
  reconnectRunIdRef.current = null;
1223
- setReconnectAfterSeq(0);
1257
+ if (loaded || afterSeq > 0 || latestContent.length === 0) {
1258
+ reconnectCanMaterializeRef.current = false;
1259
+ }
1224
1260
  window.dispatchEvent(new CustomEvent("agentNative.chatRunning", {
1225
1261
  detail: { isRunning: false, tabId: tabId || threadId },
1226
1262
  }));
1227
1263
  }
1228
1264
  if (!loaded) {
1229
- await refreshThreadFromServer();
1265
+ const repo = await refreshThreadFromServer();
1266
+ if (afterSeq > 0 || repoHasAssistantMessage(repo)) {
1267
+ setReconnectContent([]);
1268
+ setReconnectFrozen(false);
1269
+ reconnectCanMaterializeRef.current = false;
1270
+ }
1230
1271
  }
1231
1272
  };
1232
1273
  void streamReconnect();
@@ -1885,6 +1926,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1885
1926
  if (reconnectFrozen) {
1886
1927
  setReconnectFrozen(false);
1887
1928
  setReconnectContent([]);
1929
+ reconnectCanMaterializeRef.current = false;
1888
1930
  }
1889
1931
  if (forceStopped) {
1890
1932
  setForceStopped(false);
@@ -1904,6 +1946,11 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1904
1946
  const materializeFrozenReconnectContent = useCallback(() => {
1905
1947
  if (!reconnectFrozen || reconnectContent.length === 0)
1906
1948
  return;
1949
+ if (!reconnectCanMaterializeRef.current) {
1950
+ setReconnectFrozen(false);
1951
+ setReconnectContent([]);
1952
+ return;
1953
+ }
1907
1954
  try {
1908
1955
  const frozenContent = cloneContentParts(reconnectContent);
1909
1956
  settleInterruptedToolCalls(frozenContent);
@@ -1941,6 +1988,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1941
1988
  threadRuntime.import(ensureMessageMetadata(repo));
1942
1989
  setReconnectFrozen(false);
1943
1990
  setReconnectContent([]);
1991
+ reconnectCanMaterializeRef.current = false;
1944
1992
  }
1945
1993
  catch (err) {
1946
1994
  captureError(err, {
@@ -1979,6 +2027,8 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1979
2027
  setRunErrorInfo(null);
1980
2028
  setDismissedRunErrorKey(null);
1981
2029
  if (runIdToAbort) {
2030
+ if (threadId)
2031
+ clearActiveRunIfMatches(threadId, runIdToAbort);
1982
2032
  fetch(`${apiUrl}/runs/${encodeURIComponent(runIdToAbort)}/abort`, {
1983
2033
  method: "POST",
1984
2034
  }).catch(() => { });
@@ -1987,9 +2037,16 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1987
2037
  reconnectAbortRef.current?.abort();
1988
2038
  reconnectAbortRef.current = null;
1989
2039
  reconnectRunIdRef.current = null;
1990
- setReconnectAfterSeq(0);
1991
2040
  setIsReconnecting(false);
1992
- setReconnectFrozen(reconnectContent.length > 0);
2041
+ const shouldFreezeReconnectContent = reconnectCanMaterializeRef.current && reconnectContent.length > 0;
2042
+ if (shouldFreezeReconnectContent) {
2043
+ setReconnectFrozen(true);
2044
+ }
2045
+ else {
2046
+ setReconnectFrozen(false);
2047
+ setReconnectContent([]);
2048
+ reconnectCanMaterializeRef.current = false;
2049
+ }
1993
2050
  }
1994
2051
  threadRuntime.cancelRun();
1995
2052
  if (typeof window !== "undefined") {
@@ -2480,9 +2537,8 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
2480
2537
  }
2481
2538
  setRunErrorInfo(null);
2482
2539
  } })), (isReconnecting || reconnectFrozen) &&
2483
- reconnectAfterSeq === 0 &&
2484
2540
  reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), (isReconnecting || reconnectFrozen) &&
2485
- reconnectAfterSeq > 0 &&
2541
+ reconnectContent.length === 0 &&
2486
2542
  reconnectActivityContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectActivityContent })), showRunningInUI && (_jsx(RunningActivityStatus, { label: runningStatusLabel })), queuedMessages.map((msg) => {
2487
2543
  const displayText = msg.text
2488
2544
  .replace(/<context>[\s\S]*?<\/context>\n?/g, "")