@agent-native/core 0.225.0 → 0.225.1-nightly-20261106122820

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.
@@ -571,6 +571,8 @@ export async function sendAgentHarnessFollowUp(input) {
571
571
  let providerDispatchStarted = false;
572
572
  const hasFollowUpProviderDispatchStarted = () => providerDispatchStarted;
573
573
  let activeRun;
574
+ let finalizedRejected = false;
575
+ const hasFinalizedRejection = () => finalizedRejected;
574
576
  try {
575
577
  const dispatchIntent = await markAgentHarnessSessionFollowUpDispatched(session.id, claimed.generation, claimId);
576
578
  if (!dispatchIntent) {
@@ -801,7 +803,10 @@ export async function sendAgentHarnessFollowUp(input) {
801
803
  rejectFirstDispatch(runFailure ??
802
804
  new Error("The AgentHarness follow-up run ended before provider dispatch."));
803
805
  }
804
- }, rejectFirstDispatch);
806
+ }, (error) => {
807
+ finalizedRejected = true;
808
+ rejectFirstDispatch(error);
809
+ });
805
810
  if (followUpAbort.signal.aborted)
806
811
  abortActiveRun();
807
812
  return firstDispatch;
@@ -819,7 +824,13 @@ export async function sendAgentHarnessFollowUp(input) {
819
824
  refreshLiveAgentHarnessSessionGeneration(session.id, acquired.live.session, dispatch.session.generation);
820
825
  if (isAbortRequested(followUpAbort.signal))
821
826
  abortActiveRun();
822
- await activeRun.finalized;
827
+ try {
828
+ await activeRun.finalized;
829
+ }
830
+ catch (error) {
831
+ finalizedRejected = true;
832
+ throw error;
833
+ }
823
834
  }
824
835
  finally {
825
836
  followUpAbort.signal.removeEventListener("abort", abortActiveRun);
@@ -994,13 +1005,22 @@ export async function sendAgentHarnessFollowUp(input) {
994
1005
  if (isAbortRequested(followUpAbort.signal)) {
995
1006
  const reason = followUpAbort.signal.reason;
996
1007
  if (isAgentHarnessSessionConflictError(reason)) {
997
- const latest = await getAgentHarnessSessionByRunId(input.runId);
998
1008
  const cleanupErrors = [];
999
- if (!latest ||
1000
- (latest.status === "idle" && latest.followUpClaimId == null) ||
1001
- latest.status === "stopped" ||
1002
- latest.status === "errored" ||
1003
- latest.status === "destroyed") {
1009
+ let lookupFailed = false;
1010
+ let latest;
1011
+ try {
1012
+ latest = await getAgentHarnessSessionByRunId(input.runId);
1013
+ }
1014
+ catch (lookupError) {
1015
+ lookupFailed = true;
1016
+ cleanupErrors.push(lookupError);
1017
+ }
1018
+ if (latest !== undefined &&
1019
+ (!latest ||
1020
+ (latest.status === "idle" && latest.followUpClaimId == null) ||
1021
+ latest.status === "stopped" ||
1022
+ latest.status === "errored" ||
1023
+ latest.status === "destroyed")) {
1004
1024
  try {
1005
1025
  await stopAcquiredHarnessSession(session.id, acquired.live.session);
1006
1026
  }
@@ -1016,12 +1036,26 @@ export async function sendAgentHarnessFollowUp(input) {
1016
1036
  cleanupErrors.push(closeError);
1017
1037
  }
1018
1038
  }
1039
+ if (lookupFailed &&
1040
+ !hasFinalizedRejection() &&
1041
+ cleanupErrors.length === 1) {
1042
+ throw cleanupErrors[0];
1043
+ }
1019
1044
  if (cleanupErrors.length > 0) {
1020
- throw new AggregateError([reason, ...cleanupErrors], "Harness follow-up was interrupted and stream cleanup was incomplete.");
1045
+ throw new AggregateError([
1046
+ reason,
1047
+ ...(hasFinalizedRejection() ? [error] : []),
1048
+ ...cleanupErrors,
1049
+ ], "Harness follow-up was interrupted and stream cleanup was incomplete.");
1021
1050
  }
1051
+ if (hasFinalizedRejection())
1052
+ throw error;
1022
1053
  return failure(input.runId, latest ?? session, "unavailable", "The harness follow-up was interrupted because its session claim changed or stopped.");
1023
1054
  }
1024
- const failures = [reason ?? error];
1055
+ const failures = [
1056
+ reason ?? error,
1057
+ ...(hasFinalizedRejection() ? [error] : []),
1058
+ ];
1025
1059
  let failedSession = null;
1026
1060
  try {
1027
1061
  failedSession = await markOwnedFollowUpErrored(session.id, claimId, acquired.live.session, hasFollowUpProviderDispatchStarted() ? "unknown" : "not_dispatched");
@@ -1046,7 +1080,9 @@ export async function sendAgentHarnessFollowUp(input) {
1046
1080
  }
1047
1081
  }
1048
1082
  if (failures.length > 1) {
1049
- throw new AggregateError(failures, "Harness follow-up claim monitoring failed and cleanup was incomplete.");
1083
+ throw new AggregateError(failures, hasFinalizedRejection()
1084
+ ? "Harness follow-up claim monitoring failed and finalization or cleanup was incomplete."
1085
+ : "Harness follow-up claim monitoring failed and cleanup was incomplete.");
1050
1086
  }
1051
1087
  const latest = failedSession ?? (await getAgentHarnessSessionByRunId(input.runId));
1052
1088
  return failure(input.runId, latest ?? session, "unavailable", "The harness follow-up was stopped because its session claim could not be verified.");
@@ -741,6 +741,12 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
741
741
  let persistenceFailure;
742
742
  let persistenceFailureBlocked = false;
743
743
  const flushEventWrites = (retryAfterFailure) => {
744
+ if (persistenceFailure instanceof AgentRunEventNotPersistedError &&
745
+ persistenceFailure.terminalRun) {
746
+ const failed = Promise.reject(persistenceFailure);
747
+ persistenceChain = failed;
748
+ return failed;
749
+ }
744
750
  if (persistenceDrain) {
745
751
  const activeDrain = persistenceDrain;
746
752
  const settledDrain = retryAfterFailure
@@ -779,8 +785,8 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
779
785
  catch (error) {
780
786
  const terminalRun = error instanceof AgentRunEventNotPersistedError &&
781
787
  error.terminalRun;
782
- persistenceFailure = terminalRun ? undefined : error;
783
- persistenceFailureBlocked = !terminalRun;
788
+ persistenceFailure = error;
789
+ persistenceFailureBlocked = true;
784
790
  for (const queued of pendingEventWrites) {
785
791
  for (const publication of queued.publications) {
786
792
  if (publication.settled)
@@ -1527,6 +1533,14 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1527
1533
  return publication;
1528
1534
  };
1529
1535
  const emitRunEvent = (runEvent, options) => {
1536
+ if (persistenceFailure instanceof AgentRunEventNotPersistedError &&
1537
+ persistenceFailure.terminalRun) {
1538
+ const publication = Promise.reject(persistenceFailure);
1539
+ if (!options?.surfacePersistenceError)
1540
+ publication.catch(() => { });
1541
+ void checkSqlAbort();
1542
+ return publication;
1543
+ }
1530
1544
  if (privateTurn && runEvent.event.omitFromPersistedHistory !== true) {
1531
1545
  runEvent = {
1532
1546
  ...runEvent,
@@ -1722,7 +1736,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1722
1736
  completionInProgress = true;
1723
1737
  let completionError = null;
1724
1738
  let terminalPersistenceError = null;
1725
- let eventPersistenceError = null;
1739
+ let eventPersistenceFailure = null;
1726
1740
  let runTerminalErrorCode;
1727
1741
  let runTerminalBlockedTool;
1728
1742
  let runTerminalBlockedBy;
@@ -1731,21 +1745,26 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1731
1745
  let suppressContinuationEvent = false;
1732
1746
  try {
1733
1747
  await persistenceChain;
1748
+ }
1749
+ catch (error) {
1750
+ eventPersistenceFailure = { error };
1751
+ }
1752
+ try {
1734
1753
  await run.abortPersistencePromise;
1735
1754
  }
1736
1755
  catch (error) {
1737
- eventPersistenceError = error;
1738
- if (run.status !== "aborted") {
1739
- run.status = "errored";
1740
- pendingTerminalEvent = {
1741
- seq: allocateRunEventSeq(run),
1742
- event: {
1743
- type: "error",
1744
- error: "Agent run ended unexpectedly",
1745
- errorCode: "run_event_persistence_failed",
1746
- },
1747
- };
1748
- }
1756
+ eventPersistenceFailure ??= { error };
1757
+ }
1758
+ if (eventPersistenceFailure && run.status !== "aborted") {
1759
+ run.status = "errored";
1760
+ pendingTerminalEvent = {
1761
+ seq: allocateRunEventSeq(run),
1762
+ event: {
1763
+ type: "error",
1764
+ error: "Agent run ended unexpectedly",
1765
+ errorCode: "run_event_persistence_failed",
1766
+ },
1767
+ };
1749
1768
  }
1750
1769
  if (checkpointStatusReadFailed || checkpointUnknownStatus !== null) {
1751
1770
  const event = checkpointStatusReadFailed
@@ -1754,7 +1773,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1754
1773
  const abortAlreadyWon = run.status === "aborted" && run.abortReason !== undefined;
1755
1774
  if (!abortAlreadyWon) {
1756
1775
  run.status = "errored";
1757
- if (!eventPersistenceError) {
1776
+ if (!eventPersistenceFailure) {
1758
1777
  pendingTerminalEvent = {
1759
1778
  seq: peekRunEventSeq(run),
1760
1779
  event: { ...event },
@@ -1768,7 +1787,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1768
1787
  const resolveTerminalEventForCompletion = () => {
1769
1788
  if (run.status === "aborted" && run.abortReason !== undefined)
1770
1789
  return null;
1771
- if (eventPersistenceError) {
1790
+ if (eventPersistenceFailure) {
1772
1791
  return pendingTerminalEvent
1773
1792
  ? { ...pendingTerminalEvent, seq: run.events.length }
1774
1793
  : null;
@@ -1886,7 +1905,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1886
1905
  if (unfinishedTurnContinuationEvent) {
1887
1906
  terminalEvent = unfinishedTurnContinuationEvent;
1888
1907
  }
1889
- const terminalReason = eventPersistenceError && finalStatus !== "aborted"
1908
+ const terminalReason = eventPersistenceFailure && finalStatus !== "aborted"
1890
1909
  ? "error:run_event_persistence_failed"
1891
1910
  : privateTurn && terminalEvent?.type === "error"
1892
1911
  ? "error:private_content_omitted"
@@ -1989,7 +2008,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1989
2008
  : error);
1990
2009
  };
1991
2010
  if (finalStatus === "completed" || finalStatus === "errored") {
1992
- const terminalEventToEmit = eventPersistenceError
2011
+ const terminalEventToEmit = eventPersistenceFailure
1993
2012
  ? {
1994
2013
  type: "error",
1995
2014
  error: "Agent run ended unexpectedly",
@@ -2048,7 +2067,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
2048
2067
  ? { ...terminalEventToEmit, omitFromPersistedHistory: true }
2049
2068
  : terminalEventToEmit,
2050
2069
  };
2051
- if (eventPersistenceError) {
2070
+ if (eventPersistenceFailure) {
2052
2071
  volatileTerminalEvent = terminal;
2053
2072
  }
2054
2073
  else {
@@ -2100,8 +2119,10 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
2100
2119
  terminalPersistenceEstablished = false;
2101
2120
  }
2102
2121
  else {
2122
+ let abortStatusAttempted = false;
2103
2123
  try {
2104
2124
  await insertRunPromise;
2125
+ abortStatusAttempted = true;
2105
2126
  const persistAtomicAbort = () => markRunAborted(runId, run.abortReason ?? "execution-lease-claim-failed");
2106
2127
  const aborted = executionLeaseClaimFailed
2107
2128
  ? await persistAtomicAbort()
@@ -2113,6 +2134,10 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
2113
2134
  catch (error) {
2114
2135
  terminalPersistenceEstablished = false;
2115
2136
  reportTerminalStatusPersistenceError(error);
2137
+ if (eventPersistenceFailure &&
2138
+ (abortStatusAttempted || eventPersistenceFailure.error !== error)) {
2139
+ throw new AggregateError([eventPersistenceFailure.error, error], "Run event and abort status persistence both failed");
2140
+ }
2116
2141
  throw error;
2117
2142
  }
2118
2143
  }
@@ -2136,7 +2161,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
2136
2161
  await insertRunPromise;
2137
2162
  }
2138
2163
  if (!continuationStatusPersistedBeforeEvent &&
2139
- (!terminalPersistenceError || eventPersistenceError)) {
2164
+ (!terminalPersistenceError || eventPersistenceFailure)) {
2140
2165
  let statusUpdated = false;
2141
2166
  try {
2142
2167
  statusUpdated = await persistOwnTerminalStatus();
@@ -2208,7 +2233,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
2208
2233
  }
2209
2234
  }
2210
2235
  if (terminalPersistenceError) {
2211
- const reconciled = eventPersistenceError
2236
+ const reconciled = eventPersistenceFailure
2212
2237
  ? false
2213
2238
  : await reconcileTerminalRun();
2214
2239
  if (!reconciled)
@@ -2242,8 +2267,8 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
2242
2267
  attemptCount: options?.attemptCount,
2243
2268
  });
2244
2269
  }
2245
- if (eventPersistenceError && finalStatus !== "aborted") {
2246
- throw eventPersistenceError;
2270
+ if (eventPersistenceFailure) {
2271
+ throw eventPersistenceFailure.error;
2247
2272
  }
2248
2273
  })
2249
2274
  .finally(async () => {
@@ -3069,8 +3094,6 @@ export async function abortRunDurably(runId, reason = "user", options) {
3069
3094
  }
3070
3095
  if (run)
3071
3096
  run.abortPersistenceManaged = abortPersistedDurably;
3072
- if (eventFlushFailure)
3073
- throw eventFlushFailure;
3074
3097
  }
3075
3098
  catch (error) {
3076
3099
  if (run)
@@ -3090,8 +3113,13 @@ export async function abortRunDurably(runId, reason = "user", options) {
3090
3113
  },
3091
3114
  });
3092
3115
  console.error("[run-manager] durable abort persistence failed:", error instanceof Error ? error.message : error);
3116
+ if (eventFlushFailure) {
3117
+ throw new AggregateError([eventFlushFailure, error], "Run abort event flush and marker persistence failed");
3118
+ }
3093
3119
  throw error;
3094
3120
  }
3121
+ if (eventFlushFailure)
3122
+ throw eventFlushFailure;
3095
3123
  return abortedInMemory;
3096
3124
  })();
3097
3125
  if (run) {
@@ -3147,7 +3175,7 @@ export async function abortRunAtSafeBoundaryDurably(runId, reason = "user") {
3147
3175
  throw result.eventFlushFailure;
3148
3176
  return result.aborted;
3149
3177
  }
3150
- export async function abortTurnByRefDurably(threadId, turnId, reason = "user") {
3178
+ async function abortTurnByRefDurablyInternal(threadId, turnId, reason, reportedFlushFailure) {
3151
3179
  const fence = currentExecutionFence();
3152
3180
  if (fence && (fence.threadId !== threadId || fence.turnId !== turnId)) {
3153
3181
  throw new StaleExecutionFenceError(fence);
@@ -3161,24 +3189,49 @@ export async function abortTurnByRefDurably(threadId, turnId, reason = "user") {
3161
3189
  runsToFlush.push(run);
3162
3190
  }
3163
3191
  }
3164
- const flushFailures = await Promise.all(runsToFlush.map((run) => flushRunEventsBeforeAbort(run)));
3192
+ const flushResults = await Promise.allSettled(runsToFlush.map((run) => flushRunEventsBeforeAbort(run)));
3193
+ // Only the same run's repeated flush is already reported by the caller;
3194
+ // a marker write can fail with the very same error object independently.
3195
+ const unreportedFlushFailures = [];
3196
+ let hasRejectedFlush = false;
3197
+ for (const [index, result] of flushResults.entries()) {
3198
+ if (result.status === "rejected") {
3199
+ hasRejectedFlush = true;
3200
+ unreportedFlushFailures.push(result.reason);
3201
+ }
3202
+ else if (result.value &&
3203
+ !(reportedFlushFailure &&
3204
+ runsToFlush[index]?.runId === reportedFlushFailure.runId &&
3205
+ result.value === reportedFlushFailure.error)) {
3206
+ unreportedFlushFailures.push(result.value);
3207
+ }
3208
+ }
3209
+ if (hasRejectedFlush) {
3210
+ if (unreportedFlushFailures.length === 1)
3211
+ throw unreportedFlushFailures[0];
3212
+ throw new AggregateError(unreportedFlushFailures, "Turn abort event flushes failed");
3213
+ }
3165
3214
  let result;
3166
3215
  try {
3167
3216
  result = await markTurnAborted(threadId, turnId, reason);
3168
3217
  }
3169
3218
  catch (error) {
3170
- const eventFlushFailure = flushFailures.find(Boolean);
3171
- if (eventFlushFailure) {
3172
- throw new AggregateError([eventFlushFailure, error], "Turn abort event flush and marker persistence failed");
3219
+ if (unreportedFlushFailures.length) {
3220
+ throw new AggregateError([...unreportedFlushFailures, error], "Turn abort event flush and marker persistence failed");
3173
3221
  }
3174
3222
  throw error;
3175
3223
  }
3176
- const eventFlushFailure = flushFailures.find(Boolean);
3177
- if (eventFlushFailure)
3178
- throw eventFlushFailure;
3224
+ if (unreportedFlushFailures.length === 1)
3225
+ throw unreportedFlushFailures[0];
3226
+ if (unreportedFlushFailures.length > 1) {
3227
+ throw new AggregateError(unreportedFlushFailures, "Turn abort event flushes failed");
3228
+ }
3179
3229
  return result;
3180
3230
  }
3181
- export async function abortTurnDurably(runId, reason = "user") {
3231
+ export async function abortTurnByRefDurably(threadId, turnId, reason = "user") {
3232
+ return abortTurnByRefDurablyInternal(threadId, turnId, reason);
3233
+ }
3234
+ async function abortTurnDurablyInternal(runId, reason, reportedFlushFailure) {
3182
3235
  const memRun = activeRuns.get(runId);
3183
3236
  try {
3184
3237
  const ref = memRun
@@ -3187,7 +3240,7 @@ export async function abortTurnDurably(runId, reason = "user") {
3187
3240
  if (!ref) {
3188
3241
  throw new Error(`Cannot durably abort turn for missing run ${runId}`);
3189
3242
  }
3190
- return await abortTurnByRefDurably(ref.threadId, ref.turnId, reason);
3243
+ return await abortTurnByRefDurablyInternal(ref.threadId, ref.turnId, reason, reportedFlushFailure);
3191
3244
  }
3192
3245
  catch (error) {
3193
3246
  captureError(error, {
@@ -3199,6 +3252,9 @@ export async function abortTurnDurably(runId, reason = "user") {
3199
3252
  throw error;
3200
3253
  }
3201
3254
  }
3255
+ export async function abortTurnDurably(runId, reason = "user") {
3256
+ return abortTurnDurablyInternal(runId, reason);
3257
+ }
3202
3258
  /** Persist a Stop's turn marker even when a terminal event flush must be reported. */
3203
3259
  export async function abortRunAndTurnDurably(runId, reason = "user", options) {
3204
3260
  let abortedInMemory = false;
@@ -3222,7 +3278,9 @@ export async function abortRunAndTurnDurably(runId, reason = "user", options) {
3222
3278
  }
3223
3279
  if (!options?.safeBoundary || abortedInMemory) {
3224
3280
  try {
3225
- await abortTurnDurably(runId, reason);
3281
+ await abortTurnDurablyInternal(runId, reason, terminalFlushFailure
3282
+ ? { runId, error: terminalFlushFailure }
3283
+ : undefined);
3226
3284
  }
3227
3285
  catch (error) {
3228
3286
  if (terminalFlushFailure) {
@@ -1,10 +1,10 @@
1
1
  {
2
- "@agent-native/agentkit": "0.225.0",
2
+ "@agent-native/agentkit": "0.225.1-nightly-20261106122820",
3
3
  "@agent-native/code-agents-ui": "0.1.75",
4
- "@agent-native/core": "0.225.0",
5
- "@agent-native/core-corpus": "0.225.0",
4
+ "@agent-native/core": "0.225.1-nightly-20261106122820",
5
+ "@agent-native/core-corpus": "0.225.1-nightly-20261106122820",
6
6
  "@agent-native/creative-context": "0.8.66",
7
- "@agent-native/dispatch": "0.42.1",
7
+ "@agent-native/dispatch": "0.42.2-nightly-20261106122820",
8
8
  "@agent-native/embedding": "0.2.0",
9
9
  "@agent-native/migrate": "0.0.7",
10
10
  "@agent-native/otel": "0.1.33",
@@ -12,6 +12,6 @@
12
12
  "@agent-native/recap-cli": "0.5.97",
13
13
  "@agent-native/scheduling": "0.2.53",
14
14
  "@agent-native/shared-app-config": "0.1.2",
15
- "@agent-native/skills": "0.4.1",
16
- "@agent-native/toolkit": "0.225.0"
15
+ "@agent-native/skills": "0.4.2-nightly-20261106122820",
16
+ "@agent-native/toolkit": "0.225.1-nightly-20261106122820"
17
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.225.0",
3
+ "version": "0.225.1-nightly-20261106122820",
4
4
  "description": "The agentic application framework for building autonomous agents with intuitive UIs",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -760,8 +760,8 @@
760
760
  "yaml": "^2.9.0",
761
761
  "yjs": "^13.6.33",
762
762
  "zod": "^4.3.6",
763
- "@agent-native/agentkit": "^0.225.0",
764
- "@agent-native/recap-cli": "^0.5.97"
763
+ "@agent-native/recap-cli": "^0.5.97",
764
+ "@agent-native/agentkit": "^0.225.1-nightly-20261106122820"
765
765
  },
766
766
  "devDependencies": {
767
767
  "@ai-sdk/anthropic": "^3.0.71",
@@ -833,7 +833,7 @@
833
833
  "xlsx": "^0.18.5"
834
834
  },
835
835
  "peerDependencies": {
836
- "@agent-native/core-corpus": ">=0.196.0",
836
+ "@agent-native/core-corpus": "0.225.1-nightly-20261106122820",
837
837
  "@ai-sdk/anthropic": ">=3",
838
838
  "@ai-sdk/cohere": ">=3",
839
839
  "@ai-sdk/google": ">=3",