chatlab-cli 0.1.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/{chunk-YAOFJ73U.mjs → chunk-3DIWXYMJ.mjs} +80 -129
  2. package/dist/chunk-3DIWXYMJ.mjs.map +1 -0
  3. package/dist/{chunk-JMRDNHIR.mjs → chunk-EIRLEPXP.mjs} +824 -280
  4. package/dist/chunk-EIRLEPXP.mjs.map +1 -0
  5. package/dist/{chunk-DL3BFEAH.mjs → chunk-EWCSGYVT.mjs} +2 -2
  6. package/dist/chunk-EWCSGYVT.mjs.map +1 -0
  7. package/dist/{chunk-PF4QFHC6.mjs → chunk-FBTHZU55.mjs} +849 -824
  8. package/dist/chunk-FBTHZU55.mjs.map +1 -0
  9. package/dist/{chunk-P4N5GEFF.mjs → chunk-NB4BIAYM.mjs} +9 -9
  10. package/dist/{chunk-OC73KSMV.mjs → chunk-XUHPCRVT.mjs} +2 -2
  11. package/dist/cli.mjs +2 -2
  12. package/dist/{http-PQEOFGJK.mjs → http-QVYJ5HER.mjs} +6 -6
  13. package/dist/{import-UR2IE2O7.mjs → import-AJKL6JPR.mjs} +6 -4
  14. package/dist/index.mjs +6 -6
  15. package/dist/{mcp-4XCDZ5PU.mjs → mcp-FRF3YAN5.mjs} +5 -6
  16. package/dist/mcp-FRF3YAN5.mjs.map +1 -0
  17. package/dist/{src-ZELOFE7P.mjs → src-KOIGBZJX.mjs} +14 -2
  18. package/dist/{stream-import-RP3XB6NM.mjs → stream-import-URGOCXUH.mjs} +5 -3
  19. package/dist-web/assets/{DebugToolsPanel.vue_vue_type_script_setup_true_lang-BuOhHrGp.js → DebugToolsPanel.vue_vue_type_script_setup_true_lang-DFN1Co1H.js} +19 -19
  20. package/dist-web/assets/{EChartWordcloud-DcC12j9S.js → EChartWordcloud-BYLFxPAX.js} +1 -1
  21. package/dist-web/assets/{MessageExportModal-CUS9nnwi.js → MessageExportModal-BAf68-wB.js} +1 -1
  22. package/dist-web/assets/electron-2m4Vdk2z.js +1 -0
  23. package/dist-web/assets/{fetch-DvfIZxuz.js → fetch-Ayp337Ng.js} +1 -1
  24. package/dist-web/assets/{fetch-CJ8Q4qM2.js → fetch-BWtpQwBZ.js} +1 -1
  25. package/dist-web/assets/fetch-o5NJ2uWE.js +3 -0
  26. package/dist-web/assets/{index-D3siJhmm.js → index-Bd5r2oFG.js} +4 -4
  27. package/dist-web/assets/index-BfZM-q0T.js +7 -0
  28. package/dist-web/assets/{index-CCE1zef2.js → index-CLYHD_f4.js} +2 -2
  29. package/dist-web/assets/{index-CUTe0Sc3.js → index-CaTRpNBK.js} +12 -12
  30. package/dist-web/assets/index-Ksa--o23.js +173 -0
  31. package/dist-web/assets/{vendor-echarts-BXkS9r5W.js → vendor-echarts-C13vDgZW.js} +5 -5
  32. package/dist-web/assets/{vendor-echarts-wordcloud-CmDVLUv0.js → vendor-echarts-wordcloud-uVdwYsYa.js} +1 -1
  33. package/dist-web/assets/{vendor-nuxt-ui-D1aReMtR.js → vendor-nuxt-ui-CYMNNdeD.js} +2 -2
  34. package/dist-web/assets/{vendor-zrender-B6SpLIkk.js → vendor-zrender-5DcYjSZk.js} +2 -2
  35. package/dist-web/assets/{web-DOZKbBMQ.js → web-C5yfcwjn.js} +1 -1
  36. package/dist-web/index.html +2 -2
  37. package/package.json +1 -2
  38. package/CHANGELOG.md +0 -51
  39. package/LICENSE +0 -661
  40. package/dist/chunk-DL3BFEAH.mjs.map +0 -1
  41. package/dist/chunk-JMRDNHIR.mjs.map +0 -1
  42. package/dist/chunk-PF4QFHC6.mjs.map +0 -1
  43. package/dist/chunk-YAOFJ73U.mjs.map +0 -1
  44. package/dist/mcp-4XCDZ5PU.mjs.map +0 -1
  45. package/dist-web/assets/electron-DvcSSc-D.js +0 -1
  46. package/dist-web/assets/fetch-DgQkWW73.js +0 -3
  47. package/dist-web/assets/index-68UnLyFT.js +0 -173
  48. package/dist-web/assets/index-n2XUUgti.js +0 -7
  49. /package/dist/{chunk-P4N5GEFF.mjs.map → chunk-NB4BIAYM.mjs.map} +0 -0
  50. /package/dist/{chunk-OC73KSMV.mjs.map → chunk-XUHPCRVT.mjs.map} +0 -0
  51. /package/dist/{http-PQEOFGJK.mjs.map → http-QVYJ5HER.mjs.map} +0 -0
  52. /package/dist/{import-UR2IE2O7.mjs.map → import-AJKL6JPR.mjs.map} +0 -0
  53. /package/dist/{src-ZELOFE7P.mjs.map → src-KOIGBZJX.mjs.map} +0 -0
  54. /package/dist/{stream-import-RP3XB6NM.mjs.map → stream-import-URGOCXUH.mjs.map} +0 -0
@@ -19,6 +19,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
19
19
  var __commonJS = (cb, mod) => function __require2() {
20
20
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
21
21
  };
22
+ var __export = (target, all) => {
23
+ for (var name in all)
24
+ __defProp(target, name, { get: all[name], enumerable: true });
25
+ };
22
26
  var __copyProps = (to, from, except, desc) => {
23
27
  if (from && typeof from === "object" || typeof from === "function") {
24
28
  for (let key of __getOwnPropNames(from))
@@ -36,9 +40,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
36
40
  mod
37
41
  ));
38
42
 
39
- // ../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/utils/Utf8Stream.js
43
+ // ../../node_modules/stream-json/utils/Utf8Stream.js
40
44
  var require_Utf8Stream = __commonJS({
41
- "../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/utils/Utf8Stream.js"(exports, module) {
45
+ "../../node_modules/stream-json/utils/Utf8Stream.js"(exports, module) {
42
46
  "use strict";
43
47
  var { Transform } = __require("stream");
44
48
  var { StringDecoder } = __require("string_decoder");
@@ -85,9 +89,9 @@ var require_Utf8Stream = __commonJS({
85
89
  }
86
90
  });
87
91
 
88
- // ../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/Parser.js
92
+ // ../../node_modules/stream-json/Parser.js
89
93
  var require_Parser = __commonJS({
90
- "../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/Parser.js"(exports, module) {
94
+ "../../node_modules/stream-json/Parser.js"(exports, module) {
91
95
  "use strict";
92
96
  var Utf8Stream = require_Utf8Stream();
93
97
  var patterns = {
@@ -614,18 +618,18 @@ var require_Parser = __commonJS({
614
618
  }
615
619
  });
616
620
 
617
- // ../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/utils/emit.js
621
+ // ../../node_modules/stream-json/utils/emit.js
618
622
  var require_emit = __commonJS({
619
- "../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/utils/emit.js"(exports, module) {
623
+ "../../node_modules/stream-json/utils/emit.js"(exports, module) {
620
624
  "use strict";
621
625
  var emit = (stream) => stream.on("data", (item) => stream.emit(item.name, item.value));
622
626
  module.exports = emit;
623
627
  }
624
628
  });
625
629
 
626
- // ../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/index.js
630
+ // ../../node_modules/stream-json/index.js
627
631
  var require_stream_json = __commonJS({
628
- "../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/index.js"(exports, module) {
632
+ "../../node_modules/stream-json/index.js"(exports, module) {
629
633
  "use strict";
630
634
  var Parser = require_Parser();
631
635
  var emit = require_emit();
@@ -636,16 +640,16 @@ var require_stream_json = __commonJS({
636
640
  }
637
641
  });
638
642
 
639
- // ../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/filters/FilterBase.js
643
+ // ../../node_modules/stream-json/filters/FilterBase.js
640
644
  var require_FilterBase = __commonJS({
641
- "../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/filters/FilterBase.js"(exports, module) {
645
+ "../../node_modules/stream-json/filters/FilterBase.js"(exports, module) {
642
646
  "use strict";
643
647
  var { Transform } = __require("stream");
644
648
  var FilterBase = class _FilterBase extends Transform {
645
649
  static stringFilter(string, separator) {
646
650
  return (stack) => {
647
- const path36 = stack.join(separator);
648
- return path36.length === string.length && path36 === string || path36.length > string.length && path36.substr(0, string.length) === string && path36.substr(string.length, separator.length) === separator;
651
+ const path37 = stack.join(separator);
652
+ return path37.length === string.length && path37 === string || path37.length > string.length && path37.substr(0, string.length) === string && path37.substr(string.length, separator.length) === separator;
649
653
  };
650
654
  }
651
655
  static regExpFilter(regExp, separator) {
@@ -811,9 +815,9 @@ var require_FilterBase = __commonJS({
811
815
  }
812
816
  });
813
817
 
814
- // ../../node_modules/.pnpm/stream-chain@2.2.5/node_modules/stream-chain/index.js
818
+ // ../../node_modules/stream-chain/index.js
815
819
  var require_stream_chain = __commonJS({
816
- "../../node_modules/.pnpm/stream-chain@2.2.5/node_modules/stream-chain/index.js"(exports, module) {
820
+ "../../node_modules/stream-chain/index.js"(exports, module) {
817
821
  "use strict";
818
822
  var { Readable, Writable, Duplex, Transform } = __require("stream");
819
823
  var none = /* @__PURE__ */ Symbol.for("object-stream.none");
@@ -983,9 +987,9 @@ var require_stream_chain = __commonJS({
983
987
  }
984
988
  });
985
989
 
986
- // ../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/utils/withParser.js
990
+ // ../../node_modules/stream-json/utils/withParser.js
987
991
  var require_withParser = __commonJS({
988
- "../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/utils/withParser.js"(exports, module) {
992
+ "../../node_modules/stream-json/utils/withParser.js"(exports, module) {
989
993
  "use strict";
990
994
  var { chain: chain8 } = require_stream_chain();
991
995
  var Parser = require_Parser();
@@ -994,9 +998,9 @@ var require_withParser = __commonJS({
994
998
  }
995
999
  });
996
1000
 
997
- // ../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/filters/Pick.js
1001
+ // ../../node_modules/stream-json/filters/Pick.js
998
1002
  var require_Pick = __commonJS({
999
- "../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/filters/Pick.js"(exports, module) {
1003
+ "../../node_modules/stream-json/filters/Pick.js"(exports, module) {
1000
1004
  "use strict";
1001
1005
  var FilterBase = require_FilterBase();
1002
1006
  var withParser = require_withParser();
@@ -1053,9 +1057,9 @@ var require_Pick = __commonJS({
1053
1057
  }
1054
1058
  });
1055
1059
 
1056
- // ../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/Assembler.js
1060
+ // ../../node_modules/stream-json/Assembler.js
1057
1061
  var require_Assembler = __commonJS({
1058
- "../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/Assembler.js"(exports, module) {
1062
+ "../../node_modules/stream-json/Assembler.js"(exports, module) {
1059
1063
  "use strict";
1060
1064
  var EventEmitter = __require("events");
1061
1065
  var startObject = (Ctr) => function() {
@@ -1099,12 +1103,12 @@ var require_Assembler = __commonJS({
1099
1103
  return (this.stack.length >> 1) + (this.done ? 0 : 1);
1100
1104
  }
1101
1105
  get path() {
1102
- const path36 = [];
1106
+ const path37 = [];
1103
1107
  for (let i = 0; i < this.stack.length; i += 2) {
1104
1108
  const key = this.stack[i + 1];
1105
- path36.push(key === null ? this.stack[i].length : key);
1109
+ path37.push(key === null ? this.stack[i].length : key);
1106
1110
  }
1107
- return path36;
1111
+ return path37;
1108
1112
  }
1109
1113
  dropToLevel(level) {
1110
1114
  if (level < this.depth) {
@@ -1194,9 +1198,9 @@ var require_Assembler = __commonJS({
1194
1198
  }
1195
1199
  });
1196
1200
 
1197
- // ../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/streamers/StreamBase.js
1201
+ // ../../node_modules/stream-json/streamers/StreamBase.js
1198
1202
  var require_StreamBase = __commonJS({
1199
- "../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/streamers/StreamBase.js"(exports, module) {
1203
+ "../../node_modules/stream-json/streamers/StreamBase.js"(exports, module) {
1200
1204
  "use strict";
1201
1205
  var { Transform } = __require("stream");
1202
1206
  var Assembler = require_Assembler();
@@ -1293,9 +1297,9 @@ var require_StreamBase = __commonJS({
1293
1297
  }
1294
1298
  });
1295
1299
 
1296
- // ../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/streamers/StreamValues.js
1300
+ // ../../node_modules/stream-json/streamers/StreamValues.js
1297
1301
  var require_StreamValues = __commonJS({
1298
- "../../node_modules/.pnpm/stream-json@1.9.1/node_modules/stream-json/streamers/StreamValues.js"(exports, module) {
1302
+ "../../node_modules/stream-json/streamers/StreamValues.js"(exports, module) {
1299
1303
  "use strict";
1300
1304
  var StreamBase = require_StreamBase();
1301
1305
  var withParser = require_withParser();
@@ -2077,6 +2081,12 @@ function getChatSessionSummary(db, chatSessionId) {
2077
2081
  function saveChatSessionSummary(db, chatSessionId, summary) {
2078
2082
  db.prepare("UPDATE chat_session SET summary = ? WHERE id = ?").run(summary, chatSessionId);
2079
2083
  }
2084
+ function updateSessionOwnerId(db, ownerId) {
2085
+ db.prepare("UPDATE meta SET owner_id = ?").run(ownerId);
2086
+ }
2087
+ function renameSession(db, newName) {
2088
+ db.prepare("UPDATE meta SET name = ?").run(newName);
2089
+ }
2080
2090
  function clearSessionIndex(db) {
2081
2091
  db.exec("DELETE FROM message_context");
2082
2092
  db.exec("DELETE FROM chat_session");
@@ -2191,6 +2201,26 @@ function generateIncrementalSessionIndex(db, gapThreshold = DEFAULT_SESSION_GAP_
2191
2201
  return newSessionCount;
2192
2202
  });
2193
2203
  }
2204
+ function getPrivateChatMemberAvatar(db, sessionName, ownerId) {
2205
+ const members = db.prepare(
2206
+ `SELECT
2207
+ m.platform_id as platformId,
2208
+ COALESCE(m.group_nickname, m.account_name, m.platform_id) as name,
2209
+ m.avatar
2210
+ FROM member m
2211
+ WHERE COALESCE(m.account_name, '') != '\u7CFB\u7EDF\u6D88\u606F'
2212
+ ORDER BY (SELECT COUNT(*) FROM message WHERE sender_id = m.id) DESC`
2213
+ ).all();
2214
+ if (members.length === 0) return null;
2215
+ if (ownerId) {
2216
+ const other = members.find((m) => m.platformId !== ownerId);
2217
+ if (other?.avatar) return other.avatar;
2218
+ }
2219
+ const sameName = members.find((m) => m.name === sessionName);
2220
+ if (sameName?.avatar) return sameName.avatar;
2221
+ const firstWithAvatar = members.find((m) => m.avatar);
2222
+ return firstWithAvatar?.avatar || null;
2223
+ }
2194
2224
 
2195
2225
  // ../../packages/core/src/query/message-sql.ts
2196
2226
  var FULL_MSG_COLUMNS = `
@@ -2455,6 +2485,29 @@ function getSchemaDetailed(db) {
2455
2485
  };
2456
2486
  });
2457
2487
  }
2488
+ function getMemberNameHistoryFromMessages(db, memberId) {
2489
+ const rows = db.prepare(
2490
+ `SELECT
2491
+ sender_account_name as accountName,
2492
+ sender_group_nickname as groupNickname,
2493
+ MIN(ts) as startTs,
2494
+ MAX(ts) as endTs
2495
+ FROM message
2496
+ WHERE sender_id = ?
2497
+ GROUP BY sender_account_name, sender_group_nickname
2498
+ ORDER BY startTs`
2499
+ ).all(memberId);
2500
+ const history = [];
2501
+ for (const row of rows) {
2502
+ if (row.accountName) {
2503
+ history.push({ nameType: "account_name", name: row.accountName, startTs: row.startTs, endTs: row.endTs });
2504
+ }
2505
+ if (row.groupNickname) {
2506
+ history.push({ nameType: "group_nickname", name: row.groupNickname, startTs: row.startTs, endTs: row.endTs });
2507
+ }
2508
+ }
2509
+ return history;
2510
+ }
2458
2511
  function hydrateMessagesByIds(db, ids) {
2459
2512
  if (ids.length === 0) return [];
2460
2513
  const placeholders = ids.map(() => "?").join(", ");
@@ -2547,11 +2600,12 @@ function getConversationBetween(db, memberId1, memberId2, filter, limit = 100) {
2547
2600
  };
2548
2601
  }
2549
2602
  function getMemberNameHistory(db, memberId) {
2550
- if (!hasTable(db, "member_name_history")) return [];
2551
- return db.prepare(
2603
+ if (!hasTable(db, "member_name_history")) return getMemberNameHistoryFromMessages(db, memberId);
2604
+ const history = db.prepare(
2552
2605
  `SELECT name_type as nameType, name, start_ts as startTs, end_ts as endTs
2553
2606
  FROM member_name_history WHERE member_id = ? ORDER BY start_ts DESC`
2554
2607
  ).all(memberId);
2608
+ return history.length > 0 ? history : getMemberNameHistoryFromMessages(db, memberId);
2555
2609
  }
2556
2610
  function getMembersWithAliases(db) {
2557
2611
  const aliasesAvailable = hasColumn(db, "member", "aliases");
@@ -2643,6 +2697,87 @@ function executeParameterizedSql(db, query, params = {}) {
2643
2697
  return stmt.all(params);
2644
2698
  }
2645
2699
 
2700
+ // ../../packages/core/src/query/member-ops.ts
2701
+ function parseAliases(raw) {
2702
+ if (!raw) return [];
2703
+ try {
2704
+ const parsed = JSON.parse(raw);
2705
+ if (!Array.isArray(parsed)) return [];
2706
+ return parsed.filter((item) => typeof item === "string" && item.trim().length > 0);
2707
+ } catch {
2708
+ return [];
2709
+ }
2710
+ }
2711
+ function updateMemberAliases(db, memberId, aliases) {
2712
+ try {
2713
+ db.prepare("UPDATE member SET aliases = ? WHERE id = ?").run(JSON.stringify(aliases), memberId);
2714
+ return true;
2715
+ } catch {
2716
+ return false;
2717
+ }
2718
+ }
2719
+ function mergeMembers(db, memberId1, memberId2) {
2720
+ if (memberId1 === memberId2) return false;
2721
+ try {
2722
+ const rows = db.prepare(
2723
+ `
2724
+ SELECT
2725
+ m.id,
2726
+ m.platform_id as platformId,
2727
+ m.account_name as accountName,
2728
+ m.group_nickname as groupNickname,
2729
+ m.aliases,
2730
+ m.avatar,
2731
+ COUNT(msg.id) as messageCount
2732
+ FROM member m
2733
+ LEFT JOIN message msg ON m.id = msg.sender_id
2734
+ WHERE m.id IN (?, ?)
2735
+ GROUP BY m.id
2736
+ `
2737
+ ).all(memberId1, memberId2);
2738
+ if (rows.length !== 2) return false;
2739
+ const [memberA, memberB] = rows;
2740
+ let primary = memberA;
2741
+ let secondary = memberB;
2742
+ if (memberB.messageCount > memberA.messageCount || memberB.messageCount === memberA.messageCount && memberB.id < memberA.id) {
2743
+ primary = memberB;
2744
+ secondary = memberA;
2745
+ }
2746
+ const mergedAliases = Array.from(/* @__PURE__ */ new Set([...parseAliases(primary.aliases), ...parseAliases(secondary.aliases)]));
2747
+ const mergedAccountName = primary.accountName || secondary.accountName;
2748
+ const mergedGroupNickname = primary.groupNickname || secondary.groupNickname;
2749
+ const mergedAvatar = primary.avatar || secondary.avatar;
2750
+ db.transaction(() => {
2751
+ db.prepare("UPDATE message SET sender_id = ? WHERE sender_id = ?").run(primary.id, secondary.id);
2752
+ db.prepare("UPDATE member_name_history SET member_id = ? WHERE member_id = ?").run(primary.id, secondary.id);
2753
+ db.prepare("UPDATE meta SET owner_id = ? WHERE owner_id = ?").run(primary.platformId, secondary.platformId);
2754
+ db.prepare(`UPDATE member SET account_name = ?, group_nickname = ?, avatar = ?, aliases = ? WHERE id = ?`).run(
2755
+ mergedAccountName,
2756
+ mergedGroupNickname,
2757
+ mergedAvatar,
2758
+ JSON.stringify(mergedAliases),
2759
+ primary.id
2760
+ );
2761
+ db.prepare("DELETE FROM member WHERE id = ?").run(secondary.id);
2762
+ });
2763
+ return true;
2764
+ } catch {
2765
+ return false;
2766
+ }
2767
+ }
2768
+ function deleteMember(db, memberId) {
2769
+ try {
2770
+ db.transaction(() => {
2771
+ db.prepare("DELETE FROM message WHERE sender_id = ?").run(memberId);
2772
+ db.prepare("DELETE FROM member_name_history WHERE member_id = ?").run(memberId);
2773
+ db.prepare("DELETE FROM member WHERE id = ?").run(memberId);
2774
+ });
2775
+ return true;
2776
+ } catch {
2777
+ return false;
2778
+ }
2779
+ }
2780
+
2646
2781
  // ../../packages/core/src/query/advanced/repeat.ts
2647
2782
  function getCatchphraseAnalysis(db, filter) {
2648
2783
  const { clause, params } = buildTimeFilter(filter);
@@ -5563,6 +5698,111 @@ function getBuiltinModelsByProvider(providerId) {
5563
5698
  return BUILTIN_MODELS.filter((m) => m.providerId === providerId);
5564
5699
  }
5565
5700
 
5701
+ // ../../packages/core/src/ai/content-parser.ts
5702
+ var THINK_TAGS = ["think", "analysis", "reasoning", "reflection", "thought", "thinking"];
5703
+
5704
+ // ../../packages/core/src/ai/streaming-think-parser.ts
5705
+ var StreamingThinkTagParser = class {
5706
+ state = "content";
5707
+ buffer = "";
5708
+ activeTag = "";
5709
+ emit;
5710
+ constructor(emit) {
5711
+ this.emit = emit;
5712
+ }
5713
+ feed(text) {
5714
+ this.buffer += text;
5715
+ this.processBuffer();
5716
+ }
5717
+ /** Flush any remaining buffer (call at stream end). */
5718
+ flush() {
5719
+ if (!this.buffer) return;
5720
+ if (this.state === "thinking") {
5721
+ this.emit({ type: "thinking_delta", content: this.buffer });
5722
+ } else {
5723
+ this.emit({ type: "content", content: this.buffer });
5724
+ }
5725
+ this.buffer = "";
5726
+ }
5727
+ processBuffer() {
5728
+ while (this.buffer.length > 0) {
5729
+ const ltIdx = this.buffer.indexOf("<");
5730
+ if (ltIdx === -1) {
5731
+ this.emitBufferContent(this.buffer);
5732
+ this.buffer = "";
5733
+ return;
5734
+ }
5735
+ if (ltIdx > 0) {
5736
+ this.emitBufferContent(this.buffer.slice(0, ltIdx));
5737
+ this.buffer = this.buffer.slice(ltIdx);
5738
+ }
5739
+ const tagResult = this.tryMatchTag();
5740
+ if (tagResult === "incomplete") {
5741
+ return;
5742
+ }
5743
+ if (tagResult === "matched") {
5744
+ continue;
5745
+ }
5746
+ this.emitBufferContent("<");
5747
+ this.buffer = this.buffer.slice(1);
5748
+ }
5749
+ }
5750
+ /**
5751
+ * Try to match a think tag at the start of buffer.
5752
+ * Returns: 'matched' if a tag was consumed, 'incomplete' if more data
5753
+ * needed, 'no_match' if it's not a valid think tag.
5754
+ */
5755
+ tryMatchTag() {
5756
+ if (this.state === "content") {
5757
+ return this.tryMatchOpenTag();
5758
+ }
5759
+ return this.tryMatchCloseTag();
5760
+ }
5761
+ tryMatchOpenTag() {
5762
+ for (const tag of THINK_TAGS) {
5763
+ const openTag = `<${tag}>`;
5764
+ if (this.buffer.startsWith(openTag)) {
5765
+ this.buffer = this.buffer.slice(openTag.length);
5766
+ this.state = "thinking";
5767
+ this.activeTag = tag;
5768
+ this.emit({ type: "thinking_start", tag });
5769
+ return "matched";
5770
+ }
5771
+ if (openTag.startsWith(this.buffer) && this.buffer.length < openTag.length) {
5772
+ return "incomplete";
5773
+ }
5774
+ }
5775
+ return "no_match";
5776
+ }
5777
+ tryMatchCloseTag() {
5778
+ const closeTag = `</${this.activeTag}>`;
5779
+ if (this.buffer.startsWith(closeTag)) {
5780
+ this.buffer = this.buffer.slice(closeTag.length);
5781
+ this.state = "content";
5782
+ this.emit({ type: "thinking_end" });
5783
+ this.activeTag = "";
5784
+ return "matched";
5785
+ }
5786
+ if (closeTag.startsWith(this.buffer) && this.buffer.length < closeTag.length) {
5787
+ return "incomplete";
5788
+ }
5789
+ this.emit({ type: "thinking_delta", content: "<" });
5790
+ this.buffer = this.buffer.slice(1);
5791
+ return "matched";
5792
+ }
5793
+ emitBufferContent(text) {
5794
+ if (!text) return;
5795
+ if (this.state === "thinking") {
5796
+ this.emit({ type: "thinking_delta", content: text });
5797
+ } else {
5798
+ this.emit({ type: "content", content: text });
5799
+ }
5800
+ }
5801
+ };
5802
+ function needsStreamingThinkParsing(provider, _modelId) {
5803
+ return provider === "minimax";
5804
+ }
5805
+
5566
5806
  // ../../packages/core/src/import/dedup.ts
5567
5807
  function fnv1a64(input) {
5568
5808
  let h0 = 2166136261;
@@ -5845,6 +6085,10 @@ function runMigrations(db, migrationsList, forceRepair = false) {
5845
6085
  return true;
5846
6086
  }
5847
6087
 
6088
+ // ../../packages/parser/src/index.ts
6089
+ import * as fs17 from "fs";
6090
+ import * as path13 from "path";
6091
+
5848
6092
  // ../../packages/parser/src/sniffer.ts
5849
6093
  import * as fs2 from "fs";
5850
6094
  import * as path2 from "path";
@@ -9476,6 +9720,32 @@ async function* parseFileWithFormat(formatId, options) {
9476
9720
  console.log(`[Parser V2] Using parser (explicit): ${parser9.feature.name}`);
9477
9721
  yield* parser9.parse(options);
9478
9722
  }
9723
+ function findEntryFileInDirectory(dirPath, maxDepth = 1) {
9724
+ function walk(current, depth) {
9725
+ if (depth > maxDepth) return null;
9726
+ let entries;
9727
+ try {
9728
+ entries = fs17.readdirSync(current, { withFileTypes: true });
9729
+ } catch {
9730
+ return null;
9731
+ }
9732
+ for (const entry of entries) {
9733
+ const full = path13.join(current, entry.name);
9734
+ if (entry.isFile() && entry.name.endsWith(".json")) {
9735
+ const format = detectFormat(full);
9736
+ if (format) return full;
9737
+ }
9738
+ }
9739
+ for (const entry of entries) {
9740
+ if (entry.isDirectory()) {
9741
+ const found = walk(path13.join(current, entry.name), depth + 1);
9742
+ if (found) return found;
9743
+ }
9744
+ }
9745
+ return null;
9746
+ }
9747
+ return walk(dirPath, 0);
9748
+ }
9479
9749
  async function streamParseFile(filePath, callbacks, formatId) {
9480
9750
  const { onProgress, onMeta, onMembers, onMessageBatch, onLog, batchSize = 5e3, formatOptions } = callbacks;
9481
9751
  const generator = formatId ? parseFileWithFormat(formatId, { filePath, batchSize, formatOptions, onProgress, onLog }) : parseFile({ filePath, batchSize, formatOptions, onProgress, onLog });
@@ -9500,11 +9770,11 @@ async function streamParseFile(filePath, callbacks, formatId) {
9500
9770
  }
9501
9771
 
9502
9772
  // ../../packages/node-runtime/src/import/streaming-importer.ts
9503
- import * as fs19 from "fs";
9773
+ import * as fs20 from "fs";
9504
9774
 
9505
9775
  // ../../packages/node-runtime/src/nlp/segmenter.ts
9506
- import * as fs17 from "fs";
9507
- import * as path13 from "path";
9776
+ import * as fs18 from "fs";
9777
+ import * as path14 from "path";
9508
9778
  var _nlpDir = null;
9509
9779
  var jiebaInstances = /* @__PURE__ */ new Map();
9510
9780
  function initNlpDir(nlpDir) {
@@ -9515,14 +9785,14 @@ function getNlpDir() {
9515
9785
  }
9516
9786
  function existsDictOnDisk(dictId) {
9517
9787
  if (!_nlpDir) return false;
9518
- return fs17.existsSync(path13.join(_nlpDir, `${dictId}.dict`));
9788
+ return fs18.existsSync(path14.join(_nlpDir, `${dictId}.dict`));
9519
9789
  }
9520
9790
  function tryLoadDictFromDisk(dictId) {
9521
9791
  if (!_nlpDir) return null;
9522
- const dictPath = path13.join(_nlpDir, `${dictId}.dict`);
9523
- if (!fs17.existsSync(dictPath)) return null;
9792
+ const dictPath = path14.join(_nlpDir, `${dictId}.dict`);
9793
+ if (!fs18.existsSync(dictPath)) return null;
9524
9794
  try {
9525
- return fs17.readFileSync(dictPath);
9795
+ return fs18.readFileSync(dictPath);
9526
9796
  } catch {
9527
9797
  return null;
9528
9798
  }
@@ -9789,8 +10059,8 @@ function tokenizeQueryForFts(keywords) {
9789
10059
  }
9790
10060
 
9791
10061
  // ../../packages/node-runtime/src/nlp/dict-manager.ts
9792
- import * as fs18 from "fs";
9793
- import * as path14 from "path";
10062
+ import * as fs19 from "fs";
10063
+ import * as path15 from "path";
9794
10064
  import { createHash } from "crypto";
9795
10065
  var DICT_DOWNLOAD_URL_BASE = "https://chatlab.fun/assets/nlp";
9796
10066
  var DICT_SHA256 = {
@@ -9802,19 +10072,19 @@ var AVAILABLE_DICTS = [
9802
10072
  { id: "zh-TW", label: "\u7E41\u9AD4\u4E2D\u6587", locale: "zh-TW" }
9803
10073
  ];
9804
10074
  function getDictFilePath(nlpDir, dictId) {
9805
- return path14.join(nlpDir, `${dictId}.dict`);
10075
+ return path15.join(nlpDir, `${dictId}.dict`);
9806
10076
  }
9807
10077
  function isDictDownloaded(nlpDir, dictId) {
9808
- return fs18.existsSync(getDictFilePath(nlpDir, dictId));
10078
+ return fs19.existsSync(getDictFilePath(nlpDir, dictId));
9809
10079
  }
9810
10080
  function getDictList(nlpDir) {
9811
10081
  return AVAILABLE_DICTS.map((d) => {
9812
10082
  const filePath = getDictFilePath(nlpDir, d.id);
9813
- const downloaded = fs18.existsSync(filePath);
10083
+ const downloaded = fs19.existsSync(filePath);
9814
10084
  let fileSize;
9815
10085
  if (downloaded) {
9816
10086
  try {
9817
- fileSize = fs18.statSync(filePath).size;
10087
+ fileSize = fs19.statSync(filePath).size;
9818
10088
  } catch {
9819
10089
  }
9820
10090
  }
@@ -9823,9 +10093,9 @@ function getDictList(nlpDir) {
9823
10093
  }
9824
10094
  function loadDictBuffer(nlpDir, dictId) {
9825
10095
  const filePath = getDictFilePath(nlpDir, dictId);
9826
- if (!fs18.existsSync(filePath)) return null;
10096
+ if (!fs19.existsSync(filePath)) return null;
9827
10097
  try {
9828
- return fs18.readFileSync(filePath);
10098
+ return fs19.readFileSync(filePath);
9829
10099
  } catch (error) {
9830
10100
  console.error(`[NLP DictManager] Failed to read dict file: ${filePath}`, error);
9831
10101
  return null;
@@ -9835,7 +10105,7 @@ async function downloadDict(nlpDir, dictId, onProgress) {
9835
10105
  if (!AVAILABLE_DICTS.find((d) => d.id === dictId)) {
9836
10106
  return { success: false, error: `Unknown dict: ${dictId}` };
9837
10107
  }
9838
- fs18.mkdirSync(nlpDir, { recursive: true });
10108
+ fs19.mkdirSync(nlpDir, { recursive: true });
9839
10109
  const url = `${DICT_DOWNLOAD_URL_BASE}/${dictId}.dict`;
9840
10110
  const filePath = getDictFilePath(nlpDir, dictId);
9841
10111
  const tmpPath = filePath + ".tmp";
@@ -9876,16 +10146,16 @@ async function downloadDict(nlpDir, dictId, onProgress) {
9876
10146
  if (actualSha256 !== expectedSha256) {
9877
10147
  return { success: false, error: "Dictionary integrity check failed (SHA256 mismatch)" };
9878
10148
  }
9879
- fs18.writeFileSync(tmpPath, buffer);
9880
- if (fs18.existsSync(filePath)) fs18.unlinkSync(filePath);
9881
- fs18.renameSync(tmpPath, filePath);
10149
+ fs19.writeFileSync(tmpPath, buffer);
10150
+ if (fs19.existsSync(filePath)) fs19.unlinkSync(filePath);
10151
+ fs19.renameSync(tmpPath, filePath);
9882
10152
  clearJiebaInstance(dictId);
9883
- console.log(`[NLP DictManager] Dict downloaded: ${dictId} (${fs18.statSync(filePath).size} bytes)`);
10153
+ console.log(`[NLP DictManager] Dict downloaded: ${dictId} (${fs19.statSync(filePath).size} bytes)`);
9884
10154
  return { success: true };
9885
10155
  } catch (error) {
9886
- if (fs18.existsSync(tmpPath)) {
10156
+ if (fs19.existsSync(tmpPath)) {
9887
10157
  try {
9888
- fs18.unlinkSync(tmpPath);
10158
+ fs19.unlinkSync(tmpPath);
9889
10159
  } catch {
9890
10160
  }
9891
10161
  }
@@ -9896,9 +10166,9 @@ async function downloadDict(nlpDir, dictId, onProgress) {
9896
10166
  }
9897
10167
  function deleteDict(nlpDir, dictId) {
9898
10168
  const filePath = getDictFilePath(nlpDir, dictId);
9899
- if (!fs18.existsSync(filePath)) return { success: true };
10169
+ if (!fs19.existsSync(filePath)) return { success: true };
9900
10170
  try {
9901
- fs18.unlinkSync(filePath);
10171
+ fs19.unlinkSync(filePath);
9902
10172
  clearJiebaInstance(dictId);
9903
10173
  console.log(`[NLP DictManager] Dict deleted: ${dictId}`);
9904
10174
  return { success: true };
@@ -10447,7 +10717,7 @@ async function streamParseFileInfo(filePath, deps) {
10447
10717
  if (!formatFeature) {
10448
10718
  throw new Error("Unrecognized file format");
10449
10719
  }
10450
- const fileSize = fs19.statSync(filePath).size;
10720
+ const fileSize = fs20.statSync(filePath).size;
10451
10721
  deps.onProgress({
10452
10722
  stage: "parsing",
10453
10723
  bytesRead: 0,
@@ -10536,7 +10806,7 @@ async function streamParseFileInfo(filePath, deps) {
10536
10806
  }
10537
10807
  db.close();
10538
10808
  try {
10539
- if (fs19.existsSync(tempDbPath)) fs19.unlinkSync(tempDbPath);
10809
+ if (fs20.existsSync(tempDbPath)) fs20.unlinkSync(tempDbPath);
10540
10810
  } catch {
10541
10811
  }
10542
10812
  throw error;
@@ -10894,15 +11164,15 @@ async function incrementalImport(sessionId, filePath, deps, options) {
10894
11164
  }
10895
11165
 
10896
11166
  // ../../packages/node-runtime/src/ai/ai-logger.ts
10897
- import * as fs20 from "fs";
10898
- import * as path15 from "path";
11167
+ import * as fs21 from "fs";
11168
+ import * as path16 from "path";
10899
11169
  var AiLogger = class {
10900
11170
  debugMode = false;
10901
11171
  logDir;
10902
11172
  logFile = null;
10903
11173
  logStream = null;
10904
11174
  constructor(logsDir) {
10905
- this.logDir = path15.join(logsDir, "ai");
11175
+ this.logDir = path16.join(logsDir, "ai");
10906
11176
  }
10907
11177
  setDebugMode(enabled) {
10908
11178
  this.debugMode = enabled;
@@ -10932,14 +11202,14 @@ var AiLogger = class {
10932
11202
  return this.getLogFilePath();
10933
11203
  }
10934
11204
  getExistingLogPath() {
10935
- if (this.logFile && fs20.existsSync(this.logFile)) {
11205
+ if (this.logFile && fs21.existsSync(this.logFile)) {
10936
11206
  return this.logFile;
10937
11207
  }
10938
11208
  return null;
10939
11209
  }
10940
11210
  ensureLogDir() {
10941
- if (!fs20.existsSync(this.logDir)) {
10942
- fs20.mkdirSync(this.logDir, { recursive: true });
11211
+ if (!fs21.existsSync(this.logDir)) {
11212
+ fs21.mkdirSync(this.logDir, { recursive: true });
10943
11213
  }
10944
11214
  }
10945
11215
  getLogFilePath() {
@@ -10949,14 +11219,14 @@ var AiLogger = class {
10949
11219
  const date = now.toISOString().split("T")[0];
10950
11220
  const hours = String(now.getHours()).padStart(2, "0");
10951
11221
  const minutes = String(now.getMinutes()).padStart(2, "0");
10952
- this.logFile = path15.join(this.logDir, `ai_${date}_${hours}-${minutes}.log`);
11222
+ this.logFile = path16.join(this.logDir, `ai_${date}_${hours}-${minutes}.log`);
10953
11223
  return this.logFile;
10954
11224
  }
10955
11225
  getLogStream() {
10956
11226
  if (this.logStream) return this.logStream;
10957
11227
  const filePath = this.getLogFilePath();
10958
- const isNewOrEmptyFile = !fs20.existsSync(filePath) || fs20.statSync(filePath).size === 0;
10959
- this.logStream = fs20.createWriteStream(filePath, { flags: "a", encoding: "utf-8" });
11228
+ const isNewOrEmptyFile = !fs21.existsSync(filePath) || fs21.statSync(filePath).size === 0;
11229
+ this.logStream = fs21.createWriteStream(filePath, { flags: "a", encoding: "utf-8" });
10960
11230
  if (isNewOrEmptyFile) {
10961
11231
  this.logStream.write(`Local Path: ${filePath.replace(/ /g, "\\ ")}
10962
11232
 
@@ -11082,12 +11352,12 @@ ${rawErrorLabel}: ${details}`;
11082
11352
  }
11083
11353
 
11084
11354
  // ../../packages/node-runtime/src/ai/assistant-parser.ts
11085
- import * as path16 from "path";
11355
+ import * as path17 from "path";
11086
11356
  import matter from "gray-matter";
11087
11357
  function parseAssistantFile(content, filePath) {
11088
11358
  try {
11089
11359
  const { data: fm, content: body } = matter(content);
11090
- const id = fm.id ?? path16.basename(filePath, ".md");
11360
+ const id = fm.id ?? path17.basename(filePath, ".md");
11091
11361
  const name = fm.name;
11092
11362
  if (!name) return null;
11093
11363
  return {
@@ -11166,8 +11436,8 @@ var AssistantManager = class {
11166
11436
  }
11167
11437
  // ==================== Init ====================
11168
11438
  init() {
11169
- const { fs: fs38, assistantsDir } = this.deps;
11170
- fs38.ensureDir(assistantsDir);
11439
+ const { fs: fs40, assistantsDir } = this.deps;
11440
+ fs40.ensureDir(assistantsDir);
11171
11441
  const generalCreated = this.ensureGeneralAssistants();
11172
11442
  this.loadAll();
11173
11443
  this.initialized = true;
@@ -11178,26 +11448,26 @@ var AssistantManager = class {
11178
11448
  return { total: this.cache.size, generalCreated };
11179
11449
  }
11180
11450
  ensureGeneralAssistants() {
11181
- const { fs: fs38, assistantsDir } = this.deps;
11451
+ const { fs: fs40, assistantsDir } = this.deps;
11182
11452
  let anyCreated = false;
11183
11453
  for (const id of this.generalIds) {
11184
11454
  const config = this.getBuiltinConfig(id);
11185
11455
  if (!config) continue;
11186
- const filePath = fs38.joinPath(assistantsDir, `${id}.md`);
11187
- if (fs38.fileExists(filePath)) continue;
11188
- fs38.writeFile(filePath, serializeAssistant({ ...config, builtinId: config.id }));
11456
+ const filePath = fs40.joinPath(assistantsDir, `${id}.md`);
11457
+ if (fs40.fileExists(filePath)) continue;
11458
+ fs40.writeFile(filePath, serializeAssistant({ ...config, builtinId: config.id }));
11189
11459
  anyCreated = true;
11190
11460
  }
11191
11461
  return anyCreated;
11192
11462
  }
11193
11463
  loadAll() {
11194
- const { fs: fs38, assistantsDir } = this.deps;
11464
+ const { fs: fs40, assistantsDir } = this.deps;
11195
11465
  this.cache.clear();
11196
- const files = fs38.listFiles(assistantsDir, ".md");
11466
+ const files = fs40.listFiles(assistantsDir, ".md");
11197
11467
  for (const file of files) {
11198
11468
  try {
11199
- const filePath = fs38.joinPath(assistantsDir, file);
11200
- const content = fs38.readFile(filePath);
11469
+ const filePath = fs40.joinPath(assistantsDir, file);
11470
+ const content = fs40.readFile(filePath);
11201
11471
  const config = parseAssistantFile(content, filePath);
11202
11472
  if (config) {
11203
11473
  this.cache.set(config.id, config);
@@ -11309,12 +11579,12 @@ var AssistantManager = class {
11309
11579
  };
11310
11580
 
11311
11581
  // ../../packages/node-runtime/src/ai/skill-parser.ts
11312
- import * as path17 from "path";
11582
+ import * as path18 from "path";
11313
11583
  import matter2 from "gray-matter";
11314
11584
  function parseSkillFile(content, filePath) {
11315
11585
  try {
11316
11586
  const { data: fm, content: prompt } = matter2(content);
11317
- const id = fm.id ?? path17.basename(filePath, ".md");
11587
+ const id = fm.id ?? path18.basename(filePath, ".md");
11318
11588
  const name = fm.name;
11319
11589
  if (!name) return null;
11320
11590
  return {
@@ -11333,7 +11603,7 @@ function parseSkillFile(content, filePath) {
11333
11603
  function extractSkillId(content, filePath) {
11334
11604
  try {
11335
11605
  const { data: fm } = matter2(content);
11336
- return fm.id ?? path17.basename(filePath, ".md");
11606
+ return fm.id ?? path18.basename(filePath, ".md");
11337
11607
  } catch {
11338
11608
  return null;
11339
11609
  }
@@ -11352,8 +11622,8 @@ function validateChatScope(raw) {
11352
11622
 
11353
11623
  // ../../packages/node-runtime/src/ai/conversations.ts
11354
11624
  import Database2 from "better-sqlite3";
11355
- import * as fs21 from "fs";
11356
- import * as path18 from "path";
11625
+ import * as fs22 from "fs";
11626
+ import * as path19 from "path";
11357
11627
  var DEFAULT_GENERAL_ID = "general_cn";
11358
11628
  var defaultLogger = {
11359
11629
  warn(_category, message, extra) {
@@ -11372,14 +11642,14 @@ var AIConversationManager = class {
11372
11642
  this.nativeBinding = options?.nativeBinding;
11373
11643
  }
11374
11644
  ensureDir(dir) {
11375
- if (!fs21.existsSync(dir)) {
11376
- fs21.mkdirSync(dir, { recursive: true });
11645
+ if (!fs22.existsSync(dir)) {
11646
+ fs22.mkdirSync(dir, { recursive: true });
11377
11647
  }
11378
11648
  }
11379
11649
  getDb() {
11380
11650
  if (this.db) return this.db;
11381
11651
  this.ensureDir(this.aiDataDir);
11382
- const dbPath = path18.join(this.aiDataDir, "conversations.db");
11652
+ const dbPath = path19.join(this.aiDataDir, "conversations.db");
11383
11653
  this.db = this.nativeBinding ? new Database2(dbPath, { nativeBinding: this.nativeBinding }) : new Database2(dbPath);
11384
11654
  this.db.pragma("journal_mode = WAL");
11385
11655
  this.db.exec(`
@@ -11766,8 +12036,8 @@ function countMessagesTokens(messages, systemPrompt) {
11766
12036
  }
11767
12037
 
11768
12038
  // ../../packages/node-runtime/src/ai/skill-manager.ts
11769
- import * as fs22 from "fs";
11770
- import * as path19 from "path";
12039
+ import * as fs23 from "fs";
12040
+ import * as path20 from "path";
11771
12041
  var SKILLS_DIR_NAME = "skills";
11772
12042
  var MAX_SKILL_MENU_ITEMS = 15;
11773
12043
  var defaultLogger2 = {
@@ -11782,7 +12052,7 @@ var SkillManager = class {
11782
12052
  skillsDir;
11783
12053
  logger;
11784
12054
  constructor(aiDataDir, logger) {
11785
- this.skillsDir = path19.join(aiDataDir, SKILLS_DIR_NAME);
12055
+ this.skillsDir = path20.join(aiDataDir, SKILLS_DIR_NAME);
11786
12056
  this.logger = logger ?? defaultLogger2;
11787
12057
  }
11788
12058
  init() {
@@ -11839,12 +12109,12 @@ ${lines.join("\n")}
11839
12109
  }
11840
12110
  loadAll() {
11841
12111
  this.skills.clear();
11842
- if (!fs22.existsSync(this.skillsDir)) return;
11843
- const files = fs22.readdirSync(this.skillsDir).filter((f) => f.endsWith(".md"));
12112
+ if (!fs23.existsSync(this.skillsDir)) return;
12113
+ const files = fs23.readdirSync(this.skillsDir).filter((f) => f.endsWith(".md"));
11844
12114
  for (const file of files) {
11845
12115
  try {
11846
- const filePath = path19.join(this.skillsDir, file);
11847
- const content = fs22.readFileSync(filePath, "utf-8");
12116
+ const filePath = path20.join(this.skillsDir, file);
12117
+ const content = fs23.readFileSync(filePath, "utf-8");
11848
12118
  const def = parseSkillFile(content, filePath);
11849
12119
  if (def) {
11850
12120
  this.skills.set(def.id, def);
@@ -11911,21 +12181,21 @@ var SkillManagerCore = class {
11911
12181
  }
11912
12182
  // ==================== Init ====================
11913
12183
  init() {
11914
- const { fs: fs38, skillsDir } = this.deps;
11915
- fs38.ensureDir(skillsDir);
12184
+ const { fs: fs40, skillsDir } = this.deps;
12185
+ fs40.ensureDir(skillsDir);
11916
12186
  this.loadAll();
11917
12187
  this.initialized = true;
11918
12188
  this.deps.logger?.info("SkillManager", "Initialized", { total: this.cache.size });
11919
12189
  return { total: this.cache.size };
11920
12190
  }
11921
12191
  loadAll() {
11922
- const { fs: fs38, skillsDir } = this.deps;
12192
+ const { fs: fs40, skillsDir } = this.deps;
11923
12193
  this.cache.clear();
11924
- const files = fs38.listFiles(skillsDir, ".md");
12194
+ const files = fs40.listFiles(skillsDir, ".md");
11925
12195
  for (const file of files) {
11926
12196
  try {
11927
- const filePath = fs38.joinPath(skillsDir, file);
11928
- const content = fs38.readFile(filePath);
12197
+ const filePath = fs40.joinPath(skillsDir, file);
12198
+ const content = fs40.readFile(filePath);
11929
12199
  const def = parseSkillFile(content, filePath);
11930
12200
  if (def) {
11931
12201
  this.cache.set(def.id, def);
@@ -12986,11 +13256,37 @@ async function runAgentCore(options) {
12986
13256
  coreAgent.replaceMessages(toPiHistoryMessages(history));
12987
13257
  let hasReachedToolRoundLimit = false;
12988
13258
  const thinkingStartTime = /* @__PURE__ */ new Map();
13259
+ const useThinkParser = needsStreamingThinkParsing(piModel.provider, piModel.id);
13260
+ let thinkParserStartTime;
13261
+ const thinkParser = useThinkParser ? new StreamingThinkTagParser((ev) => {
13262
+ switch (ev.type) {
13263
+ case "content":
13264
+ onEvent({ type: "content", content: ev.content });
13265
+ break;
13266
+ case "thinking_start":
13267
+ thinkParserStartTime = Date.now();
13268
+ onEvent({ type: "thinking_start" });
13269
+ break;
13270
+ case "thinking_delta":
13271
+ onEvent({ type: "thinking_delta", content: ev.content });
13272
+ break;
13273
+ case "thinking_end": {
13274
+ const durationMs = thinkParserStartTime ? Date.now() - thinkParserStartTime : void 0;
13275
+ thinkParserStartTime = void 0;
13276
+ onEvent({ type: "thinking_end", durationMs });
13277
+ break;
13278
+ }
13279
+ }
13280
+ }) : null;
12989
13281
  const unsubscribe = coreAgent.subscribe((event) => {
12990
13282
  if (event.type === "message_update") {
12991
13283
  const update = event.assistantMessageEvent;
12992
13284
  if (update.type === "text_delta") {
12993
- onEvent({ type: "content", content: update.delta });
13285
+ if (thinkParser) {
13286
+ thinkParser.feed(update.delta);
13287
+ } else {
13288
+ onEvent({ type: "content", content: update.delta });
13289
+ }
12994
13290
  } else if (update.type === "thinking_start") {
12995
13291
  thinkingStartTime.set(update.contentIndex, Date.now());
12996
13292
  onEvent({ type: "thinking_start" });
@@ -13028,6 +13324,7 @@ async function runAgentCore(options) {
13028
13324
  onEvent({ type: "turn_end", round: toolRounds, hadToolCalls });
13029
13325
  } else if (event.type === "message_end") {
13030
13326
  if (event.message.role === "assistant") {
13327
+ thinkParser?.flush();
13031
13328
  addPiUsage(event.message.usage);
13032
13329
  onEvent({ type: "usage_update", usage: { ...totalUsage } });
13033
13330
  }
@@ -14577,9 +14874,9 @@ var localeMap = {
14577
14874
  "ja-JP": ja_JP_default,
14578
14875
  "zh-TW": zh_TW_default
14579
14876
  };
14580
- function getNestedValue(obj, path36) {
14877
+ function getNestedValue(obj, path37) {
14581
14878
  let current = obj;
14582
- for (const segment2 of path36.split(".")) {
14879
+ for (const segment2 of path37.split(".")) {
14583
14880
  if (current == null || typeof current !== "object") return void 0;
14584
14881
  current = current[segment2];
14585
14882
  }
@@ -15290,8 +15587,8 @@ async function runSimpleLlmStream(options) {
15290
15587
  import { Type, completeSimple as completeSimple4, streamSimple as streamSimple2 } from "@mariozechner/pi-ai";
15291
15588
 
15292
15589
  // ../../packages/node-runtime/src/ai/rag/config.ts
15293
- import * as fs23 from "fs";
15294
- import * as path20 from "path";
15590
+ import * as fs24 from "fs";
15591
+ import * as path21 from "path";
15295
15592
  import { randomUUID } from "crypto";
15296
15593
 
15297
15594
  // ../../packages/node-runtime/src/ai/rag/types.ts
@@ -15339,25 +15636,25 @@ function requireAiDataDir() {
15339
15636
  return _aiDataDir;
15340
15637
  }
15341
15638
  function getConfigPath() {
15342
- return path20.join(requireAiDataDir(), "rag-config.json");
15639
+ return path21.join(requireAiDataDir(), "rag-config.json");
15343
15640
  }
15344
15641
  function getEmbeddingConfigPath() {
15345
- return path20.join(requireAiDataDir(), "embedding-config.json");
15642
+ return path21.join(requireAiDataDir(), "embedding-config.json");
15346
15643
  }
15347
15644
  function getVectorStoreDir() {
15348
- const dir = path20.join(requireAiDataDir(), "vectors");
15349
- if (!fs23.existsSync(dir)) {
15350
- fs23.mkdirSync(dir, { recursive: true });
15645
+ const dir = path21.join(requireAiDataDir(), "vectors");
15646
+ if (!fs24.existsSync(dir)) {
15647
+ fs24.mkdirSync(dir, { recursive: true });
15351
15648
  }
15352
15649
  return dir;
15353
15650
  }
15354
15651
  function loadEmbeddingConfigStore() {
15355
15652
  const configPath = getEmbeddingConfigPath();
15356
- if (!fs23.existsSync(configPath)) {
15653
+ if (!fs24.existsSync(configPath)) {
15357
15654
  return { ...DEFAULT_EMBEDDING_CONFIG_STORE };
15358
15655
  }
15359
15656
  try {
15360
- const content = fs23.readFileSync(configPath, "utf-8");
15657
+ const content = fs24.readFileSync(configPath, "utf-8");
15361
15658
  const data = JSON.parse(content);
15362
15659
  return {
15363
15660
  configs: data.configs || [],
@@ -15371,11 +15668,11 @@ function loadEmbeddingConfigStore() {
15371
15668
  }
15372
15669
  function saveEmbeddingConfigStore(store) {
15373
15670
  const configPath = getEmbeddingConfigPath();
15374
- const dir = path20.dirname(configPath);
15375
- if (!fs23.existsSync(dir)) {
15376
- fs23.mkdirSync(dir, { recursive: true });
15671
+ const dir = path21.dirname(configPath);
15672
+ if (!fs24.existsSync(dir)) {
15673
+ fs24.mkdirSync(dir, { recursive: true });
15377
15674
  }
15378
- fs23.writeFileSync(configPath, JSON.stringify(store, null, 2), "utf-8");
15675
+ fs24.writeFileSync(configPath, JSON.stringify(store, null, 2), "utf-8");
15379
15676
  _logger.info("RAG", "Embedding configs saved");
15380
15677
  }
15381
15678
  function getAllEmbeddingConfigs() {
@@ -15461,10 +15758,10 @@ function getActiveEmbeddingConfigId() {
15461
15758
  function loadRAGConfig() {
15462
15759
  try {
15463
15760
  const configPath = getConfigPath();
15464
- if (!fs23.existsSync(configPath)) {
15761
+ if (!fs24.existsSync(configPath)) {
15465
15762
  return { ...DEFAULT_RAG_CONFIG };
15466
15763
  }
15467
- const content = fs23.readFileSync(configPath, "utf-8");
15764
+ const content = fs24.readFileSync(configPath, "utf-8");
15468
15765
  const config = JSON.parse(content);
15469
15766
  return mergeConfig(DEFAULT_RAG_CONFIG, config);
15470
15767
  } catch (error) {
@@ -15475,11 +15772,11 @@ function loadRAGConfig() {
15475
15772
  function saveRAGConfig(config) {
15476
15773
  try {
15477
15774
  const configPath = getConfigPath();
15478
- const dir = path20.dirname(configPath);
15479
- if (!fs23.existsSync(dir)) {
15480
- fs23.mkdirSync(dir, { recursive: true });
15775
+ const dir = path21.dirname(configPath);
15776
+ if (!fs24.existsSync(dir)) {
15777
+ fs24.mkdirSync(dir, { recursive: true });
15481
15778
  }
15482
- fs23.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
15779
+ fs24.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
15483
15780
  _logger.info("RAG", "Configs saved");
15484
15781
  } catch (error) {
15485
15782
  _logger.error("RAG", "Failed to save configs", error);
@@ -15979,7 +16276,7 @@ async function validateEmbeddingConfig(config) {
15979
16276
  }
15980
16277
 
15981
16278
  // ../../packages/node-runtime/src/ai/rag/store/index.ts
15982
- import * as path21 from "path";
16279
+ import * as path22 from "path";
15983
16280
 
15984
16281
  // ../../packages/node-runtime/src/ai/rag/store/sqlite.ts
15985
16282
  import Database4 from "better-sqlite3";
@@ -16096,8 +16393,8 @@ var SQLiteVectorStore = class {
16096
16393
  const dimRow = this.db.prepare("SELECT dimensions FROM vectors LIMIT 1").get();
16097
16394
  let sizeBytes;
16098
16395
  try {
16099
- const fs38 = await import("fs");
16100
- const stats = fs38.statSync(this.dbPath);
16396
+ const fs40 = await import("fs");
16397
+ const stats = fs40.statSync(this.dbPath);
16101
16398
  sizeBytes = stats.size;
16102
16399
  } catch {
16103
16400
  }
@@ -16294,7 +16591,7 @@ async function createVectorStore(config) {
16294
16591
  return new MemoryVectorStore(capacity);
16295
16592
  }
16296
16593
  case "sqlite": {
16297
- const dbPath = config.dbPath || path21.join(getVectorStoreDir(), "embeddings.db");
16594
+ const dbPath = config.dbPath || path22.join(getVectorStoreDir(), "embeddings.db");
16298
16595
  _logger7.info("Store Manager", `Using SQLite store: ${dbPath}`);
16299
16596
  return new SQLiteVectorStore(dbPath);
16300
16597
  }
@@ -16508,14 +16805,14 @@ function initRag(options) {
16508
16805
  }
16509
16806
 
16510
16807
  // ../../packages/node-runtime/src/node-path-provider.ts
16511
- import * as fs33 from "fs";
16808
+ import * as fs34 from "fs";
16512
16809
  import * as os5 from "os";
16513
- import * as path31 from "path";
16810
+ import * as path32 from "path";
16514
16811
 
16515
16812
  // ../../packages/config/src/loader.ts
16516
- import * as fs24 from "fs";
16813
+ import * as fs25 from "fs";
16517
16814
  import * as os2 from "os";
16518
- import * as path22 from "path";
16815
+ import * as path23 from "path";
16519
16816
  import { parse as parseToml } from "smol-toml";
16520
16817
 
16521
16818
  // ../../packages/config/src/schema.ts
@@ -16550,9 +16847,9 @@ var configSchema = z.object({
16550
16847
  });
16551
16848
 
16552
16849
  // ../../packages/config/src/loader.ts
16553
- var CONFIG_DIR = path22.join(os2.homedir(), ".chatlab");
16554
- var CONFIG_TOML = path22.join(CONFIG_DIR, "config.toml");
16555
- var CONFIG_JSON = path22.join(CONFIG_DIR, "config.json");
16850
+ var CONFIG_DIR = path23.join(os2.homedir(), ".chatlab");
16851
+ var CONFIG_TOML = path23.join(CONFIG_DIR, "config.toml");
16852
+ var CONFIG_JSON = path23.join(CONFIG_DIR, "config.json");
16556
16853
  function loadConfig(overrides) {
16557
16854
  const fileConfig = loadConfigFile();
16558
16855
  const envConfig = loadEnvConfig();
@@ -16560,25 +16857,25 @@ function loadConfig(overrides) {
16560
16857
  return configSchema.parse(merged);
16561
16858
  }
16562
16859
  function getConfigPath2() {
16563
- if (fs24.existsSync(CONFIG_TOML)) return CONFIG_TOML;
16564
- if (fs24.existsSync(CONFIG_JSON)) return CONFIG_JSON;
16860
+ if (fs25.existsSync(CONFIG_TOML)) return CONFIG_TOML;
16861
+ if (fs25.existsSync(CONFIG_JSON)) return CONFIG_JSON;
16565
16862
  return CONFIG_TOML;
16566
16863
  }
16567
16864
  function getConfigDir() {
16568
16865
  return CONFIG_DIR;
16569
16866
  }
16570
16867
  function loadConfigFile() {
16571
- if (fs24.existsSync(CONFIG_TOML)) {
16868
+ if (fs25.existsSync(CONFIG_TOML)) {
16572
16869
  try {
16573
- const content = fs24.readFileSync(CONFIG_TOML, "utf-8");
16870
+ const content = fs25.readFileSync(CONFIG_TOML, "utf-8");
16574
16871
  return parseToml(content);
16575
16872
  } catch (err) {
16576
16873
  console.warn(`[Config] Failed to parse ${CONFIG_TOML}:`, err);
16577
16874
  }
16578
16875
  }
16579
- if (fs24.existsSync(CONFIG_JSON)) {
16876
+ if (fs25.existsSync(CONFIG_JSON)) {
16580
16877
  try {
16581
- const content = fs24.readFileSync(CONFIG_JSON, "utf-8");
16878
+ const content = fs25.readFileSync(CONFIG_JSON, "utf-8");
16582
16879
  return JSON.parse(content);
16583
16880
  } catch (err) {
16584
16881
  console.warn(`[Config] Failed to parse ${CONFIG_JSON}:`, err);
@@ -16607,13 +16904,13 @@ function loadEnvConfig() {
16607
16904
  return result;
16608
16905
  }
16609
16906
  function writeConfigField(section, key, value) {
16610
- if (!fs24.existsSync(CONFIG_DIR)) {
16611
- fs24.mkdirSync(CONFIG_DIR, { recursive: true });
16907
+ if (!fs25.existsSync(CONFIG_DIR)) {
16908
+ fs25.mkdirSync(CONFIG_DIR, { recursive: true });
16612
16909
  }
16613
16910
  let existing = {};
16614
- if (fs24.existsSync(CONFIG_TOML)) {
16911
+ if (fs25.existsSync(CONFIG_TOML)) {
16615
16912
  try {
16616
- const content = fs24.readFileSync(CONFIG_TOML, "utf-8");
16913
+ const content = fs25.readFileSync(CONFIG_TOML, "utf-8");
16617
16914
  existing = parseToml(content);
16618
16915
  } catch {
16619
16916
  }
@@ -16635,7 +16932,7 @@ function writeConfigField(section, key, value) {
16635
16932
  }
16636
16933
  lines.push("");
16637
16934
  }
16638
- fs24.writeFileSync(CONFIG_TOML, lines.join("\n"), "utf-8");
16935
+ fs25.writeFileSync(CONFIG_TOML, lines.join("\n"), "utf-8");
16639
16936
  }
16640
16937
  function deepMerge(base, override) {
16641
16938
  const result = { ...base };
@@ -16650,19 +16947,19 @@ function deepMerge(base, override) {
16650
16947
  }
16651
16948
 
16652
16949
  // ../../packages/config/src/auth-profiles.ts
16653
- import * as fs25 from "fs";
16654
- import * as path23 from "path";
16950
+ import * as fs26 from "fs";
16951
+ import * as path24 from "path";
16655
16952
  var AUTH_PROFILES_FILE = "auth-profiles.json";
16656
16953
  function getAuthProfilesPath() {
16657
- return path23.join(getConfigDir(), AUTH_PROFILES_FILE);
16954
+ return path24.join(getConfigDir(), AUTH_PROFILES_FILE);
16658
16955
  }
16659
16956
  function loadAuthProfiles() {
16660
16957
  const filePath = getAuthProfilesPath();
16661
- if (!fs25.existsSync(filePath)) {
16958
+ if (!fs26.existsSync(filePath)) {
16662
16959
  return { version: 1, profiles: {} };
16663
16960
  }
16664
16961
  try {
16665
- const content = fs25.readFileSync(filePath, "utf-8");
16962
+ const content = fs26.readFileSync(filePath, "utf-8");
16666
16963
  const data = JSON.parse(content);
16667
16964
  if (!data.profiles || typeof data.profiles !== "object") {
16668
16965
  return { version: 1, profiles: {} };
@@ -16695,18 +16992,18 @@ function resolveApiKey(provider, authProfile) {
16695
16992
  }
16696
16993
  function writeAuthProfile(name, profile) {
16697
16994
  const configDir = getConfigDir();
16698
- if (!fs25.existsSync(configDir)) {
16699
- fs25.mkdirSync(configDir, { recursive: true });
16995
+ if (!fs26.existsSync(configDir)) {
16996
+ fs26.mkdirSync(configDir, { recursive: true });
16700
16997
  }
16701
16998
  const data = loadAuthProfiles();
16702
16999
  data.profiles[name] = profile;
16703
17000
  const filePath = getAuthProfilesPath();
16704
- fs25.writeFileSync(filePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
17001
+ fs26.writeFileSync(filePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
16705
17002
  }
16706
17003
 
16707
17004
  // ../../packages/config/src/migrations/runner.ts
16708
- import * as fs26 from "fs";
16709
- import * as path24 from "path";
17005
+ import * as fs27 from "fs";
17006
+ import * as path25 from "path";
16710
17007
  var VERSION_FILE = ".migration-version";
16711
17008
  var MigrationRunner = class {
16712
17009
  migrations;
@@ -16716,10 +17013,10 @@ var MigrationRunner = class {
16716
17013
  this.context = context;
16717
17014
  }
16718
17015
  getCurrentVersion() {
16719
- const versionPath = path24.join(this.context.dataDir, VERSION_FILE);
17016
+ const versionPath = path25.join(this.context.dataDir, VERSION_FILE);
16720
17017
  try {
16721
- if (fs26.existsSync(versionPath)) {
16722
- const raw = fs26.readFileSync(versionPath, "utf-8").trim();
17018
+ if (fs27.existsSync(versionPath)) {
17019
+ const raw = fs27.readFileSync(versionPath, "utf-8").trim();
16723
17020
  const ver = parseInt(raw, 10);
16724
17021
  return Number.isFinite(ver) ? ver : 0;
16725
17022
  }
@@ -16728,12 +17025,12 @@ var MigrationRunner = class {
16728
17025
  return 0;
16729
17026
  }
16730
17027
  writeVersion(version) {
16731
- const versionPath = path24.join(this.context.dataDir, VERSION_FILE);
17028
+ const versionPath = path25.join(this.context.dataDir, VERSION_FILE);
16732
17029
  try {
16733
- if (!fs26.existsSync(this.context.dataDir)) {
16734
- fs26.mkdirSync(this.context.dataDir, { recursive: true });
17030
+ if (!fs27.existsSync(this.context.dataDir)) {
17031
+ fs27.mkdirSync(this.context.dataDir, { recursive: true });
16735
17032
  }
16736
- fs26.writeFileSync(versionPath, String(version), "utf-8");
17033
+ fs27.writeFileSync(versionPath, String(version), "utf-8");
16737
17034
  } catch (err) {
16738
17035
  this.context.logger.error("Migration", `Failed to write version file: ${err}`);
16739
17036
  }
@@ -16765,8 +17062,8 @@ var MigrationRunner = class {
16765
17062
  };
16766
17063
 
16767
17064
  // ../../packages/config/src/migrations/m001-legacy-to-multi-config.ts
16768
- import * as fs27 from "fs";
16769
- import * as path25 from "path";
17065
+ import * as fs28 from "fs";
17066
+ import * as path26 from "path";
16770
17067
  import { randomUUID as randomUUID2 } from "crypto";
16771
17068
  function isLegacyFlatConfig(data) {
16772
17069
  if (!data || typeof data !== "object") return false;
@@ -16778,9 +17075,9 @@ var m001LegacyToMultiConfig = {
16778
17075
  name: "legacy-to-multi-config",
16779
17076
  description: "Convert legacy flat LLM config to multi-config format",
16780
17077
  async up(ctx) {
16781
- const configPath = path25.join(ctx.aiDataDir, "llm-config.json");
16782
- if (!fs27.existsSync(configPath)) return;
16783
- const raw = fs27.readFileSync(configPath, "utf-8");
17078
+ const configPath = path26.join(ctx.aiDataDir, "llm-config.json");
17079
+ if (!fs28.existsSync(configPath)) return;
17080
+ const raw = fs28.readFileSync(configPath, "utf-8");
16784
17081
  let data;
16785
17082
  try {
16786
17083
  data = JSON.parse(raw);
@@ -16806,24 +17103,24 @@ var m001LegacyToMultiConfig = {
16806
17103
  defaultAssistant: { configId: newConfig.id, modelId: newConfig.model },
16807
17104
  fastModel: null
16808
17105
  };
16809
- fs27.writeFileSync(configPath, JSON.stringify(migrated, null, 2), "utf-8");
17106
+ fs28.writeFileSync(configPath, JSON.stringify(migrated, null, 2), "utf-8");
16810
17107
  ctx.logger.info("Migration", "Legacy config migrated to multi-config format");
16811
17108
  }
16812
17109
  };
16813
17110
 
16814
17111
  // ../../packages/config/src/migrations/m002-schema-v2.ts
16815
- import * as fs28 from "fs";
16816
- import * as path26 from "path";
17112
+ import * as fs29 from "fs";
17113
+ import * as path27 from "path";
16817
17114
  var m002SchemaV2 = {
16818
17115
  version: 2,
16819
17116
  name: "schema-v2",
16820
17117
  description: "Upgrade LLM config to schema v2 (remove deprecated fields)",
16821
17118
  async up(ctx) {
16822
- const configPath = path26.join(ctx.aiDataDir, "llm-config.json");
16823
- if (!fs28.existsSync(configPath)) return;
17119
+ const configPath = path27.join(ctx.aiDataDir, "llm-config.json");
17120
+ if (!fs29.existsSync(configPath)) return;
16824
17121
  let data;
16825
17122
  try {
16826
- data = JSON.parse(fs28.readFileSync(configPath, "utf-8"));
17123
+ data = JSON.parse(fs29.readFileSync(configPath, "utf-8"));
16827
17124
  } catch {
16828
17125
  return;
16829
17126
  }
@@ -16837,23 +17134,23 @@ var m002SchemaV2 = {
16837
17134
  });
16838
17135
  data.configs = cleanedConfigs;
16839
17136
  data.schemaVersion = 2;
16840
- fs28.writeFileSync(configPath, JSON.stringify(data, null, 2), "utf-8");
17137
+ fs29.writeFileSync(configPath, JSON.stringify(data, null, 2), "utf-8");
16841
17138
  }
16842
17139
  };
16843
17140
 
16844
17141
  // ../../packages/config/src/migrations/m003-schema-v3.ts
16845
- import * as fs29 from "fs";
16846
- import * as path27 from "path";
17142
+ import * as fs30 from "fs";
17143
+ import * as path28 from "path";
16847
17144
  var m003SchemaV3 = {
16848
17145
  version: 3,
16849
17146
  name: "schema-v3-dual-slot",
16850
17147
  description: "Upgrade LLM config to schema v3 (dual-slot model selection)",
16851
17148
  async up(ctx) {
16852
- const configPath = path27.join(ctx.aiDataDir, "llm-config.json");
16853
- if (!fs29.existsSync(configPath)) return;
17149
+ const configPath = path28.join(ctx.aiDataDir, "llm-config.json");
17150
+ if (!fs30.existsSync(configPath)) return;
16854
17151
  let data;
16855
17152
  try {
16856
- data = JSON.parse(fs29.readFileSync(configPath, "utf-8"));
17153
+ data = JSON.parse(fs30.readFileSync(configPath, "utf-8"));
16857
17154
  } catch {
16858
17155
  return;
16859
17156
  }
@@ -16867,18 +17164,18 @@ var m003SchemaV3 = {
16867
17164
  data.fastModel = data.fastModel ?? null;
16868
17165
  data.schemaVersion = 3;
16869
17166
  delete data.activeConfigId;
16870
- fs29.writeFileSync(configPath, JSON.stringify(data, null, 2), "utf-8");
17167
+ fs30.writeFileSync(configPath, JSON.stringify(data, null, 2), "utf-8");
16871
17168
  }
16872
17169
  };
16873
17170
 
16874
17171
  // ../../packages/config/src/migrations/m004-encrypted-keys-to-auth-profiles.ts
16875
- import * as fs31 from "fs";
16876
- import * as path29 from "path";
17172
+ import * as fs32 from "fs";
17173
+ import * as path30 from "path";
16877
17174
 
16878
17175
  // ../../packages/config/src/migrations/crypto-legacy.ts
16879
- import * as fs30 from "fs";
17176
+ import * as fs31 from "fs";
16880
17177
  import * as os3 from "os";
16881
- import * as path28 from "path";
17178
+ import * as path29 from "path";
16882
17179
  import { createDecipheriv, createHash as createHash2 } from "crypto";
16883
17180
  import { execSync } from "child_process";
16884
17181
  var ENCRYPTED_PREFIX = "enc:";
@@ -16890,8 +17187,8 @@ function isEncrypted(value) {
16890
17187
  }
16891
17188
  function readKeyFromFile(keyPath) {
16892
17189
  try {
16893
- if (fs30.existsSync(keyPath)) {
16894
- const key = fs30.readFileSync(keyPath, "utf-8").trim();
17190
+ if (fs31.existsSync(keyPath)) {
17191
+ const key = fs31.readFileSync(keyPath, "utf-8").trim();
16895
17192
  if (key.length >= 32) return key;
16896
17193
  }
16897
17194
  } catch {
@@ -16900,14 +17197,14 @@ function readKeyFromFile(keyPath) {
16900
17197
  }
16901
17198
  function getAllDeviceKeyPaths() {
16902
17199
  const home = os3.homedir();
16903
- const paths = [path28.join(home, ".chatlab", DEVICE_KEY_FILE)];
17200
+ const paths = [path29.join(home, ".chatlab", DEVICE_KEY_FILE)];
16904
17201
  if (process.platform === "darwin") {
16905
- paths.push(path28.join(home, "Library", "Application Support", "ChatLab", "data", DEVICE_KEY_FILE));
17202
+ paths.push(path29.join(home, "Library", "Application Support", "ChatLab", "data", DEVICE_KEY_FILE));
16906
17203
  } else if (process.platform === "win32") {
16907
- const appData = process.env.APPDATA || path28.join(home, "AppData", "Roaming");
16908
- paths.push(path28.join(appData, "ChatLab", "data", DEVICE_KEY_FILE));
17204
+ const appData = process.env.APPDATA || path29.join(home, "AppData", "Roaming");
17205
+ paths.push(path29.join(appData, "ChatLab", "data", DEVICE_KEY_FILE));
16909
17206
  } else {
16910
- paths.push(path28.join(home, ".config", "ChatLab", "data", DEVICE_KEY_FILE));
17207
+ paths.push(path29.join(home, ".config", "ChatLab", "data", DEVICE_KEY_FILE));
16911
17208
  }
16912
17209
  return paths;
16913
17210
  }
@@ -17009,11 +17306,11 @@ var m004EncryptedKeysToAuthProfiles = {
17009
17306
  name: "encrypted-keys-to-auth-profiles",
17010
17307
  description: "Migrate encrypted API keys from llm-config.json to auth-profiles.json",
17011
17308
  async up(ctx) {
17012
- const configPath = path29.join(ctx.aiDataDir, "llm-config.json");
17013
- if (!fs31.existsSync(configPath)) return;
17309
+ const configPath = path30.join(ctx.aiDataDir, "llm-config.json");
17310
+ if (!fs32.existsSync(configPath)) return;
17014
17311
  let data;
17015
17312
  try {
17016
- data = JSON.parse(fs31.readFileSync(configPath, "utf-8"));
17313
+ data = JSON.parse(fs32.readFileSync(configPath, "utf-8"));
17017
17314
  } catch {
17018
17315
  return;
17019
17316
  }
@@ -17050,7 +17347,7 @@ var m004EncryptedKeysToAuthProfiles = {
17050
17347
  }
17051
17348
  }
17052
17349
  if (migrated) {
17053
- fs31.writeFileSync(configPath, JSON.stringify(data, null, 2), "utf-8");
17350
+ fs32.writeFileSync(configPath, JSON.stringify(data, null, 2), "utf-8");
17054
17351
  ctx.logger.info("Migration", "Cleared API keys from llm-config.json");
17055
17352
  }
17056
17353
  }
@@ -17065,29 +17362,29 @@ var ALL_MIGRATIONS = [
17065
17362
  ];
17066
17363
 
17067
17364
  // ../../packages/node-runtime/src/migrations/electron-data-migration.ts
17068
- import * as fs32 from "fs";
17365
+ import * as fs33 from "fs";
17069
17366
  import * as os4 from "os";
17070
- import * as path30 from "path";
17367
+ import * as path31 from "path";
17071
17368
  var SYSTEM_SUBDIRS = ["ai", "settings", "cache", "logs", "temp", "nlp"];
17072
17369
  var STORAGE_CONFIG_FILE = "storage.json";
17073
17370
  function getElectronUserDataDir() {
17074
17371
  const home = os4.homedir();
17075
17372
  switch (process.platform) {
17076
17373
  case "darwin":
17077
- return path30.join(home, "Library", "Application Support", "ChatLab");
17374
+ return path31.join(home, "Library", "Application Support", "ChatLab");
17078
17375
  case "win32": {
17079
- const appData = process.env.APPDATA || path30.join(home, "AppData", "Roaming");
17080
- return path30.join(appData, "ChatLab");
17376
+ const appData = process.env.APPDATA || path31.join(home, "AppData", "Roaming");
17377
+ return path31.join(appData, "ChatLab");
17081
17378
  }
17082
17379
  default:
17083
- return path30.join(home, ".config", "ChatLab");
17380
+ return path31.join(home, ".config", "ChatLab");
17084
17381
  }
17085
17382
  }
17086
17383
  function readElectronStorageConfig(electronUserData) {
17087
- const configPath = path30.join(electronUserData, STORAGE_CONFIG_FILE);
17088
- if (!fs32.existsSync(configPath)) return {};
17384
+ const configPath = path31.join(electronUserData, STORAGE_CONFIG_FILE);
17385
+ if (!fs33.existsSync(configPath)) return {};
17089
17386
  try {
17090
- return JSON.parse(fs32.readFileSync(configPath, "utf-8"));
17387
+ return JSON.parse(fs33.readFileSync(configPath, "utf-8"));
17091
17388
  } catch {
17092
17389
  return {};
17093
17390
  }
@@ -17095,45 +17392,45 @@ function readElectronStorageConfig(electronUserData) {
17095
17392
  function resolveElectronDataDir() {
17096
17393
  const electronUserData = getElectronUserDataDir();
17097
17394
  const storageConfig = readElectronStorageConfig(electronUserData);
17098
- if (storageConfig.dataDir && path30.isAbsolute(storageConfig.dataDir)) {
17395
+ if (storageConfig.dataDir && path31.isAbsolute(storageConfig.dataDir)) {
17099
17396
  return storageConfig.dataDir;
17100
17397
  }
17101
- return path30.join(electronUserData, "data");
17398
+ return path31.join(electronUserData, "data");
17102
17399
  }
17103
17400
  function hasDatabases(dir) {
17104
- const dbDir = path30.join(dir, "databases");
17105
- if (!fs32.existsSync(dbDir)) return false;
17401
+ const dbDir = path31.join(dir, "databases");
17402
+ if (!fs33.existsSync(dbDir)) return false;
17106
17403
  try {
17107
- return fs32.readdirSync(dbDir).some((f) => f.endsWith(".db"));
17404
+ return fs33.readdirSync(dbDir).some((f) => f.endsWith(".db"));
17108
17405
  } catch {
17109
17406
  return false;
17110
17407
  }
17111
17408
  }
17112
17409
  function ensureDir2(dirPath) {
17113
- if (!fs32.existsSync(dirPath)) {
17114
- fs32.mkdirSync(dirPath, { recursive: true });
17410
+ if (!fs33.existsSync(dirPath)) {
17411
+ fs33.mkdirSync(dirPath, { recursive: true });
17115
17412
  }
17116
17413
  }
17117
17414
  function copyDirMerge(src, dest) {
17118
17415
  const stats = { copied: 0, skipped: 0 };
17119
- if (!fs32.existsSync(src)) return stats;
17416
+ if (!fs33.existsSync(src)) return stats;
17120
17417
  ensureDir2(dest);
17121
17418
  let entries;
17122
17419
  try {
17123
- entries = fs32.readdirSync(src, { withFileTypes: true });
17420
+ entries = fs33.readdirSync(src, { withFileTypes: true });
17124
17421
  } catch {
17125
17422
  return stats;
17126
17423
  }
17127
17424
  for (const entry of entries) {
17128
- const srcPath = path30.join(src, entry.name);
17129
- const destPath = path30.join(dest, entry.name);
17425
+ const srcPath = path31.join(src, entry.name);
17426
+ const destPath = path31.join(dest, entry.name);
17130
17427
  try {
17131
17428
  if (entry.isDirectory()) {
17132
17429
  const sub = copyDirMerge(srcPath, destPath);
17133
17430
  stats.copied += sub.copied;
17134
17431
  stats.skipped += sub.skipped;
17135
- } else if (!fs32.existsSync(destPath)) {
17136
- fs32.copyFileSync(srcPath, destPath);
17432
+ } else if (!fs33.existsSync(destPath)) {
17433
+ fs33.copyFileSync(srcPath, destPath);
17137
17434
  stats.copied++;
17138
17435
  } else {
17139
17436
  stats.skipped++;
@@ -17146,22 +17443,22 @@ function copyDirMerge(src, dest) {
17146
17443
  function writeMigrationLog(logDir, message) {
17147
17444
  try {
17148
17445
  ensureDir2(logDir);
17149
- const logPath = path30.join(logDir, "app.log");
17446
+ const logPath = path31.join(logDir, "app.log");
17150
17447
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
17151
- fs32.appendFileSync(logPath, `[${ts}] [MIGRATION] ${message}
17448
+ fs33.appendFileSync(logPath, `[${ts}] [MIGRATION] ${message}
17152
17449
  `, "utf-8");
17153
17450
  } catch {
17154
17451
  }
17155
17452
  }
17156
17453
  function wasElectronUsed() {
17157
17454
  const electronUserData = getElectronUserDataDir();
17158
- if (!fs32.existsSync(electronUserData)) return false;
17159
- return fs32.existsSync(path30.join(electronUserData, "Preferences")) || fs32.existsSync(path30.join(electronUserData, "Local Storage")) || fs32.existsSync(path30.join(electronUserData, "Session Storage")) || fs32.existsSync(path30.join(electronUserData, "data"));
17455
+ if (!fs33.existsSync(electronUserData)) return false;
17456
+ return fs33.existsSync(path31.join(electronUserData, "Preferences")) || fs33.existsSync(path31.join(electronUserData, "Local Storage")) || fs33.existsSync(path31.join(electronUserData, "Session Storage")) || fs33.existsSync(path31.join(electronUserData, "data"));
17160
17457
  }
17161
17458
  function verifyCliDataPath(databaseDir) {
17162
- if (fs32.existsSync(databaseDir)) {
17459
+ if (fs33.existsSync(databaseDir)) {
17163
17460
  try {
17164
- if (fs32.readdirSync(databaseDir).some((f) => f.endsWith(".db"))) return true;
17461
+ if (fs33.readdirSync(databaseDir).some((f) => f.endsWith(".db"))) return true;
17165
17462
  } catch {
17166
17463
  }
17167
17464
  }
@@ -17179,9 +17476,9 @@ function migrateFromElectronIfNeeded(systemDir) {
17179
17476
  let totalSkipped = 0;
17180
17477
  const movedDirs = [];
17181
17478
  for (const subDir of SYSTEM_SUBDIRS) {
17182
- const srcDir = path30.join(electronDataDir, subDir);
17183
- const destDir = path30.join(systemDir, subDir);
17184
- if (!fs32.existsSync(srcDir)) continue;
17479
+ const srcDir = path31.join(electronDataDir, subDir);
17480
+ const destDir = path31.join(systemDir, subDir);
17481
+ if (!fs33.existsSync(srcDir)) continue;
17185
17482
  const { copied, skipped } = copyDirMerge(srcDir, destDir);
17186
17483
  if (copied > 0 || skipped > 0) {
17187
17484
  movedDirs.push(subDir);
@@ -17191,13 +17488,13 @@ function migrateFromElectronIfNeeded(systemDir) {
17191
17488
  }
17192
17489
  }
17193
17490
  for (const subDir of movedDirs) {
17194
- const srcDir = path30.join(electronDataDir, subDir);
17491
+ const srcDir = path31.join(electronDataDir, subDir);
17195
17492
  try {
17196
- fs32.rmSync(srcDir, { recursive: true, force: true });
17493
+ fs33.rmSync(srcDir, { recursive: true, force: true });
17197
17494
  } catch {
17198
17495
  }
17199
17496
  }
17200
- const logsDir = path30.join(systemDir, "logs");
17497
+ const logsDir = path31.join(systemDir, "logs");
17201
17498
  const summary = `CLI first-run: detected Electron data at ${electronDataDir}, pointed user_data_dir there, copied ${totalCopied} system files (${movedDirs.join(", ") || "none"})`;
17202
17499
  writeMigrationLog(logsDir, summary);
17203
17500
  console.log(`[Migration] ${summary}`);
@@ -17211,7 +17508,7 @@ function migrateFromElectronIfNeeded(systemDir) {
17211
17508
  const errorMsg = error instanceof Error ? error.message : String(error);
17212
17509
  console.error("[Migration] Electron data migration failed:", errorMsg);
17213
17510
  try {
17214
- writeMigrationLog(path30.join(systemDir, "logs"), `Electron migration failed: ${errorMsg}`);
17511
+ writeMigrationLog(path31.join(systemDir, "logs"), `Electron migration failed: ${errorMsg}`);
17215
17512
  } catch {
17216
17513
  }
17217
17514
  return { migrated: false, electronDetected: true, error: errorMsg };
@@ -17219,7 +17516,7 @@ function migrateFromElectronIfNeeded(systemDir) {
17219
17516
  }
17220
17517
 
17221
17518
  // ../../packages/node-runtime/src/node-path-provider.ts
17222
- var SYSTEM_DIR = path31.join(os5.homedir(), ".chatlab");
17519
+ var SYSTEM_DIR = path32.join(os5.homedir(), ".chatlab");
17223
17520
  var _pendingElectronDataWarning = false;
17224
17521
  function hasPendingElectronDataWarning() {
17225
17522
  return _pendingElectronDataWarning;
@@ -17238,25 +17535,25 @@ var NodePathProvider = class {
17238
17535
  return this.userDataDir;
17239
17536
  }
17240
17537
  getDatabaseDir() {
17241
- return path31.join(this.userDataDir, "databases");
17538
+ return path32.join(this.userDataDir, "databases");
17242
17539
  }
17243
17540
  getAiDataDir() {
17244
- return path31.join(this.systemDir, "ai");
17541
+ return path32.join(this.systemDir, "ai");
17245
17542
  }
17246
17543
  getSettingsDir() {
17247
- return path31.join(this.systemDir, "settings");
17544
+ return path32.join(this.systemDir, "settings");
17248
17545
  }
17249
17546
  getCacheDir() {
17250
- return path31.join(this.systemDir, "cache");
17547
+ return path32.join(this.systemDir, "cache");
17251
17548
  }
17252
17549
  getTempDir() {
17253
- return path31.join(this.systemDir, "temp");
17550
+ return path32.join(this.systemDir, "temp");
17254
17551
  }
17255
17552
  getLogsDir() {
17256
- return path31.join(this.systemDir, "logs");
17553
+ return path32.join(this.systemDir, "logs");
17257
17554
  }
17258
17555
  getDownloadsDir() {
17259
- return path31.join(os5.homedir(), "Downloads");
17556
+ return path32.join(os5.homedir(), "Downloads");
17260
17557
  }
17261
17558
  /**
17262
17559
  * 确保系统目录和用户数据目录都存在
@@ -17273,8 +17570,8 @@ var NodePathProvider = class {
17273
17570
  this.getLogsDir()
17274
17571
  ];
17275
17572
  for (const dir of dirs) {
17276
- if (!fs33.existsSync(dir)) {
17277
- fs33.mkdirSync(dir, { recursive: true });
17573
+ if (!fs34.existsSync(dir)) {
17574
+ fs34.mkdirSync(dir, { recursive: true });
17278
17575
  }
17279
17576
  }
17280
17577
  }
@@ -17301,18 +17598,18 @@ function resolveUserDataDir() {
17301
17598
  return defaultDir;
17302
17599
  }
17303
17600
  function getDefaultUserDataDir() {
17304
- return path31.join(os5.homedir(), ".chatlab", "data");
17601
+ return path32.join(os5.homedir(), ".chatlab", "data");
17305
17602
  }
17306
17603
  function expandHome(filePath) {
17307
17604
  if (filePath.startsWith("~/") || filePath === "~") {
17308
- return path31.join(os5.homedir(), filePath.slice(1));
17605
+ return path32.join(os5.homedir(), filePath.slice(1));
17309
17606
  }
17310
17607
  return filePath;
17311
17608
  }
17312
17609
 
17313
17610
  // ../../packages/node-runtime/src/database-manager.ts
17314
- import * as fs34 from "fs";
17315
- import * as path32 from "path";
17611
+ import * as fs35 from "fs";
17612
+ import * as path33 from "path";
17316
17613
 
17317
17614
  // ../../packages/node-runtime/src/migrations/chat-db-migrations.ts
17318
17615
  function getChatDbMigrations(deps) {
@@ -17442,7 +17739,7 @@ var DatabaseManager = class {
17442
17739
  return this.cache.get(sessionId);
17443
17740
  }
17444
17741
  const dbPath = this.getDbPath(sessionId);
17445
- if (!fs34.existsSync(dbPath)) return null;
17742
+ if (!fs35.existsSync(dbPath)) return null;
17446
17743
  const adapter = openBetterSqliteDatabase(dbPath, {
17447
17744
  readonly: options?.readonly ?? true,
17448
17745
  nativeBinding: this.nativeBinding
@@ -17462,7 +17759,7 @@ var DatabaseManager = class {
17462
17759
  this.cache.delete(sessionId);
17463
17760
  }
17464
17761
  const dbPath = this.getDbPath(sessionId);
17465
- if (!fs34.existsSync(dbPath)) return null;
17762
+ if (!fs35.existsSync(dbPath)) return null;
17466
17763
  const adapter = openBetterSqliteDatabase(dbPath, {
17467
17764
  readonly: false,
17468
17765
  nativeBinding: this.nativeBinding
@@ -17498,8 +17795,8 @@ var DatabaseManager = class {
17498
17795
  */
17499
17796
  listSessionIds() {
17500
17797
  const dbDir = this.pathProvider.getDatabaseDir();
17501
- if (!fs34.existsSync(dbDir)) return [];
17502
- return fs34.readdirSync(dbDir).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", "")).filter((id) => {
17798
+ if (!fs35.existsSync(dbDir)) return [];
17799
+ return fs35.readdirSync(dbDir).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", "")).filter((id) => {
17503
17800
  const db = this.open(id);
17504
17801
  if (!db) return false;
17505
17802
  return isChatSessionDb(db);
@@ -17509,7 +17806,7 @@ var DatabaseManager = class {
17509
17806
  * 获取数据库文件路径
17510
17807
  */
17511
17808
  getDbPath(sessionId) {
17512
- return path32.join(this.pathProvider.getDatabaseDir(), `${sessionId}.db`);
17809
+ return path33.join(this.pathProvider.getDatabaseDir(), `${sessionId}.db`);
17513
17810
  }
17514
17811
  };
17515
17812
 
@@ -17787,26 +18084,26 @@ function exportSessionMode(db, params, writer, progress) {
17787
18084
  }
17788
18085
 
17789
18086
  // ../../packages/node-runtime/src/cache/session-cache.ts
17790
- import * as fs35 from "fs";
17791
- import * as path33 from "path";
18087
+ import * as fs36 from "fs";
18088
+ import * as path34 from "path";
17792
18089
  function getCachePath(sessionId, cacheDir) {
17793
- return path33.join(cacheDir, `${sessionId}.cache.json`);
18090
+ return path34.join(cacheDir, `${sessionId}.cache.json`);
17794
18091
  }
17795
18092
  function readCacheFile(cachePath) {
17796
18093
  try {
17797
- if (!fs35.existsSync(cachePath)) return null;
17798
- return JSON.parse(fs35.readFileSync(cachePath, "utf-8"));
18094
+ if (!fs36.existsSync(cachePath)) return null;
18095
+ return JSON.parse(fs36.readFileSync(cachePath, "utf-8"));
17799
18096
  } catch {
17800
18097
  return null;
17801
18098
  }
17802
18099
  }
17803
18100
  function writeCacheFile(cachePath, content) {
17804
18101
  try {
17805
- const dir = path33.dirname(cachePath);
17806
- if (!fs35.existsSync(dir)) {
17807
- fs35.mkdirSync(dir, { recursive: true });
18102
+ const dir = path34.dirname(cachePath);
18103
+ if (!fs36.existsSync(dir)) {
18104
+ fs36.mkdirSync(dir, { recursive: true });
17808
18105
  }
17809
- fs35.writeFileSync(cachePath, JSON.stringify(content), "utf-8");
18106
+ fs36.writeFileSync(cachePath, JSON.stringify(content), "utf-8");
17810
18107
  } catch {
17811
18108
  }
17812
18109
  }
@@ -17826,7 +18123,7 @@ function invalidateCache(sessionId, cacheDir, key) {
17826
18123
  const cachePath = getCachePath(sessionId, cacheDir);
17827
18124
  try {
17828
18125
  if (!key) {
17829
- if (fs35.existsSync(cachePath)) fs35.unlinkSync(cachePath);
18126
+ if (fs36.existsSync(cachePath)) fs36.unlinkSync(cachePath);
17830
18127
  } else {
17831
18128
  const file = readCacheFile(cachePath);
17832
18129
  if (file && file[key]) {
@@ -17840,7 +18137,7 @@ function invalidateCache(sessionId, cacheDir, key) {
17840
18137
  function deleteSessionCache(sessionId, cacheDir) {
17841
18138
  const cachePath = getCachePath(sessionId, cacheDir);
17842
18139
  try {
17843
- if (fs35.existsSync(cachePath)) fs35.unlinkSync(cachePath);
18140
+ if (fs36.existsSync(cachePath)) fs36.unlinkSync(cachePath);
17844
18141
  } catch {
17845
18142
  }
17846
18143
  }
@@ -17882,8 +18179,8 @@ function computeAndSetMembersCache(db, sessionId, cacheDir) {
17882
18179
  }
17883
18180
 
17884
18181
  // ../../packages/node-runtime/src/preferences.ts
17885
- import * as fs36 from "fs";
17886
- import * as path34 from "path";
18182
+ import * as fs37 from "fs";
18183
+ import * as path35 from "path";
17887
18184
  var DEFAULTS = {
17888
18185
  pinnedSessionIds: [],
17889
18186
  aiPreprocessConfig: {
@@ -17923,13 +18220,13 @@ var PreferencesManager = class {
17923
18220
  filePath;
17924
18221
  cache = null;
17925
18222
  constructor(systemDir) {
17926
- this.filePath = path34.join(systemDir, "preferences.json");
18223
+ this.filePath = path35.join(systemDir, "preferences.json");
17927
18224
  }
17928
18225
  load() {
17929
18226
  if (this.cache) return this.cache;
17930
18227
  try {
17931
- if (fs36.existsSync(this.filePath)) {
17932
- const raw = fs36.readFileSync(this.filePath, "utf-8");
18228
+ if (fs37.existsSync(this.filePath)) {
18229
+ const raw = fs37.readFileSync(this.filePath, "utf-8");
17933
18230
  const parsed = JSON.parse(raw);
17934
18231
  this.cache = this.mergeDefaults(parsed);
17935
18232
  return this.cache;
@@ -17948,11 +18245,11 @@ var PreferencesManager = class {
17948
18245
  partial
17949
18246
  );
17950
18247
  this.cache = merged;
17951
- const dir = path34.dirname(this.filePath);
17952
- if (!fs36.existsSync(dir)) {
17953
- fs36.mkdirSync(dir, { recursive: true });
18248
+ const dir = path35.dirname(this.filePath);
18249
+ if (!fs37.existsSync(dir)) {
18250
+ fs37.mkdirSync(dir, { recursive: true });
17954
18251
  }
17955
- fs36.writeFileSync(this.filePath, JSON.stringify(this.cache, null, 2), "utf-8");
18252
+ fs37.writeFileSync(this.filePath, JSON.stringify(this.cache, null, 2), "utf-8");
17956
18253
  return { success: true };
17957
18254
  } catch (err) {
17958
18255
  const msg = err instanceof Error ? err.message : String(err);
@@ -18102,8 +18399,8 @@ function* serializeChatLabToJsonl(data) {
18102
18399
  }
18103
18400
 
18104
18401
  // ../../packages/node-runtime/src/merger/temp-db.ts
18105
- import * as fs37 from "fs";
18106
- import * as path35 from "path";
18402
+ import * as fs38 from "fs";
18403
+ import * as path36 from "path";
18107
18404
  var TEMP_DB_SCHEMA = `
18108
18405
  CREATE TABLE IF NOT EXISTS meta (
18109
18406
  name TEXT NOT NULL,
@@ -18348,27 +18645,272 @@ function exportSessionToJson(db) {
18348
18645
  }
18349
18646
  function deleteTempDatabase(dbPath) {
18350
18647
  try {
18351
- if (fs37.existsSync(dbPath)) fs37.unlinkSync(dbPath);
18648
+ if (fs38.existsSync(dbPath)) fs38.unlinkSync(dbPath);
18352
18649
  const walPath = dbPath + "-wal";
18353
18650
  const shmPath = dbPath + "-shm";
18354
- if (fs37.existsSync(walPath)) fs37.unlinkSync(walPath);
18355
- if (fs37.existsSync(shmPath)) fs37.unlinkSync(shmPath);
18651
+ if (fs38.existsSync(walPath)) fs38.unlinkSync(walPath);
18652
+ if (fs38.existsSync(shmPath)) fs38.unlinkSync(shmPath);
18356
18653
  } catch {
18357
18654
  }
18358
18655
  }
18359
18656
  function cleanupTempDatabases(tempDir) {
18360
18657
  try {
18361
- if (!fs37.existsSync(tempDir)) return;
18362
- const files = fs37.readdirSync(tempDir);
18658
+ if (!fs38.existsSync(tempDir)) return;
18659
+ const files = fs38.readdirSync(tempDir);
18363
18660
  for (const file of files) {
18364
18661
  if (file.startsWith("merge_") && file.endsWith(".db")) {
18365
- deleteTempDatabase(path35.join(tempDir, file));
18662
+ deleteTempDatabase(path36.join(tempDir, file));
18366
18663
  }
18367
18664
  }
18368
18665
  } catch {
18369
18666
  }
18370
18667
  }
18371
18668
 
18669
+ // ../../packages/node-runtime/src/services/session-service.ts
18670
+ var session_service_exports = {};
18671
+ __export(session_service_exports, {
18672
+ deleteSession: () => deleteSession,
18673
+ getAnalysisSession: () => getAnalysisSession,
18674
+ listAnalysisSessions: () => listAnalysisSessions,
18675
+ renameSession: () => renameSession2,
18676
+ updateSessionOwnerId: () => updateSessionOwnerId2
18677
+ });
18678
+ function buildSession(db, id, dbPath, options) {
18679
+ const meta = getSessionMeta(db);
18680
+ if (!meta) return null;
18681
+ const overview = options?.resolveOverview ? options.resolveOverview(db, id) : void 0;
18682
+ const info = overview ? buildSessionInfo(meta, overview, getSummaryCount(db)) : getSessionInfo(db);
18683
+ if (!info) return null;
18684
+ let memberAvatar = null;
18685
+ if (meta.type === "private") {
18686
+ memberAvatar = getPrivateChatMemberAvatar(db, meta.name, meta.ownerId);
18687
+ }
18688
+ let dto = { ...info, id, dbPath, memberAvatar, aiConversationCount: 0 };
18689
+ if (options?.enrichSession) {
18690
+ dto = options.enrichSession(dto);
18691
+ }
18692
+ return dto;
18693
+ }
18694
+ function listAnalysisSessions(adapter, options) {
18695
+ const sessionIds = adapter.listSessionIds();
18696
+ const sessions = [];
18697
+ for (const id of sessionIds) {
18698
+ const db = adapter.openReadonly(id);
18699
+ if (!db) continue;
18700
+ if (!isChatSessionDb(db)) continue;
18701
+ const dto = buildSession(db, id, adapter.getDbPath(id), options);
18702
+ if (dto) sessions.push(dto);
18703
+ }
18704
+ return sessions.sort((a, b) => b.importedAt - a.importedAt);
18705
+ }
18706
+ function getAnalysisSession(adapter, sessionId, options) {
18707
+ const db = adapter.openReadonly(sessionId);
18708
+ if (!db) return null;
18709
+ return buildSession(db, sessionId, adapter.getDbPath(sessionId), options);
18710
+ }
18711
+ function renameSession2(adapter, sessionId, name) {
18712
+ const db = adapter.ensureWritable(sessionId);
18713
+ renameSession(db, name);
18714
+ }
18715
+ function updateSessionOwnerId2(adapter, sessionId, ownerId) {
18716
+ const db = adapter.ensureWritable(sessionId);
18717
+ updateSessionOwnerId(db, ownerId);
18718
+ }
18719
+ function deleteSession(adapter, sessionId) {
18720
+ return adapter.deleteSessionFile(sessionId);
18721
+ }
18722
+
18723
+ // ../../packages/node-runtime/src/services/member-service.ts
18724
+ var member_service_exports = {};
18725
+ __export(member_service_exports, {
18726
+ deleteMember: () => deleteMember2,
18727
+ getMemberNameHistory: () => getMemberNameHistory2,
18728
+ getMembers: () => getMembers2,
18729
+ getMembersPaginated: () => getMembersPaginated2,
18730
+ mergeMembers: () => mergeMembers3,
18731
+ updateMemberAliases: () => updateMemberAliases2
18732
+ });
18733
+ function getMembers2(adapter, sessionId) {
18734
+ const db = adapter.ensureReadonly(sessionId);
18735
+ return getMembersWithAliases(db);
18736
+ }
18737
+ function getMembersPaginated2(adapter, sessionId, params) {
18738
+ const db = adapter.ensureReadonly(sessionId);
18739
+ const result = getMembersPaginated(db, params);
18740
+ return {
18741
+ items: result.members,
18742
+ total: result.total,
18743
+ page: result.page,
18744
+ pageSize: result.pageSize,
18745
+ totalPages: result.totalPages
18746
+ };
18747
+ }
18748
+ function updateMemberAliases2(adapter, sessionId, memberId, aliases) {
18749
+ const db = adapter.ensureWritable(sessionId);
18750
+ return updateMemberAliases(db, memberId, aliases);
18751
+ }
18752
+ function mergeMembers3(adapter, sessionId, memberId1, memberId2) {
18753
+ const db = adapter.ensureWritable(sessionId);
18754
+ return mergeMembers(db, memberId1, memberId2);
18755
+ }
18756
+ function deleteMember2(adapter, sessionId, memberId) {
18757
+ const db = adapter.ensureWritable(sessionId);
18758
+ return deleteMember(db, memberId);
18759
+ }
18760
+ function getMemberNameHistory2(adapter, sessionId, memberId) {
18761
+ const db = adapter.ensureReadonly(sessionId);
18762
+ return getMemberNameHistory(db, memberId);
18763
+ }
18764
+
18765
+ // ../../packages/node-runtime/src/services/session-index-service.ts
18766
+ var session_index_service_exports = {};
18767
+ __export(session_index_service_exports, {
18768
+ clearIndex: () => clearIndex,
18769
+ generateIndex: () => generateIndex,
18770
+ getFtsStatus: () => getFtsStatus,
18771
+ rebuildFts: () => rebuildFts,
18772
+ searchFts: () => searchFts
18773
+ });
18774
+ function generateIndex(adapter, sessionId, gapThreshold = 1800) {
18775
+ const db = adapter.ensureWritable(sessionId);
18776
+ return generateSessionIndex(db, gapThreshold);
18777
+ }
18778
+ function clearIndex(adapter, sessionId) {
18779
+ const db = adapter.ensureWritable(sessionId);
18780
+ clearSessionIndex(db);
18781
+ }
18782
+ function getFtsStatus(adapter, sessionId) {
18783
+ const db = adapter.ensureReadonly(sessionId);
18784
+ return hasFtsTable(db);
18785
+ }
18786
+ function searchFts(adapter, sessionId, keywords, limit, offset) {
18787
+ const db = adapter.ensureReadonly(sessionId);
18788
+ return searchByFts(db, keywords, limit, offset);
18789
+ }
18790
+ function rebuildFts(adapter, sessionId) {
18791
+ const db = adapter.ensureWritable(sessionId);
18792
+ return rebuildFtsIndex(db);
18793
+ }
18794
+
18795
+ // ../../packages/node-runtime/src/services/summary-service.ts
18796
+ var summary_service_exports = {};
18797
+ __export(summary_service_exports, {
18798
+ generateAllSummaries: () => generateAllSummaries,
18799
+ generateSummary: () => generateSummary
18800
+ });
18801
+ function buildSummaryDeps(db, llmConfig, deps) {
18802
+ const piModel = deps.buildPiModel(llmConfig);
18803
+ return {
18804
+ loadMessages(chatSessionId, limit = 500) {
18805
+ const data = getSessionMessages(db, chatSessionId, limit);
18806
+ if (!data) return null;
18807
+ return data.messages.map((m) => ({ senderName: m.senderName, content: m.content }));
18808
+ },
18809
+ saveSummary(chatSessionId, summary) {
18810
+ saveChatSessionSummary(db, chatSessionId, summary);
18811
+ },
18812
+ getSummary(chatSessionId) {
18813
+ return getChatSessionSummary(db, chatSessionId);
18814
+ },
18815
+ async llmComplete(systemPrompt, userPrompt, options) {
18816
+ const result = await completeSimple4(
18817
+ piModel,
18818
+ {
18819
+ systemPrompt,
18820
+ messages: [{ role: "user", content: [{ type: "text", text: userPrompt }], timestamp: Date.now() }]
18821
+ },
18822
+ { apiKey: llmConfig.apiKey, maxTokens: options?.maxTokens, temperature: options?.temperature }
18823
+ );
18824
+ return result.content.filter((item) => item.type === "text").map((item) => item.text).join("");
18825
+ },
18826
+ t: (key) => key
18827
+ };
18828
+ }
18829
+ async function generateSummary(adapter, sessionId, chatSessionId, serviceDeps, options) {
18830
+ const llmConfig = serviceDeps.getLlmConfig();
18831
+ if (!llmConfig) {
18832
+ return { success: false, error: "No LLM configuration available" };
18833
+ }
18834
+ const db = adapter.ensureWritable(sessionId);
18835
+ const deps = buildSummaryDeps(db, llmConfig, serviceDeps);
18836
+ return generateSessionSummary(deps, chatSessionId, options);
18837
+ }
18838
+ async function generateAllSummaries(adapter, sessionId, serviceDeps, options) {
18839
+ const llmConfig = serviceDeps.getLlmConfig();
18840
+ if (!llmConfig) {
18841
+ return { success: 0, failed: 0, total: 0, error: "No LLM configuration available" };
18842
+ }
18843
+ const db = adapter.ensureWritable(sessionId);
18844
+ const chatSessions = getChatSessionList(db);
18845
+ const deps = buildSummaryDeps(db, llmConfig, serviceDeps);
18846
+ let success = 0;
18847
+ let failed = 0;
18848
+ for (const cs of chatSessions) {
18849
+ const result = await generateSessionSummary(deps, cs.id, options);
18850
+ if (result.success) success++;
18851
+ else failed++;
18852
+ }
18853
+ return { success, failed, total: chatSessions.length };
18854
+ }
18855
+
18856
+ // ../../packages/node-runtime/src/services/export-service.ts
18857
+ var export_service_exports = {};
18858
+ __export(export_service_exports, {
18859
+ exportMarkdown: () => exportMarkdown
18860
+ });
18861
+ function exportMarkdown(adapter, params) {
18862
+ const chunks = [];
18863
+ const result = exportFilterResultToMarkdown(
18864
+ params,
18865
+ {
18866
+ openDatabase(sessionId) {
18867
+ return adapter.openReadonly(sessionId);
18868
+ }
18869
+ },
18870
+ {
18871
+ write(chunk) {
18872
+ chunks.push(chunk);
18873
+ },
18874
+ end() {
18875
+ }
18876
+ }
18877
+ );
18878
+ return { result, content: chunks.join("") };
18879
+ }
18880
+
18881
+ // ../../packages/node-runtime/src/services/adapters/database-manager-adapter.ts
18882
+ import * as fs39 from "fs";
18883
+ function createDatabaseManagerAdapter(dbManager) {
18884
+ return {
18885
+ listSessionIds: () => dbManager.listSessionIds(),
18886
+ openReadonly: (sessionId) => dbManager.open(sessionId),
18887
+ openWritable: (sessionId) => dbManager.openWritable(sessionId),
18888
+ closeSession: (sessionId) => dbManager.close(sessionId),
18889
+ getDbPath: (sessionId) => dbManager.getDbPath(sessionId),
18890
+ deleteSessionFile(sessionId) {
18891
+ dbManager.close(sessionId);
18892
+ const dbPath = dbManager.getDbPath(sessionId);
18893
+ if (!fs39.existsSync(dbPath)) return false;
18894
+ fs39.unlinkSync(dbPath);
18895
+ return true;
18896
+ },
18897
+ ensureReadonly(sessionId) {
18898
+ const db = dbManager.open(sessionId);
18899
+ if (!db) {
18900
+ throw Object.assign(new Error(`Session not found: ${sessionId}`), { statusCode: 404 });
18901
+ }
18902
+ return db;
18903
+ },
18904
+ ensureWritable(sessionId) {
18905
+ const db = dbManager.openWritable(sessionId);
18906
+ if (!db) {
18907
+ throw Object.assign(new Error(`Session not found: ${sessionId}`), { statusCode: 404 });
18908
+ }
18909
+ return db;
18910
+ }
18911
+ };
18912
+ }
18913
+
18372
18914
  export {
18373
18915
  DEFAULT_API_PORT,
18374
18916
  loadConfig,
@@ -18409,10 +18951,6 @@ export {
18409
18951
  searchSessions,
18410
18952
  getSessionMessages,
18411
18953
  getSessionSummaries,
18412
- getChatSessionList,
18413
- getChatSessionSummary,
18414
- saveChatSessionSummary,
18415
- clearSessionIndex,
18416
18954
  generateSessionIndex,
18417
18955
  generateIncrementalSessionIndex,
18418
18956
  queryMessages,
@@ -18428,7 +18966,6 @@ export {
18428
18966
  getConversationBetween,
18429
18967
  getMemberNameHistory,
18430
18968
  getMembersWithAliases,
18431
- getMembersPaginated,
18432
18969
  executeParameterizedSql,
18433
18970
  getCatchphraseAnalysis,
18434
18971
  getMentionAnalysis,
@@ -18452,6 +18989,7 @@ export {
18452
18989
  getSupportedFormats,
18453
18990
  getFormatFeatureById,
18454
18991
  scanMultiChatFile,
18992
+ findEntryFileInDirectory,
18455
18993
  initNlpDir,
18456
18994
  getNlpDir,
18457
18995
  getJieba,
@@ -18596,6 +19134,12 @@ export {
18596
19134
  TempDbReader,
18597
19135
  exportSessionToJson,
18598
19136
  deleteTempDatabase,
18599
- cleanupTempDatabases
19137
+ cleanupTempDatabases,
19138
+ session_service_exports,
19139
+ member_service_exports,
19140
+ session_index_service_exports,
19141
+ summary_service_exports,
19142
+ export_service_exports,
19143
+ createDatabaseManagerAdapter
18600
19144
  };
18601
- //# sourceMappingURL=chunk-JMRDNHIR.mjs.map
19145
+ //# sourceMappingURL=chunk-EIRLEPXP.mjs.map