@xopcai/xopc 0.0.95 → 0.0.96
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.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/feishu/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +2 -2
- package/dist/extensions/weixin/src/auth/accounts.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/media/data-url.js +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
- package/dist/extensions/weixin/src/workflow-progress.js +1 -1
- package/dist/gateway/static/root/assets/{agents-CKe2LMnz.js → agents-DmIuSaOE.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-Mi9mMIZ1.js → apps-page-DFcHBxLw.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-BrdyC101.js → channels-settings-DDUf55C5.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-status-swr-D55Bu0nn.js → channels-status-swr-BxF-_nzD.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-api-CPpx2l-E.js → cron-api-DylQtnb_.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-Bx2jB0YN.js → cron-page-BO0d9Pf-.js} +1 -1
- package/dist/gateway/static/root/assets/{dist-D_AiG_Kg.js → dist-BskF0qDS.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-6ieHsxRE.js → extension-debug-page-BcZdTdjJ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-B8nywHRO.js → extension-page-D2iuDa1D.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DrskdEIV.js → extension-settings-page-BKpQCgLc.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-B0aeeY0q.js → fetch-CtNDpjij.js} +1 -1
- package/dist/gateway/static/root/assets/{field-primitives--9ooY8Xl.js → field-primitives-2PekrGZF.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-DUZ_W1w-.js → heartbeat-config-api-D3D7SW8A.js} +1 -1
- package/dist/gateway/static/root/assets/index-BvEhL9RQ.css +1 -0
- package/dist/gateway/static/root/assets/{index-Dj9FuxCm.js → index-Db9fd_X4.js} +74 -74
- package/dist/gateway/static/root/assets/{logs-page-CaXqhpKf.js → logs-page-B3I1a26m.js} +1 -1
- package/dist/gateway/static/root/assets/{note-detail-page-DYzym2B0.js → note-detail-page-BOizhtJ8.js} +54 -53
- package/dist/gateway/static/root/assets/{note-detail-page-B91pLkEI.css → note-detail-page-D4ZIVQbk.css} +1 -1
- package/dist/gateway/static/root/assets/{note-time-B-vSi2dR.js → note-time-CjUGtqKr.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-BkhWdGiT.js → notes-page-BB8-I0Of.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-53YFokoe.js → sessions-page-BcH-1K9i.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-advanced-gate-BaZmaklx.js → settings-advanced-gate-Czn8nnjN.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-DIJPKpTR.js → settings-form-section-ZZWDwgVe.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-Dvb230FF.js → settings-page-BX8c_zrN.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-CRyjTAG6.js → share-preview-page-Ch3_6Qah.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-C5ZJbfAe.js → skills-page-WO0bbJ54.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-Cg_SuBw0.js → theme-store-XxRFRZDX.js} +1 -1
- package/dist/gateway/static/root/assets/url-6zpynn1R.js +3 -0
- package/dist/gateway/static/root/assets/{utils-lMYoWhqo.js → utils-uTYKh54l.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-Dda2pcUU.js → voice-api-key-field-BIAYHRs-.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-page.utils-KIladUrU.js → workflow-page.utils-BbWhqD36.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-BTis4Z7Y.js → workflows-page-D4RIF7E1.js} +1 -1
- package/dist/gateway/static/root/index.html +5 -5
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +15 -9
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/agent-scope.d.ts +0 -1
- package/dist/src/agent/agent-scope.js +2 -5
- package/dist/src/agent/agent-scope.js.map +1 -1
- package/dist/src/agent/bootstrap/bootstrap-cache.d.ts +3 -0
- package/dist/src/agent/bootstrap/bootstrap-cache.js +13 -3
- package/dist/src/agent/bootstrap/bootstrap-cache.js.map +1 -1
- package/dist/src/agent/bootstrap/bootstrap-files.d.ts +6 -0
- package/dist/src/agent/bootstrap/bootstrap-files.js +35 -12
- package/dist/src/agent/bootstrap/bootstrap-files.js.map +1 -1
- package/dist/src/agent/bootstrap/load-bootstrap-files.d.ts +5 -2
- package/dist/src/agent/bootstrap/load-bootstrap-files.js +12 -3
- package/dist/src/agent/bootstrap/load-bootstrap-files.js.map +1 -1
- package/dist/src/agent/context/workspace-seed.js +8 -4
- package/dist/src/agent/context/workspace-seed.js.map +1 -1
- package/dist/src/agent/context/workspace-state.d.ts +52 -0
- package/dist/src/agent/context/workspace-state.js +101 -0
- package/dist/src/agent/context/workspace-state.js.map +1 -0
- package/dist/src/agent/embedded/index.d.ts +2 -2
- package/dist/src/agent/embedded/index.js +3 -3
- package/dist/src/agent/embedded/run-turn.js +0 -3
- package/dist/src/agent/embedded/run-turn.js.map +1 -1
- package/dist/src/agent/embedded/session-manager-init.d.ts +0 -17
- package/dist/src/agent/embedded/session-manager-init.js +1 -36
- package/dist/src/agent/embedded/session-manager-init.js.map +1 -1
- package/dist/src/agent/embedded/session-runner.d.ts +3 -12
- package/dist/src/agent/embedded/session-runner.js +12 -26
- package/dist/src/agent/embedded/session-runner.js.map +1 -1
- package/dist/src/agent/embedded/session-tool-result-guard.js +2 -4
- package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
- package/dist/src/agent/embedded/sqlite-hydrating-session-manager.d.ts +10 -0
- package/dist/src/agent/embedded/sqlite-hydrating-session-manager.js +34 -0
- package/dist/src/agent/embedded/sqlite-hydrating-session-manager.js.map +1 -0
- package/dist/src/agent/goals/goal-run-store.js +4 -4
- package/dist/src/agent/goals/persistent-goal-service.js +8 -15
- package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
- package/dist/src/agent/goals/post-turn.js +2 -2
- package/dist/src/agent/image/load-image-media.js +2 -2
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/ipc/inbox.js +2 -2
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +2 -2
- package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
- package/dist/src/agent/mcp/mcp-transport.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
- package/dist/src/agent/memory/dreaming/events.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
- package/dist/src/agent/memory/dreaming/preview.js +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.js +1 -1
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/memory/index.d.ts +1 -0
- package/dist/src/agent/prompt/memory/index.js +34 -80
- package/dist/src/agent/prompt/memory/index.js.map +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
- package/dist/src/agent/reply/post-compaction-context.js +1 -1
- package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
- package/dist/src/agent/sandbox/path-policy.js +2 -2
- package/dist/src/agent/service/build-direct-message-content.js +1 -1
- package/dist/src/agent/service/process-direct-one-shot.js +8 -17
- package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.js +14 -23
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.js +7 -11
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/config.js +1 -1
- package/dist/src/agent/skills/hub-hash.js +2 -2
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +3 -3
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/managed-store.js +1 -1
- package/dist/src/agent/skills/scanner.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/tools/dreaming-tool.js +1 -1
- package/dist/src/agent/tools/factory.js +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +1 -1
- package/dist/src/agent/tools/index.d.ts +0 -1
- package/dist/src/agent/tools/index.js +1 -2
- package/dist/src/agent/tools/send-media.js +1 -1
- package/dist/src/agent/tools/session-search-tool.d.ts +0 -1
- package/dist/src/agent/tools/session-search-tool.js +11 -6
- package/dist/src/agent/tools/session-search-tool.js.map +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +1 -1
- package/dist/src/agent/tools/workflow-tool.js +1 -1
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/agent/workflow/catalog.js +1 -1
- package/dist/src/auth/credentials.js +3 -3
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/browser/cache-dir-policy.js +1 -1
- package/dist/src/browser/cdp-local-launcher.js +2 -2
- package/dist/src/browser/providers/browser-ext-install.js +4 -4
- package/dist/src/browser/providers/cloakbrowser.js +4 -4
- package/dist/src/browser/providers/playwright-doctor.js +1 -1
- package/dist/src/browser/stealth.js +1 -1
- package/dist/src/channels/attachments/inbound-persist.js +1 -1
- package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
- package/dist/src/channels/outbound/persist-store.js +1 -1
- package/dist/src/channels/pairing/allow-from-file.js +1 -1
- package/dist/src/channels/pairing/pairing-store.js +2 -2
- package/dist/src/chat-commands/agent-edit.js +2 -2
- package/dist/src/chat-commands/builtins/config.js +2 -2
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/cli/commands/config.js +1 -1
- package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +32 -95
- package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
- package/dist/src/cli/commands/extension-dev.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/extension-pack.js +1 -1
- package/dist/src/cli/commands/gateway/logs.js +1 -1
- package/dist/src/cli/commands/image.js +1 -1
- package/dist/src/cli/commands/init.js +5 -7
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +2 -2
- package/dist/src/commands/agents.config.js +1 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/gateway-bind.js +1 -1
- package/dist/src/config/index.js +7 -8
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/config/loader.js +2 -2
- package/dist/src/config/models-json.js +2 -2
- package/dist/src/config/paths-state.d.ts +3 -0
- package/dist/src/config/paths-state.js +7 -3
- package/dist/src/config/paths-state.js.map +1 -1
- package/dist/src/config/paths.d.ts +5 -35
- package/dist/src/config/paths.js +6 -50
- package/dist/src/config/paths.js.map +1 -1
- package/dist/src/config/profile.js +2 -2
- package/dist/src/config/schema.d.ts +15 -0
- package/dist/src/config/schema.js +11 -0
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/workspace-path.js +1 -1
- package/dist/src/cron/execution-types.d.ts +42 -0
- package/dist/src/cron/executor.js +2 -2
- package/dist/src/cron/persistence.js +1 -1
- package/dist/src/cron/run-log-store.d.ts +4 -8
- package/dist/src/cron/run-log-store.js +26 -78
- package/dist/src/cron/run-log-store.js.map +1 -1
- package/dist/src/cron/service.d.ts +3 -3
- package/dist/src/cron/service.js +2 -2
- package/dist/src/cron/service.js.map +1 -1
- package/dist/src/cron/types.d.ts +1 -42
- package/dist/src/daemon/constants.js +1 -1
- package/dist/src/daemon/install-plan.js +2 -2
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/schtasks.js +2 -2
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/extensions/bundle-mcp.js +1 -1
- package/dist/src/extensions/discover-extensions.js +1 -1
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/loader.js +1 -1
- package/dist/src/extensions/lockfile.js +2 -2
- package/dist/src/extensions/update.js +1 -1
- package/dist/src/gateway/agents-admin.js +8 -3
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/file-path-classifier.d.ts +0 -1
- package/dist/src/gateway/file-path-classifier.js +2 -8
- package/dist/src/gateway/file-path-classifier.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/lib/extension-store.js +2 -2
- package/dist/src/gateway/hono/lib/static-ui.js +2 -2
- package/dist/src/gateway/hono/oauth.js +1 -1
- package/dist/src/gateway/hono/routes/agents.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/host-fs.js +2 -2
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/shares.js +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +2 -2
- package/dist/src/gateway/lock.js +3 -3
- package/dist/src/gateway/ports.js +1 -1
- package/dist/src/gateway/service/agent-runner.js +2 -2
- package/dist/src/gateway/service/marketplace-service.js +2 -2
- package/dist/src/gateway/service.js +5 -1
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/session-reset-service.d.ts +1 -1
- package/dist/src/gateway/session-reset-service.js +1 -1
- package/dist/src/gateway/session-reset-service.js.map +1 -1
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/infra/brew.js +1 -1
- package/dist/src/infra/node-sqlite.d.ts +1 -0
- package/dist/src/infra/node-sqlite.js +17 -0
- package/dist/src/infra/node-sqlite.js.map +1 -0
- package/dist/src/infra/package-json.js +1 -1
- package/dist/src/infra/package-update-steps.js +1 -1
- package/dist/src/infra/path-env.js +2 -2
- package/dist/src/infra/restart.js +2 -2
- package/dist/src/infra/sqlite-errors.d.ts +1 -0
- package/dist/src/infra/sqlite-errors.js +77 -0
- package/dist/src/infra/sqlite-errors.js.map +1 -0
- package/dist/src/infra/stable-node-path.js +1 -1
- package/dist/src/infra/unhandled-rejections.d.ts +1 -0
- package/dist/src/infra/unhandled-rejections.js +25 -0
- package/dist/src/infra/unhandled-rejections.js.map +1 -0
- package/dist/src/infra/update-check.js +1 -1
- package/dist/src/infra/update-global.js +1 -1
- package/dist/src/infra/update-lock.js +3 -3
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/infra/update-startup.js +2 -2
- package/dist/src/infra/warning-filter.d.ts +7 -0
- package/dist/src/infra/warning-filter.js +59 -0
- package/dist/src/infra/warning-filter.js.map +1 -0
- package/dist/src/infra/write-file-atomic.js +2 -2
- package/dist/src/notes/store.d.ts +3 -9
- package/dist/src/notes/store.js +22 -196
- package/dist/src/notes/store.js.map +1 -1
- package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/session/config-store.d.ts +6 -75
- package/dist/src/session/config-store.js +38 -144
- package/dist/src/session/config-store.js.map +1 -1
- package/dist/src/session/config-types.d.ts +15 -0
- package/dist/src/session/config-types.js +1 -0
- package/dist/src/session/index.d.ts +1 -3
- package/dist/src/session/index.js +3 -5
- package/dist/src/session/init-session-turn.d.ts +0 -6
- package/dist/src/session/init-session-turn.js +18 -18
- package/dist/src/session/init-session-turn.js.map +1 -1
- package/dist/src/session/lifecycle-timestamps.d.ts +5 -2
- package/dist/src/session/lifecycle-timestamps.js.map +1 -1
- package/dist/src/session/{parity/load-jsonl-entries.js → load-jsonl-entries.js} +1 -1
- package/dist/src/session/load-jsonl-entries.js.map +1 -0
- package/dist/src/session/manager.d.ts +5 -3
- package/dist/src/session/manager.js +1 -5
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/resolve-session.d.ts +3 -6
- package/dist/src/session/resolve-session.js +26 -31
- package/dist/src/session/resolve-session.js.map +1 -1
- package/dist/src/session/session-context-for-llm.js +5 -1
- package/dist/src/session/session-context-for-llm.js.map +1 -1
- package/dist/src/session/session-id.js +12 -0
- package/dist/src/session/session-id.js.map +1 -0
- package/dist/src/session/session-title.js +2 -2
- package/dist/src/session/session-workspace.d.ts +1 -1
- package/dist/src/session/session-workspace.js.map +1 -1
- package/dist/src/session/store.d.ts +14 -63
- package/dist/src/session/store.js +172 -847
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/stored-rows-to-file-entries.d.ts +11 -0
- package/dist/src/session/stored-rows-to-file-entries.js +95 -0
- package/dist/src/session/stored-rows-to-file-entries.js.map +1 -0
- package/dist/src/session/transcript-events.d.ts +1 -2
- package/dist/src/session/transcript-events.js +5 -12
- package/dist/src/session/transcript-events.js.map +1 -1
- package/dist/src/session/transcript-format.d.ts +1 -1
- package/dist/src/session/transcript-format.js.map +1 -1
- package/dist/src/session/transcript-stats.d.ts +1 -0
- package/dist/src/session/transcript-stats.js +10 -0
- package/dist/src/session/transcript-stats.js.map +1 -0
- package/dist/src/share/share-auto.js +2 -2
- package/dist/src/share/share-store.js +3 -3
- package/dist/src/share/share-thumbnail.js +2 -2
- package/dist/src/share/share-zip.js +1 -1
- package/dist/src/share/site-share-store.js +3 -3
- package/dist/src/share/site-static-serve.js +1 -1
- package/dist/src/storage/sqlite/config-repository.d.ts +6 -0
- package/dist/src/storage/sqlite/config-repository.js +56 -0
- package/dist/src/storage/sqlite/config-repository.js.map +1 -0
- package/dist/src/storage/sqlite/connection.d.ts +38 -0
- package/dist/src/storage/sqlite/connection.js +258 -0
- package/dist/src/storage/sqlite/connection.js.map +1 -0
- package/dist/src/storage/sqlite/cron-run-repository.d.ts +5 -0
- package/dist/src/storage/sqlite/cron-run-repository.js +97 -0
- package/dist/src/storage/sqlite/cron-run-repository.js.map +1 -0
- package/dist/src/storage/sqlite/fts.d.ts +2 -0
- package/dist/src/storage/sqlite/fts.js +11 -0
- package/dist/src/storage/sqlite/fts.js.map +1 -0
- package/dist/src/storage/sqlite/index.d.ts +12 -0
- package/dist/src/storage/sqlite/index.js +13 -0
- package/dist/src/storage/sqlite/memory-index-repository.d.ts +18 -0
- package/dist/src/storage/sqlite/memory-index-repository.js +132 -0
- package/dist/src/storage/sqlite/memory-index-repository.js.map +1 -0
- package/dist/src/storage/sqlite/notes-repository.d.ts +11 -0
- package/dist/src/storage/sqlite/notes-repository.js +191 -0
- package/dist/src/storage/sqlite/notes-repository.js.map +1 -0
- package/dist/src/storage/sqlite/paths.d.ts +1 -0
- package/dist/src/storage/sqlite/paths.js +7 -0
- package/dist/src/storage/sqlite/paths.js.map +1 -0
- package/dist/src/storage/sqlite/row-mappers.d.ts +82 -0
- package/dist/src/storage/sqlite/row-mappers.js +164 -0
- package/dist/src/storage/sqlite/row-mappers.js.map +1 -0
- package/dist/src/storage/sqlite/schema.d.ts +5 -0
- package/dist/src/storage/sqlite/schema.js +43 -0
- package/dist/src/storage/sqlite/schema.js.map +1 -0
- package/dist/src/storage/sqlite/schema.sql +195 -0
- package/dist/src/storage/sqlite/session-metadata.d.ts +8 -0
- package/dist/src/storage/sqlite/session-metadata.js +83 -0
- package/dist/src/storage/sqlite/session-metadata.js.map +1 -0
- package/dist/src/storage/sqlite/session-repository.d.ts +29 -0
- package/dist/src/storage/sqlite/session-repository.js +268 -0
- package/dist/src/storage/sqlite/session-repository.js.map +1 -0
- package/dist/src/storage/sqlite/transaction.d.ts +11 -0
- package/dist/src/storage/sqlite/transaction.js +115 -0
- package/dist/src/storage/sqlite/transaction.js.map +1 -0
- package/dist/src/storage/sqlite/transcript-repository.d.ts +34 -0
- package/dist/src/storage/sqlite/transcript-repository.js +241 -0
- package/dist/src/storage/sqlite/transcript-repository.js.map +1 -0
- package/dist/src/tui/clipboard-image.js +3 -3
- package/dist/src/tui/theme-manager.js +1 -1
- package/dist/src/tui/tui-keybindings-file.js +1 -1
- package/dist/src/tui/tui-scoped-models.js +2 -2
- package/dist/src/tui/tui-settings.js +1 -1
- package/dist/src/tui/tui.js +3 -3
- package/dist/src/tunnel/frpc-binary.js +3 -3
- package/dist/src/tunnel/frpc-config.js +1 -1
- package/dist/src/tunnel/frpc-extract.js +1 -1
- package/dist/src/tunnel/tunnel-state.js +1 -1
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/log-store.js +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/dist/src/voice/tts/providers/edge-speech.js +2 -2
- package/dist/src/workflows/service/workflow-session-bridge.js +41 -64
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
- package/dist/src/workflows/store/event-store.js +1 -1
- package/dist/src/workflows/store/run-store.js +1 -1
- package/package.json +2 -2
- package/dist/gateway/static/root/assets/index-Bj_l8QDp.css +0 -1
- package/dist/gateway/static/root/assets/url-BHHmdJYc.js +0 -3
- package/dist/src/agent/embedded/session-manager-cache.d.ts +0 -19
- package/dist/src/agent/embedded/session-manager-cache.js +0 -48
- package/dist/src/agent/embedded/session-manager-cache.js.map +0 -1
- package/dist/src/session/parity/artifacts.d.ts +0 -16
- package/dist/src/session/parity/artifacts.js +0 -80
- package/dist/src/session/parity/artifacts.js.map +0 -1
- package/dist/src/session/parity/jsonl-transcript-io.d.ts +0 -54
- package/dist/src/session/parity/jsonl-transcript-io.js +0 -236
- package/dist/src/session/parity/jsonl-transcript-io.js.map +0 -1
- package/dist/src/session/parity/load-jsonl-entries.js.map +0 -1
- package/dist/src/session/parity/session-id.js +0 -18
- package/dist/src/session/parity/session-id.js.map +0 -1
- package/dist/src/session/parity/sessions-json-cache.d.ts +0 -14
- package/dist/src/session/parity/sessions-json-cache.js +0 -98
- package/dist/src/session/parity/sessions-json-cache.js.map +0 -1
- package/dist/src/session/parity/sessions-json-file-read.d.ts +0 -6
- package/dist/src/session/parity/sessions-json-file-read.js +0 -19
- package/dist/src/session/parity/sessions-json-file-read.js.map +0 -1
- package/dist/src/session/parity/sessions-json-file.d.ts +0 -11
- package/dist/src/session/parity/sessions-json-file.js +0 -52
- package/dist/src/session/parity/sessions-json-file.js.map +0 -1
- package/dist/src/session/parity/sessions-json-patch.d.ts +0 -14
- package/dist/src/session/parity/sessions-json-patch.js +0 -40
- package/dist/src/session/parity/sessions-json-patch.js.map +0 -1
- package/dist/src/session/parity/transcript-file-lock.d.ts +0 -22
- package/dist/src/session/parity/transcript-file-lock.js +0 -142
- package/dist/src/session/parity/transcript-file-lock.js.map +0 -1
- package/dist/src/session/parity/transcript-pagination.d.ts +0 -29
- package/dist/src/session/parity/transcript-pagination.js +0 -132
- package/dist/src/session/parity/transcript-pagination.js.map +0 -1
- package/dist/src/session/parity/transcript-paths.d.ts +0 -13
- package/dist/src/session/parity/transcript-paths.js +0 -64
- package/dist/src/session/parity/transcript-paths.js.map +0 -1
- package/dist/src/session/parity/xopc-session-disk-entry.d.ts +0 -22
- package/dist/src/session/search-index-cache.d.ts +0 -6
- package/dist/src/session/search-index-cache.js +0 -44
- package/dist/src/session/search-index-cache.js.map +0 -1
- package/dist/src/session/search-index.d.ts +0 -20
- package/dist/src/session/search-index.js +0 -124
- package/dist/src/session/search-index.js.map +0 -1
- /package/dist/src/{session/parity/xopc-session-disk-entry.js → cron/execution-types.js} +0 -0
- /package/dist/src/session/{parity/load-jsonl-entries.d.ts → load-jsonl-entries.d.ts} +0 -0
- /package/dist/src/session/{parity/session-id.d.ts → session-id.d.ts} +0 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
|
|
2
|
+
import { escapeFts5Query } from "./fts.js";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
5
|
+
import { join, relative } from "node:path";
|
|
6
|
+
//#region src/storage/sqlite/memory-index-repository.ts
|
|
7
|
+
const CURATED_MEMORY_FILENAMES = new Set(["MEMORY.md", "USER.md"]);
|
|
8
|
+
const MEMORY_SYNC_CACHE_TTL_MS = 3e4;
|
|
9
|
+
const memorySyncCache = /* @__PURE__ */ new Map();
|
|
10
|
+
function resolveAgentIdFromMemoriesDir(memoriesDir) {
|
|
11
|
+
if (!memoriesDir) return "main";
|
|
12
|
+
return memoriesDir.replace(/\\/g, "/").match(/\/agents\/([^/]+)\/memories\/?$/)?.[1] ?? "main";
|
|
13
|
+
}
|
|
14
|
+
function getDailyMemoryPath(baseDir, date) {
|
|
15
|
+
const d = date || /* @__PURE__ */ new Date();
|
|
16
|
+
return join(baseDir, "memory", `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}.md`);
|
|
17
|
+
}
|
|
18
|
+
function getCuratedMemoryPaths(memoriesDir) {
|
|
19
|
+
if (!memoriesDir) return [];
|
|
20
|
+
return [join(memoriesDir, "MEMORY.md"), join(memoriesDir, "USER.md")].filter((p) => existsSync(p));
|
|
21
|
+
}
|
|
22
|
+
function collectMemoryPaths(baseDir, memoriesDir) {
|
|
23
|
+
const paths = [];
|
|
24
|
+
paths.push(...getCuratedMemoryPaths(memoriesDir));
|
|
25
|
+
const longTermPath = join(baseDir, "MEMORY.md");
|
|
26
|
+
if (existsSync(longTermPath)) paths.push(longTermPath);
|
|
27
|
+
if (existsSync(join(baseDir, "memory"))) {
|
|
28
|
+
const today = /* @__PURE__ */ new Date();
|
|
29
|
+
for (let i = 0; i < 30; i++) {
|
|
30
|
+
const date = new Date(today);
|
|
31
|
+
date.setDate(date.getDate() - i);
|
|
32
|
+
const path = getDailyMemoryPath(baseDir, date);
|
|
33
|
+
if (existsSync(path)) paths.push(path);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return paths;
|
|
37
|
+
}
|
|
38
|
+
function displayPath(baseDir, memoriesDir, absPath) {
|
|
39
|
+
const normalized = absPath.replace(/\\/g, "/");
|
|
40
|
+
if (memoriesDir) {
|
|
41
|
+
const memoriesRoot = memoriesDir.replace(/\\/g, "/");
|
|
42
|
+
if (normalized.startsWith(memoriesRoot)) {
|
|
43
|
+
const filename = normalized.slice(memoriesRoot.length).replace(/^\//, "");
|
|
44
|
+
if (CURATED_MEMORY_FILENAMES.has(filename)) return filename;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return relative(baseDir, absPath).replace(/\\/g, "/");
|
|
48
|
+
}
|
|
49
|
+
function contentHash(content) {
|
|
50
|
+
return createHash("sha256").update(content).digest("hex");
|
|
51
|
+
}
|
|
52
|
+
function bm25ToScore(rank) {
|
|
53
|
+
return 1 / (1 + Math.max(0, -rank));
|
|
54
|
+
}
|
|
55
|
+
function indexFile(db, agentId, baseDir, memoriesDir, absPath) {
|
|
56
|
+
const content = readFileSync(absPath, "utf-8");
|
|
57
|
+
const mtimeMs = statSync(absPath).mtimeMs;
|
|
58
|
+
const hash = contentHash(content);
|
|
59
|
+
const relPath = displayPath(baseDir, memoriesDir, absPath);
|
|
60
|
+
const fileId = `${agentId}:${relPath}`;
|
|
61
|
+
const existing = db.prepare(`SELECT content_hash, mtime_ms FROM memory_files WHERE file_id = ?`).get(fileId);
|
|
62
|
+
if (existing && existing.content_hash === hash && existing.mtime_ms === mtimeMs) return;
|
|
63
|
+
db.prepare(`DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`).run(fileId);
|
|
64
|
+
db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(fileId);
|
|
65
|
+
db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(fileId);
|
|
66
|
+
db.prepare(`INSERT INTO memory_files (file_id, agent_id, path, mtime_ms, content_hash)
|
|
67
|
+
VALUES (?, ?, ?, ?, ?)`).run(fileId, agentId, relPath, mtimeMs, hash);
|
|
68
|
+
const lines = content.split("\n");
|
|
69
|
+
const insertChunk = db.prepare(`INSERT INTO memory_chunks (chunk_id, file_id, start_line, end_line, content)
|
|
70
|
+
VALUES (?, ?, ?, ?, ?)`);
|
|
71
|
+
const insertFts = db.prepare(`INSERT INTO memory_fts (content, chunk_id, agent_id, path, start_line, end_line)
|
|
72
|
+
VALUES (?, ?, ?, ?, ?, ?)`);
|
|
73
|
+
for (let i = 0; i < lines.length; i++) {
|
|
74
|
+
const line = lines[i];
|
|
75
|
+
if (!line.trim()) continue;
|
|
76
|
+
const lineNo = i + 1;
|
|
77
|
+
const chunkId = `${fileId}:${lineNo}`;
|
|
78
|
+
insertChunk.run(chunkId, fileId, lineNo, lineNo, line);
|
|
79
|
+
insertFts.run(line, chunkId, agentId, relPath, lineNo, lineNo);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function syncMemoryIndex(params) {
|
|
83
|
+
const cacheKey = `${params.agentId}:${params.workspaceDir}:${params.memoriesDir ?? ""}`;
|
|
84
|
+
const now = Date.now();
|
|
85
|
+
const cached = memorySyncCache.get(cacheKey);
|
|
86
|
+
if (cached && now - cached.timestamp < MEMORY_SYNC_CACHE_TTL_MS) return;
|
|
87
|
+
const paths = collectMemoryPaths(params.workspaceDir, params.memoriesDir);
|
|
88
|
+
memorySyncCache.set(cacheKey, {
|
|
89
|
+
timestamp: now,
|
|
90
|
+
paths
|
|
91
|
+
});
|
|
92
|
+
runSqliteWriteTransaction((db) => {
|
|
93
|
+
const seen = /* @__PURE__ */ new Set();
|
|
94
|
+
for (const absPath of paths) {
|
|
95
|
+
seen.add(`${params.agentId}:${displayPath(params.workspaceDir, params.memoriesDir, absPath)}`);
|
|
96
|
+
indexFile(db, params.agentId, params.workspaceDir, params.memoriesDir, absPath);
|
|
97
|
+
}
|
|
98
|
+
const stale = db.prepare(`SELECT file_id FROM memory_files WHERE agent_id = ?`).all(params.agentId);
|
|
99
|
+
for (const row of stale) if (!seen.has(row.file_id)) {
|
|
100
|
+
db.prepare(`DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`).run(row.file_id);
|
|
101
|
+
db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(row.file_id);
|
|
102
|
+
db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(row.file_id);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function searchMemoryIndex(params) {
|
|
107
|
+
const { agentId, query, maxResults = 5, minScore = .3 } = params;
|
|
108
|
+
const ftsQuery = escapeFts5Query(query);
|
|
109
|
+
if (!ftsQuery) return [];
|
|
110
|
+
const rows = getSqliteDatabase().prepare(`SELECT chunk_id, path, start_line, end_line, content, bm25(memory_fts) AS rank
|
|
111
|
+
FROM memory_fts
|
|
112
|
+
WHERE memory_fts MATCH ? AND agent_id = ?
|
|
113
|
+
ORDER BY rank
|
|
114
|
+
LIMIT ?`).all(ftsQuery, agentId, maxResults * 3);
|
|
115
|
+
const results = [];
|
|
116
|
+
for (const row of rows) {
|
|
117
|
+
const score = bm25ToScore(row.rank);
|
|
118
|
+
if (score < minScore) continue;
|
|
119
|
+
results.push({
|
|
120
|
+
path: row.path,
|
|
121
|
+
lines: row.content,
|
|
122
|
+
score,
|
|
123
|
+
lineNumbers: [row.start_line]
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
results.sort((a, b) => b.score - a.score);
|
|
127
|
+
return results.slice(0, maxResults);
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
export { resolveAgentIdFromMemoriesDir, searchMemoryIndex, syncMemoryIndex };
|
|
131
|
+
|
|
132
|
+
//# sourceMappingURL=memory-index-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-index-repository.js","names":[],"sources":["../../../../src/storage/sqlite/memory-index-repository.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\nimport { escapeFts5Query } from './fts.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\nexport type MemorySearchHit = {\n path: string;\n lines: string;\n score: number;\n lineNumbers: number[];\n};\n\nconst CURATED_MEMORY_FILENAMES = new Set(['MEMORY.md', 'USER.md']);\nconst MEMORY_SYNC_CACHE_TTL_MS = 30_000;\n\ntype MemorySyncCache = {\n timestamp: number;\n paths: string[];\n};\n\nconst memorySyncCache = new Map<string, MemorySyncCache>();\n\nexport function resolveAgentIdFromMemoriesDir(memoriesDir: string | undefined): string {\n if (!memoriesDir) return 'main';\n const normalized = memoriesDir.replace(/\\\\/g, '/');\n const match = normalized.match(/\\/agents\\/([^/]+)\\/memories\\/?$/);\n return match?.[1] ?? 'main';\n}\n\nfunction getDailyMemoryPath(baseDir: string, date?: Date): string {\n const d = date || new Date();\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return join(baseDir, 'memory', `${year}-${month}-${day}.md`);\n}\n\nfunction getCuratedMemoryPaths(memoriesDir: string | undefined): string[] {\n if (!memoriesDir) return [];\n return [join(memoriesDir, 'MEMORY.md'), join(memoriesDir, 'USER.md')].filter((p) => existsSync(p));\n}\n\nfunction collectMemoryPaths(baseDir: string, memoriesDir?: string): string[] {\n const paths: string[] = [];\n paths.push(...getCuratedMemoryPaths(memoriesDir));\n\n const longTermPath = join(baseDir, 'MEMORY.md');\n if (existsSync(longTermPath)) {\n paths.push(longTermPath);\n }\n\n const memoryDir = join(baseDir, 'memory');\n if (existsSync(memoryDir)) {\n const today = new Date();\n for (let i = 0; i < 30; i++) {\n const date = new Date(today);\n date.setDate(date.getDate() - i);\n const path = getDailyMemoryPath(baseDir, date);\n if (existsSync(path)) {\n paths.push(path);\n }\n }\n }\n\n return paths;\n}\n\nfunction displayPath(baseDir: string, memoriesDir: string | undefined, absPath: string): string {\n const normalized = absPath.replace(/\\\\/g, '/');\n if (memoriesDir) {\n const memoriesRoot = memoriesDir.replace(/\\\\/g, '/');\n if (normalized.startsWith(memoriesRoot)) {\n const filename = normalized.slice(memoriesRoot.length).replace(/^\\//, '');\n if (CURATED_MEMORY_FILENAMES.has(filename)) {\n return filename;\n }\n }\n }\n return relative(baseDir, absPath).replace(/\\\\/g, '/');\n}\n\nfunction contentHash(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nfunction bm25ToScore(rank: number): number {\n return 1 / (1 + Math.max(0, -rank));\n}\n\nfunction indexFile(\n db: ReturnType<typeof getSqliteDatabase>,\n agentId: string,\n baseDir: string,\n memoriesDir: string | undefined,\n absPath: string,\n): void {\n const content = readFileSync(absPath, 'utf-8');\n const mtimeMs = statSync(absPath).mtimeMs;\n const hash = contentHash(content);\n const relPath = displayPath(baseDir, memoriesDir, absPath);\n const fileId = `${agentId}:${relPath}`;\n\n const existing = db\n .prepare(`SELECT content_hash, mtime_ms FROM memory_files WHERE file_id = ?`)\n .get(fileId) as { content_hash: string; mtime_ms: number } | undefined;\n if (existing && existing.content_hash === hash && existing.mtime_ms === mtimeMs) {\n return;\n }\n\n db.prepare(`DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`).run(\n fileId,\n );\n db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(fileId);\n db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(fileId);\n\n db.prepare(\n `INSERT INTO memory_files (file_id, agent_id, path, mtime_ms, content_hash)\n VALUES (?, ?, ?, ?, ?)`,\n ).run(fileId, agentId, relPath, mtimeMs, hash);\n\n const lines = content.split('\\n');\n const insertChunk = db.prepare(\n `INSERT INTO memory_chunks (chunk_id, file_id, start_line, end_line, content)\n VALUES (?, ?, ?, ?, ?)`,\n );\n const insertFts = db.prepare(\n `INSERT INTO memory_fts (content, chunk_id, agent_id, path, start_line, end_line)\n VALUES (?, ?, ?, ?, ?, ?)`,\n );\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (!line.trim()) continue;\n const lineNo = i + 1;\n const chunkId = `${fileId}:${lineNo}`;\n insertChunk.run(chunkId, fileId, lineNo, lineNo, line);\n insertFts.run(line, chunkId, agentId, relPath, lineNo, lineNo);\n }\n}\n\nexport function syncMemoryIndex(params: {\n agentId: string;\n workspaceDir: string;\n memoriesDir?: string;\n}): void {\n const cacheKey = `${params.agentId}:${params.workspaceDir}:${params.memoriesDir ?? ''}`;\n const now = Date.now();\n const cached = memorySyncCache.get(cacheKey);\n if (cached && now - cached.timestamp < MEMORY_SYNC_CACHE_TTL_MS) {\n return;\n }\n\n const paths = collectMemoryPaths(params.workspaceDir, params.memoriesDir);\n memorySyncCache.set(cacheKey, { timestamp: now, paths });\n runSqliteWriteTransaction((db) => {\n const seen = new Set<string>();\n for (const absPath of paths) {\n seen.add(`${params.agentId}:${displayPath(params.workspaceDir, params.memoriesDir, absPath)}`);\n indexFile(db, params.agentId, params.workspaceDir, params.memoriesDir, absPath);\n }\n\n const stale = db\n .prepare(`SELECT file_id FROM memory_files WHERE agent_id = ?`)\n .all(params.agentId) as Array<{ file_id: string }>;\n for (const row of stale) {\n if (!seen.has(row.file_id)) {\n db.prepare(\n `DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`,\n ).run(row.file_id);\n db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(row.file_id);\n db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(row.file_id);\n }\n }\n });\n}\n\nexport function searchMemoryIndex(params: {\n agentId: string;\n query: string;\n maxResults?: number;\n minScore?: number;\n}): MemorySearchHit[] {\n const { agentId, query, maxResults = 5, minScore = 0.3 } = params;\n const ftsQuery = escapeFts5Query(query);\n if (!ftsQuery) {\n return [];\n }\n\n const db = getSqliteDatabase();\n const rows = db\n .prepare(\n `SELECT chunk_id, path, start_line, end_line, content, bm25(memory_fts) AS rank\n FROM memory_fts\n WHERE memory_fts MATCH ? AND agent_id = ?\n ORDER BY rank\n LIMIT ?`,\n )\n .all(ftsQuery, agentId, maxResults * 3) as Array<{\n chunk_id: string;\n path: string;\n start_line: number;\n end_line: number;\n content: string;\n rank: number;\n }>;\n\n const results: MemorySearchHit[] = [];\n for (const row of rows) {\n const score = bm25ToScore(row.rank);\n if (score < minScore) continue;\n results.push({\n path: row.path,\n lines: row.content,\n score,\n lineNumbers: [row.start_line],\n });\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, maxResults);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Note, NoteIndexEntry, NotesListQuery } from '../../notes/types.js';
|
|
2
|
+
export declare function upsertNoteRecord(note: Note): void;
|
|
3
|
+
export declare function getNoteRecord(noteId: string): Note | null;
|
|
4
|
+
export declare function deleteNoteRecord(noteId: string): boolean;
|
|
5
|
+
export declare function listNoteRecords(query?: NotesListQuery): {
|
|
6
|
+
items: NoteIndexEntry[];
|
|
7
|
+
total: number;
|
|
8
|
+
limit: number;
|
|
9
|
+
offset: number;
|
|
10
|
+
hasMore: boolean;
|
|
11
|
+
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
|
|
2
|
+
import { escapeFts5Query } from "./fts.js";
|
|
3
|
+
import { buildNoteIndexMeta, extractAttachmentFileNames, notePlainText } from "../../notes/note-index-meta.js";
|
|
4
|
+
//#region src/storage/sqlite/notes-repository.ts
|
|
5
|
+
function parseTags(json) {
|
|
6
|
+
try {
|
|
7
|
+
const parsed = JSON.parse(json);
|
|
8
|
+
return Array.isArray(parsed) ? parsed.filter((t) => typeof t === "string") : [];
|
|
9
|
+
} catch {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function parseAttachmentNames(json) {
|
|
14
|
+
if (!json) return void 0;
|
|
15
|
+
try {
|
|
16
|
+
const parsed = JSON.parse(json);
|
|
17
|
+
return Array.isArray(parsed) ? parsed.filter((n) => typeof n === "string") : void 0;
|
|
18
|
+
} catch {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function rowToIndexEntry(row) {
|
|
23
|
+
return {
|
|
24
|
+
id: row.note_id,
|
|
25
|
+
title: row.title ?? void 0,
|
|
26
|
+
kind: row.kind,
|
|
27
|
+
status: row.status,
|
|
28
|
+
createdAt: row.created_at,
|
|
29
|
+
updatedAt: row.updated_at,
|
|
30
|
+
pinned: row.pinned ? true : void 0,
|
|
31
|
+
tags: parseTags(row.tags_json),
|
|
32
|
+
snippet: row.snippet ?? void 0,
|
|
33
|
+
coverAttachmentId: row.cover_attachment_id ?? void 0,
|
|
34
|
+
voiceAttachmentId: row.voice_attachment_id ?? void 0,
|
|
35
|
+
voiceDurationSec: row.voice_duration_sec ?? void 0,
|
|
36
|
+
attachmentNames: parseAttachmentNames(row.attachment_names_json),
|
|
37
|
+
groupId: row.group_id ?? void 0,
|
|
38
|
+
lastOpenedAt: row.last_opened_at ?? void 0,
|
|
39
|
+
taskDone: row.task_done != null ? Boolean(row.task_done) : void 0,
|
|
40
|
+
taskDueAt: row.task_due_at ?? void 0
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function noteSearchContent(note) {
|
|
44
|
+
const plain = notePlainText(note);
|
|
45
|
+
const attachmentText = note.attachments?.map((a) => a.transcript).filter(Boolean).join(" ") ?? "";
|
|
46
|
+
const attachmentNames = extractAttachmentFileNames(note)?.join(" ") ?? "";
|
|
47
|
+
return [
|
|
48
|
+
note.title,
|
|
49
|
+
plain,
|
|
50
|
+
attachmentText,
|
|
51
|
+
attachmentNames,
|
|
52
|
+
...note.tags ?? []
|
|
53
|
+
].filter(Boolean).join("\n");
|
|
54
|
+
}
|
|
55
|
+
function noteToRow(note) {
|
|
56
|
+
const meta = buildNoteIndexMeta(note);
|
|
57
|
+
return {
|
|
58
|
+
note_id: note.id,
|
|
59
|
+
title: note.title ?? null,
|
|
60
|
+
kind: note.kind,
|
|
61
|
+
status: note.status,
|
|
62
|
+
payload_json: JSON.stringify(note),
|
|
63
|
+
created_at: note.createdAt,
|
|
64
|
+
updated_at: note.updatedAt,
|
|
65
|
+
pinned: note.pinned ? 1 : 0,
|
|
66
|
+
tags_json: JSON.stringify(note.tags ?? []),
|
|
67
|
+
snippet: meta.snippet ?? null,
|
|
68
|
+
cover_attachment_id: meta.coverAttachmentId ?? null,
|
|
69
|
+
voice_attachment_id: meta.voiceAttachmentId ?? null,
|
|
70
|
+
voice_duration_sec: meta.voiceDurationSec ?? null,
|
|
71
|
+
attachment_names_json: meta.attachmentNames ? JSON.stringify(meta.attachmentNames) : null,
|
|
72
|
+
group_id: note.groupId ?? null,
|
|
73
|
+
last_opened_at: note.lastOpenedAt ?? null,
|
|
74
|
+
task_done: note.taskMeta?.done != null ? note.taskMeta.done ? 1 : 0 : null,
|
|
75
|
+
task_due_at: note.taskMeta?.dueAt ?? null
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function upsertNoteFts(db, note) {
|
|
79
|
+
db.prepare(`DELETE FROM notes_fts WHERE note_id = ?`).run(note.id);
|
|
80
|
+
const content = noteSearchContent(note);
|
|
81
|
+
if (!content.trim()) return;
|
|
82
|
+
db.prepare(`INSERT INTO notes_fts (content, note_id) VALUES (?, ?)`).run(content, note.id);
|
|
83
|
+
}
|
|
84
|
+
function upsertNoteRecord(note) {
|
|
85
|
+
const row = noteToRow(note);
|
|
86
|
+
runSqliteWriteTransaction((db) => {
|
|
87
|
+
db.prepare(`INSERT INTO notes (
|
|
88
|
+
note_id, title, kind, status, payload_json, created_at, updated_at,
|
|
89
|
+
pinned, tags_json, snippet, cover_attachment_id, voice_attachment_id,
|
|
90
|
+
voice_duration_sec, attachment_names_json, group_id, last_opened_at,
|
|
91
|
+
task_done, task_due_at
|
|
92
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
93
|
+
ON CONFLICT(note_id) DO UPDATE SET
|
|
94
|
+
title = excluded.title,
|
|
95
|
+
kind = excluded.kind,
|
|
96
|
+
status = excluded.status,
|
|
97
|
+
payload_json = excluded.payload_json,
|
|
98
|
+
updated_at = excluded.updated_at,
|
|
99
|
+
pinned = excluded.pinned,
|
|
100
|
+
tags_json = excluded.tags_json,
|
|
101
|
+
snippet = excluded.snippet,
|
|
102
|
+
cover_attachment_id = excluded.cover_attachment_id,
|
|
103
|
+
voice_attachment_id = excluded.voice_attachment_id,
|
|
104
|
+
voice_duration_sec = excluded.voice_duration_sec,
|
|
105
|
+
attachment_names_json = excluded.attachment_names_json,
|
|
106
|
+
group_id = excluded.group_id,
|
|
107
|
+
last_opened_at = excluded.last_opened_at,
|
|
108
|
+
task_done = excluded.task_done,
|
|
109
|
+
task_due_at = excluded.task_due_at`).run(row.note_id, row.title, row.kind, row.status, row.payload_json, row.created_at, row.updated_at, row.pinned, row.tags_json, row.snippet, row.cover_attachment_id, row.voice_attachment_id, row.voice_duration_sec, row.attachment_names_json, row.group_id, row.last_opened_at, row.task_done, row.task_due_at);
|
|
110
|
+
upsertNoteFts(db, note);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function getNoteRecord(noteId) {
|
|
114
|
+
const row = getSqliteDatabase().prepare(`SELECT payload_json FROM notes WHERE note_id = ?`).get(noteId);
|
|
115
|
+
if (!row?.payload_json) return null;
|
|
116
|
+
try {
|
|
117
|
+
return JSON.parse(row.payload_json);
|
|
118
|
+
} catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function deleteNoteRecord(noteId) {
|
|
123
|
+
return runSqliteWriteTransaction((db) => {
|
|
124
|
+
if (!db.prepare(`SELECT note_id FROM notes WHERE note_id = ?`).get(noteId)) return false;
|
|
125
|
+
db.prepare(`DELETE FROM notes_fts WHERE note_id = ?`).run(noteId);
|
|
126
|
+
db.prepare(`DELETE FROM notes WHERE note_id = ?`).run(noteId);
|
|
127
|
+
return true;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function listNoteRecords(query = {}) {
|
|
131
|
+
const db = getSqliteDatabase();
|
|
132
|
+
const conditions = [];
|
|
133
|
+
const params = [];
|
|
134
|
+
if (query.status) {
|
|
135
|
+
conditions.push(`status = ?`);
|
|
136
|
+
params.push(query.status);
|
|
137
|
+
} else {
|
|
138
|
+
conditions.push(`status != ?`);
|
|
139
|
+
params.push("trashed");
|
|
140
|
+
}
|
|
141
|
+
if (query.kind) {
|
|
142
|
+
conditions.push(`kind = ?`);
|
|
143
|
+
params.push(query.kind);
|
|
144
|
+
}
|
|
145
|
+
if (query.pinned !== void 0) {
|
|
146
|
+
conditions.push(`pinned = ?`);
|
|
147
|
+
params.push(query.pinned ? 1 : 0);
|
|
148
|
+
}
|
|
149
|
+
if (query.groupId !== void 0) if (query.groupId === "ungrouped") conditions.push(`(group_id IS NULL OR group_id = '')`);
|
|
150
|
+
else {
|
|
151
|
+
conditions.push(`group_id = ?`);
|
|
152
|
+
params.push(query.groupId);
|
|
153
|
+
}
|
|
154
|
+
if (query.pendingTasksOnly) conditions.push(`kind = 'task' AND (task_done IS NULL OR task_done = 0)`);
|
|
155
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
156
|
+
let entries = db.prepare(`SELECT note_id, title, kind, status, payload_json, created_at, updated_at,
|
|
157
|
+
pinned, tags_json, snippet, cover_attachment_id, voice_attachment_id,
|
|
158
|
+
voice_duration_sec, attachment_names_json, group_id, last_opened_at,
|
|
159
|
+
task_done, task_due_at
|
|
160
|
+
FROM notes ${where}`).all(...params).map(rowToIndexEntry);
|
|
161
|
+
if (query.tag) entries = entries.filter((entry) => entry.tags?.includes(query.tag));
|
|
162
|
+
if (query.search) {
|
|
163
|
+
const ftsQuery = escapeFts5Query(query.search);
|
|
164
|
+
const ftsIds = /* @__PURE__ */ new Set();
|
|
165
|
+
if (ftsQuery) {
|
|
166
|
+
const ftsRows = db.prepare(`SELECT note_id FROM notes_fts WHERE notes_fts MATCH ? ORDER BY rank`).all(ftsQuery);
|
|
167
|
+
for (const row of ftsRows) ftsIds.add(row.note_id);
|
|
168
|
+
}
|
|
169
|
+
entries = entries.filter((entry) => ftsIds.has(entry.id));
|
|
170
|
+
}
|
|
171
|
+
const sortField = query.sortBy || "createdAt";
|
|
172
|
+
const sortDir = query.sortOrder === "asc" ? 1 : -1;
|
|
173
|
+
entries = [...entries].sort((a, b) => {
|
|
174
|
+
return ((a[sortField] ?? 0) - (b[sortField] ?? 0)) * sortDir;
|
|
175
|
+
});
|
|
176
|
+
const total = entries.length;
|
|
177
|
+
const offset = query.offset || 0;
|
|
178
|
+
const limit = Math.min(query.limit || 50, 200);
|
|
179
|
+
const items = entries.slice(offset, offset + limit);
|
|
180
|
+
return {
|
|
181
|
+
items,
|
|
182
|
+
total,
|
|
183
|
+
limit,
|
|
184
|
+
offset,
|
|
185
|
+
hasMore: offset + items.length < total
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
//#endregion
|
|
189
|
+
export { deleteNoteRecord, getNoteRecord, listNoteRecords, upsertNoteRecord };
|
|
190
|
+
|
|
191
|
+
//# sourceMappingURL=notes-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes-repository.js","names":[],"sources":["../../../../src/storage/sqlite/notes-repository.ts"],"sourcesContent":["import type { Note, NoteIndexEntry, NotesListQuery } from '../../notes/types.js';\nimport { buildNoteIndexMeta, extractAttachmentFileNames, notePlainText } from '../../notes/note-index-meta.js';\nimport { escapeFts5Query } from './fts.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\ntype NoteRow = {\n note_id: string;\n title: string | null;\n kind: string;\n status: string;\n payload_json: string;\n created_at: number;\n updated_at: number;\n pinned: number;\n tags_json: string;\n snippet: string | null;\n cover_attachment_id: string | null;\n voice_attachment_id: string | null;\n voice_duration_sec: number | null;\n attachment_names_json: string | null;\n group_id: string | null;\n last_opened_at: number | null;\n task_done: number | null;\n task_due_at: number | null;\n};\n\nfunction parseTags(json: string): string[] {\n try {\n const parsed = JSON.parse(json) as unknown;\n return Array.isArray(parsed) ? parsed.filter((t): t is string => typeof t === 'string') : [];\n } catch {\n return [];\n }\n}\n\nfunction parseAttachmentNames(json: string | null): string[] | undefined {\n if (!json) return undefined;\n try {\n const parsed = JSON.parse(json) as unknown;\n return Array.isArray(parsed) ? parsed.filter((n): n is string => typeof n === 'string') : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction rowToIndexEntry(row: NoteRow): NoteIndexEntry {\n return {\n id: row.note_id,\n title: row.title ?? undefined,\n kind: row.kind as NoteIndexEntry['kind'],\n status: row.status as NoteIndexEntry['status'],\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n pinned: row.pinned ? true : undefined,\n tags: parseTags(row.tags_json),\n snippet: row.snippet ?? undefined,\n coverAttachmentId: row.cover_attachment_id ?? undefined,\n voiceAttachmentId: row.voice_attachment_id ?? undefined,\n voiceDurationSec: row.voice_duration_sec ?? undefined,\n attachmentNames: parseAttachmentNames(row.attachment_names_json),\n groupId: row.group_id ?? undefined,\n lastOpenedAt: row.last_opened_at ?? undefined,\n taskDone: row.task_done != null ? Boolean(row.task_done) : undefined,\n taskDueAt: row.task_due_at ?? undefined,\n };\n}\n\nfunction noteSearchContent(note: Note): string {\n const plain = notePlainText(note);\n const attachmentText = note.attachments?.map((a) => a.transcript).filter(Boolean).join(' ') ?? '';\n const attachmentNames = extractAttachmentFileNames(note)?.join(' ') ?? '';\n return [note.title, plain, attachmentText, attachmentNames, ...(note.tags ?? [])].filter(Boolean).join('\\n');\n}\n\nfunction noteToRow(note: Note): Omit<NoteRow, 'payload_json'> & { payload_json: string } {\n const meta = buildNoteIndexMeta(note);\n return {\n note_id: note.id,\n title: note.title ?? null,\n kind: note.kind,\n status: note.status,\n payload_json: JSON.stringify(note),\n created_at: note.createdAt,\n updated_at: note.updatedAt,\n pinned: note.pinned ? 1 : 0,\n tags_json: JSON.stringify(note.tags ?? []),\n snippet: meta.snippet ?? null,\n cover_attachment_id: meta.coverAttachmentId ?? null,\n voice_attachment_id: meta.voiceAttachmentId ?? null,\n voice_duration_sec: meta.voiceDurationSec ?? null,\n attachment_names_json: meta.attachmentNames ? JSON.stringify(meta.attachmentNames) : null,\n group_id: note.groupId ?? null,\n last_opened_at: note.lastOpenedAt ?? null,\n task_done: note.taskMeta?.done != null ? (note.taskMeta.done ? 1 : 0) : null,\n task_due_at: note.taskMeta?.dueAt ?? null,\n };\n}\n\nfunction upsertNoteFts(db: ReturnType<typeof getSqliteDatabase>, note: Note): void {\n db.prepare(`DELETE FROM notes_fts WHERE note_id = ?`).run(note.id);\n const content = noteSearchContent(note);\n if (!content.trim()) {\n return;\n }\n db.prepare(`INSERT INTO notes_fts (content, note_id) VALUES (?, ?)`).run(content, note.id);\n}\n\nexport function upsertNoteRecord(note: Note): void {\n const row = noteToRow(note);\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO notes (\n note_id, title, kind, status, payload_json, created_at, updated_at,\n pinned, tags_json, snippet, cover_attachment_id, voice_attachment_id,\n voice_duration_sec, attachment_names_json, group_id, last_opened_at,\n task_done, task_due_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(note_id) DO UPDATE SET\n title = excluded.title,\n kind = excluded.kind,\n status = excluded.status,\n payload_json = excluded.payload_json,\n updated_at = excluded.updated_at,\n pinned = excluded.pinned,\n tags_json = excluded.tags_json,\n snippet = excluded.snippet,\n cover_attachment_id = excluded.cover_attachment_id,\n voice_attachment_id = excluded.voice_attachment_id,\n voice_duration_sec = excluded.voice_duration_sec,\n attachment_names_json = excluded.attachment_names_json,\n group_id = excluded.group_id,\n last_opened_at = excluded.last_opened_at,\n task_done = excluded.task_done,\n task_due_at = excluded.task_due_at`,\n ).run(\n row.note_id,\n row.title,\n row.kind,\n row.status,\n row.payload_json,\n row.created_at,\n row.updated_at,\n row.pinned,\n row.tags_json,\n row.snippet,\n row.cover_attachment_id,\n row.voice_attachment_id,\n row.voice_duration_sec,\n row.attachment_names_json,\n row.group_id,\n row.last_opened_at,\n row.task_done,\n row.task_due_at,\n );\n upsertNoteFts(db, note);\n });\n}\n\nexport function getNoteRecord(noteId: string): Note | null {\n const db = getSqliteDatabase();\n const row = db.prepare(`SELECT payload_json FROM notes WHERE note_id = ?`).get(noteId) as\n | { payload_json: string }\n | undefined;\n if (!row?.payload_json) {\n return null;\n }\n try {\n return JSON.parse(row.payload_json) as Note;\n } catch {\n return null;\n }\n}\n\nexport function deleteNoteRecord(noteId: string): boolean {\n return runSqliteWriteTransaction((db) => {\n const existing = db.prepare(`SELECT note_id FROM notes WHERE note_id = ?`).get(noteId);\n if (!existing) {\n return false;\n }\n db.prepare(`DELETE FROM notes_fts WHERE note_id = ?`).run(noteId);\n db.prepare(`DELETE FROM notes WHERE note_id = ?`).run(noteId);\n return true;\n });\n}\n\nexport function listNoteRecords(\n query: NotesListQuery = {},\n): { items: NoteIndexEntry[]; total: number; limit: number; offset: number; hasMore: boolean } {\n const db = getSqliteDatabase();\n const conditions: string[] = [];\n const params: Array<string | number> = [];\n\n if (query.status) {\n conditions.push(`status = ?`);\n params.push(query.status);\n } else {\n conditions.push(`status != ?`);\n params.push('trashed');\n }\n if (query.kind) {\n conditions.push(`kind = ?`);\n params.push(query.kind);\n }\n if (query.pinned !== undefined) {\n conditions.push(`pinned = ?`);\n params.push(query.pinned ? 1 : 0);\n }\n if (query.groupId !== undefined) {\n if (query.groupId === 'ungrouped') {\n conditions.push(`(group_id IS NULL OR group_id = '')`);\n } else {\n conditions.push(`group_id = ?`);\n params.push(query.groupId);\n }\n }\n if (query.pendingTasksOnly) {\n conditions.push(`kind = 'task' AND (task_done IS NULL OR task_done = 0)`);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const rows = db\n .prepare(\n `SELECT note_id, title, kind, status, payload_json, created_at, updated_at,\n pinned, tags_json, snippet, cover_attachment_id, voice_attachment_id,\n voice_duration_sec, attachment_names_json, group_id, last_opened_at,\n task_done, task_due_at\n FROM notes ${where}`,\n )\n .all(...params) as NoteRow[];\n\n let entries = rows.map(rowToIndexEntry);\n\n if (query.tag) {\n entries = entries.filter((entry) => entry.tags?.includes(query.tag!));\n }\n\n if (query.search) {\n const ftsQuery = escapeFts5Query(query.search);\n const ftsIds = new Set<string>();\n if (ftsQuery) {\n const ftsRows = db\n .prepare(\n `SELECT note_id FROM notes_fts WHERE notes_fts MATCH ? ORDER BY rank`,\n )\n .all(ftsQuery) as Array<{ note_id: string }>;\n for (const row of ftsRows) {\n ftsIds.add(row.note_id);\n }\n }\n entries = entries.filter((entry) => ftsIds.has(entry.id));\n }\n\n const sortField = query.sortBy || 'createdAt';\n const sortDir = query.sortOrder === 'asc' ? 1 : -1;\n entries = [...entries].sort((a, b) => {\n const aVal = (a[sortField] as number | undefined) ?? 0;\n const bVal = (b[sortField] as number | undefined) ?? 0;\n return (aVal - bVal) * sortDir;\n });\n\n const total = entries.length;\n const offset = query.offset || 0;\n const limit = Math.min(query.limit || 50, 200);\n const items = entries.slice(offset, offset + limit);\n const hasMore = offset + items.length < total;\n\n return { items, total, limit, offset, hasMore };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { resolveXopcDatabasePath, XOPC_DB_FILENAME } from '../../config/paths-state.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { XOPC_DB_FILENAME, init_paths_state, resolveXopcDatabasePath } from "../../config/paths-state.js";
|
|
2
|
+
//#region src/storage/sqlite/paths.ts
|
|
3
|
+
init_paths_state();
|
|
4
|
+
//#endregion
|
|
5
|
+
export { XOPC_DB_FILENAME, resolveXopcDatabasePath };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","names":[],"sources":["../../../../src/storage/sqlite/paths.ts"],"sourcesContent":["export { resolveXopcDatabasePath, XOPC_DB_FILENAME } from '../../config/paths-state.js';\n"],"mappings":";;kBAAwF"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { AgentMessage } from '@earendil-works/pi-agent-core';
|
|
2
|
+
import type { SessionAgentConfig } from '../../session/config-types.js';
|
|
3
|
+
import { type TranscriptStoredRow } from '../../session/session-context-for-llm.js';
|
|
4
|
+
import { type GlobalSessionStats, type SessionMetadata } from '../../session/types.js';
|
|
5
|
+
export type SessionRow = {
|
|
6
|
+
session_key: string;
|
|
7
|
+
agent_id: string;
|
|
8
|
+
current_transcript_id: string;
|
|
9
|
+
status: string;
|
|
10
|
+
name: string | null;
|
|
11
|
+
tags_json: string;
|
|
12
|
+
created_at: number;
|
|
13
|
+
updated_at: number;
|
|
14
|
+
last_accessed_at: number;
|
|
15
|
+
session_started_at: number | null;
|
|
16
|
+
last_interaction_at: number | null;
|
|
17
|
+
source_channel: string;
|
|
18
|
+
source_chat_id: string;
|
|
19
|
+
session_type: string | null;
|
|
20
|
+
routing_json: string | null;
|
|
21
|
+
custom_data_json: string | null;
|
|
22
|
+
abort_cutoff_timestamp: number | null;
|
|
23
|
+
message_count: number;
|
|
24
|
+
estimated_tokens: number;
|
|
25
|
+
compacted_count: number;
|
|
26
|
+
thinking_level: string | null;
|
|
27
|
+
verbose_level: string | null;
|
|
28
|
+
};
|
|
29
|
+
export type TranscriptEntryRow = {
|
|
30
|
+
entry_id: string;
|
|
31
|
+
transcript_id: string;
|
|
32
|
+
seq: number;
|
|
33
|
+
entry_kind: string;
|
|
34
|
+
role: string | null;
|
|
35
|
+
payload_json: string;
|
|
36
|
+
created_at: number;
|
|
37
|
+
};
|
|
38
|
+
export type SessionConfigRow = {
|
|
39
|
+
session_key: string;
|
|
40
|
+
thinking_level: string | null;
|
|
41
|
+
reasoning_level: string | null;
|
|
42
|
+
verbose_level: string | null;
|
|
43
|
+
elevated_mode: string | null;
|
|
44
|
+
model_override: string | null;
|
|
45
|
+
provider_override: string | null;
|
|
46
|
+
working_directory_override: string | null;
|
|
47
|
+
updated_at: number;
|
|
48
|
+
};
|
|
49
|
+
export declare function sessionRowToMetadata(sessionKey: string, row: SessionRow): SessionMetadata;
|
|
50
|
+
export declare function metadataToSessionInsert(sessionKey: string, transcriptId: string, metadata: SessionMetadata, thinkingLevel?: string | null, verboseLevel?: string | null): {
|
|
51
|
+
sessionKey: string;
|
|
52
|
+
agentId: string;
|
|
53
|
+
transcriptId: string;
|
|
54
|
+
status: string;
|
|
55
|
+
name: string | null;
|
|
56
|
+
tagsJson: string;
|
|
57
|
+
createdAt: number;
|
|
58
|
+
updatedAt: number;
|
|
59
|
+
lastAccessedAt: number;
|
|
60
|
+
sessionStartedAt: number | null;
|
|
61
|
+
lastInteractionAt: number | null;
|
|
62
|
+
sourceChannel: string;
|
|
63
|
+
sourceChatId: string;
|
|
64
|
+
sessionType: string | null;
|
|
65
|
+
routingJson: string | null;
|
|
66
|
+
customDataJson: string | null;
|
|
67
|
+
abortCutoffTimestamp: number | null;
|
|
68
|
+
messageCount: number;
|
|
69
|
+
estimatedTokens: number;
|
|
70
|
+
compactedCount: number;
|
|
71
|
+
thinkingLevel: string | null;
|
|
72
|
+
verboseLevel: string | null;
|
|
73
|
+
};
|
|
74
|
+
export declare function sessionConfigRowToConfig(row: SessionConfigRow): SessionAgentConfig;
|
|
75
|
+
export declare function transcriptEntryRowToStoredRow(row: TranscriptEntryRow): TranscriptStoredRow;
|
|
76
|
+
export declare function classifyStoredRow(row: TranscriptStoredRow): {
|
|
77
|
+
entryKind: 'message' | 'context' | 'compaction';
|
|
78
|
+
role: string | null;
|
|
79
|
+
};
|
|
80
|
+
export declare function extractFtsContent(row: TranscriptStoredRow): string;
|
|
81
|
+
export declare function estimateTokensFromMessages(messages: AgentMessage[]): number;
|
|
82
|
+
export declare function buildGlobalSessionStats(sessions: SessionMetadata[]): GlobalSessionStats;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import "../../session/types.js";
|
|
2
|
+
import { buildDefaultSessionMetadata, parseSessionKeySource, resolveAgentIdFromSessionKey } from "./session-metadata.js";
|
|
3
|
+
import { isTranscriptContextEntry } from "../../session/session-context-for-llm.js";
|
|
4
|
+
//#region src/storage/sqlite/row-mappers.ts
|
|
5
|
+
function parseJson(raw) {
|
|
6
|
+
if (!raw?.trim()) return;
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(raw);
|
|
9
|
+
} catch {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function isoFromMs(ms) {
|
|
14
|
+
if (ms == null || !Number.isFinite(ms)) return;
|
|
15
|
+
return new Date(ms).toISOString();
|
|
16
|
+
}
|
|
17
|
+
function sessionRowToMetadata(sessionKey, row) {
|
|
18
|
+
const defaults = buildDefaultSessionMetadata(sessionKey);
|
|
19
|
+
const { channel: keySource, chatId: keyChatId } = parseSessionKeySource(sessionKey);
|
|
20
|
+
const routing = parseJson(row.routing_json) ?? defaults.routing;
|
|
21
|
+
const customData = parseJson(row.custom_data_json) ?? defaults.customData;
|
|
22
|
+
const tags = parseJson(row.tags_json) ?? [];
|
|
23
|
+
const createdAt = isoFromMs(row.created_at) ?? defaults.createdAt;
|
|
24
|
+
const updatedAt = isoFromMs(row.updated_at) ?? defaults.updatedAt;
|
|
25
|
+
const lastAccessedAt = isoFromMs(row.last_accessed_at) ?? defaults.lastAccessedAt;
|
|
26
|
+
const diskSc = row.source_channel?.trim() ?? "";
|
|
27
|
+
const diskChat = row.source_chat_id?.trim() ?? "";
|
|
28
|
+
return {
|
|
29
|
+
...defaults,
|
|
30
|
+
key: sessionKey,
|
|
31
|
+
status: row.status,
|
|
32
|
+
name: row.name ?? void 0,
|
|
33
|
+
tags,
|
|
34
|
+
createdAt,
|
|
35
|
+
updatedAt,
|
|
36
|
+
lastAccessedAt,
|
|
37
|
+
sessionStartedAt: isoFromMs(row.session_started_at),
|
|
38
|
+
lastInteractionAt: isoFromMs(row.last_interaction_at),
|
|
39
|
+
sourceChannel: diskSc || keySource,
|
|
40
|
+
sourceChatId: diskChat || keyChatId,
|
|
41
|
+
sessionType: row.session_type ?? defaults.sessionType,
|
|
42
|
+
routing,
|
|
43
|
+
customData,
|
|
44
|
+
abortCutoffTimestamp: row.abort_cutoff_timestamp ?? void 0,
|
|
45
|
+
messageCount: row.message_count,
|
|
46
|
+
estimatedTokens: row.estimated_tokens,
|
|
47
|
+
compactedCount: row.compacted_count,
|
|
48
|
+
transcriptId: row.current_transcript_id,
|
|
49
|
+
stats: {
|
|
50
|
+
messageCount: row.message_count,
|
|
51
|
+
tokenCount: row.estimated_tokens,
|
|
52
|
+
lastTurnAt: row.last_interaction_at ?? void 0
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function metadataToSessionInsert(sessionKey, transcriptId, metadata, thinkingLevel, verboseLevel) {
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
return {
|
|
59
|
+
sessionKey,
|
|
60
|
+
agentId: resolveAgentIdFromSessionKey(sessionKey),
|
|
61
|
+
transcriptId,
|
|
62
|
+
status: metadata.status,
|
|
63
|
+
name: metadata.name ?? null,
|
|
64
|
+
tagsJson: JSON.stringify(metadata.tags ?? []),
|
|
65
|
+
createdAt: Date.parse(metadata.createdAt) || now,
|
|
66
|
+
updatedAt: Date.parse(metadata.updatedAt) || now,
|
|
67
|
+
lastAccessedAt: Date.parse(metadata.lastAccessedAt) || now,
|
|
68
|
+
sessionStartedAt: metadata.sessionStartedAt ? Date.parse(metadata.sessionStartedAt) : now,
|
|
69
|
+
lastInteractionAt: metadata.lastInteractionAt ? Date.parse(metadata.lastInteractionAt) : null,
|
|
70
|
+
sourceChannel: metadata.sourceChannel,
|
|
71
|
+
sourceChatId: metadata.sourceChatId,
|
|
72
|
+
sessionType: metadata.sessionType ?? null,
|
|
73
|
+
routingJson: metadata.routing ? JSON.stringify(metadata.routing) : null,
|
|
74
|
+
customDataJson: metadata.customData ? JSON.stringify(metadata.customData) : null,
|
|
75
|
+
abortCutoffTimestamp: metadata.abortCutoffTimestamp ?? null,
|
|
76
|
+
messageCount: metadata.messageCount,
|
|
77
|
+
estimatedTokens: metadata.estimatedTokens,
|
|
78
|
+
compactedCount: metadata.compactedCount,
|
|
79
|
+
thinkingLevel: thinkingLevel ?? null,
|
|
80
|
+
verboseLevel: verboseLevel ?? null
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function sessionConfigRowToConfig(row) {
|
|
84
|
+
return {
|
|
85
|
+
...row.thinking_level ? { thinkingLevel: row.thinking_level } : {},
|
|
86
|
+
...row.reasoning_level ? { reasoningLevel: row.reasoning_level } : {},
|
|
87
|
+
...row.verbose_level ? { verboseLevel: row.verbose_level } : {},
|
|
88
|
+
...row.elevated_mode ? { elevatedMode: row.elevated_mode } : {},
|
|
89
|
+
...row.model_override ? { modelOverride: row.model_override } : {},
|
|
90
|
+
...row.provider_override ? { providerOverride: row.provider_override } : {},
|
|
91
|
+
...row.working_directory_override ? { workingDirectoryOverride: row.working_directory_override } : {},
|
|
92
|
+
updatedAt: row.updated_at
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function transcriptEntryRowToStoredRow(row) {
|
|
96
|
+
return JSON.parse(row.payload_json);
|
|
97
|
+
}
|
|
98
|
+
function classifyStoredRow(row) {
|
|
99
|
+
if (isTranscriptContextEntry(row)) return {
|
|
100
|
+
entryKind: "context",
|
|
101
|
+
role: null
|
|
102
|
+
};
|
|
103
|
+
const record = row;
|
|
104
|
+
if (record.type === "compaction" || row.kind === "compaction") return {
|
|
105
|
+
entryKind: "compaction",
|
|
106
|
+
role: null
|
|
107
|
+
};
|
|
108
|
+
return {
|
|
109
|
+
entryKind: "message",
|
|
110
|
+
role: record.role ?? null
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function extractFtsContent(row) {
|
|
114
|
+
if (isTranscriptContextEntry(row)) {
|
|
115
|
+
const ctx = row;
|
|
116
|
+
return [ctx.text, ctx.id].filter(Boolean).join(" ");
|
|
117
|
+
}
|
|
118
|
+
return extractTextFromMessageContent(row.content);
|
|
119
|
+
}
|
|
120
|
+
function extractTextFromMessageContent(content) {
|
|
121
|
+
if (typeof content === "string") return content;
|
|
122
|
+
if (!Array.isArray(content)) return "";
|
|
123
|
+
const parts = [];
|
|
124
|
+
for (const block of content) {
|
|
125
|
+
if (!block || typeof block !== "object") continue;
|
|
126
|
+
if (block.type === "text" && typeof block.text === "string") parts.push(block.text);
|
|
127
|
+
}
|
|
128
|
+
return parts.join("\n");
|
|
129
|
+
}
|
|
130
|
+
function estimateTokensFromMessages(messages) {
|
|
131
|
+
let total = 0;
|
|
132
|
+
for (const msg of messages) {
|
|
133
|
+
const content = msg.content;
|
|
134
|
+
const text = extractTextFromMessageContent(content);
|
|
135
|
+
total += Math.ceil(text.length / 4);
|
|
136
|
+
}
|
|
137
|
+
return total;
|
|
138
|
+
}
|
|
139
|
+
function buildGlobalSessionStats(sessions) {
|
|
140
|
+
const byChannel = {};
|
|
141
|
+
for (const session of sessions) byChannel[session.sourceChannel] = (byChannel[session.sourceChannel] || 0) + 1;
|
|
142
|
+
let oldestSession;
|
|
143
|
+
let newestSession;
|
|
144
|
+
if (sessions.length > 0) {
|
|
145
|
+
const sorted = [...sessions].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
146
|
+
oldestSession = sorted[0].createdAt;
|
|
147
|
+
newestSession = sorted[sorted.length - 1].createdAt;
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
totalSessions: sessions.length,
|
|
151
|
+
activeSessions: sessions.filter((s) => s.status === "active" || s.status === "idle").length,
|
|
152
|
+
archivedSessions: sessions.filter((s) => s.status === "archived").length,
|
|
153
|
+
pinnedSessions: sessions.filter((s) => s.status === "pinned").length,
|
|
154
|
+
totalMessages: sessions.reduce((sum, s) => sum + s.messageCount, 0),
|
|
155
|
+
totalTokens: sessions.reduce((sum, s) => sum + s.estimatedTokens, 0),
|
|
156
|
+
oldestSession,
|
|
157
|
+
newestSession,
|
|
158
|
+
byChannel
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
export { buildGlobalSessionStats, classifyStoredRow, estimateTokensFromMessages, extractFtsContent, metadataToSessionInsert, sessionConfigRowToConfig, sessionRowToMetadata, transcriptEntryRowToStoredRow };
|
|
163
|
+
|
|
164
|
+
//# sourceMappingURL=row-mappers.js.map
|