@xopcai/xopc 0.0.93 → 0.0.94

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 (356) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  3. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  4. package/dist/extensions/telegram/src/plugin.js +1 -1
  5. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  6. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  7. package/dist/extensions/telegram/xopc.extension.json +1 -1
  8. package/dist/extensions/weixin/src/api/api.js +2 -2
  9. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  10. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  11. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  12. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  13. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  14. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  15. package/dist/extensions/weixin/src/plugin.js +1 -1
  16. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  17. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  18. package/dist/gateway/static/root/assets/agents-OqhbJkMf.js +222 -0
  19. package/dist/gateway/static/root/assets/apps-page-OHXW9XP8.js +1 -0
  20. package/dist/gateway/static/root/assets/channels-settings-4N2R-jof.js +1 -0
  21. package/dist/gateway/static/root/assets/{channels-status-swr-CsGkK9h9.js → channels-status-swr-Bv6f9kDq.js} +1 -1
  22. package/dist/gateway/static/root/assets/{cron-api-CyAm0xJT.js → cron-api-BtaQaHJq.js} +1 -1
  23. package/dist/gateway/static/root/assets/cron-page-Dah32HJK.js +1 -0
  24. package/dist/gateway/static/root/assets/{dist-DHwVV8XK.js → dist-BJfD9Qvs.js} +1 -1
  25. package/dist/gateway/static/root/assets/{extension-debug-page-BK8kcc4F.js → extension-debug-page-DnYuMzmH.js} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-page-Cf8X_QUc.js → extension-page-CJfc-6XV.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-settings-page-C5-YLMmy.js → extension-settings-page-BxdfYQMG.js} +1 -1
  28. package/dist/gateway/static/root/assets/{fetch-BAPnkYbC.js → fetch-B0aeeY0q.js} +1 -1
  29. package/dist/gateway/static/root/assets/{field-primitives-8p7ucXa1.js → field-primitives-DOLHwowi.js} +1 -1
  30. package/dist/gateway/static/root/assets/{heartbeat-config-api-CpgW2sGp.js → heartbeat-config-api-Bj2INAf5.js} +1 -1
  31. package/dist/gateway/static/root/assets/index-Bj_l8QDp.css +1 -0
  32. package/dist/gateway/static/root/assets/{index-Do52EfZK.js → index-DuQ1XPoA.js} +99 -98
  33. package/dist/gateway/static/root/assets/logs-page-AsOgLNJE.js +2 -0
  34. package/dist/gateway/static/root/assets/{note-detail-page-WLM6FUIi.js → note-detail-page-24J4mVP-.js} +3 -3
  35. package/dist/gateway/static/root/assets/{note-time-EFyIVhec.js → note-time-JBszYV3s.js} +1 -1
  36. package/dist/gateway/static/root/assets/{notes-page-BYPVYcYn.js → notes-page-BApAirFB.js} +1 -1
  37. package/dist/gateway/static/root/assets/sessions-page-DX9huWsA.js +1 -0
  38. package/dist/gateway/static/root/assets/{settings-advanced-gate-CEs8pGh6.js → settings-advanced-gate-DWvhsTuz.js} +1 -1
  39. package/dist/gateway/static/root/assets/{settings-form-section-C6cGTVwK.js → settings-form-section-CxMjaMiy.js} +1 -1
  40. package/dist/gateway/static/root/assets/settings-page-4VmUTzQs.js +3 -0
  41. package/dist/gateway/static/root/assets/{share-preview-page-tnIfJ4K6.js → share-preview-page-IX0TJvRd.js} +1 -1
  42. package/dist/gateway/static/root/assets/skills-page-CGKGKfwe.js +2 -0
  43. package/dist/gateway/static/root/assets/{theme-store-D6EsNTPr.js → theme-store-Cg_SuBw0.js} +1 -1
  44. package/dist/gateway/static/root/assets/{url-CTjpm0Uz.js → url-BHHmdJYc.js} +2 -2
  45. package/dist/gateway/static/root/assets/{utils-C86AVfY-.js → utils-BmlcxR2j.js} +1 -1
  46. package/dist/gateway/static/root/assets/voice-api-key-field-DaGm2N4J.js +1 -0
  47. package/dist/gateway/static/root/assets/{workflow-page.utils-DsEriMFW.js → workflow-page.utils-D0vsIGHD.js} +1 -1
  48. package/dist/gateway/static/root/assets/workflows-page-BFCrD3nw.js +27 -0
  49. package/dist/gateway/static/root/index.html +5 -5
  50. package/dist/package.js +1 -1
  51. package/dist/src/agent/agent-manager.js +7 -7
  52. package/dist/src/agent/agent-scope.js +1 -1
  53. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  54. package/dist/src/agent/context/workspace-seed.js +2 -2
  55. package/dist/src/agent/goals/goal-run-store.js +4 -4
  56. package/dist/src/agent/goals/persistent-goal-service.js +1 -1
  57. package/dist/src/agent/goals/post-turn.js +2 -2
  58. package/dist/src/agent/image/load-image-media.js +2 -2
  59. package/dist/src/agent/inbound/turn-dispatcher.d.ts +1 -0
  60. package/dist/src/agent/inbound/turn-dispatcher.js +3 -0
  61. package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
  62. package/dist/src/agent/ipc/bus.js +1 -1
  63. package/dist/src/agent/ipc/inbox.js +2 -2
  64. package/dist/src/agent/ipc/socket.js +1 -1
  65. package/dist/src/agent/lifecycle/handlers/compaction.js +1 -1
  66. package/dist/src/agent/lifecycle/handlers/compaction.js.map +1 -1
  67. package/dist/src/agent/mcp/bundle-mcp-materialize.js +2 -2
  68. package/dist/src/agent/mcp/bundle-mcp-materialize.js.map +1 -1
  69. package/dist/src/agent/mcp/bundle-mcp-runtime.js +18 -5
  70. package/dist/src/agent/mcp/bundle-mcp-runtime.js.map +1 -1
  71. package/dist/src/agent/mcp/mcp-transport-config.js +11 -4
  72. package/dist/src/agent/mcp/mcp-transport-config.js.map +1 -1
  73. package/dist/src/agent/mcp/mcp-transport.js +2 -2
  74. package/dist/src/agent/mcp/mcp-transport.js.map +1 -1
  75. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  76. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  77. package/dist/src/agent/memory/dreaming/events.js +1 -1
  78. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  79. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  80. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  81. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  82. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  83. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  84. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  85. package/dist/src/agent/models/manager.js +1 -1
  86. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  87. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  88. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  89. package/dist/src/agent/sandbox/path-policy.js +2 -2
  90. package/dist/src/agent/service/build-direct-message-content.js +1 -1
  91. package/dist/src/agent/service/process-direct-streaming.d.ts +1 -0
  92. package/dist/src/agent/service/process-direct-streaming.js +15 -12
  93. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  94. package/dist/src/agent/service.d.ts +4 -2
  95. package/dist/src/agent/service.js +24 -8
  96. package/dist/src/agent/service.js.map +1 -1
  97. package/dist/src/agent/service.types.d.ts +3 -1
  98. package/dist/src/agent/session/session-inspector.js +1 -1
  99. package/dist/src/agent/skills/config.js +1 -1
  100. package/dist/src/agent/skills/hub-hash.js +2 -2
  101. package/dist/src/agent/skills/hub-lock.js +1 -1
  102. package/dist/src/agent/skills/hub-pull.js +2 -2
  103. package/dist/src/agent/skills/index.js +1 -1
  104. package/dist/src/agent/skills/managed-store.js +1 -1
  105. package/dist/src/agent/skills/scanner.js +1 -1
  106. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  107. package/dist/src/agent/skills/skill-manager.js +1 -1
  108. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +1 -1
  109. package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
  110. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  111. package/dist/src/agent/tools/factory.js +1 -1
  112. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  113. package/dist/src/agent/tools/search/registry.js +1 -1
  114. package/dist/src/agent/tools/search/registry.js.map +1 -1
  115. package/dist/src/agent/tools/send-media.js +1 -1
  116. package/dist/src/agent/tools/session-search-tool.js +1 -1
  117. package/dist/src/agent/tools/session-search-tool.js.map +1 -1
  118. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  119. package/dist/src/agent/tools/workflow-tool.js +2 -2
  120. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  121. package/dist/src/agent/tools/write.js +1 -1
  122. package/dist/src/agent/workflow/catalog.js +1 -1
  123. package/dist/src/agent/workflow/progress-broker.js +1 -1
  124. package/dist/src/agent/workflow/progress-broker.js.map +1 -1
  125. package/dist/src/agent/workflow/subagent-runner.js +1 -1
  126. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  127. package/dist/src/auth/credentials.js +3 -3
  128. package/dist/src/auth/profiles/store.js +1 -1
  129. package/dist/src/auth/sync-provider-auth.js +1 -1
  130. package/dist/src/browser/cache-dir-policy.js +1 -1
  131. package/dist/src/browser/cdp-local-launcher.js +2 -2
  132. package/dist/src/browser/providers/browser-ext-install.js +3 -3
  133. package/dist/src/browser/providers/cloakbrowser.js +4 -4
  134. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  135. package/dist/src/browser/stealth.js +1 -1
  136. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  137. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  138. package/dist/src/channels/outbound/persist-store.js +1 -1
  139. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  140. package/dist/src/channels/pairing/pairing-store.js +2 -2
  141. package/dist/src/channels/pipeline.js +3 -2
  142. package/dist/src/channels/pipeline.js.map +1 -1
  143. package/dist/src/chat-commands/agent-edit.js +2 -2
  144. package/dist/src/chat-commands/builtins/config.js +2 -2
  145. package/dist/src/chat-commands/context.js +1 -1
  146. package/dist/src/cli/cli-log-level-preset.d.ts +1 -1
  147. package/dist/src/cli/cli-log-level-preset.js +2 -2
  148. package/dist/src/cli/cli-log-level-preset.js.map +1 -1
  149. package/dist/src/cli/commands/config.js +1 -1
  150. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  151. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  152. package/dist/src/cli/commands/doctor/checks/session-integrity.js +2 -2
  153. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  154. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  155. package/dist/src/cli/commands/extension-dev.js +1 -1
  156. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  157. package/dist/src/cli/commands/extension-pack.js +1 -1
  158. package/dist/src/cli/commands/gateway/logs.js +1 -1
  159. package/dist/src/cli/commands/image.js +1 -1
  160. package/dist/src/cli/commands/init.js +4 -4
  161. package/dist/src/cli/commands/logs.js +3 -3
  162. package/dist/src/cli/commands/logs.js.map +1 -1
  163. package/dist/src/cli/commands/onboard.js +1 -1
  164. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  165. package/dist/src/commands/agents.config.js +1 -1
  166. package/dist/src/config/agent-profile.js +1 -1
  167. package/dist/src/config/gateway-bind.js +1 -1
  168. package/dist/src/config/index.js +5 -5
  169. package/dist/src/config/loader.js +2 -2
  170. package/dist/src/config/models-json.js +2 -2
  171. package/dist/src/config/paths-state.js +1 -1
  172. package/dist/src/config/profile.js +2 -2
  173. package/dist/src/config/workspace-path.js +1 -1
  174. package/dist/src/cron/executor.js +9 -6
  175. package/dist/src/cron/executor.js.map +1 -1
  176. package/dist/src/cron/persistence.js +1 -1
  177. package/dist/src/cron/run-log-store.js +1 -1
  178. package/dist/src/daemon/constants.js +1 -1
  179. package/dist/src/daemon/install-plan.js +2 -2
  180. package/dist/src/daemon/launchd.js +2 -2
  181. package/dist/src/daemon/schtasks.js +2 -2
  182. package/dist/src/daemon/systemd.js +2 -2
  183. package/dist/src/extensions/bundle-mcp.js +1 -1
  184. package/dist/src/extensions/discover-extensions.js +1 -1
  185. package/dist/src/extensions/health.js +1 -1
  186. package/dist/src/extensions/loader.js +1 -1
  187. package/dist/src/extensions/lockfile.js +2 -2
  188. package/dist/src/extensions/update.js +1 -1
  189. package/dist/src/gateway/agents-admin.js +3 -3
  190. package/dist/src/gateway/file-path-classifier.js +2 -2
  191. package/dist/src/gateway/heartbeat/service.js +1 -1
  192. package/dist/src/gateway/hono/app.js +4 -1
  193. package/dist/src/gateway/hono/app.js.map +1 -1
  194. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  195. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  196. package/dist/src/gateway/hono/lib/route-logger.d.ts +6 -0
  197. package/dist/src/gateway/hono/lib/route-logger.js +31 -0
  198. package/dist/src/gateway/hono/lib/route-logger.js.map +1 -0
  199. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  200. package/dist/src/gateway/hono/middleware/auth.js +16 -3
  201. package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
  202. package/dist/src/gateway/hono/middleware/logger.js +1 -1
  203. package/dist/src/gateway/hono/middleware/logger.js.map +1 -1
  204. package/dist/src/gateway/hono/middleware/route-errors.d.ts +5 -0
  205. package/dist/src/gateway/hono/middleware/route-errors.js +27 -0
  206. package/dist/src/gateway/hono/middleware/route-errors.js.map +1 -0
  207. package/dist/src/gateway/hono/oauth.js +1 -1
  208. package/dist/src/gateway/hono/routes/agent-stream.js +6 -0
  209. package/dist/src/gateway/hono/routes/agent-stream.js.map +1 -1
  210. package/dist/src/gateway/hono/routes/agents.js +1 -1
  211. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  212. package/dist/src/gateway/hono/routes/browser-install.js +2 -4
  213. package/dist/src/gateway/hono/routes/browser-install.js.map +1 -1
  214. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  215. package/dist/src/gateway/hono/routes/config.js +25 -11
  216. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  217. package/dist/src/gateway/hono/routes/cron.js +5 -0
  218. package/dist/src/gateway/hono/routes/cron.js.map +1 -1
  219. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  220. package/dist/src/gateway/hono/routes/host-fs.js +4 -6
  221. package/dist/src/gateway/hono/routes/host-fs.js.map +1 -1
  222. package/dist/src/gateway/hono/routes/lazy-bundles.js +14 -1
  223. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  224. package/dist/src/gateway/hono/routes/lazy-fallback.js +3 -0
  225. package/dist/src/gateway/hono/routes/lazy-fallback.js.map +1 -1
  226. package/dist/src/gateway/hono/routes/logs.js +39 -7
  227. package/dist/src/gateway/hono/routes/logs.js.map +1 -1
  228. package/dist/src/gateway/hono/routes/mcp.d.ts +3 -0
  229. package/dist/src/gateway/hono/routes/mcp.js +107 -0
  230. package/dist/src/gateway/hono/routes/mcp.js.map +1 -0
  231. package/dist/src/gateway/hono/routes/models.js +1 -1
  232. package/dist/src/gateway/hono/routes/sessions.js +6 -0
  233. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  234. package/dist/src/gateway/hono/routes/shares.js +1 -1
  235. package/dist/src/gateway/hono/routes/update.js +2 -4
  236. package/dist/src/gateway/hono/routes/update.js.map +1 -1
  237. package/dist/src/gateway/hono/routes/voice.js +2 -4
  238. package/dist/src/gateway/hono/routes/voice.js.map +1 -1
  239. package/dist/src/gateway/hono/routes/workspace.js +4 -6
  240. package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
  241. package/dist/src/gateway/hono/sse.js +9 -2
  242. package/dist/src/gateway/hono/sse.js.map +1 -1
  243. package/dist/src/gateway/lock.js +3 -3
  244. package/dist/src/gateway/ports.js +1 -1
  245. package/dist/src/gateway/service/agent-runner.js +3 -3
  246. package/dist/src/gateway/service/agent-runner.js.map +1 -1
  247. package/dist/src/gateway/service/config-coordinator.js +14 -6
  248. package/dist/src/gateway/service/config-coordinator.js.map +1 -1
  249. package/dist/src/gateway/service/marketplace-service.js +3 -3
  250. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  251. package/dist/src/gateway/service/run-gateway-agent.js +22 -5
  252. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  253. package/dist/src/gateway/service/sse-hub.js +1 -1
  254. package/dist/src/gateway/service/sse-hub.js.map +1 -1
  255. package/dist/src/gateway/service.js +13 -6
  256. package/dist/src/gateway/service.js.map +1 -1
  257. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  258. package/dist/src/heartbeat/index.js +1 -1
  259. package/dist/src/infra/brew.js +1 -1
  260. package/dist/src/infra/package-json.js +1 -1
  261. package/dist/src/infra/package-update-steps.js +1 -1
  262. package/dist/src/infra/path-env.js +2 -2
  263. package/dist/src/infra/restart.js +2 -2
  264. package/dist/src/infra/stable-node-path.js +1 -1
  265. package/dist/src/infra/update-check.js +1 -1
  266. package/dist/src/infra/update-global.js +1 -1
  267. package/dist/src/infra/update-lock.js +3 -3
  268. package/dist/src/infra/update-runner.js +1 -1
  269. package/dist/src/infra/update-startup.js +2 -2
  270. package/dist/src/infra/write-file-atomic.js +2 -2
  271. package/dist/src/mcp/channel-bridge.js +26 -2
  272. package/dist/src/mcp/channel-bridge.js.map +1 -1
  273. package/dist/src/mcp/gateway-http-client.js +24 -2
  274. package/dist/src/mcp/gateway-http-client.js.map +1 -1
  275. package/dist/src/notes/store.js +2 -2
  276. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  277. package/dist/src/providers/index.js +2 -2
  278. package/dist/src/providers/model-registry.js +1 -1
  279. package/dist/src/session/config-store.js +12 -6
  280. package/dist/src/session/config-store.js.map +1 -1
  281. package/dist/src/session/index.d.ts +1 -1
  282. package/dist/src/session/index.js +2 -2
  283. package/dist/src/session/init-session-turn.js +2 -2
  284. package/dist/src/session/manager.js +8 -1
  285. package/dist/src/session/manager.js.map +1 -1
  286. package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
  287. package/dist/src/session/parity/sessions-json-file.js +1 -1
  288. package/dist/src/session/parity/transcript-file-lock.js +2 -2
  289. package/dist/src/session/parity/transcript-paths.js +1 -1
  290. package/dist/src/session/resolve-session.js +4 -4
  291. package/dist/src/session/search-index-cache.js +1 -1
  292. package/dist/src/session/search-index.js +1 -1
  293. package/dist/src/session/session-title.d.ts +19 -3
  294. package/dist/src/session/session-title.js +84 -9
  295. package/dist/src/session/session-title.js.map +1 -1
  296. package/dist/src/session/store.js +6 -6
  297. package/dist/src/share/share-auto.js +2 -2
  298. package/dist/src/share/share-store.js +3 -3
  299. package/dist/src/share/share-thumbnail.js +2 -2
  300. package/dist/src/share/share-zip.js +1 -1
  301. package/dist/src/share/site-share-store.js +3 -3
  302. package/dist/src/share/site-static-serve.js +1 -1
  303. package/dist/src/tui/clipboard-image.js +3 -3
  304. package/dist/src/tui/theme-manager.js +1 -1
  305. package/dist/src/tui/tui-keybindings-file.js +1 -1
  306. package/dist/src/tui/tui-scoped-models.js +2 -2
  307. package/dist/src/tui/tui-settings.js +1 -1
  308. package/dist/src/tui/tui.js +3 -3
  309. package/dist/src/tunnel/frpc-binary.js +3 -3
  310. package/dist/src/tunnel/frpc-config.js +1 -1
  311. package/dist/src/tunnel/frpc-extract.js +1 -1
  312. package/dist/src/tunnel/tunnel-state.js +1 -1
  313. package/dist/src/utils/index.js +4 -4
  314. package/dist/src/utils/logger/audit.js +1 -1
  315. package/dist/src/utils/logger/config.js +2 -6
  316. package/dist/src/utils/logger/config.js.map +1 -1
  317. package/dist/src/utils/logger/context.d.ts +3 -22
  318. package/dist/src/utils/logger/context.js +4 -32
  319. package/dist/src/utils/logger/context.js.map +1 -1
  320. package/dist/src/utils/logger/index.d.ts +4 -7
  321. package/dist/src/utils/logger/index.js +9 -28
  322. package/dist/src/utils/logger/index.js.map +1 -1
  323. package/dist/src/utils/logger/log-store.d.ts +14 -32
  324. package/dist/src/utils/logger/log-store.js +68 -119
  325. package/dist/src/utils/logger/log-store.js.map +1 -1
  326. package/dist/src/utils/logger/log-stream.d.ts +5 -70
  327. package/dist/src/utils/logger/log-stream.js +67 -178
  328. package/dist/src/utils/logger/log-stream.js.map +1 -1
  329. package/dist/src/utils/logger/pino-record.d.ts +8 -0
  330. package/dist/src/utils/logger/pino-record.js +83 -0
  331. package/dist/src/utils/logger/pino-record.js.map +1 -0
  332. package/dist/src/utils/logger/rotation.js +1 -1
  333. package/dist/src/utils/logger/stats.d.ts +1 -1
  334. package/dist/src/utils/logger/stats.js +2 -2
  335. package/dist/src/utils/logger/stats.js.map +1 -1
  336. package/dist/src/utils/logger/streams.js +18 -0
  337. package/dist/src/utils/logger/streams.js.map +1 -1
  338. package/dist/src/utils/logger/types.d.ts +0 -9
  339. package/dist/src/utils/logger/types.js.map +1 -1
  340. package/dist/src/utils/logger.js +4 -4
  341. package/dist/src/voice/tts/audio.js +1 -1
  342. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  343. package/dist/src/workflows/store/event-store.js +1 -1
  344. package/dist/src/workflows/store/run-store.js +1 -1
  345. package/package.json +2 -1
  346. package/dist/gateway/static/root/assets/agents-C7tTJLP9.js +0 -222
  347. package/dist/gateway/static/root/assets/apps-page-BbzdMyrg.js +0 -1
  348. package/dist/gateway/static/root/assets/channels-settings-B49vG2hE.js +0 -1
  349. package/dist/gateway/static/root/assets/cron-page-Bjx7IOdR.js +0 -1
  350. package/dist/gateway/static/root/assets/index-CwDdudZM.css +0 -1
  351. package/dist/gateway/static/root/assets/logs-page-BxukQ-J-.js +0 -1
  352. package/dist/gateway/static/root/assets/sessions-page-BFD2_-Cl.js +0 -1
  353. package/dist/gateway/static/root/assets/settings-page-BiP5iH46.js +0 -2
  354. package/dist/gateway/static/root/assets/skills-page-CNDctFIn.js +0 -2
  355. package/dist/gateway/static/root/assets/voice-api-key-field-CalxUkxm.js +0 -1
  356. package/dist/gateway/static/root/assets/workflows-page-D2fRxXJG.js +0 -27
@@ -1,8 +1,12 @@
1
+ import { createLogger } from "../utils/logger/index.js";
2
+ import { init_logger } from "../utils/logger.js";
1
3
  import { init_loader, loadConfig } from "../config/loader.js";
2
4
  import { resolveGatewayLocalClientHost } from "../config/gateway-bind.js";
3
5
  import { fetch } from "undici";
4
6
  //#region src/mcp/gateway-http-client.ts
5
7
  init_loader();
8
+ init_logger();
9
+ const log = createLogger("Mcp:GatewayClient");
6
10
  function resolveGatewayTokenFromConfig(cfg) {
7
11
  const fromConfig = cfg.gateway?.auth?.token?.trim();
8
12
  if (fromConfig) return fromConfig;
@@ -22,7 +26,16 @@ var GatewayHttpClient = class {
22
26
  }
23
27
  async getJson(path) {
24
28
  const res = await fetch(`${this.opts.baseUrl}${path}`, { headers: this.headers() });
25
- if (!res.ok) throw new Error(`Gateway GET ${path} failed: ${res.status}`);
29
+ if (!res.ok) {
30
+ const em = `Gateway GET ${path} failed: ${res.status}`;
31
+ log.warn({
32
+ phase: "mcp.gateway.http",
33
+ method: "GET",
34
+ path,
35
+ status: res.status
36
+ }, em);
37
+ throw new Error(em);
38
+ }
26
39
  const body = await res.json();
27
40
  if (body && typeof body === "object" && "payload" in body) return body.payload;
28
41
  return body;
@@ -33,7 +46,16 @@ var GatewayHttpClient = class {
33
46
  headers: this.headers({ "Content-Type": "application/json" }),
34
47
  body: JSON.stringify(data)
35
48
  });
36
- if (!res.ok) throw new Error(`Gateway POST ${path} failed: ${res.status}`);
49
+ if (!res.ok) {
50
+ const em = `Gateway POST ${path} failed: ${res.status}`;
51
+ log.warn({
52
+ phase: "mcp.gateway.http",
53
+ method: "POST",
54
+ path,
55
+ status: res.status
56
+ }, em);
57
+ throw new Error(em);
58
+ }
37
59
  const body = await res.json();
38
60
  if (body && typeof body === "object" && "payload" in body) return body.payload;
39
61
  return body;
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-http-client.js","names":["undiciFetch"],"sources":["../../../src/mcp/gateway-http-client.ts"],"sourcesContent":["import { fetch as undiciFetch } from 'undici';\nimport { resolveGatewayLocalClientHost } from '../config/gateway-bind.js';\nimport type { Config } from '../config/schema.js';\nimport { loadConfig } from '../config/loader.js';\n\nfunction resolveGatewayTokenFromConfig(cfg: Config): string | undefined {\n const fromConfig = cfg.gateway?.auth?.token?.trim();\n if (fromConfig) {\n return fromConfig;\n }\n return process.env.XOPC_GATEWAY_TOKEN?.trim() || undefined;\n}\n\nexport type GatewayHttpClientOptions = {\n baseUrl: string;\n token?: string;\n};\n\nexport class GatewayHttpClient {\n constructor(private readonly opts: GatewayHttpClientOptions) {}\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n const h: Record<string, string> = { Accept: 'application/json', ...extra };\n if (this.opts.token) {\n h.Authorization = `Bearer ${this.opts.token}`;\n }\n return h;\n }\n\n async getJson<T>(path: string): Promise<T> {\n const res = await undiciFetch(`${this.opts.baseUrl}${path}`, {\n headers: this.headers(),\n });\n if (!res.ok) {\n throw new Error(`Gateway GET ${path} failed: ${res.status}`);\n }\n const body = (await res.json()) as { ok?: boolean; payload?: T } | T;\n if (body && typeof body === 'object' && 'payload' in body) {\n return (body as { payload: T }).payload;\n }\n return body as T;\n }\n\n async postJson<T>(path: string, data: unknown): Promise<T> {\n const res = await undiciFetch(`${this.opts.baseUrl}${path}`, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(data),\n });\n if (!res.ok) {\n throw new Error(`Gateway POST ${path} failed: ${res.status}`);\n }\n const body = (await res.json()) as { ok?: boolean; payload?: T } | T;\n if (body && typeof body === 'object' && 'payload' in body) {\n return (body as { payload: T }).payload;\n }\n return body as T;\n }\n}\n\nexport function resolveGatewayHttpBaseUrl(config: Config, override?: string): string {\n if (override?.trim()) {\n return override.replace(/\\/$/, '');\n }\n const host = resolveGatewayLocalClientHost(config);\n const port = config.gateway?.port ?? 18790;\n return `http://${host}:${port}`;\n}\n\nexport function createGatewayHttpClientFromConfig(params: {\n config?: Config;\n gatewayUrl?: string;\n gatewayToken?: string;\n}): GatewayHttpClient {\n const cfg = params.config ?? loadConfig();\n const token = params.gatewayToken ?? resolveGatewayTokenFromConfig(cfg) ?? undefined;\n return new GatewayHttpClient({\n baseUrl: resolveGatewayHttpBaseUrl(cfg, params.gatewayUrl),\n token,\n });\n}\n"],"mappings":";;;;aAGiD;AAEjD,SAAS,8BAA8B,KAAiC;CACtE,MAAM,aAAa,IAAI,SAAS,MAAM,OAAO,MAAM;AACnD,KAAI,WACF,QAAO;AAET,QAAO,QAAQ,IAAI,oBAAoB,MAAM,IAAI,KAAA;;AAQnD,IAAa,oBAAb,MAA+B;CAC7B,YAAY,MAAiD;AAAhC,OAAA,OAAA;;CAE7B,QAAgB,OAAwD;EACtE,MAAM,IAA4B;GAAE,QAAQ;GAAoB,GAAG;GAAO;AAC1E,MAAI,KAAK,KAAK,MACZ,GAAE,gBAAgB,UAAU,KAAK,KAAK;AAExC,SAAO;;CAGT,MAAM,QAAW,MAA0B;EACzC,MAAM,MAAM,MAAMA,MAAY,GAAG,KAAK,KAAK,UAAU,QAAQ,EAC3D,SAAS,KAAK,SAAS,EACxB,CAAC;AACF,MAAI,CAAC,IAAI,GACP,OAAM,IAAI,MAAM,eAAe,KAAK,WAAW,IAAI,SAAS;EAE9D,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,MAAI,QAAQ,OAAO,SAAS,YAAY,aAAa,KACnD,QAAQ,KAAwB;AAElC,SAAO;;CAGT,MAAM,SAAY,MAAc,MAA2B;EACzD,MAAM,MAAM,MAAMA,MAAY,GAAG,KAAK,KAAK,UAAU,QAAQ;GAC3D,QAAQ;GACR,SAAS,KAAK,QAAQ,EAAE,gBAAgB,oBAAoB,CAAC;GAC7D,MAAM,KAAK,UAAU,KAAK;GAC3B,CAAC;AACF,MAAI,CAAC,IAAI,GACP,OAAM,IAAI,MAAM,gBAAgB,KAAK,WAAW,IAAI,SAAS;EAE/D,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,MAAI,QAAQ,OAAO,SAAS,YAAY,aAAa,KACnD,QAAQ,KAAwB;AAElC,SAAO;;;AAIX,SAAgB,0BAA0B,QAAgB,UAA2B;AACnF,KAAI,UAAU,MAAM,CAClB,QAAO,SAAS,QAAQ,OAAO,GAAG;AAIpC,QAAO,UAFM,8BAA8B,OAEtB,CAAC,GADT,OAAO,SAAS,QAAQ;;AAIvC,SAAgB,kCAAkC,QAI5B;CACpB,MAAM,MAAM,OAAO,UAAU,YAAY;CACzC,MAAM,QAAQ,OAAO,gBAAgB,8BAA8B,IAAI,IAAI,KAAA;AAC3E,QAAO,IAAI,kBAAkB;EAC3B,SAAS,0BAA0B,KAAK,OAAO,WAAW;EAC1D;EACD,CAAC"}
1
+ {"version":3,"file":"gateway-http-client.js","names":["undiciFetch"],"sources":["../../../src/mcp/gateway-http-client.ts"],"sourcesContent":["import { fetch as undiciFetch } from 'undici';\nimport { resolveGatewayLocalClientHost } from '../config/gateway-bind.js';\nimport type { Config } from '../config/schema.js';\nimport { loadConfig } from '../config/loader.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst log = createLogger('Mcp:GatewayClient');\n\nfunction resolveGatewayTokenFromConfig(cfg: Config): string | undefined {\n const fromConfig = cfg.gateway?.auth?.token?.trim();\n if (fromConfig) {\n return fromConfig;\n }\n return process.env.XOPC_GATEWAY_TOKEN?.trim() || undefined;\n}\n\nexport type GatewayHttpClientOptions = {\n baseUrl: string;\n token?: string;\n};\n\nexport class GatewayHttpClient {\n constructor(private readonly opts: GatewayHttpClientOptions) {}\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n const h: Record<string, string> = { Accept: 'application/json', ...extra };\n if (this.opts.token) {\n h.Authorization = `Bearer ${this.opts.token}`;\n }\n return h;\n }\n\n async getJson<T>(path: string): Promise<T> {\n const res = await undiciFetch(`${this.opts.baseUrl}${path}`, {\n headers: this.headers(),\n });\n if (!res.ok) {\n const em = `Gateway GET ${path} failed: ${res.status}`;\n log.warn({ phase: 'mcp.gateway.http', method: 'GET', path, status: res.status }, em);\n throw new Error(em);\n }\n const body = (await res.json()) as { ok?: boolean; payload?: T } | T;\n if (body && typeof body === 'object' && 'payload' in body) {\n return (body as { payload: T }).payload;\n }\n return body as T;\n }\n\n async postJson<T>(path: string, data: unknown): Promise<T> {\n const res = await undiciFetch(`${this.opts.baseUrl}${path}`, {\n method: 'POST',\n headers: this.headers({ 'Content-Type': 'application/json' }),\n body: JSON.stringify(data),\n });\n if (!res.ok) {\n const em = `Gateway POST ${path} failed: ${res.status}`;\n log.warn({ phase: 'mcp.gateway.http', method: 'POST', path, status: res.status }, em);\n throw new Error(em);\n }\n const body = (await res.json()) as { ok?: boolean; payload?: T } | T;\n if (body && typeof body === 'object' && 'payload' in body) {\n return (body as { payload: T }).payload;\n }\n return body as T;\n }\n}\n\nexport function resolveGatewayHttpBaseUrl(config: Config, override?: string): string {\n if (override?.trim()) {\n return override.replace(/\\/$/, '');\n }\n const host = resolveGatewayLocalClientHost(config);\n const port = config.gateway?.port ?? 18790;\n return `http://${host}:${port}`;\n}\n\nexport function createGatewayHttpClientFromConfig(params: {\n config?: Config;\n gatewayUrl?: string;\n gatewayToken?: string;\n}): GatewayHttpClient {\n const cfg = params.config ?? loadConfig();\n const token = params.gatewayToken ?? resolveGatewayTokenFromConfig(cfg) ?? undefined;\n return new GatewayHttpClient({\n baseUrl: resolveGatewayHttpBaseUrl(cfg, params.gatewayUrl),\n token,\n });\n}\n"],"mappings":";;;;;;aAGiD;aACC;AAElD,MAAM,MAAM,aAAa,oBAAoB;AAE7C,SAAS,8BAA8B,KAAiC;CACtE,MAAM,aAAa,IAAI,SAAS,MAAM,OAAO,MAAM;AACnD,KAAI,WACF,QAAO;AAET,QAAO,QAAQ,IAAI,oBAAoB,MAAM,IAAI,KAAA;;AAQnD,IAAa,oBAAb,MAA+B;CAC7B,YAAY,MAAiD;AAAhC,OAAA,OAAA;;CAE7B,QAAgB,OAAwD;EACtE,MAAM,IAA4B;GAAE,QAAQ;GAAoB,GAAG;GAAO;AAC1E,MAAI,KAAK,KAAK,MACZ,GAAE,gBAAgB,UAAU,KAAK,KAAK;AAExC,SAAO;;CAGT,MAAM,QAAW,MAA0B;EACzC,MAAM,MAAM,MAAMA,MAAY,GAAG,KAAK,KAAK,UAAU,QAAQ,EAC3D,SAAS,KAAK,SAAS,EACxB,CAAC;AACF,MAAI,CAAC,IAAI,IAAI;GACX,MAAM,KAAK,eAAe,KAAK,WAAW,IAAI;AAC9C,OAAI,KAAK;IAAE,OAAO;IAAoB,QAAQ;IAAO;IAAM,QAAQ,IAAI;IAAQ,EAAE,GAAG;AACpF,SAAM,IAAI,MAAM,GAAG;;EAErB,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,MAAI,QAAQ,OAAO,SAAS,YAAY,aAAa,KACnD,QAAQ,KAAwB;AAElC,SAAO;;CAGT,MAAM,SAAY,MAAc,MAA2B;EACzD,MAAM,MAAM,MAAMA,MAAY,GAAG,KAAK,KAAK,UAAU,QAAQ;GAC3D,QAAQ;GACR,SAAS,KAAK,QAAQ,EAAE,gBAAgB,oBAAoB,CAAC;GAC7D,MAAM,KAAK,UAAU,KAAK;GAC3B,CAAC;AACF,MAAI,CAAC,IAAI,IAAI;GACX,MAAM,KAAK,gBAAgB,KAAK,WAAW,IAAI;AAC/C,OAAI,KAAK;IAAE,OAAO;IAAoB,QAAQ;IAAQ;IAAM,QAAQ,IAAI;IAAQ,EAAE,GAAG;AACrF,SAAM,IAAI,MAAM,GAAG;;EAErB,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,MAAI,QAAQ,OAAO,SAAS,YAAY,aAAa,KACnD,QAAQ,KAAwB;AAElC,SAAO;;;AAIX,SAAgB,0BAA0B,QAAgB,UAA2B;AACnF,KAAI,UAAU,MAAM,CAClB,QAAO,SAAS,QAAQ,OAAO,GAAG;AAIpC,QAAO,UAFM,8BAA8B,OAEtB,CAAC,GADT,OAAO,SAAS,QAAQ;;AAIvC,SAAgB,kCAAkC,QAI5B;CACpB,MAAM,MAAM,OAAO,UAAU,YAAY;CACzC,MAAM,QAAQ,OAAO,gBAAgB,8BAA8B,IAAI,IAAI,KAAA;AAC3E,QAAO,IAAI,kBAAkB;EAC3B,SAAS,0BAA0B,KAAK,OAAO,WAAW;EAC1D;EACD,CAAC"}
@@ -1,11 +1,11 @@
1
- import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
2
1
  import { createLogger } from "../utils/logger/index.js";
3
2
  import { init_logger } from "../utils/logger.js";
3
+ import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
4
4
  import { buildNoteIndexMeta, notePlainText } from "./note-index-meta.js";
5
5
  import { resolveNoteHistoryDir, resolveNoteItemPath, resolveNoteMediaDir, resolveNotesDir, resolveNotesIndexPath } from "./paths.js";
6
+ import { join } from "node:path";
6
7
  import { randomUUID } from "node:crypto";
7
8
  import { access, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
8
- import { join } from "node:path";
9
9
  //#region src/notes/store.ts
10
10
  init_write_file_atomic();
11
11
  init_logger();
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
4
3
  import { dirname, join } from "node:path";
4
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
5
5
  //#region src/providers/auth-runtime/auth-profile-store.ts
6
6
  /**
7
7
  * {@link AuthProfileStore} implementations.
@@ -1,8 +1,8 @@
1
1
  import { __esmMin, __exportAll } from "../../_virtual/_rolldown/runtime.js";
2
- import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
3
- import { CredentialResolver, hasCredentials, init_credentials, resolveApiKey } from "../auth/credentials.js";
4
2
  import { hasProviderAuthOnDiskSync, init_sync_provider_auth } from "../auth/sync-provider-auth.js";
3
+ import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
5
4
  import { ModelRegistry, getModelRegistry, init_model_registry, prewarmModelRegistry, resetModelRegistry } from "./model-registry.js";
5
+ import { CredentialResolver, hasCredentials, init_credentials, resolveApiKey } from "../auth/credentials.js";
6
6
  import { getProviderRegistry, init_plugin_registry } from "./plugin-registry.js";
7
7
  import { getModel, getModels, getProviders } from "@earendil-works/pi-ai";
8
8
  //#region src/providers/index.ts
@@ -1,10 +1,10 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { createLogger } from "../utils/logger/index.js";
3
3
  import { init_logger } from "../utils/logger.js";
4
- import { getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
5
4
  import { resolveModelsJsonPath } from "../config/paths.js";
6
5
  import { init_resolve_config_value, resolveConfigValue, resolveHeaders } from "../config/resolve-config-value.js";
7
6
  import { getDefaultModelValues, init_models_json, validateModelsConfig } from "../config/models-json.js";
7
+ import { getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
8
8
  import { existsSync, readFileSync } from "fs";
9
9
  import { getModels, getProviders } from "@earendil-works/pi-ai";
10
10
  //#region src/providers/model-registry.ts
@@ -1,9 +1,9 @@
1
- import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
2
1
  import { createLogger } from "../utils/logger/index.js";
3
2
  import { init_logger } from "../utils/logger.js";
4
- import { mkdir, readFile } from "fs/promises";
3
+ import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
5
4
  import { join } from "path";
6
5
  import { existsSync } from "fs";
6
+ import { mkdir, readFile } from "fs/promises";
7
7
  //#region src/session/config-store.ts
8
8
  /**
9
9
  * Session Config Store
@@ -49,10 +49,13 @@ var SessionConfigStore = class {
49
49
  const content = await readFile(configPath, "utf-8");
50
50
  return JSON.parse(content);
51
51
  } catch (error) {
52
+ const em = error instanceof Error ? error.message : String(error);
52
53
  log.error({
54
+ err: error,
55
+ errorMessage: em,
53
56
  sessionKey,
54
- error
55
- }, "Failed to read session config");
57
+ phase: "session.config"
58
+ }, `Failed to read session config: ${em}`);
56
59
  return null;
57
60
  }
58
61
  }
@@ -69,10 +72,13 @@ var SessionConfigStore = class {
69
72
  await writeTextAtomic(configPath, JSON.stringify(configWithTimestamp, null, 2));
70
73
  log.debug({ sessionKey }, "Session config saved");
71
74
  } catch (error) {
75
+ const em = error instanceof Error ? error.message : String(error);
72
76
  log.error({
77
+ err: error,
78
+ errorMessage: em,
73
79
  sessionKey,
74
- error
75
- }, "Failed to save session config");
80
+ phase: "session.config"
81
+ }, `Failed to save session config: ${em}`);
76
82
  throw error;
77
83
  }
78
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config-store.js","names":[],"sources":["../../../src/session/config-store.ts"],"sourcesContent":["/**\n * Session Config Store\n * \n * Manages session-level configuration persistence.\n * Stores thinking level, reasoning visibility, verbose mode, and other\n * session-specific settings that can be overridden via commands.\n */\n\nimport { readFile, mkdir } from 'fs/promises';\nimport { writeTextAtomic } from '../infra/write-file-atomic.js';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport { createLogger } from '../utils/logger.js';\nimport type { ThinkLevel, ReasoningLevel, VerboseLevel, ElevatedMode } from '../agent/transcript/thinking-types.js';\n\nconst log = createLogger('SessionConfigStore');\n\n/**\n * Session-level agent configuration.\n * These settings override agent defaults for a specific session.\n */\nexport interface SessionAgentConfig {\n /** Thinking level for this session */\n thinkingLevel?: ThinkLevel;\n /** Reasoning visibility for this session */\n reasoningLevel?: ReasoningLevel;\n /** Verbose level for this session */\n verboseLevel?: VerboseLevel;\n /** Elevated mode for this session */\n elevatedMode?: ElevatedMode;\n /** Model override for this session */\n modelOverride?: string;\n /** Provider override for this session */\n providerOverride?: string;\n /** Absolute markdown workspace root for this session (set once; immutable after save). */\n workingDirectoryOverride?: string;\n /** Last updated timestamp */\n updatedAt?: number;\n}\n\n/**\n * Session config store manager.\n * Each session can have its own configuration that overrides agent defaults.\n */\nexport class SessionConfigStore {\n private configDir: string;\n\n /** @param agentHomeDir — `resolveAgentHomeDir(…)` (parent of `sessions/` transcript store) */\n constructor(agentHomeDir: string) {\n this.configDir = join(agentHomeDir, 'sessions', 'config');\n }\n\n /**\n * Initialize the config store\n */\n async initialize(): Promise<void> {\n await mkdir(this.configDir, { recursive: true });\n log.debug('Session config store initialized');\n }\n\n /**\n * Get the config file path for a session\n */\n private getConfigPath(sessionKey: string): string {\n // Sanitize session key to be a valid filename\n const safeKey = sessionKey.replace(/[^a-zA-Z0-9_-]/g, '_');\n return join(this.configDir, `${safeKey}.json`);\n }\n\n /**\n * Get config for a session\n */\n async get(sessionKey: string): Promise<SessionAgentConfig | null> {\n const configPath = this.getConfigPath(sessionKey);\n \n if (!existsSync(configPath)) {\n return null;\n }\n\n try {\n const content = await readFile(configPath, 'utf-8');\n const config = JSON.parse(content) as SessionAgentConfig;\n return config;\n } catch (error) {\n log.error({ sessionKey, error }, 'Failed to read session config');\n return null;\n }\n }\n\n /**\n * Set config for a session (full replacement)\n */\n async set(sessionKey: string, config: SessionAgentConfig): Promise<void> {\n const configPath = this.getConfigPath(sessionKey);\n const configWithTimestamp = {\n ...config,\n updatedAt: Date.now(),\n };\n\n try {\n await writeTextAtomic(configPath, JSON.stringify(configWithTimestamp, null, 2));\n log.debug({ sessionKey }, 'Session config saved');\n } catch (error) {\n log.error({ sessionKey, error }, 'Failed to save session config');\n throw error;\n }\n }\n\n /**\n * Update config for a session (partial update)\n */\n async update(sessionKey: string, partial: Partial<SessionAgentConfig>): Promise<SessionAgentConfig> {\n const existing = await this.get(sessionKey);\n const updated = {\n ...existing,\n ...partial,\n updatedAt: Date.now(),\n };\n \n await this.set(sessionKey, updated);\n return updated;\n }\n\n /**\n * Delete config for a session\n */\n async delete(sessionKey: string): Promise<void> {\n const configPath = this.getConfigPath(sessionKey);\n \n if (existsSync(configPath)) {\n try {\n const { unlink } = await import('fs/promises');\n await unlink(configPath);\n log.debug({ sessionKey }, 'Session config deleted');\n } catch (error) {\n log.error({ sessionKey, error }, 'Failed to delete session config');\n throw error;\n }\n }\n }\n\n /**\n * Check if config exists for a session\n */\n async has(sessionKey: string): Promise<boolean> {\n const configPath = this.getConfigPath(sessionKey);\n return existsSync(configPath);\n }\n\n /**\n * Get all session configs\n */\n async getAll(): Promise<Map<string, SessionAgentConfig>> {\n const { readdir } = await import('fs/promises');\n const configs = new Map<string, SessionAgentConfig>();\n\n try {\n const files = await readdir(this.configDir);\n \n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n \n const sessionKey = file.replace('.json', '').replace(/_/g, '-');\n const config = await this.get(sessionKey);\n \n if (config) {\n configs.set(sessionKey, config);\n }\n }\n } catch (error) {\n log.error({ error }, 'Failed to list session configs');\n }\n\n return configs;\n }\n\n /**\n * Clear all session configs\n */\n async clear(): Promise<void> {\n const { readdir, rm } = await import('fs/promises');\n \n try {\n const files = await readdir(this.configDir);\n \n for (const file of files) {\n if (file.endsWith('.json')) {\n await rm(join(this.configDir, file), { force: true });\n }\n }\n \n log.debug('All session configs cleared');\n } catch (error) {\n log.error({ error }, 'Failed to clear session configs');\n throw error;\n }\n }\n}\n\n// ========== Helper Functions ==========\n\n/**\n * Resolve thinking level for a session.\n * Returns session config if set, otherwise falls back to agent defaults.\n */\nexport async function resolveThinkingLevel(\n sessionConfigStore: SessionConfigStore,\n sessionKey: string,\n agentDefault?: ThinkLevel\n): Promise<ThinkLevel | undefined> {\n const config = await sessionConfigStore.get(sessionKey);\n \n if (config?.thinkingLevel) {\n return config.thinkingLevel;\n }\n \n return agentDefault;\n}\n\n/**\n * Resolve reasoning level for a session.\n */\nexport async function resolveReasoningLevel(\n sessionConfigStore: SessionConfigStore,\n sessionKey: string,\n agentDefault?: ReasoningLevel\n): Promise<ReasoningLevel | undefined> {\n const config = await sessionConfigStore.get(sessionKey);\n \n if (config?.reasoningLevel) {\n return config.reasoningLevel;\n }\n \n return agentDefault;\n}\n\n/**\n * Resolve verbose level for a session.\n */\nexport async function resolveVerboseLevel(\n sessionConfigStore: SessionConfigStore,\n sessionKey: string,\n agentDefault?: VerboseLevel\n): Promise<VerboseLevel | undefined> {\n const config = await sessionConfigStore.get(sessionKey);\n \n if (config?.verboseLevel) {\n return config.verboseLevel;\n }\n \n return agentDefault;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"config-store.js","names":[],"sources":["../../../src/session/config-store.ts"],"sourcesContent":["/**\n * Session Config Store\n * \n * Manages session-level configuration persistence.\n * Stores thinking level, reasoning visibility, verbose mode, and other\n * session-specific settings that can be overridden via commands.\n */\n\nimport { readFile, mkdir } from 'fs/promises';\nimport { writeTextAtomic } from '../infra/write-file-atomic.js';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport { createLogger } from '../utils/logger.js';\nimport type { ThinkLevel, ReasoningLevel, VerboseLevel, ElevatedMode } from '../agent/transcript/thinking-types.js';\n\nconst log = createLogger('SessionConfigStore');\n\n/**\n * Session-level agent configuration.\n * These settings override agent defaults for a specific session.\n */\nexport interface SessionAgentConfig {\n /** Thinking level for this session */\n thinkingLevel?: ThinkLevel;\n /** Reasoning visibility for this session */\n reasoningLevel?: ReasoningLevel;\n /** Verbose level for this session */\n verboseLevel?: VerboseLevel;\n /** Elevated mode for this session */\n elevatedMode?: ElevatedMode;\n /** Model override for this session */\n modelOverride?: string;\n /** Provider override for this session */\n providerOverride?: string;\n /** Absolute markdown workspace root for this session (set once; immutable after save). */\n workingDirectoryOverride?: string;\n /** Last updated timestamp */\n updatedAt?: number;\n}\n\n/**\n * Session config store manager.\n * Each session can have its own configuration that overrides agent defaults.\n */\nexport class SessionConfigStore {\n private configDir: string;\n\n /** @param agentHomeDir — `resolveAgentHomeDir(…)` (parent of `sessions/` transcript store) */\n constructor(agentHomeDir: string) {\n this.configDir = join(agentHomeDir, 'sessions', 'config');\n }\n\n /**\n * Initialize the config store\n */\n async initialize(): Promise<void> {\n await mkdir(this.configDir, { recursive: true });\n log.debug('Session config store initialized');\n }\n\n /**\n * Get the config file path for a session\n */\n private getConfigPath(sessionKey: string): string {\n // Sanitize session key to be a valid filename\n const safeKey = sessionKey.replace(/[^a-zA-Z0-9_-]/g, '_');\n return join(this.configDir, `${safeKey}.json`);\n }\n\n /**\n * Get config for a session\n */\n async get(sessionKey: string): Promise<SessionAgentConfig | null> {\n const configPath = this.getConfigPath(sessionKey);\n \n if (!existsSync(configPath)) {\n return null;\n }\n\n try {\n const content = await readFile(configPath, 'utf-8');\n const config = JSON.parse(content) as SessionAgentConfig;\n return config;\n } catch (error) {\n const em = error instanceof Error ? error.message : String(error);\n log.error({ err: error, errorMessage: em, sessionKey, phase: 'session.config' }, `Failed to read session config: ${em}`);\n return null;\n }\n }\n\n /**\n * Set config for a session (full replacement)\n */\n async set(sessionKey: string, config: SessionAgentConfig): Promise<void> {\n const configPath = this.getConfigPath(sessionKey);\n const configWithTimestamp = {\n ...config,\n updatedAt: Date.now(),\n };\n\n try {\n await writeTextAtomic(configPath, JSON.stringify(configWithTimestamp, null, 2));\n log.debug({ sessionKey }, 'Session config saved');\n } catch (error) {\n const em = error instanceof Error ? error.message : String(error);\n log.error({ err: error, errorMessage: em, sessionKey, phase: 'session.config' }, `Failed to save session config: ${em}`);\n throw error;\n }\n }\n\n /**\n * Update config for a session (partial update)\n */\n async update(sessionKey: string, partial: Partial<SessionAgentConfig>): Promise<SessionAgentConfig> {\n const existing = await this.get(sessionKey);\n const updated = {\n ...existing,\n ...partial,\n updatedAt: Date.now(),\n };\n \n await this.set(sessionKey, updated);\n return updated;\n }\n\n /**\n * Delete config for a session\n */\n async delete(sessionKey: string): Promise<void> {\n const configPath = this.getConfigPath(sessionKey);\n \n if (existsSync(configPath)) {\n try {\n const { unlink } = await import('fs/promises');\n await unlink(configPath);\n log.debug({ sessionKey }, 'Session config deleted');\n } catch (error) {\n log.error({ sessionKey, error }, 'Failed to delete session config');\n throw error;\n }\n }\n }\n\n /**\n * Check if config exists for a session\n */\n async has(sessionKey: string): Promise<boolean> {\n const configPath = this.getConfigPath(sessionKey);\n return existsSync(configPath);\n }\n\n /**\n * Get all session configs\n */\n async getAll(): Promise<Map<string, SessionAgentConfig>> {\n const { readdir } = await import('fs/promises');\n const configs = new Map<string, SessionAgentConfig>();\n\n try {\n const files = await readdir(this.configDir);\n \n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n \n const sessionKey = file.replace('.json', '').replace(/_/g, '-');\n const config = await this.get(sessionKey);\n \n if (config) {\n configs.set(sessionKey, config);\n }\n }\n } catch (error) {\n log.error({ error }, 'Failed to list session configs');\n }\n\n return configs;\n }\n\n /**\n * Clear all session configs\n */\n async clear(): Promise<void> {\n const { readdir, rm } = await import('fs/promises');\n \n try {\n const files = await readdir(this.configDir);\n \n for (const file of files) {\n if (file.endsWith('.json')) {\n await rm(join(this.configDir, file), { force: true });\n }\n }\n \n log.debug('All session configs cleared');\n } catch (error) {\n log.error({ error }, 'Failed to clear session configs');\n throw error;\n }\n }\n}\n\n// ========== Helper Functions ==========\n\n/**\n * Resolve thinking level for a session.\n * Returns session config if set, otherwise falls back to agent defaults.\n */\nexport async function resolveThinkingLevel(\n sessionConfigStore: SessionConfigStore,\n sessionKey: string,\n agentDefault?: ThinkLevel\n): Promise<ThinkLevel | undefined> {\n const config = await sessionConfigStore.get(sessionKey);\n \n if (config?.thinkingLevel) {\n return config.thinkingLevel;\n }\n \n return agentDefault;\n}\n\n/**\n * Resolve reasoning level for a session.\n */\nexport async function resolveReasoningLevel(\n sessionConfigStore: SessionConfigStore,\n sessionKey: string,\n agentDefault?: ReasoningLevel\n): Promise<ReasoningLevel | undefined> {\n const config = await sessionConfigStore.get(sessionKey);\n \n if (config?.reasoningLevel) {\n return config.reasoningLevel;\n }\n \n return agentDefault;\n}\n\n/**\n * Resolve verbose level for a session.\n */\nexport async function resolveVerboseLevel(\n sessionConfigStore: SessionConfigStore,\n sessionKey: string,\n agentDefault?: VerboseLevel\n): Promise<VerboseLevel | undefined> {\n const config = await sessionConfigStore.get(sessionKey);\n \n if (config?.verboseLevel) {\n return config.verboseLevel;\n }\n \n return agentDefault;\n}\n"],"mappings":"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"}
@@ -19,7 +19,7 @@ export { initSessionTurn, type InitSessionTurnOptions, type InitSessionTurnResul
19
19
  export { DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, bareResetAckMessage, matchResetTriggers, resolveResetTriggers, shouldSkipResetOverlapCommand, stripLeadingEnvelopeTimestamp, type ResetTriggerMatch, } from './reset-triggers.js';
20
20
  export type { CompactionConfig, CompactionResult } from '../agent/memory/compaction.js';
21
21
  export type { WindowConfig } from '../agent/memory/window.js';
22
- export { maybeAutoTitleSessionStore, generateSessionTitleFromMessages, sanitizeSessionTitle, fallbackTitleFromMessages, isWebchatSessionKey, shouldAutoTitleSessionKey, } from './session-title.js';
22
+ export { maybeSetProvisionalSessionTitle, maybeRefineSessionTitleWithLlm, generateSessionTitleFromMessages, sanitizeSessionTitle, provisionalTitleFromUserText, fallbackTitleFromMessages, getSessionTitleSource, shouldRefineSessionTitleWithLlm, isWebchatSessionKey, shouldAutoTitleSessionKey, type SessionTitleSource, } from './session-title.js';
23
23
  export { messagesToClientHistory, flattenMessageContent, type ClientHistoryMessage } from './client-history.js';
24
24
  export { XOPC_SESSION_TRANSCRIPT_TYPE, CURRENT_SESSION_TRANSCRIPT_VERSION, } from './transcript-format.js';
25
25
  export { buildSessionContextForLlm, isTranscriptContextEntry, mergeLlmMessagesPreservingContextRows, transcriptRowsFromJsonArray, type TranscriptStoredRow, type XopcTranscriptContextEntry, } from './session-context-for-llm.js';
@@ -2,7 +2,7 @@ import { emitSessionTranscriptUpdate, onSessionTranscriptUpdate } from "./transc
2
2
  import { buildSessionContextForLlm, isTranscriptContextEntry, mergeLlmMessagesPreservingContextRows, transcriptRowsFromJsonArray } from "./session-context-for-llm.js";
3
3
  import { SessionSearchIndex } from "./search-index.js";
4
4
  import { getOrLoadSessionSearchIndex, invalidateSessionSearchIndexCache } from "./search-index-cache.js";
5
- import { fallbackTitleFromMessages, generateSessionTitleFromMessages, isWebchatSessionKey, maybeAutoTitleSessionStore, sanitizeSessionTitle, shouldAutoTitleSessionKey } from "./session-title.js";
5
+ import { fallbackTitleFromMessages, generateSessionTitleFromMessages, getSessionTitleSource, isWebchatSessionKey, maybeRefineSessionTitleWithLlm, maybeSetProvisionalSessionTitle, provisionalTitleFromUserText, sanitizeSessionTitle, shouldAutoTitleSessionKey, shouldRefineSessionTitleWithLlm } from "./session-title.js";
6
6
  import { normalizeCompactionCheckpointId } from "./compaction-checkpoints.js";
7
7
  import { SessionStatus } from "./types.js";
8
8
  import { SessionStore } from "./store.js";
@@ -20,4 +20,4 @@ import { DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, bareResetAckMessage, ma
20
20
  import { initSessionTurn } from "./init-session-turn.js";
21
21
  import { flattenMessageContent, messagesToClientHistory } from "./client-history.js";
22
22
  import { CURRENT_SESSION_TRANSCRIPT_VERSION, XOPC_SESSION_TRANSCRIPT_TYPE } from "./transcript-format.js";
23
- export { CURRENT_SESSION_TRANSCRIPT_VERSION, DEFAULT_IDLE_MINUTES, DEFAULT_RESET_AT_HOUR, DEFAULT_RESET_MODE, DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, SessionConfigStore, SessionIndex, SessionSearchIndex, SessionStatus, SessionStore, XOPC_SESSION_TRANSCRIPT_TYPE, applySessionPatchToMetadata, bareResetAckMessage, buildSessionContextForLlm, effectiveWorkspacePathForSession, emitSessionTranscriptUpdate, evaluateSessionFreshness, fallbackTitleFromMessages, flattenMessageContent, generateSessionTitleFromMessages, getOrLoadSessionSearchIndex, initSessionTurn, invalidateSessionSearchIndexCache, isThreadSessionKey, isTranscriptContextEntry, isWebchatSessionKey, matchResetTriggers, maybeAutoTitleSessionStore, mergeLlmMessagesPreservingContextRows, messagesToClientHistory, normalizeCompactionCheckpointId, normalizeWorkingDirectoryInput, onSessionTranscriptUpdate, resolveChannelResetConfig, resolveDailyResetAtMs, resolveEffectiveReasoningLevel, resolveEffectiveThinkingLevel, resolveReasoningLevel, resolveResetTriggers, resolveSession, resolveSessionKeyForRequest, resolveSessionLifecycleTimestamps, resolveSessionResetPolicy, resolveSessionResetType, resolveThinkingLevel, resolveVerboseLevel, sanitizeSessionTitle, shouldAutoTitleSessionKey, shouldSkipResetOverlapCommand, shouldSkipWebchatInboundByAbortCutoff, stripLeadingEnvelopeTimestamp, transcriptRowsFromJsonArray };
23
+ export { CURRENT_SESSION_TRANSCRIPT_VERSION, DEFAULT_IDLE_MINUTES, DEFAULT_RESET_AT_HOUR, DEFAULT_RESET_MODE, DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, SessionConfigStore, SessionIndex, SessionSearchIndex, SessionStatus, SessionStore, XOPC_SESSION_TRANSCRIPT_TYPE, applySessionPatchToMetadata, bareResetAckMessage, buildSessionContextForLlm, effectiveWorkspacePathForSession, emitSessionTranscriptUpdate, evaluateSessionFreshness, fallbackTitleFromMessages, flattenMessageContent, generateSessionTitleFromMessages, getOrLoadSessionSearchIndex, getSessionTitleSource, initSessionTurn, invalidateSessionSearchIndexCache, isThreadSessionKey, isTranscriptContextEntry, isWebchatSessionKey, matchResetTriggers, maybeRefineSessionTitleWithLlm, maybeSetProvisionalSessionTitle, mergeLlmMessagesPreservingContextRows, messagesToClientHistory, normalizeCompactionCheckpointId, normalizeWorkingDirectoryInput, onSessionTranscriptUpdate, provisionalTitleFromUserText, resolveChannelResetConfig, resolveDailyResetAtMs, resolveEffectiveReasoningLevel, resolveEffectiveThinkingLevel, resolveReasoningLevel, resolveResetTriggers, resolveSession, resolveSessionKeyForRequest, resolveSessionLifecycleTimestamps, resolveSessionResetPolicy, resolveSessionResetType, resolveThinkingLevel, resolveVerboseLevel, sanitizeSessionTitle, shouldAutoTitleSessionKey, shouldRefineSessionTitleWithLlm, shouldSkipResetOverlapCommand, shouldSkipWebchatInboundByAbortCutoff, stripLeadingEnvelopeTimestamp, transcriptRowsFromJsonArray };
@@ -1,7 +1,7 @@
1
- import { createLogger } from "../utils/logger/index.js";
2
- import { init_logger } from "../utils/logger.js";
3
1
  import { SessionConfigSchema, init_schema } from "../config/schema.js";
4
2
  import { init_session_key, parseSessionKey } from "../routing/session-key.js";
3
+ import { createLogger } from "../utils/logger/index.js";
4
+ import { init_logger } from "../utils/logger.js";
5
5
  import { evaluateSessionFreshness, resolveSessionResetPolicy } from "./reset-policy.js";
6
6
  import { resolveChannelResetConfig, resolveSessionResetType } from "./reset-type.js";
7
7
  import { resolveSessionLifecycleTimestamps } from "./lifecycle-timestamps.js";
@@ -84,7 +84,14 @@ var SessionIndex = class extends EventEmitter$1 {
84
84
  return result;
85
85
  }
86
86
  async renameSession(key, name) {
87
- await this.store.updateMetadata(key, { name });
87
+ const existing = await this.store.getMetadata(key);
88
+ await this.store.updateMetadata(key, {
89
+ name,
90
+ customData: {
91
+ ...existing?.customData ?? {},
92
+ titleSource: "user"
93
+ }
94
+ });
88
95
  this.emit("sessionUpdated", {
89
96
  key,
90
97
  name
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","names":["EventEmitter"],"sources":["../../../src/session/manager.ts"],"sourcesContent":["// Session manager - high-level session management service\n\nimport EventEmitter from 'events';\nimport { createLogger } from '../utils/logger.js';\nimport { SessionStore } from './store.js';\nimport type {\n SessionMetadata,\n SessionDetail,\n SessionListQuery,\n PaginatedResult,\n GlobalSessionStats,\n ExportFormat,\n SessionStatus,\n} from './types.js';\nimport type { Message } from './types.js';\nimport type { CompactionConfig, CompactionResult } from '../agent/memory/compaction.js';\nimport type { XopcSessionTranscriptV1 } from './transcript-format.js';\nimport type { XopcTranscriptContextEntry } from './session-context-for-llm.js';\nimport { applySessionPatchToMetadata, type SessionPatchBody } from './patch-metadata.js';\nimport type { WindowConfig } from '../agent/memory/window.js';\nimport type { Config } from '../config/schema.js';\n\nconst log = createLogger('SessionIndex');\n\nexport interface SessionIndexConfig {\n config: Config;\n agentId?: string;\n sessionsDir?: string;\n windowConfig?: Partial<WindowConfig>;\n compactionConfig?: Partial<CompactionConfig>;\n}\n\nexport class SessionIndex extends EventEmitter {\n private store: SessionStore;\n\n constructor(config: SessionIndexConfig) {\n super();\n this.store = new SessionStore(\n {\n config: config.config,\n agentId: config.agentId,\n sessionsDir: config.sessionsDir,\n },\n config.windowConfig,\n config.compactionConfig\n );\n }\n\n async initialize(): Promise<void> {\n await this.store.initialize();\n this.emit('ready');\n }\n\n /** Low-level store (e.g. cron resolving weixin delivery from session index). */\n getStore(): SessionStore {\n return this.store;\n }\n\n // ========== CRUD Operations ==========\n\n async listSessions(query?: SessionListQuery): Promise<PaginatedResult<SessionMetadata>> {\n return this.store.list(query);\n }\n\n /**\n * List all subagent sessions.\n * Subagent sessions have keys starting with 'subagent:'.\n */\n async listSubagents(query: SessionListQuery = {}): Promise<PaginatedResult<SessionMetadata>> {\n // Filter for subagent sessions only\n const subagentQuery: SessionListQuery = {\n ...query,\n search: query.search ? `subagent:${query.search}` : 'subagent:',\n };\n \n const result = await this.store.list(subagentQuery);\n \n // Additional filtering to ensure only subagent sessions\n const subagentSessions = result.items.filter((s) => s.key.startsWith('subagent:'));\n \n return {\n ...result,\n items: subagentSessions,\n total: subagentSessions.length,\n hasMore: false, // Simplified for now\n };\n }\n\n async getSession(\n key: string,\n options?: { includeTranscriptSummary?: boolean; includeTranscriptRows?: boolean },\n ): Promise<SessionDetail | null> {\n const session = await this.store.get(key, options);\n if (session) {\n this.emit('sessionAccessed', { key });\n }\n return session;\n }\n\n async getSessionMessagePage(\n key: string,\n options?: {\n offset?: number;\n limit?: number;\n before?: string;\n includeTranscriptSummary?: boolean;\n includeTranscriptRows?: boolean;\n },\n ): Promise<{\n session: SessionDetail;\n pagination: {\n total: number;\n limit: number;\n offset: number;\n hasMore: boolean;\n before?: string;\n nextBeforeCursor?: string;\n };\n } | null> {\n const result = await this.store.getMessagePage(key, options);\n if (result) {\n this.emit('sessionAccessed', { key });\n }\n return result;\n }\n\n /**\n * OpenClaw-style `sessions.patch`: partial metadata (name, tags, customData shallow merge).\n */\n async patchSession(\n key: string,\n patch: SessionPatchBody,\n ): Promise<{ ok: true } | { ok: false; error: string }> {\n const meta = await this.store.getMetadata(key);\n if (!meta) {\n return { ok: false, error: 'Session not found' };\n }\n const updates = applySessionPatchToMetadata(meta, patch);\n if (Object.keys(updates).length === 0) {\n return { ok: true };\n }\n await this.store.updateMetadata(key, updates);\n this.emit('sessionUpdated', { key });\n return { ok: true };\n }\n\n async getSessionMetadata(key: string): Promise<SessionMetadata | null> {\n return this.store.getMetadata(key);\n }\n\n async deleteSession(key: string): Promise<boolean> {\n const result = await this.store.delete(key);\n if (result) {\n this.emit('sessionDeleted', { key });\n }\n return result;\n }\n\n async deleteSessions(keys: string[]): Promise<{ success: string[]; failed: string[] }> {\n const result = await this.store.deleteMany(keys);\n for (const key of result.success) {\n this.emit('sessionDeleted', { key });\n }\n return result;\n }\n\n // ========== Metadata Updates ==========\n\n async renameSession(key: string, name: string): Promise<void> {\n await this.store.updateMetadata(key, { name });\n this.emit('sessionUpdated', { key, name });\n }\n\n /** Partial metadata update (caller merges nested fields like `customData` when needed). */\n async updateSessionMetadata(key: string, updates: Partial<SessionMetadata>): Promise<void> {\n await this.store.updateMetadata(key, updates);\n this.emit('sessionUpdated', { key });\n }\n\n async tagSession(key: string, tags: string[]): Promise<void> {\n const existing = await this.store.getMetadata(key);\n if (!existing) {\n throw new Error(`Session not found: ${key}`);\n }\n\n // Merge tags, remove duplicates\n const mergedTags = [...new Set([...existing.tags, ...tags])];\n await this.store.updateMetadata(key, { tags: mergedTags });\n this.emit('sessionUpdated', { key, tags: mergedTags });\n }\n\n async untagSession(key: string, tags: string[]): Promise<void> {\n const existing = await this.store.getMetadata(key);\n if (!existing) {\n throw new Error(`Session not found: ${key}`);\n }\n\n const filteredTags = existing.tags.filter((t) => !tags.includes(t));\n await this.store.updateMetadata(key, { tags: filteredTags });\n this.emit('sessionUpdated', { key, tags: filteredTags });\n }\n\n async setSessionTags(key: string, tags: string[]): Promise<void> {\n await this.store.updateMetadata(key, { tags: [...new Set(tags)] });\n this.emit('sessionUpdated', { key, tags });\n }\n\n // ========== Status Management ==========\n\n async archiveSession(key: string): Promise<void> {\n await this.store.archive(key);\n this.emit('sessionArchived', { key });\n }\n\n async unarchiveSession(key: string): Promise<void> {\n await this.store.unarchive(key);\n this.emit('sessionRestored', { key });\n }\n\n async pinSession(key: string): Promise<void> {\n await this.store.pin(key);\n this.emit('sessionPinned', { key });\n }\n\n async unpinSession(key: string): Promise<void> {\n await this.store.unpin(key);\n this.emit('sessionUnpinned', { key });\n }\n\n async setSessionStatus(key: string, status: SessionStatus): Promise<void> {\n await this.store.setStatus(key, status);\n this.emit('sessionStatusChanged', { key, status });\n }\n\n // ========== Search ==========\n\n async searchSessions(query: string): Promise<SessionMetadata[]> {\n const result = await this.store.list({ search: query, limit: 100 });\n return result.items;\n }\n\n async searchInSession(key: string, keyword: string): Promise<Message[]> {\n return this.store.searchInSession(key, keyword);\n }\n\n // ========== Export/Import ==========\n\n async exportSession(key: string, format: ExportFormat): Promise<string> {\n return this.store.exportSession(key, format);\n }\n\n // ========== Statistics ==========\n\n async getStats(): Promise<GlobalSessionStats> {\n return this.store.getStats();\n }\n\n // ========== Maintenance ==========\n\n async archiveOldSessions(olderThanDays: number): Promise<number> {\n const count = await this.store.archiveOld(olderThanDays);\n log.info({ count, olderThanDays }, 'Archived old sessions');\n return count;\n }\n\n // ========== Event Helpers ==========\n\n onSessionCreated(callback: (metadata: SessionMetadata) => void): void {\n this.on('sessionCreated', callback);\n }\n\n onSessionUpdated(callback: (data: { key: string; name?: string; tags?: string[] }) => void): void {\n this.on('sessionUpdated', callback);\n }\n\n onSessionDeleted(callback: (data: { key: string }) => void): void {\n this.on('sessionDeleted', callback);\n }\n\n onSessionArchived(callback: (data: { key: string }) => void): void {\n this.on('sessionArchived', callback);\n }\n\n onSessionRestored(callback: (data: { key: string }) => void): void {\n this.on('sessionRestored', callback);\n }\n\n onSessionPinned(callback: (data: { key: string }) => void): void {\n this.on('sessionPinned', callback);\n }\n\n onSessionUnpinned(callback: (data: { key: string }) => void): void {\n this.on('sessionUnpinned', callback);\n }\n\n onSessionStatusChanged(callback: (data: { key: string; status: SessionStatus }) => void): void {\n this.on('sessionStatusChanged', callback);\n }\n\n onSessionAccessed(callback: (data: { key: string }) => void): void {\n this.on('sessionAccessed', callback);\n }\n\n // ========== Store delegation (messages, compaction) ==========\n\n /** Load messages for a session key */\n async loadMessages(key: string) {\n return this.store.loadMessages(key);\n }\n\n /** Wrapped transcript document (stable id, compaction history); null if missing or not a valid envelope. */\n async loadTranscriptDocument(key: string): Promise<XopcSessionTranscriptV1 | null> {\n return this.store.loadTranscriptDocument(key);\n }\n\n /**\n * Runtime turns must use PiTranscriptManager.appendMessage; this entry point\n * is reserved for compaction, tests, and admin tools.\n */\n async saveMessages(key: string, messages: any[]) {\n return this.store.saveMessages(key, messages);\n }\n\n /**\n * Append `kind: 'context'` transcript row (persisted, excluded from {@link loadMessages} / LLM).\n */\n async appendTranscriptContextEntry(\n key: string,\n entry: Omit<XopcTranscriptContextEntry, 'kind'> & Partial<Pick<XopcTranscriptContextEntry, 'kind'>>,\n ): Promise<void> {\n await this.store.appendTranscriptContextEntry(key, entry);\n this.emit('sessionUpdated', { key });\n }\n\n /** Delete session data */\n async delete(key: string): Promise<void> {\n await this.store.delete(key);\n }\n\n /** Archive transcript and start a new session id for the same key. */\n async resetSession(\n key: string,\n ): Promise<{ sessionId: string; previousSessionId: string } | null> {\n const result = await this.store.reset(key);\n if (result) {\n this.emit('sessionUpdated', { key });\n }\n return result;\n }\n\n /** Token/window stats for a message list */\n getWindowStats(messages: any[]) {\n return this.store.getWindowStats(messages);\n }\n\n /** Prepare compaction run */\n prepareCompaction(key: string, messages: any[], contextWindow: number) {\n return this.store.prepareCompaction(key, messages, contextWindow);\n }\n\n /** Compact session messages */\n compact(\n key: string,\n messages: any[],\n contextWindow: number,\n instructions?: string,\n force?: boolean,\n ): Promise<CompactionResult> {\n return this.store.compact(key, messages, contextWindow, instructions, force);\n }\n\n /** Compaction stats for a session */\n async getCompactionStats(key: string) {\n return this.store.getCompactionStats(key);\n }\n\n /** List pre-compaction transcript snapshots (newest first). */\n listCompactionCheckpoints(key: string) {\n return this.store.listCompactionCheckpoints(key);\n }\n\n getCompactionCheckpointDetail(key: string, checkpointId: string) {\n return this.store.getCompactionCheckpointDetail(key, checkpointId);\n }\n\n restoreCompactionCheckpoint(key: string, checkpointId: string) {\n return this.store.restoreCompactionCheckpoint(key, checkpointId);\n }\n\n /** Estimate token usage for messages */\n async estimateTokenUsage(key: string, messages: any[]): Promise<number> {\n return this.store.estimateTokens(messages);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"manager.js","names":["EventEmitter"],"sources":["../../../src/session/manager.ts"],"sourcesContent":["// Session manager - high-level session management service\n\nimport EventEmitter from 'events';\nimport { createLogger } from '../utils/logger.js';\nimport { SessionStore } from './store.js';\nimport type {\n SessionMetadata,\n SessionDetail,\n SessionListQuery,\n PaginatedResult,\n GlobalSessionStats,\n ExportFormat,\n SessionStatus,\n} from './types.js';\nimport type { Message } from './types.js';\nimport type { CompactionConfig, CompactionResult } from '../agent/memory/compaction.js';\nimport type { XopcSessionTranscriptV1 } from './transcript-format.js';\nimport type { XopcTranscriptContextEntry } from './session-context-for-llm.js';\nimport { applySessionPatchToMetadata, type SessionPatchBody } from './patch-metadata.js';\nimport type { WindowConfig } from '../agent/memory/window.js';\nimport type { Config } from '../config/schema.js';\n\nconst log = createLogger('SessionIndex');\n\nexport interface SessionIndexConfig {\n config: Config;\n agentId?: string;\n sessionsDir?: string;\n windowConfig?: Partial<WindowConfig>;\n compactionConfig?: Partial<CompactionConfig>;\n}\n\nexport class SessionIndex extends EventEmitter {\n private store: SessionStore;\n\n constructor(config: SessionIndexConfig) {\n super();\n this.store = new SessionStore(\n {\n config: config.config,\n agentId: config.agentId,\n sessionsDir: config.sessionsDir,\n },\n config.windowConfig,\n config.compactionConfig\n );\n }\n\n async initialize(): Promise<void> {\n await this.store.initialize();\n this.emit('ready');\n }\n\n /** Low-level store (e.g. cron resolving weixin delivery from session index). */\n getStore(): SessionStore {\n return this.store;\n }\n\n // ========== CRUD Operations ==========\n\n async listSessions(query?: SessionListQuery): Promise<PaginatedResult<SessionMetadata>> {\n return this.store.list(query);\n }\n\n /**\n * List all subagent sessions.\n * Subagent sessions have keys starting with 'subagent:'.\n */\n async listSubagents(query: SessionListQuery = {}): Promise<PaginatedResult<SessionMetadata>> {\n // Filter for subagent sessions only\n const subagentQuery: SessionListQuery = {\n ...query,\n search: query.search ? `subagent:${query.search}` : 'subagent:',\n };\n \n const result = await this.store.list(subagentQuery);\n \n // Additional filtering to ensure only subagent sessions\n const subagentSessions = result.items.filter((s) => s.key.startsWith('subagent:'));\n \n return {\n ...result,\n items: subagentSessions,\n total: subagentSessions.length,\n hasMore: false, // Simplified for now\n };\n }\n\n async getSession(\n key: string,\n options?: { includeTranscriptSummary?: boolean; includeTranscriptRows?: boolean },\n ): Promise<SessionDetail | null> {\n const session = await this.store.get(key, options);\n if (session) {\n this.emit('sessionAccessed', { key });\n }\n return session;\n }\n\n async getSessionMessagePage(\n key: string,\n options?: {\n offset?: number;\n limit?: number;\n before?: string;\n includeTranscriptSummary?: boolean;\n includeTranscriptRows?: boolean;\n },\n ): Promise<{\n session: SessionDetail;\n pagination: {\n total: number;\n limit: number;\n offset: number;\n hasMore: boolean;\n before?: string;\n nextBeforeCursor?: string;\n };\n } | null> {\n const result = await this.store.getMessagePage(key, options);\n if (result) {\n this.emit('sessionAccessed', { key });\n }\n return result;\n }\n\n /**\n * OpenClaw-style `sessions.patch`: partial metadata (name, tags, customData shallow merge).\n */\n async patchSession(\n key: string,\n patch: SessionPatchBody,\n ): Promise<{ ok: true } | { ok: false; error: string }> {\n const meta = await this.store.getMetadata(key);\n if (!meta) {\n return { ok: false, error: 'Session not found' };\n }\n const updates = applySessionPatchToMetadata(meta, patch);\n if (Object.keys(updates).length === 0) {\n return { ok: true };\n }\n await this.store.updateMetadata(key, updates);\n this.emit('sessionUpdated', { key });\n return { ok: true };\n }\n\n async getSessionMetadata(key: string): Promise<SessionMetadata | null> {\n return this.store.getMetadata(key);\n }\n\n async deleteSession(key: string): Promise<boolean> {\n const result = await this.store.delete(key);\n if (result) {\n this.emit('sessionDeleted', { key });\n }\n return result;\n }\n\n async deleteSessions(keys: string[]): Promise<{ success: string[]; failed: string[] }> {\n const result = await this.store.deleteMany(keys);\n for (const key of result.success) {\n this.emit('sessionDeleted', { key });\n }\n return result;\n }\n\n // ========== Metadata Updates ==========\n\n async renameSession(key: string, name: string): Promise<void> {\n const existing = await this.store.getMetadata(key);\n await this.store.updateMetadata(key, {\n name,\n customData: { ...(existing?.customData ?? {}), titleSource: 'user' },\n });\n this.emit('sessionUpdated', { key, name });\n }\n\n /** Partial metadata update (caller merges nested fields like `customData` when needed). */\n async updateSessionMetadata(key: string, updates: Partial<SessionMetadata>): Promise<void> {\n await this.store.updateMetadata(key, updates);\n this.emit('sessionUpdated', { key });\n }\n\n async tagSession(key: string, tags: string[]): Promise<void> {\n const existing = await this.store.getMetadata(key);\n if (!existing) {\n throw new Error(`Session not found: ${key}`);\n }\n\n // Merge tags, remove duplicates\n const mergedTags = [...new Set([...existing.tags, ...tags])];\n await this.store.updateMetadata(key, { tags: mergedTags });\n this.emit('sessionUpdated', { key, tags: mergedTags });\n }\n\n async untagSession(key: string, tags: string[]): Promise<void> {\n const existing = await this.store.getMetadata(key);\n if (!existing) {\n throw new Error(`Session not found: ${key}`);\n }\n\n const filteredTags = existing.tags.filter((t) => !tags.includes(t));\n await this.store.updateMetadata(key, { tags: filteredTags });\n this.emit('sessionUpdated', { key, tags: filteredTags });\n }\n\n async setSessionTags(key: string, tags: string[]): Promise<void> {\n await this.store.updateMetadata(key, { tags: [...new Set(tags)] });\n this.emit('sessionUpdated', { key, tags });\n }\n\n // ========== Status Management ==========\n\n async archiveSession(key: string): Promise<void> {\n await this.store.archive(key);\n this.emit('sessionArchived', { key });\n }\n\n async unarchiveSession(key: string): Promise<void> {\n await this.store.unarchive(key);\n this.emit('sessionRestored', { key });\n }\n\n async pinSession(key: string): Promise<void> {\n await this.store.pin(key);\n this.emit('sessionPinned', { key });\n }\n\n async unpinSession(key: string): Promise<void> {\n await this.store.unpin(key);\n this.emit('sessionUnpinned', { key });\n }\n\n async setSessionStatus(key: string, status: SessionStatus): Promise<void> {\n await this.store.setStatus(key, status);\n this.emit('sessionStatusChanged', { key, status });\n }\n\n // ========== Search ==========\n\n async searchSessions(query: string): Promise<SessionMetadata[]> {\n const result = await this.store.list({ search: query, limit: 100 });\n return result.items;\n }\n\n async searchInSession(key: string, keyword: string): Promise<Message[]> {\n return this.store.searchInSession(key, keyword);\n }\n\n // ========== Export/Import ==========\n\n async exportSession(key: string, format: ExportFormat): Promise<string> {\n return this.store.exportSession(key, format);\n }\n\n // ========== Statistics ==========\n\n async getStats(): Promise<GlobalSessionStats> {\n return this.store.getStats();\n }\n\n // ========== Maintenance ==========\n\n async archiveOldSessions(olderThanDays: number): Promise<number> {\n const count = await this.store.archiveOld(olderThanDays);\n log.info({ count, olderThanDays }, 'Archived old sessions');\n return count;\n }\n\n // ========== Event Helpers ==========\n\n onSessionCreated(callback: (metadata: SessionMetadata) => void): void {\n this.on('sessionCreated', callback);\n }\n\n onSessionUpdated(callback: (data: { key: string; name?: string; tags?: string[] }) => void): void {\n this.on('sessionUpdated', callback);\n }\n\n onSessionDeleted(callback: (data: { key: string }) => void): void {\n this.on('sessionDeleted', callback);\n }\n\n onSessionArchived(callback: (data: { key: string }) => void): void {\n this.on('sessionArchived', callback);\n }\n\n onSessionRestored(callback: (data: { key: string }) => void): void {\n this.on('sessionRestored', callback);\n }\n\n onSessionPinned(callback: (data: { key: string }) => void): void {\n this.on('sessionPinned', callback);\n }\n\n onSessionUnpinned(callback: (data: { key: string }) => void): void {\n this.on('sessionUnpinned', callback);\n }\n\n onSessionStatusChanged(callback: (data: { key: string; status: SessionStatus }) => void): void {\n this.on('sessionStatusChanged', callback);\n }\n\n onSessionAccessed(callback: (data: { key: string }) => void): void {\n this.on('sessionAccessed', callback);\n }\n\n // ========== Store delegation (messages, compaction) ==========\n\n /** Load messages for a session key */\n async loadMessages(key: string) {\n return this.store.loadMessages(key);\n }\n\n /** Wrapped transcript document (stable id, compaction history); null if missing or not a valid envelope. */\n async loadTranscriptDocument(key: string): Promise<XopcSessionTranscriptV1 | null> {\n return this.store.loadTranscriptDocument(key);\n }\n\n /**\n * Runtime turns must use PiTranscriptManager.appendMessage; this entry point\n * is reserved for compaction, tests, and admin tools.\n */\n async saveMessages(key: string, messages: any[]) {\n return this.store.saveMessages(key, messages);\n }\n\n /**\n * Append `kind: 'context'` transcript row (persisted, excluded from {@link loadMessages} / LLM).\n */\n async appendTranscriptContextEntry(\n key: string,\n entry: Omit<XopcTranscriptContextEntry, 'kind'> & Partial<Pick<XopcTranscriptContextEntry, 'kind'>>,\n ): Promise<void> {\n await this.store.appendTranscriptContextEntry(key, entry);\n this.emit('sessionUpdated', { key });\n }\n\n /** Delete session data */\n async delete(key: string): Promise<void> {\n await this.store.delete(key);\n }\n\n /** Archive transcript and start a new session id for the same key. */\n async resetSession(\n key: string,\n ): Promise<{ sessionId: string; previousSessionId: string } | null> {\n const result = await this.store.reset(key);\n if (result) {\n this.emit('sessionUpdated', { key });\n }\n return result;\n }\n\n /** Token/window stats for a message list */\n getWindowStats(messages: any[]) {\n return this.store.getWindowStats(messages);\n }\n\n /** Prepare compaction run */\n prepareCompaction(key: string, messages: any[], contextWindow: number) {\n return this.store.prepareCompaction(key, messages, contextWindow);\n }\n\n /** Compact session messages */\n compact(\n key: string,\n messages: any[],\n contextWindow: number,\n instructions?: string,\n force?: boolean,\n ): Promise<CompactionResult> {\n return this.store.compact(key, messages, contextWindow, instructions, force);\n }\n\n /** Compaction stats for a session */\n async getCompactionStats(key: string) {\n return this.store.getCompactionStats(key);\n }\n\n /** List pre-compaction transcript snapshots (newest first). */\n listCompactionCheckpoints(key: string) {\n return this.store.listCompactionCheckpoints(key);\n }\n\n getCompactionCheckpointDetail(key: string, checkpointId: string) {\n return this.store.getCompactionCheckpointDetail(key, checkpointId);\n }\n\n restoreCompactionCheckpoint(key: string, checkpointId: string) {\n return this.store.restoreCompactionCheckpoint(key, checkpointId);\n }\n\n /** Estimate token usage for messages */\n async estimateTokenUsage(key: string, messages: any[]): Promise<number> {\n return this.store.estimateTokens(messages);\n }\n}\n"],"mappings":"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"}
@@ -3,9 +3,9 @@ import { loadEntriesFromFile } from "./load-jsonl-entries.js";
3
3
  import { withTranscriptFileLock } from "./transcript-file-lock.js";
4
4
  import { emitSessionTranscriptUpdate } from "../transcript-events.js";
5
5
  import { buildSessionContextForLlm, isTranscriptContextEntry } from "../session-context-for-llm.js";
6
- import { randomUUID } from "node:crypto";
7
- import { existsSync } from "node:fs";
8
6
  import path from "node:path";
7
+ import { existsSync } from "node:fs";
8
+ import { randomUUID } from "node:crypto";
9
9
  import { CURRENT_SESSION_VERSION, SessionManager } from "@earendil-works/pi-coding-agent";
10
10
  //#region src/session/parity/jsonl-transcript-io.ts
11
11
  init_write_file_atomic();
@@ -1,9 +1,9 @@
1
1
  import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
2
2
  import { readSessionsJsonFileRaw } from "./sessions-json-file-read.js";
3
3
  import { commitSessionsJsonWrite, getSessionsJsonWriteStats, invalidateSessionsJsonCache, noteSessionsJsonWritten, readSessionsJsonCached, resetSessionsJsonCacheForTest } from "./sessions-json-cache.js";
4
+ import { dirname } from "node:path";
4
5
  import { existsSync } from "node:fs";
5
6
  import { mkdir } from "node:fs/promises";
6
- import { dirname } from "node:path";
7
7
  import lockfile from "proper-lockfile";
8
8
  //#region src/session/parity/sessions-json-file.ts
9
9
  init_write_file_atomic();
@@ -1,7 +1,7 @@
1
- import { createHash } from "node:crypto";
1
+ import path from "node:path";
2
2
  import { existsSync } from "node:fs";
3
+ import { createHash } from "node:crypto";
3
4
  import { mkdir, open, readFile, rm, stat } from "node:fs/promises";
4
- import path from "node:path";
5
5
  //#region src/session/parity/transcript-file-lock.ts
6
6
  /**
7
7
  * Cross-process (and re-entrant same-process) advisory lock for session transcript JSONL.
@@ -1,8 +1,8 @@
1
1
  import { __esmMin } from "../../../_virtual/_rolldown/runtime.js";
2
2
  import { formatSessionArchiveTimestamp, init_artifacts } from "./artifacts.js";
3
3
  import { init_session_id, validateSessionId } from "./session-id.js";
4
- import fs from "node:fs";
5
4
  import { dirname, relative, resolve } from "node:path";
5
+ import fs from "node:fs";
6
6
  //#region src/session/parity/transcript-paths.ts
7
7
  function resolveSessionsDir(opts) {
8
8
  const sessionsDir = opts?.sessionsDir?.trim();
@@ -1,10 +1,10 @@
1
- import { createLogger } from "../utils/logger/index.js";
2
- import { init_logger } from "../utils/logger.js";
3
- import { init_agent_scope, resolveDefaultAgentId } from "../agent/agent-scope.js";
4
- import { init_paths, resolveSessionsMapPath } from "../config/paths.js";
5
1
  import { SessionConfigSchema, init_schema } from "../config/schema.js";
2
+ import { init_agent_scope, resolveDefaultAgentId } from "../agent/agent-scope.js";
6
3
  import { init_agent_session_key, normalizeAgentId, resolveAgentIdFromSessionKey } from "../routing/agent-session-key.js";
7
4
  import { init_session_key, parseSessionKey } from "../routing/session-key.js";
5
+ import { createLogger } from "../utils/logger/index.js";
6
+ import { init_logger } from "../utils/logger.js";
7
+ import { init_paths, resolveSessionsMapPath } from "../config/paths.js";
8
8
  import { readSessionsJsonFile } from "./parity/sessions-json-file.js";
9
9
  import { normalizeThinkLevel, normalizeVerboseLevel } from "../agent/transcript/thinking-types.js";
10
10
  import { evaluateSessionFreshness, resolveSessionResetPolicy } from "./reset-policy.js";
@@ -1,7 +1,7 @@
1
1
  import { FILENAMES, init_paths } from "../config/paths.js";
2
2
  import { SessionSearchIndex } from "./search-index.js";
3
- import { stat } from "node:fs/promises";
4
3
  import { join } from "node:path";
4
+ import { stat } from "node:fs/promises";
5
5
  //#region src/session/search-index-cache.ts
6
6
  /**
7
7
  * Shared cache for {@link SessionSearchIndex} builds (invalidated on session writes).
@@ -2,8 +2,8 @@ import { init_transcript_paths, resolveSessionFilePath } from "./parity/transcri
2
2
  import { FILENAMES, init_paths } from "../config/paths.js";
3
3
  import { isTranscriptContextEntry } from "./session-context-for-llm.js";
4
4
  import { readTranscriptRowsFromFile, rowsToLlmMessages } from "./parity/jsonl-transcript-io.js";
5
- import { readFile } from "node:fs/promises";
6
5
  import { join } from "node:path";
6
+ import { readFile } from "node:fs/promises";
7
7
  //#region src/session/search-index.ts
8
8
  /**
9
9
  * In-memory inverted index over session transcripts (`sessions.json` + JSONL).
@@ -7,14 +7,30 @@ export declare function isWebchatSessionKey(sessionKey: string): boolean;
7
7
  /** Whether to run LLM/fallback session naming for this key (excludes cron, heartbeat). */
8
8
  export declare function shouldAutoTitleSessionKey(sessionKey: string): boolean;
9
9
  export declare function sanitizeSessionTitle(raw: string): string;
10
+ export type SessionTitleSource = 'provisional' | 'llm' | 'user';
11
+ export declare function getSessionTitleSource(meta: {
12
+ customData?: Record<string, unknown>;
13
+ } | null | undefined): SessionTitleSource | null;
14
+ /** Title from a single user message (first line), for immediate sidebar labels. */
15
+ export declare function provisionalTitleFromUserText(raw: string): string | null;
10
16
  /** Non-LLM title: first line of first user text, else first assistant line. */
11
17
  export declare function fallbackTitleFromMessages(messages: AgentMessage[]): string | null;
12
18
  /**
13
19
  * Returns a title string, or null if generation should be skipped or failed.
14
20
  */
15
21
  export declare function generateSessionTitleFromMessages(modelRef: string, messages: AgentMessage[], signal?: AbortSignal): Promise<string | null>;
22
+ export type SessionTitleUpdatedHook = (sessionKey: string, name: string) => void | Promise<void>;
23
+ /** Whether post-turn LLM refine may run (provisional or still unnamed; not user-locked). */
24
+ export declare function shouldRefineSessionTitleWithLlm(meta: {
25
+ name?: string;
26
+ customData?: Record<string, unknown>;
27
+ } | null | undefined): boolean;
16
28
  /**
17
- * If the session is still unnamed, set `name` (LLM when possible, else first-line fallback).
18
- * Skips cron/heartbeat keys. Ensures index row exists by re-saving when metadata is missing (fixes index lag).
29
+ * Set provisional title from first user text when session is still unnamed.
30
+ * Skips cron/heartbeat keys and user-locked titles.
19
31
  */
20
- export declare function maybeAutoTitleSessionStore(sessionStore: SessionStore, sessionKey: string, modelRef: string | undefined): Promise<void>;
32
+ export declare function maybeSetProvisionalSessionTitle(sessionStore: SessionStore, sessionKey: string, userText?: string, onUpdated?: SessionTitleUpdatedHook): Promise<void>;
33
+ /**
34
+ * LLM refine when title is empty or still provisional (not user-locked).
35
+ */
36
+ export declare function maybeRefineSessionTitleWithLlm(sessionStore: SessionStore, sessionKey: string, modelRef: string | undefined, onUpdated?: SessionTitleUpdatedHook): Promise<void>;