codesesh 1.0.8 → 1.0.10

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 (53) hide show
  1. package/README.md +19 -0
  2. package/dist/{chunk-YLXHGL4S.js → chunk-2LXZFMSH.js} +28 -2
  3. package/dist/{chunk-YLXHGL4S.js.map → chunk-2LXZFMSH.js.map} +1 -1
  4. package/dist/{chunk-L4G3LE7I.js → chunk-543OWZIC.js} +2 -2
  5. package/dist/{chunk-DHQPM5FF.js → chunk-56FKVL5K.js} +5 -5
  6. package/dist/{chunk-V3HKVTIO.js → chunk-CYZ6OC6J.js} +2 -2
  7. package/dist/{chunk-KVTLNX7V.js → chunk-DWY4HWVI.js} +2 -2
  8. package/dist/{chunk-AGUAXTKC.js → chunk-R6QKSHPH.js} +2 -2
  9. package/dist/{chunk-RBCCNCDO.js → chunk-WRVILHZR.js} +1059 -26
  10. package/dist/chunk-WRVILHZR.js.map +1 -0
  11. package/dist/{discovery-KEZQU6RL.js → discovery-NTMSA6UE.js} +5 -5
  12. package/dist/index.js +36 -9
  13. package/dist/index.js.map +1 -1
  14. package/dist/project-identity-worker.js +4 -4
  15. package/dist/scan-refresh-worker.js +6 -6
  16. package/dist/search-index-worker.js +6 -6
  17. package/dist/session-detail-worker.js +6 -6
  18. package/dist/smart-tag-worker.js +3 -3
  19. package/dist/web/assets/CustomTimeWindowDialog-CGPvUFkc.js +1 -0
  20. package/dist/web/assets/DetailLanding-D1FLK4EW.js +1 -0
  21. package/dist/web/assets/{InteractiveReceipt-Bsj37HtN.js → InteractiveReceipt-C7FJhzdv.js} +1 -1
  22. package/dist/web/assets/OverviewScreen-DX7F_6dH.js +1 -0
  23. package/dist/web/assets/{PrismHighlighter-DWS6Nx_X.js → PrismHighlighter-DZ2CWVc0.js} +1 -1
  24. package/dist/web/assets/Projects-B_7w5TDw.js +1 -0
  25. package/dist/web/assets/{SearchResultsPanel-BAManMmt.js → SearchResultsPanel-BMBhKuPS.js} +1 -1
  26. package/dist/web/assets/SessionDetail-wJYzzF0i.js +53 -0
  27. package/dist/web/assets/index-BXhaumu7.css +1 -0
  28. package/dist/web/assets/index-DUcpWdzX.js +1423 -0
  29. package/dist/web/assets/{panel-DcOuALYX.js → panel-B-5dVddJ.js} +1 -1
  30. package/dist/web/assets/session-indexes-3LjxBYNe.js +4 -0
  31. package/dist/web/assets/utils-BuYa9y6l.js +1 -0
  32. package/dist/web/icon/agent/cherrystudio.svg +7 -0
  33. package/dist/web/icon/agent/deepchat.LICENSE.txt +206 -0
  34. package/dist/web/icon/agent/deepchat.svg +6 -0
  35. package/dist/web/icon/agent/minimax-code.svg +1 -0
  36. package/dist/web/index.html +5 -192
  37. package/package.json +3 -3
  38. package/dist/chunk-RBCCNCDO.js.map +0 -1
  39. package/dist/web/assets/CustomTimeWindowDialog-z5xtqkBF.js +0 -1
  40. package/dist/web/assets/DetailLanding-CpV0jLmT.js +0 -1
  41. package/dist/web/assets/OverviewScreen-B9qZqEQA.js +0 -1
  42. package/dist/web/assets/Projects-oY3KCgS4.js +0 -1
  43. package/dist/web/assets/SessionDetail-KSgkmLV7.js +0 -53
  44. package/dist/web/assets/index-BSLHxV0w.css +0 -1
  45. package/dist/web/assets/index-DNw59Qsn.js +0 -1423
  46. package/dist/web/assets/session-indexes-DKukxoe1.js +0 -4
  47. package/dist/web/assets/utils-Dk_44zMo.js +0 -1
  48. /package/dist/{chunk-L4G3LE7I.js.map → chunk-543OWZIC.js.map} +0 -0
  49. /package/dist/{chunk-DHQPM5FF.js.map → chunk-56FKVL5K.js.map} +0 -0
  50. /package/dist/{chunk-V3HKVTIO.js.map → chunk-CYZ6OC6J.js.map} +0 -0
  51. /package/dist/{chunk-KVTLNX7V.js.map → chunk-DWY4HWVI.js.map} +0 -0
  52. /package/dist/{chunk-AGUAXTKC.js.map → chunk-R6QKSHPH.js.map} +0 -0
  53. /package/dist/{discovery-KEZQU6RL.js.map → discovery-NTMSA6UE.js.map} +0 -0
@@ -32,14 +32,14 @@ import {
32
32
  reportFieldMismatch,
33
33
  resolveSessionTitle,
34
34
  safeParseJsonRecord
35
- } from "./chunk-YLXHGL4S.js";
35
+ } from "./chunk-2LXZFMSH.js";
36
36
 
37
- // ../core/dist/chunk-V6GZEKLJ.mjs
37
+ // ../core/dist/chunk-XW3NUJH2.mjs
38
38
  import { statSync } from "fs";
39
39
  import { readdirSync, statSync as statSync2 } from "fs";
40
40
  import { join } from "path";
41
41
  import { existsSync as existsSync2, readFileSync, statSync as statSync3 } from "fs";
42
- import { join as join3, basename, dirname } from "path";
42
+ import { join as join3, basename, dirname, isAbsolute as isAbsolute2, relative, sep } from "path";
43
43
  import { existsSync } from "fs";
44
44
  import { homedir, platform } from "os";
45
45
  import { isAbsolute, join as join2, resolve } from "path";
@@ -68,6 +68,15 @@ import * as zlib from "zlib";
68
68
  import { createHash as createHash2 } from "crypto";
69
69
  import { readFileSync as readFileSync8 } from "fs";
70
70
  import { join as join13 } from "path";
71
+ import { createHash as createHash3 } from "crypto";
72
+ import { homedir as homedir4, platform as platform4 } from "os";
73
+ import { join as join15 } from "path";
74
+ import { createHash as createHash4 } from "crypto";
75
+ import { homedir as homedir5, platform as platform5 } from "os";
76
+ import { join as join16 } from "path";
77
+ import { createHash as createHash5 } from "crypto";
78
+ import { homedir as homedir6 } from "os";
79
+ import { join as join17 } from "path";
71
80
  function fingerprintMatches(ref, cached) {
72
81
  return typeof cached?.sourceFingerprint === "string" && cached.sourceFingerprint === ref.fingerprint;
73
82
  }
@@ -913,9 +922,9 @@ var ClaudeRecordConverter = class {
913
922
  if (partType !== "tool_use") continue;
914
923
  const toolCallId = String(part["id"] ?? "").trim();
915
924
  const subagentId = childSessionIdByToolUseId.get(toolCallId);
916
- const toolPart2 = this.buildToolPart(part, timestampMs);
925
+ const toolPart3 = this.buildToolPart(part, timestampMs);
917
926
  const message = builder.appendToolCall(
918
- toolPart2,
927
+ toolPart3,
919
928
  { id: uuid, timestampMs, agent: "claude", subagentId, model },
920
929
  { modeOnCreate: "tool" }
921
930
  );
@@ -1423,6 +1432,16 @@ var ClaudeCodeAgent = class extends SingleFileSessionSource {
1423
1432
  }
1424
1433
  return false;
1425
1434
  }
1435
+ filterCachedSessions(sessions) {
1436
+ const basePath = this.basePath ?? this.findBasePath();
1437
+ if (!basePath) return sessions;
1438
+ return sessions.filter((session) => {
1439
+ const sourcePath = this.sessionMetaMap.get(session.reference.sessionId)?.sourcePath;
1440
+ if (!sourcePath) return true;
1441
+ const path = relative(basePath, sourcePath);
1442
+ return path !== ".." && !path.startsWith(`..${sep}`) && !isAbsolute2(path);
1443
+ });
1444
+ }
1426
1445
  listSessionSources(options) {
1427
1446
  if (!this.basePath) return [];
1428
1447
  const projectDirs = this.listProjectDirs();
@@ -2421,12 +2440,12 @@ var KimiUsageAccumulator = class {
2421
2440
  totalCost = 0;
2422
2441
  applyContextRecord(record) {
2423
2442
  if (record.role !== "_usage") return;
2424
- const tokenCount2 = asNumber(record.token_count);
2425
- if (tokenCount2 === void 0) {
2443
+ const tokenCount3 = asNumber(record.token_count);
2444
+ if (tokenCount3 === void 0) {
2426
2445
  reportFieldMismatch("kimi", "usage.token_count");
2427
2446
  return;
2428
2447
  }
2429
- this.stats.total_tokens = tokenCount2;
2448
+ this.stats.total_tokens = tokenCount3;
2430
2449
  }
2431
2450
  applyWireRecord(record) {
2432
2451
  if (this.usesWireTotalFallback) this.applyContextRecord(record);
@@ -2843,7 +2862,7 @@ var KimiAgent = class extends FileSystemSessionSource {
2843
2862
  const rawArgs = function_.arguments;
2844
2863
  const normalizedArgs = normalizeToolArguments(rawArgs);
2845
2864
  const buffer = typeof rawArgs === "string" && typeof normalizedArgs !== "string" ? rawArgs : null;
2846
- const toolPart2 = {
2865
+ const toolPart3 = {
2847
2866
  type: "tool",
2848
2867
  tool: toolName,
2849
2868
  callID: callId,
@@ -2852,7 +2871,7 @@ var KimiAgent = class extends FileSystemSessionSource {
2852
2871
  time_created: timestampMs
2853
2872
  };
2854
2873
  builder.appendToolCall(
2855
- toolPart2,
2874
+ toolPart3,
2856
2875
  { id: `wire-${seq}`, timestampMs, agent: "kimi" },
2857
2876
  { markModeAsTool: true, target: "current" }
2858
2877
  );
@@ -4176,7 +4195,7 @@ var CodexRecordConverter = class {
4176
4195
  if (!name) return;
4177
4196
  const toolIdentity = resolveToolIdentity(name, payload["namespace"]);
4178
4197
  const arguments_ = normalizeToolArguments(payload["arguments"]);
4179
- const toolPart2 = {
4198
+ const toolPart3 = {
4180
4199
  type: "tool",
4181
4200
  tool: toolIdentity.tool,
4182
4201
  callID: callId,
@@ -4190,7 +4209,7 @@ var CodexRecordConverter = class {
4190
4209
  time_created: timestampMs
4191
4210
  };
4192
4211
  transcript.appendToolCall(
4193
- toolPart2,
4212
+ toolPart3,
4194
4213
  { id: "", timestampMs, agent: "codex", model: activeModel },
4195
4214
  { markModeAsTool: true }
4196
4215
  );
@@ -4222,7 +4241,7 @@ var CodexRecordConverter = class {
4222
4241
  const toolIdentity = resolveToolIdentity(name, payload["namespace"]);
4223
4242
  const rawInput = payload["input"];
4224
4243
  const normalizedInput = normalizeCustomToolArguments(name, rawInput);
4225
- const toolPart2 = {
4244
+ const toolPart3 = {
4226
4245
  type: "tool",
4227
4246
  tool: toolIdentity.tool,
4228
4247
  callID: callId,
@@ -4236,7 +4255,7 @@ var CodexRecordConverter = class {
4236
4255
  time_created: timestampMs
4237
4256
  };
4238
4257
  transcript.appendToolCall(
4239
- toolPart2,
4258
+ toolPart3,
4240
4259
  { id: "", timestampMs, agent: "codex", model: activeModel },
4241
4260
  { markModeAsTool: true }
4242
4261
  );
@@ -4253,7 +4272,7 @@ var CodexRecordConverter = class {
4253
4272
  const { name, namespace } = splitExecToolName(call.name);
4254
4273
  const toolIdentity = resolveToolIdentity(name, namespace);
4255
4274
  const arguments_ = name === "apply_patch" ? parseApplyPatchInput(getExecPatchText(call.args)) : call.args;
4256
- const toolPart2 = {
4275
+ const toolPart3 = {
4257
4276
  type: "tool",
4258
4277
  tool: toolIdentity.tool,
4259
4278
  callID: callId,
@@ -4267,7 +4286,7 @@ var CodexRecordConverter = class {
4267
4286
  time_created: timestampMs
4268
4287
  };
4269
4288
  transcript.appendToolCall(
4270
- toolPart2,
4289
+ toolPart3,
4271
4290
  { id: "", timestampMs, agent: "codex", model: activeModel },
4272
4291
  { markModeAsTool: true }
4273
4292
  );
@@ -5109,7 +5128,7 @@ function parseBubbleRow(value) {
5109
5128
  const record = safeParseJsonRecord(value);
5110
5129
  if (!record) return null;
5111
5130
  const timingInfo = asRecord(record.timingInfo);
5112
- const tokenCount2 = asRecord(record.tokenCount);
5131
+ const tokenCount3 = asRecord(record.tokenCount);
5113
5132
  const modelInfo = asRecord(record.modelInfo);
5114
5133
  const toolFormerData = asRecord(record.toolFormerData);
5115
5134
  return {
@@ -5133,9 +5152,9 @@ function parseBubbleRow(value) {
5133
5152
  ),
5134
5153
  clientEndTime: narrowNumber("bubble.timingInfo.clientEndTime", timingInfo.clientEndTime)
5135
5154
  } : void 0,
5136
- tokenCount: tokenCount2 ? {
5137
- inputTokens: narrowNumber("bubble.tokenCount.inputTokens", tokenCount2.inputTokens),
5138
- outputTokens: narrowNumber("bubble.tokenCount.outputTokens", tokenCount2.outputTokens)
5155
+ tokenCount: tokenCount3 ? {
5156
+ inputTokens: narrowNumber("bubble.tokenCount.inputTokens", tokenCount3.inputTokens),
5157
+ outputTokens: narrowNumber("bubble.tokenCount.outputTokens", tokenCount3.outputTokens)
5139
5158
  } : void 0,
5140
5159
  modelInfo: modelInfo ? { modelName: narrowString("bubble.modelInfo.modelName", modelInfo.modelName) } : void 0,
5141
5160
  toolFormerData: toolFormerData ? {
@@ -5717,9 +5736,9 @@ var CursorAgent = class extends DatabaseSessionSource {
5717
5736
  parts.push({ type: "text", text, time_created: timestampMs });
5718
5737
  }
5719
5738
  if (bubble.toolFormerData) {
5720
- const toolPart2 = this.convertToolFormerData(bubble.toolFormerData, timestampMs);
5721
- if (toolPart2) {
5722
- parts.push(toolPart2);
5739
+ const toolPart3 = this.convertToolFormerData(bubble.toolFormerData, timestampMs);
5740
+ if (toolPart3) {
5741
+ parts.push(toolPart3);
5723
5742
  }
5724
5743
  }
5725
5744
  if (parts.length === 0) continue;
@@ -6193,7 +6212,7 @@ var PiAgent = class extends SingleFileSessionSource {
6193
6212
  if (type === "toolCall") {
6194
6213
  const callId = String(item["id"] ?? "").trim();
6195
6214
  const toolName = String(item["name"] ?? "").trim() || "tool";
6196
- const toolPart2 = {
6215
+ const toolPart3 = {
6197
6216
  type: "tool",
6198
6217
  tool: toolName,
6199
6218
  title: `Tool: ${toolName}`,
@@ -6204,7 +6223,7 @@ var PiAgent = class extends SingleFileSessionSource {
6204
6223
  input: item["arguments"] ?? {}
6205
6224
  }
6206
6225
  };
6207
- parts.push(toolPart2);
6226
+ parts.push(toolPart3);
6208
6227
  }
6209
6228
  }
6210
6229
  return parts;
@@ -8305,7 +8324,1013 @@ function isMissingDirectory(error) {
8305
8324
  const code = error.code;
8306
8325
  return code === "ENOENT" || code === "ENOTDIR";
8307
8326
  }
8327
+ function parseDeepChatJson(value) {
8328
+ if (typeof value !== "string") return value;
8329
+ try {
8330
+ return JSON.parse(value);
8331
+ } catch {
8332
+ return value;
8333
+ }
8334
+ }
8335
+ function deepChatTokens(metadata) {
8336
+ const input = asNumber(metadata.inputTokens);
8337
+ const output = asNumber(metadata.outputTokens);
8338
+ if (input === void 0 && output === void 0) return void 0;
8339
+ const cacheRead = Math.max(0, asNumber(metadata.cachedInputTokens) ?? 0);
8340
+ const cacheCreate = Math.max(0, asNumber(metadata.cacheWriteInputTokens) ?? 0);
8341
+ return {
8342
+ input: Math.max(0, input ?? 0),
8343
+ output: Math.max(0, output ?? 0),
8344
+ cache_read: Math.min(cacheRead, Math.max(0, input ?? 0)),
8345
+ cache_create: Math.min(cacheCreate, Math.max(0, (input ?? 0) - cacheRead))
8346
+ };
8347
+ }
8348
+ function deepChatAssistantPart(block) {
8349
+ const time_created = asNumber(block.timestamp);
8350
+ const content = asString(block.content);
8351
+ if (block.type === "tool_call") {
8352
+ const tool = asRecord(block.tool_call);
8353
+ if (!tool) return null;
8354
+ const status = block.status === "pending" || block.status === "loading" ? "running" : block.status === "error" || block.status === "denied" ? "error" : "completed";
8355
+ const output = parseDeepChatJson(tool.response);
8356
+ return {
8357
+ type: "tool",
8358
+ tool: asString(tool.name) ?? "unknown",
8359
+ callID: asString(tool.id),
8360
+ time_created,
8361
+ state: {
8362
+ status,
8363
+ input: parseDeepChatJson(tool.params),
8364
+ output,
8365
+ error: status === "error" ? output ?? content : void 0,
8366
+ metadata: asRecord(block.extra)
8367
+ }
8368
+ };
8369
+ }
8370
+ if (block.type === "image") {
8371
+ const image = asRecord(block.image_data);
8372
+ const data = asString(image?.data);
8373
+ const mime = asString(image?.mimeType);
8374
+ if (data && mime) return { type: "image", data, mime_type: mime, time_created };
8375
+ }
8376
+ if (!content) return null;
8377
+ return {
8378
+ type: block.type === "reasoning_content" ? "reasoning" : "text",
8379
+ text: content,
8380
+ time_created
8381
+ };
8382
+ }
8383
+ function deepChatStoredBlockPart(row) {
8384
+ const extra = asRecord(parseDeepChatJson(row.extra_json));
8385
+ return deepChatAssistantPart({
8386
+ type: row.block_type,
8387
+ content: row.text_content,
8388
+ status: row.status,
8389
+ timestamp: extra?.timestamp ?? row.updated_at,
8390
+ extra: extra?.extra,
8391
+ tool_call: {
8392
+ id: row.tool_call_id,
8393
+ name: row.tool_name,
8394
+ params: row.tool_params,
8395
+ response: row.tool_response
8396
+ },
8397
+ image_data: { data: extra?.imageData, mimeType: row.image_mime_type }
8398
+ });
8399
+ }
8400
+ function deepChatUserParts(content) {
8401
+ const parts = [];
8402
+ const text = asString(content.text);
8403
+ if (text) parts.push({ type: "text", text });
8404
+ for (const file of asArray(content.files) ?? []) {
8405
+ const record = asRecord(file);
8406
+ const path = asString(record?.path);
8407
+ const name = asString(record?.name);
8408
+ if (path || name) parts.push({ type: "text", text: `Attachment: ${path ?? name}` });
8409
+ }
8410
+ for (const link of asArray(content.links) ?? []) {
8411
+ if (typeof link === "string") parts.push({ type: "text", text: link });
8412
+ }
8413
+ return parts;
8414
+ }
8415
+ function deepChatRawParts(role, content) {
8416
+ const parsed = parseDeepChatJson(content);
8417
+ if (role === "user") {
8418
+ const user = asRecord(parsed);
8419
+ if (user) return deepChatUserParts(user);
8420
+ }
8421
+ if (Array.isArray(parsed)) {
8422
+ const parts = [];
8423
+ for (const value of parsed) {
8424
+ const block = asRecord(value);
8425
+ const part = block ? deepChatAssistantPart(block) : null;
8426
+ if (part) parts.push(part);
8427
+ }
8428
+ return parts;
8429
+ }
8430
+ return typeof parsed === "string" && parsed ? [{ type: "text", text: parsed }] : [];
8431
+ }
8432
+ var AGENT_METADATA11 = getAgentCatalogEntry("deepchat");
8433
+ function resolveDeepChatDataRoot() {
8434
+ const configured = readEnvPath("DEEPCHAT_USER_DATA_DIR");
8435
+ if (configured) return configured;
8436
+ if (platform4() === "darwin") return join15(homedir4(), "Library", "Application Support", "DeepChat");
8437
+ if (platform4() === "win32") {
8438
+ return join15(readEnvPath("APPDATA") ?? join15(homedir4(), "AppData", "Roaming"), "DeepChat");
8439
+ }
8440
+ return join15(readEnvPath("XDG_CONFIG_HOME") ?? join15(homedir4(), ".config"), "DeepChat");
8441
+ }
8442
+ function accumulateUsage(session, row) {
8443
+ const model = asString(row.model) ?? session.model;
8444
+ const provider = asString(row.provider) ?? session.provider;
8445
+ const tokens = deepChatTokens(row);
8446
+ if (!tokens && asNumber(row.totalTokens) === void 0) return;
8447
+ const input = tokens?.input ?? 0;
8448
+ const output = tokens?.output ?? 0;
8449
+ const total = Math.max(0, asNumber(row.totalTokens) ?? input + output);
8450
+ const { result: estimate, unpricedModels } = capturePricingMisses(
8451
+ () => estimateTokenCost(model, tokens)
8452
+ );
8453
+ for (const missing of unpricedModels) session.unpricedModels.add(missing);
8454
+ const cost = estimate ?? 0;
8455
+ const stats = session.head.stats;
8456
+ stats.total_input_tokens += input;
8457
+ stats.total_output_tokens += output;
8458
+ stats.total_tokens = (stats.total_tokens ?? 0) + total;
8459
+ stats.total_cache_read_tokens = (stats.total_cache_read_tokens ?? 0) + (tokens?.cache_read ?? 0);
8460
+ stats.total_cache_create_tokens = (stats.total_cache_create_tokens ?? 0) + (tokens?.cache_create ?? 0);
8461
+ stats.total_cost += cost;
8462
+ if (cost > 0) stats.cost_source = "estimated";
8463
+ if (model && total > 0) {
8464
+ const usage = session.head.model_usage ??= /* @__PURE__ */ Object.create(null);
8465
+ usage[model] = (usage[model] ?? 0) + total;
8466
+ }
8467
+ const messageId = asString(row.message_id);
8468
+ if (!messageId) return;
8469
+ const previous = session.messageUsage.get(messageId);
8470
+ session.messageUsage.set(messageId, {
8471
+ model,
8472
+ provider,
8473
+ cost: (previous?.cost ?? 0) + cost,
8474
+ tokens: {
8475
+ input: (previous?.tokens.input ?? 0) + input,
8476
+ output: (previous?.tokens.output ?? 0) + output,
8477
+ cache_read: (previous?.tokens.cache_read ?? 0) + (tokens?.cache_read ?? 0),
8478
+ cache_create: (previous?.tokens.cache_create ?? 0) + (tokens?.cache_create ?? 0)
8479
+ }
8480
+ });
8481
+ }
8482
+ var DeepChatAgent = class extends DatabaseSessionSource {
8483
+ name = AGENT_METADATA11.name;
8484
+ displayName = AGENT_METADATA11.displayName;
8485
+ sourceRoot;
8486
+ constructor(options = {}) {
8487
+ super();
8488
+ this.sourceRoot = options.sourceRoot ?? resolveDeepChatDataRoot();
8489
+ }
8490
+ getDatabasePath() {
8491
+ return firstExisting(join15(this.sourceRoot, "app_db", "agent.db"));
8492
+ }
8493
+ isAvailable() {
8494
+ return isSqliteAvailable() && this.getDatabasePath() !== null;
8495
+ }
8496
+ getSessionWatchPlan() {
8497
+ return {
8498
+ status: "supported",
8499
+ targets: [{ root: this.sourceRoot, path: join15(this.sourceRoot, "app_db", "agent.db") }]
8500
+ };
8501
+ }
8502
+ readDatabase(read) {
8503
+ const path = this.getDatabasePath();
8504
+ if (!path) throw new Error("DeepChat agent.db is missing");
8505
+ return this.scanStep("reading unencrypted DeepChat agent.db", path, () => {
8506
+ const db = openDbReadOnly(path);
8507
+ if (!db)
8508
+ throw new Error("Cannot open DeepChat agent.db; only unencrypted databases are supported");
8509
+ try {
8510
+ return db.transaction(() => read(db))();
8511
+ } finally {
8512
+ db.close();
8513
+ }
8514
+ });
8515
+ }
8516
+ scan(options) {
8517
+ if (!this.getDatabasePath()) return [];
8518
+ return this.readDatabase((db) => {
8519
+ const projections = this.readProjections(db);
8520
+ const selected = /* @__PURE__ */ new Set();
8521
+ const children = /* @__PURE__ */ new Map();
8522
+ for (const [id, projection] of projections) {
8523
+ const parent = projection.head.parent_reference?.sessionId;
8524
+ if (parent && projections.has(parent)) {
8525
+ const siblings = children.get(parent) ?? [];
8526
+ siblings.push(id);
8527
+ children.set(parent, siblings);
8528
+ } else if (matchesScanWindow(projection.head.time_updated ?? projection.head.time_created, options)) {
8529
+ selected.add(id);
8530
+ }
8531
+ }
8532
+ if (options?.includeRelatedSessions !== false) {
8533
+ for (const id of selected) {
8534
+ for (const child of children.get(id) ?? []) selected.add(child);
8535
+ }
8536
+ }
8537
+ const sessions = [];
8538
+ for (const id of selected) {
8539
+ const projection = projections.get(id);
8540
+ if (projection.head.stats.message_count === 0) continue;
8541
+ this.rememberSession(id, {
8542
+ sourceFingerprint: projection.signature.digest("hex"),
8543
+ headParserVersion: "deepchat-v1",
8544
+ unpricedModels: [...projection.unpricedModels]
8545
+ });
8546
+ sessions.push(projection.head);
8547
+ }
8548
+ sessions.sort(
8549
+ (left, right) => (right.time_updated ?? 0) - (left.time_updated ?? 0) || left.reference.sessionId.localeCompare(right.reference.sessionId)
8550
+ );
8551
+ options?.onProgress?.({
8552
+ total: selected.size,
8553
+ processed: selected.size,
8554
+ sessions: sessions.length
8555
+ });
8556
+ return sessions;
8557
+ });
8558
+ }
8559
+ readProjections(db, sessionId) {
8560
+ const filter = sessionId ? "AND s.id = ?" : "";
8561
+ const bindings = sessionId ? [sessionId] : [];
8562
+ const projections = /* @__PURE__ */ new Map();
8563
+ const sessions = db.prepare(`
8564
+ SELECT s.id, s.agent_id, s.title, s.project_dir, s.parent_session_id,
8565
+ s.created_at, s.updated_at, s.revision, d.model_id, d.provider_id
8566
+ FROM new_sessions s LEFT JOIN deepchat_sessions d ON d.id = s.id
8567
+ WHERE s.is_draft = 0 ${filter}
8568
+ ORDER BY s.id
8569
+ `).iterate(...bindings);
8570
+ for (const row of sessions) {
8571
+ const id = String(row.id);
8572
+ const parent = asString(row.parent_session_id);
8573
+ projections.set(id, {
8574
+ head: {
8575
+ ...this.sessionIdentity(id),
8576
+ title: resolveSessionTitle(asString(row.title), null, null),
8577
+ directory: asString(row.project_dir) ?? "",
8578
+ parent_reference: parent ? { agentName: this.name, sessionId: parent } : void 0,
8579
+ time_created: Number(row.created_at),
8580
+ time_updated: Number(row.updated_at),
8581
+ stats: { message_count: 0, total_input_tokens: 0, total_output_tokens: 0, total_cost: 0 }
8582
+ },
8583
+ agentId: String(row.agent_id),
8584
+ model: asString(row.model_id) ?? null,
8585
+ provider: asString(row.provider_id) ?? null,
8586
+ signature: createHash3("sha256").update(JSON.stringify(row)),
8587
+ unpricedModels: /* @__PURE__ */ new Set(),
8588
+ messageUsage: /* @__PURE__ */ new Map()
8589
+ });
8590
+ }
8591
+ const usageRows = db.prepare(`
8592
+ SELECT u.session_id, u.message_id, u.usage_id, u.created_at, u.updated_at,
8593
+ u.model_id AS model, u.provider_id AS provider,
8594
+ u.input_tokens AS inputTokens, u.output_tokens AS outputTokens,
8595
+ u.total_tokens AS totalTokens, u.cached_input_tokens AS cachedInputTokens,
8596
+ u.cache_write_input_tokens AS cacheWriteInputTokens
8597
+ FROM deepchat_usage_stats u JOIN new_sessions s ON s.id = u.session_id
8598
+ WHERE s.is_draft = 0 ${filter}
8599
+ ORDER BY u.session_id, u.usage_id
8600
+ `).iterate(...bindings);
8601
+ for (const row of usageRows) {
8602
+ const projection = projections.get(String(row.session_id));
8603
+ accumulateUsage(projection, row);
8604
+ projection.signature.update(JSON.stringify(row));
8605
+ projection.head.time_updated = Math.max(
8606
+ projection.head.time_updated ?? 0,
8607
+ Number(row.created_at)
8608
+ );
8609
+ }
8610
+ const messageRows = db.prepare(`
8611
+ SELECT m.id, m.session_id, m.order_seq, m.role, m.status, m.metadata, m.updated_at
8612
+ FROM deepchat_messages m JOIN new_sessions s ON s.id = m.session_id
8613
+ WHERE s.is_draft = 0 ${filter}
8614
+ ORDER BY m.session_id, m.order_seq, m.id
8615
+ `).iterate(...bindings);
8616
+ for (const row of messageRows) {
8617
+ const projection = projections.get(String(row.session_id));
8618
+ projection.signature.update(JSON.stringify(row));
8619
+ projection.head.stats.message_count += 1;
8620
+ projection.head.time_updated = Math.max(
8621
+ projection.head.time_updated ?? 0,
8622
+ Number(row.updated_at)
8623
+ );
8624
+ const metadata = asRecord(parseDeepChatJson(row.metadata));
8625
+ if (row.role === "assistant" && metadata && !projection.messageUsage.has(String(row.id))) {
8626
+ accumulateUsage(projection, { ...metadata, message_id: row.id });
8627
+ }
8628
+ }
8629
+ const blockActivity = db.prepare(`
8630
+ SELECT m.session_id, COUNT(*) AS block_count, MAX(b.updated_at) AS updated_at,
8631
+ SUM(b.updated_at) AS block_revision
8632
+ FROM deepchat_assistant_blocks b
8633
+ JOIN deepchat_messages m ON m.id = b.message_id
8634
+ JOIN new_sessions s ON s.id = m.session_id
8635
+ WHERE s.is_draft = 0 ${filter}
8636
+ GROUP BY m.session_id ORDER BY m.session_id
8637
+ `).iterate(...bindings);
8638
+ for (const row of blockActivity) {
8639
+ const projection = projections.get(String(row.session_id));
8640
+ projection.signature.update(JSON.stringify(row));
8641
+ projection.head.time_updated = Math.max(
8642
+ projection.head.time_updated ?? 0,
8643
+ Number(row.updated_at)
8644
+ );
8645
+ }
8646
+ return projections;
8647
+ }
8648
+ getSessionData(sessionId) {
8649
+ return this.readDatabase((db) => {
8650
+ const projection = this.readProjections(db, sessionId).get(sessionId);
8651
+ if (!projection) throw new Error(`DeepChat session not found: ${sessionId}`);
8652
+ const partsByMessage = this.readStructuredParts(db, sessionId);
8653
+ const rows = db.prepare(`
8654
+ SELECT id, role, content, metadata, status, created_at, updated_at
8655
+ FROM deepchat_messages WHERE session_id = ? ORDER BY order_seq, id
8656
+ `).iterate(sessionId);
8657
+ const messages = [];
8658
+ for (const row of rows) {
8659
+ if (row.role !== "user" && row.role !== "assistant") continue;
8660
+ const id = String(row.id);
8661
+ const metadata = asRecord(parseDeepChatJson(row.metadata));
8662
+ const usage = projection.messageUsage.get(id);
8663
+ messages.push({
8664
+ id,
8665
+ role: row.role,
8666
+ agent: row.role === "assistant" ? projection.agentId : void 0,
8667
+ time_created: Number(row.created_at),
8668
+ time_completed: row.status === "pending" ? void 0 : Number(row.updated_at),
8669
+ model: usage?.model ?? asString(metadata?.model) ?? projection.model,
8670
+ provider: usage?.provider ?? asString(metadata?.provider) ?? projection.provider,
8671
+ tokens: usage?.tokens,
8672
+ cost: usage?.cost,
8673
+ cost_source: usage && usage.cost > 0 ? "estimated" : void 0,
8674
+ parts: partsByMessage.get(id) ?? deepChatRawParts(row.role, String(row.content))
8675
+ });
8676
+ }
8677
+ return { ...projection.head, messages };
8678
+ });
8679
+ }
8680
+ readStructuredParts(db, sessionId) {
8681
+ const parts = /* @__PURE__ */ new Map();
8682
+ const blocks = db.prepare(`
8683
+ SELECT b.* FROM deepchat_assistant_blocks b
8684
+ JOIN deepchat_messages m ON m.id = b.message_id
8685
+ WHERE m.session_id = ? ORDER BY b.message_id, b.block_index
8686
+ `).iterate(sessionId);
8687
+ for (const block of blocks) {
8688
+ const id = String(block.message_id);
8689
+ const messageParts = parts.get(id) ?? [];
8690
+ const part = deepChatStoredBlockPart(block);
8691
+ if (part) messageParts.push(part);
8692
+ parts.set(id, messageParts);
8693
+ }
8694
+ const users = db.prepare(`
8695
+ SELECT u.message_id, u.text FROM deepchat_user_messages u
8696
+ JOIN deepchat_messages m ON m.id = u.message_id WHERE m.session_id = ?
8697
+ `).iterate(sessionId);
8698
+ for (const user of users) parts.set(String(user.message_id), deepChatUserParts(user));
8699
+ const attachments = db.prepare(`
8700
+ SELECT f.message_id, f.path, f.name FROM deepchat_user_message_files f
8701
+ JOIN deepchat_messages m ON m.id = f.message_id
8702
+ WHERE m.session_id = ? ORDER BY f.message_id, f.ordinal
8703
+ `).iterate(sessionId);
8704
+ for (const attachment of attachments) {
8705
+ parts.get(String(attachment.message_id))?.push(...deepChatUserParts({ files: [attachment] }));
8706
+ }
8707
+ const links = db.prepare(`
8708
+ SELECT l.message_id, l.url FROM deepchat_user_message_links l
8709
+ JOIN deepchat_messages m ON m.id = l.message_id
8710
+ WHERE m.session_id = ? ORDER BY l.message_id, l.ordinal
8711
+ `).iterate(sessionId);
8712
+ for (const link of links)
8713
+ parts.get(String(link.message_id))?.push(...deepChatUserParts({ links: [link.url] }));
8714
+ return parts;
8715
+ }
8716
+ };
8717
+ function jsonRecord(value) {
8718
+ return asRecord(typeof value === "string" ? JSON.parse(value) : value);
8719
+ }
8720
+ function nonnegative(value) {
8721
+ return Math.max(0, asNumber(value) ?? 0);
8722
+ }
8723
+ function tokensFromStats(stats) {
8724
+ if (!stats) return void 0;
8725
+ const input = asRecord(stats.inputTokenDetails);
8726
+ const output = asRecord(stats.outputTokenDetails);
8727
+ return {
8728
+ input: asNumber(stats.inputTokens) ?? nonnegative(input?.noCacheTokens) + nonnegative(input?.cacheReadTokens) + nonnegative(input?.cacheWriteTokens),
8729
+ output: asNumber(stats.outputTokens) ?? nonnegative(output?.textTokens) + nonnegative(output?.reasoningTokens),
8730
+ cache_read: nonnegative(input?.cacheReadTokens),
8731
+ cache_create: nonnegative(input?.cacheWriteTokens),
8732
+ reasoning: nonnegative(output?.reasoningTokens)
8733
+ };
8734
+ }
8735
+ function messageCost(stats, model, tokens) {
8736
+ const costs = (asArray(stats?.costs) ?? []).flatMap((value) => {
8737
+ const cost2 = asRecord(value);
8738
+ return cost2 ? [cost2] : [];
8739
+ });
8740
+ if (costs.length > 0 && costs.every((cost2) => cost2.currency === "USD")) {
8741
+ return {
8742
+ cost: costs.reduce((sum, cost2) => sum + nonnegative(cost2.amount), 0),
8743
+ costSource: costs.some((cost2) => nonnegative(cost2.computedRequestCount) > 0) ? "estimated" : "recorded"
8744
+ };
8745
+ }
8746
+ const cost = estimateTokenCost(model, tokens ? { ...tokens, reasoning: 0 } : void 0);
8747
+ return {
8748
+ cost: cost ?? void 0,
8749
+ costSource: cost === null ? void 0 : "estimated"
8750
+ };
8751
+ }
8752
+ function convertPart(part) {
8753
+ const type = asString(part.type);
8754
+ const text = asString(part.text);
8755
+ if ((type === "text" || type === "reasoning") && text) return { type, text };
8756
+ if (type === "dynamic-tool" || type?.startsWith("tool-")) {
8757
+ const state = asString(part.state);
8758
+ const failed = state === "output-error" || state === "output-denied";
8759
+ return {
8760
+ type: "tool",
8761
+ tool: asString(part.toolName) ?? (type === "dynamic-tool" ? "unknown" : type.slice(5)),
8762
+ callID: asString(part.toolCallId),
8763
+ title: asString(part.title),
8764
+ state: {
8765
+ status: failed ? "error" : state === "output-available" ? "completed" : "running",
8766
+ input: part.input,
8767
+ output: part.output,
8768
+ error: failed ? part.errorText ?? "Tool execution failed" : void 0,
8769
+ metadata: part.providerMetadata
8770
+ }
8771
+ };
8772
+ }
8773
+ if (type === "file") {
8774
+ const url = asString(part.url);
8775
+ const mime = asString(part.mediaType);
8776
+ if (url && mime?.startsWith("image/")) return { type: "image", url, mime_type: mime };
8777
+ const label = asString(part.filename) ?? url;
8778
+ return label ? { type: "text", text: `Attachment: ${label}` } : null;
8779
+ }
8780
+ const data = asRecord(part.data);
8781
+ if (type === "data-error") {
8782
+ const message = asString(data?.message);
8783
+ return message ? { type: "text", text: message } : null;
8784
+ }
8785
+ if (type === "data-compact" || type === "data-code" || type === "data-translation") {
8786
+ const content = asString(data?.content);
8787
+ return content ? { type: "text", text: content } : null;
8788
+ }
8789
+ return null;
8790
+ }
8791
+ function cherryStudioTranscript(rows) {
8792
+ const builder = new TranscriptBuilder();
8793
+ const modelUsage = /* @__PURE__ */ Object.create(null);
8794
+ let totalTokens = 0;
8795
+ for (const row of rows) {
8796
+ if (row.role !== "user" && row.role !== "assistant") continue;
8797
+ const data = jsonRecord(row.data);
8798
+ const snapshot = jsonRecord(row.message_snapshot);
8799
+ const modelSnapshot = asRecord(snapshot?.model);
8800
+ const uniqueModel = asString(row.model_id);
8801
+ const separator = uniqueModel?.indexOf("::") ?? -1;
8802
+ const model = asString(modelSnapshot?.id) ?? (separator >= 0 ? uniqueModel?.slice(separator + 2) : uniqueModel);
8803
+ const provider = asString(modelSnapshot?.provider) ?? (separator >= 0 ? uniqueModel?.slice(0, separator) : void 0);
8804
+ const stats = row.role === "assistant" ? jsonRecord(row.stats) : void 0;
8805
+ const tokens = tokensFromStats(stats);
8806
+ const total = nonnegative(stats?.totalTokens ?? (tokens?.input ?? 0) + (tokens?.output ?? 0));
8807
+ totalTokens += total;
8808
+ if (model && total > 0) modelUsage[model] = (modelUsage[model] ?? 0) + total;
8809
+ const message = builder.appendMessage({
8810
+ id: String(row.id),
8811
+ role: row.role,
8812
+ timestampMs: Number(row.created_at),
8813
+ agent: asString(snapshot?.name),
8814
+ model,
8815
+ provider,
8816
+ tokens,
8817
+ ...messageCost(stats, model, tokens),
8818
+ parts: (asArray(data?.parts) ?? []).flatMap((value) => {
8819
+ const part = asRecord(value);
8820
+ const converted = part ? convertPart(part) : null;
8821
+ return converted ? [converted] : [];
8822
+ })
8823
+ });
8824
+ if (row.status !== "pending") message.time_completed = Number(row.updated_at);
8825
+ }
8826
+ const transcript = builder.finish();
8827
+ return {
8828
+ ...transcript,
8829
+ stats: { ...transcript.stats, total_tokens: totalTokens },
8830
+ modelUsage
8831
+ };
8832
+ }
8833
+ var AGENT_METADATA12 = getAgentCatalogEntry("cherrystudio");
8834
+ function resolveCherryStudioDataRoot() {
8835
+ const configured = readEnvPath("CHERRYSTUDIO_USER_DATA_DIR");
8836
+ if (configured) return configured;
8837
+ if (platform5() === "darwin")
8838
+ return join16(homedir5(), "Library", "Application Support", "CherryStudio");
8839
+ if (platform5() === "win32") {
8840
+ return join16(readEnvPath("APPDATA") ?? join16(homedir5(), "AppData", "Roaming"), "CherryStudio");
8841
+ }
8842
+ return join16(readEnvPath("XDG_CONFIG_HOME") ?? join16(homedir5(), ".config"), "CherryStudio");
8843
+ }
8844
+ function liveRows(db, table, alias) {
8845
+ const columns = db.prepare(`PRAGMA table_info(${table})`).all();
8846
+ return columns.some((column) => column.name === "deleted_at") ? `${alias}.deleted_at IS NULL` : "1 = 1";
8847
+ }
8848
+ function activeBranch(rows, activeId) {
8849
+ const byId = new Map(rows.map((row) => [String(row.id), row]));
8850
+ const selected = [];
8851
+ const visited = /* @__PURE__ */ new Set();
8852
+ let id = asString(activeId);
8853
+ while (id) {
8854
+ if (visited.has(id)) throw new Error("Cherry Studio message branch contains a cycle");
8855
+ visited.add(id);
8856
+ const row = byId.get(id);
8857
+ if (!row) break;
8858
+ selected.push(row);
8859
+ id = asString(row.parent_id);
8860
+ }
8861
+ return selected.reverse();
8862
+ }
8863
+ var CherryStudioAgent = class extends DatabaseSessionSource {
8864
+ name = AGENT_METADATA12.name;
8865
+ displayName = AGENT_METADATA12.displayName;
8866
+ sourceRoot;
8867
+ constructor(options = {}) {
8868
+ super();
8869
+ this.sourceRoot = options.sourceRoot ?? resolveCherryStudioDataRoot();
8870
+ }
8871
+ getDatabasePath() {
8872
+ return firstExisting(join16(this.sourceRoot, "Data", "cherrystudio.sqlite"));
8873
+ }
8874
+ isAvailable() {
8875
+ return isSqliteAvailable() && this.getDatabasePath() !== null;
8876
+ }
8877
+ getSessionWatchPlan() {
8878
+ return {
8879
+ status: "supported",
8880
+ targets: [
8881
+ { root: this.sourceRoot, path: join16(this.sourceRoot, "Data", "cherrystudio.sqlite") }
8882
+ ]
8883
+ };
8884
+ }
8885
+ readDatabase(read) {
8886
+ const path = this.getDatabasePath();
8887
+ if (!path) throw new Error("Cherry Studio 2.x cherrystudio.sqlite is missing");
8888
+ return this.scanStep("reading Cherry Studio 2.x cherrystudio.sqlite", path, () => {
8889
+ const db = openDbReadOnly(path);
8890
+ if (!db) throw new Error("Cannot open Cherry Studio database");
8891
+ try {
8892
+ return db.transaction(() => read(db))();
8893
+ } finally {
8894
+ db.close();
8895
+ }
8896
+ });
8897
+ }
8898
+ scan(options) {
8899
+ if (!this.getDatabasePath()) return [];
8900
+ return this.readDatabase((db) => {
8901
+ const sessions = [];
8902
+ for (const kind of ["agent", "topic"]) {
8903
+ for (const projection of this.readConversations(db, kind)) {
8904
+ const { messages: _messages, ...head } = projection.session;
8905
+ if (!head.stats.message_count || !matchesScanWindow(head.time_updated ?? head.time_created, options))
8906
+ continue;
8907
+ this.rememberSession(head.reference.sessionId, {
8908
+ sourceFingerprint: projection.fingerprint,
8909
+ headParserVersion: "cherrystudio-v1",
8910
+ unpricedModels: projection.unpricedModels
8911
+ });
8912
+ sessions.push(head);
8913
+ }
8914
+ }
8915
+ sessions.sort(
8916
+ (left, right) => (right.time_updated ?? 0) - (left.time_updated ?? 0) || left.reference.sessionId.localeCompare(right.reference.sessionId)
8917
+ );
8918
+ options?.onProgress?.({
8919
+ total: sessions.length,
8920
+ processed: sessions.length,
8921
+ sessions: sessions.length
8922
+ });
8923
+ return sessions;
8924
+ });
8925
+ }
8926
+ getSessionData(sessionId) {
8927
+ const separator = sessionId.indexOf(":");
8928
+ const kind = sessionId.slice(0, separator);
8929
+ const id = sessionId.slice(separator + 1);
8930
+ if (kind !== "agent" && kind !== "topic" || !id)
8931
+ throw new Error(`Invalid Cherry Studio session: ${sessionId}`);
8932
+ return this.readDatabase((db) => {
8933
+ for (const projection of this.readConversations(db, kind, id)) return projection.session;
8934
+ throw new Error(`Cherry Studio session not found: ${sessionId}`);
8935
+ });
8936
+ }
8937
+ *readConversations(db, kind, id) {
8938
+ const table = kind === "agent" ? "agent_session" : "topic";
8939
+ const messageTable = kind === "agent" ? "agent_session_message" : "message";
8940
+ const foreignKey = kind === "agent" ? "session_id" : "topic_id";
8941
+ const filter = `${liveRows(db, table, "s")} ${id ? "AND s.id = ?" : ""}`;
8942
+ const bindings = id ? [id] : [];
8943
+ const headers = db.prepare(`
8944
+ SELECT s.id, s.name, s.created_at, s.updated_at, s.last_activity_at,
8945
+ ${kind === "agent" ? "w.path AS directory, NULL AS active_node_id" : "NULL AS directory, s.active_node_id"}
8946
+ FROM ${table} s ${kind === "agent" ? "LEFT JOIN agent_workspace w ON w.id = s.workspace_id" : ""}
8947
+ WHERE ${filter}
8948
+ `).all(...bindings);
8949
+ const byId = new Map(headers.map((row) => [String(row.id), row]));
8950
+ const messages = db.prepare(`
8951
+ SELECT m.id, m.${foreignKey} AS conversation_id, m.role, m.data, m.stats,
8952
+ m.model_id, m.message_snapshot, m.status, m.created_at, m.updated_at,
8953
+ ${kind === "topic" ? "m.parent_id" : "NULL AS parent_id"}
8954
+ FROM ${messageTable} m JOIN ${table} s ON s.id = m.${foreignKey}
8955
+ WHERE ${filter} AND ${liveRows(db, messageTable, "m")}
8956
+ ORDER BY m.${foreignKey}, m.created_at, m.id
8957
+ `).iterate(...bindings);
8958
+ let currentId;
8959
+ let rows = [];
8960
+ for (const row of messages) {
8961
+ const nextId = String(row.conversation_id);
8962
+ if (currentId !== void 0 && nextId !== currentId) {
8963
+ yield this.projectConversation(kind, byId.get(currentId), rows);
8964
+ rows = [];
8965
+ }
8966
+ currentId = nextId;
8967
+ rows.push(row);
8968
+ }
8969
+ if (currentId !== void 0) yield this.projectConversation(kind, byId.get(currentId), rows);
8970
+ }
8971
+ projectConversation(kind, row, rows) {
8972
+ const selected = kind === "topic" ? activeBranch(rows, row.active_node_id) : rows;
8973
+ const { result: transcript, unpricedModels } = capturePricingMisses(
8974
+ () => cherryStudioTranscript(selected)
8975
+ );
8976
+ const signature = createHash4("sha256").update(JSON.stringify(row));
8977
+ for (const message of selected) signature.update(JSON.stringify(message));
8978
+ const session = {
8979
+ ...this.sessionIdentity(`${kind}:${row.id}`),
8980
+ title: resolveSessionTitle(
8981
+ asString(row.name),
8982
+ firstUserMessageTitle(transcript.messages),
8983
+ "Cherry Studio"
8984
+ ),
8985
+ directory: asString(row.directory) || this.sourceRoot,
8986
+ time_created: Number(row.created_at),
8987
+ time_updated: Number(row.last_activity_at),
8988
+ stats: transcript.stats,
8989
+ model_usage: transcript.modelUsage,
8990
+ messages: transcript.messages
8991
+ };
8992
+ return { session, fingerprint: signature.digest("hex"), unpricedModels };
8993
+ }
8994
+ };
8995
+ function parseToolJson(value) {
8996
+ if (typeof value !== "string") return value;
8997
+ try {
8998
+ return JSON.parse(value);
8999
+ } catch {
9000
+ return value;
9001
+ }
9002
+ }
9003
+ function toolPart2(value) {
9004
+ const call = asRecord(value);
9005
+ if (!call) return null;
9006
+ const tool = asString(call.tool_name);
9007
+ if (!tool) return null;
9008
+ const input = parseToolJson(call.tool_call_args);
9009
+ const output = parseToolJson(call.tool_call_result_data);
9010
+ const result = asRecord(output);
9011
+ const failed = call.tool_call_status === 3 || result?.isError === true || result?.error != null;
9012
+ return {
9013
+ type: "tool",
9014
+ tool,
9015
+ callID: asString(call.tool_call_id),
9016
+ state: {
9017
+ status: failed ? "error" : call.tool_call_status === 2 ? "completed" : "running",
9018
+ input,
9019
+ output,
9020
+ error: failed ? result?.error ?? result?.text ?? output : void 0,
9021
+ metadata: {
9022
+ ...asRecord(result?.details),
9023
+ minimax_status: call.tool_call_status
9024
+ }
9025
+ }
9026
+ };
9027
+ }
9028
+ function attachmentPart(value) {
9029
+ const attachment = asRecord(value);
9030
+ if (!attachment) return null;
9031
+ const path = asString(attachment.file_path) ?? asString(attachment.desktop_path);
9032
+ const mime = asString(attachment.mime_type);
9033
+ const name = path ?? asString(attachment.file_name) ?? asString(attachment.asset_id) ?? asString(attachment.url);
9034
+ return name ? { type: "text", text: `Attachment: ${name}${mime ? ` (${mime})` : ""}` } : null;
9035
+ }
9036
+ var EVENT_LABELS = {
9037
+ compaction_start: "Context compaction started",
9038
+ compaction: "Context compacted",
9039
+ compaction_failed: "Context compaction failed",
9040
+ review_start: "Review started",
9041
+ review_result: "Review result",
9042
+ review_failed: "Review failed",
9043
+ review_aborted: "Review aborted",
9044
+ review_interrupted: "Review interrupted"
9045
+ };
9046
+ var AUTOMATED_SOURCES = /* @__PURE__ */ new Set(["cron", "thread-goal", "team", "background-task", "system"]);
9047
+ function miniMaxMessage(row, agent) {
9048
+ const data = asRecord(JSON.parse(String(row.data_json)));
9049
+ const id = asString(row.msg_id);
9050
+ if (!data || !id || data.msg_id !== id) throw new Error("Invalid MiniMax display message");
9051
+ const role = row.role ?? data.role ?? "assistant";
9052
+ if (role !== "user" && role !== "assistant") throw new Error(`Invalid MiniMax role: ${role}`);
9053
+ const kind = asString(data.kind);
9054
+ const parts = [];
9055
+ if (kind) parts.push({ type: "text", text: EVENT_LABELS[kind] ?? `Event: ${kind}` });
9056
+ const thinking = asString(data.thinking_content);
9057
+ if (thinking) parts.push({ type: "reasoning", text: thinking });
9058
+ const text = asString(data.msg_content);
9059
+ if (text) parts.push({ type: "text", text });
9060
+ for (const value of Array.isArray(data.attachments) ? data.attachments : []) {
9061
+ const part = attachmentPart(value);
9062
+ if (part) parts.push(part);
9063
+ }
9064
+ const children = /* @__PURE__ */ new Set();
9065
+ for (const value of Array.isArray(data.tool_calls) ? data.tool_calls : []) {
9066
+ const part = toolPart2(value);
9067
+ if (!part) continue;
9068
+ parts.push(part);
9069
+ if (part.tool === "task" || part.tool.startsWith("task_")) {
9070
+ const metadata = asRecord(part.state.metadata);
9071
+ const child = asString(metadata?.sub_session_id) ?? asString(metadata?.session_id);
9072
+ if (child) children.add(child);
9073
+ }
9074
+ }
9075
+ const error = asString(data.error);
9076
+ if (error) parts.push({ type: "text", text: error });
9077
+ const timestamp = asNumber(row.created_at_ms) ?? asNumber(data.timestamp) ?? 0;
9078
+ return {
9079
+ id,
9080
+ role,
9081
+ agent: role === "assistant" ? agent : void 0,
9082
+ time_created: timestamp,
9083
+ time_completed: data.finish_reason ? timestamp : void 0,
9084
+ mode: kind,
9085
+ automated: role === "user" && (Boolean(kind) || AUTOMATED_SOURCES.has(String(row.source))) ? true : void 0,
9086
+ subagent_id: children.size === 1 ? children.values().next().value : void 0,
9087
+ parts
9088
+ };
9089
+ }
9090
+ function tokenCount2(value) {
9091
+ return Math.max(0, asNumber(value) ?? 0);
9092
+ }
9093
+ function miniMaxUsage(row) {
9094
+ const model = asString(row.model) || void 0;
9095
+ const tokens = {
9096
+ input: tokenCount2(row.input_tokens),
9097
+ output: tokenCount2(row.output_tokens),
9098
+ reasoning: tokenCount2(row.reasoning_tokens),
9099
+ cache_read: tokenCount2(row.cache_read_tokens),
9100
+ cache_create: tokenCount2(row.cache_write_tokens)
9101
+ };
9102
+ const recorded = asNumber(row.cost_usd);
9103
+ const cost = recorded !== void 0 && recorded >= 0 ? recorded : estimateTokenCost(model, tokens);
9104
+ return {
9105
+ turnId: asString(row.turn_id),
9106
+ model,
9107
+ time: tokenCount2(row.ts),
9108
+ tokens,
9109
+ total: Object.values(tokens).reduce((sum, value) => sum + value, 0),
9110
+ cost: cost ?? 0,
9111
+ costSource: recorded !== void 0 && recorded >= 0 ? "recorded" : cost !== null ? "estimated" : void 0
9112
+ };
9113
+ }
9114
+ function attachMiniMaxUsage(message, usages) {
9115
+ const models = new Set(usages.map((usage) => usage.model));
9116
+ if (models.size !== 1) return;
9117
+ message.model = usages[0]?.model;
9118
+ message.tokens = {};
9119
+ message.cost = 0;
9120
+ for (const usage of usages) {
9121
+ for (const key of ["input", "output", "reasoning", "cache_read", "cache_create"]) {
9122
+ message.tokens[key] = (message.tokens[key] ?? 0) + (usage.tokens[key] ?? 0);
9123
+ }
9124
+ message.cost += usage.cost;
9125
+ if (usage.costSource === "estimated" || !message.cost_source)
9126
+ message.cost_source = usage.costSource;
9127
+ }
9128
+ }
9129
+ var AGENT_METADATA13 = getAgentCatalogEntry("minimax-code");
9130
+ var DATABASE_PATH = join17("v2", "sqlite", "runtime-state.sqlite");
9131
+ var SESSION_FILTER = "(s.visibility <> 'hidden' OR s.parent_session_id IS NOT NULL) AND s.session_kind NOT IN ('peek', 'cron', 'channel')";
9132
+ function dataRoots() {
9133
+ const configured = readEnvPath("MINIMAX_DATA_DIR") ?? readEnvPath("MAVIS_DATA_DIR");
9134
+ return configured ? [configured] : [join17(homedir6(), ".minimax"), join17(homedir6(), ".minimax-code")];
9135
+ }
9136
+ function resolveMiniMaxCodeDataRoot() {
9137
+ const roots = dataRoots();
9138
+ return roots.find((root) => firstExisting(join17(root, DATABASE_PATH))) ?? roots[0];
9139
+ }
9140
+ var MiniMaxCodeAgent = class extends DatabaseSessionSource {
9141
+ name = AGENT_METADATA13.name;
9142
+ displayName = AGENT_METADATA13.displayName;
9143
+ roots;
9144
+ constructor(options = {}) {
9145
+ super();
9146
+ this.roots = options.sourceRoot ? [options.sourceRoot] : dataRoots();
9147
+ }
9148
+ getDatabasePath() {
9149
+ return firstExisting(...this.roots.map((root) => join17(root, DATABASE_PATH)));
9150
+ }
9151
+ isAvailable() {
9152
+ return isSqliteAvailable() && this.getDatabasePath() !== null;
9153
+ }
9154
+ getSessionWatchPlan() {
9155
+ return {
9156
+ status: "supported",
9157
+ targets: this.roots.flatMap(
9158
+ (root) => ["", "-wal", "-journal"].map((suffix) => ({
9159
+ path: `${join17(root, DATABASE_PATH)}${suffix}`,
9160
+ pollForChanges: true
9161
+ }))
9162
+ )
9163
+ };
9164
+ }
9165
+ readDatabase(read) {
9166
+ const path = this.getDatabasePath();
9167
+ if (!path) throw new Error("MiniMax Code runtime-state.sqlite is missing");
9168
+ return this.scanStep("reading MiniMax Code 0.4.12 sessions", path, () => {
9169
+ const db = openDbReadOnly(path);
9170
+ if (!db) throw new Error("Cannot open MiniMax Code database");
9171
+ try {
9172
+ return db.transaction(() => read(db))();
9173
+ } finally {
9174
+ db.close();
9175
+ }
9176
+ });
9177
+ }
9178
+ scan(options) {
9179
+ if (!this.getDatabasePath()) return [];
9180
+ return this.readDatabase((db) => {
9181
+ const projections = this.readProjections(db);
9182
+ const selected = /* @__PURE__ */ new Set();
9183
+ const children = /* @__PURE__ */ new Map();
9184
+ for (const [id, { head }] of projections) {
9185
+ const parent = head.parent_reference?.sessionId;
9186
+ if (parent && projections.has(parent)) {
9187
+ const siblings = children.get(parent) ?? [];
9188
+ siblings.push(id);
9189
+ children.set(parent, siblings);
9190
+ } else if (matchesScanWindow(head.time_updated ?? head.time_created, options)) {
9191
+ selected.add(id);
9192
+ }
9193
+ }
9194
+ if (options?.includeRelatedSessions !== false) {
9195
+ for (const id of selected) {
9196
+ for (const child of children.get(id) ?? []) selected.add(child);
9197
+ }
9198
+ }
9199
+ const sessions = [];
9200
+ for (const id of selected) {
9201
+ const projection = projections.get(id);
9202
+ if (!projection.head.stats.message_count) continue;
9203
+ this.rememberSession(id, {
9204
+ sourceFingerprint: projection.signature.digest("hex"),
9205
+ headParserVersion: "minimax-code-v1",
9206
+ unpricedModels: [...projection.unpricedModels]
9207
+ });
9208
+ sessions.push(projection.head);
9209
+ }
9210
+ sessions.sort(
9211
+ (left, right) => (right.time_updated ?? 0) - (left.time_updated ?? 0) || left.reference.sessionId.localeCompare(right.reference.sessionId)
9212
+ );
9213
+ options?.onProgress?.({
9214
+ total: selected.size,
9215
+ processed: selected.size,
9216
+ sessions: sessions.length
9217
+ });
9218
+ return sessions;
9219
+ });
9220
+ }
9221
+ getSessionData(sessionId) {
9222
+ return this.readDatabase((db) => {
9223
+ const projection = this.readProjections(db, sessionId).get(sessionId);
9224
+ if (!projection) throw new Error(`MiniMax Code session not found: ${sessionId}`);
9225
+ for (const [turnId, usage] of projection.usageByTurn) {
9226
+ const message = projection.lastAssistantByTurn.get(turnId);
9227
+ if (message) attachMiniMaxUsage(message, usage);
9228
+ }
9229
+ return { ...projection.head, messages: projection.messages };
9230
+ });
9231
+ }
9232
+ readProjections(db, sessionId) {
9233
+ const filter = `${SESSION_FILTER}${sessionId ? " AND s.session_id = ?" : ""}`;
9234
+ const bindings = sessionId ? [sessionId] : [];
9235
+ const projections = /* @__PURE__ */ new Map();
9236
+ const sessions = db.prepare(`
9237
+ SELECT s.session_id, s.columnar_version, s.title, s.workspace_dir, s.parent_session_id,
9238
+ s.created_at_ms, s.updated_at_ms, s.agent_name, s.status, s.archived, s.extra_data_json
9239
+ FROM local_runtime_sessions s WHERE ${filter} ORDER BY s.session_id
9240
+ `).iterate(...bindings);
9241
+ for (const row of sessions) {
9242
+ if (row.columnar_version !== 3)
9243
+ throw new Error("Unsupported MiniMax session columnar version");
9244
+ const id = String(row.session_id);
9245
+ const parent = asString(row.parent_session_id);
9246
+ projections.set(id, {
9247
+ head: {
9248
+ ...this.sessionIdentity(id),
9249
+ title: asString(row.title) ?? "",
9250
+ directory: asString(row.workspace_dir) ?? "",
9251
+ parent_reference: parent && parent !== id ? { agentName: this.name, sessionId: parent } : void 0,
9252
+ time_created: Number(row.created_at_ms ?? row.updated_at_ms),
9253
+ time_updated: Number(row.updated_at_ms),
9254
+ stats: { message_count: 0, total_input_tokens: 0, total_output_tokens: 0, total_cost: 0 }
9255
+ },
9256
+ agent: asString(row.agent_name) ?? this.displayName,
9257
+ signature: createHash5("sha256").update(JSON.stringify(row)),
9258
+ unpricedModels: /* @__PURE__ */ new Set(),
9259
+ messages: [],
9260
+ lastAssistantByTurn: /* @__PURE__ */ new Map(),
9261
+ usageByTurn: /* @__PURE__ */ new Map()
9262
+ });
9263
+ }
9264
+ const messages = db.prepare(`
9265
+ SELECT m.id, m.session_id, m.msg_id, m.role, m.turn_id, m.source, m.created_at_ms, m.data_json
9266
+ FROM local_runtime_message_rows m JOIN local_runtime_sessions s ON s.session_id = m.session_id
9267
+ WHERE ${filter} ORDER BY m.session_id, m.id
9268
+ `).iterate(...bindings);
9269
+ for (const row of messages) {
9270
+ const projection = projections.get(String(row.session_id));
9271
+ projection.signature.update(JSON.stringify(row));
9272
+ const message = miniMaxMessage(row, projection.agent);
9273
+ projection.head.stats.message_count += 1;
9274
+ projection.head.time_updated = Math.max(
9275
+ projection.head.time_updated ?? 0,
9276
+ message.time_created
9277
+ );
9278
+ if (message.role === "user" && !message.automated && !projection.firstUserText) {
9279
+ projection.firstUserText = message.parts.find((part) => part.type === "text")?.text;
9280
+ }
9281
+ if (sessionId) {
9282
+ projection.messages.push(message);
9283
+ const turnId = asString(row.turn_id);
9284
+ if (turnId && message.role === "assistant" && !message.mode)
9285
+ projection.lastAssistantByTurn.set(turnId, message);
9286
+ }
9287
+ }
9288
+ const usages = db.prepare(`
9289
+ SELECT u.id, u.session_id, u.turn_id, u.model, u.ts, u.input_tokens, u.output_tokens,
9290
+ u.reasoning_tokens, u.cache_read_tokens, u.cache_write_tokens, u.cost_usd
9291
+ FROM local_runtime_token_usage u JOIN local_runtime_sessions s ON s.session_id = u.session_id
9292
+ WHERE ${filter} ORDER BY u.session_id, u.id
9293
+ `).iterate(...bindings);
9294
+ for (const row of usages) {
9295
+ const projection = projections.get(String(row.session_id));
9296
+ projection.signature.update(JSON.stringify(row));
9297
+ const { result: usage, unpricedModels } = capturePricingMisses(() => miniMaxUsage(row));
9298
+ for (const model of unpricedModels) projection.unpricedModels.add(model);
9299
+ const stats = projection.head.stats;
9300
+ stats.total_input_tokens += usage.tokens.input ?? 0;
9301
+ stats.total_output_tokens += usage.tokens.output ?? 0;
9302
+ stats.total_tokens = (stats.total_tokens ?? 0) + usage.total;
9303
+ stats.total_cache_read_tokens = (stats.total_cache_read_tokens ?? 0) + (usage.tokens.cache_read ?? 0);
9304
+ stats.total_cache_create_tokens = (stats.total_cache_create_tokens ?? 0) + (usage.tokens.cache_create ?? 0);
9305
+ stats.total_cost += usage.cost;
9306
+ if (usage.costSource === "estimated" || !stats.cost_source)
9307
+ stats.cost_source = usage.costSource;
9308
+ if (usage.model) {
9309
+ const modelUsage = projection.head.model_usage ??= /* @__PURE__ */ Object.create(null);
9310
+ modelUsage[usage.model] = (modelUsage[usage.model] ?? 0) + usage.total;
9311
+ }
9312
+ projection.head.time_updated = Math.max(projection.head.time_updated ?? 0, usage.time);
9313
+ if (sessionId && usage.turnId) {
9314
+ const turnUsage = projection.usageByTurn.get(usage.turnId) ?? [];
9315
+ turnUsage.push(usage);
9316
+ projection.usageByTurn.set(usage.turnId, turnUsage);
9317
+ }
9318
+ }
9319
+ for (const projection of projections.values()) {
9320
+ projection.head.title = resolveSessionTitle(
9321
+ projection.head.title,
9322
+ projection.firstUserText ?? null,
9323
+ null
9324
+ );
9325
+ }
9326
+ return projections;
9327
+ }
9328
+ };
8308
9329
  var RUNTIME_REGISTRATIONS = {
9330
+ "minimax-code": {
9331
+ create: () => new MiniMaxCodeAgent(),
9332
+ resolveDataRoot: resolveMiniMaxCodeDataRoot
9333
+ },
8309
9334
  claudecode: {
8310
9335
  create: () => new ClaudeCodeAgent(),
8311
9336
  resolveDataRoot: resolveClaudeCodeDataRoot
@@ -8345,6 +9370,14 @@ var RUNTIME_REGISTRATIONS = {
8345
9370
  dsh: {
8346
9371
  create: () => new DshAgent(),
8347
9372
  resolveDataRoot: resolveDshDataRoot
9373
+ },
9374
+ deepchat: {
9375
+ create: () => new DeepChatAgent(),
9376
+ resolveDataRoot: resolveDeepChatDataRoot
9377
+ },
9378
+ cherrystudio: {
9379
+ create: () => new CherryStudioAgent(),
9380
+ resolveDataRoot: resolveCherryStudioDataRoot
8348
9381
  }
8349
9382
  };
8350
9383
  var AGENT_REGISTRATIONS = Object.freeze(
@@ -8387,4 +9420,4 @@ export {
8387
9420
  createRegisteredAgents,
8388
9421
  getAgentInfoMap
8389
9422
  };
8390
- //# sourceMappingURL=chunk-RBCCNCDO.js.map
9423
+ //# sourceMappingURL=chunk-WRVILHZR.js.map