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

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.
@@ -3,6 +3,7 @@
3
3
  * native-history / source-resolution / normalization helpers they use.
4
4
  */
5
5
  import type { CommandResult, CommandHelpers } from './handler.js';
6
+ import type { ChatMessage } from '../types.js';
6
7
  /**
7
8
  * Test-only: clear the in-memory read-pin map and re-arm cold-start hydration so
8
9
  * each test starts from a clean pin state. The on-disk mirror is isolated per
@@ -19,5 +20,6 @@ export declare function __resetProviderSessionPinsForTest(): void;
19
20
  * non-owner-confirmed read did NOT. Not part of the runtime contract.
20
21
  */
21
22
  export declare function __getProviderSessionPinForTest(meshSessionId: string): string | undefined;
23
+ export declare function normalizeNativeHistoryMessages(providerType: string, messages: ChatMessage[], nativeSessionId?: string): ChatMessage[];
22
24
  export declare function handleChatHistory(h: CommandHelpers, args: any): Promise<CommandResult>;
23
25
  export declare function handleReadChat(h: CommandHelpers, args: any): Promise<CommandResult>;
package/dist/index.js CHANGED
@@ -73,7 +73,9 @@ function normalizeAutoFastForwardPolicy(value) {
73
73
  return {
74
74
  enabled: record.enabled !== false,
75
75
  ...Number.isFinite(maxBehind) && maxBehind >= 0 ? { maxBehind: Math.floor(maxBehind) } : {},
76
- requireCleanSubmodules: record.requireCleanSubmodules !== false
76
+ requireCleanSubmodules: record.requireCleanSubmodules !== false,
77
+ ...record.remoteNodes === true ? { remoteNodes: true } : {},
78
+ ...record.mode === "continuous" ? { mode: "continuous" } : {}
77
79
  };
78
80
  }
79
81
  function mergeAndNormalizePolicy(base, patch) {
@@ -417,10 +419,10 @@ function readInjected(value) {
417
419
  }
418
420
  function getDaemonBuildInfo() {
419
421
  if (cached) return cached;
420
- const commit = readInjected(true ? "ba90523a7fd7277668cc67ab7c596402c3d77959" : void 0) ?? "unknown";
421
- const commitShort = readInjected(true ? "ba90523a" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
422
- const version = readInjected(true ? "0.9.82-rc.521" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
423
- const builtAt = readInjected(true ? "2026-07-14T01:41:02.959Z" : void 0);
422
+ const commit = readInjected(true ? "d3a44d29416fef77ac6cd36f4798637571260dfb" : void 0) ?? "unknown";
423
+ const commitShort = readInjected(true ? "d3a44d29" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
424
+ const version = readInjected(true ? "0.9.82-rc.522" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
425
+ const builtAt = readInjected(true ? "2026-07-14T03:03:55.067Z" : void 0);
424
426
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
425
427
  return cached;
426
428
  }
@@ -15826,8 +15828,25 @@ var init_model_provider_compat = __esm({
15826
15828
  function localCoordinatorDaemonId() {
15827
15829
  return canonicalDaemonId(readNonEmptyString2(loadConfig().machineId));
15828
15830
  }
15831
+ function acquireAutoFastForwardLease(workspace) {
15832
+ const key2 = normalizeMeshWorkspaceForCompare(workspace);
15833
+ if (!key2) return false;
15834
+ if (autoFastForwardWorkspaceLease.has(key2)) return false;
15835
+ autoFastForwardWorkspaceLease.add(key2);
15836
+ return true;
15837
+ }
15838
+ function releaseAutoFastForwardLease(workspace) {
15839
+ const key2 = normalizeMeshWorkspaceForCompare(workspace);
15840
+ if (key2) autoFastForwardWorkspaceLease.delete(key2);
15841
+ }
15842
+ function isWorkspaceAutoFastForwardInFlight(workspace) {
15843
+ const key2 = normalizeMeshWorkspaceForCompare(workspace || "");
15844
+ return !!key2 && autoFastForwardWorkspaceLease.has(key2);
15845
+ }
15829
15846
  function __resetIdleAutoFastForwardForTests() {
15830
15847
  idleAutoFastForwardLastAttempt.clear();
15848
+ continuousAutoFastForwardLastScan.clear();
15849
+ autoFastForwardWorkspaceLease.clear();
15831
15850
  }
15832
15851
  function getMeshWithCache(components, meshId) {
15833
15852
  const localMesh = getMesh(meshId);
@@ -15960,6 +15979,10 @@ function deliverTaskToSession(dispatchThunk, ctx, warmup) {
15960
15979
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
15961
15980
  const mesh = getMeshWithCache(components, meshId);
15962
15981
  const node = mesh?.nodes.find((n) => meshNodeIdMatches(n, nodeId));
15982
+ if (isWorkspaceAutoFastForwardInFlight(readNonEmptyString2(node?.workspace))) {
15983
+ 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`);
15984
+ return false;
15985
+ }
15963
15986
  const inlineBootstrapNode = (() => {
15964
15987
  try {
15965
15988
  const inlineMesh = components.router?.getCachedInlineMesh?.(meshId);
@@ -16285,7 +16308,12 @@ function resolveAutoFastForwardPolicy(mesh) {
16285
16308
  return {
16286
16309
  enabled: record.enabled !== false,
16287
16310
  ...Number.isFinite(maxBehind) && maxBehind >= 0 ? { maxBehind: Math.floor(maxBehind) } : {},
16288
- requireCleanSubmodules: record.requireCleanSubmodules !== false
16311
+ requireCleanSubmodules: record.requireCleanSubmodules !== false,
16312
+ // Strict opt-in: absent/false → self-only (historical behavior). Only an
16313
+ // explicit `true` extends auto ff to remote owning-daemon nodes.
16314
+ remoteNodes: record.remoteNodes === true,
16315
+ // Absent/anything-but-continuous → 'idle' (historical idle-edge-only detection).
16316
+ mode: record.mode === "continuous" ? "continuous" : "idle"
16289
16317
  };
16290
16318
  }
16291
16319
  function sessionStateLooksActive(state) {
@@ -17035,51 +17063,157 @@ async function triggerMeshQueue(components, meshId) {
17035
17063
  ...pendingAfter > 0 && newlyAssignedTasks.length === 0 && localIdleSessionsChecked === 0 && remoteIdleSessionsChecked === 0 && !autoLaunchPending ? { noIdleMeshSessionAvailable: true } : {}
17036
17064
  };
17037
17065
  }
17038
- async function maybeAutoFastForwardIdleNode(components, args) {
17066
+ function dryRunSatisfiesAutoFastForwardPolicy(dryRun, policy) {
17067
+ if (!dryRun || dryRun.code !== "fast_forward_available" || dryRun.allowed !== true) return false;
17068
+ const behind = Number(dryRun.current?.behind);
17069
+ if (!Number.isFinite(behind) || behind <= 0) return false;
17070
+ if (policy.maxBehind !== void 0 && behind > policy.maxBehind) return false;
17071
+ if (policy.requireCleanSubmodules) {
17072
+ const submodules = Array.isArray(dryRun.current?.submodules) ? dryRun.current.submodules : [];
17073
+ if (submodules.some((submodule) => submodule?.dirty || submodule?.outOfSync || submodule?.error)) return false;
17074
+ }
17075
+ return true;
17076
+ }
17077
+ function readNodeSubmoduleIgnorePaths(node) {
17078
+ return Array.isArray(node?.policy?.submoduleIgnorePaths) ? node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
17079
+ }
17080
+ function nodeIsAutoFastForwardEligible(components, meshId, nodeId, node, currentSessionId) {
17081
+ if (!node) return false;
17082
+ if (node.status === "disabled" || node.status === "removed") return false;
17083
+ if (node.readOnly === true || node.policy?.readOnly === true) return false;
17084
+ if (isWorktreeBootstrapStaleRunning(node)) return false;
17085
+ if (node.worktreeBootstrap?.status === "running") return false;
17086
+ if (nodeHasActiveMeshWork(components, meshId, nodeId, currentSessionId)) return false;
17087
+ return true;
17088
+ }
17089
+ function remoteNodeIsConnected(components, node) {
17090
+ const daemonId = readMeshNodeDaemonId(node ?? {});
17091
+ if (!daemonId) return false;
17092
+ const getPeerStatus = components.getMeshPeerConnectionStatus;
17093
+ if (getPeerStatus) {
17094
+ const snapshot = getPeerStatus(daemonId);
17095
+ return !!snapshot && String(snapshot.state) === "connected";
17096
+ }
17097
+ return readNonEmptyString2(node?.connection?.state).toLowerCase() === "connected";
17098
+ }
17099
+ async function delegateRemoteAutoFastForward(components, args) {
17100
+ const dispatchMeshCommand = components.dispatchMeshCommand;
17101
+ if (!dispatchMeshCommand) return;
17102
+ if (!acquireAutoFastForwardLease(args.workspace)) return;
17103
+ const submoduleIgnorePaths = readNodeSubmoduleIgnorePaths(args.node);
17039
17104
  const mesh = getMeshWithCache(components, args.meshId);
17040
- const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
17041
- const workspace = readNonEmptyString2(node?.workspace);
17042
- if (!workspace) return;
17043
- if (!(0, import_fs13.existsSync)(workspace)) return;
17044
- const policy = resolveAutoFastForwardPolicy(mesh);
17045
- if (!policy.enabled) return;
17046
- if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
17047
- const throttleKey = `${args.meshId}:${args.nodeId}`;
17048
- const now = Date.now();
17049
- const lastAttempt = idleAutoFastForwardLastAttempt.get(throttleKey) || 0;
17050
- if (now - lastAttempt < IDLE_AUTO_FAST_FORWARD_THROTTLE_MS) return;
17051
- idleAutoFastForwardLastAttempt.set(throttleKey, now);
17052
- const submoduleIgnorePaths = Array.isArray(node?.policy?.submoduleIgnorePaths) ? node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
17105
+ const baseArgs = {
17106
+ meshId: args.meshId,
17107
+ nodeId: args.nodeId,
17108
+ workspace: args.workspace,
17109
+ inlineMesh: mesh,
17110
+ ...submoduleIgnorePaths ? { submoduleIgnorePaths } : {},
17111
+ trigger: args.trigger,
17112
+ // Preserve the pre-fix self-only semantics for submodules: the local idle path
17113
+ // never updated submodules (updateSubmodules:false), so the remote path matches.
17114
+ updateSubmodules: false
17115
+ };
17116
+ try {
17117
+ const remoteDry = await dispatchMeshCommand(args.daemonId, "fast_forward_mesh_node", {
17118
+ ...baseArgs,
17119
+ execute: false,
17120
+ dryRun: true
17121
+ });
17122
+ if (!dryRunSatisfiesAutoFastForwardPolicy(remoteDry, args.policy)) return;
17123
+ if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId)) return;
17124
+ const executed = await dispatchMeshCommand(args.daemonId, "fast_forward_mesh_node", {
17125
+ ...baseArgs,
17126
+ execute: true,
17127
+ dryRun: false
17128
+ });
17129
+ if (executed?.executed === true) {
17130
+ LOG.info("MeshFastForward", `Remote auto fast-forward executed for node ${args.nodeId} (daemon ${String(args.daemonId).slice(0, 12)}, trigger ${args.trigger})`);
17131
+ }
17132
+ } catch (e) {
17133
+ LOG.warn("MeshFastForward", `Remote auto fast-forward delegation failed for ${args.nodeId}: ${e?.message || e}`);
17134
+ } finally {
17135
+ releaseAutoFastForwardLease(args.workspace);
17136
+ }
17137
+ }
17138
+ async function executeLocalAutoFastForward(args) {
17139
+ if (!acquireAutoFastForwardLease(args.workspace)) return;
17140
+ const submoduleIgnorePaths = readNodeSubmoduleIgnorePaths(args.node);
17053
17141
  try {
17054
17142
  const dryRun = await fastForwardMeshNode({
17055
17143
  meshId: args.meshId,
17056
17144
  nodeId: args.nodeId,
17057
- workspace,
17145
+ workspace: args.workspace,
17058
17146
  execute: false,
17059
17147
  dryRun: true,
17060
17148
  updateSubmodules: false,
17061
17149
  submoduleIgnorePaths,
17062
- trigger: "idle_auto"
17150
+ trigger: args.trigger
17063
17151
  });
17064
- if (!dryRun || dryRun.code !== "fast_forward_available" || dryRun.allowed !== true) return;
17065
- const behind = Number(dryRun.current?.behind);
17066
- if (policy.maxBehind !== void 0 && Number.isFinite(behind) && behind > policy.maxBehind) return;
17067
- if (policy.requireCleanSubmodules) {
17068
- const submodules = Array.isArray(dryRun.current?.submodules) ? dryRun.current.submodules : [];
17069
- if (submodules.some((submodule) => submodule?.dirty || submodule?.outOfSync || submodule?.error)) return;
17070
- }
17152
+ if (!dryRunSatisfiesAutoFastForwardPolicy(dryRun, args.policy)) return;
17071
17153
  await fastForwardMeshNode({
17072
17154
  meshId: args.meshId,
17073
17155
  nodeId: args.nodeId,
17074
- workspace,
17156
+ workspace: args.workspace,
17075
17157
  execute: true,
17076
17158
  dryRun: false,
17077
17159
  updateSubmodules: false,
17078
17160
  submoduleIgnorePaths,
17079
- trigger: "idle_auto"
17161
+ trigger: args.trigger
17080
17162
  });
17081
17163
  } catch (e) {
17082
17164
  LOG.warn("MeshFastForward", `Idle auto fast-forward check failed for ${args.nodeId}: ${e?.message || e}`);
17165
+ } finally {
17166
+ releaseAutoFastForwardLease(args.workspace);
17167
+ }
17168
+ }
17169
+ async function maybeAutoFastForwardIdleNode(components, args) {
17170
+ const mesh = getMeshWithCache(components, args.meshId);
17171
+ const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
17172
+ const workspace = readNonEmptyString2(node?.workspace);
17173
+ if (!workspace) return;
17174
+ const policy = resolveAutoFastForwardPolicy(mesh);
17175
+ if (!policy.enabled) return;
17176
+ if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
17177
+ const throttleKey = `${args.meshId}:${args.nodeId}`;
17178
+ const now = Date.now();
17179
+ const lastAttempt = idleAutoFastForwardLastAttempt.get(throttleKey) || 0;
17180
+ if (now - lastAttempt < IDLE_AUTO_FAST_FORWARD_THROTTLE_MS) return;
17181
+ idleAutoFastForwardLastAttempt.set(throttleKey, now);
17182
+ if (isLocalAutoLaunchNode(node)) {
17183
+ if (!(0, import_fs13.existsSync)(workspace)) return;
17184
+ await executeLocalAutoFastForward({ meshId: args.meshId, nodeId: args.nodeId, node, workspace, policy, trigger: "idle_auto" });
17185
+ return;
17186
+ }
17187
+ if (!policy.remoteNodes) return;
17188
+ const daemonId = readMeshNodeDaemonId(node ?? {});
17189
+ if (!daemonId || !components.dispatchMeshCommand) return;
17190
+ if (!remoteNodeIsConnected(components, node)) return;
17191
+ await delegateRemoteAutoFastForward(components, { meshId: args.meshId, nodeId: args.nodeId, node, daemonId, workspace, policy, trigger: "idle_auto" });
17192
+ }
17193
+ async function runContinuousAutoFastForwardScan(components, mesh) {
17194
+ if (!components.dispatchMeshCommand) return;
17195
+ const policy = resolveAutoFastForwardPolicy(mesh);
17196
+ if (!policy.enabled || !policy.remoteNodes || policy.mode !== "continuous") return;
17197
+ const meshId = readNonEmptyString2(mesh?.id);
17198
+ if (!meshId) return;
17199
+ const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
17200
+ const now = Date.now();
17201
+ for (const node of nodes) {
17202
+ const nodeId = normalizeMeshNodeId(node);
17203
+ if (!nodeId) continue;
17204
+ if (node?.isLocalWorktree === true) continue;
17205
+ if (isLocalAutoLaunchNode(node)) continue;
17206
+ const workspace = readNonEmptyString2(node?.workspace);
17207
+ if (!workspace) continue;
17208
+ const daemonId = readMeshNodeDaemonId(node ?? {});
17209
+ if (!daemonId) continue;
17210
+ if (!nodeIsAutoFastForwardEligible(components, meshId, nodeId, node)) continue;
17211
+ if (!remoteNodeIsConnected(components, node)) continue;
17212
+ const cooldownKey = `${meshId}:${nodeId}`;
17213
+ const lastScan = continuousAutoFastForwardLastScan.get(cooldownKey) || 0;
17214
+ if (now - lastScan < CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS) continue;
17215
+ continuousAutoFastForwardLastScan.set(cooldownKey, now);
17216
+ await delegateRemoteAutoFastForward(components, { meshId, nodeId, node, daemonId, workspace, policy, trigger: "reconcile_auto" });
17083
17217
  }
17084
17218
  }
17085
17219
  function runIdleMaintenanceThenAssignQueue(components, args) {
@@ -17093,7 +17227,7 @@ function runIdleMaintenanceThenAssignQueue(components, args) {
17093
17227
  });
17094
17228
  });
17095
17229
  }
17096
- var import_fs13, 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;
17230
+ var import_fs13, 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;
17097
17231
  var init_mesh_queue_assignment = __esm({
17098
17232
  "src/mesh/mesh-queue-assignment.ts"() {
17099
17233
  "use strict";
@@ -17123,6 +17257,9 @@ var init_mesh_queue_assignment = __esm({
17123
17257
  init_model_provider_compat();
17124
17258
  IDLE_AUTO_FAST_FORWARD_THROTTLE_MS = 30 * 60 * 1e3;
17125
17259
  idleAutoFastForwardLastAttempt = /* @__PURE__ */ new Map();
17260
+ CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS = 45 * 1e3;
17261
+ continuousAutoFastForwardLastScan = /* @__PURE__ */ new Map();
17262
+ autoFastForwardWorkspaceLease = /* @__PURE__ */ new Set();
17126
17263
  BOOTSTRAP_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["complete", "failed"]);
17127
17264
  DISPATCH_CONFIRM_TIMEOUT_MS = 12e4;
17128
17265
  DISPATCH_CONNECT_TIMEOUT_MS = MESH_CONNECT_TIMEOUT_MS;
@@ -22075,6 +22212,17 @@ async function runMeshReconcileTick(components) {
22075
22212
  }
22076
22213
  }
22077
22214
  }
22215
+ if (dispatchMeshCommand) {
22216
+ for (const mesh of listMeshes()) {
22217
+ const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
22218
+ if (!daemonHostsMesh(mesh, selfIds)) continue;
22219
+ try {
22220
+ await runContinuousAutoFastForwardScan(components, mesh);
22221
+ } catch (e) {
22222
+ LOG.warn("MeshReconcile", `Continuous auto fast-forward scan failed for mesh ${mesh.id}: ${e?.message || e}`);
22223
+ }
22224
+ }
22225
+ }
22078
22226
  for (const mesh of listMeshes()) {
22079
22227
  const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
22080
22228
  if (!daemonHostsMesh(mesh, selfIds)) continue;
@@ -24435,13 +24583,17 @@ function stableHash(value) {
24435
24583
  function normalizeMessageIdentity(messages, status) {
24436
24584
  const list = Array.isArray(messages) ? messages : [];
24437
24585
  let turnIndex = -1;
24586
+ const signatureOccurrences = /* @__PURE__ */ new Map();
24438
24587
  return list.map((message, index) => {
24439
24588
  const role = message?.role || "assistant";
24440
24589
  const kind = message?.kind || "standard";
24441
24590
  const content = typeof message?.content === "string" ? message.content : "";
24442
24591
  if (role === "user" || turnIndex < 0) turnIndex += 1;
24443
- const seed = [role, kind, "", index, content].join("\n");
24444
- const providerUnitKey = `v2-pty:${role}:${kind}:${index}:${stableHash(seed)}`;
24592
+ const seed = [role, kind, "", content].join("\n");
24593
+ const contentHash = stableHash(seed);
24594
+ const occurrence = signatureOccurrences.get(contentHash) ?? 0;
24595
+ signatureOccurrences.set(contentHash, occurrence + 1);
24596
+ const providerUnitKey = `v2-pty:${role}:${kind}:${contentHash}:#${occurrence}`;
24445
24597
  const bubbleId = `bubble:${providerUnitKey}`;
24446
24598
  const turnKey = `turn:${turnIndex}`;
24447
24599
  const isStreamingTail = status === "generating" && role === "assistant" && index === list.length - 1;
@@ -35833,7 +35985,7 @@ function shouldPreserveNativeIdentity(providerType, sessionId, message) {
35833
35985
  const providerUnitKey = typeof message.providerUnitKey === "string" ? message.providerUnitKey.trim() : "";
35834
35986
  const turnKey = typeof message._turnKey === "string" ? message._turnKey.trim() : "";
35835
35987
  if (!providerUnitKey) return false;
35836
- if (providerUnitKey.startsWith("v2:") || providerUnitKey.startsWith("v2-pty:")) {
35988
+ if (providerUnitKey.startsWith("v2:") || providerUnitKey.startsWith("v2-pty:") || providerUnitKey.startsWith("v3:")) {
35837
35989
  return true;
35838
35990
  }
35839
35991
  if (!turnKey) return false;
@@ -35878,30 +36030,48 @@ function normalizeAndFilterNativeHistory(h, providerType, args, messages, native
35878
36030
  }
35879
36031
  function normalizeNativeHistoryMessages(providerType, messages, nativeSessionId) {
35880
36032
  let turnIndex = 0;
36033
+ const signatureOccurrences = /* @__PURE__ */ new Map();
36034
+ let lastSequenceAnchor = 0;
36035
+ let anchorOffset = 0;
35881
36036
  return normalizeChatMessages(messages).map((message, index) => {
35882
36037
  const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
35883
36038
  const kind = typeof message.kind === "string" && message.kind.trim() ? message.kind.trim() : role === "system" ? "system" : "standard";
35884
36039
  if ((role === "user" || role === "human") && index > 0) turnIndex += 1;
35885
36040
  const historySessionId = typeof message.historySessionId === "string" ? message.historySessionId.trim() : "";
35886
- const contentHash = hashSignatureParts([
36041
+ const contentSignature = hashSignatureParts([
35887
36042
  providerType,
35888
36043
  historySessionId,
35889
- String(message.receivedAt || message.timestamp || index),
36044
+ String(message.receivedAt || message.timestamp || ""),
35890
36045
  role,
35891
36046
  kind,
35892
36047
  flattenContent(message.content)
35893
- ]).slice(0, 12);
36048
+ ]);
36049
+ const contentHash = contentSignature.slice(0, 12);
35894
36050
  const nativeIdentitySessionId = historySessionId || (typeof nativeSessionId === "string" ? nativeSessionId.trim() : "");
36051
+ const nativeMessageId = typeof message.id === "string" && message.id.trim() ? message.id.trim() : "";
36052
+ const occurrence = signatureOccurrences.get(contentSignature) ?? 0;
36053
+ signatureOccurrences.set(contentSignature, occurrence + 1);
36054
+ const collisionDiscriminator = nativeMessageId || `#${occurrence}`;
35895
36055
  const preserveNativeIdentity = shouldPreserveNativeIdentity(providerType, nativeIdentitySessionId, message);
35896
36056
  const existingProviderUnitKey = typeof message.providerUnitKey === "string" ? message.providerUnitKey.trim() : "";
35897
36057
  const existingTurnKey = typeof message._turnKey === "string" ? message._turnKey.trim() : "";
35898
- const providerUnitKey = preserveNativeIdentity ? existingProviderUnitKey : `${providerType}:native:${nativeIdentitySessionId || "workspace"}:${index}:${role || "message"}:${kind}:${contentHash}`;
36058
+ const providerUnitKey = preserveNativeIdentity ? existingProviderUnitKey : `v3:${providerType}:native:${nativeIdentitySessionId || "workspace"}:${role || "message"}:${kind}:${contentHash}:${collisionDiscriminator}`;
35899
36059
  const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
35900
36060
  const isSystemSessionStart = role === "system" || kind === "system" || kind === "session_start";
35901
36061
  const isActivity = role === "assistant" && (kind === "tool" || kind === "terminal" || kind === "thought");
35902
36062
  const existingSequence = typeof message.sequence === "number" && Number.isFinite(message.sequence) ? message.sequence : null;
35903
36063
  const tsCandidate = Number(message.receivedAt || message.timestamp || 0);
35904
- const sequence = existingSequence !== null ? existingSequence : tsCandidate > 0 ? tsCandidate : index;
36064
+ let sequence;
36065
+ if (existingSequence !== null) {
36066
+ sequence = existingSequence;
36067
+ } else if (tsCandidate > 0) {
36068
+ sequence = tsCandidate;
36069
+ lastSequenceAnchor = tsCandidate;
36070
+ anchorOffset = 0;
36071
+ } else {
36072
+ anchorOffset += 1;
36073
+ sequence = lastSequenceAnchor + anchorOffset;
36074
+ }
35905
36075
  return {
35906
36076
  ...message,
35907
36077
  role: role === "human" ? "user" : role || "assistant",