@tanstack/ai-persistence 0.6.7 → 0.7.2

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.
@@ -24,6 +24,39 @@ function generationScope(ctx, opts) {
24
24
  var DEFAULT_ARTIFACT_FETCH_TIMEOUT_MS = 3e4;
25
25
  var DEFAULT_MAX_ARTIFACT_BYTES = 1073741824;
26
26
  var runState = /* @__PURE__ */ new WeakMap();
27
+ /** `metadata.tanstack.run.id` of a stored message, when set. */
28
+ function runTagOf(message) {
29
+ const tanstack = message.metadata?.tanstack;
30
+ if (typeof tanstack !== "object" || tanstack === null) return;
31
+ const run = tanstack.run;
32
+ if (typeof run !== "object" || run === null) return;
33
+ const id = run.id;
34
+ return typeof id === "string" && id !== "" ? id : void 0;
35
+ }
36
+ function withRunTag(message, runId) {
37
+ const metadata = message.metadata ?? {};
38
+ const tanstack = metadata.tanstack;
39
+ return {
40
+ ...message,
41
+ metadata: {
42
+ ...metadata,
43
+ tanstack: {
44
+ ...typeof tanstack === "object" && tanstack !== null ? tanstack : {},
45
+ run: { id: runId }
46
+ }
47
+ }
48
+ };
49
+ }
50
+ /**
51
+ * The thread to save, with this run's id on the assistant messages it added
52
+ * (`metadata.tanstack.run.id`). `reconstructChat` uses it to match each
53
+ * message to its run. Messages from earlier runs are left as they are.
54
+ */
55
+ function runMessages(ctx, state) {
56
+ const from = state?.firstRunMessage;
57
+ if (from === void 0) return [...ctx.messages];
58
+ return ctx.messages.map((message, index) => index >= from && message.role === "assistant" && runTagOf(message) === void 0 ? withRunTag(message, ctx.runId) : message);
59
+ }
27
60
  var validResumeStatuses = /* @__PURE__ */ new Set(["resolved", "cancelled"]);
28
61
  function mergeMaps(left, right) {
29
62
  if (!left && !right) return void 0;
@@ -39,6 +72,7 @@ function mergeResumeToolState(left, right) {
39
72
  return {
40
73
  approvals: mergeMaps(left.approvals, right.approvals),
41
74
  clientToolResults: mergeMaps(left.clientToolResults, right.clientToolResults),
75
+ clientToolErrors: mergeMaps(left.clientToolErrors, right.clientToolErrors),
42
76
  genericInterrupts: mergeMaps(left.genericInterrupts, right.genericInterrupts),
43
77
  genericInterruptRequests: mergeMaps(left.genericInterruptRequests, right.genericInterruptRequests),
44
78
  deniedToolResults: mergeMaps(left.deniedToolResults, right.deniedToolResults),
@@ -321,6 +355,7 @@ function resumeToolStateFromPending(pending, resumeByInterruptId) {
321
355
  for (const interrupt of pending) {
322
356
  const entry = resumeByInterruptId.get(interrupt.interruptId);
323
357
  if (!entry) continue;
358
+ if (hasReservedInterruptBinding(interrupt.payload)) continue;
324
359
  const kind = interruptKind(interrupt);
325
360
  const reason = stringField(interrupt.payload, "reason");
326
361
  const toolCallId = stringField(interrupt.payload, "toolCallId");
@@ -1075,6 +1110,8 @@ function withPersistence(persistence, options = {}) {
1075
1110
  return Object.keys(patch).length > 0 ? patch : void 0;
1076
1111
  },
1077
1112
  async onStart(ctx) {
1113
+ const state = runState.get(ctx);
1114
+ if (state) state.firstRunMessage = ctx.messages.length;
1078
1115
  try {
1079
1116
  await messageStore.saveThread(ctx.threadId, [...ctx.messages]);
1080
1117
  } catch {}
@@ -1131,7 +1168,7 @@ function withPersistence(persistence, options = {}) {
1131
1168
  const usage = ctx.phase === "modelStream" && chunkUsage ? accumulateTokenUsage(state.usage, chunkUsage) : state.usage ?? chunkUsage;
1132
1169
  state.usage = usage;
1133
1170
  await interruptRun(runs, ctx.runId, usage);
1134
- await messageStore.saveThread(ctx.threadId, [...ctx.messages]);
1171
+ await messageStore.saveThread(ctx.threadId, runMessages(ctx, state));
1135
1172
  state.interrupted = true;
1136
1173
  },
1137
1174
  onUsage(ctx, usage) {
@@ -1143,7 +1180,7 @@ function withPersistence(persistence, options = {}) {
1143
1180
  const state = runState.get(ctx);
1144
1181
  if (state?.interrupted) return;
1145
1182
  try {
1146
- await messageStore.saveThread(ctx.threadId, [...ctx.messages]);
1183
+ await messageStore.saveThread(ctx.threadId, runMessages(ctx, state));
1147
1184
  await commitPendingResumes(state, persistence.stores.interrupts);
1148
1185
  await completeRun(runs, ctx.runId, state?.usage ?? info.usage);
1149
1186
  state?.completion?.resolve();