@jingyi0605/codingns 0.2.5 → 0.3.0

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 (109) hide show
  1. package/bin/codingns.mjs +278 -2
  2. package/dist/public/assets/{TerminalPage-BkjqU9NG.js → TerminalPage-Dfw1QUqW.js} +1 -1
  3. package/dist/public/assets/index-DR2rPNi7.css +1 -0
  4. package/dist/public/assets/index-DTOruahn.js +114 -0
  5. package/dist/public/index.html +2 -2
  6. package/dist/server/config/env.d.ts +2 -0
  7. package/dist/server/config/env.js +32 -3
  8. package/dist/server/config/env.js.map +1 -1
  9. package/dist/server/modules/butler/butler-control-session-service.d.ts +3 -1
  10. package/dist/server/modules/butler/butler-control-session-service.js +28 -4
  11. package/dist/server/modules/butler/butler-control-session-service.js.map +1 -1
  12. package/dist/server/modules/butler/butler-session-service.d.ts +1 -0
  13. package/dist/server/modules/butler/butler-session-service.js +72 -15
  14. package/dist/server/modules/butler/butler-session-service.js.map +1 -1
  15. package/dist/server/modules/debug-target/debug-target-service.d.ts +5 -2
  16. package/dist/server/modules/debug-target/debug-target-service.js +170 -10
  17. package/dist/server/modules/debug-target/debug-target-service.js.map +1 -1
  18. package/dist/server/modules/file/file-constants.d.ts +1 -0
  19. package/dist/server/modules/file/file-constants.js +1 -0
  20. package/dist/server/modules/file/file-constants.js.map +1 -1
  21. package/dist/server/modules/file/file-controller.js +12 -3
  22. package/dist/server/modules/file/file-controller.js.map +1 -1
  23. package/dist/server/modules/file/file-preview-link-service.js +6 -37
  24. package/dist/server/modules/file/file-preview-link-service.js.map +1 -1
  25. package/dist/server/modules/file/file-preview-service.d.ts +6 -12
  26. package/dist/server/modules/file/file-preview-service.js +114 -28
  27. package/dist/server/modules/file/file-preview-service.js.map +1 -1
  28. package/dist/server/modules/file/file-preview-types.d.ts +37 -0
  29. package/dist/server/modules/file/file-preview-types.js +84 -0
  30. package/dist/server/modules/file/file-preview-types.js.map +1 -0
  31. package/dist/server/modules/git/git-controller.d.ts +6 -0
  32. package/dist/server/modules/git/git-controller.js +13 -0
  33. package/dist/server/modules/git/git-controller.js.map +1 -1
  34. package/dist/server/modules/git/git-read-service.d.ts +2 -1
  35. package/dist/server/modules/git/git-read-service.js +100 -0
  36. package/dist/server/modules/git/git-read-service.js.map +1 -1
  37. package/dist/server/modules/git/types.d.ts +23 -0
  38. package/dist/server/modules/sessions/session-activity-authority-service.js +13 -1
  39. package/dist/server/modules/sessions/session-activity-authority-service.js.map +1 -1
  40. package/dist/server/modules/sessions/session-activity-inspector.js +21 -5
  41. package/dist/server/modules/sessions/session-activity-inspector.js.map +1 -1
  42. package/dist/server/modules/sessions/session-history-service.d.ts +8 -2
  43. package/dist/server/modules/sessions/session-history-service.js +117 -42
  44. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  45. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +2 -1
  46. package/dist/server/modules/sessions/session-live-runtime-service.js +12 -0
  47. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  48. package/dist/server/modules/skills/skill-controller.d.ts +23 -0
  49. package/dist/server/modules/skills/skill-controller.js +35 -0
  50. package/dist/server/modules/skills/skill-controller.js.map +1 -0
  51. package/dist/server/modules/skills/skill-manager-service.d.ts +86 -0
  52. package/dist/server/modules/skills/skill-manager-service.js +557 -0
  53. package/dist/server/modules/skills/skill-manager-service.js.map +1 -0
  54. package/dist/server/modules/skills/skill-reconciler.d.ts +21 -0
  55. package/dist/server/modules/skills/skill-reconciler.js +99 -0
  56. package/dist/server/modules/skills/skill-reconciler.js.map +1 -0
  57. package/dist/server/modules/skills/skill-sync-planner.d.ts +8 -0
  58. package/dist/server/modules/skills/skill-sync-planner.js +20 -0
  59. package/dist/server/modules/skills/skill-sync-planner.js.map +1 -0
  60. package/dist/server/modules/skills/skill-target-adapter.d.ts +34 -0
  61. package/dist/server/modules/skills/skill-target-adapter.js +65 -0
  62. package/dist/server/modules/skills/skill-target-adapter.js.map +1 -0
  63. package/dist/server/modules/tailscale/tailscale-controller.d.ts +15 -0
  64. package/dist/server/modules/tailscale/tailscale-controller.js +33 -0
  65. package/dist/server/modules/tailscale/tailscale-controller.js.map +1 -0
  66. package/dist/server/modules/tailscale/tailscale-helper-client.d.ts +41 -0
  67. package/dist/server/modules/tailscale/tailscale-helper-client.js +135 -0
  68. package/dist/server/modules/tailscale/tailscale-helper-client.js.map +1 -0
  69. package/dist/server/modules/tailscale/tailscale-helper-process.d.ts +1 -0
  70. package/dist/server/modules/tailscale/tailscale-helper-process.js +327 -0
  71. package/dist/server/modules/tailscale/tailscale-helper-process.js.map +1 -0
  72. package/dist/server/modules/tailscale/tailscale-manager.d.ts +41 -0
  73. package/dist/server/modules/tailscale/tailscale-manager.js +259 -0
  74. package/dist/server/modules/tailscale/tailscale-manager.js.map +1 -0
  75. package/dist/server/modules/tailscale/tailscale-service.d.ts +43 -0
  76. package/dist/server/modules/tailscale/tailscale-service.js +201 -0
  77. package/dist/server/modules/tailscale/tailscale-service.js.map +1 -0
  78. package/dist/server/routes/git.js +1 -0
  79. package/dist/server/routes/git.js.map +1 -1
  80. package/dist/server/routes/skills.d.ts +3 -0
  81. package/dist/server/routes/skills.js +7 -0
  82. package/dist/server/routes/skills.js.map +1 -0
  83. package/dist/server/routes/system.d.ts +3 -0
  84. package/dist/server/routes/system.js +9 -0
  85. package/dist/server/routes/system.js.map +1 -0
  86. package/dist/server/server/create-server.d.ts +12 -0
  87. package/dist/server/server/create-server.js +42 -3
  88. package/dist/server/server/create-server.js.map +1 -1
  89. package/dist/server/shared/utils/command-availability.d.ts +1 -0
  90. package/dist/server/shared/utils/command-availability.js +26 -3
  91. package/dist/server/shared/utils/command-availability.js.map +1 -1
  92. package/dist/server/storage/repositories/instance-tailscale-repository.d.ts +10 -0
  93. package/dist/server/storage/repositories/instance-tailscale-repository.js +112 -0
  94. package/dist/server/storage/repositories/instance-tailscale-repository.js.map +1 -0
  95. package/dist/server/storage/repositories/managed-skill-repository.d.ts +11 -0
  96. package/dist/server/storage/repositories/managed-skill-repository.js +102 -0
  97. package/dist/server/storage/repositories/managed-skill-repository.js.map +1 -0
  98. package/dist/server/storage/repositories/skill-target-binding-repository.d.ts +10 -0
  99. package/dist/server/storage/repositories/skill-target-binding-repository.js +77 -0
  100. package/dist/server/storage/repositories/skill-target-binding-repository.js.map +1 -0
  101. package/dist/server/storage/sqlite/client.js +10 -0
  102. package/dist/server/storage/sqlite/client.js.map +1 -1
  103. package/dist/server/storage/sqlite/schema.sql +65 -0
  104. package/dist/server/types/domain.d.ts +72 -0
  105. package/dist/server/ws/ws-server.js +4 -4
  106. package/dist/server/ws/ws-server.js.map +1 -1
  107. package/package.json +1 -1
  108. package/dist/public/assets/index-C6U8-9jg.css +0 -1
  109. package/dist/public/assets/index-CKSumuV2.js +0 -109
@@ -58,6 +58,7 @@ export class SessionHistoryService {
58
58
  workspaceDiscoveryStatuses = new Map();
59
59
  workspaceStateRefreshInflight = new Map();
60
60
  providerCapabilityCache = new Map();
61
+ liveActivityObservationResolvers = new Set();
61
62
  workspaceSessionRelations = new Map();
62
63
  constructor(db, workspaceRepository, sessionBindingRepository, sessionChangedFileService, sessionIndexRepository, sessionMessageAttachmentService, sessionStateRepository, sessionStatusSnapshotRepository, config, sessionActivityAuthorityService = new SessionActivityAuthorityService(), sessionMessageOriginRepository = null, sessionForkRepository = null, adapterOverrides = {}, taskManager = createTaskManager()) {
63
64
  this.db = db;
@@ -130,6 +131,19 @@ export class SessionHistoryService {
130
131
  observeBackgroundTaskMetrics() {
131
132
  return this.taskManager.observe();
132
133
  }
134
+ registerLiveActivityObservationResolver(resolver) {
135
+ this.liveActivityObservationResolvers.add(resolver);
136
+ let closed = false;
137
+ return {
138
+ close: () => {
139
+ if (closed) {
140
+ return;
141
+ }
142
+ closed = true;
143
+ this.liveActivityObservationResolvers.delete(resolver);
144
+ }
145
+ };
146
+ }
133
147
  registerBackgroundTasks() {
134
148
  if (!this.taskManager.has(HOST_TASK_TYPES.workspaceDiscovery)) {
135
149
  this.taskManager.register({
@@ -1078,11 +1092,11 @@ export class SessionHistoryService {
1078
1092
  });
1079
1093
  const currentBinding = this.sessionBindingRepository.findBySessionId(sessionId);
1080
1094
  const timestamp = nowIso();
1081
- const duplicateBinding = this.findPendingBindingDuplicate(sessionId, workspaceId, currentBinding, resolvedSnapshot);
1095
+ const duplicateBinding = this.findSameWorkspaceBindingDuplicate(sessionId, workspaceId, resolvedSnapshot);
1082
1096
  this.db.transaction(() => {
1083
1097
  if (duplicateBinding) {
1084
- // 新建运行时会话会先写入 pending 绑定,后台发现链路可能在真 ID 回填前先落一条重复记录。
1085
- // 这里保留当前 runtime session,把扫描出的重复会话并回当前会话,避免 provider_session_id 撞唯一键。
1098
+ // 运行时链路显式指定了当前 sessionId,就应该由当前会话接管同工作区里的重复底层会话。
1099
+ // 否则后续事件重放或后台发现补录都会持续撞 UNIQUE(provider, provider_session_id)。
1086
1100
  this.mergeSessionIntoTarget({
1087
1101
  workspaceId,
1088
1102
  targetSessionId: sessionId,
@@ -1705,11 +1719,11 @@ export class SessionHistoryService {
1705
1719
  return this.sessionBindingRepository.findBySessionId(aliasTargetSessionId);
1706
1720
  }
1707
1721
  findPendingSessionAliasTargetSessionId(descriptor) {
1708
- if (!descriptor || descriptor.provider !== "gemini") {
1722
+ if (!descriptor) {
1709
1723
  return null;
1710
1724
  }
1711
- const aliasTargetSessionId = extractPendingBindingTargetSessionId(descriptor.providerSessionId)
1712
- ?? extractPendingBindingTargetSessionId(descriptor.rawStoreRef);
1725
+ const aliasTargetSessionId = extractSessionAliasTargetSessionId(descriptor.providerSessionId)
1726
+ ?? extractSessionAliasTargetSessionId(descriptor.rawStoreRef);
1713
1727
  if (!aliasTargetSessionId || aliasTargetSessionId === descriptor.sessionId) {
1714
1728
  return null;
1715
1729
  }
@@ -1794,10 +1808,7 @@ export class SessionHistoryService {
1794
1808
  });
1795
1809
  await runBatchedTransactions(staleHiddenSessions.map((session) => session.sessionId), WORKSPACE_DISCOVERY_PERSIST_BATCH_SIZE, deleteTransaction);
1796
1810
  }
1797
- findPendingBindingDuplicate(sessionId, workspaceId, currentBinding, snapshot) {
1798
- if (!currentBinding || !isPendingBindingValue(currentBinding.providerSessionId)) {
1799
- return null;
1800
- }
1811
+ findSameWorkspaceBindingDuplicate(sessionId, workspaceId, snapshot) {
1801
1812
  if (isPendingBindingValue(snapshot.providerSessionId)) {
1802
1813
  return null;
1803
1814
  }
@@ -1889,12 +1900,22 @@ export class SessionHistoryService {
1889
1900
  this.db
1890
1901
  .prepare("DELETE FROM session_forks WHERE session_id = ?")
1891
1902
  .run(input.sourceSessionId);
1892
- this.db
1893
- .prepare("DELETE FROM session_indices WHERE session_id = ?")
1894
- .run(input.sourceSessionId);
1895
- this.db
1896
- .prepare("DELETE FROM session_bindings WHERE session_id = ?")
1897
- .run(input.sourceSessionId);
1903
+ // 保留旧 session_id 作为 alias,避免前端或 Butler 还拿着旧 id 时直接炸成 SESSION_NOT_FOUND。
1904
+ this.sessionBindingRepository.upsert({
1905
+ sessionId: input.sourceSessionId,
1906
+ workspaceId: sourceBinding.workspaceId,
1907
+ provider: sourceBinding.provider,
1908
+ providerSessionId: buildAliasBindingValue(input.provider, input.targetSessionId, input.sourceSessionId),
1909
+ rawStoreRef: buildAliasBindingValue(input.provider, input.targetSessionId, input.sourceSessionId),
1910
+ createdAt: sourceBinding.createdAt,
1911
+ updatedAt: input.timestamp
1912
+ });
1913
+ if (sourceIndex) {
1914
+ this.sessionIndexRepository.upsert({
1915
+ ...sourceIndex,
1916
+ updatedAt: input.timestamp
1917
+ });
1918
+ }
1898
1919
  this.rewriteWorkspaceSessionRelations(input.workspaceId, input.targetSessionId, input.sourceSessionId, targetIndex, sourceIndex);
1899
1920
  }
1900
1921
  listSessionStatesBySessionId(sessionId) {
@@ -2020,6 +2041,7 @@ export class SessionHistoryService {
2020
2041
  }
2021
2042
  buildKnownSessionSummaries(sessions, workspacePath) {
2022
2043
  return sessions
2044
+ .filter((session) => !this.isPendingSessionAlias(session))
2023
2045
  .filter((session) => !shouldSkipClaudePendingBinding(session))
2024
2046
  .map((session) => {
2025
2047
  const stats = safeStat(session.rawStoreRef);
@@ -2039,19 +2061,28 @@ export class SessionHistoryService {
2039
2061
  async refreshSessionState(sessionId, userId) {
2040
2062
  const binding = this.getBindingOrThrow(sessionId);
2041
2063
  const current = this.sessionStateRepository.findBySessionAndUser(sessionId, userId);
2042
- const inspection = inspectSessionActivity(binding.provider, binding.rawStoreRef);
2043
2064
  const timestamp = nowIso();
2044
- const nowMs = Date.parse(timestamp);
2045
- if (shouldClearStaleRuntimeWithoutInspection(current, inspection, nowMs)) {
2046
- this.sessionActivityAuthorityService.clearSession(sessionId);
2047
- }
2048
- if (shouldPreserveRuntimeTerminalState(current, inspection)) {
2049
- return current;
2065
+ const liveObservation = this.resolveLiveActivityObservation(sessionId);
2066
+ const inspection = liveObservation
2067
+ ? null
2068
+ : inspectSessionActivity(binding.provider, binding.rawStoreRef);
2069
+ if (inspection) {
2070
+ const nowMs = Date.parse(timestamp);
2071
+ if (shouldClearStaleRuntimeWithoutInspection(current, inspection, nowMs)) {
2072
+ this.sessionActivityAuthorityService.clearSession(sessionId);
2073
+ }
2074
+ if (shouldPreserveRuntimeTerminalState(current, inspection)) {
2075
+ return current;
2076
+ }
2050
2077
  }
2051
- const resolution = this.sessionActivityAuthorityService.observe(buildInspectionActivityObservation(sessionId, inspection, timestamp));
2052
- const resolvedLastEventAt = hasInspectionEvidence(inspection)
2053
- ? resolution.lastObservedAt ?? inspection.lastEventAt ?? current?.lastEventAt ?? null
2054
- : current?.lastEventAt ?? null;
2078
+ const resolution = liveObservation
2079
+ ? this.sessionActivityAuthorityService.observe(liveObservation)
2080
+ : this.sessionActivityAuthorityService.observe(buildInspectionActivityObservation(sessionId, inspection, timestamp));
2081
+ const resolvedLastEventAt = liveObservation
2082
+ ? resolution.lastObservedAt ?? current?.lastEventAt ?? null
2083
+ : inspection && hasInspectionEvidence(inspection)
2084
+ ? resolution.lastObservedAt ?? inspection.lastEventAt ?? current?.lastEventAt ?? null
2085
+ : current?.lastEventAt ?? null;
2055
2086
  const nextRecord = {
2056
2087
  sessionId,
2057
2088
  userId,
@@ -2060,7 +2091,7 @@ export class SessionHistoryService {
2060
2091
  favorite: current?.favorite ?? false,
2061
2092
  lastEventAt: resolvedLastEventAt,
2062
2093
  completedAt: isTerminalResolvedRunningState(resolution.runningState)
2063
- ? resolution.terminalAt ?? inspection.completedAtCandidate ?? current?.completedAt ?? null
2094
+ ? resolution.terminalAt ?? inspection?.completedAtCandidate ?? current?.completedAt ?? null
2064
2095
  : null,
2065
2096
  lastSeenAt: current?.lastSeenAt ?? null,
2066
2097
  updatedAt: timestamp
@@ -2078,8 +2109,8 @@ export class SessionHistoryService {
2078
2109
  syncCursor: currentSnapshot?.syncCursor ?? null,
2079
2110
  lastSyncAt: resolution.lastObservedAt
2080
2111
  ?? resolution.terminalAt
2081
- ?? inspection.lastEventAt
2082
- ?? inspection.completedAtCandidate
2112
+ ?? inspection?.lastEventAt
2113
+ ?? inspection?.completedAtCandidate
2083
2114
  ?? currentSnapshot?.lastSyncAt
2084
2115
  ?? null,
2085
2116
  lastErrorCode: resolution.runningState === "failed"
@@ -2097,17 +2128,34 @@ export class SessionHistoryService {
2097
2128
  });
2098
2129
  return nextRecord;
2099
2130
  }
2131
+ resolveLiveActivityObservation(sessionId) {
2132
+ for (const resolver of this.liveActivityObservationResolvers) {
2133
+ const observation = resolver(sessionId);
2134
+ if (observation) {
2135
+ return observation;
2136
+ }
2137
+ }
2138
+ return null;
2139
+ }
2100
2140
  upsertSnapshot(sessionId, input) {
2141
+ const resolvedSessionId = this.resolveCanonicalSessionId(sessionId);
2142
+ if (!this.sessionBindingRepository.findBySessionId(resolvedSessionId)) {
2143
+ return;
2144
+ }
2101
2145
  this.sessionStatusSnapshotRepository.upsert({
2102
- sessionId,
2146
+ sessionId: resolvedSessionId,
2103
2147
  ...input,
2104
2148
  updatedAt: nowIso()
2105
2149
  });
2106
2150
  }
2107
2151
  markSessionError(sessionId, errorCode, error) {
2108
- const current = this.sessionStatusSnapshotRepository.findBySessionId(sessionId);
2152
+ const resolvedSessionId = this.resolveCanonicalSessionId(sessionId);
2153
+ if (!this.sessionBindingRepository.findBySessionId(resolvedSessionId)) {
2154
+ return;
2155
+ }
2156
+ const current = this.sessionStatusSnapshotRepository.findBySessionId(resolvedSessionId);
2109
2157
  this.sessionStatusSnapshotRepository.upsert({
2110
- sessionId,
2158
+ sessionId: resolvedSessionId,
2111
2159
  syncStatus: "error",
2112
2160
  syncCursor: current?.syncCursor ?? null,
2113
2161
  lastSyncAt: current?.lastSyncAt ?? null,
@@ -2177,23 +2225,28 @@ function hasInspectionEvidence(inspection) {
2177
2225
  || !!inspection.completedAtCandidate;
2178
2226
  }
2179
2227
  function applySessionActivityResolution(item, resolution) {
2180
- const runningState = resolution.runningState;
2181
- const shouldClearResolvedFailure = runningState !== "failed" && item.runningState === "failed";
2228
+ const rawResolvedRunningState = resolution.runningState === "unknown" && item.runningState === null
2229
+ ? null
2230
+ : resolution.runningState;
2231
+ const resolvedRunningState = resolution.activityResolutionSource === "inferred_log" && rawResolvedRunningState === "completed"
2232
+ ? "idle"
2233
+ : rawResolvedRunningState;
2234
+ const shouldClearResolvedFailure = resolvedRunningState !== "failed" && item.runningState === "failed";
2182
2235
  const lastEventAt = resolution.lastObservedAt ?? item.lastEventAt;
2183
- const completedAt = isTerminalResolvedRunningState(runningState)
2236
+ const completedAt = rawResolvedRunningState && isTerminalResolvedRunningState(rawResolvedRunningState)
2184
2237
  ? resolution.terminalAt ?? item.completedAt
2185
2238
  : null;
2186
- const lastErrorCode = runningState === "failed"
2239
+ const lastErrorCode = resolvedRunningState === "failed"
2187
2240
  ? resolution.errorCode ?? item.lastErrorCode
2188
2241
  : shouldClearResolvedFailure
2189
2242
  ? null
2190
2243
  : item.lastErrorCode;
2191
- const lastErrorDetail = runningState === "failed"
2244
+ const lastErrorDetail = resolvedRunningState === "failed"
2192
2245
  ? resolution.detail ?? item.lastErrorDetail
2193
2246
  : shouldClearResolvedFailure
2194
2247
  ? null
2195
2248
  : item.lastErrorDetail;
2196
- const syncStatus = runningState === "failed"
2249
+ const syncStatus = resolvedRunningState === "failed"
2197
2250
  ? "error"
2198
2251
  : shouldClearResolvedFailure && item.syncStatus === "error"
2199
2252
  ? "idle"
@@ -2201,7 +2254,7 @@ function applySessionActivityResolution(item, resolution) {
2201
2254
  return {
2202
2255
  ...item,
2203
2256
  syncStatus,
2204
- runningState,
2257
+ runningState: resolvedRunningState,
2205
2258
  activitySource: mapResolutionSourceToCompatibilitySource(resolution.activityResolutionSource),
2206
2259
  activityResolutionSource: resolution.activityResolutionSource,
2207
2260
  activityConfidence: resolution.activityConfidence,
@@ -2211,7 +2264,7 @@ function applySessionActivityResolution(item, resolution) {
2211
2264
  lastErrorCode,
2212
2265
  lastErrorDetail,
2213
2266
  watchdogTriggeredAt: resolution.watchdogTriggeredAt,
2214
- activityState: resolveActivityState(runningState, completedAt, item.lastSeenAt)
2267
+ activityState: resolveActivityState(resolvedRunningState, completedAt, item.lastSeenAt)
2215
2268
  };
2216
2269
  }
2217
2270
  function clampLimit(limit) {
@@ -2410,6 +2463,9 @@ function isPendingBindingValue(value) {
2410
2463
  function buildPendingBindingValue(provider, sessionId) {
2411
2464
  return `pending://${provider}/${sessionId}`;
2412
2465
  }
2466
+ function buildAliasBindingValue(provider, targetSessionId, sourceSessionId) {
2467
+ return `alias://${provider}/${targetSessionId}/${sourceSessionId}`;
2468
+ }
2413
2469
  function extractPendingBindingTargetSessionId(value) {
2414
2470
  if (!isPendingBindingValue(value)) {
2415
2471
  return null;
@@ -2418,6 +2474,25 @@ function extractPendingBindingTargetSessionId(value) {
2418
2474
  const targetSessionId = normalizedValue.slice(normalizedValue.indexOf("/", "pending://".length) + 1).trim();
2419
2475
  return targetSessionId || null;
2420
2476
  }
2477
+ function extractAliasBindingTargetSessionId(value) {
2478
+ const normalizedValue = value.trim();
2479
+ if (!normalizedValue.toLowerCase().startsWith("alias://")) {
2480
+ return null;
2481
+ }
2482
+ const pathStart = normalizedValue.indexOf("/", "alias://".length);
2483
+ if (pathStart < 0) {
2484
+ return null;
2485
+ }
2486
+ const targetAndSource = normalizedValue.slice(pathStart + 1).trim();
2487
+ if (targetAndSource.length === 0) {
2488
+ return null;
2489
+ }
2490
+ const [targetSessionId] = targetAndSource.split("/", 1);
2491
+ return targetSessionId?.trim() || null;
2492
+ }
2493
+ function extractSessionAliasTargetSessionId(value) {
2494
+ return extractAliasBindingTargetSessionId(value) ?? extractPendingBindingTargetSessionId(value);
2495
+ }
2421
2496
  function isClaudePendingRuntimeRawStoreRef(rawStoreRef) {
2422
2497
  const normalizedRawStoreRef = rawStoreRef.replaceAll("\\", "/").toLowerCase();
2423
2498
  return normalizedRawStoreRef.includes("/.pending-");
@@ -2786,7 +2861,7 @@ function mapResolutionSourceToLegacyActivitySource(source, inspection) {
2786
2861
  if (source === "authoritative_runtime" || source === "authoritative_provider_event") {
2787
2862
  return "runtime";
2788
2863
  }
2789
- if (inspection.lastEventAt || inspection.completedAtCandidate) {
2864
+ if (inspection && (inspection.lastEventAt || inspection.completedAtCandidate)) {
2790
2865
  return "inferred";
2791
2866
  }
2792
2867
  return "none";