@adhdev/daemon-core 0.9.82-rc.521 → 0.9.82-rc.523

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.
package/dist/index.mjs CHANGED
@@ -68,7 +68,9 @@ function normalizeAutoFastForwardPolicy(value) {
68
68
  return {
69
69
  enabled: record.enabled !== false,
70
70
  ...Number.isFinite(maxBehind) && maxBehind >= 0 ? { maxBehind: Math.floor(maxBehind) } : {},
71
- requireCleanSubmodules: record.requireCleanSubmodules !== false
71
+ requireCleanSubmodules: record.requireCleanSubmodules !== false,
72
+ ...record.remoteNodes === true ? { remoteNodes: true } : {},
73
+ ...record.mode === "continuous" ? { mode: "continuous" } : {}
72
74
  };
73
75
  }
74
76
  function mergeAndNormalizePolicy(base, patch) {
@@ -412,10 +414,10 @@ function readInjected(value) {
412
414
  }
413
415
  function getDaemonBuildInfo() {
414
416
  if (cached) return cached;
415
- const commit = readInjected(true ? "ba90523a7fd7277668cc67ab7c596402c3d77959" : void 0) ?? "unknown";
416
- const commitShort = readInjected(true ? "ba90523a" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
417
- const version = readInjected(true ? "0.9.82-rc.521" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
418
- const builtAt = readInjected(true ? "2026-07-14T01:41:02.959Z" : void 0);
417
+ const commit = readInjected(true ? "3dbfe60d143e6cc534bfe10d93d0e26eb4fdcc1b" : void 0) ?? "unknown";
418
+ const commitShort = readInjected(true ? "3dbfe60d" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
419
+ const version = readInjected(true ? "0.9.82-rc.523" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
420
+ const builtAt = readInjected(true ? "2026-07-14T03:48:53.299Z" : void 0);
419
421
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
420
422
  return cached;
421
423
  }
@@ -15829,8 +15831,25 @@ import { existsSync as existsSync18 } from "fs";
15829
15831
  function localCoordinatorDaemonId() {
15830
15832
  return canonicalDaemonId(readNonEmptyString2(loadConfig().machineId));
15831
15833
  }
15834
+ function acquireAutoFastForwardLease(workspace) {
15835
+ const key2 = normalizeMeshWorkspaceForCompare(workspace);
15836
+ if (!key2) return false;
15837
+ if (autoFastForwardWorkspaceLease.has(key2)) return false;
15838
+ autoFastForwardWorkspaceLease.add(key2);
15839
+ return true;
15840
+ }
15841
+ function releaseAutoFastForwardLease(workspace) {
15842
+ const key2 = normalizeMeshWorkspaceForCompare(workspace);
15843
+ if (key2) autoFastForwardWorkspaceLease.delete(key2);
15844
+ }
15845
+ function isWorkspaceAutoFastForwardInFlight(workspace) {
15846
+ const key2 = normalizeMeshWorkspaceForCompare(workspace || "");
15847
+ return !!key2 && autoFastForwardWorkspaceLease.has(key2);
15848
+ }
15832
15849
  function __resetIdleAutoFastForwardForTests() {
15833
15850
  idleAutoFastForwardLastAttempt.clear();
15851
+ continuousAutoFastForwardLastScan.clear();
15852
+ autoFastForwardWorkspaceLease.clear();
15834
15853
  }
15835
15854
  function getMeshWithCache(components, meshId) {
15836
15855
  const localMesh = getMesh(meshId);
@@ -15963,6 +15982,10 @@ function deliverTaskToSession(dispatchThunk, ctx, warmup) {
15963
15982
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
15964
15983
  const mesh = getMeshWithCache(components, meshId);
15965
15984
  const node = mesh?.nodes.find((n) => meshNodeIdMatches(n, nodeId));
15985
+ if (isWorkspaceAutoFastForwardInFlight(readNonEmptyString2(node?.workspace))) {
15986
+ LOG.info("MeshQueue", `Deferring queue claim for node ${nodeId} (${sessionId}): an auto fast-forward is mutating its workspace \u2014 task left pending, claim re-fires next tick`);
15987
+ return false;
15988
+ }
15966
15989
  const inlineBootstrapNode = (() => {
15967
15990
  try {
15968
15991
  const inlineMesh = components.router?.getCachedInlineMesh?.(meshId);
@@ -16288,7 +16311,12 @@ function resolveAutoFastForwardPolicy(mesh) {
16288
16311
  return {
16289
16312
  enabled: record.enabled !== false,
16290
16313
  ...Number.isFinite(maxBehind) && maxBehind >= 0 ? { maxBehind: Math.floor(maxBehind) } : {},
16291
- requireCleanSubmodules: record.requireCleanSubmodules !== false
16314
+ requireCleanSubmodules: record.requireCleanSubmodules !== false,
16315
+ // Strict opt-in: absent/false → self-only (historical behavior). Only an
16316
+ // explicit `true` extends auto ff to remote owning-daemon nodes.
16317
+ remoteNodes: record.remoteNodes === true,
16318
+ // Absent/anything-but-continuous → 'idle' (historical idle-edge-only detection).
16319
+ mode: record.mode === "continuous" ? "continuous" : "idle"
16292
16320
  };
16293
16321
  }
16294
16322
  function sessionStateLooksActive(state) {
@@ -17038,51 +17066,157 @@ async function triggerMeshQueue(components, meshId) {
17038
17066
  ...pendingAfter > 0 && newlyAssignedTasks.length === 0 && localIdleSessionsChecked === 0 && remoteIdleSessionsChecked === 0 && !autoLaunchPending ? { noIdleMeshSessionAvailable: true } : {}
17039
17067
  };
17040
17068
  }
17041
- async function maybeAutoFastForwardIdleNode(components, args) {
17069
+ function dryRunSatisfiesAutoFastForwardPolicy(dryRun, policy) {
17070
+ if (!dryRun || dryRun.code !== "fast_forward_available" || dryRun.allowed !== true) return false;
17071
+ const behind = Number(dryRun.current?.behind);
17072
+ if (!Number.isFinite(behind) || behind <= 0) return false;
17073
+ if (policy.maxBehind !== void 0 && behind > policy.maxBehind) return false;
17074
+ if (policy.requireCleanSubmodules) {
17075
+ const submodules = Array.isArray(dryRun.current?.submodules) ? dryRun.current.submodules : [];
17076
+ if (submodules.some((submodule) => submodule?.dirty || submodule?.outOfSync || submodule?.error)) return false;
17077
+ }
17078
+ return true;
17079
+ }
17080
+ function readNodeSubmoduleIgnorePaths(node) {
17081
+ return Array.isArray(node?.policy?.submoduleIgnorePaths) ? node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
17082
+ }
17083
+ function nodeIsAutoFastForwardEligible(components, meshId, nodeId, node, currentSessionId) {
17084
+ if (!node) return false;
17085
+ if (node.status === "disabled" || node.status === "removed") return false;
17086
+ if (node.readOnly === true || node.policy?.readOnly === true) return false;
17087
+ if (isWorktreeBootstrapStaleRunning(node)) return false;
17088
+ if (node.worktreeBootstrap?.status === "running") return false;
17089
+ if (nodeHasActiveMeshWork(components, meshId, nodeId, currentSessionId)) return false;
17090
+ return true;
17091
+ }
17092
+ function remoteNodeIsConnected(components, node) {
17093
+ const daemonId = readMeshNodeDaemonId(node ?? {});
17094
+ if (!daemonId) return false;
17095
+ const getPeerStatus = components.getMeshPeerConnectionStatus;
17096
+ if (getPeerStatus) {
17097
+ const snapshot = getPeerStatus(daemonId);
17098
+ return !!snapshot && String(snapshot.state) === "connected";
17099
+ }
17100
+ return readNonEmptyString2(node?.connection?.state).toLowerCase() === "connected";
17101
+ }
17102
+ async function delegateRemoteAutoFastForward(components, args) {
17103
+ const dispatchMeshCommand = components.dispatchMeshCommand;
17104
+ if (!dispatchMeshCommand) return;
17105
+ if (!acquireAutoFastForwardLease(args.workspace)) return;
17106
+ const submoduleIgnorePaths = readNodeSubmoduleIgnorePaths(args.node);
17042
17107
  const mesh = getMeshWithCache(components, args.meshId);
17043
- const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
17044
- const workspace = readNonEmptyString2(node?.workspace);
17045
- if (!workspace) return;
17046
- if (!existsSync18(workspace)) return;
17047
- const policy = resolveAutoFastForwardPolicy(mesh);
17048
- if (!policy.enabled) return;
17049
- if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
17050
- const throttleKey = `${args.meshId}:${args.nodeId}`;
17051
- const now = Date.now();
17052
- const lastAttempt = idleAutoFastForwardLastAttempt.get(throttleKey) || 0;
17053
- if (now - lastAttempt < IDLE_AUTO_FAST_FORWARD_THROTTLE_MS) return;
17054
- idleAutoFastForwardLastAttempt.set(throttleKey, now);
17055
- const submoduleIgnorePaths = Array.isArray(node?.policy?.submoduleIgnorePaths) ? node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
17108
+ const baseArgs = {
17109
+ meshId: args.meshId,
17110
+ nodeId: args.nodeId,
17111
+ workspace: args.workspace,
17112
+ inlineMesh: mesh,
17113
+ ...submoduleIgnorePaths ? { submoduleIgnorePaths } : {},
17114
+ trigger: args.trigger,
17115
+ // Preserve the pre-fix self-only semantics for submodules: the local idle path
17116
+ // never updated submodules (updateSubmodules:false), so the remote path matches.
17117
+ updateSubmodules: false
17118
+ };
17119
+ try {
17120
+ const remoteDry = await dispatchMeshCommand(args.daemonId, "fast_forward_mesh_node", {
17121
+ ...baseArgs,
17122
+ execute: false,
17123
+ dryRun: true
17124
+ });
17125
+ if (!dryRunSatisfiesAutoFastForwardPolicy(remoteDry, args.policy)) return;
17126
+ if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId)) return;
17127
+ const executed = await dispatchMeshCommand(args.daemonId, "fast_forward_mesh_node", {
17128
+ ...baseArgs,
17129
+ execute: true,
17130
+ dryRun: false
17131
+ });
17132
+ if (executed?.executed === true) {
17133
+ LOG.info("MeshFastForward", `Remote auto fast-forward executed for node ${args.nodeId} (daemon ${String(args.daemonId).slice(0, 12)}, trigger ${args.trigger})`);
17134
+ }
17135
+ } catch (e) {
17136
+ LOG.warn("MeshFastForward", `Remote auto fast-forward delegation failed for ${args.nodeId}: ${e?.message || e}`);
17137
+ } finally {
17138
+ releaseAutoFastForwardLease(args.workspace);
17139
+ }
17140
+ }
17141
+ async function executeLocalAutoFastForward(args) {
17142
+ if (!acquireAutoFastForwardLease(args.workspace)) return;
17143
+ const submoduleIgnorePaths = readNodeSubmoduleIgnorePaths(args.node);
17056
17144
  try {
17057
17145
  const dryRun = await fastForwardMeshNode({
17058
17146
  meshId: args.meshId,
17059
17147
  nodeId: args.nodeId,
17060
- workspace,
17148
+ workspace: args.workspace,
17061
17149
  execute: false,
17062
17150
  dryRun: true,
17063
17151
  updateSubmodules: false,
17064
17152
  submoduleIgnorePaths,
17065
- trigger: "idle_auto"
17153
+ trigger: args.trigger
17066
17154
  });
17067
- if (!dryRun || dryRun.code !== "fast_forward_available" || dryRun.allowed !== true) return;
17068
- const behind = Number(dryRun.current?.behind);
17069
- if (policy.maxBehind !== void 0 && Number.isFinite(behind) && behind > policy.maxBehind) return;
17070
- if (policy.requireCleanSubmodules) {
17071
- const submodules = Array.isArray(dryRun.current?.submodules) ? dryRun.current.submodules : [];
17072
- if (submodules.some((submodule) => submodule?.dirty || submodule?.outOfSync || submodule?.error)) return;
17073
- }
17155
+ if (!dryRunSatisfiesAutoFastForwardPolicy(dryRun, args.policy)) return;
17074
17156
  await fastForwardMeshNode({
17075
17157
  meshId: args.meshId,
17076
17158
  nodeId: args.nodeId,
17077
- workspace,
17159
+ workspace: args.workspace,
17078
17160
  execute: true,
17079
17161
  dryRun: false,
17080
17162
  updateSubmodules: false,
17081
17163
  submoduleIgnorePaths,
17082
- trigger: "idle_auto"
17164
+ trigger: args.trigger
17083
17165
  });
17084
17166
  } catch (e) {
17085
17167
  LOG.warn("MeshFastForward", `Idle auto fast-forward check failed for ${args.nodeId}: ${e?.message || e}`);
17168
+ } finally {
17169
+ releaseAutoFastForwardLease(args.workspace);
17170
+ }
17171
+ }
17172
+ async function maybeAutoFastForwardIdleNode(components, args) {
17173
+ const mesh = getMeshWithCache(components, args.meshId);
17174
+ const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
17175
+ const workspace = readNonEmptyString2(node?.workspace);
17176
+ if (!workspace) return;
17177
+ const policy = resolveAutoFastForwardPolicy(mesh);
17178
+ if (!policy.enabled) return;
17179
+ if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
17180
+ const throttleKey = `${args.meshId}:${args.nodeId}`;
17181
+ const now = Date.now();
17182
+ const lastAttempt = idleAutoFastForwardLastAttempt.get(throttleKey) || 0;
17183
+ if (now - lastAttempt < IDLE_AUTO_FAST_FORWARD_THROTTLE_MS) return;
17184
+ idleAutoFastForwardLastAttempt.set(throttleKey, now);
17185
+ if (isLocalAutoLaunchNode(node)) {
17186
+ if (!existsSync18(workspace)) return;
17187
+ await executeLocalAutoFastForward({ meshId: args.meshId, nodeId: args.nodeId, node, workspace, policy, trigger: "idle_auto" });
17188
+ return;
17189
+ }
17190
+ if (!policy.remoteNodes) return;
17191
+ const daemonId = readMeshNodeDaemonId(node ?? {});
17192
+ if (!daemonId || !components.dispatchMeshCommand) return;
17193
+ if (!remoteNodeIsConnected(components, node)) return;
17194
+ await delegateRemoteAutoFastForward(components, { meshId: args.meshId, nodeId: args.nodeId, node, daemonId, workspace, policy, trigger: "idle_auto" });
17195
+ }
17196
+ async function runContinuousAutoFastForwardScan(components, mesh) {
17197
+ if (!components.dispatchMeshCommand) return;
17198
+ const policy = resolveAutoFastForwardPolicy(mesh);
17199
+ if (!policy.enabled || !policy.remoteNodes || policy.mode !== "continuous") return;
17200
+ const meshId = readNonEmptyString2(mesh?.id);
17201
+ if (!meshId) return;
17202
+ const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
17203
+ const now = Date.now();
17204
+ for (const node of nodes) {
17205
+ const nodeId = normalizeMeshNodeId(node);
17206
+ if (!nodeId) continue;
17207
+ if (node?.isLocalWorktree === true) continue;
17208
+ if (isLocalAutoLaunchNode(node)) continue;
17209
+ const workspace = readNonEmptyString2(node?.workspace);
17210
+ if (!workspace) continue;
17211
+ const daemonId = readMeshNodeDaemonId(node ?? {});
17212
+ if (!daemonId) continue;
17213
+ if (!nodeIsAutoFastForwardEligible(components, meshId, nodeId, node)) continue;
17214
+ if (!remoteNodeIsConnected(components, node)) continue;
17215
+ const cooldownKey = `${meshId}:${nodeId}`;
17216
+ const lastScan = continuousAutoFastForwardLastScan.get(cooldownKey) || 0;
17217
+ if (now - lastScan < CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS) continue;
17218
+ continuousAutoFastForwardLastScan.set(cooldownKey, now);
17219
+ await delegateRemoteAutoFastForward(components, { meshId, nodeId, node, daemonId, workspace, policy, trigger: "reconcile_auto" });
17086
17220
  }
17087
17221
  }
17088
17222
  function runIdleMaintenanceThenAssignQueue(components, args) {
@@ -17096,7 +17230,7 @@ function runIdleMaintenanceThenAssignQueue(components, args) {
17096
17230
  });
17097
17231
  });
17098
17232
  }
17099
- var IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, BOOTSTRAP_TERMINAL_STATUSES, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, LOCAL_LAUNCH_READY_TIMEOUT_MS, LOCAL_LAUNCH_READY_POLL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES, AUTO_LAUNCH_REMOTE_IDLE_TTL_MS, autoLaunchAwaitClaimBackoff, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, ACTIONABLE_SKIP_REASON_PREFIXES, TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON, lastActionableSkipNotified;
17233
+ var IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS, continuousAutoFastForwardLastScan, autoFastForwardWorkspaceLease, BOOTSTRAP_TERMINAL_STATUSES, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, LOCAL_LAUNCH_READY_TIMEOUT_MS, LOCAL_LAUNCH_READY_POLL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES, AUTO_LAUNCH_REMOTE_IDLE_TTL_MS, autoLaunchAwaitClaimBackoff, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, ACTIONABLE_SKIP_REASON_PREFIXES, TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON, lastActionableSkipNotified;
17100
17234
  var init_mesh_queue_assignment = __esm({
17101
17235
  "src/mesh/mesh-queue-assignment.ts"() {
17102
17236
  "use strict";
@@ -17125,6 +17259,9 @@ var init_mesh_queue_assignment = __esm({
17125
17259
  init_model_provider_compat();
17126
17260
  IDLE_AUTO_FAST_FORWARD_THROTTLE_MS = 30 * 60 * 1e3;
17127
17261
  idleAutoFastForwardLastAttempt = /* @__PURE__ */ new Map();
17262
+ CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS = 45 * 1e3;
17263
+ continuousAutoFastForwardLastScan = /* @__PURE__ */ new Map();
17264
+ autoFastForwardWorkspaceLease = /* @__PURE__ */ new Set();
17128
17265
  BOOTSTRAP_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["complete", "failed"]);
17129
17266
  DISPATCH_CONFIRM_TIMEOUT_MS = 12e4;
17130
17267
  DISPATCH_CONNECT_TIMEOUT_MS = MESH_CONNECT_TIMEOUT_MS;
@@ -22077,6 +22214,17 @@ async function runMeshReconcileTick(components) {
22077
22214
  }
22078
22215
  }
22079
22216
  }
22217
+ if (dispatchMeshCommand) {
22218
+ for (const mesh of listMeshes()) {
22219
+ const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
22220
+ if (!daemonHostsMesh(mesh, selfIds)) continue;
22221
+ try {
22222
+ await runContinuousAutoFastForwardScan(components, mesh);
22223
+ } catch (e) {
22224
+ LOG.warn("MeshReconcile", `Continuous auto fast-forward scan failed for mesh ${mesh.id}: ${e?.message || e}`);
22225
+ }
22226
+ }
22227
+ }
22080
22228
  for (const mesh of listMeshes()) {
22081
22229
  const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
22082
22230
  if (!daemonHostsMesh(mesh, selfIds)) continue;
@@ -24437,13 +24585,17 @@ function stableHash(value) {
24437
24585
  function normalizeMessageIdentity(messages, status) {
24438
24586
  const list = Array.isArray(messages) ? messages : [];
24439
24587
  let turnIndex = -1;
24588
+ const signatureOccurrences = /* @__PURE__ */ new Map();
24440
24589
  return list.map((message, index) => {
24441
24590
  const role = message?.role || "assistant";
24442
24591
  const kind = message?.kind || "standard";
24443
24592
  const content = typeof message?.content === "string" ? message.content : "";
24444
24593
  if (role === "user" || turnIndex < 0) turnIndex += 1;
24445
- const seed = [role, kind, "", index, content].join("\n");
24446
- const providerUnitKey = `v2-pty:${role}:${kind}:${index}:${stableHash(seed)}`;
24594
+ const seed = [role, kind, "", content].join("\n");
24595
+ const contentHash = stableHash(seed);
24596
+ const occurrence = signatureOccurrences.get(contentHash) ?? 0;
24597
+ signatureOccurrences.set(contentHash, occurrence + 1);
24598
+ const providerUnitKey = `v2-pty:${role}:${kind}:${contentHash}:#${occurrence}`;
24447
24599
  const bubbleId = `bubble:${providerUnitKey}`;
24448
24600
  const turnKey = `turn:${turnIndex}`;
24449
24601
  const isStreamingTail = status === "generating" && role === "assistant" && index === list.length - 1;
@@ -35405,7 +35557,7 @@ function shouldPreserveNativeIdentity(providerType, sessionId, message) {
35405
35557
  const providerUnitKey = typeof message.providerUnitKey === "string" ? message.providerUnitKey.trim() : "";
35406
35558
  const turnKey = typeof message._turnKey === "string" ? message._turnKey.trim() : "";
35407
35559
  if (!providerUnitKey) return false;
35408
- if (providerUnitKey.startsWith("v2:") || providerUnitKey.startsWith("v2-pty:")) {
35560
+ if (providerUnitKey.startsWith("v2:") || providerUnitKey.startsWith("v2-pty:") || providerUnitKey.startsWith("v3:")) {
35409
35561
  return true;
35410
35562
  }
35411
35563
  if (!turnKey) return false;
@@ -35450,30 +35602,48 @@ function normalizeAndFilterNativeHistory(h, providerType, args, messages, native
35450
35602
  }
35451
35603
  function normalizeNativeHistoryMessages(providerType, messages, nativeSessionId) {
35452
35604
  let turnIndex = 0;
35605
+ const signatureOccurrences = /* @__PURE__ */ new Map();
35606
+ let lastSequenceAnchor = 0;
35607
+ let anchorOffset = 0;
35453
35608
  return normalizeChatMessages(messages).map((message, index) => {
35454
35609
  const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
35455
35610
  const kind = typeof message.kind === "string" && message.kind.trim() ? message.kind.trim() : role === "system" ? "system" : "standard";
35456
35611
  if ((role === "user" || role === "human") && index > 0) turnIndex += 1;
35457
35612
  const historySessionId = typeof message.historySessionId === "string" ? message.historySessionId.trim() : "";
35458
- const contentHash = hashSignatureParts([
35613
+ const contentSignature = hashSignatureParts([
35459
35614
  providerType,
35460
35615
  historySessionId,
35461
- String(message.receivedAt || message.timestamp || index),
35616
+ String(message.receivedAt || message.timestamp || ""),
35462
35617
  role,
35463
35618
  kind,
35464
35619
  flattenContent(message.content)
35465
- ]).slice(0, 12);
35620
+ ]);
35621
+ const contentHash = contentSignature.slice(0, 12);
35466
35622
  const nativeIdentitySessionId = historySessionId || (typeof nativeSessionId === "string" ? nativeSessionId.trim() : "");
35623
+ const nativeMessageId = typeof message.id === "string" && message.id.trim() ? message.id.trim() : "";
35624
+ const occurrence = signatureOccurrences.get(contentSignature) ?? 0;
35625
+ signatureOccurrences.set(contentSignature, occurrence + 1);
35626
+ const collisionDiscriminator = nativeMessageId || `#${occurrence}`;
35467
35627
  const preserveNativeIdentity = shouldPreserveNativeIdentity(providerType, nativeIdentitySessionId, message);
35468
35628
  const existingProviderUnitKey = typeof message.providerUnitKey === "string" ? message.providerUnitKey.trim() : "";
35469
35629
  const existingTurnKey = typeof message._turnKey === "string" ? message._turnKey.trim() : "";
35470
- const providerUnitKey = preserveNativeIdentity ? existingProviderUnitKey : `${providerType}:native:${nativeIdentitySessionId || "workspace"}:${index}:${role || "message"}:${kind}:${contentHash}`;
35630
+ const providerUnitKey = preserveNativeIdentity ? existingProviderUnitKey : `v3:${providerType}:native:${nativeIdentitySessionId || "workspace"}:${role || "message"}:${kind}:${contentHash}:${collisionDiscriminator}`;
35471
35631
  const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
35472
35632
  const isSystemSessionStart = role === "system" || kind === "system" || kind === "session_start";
35473
35633
  const isActivity = role === "assistant" && (kind === "tool" || kind === "terminal" || kind === "thought");
35474
35634
  const existingSequence = typeof message.sequence === "number" && Number.isFinite(message.sequence) ? message.sequence : null;
35475
35635
  const tsCandidate = Number(message.receivedAt || message.timestamp || 0);
35476
- const sequence = existingSequence !== null ? existingSequence : tsCandidate > 0 ? tsCandidate : index;
35636
+ let sequence;
35637
+ if (existingSequence !== null) {
35638
+ sequence = existingSequence;
35639
+ } else if (tsCandidate > 0) {
35640
+ sequence = tsCandidate;
35641
+ lastSequenceAnchor = tsCandidate;
35642
+ anchorOffset = 0;
35643
+ } else {
35644
+ anchorOffset += 1;
35645
+ sequence = lastSequenceAnchor + anchorOffset;
35646
+ }
35477
35647
  return {
35478
35648
  ...message,
35479
35649
  role: role === "human" ? "user" : role || "assistant",