chatlab-cli 0.37.2 → 0.37.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/LICENSE +661 -0
  2. package/dist/{chat-command-G2EX7VHR.mjs → chat-command-DJKSQP6Y.mjs} +37 -9
  3. package/dist/chat-command-DJKSQP6Y.mjs.map +1 -0
  4. package/dist/{chunk-F4HVCFZL.mjs → chunk-3K7F2SRZ.mjs} +3 -3
  5. package/dist/{chunk-FCUUAGGC.mjs → chunk-ARRFRJOH.mjs} +2 -2
  6. package/dist/{chunk-H46CLFWK.mjs → chunk-D6BRSG3V.mjs} +4 -4
  7. package/dist/{chunk-YI3EQYEG.mjs → chunk-DJ7QEJNO.mjs} +12 -12
  8. package/dist/{chunk-XQ6Z2KNN.mjs → chunk-JWWWLW5G.mjs} +2 -2
  9. package/dist/{chunk-HBAQPF6X.mjs → chunk-NKSPJN6X.mjs} +210 -60
  10. package/dist/chunk-NKSPJN6X.mjs.map +1 -0
  11. package/dist/{chunk-HMVM7VCA.mjs → chunk-NVW3ZCYD.mjs} +3 -3
  12. package/dist/{chunk-T5H56AZV.mjs → chunk-OXRS2UPE.mjs} +13 -11
  13. package/dist/chunk-OXRS2UPE.mjs.map +1 -0
  14. package/dist/{chunk-EFX66A2O.mjs → chunk-QP77JL6O.mjs} +2 -2
  15. package/dist/{chunk-EK5QIJLZ.mjs → chunk-VCKF7RYB.mjs} +11 -11
  16. package/dist/{chunk-L6RJIVLS.mjs → chunk-WBPOMYBE.mjs} +315 -24
  17. package/dist/chunk-WBPOMYBE.mjs.map +1 -0
  18. package/dist/{chunk-E6LCCPIB.mjs → chunk-YPP3N2AX.mjs} +2 -2
  19. package/dist/cli.mjs +9 -9
  20. package/dist/contacts-worker.mjs +2 -2
  21. package/dist/global-insight-worker.mjs +1 -1
  22. package/dist/{http-5BRVWAJR.mjs → http-O4AZUIOD.mjs} +12 -12
  23. package/dist/{import-IAECQDKC.mjs → import-IALJQB7V.mjs} +7 -7
  24. package/dist/index.mjs +12 -12
  25. package/dist/{mcp-XXSQJBGU.mjs → mcp-VNBL4WMM.mjs} +24 -17
  26. package/dist/mcp-VNBL4WMM.mjs.map +1 -0
  27. package/dist/people-relationships-worker.mjs +2 -2
  28. package/dist/semantic-index-worker.mjs +1 -1
  29. package/dist/{src-4HLKMQ7S.mjs → src-6ICLBMOR.mjs} +6 -6
  30. package/dist/{stream-import-PUG42I36.mjs → stream-import-NKQYYSGZ.mjs} +7 -7
  31. package/dist/{worker-runtime-X5563TVT.mjs → worker-runtime-AE2I6U2G.mjs} +5 -5
  32. package/dist-cli-web/assets/{AISettingsTab-m_r2fFEj.js → AISettingsTab-mecu-HsX.js} +1 -1
  33. package/dist-cli-web/assets/{AboutTab-J65UqIuk.js → AboutTab-CgXYD50w.js} +1 -1
  34. package/dist-cli-web/assets/{Alert-qBIGn_CW.js → Alert-DR892gaV.js} +1 -1
  35. package/dist-cli-web/assets/{ApiSettingsTab-CxWRJI9j.js → ApiSettingsTab-Cvw8gStg.js} +1 -1
  36. package/dist-cli-web/assets/{BatchManageTab-BINNVwm1.js → BatchManageTab-DqSEzAtr.js} +1 -1
  37. package/dist-cli-web/assets/{BufferResource-C-jLPrHv.js → BufferResource-rydt5j-b.js} +1 -1
  38. package/dist-cli-web/assets/{CanvasRenderer-kDLW8GSt.js → CanvasRenderer-Ci5IaFxW.js} +1 -1
  39. package/dist-cli-web/assets/{CardDecoration-CnYxleQM.js → CardDecoration-8F4sZO4v.js} +1 -1
  40. package/dist-cli-web/assets/{ChatRecordDrawer-CMg3FEWH.js → ChatRecordDrawer-D3LzSRkL.js} +1 -1
  41. package/dist-cli-web/assets/{ChatRecordWorkspace-AfFIMUbZ.js → ChatRecordWorkspace-BDCIAjm3.js} +1 -1
  42. package/dist-cli-web/assets/{Checkbox-D-hAv15R.js → Checkbox-I1cjN4s_.js} +1 -1
  43. package/dist-cli-web/assets/{DataDirCleanupNotice-P80h2p4l.js → DataDirCleanupNotice-8zcIOyGl.js} +1 -1
  44. package/dist-cli-web/assets/{DatePicker.vue_vue_type_script_setup_true_lang-CSp691Uv.js → DatePicker.vue_vue_type_script_setup_true_lang-DWWzQOTU.js} +1 -1
  45. package/dist-cli-web/assets/{DebugToolsPanel-BK2VbKB0.js → DebugToolsPanel-CiGd5ttA.js} +1 -1
  46. package/dist-cli-web/assets/{EChart.vue_vue_type_script_setup_true_lang-BcE0mE_N.js → EChart.vue_vue_type_script_setup_true_lang-Rk-Bu-rv.js} +1 -1
  47. package/dist-cli-web/assets/{EChartBar.vue_vue_type_script_setup_true_lang-BypaV5wc.js → EChartBar.vue_vue_type_script_setup_true_lang-CB_KuKt4.js} +1 -1
  48. package/dist-cli-web/assets/{EChartLine.vue_vue_type_script_setup_true_lang-D8SyOfWC.js → EChartLine.vue_vue_type_script_setup_true_lang-5iW9KPRe.js} +1 -1
  49. package/dist-cli-web/assets/{EChartWordcloud-0rihhg03.js → EChartWordcloud-BiN68kpp.js} +1 -1
  50. package/dist-cli-web/assets/{FileDropZone.vue_vue_type_script_setup_true_lang-Dyuzh7Ex.js → FileDropZone.vue_vue_type_script_setup_true_lang-DpK_xXUN.js} +1 -1
  51. package/dist-cli-web/assets/{Filter-rD_jWpbO.js → Filter-Tmam9FK9.js} +1 -1
  52. package/dist-cli-web/assets/{GlobalTaskBar-sXQuGvF-.js → GlobalTaskBar-B77auVn7.js} +1 -1
  53. package/dist-cli-web/assets/{GroupRelationshipGalaxyView-BN1L9DFf.js → GroupRelationshipGalaxyView-DAmdqVxU.js} +1 -1
  54. package/dist-cli-web/assets/{Label-Ce4wl_Ph.js → Label-DTrL45eR.js} +1 -1
  55. package/dist-cli-web/assets/{LoadingState.vue_vue_type_script_setup_true_lang-DmVfwvnD.js → LoadingState.vue_vue_type_script_setup_true_lang-DH0zYa8f.js} +1 -1
  56. package/dist-cli-web/assets/{MessageExportModal-C2IUNPhg.js → MessageExportModal-DgvQvcc5.js} +1 -1
  57. package/dist-cli-web/assets/{PageHeader-D5BcYKBs.js → PageHeader-C-UYITO9.js} +1 -1
  58. package/dist-cli-web/assets/{PageTabs.vue_vue_type_script_setup_true_lang-DHly2-fe.js → PageTabs.vue_vue_type_script_setup_true_lang-BV344PR7.js} +1 -1
  59. package/dist-cli-web/assets/{RelationshipGalaxyCanvas-CHPqtqQz.js → RelationshipGalaxyCanvas-Bzh-vQI8.js} +3 -3
  60. package/dist-cli-web/assets/{RelationshipGalaxyThreeCanvas-qR4S-9n7.js → RelationshipGalaxyThreeCanvas--DDkxCCc.js} +1 -1
  61. package/dist-cli-web/assets/{RenderTargetSystem-BaIFulUj.js → RenderTargetSystem-BP0KBa7R.js} +1 -1
  62. package/dist-cli-web/assets/{RovingFocusItem-Bqgmzo42.js → RovingFocusItem-BAQO8BlG.js} +1 -1
  63. package/dist-cli-web/assets/{ScreenCaptureModal-sJqB_hrK.js → ScreenCaptureModal-DtAB4lyN.js} +1 -1
  64. package/dist-cli-web/assets/{SectionTabs.vue_vue_type_script_setup_true_lang-BPt98e6z.js → SectionTabs.vue_vue_type_script_setup_true_lang-DjUq1i7-.js} +1 -1
  65. package/dist-cli-web/assets/{Select-BAnN4HMs.js → Select-CaRAtYOu.js} +1 -1
  66. package/dist-cli-web/assets/{SettingsModal-C4ANMlJJ.js → SettingsModal-BKu9l7vR.js} +2 -2
  67. package/dist-cli-web/assets/{StorageTab-BgNQliz4.js → StorageTab-DWUzStD4.js} +1 -1
  68. package/dist-cli-web/assets/{Switch-DddEvDJa.js → Switch-mMuTJ87v.js} +1 -1
  69. package/dist-cli-web/assets/{Tabs-xVtuBuO0.js → Tabs-B0DXvZn9.js} +1 -1
  70. package/dist-cli-web/assets/{Tabs-DwjL-ueH.js → Tabs-Bw65ChMB.js} +1 -1
  71. package/dist-cli-web/assets/{ThemeCard.vue_vue_type_script_setup_true_lang-CNCVa86b.js → ThemeCard.vue_vue_type_script_setup_true_lang-CFSCaL65.js} +1 -1
  72. package/dist-cli-web/assets/{TimeSelect.vue_vue_type_script_setup_true_lang-BehUIWki.js → TimeSelect.vue_vue_type_script_setup_true_lang-sP4Z2nbi.js} +1 -1
  73. package/dist-cli-web/assets/{VisuallyHiddenInput-ST6JNfSG.js → VisuallyHiddenInput-Cy3d6wW5.js} +1 -1
  74. package/dist-cli-web/assets/{WebGLRenderer-DRraqD4Y.js → WebGLRenderer-C86bSgXH.js} +1 -1
  75. package/dist-cli-web/assets/{WebGPURenderer-CnzaYARg.js → WebGPURenderer-EcnRVF_C.js} +1 -1
  76. package/dist-cli-web/assets/{aiChat-CeJy-gG-.js → aiChat-ZrHuq9Eb.js} +3 -3
  77. package/dist-cli-web/assets/{base-BHbtUviQ.js → base-DwqzgeyP.js} +1 -1
  78. package/dist-cli-web/assets/{browserAll-DYxkitnx.js → browserAll-DUX8qJC8.js} +1 -1
  79. package/dist-cli-web/assets/{chatMessages-Dj1u-tFB.js → chatMessages-By6kR5_1.js} +3 -3
  80. package/dist-cli-web/assets/{cli-web-BtH8nfjA.js → cli-web-JlckDfz0.js} +1 -1
  81. package/dist-cli-web/assets/{fetch-CAEyoWQA.js → fetch-Bhl8mtJ2.js} +11 -13
  82. package/dist-cli-web/assets/{fetch-DNmRaRxX.js → fetch-BjtwVVBg.js} +1 -1
  83. package/dist-cli-web/assets/{fetch-ejEMWPM2.js → fetch-BpoJa14b.js} +1 -1
  84. package/dist-cli-web/assets/{fetch-emZXHmoE.js → fetch-CY5yJNTL.js} +1 -1
  85. package/dist-cli-web/assets/{fetch-C1Tm66i9.js → fetch-ChSI9rRd.js} +1 -1
  86. package/dist-cli-web/assets/{fetch-JEEBqR_7.js → fetch-CuySZ9TW.js} +1 -1
  87. package/dist-cli-web/assets/{fetch-T5Gi1TUZ.js → fetch-DS-lTLBb.js} +1 -1
  88. package/dist-cli-web/assets/{fetch-D7hfFyoG.js → fetch-Dkyidev6.js} +1 -1
  89. package/dist-cli-web/assets/{fetch-U9QyidNZ.js → fetch-DtqHZHIT.js} +1 -1
  90. package/dist-cli-web/assets/{fetch-CGnWNSsG.js → fetch-GYzy1nua.js} +1 -1
  91. package/dist-cli-web/assets/{fetch-DogRrvT6.js → fetch-LZAcmdq3.js} +1 -1
  92. package/dist-cli-web/assets/{fetch-BJ82mWvv.js → fetch-w66ywFn5.js} +1 -1
  93. package/dist-cli-web/assets/{host-BUvwCvZR.js → host-CBXwW7_e.js} +1 -1
  94. package/dist-cli-web/assets/{host-VTWF81F5.js → host-CDCKLdfF.js} +1 -1
  95. package/dist-cli-web/assets/{index-DQFcmWSa.js → index-3KDkw8sV.js} +1 -1
  96. package/dist-cli-web/assets/{index-e6fOnhNS.js → index-BAjafcRU.js} +1 -1
  97. package/dist-cli-web/assets/{index-DZK9Njvy.js → index-BLO0CYvx.js} +1 -1
  98. package/dist-cli-web/assets/{index-KpnLSzzX.js → index-BVoFqt2r.js} +4 -4
  99. package/dist-cli-web/assets/{index-DDt7Tfda.js → index-CYmoNVAj.js} +1 -1
  100. package/dist-cli-web/assets/{index-D9C3dyV8.js → index-D07viL9P.js} +4 -4
  101. package/dist-cli-web/assets/{index-iEQnKg2R.js → index-DD7RFB6N.js} +2 -2
  102. package/dist-cli-web/assets/index-DEafpen2.js +137 -0
  103. package/dist-cli-web/assets/index-DRFMz0cs.css +1 -0
  104. package/dist-cli-web/assets/{index-HjrJ3DXO.js → index-D_CX3gzo.js} +1 -1
  105. package/dist-cli-web/assets/{index-BLYSew5C.js → index-D_SJKdur.js} +1 -1
  106. package/dist-cli-web/assets/{index-C75W1B5J.css → index-DbP9vQhR.css} +1 -1
  107. package/dist-cli-web/assets/{index-BI2Rb_L3.js → index-RqQZ2vvr.js} +2 -2
  108. package/dist-cli-web/assets/{index-B3MCGDwx.js → index-T_aveLoS.js} +1 -1
  109. package/dist-cli-web/assets/{index-BZpR015e.css → index-XC-s67UA.css} +1 -1
  110. package/dist-cli-web/assets/{index-DUBl6aBF.js → index-fhyFEtxF.js} +1 -1
  111. package/dist-cli-web/assets/{index-CVRBBnQw.js → index-sMeHjrc9.js} +1 -1
  112. package/dist-cli-web/assets/{people-page-header-DWXwFJ8M.js → people-page-header-DPOKmbHG.js} +1 -1
  113. package/dist-cli-web/assets/{prompt-Cepfb-5-.js → prompt-ipERjPzE.js} +1 -1
  114. package/dist-cli-web/assets/{semantic-index-config-builder-hTY6QyCe.js → semantic-index-config-builder-CjJ4q8PF.js} +1 -1
  115. package/dist-cli-web/assets/service-2UJZvVpa.js +1 -0
  116. package/dist-cli-web/assets/{service-DwCmXFtI.js → service-CAdsM9Hy.js} +1 -1
  117. package/dist-cli-web/assets/service-i_PJfTaR.js +1 -0
  118. package/dist-cli-web/assets/useFormControl-BPt9mIxj.js +1 -0
  119. package/dist-cli-web/assets/{useInsightTabAnalytics-CplGbsbe.js → useInsightTabAnalytics-s3wcN9Eo.js} +4 -4
  120. package/dist-cli-web/assets/{useTable-Dmpbk7fZ.js → useTable-DOM-gqX0.js} +1 -1
  121. package/dist-cli-web/assets/{useToast-Bmgpd3sl.js → useToast-BzK6i1Tk.js} +1 -1
  122. package/dist-cli-web/assets/{webworkerAll-DkPWEyVL.js → webworkerAll-ClkzpxNT.js} +1 -1
  123. package/dist-cli-web/index.html +2 -2
  124. package/package.json +1 -1
  125. package/dist/chat-command-G2EX7VHR.mjs.map +0 -1
  126. package/dist/chunk-HBAQPF6X.mjs.map +0 -1
  127. package/dist/chunk-L6RJIVLS.mjs.map +0 -1
  128. package/dist/chunk-T5H56AZV.mjs.map +0 -1
  129. package/dist/mcp-XXSQJBGU.mjs.map +0 -1
  130. package/dist-cli-web/assets/index-Bs7gk1gf.css +0 -1
  131. package/dist-cli-web/assets/index-Cza8BzZE.js +0 -137
  132. package/dist-cli-web/assets/service-BjE0YJaM.js +0 -1
  133. package/dist-cli-web/assets/service-DQxttlJp.js +0 -1
  134. package/dist-cli-web/assets/useFormControl-CJyJY8AK.js +0 -1
  135. /package/dist/{chunk-F4HVCFZL.mjs.map → chunk-3K7F2SRZ.mjs.map} +0 -0
  136. /package/dist/{chunk-FCUUAGGC.mjs.map → chunk-ARRFRJOH.mjs.map} +0 -0
  137. /package/dist/{chunk-H46CLFWK.mjs.map → chunk-D6BRSG3V.mjs.map} +0 -0
  138. /package/dist/{chunk-YI3EQYEG.mjs.map → chunk-DJ7QEJNO.mjs.map} +0 -0
  139. /package/dist/{chunk-XQ6Z2KNN.mjs.map → chunk-JWWWLW5G.mjs.map} +0 -0
  140. /package/dist/{chunk-HMVM7VCA.mjs.map → chunk-NVW3ZCYD.mjs.map} +0 -0
  141. /package/dist/{chunk-EFX66A2O.mjs.map → chunk-QP77JL6O.mjs.map} +0 -0
  142. /package/dist/{chunk-EK5QIJLZ.mjs.map → chunk-VCKF7RYB.mjs.map} +0 -0
  143. /package/dist/{chunk-E6LCCPIB.mjs.map → chunk-YPP3N2AX.mjs.map} +0 -0
  144. /package/dist/{http-5BRVWAJR.mjs.map → http-O4AZUIOD.mjs.map} +0 -0
  145. /package/dist/{import-IAECQDKC.mjs.map → import-IALJQB7V.mjs.map} +0 -0
  146. /package/dist/{src-4HLKMQ7S.mjs.map → src-6ICLBMOR.mjs.map} +0 -0
  147. /package/dist/{stream-import-PUG42I36.mjs.map → stream-import-NKQYYSGZ.mjs.map} +0 -0
  148. /package/dist/{worker-runtime-X5563TVT.mjs.map → worker-runtime-AE2I6U2G.mjs.map} +0 -0
@@ -918,6 +918,22 @@ var BUILTIN_TOOL_CATALOG = [
918
918
  { name: "unanswered_messages", category: "analysis" }
919
919
  ];
920
920
 
921
+ // ../../packages/core/src/ai/tool-result-text.ts
922
+ var MAX_PERSISTED_TOOL_RESULT_CHARS = 4e3;
923
+ var TRUNCATION_MARKER = "\n\u2026[truncated]";
924
+ function isRecord(value) {
925
+ return typeof value === "object" && value !== null && !Array.isArray(value);
926
+ }
927
+ function extractToolResultText(toolResult) {
928
+ if (!isRecord(toolResult)) return "";
929
+ if (!Array.isArray(toolResult.content)) return "";
930
+ return toolResult.content.map((part) => isRecord(part) && part.type === "text" && typeof part.text === "string" ? part.text : "").filter((text) => text.length > 0).join("\n");
931
+ }
932
+ function truncateToolResultText(text, maxChars = MAX_PERSISTED_TOOL_RESULT_CHARS) {
933
+ if (text.length <= maxChars) return text;
934
+ return text.slice(0, maxChars) + TRUNCATION_MARKER;
935
+ }
936
+
921
937
  // ../../packages/core/src/ai/provider-registry.ts
922
938
  var OPENAI = {
923
939
  id: "openai",
@@ -2274,14 +2290,6 @@ function getThinkingCompat(provider, modelId) {
2274
2290
  return compat;
2275
2291
  }
2276
2292
 
2277
- // ../../packages/core/src/ai/tool-result-text.ts
2278
- var MAX_PERSISTED_TOOL_RESULT_CHARS = 4e3;
2279
- var TRUNCATION_MARKER = "\n\u2026[truncated]";
2280
- function truncateToolResultText(text, maxChars = MAX_PERSISTED_TOOL_RESULT_CHARS) {
2281
- if (text.length <= maxChars) return text;
2282
- return text.slice(0, maxChars) + TRUNCATION_MARKER;
2283
- }
2284
-
2285
2293
  // ../../packages/core/src/import/writers.ts
2286
2294
  function writeParseResultToDb(db, meta, members, messages) {
2287
2295
  let messageCount = 0;
@@ -6688,7 +6696,7 @@ function getMemberNameHistoryFromMessages(db, memberId) {
6688
6696
  function hydrateMessagesByIds(db, ids) {
6689
6697
  if (ids.length === 0) return [];
6690
6698
  const placeholders = ids.map(() => "?").join(", ");
6691
- const rows = db.prepare(`${FULL_MSG_SELECT} WHERE msg.id IN (${placeholders}) ORDER BY msg.id ASC`).all(...ids);
6699
+ const rows = db.prepare(`${FULL_MSG_SELECT} WHERE msg.id IN (${placeholders}) ORDER BY msg.ts ASC, msg.id ASC`).all(...ids);
6692
6700
  return rows.map(mapMessageRow);
6693
6701
  }
6694
6702
  function getMessageContext(db, messageIds, contextSize = 20) {
@@ -6696,9 +6704,17 @@ function getMessageContext(db, messageIds, contextSize = 20) {
6696
6704
  const contextIds = /* @__PURE__ */ new Set();
6697
6705
  for (const messageId of messageIds) {
6698
6706
  contextIds.add(messageId);
6699
- const beforeRows = db.prepare("SELECT id FROM message WHERE id < ? ORDER BY id DESC LIMIT ?").all(messageId, contextSize);
6707
+ const beforeRows = db.prepare(
6708
+ `SELECT msg.id FROM message msg
6709
+ WHERE (msg.ts, msg.id) < (SELECT ts, id FROM message WHERE id = ?)
6710
+ ORDER BY msg.ts DESC, msg.id DESC LIMIT ?`
6711
+ ).all(messageId, contextSize);
6700
6712
  beforeRows.forEach((r) => contextIds.add(r.id));
6701
- const afterRows = db.prepare("SELECT id FROM message WHERE id > ? ORDER BY id ASC LIMIT ?").all(messageId, contextSize);
6713
+ const afterRows = db.prepare(
6714
+ `SELECT msg.id FROM message msg
6715
+ WHERE (msg.ts, msg.id) > (SELECT ts, id FROM message WHERE id = ?)
6716
+ ORDER BY msg.ts ASC, msg.id ASC LIMIT ?`
6717
+ ).all(messageId, contextSize);
6702
6718
  afterRows.forEach((r) => contextIds.add(r.id));
6703
6719
  }
6704
6720
  return hydrateMessagesByIds(db, Array.from(contextIds));
@@ -6706,37 +6722,51 @@ function getMessageContext(db, messageIds, contextSize = 20) {
6706
6722
  function getSearchMessageContext(db, messageIds, contextBefore = 2, contextAfter = 2) {
6707
6723
  if (messageIds.length === 0) return [];
6708
6724
  const contextIds = /* @__PURE__ */ new Set();
6725
+ const segments = /* @__PURE__ */ new Map();
6709
6726
  const hasSessionData = hasTable(db, "message_context") && db.prepare("SELECT 1 FROM message_context LIMIT 1").get() !== void 0;
6710
6727
  for (const messageId of messageIds) {
6711
6728
  contextIds.add(messageId);
6712
6729
  if (hasSessionData) {
6713
6730
  const sessionRow = db.prepare("SELECT segment_id FROM message_context WHERE message_id = ?").get(messageId);
6714
6731
  if (sessionRow) {
6715
- if (contextBefore > 0) {
6732
+ if (contextBefore <= 0 && contextAfter <= 0) continue;
6733
+ let segment2 = segments.get(sessionRow.segment_id);
6734
+ if (!segment2) {
6716
6735
  const rows = db.prepare(
6717
- `SELECT mc.message_id as id FROM message_context mc
6718
- WHERE mc.segment_id = ? AND mc.message_id < ?
6719
- ORDER BY mc.message_id DESC LIMIT ?`
6720
- ).all(sessionRow.segment_id, messageId, contextBefore);
6721
- rows.forEach((r) => contextIds.add(r.id));
6736
+ `SELECT msg.id FROM message_context mc
6737
+ JOIN message msg ON msg.id = mc.message_id
6738
+ WHERE mc.segment_id = ? ORDER BY msg.ts ASC, msg.id ASC`
6739
+ ).all(sessionRow.segment_id);
6740
+ const ids = rows.map((row) => row.id);
6741
+ segment2 = { ids, positions: new Map(ids.map((id, index) => [id, index])) };
6742
+ segments.set(sessionRow.segment_id, segment2);
6722
6743
  }
6723
- if (contextAfter > 0) {
6724
- const rows = db.prepare(
6725
- `SELECT mc.message_id as id FROM message_context mc
6726
- WHERE mc.segment_id = ? AND mc.message_id > ?
6727
- ORDER BY mc.message_id ASC LIMIT ?`
6728
- ).all(sessionRow.segment_id, messageId, contextAfter);
6729
- rows.forEach((r) => contextIds.add(r.id));
6744
+ const position = segment2.positions.get(messageId);
6745
+ if (position !== void 0) {
6746
+ for (const id of segment2.ids.slice(
6747
+ Math.max(0, position - Math.max(0, contextBefore)),
6748
+ position + Math.max(0, contextAfter) + 1
6749
+ )) {
6750
+ contextIds.add(id);
6751
+ }
6730
6752
  }
6731
6753
  continue;
6732
6754
  }
6733
6755
  }
6734
6756
  if (contextBefore > 0) {
6735
- const rows = db.prepare("SELECT id FROM message WHERE id < ? ORDER BY id DESC LIMIT ?").all(messageId, contextBefore);
6757
+ const rows = db.prepare(
6758
+ `SELECT msg.id FROM message msg
6759
+ WHERE (msg.ts, msg.id) < (SELECT ts, id FROM message WHERE id = ?)
6760
+ ORDER BY msg.ts DESC, msg.id DESC LIMIT ?`
6761
+ ).all(messageId, contextBefore);
6736
6762
  rows.forEach((r) => contextIds.add(r.id));
6737
6763
  }
6738
6764
  if (contextAfter > 0) {
6739
- const rows = db.prepare("SELECT id FROM message WHERE id > ? ORDER BY id ASC LIMIT ?").all(messageId, contextAfter);
6765
+ const rows = db.prepare(
6766
+ `SELECT msg.id FROM message msg
6767
+ WHERE (msg.ts, msg.id) > (SELECT ts, id FROM message WHERE id = ?)
6768
+ ORDER BY msg.ts ASC, msg.id ASC LIMIT ?`
6769
+ ).all(messageId, contextAfter);
6740
6770
  rows.forEach((r) => contextIds.add(r.id));
6741
6771
  }
6742
6772
  }
@@ -8931,7 +8961,7 @@ var ChartValidationError = class extends Error {
8931
8961
  }
8932
8962
  };
8933
8963
  var CHART_TYPES = /* @__PURE__ */ new Set(["bar", "line", "pie", "heatmap"]);
8934
- function isRecord(value) {
8964
+ function isRecord2(value) {
8935
8965
  return typeof value === "object" && value !== null && !Array.isArray(value);
8936
8966
  }
8937
8967
  function asFieldName(value, label) {
@@ -8970,7 +9000,7 @@ function inferFieldType(values) {
8970
9000
  return "category";
8971
9001
  }
8972
9002
  function normalizeChartSpec(raw) {
8973
- if (!isRecord(raw)) throw new ChartValidationError("chartSpec must be an object");
9003
+ if (!isRecord2(raw)) throw new ChartValidationError("chartSpec must be an object");
8974
9004
  if (raw.version !== 1) throw new ChartValidationError("chartSpec.version must be 1");
8975
9005
  if (typeof raw.type !== "string" || !CHART_TYPES.has(raw.type)) {
8976
9006
  throw new ChartValidationError("chartSpec.type must be one of: bar, line, pie, heatmap");
@@ -8978,7 +9008,7 @@ function normalizeChartSpec(raw) {
8978
9008
  if (typeof raw.title !== "string" || raw.title.trim().length === 0) {
8979
9009
  throw new ChartValidationError("chartSpec.title must be a non-empty string");
8980
9010
  }
8981
- if (!isRecord(raw.encoding)) throw new ChartValidationError("chartSpec.encoding must be an object");
9011
+ if (!isRecord2(raw.encoding)) throw new ChartValidationError("chartSpec.encoding must be an object");
8982
9012
  const spec = raw;
8983
9013
  switch (spec.type) {
8984
9014
  case "bar":
@@ -9568,7 +9598,7 @@ function formatData(data) {
9568
9598
  if (data === void 0) return "";
9569
9599
  if (data instanceof Error) {
9570
9600
  const info = extractErrorInfo(data);
9571
- const stack = extractErrorStack(data);
9601
+ const stack = data.stack;
9572
9602
  return JSON.stringify(info) + (stack ? `
9573
9603
  ${stack}` : "");
9574
9604
  }
@@ -13571,6 +13601,10 @@ function applyPreprocessingPipeline(options) {
13571
13601
  // ../../packages/node-runtime/src/ai/i18n/locales/zh-CN.ts
13572
13602
  var zh_CN_default = {
13573
13603
  ai: {
13604
+ topics: {
13605
+ reasoningLimitReached: "\u6A21\u578B\u8FBE\u5230\u8F93\u51FA\u4E0A\u9650\uFF0C\u4F46\u4EC5\u8FD4\u56DE\u4E86\u601D\u8003\u5185\u5BB9\uFF0C\u672A\u751F\u6210\u8BDD\u9898\u7ED3\u679C\u3002\u8BF7\u66F4\u6362\u5FEB\u901F\u6A21\u578B\uFF0C\u6216\u4F7F\u7528\u652F\u6301\u5173\u95ED\u601D\u8003\u7684\u63A5\u53E3\u3002",
13606
+ outputLimitReached: "\u8BDD\u9898\u7ED3\u679C\u8FBE\u5230\u6A21\u578B\u8F93\u51FA\u4E0A\u9650\uFF0C\u5185\u5BB9\u53EF\u80FD\u4E0D\u5B8C\u6574\u3002\u8BF7\u66F4\u6362\u5FEB\u901F\u6A21\u578B\u540E\u91CD\u8BD5\u3002"
13607
+ },
13574
13608
  tools: {
13575
13609
  search_messages: {
13576
13610
  desc: "\u6839\u636E\u5173\u952E\u8BCD\u641C\u7D22\u804A\u5929\u8BB0\u5F55\uFF0C\u662F\u56DE\u7B54\u5173\u952E\u8BCD\u3001\u6210\u5458\u53D1\u8A00\u3001\u662F\u5426\u51FA\u73B0\u8FC7\u67D0\u8BDD\u9898\u7B49\u4E8B\u5B9E\u95EE\u9898\u7684\u4E3B\u8981\u8BC1\u636E\u5DE5\u5177\u3002\u53EF\u4EE5\u6307\u5B9A\u65F6\u95F4\u8303\u56F4\u548C\u53D1\u9001\u8005\u6765\u7B5B\u9009\u6D88\u606F\u3002\u652F\u6301\u7CBE\u786E\u5230\u5206\u949F\u7EA7\u522B\u7684\u65F6\u95F4\u67E5\u8BE2\u3002",
@@ -13787,14 +13821,18 @@ var zh_CN_default = {
13787
13821
  response_time_analysis: {
13788
13822
  desc: '\u5206\u6790\u6D88\u606F\u4E4B\u95F4\u7684\u54CD\u5E94\u65F6\u95F4\uFF0C\u6309\u6210\u5458\u7EF4\u5EA6\u7EDF\u8BA1\u4E2D\u4F4D\u6570\u548C\u5E73\u5747\u56DE\u590D\u901F\u5EA6\u3002\u9002\u7528\u4E8E"\u5927\u5BB6\u5E73\u5747\u591A\u4E45\u56DE\u590D\u6D88\u606F"\u3001"\u8C01\u56DE\u590D\u6700\u5FEB"\u3002',
13789
13823
  params: {
13790
- days: "\u7EDF\u8BA1\u6700\u8FD1\u591A\u5C11\u5929\u7684\u6570\u636E",
13824
+ days: "\u6CA1\u6709\u6709\u6548\u7684\u663E\u5F0F\u65F6\u95F4\u6216\u6240\u9009\u65F6\u95F4\u8303\u56F4\u65F6\uFF0C\u7EDF\u8BA1\u6700\u8FD1\u591A\u5C11\u5929\u7684\u6570\u636E\uFF0C\u9ED8\u8BA4 30",
13825
+ start_time: '\u5F00\u59CB\u65F6\u95F4\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\u3002\u663E\u5F0F\u65F6\u95F4\u4F18\u5148\u4E8E\u6240\u9009\u8303\u56F4\u548C days',
13826
+ end_time: '\u7ED3\u675F\u65F6\u95F4\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\u3002\u663E\u5F0F\u65F6\u95F4\u4F18\u5148\u4E8E\u6240\u9009\u8303\u56F4\u548C days',
13791
13827
  top_n: "\u8FD4\u56DE\u524D\u591A\u5C11\u540D"
13792
13828
  }
13793
13829
  },
13794
13830
  keyword_frequency: {
13795
13831
  desc: '\u5BF9\u6307\u5B9A\u65F6\u95F4\u6BB5\u7684\u6587\u672C\u6D88\u606F\u8FDB\u884C\u5206\u8BCD\uFF0C\u7EDF\u8BA1\u9AD8\u9891\u5173\u952E\u8BCD\u6392\u884C\u3002\u652F\u6301\u4E2D\u82F1\u65E5\u6587\u5206\u8BCD\u3002\u9002\u7528\u4E8E"\u5927\u5BB6\u6700\u5E38\u8BF4\u4EC0\u4E48"\u3001"\u9AD8\u9891\u5173\u952E\u8BCD\u662F\u4EC0\u4E48"\u3002',
13796
13832
  params: {
13797
- days: "\u7EDF\u8BA1\u6700\u8FD1\u591A\u5C11\u5929\u7684\u6570\u636E",
13833
+ days: "\u6CA1\u6709\u6709\u6548\u7684\u663E\u5F0F\u65F6\u95F4\u6216\u6240\u9009\u65F6\u95F4\u8303\u56F4\u65F6\uFF0C\u7EDF\u8BA1\u6700\u8FD1\u591A\u5C11\u5929\u7684\u6570\u636E\uFF0C\u9ED8\u8BA4 30",
13834
+ start_time: '\u5F00\u59CB\u65F6\u95F4\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\u3002\u663E\u5F0F\u65F6\u95F4\u4F18\u5148\u4E8E\u6240\u9009\u8303\u56F4\u548C days',
13835
+ end_time: '\u7ED3\u675F\u65F6\u95F4\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\u3002\u663E\u5F0F\u65F6\u95F4\u4F18\u5148\u4E8E\u6240\u9009\u8303\u56F4\u548C days',
13798
13836
  top_n: "\u8FD4\u56DE\u524D\u591A\u5C11\u4E2A\u5173\u952E\u8BCD"
13799
13837
  }
13800
13838
  },
@@ -13933,6 +13971,10 @@ var zh_CN_default = {
13933
13971
  // ../../packages/node-runtime/src/ai/i18n/locales/en-US.ts
13934
13972
  var en_US_default = {
13935
13973
  ai: {
13974
+ topics: {
13975
+ reasoningLimitReached: "The model reached its output limit with only reasoning and no topic result. Use a different fast model or an endpoint that supports disabling thinking.",
13976
+ outputLimitReached: "The topic response reached the model output limit and may be incomplete. Use a different fast model and retry."
13977
+ },
13936
13978
  tools: {
13937
13979
  search_messages: {
13938
13980
  desc: "Search chat records by keywords. This is the primary evidence tool for factual questions about keywords, member messages, or whether a topic appeared. Can specify time range and sender to filter messages. Supports minute-level time queries.",
@@ -14150,14 +14192,18 @@ Returned summaries are brief descriptions of each segment, helping quickly locat
14150
14192
  response_time_analysis: {
14151
14193
  desc: 'Analyze response times between messages, showing median and average reply speed per member. Useful for "how quickly do people reply" or "who replies the fastest".',
14152
14194
  params: {
14153
- days: "Number of recent days to analyze",
14195
+ days: "Recent days to analyze when no explicit or selected time range is available; defaults to 30",
14196
+ start_time: 'Start time, format "YYYY-MM-DD HH:mm". Explicit dates override the selected range and days',
14197
+ end_time: 'End time, format "YYYY-MM-DD HH:mm". Explicit dates override the selected range and days',
14154
14198
  top_n: "Number of top members to return"
14155
14199
  }
14156
14200
  },
14157
14201
  keyword_frequency: {
14158
14202
  desc: 'Segment text messages and rank high-frequency keywords. Supports Chinese, English, and Japanese. Useful for "what do people talk about most" or "what are the hot keywords".',
14159
14203
  params: {
14160
- days: "Number of recent days to analyze",
14204
+ days: "Recent days to analyze when no explicit or selected time range is available; defaults to 30",
14205
+ start_time: 'Start time, format "YYYY-MM-DD HH:mm". Explicit dates override the selected range and days',
14206
+ end_time: 'End time, format "YYYY-MM-DD HH:mm". Explicit dates override the selected range and days',
14161
14207
  top_n: "Number of top keywords to return"
14162
14208
  }
14163
14209
  },
@@ -14297,6 +14343,10 @@ Usage rules:
14297
14343
  // ../../packages/node-runtime/src/ai/i18n/locales/ja-JP.ts
14298
14344
  var ja_JP_default = {
14299
14345
  ai: {
14346
+ topics: {
14347
+ reasoningLimitReached: "\u30E2\u30C7\u30EB\u304C\u51FA\u529B\u4E0A\u9650\u306B\u9054\u3057\u307E\u3057\u305F\u304C\u3001\u601D\u8003\u5185\u5BB9\u306E\u307F\u304C\u8FD4\u3055\u308C\u3001\u30C8\u30D4\u30C3\u30AF\u306E\u7D50\u679C\u306F\u751F\u6210\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u9AD8\u901F\u30E2\u30C7\u30EB\u3092\u5909\u66F4\u3059\u308B\u304B\u3001\u601D\u8003\u3092\u7121\u52B9\u306B\u3067\u304D\u308B\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
14348
+ outputLimitReached: "\u30C8\u30D4\u30C3\u30AF\u306E\u5FDC\u7B54\u304C\u30E2\u30C7\u30EB\u306E\u51FA\u529B\u4E0A\u9650\u306B\u9054\u3057\u3001\u5185\u5BB9\u304C\u4E0D\u5B8C\u5168\u306A\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\u9AD8\u901F\u30E2\u30C7\u30EB\u3092\u5909\u66F4\u3057\u3066\u518D\u8A66\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
14349
+ },
14300
14350
  tools: {
14301
14351
  search_messages: {
14302
14352
  desc: "\u30AD\u30FC\u30EF\u30FC\u30C9\u3067\u30C1\u30E3\u30C3\u30C8\u5C65\u6B74\u3092\u691C\u7D22\u3059\u308B\u3002\u30AD\u30FC\u30EF\u30FC\u30C9\u3001\u30E1\u30F3\u30D0\u30FC\u306E\u767A\u8A00\u3001\u7279\u5B9A\u30C8\u30D4\u30C3\u30AF\u304C\u51FA\u305F\u304B\u3069\u3046\u304B\u306A\u3069\u306E\u4E8B\u5B9F\u8CEA\u554F\u306B\u5BFE\u3059\u308B\u4E3B\u8981\u306A\u8A3C\u62E0\u53D6\u5F97\u30C4\u30FC\u30EB\u3002\u6642\u9593\u7BC4\u56F2\u3084\u9001\u4FE1\u8005\u3067\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30D5\u30A3\u30EB\u30BF\u30EA\u30F3\u30B0\u3067\u304D\u308B\u3002\u5206\u5358\u4F4D\u306E\u7CBE\u5EA6\u3067\u6642\u9593\u30AF\u30A8\u30EA\u3092\u30B5\u30DD\u30FC\u30C8\u3059\u308B\u3002",
@@ -14513,14 +14563,18 @@ var ja_JP_default = {
14513
14563
  response_time_analysis: {
14514
14564
  desc: "\u30E1\u30C3\u30BB\u30FC\u30B8\u9593\u306E\u5FDC\u7B54\u6642\u9593\u3092\u5206\u6790\u3057\u3001\u30E1\u30F3\u30D0\u30FC\u3054\u3068\u306E\u4E2D\u592E\u5024\u3068\u5E73\u5747\u8FD4\u4FE1\u901F\u5EA6\u3092\u96C6\u8A08\u3059\u308B\u3002\u300C\u307F\u3093\u306A\u3069\u306E\u304F\u3089\u3044\u3067\u8FD4\u4FE1\u3059\u308B\u304B\u300D\u300C\u8AB0\u304C\u6700\u3082\u901F\u304F\u8FD4\u4FE1\u3059\u308B\u304B\u300D\u306B\u9069\u3057\u3066\u3044\u308B\u3002",
14515
14565
  params: {
14516
- days: "\u76F4\u8FD1\u4F55\u65E5\u9593\u306E\u30C7\u30FC\u30BF\u3092\u96C6\u8A08\u3059\u308B\u304B",
14566
+ days: "\u6709\u52B9\u306A\u660E\u793A\u65E5\u6642\u3084\u9078\u629E\u671F\u9593\u304C\u306A\u3044\u5834\u5408\u306B\u96C6\u8A08\u3059\u308B\u76F4\u8FD1\u65E5\u6570\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F30\u65E5",
14567
+ start_time: '\u958B\u59CB\u6642\u523B\u3002\u5F62\u5F0F "YYYY-MM-DD HH:mm"\u3002\u660E\u793A\u65E5\u6642\u306F\u9078\u629E\u671F\u9593\u3068 days \u3088\u308A\u512A\u5148\u3055\u308C\u308B',
14568
+ end_time: '\u7D42\u4E86\u6642\u523B\u3002\u5F62\u5F0F "YYYY-MM-DD HH:mm"\u3002\u660E\u793A\u65E5\u6642\u306F\u9078\u629E\u671F\u9593\u3068 days \u3088\u308A\u512A\u5148\u3055\u308C\u308B',
14517
14569
  top_n: "\u4E0A\u4F4D\u4F55\u540D\u3092\u8FD4\u5374\u3059\u308B\u304B"
14518
14570
  }
14519
14571
  },
14520
14572
  keyword_frequency: {
14521
14573
  desc: "\u6307\u5B9A\u671F\u9593\u306E\u30C6\u30AD\u30B9\u30C8\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u5206\u8A5E\u3057\u3001\u9AD8\u983B\u5EA6\u30AD\u30FC\u30EF\u30FC\u30C9\u3092\u30E9\u30F3\u30AD\u30F3\u30B0\u3059\u308B\u3002\u4E2D\u56FD\u8A9E\u30FB\u82F1\u8A9E\u30FB\u65E5\u672C\u8A9E\u306E\u5206\u8A5E\u306B\u5BFE\u5FDC\u3002\u300C\u307F\u3093\u306A\u304C\u6700\u3082\u3088\u304F\u8A71\u3059\u8A71\u984C\u306F\u4F55\u304B\u300D\u300C\u9AD8\u983B\u5EA6\u30AD\u30FC\u30EF\u30FC\u30C9\u306F\u4F55\u304B\u300D\u306B\u9069\u3057\u3066\u3044\u308B\u3002",
14522
14574
  params: {
14523
- days: "\u76F4\u8FD1\u4F55\u65E5\u9593\u306E\u30C7\u30FC\u30BF\u3092\u96C6\u8A08\u3059\u308B\u304B",
14575
+ days: "\u6709\u52B9\u306A\u660E\u793A\u65E5\u6642\u3084\u9078\u629E\u671F\u9593\u304C\u306A\u3044\u5834\u5408\u306B\u96C6\u8A08\u3059\u308B\u76F4\u8FD1\u65E5\u6570\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F30\u65E5",
14576
+ start_time: '\u958B\u59CB\u6642\u523B\u3002\u5F62\u5F0F "YYYY-MM-DD HH:mm"\u3002\u660E\u793A\u65E5\u6642\u306F\u9078\u629E\u671F\u9593\u3068 days \u3088\u308A\u512A\u5148\u3055\u308C\u308B',
14577
+ end_time: '\u7D42\u4E86\u6642\u523B\u3002\u5F62\u5F0F "YYYY-MM-DD HH:mm"\u3002\u660E\u793A\u65E5\u6642\u306F\u9078\u629E\u671F\u9593\u3068 days \u3088\u308A\u512A\u5148\u3055\u308C\u308B',
14524
14578
  top_n: "\u4E0A\u4F4D\u4F55\u500B\u306E\u30AD\u30FC\u30EF\u30FC\u30C9\u3092\u8FD4\u5374\u3059\u308B\u304B"
14525
14579
  }
14526
14580
  },
@@ -14657,6 +14711,10 @@ var ja_JP_default = {
14657
14711
  // ../../packages/node-runtime/src/ai/i18n/locales/zh-TW.ts
14658
14712
  var zh_TW_default = {
14659
14713
  ai: {
14714
+ topics: {
14715
+ reasoningLimitReached: "\u6A21\u578B\u9054\u5230\u8F38\u51FA\u4E0A\u9650\uFF0C\u4F46\u50C5\u56DE\u50B3\u4E86\u601D\u8003\u5167\u5BB9\uFF0C\u672A\u7522\u751F\u8A71\u984C\u7D50\u679C\u3002\u8ACB\u66F4\u63DB\u5FEB\u901F\u6A21\u578B\uFF0C\u6216\u4F7F\u7528\u652F\u63F4\u95DC\u9589\u601D\u8003\u7684\u4ECB\u9762\u3002",
14716
+ outputLimitReached: "\u8A71\u984C\u7D50\u679C\u9054\u5230\u6A21\u578B\u8F38\u51FA\u4E0A\u9650\uFF0C\u5167\u5BB9\u53EF\u80FD\u4E0D\u5B8C\u6574\u3002\u8ACB\u66F4\u63DB\u5FEB\u901F\u6A21\u578B\u5F8C\u91CD\u8A66\u3002"
14717
+ },
14660
14718
  tools: {
14661
14719
  search_messages: {
14662
14720
  desc: "\u6839\u64DA\u95DC\u9375\u8A5E\u641C\u5C0B\u804A\u5929\u7D00\u9304\uFF0C\u662F\u56DE\u7B54\u95DC\u9375\u8A5E\u3001\u6210\u54E1\u767C\u8A00\u3001\u662F\u5426\u51FA\u73FE\u904E\u67D0\u8A71\u984C\u7B49\u4E8B\u5BE6\u554F\u984C\u7684\u4E3B\u8981\u8B49\u64DA\u5DE5\u5177\u3002\u53EF\u4EE5\u6307\u5B9A\u6642\u9593\u7BC4\u570D\u548C\u50B3\u9001\u8005\u4F86\u7BE9\u9078\u8A0A\u606F\u3002\u652F\u63F4\u7CBE\u78BA\u5230\u5206\u9418\u7D1A\u5225\u7684\u6642\u9593\u67E5\u8A62\u3002",
@@ -14873,14 +14931,18 @@ var zh_TW_default = {
14873
14931
  response_time_analysis: {
14874
14932
  desc: "\u5206\u6790\u8A0A\u606F\u4E4B\u9593\u7684\u56DE\u61C9\u6642\u9593\uFF0C\u6309\u6210\u54E1\u7DAD\u5EA6\u7D71\u8A08\u4E2D\u4F4D\u6578\u548C\u5E73\u5747\u56DE\u8986\u901F\u5EA6\u3002\u9069\u7528\u65BC\u300C\u5927\u5BB6\u5E73\u5747\u591A\u4E45\u56DE\u8986\u8A0A\u606F\u300D\u3001\u300C\u8AB0\u56DE\u8986\u6700\u5FEB\u300D\u3002",
14875
14933
  params: {
14876
- days: "\u7D71\u8A08\u6700\u8FD1\u591A\u5C11\u5929\u7684\u8CC7\u6599",
14934
+ days: "\u6C92\u6709\u6709\u6548\u7684\u660E\u78BA\u6642\u9593\u6216\u6240\u9078\u6642\u9593\u7BC4\u570D\u6642\uFF0C\u7D71\u8A08\u6700\u8FD1\u591A\u5C11\u5929\u7684\u8CC7\u6599\uFF0C\u9810\u8A2D 30",
14935
+ start_time: '\u958B\u59CB\u6642\u9593\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\u3002\u660E\u78BA\u6307\u5B9A\u7684\u6642\u9593\u512A\u5148\u65BC\u6240\u9078\u7BC4\u570D\u548C days',
14936
+ end_time: '\u7D50\u675F\u6642\u9593\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\u3002\u660E\u78BA\u6307\u5B9A\u7684\u6642\u9593\u512A\u5148\u65BC\u6240\u9078\u7BC4\u570D\u548C days',
14877
14937
  top_n: "\u56DE\u50B3\u524D\u591A\u5C11\u540D"
14878
14938
  }
14879
14939
  },
14880
14940
  keyword_frequency: {
14881
14941
  desc: "\u5C0D\u6307\u5B9A\u6642\u9593\u6BB5\u7684\u6587\u5B57\u8A0A\u606F\u9032\u884C\u5206\u8A5E\uFF0C\u7D71\u8A08\u9AD8\u983B\u95DC\u9375\u8A5E\u6392\u884C\u3002\u652F\u63F4\u4E2D\u82F1\u65E5\u6587\u5206\u8A5E\u3002\u9069\u7528\u65BC\u300C\u5927\u5BB6\u6700\u5E38\u8AAA\u4EC0\u9EBC\u300D\u3001\u300C\u9AD8\u983B\u95DC\u9375\u8A5E\u662F\u4EC0\u9EBC\u300D\u3002",
14882
14942
  params: {
14883
- days: "\u7D71\u8A08\u6700\u8FD1\u591A\u5C11\u5929\u7684\u8CC7\u6599",
14943
+ days: "\u6C92\u6709\u6709\u6548\u7684\u660E\u78BA\u6642\u9593\u6216\u6240\u9078\u6642\u9593\u7BC4\u570D\u6642\uFF0C\u7D71\u8A08\u6700\u8FD1\u591A\u5C11\u5929\u7684\u8CC7\u6599\uFF0C\u9810\u8A2D 30",
14944
+ start_time: '\u958B\u59CB\u6642\u9593\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\u3002\u660E\u78BA\u6307\u5B9A\u7684\u6642\u9593\u512A\u5148\u65BC\u6240\u9078\u7BC4\u570D\u548C days',
14945
+ end_time: '\u7D50\u675F\u6642\u9593\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\u3002\u660E\u78BA\u6307\u5B9A\u7684\u6642\u9593\u512A\u5148\u65BC\u6240\u9078\u7BC4\u570D\u548C days',
14884
14946
  top_n: "\u56DE\u50B3\u524D\u591A\u5C11\u500B\u95DC\u9375\u8A5E"
14885
14947
  }
14886
14948
  },
@@ -15058,6 +15120,75 @@ import {
15058
15120
  function isPiMessage(message) {
15059
15121
  return message.role === "user" || message.role === "assistant" || message.role === "toolResult";
15060
15122
  }
15123
+ function fitToolResults(context, contextWindow, maxTokens) {
15124
+ const safetyTokens = Math.min(4096, Math.floor(contextWindow / 2));
15125
+ const budget = contextWindow - safetyTokens - Math.min(maxTokens, Math.floor(contextWindow / 4));
15126
+ const estimate = (text) => {
15127
+ let tokens2 = 0;
15128
+ for (let i = 0; i < text.length; i += 256) tokens2 += countTokens(text.slice(i, i + 256));
15129
+ return Math.max(tokens2, Math.ceil(text.length / 4));
15130
+ };
15131
+ const messageTokens = (message) => 8 + estimate(
15132
+ JSON.stringify({
15133
+ role: message.role,
15134
+ content: message.content,
15135
+ ...message.role === "toolResult" ? { toolCallId: message.toolCallId, toolName: message.toolName } : {}
15136
+ })
15137
+ );
15138
+ let tokens = 8 + estimate(context.systemPrompt ?? "") + estimate(
15139
+ JSON.stringify(
15140
+ context.tools?.map(({ name, description, parameters }) => ({ name, description, parameters })) ?? []
15141
+ )
15142
+ ) + context.messages.reduce((sum, message) => sum + messageTokens(message), 0);
15143
+ if (tokens <= budget) return { context, maxTokens: Math.min(maxTokens, contextWindow - tokens - 16) };
15144
+ const messages = context.messages.slice();
15145
+ const marker = "\n[Tool result truncated to fit the context window. Use a narrower query if needed.]";
15146
+ for (let i = 0; i < messages.length && tokens > budget; i++) {
15147
+ const message = messages[i];
15148
+ if (message.role !== "toolResult") continue;
15149
+ const content = message.content.slice();
15150
+ for (let j = 0; j < content.length && tokens > budget; j++) {
15151
+ const block = content[j];
15152
+ if (block.type !== "text") continue;
15153
+ const before = messageTokens({ ...message, content });
15154
+ content[j] = { ...block, text: marker };
15155
+ const after = messageTokens({ ...message, content });
15156
+ if (after >= before) {
15157
+ content[j] = block;
15158
+ continue;
15159
+ }
15160
+ if (tokens - before + after <= budget) {
15161
+ let low = 0;
15162
+ let high = block.text.length;
15163
+ while (low < high) {
15164
+ const mid = Math.ceil((low + high) / 2);
15165
+ content[j] = { ...block, text: block.text.slice(0, mid) + marker };
15166
+ if (tokens - before + messageTokens({ ...message, content }) <= budget) low = mid;
15167
+ else high = mid - 1;
15168
+ }
15169
+ content[j] = { ...block, text: block.text.slice(0, low) + marker };
15170
+ }
15171
+ tokens += messageTokens({ ...message, content }) - before;
15172
+ }
15173
+ messages[i] = { ...message, content };
15174
+ }
15175
+ if (tokens + 16 > contextWindow)
15176
+ throw new Error(
15177
+ "Agent context exceeds the model window after trimming tool results. Start a new conversation or shorten the request."
15178
+ );
15179
+ return {
15180
+ context: {
15181
+ ...context,
15182
+ messages: messages.map(
15183
+ (message) => message.role === "assistant" ? {
15184
+ ...message,
15185
+ usage: { ...message.usage, input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0 }
15186
+ } : message
15187
+ )
15188
+ },
15189
+ maxTokens: Math.max(1, Math.min(maxTokens, contextWindow - tokens - 16))
15190
+ };
15191
+ }
15061
15192
  async function runAgentCore(options) {
15062
15193
  const {
15063
15194
  piModel,
@@ -15127,12 +15258,15 @@ async function runAgentCore(options) {
15127
15258
  messages: toPiHistoryMessages(history, replayOptions)
15128
15259
  },
15129
15260
  getApiKey: () => apiKey,
15130
- streamFn: resolvedStreamFn,
15261
+ streamFn: (model, context, streamOptions) => {
15262
+ const fitted = fitToolResults(context, model.contextWindow, model.maxTokens);
15263
+ onConvertToLlm?.(fitted.context.messages);
15264
+ return resolvedStreamFn(model, fitted.context, { ...streamOptions, maxTokens: fitted.maxTokens });
15265
+ },
15131
15266
  convertToLlm: (messages) => {
15132
15267
  const filtered = messages.filter(
15133
15268
  (msg) => msg.role === "user" || msg.role === "assistant" || msg.role === "toolResult"
15134
15269
  );
15135
- onConvertToLlm?.(filtered);
15136
15270
  return filtered;
15137
15271
  },
15138
15272
  afterToolCall: async ({ result }) => result.isError === true ? { isError: true } : void 0,
@@ -15602,7 +15736,7 @@ var PLAN_INTENTS = [
15602
15736
  "mixed"
15603
15737
  ];
15604
15738
  var STREAM_MARKER_HOLDBACK_CHARS = Math.max("</draft>".length, "</plan>".length, "<json>".length) - 1;
15605
- function isRecord2(value) {
15739
+ function isRecord3(value) {
15606
15740
  return typeof value === "object" && value !== null && !Array.isArray(value);
15607
15741
  }
15608
15742
  function isIntent(value) {
@@ -15624,10 +15758,10 @@ function extractJsonObject2(text) {
15624
15758
  function parsePlanJson(rawText, availableTools) {
15625
15759
  try {
15626
15760
  const parsed = JSON.parse(extractJsonObject2(rawText));
15627
- if (!isRecord2(parsed)) return null;
15761
+ if (!isRecord3(parsed)) return null;
15628
15762
  const title = normalizeString(parsed.title);
15629
15763
  if (!title || !isIntent(parsed.intent) || !Array.isArray(parsed.steps)) return null;
15630
- const steps = parsed.steps.filter(isRecord2).map((step) => {
15764
+ const steps = parsed.steps.filter(isRecord3).map((step) => {
15631
15765
  const goal = normalizeString(step.goal);
15632
15766
  const evidenceNeeded = normalizeString(step.evidenceNeeded);
15633
15767
  if (!goal || !evidenceNeeded) return null;
@@ -17350,6 +17484,7 @@ function buildPiModel(config, options) {
17350
17484
  }
17351
17485
  const resolvedBaseUrl = config.provider === "openai-compatible" && (apiFormat === "openai-completions" || apiFormat === "openai-responses") ? normalizeOpenAICompatibleBaseUrl(baseUrl) : baseUrl;
17352
17486
  const { reasoning, compat, thinkingLevelMap } = inferReasoning(config.provider, modelId, modelDef);
17487
+ const requiresSystemRole = apiFormat === "openai-completions" && (config.provider.toLowerCase() === "qwen" || /\bqwen|qwq/i.test(modelId));
17353
17488
  return {
17354
17489
  id: modelId,
17355
17490
  name: modelId,
@@ -17364,7 +17499,7 @@ function buildPiModel(config, options) {
17364
17499
  contextWindow,
17365
17500
  // Reasoning and visible text share the output budget on compatible APIs.
17366
17501
  maxTokens: config.maxTokens ?? (reasoning ? 16384 : 4096),
17367
- compat
17502
+ compat: requiresSystemRole ? { ...compat, supportsDeveloperRole: false } : compat
17368
17503
  };
17369
17504
  }
17370
17505
 
@@ -17922,7 +18057,7 @@ function getMetaPath(userDataDir) {
17922
18057
  return path22.join(userDataDir, ".chatlab-meta.json");
17923
18058
  }
17924
18059
  function validateDataDirCompatibilityMeta(value, userDataDir, metaPath) {
17925
- if (!isRecord3(value)) {
18060
+ if (!isRecord4(value)) {
17926
18061
  throw createInvalidMetaError(userDataDir, metaPath, "Data directory compatibility meta must be an object.");
17927
18062
  }
17928
18063
  if (value.formatVersion !== 1) {
@@ -17933,7 +18068,7 @@ function validateDataDirCompatibilityMeta(value, userDataDir, metaPath) {
17933
18068
  const reasons = value.reasons;
17934
18069
  const updatedBy = value.updatedBy;
17935
18070
  const updatedAt = value.updatedAt;
17936
- if (!isStableSemver(minRuntimeVersion) || typeof dataCompatibilityVersion !== "number" || !Number.isInteger(dataCompatibilityVersion) || dataCompatibilityVersion < 0 || !Array.isArray(reasons) || !reasons.every(isNonEmptyString) || !isRecord3(updatedBy) || !isRuntimeKind(updatedBy.runtime) || !isNonEmptyString(updatedBy.module) || !isStableSemver(updatedBy.version) || typeof updatedAt !== "number" || !Number.isInteger(updatedAt) || updatedAt < 0) {
18071
+ if (!isStableSemver(minRuntimeVersion) || typeof dataCompatibilityVersion !== "number" || !Number.isInteger(dataCompatibilityVersion) || dataCompatibilityVersion < 0 || !Array.isArray(reasons) || !reasons.every(isNonEmptyString) || !isRecord4(updatedBy) || !isRuntimeKind(updatedBy.runtime) || !isNonEmptyString(updatedBy.module) || !isStableSemver(updatedBy.version) || typeof updatedAt !== "number" || !Number.isInteger(updatedAt) || updatedAt < 0) {
17937
18072
  throw createInvalidMetaError(userDataDir, metaPath, "Invalid data directory compatibility meta fields.");
17938
18073
  }
17939
18074
  return {
@@ -18004,7 +18139,7 @@ function writeMetaAtomic(userDataDir, metaPath, meta) {
18004
18139
  throw error;
18005
18140
  }
18006
18141
  }
18007
- function isRecord3(value) {
18142
+ function isRecord4(value) {
18008
18143
  return typeof value === "object" && value !== null && !Array.isArray(value);
18009
18144
  }
18010
18145
  function isNonEmptyString(value) {
@@ -18410,16 +18545,23 @@ function createChatTopicModelClient(config, deps = {}) {
18410
18545
  if (result.stopReason === "error" || result.stopReason === "aborted") {
18411
18546
  throw new Error(result.errorMessage || `Topic model request ${result.stopReason}`);
18412
18547
  }
18548
+ const text = result.content.filter((item) => item.type === "text").map((item) => item.text).join("");
18549
+ const outputLimit = result.stopReason === "length" ? !text.trim() && result.content.some((item) => item.type === "thinking") ? "reasoning" : "text" : void 0;
18413
18550
  return {
18414
- text: result.content.filter((item) => item.type === "text").map((item) => item.text).join(""),
18551
+ text,
18415
18552
  inputTokens: result.usage.input,
18416
- outputTokens: result.usage.output
18553
+ outputTokens: result.usage.output,
18554
+ ...outputLimit ? { outputLimit } : {}
18417
18555
  };
18418
18556
  }
18419
18557
  };
18420
18558
  }
18421
18559
  function normalizeTopicModelPayload(payload, model) {
18422
- if (!isRecord4(payload) || !isDeepSeekEndpoint(model)) return void 0;
18560
+ if (!isRecord5(payload)) return void 0;
18561
+ if (model.api === "anthropic-messages" && /\bqwen/i.test(model.id)) {
18562
+ return { ...payload, thinking: { type: "disabled" } };
18563
+ }
18564
+ if (!isDeepSeekEndpoint(model)) return void 0;
18423
18565
  const normalized = {
18424
18566
  ...payload,
18425
18567
  thinking: { type: "disabled" }
@@ -18434,7 +18576,7 @@ function normalizeTopicModelPayload(payload, model) {
18434
18576
  function isDeepSeekEndpoint(model) {
18435
18577
  return model.provider === "deepseek" || model.baseUrl.includes("deepseek.com");
18436
18578
  }
18437
- function isRecord4(value) {
18579
+ function isRecord5(value) {
18438
18580
  return typeof value === "object" && value !== null && !Array.isArray(value);
18439
18581
  }
18440
18582
 
@@ -19394,7 +19536,7 @@ function serializeTopicLedger(ledger) {
19394
19536
  }
19395
19537
  function parseTopicLedger(value) {
19396
19538
  const parsed = JSON.parse(value);
19397
- if (!isRecord5(parsed) || !Array.isArray(parsed.topics)) throw new Error("Invalid topic ledger checkpoint");
19539
+ if (!isRecord6(parsed) || !Array.isArray(parsed.topics)) throw new Error("Invalid topic ledger checkpoint");
19398
19540
  const topics = parsed.topics.map((topic) => parseLedgerItem(topic));
19399
19541
  const ledger = { topics };
19400
19542
  assertTopicLedgerSize(ledger);
@@ -19457,7 +19599,7 @@ function cloneLedger(ledger) {
19457
19599
  };
19458
19600
  }
19459
19601
  function parseLedgerItem(value) {
19460
- if (!isRecord5(value)) throw new Error("Invalid topic ledger item");
19602
+ if (!isRecord6(value)) throw new Error("Invalid topic ledger item");
19461
19603
  const id = requireString(value.id, "id");
19462
19604
  const title = requireString(value.title, "title");
19463
19605
  const summary = requireString(value.summary, "summary");
@@ -19471,7 +19613,7 @@ function parseLedgerItem(value) {
19471
19613
  return { id, title, summary, state, evidence, messageIds: deduplicateMessageIds(rawMessageIds) };
19472
19614
  }
19473
19615
  function parseEvidence(value) {
19474
- if (!isRecord5(value)) throw new Error("Invalid topic evidence");
19616
+ if (!isRecord6(value)) throw new Error("Invalid topic evidence");
19475
19617
  const messageId = Number(value.messageId);
19476
19618
  const timestamp = Number(value.timestamp);
19477
19619
  const role = value.role;
@@ -19489,7 +19631,7 @@ function requireString(value, field, maxLength = 4e3) {
19489
19631
  }
19490
19632
  return value.trim();
19491
19633
  }
19492
- function isRecord5(value) {
19634
+ function isRecord6(value) {
19493
19635
  return typeof value === "object" && value !== null && !Array.isArray(value);
19494
19636
  }
19495
19637
 
@@ -19565,7 +19707,7 @@ function parseTopicFinalizationResponse(text) {
19565
19707
  return {
19566
19708
  overview,
19567
19709
  topics: payload.topics.map((value) => {
19568
- if (!isRecord5(value)) throw new Error("Invalid final topic");
19710
+ if (!isRecord6(value)) throw new Error("Invalid final topic");
19569
19711
  return {
19570
19712
  id: requireString(value.id, "id", 200),
19571
19713
  title: requireString(value.title, "title", 200),
@@ -19576,7 +19718,7 @@ function parseTopicFinalizationResponse(text) {
19576
19718
  };
19577
19719
  }
19578
19720
  function parseOperation(value) {
19579
- if (!isRecord5(value)) throw new Error("Invalid topic operation");
19721
+ if (!isRecord6(value)) throw new Error("Invalid topic operation");
19580
19722
  const operation = value.operation ?? value.op;
19581
19723
  const evidence = parseEvidenceArray(value.evidence);
19582
19724
  if (operation === "create") {
@@ -19629,7 +19771,7 @@ function parseEvidenceArray(value) {
19629
19771
  return value.map(parseEvidence);
19630
19772
  }
19631
19773
  function parseAssignment(value) {
19632
- if (!isRecord5(value)) throw new Error("Invalid topic assignment");
19774
+ if (!isRecord6(value)) throw new Error("Invalid topic assignment");
19633
19775
  if (!Array.isArray(value.messageIds) || value.messageIds.length > 240) {
19634
19776
  throw new Error("Invalid topic assignment message ids");
19635
19777
  }
@@ -19652,7 +19794,7 @@ function parseJsonObject(text) {
19652
19794
  const end = unfenced.lastIndexOf("}");
19653
19795
  if (start < 0 || end < start) throw new Error("Model did not return a JSON object");
19654
19796
  const parsed = JSON.parse(unfenced.slice(start, end + 1));
19655
- if (!isRecord5(parsed)) throw new Error("Model response must be a JSON object");
19797
+ if (!isRecord6(parsed)) throw new Error("Model response must be a JSON object");
19656
19798
  return parsed;
19657
19799
  }
19658
19800
  function formatLedgerForModel(ledger) {
@@ -20292,6 +20434,12 @@ Your previous response was invalid: ${validationErrorMessage(lastValidationError
20292
20434
  };
20293
20435
  const response = await modelClient.complete(attemptPrompts, { signal, sessionId });
20294
20436
  run = recordModelUsage(run, response);
20437
+ if (response.outputLimit) {
20438
+ const t2 = createAiTranslate(run.locale ?? void 0);
20439
+ throw new Error(
20440
+ t2(response.outputLimit === "reasoning" ? "ai.topics.reasoningLimitReached" : "ai.topics.outputLimitReached")
20441
+ );
20442
+ }
20295
20443
  try {
20296
20444
  return { run, value: validate(response.text) };
20297
20445
  } catch (error) {
@@ -21117,6 +21265,8 @@ export {
21117
21265
  BUILTIN_MODELS,
21118
21266
  getBuiltinModelsByProvider,
21119
21267
  stripAvatarFields,
21268
+ extractToolResultText,
21269
+ truncateToolResultText,
21120
21270
  generateMessageKey,
21121
21271
  writeParseResultToDb,
21122
21272
  getCollidingPlatformIds,
@@ -21297,4 +21447,4 @@ export {
21297
21447
  StaticPathProvider,
21298
21448
  createDatabaseManagerAdapter
21299
21449
  };
21300
- //# sourceMappingURL=chunk-HBAQPF6X.mjs.map
21450
+ //# sourceMappingURL=chunk-NKSPJN6X.mjs.map