chatlab-cli 0.37.2 → 0.37.3

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 (146) hide show
  1. package/dist/{chat-command-G2EX7VHR.mjs → chat-command-RQC44FPF.mjs} +37 -9
  2. package/dist/chat-command-RQC44FPF.mjs.map +1 -0
  3. package/dist/{chunk-YI3EQYEG.mjs → chunk-4FAEB4C2.mjs} +12 -12
  4. package/dist/{chunk-HMVM7VCA.mjs → chunk-5OA4QI3Q.mjs} +3 -3
  5. package/dist/{chunk-EK5QIJLZ.mjs → chunk-E2ZFGNZQ.mjs} +11 -11
  6. package/dist/{chunk-F4HVCFZL.mjs → chunk-E6IRRNBQ.mjs} +3 -3
  7. package/dist/{chunk-FCUUAGGC.mjs → chunk-GDKQKHJT.mjs} +2 -2
  8. package/dist/{chunk-H46CLFWK.mjs → chunk-HJWBFHNR.mjs} +4 -4
  9. package/dist/{chunk-L6RJIVLS.mjs → chunk-IDDTW5JN.mjs} +313 -24
  10. package/dist/chunk-IDDTW5JN.mjs.map +1 -0
  11. package/dist/{chunk-E6LCCPIB.mjs → chunk-IMJVOODY.mjs} +2 -2
  12. package/dist/{chunk-T5H56AZV.mjs → chunk-LUENE6L7.mjs} +13 -11
  13. package/dist/chunk-LUENE6L7.mjs.map +1 -0
  14. package/dist/{chunk-XQ6Z2KNN.mjs → chunk-O57SQSCO.mjs} +2 -2
  15. package/dist/{chunk-EFX66A2O.mjs → chunk-ZGXXAPLX.mjs} +2 -2
  16. package/dist/{chunk-HBAQPF6X.mjs → chunk-ZOHSWBD2.mjs} +104 -55
  17. package/dist/chunk-ZOHSWBD2.mjs.map +1 -0
  18. package/dist/cli.mjs +9 -9
  19. package/dist/contacts-worker.mjs +2 -2
  20. package/dist/global-insight-worker.mjs +1 -1
  21. package/dist/{http-5BRVWAJR.mjs → http-QJDZKDNJ.mjs} +12 -12
  22. package/dist/{import-IAECQDKC.mjs → import-XK6YM26A.mjs} +7 -7
  23. package/dist/index.mjs +12 -12
  24. package/dist/{mcp-XXSQJBGU.mjs → mcp-DMGZFSYN.mjs} +24 -17
  25. package/dist/mcp-DMGZFSYN.mjs.map +1 -0
  26. package/dist/people-relationships-worker.mjs +2 -2
  27. package/dist/semantic-index-worker.mjs +1 -1
  28. package/dist/{src-4HLKMQ7S.mjs → src-4AHJUFCW.mjs} +6 -6
  29. package/dist/{stream-import-PUG42I36.mjs → stream-import-7VQVT5ST.mjs} +7 -7
  30. package/dist/{worker-runtime-X5563TVT.mjs → worker-runtime-PQBAV75N.mjs} +5 -5
  31. package/dist-cli-web/assets/{AISettingsTab-m_r2fFEj.js → AISettingsTab-qS3XKnvh.js} +1 -1
  32. package/dist-cli-web/assets/{AboutTab-J65UqIuk.js → AboutTab-K-i40dPv.js} +1 -1
  33. package/dist-cli-web/assets/{Alert-qBIGn_CW.js → Alert-GSvA5B7J.js} +1 -1
  34. package/dist-cli-web/assets/{ApiSettingsTab-CxWRJI9j.js → ApiSettingsTab-DIVGTR3g.js} +1 -1
  35. package/dist-cli-web/assets/{BatchManageTab-BINNVwm1.js → BatchManageTab-CJhwvYWV.js} +1 -1
  36. package/dist-cli-web/assets/{BufferResource-C-jLPrHv.js → BufferResource-Cjm0m7sF.js} +1 -1
  37. package/dist-cli-web/assets/{CanvasRenderer-kDLW8GSt.js → CanvasRenderer-C-fmrahh.js} +1 -1
  38. package/dist-cli-web/assets/{CardDecoration-CnYxleQM.js → CardDecoration-Cz54ZPyh.js} +1 -1
  39. package/dist-cli-web/assets/{ChatRecordDrawer-CMg3FEWH.js → ChatRecordDrawer-Cst8zTUv.js} +1 -1
  40. package/dist-cli-web/assets/{ChatRecordWorkspace-AfFIMUbZ.js → ChatRecordWorkspace-DKVKaimw.js} +1 -1
  41. package/dist-cli-web/assets/{Checkbox-D-hAv15R.js → Checkbox-CrlY3jiJ.js} +1 -1
  42. package/dist-cli-web/assets/{DataDirCleanupNotice-P80h2p4l.js → DataDirCleanupNotice-Cjqiub4e.js} +1 -1
  43. package/dist-cli-web/assets/{DatePicker.vue_vue_type_script_setup_true_lang-CSp691Uv.js → DatePicker.vue_vue_type_script_setup_true_lang-BYY2UmPA.js} +1 -1
  44. package/dist-cli-web/assets/{DebugToolsPanel-BK2VbKB0.js → DebugToolsPanel-I00RV_Lr.js} +1 -1
  45. package/dist-cli-web/assets/{EChart.vue_vue_type_script_setup_true_lang-BcE0mE_N.js → EChart.vue_vue_type_script_setup_true_lang-CRTZh9kh.js} +1 -1
  46. package/dist-cli-web/assets/{EChartBar.vue_vue_type_script_setup_true_lang-BypaV5wc.js → EChartBar.vue_vue_type_script_setup_true_lang-DjDFhnN9.js} +1 -1
  47. package/dist-cli-web/assets/{EChartLine.vue_vue_type_script_setup_true_lang-D8SyOfWC.js → EChartLine.vue_vue_type_script_setup_true_lang-BLqlW9E4.js} +1 -1
  48. package/dist-cli-web/assets/{EChartWordcloud-0rihhg03.js → EChartWordcloud-ChKJM8bU.js} +1 -1
  49. package/dist-cli-web/assets/{FileDropZone.vue_vue_type_script_setup_true_lang-Dyuzh7Ex.js → FileDropZone.vue_vue_type_script_setup_true_lang-CsRmQhVQ.js} +1 -1
  50. package/dist-cli-web/assets/{Filter-rD_jWpbO.js → Filter-Duzxgudo.js} +1 -1
  51. package/dist-cli-web/assets/{GlobalTaskBar-sXQuGvF-.js → GlobalTaskBar-DL0IJxlt.js} +1 -1
  52. package/dist-cli-web/assets/{GroupRelationshipGalaxyView-BN1L9DFf.js → GroupRelationshipGalaxyView-BZrB2o2g.js} +1 -1
  53. package/dist-cli-web/assets/{Label-Ce4wl_Ph.js → Label-CaVKlQnJ.js} +1 -1
  54. package/dist-cli-web/assets/{LoadingState.vue_vue_type_script_setup_true_lang-DmVfwvnD.js → LoadingState.vue_vue_type_script_setup_true_lang-uF54r-dT.js} +1 -1
  55. package/dist-cli-web/assets/{MessageExportModal-C2IUNPhg.js → MessageExportModal-JpurBsUW.js} +1 -1
  56. package/dist-cli-web/assets/{PageHeader-D5BcYKBs.js → PageHeader-BciykZ_-.js} +1 -1
  57. package/dist-cli-web/assets/{PageTabs.vue_vue_type_script_setup_true_lang-DHly2-fe.js → PageTabs.vue_vue_type_script_setup_true_lang-2Xe2iUFO.js} +1 -1
  58. package/dist-cli-web/assets/{RelationshipGalaxyCanvas-CHPqtqQz.js → RelationshipGalaxyCanvas-BO5-MowG.js} +3 -3
  59. package/dist-cli-web/assets/{RelationshipGalaxyThreeCanvas-qR4S-9n7.js → RelationshipGalaxyThreeCanvas-Dp4CcWU5.js} +1 -1
  60. package/dist-cli-web/assets/{RenderTargetSystem-BaIFulUj.js → RenderTargetSystem-CfuoUG_y.js} +1 -1
  61. package/dist-cli-web/assets/{RovingFocusItem-Bqgmzo42.js → RovingFocusItem-FpYwYEP_.js} +1 -1
  62. package/dist-cli-web/assets/{ScreenCaptureModal-sJqB_hrK.js → ScreenCaptureModal-cElYPaSj.js} +1 -1
  63. package/dist-cli-web/assets/{SectionTabs.vue_vue_type_script_setup_true_lang-BPt98e6z.js → SectionTabs.vue_vue_type_script_setup_true_lang-pVQMbTsj.js} +1 -1
  64. package/dist-cli-web/assets/{Select-BAnN4HMs.js → Select-H8Fz6RkU.js} +1 -1
  65. package/dist-cli-web/assets/{SettingsModal-C4ANMlJJ.js → SettingsModal-52Fw4fVW.js} +2 -2
  66. package/dist-cli-web/assets/{StorageTab-BgNQliz4.js → StorageTab-BnugE5BO.js} +1 -1
  67. package/dist-cli-web/assets/{Switch-DddEvDJa.js → Switch-K4aqYC4Y.js} +1 -1
  68. package/dist-cli-web/assets/{Tabs-DwjL-ueH.js → Tabs-BXjD45rO.js} +1 -1
  69. package/dist-cli-web/assets/{Tabs-xVtuBuO0.js → Tabs-DJ5p8gb6.js} +1 -1
  70. package/dist-cli-web/assets/{ThemeCard.vue_vue_type_script_setup_true_lang-CNCVa86b.js → ThemeCard.vue_vue_type_script_setup_true_lang-BLmTpx4f.js} +1 -1
  71. package/dist-cli-web/assets/{TimeSelect.vue_vue_type_script_setup_true_lang-BehUIWki.js → TimeSelect.vue_vue_type_script_setup_true_lang-geQAlopO.js} +1 -1
  72. package/dist-cli-web/assets/{VisuallyHiddenInput-ST6JNfSG.js → VisuallyHiddenInput-J2KEIQBX.js} +1 -1
  73. package/dist-cli-web/assets/{WebGLRenderer-DRraqD4Y.js → WebGLRenderer-BDFzRniS.js} +1 -1
  74. package/dist-cli-web/assets/{WebGPURenderer-CnzaYARg.js → WebGPURenderer-BKYZyUCZ.js} +1 -1
  75. package/dist-cli-web/assets/{aiChat-CeJy-gG-.js → aiChat-CdJzpNYW.js} +3 -3
  76. package/dist-cli-web/assets/{base-BHbtUviQ.js → base-129JztT1.js} +1 -1
  77. package/dist-cli-web/assets/{browserAll-DYxkitnx.js → browserAll-CZNZDK1i.js} +1 -1
  78. package/dist-cli-web/assets/{chatMessages-Dj1u-tFB.js → chatMessages-zmzHCUCy.js} +3 -3
  79. package/dist-cli-web/assets/{cli-web-BtH8nfjA.js → cli-web-_WGCg-ZY.js} +1 -1
  80. package/dist-cli-web/assets/{fetch-DNmRaRxX.js → fetch-B7Tdp7Uo.js} +1 -1
  81. package/dist-cli-web/assets/{fetch-JEEBqR_7.js → fetch-BBdyPNj3.js} +1 -1
  82. package/dist-cli-web/assets/{fetch-DogRrvT6.js → fetch-Bafz8jLM.js} +1 -1
  83. package/dist-cli-web/assets/{fetch-T5Gi1TUZ.js → fetch-C4W6tD-D.js} +1 -1
  84. package/dist-cli-web/assets/{fetch-C1Tm66i9.js → fetch-DOsmgros.js} +1 -1
  85. package/dist-cli-web/assets/{fetch-emZXHmoE.js → fetch-DTPDtL38.js} +1 -1
  86. package/dist-cli-web/assets/{fetch-ejEMWPM2.js → fetch-DaeoNUip.js} +1 -1
  87. package/dist-cli-web/assets/{fetch-CGnWNSsG.js → fetch-DgHdAlO7.js} +1 -1
  88. package/dist-cli-web/assets/{fetch-D7hfFyoG.js → fetch-Di4QpfqL.js} +1 -1
  89. package/dist-cli-web/assets/{fetch-CAEyoWQA.js → fetch-Dw33HaVP.js} +11 -13
  90. package/dist-cli-web/assets/{fetch-BJ82mWvv.js → fetch-IP6i-mtr.js} +1 -1
  91. package/dist-cli-web/assets/{fetch-U9QyidNZ.js → fetch-sbr95ipd.js} +1 -1
  92. package/dist-cli-web/assets/{host-BUvwCvZR.js → host-CMnAiJSx.js} +1 -1
  93. package/dist-cli-web/assets/{host-VTWF81F5.js → host-CuuNLUWx.js} +1 -1
  94. package/dist-cli-web/assets/{index-B3MCGDwx.js → index-BBYtZa7g.js} +1 -1
  95. package/dist-cli-web/assets/{index-DZK9Njvy.js → index-BOXh7X5Y.js} +1 -1
  96. package/dist-cli-web/assets/{index-KpnLSzzX.js → index-BepItDCQ.js} +4 -4
  97. package/dist-cli-web/assets/{index-HjrJ3DXO.js → index-BmGA3geF.js} +1 -1
  98. package/dist-cli-web/assets/{index-CVRBBnQw.js → index-C-u3l4Uh.js} +1 -1
  99. package/dist-cli-web/assets/{index-iEQnKg2R.js → index-CN9WMxb3.js} +2 -2
  100. package/dist-cli-web/assets/{index-DUBl6aBF.js → index-Chh0gCp7.js} +1 -1
  101. package/dist-cli-web/assets/index-DRFMz0cs.css +1 -0
  102. package/dist-cli-web/assets/{index-C75W1B5J.css → index-DbP9vQhR.css} +1 -1
  103. package/dist-cli-web/assets/{index-BI2Rb_L3.js → index-DgCXdbsG.js} +2 -2
  104. package/dist-cli-web/assets/{index-DQFcmWSa.js → index-DhRaZS6z.js} +1 -1
  105. package/dist-cli-web/assets/{index-DDt7Tfda.js → index-Dz4yfeg6.js} +1 -1
  106. package/dist-cli-web/assets/{index-BLYSew5C.js → index-EtteazuD.js} +1 -1
  107. package/dist-cli-web/assets/index-GNMlsoVH.js +137 -0
  108. package/dist-cli-web/assets/{index-D9C3dyV8.js → index-bQ9oj54q.js} +3 -3
  109. package/dist-cli-web/assets/{index-e6fOnhNS.js → index-fsLAooCi.js} +1 -1
  110. package/dist-cli-web/assets/{people-page-header-DWXwFJ8M.js → people-page-header-CKXRSnpl.js} +1 -1
  111. package/dist-cli-web/assets/{prompt-Cepfb-5-.js → prompt-DNxAd1Bj.js} +1 -1
  112. package/dist-cli-web/assets/{semantic-index-config-builder-hTY6QyCe.js → semantic-index-config-builder-CQ27G4TK.js} +1 -1
  113. package/dist-cli-web/assets/{service-DwCmXFtI.js → service-BwbGKwDn.js} +1 -1
  114. package/dist-cli-web/assets/service-DQjyjQZx.js +1 -0
  115. package/dist-cli-web/assets/service-Dtve_40X.js +1 -0
  116. package/dist-cli-web/assets/useFormControl-CNmp_2bd.js +1 -0
  117. package/dist-cli-web/assets/{useInsightTabAnalytics-CplGbsbe.js → useInsightTabAnalytics-DaU_ADbQ.js} +4 -4
  118. package/dist-cli-web/assets/{useTable-Dmpbk7fZ.js → useTable-BYXxnZMd.js} +1 -1
  119. package/dist-cli-web/assets/{useToast-Bmgpd3sl.js → useToast-DPkgv34s.js} +1 -1
  120. package/dist-cli-web/assets/{webworkerAll-DkPWEyVL.js → webworkerAll-Um4PrCaA.js} +1 -1
  121. package/dist-cli-web/index.html +1 -1
  122. package/package.json +1 -1
  123. package/dist/chat-command-G2EX7VHR.mjs.map +0 -1
  124. package/dist/chunk-HBAQPF6X.mjs.map +0 -1
  125. package/dist/chunk-L6RJIVLS.mjs.map +0 -1
  126. package/dist/chunk-T5H56AZV.mjs.map +0 -1
  127. package/dist/mcp-XXSQJBGU.mjs.map +0 -1
  128. package/dist-cli-web/assets/index-Bs7gk1gf.css +0 -1
  129. package/dist-cli-web/assets/index-Cza8BzZE.js +0 -137
  130. package/dist-cli-web/assets/service-BjE0YJaM.js +0 -1
  131. package/dist-cli-web/assets/service-DQxttlJp.js +0 -1
  132. package/dist-cli-web/assets/useFormControl-CJyJY8AK.js +0 -1
  133. /package/dist/{chunk-YI3EQYEG.mjs.map → chunk-4FAEB4C2.mjs.map} +0 -0
  134. /package/dist/{chunk-HMVM7VCA.mjs.map → chunk-5OA4QI3Q.mjs.map} +0 -0
  135. /package/dist/{chunk-EK5QIJLZ.mjs.map → chunk-E2ZFGNZQ.mjs.map} +0 -0
  136. /package/dist/{chunk-F4HVCFZL.mjs.map → chunk-E6IRRNBQ.mjs.map} +0 -0
  137. /package/dist/{chunk-FCUUAGGC.mjs.map → chunk-GDKQKHJT.mjs.map} +0 -0
  138. /package/dist/{chunk-H46CLFWK.mjs.map → chunk-HJWBFHNR.mjs.map} +0 -0
  139. /package/dist/{chunk-E6LCCPIB.mjs.map → chunk-IMJVOODY.mjs.map} +0 -0
  140. /package/dist/{chunk-XQ6Z2KNN.mjs.map → chunk-O57SQSCO.mjs.map} +0 -0
  141. /package/dist/{chunk-EFX66A2O.mjs.map → chunk-ZGXXAPLX.mjs.map} +0 -0
  142. /package/dist/{http-5BRVWAJR.mjs.map → http-QJDZKDNJ.mjs.map} +0 -0
  143. /package/dist/{import-IAECQDKC.mjs.map → import-XK6YM26A.mjs.map} +0 -0
  144. /package/dist/{src-4HLKMQ7S.mjs.map → src-4AHJUFCW.mjs.map} +0 -0
  145. /package/dist/{stream-import-PUG42I36.mjs.map → stream-import-7VQVT5ST.mjs.map} +0 -0
  146. /package/dist/{worker-runtime-X5563TVT.mjs.map → worker-runtime-PQBAV75N.mjs.map} +0 -0
@@ -21,7 +21,7 @@ import {
21
21
  resolveOwnerMember,
22
22
  setCache,
23
23
  shouldScopeContactToSession
24
- } from "./chunk-HBAQPF6X.mjs";
24
+ } from "./chunk-ZOHSWBD2.mjs";
25
25
 
26
26
  // ../../packages/node-runtime/src/services/people/relationships/facts-cache.ts
27
27
  var PEOPLE_RELATIONSHIPS_FACTS_FORMAT_VERSION = 3;
@@ -1329,4 +1329,4 @@ export {
1329
1329
  compareNodes,
1330
1330
  compareEdges
1331
1331
  };
1332
- //# sourceMappingURL=chunk-E6LCCPIB.mjs.map
1332
+ //# sourceMappingURL=chunk-IMJVOODY.mjs.map
@@ -10,13 +10,14 @@ import {
10
10
  SEMANTIC_SEARCH_TOOL_NAME,
11
11
  createCrossChatAgentToolAdapters,
12
12
  executeToolForAgent,
13
+ getLocalizedToolMetadata,
13
14
  toAgentToolParameters
14
- } from "./chunk-L6RJIVLS.mjs";
15
+ } from "./chunk-IDDTW5JN.mjs";
15
16
  import {
16
17
  preprocessCrossChatLabel,
17
18
  preprocessCrossChatMessages,
18
19
  preprocessCrossChatSummaries
19
- } from "./chunk-H46CLFWK.mjs";
20
+ } from "./chunk-HJWBFHNR.mjs";
20
21
  import {
21
22
  AgentEventHandler,
22
23
  AiLogger,
@@ -63,7 +64,7 @@ import {
63
64
  runCrossChatAgent,
64
65
  shouldUseChartCapabilityForMessage,
65
66
  wrapWithChartSchemaGate
66
- } from "./chunk-HBAQPF6X.mjs";
67
+ } from "./chunk-ZOHSWBD2.mjs";
67
68
 
68
69
  // src/ai/logger.ts
69
70
  var logger = null;
@@ -158,13 +159,14 @@ var TOOL_TRUNCATION_STRATEGY = {
158
159
  function adaptToolsForAgent(tools, getContext, options) {
159
160
  const tokenBudget = options?.maxToolResultTokens ?? DEFAULT_MAX_TOOL_RESULT_TOKENS;
160
161
  const chartSchemaGateState = createChartSchemaGateState();
161
- return tools.map(
162
- (tool) => wrapWithChartSchemaGate(
162
+ return tools.map((tool) => {
163
+ const localized = getLocalizedToolMetadata(tool, options?.locale);
164
+ return wrapWithChartSchemaGate(
163
165
  {
164
166
  name: tool.name,
165
167
  label: tool.name,
166
- description: tool.description,
167
- parameters: toAgentToolParameters(tool.inputSchema),
168
+ description: localized.description,
169
+ parameters: toAgentToolParameters(localized.inputSchema),
168
170
  executionMode: tool.executionMode,
169
171
  async execute(_toolCallId, params, signal, onUpdate) {
170
172
  const ctx = getContext();
@@ -211,8 +213,8 @@ function adaptToolsForAgent(tools, getContext, options) {
211
213
  }
212
214
  },
213
215
  chartSchemaGateState
214
- )
215
- );
216
+ );
217
+ });
216
218
  }
217
219
 
218
220
  // src/ai/assistant-loader.ts
@@ -600,7 +602,7 @@ function createCliRunAgentStream(dbManager, aiChatManager, options = {}) {
600
602
  timeFilter: params.timeFilter,
601
603
  maxMessagesLimit: params.maxMessagesLimit
602
604
  }),
603
- { maxToolResultTokens }
605
+ { maxToolResultTokens, locale }
604
606
  ) : [];
605
607
  if (canSemanticSearch) {
606
608
  assistantSystemPrompt = [assistantSystemPrompt, buildSemanticSearchGuidance(locale)].filter(Boolean).join("\n\n");
@@ -669,4 +671,4 @@ export {
669
671
  getSkillManagerCore,
670
672
  createCliRunAgentStream
671
673
  };
672
- //# sourceMappingURL=chunk-T5H56AZV.mjs.map
674
+ //# sourceMappingURL=chunk-LUENE6L7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ai/logger.ts","../src/ai/manager-factory.ts","../src/ai/tool-adapter.ts","../src/ai/assistant-loader.ts","../src/ai/agent.ts","../src/ai/cross-chat-tool-adapter.ts","../src/ai/agent-stream-runner.ts"],"sourcesContent":["/**\n * Server 端 AI 日志\n *\n * 复用 @openchatlab/node-runtime 的 AiLogger,\n * 在 startHttpServer() 中通过 initServerAiLogger() 初始化。\n */\n\nimport { AiLogger } from '@openchatlab/node-runtime'\n\nlet logger: AiLogger | null = null\n\nexport function initServerAiLogger(logsDir: string): AiLogger {\n if (!logger) {\n logger = new AiLogger(logsDir)\n }\n return logger\n}\n\nexport function getServerAiLogger(): AiLogger | null {\n return logger\n}\n\nexport function closeServerAiLogger(): void {\n if (logger) {\n logger.close()\n logger = null\n }\n}\n","/**\n * Factory functions for creating AssistantManager and SkillManagerCore instances.\n *\n * Server-side equivalent of the Electron adapter in electron/main/ai/assistant/manager.ts.\n * Uses Node.js fs directly (no Electron dependency).\n */\n\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { createHash, randomUUID } from 'crypto'\nimport {\n appLogger,\n AssistantManager,\n DEFAULT_GENERAL_ASSISTANT_RAW_CONFIGS,\n LEGACY_GENERAL_ASSISTANT_DIGESTS,\n SkillManagerCore,\n type AssistantManagerFs,\n type SkillManagerFs,\n} from '@openchatlab/node-runtime'\n\nconst nodeFs: AssistantManagerFs & SkillManagerFs = {\n ensureDir(dir: string) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })\n },\n listFiles(dir: string, ext: string) {\n if (!fs.existsSync(dir)) return []\n return fs.readdirSync(dir).filter((f) => f.endsWith(ext))\n },\n readFile(filePath: string) {\n return fs.readFileSync(filePath, 'utf-8')\n },\n writeFile(filePath: string, content: string) {\n fs.writeFileSync(filePath, content, 'utf-8')\n },\n deleteFile(filePath: string) {\n if (fs.existsSync(filePath)) fs.unlinkSync(filePath)\n },\n fileExists(filePath: string) {\n return fs.existsSync(filePath)\n },\n joinPath(...parts: string[]) {\n return path.join(...parts)\n },\n}\n\nconst managerCache = new Map<string, { assistant: AssistantManager; skill: SkillManagerCore }>()\n\nexport function getAssistantManager(aiDataDir: string): AssistantManager {\n let cached = managerCache.get(aiDataDir)\n if (!cached) {\n cached = {\n assistant: new AssistantManager({\n fs: nodeFs,\n assistantsDir: path.join(aiDataDir, 'assistants'),\n builtinRawConfigs: DEFAULT_GENERAL_ASSISTANT_RAW_CONFIGS,\n contentHash: (content: string) => createHash('sha256').update(content).digest('hex'),\n legacyBuiltinDigests: LEGACY_GENERAL_ASSISTANT_DIGESTS,\n generateId: () => `custom_${randomUUID().replace(/-/g, '').slice(0, 12)}`,\n logger: appLogger,\n }),\n skill: new SkillManagerCore({\n fs: nodeFs,\n skillsDir: path.join(aiDataDir, 'skills'),\n builtinRawSkills: [],\n contentHash: (content: string) => createHash('md5').update(content).digest('hex'),\n }),\n }\n managerCache.set(aiDataDir, cached)\n }\n return cached.assistant\n}\n\nexport function getSkillManagerCore(aiDataDir: string): SkillManagerCore {\n let cached = managerCache.get(aiDataDir)\n if (!cached) {\n getAssistantManager(aiDataDir)\n cached = managerCache.get(aiDataDir)!\n }\n return cached.skill\n}\n","/**\n * 工具适配层\n *\n * 将 @openchatlab/tools 的 ToolDefinition 适配为 @earendil-works/pi-agent-core 的 AgentTool 格式。\n * 消息类工具返回 rawMessages 时自动执行预处理管道(清洗、去噪、脱敏、截断、格式化)。\n */\n\nimport type {\n ToolDefinition,\n ToolExecutionContext,\n SemanticSearchToolService,\n RawMessage,\n ToolTimeRange,\n} from '@openchatlab/tools'\nimport {\n CoreDataProvider,\n executeToolForAgent,\n getLocalizedToolMetadata,\n toAgentToolParameters,\n} from '@openchatlab/tools'\nimport type { DatabaseAdapter } from '@openchatlab/core'\nimport {\n applyPreprocessingPipeline,\n batchSegmentWithFrequency,\n preprocessMessages,\n type AgentTool,\n type PreprocessableMessage,\n type PreprocessConfig,\n type TruncationStrategy,\n createChartSchemaGateState,\n wrapWithChartSchemaGate,\n} from '@openchatlab/node-runtime'\nimport { getServerAiLogger } from './logger'\n\nconst DEFAULT_MAX_TOOL_RESULT_TOKENS = 8000\n\nconst TOOL_TRUNCATION_STRATEGY: Record<string, TruncationStrategy> = {\n search_messages: 'keep_first',\n deep_search_messages: 'keep_first',\n get_recent_messages: 'keep_last',\n get_message_context: 'keep_last',\n get_segment_messages: 'keep_last',\n get_conversation_between: 'keep_last',\n}\n\nexport interface ServerToolContext {\n db: DatabaseAdapter\n sessionId: string\n locale?: string\n /** 语义检索窄接口(仅当前会话可检索时由 runner 注入) */\n semanticIndexService?: SemanticSearchToolService\n /** 预处理配置(脱敏/匿名化/清洗) */\n preprocessConfig?: Record<string, unknown>\n /** 当前用户平台 id(昵称匿名化 owner 识别) */\n ownerPlatformId?: string\n /** 会话时间范围筛选(来自请求参数,供证据类工具继承) */\n timeFilter?: ToolTimeRange\n /** 关键词搜索消息条数上限 */\n maxMessagesLimit?: number\n}\n\nexport interface AdaptToolsOptions {\n maxToolResultTokens?: number\n /** Request locale; decides whether the LLM sees Chinese or English tool descriptions. */\n locale?: string\n}\n\nexport function adaptToolsForAgent(\n tools: ToolDefinition[],\n getContext: () => ServerToolContext,\n options?: AdaptToolsOptions\n): AgentTool<any, any>[] {\n const tokenBudget = options?.maxToolResultTokens ?? DEFAULT_MAX_TOOL_RESULT_TOKENS\n const chartSchemaGateState = createChartSchemaGateState()\n\n return tools.map((tool) => {\n const localized = getLocalizedToolMetadata(tool, options?.locale)\n return wrapWithChartSchemaGate(\n {\n name: tool.name,\n label: tool.name,\n description: localized.description,\n parameters: toAgentToolParameters(localized.inputSchema) as any,\n executionMode: tool.executionMode,\n async execute(_toolCallId: string, params: unknown, signal, onUpdate) {\n const ctx = getContext()\n const execCtx: ToolExecutionContext = {\n db: ctx.db,\n dataProvider: new CoreDataProvider(ctx.db),\n sessionId: ctx.sessionId,\n locale: ctx.locale,\n abortSignal: signal,\n reportProgress: (progress) => onUpdate?.({ content: [], details: { progress } }),\n semanticIndexService: ctx.semanticIndexService,\n preprocessConfig: ctx.preprocessConfig,\n ownerPlatformId: ctx.ownerPlatformId,\n timeFilter: ctx.timeFilter,\n maxMessagesLimit: ctx.maxMessagesLimit,\n maxToolResultTokens: tokenBudget,\n segmentText: (texts, locale, options) => batchSegmentWithFrequency(texts, locale as any, options as any),\n desensitizeMessages: (messages: RawMessage[]): RawMessage[] =>\n preprocessMessages(\n messages as PreprocessableMessage[],\n ctx.preprocessConfig as PreprocessConfig | undefined\n ) as RawMessage[],\n }\n const result = await executeToolForAgent(tool, params, execCtx)\n const details = result.details as Record<string, unknown> | null\n if (!Array.isArray(details?.rawMessages)) return result\n\n const { rawMessages, chart, charts, ...extraDetails } = details\n const preprocessCfg = ctx.preprocessConfig as PreprocessConfig | undefined\n const pipelineResult = applyPreprocessingPipeline({\n rawMessages: rawMessages as PreprocessableMessage[],\n preprocessConfig: preprocessCfg,\n anonymizeNames: preprocessCfg?.anonymizeNames ?? false,\n ownerPlatformId: ctx.ownerPlatformId,\n locale: ctx.locale,\n maxToolResultTokens: tokenBudget,\n truncationStrategy: TOOL_TRUNCATION_STRATEGY[tool.name] ?? 'keep_last',\n extraDetails,\n logger: getServerAiLogger() ?? undefined,\n })\n const chartDetails = { ...(chart ? { chart } : {}), ...(charts ? { charts } : {}) }\n return {\n content: [{ type: 'text', text: pipelineResult.text }],\n details: Object.keys(chartDetails).length > 0 ? chartDetails : null,\n }\n },\n },\n chartSchemaGateState\n )\n })\n}\n","/**\n * 助手配置加载器\n *\n * 通过共享 AssistantManager 加载配置,确保 standalone CLI 在首次使用时\n * 也会创建默认助手,而不是绕过初始化直接读取磁盘。\n */\n\nimport type { AssistantConfig } from '@openchatlab/node-runtime'\nimport { getAssistantManager } from './manager-factory'\n\nexport function loadAssistantConfig(aiDataDir: string, assistantId: string): AssistantConfig | null {\n return getAssistantManager(aiDataDir).getAssistantConfig(assistantId)\n}\n","/**\n * 服务端 Agent\n *\n * 使用 @openchatlab/node-runtime 的 runAgentCore 编排对话流程,\n * 通过 AgentEventHandler 输出与 Electron 端一致的流式事件。\n */\n\nimport {\n DEFAULT_MAX_TOOL_ROUNDS,\n DEFAULT_CONTEXT_COMPRESSION_CONFIG,\n buildPiModel,\n buildPlanGuidance,\n createAnalysisPlanner,\n createLlmRouteDecider,\n createPlanContentBlock,\n decideRequestRoute,\n runAgentCore,\n checkAndCompress,\n buildSystemPrompt,\n createAiTranslate,\n createCompressionLlmAdapter,\n AgentEventHandler,\n formatAIError,\n shouldUseChartCapabilityForMessage,\n getChartPlannerCapabilityForMessage,\n initTokenizer,\n type AgentStreamChunk,\n type PiMessage,\n type SimpleHistoryMessage,\n type AIChatManager,\n type AgentTool,\n type DataSnapshot,\n type AIServiceConfig,\n type OwnerInfo,\n type MentionedMember,\n} from '@openchatlab/node-runtime'\nimport type { ChartAutoMode } from '@openchatlab/shared-types'\n\nimport { getServerAiLogger } from './logger'\n\nexport type { AgentStreamChunk }\n\nexport interface RunAgentOptions {\n userMessage: string\n aiChatId: string\n historyLeafMessageId?: string | null\n chatType?: 'group' | 'private'\n locale?: string\n assistantSystemPrompt?: string\n skillMenu?: string | null\n skillDef?: { name: string; prompt: string }\n tools?: AgentTool[]\n llmConfig: AIServiceConfig | null\n aiChatManager: AIChatManager\n onEvent: (event: AgentStreamChunk) => void\n abortSignal?: AbortSignal\n ownerInfo?: OwnerInfo\n mentionedMembers?: MentionedMember[]\n dataSnapshot?: DataSnapshot\n thinkingLevel?: string\n chartAutoMode?: ChartAutoMode\n}\n\nexport async function runServerAgent(options: RunAgentOptions): Promise<void> {\n const {\n userMessage,\n aiChatId,\n historyLeafMessageId,\n chatType = 'group',\n locale = 'zh-CN',\n assistantSystemPrompt,\n skillMenu,\n skillDef,\n tools = [],\n llmConfig,\n aiChatManager,\n onEvent,\n abortSignal,\n ownerInfo,\n mentionedMembers,\n dataSnapshot,\n thinkingLevel,\n chartAutoMode = 'suggest',\n } = options\n\n const aiLogger = getServerAiLogger()\n\n // 确保 tokenizer rank 表已加载(compression + agent 路径均依赖)\n await initTokenizer()\n\n if (!llmConfig) {\n onEvent({ type: 'error', error: { name: 'ConfigError', message: 'LLM service not configured' } })\n onEvent({ type: 'done', isFinished: true })\n return\n }\n\n const piModel = buildPiModel(llmConfig)\n const t = createAiTranslate(locale)\n\n let skillCtx: { skillDef?: { name: string; prompt: string }; skillMenu?: string } | undefined\n if (skillDef) {\n skillCtx = { skillDef }\n } else if (skillMenu) {\n skillCtx = { skillMenu }\n }\n\n const systemPrompt = buildSystemPrompt({\n t,\n chatType,\n assistantSystemPrompt,\n ownerInfo,\n locale,\n skillCtx,\n mentionedMembers,\n dataSnapshot,\n })\n\n const handler = new AgentEventHandler({\n onChunk: onEvent,\n context: {},\n systemPrompt,\n })\n\n if (historyLeafMessageId === undefined) {\n const llmAdapter = createCompressionLlmAdapter({\n piModel,\n apiKey: llmConfig.apiKey,\n onCompressing: () => handler.emitStatus('compressing', []),\n })\n const compressionResult = await checkAndCompress(\n aiChatId,\n DEFAULT_CONTEXT_COMPRESSION_CONFIG,\n systemPrompt,\n llmAdapter,\n aiChatManager,\n aiLogger ?? undefined,\n { signal: abortSignal }\n )\n if (compressionResult.compressed) {\n onEvent({\n type: 'compression_done',\n compressionResult: {\n summaryContent: compressionResult.summaryContent ?? '',\n tokensBefore: compressionResult.tokensBefore ?? 0,\n tokensAfter: compressionResult.tokensAfter ?? 0,\n timestamp: Date.now(),\n },\n })\n }\n } else {\n aiLogger?.info?.('Compression', 'Skipping compression for edited branch request', {\n aiChatId,\n historyLeafMessageId,\n })\n }\n\n if (abortSignal?.aborted) {\n handler.emitStatus('aborted', [], { force: true })\n onEvent({ type: 'done', isFinished: true, usage: handler.cloneUsage() })\n return\n }\n\n let history: SimpleHistoryMessage[] = []\n try {\n history = aiChatManager.getHistoryForAgent(aiChatId, undefined, historyLeafMessageId)\n } catch {\n // empty history on failure\n }\n\n handler.emitStatus('preparing', [], { pendingUserMessage: userMessage, force: true })\n\n const steerMessage = t('ai.agent.answerWithoutTools')\n let cachedMessages: PiMessage[] = []\n const effectiveTools =\n chartAutoMode === 'explicit' && !shouldUseChartCapabilityForMessage(userMessage)\n ? tools.filter((tool) => tool.name !== 'render_chart')\n : tools\n\n try {\n const routeInput = {\n userMessage,\n chatType,\n locale,\n dataSnapshot,\n availableTools: effectiveTools.map((tool) => tool.name),\n availableCapabilities: [\n getChartPlannerCapabilityForMessage({\n userMessage,\n locale,\n availableTools: effectiveTools.map((tool) => tool.name),\n chartAutoMode,\n }),\n ].filter((capability) => capability !== null),\n skillSummary: skillDef?.name ?? (skillMenu ? 'auto_skill_menu' : undefined),\n }\n const routeStartedAt = Date.now()\n const routeDecision = await decideRequestRoute(routeInput, {\n llmRouter: createLlmRouteDecider({\n piModel,\n apiKey: llmConfig.apiKey,\n abortSignal,\n }),\n })\n aiLogger?.info('Router', 'Shadow route decision', {\n ...routeDecision,\n elapsedMs: Date.now() - routeStartedAt,\n availableToolCount: tools.length,\n shadowOnly: true,\n })\n onEvent({ type: 'route', routeDecision })\n\n let effectiveSystemPrompt = systemPrompt\n if (routeDecision.route === 'planned_execution') {\n const planStartedAt = Date.now()\n const planner = createAnalysisPlanner({\n piModel,\n apiKey: llmConfig.apiKey,\n onPlanDelta: (delta) => onEvent({ type: 'plan_delta', planDelta: delta }),\n onThinkingDelta: (delta) => onEvent({ type: 'think', content: delta, thinkTag: 'thinking' }),\n onThinkingEnd: (durationMs) =>\n onEvent({ type: 'think', content: '', thinkTag: 'thinking', thinkDurationMs: durationMs }),\n onValidationDelta: (delta) => onEvent({ type: 'think', content: delta, thinkTag: 'plan_validation' }),\n onValidationEnd: (durationMs) =>\n onEvent({ type: 'think', content: '', thinkTag: 'plan_validation', thinkDurationMs: durationMs }),\n })\n const plan = await planner(routeInput, abortSignal)\n if (plan) {\n const planBlock = createPlanContentBlock(plan)\n onEvent({ type: 'plan', plan: planBlock })\n effectiveSystemPrompt = `${systemPrompt}\\n\\n${buildPlanGuidance(plan)}`\n aiLogger?.info('Planner', 'Plan generated', {\n title: plan.title,\n steps: plan.steps.length,\n successCriteria: plan.successCriteria.length,\n elapsedMs: Date.now() - planStartedAt,\n })\n } else {\n aiLogger?.warn('Planner', 'Plan generation skipped or failed', {\n elapsedMs: Date.now() - planStartedAt,\n route: routeDecision.route,\n })\n onEvent({ type: 'plan_skipped' })\n }\n }\n\n const result = await runAgentCore({\n piModel,\n apiKey: llmConfig.apiKey,\n systemPrompt: effectiveSystemPrompt,\n tools: effectiveTools,\n history,\n userMessage,\n maxToolRounds: DEFAULT_MAX_TOOL_ROUNDS,\n abortSignal,\n providerSessionId: aiChatId,\n locale,\n logger: aiLogger ?? undefined,\n steerMessage,\n thinkingLevel: thinkingLevel as import('@openchatlab/core').ThinkingLevel | undefined,\n onConvertToLlm: (filteredMessages) => {\n cachedMessages = filteredMessages as PiMessage[]\n },\n onEvent: (coreEvent) => handler.handleCoreEvent(coreEvent, cachedMessages),\n onDebugContext: (messages) => {\n try {\n aiChatManager.setPendingDebugContext(aiChatId, JSON.stringify(messages, null, 2))\n } catch {\n // silent\n }\n },\n })\n\n if (result.error && !abortSignal?.aborted) {\n const friendlyMessage = formatAIError(result.error)\n onEvent({\n type: 'error',\n error: { name: result.stopReason === 'length' ? 'OutputLimitError' : 'AgentError', message: friendlyMessage },\n })\n }\n\n handler.emitStatus(abortSignal?.aborted ? 'aborted' : result.error ? 'error' : 'completed', cachedMessages, {\n force: true,\n })\n onEvent({ type: 'done', isFinished: true, usage: result.usage })\n } catch (error) {\n const friendlyMessage = formatAIError(error)\n aiLogger?.error('ServerAgent', 'Agent execution error', { error: String(error) })\n handler.emitStatus('error', cachedMessages, { force: true })\n onEvent({ type: 'error', error: { name: 'AgentError', message: friendlyMessage } })\n onEvent({ type: 'done', isFinished: true, usage: handler.cloneUsage() })\n }\n}\n","import type {\n AgentTool,\n AIMemoryService,\n CrossChatAnalysisService,\n PreprocessConfig,\n SessionRuntimeAdapter,\n} from '@openchatlab/node-runtime'\nimport type { AIEntityRef } from '@openchatlab/shared-types'\nimport {\n countTokens,\n preprocessCrossChatLabel,\n preprocessCrossChatMessages,\n preprocessCrossChatSummaries,\n} from '@openchatlab/node-runtime'\nimport { createCrossChatAgentToolAdapters, type CrossChatToolExecutionContext } from '@openchatlab/tools'\n\nexport function createCliCrossChatTools(options: {\n analysisService: CrossChatAnalysisService\n sessionAdapter: SessionRuntimeAdapter\n locale?: string\n entityRefs?: AIEntityRef[]\n preprocessConfig?: Record<string, unknown>\n maxToolResultTokens: number\n memoryService: AIMemoryService\n aiChatId: string\n reportMemoryChange?: (memoryId: string) => void\n}): AgentTool<any, any>[] {\n const context: Omit<CrossChatToolExecutionContext, 'abortSignal' | 'reportProgress'> = {\n locale: options.locale,\n entityRefs: options.entityRefs,\n analysisService: options.analysisService,\n memoryService: options.memoryService,\n aiChatId: options.aiChatId,\n reportMemoryChange: options.reportMemoryChange,\n maxToolResultTokens: options.maxToolResultTokens,\n countTokens,\n preprocessMessagesBySession: (sessionId, messages) =>\n preprocessCrossChatMessages(\n options.sessionAdapter,\n sessionId,\n messages,\n options.preprocessConfig as PreprocessConfig | undefined\n ),\n preprocessSummariesBySession: (sessionId, summaries) =>\n preprocessCrossChatSummaries(\n options.sessionAdapter,\n sessionId,\n summaries,\n options.preprocessConfig as PreprocessConfig | undefined\n ),\n preprocessModelLabel: (value, pseudonym) =>\n preprocessCrossChatLabel(value, pseudonym, options.preprocessConfig as PreprocessConfig | undefined),\n }\n\n return createCrossChatAgentToolAdapters(context) as AgentTool<any, any>[]\n}\n","/**\n * CLI Agent stream runner — provides runAgentStream implementation\n * for the shared HTTP route context.\n */\n\nimport type {\n DatabaseManager,\n AIChatManager,\n AgentStreamChunk,\n LLMConfigStore,\n SemanticIndexRuntime,\n CrossChatAnalysisService,\n SessionRuntimeAdapter,\n AIMemoryService,\n} from '@openchatlab/node-runtime'\nimport {\n CHART_CAPABILITY_CORE_TOOLS,\n DEFAULT_CONTEXT_COMPRESSION_CONFIG,\n SkillManager,\n buildPiModel,\n buildSkillMenuWithBuiltinChart,\n createLlmRuntimeStores,\n createActivateSkillTool,\n createDataSnapshotFromOverview,\n getAllowedBuiltinToolsForChartAutoSkill,\n getChartCapabilitySkill,\n getSkillConfigWithBuiltinChart,\n resolveChartRuntimeForRequest,\n resolveCrossChatToolResultTokenBudget,\n runCrossChatAgent,\n} from '@openchatlab/node-runtime'\nimport { getChatOverview, normalizeBuiltinToolNames } from '@openchatlab/core'\nimport type { ChartAutoMode } from '@openchatlab/shared-types'\nimport type { DataSnapshot } from '@openchatlab/node-runtime'\nimport type { AgentStreamRequest } from '@openchatlab/http-routes'\nimport { AGENT_TOOL_REGISTRY, SEMANTIC_SEARCH_TOOL_NAME } from '@openchatlab/tools'\nimport { buildSemanticSearchGuidance } from '@openchatlab/node-runtime'\nimport { adaptToolsForAgent } from './tool-adapter'\nimport { loadAssistantConfig } from './assistant-loader'\nimport { runServerAgent } from './agent'\nimport { createCliCrossChatTools } from './cross-chat-tool-adapter'\nimport { getServerAiLogger } from './logger'\n\nfunction getAiDir(dbManager: DatabaseManager): string {\n const pathProvider = (dbManager as any)['pathProvider']\n if (!pathProvider) {\n throw Object.assign(new Error('PathProvider not available'), { statusCode: 500 })\n }\n return pathProvider.getAiDataDir()\n}\n\nconst RAW_SQL_TOOL_NAMES = new Set(['execute_sql'])\n\nexport function getAvailableToolDefs(isChartCapability: boolean, allowedToolSet: Set<string> | null) {\n if (isChartCapability) {\n const chartCoreTools = new Set<string>(CHART_CAPABILITY_CORE_TOOLS)\n return AGENT_TOOL_REGISTRY.filter(\n (tool) =>\n chartCoreTools.has(tool.name) ||\n (tool.category === 'analysis' && allowedToolSet?.has(tool.name) && !RAW_SQL_TOOL_NAMES.has(tool.name))\n )\n }\n\n return allowedToolSet\n ? AGENT_TOOL_REGISTRY.filter((tool) => tool.category !== 'analysis' || allowedToolSet.has(tool.name))\n : AGENT_TOOL_REGISTRY\n}\n\n// 区分“未配置白名单”和“配置为空白名单”:前者无限制,后者禁用 analysis 工具。\nexport function getAllowedToolSet(\n isChartCapability: boolean,\n allowedBuiltinTools?: readonly string[]\n): Set<string> | null {\n if (isChartCapability) {\n return new Set(normalizeBuiltinToolNames(allowedBuiltinTools ?? []))\n }\n return allowedBuiltinTools === undefined ? null : new Set(normalizeBuiltinToolNames(allowedBuiltinTools))\n}\n\nexport function createCliRunAgentStream(\n dbManager: DatabaseManager,\n aiChatManager: AIChatManager,\n options: {\n llmConfigStore?: LLMConfigStore\n semanticIndexService?: SemanticIndexRuntime\n crossChatAnalysisService?: CrossChatAnalysisService\n sessionAdapter?: SessionRuntimeAdapter\n memoryService?: AIMemoryService\n } = {}\n): (params: AgentStreamRequest, onEvent: (chunk: AgentStreamChunk) => void, abortSignal: AbortSignal) => Promise<void> {\n const aiDataDir = getAiDir(dbManager)\n const llmConfigStore = options.llmConfigStore ?? createLlmRuntimeStores(aiDataDir).llmConfigStore\n const semanticIndexService = options.semanticIndexService\n\n return async (params, onEvent, abortSignal) => {\n const {\n userMessage,\n aiChatId,\n historyLeafMessageId,\n chatKind = 'session',\n sessionId,\n entityRefs,\n chatType,\n locale,\n assistantId,\n skillId,\n enableAutoSkill,\n chartAutoMode,\n ownerInfo,\n mentionedMembers,\n thinkingLevel,\n } = params\n\n const conversation = aiChatManager.getAIChat(aiChatId)\n if (\n !conversation ||\n conversation.kind !== chatKind ||\n (chatKind === 'session' && conversation.sessionId !== sessionId)\n ) {\n onEvent({\n type: 'error',\n error: { name: 'ValidationError', message: 'AI conversation does not match the requested target' },\n })\n onEvent({ type: 'done', isFinished: true })\n return\n }\n\n let assistantSystemPrompt: string | undefined\n let assistantAllowedTools: string[] | undefined\n if (assistantId) {\n const assistantConfig = loadAssistantConfig(aiDataDir, assistantId)\n if (assistantConfig?.systemPrompt) {\n assistantSystemPrompt = assistantConfig.systemPrompt\n }\n assistantAllowedTools = assistantConfig?.allowedBuiltinTools\n }\n\n const llmConfig = llmConfigStore.getDefaultAssistantConfig()\n const maxToolResultPercent = DEFAULT_CONTEXT_COMPRESSION_CONFIG.maxToolResultPercent ?? 50\n const contextWindow = llmConfig ? (buildPiModel(llmConfig).contextWindow ?? 128000) : 128000\n const maxToolResultTokens = Math.floor(contextWindow * (maxToolResultPercent / 100))\n\n if (chatKind === 'global') {\n if (!llmConfig) {\n onEvent({ type: 'error', error: { name: 'ConfigError', message: 'LLM service not configured' } })\n onEvent({ type: 'done', isFinished: true })\n return\n }\n if (!options.crossChatAnalysisService || !options.sessionAdapter || !options.memoryService) {\n onEvent({ type: 'error', error: { name: 'RuntimeError', message: 'Cross-chat analysis is unavailable' } })\n onEvent({ type: 'done', isFinished: true })\n return\n }\n const tools = createCliCrossChatTools({\n analysisService: options.crossChatAnalysisService,\n sessionAdapter: options.sessionAdapter,\n locale,\n entityRefs,\n preprocessConfig: params.preprocessConfig,\n maxToolResultTokens: resolveCrossChatToolResultTokenBudget(contextWindow),\n memoryService: options.memoryService,\n aiChatId,\n reportMemoryChange: (memoryId) => onEvent({ type: 'memory_change', memoryId }),\n })\n await runCrossChatAgent({\n userMessage,\n entityRefs,\n aiChatId,\n historyLeafMessageId,\n locale,\n piModel: buildPiModel(llmConfig),\n apiKey: llmConfig.apiKey,\n tools,\n aiChatManager,\n memoryService: options.memoryService,\n onEvent,\n abortSignal,\n thinkingLevel: thinkingLevel as import('@openchatlab/core').ThinkingLevel | undefined,\n logger: getServerAiLogger() ?? undefined,\n })\n return\n }\n\n if (!sessionId) {\n onEvent({ type: 'error', error: { name: 'ValidationError', message: 'Session ID is required' } })\n onEvent({ type: 'done', isFinished: true })\n return\n }\n\n const db = (dbManager as any).open?.(sessionId)\n const resolvedChartAutoMode: ChartAutoMode = chartAutoMode ?? 'suggest'\n const chartRuntime = resolveChartRuntimeForRequest({\n skillId,\n userMessage,\n locale,\n assistantAllowedTools,\n enableAutoDetection: enableAutoSkill === true,\n chartAutoMode: resolvedChartAutoMode,\n })\n const isChartCapability = chartRuntime.isChartCapability\n const autoSkillAllowedTools =\n !skillId && enableAutoSkill && resolvedChartAutoMode !== 'explicit'\n ? getAllowedBuiltinToolsForChartAutoSkill(assistantAllowedTools)\n : assistantAllowedTools\n const allowedToolSet = getAllowedToolSet(\n isChartCapability,\n isChartCapability ? chartRuntime.allowedBuiltinTools : autoSkillAllowedTools\n )\n const availableToolDefs = getAvailableToolDefs(isChartCapability, allowedToolSet)\n\n // 语义检索按需暴露:仅当前会话可检索时保留工具,否则从工具集中过滤掉以减少 schema token 与无效调用。\n const canSemanticSearch = !!db && !!semanticIndexService && (await semanticIndexService.canSearch(sessionId))\n const filteredToolDefs = canSemanticSearch\n ? availableToolDefs\n : availableToolDefs.filter((tool) => tool.name !== SEMANTIC_SEARCH_TOOL_NAME)\n\n const agentTools = db\n ? adaptToolsForAgent(\n filteredToolDefs,\n () => ({\n db,\n sessionId,\n locale,\n semanticIndexService,\n preprocessConfig: params.preprocessConfig,\n ownerPlatformId: ownerInfo?.platformId,\n timeFilter: params.timeFilter,\n maxMessagesLimit: params.maxMessagesLimit,\n }),\n { maxToolResultTokens, locale }\n )\n : []\n\n // 工具可用时向 system prompt 加简短引导,提示何时调用语义检索。\n if (canSemanticSearch) {\n assistantSystemPrompt = [assistantSystemPrompt, buildSemanticSearchGuidance(locale)].filter(Boolean).join('\\n\\n')\n }\n\n const skillMgr = new SkillManager(aiDataDir)\n skillMgr.init()\n const toolNames = agentTools.map((t: { name: string }) => t.name)\n\n let resolvedSkillDef: { name: string; prompt: string } | undefined\n let resolvedSkillMenu: string | undefined\n if (isChartCapability) {\n const def = chartRuntime.skillDef ?? getChartCapabilitySkill(locale ?? 'zh-CN')\n resolvedSkillDef = { name: def.name, prompt: def.prompt }\n } else if (skillId) {\n const def = skillMgr.getSkillConfig(skillId)\n if (def) resolvedSkillDef = { name: def.name, prompt: def.prompt }\n } else if (enableAutoSkill) {\n const baseMenu = skillMgr.getSkillMenu(chatType ?? 'group', toolNames)\n const menu =\n resolvedChartAutoMode === 'aggressive' ? buildSkillMenuWithBuiltinChart(baseMenu, locale, toolNames) : baseMenu\n if (menu) resolvedSkillMenu = menu\n }\n\n if (resolvedSkillMenu) {\n const activateSkillTool = createActivateSkillTool({\n chatType: chatType ?? 'group',\n allowedTools: toolNames,\n coreToolNames: new Set<string>(CHART_CAPABILITY_CORE_TOOLS),\n locale,\n getSkillConfig: (id) =>\n resolvedChartAutoMode === 'aggressive'\n ? getSkillConfigWithBuiltinChart(id, locale, (skillConfigId) => skillMgr.getSkillConfig(skillConfigId))\n : skillMgr.getSkillConfig(id),\n })\n agentTools.push(activateSkillTool as any)\n }\n\n let dataSnapshot: DataSnapshot | undefined\n if (db) {\n try {\n dataSnapshot = createDataSnapshotFromOverview(getChatOverview(db, 10))\n } catch {\n // non-fatal\n }\n }\n\n await runServerAgent({\n userMessage,\n aiChatId,\n historyLeafMessageId,\n chatType,\n locale,\n assistantSystemPrompt,\n skillMenu: resolvedSkillMenu,\n skillDef: resolvedSkillDef,\n tools: agentTools,\n llmConfig,\n aiChatManager,\n onEvent,\n abortSignal,\n ownerInfo,\n mentionedMembers,\n dataSnapshot,\n thinkingLevel,\n chartAutoMode: resolvedChartAutoMode,\n })\n }\n}\n"],"mappings":"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","names":["options"]}
@@ -6,7 +6,7 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __pathDirname(__filename);
7
7
  import {
8
8
  createLocalEmbeddingRuntimeManager
9
- } from "./chunk-H46CLFWK.mjs";
9
+ } from "./chunk-HJWBFHNR.mjs";
10
10
 
11
11
  // src/http/port.ts
12
12
  import * as fs from "fs/promises";
@@ -98,4 +98,4 @@ export {
98
98
  resolveCliLocalEmbeddingRuntimeConfig,
99
99
  installCliLocalEmbeddingRuntime
100
100
  };
101
- //# sourceMappingURL=chunk-XQ6Z2KNN.mjs.map
101
+ //# sourceMappingURL=chunk-O57SQSCO.mjs.map
@@ -21,7 +21,7 @@ import {
21
21
  setCache,
22
22
  shouldEnableContactsEntry,
23
23
  shouldScopeContactToSession
24
- } from "./chunk-HBAQPF6X.mjs";
24
+ } from "./chunk-ZOHSWBD2.mjs";
25
25
 
26
26
  // ../../packages/node-runtime/src/services/contacts/facts-cache.ts
27
27
  var CONTACTS_FACTS_FORMAT_VERSION = 1;
@@ -517,4 +517,4 @@ export {
517
517
  computeContactsSnapshot,
518
518
  createEmptyContactsDiagnostics
519
519
  };
520
- //# sourceMappingURL=chunk-EFX66A2O.mjs.map
520
+ //# sourceMappingURL=chunk-ZGXXAPLX.mjs.map
@@ -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":
@@ -13787,14 +13817,18 @@ var zh_CN_default = {
13787
13817
  response_time_analysis: {
13788
13818
  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
13819
  params: {
13790
- days: "\u7EDF\u8BA1\u6700\u8FD1\u591A\u5C11\u5929\u7684\u6570\u636E",
13820
+ 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",
13821
+ 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',
13822
+ 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
13823
  top_n: "\u8FD4\u56DE\u524D\u591A\u5C11\u540D"
13792
13824
  }
13793
13825
  },
13794
13826
  keyword_frequency: {
13795
13827
  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
13828
  params: {
13797
- days: "\u7EDF\u8BA1\u6700\u8FD1\u591A\u5C11\u5929\u7684\u6570\u636E",
13829
+ 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",
13830
+ 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',
13831
+ 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
13832
  top_n: "\u8FD4\u56DE\u524D\u591A\u5C11\u4E2A\u5173\u952E\u8BCD"
13799
13833
  }
13800
13834
  },
@@ -14150,14 +14184,18 @@ Returned summaries are brief descriptions of each segment, helping quickly locat
14150
14184
  response_time_analysis: {
14151
14185
  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
14186
  params: {
14153
- days: "Number of recent days to analyze",
14187
+ days: "Recent days to analyze when no explicit or selected time range is available; defaults to 30",
14188
+ start_time: 'Start time, format "YYYY-MM-DD HH:mm". Explicit dates override the selected range and days',
14189
+ end_time: 'End time, format "YYYY-MM-DD HH:mm". Explicit dates override the selected range and days',
14154
14190
  top_n: "Number of top members to return"
14155
14191
  }
14156
14192
  },
14157
14193
  keyword_frequency: {
14158
14194
  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
14195
  params: {
14160
- days: "Number of recent days to analyze",
14196
+ days: "Recent days to analyze when no explicit or selected time range is available; defaults to 30",
14197
+ start_time: 'Start time, format "YYYY-MM-DD HH:mm". Explicit dates override the selected range and days',
14198
+ end_time: 'End time, format "YYYY-MM-DD HH:mm". Explicit dates override the selected range and days',
14161
14199
  top_n: "Number of top keywords to return"
14162
14200
  }
14163
14201
  },
@@ -14513,14 +14551,18 @@ var ja_JP_default = {
14513
14551
  response_time_analysis: {
14514
14552
  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
14553
  params: {
14516
- days: "\u76F4\u8FD1\u4F55\u65E5\u9593\u306E\u30C7\u30FC\u30BF\u3092\u96C6\u8A08\u3059\u308B\u304B",
14554
+ 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",
14555
+ 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',
14556
+ 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
14557
  top_n: "\u4E0A\u4F4D\u4F55\u540D\u3092\u8FD4\u5374\u3059\u308B\u304B"
14518
14558
  }
14519
14559
  },
14520
14560
  keyword_frequency: {
14521
14561
  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
14562
  params: {
14523
- days: "\u76F4\u8FD1\u4F55\u65E5\u9593\u306E\u30C7\u30FC\u30BF\u3092\u96C6\u8A08\u3059\u308B\u304B",
14563
+ 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",
14564
+ 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',
14565
+ 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
14566
  top_n: "\u4E0A\u4F4D\u4F55\u500B\u306E\u30AD\u30FC\u30EF\u30FC\u30C9\u3092\u8FD4\u5374\u3059\u308B\u304B"
14525
14567
  }
14526
14568
  },
@@ -14873,14 +14915,18 @@ var zh_TW_default = {
14873
14915
  response_time_analysis: {
14874
14916
  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
14917
  params: {
14876
- days: "\u7D71\u8A08\u6700\u8FD1\u591A\u5C11\u5929\u7684\u8CC7\u6599",
14918
+ 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",
14919
+ 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',
14920
+ 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
14921
  top_n: "\u56DE\u50B3\u524D\u591A\u5C11\u540D"
14878
14922
  }
14879
14923
  },
14880
14924
  keyword_frequency: {
14881
14925
  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
14926
  params: {
14883
- days: "\u7D71\u8A08\u6700\u8FD1\u591A\u5C11\u5929\u7684\u8CC7\u6599",
14927
+ 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",
14928
+ 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',
14929
+ 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
14930
  top_n: "\u56DE\u50B3\u524D\u591A\u5C11\u500B\u95DC\u9375\u8A5E"
14885
14931
  }
14886
14932
  },
@@ -15602,7 +15648,7 @@ var PLAN_INTENTS = [
15602
15648
  "mixed"
15603
15649
  ];
15604
15650
  var STREAM_MARKER_HOLDBACK_CHARS = Math.max("</draft>".length, "</plan>".length, "<json>".length) - 1;
15605
- function isRecord2(value) {
15651
+ function isRecord3(value) {
15606
15652
  return typeof value === "object" && value !== null && !Array.isArray(value);
15607
15653
  }
15608
15654
  function isIntent(value) {
@@ -15624,10 +15670,10 @@ function extractJsonObject2(text) {
15624
15670
  function parsePlanJson(rawText, availableTools) {
15625
15671
  try {
15626
15672
  const parsed = JSON.parse(extractJsonObject2(rawText));
15627
- if (!isRecord2(parsed)) return null;
15673
+ if (!isRecord3(parsed)) return null;
15628
15674
  const title = normalizeString(parsed.title);
15629
15675
  if (!title || !isIntent(parsed.intent) || !Array.isArray(parsed.steps)) return null;
15630
- const steps = parsed.steps.filter(isRecord2).map((step) => {
15676
+ const steps = parsed.steps.filter(isRecord3).map((step) => {
15631
15677
  const goal = normalizeString(step.goal);
15632
15678
  const evidenceNeeded = normalizeString(step.evidenceNeeded);
15633
15679
  if (!goal || !evidenceNeeded) return null;
@@ -17350,6 +17396,7 @@ function buildPiModel(config, options) {
17350
17396
  }
17351
17397
  const resolvedBaseUrl = config.provider === "openai-compatible" && (apiFormat === "openai-completions" || apiFormat === "openai-responses") ? normalizeOpenAICompatibleBaseUrl(baseUrl) : baseUrl;
17352
17398
  const { reasoning, compat, thinkingLevelMap } = inferReasoning(config.provider, modelId, modelDef);
17399
+ const requiresSystemRole = apiFormat === "openai-completions" && (config.provider.toLowerCase() === "qwen" || /\bqwen|qwq/i.test(modelId));
17353
17400
  return {
17354
17401
  id: modelId,
17355
17402
  name: modelId,
@@ -17364,7 +17411,7 @@ function buildPiModel(config, options) {
17364
17411
  contextWindow,
17365
17412
  // Reasoning and visible text share the output budget on compatible APIs.
17366
17413
  maxTokens: config.maxTokens ?? (reasoning ? 16384 : 4096),
17367
- compat
17414
+ compat: requiresSystemRole ? { ...compat, supportsDeveloperRole: false } : compat
17368
17415
  };
17369
17416
  }
17370
17417
 
@@ -17922,7 +17969,7 @@ function getMetaPath(userDataDir) {
17922
17969
  return path22.join(userDataDir, ".chatlab-meta.json");
17923
17970
  }
17924
17971
  function validateDataDirCompatibilityMeta(value, userDataDir, metaPath) {
17925
- if (!isRecord3(value)) {
17972
+ if (!isRecord4(value)) {
17926
17973
  throw createInvalidMetaError(userDataDir, metaPath, "Data directory compatibility meta must be an object.");
17927
17974
  }
17928
17975
  if (value.formatVersion !== 1) {
@@ -17933,7 +17980,7 @@ function validateDataDirCompatibilityMeta(value, userDataDir, metaPath) {
17933
17980
  const reasons = value.reasons;
17934
17981
  const updatedBy = value.updatedBy;
17935
17982
  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) {
17983
+ 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
17984
  throw createInvalidMetaError(userDataDir, metaPath, "Invalid data directory compatibility meta fields.");
17938
17985
  }
17939
17986
  return {
@@ -18004,7 +18051,7 @@ function writeMetaAtomic(userDataDir, metaPath, meta) {
18004
18051
  throw error;
18005
18052
  }
18006
18053
  }
18007
- function isRecord3(value) {
18054
+ function isRecord4(value) {
18008
18055
  return typeof value === "object" && value !== null && !Array.isArray(value);
18009
18056
  }
18010
18057
  function isNonEmptyString(value) {
@@ -18419,7 +18466,7 @@ function createChatTopicModelClient(config, deps = {}) {
18419
18466
  };
18420
18467
  }
18421
18468
  function normalizeTopicModelPayload(payload, model) {
18422
- if (!isRecord4(payload) || !isDeepSeekEndpoint(model)) return void 0;
18469
+ if (!isRecord5(payload) || !isDeepSeekEndpoint(model)) return void 0;
18423
18470
  const normalized = {
18424
18471
  ...payload,
18425
18472
  thinking: { type: "disabled" }
@@ -18434,7 +18481,7 @@ function normalizeTopicModelPayload(payload, model) {
18434
18481
  function isDeepSeekEndpoint(model) {
18435
18482
  return model.provider === "deepseek" || model.baseUrl.includes("deepseek.com");
18436
18483
  }
18437
- function isRecord4(value) {
18484
+ function isRecord5(value) {
18438
18485
  return typeof value === "object" && value !== null && !Array.isArray(value);
18439
18486
  }
18440
18487
 
@@ -19394,7 +19441,7 @@ function serializeTopicLedger(ledger) {
19394
19441
  }
19395
19442
  function parseTopicLedger(value) {
19396
19443
  const parsed = JSON.parse(value);
19397
- if (!isRecord5(parsed) || !Array.isArray(parsed.topics)) throw new Error("Invalid topic ledger checkpoint");
19444
+ if (!isRecord6(parsed) || !Array.isArray(parsed.topics)) throw new Error("Invalid topic ledger checkpoint");
19398
19445
  const topics = parsed.topics.map((topic) => parseLedgerItem(topic));
19399
19446
  const ledger = { topics };
19400
19447
  assertTopicLedgerSize(ledger);
@@ -19457,7 +19504,7 @@ function cloneLedger(ledger) {
19457
19504
  };
19458
19505
  }
19459
19506
  function parseLedgerItem(value) {
19460
- if (!isRecord5(value)) throw new Error("Invalid topic ledger item");
19507
+ if (!isRecord6(value)) throw new Error("Invalid topic ledger item");
19461
19508
  const id = requireString(value.id, "id");
19462
19509
  const title = requireString(value.title, "title");
19463
19510
  const summary = requireString(value.summary, "summary");
@@ -19471,7 +19518,7 @@ function parseLedgerItem(value) {
19471
19518
  return { id, title, summary, state, evidence, messageIds: deduplicateMessageIds(rawMessageIds) };
19472
19519
  }
19473
19520
  function parseEvidence(value) {
19474
- if (!isRecord5(value)) throw new Error("Invalid topic evidence");
19521
+ if (!isRecord6(value)) throw new Error("Invalid topic evidence");
19475
19522
  const messageId = Number(value.messageId);
19476
19523
  const timestamp = Number(value.timestamp);
19477
19524
  const role = value.role;
@@ -19489,7 +19536,7 @@ function requireString(value, field, maxLength = 4e3) {
19489
19536
  }
19490
19537
  return value.trim();
19491
19538
  }
19492
- function isRecord5(value) {
19539
+ function isRecord6(value) {
19493
19540
  return typeof value === "object" && value !== null && !Array.isArray(value);
19494
19541
  }
19495
19542
 
@@ -19565,7 +19612,7 @@ function parseTopicFinalizationResponse(text) {
19565
19612
  return {
19566
19613
  overview,
19567
19614
  topics: payload.topics.map((value) => {
19568
- if (!isRecord5(value)) throw new Error("Invalid final topic");
19615
+ if (!isRecord6(value)) throw new Error("Invalid final topic");
19569
19616
  return {
19570
19617
  id: requireString(value.id, "id", 200),
19571
19618
  title: requireString(value.title, "title", 200),
@@ -19576,7 +19623,7 @@ function parseTopicFinalizationResponse(text) {
19576
19623
  };
19577
19624
  }
19578
19625
  function parseOperation(value) {
19579
- if (!isRecord5(value)) throw new Error("Invalid topic operation");
19626
+ if (!isRecord6(value)) throw new Error("Invalid topic operation");
19580
19627
  const operation = value.operation ?? value.op;
19581
19628
  const evidence = parseEvidenceArray(value.evidence);
19582
19629
  if (operation === "create") {
@@ -19629,7 +19676,7 @@ function parseEvidenceArray(value) {
19629
19676
  return value.map(parseEvidence);
19630
19677
  }
19631
19678
  function parseAssignment(value) {
19632
- if (!isRecord5(value)) throw new Error("Invalid topic assignment");
19679
+ if (!isRecord6(value)) throw new Error("Invalid topic assignment");
19633
19680
  if (!Array.isArray(value.messageIds) || value.messageIds.length > 240) {
19634
19681
  throw new Error("Invalid topic assignment message ids");
19635
19682
  }
@@ -19652,7 +19699,7 @@ function parseJsonObject(text) {
19652
19699
  const end = unfenced.lastIndexOf("}");
19653
19700
  if (start < 0 || end < start) throw new Error("Model did not return a JSON object");
19654
19701
  const parsed = JSON.parse(unfenced.slice(start, end + 1));
19655
- if (!isRecord5(parsed)) throw new Error("Model response must be a JSON object");
19702
+ if (!isRecord6(parsed)) throw new Error("Model response must be a JSON object");
19656
19703
  return parsed;
19657
19704
  }
19658
19705
  function formatLedgerForModel(ledger) {
@@ -21117,6 +21164,8 @@ export {
21117
21164
  BUILTIN_MODELS,
21118
21165
  getBuiltinModelsByProvider,
21119
21166
  stripAvatarFields,
21167
+ extractToolResultText,
21168
+ truncateToolResultText,
21120
21169
  generateMessageKey,
21121
21170
  writeParseResultToDb,
21122
21171
  getCollidingPlatformIds,
@@ -21297,4 +21346,4 @@ export {
21297
21346
  StaticPathProvider,
21298
21347
  createDatabaseManagerAdapter
21299
21348
  };
21300
- //# sourceMappingURL=chunk-HBAQPF6X.mjs.map
21349
+ //# sourceMappingURL=chunk-ZOHSWBD2.mjs.map