@xopcai/xopc 0.0.90 → 0.0.92
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/README.md +36 -12
- package/README.zh-CN.md +36 -12
- 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/Combination-HAlzriaz.js +41 -0
- package/dist/gateway/static/root/assets/agents-uwPn7ZW9.js +222 -0
- package/dist/gateway/static/root/assets/apps-page-CWKdhSPU.js +1 -0
- package/dist/gateway/static/root/assets/{attachment-preview-renderer-CpyoFbs4.js → attachment-preview-renderer-DBAxQXb-.js} +2 -2
- package/dist/gateway/static/root/assets/{attachment-process-heavy-CqVriadb.js → attachment-process-heavy-Csq3TrrP.js} +4 -4
- package/dist/gateway/static/root/assets/channels-settings-hEhW7Mbk.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-BrtH2VzC.js → channels-status-swr-XzddfJW2.js} +1 -1
- package/dist/gateway/static/root/assets/copy-Dv6d4Dvw.js +1 -0
- package/dist/gateway/static/root/assets/{cron-api-CyqbgfHM.js → cron-api--I8LJ44S.js} +1 -1
- package/dist/gateway/static/root/assets/cron-page-B0kvgZGR.js +1 -0
- package/dist/gateway/static/root/assets/dist-CYgHMQO0.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-D6Ak0STa.js → extension-debug-page-6cRP0nA9.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-Q0P3d6DW.js → extension-page-DpwIkspI.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-CL55LwU_.js → extension-settings-page-DYbnQUxH.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-Dqa9iTWl.js → fetch-DTN0w7rV.js} +1 -1
- package/dist/gateway/static/root/assets/{field-primitives-HUR6JElP.js → field-primitives-CslW6HwD.js} +1 -1
- package/dist/gateway/static/root/assets/heartbeat-config-api-2UiKevxG.js +1 -0
- package/dist/gateway/static/root/assets/index-BUKUv7QW.css +1 -0
- package/dist/gateway/static/root/assets/{index-BYcGfwcE.js → index-DnevRVa6.js} +63 -59
- package/dist/gateway/static/root/assets/logs-page-sOP4TXJ4.js +1 -0
- package/dist/gateway/static/root/assets/note-detail-page-B91pLkEI.css +1 -0
- package/dist/gateway/static/root/assets/note-detail-page-DvW2qg4i.js +179 -0
- package/dist/gateway/static/root/assets/note-time-BEiibLJv.js +1 -0
- package/dist/gateway/static/root/assets/notes-page-BFQaquHU.js +1 -0
- package/dist/gateway/static/root/assets/{pdf-BnEvgIXZ.js → pdf-epILhEOn.js} +1 -1
- package/dist/gateway/static/root/assets/preload-helper-zJ_50EbN.js +1 -0
- package/dist/gateway/static/root/assets/sessions-page-CptjDKAX.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BctKqHcf.js +2 -0
- package/dist/gateway/static/root/assets/{settings-form-section-a0qGVOlr.js → settings-form-section-QJh5ruel.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-V3p-hISB.js +2 -0
- package/dist/gateway/static/root/assets/share-preview-page-DBsvvbmD.js +2 -0
- package/dist/gateway/static/root/assets/skills-page-q2zPUJAR.js +2 -0
- package/dist/gateway/static/root/assets/{theme-store-C0Ehmdo5.js → theme-store-ht5iswWS.js} +1 -1
- package/dist/gateway/static/root/assets/toast-z0toXu32.js +1 -0
- package/dist/gateway/static/root/assets/url-CWWpfkq1.js +3 -0
- package/dist/gateway/static/root/assets/{utils-DRQryzdn.js → utils-DhPv9xoB.js} +1 -1
- package/dist/gateway/static/root/assets/vendor-codemirror-DYoKfS8f.js +45 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-DLSKUipa.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-page.utils-DnG8JBhV.js → workflow-page.utils-CJqnPWkW.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-DRRQ1A0l.js +27 -0
- package/dist/gateway/static/root/index.html +10 -8
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +7 -7
- package/dist/src/agent/agent-scope.js +1 -1
- package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
- package/dist/src/agent/context/workspace-seed.js +2 -2
- package/dist/src/agent/goals/goal-run-store.js +4 -4
- package/dist/src/agent/goals/persistent-goal-service.js +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-config.d.ts +2 -9
- package/dist/src/agent/mcp/bundle-mcp-config.js +10 -34
- package/dist/src/agent/mcp/bundle-mcp-config.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-policy.js +2 -2
- package/dist/src/agent/mcp/bundle-mcp-policy.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +5 -5
- package/dist/src/agent/mcp/bundle-mcp-runtime.js.map +1 -1
- package/dist/src/agent/mcp/index.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/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.js +4 -4
- 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 +2 -2
- 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/send-media.js +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 +3 -3
- 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/command-catalog.js +0 -4
- package/dist/src/cli/command-catalog.js.map +1 -1
- package/dist/src/cli/command-loaders.js +1 -2
- package/dist/src/cli/command-loaders.js.map +1 -1
- package/dist/src/cli/command-manifest.js +0 -4
- package/dist/src/cli/command-manifest.js.map +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 +2 -2
- 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 +4 -4
- 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.d.ts +0 -1
- package/dist/src/config/index.js +6 -7
- 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.js +1 -1
- package/dist/src/config/profile.js +2 -2
- package/dist/src/config/schema.d.ts +36 -6
- package/dist/src/config/schema.js +13 -11
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/workspace-path.js +1 -1
- package/dist/src/connectors/builtin-catalog.d.ts +2 -0
- package/dist/src/connectors/builtin-catalog.js +152 -0
- package/dist/src/connectors/builtin-catalog.js.map +1 -0
- package/dist/src/connectors/catalog.d.ts +5 -0
- package/dist/src/connectors/catalog.js +13 -0
- package/dist/src/connectors/catalog.js.map +1 -0
- package/dist/src/connectors/health.d.ts +3 -0
- package/dist/src/connectors/health.js +61 -0
- package/dist/src/connectors/health.js.map +1 -0
- package/dist/src/connectors/install.d.ts +5 -0
- package/dist/src/connectors/install.js +46 -0
- package/dist/src/connectors/install.js.map +1 -0
- package/dist/src/connectors/instances.d.ts +4 -0
- package/dist/src/connectors/instances.js +43 -0
- package/dist/src/connectors/instances.js.map +1 -0
- package/dist/src/connectors/materialize.d.ts +9 -0
- package/dist/src/connectors/materialize.js +76 -0
- package/dist/src/connectors/materialize.js.map +1 -0
- package/dist/src/connectors/oauth.d.ts +22 -0
- package/dist/src/connectors/oauth.js +99 -0
- package/dist/src/connectors/oauth.js.map +1 -0
- package/dist/src/connectors/providers.d.ts +9 -0
- package/dist/src/connectors/providers.js +20 -0
- package/dist/src/connectors/providers.js.map +1 -0
- package/dist/src/connectors/secret-store.d.ts +7 -0
- package/dist/src/connectors/secret-store.js +47 -0
- package/dist/src/connectors/secret-store.js.map +1 -0
- package/dist/src/connectors/types.d.ts +102 -0
- package/dist/src/connectors/types.js +1 -0
- package/dist/src/connectors/usage.d.ts +6 -0
- package/dist/src/connectors/usage.js +63 -0
- package/dist/src/connectors/usage.js.map +1 -0
- package/dist/src/cron/executor.js +2 -2
- package/dist/src/cron/persistence.js +1 -1
- package/dist/src/cron/run-log-store.js +1 -1
- 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 +3 -3
- package/dist/src/gateway/file-path-classifier.js +2 -2
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -0
- package/dist/src/gateway/hono/lib/config-payload.js +2 -1
- package/dist/src/gateway/hono/lib/config-payload.js.map +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/middleware/auth.js +1 -2
- package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
- 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/gateway.d.ts +2 -2
- package/dist/src/gateway/hono/routes/config-patch/gateway.js +12 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
- package/dist/src/gateway/hono/routes/connectors.d.ts +3 -0
- package/dist/src/gateway/hono/routes/connectors.js +177 -0
- package/dist/src/gateway/hono/routes/connectors.js.map +1 -0
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/home.d.ts +12 -0
- package/dist/src/gateway/hono/routes/home.js +50 -0
- package/dist/src/gateway/hono/routes/home.js.map +1 -0
- package/dist/src/gateway/hono/routes/host-fs.js +2 -2
- package/dist/src/gateway/hono/routes/lazy-bundles.js +20 -4
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/notes.d.ts +3 -0
- package/dist/src/gateway/hono/routes/notes.js +305 -0
- package/dist/src/gateway/hono/routes/notes.js.map +1 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/shares.js +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +4 -4
- 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.d.ts +3 -0
- package/dist/src/gateway/service.js +11 -1
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/gateway/workspace-ripgrep.d.ts +6 -0
- package/dist/src/gateway/workspace-ripgrep.js +62 -11
- package/dist/src/gateway/workspace-ripgrep.js.map +1 -1
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/brew.js +1 -1
- 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/stable-node-path.js +1 -1
- 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/write-file-atomic.js +2 -2
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/mcp/channel-bridge.js.map +1 -1
- package/dist/src/notes/attachment-ref.d.ts +9 -0
- package/dist/src/notes/attachment-ref.js +27 -0
- package/dist/src/notes/attachment-ref.js.map +1 -0
- package/dist/src/notes/index.d.ts +4 -0
- package/dist/src/notes/index.js +4 -0
- package/dist/src/notes/note-attachment-sync.d.ts +7 -0
- package/dist/src/notes/note-attachment-sync.js +46 -0
- package/dist/src/notes/note-attachment-sync.js.map +1 -0
- package/dist/src/notes/note-index-meta.d.ts +14 -0
- package/dist/src/notes/note-index-meta.js +87 -0
- package/dist/src/notes/note-index-meta.js.map +1 -0
- package/dist/src/notes/paths.d.ts +5 -0
- package/dist/src/notes/paths.js +23 -0
- package/dist/src/notes/paths.js.map +1 -0
- package/dist/src/notes/service.d.ts +53 -0
- package/dist/src/notes/service.js +373 -0
- package/dist/src/notes/service.js.map +1 -0
- package/dist/src/notes/store.d.ts +34 -0
- package/dist/src/notes/store.js +342 -0
- package/dist/src/notes/store.js.map +1 -0
- package/dist/src/notes/types.d.ts +199 -0
- package/dist/src/notes/types.js +1 -0
- 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.js +2 -2
- package/dist/src/session/init-session-turn.js +2 -2
- package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
- package/dist/src/session/parity/sessions-json-file.js +1 -1
- package/dist/src/session/parity/transcript-file-lock.js +2 -2
- package/dist/src/session/parity/transcript-paths.js +1 -1
- package/dist/src/session/resolve-session.js +4 -4
- package/dist/src/session/search-index-cache.js +1 -1
- package/dist/src/session/search-index.js +1 -1
- package/dist/src/session/session-title.js +2 -2
- package/dist/src/session/store.d.ts +2 -0
- package/dist/src/session/store.js +27 -7
- package/dist/src/session/store.js.map +1 -1
- 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/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/store/event-store.js +1 -1
- package/dist/src/workflows/store/run-store.js +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agents-cPvvYLXo.js +0 -222
- package/dist/gateway/static/root/assets/apps-page-Bk1_P5FJ.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-CZoeQwHz.js +0 -1
- package/dist/gateway/static/root/assets/cron-dreaming-jobs-Ip703-qM.js +0 -2
- package/dist/gateway/static/root/assets/cron-page-BpLdiQN8.js +0 -1
- package/dist/gateway/static/root/assets/dist-BTWC-BTN.js +0 -45
- package/dist/gateway/static/root/assets/dist-BpAiK86n.js +0 -1
- package/dist/gateway/static/root/assets/eye-DAfL1U7M.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-config-api-DusckjUX.js +0 -1
- package/dist/gateway/static/root/assets/index-V7MQ7834.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-_HcZ2fgK.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-iezSMjho.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-C9_nYQwM.js +0 -3
- package/dist/gateway/static/root/assets/share-preview-page-DExl7CJy.js +0 -2
- package/dist/gateway/static/root/assets/skills-page-BlgGD93t.js +0 -2
- package/dist/gateway/static/root/assets/url-fxyYANfA.js +0 -3
- package/dist/gateway/static/root/assets/vendor-codemirror-D0yxdRpg.js +0 -58
- package/dist/gateway/static/root/assets/voice-api-key-field-D0viACE2.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-BvMobnJP.js +0 -27
- package/dist/src/cli/commands/mcp.d.ts +0 -4
- package/dist/src/cli/commands/mcp.js +0 -85
- package/dist/src/cli/commands/mcp.js.map +0 -1
- package/dist/src/config/mcp-config.d.ts +0 -34
- package/dist/src/config/mcp-config.js +0 -116
- package/dist/src/config/mcp-config.js.map +0 -1
- package/dist/src/gateway/hono/routes/mcp.d.ts +0 -3
- package/dist/src/gateway/hono/routes/mcp.js +0 -99
- package/dist/src/gateway/hono/routes/mcp.js.map +0 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function resolveNotesDir(): string;
|
|
2
|
+
export declare function resolveNotesIndexPath(): string;
|
|
3
|
+
export declare function resolveNoteItemPath(noteId: string): string;
|
|
4
|
+
export declare function resolveNoteMediaDir(noteId: string): string;
|
|
5
|
+
export declare function resolveNoteHistoryDir(noteId: string): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { init_paths_state, resolveStateDir } from "../config/paths-state.js";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
//#region src/notes/paths.ts
|
|
4
|
+
init_paths_state();
|
|
5
|
+
function resolveNotesDir() {
|
|
6
|
+
return join(resolveStateDir(), "notes");
|
|
7
|
+
}
|
|
8
|
+
function resolveNotesIndexPath() {
|
|
9
|
+
return join(resolveNotesDir(), "index.json");
|
|
10
|
+
}
|
|
11
|
+
function resolveNoteItemPath(noteId) {
|
|
12
|
+
return join(resolveNotesDir(), "items", `${noteId}.json`);
|
|
13
|
+
}
|
|
14
|
+
function resolveNoteMediaDir(noteId) {
|
|
15
|
+
return join(resolveNotesDir(), "media", noteId);
|
|
16
|
+
}
|
|
17
|
+
function resolveNoteHistoryDir(noteId) {
|
|
18
|
+
return join(resolveNotesDir(), "history", noteId);
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { resolveNoteHistoryDir, resolveNoteItemPath, resolveNoteMediaDir, resolveNotesDir, resolveNotesIndexPath };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","names":[],"sources":["../../../src/notes/paths.ts"],"sourcesContent":["import { join } from 'node:path';\n\nimport { resolveStateDir } from '../config/paths-state.js';\n\nexport function resolveNotesDir(): string {\n return join(resolveStateDir(), 'notes');\n}\n\nexport function resolveNotesIndexPath(): string {\n return join(resolveNotesDir(), 'index.json');\n}\n\nexport function resolveNoteItemPath(noteId: string): string {\n return join(resolveNotesDir(), 'items', `${noteId}.json`);\n}\n\nexport function resolveNoteMediaDir(noteId: string): string {\n return join(resolveNotesDir(), 'media', noteId);\n}\n\nexport function resolveNoteHistoryDir(noteId: string): string {\n return join(resolveNotesDir(), 'history', noteId);\n}\n"],"mappings":";;;kBAE2D;AAE3D,SAAgB,kBAA0B;AACxC,QAAO,KAAK,iBAAiB,EAAE,QAAQ;;AAGzC,SAAgB,wBAAgC;AAC9C,QAAO,KAAK,iBAAiB,EAAE,aAAa;;AAG9C,SAAgB,oBAAoB,QAAwB;AAC1D,QAAO,KAAK,iBAAiB,EAAE,SAAS,GAAG,OAAO,OAAO;;AAG3D,SAAgB,oBAAoB,QAAwB;AAC1D,QAAO,KAAK,iBAAiB,EAAE,SAAS,OAAO;;AAGjD,SAAgB,sBAAsB,QAAwB;AAC5D,QAAO,KAAK,iBAAiB,EAAE,WAAW,OAAO"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { NotesStore } from './store.js';
|
|
2
|
+
import type { CaptureSource, CreateNoteParams, Note, NoteAiPatch, NoteAttachment, NoteBlock, NoteIndexEntry, NoteSnapshot, NoteSnapshotEntry, NotesListQuery, SnapshotTrigger } from './types.js';
|
|
3
|
+
export declare class NotesService {
|
|
4
|
+
private store;
|
|
5
|
+
private lastSnapshotAt;
|
|
6
|
+
constructor(store: NotesStore);
|
|
7
|
+
initialize(): Promise<void>;
|
|
8
|
+
quickCapture(text: string, source: CaptureSource): Promise<Note>;
|
|
9
|
+
createNote(params: CreateNoteParams): Promise<Note>;
|
|
10
|
+
getNote(id: string): Promise<Note | null>;
|
|
11
|
+
updateNote(id: string, patch: Partial<Note>, trigger?: SnapshotTrigger): Promise<Note | null>;
|
|
12
|
+
private reconcileAttachments;
|
|
13
|
+
syncNote(id: string, patch: Partial<Note>, baseRemoteVersion?: number): Promise<{
|
|
14
|
+
note: Note | null;
|
|
15
|
+
conflict: boolean;
|
|
16
|
+
}>;
|
|
17
|
+
createAiEditPatch(id: string, instruction: string, blocks?: NoteBlock[]): Promise<{
|
|
18
|
+
message: string;
|
|
19
|
+
patch: NoteAiPatch;
|
|
20
|
+
} | null>;
|
|
21
|
+
deleteNote(id: string): Promise<boolean>;
|
|
22
|
+
listNotes(query?: NotesListQuery): Promise<{
|
|
23
|
+
items: NoteIndexEntry[];
|
|
24
|
+
total: number;
|
|
25
|
+
}>;
|
|
26
|
+
addAttachment(noteId: string, file: {
|
|
27
|
+
name: string;
|
|
28
|
+
buffer: Buffer;
|
|
29
|
+
mimeType: string;
|
|
30
|
+
duration?: number;
|
|
31
|
+
}): Promise<NoteAttachment | null>;
|
|
32
|
+
getAttachmentPath(noteId: string, attachmentId: string): Promise<{
|
|
33
|
+
filePath: string;
|
|
34
|
+
mimeType: string;
|
|
35
|
+
fileName: string;
|
|
36
|
+
} | null>;
|
|
37
|
+
listNoteHistory(noteId: string): Promise<NoteSnapshotEntry[]>;
|
|
38
|
+
getNoteSnapshot(noteId: string, timestamp: number): Promise<NoteSnapshot | null>;
|
|
39
|
+
restoreNoteSnapshot(noteId: string, timestamp: number): Promise<Note | null>;
|
|
40
|
+
flush(): Promise<void>;
|
|
41
|
+
moveToGroup(noteId: string, groupId: string | null): Promise<Note | null>;
|
|
42
|
+
createTask(title: string, source: CaptureSource, options?: {
|
|
43
|
+
dueAt?: number;
|
|
44
|
+
priority?: 'high' | 'medium' | 'low';
|
|
45
|
+
sourceSessionKey?: string;
|
|
46
|
+
sourceNoteId?: string;
|
|
47
|
+
groupId?: string;
|
|
48
|
+
}): Promise<Note>;
|
|
49
|
+
toggleTaskDone(noteId: string): Promise<Note | null>;
|
|
50
|
+
updateTaskMeta(noteId: string, patch: Partial<import('./types.js').NoteTaskMeta>): Promise<Note | null>;
|
|
51
|
+
recordOpen(noteId: string): Promise<Note | null>;
|
|
52
|
+
private maybeSaveSnapshot;
|
|
53
|
+
}
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
import { attachmentIdFromTarget, buildNoteAttachmentRef } from "./attachment-ref.js";
|
|
4
|
+
import { partitionAttachmentsByReference } from "./note-attachment-sync.js";
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
//#region src/notes/service.ts
|
|
7
|
+
init_logger();
|
|
8
|
+
const log = createLogger("NotesService");
|
|
9
|
+
function inferKind(text, hasAttachments, attachments) {
|
|
10
|
+
if (hasAttachments && attachments?.length && attachments.every((item) => item.type === "audio")) return "voice";
|
|
11
|
+
if (hasAttachments) return "media";
|
|
12
|
+
if (!text) return "thought";
|
|
13
|
+
const lower = text.toLowerCase();
|
|
14
|
+
if (/^(todo|task|remind|buy|call|email|meet|finish|submit|send)\b/i.test(lower) || /\b(明天|今天|记得|别忘|待办|提醒)\b/.test(text)) return "todo";
|
|
15
|
+
if (/^https?:\/\//.test(text.trim())) return "bookmark";
|
|
16
|
+
return "thought";
|
|
17
|
+
}
|
|
18
|
+
function createBlockId() {
|
|
19
|
+
return `block_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
20
|
+
}
|
|
21
|
+
const IMAGE_MARKDOWN = /^!\[([^\]]*)\]\(([^)]+)\)$/;
|
|
22
|
+
function noteTextToBlocks(text, noteId) {
|
|
23
|
+
if (!text?.trim()) return void 0;
|
|
24
|
+
const now = Date.now();
|
|
25
|
+
return text.split(/\n{2,}/).map((part) => {
|
|
26
|
+
const trimmed = part.trim();
|
|
27
|
+
if (noteId) {
|
|
28
|
+
const imageMatch = trimmed.match(IMAGE_MARKDOWN);
|
|
29
|
+
if (imageMatch) {
|
|
30
|
+
const attachmentId = attachmentIdFromTarget(imageMatch[2], noteId);
|
|
31
|
+
if (attachmentId) return {
|
|
32
|
+
id: createBlockId(),
|
|
33
|
+
type: "image",
|
|
34
|
+
attachmentId,
|
|
35
|
+
alt: imageMatch[1] || void 0,
|
|
36
|
+
createdAt: now,
|
|
37
|
+
updatedAt: now
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
id: createBlockId(),
|
|
43
|
+
type: "paragraph",
|
|
44
|
+
text: trimmed,
|
|
45
|
+
createdAt: now,
|
|
46
|
+
updatedAt: now
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function blocksToPlainText(blocks, noteId) {
|
|
51
|
+
if (!blocks?.length) return void 0;
|
|
52
|
+
return blocks.map((block) => {
|
|
53
|
+
if (block.type === "divider") return "---";
|
|
54
|
+
if (block.type === "todo") return `${block.checked ? "[x]" : "[ ]"} ${block.text}`;
|
|
55
|
+
if (block.type === "image") {
|
|
56
|
+
if (noteId) return `})`;
|
|
57
|
+
return block.alt ?? "";
|
|
58
|
+
}
|
|
59
|
+
return block.text;
|
|
60
|
+
}).filter((text) => text.trim().length > 0).join("\n\n");
|
|
61
|
+
}
|
|
62
|
+
function createAiOrganizedBlocks(blocks, instruction) {
|
|
63
|
+
const now = Date.now();
|
|
64
|
+
const lines = (blocksToPlainText(blocks) || "").split(/\n+/).map((line) => line.trim()).filter(Boolean);
|
|
65
|
+
const wantsTodos = /待办|todo|task|行动|提醒/i.test(instruction);
|
|
66
|
+
const wantsSummary = /摘要|总结|summary|压缩/i.test(instruction);
|
|
67
|
+
if (wantsTodos) {
|
|
68
|
+
const candidates = lines.filter((line) => /要|需|记得|todo|task|完成|提交|联系|跟进|提醒/i.test(line));
|
|
69
|
+
return (candidates.length ? candidates : lines).slice(0, 12).map((line) => ({
|
|
70
|
+
id: createBlockId(),
|
|
71
|
+
type: "todo",
|
|
72
|
+
text: line.replace(/^[-*\d.\s\[\]x]+/i, "").trim(),
|
|
73
|
+
checked: false,
|
|
74
|
+
createdAt: now,
|
|
75
|
+
updatedAt: now
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
if (wantsSummary) {
|
|
79
|
+
const summary = lines.join(" ").slice(0, 220);
|
|
80
|
+
return [{
|
|
81
|
+
id: createBlockId(),
|
|
82
|
+
type: "paragraph",
|
|
83
|
+
text: summary,
|
|
84
|
+
createdAt: now,
|
|
85
|
+
updatedAt: now
|
|
86
|
+
}];
|
|
87
|
+
}
|
|
88
|
+
const titleText = lines[0]?.slice(0, 40) || "整理后的笔记";
|
|
89
|
+
const bodyLines = lines.slice(1).length ? lines.slice(1) : lines;
|
|
90
|
+
return [{
|
|
91
|
+
id: createBlockId(),
|
|
92
|
+
type: "heading",
|
|
93
|
+
text: titleText,
|
|
94
|
+
level: 2,
|
|
95
|
+
createdAt: now,
|
|
96
|
+
updatedAt: now
|
|
97
|
+
}, ...bodyLines.map((line) => ({
|
|
98
|
+
id: createBlockId(),
|
|
99
|
+
type: "bulletList",
|
|
100
|
+
text: line.replace(/^[-*\d.\s]+/, "").trim(),
|
|
101
|
+
indent: 0,
|
|
102
|
+
createdAt: now,
|
|
103
|
+
updatedAt: now
|
|
104
|
+
}))];
|
|
105
|
+
}
|
|
106
|
+
const SNAPSHOT_THROTTLE_MS = 6e4;
|
|
107
|
+
const MAX_SNAPSHOTS_PER_NOTE = 30;
|
|
108
|
+
var NotesService = class {
|
|
109
|
+
store;
|
|
110
|
+
lastSnapshotAt = /* @__PURE__ */ new Map();
|
|
111
|
+
constructor(store) {
|
|
112
|
+
this.store = store;
|
|
113
|
+
}
|
|
114
|
+
async initialize() {
|
|
115
|
+
await this.store.initialize();
|
|
116
|
+
log.debug("NotesService initialized");
|
|
117
|
+
}
|
|
118
|
+
async quickCapture(text, source) {
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
const id = randomUUID();
|
|
121
|
+
const blocks = noteTextToBlocks(text, id);
|
|
122
|
+
const note = {
|
|
123
|
+
id,
|
|
124
|
+
kind: inferKind(text),
|
|
125
|
+
status: "inbox",
|
|
126
|
+
text,
|
|
127
|
+
blocks,
|
|
128
|
+
createdAt: now,
|
|
129
|
+
updatedAt: now,
|
|
130
|
+
capturedVia: source,
|
|
131
|
+
localVersion: 0,
|
|
132
|
+
remoteVersion: 1
|
|
133
|
+
};
|
|
134
|
+
await this.store.addNote(note);
|
|
135
|
+
log.debug({
|
|
136
|
+
id: note.id,
|
|
137
|
+
kind: note.kind
|
|
138
|
+
}, "Quick capture");
|
|
139
|
+
return note;
|
|
140
|
+
}
|
|
141
|
+
async createNote(params) {
|
|
142
|
+
const now = Date.now();
|
|
143
|
+
const id = randomUUID();
|
|
144
|
+
const blocks = params.blocks ?? noteTextToBlocks(params.text, id);
|
|
145
|
+
const text = params.text ?? blocksToPlainText(blocks, id);
|
|
146
|
+
const note = {
|
|
147
|
+
id,
|
|
148
|
+
title: params.title,
|
|
149
|
+
kind: params.kind || inferKind(text),
|
|
150
|
+
status: "inbox",
|
|
151
|
+
text,
|
|
152
|
+
blocks,
|
|
153
|
+
createdAt: now,
|
|
154
|
+
updatedAt: now,
|
|
155
|
+
capturedVia: params.capturedVia,
|
|
156
|
+
tags: params.tags,
|
|
157
|
+
pinned: params.pinned,
|
|
158
|
+
localVersion: 0,
|
|
159
|
+
remoteVersion: 1
|
|
160
|
+
};
|
|
161
|
+
await this.store.addNote(note);
|
|
162
|
+
log.debug({
|
|
163
|
+
id: note.id,
|
|
164
|
+
kind: note.kind
|
|
165
|
+
}, "Note created");
|
|
166
|
+
return note;
|
|
167
|
+
}
|
|
168
|
+
async getNote(id) {
|
|
169
|
+
return this.store.getNote(id);
|
|
170
|
+
}
|
|
171
|
+
async updateNote(id, patch, trigger = "edit") {
|
|
172
|
+
const existing = await this.store.getNote(id);
|
|
173
|
+
if (!existing) return null;
|
|
174
|
+
const contentTouched = patch.text !== void 0 || patch.blocks !== void 0 || patch.title !== void 0;
|
|
175
|
+
if (contentTouched) await this.maybeSaveSnapshot(existing, trigger);
|
|
176
|
+
const normalizedPatch = { ...patch };
|
|
177
|
+
if (patch.blocks) normalizedPatch.text = patch.text ?? blocksToPlainText(patch.blocks, existing.id);
|
|
178
|
+
else if (typeof patch.text === "string") normalizedPatch.blocks = patch.blocks ?? noteTextToBlocks(patch.text, existing.id);
|
|
179
|
+
normalizedPatch.remoteVersion = (existing.remoteVersion ?? 0) + 1;
|
|
180
|
+
if (contentTouched) {
|
|
181
|
+
const merged = {
|
|
182
|
+
...existing,
|
|
183
|
+
...normalizedPatch,
|
|
184
|
+
id: existing.id,
|
|
185
|
+
createdAt: existing.createdAt,
|
|
186
|
+
updatedAt: Date.now()
|
|
187
|
+
};
|
|
188
|
+
const reconciled = await this.reconcileAttachments(merged);
|
|
189
|
+
normalizedPatch.attachments = reconciled.attachments;
|
|
190
|
+
normalizedPatch.kind = reconciled.kind;
|
|
191
|
+
}
|
|
192
|
+
return this.store.updateNote(id, normalizedPatch);
|
|
193
|
+
}
|
|
194
|
+
async reconcileAttachments(note) {
|
|
195
|
+
const { kept, removed } = partitionAttachmentsByReference(note);
|
|
196
|
+
if (removed.length === 0) return note;
|
|
197
|
+
for (const attachment of removed) await this.store.deleteAttachmentFile(note.id, attachment.relativePath);
|
|
198
|
+
log.debug({
|
|
199
|
+
noteId: note.id,
|
|
200
|
+
removedIds: removed.map((attachment) => attachment.id)
|
|
201
|
+
}, "Pruned orphan note attachments");
|
|
202
|
+
const hasAttachments = kept.length > 0;
|
|
203
|
+
return {
|
|
204
|
+
...note,
|
|
205
|
+
attachments: hasAttachments ? kept : void 0,
|
|
206
|
+
kind: inferKind(note.text, hasAttachments, kept)
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
async syncNote(id, patch, baseRemoteVersion) {
|
|
210
|
+
const existing = await this.store.getNote(id);
|
|
211
|
+
if (!existing) return {
|
|
212
|
+
note: null,
|
|
213
|
+
conflict: false
|
|
214
|
+
};
|
|
215
|
+
const currentRemoteVersion = existing.remoteVersion ?? 0;
|
|
216
|
+
if (baseRemoteVersion !== void 0 && baseRemoteVersion < currentRemoteVersion) return {
|
|
217
|
+
note: existing,
|
|
218
|
+
conflict: true
|
|
219
|
+
};
|
|
220
|
+
return {
|
|
221
|
+
note: await this.updateNote(id, patch, "sync"),
|
|
222
|
+
conflict: false
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
async createAiEditPatch(id, instruction, blocks) {
|
|
226
|
+
const note = await this.store.getNote(id);
|
|
227
|
+
if (!note) return null;
|
|
228
|
+
const organizedBlocks = createAiOrganizedBlocks(blocks?.length ? blocks : note.blocks ?? noteTextToBlocks(note.text, note.id) ?? [], instruction);
|
|
229
|
+
return {
|
|
230
|
+
message: "AI edit patch generated",
|
|
231
|
+
patch: {
|
|
232
|
+
id: randomUUID(),
|
|
233
|
+
summary: `已根据「${instruction.slice(0, 40)}」生成可预览的块级整理建议`,
|
|
234
|
+
operations: [{
|
|
235
|
+
type: "replaceBlocks",
|
|
236
|
+
blocks: organizedBlocks
|
|
237
|
+
}]
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
async deleteNote(id) {
|
|
242
|
+
const deleted = await this.store.deleteNote(id);
|
|
243
|
+
if (deleted) {
|
|
244
|
+
await this.store.deleteAllSnapshots(id);
|
|
245
|
+
this.lastSnapshotAt.delete(id);
|
|
246
|
+
}
|
|
247
|
+
return deleted;
|
|
248
|
+
}
|
|
249
|
+
async listNotes(query = {}) {
|
|
250
|
+
return this.store.listNotes(query);
|
|
251
|
+
}
|
|
252
|
+
async addAttachment(noteId, file) {
|
|
253
|
+
const note = await this.store.getNote(noteId);
|
|
254
|
+
if (!note) return null;
|
|
255
|
+
const { relativePath, size } = await this.store.saveAttachment(noteId, file.name, file.buffer);
|
|
256
|
+
const attachment = {
|
|
257
|
+
id: randomUUID(),
|
|
258
|
+
type: inferAttachmentType(file.mimeType),
|
|
259
|
+
mimeType: file.mimeType,
|
|
260
|
+
fileName: file.name,
|
|
261
|
+
size,
|
|
262
|
+
relativePath,
|
|
263
|
+
duration: file.duration
|
|
264
|
+
};
|
|
265
|
+
const attachments = [...note.attachments || [], attachment];
|
|
266
|
+
const kind = note.kind === "thought" && attachment.type === "audio" ? "voice" : note.kind === "thought" ? "media" : note.kind;
|
|
267
|
+
await this.store.updateNote(noteId, {
|
|
268
|
+
attachments,
|
|
269
|
+
kind
|
|
270
|
+
});
|
|
271
|
+
return attachment;
|
|
272
|
+
}
|
|
273
|
+
async getAttachmentPath(noteId, attachmentId) {
|
|
274
|
+
const note = await this.store.getNote(noteId);
|
|
275
|
+
if (!note) return null;
|
|
276
|
+
const attachment = note.attachments?.find((a) => a.id === attachmentId);
|
|
277
|
+
if (!attachment) return null;
|
|
278
|
+
return {
|
|
279
|
+
filePath: this.store.resolveAttachmentPath(noteId, attachment.relativePath),
|
|
280
|
+
mimeType: attachment.mimeType,
|
|
281
|
+
fileName: attachment.fileName
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
async listNoteHistory(noteId) {
|
|
285
|
+
return this.store.listSnapshots(noteId);
|
|
286
|
+
}
|
|
287
|
+
async getNoteSnapshot(noteId, timestamp) {
|
|
288
|
+
return this.store.getSnapshot(noteId, timestamp);
|
|
289
|
+
}
|
|
290
|
+
async restoreNoteSnapshot(noteId, timestamp) {
|
|
291
|
+
const snapshot = await this.store.getSnapshot(noteId, timestamp);
|
|
292
|
+
if (!snapshot) return null;
|
|
293
|
+
const existing = await this.store.getNote(noteId);
|
|
294
|
+
if (!existing) return null;
|
|
295
|
+
await this.store.saveSnapshot(existing, "restore");
|
|
296
|
+
this.lastSnapshotAt.set(noteId, Date.now());
|
|
297
|
+
await this.store.pruneSnapshots(noteId, MAX_SNAPSHOTS_PER_NOTE);
|
|
298
|
+
return this.store.updateNote(noteId, {
|
|
299
|
+
title: snapshot.title,
|
|
300
|
+
text: snapshot.text,
|
|
301
|
+
blocks: snapshot.blocks,
|
|
302
|
+
tags: snapshot.tags
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
async flush() {
|
|
306
|
+
await this.store.flush();
|
|
307
|
+
}
|
|
308
|
+
async moveToGroup(noteId, groupId) {
|
|
309
|
+
return this.updateNote(noteId, { groupId: groupId ?? void 0 });
|
|
310
|
+
}
|
|
311
|
+
async createTask(title, source, options) {
|
|
312
|
+
return this.createNote({
|
|
313
|
+
title,
|
|
314
|
+
kind: "task",
|
|
315
|
+
capturedVia: source,
|
|
316
|
+
groupId: options?.groupId,
|
|
317
|
+
taskMeta: {
|
|
318
|
+
done: false,
|
|
319
|
+
dueAt: options?.dueAt,
|
|
320
|
+
priority: options?.priority,
|
|
321
|
+
sourceSessionKey: options?.sourceSessionKey,
|
|
322
|
+
sourceNoteId: options?.sourceNoteId
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
async toggleTaskDone(noteId) {
|
|
327
|
+
const note = await this.store.getNote(noteId);
|
|
328
|
+
if (!note || note.kind !== "task") return null;
|
|
329
|
+
const done = !note.taskMeta?.done;
|
|
330
|
+
return this.updateNote(noteId, {
|
|
331
|
+
taskMeta: {
|
|
332
|
+
...note.taskMeta,
|
|
333
|
+
done
|
|
334
|
+
},
|
|
335
|
+
status: done ? "archived" : "processed"
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
async updateTaskMeta(noteId, patch) {
|
|
339
|
+
const note = await this.store.getNote(noteId);
|
|
340
|
+
if (!note || note.kind !== "task") return null;
|
|
341
|
+
return this.updateNote(noteId, { taskMeta: {
|
|
342
|
+
...note.taskMeta,
|
|
343
|
+
done: note.taskMeta?.done ?? false,
|
|
344
|
+
...patch
|
|
345
|
+
} });
|
|
346
|
+
}
|
|
347
|
+
async recordOpen(noteId) {
|
|
348
|
+
return this.updateNote(noteId, { lastOpenedAt: Date.now() });
|
|
349
|
+
}
|
|
350
|
+
async maybeSaveSnapshot(note, trigger) {
|
|
351
|
+
if (trigger !== "edit") {
|
|
352
|
+
await this.store.saveSnapshot(note, trigger);
|
|
353
|
+
this.lastSnapshotAt.set(note.id, Date.now());
|
|
354
|
+
await this.store.pruneSnapshots(note.id, MAX_SNAPSHOTS_PER_NOTE);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const last = this.lastSnapshotAt.get(note.id) ?? 0;
|
|
358
|
+
if (Date.now() - last < SNAPSHOT_THROTTLE_MS) return;
|
|
359
|
+
await this.store.saveSnapshot(note, trigger);
|
|
360
|
+
this.lastSnapshotAt.set(note.id, Date.now());
|
|
361
|
+
await this.store.pruneSnapshots(note.id, MAX_SNAPSHOTS_PER_NOTE);
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
function inferAttachmentType(mimeType) {
|
|
365
|
+
if (mimeType.startsWith("image/")) return "image";
|
|
366
|
+
if (mimeType.startsWith("video/")) return "video";
|
|
367
|
+
if (mimeType.startsWith("audio/")) return "audio";
|
|
368
|
+
return "file";
|
|
369
|
+
}
|
|
370
|
+
//#endregion
|
|
371
|
+
export { NotesService };
|
|
372
|
+
|
|
373
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","names":[],"sources":["../../../src/notes/service.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { createLogger } from '../utils/logger.js';\nimport { buildNoteAttachmentRef, attachmentIdFromTarget } from './attachment-ref.js';\nimport { partitionAttachmentsByReference } from './note-attachment-sync.js';\nimport { NotesStore } from './store.js';\nimport type {\n CaptureSource,\n CreateNoteParams,\n Note,\n NoteAiPatch,\n NoteAttachment,\n NoteBlock,\n NoteIndexEntry,\n NoteKind,\n NoteSnapshot,\n NoteSnapshotEntry,\n NotesListQuery,\n SnapshotTrigger,\n} from './types.js';\n\nconst log = createLogger('NotesService');\n\nfunction inferKind(\n text?: string,\n hasAttachments?: boolean,\n attachments?: NoteAttachment[],\n): NoteKind {\n if (hasAttachments && attachments?.length && attachments.every((item) => item.type === 'audio')) {\n return 'voice';\n }\n if (hasAttachments) return 'media';\n if (!text) return 'thought';\n const lower = text.toLowerCase();\n if (/^(todo|task|remind|buy|call|email|meet|finish|submit|send)\\b/i.test(lower) ||\n /\\b(明天|今天|记得|别忘|待办|提醒)\\b/.test(text)) {\n return 'todo';\n }\n if (/^https?:\\/\\//.test(text.trim())) return 'bookmark';\n return 'thought';\n}\n\nfunction createBlockId(): string {\n return `block_${Date.now()}_${randomUUID().slice(0, 8)}`;\n}\n\nconst IMAGE_MARKDOWN = /^!\\[([^\\]]*)\\]\\(([^)]+)\\)$/;\n\nfunction noteTextToBlocks(text?: string, noteId?: string): NoteBlock[] | undefined {\n if (!text?.trim()) return undefined;\n const now = Date.now();\n return text.split(/\\n{2,}/).map((part) => {\n const trimmed = part.trim();\n if (noteId) {\n const imageMatch = trimmed.match(IMAGE_MARKDOWN);\n if (imageMatch) {\n const attachmentId = attachmentIdFromTarget(imageMatch[2], noteId);\n if (attachmentId) {\n return {\n id: createBlockId(),\n type: 'image' as const,\n attachmentId,\n alt: imageMatch[1] || undefined,\n createdAt: now,\n updatedAt: now,\n };\n }\n }\n }\n return {\n id: createBlockId(),\n type: 'paragraph' as const,\n text: trimmed,\n createdAt: now,\n updatedAt: now,\n };\n });\n}\n\nfunction blocksToPlainText(blocks?: NoteBlock[], noteId?: string): string | undefined {\n if (!blocks?.length) return undefined;\n return blocks\n .map((block) => {\n if (block.type === 'divider') return '---';\n if (block.type === 'todo') return `${block.checked ? '[x]' : '[ ]'} ${block.text}`;\n if (block.type === 'image') {\n if (noteId) {\n return `})`;\n }\n return block.alt ?? '';\n }\n return block.text;\n })\n .filter((text) => text.trim().length > 0)\n .join('\\n\\n');\n}\n\nfunction createAiOrganizedBlocks(blocks: NoteBlock[], instruction: string): NoteBlock[] {\n const now = Date.now();\n const plainText = blocksToPlainText(blocks) || '';\n const lines = plainText\n .split(/\\n+/)\n .map((line) => line.trim())\n .filter(Boolean);\n const wantsTodos = /待办|todo|task|行动|提醒/i.test(instruction);\n const wantsSummary = /摘要|总结|summary|压缩/i.test(instruction);\n\n if (wantsTodos) {\n const candidates = lines.filter((line) => /要|需|记得|todo|task|完成|提交|联系|跟进|提醒/i.test(line));\n return (candidates.length ? candidates : lines).slice(0, 12).map((line) => ({\n id: createBlockId(),\n type: 'todo' as const,\n text: line.replace(/^[-*\\d.\\s\\[\\]x]+/i, '').trim(),\n checked: false,\n createdAt: now,\n updatedAt: now,\n }));\n }\n\n if (wantsSummary) {\n const summary = lines.join(' ').slice(0, 220);\n return [{\n id: createBlockId(),\n type: 'paragraph',\n text: summary,\n createdAt: now,\n updatedAt: now,\n }];\n }\n\n const titleText = lines[0]?.slice(0, 40) || '整理后的笔记';\n const bodyLines = lines.slice(1).length ? lines.slice(1) : lines;\n return [\n {\n id: createBlockId(),\n type: 'heading',\n text: titleText,\n level: 2,\n createdAt: now,\n updatedAt: now,\n },\n ...bodyLines.map((line) => ({\n id: createBlockId(),\n type: 'bulletList' as const,\n text: line.replace(/^[-*\\d.\\s]+/, '').trim(),\n indent: 0,\n createdAt: now,\n updatedAt: now,\n })),\n ];\n}\n\nconst SNAPSHOT_THROTTLE_MS = 60_000;\nconst MAX_SNAPSHOTS_PER_NOTE = 30;\n\nexport class NotesService {\n private store: NotesStore;\n private lastSnapshotAt = new Map<string, number>();\n\n constructor(store: NotesStore) {\n this.store = store;\n }\n\n async initialize(): Promise<void> {\n await this.store.initialize();\n log.debug('NotesService initialized');\n }\n\n async quickCapture(text: string, source: CaptureSource): Promise<Note> {\n const now = Date.now();\n const id = randomUUID();\n const blocks = noteTextToBlocks(text, id);\n const note: Note = {\n id,\n kind: inferKind(text),\n status: 'inbox',\n text,\n blocks,\n createdAt: now,\n updatedAt: now,\n capturedVia: source,\n localVersion: 0,\n remoteVersion: 1,\n };\n await this.store.addNote(note);\n log.debug({ id: note.id, kind: note.kind }, 'Quick capture');\n return note;\n }\n\n async createNote(params: CreateNoteParams): Promise<Note> {\n const now = Date.now();\n const id = randomUUID();\n const blocks = params.blocks ?? noteTextToBlocks(params.text, id);\n const text = params.text ?? blocksToPlainText(blocks, id);\n const note: Note = {\n id,\n title: params.title,\n kind: params.kind || inferKind(text),\n status: 'inbox',\n text,\n blocks,\n createdAt: now,\n updatedAt: now,\n capturedVia: params.capturedVia,\n tags: params.tags,\n pinned: params.pinned,\n localVersion: 0,\n remoteVersion: 1,\n };\n await this.store.addNote(note);\n log.debug({ id: note.id, kind: note.kind }, 'Note created');\n return note;\n }\n\n async getNote(id: string): Promise<Note | null> {\n return this.store.getNote(id);\n }\n\n async updateNote(id: string, patch: Partial<Note>, trigger: SnapshotTrigger = 'edit'): Promise<Note | null> {\n const existing = await this.store.getNote(id);\n if (!existing) return null;\n\n const contentTouched = patch.text !== undefined || patch.blocks !== undefined || patch.title !== undefined;\n if (contentTouched) {\n await this.maybeSaveSnapshot(existing, trigger);\n }\n\n const normalizedPatch: Partial<Note> = { ...patch };\n if (patch.blocks) {\n normalizedPatch.text = patch.text ?? blocksToPlainText(patch.blocks, existing.id);\n } else if (typeof patch.text === 'string') {\n normalizedPatch.blocks = patch.blocks ?? noteTextToBlocks(patch.text, existing.id);\n }\n normalizedPatch.remoteVersion = (existing.remoteVersion ?? 0) + 1;\n\n if (contentTouched) {\n const merged: Note = {\n ...existing,\n ...normalizedPatch,\n id: existing.id,\n createdAt: existing.createdAt,\n updatedAt: Date.now(),\n };\n const reconciled = await this.reconcileAttachments(merged);\n normalizedPatch.attachments = reconciled.attachments;\n normalizedPatch.kind = reconciled.kind;\n }\n\n return this.store.updateNote(id, normalizedPatch);\n }\n\n private async reconcileAttachments(note: Note): Promise<Note> {\n const { kept, removed } = partitionAttachmentsByReference(note);\n if (removed.length === 0) return note;\n\n for (const attachment of removed) {\n await this.store.deleteAttachmentFile(note.id, attachment.relativePath);\n }\n\n log.debug(\n { noteId: note.id, removedIds: removed.map((attachment) => attachment.id) },\n 'Pruned orphan note attachments',\n );\n\n const hasAttachments = kept.length > 0;\n return {\n ...note,\n attachments: hasAttachments ? kept : undefined,\n kind: inferKind(note.text, hasAttachments, kept),\n };\n }\n\n async syncNote(\n id: string,\n patch: Partial<Note>,\n baseRemoteVersion?: number,\n ): Promise<{ note: Note | null; conflict: boolean }> {\n const existing = await this.store.getNote(id);\n if (!existing) return { note: null, conflict: false };\n\n const currentRemoteVersion = existing.remoteVersion ?? 0;\n if (baseRemoteVersion !== undefined && baseRemoteVersion < currentRemoteVersion) {\n return { note: existing, conflict: true };\n }\n\n const updated = await this.updateNote(id, patch, 'sync');\n return { note: updated, conflict: false };\n }\n\n async createAiEditPatch(\n id: string,\n instruction: string,\n blocks?: NoteBlock[],\n ): Promise<{ message: string; patch: NoteAiPatch } | null> {\n const note = await this.store.getNote(id);\n if (!note) return null;\n\n const sourceBlocks = blocks?.length ? blocks : note.blocks ?? noteTextToBlocks(note.text, note.id) ?? [];\n const organizedBlocks = createAiOrganizedBlocks(sourceBlocks, instruction);\n const patch: NoteAiPatch = {\n id: randomUUID(),\n summary: `已根据「${instruction.slice(0, 40)}」生成可预览的块级整理建议`,\n operations: [{ type: 'replaceBlocks', blocks: organizedBlocks }],\n };\n\n return {\n message: 'AI edit patch generated',\n patch,\n };\n }\n\n async deleteNote(id: string): Promise<boolean> {\n const deleted = await this.store.deleteNote(id);\n if (deleted) {\n await this.store.deleteAllSnapshots(id);\n this.lastSnapshotAt.delete(id);\n }\n return deleted;\n }\n\n async listNotes(query: NotesListQuery = {}): Promise<{ items: NoteIndexEntry[]; total: number }> {\n return this.store.listNotes(query);\n }\n\n async addAttachment(\n noteId: string,\n file: { name: string; buffer: Buffer; mimeType: string; duration?: number },\n ): Promise<NoteAttachment | null> {\n const note = await this.store.getNote(noteId);\n if (!note) return null;\n\n const { relativePath, size } = await this.store.saveAttachment(noteId, file.name, file.buffer);\n\n const attachment: NoteAttachment = {\n id: randomUUID(),\n type: inferAttachmentType(file.mimeType),\n mimeType: file.mimeType,\n fileName: file.name,\n size,\n relativePath,\n duration: file.duration,\n };\n\n const attachments = [...(note.attachments || []), attachment];\n const kind: NoteKind =\n note.kind === 'thought' && attachment.type === 'audio'\n ? 'voice'\n : note.kind === 'thought'\n ? 'media'\n : note.kind;\n await this.store.updateNote(noteId, { attachments, kind });\n\n return attachment;\n }\n\n async getAttachmentPath(\n noteId: string,\n attachmentId: string,\n ): Promise<{ filePath: string; mimeType: string; fileName: string } | null> {\n const note = await this.store.getNote(noteId);\n if (!note) return null;\n\n const attachment = note.attachments?.find((a) => a.id === attachmentId);\n if (!attachment) return null;\n\n const fullPath = this.store.resolveAttachmentPath(noteId, attachment.relativePath);\n return { filePath: fullPath, mimeType: attachment.mimeType, fileName: attachment.fileName };\n }\n\n async listNoteHistory(noteId: string): Promise<NoteSnapshotEntry[]> {\n return this.store.listSnapshots(noteId);\n }\n\n async getNoteSnapshot(noteId: string, timestamp: number): Promise<NoteSnapshot | null> {\n return this.store.getSnapshot(noteId, timestamp);\n }\n\n async restoreNoteSnapshot(noteId: string, timestamp: number): Promise<Note | null> {\n const snapshot = await this.store.getSnapshot(noteId, timestamp);\n if (!snapshot) return null;\n const existing = await this.store.getNote(noteId);\n if (!existing) return null;\n\n await this.store.saveSnapshot(existing, 'restore');\n this.lastSnapshotAt.set(noteId, Date.now());\n await this.store.pruneSnapshots(noteId, MAX_SNAPSHOTS_PER_NOTE);\n\n return this.store.updateNote(noteId, {\n title: snapshot.title,\n text: snapshot.text,\n blocks: snapshot.blocks,\n tags: snapshot.tags,\n });\n }\n\n async flush(): Promise<void> {\n await this.store.flush();\n }\n\n // ── Space grouping ──────────────────────────────────────────────────\n\n async moveToGroup(noteId: string, groupId: string | null): Promise<Note | null> {\n return this.updateNote(noteId, { groupId: groupId ?? undefined });\n }\n\n // ── Task lifecycle ──────────────────────────────────────────────────\n\n async createTask(\n title: string,\n source: CaptureSource,\n options?: { dueAt?: number; priority?: 'high' | 'medium' | 'low'; sourceSessionKey?: string; sourceNoteId?: string; groupId?: string },\n ): Promise<Note> {\n return this.createNote({\n title,\n kind: 'task',\n capturedVia: source,\n groupId: options?.groupId,\n taskMeta: {\n done: false,\n dueAt: options?.dueAt,\n priority: options?.priority,\n sourceSessionKey: options?.sourceSessionKey,\n sourceNoteId: options?.sourceNoteId,\n },\n });\n }\n\n async toggleTaskDone(noteId: string): Promise<Note | null> {\n const note = await this.store.getNote(noteId);\n if (!note || note.kind !== 'task') return null;\n const done = !note.taskMeta?.done;\n return this.updateNote(noteId, {\n taskMeta: { ...note.taskMeta, done },\n status: done ? 'archived' : 'processed',\n });\n }\n\n async updateTaskMeta(noteId: string, patch: Partial<import('./types.js').NoteTaskMeta>): Promise<Note | null> {\n const note = await this.store.getNote(noteId);\n if (!note || note.kind !== 'task') return null;\n return this.updateNote(noteId, {\n taskMeta: { ...note.taskMeta, done: note.taskMeta?.done ?? false, ...patch },\n });\n }\n\n // ── Open tracking ──────────────────────────────────────────────────\n\n async recordOpen(noteId: string): Promise<Note | null> {\n return this.updateNote(noteId, { lastOpenedAt: Date.now() } as Partial<Note>);\n }\n\n private async maybeSaveSnapshot(note: Note, trigger: SnapshotTrigger): Promise<void> {\n if (trigger !== 'edit') {\n await this.store.saveSnapshot(note, trigger);\n this.lastSnapshotAt.set(note.id, Date.now());\n await this.store.pruneSnapshots(note.id, MAX_SNAPSHOTS_PER_NOTE);\n return;\n }\n const last = this.lastSnapshotAt.get(note.id) ?? 0;\n if (Date.now() - last < SNAPSHOT_THROTTLE_MS) return;\n await this.store.saveSnapshot(note, trigger);\n this.lastSnapshotAt.set(note.id, Date.now());\n await this.store.pruneSnapshots(note.id, MAX_SNAPSHOTS_PER_NOTE);\n }\n}\n\nfunction inferAttachmentType(mimeType: string): NoteAttachment['type'] {\n if (mimeType.startsWith('image/')) return 'image';\n if (mimeType.startsWith('video/')) return 'video';\n if (mimeType.startsWith('audio/')) return 'audio';\n return 'file';\n}\n"],"mappings":";;;;;;aAEkD;AAmBlD,MAAM,MAAM,aAAa,eAAe;AAExC,SAAS,UACP,MACA,gBACA,aACU;AACV,KAAI,kBAAkB,aAAa,UAAU,YAAY,OAAO,SAAS,KAAK,SAAS,QAAQ,CAC7F,QAAO;AAET,KAAI,eAAgB,QAAO;AAC3B,KAAI,CAAC,KAAM,QAAO;CAClB,MAAM,QAAQ,KAAK,aAAa;AAChC,KAAI,gEAAgE,KAAK,MAAM,IAC3E,0BAA0B,KAAK,KAAK,CACtC,QAAO;AAET,KAAI,eAAe,KAAK,KAAK,MAAM,CAAC,CAAE,QAAO;AAC7C,QAAO;;AAGT,SAAS,gBAAwB;AAC/B,QAAO,SAAS,KAAK,KAAK,CAAC,GAAG,YAAY,CAAC,MAAM,GAAG,EAAE;;AAGxD,MAAM,iBAAiB;AAEvB,SAAS,iBAAiB,MAAe,QAA0C;AACjF,KAAI,CAAC,MAAM,MAAM,CAAE,QAAO,KAAA;CAC1B,MAAM,MAAM,KAAK,KAAK;AACtB,QAAO,KAAK,MAAM,SAAS,CAAC,KAAK,SAAS;EACxC,MAAM,UAAU,KAAK,MAAM;AAC3B,MAAI,QAAQ;GACV,MAAM,aAAa,QAAQ,MAAM,eAAe;AAChD,OAAI,YAAY;IACd,MAAM,eAAe,uBAAuB,WAAW,IAAI,OAAO;AAClE,QAAI,aACF,QAAO;KACL,IAAI,eAAe;KACnB,MAAM;KACN;KACA,KAAK,WAAW,MAAM,KAAA;KACtB,WAAW;KACX,WAAW;KACZ;;;AAIP,SAAO;GACL,IAAI,eAAe;GACnB,MAAM;GACN,MAAM;GACN,WAAW;GACX,WAAW;GACZ;GACD;;AAGJ,SAAS,kBAAkB,QAAsB,QAAqC;AACpF,KAAI,CAAC,QAAQ,OAAQ,QAAO,KAAA;AAC5B,QAAO,OACJ,KAAK,UAAU;AACd,MAAI,MAAM,SAAS,UAAW,QAAO;AACrC,MAAI,MAAM,SAAS,OAAQ,QAAO,GAAG,MAAM,UAAU,QAAQ,MAAM,GAAG,MAAM;AAC5E,MAAI,MAAM,SAAS,SAAS;AAC1B,OAAI,OACF,QAAO,KAAK,MAAM,OAAO,GAAG,IAAI,uBAAuB,QAAQ,MAAM,aAAa,CAAC;AAErF,UAAO,MAAM,OAAO;;AAEtB,SAAO,MAAM;GACb,CACD,QAAQ,SAAS,KAAK,MAAM,CAAC,SAAS,EAAE,CACxC,KAAK,OAAO;;AAGjB,SAAS,wBAAwB,QAAqB,aAAkC;CACtF,MAAM,MAAM,KAAK,KAAK;CAEtB,MAAM,SADY,kBAAkB,OAAO,IAAI,IAE5C,MAAM,MAAM,CACZ,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ;CAClB,MAAM,aAAa,sBAAsB,KAAK,YAAY;CAC1D,MAAM,eAAe,oBAAoB,KAAK,YAAY;AAE1D,KAAI,YAAY;EACd,MAAM,aAAa,MAAM,QAAQ,SAAS,mCAAmC,KAAK,KAAK,CAAC;AACxF,UAAQ,WAAW,SAAS,aAAa,OAAO,MAAM,GAAG,GAAG,CAAC,KAAK,UAAU;GAC1E,IAAI,eAAe;GACnB,MAAM;GACN,MAAM,KAAK,QAAQ,qBAAqB,GAAG,CAAC,MAAM;GAClD,SAAS;GACT,WAAW;GACX,WAAW;GACZ,EAAE;;AAGL,KAAI,cAAc;EAChB,MAAM,UAAU,MAAM,KAAK,IAAI,CAAC,MAAM,GAAG,IAAI;AAC7C,SAAO,CAAC;GACN,IAAI,eAAe;GACnB,MAAM;GACN,MAAM;GACN,WAAW;GACX,WAAW;GACZ,CAAC;;CAGJ,MAAM,YAAY,MAAM,IAAI,MAAM,GAAG,GAAG,IAAI;CAC5C,MAAM,YAAY,MAAM,MAAM,EAAE,CAAC,SAAS,MAAM,MAAM,EAAE,GAAG;AAC3D,QAAO,CACL;EACE,IAAI,eAAe;EACnB,MAAM;EACN,MAAM;EACN,OAAO;EACP,WAAW;EACX,WAAW;EACZ,EACD,GAAG,UAAU,KAAK,UAAU;EAC1B,IAAI,eAAe;EACnB,MAAM;EACN,MAAM,KAAK,QAAQ,eAAe,GAAG,CAAC,MAAM;EAC5C,QAAQ;EACR,WAAW;EACX,WAAW;EACZ,EAAE,CACJ;;AAGH,MAAM,uBAAuB;AAC7B,MAAM,yBAAyB;AAE/B,IAAa,eAAb,MAA0B;CACxB;CACA,iCAAyB,IAAI,KAAqB;CAElD,YAAY,OAAmB;AAC7B,OAAK,QAAQ;;CAGf,MAAM,aAA4B;AAChC,QAAM,KAAK,MAAM,YAAY;AAC7B,MAAI,MAAM,2BAA2B;;CAGvC,MAAM,aAAa,MAAc,QAAsC;EACrE,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,KAAK,YAAY;EACvB,MAAM,SAAS,iBAAiB,MAAM,GAAG;EACzC,MAAM,OAAa;GACjB;GACA,MAAM,UAAU,KAAK;GACrB,QAAQ;GACR;GACA;GACA,WAAW;GACX,WAAW;GACX,aAAa;GACb,cAAc;GACd,eAAe;GAChB;AACD,QAAM,KAAK,MAAM,QAAQ,KAAK;AAC9B,MAAI,MAAM;GAAE,IAAI,KAAK;GAAI,MAAM,KAAK;GAAM,EAAE,gBAAgB;AAC5D,SAAO;;CAGT,MAAM,WAAW,QAAyC;EACxD,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,KAAK,YAAY;EACvB,MAAM,SAAS,OAAO,UAAU,iBAAiB,OAAO,MAAM,GAAG;EACjE,MAAM,OAAO,OAAO,QAAQ,kBAAkB,QAAQ,GAAG;EACzD,MAAM,OAAa;GACjB;GACA,OAAO,OAAO;GACd,MAAM,OAAO,QAAQ,UAAU,KAAK;GACpC,QAAQ;GACR;GACA;GACA,WAAW;GACX,WAAW;GACX,aAAa,OAAO;GACpB,MAAM,OAAO;GACb,QAAQ,OAAO;GACf,cAAc;GACd,eAAe;GAChB;AACD,QAAM,KAAK,MAAM,QAAQ,KAAK;AAC9B,MAAI,MAAM;GAAE,IAAI,KAAK;GAAI,MAAM,KAAK;GAAM,EAAE,eAAe;AAC3D,SAAO;;CAGT,MAAM,QAAQ,IAAkC;AAC9C,SAAO,KAAK,MAAM,QAAQ,GAAG;;CAG/B,MAAM,WAAW,IAAY,OAAsB,UAA2B,QAA8B;EAC1G,MAAM,WAAW,MAAM,KAAK,MAAM,QAAQ,GAAG;AAC7C,MAAI,CAAC,SAAU,QAAO;EAEtB,MAAM,iBAAiB,MAAM,SAAS,KAAA,KAAa,MAAM,WAAW,KAAA,KAAa,MAAM,UAAU,KAAA;AACjG,MAAI,eACF,OAAM,KAAK,kBAAkB,UAAU,QAAQ;EAGjD,MAAM,kBAAiC,EAAE,GAAG,OAAO;AACnD,MAAI,MAAM,OACR,iBAAgB,OAAO,MAAM,QAAQ,kBAAkB,MAAM,QAAQ,SAAS,GAAG;WACxE,OAAO,MAAM,SAAS,SAC/B,iBAAgB,SAAS,MAAM,UAAU,iBAAiB,MAAM,MAAM,SAAS,GAAG;AAEpF,kBAAgB,iBAAiB,SAAS,iBAAiB,KAAK;AAEhE,MAAI,gBAAgB;GAClB,MAAM,SAAe;IACnB,GAAG;IACH,GAAG;IACH,IAAI,SAAS;IACb,WAAW,SAAS;IACpB,WAAW,KAAK,KAAK;IACtB;GACD,MAAM,aAAa,MAAM,KAAK,qBAAqB,OAAO;AAC1D,mBAAgB,cAAc,WAAW;AACzC,mBAAgB,OAAO,WAAW;;AAGpC,SAAO,KAAK,MAAM,WAAW,IAAI,gBAAgB;;CAGnD,MAAc,qBAAqB,MAA2B;EAC5D,MAAM,EAAE,MAAM,YAAY,gCAAgC,KAAK;AAC/D,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,OAAK,MAAM,cAAc,QACvB,OAAM,KAAK,MAAM,qBAAqB,KAAK,IAAI,WAAW,aAAa;AAGzE,MAAI,MACF;GAAE,QAAQ,KAAK;GAAI,YAAY,QAAQ,KAAK,eAAe,WAAW,GAAG;GAAE,EAC3E,iCACD;EAED,MAAM,iBAAiB,KAAK,SAAS;AACrC,SAAO;GACL,GAAG;GACH,aAAa,iBAAiB,OAAO,KAAA;GACrC,MAAM,UAAU,KAAK,MAAM,gBAAgB,KAAK;GACjD;;CAGH,MAAM,SACJ,IACA,OACA,mBACmD;EACnD,MAAM,WAAW,MAAM,KAAK,MAAM,QAAQ,GAAG;AAC7C,MAAI,CAAC,SAAU,QAAO;GAAE,MAAM;GAAM,UAAU;GAAO;EAErD,MAAM,uBAAuB,SAAS,iBAAiB;AACvD,MAAI,sBAAsB,KAAA,KAAa,oBAAoB,qBACzD,QAAO;GAAE,MAAM;GAAU,UAAU;GAAM;AAI3C,SAAO;GAAE,MAAM,MADO,KAAK,WAAW,IAAI,OAAO,OAAO;GAChC,UAAU;GAAO;;CAG3C,MAAM,kBACJ,IACA,aACA,QACyD;EACzD,MAAM,OAAO,MAAM,KAAK,MAAM,QAAQ,GAAG;AACzC,MAAI,CAAC,KAAM,QAAO;EAGlB,MAAM,kBAAkB,wBADH,QAAQ,SAAS,SAAS,KAAK,UAAU,iBAAiB,KAAK,MAAM,KAAK,GAAG,IAAI,EAAE,EAC1C,YAAY;AAO1E,SAAO;GACL,SAAS;GACT,OAAA;IAPA,IAAI,YAAY;IAChB,SAAS,OAAO,YAAY,MAAM,GAAG,GAAG,CAAC;IACzC,YAAY,CAAC;KAAE,MAAM;KAAiB,QAAQ;KAAiB,CAAC;IAK3D;GACN;;CAGH,MAAM,WAAW,IAA8B;EAC7C,MAAM,UAAU,MAAM,KAAK,MAAM,WAAW,GAAG;AAC/C,MAAI,SAAS;AACX,SAAM,KAAK,MAAM,mBAAmB,GAAG;AACvC,QAAK,eAAe,OAAO,GAAG;;AAEhC,SAAO;;CAGT,MAAM,UAAU,QAAwB,EAAE,EAAuD;AAC/F,SAAO,KAAK,MAAM,UAAU,MAAM;;CAGpC,MAAM,cACJ,QACA,MACgC;EAChC,MAAM,OAAO,MAAM,KAAK,MAAM,QAAQ,OAAO;AAC7C,MAAI,CAAC,KAAM,QAAO;EAElB,MAAM,EAAE,cAAc,SAAS,MAAM,KAAK,MAAM,eAAe,QAAQ,KAAK,MAAM,KAAK,OAAO;EAE9F,MAAM,aAA6B;GACjC,IAAI,YAAY;GAChB,MAAM,oBAAoB,KAAK,SAAS;GACxC,UAAU,KAAK;GACf,UAAU,KAAK;GACf;GACA;GACA,UAAU,KAAK;GAChB;EAED,MAAM,cAAc,CAAC,GAAI,KAAK,eAAe,EAAE,EAAG,WAAW;EAC7D,MAAM,OACJ,KAAK,SAAS,aAAa,WAAW,SAAS,UAC3C,UACA,KAAK,SAAS,YACZ,UACA,KAAK;AACb,QAAM,KAAK,MAAM,WAAW,QAAQ;GAAE;GAAa;GAAM,CAAC;AAE1D,SAAO;;CAGT,MAAM,kBACJ,QACA,cAC0E;EAC1E,MAAM,OAAO,MAAM,KAAK,MAAM,QAAQ,OAAO;AAC7C,MAAI,CAAC,KAAM,QAAO;EAElB,MAAM,aAAa,KAAK,aAAa,MAAM,MAAM,EAAE,OAAO,aAAa;AACvE,MAAI,CAAC,WAAY,QAAO;AAGxB,SAAO;GAAE,UADQ,KAAK,MAAM,sBAAsB,QAAQ,WAAW,aAC1C;GAAE,UAAU,WAAW;GAAU,UAAU,WAAW;GAAU;;CAG7F,MAAM,gBAAgB,QAA8C;AAClE,SAAO,KAAK,MAAM,cAAc,OAAO;;CAGzC,MAAM,gBAAgB,QAAgB,WAAiD;AACrF,SAAO,KAAK,MAAM,YAAY,QAAQ,UAAU;;CAGlD,MAAM,oBAAoB,QAAgB,WAAyC;EACjF,MAAM,WAAW,MAAM,KAAK,MAAM,YAAY,QAAQ,UAAU;AAChE,MAAI,CAAC,SAAU,QAAO;EACtB,MAAM,WAAW,MAAM,KAAK,MAAM,QAAQ,OAAO;AACjD,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,KAAK,MAAM,aAAa,UAAU,UAAU;AAClD,OAAK,eAAe,IAAI,QAAQ,KAAK,KAAK,CAAC;AAC3C,QAAM,KAAK,MAAM,eAAe,QAAQ,uBAAuB;AAE/D,SAAO,KAAK,MAAM,WAAW,QAAQ;GACnC,OAAO,SAAS;GAChB,MAAM,SAAS;GACf,QAAQ,SAAS;GACjB,MAAM,SAAS;GAChB,CAAC;;CAGJ,MAAM,QAAuB;AAC3B,QAAM,KAAK,MAAM,OAAO;;CAK1B,MAAM,YAAY,QAAgB,SAA8C;AAC9E,SAAO,KAAK,WAAW,QAAQ,EAAE,SAAS,WAAW,KAAA,GAAW,CAAC;;CAKnE,MAAM,WACJ,OACA,QACA,SACe;AACf,SAAO,KAAK,WAAW;GACrB;GACA,MAAM;GACN,aAAa;GACb,SAAS,SAAS;GAClB,UAAU;IACR,MAAM;IACN,OAAO,SAAS;IAChB,UAAU,SAAS;IACnB,kBAAkB,SAAS;IAC3B,cAAc,SAAS;IACxB;GACF,CAAC;;CAGJ,MAAM,eAAe,QAAsC;EACzD,MAAM,OAAO,MAAM,KAAK,MAAM,QAAQ,OAAO;AAC7C,MAAI,CAAC,QAAQ,KAAK,SAAS,OAAQ,QAAO;EAC1C,MAAM,OAAO,CAAC,KAAK,UAAU;AAC7B,SAAO,KAAK,WAAW,QAAQ;GAC7B,UAAU;IAAE,GAAG,KAAK;IAAU;IAAM;GACpC,QAAQ,OAAO,aAAa;GAC7B,CAAC;;CAGJ,MAAM,eAAe,QAAgB,OAAyE;EAC5G,MAAM,OAAO,MAAM,KAAK,MAAM,QAAQ,OAAO;AAC7C,MAAI,CAAC,QAAQ,KAAK,SAAS,OAAQ,QAAO;AAC1C,SAAO,KAAK,WAAW,QAAQ,EAC7B,UAAU;GAAE,GAAG,KAAK;GAAU,MAAM,KAAK,UAAU,QAAQ;GAAO,GAAG;GAAO,EAC7E,CAAC;;CAKJ,MAAM,WAAW,QAAsC;AACrD,SAAO,KAAK,WAAW,QAAQ,EAAE,cAAc,KAAK,KAAK,EAAE,CAAkB;;CAG/E,MAAc,kBAAkB,MAAY,SAAyC;AACnF,MAAI,YAAY,QAAQ;AACtB,SAAM,KAAK,MAAM,aAAa,MAAM,QAAQ;AAC5C,QAAK,eAAe,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC;AAC5C,SAAM,KAAK,MAAM,eAAe,KAAK,IAAI,uBAAuB;AAChE;;EAEF,MAAM,OAAO,KAAK,eAAe,IAAI,KAAK,GAAG,IAAI;AACjD,MAAI,KAAK,KAAK,GAAG,OAAO,qBAAsB;AAC9C,QAAM,KAAK,MAAM,aAAa,MAAM,QAAQ;AAC5C,OAAK,eAAe,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC;AAC5C,QAAM,KAAK,MAAM,eAAe,KAAK,IAAI,uBAAuB;;;AAIpE,SAAS,oBAAoB,UAA0C;AACrE,KAAI,SAAS,WAAW,SAAS,CAAE,QAAO;AAC1C,KAAI,SAAS,WAAW,SAAS,CAAE,QAAO;AAC1C,KAAI,SAAS,WAAW,SAAS,CAAE,QAAO;AAC1C,QAAO"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Note, NoteIndexEntry, NoteSnapshot, NoteSnapshotEntry, NotesListQuery, SnapshotTrigger } from './types.js';
|
|
2
|
+
export declare class NotesStore {
|
|
3
|
+
private indexCache;
|
|
4
|
+
private dirty;
|
|
5
|
+
private saveTimeout;
|
|
6
|
+
private initialized;
|
|
7
|
+
initialize(): Promise<void>;
|
|
8
|
+
addNote(note: Note): Promise<void>;
|
|
9
|
+
getNote(id: string): Promise<Note | null>;
|
|
10
|
+
updateNote(id: string, patch: Partial<Note>): Promise<Note | null>;
|
|
11
|
+
deleteNote(id: string): Promise<boolean>;
|
|
12
|
+
listNotes(query?: NotesListQuery): Promise<{
|
|
13
|
+
items: NoteIndexEntry[];
|
|
14
|
+
total: number;
|
|
15
|
+
}>;
|
|
16
|
+
private noteIndexEntryMatchesSearch;
|
|
17
|
+
saveAttachment(noteId: string, fileName: string, buffer: Buffer): Promise<{
|
|
18
|
+
relativePath: string;
|
|
19
|
+
size: number;
|
|
20
|
+
}>;
|
|
21
|
+
resolveAttachmentPath(noteId: string, relativePath: string): string;
|
|
22
|
+
deleteAttachmentFile(noteId: string, relativePath: string): Promise<void>;
|
|
23
|
+
saveSnapshot(note: Note, trigger: SnapshotTrigger): Promise<void>;
|
|
24
|
+
listSnapshots(noteId: string): Promise<NoteSnapshotEntry[]>;
|
|
25
|
+
getSnapshot(noteId: string, timestamp: number): Promise<NoteSnapshot | null>;
|
|
26
|
+
pruneSnapshots(noteId: string, maxCount: number): Promise<void>;
|
|
27
|
+
deleteAllSnapshots(noteId: string): Promise<void>;
|
|
28
|
+
flush(): Promise<void>;
|
|
29
|
+
private loadIndex;
|
|
30
|
+
private writeIndex;
|
|
31
|
+
private writeNoteItem;
|
|
32
|
+
private scheduleIndexSave;
|
|
33
|
+
private rebuildIndexFromItems;
|
|
34
|
+
}
|