@xopcai/xopc 0.0.90 → 0.0.91

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 (290) hide show
  1. package/README.md +36 -12
  2. package/README.zh-CN.md +36 -12
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  5. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  6. package/dist/extensions/telegram/src/plugin.js +1 -1
  7. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  8. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  9. package/dist/extensions/telegram/xopc.extension.json +1 -1
  10. package/dist/extensions/weixin/src/api/api.js +2 -2
  11. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  12. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  13. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  14. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  15. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  16. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  17. package/dist/extensions/weixin/src/plugin.js +1 -1
  18. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  19. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  20. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +41 -0
  21. package/dist/gateway/static/root/assets/agents-bVWUlrlD.js +222 -0
  22. package/dist/gateway/static/root/assets/apps-page-CIC8bmvZ.js +1 -0
  23. package/dist/gateway/static/root/assets/{attachment-preview-renderer-CpyoFbs4.js → attachment-preview-renderer-DBAxQXb-.js} +2 -2
  24. package/dist/gateway/static/root/assets/{attachment-process-heavy-CqVriadb.js → attachment-process-heavy-Csq3TrrP.js} +4 -4
  25. package/dist/gateway/static/root/assets/channels-settings-C8G8RAAP.js +1 -0
  26. package/dist/gateway/static/root/assets/{channels-status-swr-BrtH2VzC.js → channels-status-swr-CYWL5DLD.js} +1 -1
  27. package/dist/gateway/static/root/assets/copy-Dv6d4Dvw.js +1 -0
  28. package/dist/gateway/static/root/assets/{cron-api-CyqbgfHM.js → cron-api-TVqLlGAC.js} +1 -1
  29. package/dist/gateway/static/root/assets/cron-page-BtcFYlvv.js +1 -0
  30. package/dist/gateway/static/root/assets/dist-CUV1uY5f.js +1 -0
  31. package/dist/gateway/static/root/assets/{extension-debug-page-D6Ak0STa.js → extension-debug-page-mTLHRDp1.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-page-Q0P3d6DW.js → extension-page-iI8BI7WK.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-settings-page-CL55LwU_.js → extension-settings-page-ByXcdubM.js} +1 -1
  34. package/dist/gateway/static/root/assets/{fetch-Dqa9iTWl.js → fetch-BWtQq_Ys.js} +1 -1
  35. package/dist/gateway/static/root/assets/{field-primitives-HUR6JElP.js → field-primitives-BsZ-4VT5.js} +1 -1
  36. package/dist/gateway/static/root/assets/{heartbeat-config-api-DusckjUX.js → heartbeat-config-api-WjTsRLCU.js} +1 -1
  37. package/dist/gateway/static/root/assets/{index-BYcGfwcE.js → index-CKkR-v9U.js} +85 -81
  38. package/dist/gateway/static/root/assets/index-VlELBY99.css +1 -0
  39. package/dist/gateway/static/root/assets/logs-page-ClnIpxfd.js +1 -0
  40. package/dist/gateway/static/root/assets/note-detail-page-B91pLkEI.css +1 -0
  41. package/dist/gateway/static/root/assets/note-detail-page-DJ2Mb4x7.js +179 -0
  42. package/dist/gateway/static/root/assets/note-time-JLBPSLzK.js +1 -0
  43. package/dist/gateway/static/root/assets/notes-page-BE-75qz9.js +1 -0
  44. package/dist/gateway/static/root/assets/{pdf-BnEvgIXZ.js → pdf-epILhEOn.js} +1 -1
  45. package/dist/gateway/static/root/assets/preload-helper-zJ_50EbN.js +1 -0
  46. package/dist/gateway/static/root/assets/sessions-page-bJJkWtTl.js +1 -0
  47. package/dist/gateway/static/root/assets/{settings-form-section-a0qGVOlr.js → settings-form-section-DSYCknxM.js} +1 -1
  48. package/dist/gateway/static/root/assets/settings-page-WcMXLq2U.js +3 -0
  49. package/dist/gateway/static/root/assets/share-preview-page-awRqs4hV.js +2 -0
  50. package/dist/gateway/static/root/assets/skills-page-Lu-i1JG7.js +2 -0
  51. package/dist/gateway/static/root/assets/{theme-store-C0Ehmdo5.js → theme-store-BC-42BoZ.js} +1 -1
  52. package/dist/gateway/static/root/assets/toast-z0toXu32.js +1 -0
  53. package/dist/gateway/static/root/assets/url-CY1RQKTU.js +3 -0
  54. package/dist/gateway/static/root/assets/{utils-DRQryzdn.js → utils-DX3TQuap.js} +1 -1
  55. package/dist/gateway/static/root/assets/vendor-codemirror-DYoKfS8f.js +45 -0
  56. package/dist/gateway/static/root/assets/{voice-api-key-field-D0viACE2.js → voice-api-key-field-B5uKlDqA.js} +1 -1
  57. package/dist/gateway/static/root/assets/{workflow-page.utils-DnG8JBhV.js → workflow-page.utils-ClC37yEp.js} +1 -1
  58. package/dist/gateway/static/root/assets/workflows-page-C7VhIXtR.js +27 -0
  59. package/dist/gateway/static/root/index.html +10 -8
  60. package/dist/package.js +1 -1
  61. package/dist/src/agent/agent-manager.js +7 -7
  62. package/dist/src/agent/agent-scope.js +1 -1
  63. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  64. package/dist/src/agent/context/workspace-seed.js +2 -2
  65. package/dist/src/agent/goals/goal-run-store.js +4 -4
  66. package/dist/src/agent/goals/persistent-goal-service.js +1 -1
  67. package/dist/src/agent/goals/post-turn.js +2 -2
  68. package/dist/src/agent/image/load-image-media.js +2 -2
  69. package/dist/src/agent/ipc/bus.js +1 -1
  70. package/dist/src/agent/ipc/inbox.js +2 -2
  71. package/dist/src/agent/ipc/socket.js +1 -1
  72. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  73. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  74. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  75. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  76. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  77. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  78. package/dist/src/agent/memory/dreaming/events.js +1 -1
  79. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  80. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  81. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  82. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  83. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  84. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  85. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  86. package/dist/src/agent/models/manager.js +1 -1
  87. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  88. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  89. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  90. package/dist/src/agent/sandbox/path-policy.js +2 -2
  91. package/dist/src/agent/service/build-direct-message-content.js +1 -1
  92. package/dist/src/agent/service.js +4 -4
  93. package/dist/src/agent/session/session-inspector.js +1 -1
  94. package/dist/src/agent/skills/config.js +1 -1
  95. package/dist/src/agent/skills/hub-hash.js +2 -2
  96. package/dist/src/agent/skills/hub-lock.js +1 -1
  97. package/dist/src/agent/skills/hub-pull.js +2 -2
  98. package/dist/src/agent/skills/index.js +1 -1
  99. package/dist/src/agent/skills/managed-store.js +1 -1
  100. package/dist/src/agent/skills/scanner.js +1 -1
  101. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  102. package/dist/src/agent/skills/skill-manager.js +1 -1
  103. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  104. package/dist/src/agent/tools/factory.js +1 -1
  105. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  106. package/dist/src/agent/tools/send-media.js +1 -1
  107. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  108. package/dist/src/agent/tools/workflow-tool.js +1 -1
  109. package/dist/src/agent/tools/write.js +1 -1
  110. package/dist/src/agent/workflow/catalog.js +1 -1
  111. package/dist/src/auth/credentials.js +3 -3
  112. package/dist/src/auth/profiles/store.js +1 -1
  113. package/dist/src/auth/sync-provider-auth.js +1 -1
  114. package/dist/src/browser/cache-dir-policy.js +1 -1
  115. package/dist/src/browser/cdp-local-launcher.js +2 -2
  116. package/dist/src/browser/providers/browser-ext-install.js +3 -3
  117. package/dist/src/browser/providers/cloakbrowser.js +4 -4
  118. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  119. package/dist/src/browser/stealth.js +1 -1
  120. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  121. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  122. package/dist/src/channels/outbound/persist-store.js +1 -1
  123. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  124. package/dist/src/channels/pairing/pairing-store.js +2 -2
  125. package/dist/src/chat-commands/agent-edit.js +2 -2
  126. package/dist/src/chat-commands/builtins/config.js +2 -2
  127. package/dist/src/chat-commands/context.js +1 -1
  128. package/dist/src/cli/commands/config.js +1 -1
  129. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  130. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  131. package/dist/src/cli/commands/doctor/checks/session-integrity.js +2 -2
  132. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  133. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  134. package/dist/src/cli/commands/extension-dev.js +1 -1
  135. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  136. package/dist/src/cli/commands/extension-pack.js +1 -1
  137. package/dist/src/cli/commands/gateway/logs.js +1 -1
  138. package/dist/src/cli/commands/image.js +1 -1
  139. package/dist/src/cli/commands/init.js +4 -4
  140. package/dist/src/cli/commands/onboard.js +1 -1
  141. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  142. package/dist/src/commands/agents.config.js +1 -1
  143. package/dist/src/config/agent-profile.js +1 -1
  144. package/dist/src/config/gateway-bind.js +1 -1
  145. package/dist/src/config/index.js +5 -5
  146. package/dist/src/config/loader.js +2 -2
  147. package/dist/src/config/models-json.js +2 -2
  148. package/dist/src/config/paths-state.js +1 -1
  149. package/dist/src/config/profile.js +2 -2
  150. package/dist/src/config/workspace-path.js +1 -1
  151. package/dist/src/cron/executor.js +2 -2
  152. package/dist/src/cron/persistence.js +1 -1
  153. package/dist/src/cron/run-log-store.js +1 -1
  154. package/dist/src/daemon/constants.js +1 -1
  155. package/dist/src/daemon/install-plan.js +2 -2
  156. package/dist/src/daemon/launchd.js +2 -2
  157. package/dist/src/daemon/schtasks.js +2 -2
  158. package/dist/src/daemon/systemd.js +2 -2
  159. package/dist/src/extensions/bundle-mcp.js +1 -1
  160. package/dist/src/extensions/discover-extensions.js +1 -1
  161. package/dist/src/extensions/health.js +1 -1
  162. package/dist/src/extensions/loader.js +1 -1
  163. package/dist/src/extensions/lockfile.js +2 -2
  164. package/dist/src/extensions/update.js +1 -1
  165. package/dist/src/gateway/agents-admin.js +3 -3
  166. package/dist/src/gateway/file-path-classifier.js +2 -2
  167. package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -0
  168. package/dist/src/gateway/hono/lib/config-payload.js +2 -1
  169. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  170. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  171. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  172. package/dist/src/gateway/hono/middleware/auth.js +1 -2
  173. package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
  174. package/dist/src/gateway/hono/oauth.js +1 -1
  175. package/dist/src/gateway/hono/routes/agents.js +1 -1
  176. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  177. package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +2 -2
  178. package/dist/src/gateway/hono/routes/config-patch/gateway.js +12 -0
  179. package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -1
  180. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  181. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  182. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  183. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  184. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  185. package/dist/src/gateway/hono/routes/models.js +1 -1
  186. package/dist/src/gateway/hono/routes/notes.d.ts +3 -0
  187. package/dist/src/gateway/hono/routes/notes.js +274 -0
  188. package/dist/src/gateway/hono/routes/notes.js.map +1 -0
  189. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  190. package/dist/src/gateway/hono/routes/shares.js +1 -1
  191. package/dist/src/gateway/hono/routes/workspace.js +4 -4
  192. package/dist/src/gateway/lock.js +3 -3
  193. package/dist/src/gateway/ports.js +1 -1
  194. package/dist/src/gateway/service/agent-runner.js +2 -2
  195. package/dist/src/gateway/service/marketplace-service.js +2 -2
  196. package/dist/src/gateway/service.d.ts +3 -0
  197. package/dist/src/gateway/service.js +11 -1
  198. package/dist/src/gateway/service.js.map +1 -1
  199. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  200. package/dist/src/gateway/workspace-ripgrep.d.ts +6 -0
  201. package/dist/src/gateway/workspace-ripgrep.js +62 -11
  202. package/dist/src/gateway/workspace-ripgrep.js.map +1 -1
  203. package/dist/src/infra/brew.js +1 -1
  204. package/dist/src/infra/package-json.js +1 -1
  205. package/dist/src/infra/package-update-steps.js +1 -1
  206. package/dist/src/infra/path-env.js +2 -2
  207. package/dist/src/infra/restart.js +2 -2
  208. package/dist/src/infra/stable-node-path.js +1 -1
  209. package/dist/src/infra/update-check.js +1 -1
  210. package/dist/src/infra/update-global.js +1 -1
  211. package/dist/src/infra/update-lock.js +3 -3
  212. package/dist/src/infra/update-runner.js +1 -1
  213. package/dist/src/infra/update-startup.js +2 -2
  214. package/dist/src/infra/write-file-atomic.js +2 -2
  215. package/dist/src/notes/attachment-ref.d.ts +9 -0
  216. package/dist/src/notes/attachment-ref.js +27 -0
  217. package/dist/src/notes/attachment-ref.js.map +1 -0
  218. package/dist/src/notes/index.d.ts +4 -0
  219. package/dist/src/notes/index.js +4 -0
  220. package/dist/src/notes/note-attachment-sync.d.ts +7 -0
  221. package/dist/src/notes/note-attachment-sync.js +46 -0
  222. package/dist/src/notes/note-attachment-sync.js.map +1 -0
  223. package/dist/src/notes/note-index-meta.d.ts +14 -0
  224. package/dist/src/notes/note-index-meta.js +87 -0
  225. package/dist/src/notes/note-index-meta.js.map +1 -0
  226. package/dist/src/notes/paths.d.ts +5 -0
  227. package/dist/src/notes/paths.js +23 -0
  228. package/dist/src/notes/paths.js.map +1 -0
  229. package/dist/src/notes/service.d.ts +42 -0
  230. package/dist/src/notes/service.js +331 -0
  231. package/dist/src/notes/service.js.map +1 -0
  232. package/dist/src/notes/store.d.ts +33 -0
  233. package/dist/src/notes/store.js +317 -0
  234. package/dist/src/notes/store.js.map +1 -0
  235. package/dist/src/notes/types.d.ts +162 -0
  236. package/dist/src/notes/types.js +1 -0
  237. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  238. package/dist/src/providers/index.js +2 -2
  239. package/dist/src/providers/model-registry.js +1 -1
  240. package/dist/src/session/config-store.js +2 -2
  241. package/dist/src/session/init-session-turn.js +2 -2
  242. package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
  243. package/dist/src/session/parity/sessions-json-file.js +1 -1
  244. package/dist/src/session/parity/transcript-file-lock.js +2 -2
  245. package/dist/src/session/parity/transcript-paths.js +1 -1
  246. package/dist/src/session/resolve-session.js +4 -4
  247. package/dist/src/session/search-index-cache.js +1 -1
  248. package/dist/src/session/search-index.js +1 -1
  249. package/dist/src/session/session-title.js +2 -2
  250. package/dist/src/session/store.js +6 -6
  251. package/dist/src/share/share-auto.js +2 -2
  252. package/dist/src/share/share-store.js +3 -3
  253. package/dist/src/share/share-thumbnail.js +2 -2
  254. package/dist/src/share/share-zip.js +1 -1
  255. package/dist/src/share/site-share-store.js +3 -3
  256. package/dist/src/share/site-static-serve.js +1 -1
  257. package/dist/src/tui/clipboard-image.js +3 -3
  258. package/dist/src/tui/theme-manager.js +1 -1
  259. package/dist/src/tui/tui-keybindings-file.js +1 -1
  260. package/dist/src/tui/tui-scoped-models.js +2 -2
  261. package/dist/src/tui/tui-settings.js +1 -1
  262. package/dist/src/tui/tui.js +3 -3
  263. package/dist/src/tunnel/frpc-binary.js +3 -3
  264. package/dist/src/tunnel/frpc-config.js +1 -1
  265. package/dist/src/tunnel/frpc-extract.js +1 -1
  266. package/dist/src/tunnel/tunnel-state.js +1 -1
  267. package/dist/src/utils/logger/audit.js +1 -1
  268. package/dist/src/utils/logger/log-store.js +1 -1
  269. package/dist/src/utils/logger/rotation.js +1 -1
  270. package/dist/src/voice/tts/audio.js +1 -1
  271. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  272. package/dist/src/workflows/store/event-store.js +1 -1
  273. package/dist/src/workflows/store/run-store.js +1 -1
  274. package/package.json +1 -1
  275. package/dist/gateway/static/root/assets/agents-cPvvYLXo.js +0 -222
  276. package/dist/gateway/static/root/assets/apps-page-Bk1_P5FJ.js +0 -1
  277. package/dist/gateway/static/root/assets/channels-settings-CZoeQwHz.js +0 -1
  278. package/dist/gateway/static/root/assets/cron-page-BpLdiQN8.js +0 -1
  279. package/dist/gateway/static/root/assets/dist-BTWC-BTN.js +0 -45
  280. package/dist/gateway/static/root/assets/dist-BpAiK86n.js +0 -1
  281. package/dist/gateway/static/root/assets/eye-DAfL1U7M.js +0 -1
  282. package/dist/gateway/static/root/assets/index-V7MQ7834.css +0 -1
  283. package/dist/gateway/static/root/assets/logs-page-_HcZ2fgK.js +0 -1
  284. package/dist/gateway/static/root/assets/sessions-page-iezSMjho.js +0 -1
  285. package/dist/gateway/static/root/assets/settings-page-C9_nYQwM.js +0 -3
  286. package/dist/gateway/static/root/assets/share-preview-page-DExl7CJy.js +0 -2
  287. package/dist/gateway/static/root/assets/skills-page-BlgGD93t.js +0 -2
  288. package/dist/gateway/static/root/assets/url-fxyYANfA.js +0 -3
  289. package/dist/gateway/static/root/assets/vendor-codemirror-D0yxdRpg.js +0 -58
  290. package/dist/gateway/static/root/assets/workflows-page-BvMobnJP.js +0 -27
@@ -0,0 +1,317 @@
1
+ import { createLogger } from "../utils/logger/index.js";
2
+ import { init_logger } from "../utils/logger.js";
3
+ import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
4
+ import { buildNoteIndexMeta } from "./note-index-meta.js";
5
+ import { resolveNoteHistoryDir, resolveNoteItemPath, resolveNoteMediaDir, resolveNotesDir, resolveNotesIndexPath } from "./paths.js";
6
+ import { join } from "node:path";
7
+ import { randomUUID } from "node:crypto";
8
+ import { access, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
9
+ //#region src/notes/store.ts
10
+ init_write_file_atomic();
11
+ init_logger();
12
+ const log = createLogger("NotesStore");
13
+ const DEFAULT_INDEX = {
14
+ version: 3,
15
+ notes: []
16
+ };
17
+ const INDEX_VERSION = 3;
18
+ const DEBOUNCE_MS = 500;
19
+ function noteToIndexEntry(note) {
20
+ const { snippet, coverAttachmentId, voiceAttachmentId, voiceDurationSec, attachmentNames } = buildNoteIndexMeta(note);
21
+ return {
22
+ id: note.id,
23
+ title: note.title || void 0,
24
+ kind: note.kind,
25
+ status: note.status,
26
+ createdAt: note.createdAt,
27
+ updatedAt: note.updatedAt,
28
+ pinned: note.pinned || void 0,
29
+ tags: note.tags?.length ? note.tags : void 0,
30
+ snippet,
31
+ coverAttachmentId,
32
+ voiceAttachmentId,
33
+ voiceDurationSec,
34
+ attachmentNames
35
+ };
36
+ }
37
+ var NotesStore = class {
38
+ indexCache = null;
39
+ dirty = false;
40
+ saveTimeout = null;
41
+ initialized = false;
42
+ async initialize() {
43
+ if (this.initialized) return;
44
+ const indexPath = resolveNotesIndexPath();
45
+ try {
46
+ await access(indexPath);
47
+ await this.loadIndex();
48
+ if ((this.indexCache?.version ?? 0) < INDEX_VERSION) await this.rebuildIndexFromItems();
49
+ } catch {
50
+ await this.writeIndex(DEFAULT_INDEX);
51
+ this.indexCache = DEFAULT_INDEX;
52
+ }
53
+ this.initialized = true;
54
+ log.debug("NotesStore initialized");
55
+ }
56
+ async addNote(note) {
57
+ const index = await this.loadIndex();
58
+ await this.writeNoteItem(note);
59
+ index.notes.push(noteToIndexEntry(note));
60
+ index.version++;
61
+ this.scheduleIndexSave(index);
62
+ }
63
+ async getNote(id) {
64
+ const itemPath = resolveNoteItemPath(id);
65
+ try {
66
+ const content = await readFile(itemPath, "utf-8");
67
+ return JSON.parse(content);
68
+ } catch (err) {
69
+ if ((err && typeof err === "object" && "code" in err ? err.code : "") !== "ENOENT") log.debug({
70
+ err,
71
+ id
72
+ }, "Failed to read note item");
73
+ return null;
74
+ }
75
+ }
76
+ async updateNote(id, patch) {
77
+ const existing = await this.getNote(id);
78
+ if (!existing) return null;
79
+ const updated = {
80
+ ...existing,
81
+ ...patch,
82
+ id: existing.id,
83
+ createdAt: existing.createdAt,
84
+ updatedAt: Date.now()
85
+ };
86
+ await this.writeNoteItem(updated);
87
+ const index = await this.loadIndex();
88
+ const idx = index.notes.findIndex((n) => n.id === id);
89
+ if (idx !== -1) index.notes[idx] = noteToIndexEntry(updated);
90
+ index.version++;
91
+ this.scheduleIndexSave(index);
92
+ return updated;
93
+ }
94
+ async deleteNote(id) {
95
+ if (!await this.getNote(id)) return false;
96
+ await rm(resolveNoteItemPath(id), { force: true }).catch((err) => {
97
+ log.warn({
98
+ err,
99
+ id
100
+ }, "Failed to remove note item file");
101
+ });
102
+ await rm(resolveNoteMediaDir(id), {
103
+ recursive: true,
104
+ force: true
105
+ }).catch(() => void 0);
106
+ const index = await this.loadIndex();
107
+ const before = index.notes.length;
108
+ index.notes = index.notes.filter((n) => n.id !== id);
109
+ if (index.notes.length === before) log.debug({ id }, "Deleted note file but index entry was missing");
110
+ index.version++;
111
+ this.scheduleIndexSave(index);
112
+ return true;
113
+ }
114
+ async listNotes(query = {}) {
115
+ let results = (await this.loadIndex()).notes;
116
+ if (query.status) results = results.filter((n) => n.status === query.status);
117
+ else results = results.filter((n) => n.status !== "trashed");
118
+ if (query.kind) results = results.filter((n) => n.kind === query.kind);
119
+ if (query.tag) results = results.filter((n) => n.tags?.includes(query.tag));
120
+ if (query.pinned !== void 0) results = results.filter((n) => Boolean(n.pinned) === query.pinned);
121
+ if (query.search) {
122
+ const term = query.search.toLowerCase();
123
+ results = results.filter((n) => n.title?.toLowerCase().includes(term) || n.snippet?.toLowerCase().includes(term) || n.tags?.some((t) => t.toLowerCase().includes(term)) || n.attachmentNames?.some((name) => name.includes(term)));
124
+ }
125
+ const sortField = query.sortBy || "createdAt";
126
+ const sortDir = query.sortOrder === "asc" ? 1 : -1;
127
+ results = [...results].sort((a, b) => (a[sortField] - b[sortField]) * sortDir);
128
+ const total = results.length;
129
+ const offset = query.offset || 0;
130
+ const limit = Math.min(query.limit || 50, 200);
131
+ return {
132
+ items: results.slice(offset, offset + limit),
133
+ total
134
+ };
135
+ }
136
+ async saveAttachment(noteId, fileName, buffer) {
137
+ const mediaDir = resolveNoteMediaDir(noteId);
138
+ await mkdir(mediaDir, { recursive: true });
139
+ const safeName = `${randomUUID().slice(0, 8)}_${fileName.replace(/[^a-zA-Z0-9._-]/g, "_")}`;
140
+ await writeFile(join(mediaDir, safeName), buffer);
141
+ return {
142
+ relativePath: safeName,
143
+ size: buffer.length
144
+ };
145
+ }
146
+ resolveAttachmentPath(noteId, relativePath) {
147
+ return join(resolveNoteMediaDir(noteId), relativePath);
148
+ }
149
+ async deleteAttachmentFile(noteId, relativePath) {
150
+ await rm(this.resolveAttachmentPath(noteId, relativePath), { force: true }).catch((err) => {
151
+ log.warn({
152
+ err,
153
+ noteId,
154
+ relativePath
155
+ }, "Failed to remove note attachment file");
156
+ });
157
+ }
158
+ async saveSnapshot(note, trigger) {
159
+ const historyDir = resolveNoteHistoryDir(note.id);
160
+ await mkdir(historyDir, { recursive: true });
161
+ const snapshot = {
162
+ noteId: note.id,
163
+ timestamp: Date.now(),
164
+ trigger,
165
+ title: note.title,
166
+ text: note.text,
167
+ blocks: note.blocks,
168
+ tags: note.tags,
169
+ kind: note.kind,
170
+ status: note.status
171
+ };
172
+ await writeTextAtomic(join(historyDir, `${snapshot.timestamp}.json`), JSON.stringify(snapshot, null, 2));
173
+ log.debug({
174
+ noteId: note.id,
175
+ trigger,
176
+ timestamp: snapshot.timestamp
177
+ }, "Snapshot saved");
178
+ }
179
+ async listSnapshots(noteId) {
180
+ const historyDir = resolveNoteHistoryDir(noteId);
181
+ let files;
182
+ try {
183
+ files = await readdir(historyDir);
184
+ } catch {
185
+ return [];
186
+ }
187
+ const entries = [];
188
+ for (const file of files) {
189
+ if (!file.endsWith(".json")) continue;
190
+ const timestamp = parseInt(file.slice(0, -5), 10);
191
+ if (!Number.isFinite(timestamp)) continue;
192
+ try {
193
+ const content = await readFile(join(historyDir, file), "utf-8");
194
+ const snapshot = JSON.parse(content);
195
+ const rawText = snapshot.text ?? "";
196
+ entries.push({
197
+ timestamp: snapshot.timestamp,
198
+ trigger: snapshot.trigger,
199
+ snippet: rawText.slice(0, 80) || void 0
200
+ });
201
+ } catch {
202
+ log.debug({
203
+ noteId,
204
+ file
205
+ }, "Skipped unreadable snapshot");
206
+ }
207
+ }
208
+ entries.sort((a, b) => b.timestamp - a.timestamp);
209
+ return entries;
210
+ }
211
+ async getSnapshot(noteId, timestamp) {
212
+ const filePath = join(resolveNoteHistoryDir(noteId), `${timestamp}.json`);
213
+ try {
214
+ const content = await readFile(filePath, "utf-8");
215
+ return JSON.parse(content);
216
+ } catch {
217
+ return null;
218
+ }
219
+ }
220
+ async pruneSnapshots(noteId, maxCount) {
221
+ const historyDir = resolveNoteHistoryDir(noteId);
222
+ let files;
223
+ try {
224
+ files = await readdir(historyDir);
225
+ } catch {
226
+ return;
227
+ }
228
+ const jsonFiles = files.filter((f) => f.endsWith(".json")).sort();
229
+ if (jsonFiles.length <= maxCount) return;
230
+ const toDelete = jsonFiles.slice(0, jsonFiles.length - maxCount);
231
+ for (const file of toDelete) await rm(join(historyDir, file), { force: true }).catch(() => void 0);
232
+ log.debug({
233
+ noteId,
234
+ deleted: toDelete.length
235
+ }, "Pruned old snapshots");
236
+ }
237
+ async deleteAllSnapshots(noteId) {
238
+ await rm(resolveNoteHistoryDir(noteId), {
239
+ recursive: true,
240
+ force: true
241
+ }).catch(() => void 0);
242
+ }
243
+ async flush() {
244
+ if (!this.dirty || !this.indexCache) return;
245
+ if (this.saveTimeout) {
246
+ clearTimeout(this.saveTimeout);
247
+ this.saveTimeout = null;
248
+ }
249
+ await this.writeIndex(this.indexCache);
250
+ this.dirty = false;
251
+ }
252
+ async loadIndex() {
253
+ if (this.indexCache) return this.indexCache;
254
+ const indexPath = resolveNotesIndexPath();
255
+ try {
256
+ const content = await readFile(indexPath, "utf-8");
257
+ const data = JSON.parse(content);
258
+ if (!data.notes || !Array.isArray(data.notes)) {
259
+ log.warn("Notes index invalid, resetting");
260
+ this.indexCache = DEFAULT_INDEX;
261
+ return this.indexCache;
262
+ }
263
+ this.indexCache = data;
264
+ return data;
265
+ } catch {
266
+ this.indexCache = DEFAULT_INDEX;
267
+ return this.indexCache;
268
+ }
269
+ }
270
+ async writeIndex(data) {
271
+ await writeTextAtomic(resolveNotesIndexPath(), JSON.stringify(data, null, 2));
272
+ log.debug({ count: data.notes.length }, "Notes index saved");
273
+ }
274
+ async writeNoteItem(note) {
275
+ await writeTextAtomic(resolveNoteItemPath(note.id), JSON.stringify(note, null, 2));
276
+ }
277
+ scheduleIndexSave(data) {
278
+ this.indexCache = data;
279
+ this.dirty = true;
280
+ if (this.saveTimeout) clearTimeout(this.saveTimeout);
281
+ this.saveTimeout = setTimeout(() => {
282
+ this.flush().catch((err) => {
283
+ log.error({ err }, "Failed to flush notes index");
284
+ });
285
+ }, DEBOUNCE_MS);
286
+ }
287
+ async rebuildIndexFromItems() {
288
+ const itemsDir = join(resolveNotesDir(), "items");
289
+ let files;
290
+ try {
291
+ files = await readdir(itemsDir);
292
+ } catch {
293
+ this.indexCache = DEFAULT_INDEX;
294
+ await this.writeIndex(DEFAULT_INDEX);
295
+ return;
296
+ }
297
+ const entries = [];
298
+ for (const file of files) {
299
+ if (!file.endsWith(".json")) continue;
300
+ const noteId = file.slice(0, -5);
301
+ const note = await this.getNote(noteId);
302
+ if (note) entries.push(noteToIndexEntry(note));
303
+ }
304
+ entries.sort((a, b) => b.createdAt - a.createdAt);
305
+ const index = {
306
+ version: INDEX_VERSION,
307
+ notes: entries
308
+ };
309
+ this.indexCache = index;
310
+ await this.writeIndex(index);
311
+ log.debug({ count: entries.length }, "Notes index rebuilt");
312
+ }
313
+ };
314
+ //#endregion
315
+ export { NotesStore };
316
+
317
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","names":[],"sources":["../../../src/notes/store.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { readFile, access, mkdir, writeFile, rm, readdir } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport { writeTextAtomic } from '../infra/write-file-atomic.js';\nimport { createLogger } from '../utils/logger.js';\nimport { buildNoteIndexMeta } from './note-index-meta.js';\nimport { resolveNotesDir, resolveNotesIndexPath, resolveNoteItemPath, resolveNoteMediaDir, resolveNoteHistoryDir } from './paths.js';\nimport type {\n Note,\n NoteIndexEntry,\n NoteSnapshot,\n NoteSnapshotEntry,\n NotesIndexFile,\n NotesListQuery,\n SnapshotTrigger,\n} from './types.js';\n\nconst log = createLogger('NotesStore');\n\nconst DEFAULT_INDEX: NotesIndexFile = { version: 3, notes: [] };\nconst INDEX_VERSION = 3;\nconst DEBOUNCE_MS = 500;\n\nfunction noteToIndexEntry(note: Note): NoteIndexEntry {\n const { snippet, coverAttachmentId, voiceAttachmentId, voiceDurationSec, attachmentNames } = buildNoteIndexMeta(note);\n return {\n id: note.id,\n title: note.title || undefined,\n kind: note.kind,\n status: note.status,\n createdAt: note.createdAt,\n updatedAt: note.updatedAt,\n pinned: note.pinned || undefined,\n tags: note.tags?.length ? note.tags : undefined,\n snippet,\n coverAttachmentId,\n voiceAttachmentId,\n voiceDurationSec,\n attachmentNames,\n };\n}\n\nexport class NotesStore {\n private indexCache: NotesIndexFile | null = null;\n private dirty = false;\n private saveTimeout: ReturnType<typeof setTimeout> | null = null;\n private initialized = false;\n\n async initialize(): Promise<void> {\n if (this.initialized) return;\n const indexPath = resolveNotesIndexPath();\n try {\n await access(indexPath);\n await this.loadIndex();\n if ((this.indexCache?.version ?? 0) < INDEX_VERSION) {\n await this.rebuildIndexFromItems();\n }\n } catch {\n await this.writeIndex(DEFAULT_INDEX);\n this.indexCache = DEFAULT_INDEX;\n }\n this.initialized = true;\n log.debug('NotesStore initialized');\n }\n\n async addNote(note: Note): Promise<void> {\n const index = await this.loadIndex();\n await this.writeNoteItem(note);\n index.notes.push(noteToIndexEntry(note));\n index.version++;\n this.scheduleIndexSave(index);\n }\n\n async getNote(id: string): Promise<Note | null> {\n const itemPath = resolveNoteItemPath(id);\n try {\n const content = await readFile(itemPath, 'utf-8');\n return JSON.parse(content) as Note;\n } catch (err) {\n const code = err && typeof err === 'object' && 'code' in err\n ? (err as NodeJS.ErrnoException).code : '';\n if (code !== 'ENOENT') {\n log.debug({ err, id }, 'Failed to read note item');\n }\n return null;\n }\n }\n\n async updateNote(id: string, patch: Partial<Note>): Promise<Note | null> {\n const existing = await this.getNote(id);\n if (!existing) return null;\n\n const updated: Note = {\n ...existing,\n ...patch,\n id: existing.id,\n createdAt: existing.createdAt,\n updatedAt: Date.now(),\n };\n\n await this.writeNoteItem(updated);\n\n const index = await this.loadIndex();\n const idx = index.notes.findIndex((n) => n.id === id);\n if (idx !== -1) {\n index.notes[idx] = noteToIndexEntry(updated);\n }\n index.version++;\n this.scheduleIndexSave(index);\n\n return updated;\n }\n\n async deleteNote(id: string): Promise<boolean> {\n const existing = await this.getNote(id);\n if (!existing) return false;\n\n const itemPath = resolveNoteItemPath(id);\n await rm(itemPath, { force: true }).catch((err) => {\n log.warn({ err, id }, 'Failed to remove note item file');\n });\n\n const mediaDir = resolveNoteMediaDir(id);\n await rm(mediaDir, { recursive: true, force: true }).catch(() => undefined);\n\n const index = await this.loadIndex();\n const before = index.notes.length;\n index.notes = index.notes.filter((n) => n.id !== id);\n if (index.notes.length === before) {\n log.debug({ id }, 'Deleted note file but index entry was missing');\n }\n index.version++;\n this.scheduleIndexSave(index);\n\n return true;\n }\n\n async listNotes(query: NotesListQuery = {}): Promise<{ items: NoteIndexEntry[]; total: number }> {\n const index = await this.loadIndex();\n let results = index.notes;\n\n if (query.status) {\n results = results.filter((n) => n.status === query.status);\n } else {\n results = results.filter((n) => n.status !== 'trashed');\n }\n if (query.kind) {\n results = results.filter((n) => n.kind === query.kind);\n }\n if (query.tag) {\n results = results.filter((n) => n.tags?.includes(query.tag!));\n }\n if (query.pinned !== undefined) {\n results = results.filter((n) => Boolean(n.pinned) === query.pinned);\n }\n if (query.search) {\n const term = query.search.toLowerCase();\n results = results.filter((n) =>\n n.title?.toLowerCase().includes(term) ||\n n.snippet?.toLowerCase().includes(term) ||\n n.tags?.some((t) => t.toLowerCase().includes(term)) ||\n n.attachmentNames?.some((name) => name.includes(term)),\n );\n }\n\n const sortField = query.sortBy || 'createdAt';\n const sortDir = query.sortOrder === 'asc' ? 1 : -1;\n results = [...results].sort((a, b) => (a[sortField] - b[sortField]) * sortDir);\n\n const total = results.length;\n const offset = query.offset || 0;\n const limit = Math.min(query.limit || 50, 200);\n const items = results.slice(offset, offset + limit);\n\n return { items, total };\n }\n\n async saveAttachment(\n noteId: string,\n fileName: string,\n buffer: Buffer,\n ): Promise<{ relativePath: string; size: number }> {\n const mediaDir = resolveNoteMediaDir(noteId);\n await mkdir(mediaDir, { recursive: true });\n const safeName = `${randomUUID().slice(0, 8)}_${fileName.replace(/[^a-zA-Z0-9._-]/g, '_')}`;\n const filePath = join(mediaDir, safeName);\n await writeFile(filePath, buffer);\n return { relativePath: safeName, size: buffer.length };\n }\n\n resolveAttachmentPath(noteId: string, relativePath: string): string {\n return join(resolveNoteMediaDir(noteId), relativePath);\n }\n\n async deleteAttachmentFile(noteId: string, relativePath: string): Promise<void> {\n const filePath = this.resolveAttachmentPath(noteId, relativePath);\n await rm(filePath, { force: true }).catch((err) => {\n log.warn({ err, noteId, relativePath }, 'Failed to remove note attachment file');\n });\n }\n\n async saveSnapshot(note: Note, trigger: SnapshotTrigger): Promise<void> {\n const historyDir = resolveNoteHistoryDir(note.id);\n await mkdir(historyDir, { recursive: true });\n const snapshot: NoteSnapshot = {\n noteId: note.id,\n timestamp: Date.now(),\n trigger,\n title: note.title,\n text: note.text,\n blocks: note.blocks,\n tags: note.tags,\n kind: note.kind,\n status: note.status,\n };\n const filePath = join(historyDir, `${snapshot.timestamp}.json`);\n await writeTextAtomic(filePath, JSON.stringify(snapshot, null, 2));\n log.debug({ noteId: note.id, trigger, timestamp: snapshot.timestamp }, 'Snapshot saved');\n }\n\n async listSnapshots(noteId: string): Promise<NoteSnapshotEntry[]> {\n const historyDir = resolveNoteHistoryDir(noteId);\n let files: string[];\n try {\n files = await readdir(historyDir);\n } catch {\n return [];\n }\n const entries: NoteSnapshotEntry[] = [];\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const timestamp = parseInt(file.slice(0, -'.json'.length), 10);\n if (!Number.isFinite(timestamp)) continue;\n try {\n const content = await readFile(join(historyDir, file), 'utf-8');\n const snapshot = JSON.parse(content) as NoteSnapshot;\n const rawText = snapshot.text ?? '';\n entries.push({\n timestamp: snapshot.timestamp,\n trigger: snapshot.trigger,\n snippet: rawText.slice(0, 80) || undefined,\n });\n } catch {\n log.debug({ noteId, file }, 'Skipped unreadable snapshot');\n }\n }\n entries.sort((a, b) => b.timestamp - a.timestamp);\n return entries;\n }\n\n async getSnapshot(noteId: string, timestamp: number): Promise<NoteSnapshot | null> {\n const filePath = join(resolveNoteHistoryDir(noteId), `${timestamp}.json`);\n try {\n const content = await readFile(filePath, 'utf-8');\n return JSON.parse(content) as NoteSnapshot;\n } catch {\n return null;\n }\n }\n\n async pruneSnapshots(noteId: string, maxCount: number): Promise<void> {\n const historyDir = resolveNoteHistoryDir(noteId);\n let files: string[];\n try {\n files = await readdir(historyDir);\n } catch {\n return;\n }\n const jsonFiles = files\n .filter((f) => f.endsWith('.json'))\n .sort();\n if (jsonFiles.length <= maxCount) return;\n const toDelete = jsonFiles.slice(0, jsonFiles.length - maxCount);\n for (const file of toDelete) {\n await rm(join(historyDir, file), { force: true }).catch(() => undefined);\n }\n log.debug({ noteId, deleted: toDelete.length }, 'Pruned old snapshots');\n }\n\n async deleteAllSnapshots(noteId: string): Promise<void> {\n const historyDir = resolveNoteHistoryDir(noteId);\n await rm(historyDir, { recursive: true, force: true }).catch(() => undefined);\n }\n\n async flush(): Promise<void> {\n if (!this.dirty || !this.indexCache) return;\n if (this.saveTimeout) {\n clearTimeout(this.saveTimeout);\n this.saveTimeout = null;\n }\n await this.writeIndex(this.indexCache);\n this.dirty = false;\n }\n\n private async loadIndex(): Promise<NotesIndexFile> {\n if (this.indexCache) return this.indexCache;\n const indexPath = resolveNotesIndexPath();\n try {\n const content = await readFile(indexPath, 'utf-8');\n const data = JSON.parse(content) as NotesIndexFile;\n if (!data.notes || !Array.isArray(data.notes)) {\n log.warn('Notes index invalid, resetting');\n this.indexCache = DEFAULT_INDEX;\n return this.indexCache;\n }\n this.indexCache = data;\n return data;\n } catch {\n this.indexCache = DEFAULT_INDEX;\n return this.indexCache;\n }\n }\n\n private async writeIndex(data: NotesIndexFile): Promise<void> {\n const indexPath = resolveNotesIndexPath();\n await writeTextAtomic(indexPath, JSON.stringify(data, null, 2));\n log.debug({ count: data.notes.length }, 'Notes index saved');\n }\n\n private async writeNoteItem(note: Note): Promise<void> {\n const itemPath = resolveNoteItemPath(note.id);\n await writeTextAtomic(itemPath, JSON.stringify(note, null, 2));\n }\n\n private scheduleIndexSave(data: NotesIndexFile): void {\n this.indexCache = data;\n this.dirty = true;\n if (this.saveTimeout) {\n clearTimeout(this.saveTimeout);\n }\n this.saveTimeout = setTimeout(() => {\n this.flush().catch((err) => {\n log.error({ err }, 'Failed to flush notes index');\n });\n }, DEBOUNCE_MS);\n }\n\n private async rebuildIndexFromItems(): Promise<void> {\n const itemsDir = join(resolveNotesDir(), 'items');\n let files: string[];\n try {\n files = await readdir(itemsDir);\n } catch {\n this.indexCache = DEFAULT_INDEX;\n await this.writeIndex(DEFAULT_INDEX);\n return;\n }\n\n const entries: NoteIndexEntry[] = [];\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const noteId = file.slice(0, -'.json'.length);\n const note = await this.getNote(noteId);\n if (note) {\n entries.push(noteToIndexEntry(note));\n }\n }\n\n entries.sort((a, b) => b.createdAt - a.createdAt);\n const index: NotesIndexFile = { version: INDEX_VERSION, notes: entries };\n this.indexCache = index;\n await this.writeIndex(index);\n log.debug({ count: entries.length }, 'Notes index rebuilt');\n }\n}\n"],"mappings":";;;;;;;;;wBAIgE;aACd;AAalD,MAAM,MAAM,aAAa,aAAa;AAEtC,MAAM,gBAAgC;CAAE,SAAS;CAAG,OAAO,EAAE;CAAE;AAC/D,MAAM,gBAAgB;AACtB,MAAM,cAAc;AAEpB,SAAS,iBAAiB,MAA4B;CACpD,MAAM,EAAE,SAAS,mBAAmB,mBAAmB,kBAAkB,oBAAoB,mBAAmB,KAAK;AACrH,QAAO;EACL,IAAI,KAAK;EACT,OAAO,KAAK,SAAS,KAAA;EACrB,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,WAAW,KAAK;EAChB,WAAW,KAAK;EAChB,QAAQ,KAAK,UAAU,KAAA;EACvB,MAAM,KAAK,MAAM,SAAS,KAAK,OAAO,KAAA;EACtC;EACA;EACA;EACA;EACA;EACD;;AAGH,IAAa,aAAb,MAAwB;CACtB,aAA4C;CAC5C,QAAgB;CAChB,cAA4D;CAC5D,cAAsB;CAEtB,MAAM,aAA4B;AAChC,MAAI,KAAK,YAAa;EACtB,MAAM,YAAY,uBAAuB;AACzC,MAAI;AACF,SAAM,OAAO,UAAU;AACvB,SAAM,KAAK,WAAW;AACtB,QAAK,KAAK,YAAY,WAAW,KAAK,cACpC,OAAM,KAAK,uBAAuB;UAE9B;AACN,SAAM,KAAK,WAAW,cAAc;AACpC,QAAK,aAAa;;AAEpB,OAAK,cAAc;AACnB,MAAI,MAAM,yBAAyB;;CAGrC,MAAM,QAAQ,MAA2B;EACvC,MAAM,QAAQ,MAAM,KAAK,WAAW;AACpC,QAAM,KAAK,cAAc,KAAK;AAC9B,QAAM,MAAM,KAAK,iBAAiB,KAAK,CAAC;AACxC,QAAM;AACN,OAAK,kBAAkB,MAAM;;CAG/B,MAAM,QAAQ,IAAkC;EAC9C,MAAM,WAAW,oBAAoB,GAAG;AACxC,MAAI;GACF,MAAM,UAAU,MAAM,SAAS,UAAU,QAAQ;AACjD,UAAO,KAAK,MAAM,QAAQ;WACnB,KAAK;AAGZ,QAFa,OAAO,OAAO,QAAQ,YAAY,UAAU,MACpD,IAA8B,OAAO,QAC7B,SACX,KAAI,MAAM;IAAE;IAAK;IAAI,EAAE,2BAA2B;AAEpD,UAAO;;;CAIX,MAAM,WAAW,IAAY,OAA4C;EACvE,MAAM,WAAW,MAAM,KAAK,QAAQ,GAAG;AACvC,MAAI,CAAC,SAAU,QAAO;EAEtB,MAAM,UAAgB;GACpB,GAAG;GACH,GAAG;GACH,IAAI,SAAS;GACb,WAAW,SAAS;GACpB,WAAW,KAAK,KAAK;GACtB;AAED,QAAM,KAAK,cAAc,QAAQ;EAEjC,MAAM,QAAQ,MAAM,KAAK,WAAW;EACpC,MAAM,MAAM,MAAM,MAAM,WAAW,MAAM,EAAE,OAAO,GAAG;AACrD,MAAI,QAAQ,GACV,OAAM,MAAM,OAAO,iBAAiB,QAAQ;AAE9C,QAAM;AACN,OAAK,kBAAkB,MAAM;AAE7B,SAAO;;CAGT,MAAM,WAAW,IAA8B;AAE7C,MAAI,CAAC,MADkB,KAAK,QAAQ,GAAG,CACxB,QAAO;AAGtB,QAAM,GADW,oBAAoB,GACpB,EAAE,EAAE,OAAO,MAAM,CAAC,CAAC,OAAO,QAAQ;AACjD,OAAI,KAAK;IAAE;IAAK;IAAI,EAAE,kCAAkC;IACxD;AAGF,QAAM,GADW,oBAAoB,GACpB,EAAE;GAAE,WAAW;GAAM,OAAO;GAAM,CAAC,CAAC,YAAY,KAAA,EAAU;EAE3E,MAAM,QAAQ,MAAM,KAAK,WAAW;EACpC,MAAM,SAAS,MAAM,MAAM;AAC3B,QAAM,QAAQ,MAAM,MAAM,QAAQ,MAAM,EAAE,OAAO,GAAG;AACpD,MAAI,MAAM,MAAM,WAAW,OACzB,KAAI,MAAM,EAAE,IAAI,EAAE,gDAAgD;AAEpE,QAAM;AACN,OAAK,kBAAkB,MAAM;AAE7B,SAAO;;CAGT,MAAM,UAAU,QAAwB,EAAE,EAAuD;EAE/F,IAAI,WAAU,MADM,KAAK,WAAW,EAChB;AAEpB,MAAI,MAAM,OACR,WAAU,QAAQ,QAAQ,MAAM,EAAE,WAAW,MAAM,OAAO;MAE1D,WAAU,QAAQ,QAAQ,MAAM,EAAE,WAAW,UAAU;AAEzD,MAAI,MAAM,KACR,WAAU,QAAQ,QAAQ,MAAM,EAAE,SAAS,MAAM,KAAK;AAExD,MAAI,MAAM,IACR,WAAU,QAAQ,QAAQ,MAAM,EAAE,MAAM,SAAS,MAAM,IAAK,CAAC;AAE/D,MAAI,MAAM,WAAW,KAAA,EACnB,WAAU,QAAQ,QAAQ,MAAM,QAAQ,EAAE,OAAO,KAAK,MAAM,OAAO;AAErE,MAAI,MAAM,QAAQ;GAChB,MAAM,OAAO,MAAM,OAAO,aAAa;AACvC,aAAU,QAAQ,QAAQ,MACxB,EAAE,OAAO,aAAa,CAAC,SAAS,KAAK,IACrC,EAAE,SAAS,aAAa,CAAC,SAAS,KAAK,IACvC,EAAE,MAAM,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,KAAK,CAAC,IACnD,EAAE,iBAAiB,MAAM,SAAS,KAAK,SAAS,KAAK,CAAC,CACvD;;EAGH,MAAM,YAAY,MAAM,UAAU;EAClC,MAAM,UAAU,MAAM,cAAc,QAAQ,IAAI;AAChD,YAAU,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,OAAO,EAAE,aAAa,EAAE,cAAc,QAAQ;EAE9E,MAAM,QAAQ,QAAQ;EACtB,MAAM,SAAS,MAAM,UAAU;EAC/B,MAAM,QAAQ,KAAK,IAAI,MAAM,SAAS,IAAI,IAAI;AAG9C,SAAO;GAAE,OAFK,QAAQ,MAAM,QAAQ,SAAS,MAE/B;GAAE;GAAO;;CAGzB,MAAM,eACJ,QACA,UACA,QACiD;EACjD,MAAM,WAAW,oBAAoB,OAAO;AAC5C,QAAM,MAAM,UAAU,EAAE,WAAW,MAAM,CAAC;EAC1C,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,SAAS,QAAQ,oBAAoB,IAAI;AAEzF,QAAM,UADW,KAAK,UAAU,SACR,EAAE,OAAO;AACjC,SAAO;GAAE,cAAc;GAAU,MAAM,OAAO;GAAQ;;CAGxD,sBAAsB,QAAgB,cAA8B;AAClE,SAAO,KAAK,oBAAoB,OAAO,EAAE,aAAa;;CAGxD,MAAM,qBAAqB,QAAgB,cAAqC;AAE9E,QAAM,GADW,KAAK,sBAAsB,QAAQ,aACnC,EAAE,EAAE,OAAO,MAAM,CAAC,CAAC,OAAO,QAAQ;AACjD,OAAI,KAAK;IAAE;IAAK;IAAQ;IAAc,EAAE,wCAAwC;IAChF;;CAGJ,MAAM,aAAa,MAAY,SAAyC;EACtE,MAAM,aAAa,sBAAsB,KAAK,GAAG;AACjD,QAAM,MAAM,YAAY,EAAE,WAAW,MAAM,CAAC;EAC5C,MAAM,WAAyB;GAC7B,QAAQ,KAAK;GACb,WAAW,KAAK,KAAK;GACrB;GACA,OAAO,KAAK;GACZ,MAAM,KAAK;GACX,QAAQ,KAAK;GACb,MAAM,KAAK;GACX,MAAM,KAAK;GACX,QAAQ,KAAK;GACd;AAED,QAAM,gBADW,KAAK,YAAY,GAAG,SAAS,UAAU,OAC1B,EAAE,KAAK,UAAU,UAAU,MAAM,EAAE,CAAC;AAClE,MAAI,MAAM;GAAE,QAAQ,KAAK;GAAI;GAAS,WAAW,SAAS;GAAW,EAAE,iBAAiB;;CAG1F,MAAM,cAAc,QAA8C;EAChE,MAAM,aAAa,sBAAsB,OAAO;EAChD,IAAI;AACJ,MAAI;AACF,WAAQ,MAAM,QAAQ,WAAW;UAC3B;AACN,UAAO,EAAE;;EAEX,MAAM,UAA+B,EAAE;AACvC,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,CAAC,KAAK,SAAS,QAAQ,CAAE;GAC7B,MAAM,YAAY,SAAS,KAAK,MAAM,GAAG,GAAgB,EAAE,GAAG;AAC9D,OAAI,CAAC,OAAO,SAAS,UAAU,CAAE;AACjC,OAAI;IACF,MAAM,UAAU,MAAM,SAAS,KAAK,YAAY,KAAK,EAAE,QAAQ;IAC/D,MAAM,WAAW,KAAK,MAAM,QAAQ;IACpC,MAAM,UAAU,SAAS,QAAQ;AACjC,YAAQ,KAAK;KACX,WAAW,SAAS;KACpB,SAAS,SAAS;KAClB,SAAS,QAAQ,MAAM,GAAG,GAAG,IAAI,KAAA;KAClC,CAAC;WACI;AACN,QAAI,MAAM;KAAE;KAAQ;KAAM,EAAE,8BAA8B;;;AAG9D,UAAQ,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,UAAU;AACjD,SAAO;;CAGT,MAAM,YAAY,QAAgB,WAAiD;EACjF,MAAM,WAAW,KAAK,sBAAsB,OAAO,EAAE,GAAG,UAAU,OAAO;AACzE,MAAI;GACF,MAAM,UAAU,MAAM,SAAS,UAAU,QAAQ;AACjD,UAAO,KAAK,MAAM,QAAQ;UACpB;AACN,UAAO;;;CAIX,MAAM,eAAe,QAAgB,UAAiC;EACpE,MAAM,aAAa,sBAAsB,OAAO;EAChD,IAAI;AACJ,MAAI;AACF,WAAQ,MAAM,QAAQ,WAAW;UAC3B;AACN;;EAEF,MAAM,YAAY,MACf,QAAQ,MAAM,EAAE,SAAS,QAAQ,CAAC,CAClC,MAAM;AACT,MAAI,UAAU,UAAU,SAAU;EAClC,MAAM,WAAW,UAAU,MAAM,GAAG,UAAU,SAAS,SAAS;AAChE,OAAK,MAAM,QAAQ,SACjB,OAAM,GAAG,KAAK,YAAY,KAAK,EAAE,EAAE,OAAO,MAAM,CAAC,CAAC,YAAY,KAAA,EAAU;AAE1E,MAAI,MAAM;GAAE;GAAQ,SAAS,SAAS;GAAQ,EAAE,uBAAuB;;CAGzE,MAAM,mBAAmB,QAA+B;AAEtD,QAAM,GADa,sBAAsB,OACtB,EAAE;GAAE,WAAW;GAAM,OAAO;GAAM,CAAC,CAAC,YAAY,KAAA,EAAU;;CAG/E,MAAM,QAAuB;AAC3B,MAAI,CAAC,KAAK,SAAS,CAAC,KAAK,WAAY;AACrC,MAAI,KAAK,aAAa;AACpB,gBAAa,KAAK,YAAY;AAC9B,QAAK,cAAc;;AAErB,QAAM,KAAK,WAAW,KAAK,WAAW;AACtC,OAAK,QAAQ;;CAGf,MAAc,YAAqC;AACjD,MAAI,KAAK,WAAY,QAAO,KAAK;EACjC,MAAM,YAAY,uBAAuB;AACzC,MAAI;GACF,MAAM,UAAU,MAAM,SAAS,WAAW,QAAQ;GAClD,MAAM,OAAO,KAAK,MAAM,QAAQ;AAChC,OAAI,CAAC,KAAK,SAAS,CAAC,MAAM,QAAQ,KAAK,MAAM,EAAE;AAC7C,QAAI,KAAK,iCAAiC;AAC1C,SAAK,aAAa;AAClB,WAAO,KAAK;;AAEd,QAAK,aAAa;AAClB,UAAO;UACD;AACN,QAAK,aAAa;AAClB,UAAO,KAAK;;;CAIhB,MAAc,WAAW,MAAqC;AAE5D,QAAM,gBADY,uBACa,EAAE,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AAC/D,MAAI,MAAM,EAAE,OAAO,KAAK,MAAM,QAAQ,EAAE,oBAAoB;;CAG9D,MAAc,cAAc,MAA2B;AAErD,QAAM,gBADW,oBAAoB,KAAK,GACZ,EAAE,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;;CAGhE,kBAA0B,MAA4B;AACpD,OAAK,aAAa;AAClB,OAAK,QAAQ;AACb,MAAI,KAAK,YACP,cAAa,KAAK,YAAY;AAEhC,OAAK,cAAc,iBAAiB;AAClC,QAAK,OAAO,CAAC,OAAO,QAAQ;AAC1B,QAAI,MAAM,EAAE,KAAK,EAAE,8BAA8B;KACjD;KACD,YAAY;;CAGjB,MAAc,wBAAuC;EACnD,MAAM,WAAW,KAAK,iBAAiB,EAAE,QAAQ;EACjD,IAAI;AACJ,MAAI;AACF,WAAQ,MAAM,QAAQ,SAAS;UACzB;AACN,QAAK,aAAa;AAClB,SAAM,KAAK,WAAW,cAAc;AACpC;;EAGF,MAAM,UAA4B,EAAE;AACpC,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,CAAC,KAAK,SAAS,QAAQ,CAAE;GAC7B,MAAM,SAAS,KAAK,MAAM,GAAG,GAAgB;GAC7C,MAAM,OAAO,MAAM,KAAK,QAAQ,OAAO;AACvC,OAAI,KACF,SAAQ,KAAK,iBAAiB,KAAK,CAAC;;AAIxC,UAAQ,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,UAAU;EACjD,MAAM,QAAwB;GAAE,SAAS;GAAe,OAAO;GAAS;AACxE,OAAK,aAAa;AAClB,QAAM,KAAK,WAAW,MAAM;AAC5B,MAAI,MAAM,EAAE,OAAO,QAAQ,QAAQ,EAAE,sBAAsB"}
@@ -0,0 +1,162 @@
1
+ export type NoteKind = 'thought' | 'todo' | 'voice' | 'media' | 'bookmark' | 'mixed';
2
+ export type NoteStatus = 'inbox' | 'processed' | 'archived' | 'trashed';
3
+ export type CaptureChannel = 'app' | 'web' | 'electron' | 'tui' | 'telegram' | 'wechat' | 'feishu';
4
+ export type NoteBlockType = 'paragraph' | 'heading' | 'todo' | 'bulletList' | 'numberedList' | 'quote' | 'code' | 'divider' | 'image' | 'aiSuggestion';
5
+ export interface BaseNoteBlock {
6
+ id: string;
7
+ type: NoteBlockType;
8
+ createdAt: number;
9
+ updatedAt: number;
10
+ }
11
+ export interface TextNoteBlock extends BaseNoteBlock {
12
+ type: 'paragraph' | 'heading' | 'bulletList' | 'numberedList' | 'quote' | 'code' | 'aiSuggestion';
13
+ text: string;
14
+ level?: 1 | 2 | 3;
15
+ indent?: number;
16
+ }
17
+ export interface TodoNoteBlock extends BaseNoteBlock {
18
+ type: 'todo';
19
+ text: string;
20
+ checked: boolean;
21
+ }
22
+ export interface DividerNoteBlock extends BaseNoteBlock {
23
+ type: 'divider';
24
+ }
25
+ export interface ImageNoteBlock extends BaseNoteBlock {
26
+ type: 'image';
27
+ attachmentId: string;
28
+ alt?: string;
29
+ width?: number;
30
+ }
31
+ export type NoteBlock = TextNoteBlock | TodoNoteBlock | DividerNoteBlock | ImageNoteBlock;
32
+ export type NotePatchOperation = {
33
+ type: 'replaceBlocks';
34
+ blocks: NoteBlock[];
35
+ } | {
36
+ type: 'insertBlocksAfter';
37
+ afterBlockId: string;
38
+ blocks: NoteBlock[];
39
+ } | {
40
+ type: 'updateBlock';
41
+ blockId: string;
42
+ patch: Partial<NoteBlock>;
43
+ } | {
44
+ type: 'updateMetadata';
45
+ title?: string;
46
+ tags?: string[];
47
+ status?: NoteStatus;
48
+ };
49
+ export interface NoteAiPatch {
50
+ id: string;
51
+ summary: string;
52
+ operations: NotePatchOperation[];
53
+ }
54
+ export interface NoteAttachment {
55
+ id: string;
56
+ type: 'image' | 'video' | 'audio' | 'file';
57
+ mimeType: string;
58
+ fileName: string;
59
+ size: number;
60
+ relativePath: string;
61
+ transcript?: string;
62
+ duration?: number;
63
+ }
64
+ export interface NoteAiMeta {
65
+ summary?: string;
66
+ intent?: 'action_item' | 'idea' | 'reference' | 'question' | 'log';
67
+ extractedTodos?: Array<{
68
+ text: string;
69
+ deadline?: string;
70
+ done: boolean;
71
+ }>;
72
+ suggestedTags?: string[];
73
+ }
74
+ export interface NoteAiDeepMeta {
75
+ processedAt: number;
76
+ priority?: 'high' | 'medium' | 'low';
77
+ relatedNoteIds?: string[];
78
+ relatedGoalId?: string;
79
+ insights?: string;
80
+ }
81
+ export interface CaptureSource {
82
+ channel: CaptureChannel;
83
+ platform?: 'ios' | 'android';
84
+ }
85
+ export interface Note {
86
+ id: string;
87
+ title?: string;
88
+ kind: NoteKind;
89
+ status: NoteStatus;
90
+ text?: string;
91
+ blocks?: NoteBlock[];
92
+ attachments?: NoteAttachment[];
93
+ createdAt: number;
94
+ updatedAt: number;
95
+ capturedVia: CaptureSource;
96
+ ai?: NoteAiMeta;
97
+ aiDeep?: NoteAiDeepMeta;
98
+ tags?: string[];
99
+ pinned?: boolean;
100
+ localVersion?: number;
101
+ remoteVersion?: number;
102
+ }
103
+ export interface NoteIndexEntry {
104
+ id: string;
105
+ title?: string;
106
+ kind: NoteKind;
107
+ status: NoteStatus;
108
+ createdAt: number;
109
+ updatedAt: number;
110
+ pinned?: boolean;
111
+ tags?: string[];
112
+ snippet?: string;
113
+ /** First image attachment id for list thumbnails. */
114
+ coverAttachmentId?: string;
115
+ /** First audio attachment id for inline voice playback. */
116
+ voiceAttachmentId?: string;
117
+ /** Duration in seconds of the voice attachment (when available). */
118
+ voiceDurationSec?: number;
119
+ /** Lowercased attachment file names for list search. */
120
+ attachmentNames?: string[];
121
+ }
122
+ export interface NotesIndexFile {
123
+ version: number;
124
+ notes: NoteIndexEntry[];
125
+ }
126
+ export type SnapshotTrigger = 'edit' | 'ai_edit' | 'sync' | 'restore';
127
+ export interface NoteSnapshot {
128
+ noteId: string;
129
+ timestamp: number;
130
+ trigger: SnapshotTrigger;
131
+ title?: string;
132
+ text?: string;
133
+ blocks?: NoteBlock[];
134
+ tags?: string[];
135
+ kind: NoteKind;
136
+ status: NoteStatus;
137
+ }
138
+ export interface NoteSnapshotEntry {
139
+ timestamp: number;
140
+ trigger: SnapshotTrigger;
141
+ snippet?: string;
142
+ }
143
+ export interface NotesListQuery {
144
+ status?: NoteStatus;
145
+ kind?: NoteKind;
146
+ tag?: string;
147
+ pinned?: boolean;
148
+ search?: string;
149
+ limit?: number;
150
+ offset?: number;
151
+ sortBy?: 'createdAt' | 'updatedAt';
152
+ sortOrder?: 'asc' | 'desc';
153
+ }
154
+ export interface CreateNoteParams {
155
+ title?: string;
156
+ text?: string;
157
+ blocks?: NoteBlock[];
158
+ kind?: NoteKind;
159
+ tags?: string[];
160
+ capturedVia: CaptureSource;
161
+ pinned?: boolean;
162
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -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
@@ -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";
@@ -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).