codesesh 1.0.2 → 1.0.4

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 (64) hide show
  1. package/README.md +18 -10
  2. package/dist/chunk-3SXCTDD6.js +326 -0
  3. package/dist/chunk-3SXCTDD6.js.map +1 -0
  4. package/dist/chunk-BYB77UAJ.js +6054 -0
  5. package/dist/chunk-BYB77UAJ.js.map +1 -0
  6. package/dist/{chunk-PROMURPM.js → chunk-G4HRD3AR.js} +13 -8
  7. package/dist/chunk-G4HRD3AR.js.map +1 -0
  8. package/dist/chunk-MBZ4VV4C.js +670 -0
  9. package/dist/chunk-MBZ4VV4C.js.map +1 -0
  10. package/dist/chunk-QH2HOXJH.js +2 -0
  11. package/dist/chunk-RF3EEWPH.js +17 -0
  12. package/dist/chunk-RF3EEWPH.js.map +1 -0
  13. package/dist/chunk-W4PZHL2C.js +2035 -0
  14. package/dist/chunk-W4PZHL2C.js.map +1 -0
  15. package/dist/chunk-YCUN52HA.js +8422 -0
  16. package/dist/chunk-YCUN52HA.js.map +1 -0
  17. package/dist/discovery-K3GLISI6.js +102 -0
  18. package/dist/discovery-K3GLISI6.js.map +1 -0
  19. package/dist/index.js +3016 -1392
  20. package/dist/index.js.map +1 -1
  21. package/dist/project-identity-worker.js +29 -0
  22. package/dist/project-identity-worker.js.map +1 -0
  23. package/dist/scan-refresh-worker.js +129 -139
  24. package/dist/scan-refresh-worker.js.map +1 -1
  25. package/dist/search-index-worker.js +39 -13
  26. package/dist/search-index-worker.js.map +1 -1
  27. package/dist/smart-tag-worker.js +8 -5
  28. package/dist/smart-tag-worker.js.map +1 -1
  29. package/dist/web/assets/InteractiveReceipt-Dk50TBsH.js +1 -0
  30. package/dist/web/assets/OverviewScreen-5hvQVp4H.js +1 -0
  31. package/dist/web/assets/{PrismHighlighter-BZkkX0AU.js → PrismHighlighter-B1a2dPJO.js} +2 -2
  32. package/dist/web/assets/Projects-Cy_v2yep.js +1 -0
  33. package/dist/web/assets/SearchResultsPanel-DfheEwpz.js +1 -0
  34. package/dist/web/assets/SessionDetail-DRI8R3st.js +53 -0
  35. package/dist/web/assets/api-GP9UCedC.js +1 -0
  36. package/dist/web/assets/contract-xJyW5u7a.js +2 -0
  37. package/dist/web/assets/index-Bd-YkWkZ.css +1 -0
  38. package/dist/web/assets/index-DEjvzumm.js +1410 -0
  39. package/dist/web/assets/panel-ND0J63d3.js +1 -0
  40. package/dist/web/assets/{session-indexes-0oT5HSS5.js → session-indexes-BsgjUoc1.js} +2 -2
  41. package/dist/web/assets/utils-C7BqyxxV.js +1 -0
  42. package/dist/web/index.html +7 -11
  43. package/package.json +4 -10
  44. package/dist/chunk-PROMURPM.js.map +0 -1
  45. package/dist/chunk-VAUC2W7I.js +0 -16119
  46. package/dist/chunk-VAUC2W7I.js.map +0 -1
  47. package/dist/dist-6QTGTYZT.js +0 -175
  48. package/dist/web/assets/ErrorBoundary-D11tWzfn.js +0 -1
  49. package/dist/web/assets/InteractiveReceipt-DYGyHeZd.js +0 -1
  50. package/dist/web/assets/OverviewScreen-DriPmCam.js +0 -1
  51. package/dist/web/assets/Projects-BPDIcUBK.js +0 -1
  52. package/dist/web/assets/SearchFilterBar-Bx73B5e9.js +0 -1
  53. package/dist/web/assets/SearchResultsPanel-A6_3TPhW.js +0 -1
  54. package/dist/web/assets/SessionDetail-BnpvDwtH.js +0 -54
  55. package/dist/web/assets/SmartTagChips-ux6idUGJ.js +0 -1
  56. package/dist/web/assets/agents-BkRP_ww3.js +0 -1
  57. package/dist/web/assets/code-metrics-UYFsCC7E.js +0 -1
  58. package/dist/web/assets/contract-V6QuD0UY.js +0 -1
  59. package/dist/web/assets/index-99ZxpV2y.js +0 -1410
  60. package/dist/web/assets/index-B2RqUgZ5.css +0 -1
  61. package/dist/web/assets/panel-C-gc79Gz.js +0 -1
  62. package/dist/web/assets/session-title-DdtlxtlR.js +0 -1
  63. package/dist/web/assets/utils-DgUgu15E.js +0 -1
  64. /package/dist/{dist-6QTGTYZT.js.map → chunk-QH2HOXJH.js.map} +0 -0
@@ -0,0 +1,2035 @@
1
+ #!/usr/bin/env node
2
+
3
+ // ../core/dist/chunk-AXHUQ6MM.mjs
4
+ var SMART_TAGS = [
5
+ "bugfix",
6
+ "refactoring",
7
+ "feature-dev",
8
+ "testing",
9
+ "docs",
10
+ "git-ops",
11
+ "build-deploy",
12
+ "exploration",
13
+ "planning"
14
+ ];
15
+ function isSmartTag(value) {
16
+ return SMART_TAGS.some((tag) => tag === value);
17
+ }
18
+ function assertIdentifiedSessionHead(session) {
19
+ if (session.project_identity) return;
20
+ throw new Error(
21
+ `Session ${session.reference.agentName}/${session.reference.sessionId} is missing project_identity`
22
+ );
23
+ }
24
+ function toPublicSessionHead(session) {
25
+ const {
26
+ model_usage: _modelUsage,
27
+ project_identity_resolver_revision: _resolverRevision,
28
+ project_identity_input_signature: _identityInputSignature,
29
+ smart_tags_source_updated_at: _smartTagsSourceUpdatedAt,
30
+ smart_tags_classifier_revision: _classifierRevision,
31
+ ...publicSession
32
+ } = session;
33
+ return publicSession;
34
+ }
35
+ function toPublicReferencedSessionHead(item) {
36
+ return { ...item, session: toPublicSessionHead(item.session) };
37
+ }
38
+
39
+ // ../core/dist/chunk-EY7UDYHJ.mjs
40
+ var SMART_TAG_CLASSIFIER_REVISION = "smart-tags-v1";
41
+ var USER_RULES = [
42
+ ["bugfix", /\b(fix|bug|error|crash|exception|fail(?:ed|ure)?)\b|修复|错误|报错|崩溃|异常/i],
43
+ ["refactoring", /\b(refactor|rename|simplify|clean up|cleanup)\b|重构|重命名|简化|清理/i],
44
+ ["feature-dev", /\b(add|create|implement|new|support|build)\b|新增|创建|实现|增加|开发|支持/i],
45
+ ["docs", /\b(document|documentation|readme|docs?)\b|文档|说明/i]
46
+ ];
47
+ var TESTING_COMMAND_RE = /\b(pytest|vitest|jest|mocha|pnpm\s+test|npm\s+test|yarn\s+test)\b/i;
48
+ var GIT_COMMAND_RE = /\bgit\s+(push|commit|merge|branch|checkout|switch|rebase|tag)\b/i;
49
+ var BUILD_DEPLOY_COMMAND_RE = /\b((npm|pnpm|yarn|bun)\s+(run\s+)?build|docker|pm2|deploy|vercel|netlify)\b/i;
50
+ var DOC_PATH_RE = /\.(md|mdx|txt|rst|adoc)$/i;
51
+ var READ_TOOL_RE = /\b(read|grep|glob|websearch|web_search|search|find|rg)\b/i;
52
+ var EDIT_TOOL_RE = /\b(edit|write|apply_patch|patch|multiedit|notebookedit)\b/i;
53
+ var PLAN_TOOL_RE = /\b(enterplanmode|taskcreate|update_plan|plan)\b/i;
54
+ function getSmartTagSourceTimestamp(session) {
55
+ return session.time_updated ?? session.time_created;
56
+ }
57
+ function classifySessionTags(session) {
58
+ const tags = /* @__PURE__ */ new Set();
59
+ let readToolCount = 0;
60
+ let editToolCount = 0;
61
+ for (const message of session.messages) {
62
+ if (message.role === "user") {
63
+ const text = message.parts.map(partText).join("\n");
64
+ for (const [tag, pattern] of USER_RULES) {
65
+ if (pattern.test(text)) tags.add(tag);
66
+ }
67
+ }
68
+ for (const part of message.parts) {
69
+ if (part.type === "plan") tags.add("planning");
70
+ if (part.type !== "tool") continue;
71
+ const toolName = `${part.tool} ${part.title ?? ""}`;
72
+ const toolPayload = stringifyToolPayload(part);
73
+ if (PLAN_TOOL_RE.test(toolName)) tags.add("planning");
74
+ if (READ_TOOL_RE.test(toolName)) readToolCount += 1;
75
+ if (EDIT_TOOL_RE.test(toolName)) editToolCount += 1;
76
+ if (TESTING_COMMAND_RE.test(toolPayload)) tags.add("testing");
77
+ if (GIT_COMMAND_RE.test(toolPayload)) tags.add("git-ops");
78
+ if (BUILD_DEPLOY_COMMAND_RE.test(toolPayload)) tags.add("build-deploy");
79
+ if (hasEditedDocPath(part.state.input)) {
80
+ tags.add("docs");
81
+ }
82
+ }
83
+ }
84
+ if (readToolCount >= 3 && editToolCount <= 1) {
85
+ tags.add("exploration");
86
+ }
87
+ return SMART_TAGS.filter((tag) => tags.has(tag));
88
+ }
89
+ function partText(part) {
90
+ return part.type === "text" || part.type === "reasoning" || part.type === "plan" ? part.text : "";
91
+ }
92
+ function stringifyToolPayload(part) {
93
+ return [part.tool, part.title, valueToText(part.state)].filter(Boolean).join("\n");
94
+ }
95
+ function valueToText(value) {
96
+ if (value == null) return "";
97
+ if (typeof value === "string") return value;
98
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
99
+ try {
100
+ return JSON.stringify(value);
101
+ } catch {
102
+ return "";
103
+ }
104
+ }
105
+ function hasEditedDocPath(value) {
106
+ if (value == null) return false;
107
+ if (typeof value === "string") return DOC_PATH_RE.test(value);
108
+ if (Array.isArray(value)) return value.some(hasEditedDocPath);
109
+ if (typeof value !== "object") return false;
110
+ const record = value;
111
+ for (const key of ["path", "file", "filePath", "file_path", "targetPath", "target_path"]) {
112
+ const raw = record[key];
113
+ if (typeof raw === "string" && DOC_PATH_RE.test(raw)) return true;
114
+ }
115
+ return Object.values(record).some(hasEditedDocPath);
116
+ }
117
+ var WORKER_LOG_MESSAGE_TYPE = "codesesh.worker-log";
118
+ function isRecord(value) {
119
+ return value != null && typeof value === "object" && !Array.isArray(value);
120
+ }
121
+ function isWorkerLogMessage(value) {
122
+ if (!isRecord(value) || value.type !== WORKER_LOG_MESSAGE_TYPE) return false;
123
+ return typeof value.ts === "string" && value.ts.length > 0 && (value.level === "debug" || value.level === "info" || value.level === "warn" || value.level === "error") && typeof value.event === "string" && value.event.length > 0 && Number.isSafeInteger(value.pid) && Number(value.pid) > 0 && Number.isSafeInteger(value.threadId) && Number(value.threadId) >= 0 && isRecord(value.data);
124
+ }
125
+
126
+ // ../core/dist/chunk-FDGCEOYE.mjs
127
+ function normalizeSessionReference(reference) {
128
+ return {
129
+ agentName: reference.agentName.trim().toLowerCase(),
130
+ sessionId: reference.sessionId
131
+ };
132
+ }
133
+ function formatSessionReference(reference) {
134
+ const normalized = normalizeSessionReference(reference);
135
+ return `${normalized.agentName}/${normalized.sessionId}`;
136
+ }
137
+ function getSessionReferenceKey(reference) {
138
+ return formatSessionReference(reference);
139
+ }
140
+ function createSessionIdentity(reference) {
141
+ return {
142
+ reference: normalizeSessionReference(reference)
143
+ };
144
+ }
145
+ function assertSessionIdentity(identity, agentName) {
146
+ const normalized = normalizeSessionReference(identity.reference);
147
+ const expectedAgentName = agentName?.trim().toLowerCase();
148
+ if (identity.reference.agentName !== normalized.agentName) {
149
+ throw new Error("Session reference is not normalized");
150
+ }
151
+ if (expectedAgentName != null && normalized.agentName !== expectedAgentName) {
152
+ throw new Error(
153
+ `Session reference agent "${normalized.agentName}" does not match "${expectedAgentName}"`
154
+ );
155
+ }
156
+ }
157
+ function getSessionAgentKey(session) {
158
+ return normalizeSessionReference(session.reference).agentName;
159
+ }
160
+ function agentRoutePath(agentName) {
161
+ return `/${encodeURIComponent(agentName.trim().toLowerCase())}`;
162
+ }
163
+ function sessionRoutePath(reference) {
164
+ const normalized = normalizeSessionReference(reference);
165
+ return `${agentRoutePath(normalized.agentName)}/${encodeURIComponent(normalized.sessionId)}`;
166
+ }
167
+
168
+ // ../core/dist/chunk-GHNYETRY.mjs
169
+ var FILE_TOOL_KINDS = {
170
+ read: "read",
171
+ read_file: "read",
172
+ read_file_v2: "read",
173
+ read_text_file: "read",
174
+ readfile: "read",
175
+ view_image: "read",
176
+ apply_patch: "edit",
177
+ edit: "edit",
178
+ edit_file: "edit",
179
+ edit_file_v2: "edit",
180
+ editfile: "edit",
181
+ multiedit: "edit",
182
+ notebookedit: "edit",
183
+ patch: "edit",
184
+ search_replace: "edit",
185
+ str_replace: "edit",
186
+ create_file: "write",
187
+ write: "write",
188
+ write_file: "write",
189
+ writefile: "write",
190
+ delete: "delete",
191
+ delete_file: "delete"
192
+ };
193
+ var PATCH_KINDS = {
194
+ edit_file: "edit",
195
+ update_file: "edit",
196
+ write_file: "write",
197
+ delete_file: "delete",
198
+ move_file: "edit"
199
+ };
200
+ function toRecord(value) {
201
+ if (value && typeof value === "object" && !Array.isArray(value)) {
202
+ return value;
203
+ }
204
+ return {};
205
+ }
206
+ function looksLikeFilePath(value) {
207
+ const text = value.trim();
208
+ if (!text || text.length > 300 || text.includes("\n")) return false;
209
+ if (/^[a-z]+:\/\//i.test(text) || /[<>{}]/.test(text)) return false;
210
+ if (text.startsWith("/") || text.startsWith("./") || text.startsWith("../")) return true;
211
+ if (text.startsWith("~/") || text.includes("/") || text.includes("\\")) return true;
212
+ return /^[A-Za-z0-9_.@-]+\.[A-Za-z0-9_-]+$/.test(text);
213
+ }
214
+ function isPathKey(key) {
215
+ const normalized = key.trim().toLowerCase();
216
+ if (!normalized) return false;
217
+ if (normalized.includes("command") || normalized.includes("content") || normalized.includes("text") || normalized.includes("prompt") || normalized.includes("url") || normalized.includes("body") || normalized.includes("title") || normalized.includes("description") || normalized === "cwd" || normalized === "workdir" || normalized === "directory") {
218
+ return false;
219
+ }
220
+ return normalized.includes("file") || normalized.includes("path");
221
+ }
222
+ function collectPaths(value, key, paths, depth = 0) {
223
+ if (value == null || depth > 4) return;
224
+ if (typeof value === "string") {
225
+ if (isPathKey(key) && looksLikeFilePath(value)) paths.add(value.trim());
226
+ return;
227
+ }
228
+ if (Array.isArray(value)) {
229
+ for (const item of value) collectPaths(item, key, paths, depth + 1);
230
+ return;
231
+ }
232
+ if (typeof value === "object") {
233
+ for (const [nestedKey, nested] of Object.entries(value)) {
234
+ collectPaths(nested, nestedKey, paths, depth + 1);
235
+ }
236
+ }
237
+ }
238
+ function extractPatchOperations(input) {
239
+ const record = toRecord(input);
240
+ const content = Array.isArray(input) ? input : Array.isArray(record.content) ? record.content : [];
241
+ return content.flatMap((entry) => {
242
+ const patch = toRecord(entry);
243
+ const kind = typeof patch.type === "string" ? PATCH_KINDS[patch.type] : void 0;
244
+ const pathValue = patch.path || patch.old_path;
245
+ const path = typeof pathValue === "string" ? pathValue.trim() : "";
246
+ return kind && path ? [{ kind, path }] : [];
247
+ });
248
+ }
249
+ function classifyFileTool(part) {
250
+ return FILE_TOOL_KINDS[part.tool.trim().toLowerCase()] ?? null;
251
+ }
252
+ function extractFileToolOperations(part) {
253
+ const patchOperations = extractPatchOperations(part.state.input);
254
+ if (patchOperations.length > 0) return patchOperations;
255
+ const kind = classifyFileTool(part);
256
+ if (!kind) return [];
257
+ const paths = /* @__PURE__ */ new Set();
258
+ collectPaths(part.state.input, "", paths);
259
+ return [...paths].map((path) => ({ kind, path }));
260
+ }
261
+ function mergeSessionsUpdatedEvents(previous, next) {
262
+ const changedSessionHeads = /* @__PURE__ */ new Map();
263
+ const projectionRelatedSessionHeads = /* @__PURE__ */ new Map();
264
+ const projectionSessionOrder = /* @__PURE__ */ new Map();
265
+ const newSessionRefs = /* @__PURE__ */ new Map();
266
+ const removedSessionRefs = /* @__PURE__ */ new Map();
267
+ const sessionKey2 = (agentName, sessionId) => `${agentName}\0${sessionId}`;
268
+ const addChanged = (item) => {
269
+ const key = sessionKey2(item.reference.agentName, item.reference.sessionId);
270
+ removedSessionRefs.delete(key);
271
+ projectionRelatedSessionHeads.delete(key);
272
+ changedSessionHeads.set(key, item);
273
+ };
274
+ const addProjectionRelated = (item) => {
275
+ const key = sessionKey2(item.reference.agentName, item.reference.sessionId);
276
+ if (changedSessionHeads.has(key) || removedSessionRefs.has(key)) return;
277
+ projectionRelatedSessionHeads.set(key, item);
278
+ };
279
+ const addNew = (item) => {
280
+ const key = sessionKey2(item.agentName, item.sessionId);
281
+ removedSessionRefs.delete(key);
282
+ newSessionRefs.set(key, item);
283
+ };
284
+ const addProjectionOrder = (item) => {
285
+ const key = sessionKey2(item.agentName, item.sessionId);
286
+ projectionSessionOrder.delete(key);
287
+ projectionSessionOrder.set(key, item);
288
+ };
289
+ const addRemoved = (item) => {
290
+ const key = sessionKey2(item.agentName, item.sessionId);
291
+ changedSessionHeads.delete(key);
292
+ projectionRelatedSessionHeads.delete(key);
293
+ projectionSessionOrder.delete(key);
294
+ newSessionRefs.delete(key);
295
+ removedSessionRefs.set(key, item);
296
+ };
297
+ for (const item of previous.newSessionRefs) addNew(item);
298
+ for (const item of previous.projectionRelatedSessionHeads ?? []) addProjectionRelated(item);
299
+ for (const item of previous.projectionSessionOrder ?? []) addProjectionOrder(item);
300
+ for (const item of previous.changedSessionHeads) addChanged(item);
301
+ for (const item of previous.removedSessionRefs) addRemoved(item);
302
+ for (const item of next.newSessionRefs) addNew(item);
303
+ for (const item of next.projectionRelatedSessionHeads ?? []) addProjectionRelated(item);
304
+ for (const item of next.projectionSessionOrder ?? []) addProjectionOrder(item);
305
+ for (const item of next.changedSessionHeads) addChanged(item);
306
+ for (const item of next.removedSessionRefs) addRemoved(item);
307
+ return {
308
+ type: "sessions-updated",
309
+ changedAgents: Array.from(/* @__PURE__ */ new Set([...previous.changedAgents, ...next.changedAgents])),
310
+ newSessionRefs: [...newSessionRefs.values()],
311
+ totalSessions: next.totalSessions,
312
+ timestamp: next.timestamp,
313
+ changedSessionHeads: [...changedSessionHeads.values()],
314
+ projectionRelatedSessionHeads: [...projectionRelatedSessionHeads.values()],
315
+ projectionSessionOrder: [...projectionSessionOrder.values()],
316
+ removedSessionRefs: [...removedSessionRefs.values()]
317
+ };
318
+ }
319
+ function startOfCalendarDay(timestamp) {
320
+ const date = new Date(timestamp);
321
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
322
+ }
323
+ function addCalendarDays(timestamp, days) {
324
+ const date = new Date(timestamp);
325
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days).getTime();
326
+ }
327
+ function toCalendarDayNumber(timestamp) {
328
+ const date = new Date(timestamp);
329
+ return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) / 864e5;
330
+ }
331
+ function countCalendarDays(from, to) {
332
+ return Math.max(1, toCalendarDayNumber(to) - toCalendarDayNumber(from) + 1);
333
+ }
334
+ function toCalendarDayKey(timestamp) {
335
+ const date = new Date(timestamp);
336
+ return `${String(date.getFullYear()).padStart(4, "0")}-${String(date.getMonth() + 1).padStart(
337
+ 2,
338
+ "0"
339
+ )}-${String(date.getDate()).padStart(2, "0")}`;
340
+ }
341
+ var PROJECT_IDENTITY_KINDS = [
342
+ "git_remote",
343
+ "git_common_dir",
344
+ "manifest_path",
345
+ "synthetic",
346
+ "path",
347
+ "loose"
348
+ ];
349
+ var KIND_LOOKUP = new Set(PROJECT_IDENTITY_KINDS);
350
+ function isProjectIdentityKind(value) {
351
+ return KIND_LOOKUP.has(value);
352
+ }
353
+ function getProjectIdentityKey(identity) {
354
+ return `${identity.kind}:${identity.key}`;
355
+ }
356
+ function matchesProjectIdentity(identity, expected) {
357
+ return identity?.kind === expected.kind && identity.key === expected.key;
358
+ }
359
+ function getProjectAgentKey(projectIdentityKey, agentName) {
360
+ return `${projectIdentityKey}\0${agentName.toLowerCase()}`;
361
+ }
362
+ function compareSessionActivityDesc(a, b) {
363
+ return (b.time_updated ?? b.time_created) - (a.time_updated ?? a.time_created);
364
+ }
365
+ function sortSessionsByActivity(sessions) {
366
+ for (let index = 1; index < sessions.length; index += 1) {
367
+ if (compareSessionActivityDesc(sessions[index - 1], sessions[index]) > 0) {
368
+ return [...sessions].sort(compareSessionActivityDesc);
369
+ }
370
+ }
371
+ return [...sessions];
372
+ }
373
+ function mergeSortedSessions(shards) {
374
+ const active = shards.filter((shard) => shard.length > 0);
375
+ if (active.length === 0) return [];
376
+ if (active.length === 1) return [...active[0]];
377
+ const total = active.reduce((sum, shard) => sum + shard.length, 0);
378
+ const merged = [];
379
+ const cursors = Array.from({ length: active.length }, () => 0);
380
+ for (let position = 0; position < total; position += 1) {
381
+ let pick = -1;
382
+ for (let shard = 0; shard < active.length; shard += 1) {
383
+ const cursor = cursors[shard];
384
+ if (cursor >= active[shard].length) continue;
385
+ if (pick === -1 || compareSessionActivityDesc(active[shard][cursor], active[pick][cursors[pick]]) < 0) {
386
+ pick = shard;
387
+ }
388
+ }
389
+ merged.push(active[pick][cursors[pick]]);
390
+ cursors[pick] += 1;
391
+ }
392
+ return merged;
393
+ }
394
+ function pushMapValue(map, key, value) {
395
+ const current = map.get(key);
396
+ if (current) {
397
+ current.push(value);
398
+ } else {
399
+ map.set(key, [value]);
400
+ }
401
+ }
402
+ function createSessionIndex(sourceSessions) {
403
+ const byRouteKey = /* @__PURE__ */ new Map();
404
+ const childrenByParentRouteKey = /* @__PURE__ */ new Map();
405
+ const byAgent = /* @__PURE__ */ new Map();
406
+ const byProjectIdentityKey = /* @__PURE__ */ new Map();
407
+ const byProjectAgentKey = /* @__PURE__ */ new Map();
408
+ for (const session of sourceSessions) {
409
+ const routeKey = getSessionReferenceKey(session.reference);
410
+ if (!byRouteKey.has(routeKey)) byRouteKey.set(routeKey, session);
411
+ if (session.parent_reference) {
412
+ pushMapValue(
413
+ childrenByParentRouteKey,
414
+ getSessionReferenceKey(session.parent_reference),
415
+ session
416
+ );
417
+ }
418
+ }
419
+ const sessionsByActivity = sortSessionsByActivity(sourceSessions);
420
+ for (const session of sessionsByActivity) {
421
+ const { agentName } = session.reference;
422
+ pushMapValue(byAgent, agentName, session);
423
+ const identity = session.project_identity;
424
+ if (!identity?.key) continue;
425
+ const projectIdentityKey = getProjectIdentityKey(identity);
426
+ pushMapValue(byProjectIdentityKey, projectIdentityKey, session);
427
+ pushMapValue(byProjectAgentKey, getProjectAgentKey(projectIdentityKey, agentName), session);
428
+ }
429
+ return {
430
+ sourceSessions,
431
+ sessionsByActivity,
432
+ byRouteKey,
433
+ childrenByParentRouteKey,
434
+ byAgent,
435
+ byProjectIdentityKey,
436
+ byProjectAgentKey
437
+ };
438
+ }
439
+ function sessionKey(session) {
440
+ return getSessionReferenceKey(session.reference);
441
+ }
442
+ function parentKey(session) {
443
+ return session.parent_reference ? getSessionReferenceKey(session.parent_reference) : null;
444
+ }
445
+ function activityTime(session) {
446
+ return session.time_updated ?? session.time_created;
447
+ }
448
+ function hasActivityInWindow(session, from, to) {
449
+ const activity = activityTime(session);
450
+ return (from == null || activity >= from) && (to == null || activity <= to);
451
+ }
452
+ function ownStats(session) {
453
+ const stats = session.stats;
454
+ const cost = stats.total_cost ?? 0;
455
+ return {
456
+ messageCount: stats.message_count,
457
+ inputTokens: stats.total_input_tokens,
458
+ outputTokens: stats.total_output_tokens,
459
+ cacheReadTokens: stats.total_cache_read_tokens ?? 0,
460
+ cacheCreateTokens: stats.total_cache_create_tokens ?? 0,
461
+ totalTokens: stats.total_tokens ?? stats.total_input_tokens + stats.total_output_tokens,
462
+ cost,
463
+ costSource: cost > 0 ? stats.cost_source ?? "recorded" : void 0
464
+ };
465
+ }
466
+ function addStats(target, source) {
467
+ target.messageCount += source.messageCount;
468
+ target.inputTokens += source.inputTokens;
469
+ target.outputTokens += source.outputTokens;
470
+ target.cacheReadTokens += source.cacheReadTokens;
471
+ target.cacheCreateTokens += source.cacheCreateTokens;
472
+ target.totalTokens += source.totalTokens;
473
+ target.cost += source.cost;
474
+ if (source.costSource === "estimated") target.costSource = "estimated";
475
+ }
476
+ function rollUpSubtree(entry) {
477
+ const order = [];
478
+ const pending2 = [entry];
479
+ while (pending2.length > 0) {
480
+ const node = pending2.pop();
481
+ order.push(node);
482
+ for (const child of node.children) pending2.push(child);
483
+ }
484
+ for (let index = order.length - 1; index >= 0; index -= 1) {
485
+ const node = order[index];
486
+ const stats = node.inclusiveStats;
487
+ let descendants = 0;
488
+ for (const child of node.children) {
489
+ descendants += 1 + child.descendantCount;
490
+ addStats(stats, child.inclusiveStats);
491
+ }
492
+ if (stats.cost > 0 && stats.costSource == null) stats.costSource = "recorded";
493
+ node.descendantCount = descendants;
494
+ }
495
+ }
496
+ function buildSessionTree(sessions) {
497
+ const byRouteKey = /* @__PURE__ */ new Map();
498
+ for (const session of sessions) {
499
+ const key = sessionKey(session);
500
+ if (byRouteKey.has(key)) continue;
501
+ byRouteKey.set(key, {
502
+ session,
503
+ children: [],
504
+ descendantCount: 0,
505
+ inclusiveStats: ownStats(session)
506
+ });
507
+ }
508
+ const nodes = [...byRouteKey.values()];
509
+ const chainTerminates = /* @__PURE__ */ new Map();
510
+ function reachesRoot(startKey) {
511
+ const path = [];
512
+ const onPath = /* @__PURE__ */ new Set();
513
+ let key = startKey;
514
+ let terminates = true;
515
+ while (key != null) {
516
+ const memo = chainTerminates.get(key);
517
+ if (memo != null) {
518
+ terminates = memo;
519
+ break;
520
+ }
521
+ if (onPath.has(key)) {
522
+ terminates = false;
523
+ break;
524
+ }
525
+ onPath.add(key);
526
+ path.push(key);
527
+ const parent = parentKey(byRouteKey.get(key).session);
528
+ key = parent != null && byRouteKey.has(parent) ? parent : null;
529
+ }
530
+ for (const visited of path) chainTerminates.set(visited, terminates);
531
+ return terminates;
532
+ }
533
+ const mountStates = /* @__PURE__ */ new Map();
534
+ const roots = [];
535
+ const orphans = [];
536
+ const entries = [];
537
+ for (const node of nodes) {
538
+ const key = sessionKey(node.session);
539
+ const parent = parentKey(node.session);
540
+ const state = parent == null ? "root" : byRouteKey.has(parent) && reachesRoot(key) ? "mounted-child" : "orphan";
541
+ mountStates.set(key, state);
542
+ if (state === "mounted-child") {
543
+ byRouteKey.get(parent).children.push(node);
544
+ continue;
545
+ }
546
+ (state === "root" ? roots : orphans).push(node);
547
+ entries.push(node);
548
+ }
549
+ for (const entry of entries) rollUpSubtree(entry);
550
+ return {
551
+ roots,
552
+ orphans,
553
+ entries,
554
+ byRouteKey,
555
+ mountStateOf(session) {
556
+ return mountStates.get(sessionKey(session)) ?? (session.parent_reference ? "orphan" : "root");
557
+ }
558
+ };
559
+ }
560
+ function filterSessionTreeByActivityWindow(sessions, from, to, tree = buildSessionTree(sessions)) {
561
+ if (from == null && to == null) return sessions;
562
+ const pending2 = filterSessionTreeEntriesByActivityWindow(tree, from, to);
563
+ const visible = /* @__PURE__ */ new Set();
564
+ while (pending2.length > 0) {
565
+ const node = pending2.pop();
566
+ const key = sessionKey(node.session);
567
+ if (visible.has(key)) continue;
568
+ visible.add(key);
569
+ for (const child of node.children) pending2.push(child);
570
+ }
571
+ return sessions.filter((session) => visible.has(sessionKey(session)));
572
+ }
573
+ function filterSessionTreeEntriesByActivityWindow(tree, from, to) {
574
+ if (from == null && to == null) return tree.entries;
575
+ return tree.entries.filter((node) => hasActivityInWindow(node.session, from, to));
576
+ }
577
+ function createSessionHierarchyGraph(sessions) {
578
+ const sessionsByKey = /* @__PURE__ */ new Map();
579
+ for (const session of sessions) {
580
+ const key = sessionKey(session);
581
+ if (!sessionsByKey.has(key)) sessionsByKey.set(key, session);
582
+ }
583
+ const parentByKey = /* @__PURE__ */ new Map();
584
+ const childrenByKey = /* @__PURE__ */ new Map();
585
+ for (const [key, session] of sessionsByKey) {
586
+ const parent = parentKey(session);
587
+ if (!parent || !sessionsByKey.has(parent)) continue;
588
+ parentByKey.set(key, parent);
589
+ const children = childrenByKey.get(parent);
590
+ if (children) children.push(key);
591
+ else childrenByKey.set(parent, [key]);
592
+ }
593
+ return { sessionsByKey, parentByKey, childrenByKey };
594
+ }
595
+ function collectAffectedHierarchyKeys(graph, seedKeys, includeAncestors, collected) {
596
+ const visited = /* @__PURE__ */ new Set();
597
+ const pending2 = [...seedKeys].filter((key) => graph.sessionsByKey.has(key));
598
+ while (pending2.length > 0) {
599
+ const key = pending2.pop();
600
+ if (visited.has(key)) continue;
601
+ visited.add(key);
602
+ collected.add(key);
603
+ for (const child of graph.childrenByKey.get(key) ?? []) pending2.push(child);
604
+ }
605
+ if (!includeAncestors) return;
606
+ for (const seed of seedKeys) {
607
+ let key = graph.sessionsByKey.has(seed) ? seed : void 0;
608
+ const onPath = /* @__PURE__ */ new Set();
609
+ while (key && !onPath.has(key)) {
610
+ onPath.add(key);
611
+ collected.add(key);
612
+ key = graph.parentByKey.get(key);
613
+ }
614
+ }
615
+ }
616
+ function createSessionProjectionContext(previousSessions, nextSessions, changedSessionHeads, removedSessionRefs) {
617
+ const changedKeys = new Set(
618
+ changedSessionHeads.map(({ reference }) => getSessionReferenceKey(reference))
619
+ );
620
+ const removedKeys = removedSessionRefs.map(getSessionReferenceKey);
621
+ const affectedKeys = /* @__PURE__ */ new Set();
622
+ const previousGraph = createSessionHierarchyGraph(previousSessions);
623
+ const nextGraph = createSessionHierarchyGraph(nextSessions);
624
+ collectAffectedHierarchyKeys(previousGraph, changedKeys, true, affectedKeys);
625
+ collectAffectedHierarchyKeys(nextGraph, changedKeys, true, affectedKeys);
626
+ collectAffectedHierarchyKeys(previousGraph, removedKeys, false, affectedKeys);
627
+ const emitted = /* @__PURE__ */ new Set();
628
+ const relatedSessionHeads = nextSessions.flatMap((session) => {
629
+ const key = sessionKey(session);
630
+ if (!affectedKeys.has(key) || changedKeys.has(key) || emitted.has(key)) return [];
631
+ emitted.add(key);
632
+ return [
633
+ {
634
+ reference: session.reference,
635
+ session
636
+ }
637
+ ];
638
+ });
639
+ const affectedActivityTimes = new Set(
640
+ [...changedSessionHeads, ...relatedSessionHeads].map(({ session }) => activityTime(session))
641
+ );
642
+ const sessionOrder = nextSessions.flatMap(
643
+ (session) => affectedActivityTimes.has(activityTime(session)) ? [session.reference] : []
644
+ );
645
+ return { relatedSessionHeads, sessionOrder };
646
+ }
647
+
648
+ // ../core/dist/chunk-3ENBOS4I.mjs
649
+ function normalizeToolLabel(part) {
650
+ if (part.title?.trim()) {
651
+ return part.title.trim().replace(/^tool:\s*/i, "");
652
+ }
653
+ if (part.tool.trim()) return part.tool.trim();
654
+ return "tool";
655
+ }
656
+ function extractFileActivityOccurrences(messages) {
657
+ const occurrences = [];
658
+ messages.forEach((message, messageIndex) => {
659
+ let toolIndex = 0;
660
+ for (const part of message.parts) {
661
+ if (part.type !== "tool") continue;
662
+ const toolLabel = normalizeToolLabel(part);
663
+ const time = part.time_created ?? message.time_created;
664
+ const currentToolIndex = toolIndex;
665
+ toolIndex += 1;
666
+ for (const { kind, path } of extractFileToolOperations(part)) {
667
+ occurrences.push({
668
+ path,
669
+ kind,
670
+ time,
671
+ tool_label: toolLabel,
672
+ message_index: messageIndex,
673
+ tool_index: currentToolIndex
674
+ });
675
+ }
676
+ }
677
+ });
678
+ return occurrences;
679
+ }
680
+ function summarizeFileActivity(agentName, sessionId, projectIdentityKey, occurrences) {
681
+ const grouped = /* @__PURE__ */ new Map();
682
+ for (const occurrence of occurrences) {
683
+ const key = `${occurrence.kind}\0${occurrence.path}`;
684
+ const current = grouped.get(key);
685
+ if (current) {
686
+ current.count += 1;
687
+ current.latestTime = Math.max(current.latestTime, occurrence.time);
688
+ continue;
689
+ }
690
+ grouped.set(key, {
691
+ reference: { agentName, sessionId },
692
+ projectIdentityKey,
693
+ path: occurrence.path,
694
+ kind: occurrence.kind,
695
+ count: 1,
696
+ latestTime: occurrence.time
697
+ });
698
+ }
699
+ return [...grouped.values()].sort((a, b) => {
700
+ if (b.latestTime !== a.latestTime) return b.latestTime - a.latestTime;
701
+ return a.path.localeCompare(b.path);
702
+ });
703
+ }
704
+ function extractSessionFileActivity(agentName, sessionId, projectIdentityKey, messages) {
705
+ return summarizeFileActivity(
706
+ agentName,
707
+ sessionId,
708
+ projectIdentityKey,
709
+ extractFileActivityOccurrences(messages)
710
+ );
711
+ }
712
+
713
+ // ../core/dist/chunk-WABZHIV5.mjs
714
+ import { chmodSync, existsSync, mkdirSync, readdirSync, statSync } from "fs";
715
+ import { basename, dirname, join } from "path";
716
+ var diagnostics = null;
717
+ function toSafeSink(sink) {
718
+ return {
719
+ info(event, detail) {
720
+ try {
721
+ sink.info?.(event, detail);
722
+ } catch {
723
+ }
724
+ },
725
+ warn(event, detail) {
726
+ try {
727
+ sink.warn(event, detail);
728
+ } catch {
729
+ }
730
+ }
731
+ };
732
+ }
733
+ function setCoreDiagnostics(next) {
734
+ diagnostics = next ? toSafeSink(next) : null;
735
+ }
736
+ function getCoreDiagnostics() {
737
+ return diagnostics;
738
+ }
739
+ var PRIVATE_DIR_MODE = 448;
740
+ var PRIVATE_FILE_MODE = 384;
741
+ var SQLITE_SIDECAR_SUFFIXES = ["-wal", "-shm", "-journal"];
742
+ var isPosix = process.platform !== "win32";
743
+ function reportChmodFailure(path, error) {
744
+ getCoreDiagnostics()?.warn("storage.permissions_failed", {
745
+ path,
746
+ message: error instanceof Error ? error.message : String(error)
747
+ });
748
+ }
749
+ function restrict(path, mode) {
750
+ if (!isPosix || !existsSync(path)) return;
751
+ try {
752
+ if ((statSync(path).mode & 511) === mode) return;
753
+ chmodSync(path, mode);
754
+ } catch (error) {
755
+ reportChmodFailure(path, error);
756
+ }
757
+ }
758
+ function ensurePrivateDirectory(path) {
759
+ mkdirSync(path, { recursive: true, mode: PRIVATE_DIR_MODE });
760
+ restrict(path, PRIVATE_DIR_MODE);
761
+ }
762
+ function restrictPrivateFile(path) {
763
+ restrict(path, PRIVATE_FILE_MODE);
764
+ }
765
+ function restrictExistingPrivateFiles(directory, owns) {
766
+ try {
767
+ for (const entry of readdirSync(directory)) {
768
+ if (owns(entry)) restrictPrivateFile(join(directory, entry));
769
+ }
770
+ } catch (error) {
771
+ reportChmodFailure(directory, error);
772
+ }
773
+ }
774
+ var sweptBackupsFor = /* @__PURE__ */ new Set();
775
+ function restrictExistingBackups(dbPath) {
776
+ if (sweptBackupsFor.has(dbPath)) return;
777
+ sweptBackupsFor.add(dbPath);
778
+ const prefix = `${basename(dbPath)}.`;
779
+ restrictExistingPrivateFiles(
780
+ dirname(dbPath),
781
+ (name) => name.startsWith(prefix) && name.endsWith(".bak")
782
+ );
783
+ }
784
+ function restrictPrivateDatabase(dbPath) {
785
+ restrictPrivateFile(dbPath);
786
+ for (const suffix of SQLITE_SIDECAR_SUFFIXES) restrictPrivateFile(`${dbPath}${suffix}`);
787
+ restrictExistingBackups(dbPath);
788
+ }
789
+
790
+ // ../core/dist/chunk-3JGIS7MJ.mjs
791
+ import { createHash } from "crypto";
792
+ import { existsSync as existsSync2, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
793
+ import { homedir } from "os";
794
+ import { join as join2 } from "path";
795
+ import { AsyncLocalStorage } from "async_hooks";
796
+ var snapshot_default = {
797
+ "claude-3-5-haiku": [8e-7, 4e-6, 1e-6, 8e-8],
798
+ "claude-3-5-sonnet": [3e-6, 15e-6, 375e-8, 3e-7],
799
+ "claude-3-7-sonnet": [3e-6, 15e-6, 375e-8, 3e-7],
800
+ "claude-haiku-4-5": [1e-6, 5e-6, 125e-8, 1e-7],
801
+ "claude-sonnet-4": [3e-6, 15e-6, 375e-8, 3e-7],
802
+ "claude-sonnet-4-5": [3e-6, 15e-6, 375e-8, 3e-7],
803
+ "claude-sonnet-4-6": [3e-6, 15e-6, 375e-8, 3e-7],
804
+ "claude-opus-4": [15e-6, 75e-6, 1875e-8, 15e-7],
805
+ "claude-opus-4-1": [15e-6, 75e-6, 1875e-8, 15e-7],
806
+ "claude-opus-4-5": [5e-6, 25e-6, 625e-8, 5e-7],
807
+ "claude-opus-4-6": [5e-6, 25e-6, 625e-8, 5e-7],
808
+ "claude-opus-4-7": [5e-6, 25e-6, 625e-8, 5e-7],
809
+ "anthropic/claude-sonnet-4-5": [3e-6, 15e-6, 375e-8, 3e-7],
810
+ "anthropic/claude-sonnet-4-6": [3e-6, 15e-6, 375e-8, 3e-7],
811
+ "anthropic/claude-opus-4-6": [5e-6, 25e-6, 625e-8, 5e-7],
812
+ "gpt-4.1": [2e-6, 8e-6, null, 5e-7],
813
+ "gpt-4.1-mini": [4e-7, 16e-7, null, 1e-7],
814
+ "gpt-4.1-nano": [1e-7, 4e-7, null, 25e-9],
815
+ "gpt-4o": [25e-7, 1e-5, null, 125e-8],
816
+ "gpt-4o-mini": [15e-8, 6e-7, null, 75e-9],
817
+ "gpt-5": [125e-8, 1e-5, null, 125e-9],
818
+ "gpt-5.1": [125e-8, 1e-5, null, 125e-9],
819
+ "gpt-5.1-codex": [125e-8, 1e-5, null, 125e-9],
820
+ "gpt-5.1-codex-mini": [25e-8, 2e-6, null, 25e-9],
821
+ "gpt-5.2": [175e-8, 14e-6, null, 175e-9],
822
+ "gpt-5.2-codex": [175e-8, 14e-6, null, 175e-9],
823
+ "gpt-5.3-codex": [175e-8, 14e-6, null, 175e-9],
824
+ "gpt-5.4": [25e-7, 15e-6, null, 25e-8],
825
+ "gpt-5.4-mini": [75e-8, 45e-7, null, 75e-9],
826
+ "gpt-5.4-nano": [2e-7, 125e-8, null, 2e-8],
827
+ "gpt-5.5": [5e-6, 3e-5, null, 5e-7],
828
+ "gpt-5-mini": [25e-8, 2e-6, null, 25e-9],
829
+ "gpt-5-nano": [5e-8, 4e-7, null, 5e-9],
830
+ "moonshotai/kimi-k2-0905": [6e-7, 25e-7, null, null],
831
+ "moonshotai/kimi-k2-instruct": [57e-8, 23e-7, null, null],
832
+ "moonshotai/kimi-k2-thinking": [6e-7, 25e-7, null, null],
833
+ "deepseek-chat": [28e-8, 42e-8, null, 28e-9],
834
+ "deepseek-reasoner": [28e-8, 42e-8, null, 28e-9],
835
+ "qwen3-coder-480b-a35b-instruct": [3e-7, 13e-7, null, null],
836
+ "gemini-2.5-pro": [125e-8, 1e-5, null, 125e-9],
837
+ "gemini-2.5-flash": [3e-7, 25e-7, null, 3e-8]
838
+ };
839
+ var LITELLM_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
840
+ var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
841
+ var WEB_SEARCH_COST = 0.01;
842
+ var REFRESH_TIMEOUT_MS = 1e4;
843
+ var published = createPricingGeneration(loadSnapshot());
844
+ var pending = null;
845
+ published = readDiskCache() ?? published;
846
+ function normalizeModelKey(key) {
847
+ return key.trim().toLowerCase().replaceAll("_", "-");
848
+ }
849
+ function createPricingGeneration(pricing) {
850
+ const hash = createHash("sha256");
851
+ const entries = [...pricing.entries()].sort(
852
+ ([left], [right]) => left < right ? -1 : left > right ? 1 : 0
853
+ );
854
+ for (const [name, modelPricing] of entries) {
855
+ hash.update(name);
856
+ hash.update("\0");
857
+ hash.update(JSON.stringify(modelPricing));
858
+ hash.update("\n");
859
+ }
860
+ return {
861
+ id: Number.parseInt(hash.digest("hex").slice(0, 13), 16) || 1,
862
+ pricing
863
+ };
864
+ }
865
+ function costNumber(value, fallback) {
866
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
867
+ }
868
+ function getCacheDir() {
869
+ return join2(homedir(), ".cache", "codesesh");
870
+ }
871
+ function getCachePath() {
872
+ return join2(getCacheDir(), "litellm-pricing.json");
873
+ }
874
+ function loadSnapshot() {
875
+ const map = /* @__PURE__ */ new Map();
876
+ const snapshot = snapshot_default;
877
+ for (const [name, entry] of Object.entries(snapshot)) {
878
+ const [input, output, cacheCreate, cacheRead, reasoning, webSearch] = entry;
879
+ indexPricing(map, name, {
880
+ inputCostPerToken: input,
881
+ outputCostPerToken: output,
882
+ cacheCreateCostPerToken: cacheCreate ?? input * 1.25,
883
+ cacheReadCostPerToken: cacheRead ?? input * 0.1,
884
+ reasoningCostPerToken: reasoning ?? output,
885
+ webSearchCostPerRequest: webSearch ?? WEB_SEARCH_COST
886
+ });
887
+ }
888
+ return map;
889
+ }
890
+ function parseLiteLLMEntry(entry) {
891
+ const input = entry.input_cost_per_token;
892
+ const output = entry.output_cost_per_token;
893
+ if (typeof input !== "number" || typeof output !== "number") return null;
894
+ return {
895
+ inputCostPerToken: input,
896
+ outputCostPerToken: output,
897
+ cacheCreateCostPerToken: entry.cache_creation_input_token_cost ?? input * 1.25,
898
+ cacheReadCostPerToken: entry.cache_read_input_token_cost ?? input * 0.1,
899
+ reasoningCostPerToken: entry.output_reasoning_cost_per_token ?? output,
900
+ webSearchCostPerRequest: costNumber(
901
+ entry.web_search_cost_per_request ?? entry.search_context_cost_per_query,
902
+ WEB_SEARCH_COST
903
+ )
904
+ };
905
+ }
906
+ function normalizeCachedPricing(raw) {
907
+ const input = costNumber(raw["inputCostPerToken"], 0);
908
+ const output = costNumber(raw["outputCostPerToken"], 0);
909
+ if (input <= 0 || output <= 0) return null;
910
+ return {
911
+ inputCostPerToken: input,
912
+ outputCostPerToken: output,
913
+ cacheCreateCostPerToken: costNumber(raw["cacheCreateCostPerToken"], input * 1.25),
914
+ cacheReadCostPerToken: costNumber(raw["cacheReadCostPerToken"], input * 0.1),
915
+ reasoningCostPerToken: costNumber(raw["reasoningCostPerToken"], output),
916
+ webSearchCostPerRequest: costNumber(raw["webSearchCostPerRequest"], WEB_SEARCH_COST)
917
+ };
918
+ }
919
+ function indexPricing(map, name, pricing) {
920
+ const normalized = normalizeModelKey(name);
921
+ map.set(normalized, pricing);
922
+ const slashIndex = normalized.indexOf("/");
923
+ if (slashIndex >= 0) {
924
+ const stripped = normalized.slice(slashIndex + 1);
925
+ if (!map.has(stripped)) map.set(stripped, pricing);
926
+ }
927
+ }
928
+ function parseLiteLLMData(data) {
929
+ const map = /* @__PURE__ */ new Map();
930
+ for (const [name, entry] of Object.entries(data)) {
931
+ const pricing = parseLiteLLMEntry(entry);
932
+ if (pricing) indexPricing(map, name, pricing);
933
+ }
934
+ return map;
935
+ }
936
+ function readDiskCache() {
937
+ const path = getCachePath();
938
+ if (!existsSync2(path)) return null;
939
+ try {
940
+ const cached = JSON.parse(readFileSync(path, "utf-8"));
941
+ if (!Number.isFinite(cached.timestamp)) return null;
942
+ if (cached.data == null || typeof cached.data !== "object" || Array.isArray(cached.data)) {
943
+ return null;
944
+ }
945
+ const next = loadSnapshot();
946
+ for (const [name, rawPricing] of Object.entries(cached.data)) {
947
+ const pricing = normalizeCachedPricing(rawPricing);
948
+ if (!pricing) continue;
949
+ indexPricing(next, name, pricing);
950
+ }
951
+ return createPricingGeneration(next);
952
+ } catch {
953
+ return null;
954
+ }
955
+ }
956
+ function getPricingRegistry() {
957
+ return published.pricing;
958
+ }
959
+ function getPricingGeneration() {
960
+ return published;
961
+ }
962
+ function synchronizePricingGeneration(expectedId) {
963
+ if (!Number.isSafeInteger(expectedId) || expectedId < 1) {
964
+ throw new Error(`Invalid pricing generation: ${expectedId}`);
965
+ }
966
+ if (published.id === expectedId) return;
967
+ const cached = readDiskCache();
968
+ if (cached?.id !== expectedId) {
969
+ throw new Error(
970
+ `Pricing generation ${expectedId} is unavailable (current ${published.id}, cached ${cached?.id ?? "none"})`
971
+ );
972
+ }
973
+ published = cached;
974
+ getCoreDiagnostics()?.info?.("pricing.generation.synchronized", {
975
+ generation: published.id,
976
+ models: published.pricing.size
977
+ });
978
+ }
979
+ function publishPendingPricing() {
980
+ if (!pending) return false;
981
+ const next = createPricingGeneration(pending);
982
+ if (!writeDiskCacheAtomically(getCachePath(), next)) return false;
983
+ published = next;
984
+ pending = null;
985
+ getCoreDiagnostics()?.info?.("pricing.generation.published", {
986
+ generation: published.id,
987
+ models: published.pricing.size
988
+ });
989
+ return true;
990
+ }
991
+ function hasBillablePricing(pricing) {
992
+ return pricing.inputCostPerToken > 0 || pricing.outputCostPerToken > 0 || pricing.cacheReadCostPerToken > 0 || pricing.cacheCreateCostPerToken > 0;
993
+ }
994
+ function writeDiskCacheAtomically(path, generation) {
995
+ const temporaryPath = `${path}.${process.pid}.tmp`;
996
+ const payload = JSON.stringify({
997
+ timestamp: Date.now(),
998
+ data: Object.fromEntries(generation.pricing)
999
+ });
1000
+ try {
1001
+ ensurePrivateDirectory(getCacheDir());
1002
+ writeFileSync(temporaryPath, payload);
1003
+ restrictPrivateFile(temporaryPath);
1004
+ renameSync(temporaryPath, path);
1005
+ return true;
1006
+ } catch (error) {
1007
+ rmSync(temporaryPath, { force: true });
1008
+ getCoreDiagnostics()?.warn("pricing.cache_write_failed", {
1009
+ message: error instanceof Error ? error.message : String(error)
1010
+ });
1011
+ return false;
1012
+ }
1013
+ }
1014
+ async function refreshPricingCache(options = {}) {
1015
+ const path = getCachePath();
1016
+ if (existsSync2(path)) {
1017
+ try {
1018
+ const cached = JSON.parse(readFileSync(path, "utf-8"));
1019
+ if (typeof cached.timestamp === "number" && Date.now() - cached.timestamp <= CACHE_TTL_MS) {
1020
+ return false;
1021
+ }
1022
+ } catch {
1023
+ }
1024
+ }
1025
+ const timeout = AbortSignal.timeout(options.timeoutMs ?? REFRESH_TIMEOUT_MS);
1026
+ const signal = options.signal ? AbortSignal.any([options.signal, timeout]) : timeout;
1027
+ getCoreDiagnostics()?.info?.("pricing.refresh.started", { generation: published.id });
1028
+ try {
1029
+ const response = await fetch(LITELLM_URL, { signal });
1030
+ if (!response.ok) return false;
1031
+ const data = await response.json();
1032
+ const remote = parseLiteLLMData(data);
1033
+ if (remote.size === 0) return false;
1034
+ const next = loadSnapshot();
1035
+ for (const [name, pricing] of remote.entries()) {
1036
+ next.set(name, pricing);
1037
+ }
1038
+ pending = next;
1039
+ getCoreDiagnostics()?.info?.("pricing.refresh.completed", {
1040
+ generation: published.id,
1041
+ models: next.size
1042
+ });
1043
+ return true;
1044
+ } catch (error) {
1045
+ getCoreDiagnostics()?.warn("pricing.refresh.failed", {
1046
+ generation: published.id,
1047
+ aborted: signal.aborted,
1048
+ message: error instanceof Error ? error.message : String(error)
1049
+ });
1050
+ return false;
1051
+ }
1052
+ }
1053
+ var aliases_default = {
1054
+ "anthropic--claude-4.6-opus": "claude-opus-4-6",
1055
+ "anthropic--claude-4.6-sonnet": "claude-sonnet-4-6",
1056
+ "claude-4.6-sonnet": "claude-sonnet-4-6",
1057
+ "anthropic--claude-4.5-opus": "claude-opus-4-5",
1058
+ "anthropic--claude-4.5-sonnet": "claude-sonnet-4-5",
1059
+ "anthropic--claude-4.5-haiku": "claude-haiku-4-5",
1060
+ "claude-4.5-sonnet-thinking": "claude-sonnet-4-5",
1061
+ "claude-4-sonnet-thinking": "claude-sonnet-4-5",
1062
+ "claude-4-opus": "claude-opus-4-5",
1063
+ "cursor-auto": "claude-sonnet-4-5",
1064
+ "cursor-agent-auto": "claude-sonnet-4-5",
1065
+ "copilot-auto": "claude-sonnet-4-5",
1066
+ "copilot-openai-auto": "gpt-5.3-codex",
1067
+ "copilot-anthropic-auto": "claude-sonnet-4-5",
1068
+ "kimi-for-coding": "moonshotai/kimi-k2-0905",
1069
+ "kimi-k2.5": "moonshotai/kimi-k2-0905",
1070
+ "moonshot-cn/kimi-k2.5": "moonshotai/kimi-k2-0905",
1071
+ "gpt-5-codex": "gpt-5",
1072
+ "gpt-5.1-codex-high": "gpt-5.3-codex",
1073
+ "gpt-5.2-low": "gpt-5.2"
1074
+ };
1075
+ var BUILTIN_ALIASES = Object.fromEntries(
1076
+ Object.entries(aliases_default).map(([key, value]) => [
1077
+ normalizeModelKey(key),
1078
+ normalizeModelKey(value)
1079
+ ])
1080
+ );
1081
+ function stripVersion(model) {
1082
+ return model.replace(/@.*$/, "").replace(/-\d{8}$/, "");
1083
+ }
1084
+ function stripProviderPrefix(model) {
1085
+ const parts = model.split("/");
1086
+ return parts[parts.length - 1] ?? model;
1087
+ }
1088
+ function resolveAlias(model) {
1089
+ return BUILTIN_ALIASES[model] ?? model;
1090
+ }
1091
+ function getCandidates(rawModel) {
1092
+ const withPrefix = stripVersion(normalizeModelKey(rawModel));
1093
+ const stripped = stripProviderPrefix(withPrefix);
1094
+ const aliased = resolveAlias(stripped);
1095
+ const candidates = [
1096
+ withPrefix,
1097
+ resolveAlias(withPrefix),
1098
+ stripped,
1099
+ aliased,
1100
+ `anthropic/${stripped}`,
1101
+ `openai/${stripped}`,
1102
+ `openrouter/openai/${stripped}`,
1103
+ `openrouter/anthropic/${stripped}`,
1104
+ `moonshotai/${stripped}`,
1105
+ `novita/moonshotai/${stripped}`
1106
+ ];
1107
+ return [...new Set(candidates.filter(Boolean))];
1108
+ }
1109
+ function lookupCandidate(model, registry) {
1110
+ const direct = registry.get(model);
1111
+ if (direct && hasBillablePricing(direct)) return direct;
1112
+ const alias = resolveAlias(model);
1113
+ if (alias !== model) {
1114
+ const aliased = registry.get(alias);
1115
+ if (aliased && hasBillablePricing(aliased)) return aliased;
1116
+ }
1117
+ return null;
1118
+ }
1119
+ function fuzzyLookup(model, registry) {
1120
+ let best = null;
1121
+ for (const [key, pricing] of registry.entries()) {
1122
+ if (!hasBillablePricing(pricing)) continue;
1123
+ if (model.startsWith(`${key}-`) || model.startsWith(`${key}@`) || model === key) {
1124
+ if (!best || key.length > best[0].length) best = [key, pricing];
1125
+ }
1126
+ }
1127
+ return best?.[1] ?? null;
1128
+ }
1129
+ var pricingResolver = {
1130
+ resolve(rawModelName) {
1131
+ const registry = getPricingRegistry();
1132
+ const candidates = getCandidates(rawModelName);
1133
+ for (const candidate of candidates) {
1134
+ const pricing = lookupCandidate(candidate, registry);
1135
+ if (pricing) return pricing;
1136
+ }
1137
+ for (const candidate of candidates) {
1138
+ const pricing = fuzzyLookup(candidate, registry);
1139
+ if (pricing) return pricing;
1140
+ }
1141
+ return null;
1142
+ }
1143
+ };
1144
+ function positive(value) {
1145
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
1146
+ }
1147
+ var pricingMissCapture = new AsyncLocalStorage();
1148
+ var PRICING_CAPTURE_EPOCH = "pricing-capture-v1";
1149
+ function pricingBecameAvailable(unpricedModels) {
1150
+ if (!Array.isArray(unpricedModels)) return false;
1151
+ return unpricedModels.some(
1152
+ (model) => typeof model === "string" && pricingResolver.resolve(model) !== null
1153
+ );
1154
+ }
1155
+ function capturePricingMisses(run) {
1156
+ const capture = /* @__PURE__ */ new Set();
1157
+ const result = pricingMissCapture.run(capture, run);
1158
+ if (result instanceof Promise) {
1159
+ return result.then((resolved) => ({ result: resolved, unpricedModels: [...capture] }));
1160
+ }
1161
+ return { result, unpricedModels: [...capture] };
1162
+ }
1163
+ function estimateCostForTokens(model, usage) {
1164
+ if (!model || !usage) return null;
1165
+ const pricing = pricingResolver.resolve(model);
1166
+ if (!pricing) {
1167
+ pricingMissCapture.getStore()?.add(model);
1168
+ return null;
1169
+ }
1170
+ const cacheRead = positive(usage.cache_read);
1171
+ const cacheCreate = positive(usage.cache_create);
1172
+ const input = Math.max(0, positive(usage.input) - cacheRead - cacheCreate);
1173
+ const output = positive(usage.output);
1174
+ const reasoning = positive(usage.reasoning);
1175
+ const webSearchRequests = positive(usage.web_search_requests);
1176
+ const cost = input * pricing.inputCostPerToken + output * pricing.outputCostPerToken + reasoning * pricing.reasoningCostPerToken + cacheRead * pricing.cacheReadCostPerToken + cacheCreate * pricing.cacheCreateCostPerToken + webSearchRequests * pricing.webSearchCostPerRequest;
1177
+ return cost > 0 ? { cost: Number(cost.toFixed(8)), source: "estimated" } : null;
1178
+ }
1179
+
1180
+ // ../core/dist/chunk-326ZXYCY.mjs
1181
+ import { closeSync, openSync, readSync } from "fs";
1182
+ import { StringDecoder } from "string_decoder";
1183
+ import { basename as basename2 } from "path";
1184
+ var PerfTracer = class {
1185
+ rootMarkers = [];
1186
+ activeStack = [];
1187
+ enabled = false;
1188
+ enable() {
1189
+ this.enabled = true;
1190
+ }
1191
+ start(name) {
1192
+ const marker = {
1193
+ name,
1194
+ startTime: performance.now(),
1195
+ children: []
1196
+ };
1197
+ if (!this.enabled) return marker;
1198
+ const parent = this.activeStack[this.activeStack.length - 1];
1199
+ if (parent) {
1200
+ marker.parent = parent;
1201
+ parent.children.push(marker);
1202
+ } else {
1203
+ this.rootMarkers.push(marker);
1204
+ }
1205
+ this.activeStack.push(marker);
1206
+ return marker;
1207
+ }
1208
+ end(marker) {
1209
+ if (!this.enabled) return;
1210
+ const target = marker ?? this.activeStack[this.activeStack.length - 1];
1211
+ if (!target) return;
1212
+ target.endTime = performance.now();
1213
+ target.duration = target.endTime - target.startTime;
1214
+ while (this.activeStack.length > 0) {
1215
+ const popped = this.activeStack.pop();
1216
+ if (popped === target) break;
1217
+ }
1218
+ }
1219
+ measure(name, fn) {
1220
+ const marker = this.start(name);
1221
+ try {
1222
+ return fn();
1223
+ } finally {
1224
+ this.end(marker);
1225
+ }
1226
+ }
1227
+ async measureAsync(name, fn) {
1228
+ const marker = this.start(name);
1229
+ try {
1230
+ return await fn();
1231
+ } finally {
1232
+ this.end(marker);
1233
+ }
1234
+ }
1235
+ getReport() {
1236
+ if (!this.enabled) return "Performance tracing disabled";
1237
+ const lines = [];
1238
+ lines.push("\n=== Performance Report ===\n");
1239
+ for (const marker of this.rootMarkers) {
1240
+ this.formatMarker(marker, 0, lines);
1241
+ }
1242
+ return lines.join("\n");
1243
+ }
1244
+ formatMarker(marker, depth, lines) {
1245
+ const indent = " ".repeat(depth);
1246
+ const duration = marker.duration?.toFixed(2) ?? "?";
1247
+ lines.push(`${indent}${marker.name}: ${duration}ms`);
1248
+ for (const child of marker.children) {
1249
+ this.formatMarker(child, depth + 1, lines);
1250
+ }
1251
+ }
1252
+ reset() {
1253
+ this.rootMarkers = [];
1254
+ this.activeStack = [];
1255
+ }
1256
+ };
1257
+ var perf = new PerfTracer();
1258
+ var READ_CHUNK_BYTES = 1 << 20;
1259
+ function* parseJsonlLines(content) {
1260
+ let total = 0;
1261
+ let skipped = 0;
1262
+ for (const line of content.split("\n")) {
1263
+ const trimmed = line.trim();
1264
+ if (!trimmed) continue;
1265
+ total += 1;
1266
+ try {
1267
+ yield JSON.parse(trimmed);
1268
+ } catch {
1269
+ skipped += 1;
1270
+ }
1271
+ }
1272
+ if (skipped > 0) {
1273
+ getCoreDiagnostics()?.warn("agent.jsonl_lines_skipped", { skipped, total });
1274
+ }
1275
+ }
1276
+ function* readJsonlFileLines(filePath, chunkBytes = READ_CHUNK_BYTES) {
1277
+ const fd = openSync(filePath, "r");
1278
+ try {
1279
+ const buffer = Buffer.alloc(chunkBytes);
1280
+ const decoder = new StringDecoder("utf8");
1281
+ let pending2 = [];
1282
+ let bytesRead = readSync(fd, buffer, 0, chunkBytes, -1);
1283
+ while (bytesRead > 0) {
1284
+ const decoded = decoder.write(buffer.subarray(0, bytesRead));
1285
+ const lastBreak = decoded.lastIndexOf("\n");
1286
+ if (lastBreak === -1) {
1287
+ if (decoded) pending2.push(decoded);
1288
+ } else {
1289
+ pending2.push(decoded.slice(0, lastBreak));
1290
+ const complete = pending2.join("");
1291
+ pending2 = [decoded.slice(lastBreak + 1)];
1292
+ for (const line of complete.split("\n")) {
1293
+ const trimmed = line.trim();
1294
+ if (trimmed) yield trimmed;
1295
+ }
1296
+ }
1297
+ bytesRead = readSync(fd, buffer, 0, chunkBytes, -1);
1298
+ }
1299
+ pending2.push(decoder.end());
1300
+ const tail = pending2.join("").trim();
1301
+ if (tail) yield tail;
1302
+ } finally {
1303
+ closeSync(fd);
1304
+ }
1305
+ }
1306
+ function* readJsonlFile(filePath) {
1307
+ let total = 0;
1308
+ let skipped = 0;
1309
+ for (const line of readJsonlFileLines(filePath)) {
1310
+ total += 1;
1311
+ try {
1312
+ yield JSON.parse(line);
1313
+ } catch {
1314
+ skipped += 1;
1315
+ }
1316
+ }
1317
+ if (skipped > 0) {
1318
+ getCoreDiagnostics()?.warn("agent.jsonl_lines_skipped", { skipped, total, filePath });
1319
+ }
1320
+ }
1321
+ var INTERNAL_BLOCK_TAGS = [
1322
+ "command-message",
1323
+ "command-name",
1324
+ "local-command-caveat",
1325
+ "local-command-stdout",
1326
+ "system-reminder"
1327
+ ];
1328
+ var TRANSPARENT_TAGS = ["command-args"];
1329
+ var INTERNAL_EVENT_TYPES = /* @__PURE__ */ new Set([
1330
+ "progress",
1331
+ "file history snapshot",
1332
+ "file-history snapshot",
1333
+ "file_history snapshot",
1334
+ "queue operation",
1335
+ "queue-operation",
1336
+ "queue_operation",
1337
+ "last prompt",
1338
+ "last-prompt",
1339
+ "last_prompt"
1340
+ ]);
1341
+ function blockTagPattern(tag) {
1342
+ return new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*?<\\/${tag}>`, "gi");
1343
+ }
1344
+ function blockTagLinePattern(tag) {
1345
+ return new RegExp(
1346
+ `(^|\\r?\\n)[ \\t]*<${tag}\\b[^>]*>[\\s\\S]*?<\\/${tag}>[ \\t]*(?:\\r?\\n|$)`,
1347
+ "gi"
1348
+ );
1349
+ }
1350
+ function openBlockTagPattern(tag) {
1351
+ return new RegExp(`\\n*<${tag}\\b[^>]*>[\\s\\S]*$`, "gi");
1352
+ }
1353
+ function looseTagPattern(tag) {
1354
+ return new RegExp(`<\\/?${tag}\\b[^>]*>`, "gi");
1355
+ }
1356
+ function isInternalEventType(value) {
1357
+ if (typeof value !== "string") return false;
1358
+ const normalized = value.trim().toLowerCase().replace(/[_-]+/g, " ");
1359
+ return INTERNAL_EVENT_TYPES.has(normalized);
1360
+ }
1361
+ function cleanDisplayText(text) {
1362
+ let cleaned = text;
1363
+ for (const tag of INTERNAL_BLOCK_TAGS) {
1364
+ cleaned = cleaned.replace(blockTagLinePattern(tag), "$1");
1365
+ cleaned = cleaned.replace(blockTagPattern(tag), "");
1366
+ cleaned = cleaned.replace(openBlockTagPattern(tag), "");
1367
+ }
1368
+ for (const tag of INTERNAL_BLOCK_TAGS) {
1369
+ cleaned = cleaned.replace(looseTagPattern(tag), "");
1370
+ }
1371
+ for (const tag of TRANSPARENT_TAGS) {
1372
+ cleaned = cleaned.replace(looseTagPattern(tag), "");
1373
+ }
1374
+ cleaned = cleaned.replace(/[ \t]+(?=\r?\n|$)/g, "").replace(/(?:\r?\n)+$/g, "");
1375
+ return cleaned.trim() ? cleaned : null;
1376
+ }
1377
+ var TITLE_MAX_LENGTH = 100;
1378
+ var UNTITLED_SESSION = "Untitled Session";
1379
+ function normalizeTitleText(text) {
1380
+ const visible = cleanDisplayText(text)?.split("\n").find((line) => line.trim())?.trim() ?? null;
1381
+ if (!visible) return null;
1382
+ const cleaned = visible.replace(/\s+/g, " ").trim();
1383
+ if (!cleaned) return null;
1384
+ return cleaned.slice(0, TITLE_MAX_LENGTH);
1385
+ }
1386
+ function basenameTitle(path) {
1387
+ if (!path) return null;
1388
+ const normalized = path.trim().replace(/[/\\]+$/, "");
1389
+ if (!normalized) return null;
1390
+ const name = basename2(normalized).trim();
1391
+ return name || null;
1392
+ }
1393
+ function resolveSessionTitle(explicit, message, directory) {
1394
+ for (const candidate of [explicit, message, directory]) {
1395
+ if (candidate) {
1396
+ const normalized = normalizeTitleText(candidate);
1397
+ if (normalized) return normalized;
1398
+ }
1399
+ }
1400
+ return UNTITLED_SESSION;
1401
+ }
1402
+ function estimateTokenCost(model, tokens) {
1403
+ return estimateCostForTokens(model, tokens)?.cost ?? null;
1404
+ }
1405
+ function asRecord(value) {
1406
+ if (value && typeof value === "object" && !Array.isArray(value)) {
1407
+ return value;
1408
+ }
1409
+ return void 0;
1410
+ }
1411
+ function asString(value) {
1412
+ return typeof value === "string" ? value : void 0;
1413
+ }
1414
+ function asNumber(value) {
1415
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1416
+ }
1417
+ function asArray(value) {
1418
+ return Array.isArray(value) ? value : void 0;
1419
+ }
1420
+ function safeParseJsonRecord(json) {
1421
+ let raw;
1422
+ try {
1423
+ raw = JSON.parse(json);
1424
+ } catch {
1425
+ return void 0;
1426
+ }
1427
+ return asRecord(raw);
1428
+ }
1429
+ var reportedFieldMismatches = /* @__PURE__ */ new Set();
1430
+ function reportFieldMismatch(agentName, field) {
1431
+ const key = `${agentName}\0${field}`;
1432
+ if (reportedFieldMismatches.has(key)) return;
1433
+ reportedFieldMismatches.add(key);
1434
+ getCoreDiagnostics()?.warn("agent.field_shape_mismatch", { agentName, field });
1435
+ }
1436
+ function narrowField(agent, field, value, narrow) {
1437
+ if (value === void 0 || value === null) return void 0;
1438
+ const result = narrow(value);
1439
+ if (result === void 0) reportFieldMismatch(agent, field);
1440
+ return result;
1441
+ }
1442
+ function isInternalEventType2(value) {
1443
+ return isInternalEventType(value);
1444
+ }
1445
+ function cleanInternalText(text) {
1446
+ return cleanDisplayText(text) ?? "";
1447
+ }
1448
+ function cleanUnknown(value) {
1449
+ if (typeof value === "string") return cleanInternalText(value);
1450
+ if (Array.isArray(value)) return value.map(cleanUnknown);
1451
+ if (!value || typeof value !== "object") return value;
1452
+ const cleaned = {};
1453
+ for (const [key, child] of Object.entries(value)) {
1454
+ cleaned[key] = cleanUnknown(child);
1455
+ }
1456
+ return cleaned;
1457
+ }
1458
+ function cleanMessagePart(part) {
1459
+ if (part.type === "text" || part.type === "reasoning" || part.type === "plan") {
1460
+ const text = cleanInternalText(part.text);
1461
+ return text ? { ...part, text } : null;
1462
+ }
1463
+ if (part.type !== "tool") return part;
1464
+ const title = part.title ? cleanInternalText(part.title) : "";
1465
+ const state = {
1466
+ ...part.state,
1467
+ ...part.state.input !== void 0 ? { input: cleanUnknown(part.state.input) } : {},
1468
+ ...part.state.output !== void 0 ? { output: cleanUnknown(part.state.output) } : {},
1469
+ ...part.state.error !== void 0 ? { error: cleanUnknown(part.state.error) } : {},
1470
+ ...part.state.metadata !== void 0 ? { metadata: cleanUnknown(part.state.metadata) } : {}
1471
+ };
1472
+ const { title: _title, ...withoutTitle } = part;
1473
+ return {
1474
+ ...withoutTitle,
1475
+ ...title ? { title } : {},
1476
+ state
1477
+ };
1478
+ }
1479
+ function cleanMessageParts(parts) {
1480
+ return parts.flatMap((part) => {
1481
+ const cleaned = cleanMessagePart(part);
1482
+ return cleaned ? [cleaned] : [];
1483
+ });
1484
+ }
1485
+ function cleanParsedMessage(message) {
1486
+ const parts = cleanMessageParts(message.parts);
1487
+ if (parts.length === 0) return null;
1488
+ return { ...message, parts };
1489
+ }
1490
+ function cleanParsedMessages(messages) {
1491
+ return messages.flatMap((message) => {
1492
+ const cleaned = cleanParsedMessage(message);
1493
+ return cleaned ? [cleaned] : [];
1494
+ });
1495
+ }
1496
+ function firstUserMessageTitle(messages) {
1497
+ for (const message of messages) {
1498
+ if (message.role !== "user") continue;
1499
+ for (const part of message.parts) {
1500
+ if (part.type !== "text") continue;
1501
+ const title = normalizeTitleText(cleanInternalText(part.text));
1502
+ if (title) return title;
1503
+ }
1504
+ }
1505
+ return null;
1506
+ }
1507
+
1508
+ // ../core/dist/chunk-BAU7ZBXA.mjs
1509
+ import { existsSync as existsSync3 } from "fs";
1510
+ import { basename as basename3, dirname as dirname2, join as join3 } from "path";
1511
+ import { createRequire } from "module";
1512
+ var SQLITE_BUSY_TIMEOUT_MS = 5e3;
1513
+ var DatabaseConstructor = null;
1514
+ var loadErrorMessage = null;
1515
+ try {
1516
+ const require2 = createRequire(import.meta.url);
1517
+ const mod = require2("better-sqlite3");
1518
+ DatabaseConstructor = typeof mod === "function" ? mod : mod.default;
1519
+ } catch (error) {
1520
+ loadErrorMessage = error instanceof Error ? error.message : String(error);
1521
+ }
1522
+ var unavailableReported = false;
1523
+ function reportUnavailableOnce() {
1524
+ if (unavailableReported) return;
1525
+ unavailableReported = true;
1526
+ getCoreDiagnostics()?.warn("sqlite.unavailable", { message: loadErrorMessage });
1527
+ }
1528
+ var SchemaMigrationPlanError = class extends Error {
1529
+ constructor(message) {
1530
+ super(message);
1531
+ this.name = "SchemaMigrationPlanError";
1532
+ }
1533
+ };
1534
+ function validateSchemaVersion(value, label) {
1535
+ if (Number.isSafeInteger(value) && value >= 0) return;
1536
+ throw new SchemaMigrationPlanError(`${label} must be a non-negative safe integer`);
1537
+ }
1538
+ function validateMigrationPlan(options) {
1539
+ let previousVersion = -1;
1540
+ let reachesTarget = false;
1541
+ for (const migration of options.migrations) {
1542
+ if (!Number.isSafeInteger(migration.version) || migration.version < 0) {
1543
+ throw new SchemaMigrationPlanError(
1544
+ `${options.backupLabel} migration version must be a non-negative safe integer`
1545
+ );
1546
+ }
1547
+ if (migration.version <= previousVersion) {
1548
+ throw new SchemaMigrationPlanError(
1549
+ `${options.backupLabel} migrations must be ordered by strictly increasing version`
1550
+ );
1551
+ }
1552
+ previousVersion = migration.version;
1553
+ reachesTarget ||= migration.version === options.targetVersion;
1554
+ }
1555
+ if (!reachesTarget) {
1556
+ throw new SchemaMigrationPlanError(
1557
+ `${options.backupLabel} has no migration for target version ${options.targetVersion}`
1558
+ );
1559
+ }
1560
+ }
1561
+ function quoteIdentifier(value) {
1562
+ return `"${value.replaceAll('"', '""')}"`;
1563
+ }
1564
+ function quoteSqlString(value) {
1565
+ return `'${value.replaceAll("'", "''")}'`;
1566
+ }
1567
+ function isInMemoryPath(dbPath) {
1568
+ return dbPath === ":memory:" || dbPath.startsWith("file::memory:") || dbPath.includes("mode=memory");
1569
+ }
1570
+ function getUserVersion(db) {
1571
+ const row = db.prepare("PRAGMA user_version").get();
1572
+ return Number(row?.user_version ?? 0);
1573
+ }
1574
+ function setUserVersion(db, version) {
1575
+ db.exec(`PRAGMA user_version = ${Math.trunc(version)}`);
1576
+ }
1577
+ function tableExists(db, tableName) {
1578
+ const row = db.prepare(
1579
+ `
1580
+ SELECT 1 AS value
1581
+ FROM sqlite_master
1582
+ WHERE name = ? AND type IN ('table', 'view')
1583
+ LIMIT 1
1584
+ `
1585
+ ).get(tableName);
1586
+ return row !== void 0;
1587
+ }
1588
+ function columnExists(db, tableName, columnName) {
1589
+ if (!tableExists(db, tableName)) {
1590
+ return false;
1591
+ }
1592
+ const rows = db.prepare(`PRAGMA table_info(${quoteIdentifier(tableName)})`).all();
1593
+ return rows.some((row) => String(row.name) === columnName);
1594
+ }
1595
+ function tableHasRows(db, tableName) {
1596
+ if (!tableExists(db, tableName)) {
1597
+ return false;
1598
+ }
1599
+ const row = db.prepare(`SELECT 1 AS value FROM ${quoteIdentifier(tableName)} LIMIT 1`).get();
1600
+ return row !== void 0;
1601
+ }
1602
+ function backupDatabase(db, dbPath, label) {
1603
+ if (isInMemoryPath(dbPath)) {
1604
+ return null;
1605
+ }
1606
+ const timestamp = new Date(Date.now()).toISOString().replaceAll(":", "").replaceAll(".", "-");
1607
+ let backupPath = join3(dirname2(dbPath), `${basename3(dbPath)}.${timestamp}.${label}.bak`);
1608
+ for (let counter = 1; existsSync3(backupPath); counter += 1) {
1609
+ backupPath = join3(dirname2(dbPath), `${basename3(dbPath)}.${timestamp}.${label}.${counter}.bak`);
1610
+ }
1611
+ db.exec(`VACUUM INTO ${quoteSqlString(backupPath)}`);
1612
+ restrictPrivateFile(backupPath);
1613
+ return backupPath;
1614
+ }
1615
+ function backupDatabaseIfPopulated(db, dbPath, label, tables) {
1616
+ if (!tables.some((table) => tableHasRows(db, table))) {
1617
+ return null;
1618
+ }
1619
+ return backupDatabase(db, dbPath, label);
1620
+ }
1621
+ function runSchemaMigrations(db, options) {
1622
+ const backups = [];
1623
+ let currentVersion = options.currentVersion;
1624
+ validateSchemaVersion(currentVersion, `${options.backupLabel} current version`);
1625
+ validateSchemaVersion(options.targetVersion, `${options.backupLabel} target version`);
1626
+ if (currentVersion >= options.targetVersion) return backups;
1627
+ validateMigrationPlan(options);
1628
+ for (const migration of options.migrations) {
1629
+ if (migration.version <= currentVersion) {
1630
+ continue;
1631
+ }
1632
+ if (migration.version > options.targetVersion) {
1633
+ break;
1634
+ }
1635
+ const fromVersion = currentVersion;
1636
+ const startedAt = performance.now();
1637
+ getCoreDiagnostics()?.info?.("sqlite.migration.started", {
1638
+ label: options.backupLabel,
1639
+ from_version: fromVersion,
1640
+ to_version: migration.version,
1641
+ destructive: migration.destructive ?? false
1642
+ });
1643
+ try {
1644
+ let backupCreated = false;
1645
+ if (migration.destructive) {
1646
+ const backupPath = backupDatabaseIfPopulated(
1647
+ db,
1648
+ options.dbPath,
1649
+ options.backupLabel,
1650
+ options.backupTables
1651
+ );
1652
+ if (backupPath) {
1653
+ backups.push(backupPath);
1654
+ backupCreated = true;
1655
+ }
1656
+ }
1657
+ const apply = db.transaction(() => {
1658
+ migration.migrate(db);
1659
+ setUserVersion(db, migration.version);
1660
+ });
1661
+ apply.immediate();
1662
+ currentVersion = migration.version;
1663
+ getCoreDiagnostics()?.info?.("sqlite.migration.completed", {
1664
+ label: options.backupLabel,
1665
+ from_version: fromVersion,
1666
+ to_version: migration.version,
1667
+ destructive: migration.destructive ?? false,
1668
+ backup_created: backupCreated,
1669
+ duration_ms: Math.round(performance.now() - startedAt)
1670
+ });
1671
+ } catch (error) {
1672
+ getCoreDiagnostics()?.warn("sqlite.migration.failed", {
1673
+ label: options.backupLabel,
1674
+ from_version: fromVersion,
1675
+ to_version: migration.version,
1676
+ destructive: migration.destructive ?? false,
1677
+ duration_ms: Math.round(performance.now() - startedAt),
1678
+ message: error instanceof Error ? error.message : String(error)
1679
+ });
1680
+ throw error;
1681
+ }
1682
+ }
1683
+ if (currentVersion !== options.targetVersion) {
1684
+ throw new SchemaMigrationPlanError(
1685
+ `${options.backupLabel} stopped at version ${currentVersion}, expected ${options.targetVersion}`
1686
+ );
1687
+ }
1688
+ return backups;
1689
+ }
1690
+ function openDbReadOnly(dbPath) {
1691
+ if (!DatabaseConstructor) {
1692
+ reportUnavailableOnce();
1693
+ return null;
1694
+ }
1695
+ try {
1696
+ const db = DatabaseConstructor(dbPath, { readonly: true });
1697
+ try {
1698
+ db.pragma(`busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS}`);
1699
+ } catch {
1700
+ }
1701
+ return db;
1702
+ } catch (error) {
1703
+ getCoreDiagnostics()?.warn("sqlite.open_failed", {
1704
+ dbPath,
1705
+ readonly: true,
1706
+ message: error instanceof Error ? error.message : String(error)
1707
+ });
1708
+ return null;
1709
+ }
1710
+ }
1711
+ function openDb(dbPath) {
1712
+ if (!DatabaseConstructor) {
1713
+ reportUnavailableOnce();
1714
+ return null;
1715
+ }
1716
+ try {
1717
+ ensurePrivateDirectory(dirname2(dbPath));
1718
+ if (!isInMemoryPath(dbPath)) process.env.SQLITE_TMPDIR ||= dirname2(dbPath);
1719
+ const db = DatabaseConstructor(dbPath);
1720
+ restrictPrivateDatabase(dbPath);
1721
+ try {
1722
+ db.pragma(`busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS}`);
1723
+ db.pragma("journal_mode = WAL");
1724
+ db.pragma("synchronous = NORMAL");
1725
+ db.pragma("foreign_keys = ON");
1726
+ db.pragma("temp_store = FILE");
1727
+ } catch {
1728
+ }
1729
+ return db;
1730
+ } catch (error) {
1731
+ getCoreDiagnostics()?.warn("sqlite.open_failed", {
1732
+ dbPath,
1733
+ readonly: false,
1734
+ message: error instanceof Error ? error.message : String(error)
1735
+ });
1736
+ return null;
1737
+ }
1738
+ }
1739
+ function isSqliteAvailable() {
1740
+ return DatabaseConstructor !== null;
1741
+ }
1742
+
1743
+ // ../core/dist/chunk-PIUQAREY.mjs
1744
+ function toRecord2(value) {
1745
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
1746
+ }
1747
+ function optionalString(value) {
1748
+ return typeof value === "string" && value ? value : void 0;
1749
+ }
1750
+ function optionalTime(value) {
1751
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1752
+ }
1753
+ function timeField(time_created) {
1754
+ return time_created === void 0 ? {} : { time_created };
1755
+ }
1756
+ function firstDefined(...values) {
1757
+ return values.find((value) => value !== void 0);
1758
+ }
1759
+ function normalizeStatus(state, output, error) {
1760
+ const status = state.status;
1761
+ if (status === "running" || status === "completed" || status === "error") return status;
1762
+ if (status === "success") return "completed";
1763
+ if (error != null) return "error";
1764
+ if (output !== void 0) return "completed";
1765
+ return "running";
1766
+ }
1767
+ function normalizeMetadata(state) {
1768
+ const rawMetadata = state.metadata ?? state.meta;
1769
+ const extras = Object.fromEntries(
1770
+ Object.entries(state).filter(
1771
+ ([key]) => !["status", "input", "arguments", "output", "result", "error", "metadata", "meta"].includes(
1772
+ key
1773
+ )
1774
+ )
1775
+ );
1776
+ if (Object.keys(extras).length === 0) return rawMetadata;
1777
+ const metadata = toRecord2(rawMetadata);
1778
+ return metadata ? { ...metadata, ...extras } : extras;
1779
+ }
1780
+ function normalizeToolState(value, legacyPart) {
1781
+ const state = toRecord2(value) ?? {};
1782
+ const input = firstDefined(state.input, state.arguments, legacyPart.input);
1783
+ const output = firstDefined(state.output, state.result, legacyPart.output);
1784
+ const error = state.error;
1785
+ const metadata = normalizeMetadata(state);
1786
+ return {
1787
+ status: normalizeStatus(state, output, error),
1788
+ ...input !== void 0 ? { input } : {},
1789
+ ...output !== void 0 ? { output } : {},
1790
+ ...error !== void 0 ? { error } : {},
1791
+ ...metadata !== void 0 ? { metadata } : {}
1792
+ };
1793
+ }
1794
+ function planText(value) {
1795
+ if (typeof value === "string") return value;
1796
+ const record = toRecord2(value);
1797
+ if (!record) return "";
1798
+ return planText(record.text ?? record.plan ?? record.content);
1799
+ }
1800
+ function normalizePlanPart(value, time_created) {
1801
+ const approval_status = value.approval_status === "fail" ? "fail" : "success";
1802
+ const text = planText(value.text ?? (approval_status === "fail" ? value.output : value.input));
1803
+ return text ? { type: "plan", text, approval_status, ...timeField(time_created) } : null;
1804
+ }
1805
+ function normalizeImagePart(value, time_created) {
1806
+ const data = optionalString(value.data);
1807
+ const url = optionalString(value.url);
1808
+ const mime_type = optionalString(value.mime_type);
1809
+ if (data && mime_type) {
1810
+ return {
1811
+ type: "image",
1812
+ data,
1813
+ mime_type,
1814
+ ...url ? { url } : {},
1815
+ ...timeField(time_created)
1816
+ };
1817
+ }
1818
+ if (url) {
1819
+ return {
1820
+ type: "image",
1821
+ url,
1822
+ ...data ? { data } : {},
1823
+ ...mime_type ? { mime_type } : {},
1824
+ ...timeField(time_created)
1825
+ };
1826
+ }
1827
+ return null;
1828
+ }
1829
+ function normalizeToolPart(value, time_created) {
1830
+ const title = optionalString(value.title);
1831
+ const callID = optionalString(value.callID);
1832
+ const tool = optionalString(value.tool)?.trim() || title?.replace(/^tool:\s*/i, "").trim();
1833
+ if (!tool) return null;
1834
+ return {
1835
+ type: "tool",
1836
+ tool,
1837
+ ...title ? { title } : {},
1838
+ ...callID ? { callID } : {},
1839
+ state: normalizeToolState(value.state, value),
1840
+ ...timeField(time_created)
1841
+ };
1842
+ }
1843
+ function normalizeMessagePart(value) {
1844
+ const part = toRecord2(value);
1845
+ if (!part) return null;
1846
+ const time_created = optionalTime(part.time_created);
1847
+ if (part.type === "text" || part.type === "reasoning") {
1848
+ if (typeof part.text !== "string") return null;
1849
+ return { type: part.type, text: part.text, ...timeField(time_created) };
1850
+ }
1851
+ if (part.type === "plan") return normalizePlanPart(part, time_created);
1852
+ if (part.type === "image") return normalizeImagePart(part, time_created);
1853
+ if (part.type === "tool") return normalizeToolPart(part, time_created);
1854
+ return null;
1855
+ }
1856
+ function normalizeMessageParts(value) {
1857
+ if (!Array.isArray(value)) return [];
1858
+ return value.flatMap((part) => {
1859
+ const normalized = normalizeMessagePart(part);
1860
+ return normalized ? [normalized] : [];
1861
+ });
1862
+ }
1863
+
1864
+ // ../core/dist/chunk-IKDMAP3N.mjs
1865
+ var AGENT_CATALOG = [
1866
+ {
1867
+ name: "claudecode",
1868
+ displayName: "Claude Code",
1869
+ icon: "/icon/agent/claudecode.svg",
1870
+ iconColored: true,
1871
+ sourceKind: "filesystem",
1872
+ resumeCommandPrefix: "claude --resume",
1873
+ toolStrategy: "custom"
1874
+ },
1875
+ {
1876
+ name: "cursor",
1877
+ displayName: "Cursor",
1878
+ icon: "/icon/agent/cursor.svg",
1879
+ sourceKind: "sqlite",
1880
+ resumeCommandPrefix: null,
1881
+ toolStrategy: "custom"
1882
+ },
1883
+ {
1884
+ name: "kimi",
1885
+ displayName: "Kimi-Cli",
1886
+ icon: "/icon/agent/kimi.svg",
1887
+ sourceKind: "filesystem",
1888
+ resumeCommandPrefix: "kimi -r",
1889
+ toolStrategy: "custom"
1890
+ },
1891
+ {
1892
+ name: "kimi-code",
1893
+ displayName: "Kimi-Code",
1894
+ icon: "/icon/agent/kimi.svg",
1895
+ sourceKind: "filesystem",
1896
+ resumeCommandPrefix: "kimi -r",
1897
+ toolStrategy: "custom"
1898
+ },
1899
+ {
1900
+ name: "codex",
1901
+ displayName: "Codex",
1902
+ icon: "/icon/agent/codex.svg",
1903
+ sourceKind: "filesystem",
1904
+ resumeCommandPrefix: "codex resume",
1905
+ toolStrategy: "custom"
1906
+ },
1907
+ {
1908
+ name: "grok",
1909
+ displayName: "Grok",
1910
+ icon: "/icon/agent/grok.svg",
1911
+ sourceKind: "filesystem",
1912
+ resumeCommandPrefix: "grok --resume",
1913
+ toolStrategy: "custom"
1914
+ },
1915
+ {
1916
+ name: "pi",
1917
+ displayName: "Pi",
1918
+ icon: "/icon/agent/pi.svg",
1919
+ sourceKind: "filesystem",
1920
+ resumeCommandPrefix: "pi --session",
1921
+ toolStrategy: "custom"
1922
+ },
1923
+ {
1924
+ name: "opencode",
1925
+ displayName: "OpenCode",
1926
+ icon: "/icon/agent/opencode.svg",
1927
+ sourceKind: "sqlite",
1928
+ resumeCommandPrefix: "opencode -s",
1929
+ toolStrategy: "custom"
1930
+ },
1931
+ {
1932
+ name: "zcode",
1933
+ displayName: "ZCode",
1934
+ icon: "/icon/agent/zcode.svg",
1935
+ sourceKind: "sqlite",
1936
+ resumeCommandPrefix: null,
1937
+ toolStrategy: "custom"
1938
+ },
1939
+ {
1940
+ name: "dsh",
1941
+ displayName: "DSH",
1942
+ icon: "/icon/agent/dsh.svg",
1943
+ iconColored: true,
1944
+ sourceKind: "filesystem",
1945
+ // DSH delegates launch arguments to installation-specific profiles.
1946
+ resumeCommandPrefix: null,
1947
+ toolStrategy: "custom"
1948
+ }
1949
+ ];
1950
+ function getAgentCatalogEntry(name) {
1951
+ const entry = AGENT_CATALOG.find((candidate) => candidate.name === name);
1952
+ if (!entry) throw new Error(`Unknown agent catalog entry: ${name}`);
1953
+ return entry;
1954
+ }
1955
+
1956
+ export {
1957
+ SMART_TAGS,
1958
+ isSmartTag,
1959
+ assertIdentifiedSessionHead,
1960
+ toPublicSessionHead,
1961
+ toPublicReferencedSessionHead,
1962
+ SMART_TAG_CLASSIFIER_REVISION,
1963
+ getSmartTagSourceTimestamp,
1964
+ classifySessionTags,
1965
+ WORKER_LOG_MESSAGE_TYPE,
1966
+ isWorkerLogMessage,
1967
+ normalizeSessionReference,
1968
+ formatSessionReference,
1969
+ getSessionReferenceKey,
1970
+ createSessionIdentity,
1971
+ assertSessionIdentity,
1972
+ getSessionAgentKey,
1973
+ sessionRoutePath,
1974
+ mergeSessionsUpdatedEvents,
1975
+ startOfCalendarDay,
1976
+ addCalendarDays,
1977
+ countCalendarDays,
1978
+ toCalendarDayKey,
1979
+ isProjectIdentityKind,
1980
+ getProjectIdentityKey,
1981
+ matchesProjectIdentity,
1982
+ sortSessionsByActivity,
1983
+ mergeSortedSessions,
1984
+ createSessionIndex,
1985
+ buildSessionTree,
1986
+ filterSessionTreeByActivityWindow,
1987
+ filterSessionTreeEntriesByActivityWindow,
1988
+ createSessionProjectionContext,
1989
+ extractSessionFileActivity,
1990
+ setCoreDiagnostics,
1991
+ getCoreDiagnostics,
1992
+ ensurePrivateDirectory,
1993
+ restrictPrivateFile,
1994
+ restrictExistingPrivateFiles,
1995
+ getPricingGeneration,
1996
+ synchronizePricingGeneration,
1997
+ publishPendingPricing,
1998
+ refreshPricingCache,
1999
+ PRICING_CAPTURE_EPOCH,
2000
+ pricingBecameAvailable,
2001
+ capturePricingMisses,
2002
+ perf,
2003
+ parseJsonlLines,
2004
+ readJsonlFileLines,
2005
+ readJsonlFile,
2006
+ isInternalEventType,
2007
+ normalizeTitleText,
2008
+ basenameTitle,
2009
+ resolveSessionTitle,
2010
+ estimateTokenCost,
2011
+ asRecord,
2012
+ asString,
2013
+ asNumber,
2014
+ asArray,
2015
+ safeParseJsonRecord,
2016
+ reportFieldMismatch,
2017
+ narrowField,
2018
+ isInternalEventType2,
2019
+ cleanInternalText,
2020
+ cleanMessagePart,
2021
+ cleanParsedMessages,
2022
+ firstUserMessageTitle,
2023
+ getUserVersion,
2024
+ setUserVersion,
2025
+ tableExists,
2026
+ columnExists,
2027
+ runSchemaMigrations,
2028
+ openDbReadOnly,
2029
+ openDb,
2030
+ isSqliteAvailable,
2031
+ normalizeMessageParts,
2032
+ AGENT_CATALOG,
2033
+ getAgentCatalogEntry
2034
+ };
2035
+ //# sourceMappingURL=chunk-W4PZHL2C.js.map