@xopcai/xopc 0.0.91 → 0.0.93
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-C7tTJLP9.js +222 -0
- package/dist/gateway/static/root/assets/apps-page-BbzdMyrg.js +1 -0
- package/dist/gateway/static/root/assets/channels-settings-B49vG2hE.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-CYWL5DLD.js → channels-status-swr-CsGkK9h9.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-api-TVqLlGAC.js → cron-api-CyAm0xJT.js} +1 -1
- package/dist/gateway/static/root/assets/cron-page-Bjx7IOdR.js +1 -0
- package/dist/gateway/static/root/assets/{dist-CUV1uY5f.js → dist-DHwVV8XK.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-mTLHRDp1.js → extension-debug-page-BK8kcc4F.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-iI8BI7WK.js → extension-page-Cf8X_QUc.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-ByXcdubM.js → extension-settings-page-C5-YLMmy.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-BWtQq_Ys.js → fetch-BAPnkYbC.js} +1 -1
- package/dist/gateway/static/root/assets/{field-primitives-BsZ-4VT5.js → field-primitives-8p7ucXa1.js} +1 -1
- package/dist/gateway/static/root/assets/heartbeat-config-api-CpgW2sGp.js +1 -0
- package/dist/gateway/static/root/assets/index-CwDdudZM.css +1 -0
- package/dist/gateway/static/root/assets/{index-CKkR-v9U.js → index-Do52EfZK.js} +82 -82
- package/dist/gateway/static/root/assets/logs-page-BxukQ-J-.js +1 -0
- package/dist/gateway/static/root/assets/{note-detail-page-DJ2Mb4x7.js → note-detail-page-WLM6FUIi.js} +53 -53
- package/dist/gateway/static/root/assets/{note-time-JLBPSLzK.js → note-time-EFyIVhec.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-BYPVYcYn.js +1 -0
- package/dist/gateway/static/root/assets/sessions-page-BFD2_-Cl.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-CEs8pGh6.js +2 -0
- package/dist/gateway/static/root/assets/{settings-form-section-DSYCknxM.js → settings-form-section-C6cGTVwK.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-BiP5iH46.js +2 -0
- package/dist/gateway/static/root/assets/{share-preview-page-awRqs4hV.js → share-preview-page-tnIfJ4K6.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page-CNDctFIn.js +2 -0
- package/dist/gateway/static/root/assets/{theme-store-BC-42BoZ.js → theme-store-D6EsNTPr.js} +1 -1
- package/dist/gateway/static/root/assets/url-CTjpm0Uz.js +3 -0
- package/dist/gateway/static/root/assets/{utils-DX3TQuap.js → utils-C86AVfY-.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-CalxUkxm.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-page.utils-ClC37yEp.js → workflow-page.utils-DsEriMFW.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-D2fRxXJG.js +27 -0
- package/dist/gateway/static/root/index.html +5 -5
- 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/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/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 +12 -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.js +136 -1
- package/dist/src/gateway/hono/routes/notes.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/host.d.ts +2 -0
- package/dist/src/gateway/host.js +6 -3
- package/dist/src/gateway/host.js.map +1 -1
- 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 +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/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/index.d.ts +1 -1
- package/dist/src/notes/service.d.ts +24 -1
- package/dist/src/notes/service.js +279 -0
- package/dist/src/notes/service.js.map +1 -1
- package/dist/src/notes/store.d.ts +4 -0
- package/dist/src/notes/store.js +37 -8
- package/dist/src/notes/store.js.map +1 -1
- package/dist/src/notes/types.d.ts +70 -2
- 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 +5 -1
- package/dist/gateway/static/root/assets/agents-bVWUlrlD.js +0 -222
- package/dist/gateway/static/root/assets/apps-page-CIC8bmvZ.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-C8G8RAAP.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-BtcFYlvv.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-config-api-WjTsRLCU.js +0 -1
- package/dist/gateway/static/root/assets/index-VlELBY99.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-ClnIpxfd.js +0 -1
- package/dist/gateway/static/root/assets/notes-page-BE-75qz9.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-bJJkWtTl.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-WcMXLq2U.js +0 -3
- package/dist/gateway/static/root/assets/skills-page-Lu-i1JG7.js +0 -2
- package/dist/gateway/static/root/assets/url-CY1RQKTU.js +0 -3
- package/dist/gateway/static/root/assets/voice-api-key-field-B5uKlDqA.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-C7VhIXtR.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 @@
|
|
|
1
|
+
{"version":3,"file":"connectors.js","names":[],"sources":["../../../../../src/gateway/hono/routes/connectors.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport type { Config } from '../../../config/schema.js';\nimport { getConnectorDefinition, listConnectorCatalog, listConnectorProviders } from '../../../connectors/catalog.js';\nimport { testConnectorInstance } from '../../../connectors/health.js';\nimport { installConnector, uninstallConnector } from '../../../connectors/install.js';\nimport { getConnectorInstance, listConnectorInstances } from '../../../connectors/instances.js';\nimport { startConnectorOAuth, completeConnectorOAuth } from '../../../connectors/oauth.js';\nimport { recordConnectorHealthUsage } from '../../../connectors/usage.js';\nimport type { ConnectorInstallInput } from '../../../connectors/types.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function registerConnectorRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.get('/api/connectors/catalog', (c) => {\n return c.json({\n ok: true,\n payload: {\n connectors: listConnectorCatalog(),\n providers: listConnectorProviders().map((provider) => ({\n id: provider.id,\n displayName: provider.displayName,\n })),\n },\n });\n });\n\n authenticated.get('/api/connectors/installed', (c) => {\n const config = service.currentConfig as Config;\n return c.json({ ok: true, payload: { instances: listConnectorInstances(config) } });\n });\n\n authenticated.get('/api/connectors/:id', (c) => {\n const connectorId = c.req.param('id');\n const connector = getConnectorDefinition(connectorId);\n if (!connector) {\n return c.json({ ok: false, error: `Unknown connector: ${connectorId}` }, 404);\n }\n const config = service.currentConfig as Config;\n const instances = listConnectorInstances(config).filter((instance) => instance.connectorId === connectorId);\n return c.json({ ok: true, payload: { connector, instances } });\n });\n\n authenticated.post('/api/connectors/approvals/respond', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n return c.json({ ok: true, payload: { acknowledged: true, body } });\n });\n\n authenticated.post('/api/connectors/:id/oauth/start', strictRateLimitMiddleware, async (c) => {\n const connectorId = c.req.param('id');\n const connector = getConnectorDefinition(connectorId);\n if (!connector) {\n return c.json({ ok: false, error: `Unknown connector: ${connectorId}` }, 404);\n }\n try {\n const oauth = await startConnectorOAuth(connector);\n return c.json({ ok: true, payload: { oauth } });\n } catch (error) {\n return c.json({ ok: false, error: errorMessage(error) }, 400);\n }\n });\n\n authenticated.post('/api/connectors/:id/oauth/complete', strictRateLimitMiddleware, async (c) => {\n const connectorId = c.req.param('id');\n const connector = getConnectorDefinition(connectorId);\n if (!connector) {\n return c.json({ ok: false, error: `Unknown connector: ${connectorId}` }, 404);\n }\n const body = await c.req.json().catch(() => ({}));\n const deviceCode = body && typeof body === 'object' && !Array.isArray(body) && typeof body.deviceCode === 'string'\n ? body.deviceCode\n : '';\n try {\n const oauth = await completeConnectorOAuth(connector, { deviceCode });\n return c.json({ ok: true, payload: { oauth } });\n } catch (error) {\n return c.json({ ok: false, error: errorMessage(error) }, 400);\n }\n });\n\n authenticated.post('/api/connectors/:id/install', strictRateLimitMiddleware, async (c) => {\n const connectorId = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n const input: ConnectorInstallInput = body && typeof body === 'object' && !Array.isArray(body) ? body : {};\n const config = service.currentConfig as Config;\n try {\n const instance = await installConnector(config, connectorId, input);\n const saved = await service.saveConfig(config);\n if (!saved.saved) {\n return c.json({ ok: false, error: saved.error }, 500);\n }\n return c.json({ ok: true, payload: { instance } });\n } catch (error) {\n return c.json({ ok: false, error: errorMessage(error) }, 400);\n }\n });\n\n authenticated.post('/api/connectors/:id/test', async (c) => {\n const instanceId = c.req.param('id');\n const config = service.currentConfig as Config;\n const instance = getConnectorInstance(config, instanceId);\n if (!instance) {\n return c.json({ ok: false, error: `Connector instance not found: ${instanceId}` }, 404);\n }\n try {\n const result = await testConnectorInstance(config, instance.materialized.serverId);\n recordConnectorHealthUsage(config, instance.instanceId, result);\n const saved = await service.saveConfig(config);\n if (!saved.saved) {\n return c.json({ ok: false, error: saved.error }, 500);\n }\n return c.json({ ok: true, payload: result });\n } catch (error) {\n return c.json({ ok: false, error: errorMessage(error) }, 500);\n }\n });\n\n authenticated.delete('/api/connectors/:id', strictRateLimitMiddleware, async (c) => {\n const instanceId = c.req.param('id');\n const config = service.currentConfig as Config;\n try {\n const instance = uninstallConnector(config, instanceId);\n const saved = await service.saveConfig(config);\n if (!saved.saved) {\n return c.json({ ok: false, error: saved.error }, 500);\n }\n return c.json({ ok: true, payload: { instance } });\n } catch (error) {\n return c.json({ ok: false, error: errorMessage(error) }, 400);\n }\n });\n}\n"],"mappings":"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"}
|
|
@@ -5,8 +5,8 @@ import { getWorkspacePath } from "../../../config/workspace-path-helpers.js";
|
|
|
5
5
|
import { parseDreamingLastRunFile } from "../../../agent/memory/dreaming/last-run.js";
|
|
6
6
|
import { readDreamingEvents } from "../../../agent/memory/dreaming/events.js";
|
|
7
7
|
import { previewDreamingDeepPromotion } from "../../../agent/memory/dreaming/preview.js";
|
|
8
|
-
import path from "node:path";
|
|
9
8
|
import fs from "node:fs/promises";
|
|
9
|
+
import path from "node:path";
|
|
10
10
|
//#region src/gateway/hono/routes/dreaming.ts
|
|
11
11
|
function isRecord(v) {
|
|
12
12
|
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Hono } from 'hono';
|
|
2
|
+
import type { AuthenticatedRouteDeps } from './deps.js';
|
|
3
|
+
/**
|
|
4
|
+
* GET /api/home — Aggregated home screen data for the mobile app.
|
|
5
|
+
*
|
|
6
|
+
* Returns:
|
|
7
|
+
* - recentlyOpened: notes sorted by lastOpenedAt (continue rail)
|
|
8
|
+
* - inboxCount: number of notes with status === 'inbox'
|
|
9
|
+
* - pendingTasks: task notes where done === false
|
|
10
|
+
* - recentSessions: last 5 active AI sessions (threads)
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerHomeRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/gateway/hono/routes/home.ts
|
|
2
|
+
/**
|
|
3
|
+
* GET /api/home — Aggregated home screen data for the mobile app.
|
|
4
|
+
*
|
|
5
|
+
* Returns:
|
|
6
|
+
* - recentlyOpened: notes sorted by lastOpenedAt (continue rail)
|
|
7
|
+
* - inboxCount: number of notes with status === 'inbox'
|
|
8
|
+
* - pendingTasks: task notes where done === false
|
|
9
|
+
* - recentSessions: last 5 active AI sessions (threads)
|
|
10
|
+
*/
|
|
11
|
+
function registerHomeRoutes(authenticated, deps) {
|
|
12
|
+
const { service } = deps;
|
|
13
|
+
authenticated.get("/api/home", async (c) => {
|
|
14
|
+
const notes = service.notesServiceInstance;
|
|
15
|
+
const sessions = service.sessions;
|
|
16
|
+
const [recentlyOpened, inbox, pendingTasks, recentSessions] = await Promise.all([
|
|
17
|
+
notes.listNotes({
|
|
18
|
+
sortBy: "lastOpenedAt",
|
|
19
|
+
sortOrder: "desc",
|
|
20
|
+
limit: 10
|
|
21
|
+
}),
|
|
22
|
+
notes.listNotes({
|
|
23
|
+
status: "inbox",
|
|
24
|
+
limit: 0
|
|
25
|
+
}),
|
|
26
|
+
notes.listNotes({
|
|
27
|
+
pendingTasksOnly: true,
|
|
28
|
+
sortBy: "createdAt",
|
|
29
|
+
sortOrder: "desc",
|
|
30
|
+
limit: 10
|
|
31
|
+
}),
|
|
32
|
+
sessions.listSessions({
|
|
33
|
+
sortBy: "updatedAt",
|
|
34
|
+
sortOrder: "desc",
|
|
35
|
+
limit: 5
|
|
36
|
+
})
|
|
37
|
+
]);
|
|
38
|
+
return c.json({
|
|
39
|
+
recentlyOpened: recentlyOpened.items.filter((n) => n.lastOpenedAt),
|
|
40
|
+
inboxCount: inbox.total,
|
|
41
|
+
pendingTasks: pendingTasks.items,
|
|
42
|
+
pendingTaskCount: pendingTasks.total,
|
|
43
|
+
recentSessions: recentSessions.items
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { registerHomeRoutes };
|
|
49
|
+
|
|
50
|
+
//# sourceMappingURL=home.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"home.js","names":[],"sources":["../../../../../src/gateway/hono/routes/home.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\n/**\n * GET /api/home — Aggregated home screen data for the mobile app.\n *\n * Returns:\n * - recentlyOpened: notes sorted by lastOpenedAt (continue rail)\n * - inboxCount: number of notes with status === 'inbox'\n * - pendingTasks: task notes where done === false\n * - recentSessions: last 5 active AI sessions (threads)\n */\nexport function registerHomeRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n authenticated.get('/api/home', async (c) => {\n const notes = service.notesServiceInstance;\n const sessions = service.sessions;\n\n const [recentlyOpened, inbox, pendingTasks, recentSessions] = await Promise.all([\n notes.listNotes({ sortBy: 'lastOpenedAt', sortOrder: 'desc', limit: 10 }),\n notes.listNotes({ status: 'inbox', limit: 0 }),\n notes.listNotes({ pendingTasksOnly: true, sortBy: 'createdAt', sortOrder: 'desc', limit: 10 }),\n sessions.listSessions({ sortBy: 'updatedAt', sortOrder: 'desc', limit: 5 }),\n ]);\n\n return c.json({\n recentlyOpened: recentlyOpened.items.filter((n) => n.lastOpenedAt),\n inboxCount: inbox.total,\n pendingTasks: pendingTasks.items,\n pendingTaskCount: pendingTasks.total,\n recentSessions: recentSessions.items,\n });\n });\n}\n"],"mappings":";;;;;;;;;;AAaA,SAAgB,mBAAmB,eAAqB,MAAoC;CAC1F,MAAM,EAAE,YAAY;AAEpB,eAAc,IAAI,aAAa,OAAO,MAAM;EAC1C,MAAM,QAAQ,QAAQ;EACtB,MAAM,WAAW,QAAQ;EAEzB,MAAM,CAAC,gBAAgB,OAAO,cAAc,kBAAkB,MAAM,QAAQ,IAAI;GAC9E,MAAM,UAAU;IAAE,QAAQ;IAAgB,WAAW;IAAQ,OAAO;IAAI,CAAC;GACzE,MAAM,UAAU;IAAE,QAAQ;IAAS,OAAO;IAAG,CAAC;GAC9C,MAAM,UAAU;IAAE,kBAAkB;IAAM,QAAQ;IAAa,WAAW;IAAQ,OAAO;IAAI,CAAC;GAC9F,SAAS,aAAa;IAAE,QAAQ;IAAa,WAAW;IAAQ,OAAO;IAAG,CAAC;GAC5E,CAAC;AAEF,SAAO,EAAE,KAAK;GACZ,gBAAgB,eAAe,MAAM,QAAQ,MAAM,EAAE,aAAa;GAClE,YAAY,MAAM;GAClB,cAAc,aAAa;GAC3B,kBAAkB,aAAa;GAC/B,gBAAgB,eAAe;GAChC,CAAC;GACF"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createLogger } from "../../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../../utils/logger.js";
|
|
3
|
-
import * as os$1 from "node:os";
|
|
4
|
-
import * as path$1 from "node:path";
|
|
5
3
|
import { readdir, realpath, stat } from "node:fs/promises";
|
|
4
|
+
import * as path$1 from "node:path";
|
|
5
|
+
import * as os$1 from "node:os";
|
|
6
6
|
//#region src/gateway/hono/routes/host-fs.ts
|
|
7
7
|
init_logger();
|
|
8
8
|
const log = createLogger("HostFs");
|
|
@@ -134,6 +134,14 @@ const AUTHENTICATED_LAZY_ROUTE_BUNDLES = [
|
|
|
134
134
|
return { register: registerNotesRoutes };
|
|
135
135
|
}
|
|
136
136
|
},
|
|
137
|
+
{
|
|
138
|
+
id: "home",
|
|
139
|
+
match: (path) => startsWithAny(path, ["/api/home"]),
|
|
140
|
+
load: async () => {
|
|
141
|
+
const { registerHomeRoutes } = await import("./home.js");
|
|
142
|
+
return { register: registerHomeRoutes };
|
|
143
|
+
}
|
|
144
|
+
},
|
|
137
145
|
{
|
|
138
146
|
id: "workflows",
|
|
139
147
|
match: (path) => startsWithAny(path, ["/api/workflows"]),
|
|
@@ -207,11 +215,11 @@ const AUTHENTICATED_LAZY_ROUTE_BUNDLES = [
|
|
|
207
215
|
}
|
|
208
216
|
},
|
|
209
217
|
{
|
|
210
|
-
id: "
|
|
211
|
-
match: (path) => startsWithAny(path, ["/api/
|
|
218
|
+
id: "connectors",
|
|
219
|
+
match: (path) => startsWithAny(path, ["/api/connectors"]),
|
|
212
220
|
load: async () => {
|
|
213
|
-
const {
|
|
214
|
-
return { register:
|
|
221
|
+
const { registerConnectorRoutes } = await import("./connectors.js");
|
|
222
|
+
return { register: registerConnectorRoutes };
|
|
215
223
|
}
|
|
216
224
|
}
|
|
217
225
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy-bundles.js","names":[],"sources":["../../../../../src/gateway/hono/routes/lazy-bundles.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport type { GatewayService } from '../../service.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nexport type AuthenticatedLazyRouteBundle = {\n id: string;\n match: (path: string) => boolean;\n load: () => Promise<{ register: (authenticated: Hono, deps: AuthenticatedRouteDeps) => void }>;\n};\n\nexport type AppLazyRouteBundle = {\n id: string;\n prefixes: readonly string[];\n match: (path: string) => boolean;\n load: () => Promise<{\n registerOnApp: (app: Hono, service: GatewayService) => void;\n }>;\n};\n\nfunction startsWithAny(path: string, prefixes: readonly string[]): boolean {\n return prefixes.some((prefix) => path === prefix || path.startsWith(`${prefix}/`));\n}\n\nexport const AUTHENTICATED_LAZY_ROUTE_BUNDLES: readonly AuthenticatedLazyRouteBundle[] = [\n {\n id: 'workspace',\n match: (path) => startsWithAny(path, ['/api/workspace']),\n load: async () => {\n const { registerWorkspaceRoutes } = await import('./workspace.js');\n return { register: registerWorkspaceRoutes };\n },\n },\n {\n id: 'host-fs',\n match: (path) => startsWithAny(path, ['/api/host/fs']),\n load: async () => {\n const { registerHostFsRoutes } = await import('./host-fs.js');\n return { register: registerHostFsRoutes };\n },\n },\n {\n id: 'channels',\n match: (path) => startsWithAny(path, ['/api/channels']),\n load: async () => {\n const { registerChannelRoutes } = await import('./channels.js');\n return { register: registerChannelRoutes };\n },\n },\n {\n id: 'browser-install',\n match: (path) =>\n path === '/api/browser/playwright/install/stream' ||\n path === '/api/browser/cloakbrowser/install/stream',\n load: async () => {\n const { registerBrowserInstallRoutes } = await import('./browser-install.js');\n return { register: registerBrowserInstallRoutes };\n },\n },\n {\n id: 'browser',\n // `browser-install` above already matched the SSE install streams; this\n // catches the remaining /api/browser/* handlers (extension, cdp,\n // cloakbrowser doctor/launch/install, playwright doctor/install, cloud).\n match: (path) => startsWithAny(path, ['/api/browser']),\n load: async () => {\n const { registerBrowserRoutes } = await import('./browser.js');\n return { register: registerBrowserRoutes };\n },\n },\n {\n id: 'config',\n match: (path) =>\n startsWithAny(path, ['/api/config', '/api/heartbeat/trigger']),\n load: async () => {\n const { registerConfigRoutes } = await import('./config.js');\n return { register: registerConfigRoutes };\n },\n },\n {\n id: 'doctor',\n match: (path) => startsWithAny(path, ['/api/doctor']),\n load: async () => {\n const { registerDoctorRoutes } = await import('./doctor.js');\n return { register: registerDoctorRoutes };\n },\n },\n {\n id: 'dreaming',\n match: (path) => startsWithAny(path, ['/api/dreaming']),\n load: async () => {\n const { registerDreamingRoutes } = await import('./dreaming.js');\n return { register: registerDreamingRoutes };\n },\n },\n {\n id: 'agents',\n match: (path) => startsWithAny(path, ['/api/agents', '/api/voice/models']),\n load: async () => {\n const { registerAgentsRoutes } = await import('./agents.js');\n return { register: registerAgentsRoutes };\n },\n },\n {\n id: 'auth-registry-extensions',\n match: (path) =>\n startsWithAny(path, [\n '/api/auth',\n '/api/registry',\n '/api/extensions',\n '/api/context',\n '/api/marketplace',\n ]),\n load: async () => {\n const { registerAuthRegistryExtensionsRoutes } = await import('./auth-registry-extensions.js');\n return { register: registerAuthRegistryExtensionsRoutes };\n },\n },\n {\n id: 'models',\n match: (path) =>\n startsWithAny(path, ['/api/models', '/api/models-json', '/api/providers', '/api/image']),\n load: async () => {\n const { registerModelsRoutes } = await import('./models.js');\n return { register: registerModelsRoutes };\n },\n },\n {\n id: 'commands-skills',\n match: (path) => startsWithAny(path, ['/api/commands', '/api/skills']),\n load: async () => {\n const { registerCommandsSkillsRoutes } = await import('./commands-skills.js');\n return { register: registerCommandsSkillsRoutes };\n },\n },\n {\n id: 'cron',\n match: (path) => startsWithAny(path, ['/api/cron']),\n load: async () => {\n const { registerCronRoutes } = await import('./cron.js');\n return { register: registerCronRoutes };\n },\n },\n {\n id: 'goals',\n match: (path) => startsWithAny(path, ['/api/goals']),\n load: async () => {\n const { registerGoalsRoutes } = await import('./goals.js');\n return { register: registerGoalsRoutes };\n },\n },\n {\n id: 'notes',\n match: (path) => startsWithAny(path, ['/api/notes']),\n load: async () => {\n const { registerNotesRoutes } = await import('./notes.js');\n return { register: registerNotesRoutes };\n },\n },\n {\n id: 'workflows',\n match: (path) => startsWithAny(path, ['/api/workflows']),\n load: async () => {\n const { registerWorkflowRoutes } = await import('./workflows.js');\n return { register: registerWorkflowRoutes };\n },\n },\n {\n id: 'logs',\n match: (path) => startsWithAny(path, ['/api/logs']),\n load: async () => {\n const { registerLogsRoutes } = await import('./logs.js');\n return { register: registerLogsRoutes };\n },\n },\n {\n id: 'shares',\n match: (path) => startsWithAny(path, ['/api/shares']),\n load: async () => {\n const { registerShareRoutes } = await import('./shares.js');\n return { register: registerShareRoutes };\n },\n },\n {\n id: 'site-shares',\n match: (path) => startsWithAny(path, ['/api/site-shares']),\n load: async () => {\n const { registerSiteShareRoutes } = await import('./site-shares.js');\n return { register: registerSiteShareRoutes };\n },\n },\n {\n id: 'tunnel',\n match: (path) => startsWithAny(path, ['/api/tunnel']),\n load: async () => {\n const { registerTunnelRoutes } = await import('./tunnel.js');\n return { register: registerTunnelRoutes };\n },\n },\n {\n id: 'exposure',\n match: (path) => startsWithAny(path, ['/api/exposure']),\n load: async () => {\n const { registerExposureRoutes } = await import('./exposure.js');\n return { register: registerExposureRoutes };\n },\n },\n {\n id: 'extension-gateway',\n match: (path) => startsWithAny(path, ['/api/gateway']),\n load: async () => {\n const { registerExtensionGatewayRoutes } = await import('./extension-gateway.js');\n return { register: registerExtensionGatewayRoutes };\n },\n },\n {\n id: 'update',\n match: (path) => startsWithAny(path, ['/api/update']),\n load: async () => {\n const { registerUpdateRoutes } = await import('./update.js');\n return { register: registerUpdateRoutes };\n },\n },\n {\n id: 'voice',\n match: (path) => startsWithAny(path, ['/api/voice']) && path !== '/api/voice/models',\n load: async () => {\n const { registerVoiceRoutes } = await import('./voice.js');\n return { register: registerVoiceRoutes };\n },\n },\n {\n id: 'mcp',\n match: (path) => startsWithAny(path, ['/api/mcp']),\n load: async () => {\n const { registerMcpRoutes } = await import('./mcp.js');\n return { register: registerMcpRoutes };\n },\n },\n];\n\nexport const APP_LAZY_ROUTE_BUNDLES: readonly AppLazyRouteBundle[] = [\n {\n id: 'shares-public',\n prefixes: ['/s'],\n match: (path) => startsWithAny(path, ['/s']),\n load: async () => {\n const { registerSharePublicRoutes } = await import('./shares.js');\n return { registerOnApp: registerSharePublicRoutes };\n },\n },\n {\n id: 'tunnel-public',\n prefixes: [\n '/api/tunnel/pair/ping',\n '/api/tunnel/pair/validate-url',\n '/api/tunnel/exchange-token',\n ],\n match: (path) =>\n path === '/api/tunnel/exchange-token' ||\n path === '/api/tunnel/pair/ping' ||\n path === '/api/tunnel/pair/validate-url',\n load: async () => {\n const { registerTunnelPublicRoutes } = await import('./tunnel.js');\n return { registerOnApp: registerTunnelPublicRoutes };\n },\n },\n];\n\nexport function findAuthenticatedLazyRouteBundle(path: string): AuthenticatedLazyRouteBundle | undefined {\n return AUTHENTICATED_LAZY_ROUTE_BUNDLES.find((bundle) => bundle.match(path));\n}\n"],"mappings":";AAoBA,SAAS,cAAc,MAAc,UAAsC;AACzE,QAAO,SAAS,MAAM,WAAW,SAAS,UAAU,KAAK,WAAW,GAAG,OAAO,GAAG,CAAC;;AAGpF,MAAa,mCAA4E;CACvF;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,iBAAiB,CAAC;EACxD,MAAM,YAAY;GAChB,MAAM,EAAE,4BAA4B,MAAM,OAAO;AACjD,UAAO,EAAE,UAAU,yBAAyB;;EAE/C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,eAAe,CAAC;EACtD,MAAM,YAAY;GAChB,MAAM,EAAE,yBAAyB,MAAM,OAAO;AAC9C,UAAO,EAAE,UAAU,sBAAsB;;EAE5C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,gBAAgB,CAAC;EACvD,MAAM,YAAY;GAChB,MAAM,EAAE,0BAA0B,MAAM,OAAO;AAC/C,UAAO,EAAE,UAAU,uBAAuB;;EAE7C;CACD;EACE,IAAI;EACJ,QAAQ,SACN,SAAS,4CACT,SAAS;EACX,MAAM,YAAY;GAChB,MAAM,EAAE,iCAAiC,MAAM,OAAO;AACtD,UAAO,EAAE,UAAU,8BAA8B;;EAEpD;CACD;EACE,IAAI;EAIJ,QAAQ,SAAS,cAAc,MAAM,CAAC,eAAe,CAAC;EACtD,MAAM,YAAY;GAChB,MAAM,EAAE,0BAA0B,MAAM,OAAO;AAC/C,UAAO,EAAE,UAAU,uBAAuB;;EAE7C;CACD;EACE,IAAI;EACJ,QAAQ,SACN,cAAc,MAAM,CAAC,eAAe,yBAAyB,CAAC;EAChE,MAAM,YAAY;GAChB,MAAM,EAAE,yBAAyB,MAAM,OAAO;AAC9C,UAAO,EAAE,UAAU,sBAAsB;;EAE5C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,cAAc,CAAC;EACrD,MAAM,YAAY;GAChB,MAAM,EAAE,yBAAyB,MAAM,OAAO;AAC9C,UAAO,EAAE,UAAU,sBAAsB;;EAE5C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,gBAAgB,CAAC;EACvD,MAAM,YAAY;GAChB,MAAM,EAAE,2BAA2B,MAAM,OAAO;AAChD,UAAO,EAAE,UAAU,wBAAwB;;EAE9C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,eAAe,oBAAoB,CAAC;EAC1E,MAAM,YAAY;GAChB,MAAM,EAAE,yBAAyB,MAAM,OAAO;AAC9C,UAAO,EAAE,UAAU,sBAAsB;;EAE5C;CACD;EACE,IAAI;EACJ,QAAQ,SACN,cAAc,MAAM;GAClB;GACA;GACA;GACA;GACA;GACD,CAAC;EACJ,MAAM,YAAY;GAChB,MAAM,EAAE,yCAAyC,MAAM,OAAO;AAC9D,UAAO,EAAE,UAAU,sCAAsC;;EAE5D;CACD;EACE,IAAI;EACJ,QAAQ,SACN,cAAc,MAAM;GAAC;GAAe;GAAoB;GAAkB;GAAa,CAAC;EAC1F,MAAM,YAAY;GAChB,MAAM,EAAE,yBAAyB,MAAM,OAAO;AAC9C,UAAO,EAAE,UAAU,sBAAsB;;EAE5C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,iBAAiB,cAAc,CAAC;EACtE,MAAM,YAAY;GAChB,MAAM,EAAE,iCAAiC,MAAM,OAAO;AACtD,UAAO,EAAE,UAAU,8BAA8B;;EAEpD;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,YAAY,CAAC;EACnD,MAAM,YAAY;GAChB,MAAM,EAAE,uBAAuB,MAAM,OAAO;AAC5C,UAAO,EAAE,UAAU,oBAAoB;;EAE1C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,aAAa,CAAC;EACpD,MAAM,YAAY;GAChB,MAAM,EAAE,wBAAwB,MAAM,OAAO;AAC7C,UAAO,EAAE,UAAU,qBAAqB;;EAE3C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,aAAa,CAAC;EACpD,MAAM,YAAY;GAChB,MAAM,EAAE,wBAAwB,MAAM,OAAO;AAC7C,UAAO,EAAE,UAAU,qBAAqB;;EAE3C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,iBAAiB,CAAC;EACxD,MAAM,YAAY;GAChB,MAAM,EAAE,2BAA2B,MAAM,OAAO;AAChD,UAAO,EAAE,UAAU,wBAAwB;;EAE9C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,YAAY,CAAC;EACnD,MAAM,YAAY;GAChB,MAAM,EAAE,uBAAuB,MAAM,OAAO;AAC5C,UAAO,EAAE,UAAU,oBAAoB;;EAE1C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,cAAc,CAAC;EACrD,MAAM,YAAY;GAChB,MAAM,EAAE,wBAAwB,MAAM,OAAO;AAC7C,UAAO,EAAE,UAAU,qBAAqB;;EAE3C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,mBAAmB,CAAC;EAC1D,MAAM,YAAY;GAChB,MAAM,EAAE,4BAA4B,MAAM,OAAO;AACjD,UAAO,EAAE,UAAU,yBAAyB;;EAE/C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,cAAc,CAAC;EACrD,MAAM,YAAY;GAChB,MAAM,EAAE,yBAAyB,MAAM,OAAO;AAC9C,UAAO,EAAE,UAAU,sBAAsB;;EAE5C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,gBAAgB,CAAC;EACvD,MAAM,YAAY;GAChB,MAAM,EAAE,2BAA2B,MAAM,OAAO;AAChD,UAAO,EAAE,UAAU,wBAAwB;;EAE9C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,eAAe,CAAC;EACtD,MAAM,YAAY;GAChB,MAAM,EAAE,mCAAmC,MAAM,OAAO;AACxD,UAAO,EAAE,UAAU,gCAAgC;;EAEtD;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,cAAc,CAAC;EACrD,MAAM,YAAY;GAChB,MAAM,EAAE,yBAAyB,MAAM,OAAO;AAC9C,UAAO,EAAE,UAAU,sBAAsB;;EAE5C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,aAAa,CAAC,IAAI,SAAS;EACjE,MAAM,YAAY;GAChB,MAAM,EAAE,wBAAwB,MAAM,OAAO;AAC7C,UAAO,EAAE,UAAU,qBAAqB;;EAE3C;CACD;EACE,IAAI;EACJ,QAAQ,SAAS,cAAc,MAAM,CAAC,WAAW,CAAC;EAClD,MAAM,YAAY;GAChB,MAAM,EAAE,sBAAsB,MAAM,OAAO;AAC3C,UAAO,EAAE,UAAU,mBAAmB;;EAEzC;CACF;AAED,MAAa,yBAAwD,CACnE;CACE,IAAI;CACJ,UAAU,CAAC,KAAK;CAChB,QAAQ,SAAS,cAAc,MAAM,CAAC,KAAK,CAAC;CAC5C,MAAM,YAAY;EAChB,MAAM,EAAE,8BAA8B,MAAM,OAAO;AACnD,SAAO,EAAE,eAAe,2BAA2B;;CAEtD,EACD;CACE,IAAI;CACJ,UAAU;EACR;EACA;EACA;EACD;CACD,QAAQ,SACN,SAAS,gCACT,SAAS,2BACT,SAAS;CACX,MAAM,YAAY;EAChB,MAAM,EAAE,+BAA+B,MAAM,OAAO;AACpD,SAAO,EAAE,eAAe,4BAA4B;;CAEvD,CACF;AAED,SAAgB,iCAAiC,MAAwD;AACvG,QAAO,iCAAiC,MAAM,WAAW,OAAO,MAAM,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"lazy-bundles.js","names":[],"sources":["../../../../../src/gateway/hono/routes/lazy-bundles.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport type { GatewayService } from '../../service.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nexport type AuthenticatedLazyRouteBundle = {\n id: string;\n match: (path: string) => boolean;\n load: () => Promise<{ register: (authenticated: Hono, deps: AuthenticatedRouteDeps) => void }>;\n};\n\nexport type AppLazyRouteBundle = {\n id: string;\n prefixes: readonly string[];\n match: (path: string) => boolean;\n load: () => Promise<{\n registerOnApp: (app: Hono, service: GatewayService) => void;\n }>;\n};\n\nfunction startsWithAny(path: string, prefixes: readonly string[]): boolean {\n return prefixes.some((prefix) => path === prefix || path.startsWith(`${prefix}/`));\n}\n\nexport const AUTHENTICATED_LAZY_ROUTE_BUNDLES: readonly AuthenticatedLazyRouteBundle[] = [\n {\n id: 'workspace',\n match: (path) => startsWithAny(path, ['/api/workspace']),\n load: async () => {\n const { registerWorkspaceRoutes } = await import('./workspace.js');\n return { register: registerWorkspaceRoutes };\n },\n },\n {\n id: 'host-fs',\n match: (path) => startsWithAny(path, ['/api/host/fs']),\n load: async () => {\n const { registerHostFsRoutes } = await import('./host-fs.js');\n return { register: registerHostFsRoutes };\n },\n },\n {\n id: 'channels',\n match: (path) => startsWithAny(path, ['/api/channels']),\n load: async () => {\n const { registerChannelRoutes } = await import('./channels.js');\n return { register: registerChannelRoutes };\n },\n },\n {\n id: 'browser-install',\n match: (path) =>\n path === '/api/browser/playwright/install/stream' ||\n path === '/api/browser/cloakbrowser/install/stream',\n load: async () => {\n const { registerBrowserInstallRoutes } = await import('./browser-install.js');\n return { register: registerBrowserInstallRoutes };\n },\n },\n {\n id: 'browser',\n // `browser-install` above already matched the SSE install streams; this\n // catches the remaining /api/browser/* handlers (extension, cdp,\n // cloakbrowser doctor/launch/install, playwright doctor/install, cloud).\n match: (path) => startsWithAny(path, ['/api/browser']),\n load: async () => {\n const { registerBrowserRoutes } = await import('./browser.js');\n return { register: registerBrowserRoutes };\n },\n },\n {\n id: 'config',\n match: (path) =>\n startsWithAny(path, ['/api/config', '/api/heartbeat/trigger']),\n load: async () => {\n const { registerConfigRoutes } = await import('./config.js');\n return { register: registerConfigRoutes };\n },\n },\n {\n id: 'doctor',\n match: (path) => startsWithAny(path, ['/api/doctor']),\n load: async () => {\n const { registerDoctorRoutes } = await import('./doctor.js');\n return { register: registerDoctorRoutes };\n },\n },\n {\n id: 'dreaming',\n match: (path) => startsWithAny(path, ['/api/dreaming']),\n load: async () => {\n const { registerDreamingRoutes } = await import('./dreaming.js');\n return { register: registerDreamingRoutes };\n },\n },\n {\n id: 'agents',\n match: (path) => startsWithAny(path, ['/api/agents', '/api/voice/models']),\n load: async () => {\n const { registerAgentsRoutes } = await import('./agents.js');\n return { register: registerAgentsRoutes };\n },\n },\n {\n id: 'auth-registry-extensions',\n match: (path) =>\n startsWithAny(path, [\n '/api/auth',\n '/api/registry',\n '/api/extensions',\n '/api/context',\n '/api/marketplace',\n ]),\n load: async () => {\n const { registerAuthRegistryExtensionsRoutes } = await import('./auth-registry-extensions.js');\n return { register: registerAuthRegistryExtensionsRoutes };\n },\n },\n {\n id: 'models',\n match: (path) =>\n startsWithAny(path, ['/api/models', '/api/models-json', '/api/providers', '/api/image']),\n load: async () => {\n const { registerModelsRoutes } = await import('./models.js');\n return { register: registerModelsRoutes };\n },\n },\n {\n id: 'commands-skills',\n match: (path) => startsWithAny(path, ['/api/commands', '/api/skills']),\n load: async () => {\n const { registerCommandsSkillsRoutes } = await import('./commands-skills.js');\n return { register: registerCommandsSkillsRoutes };\n },\n },\n {\n id: 'cron',\n match: (path) => startsWithAny(path, ['/api/cron']),\n load: async () => {\n const { registerCronRoutes } = await import('./cron.js');\n return { register: registerCronRoutes };\n },\n },\n {\n id: 'goals',\n match: (path) => startsWithAny(path, ['/api/goals']),\n load: async () => {\n const { registerGoalsRoutes } = await import('./goals.js');\n return { register: registerGoalsRoutes };\n },\n },\n {\n id: 'notes',\n match: (path) => startsWithAny(path, ['/api/notes']),\n load: async () => {\n const { registerNotesRoutes } = await import('./notes.js');\n return { register: registerNotesRoutes };\n },\n },\n {\n id: 'home',\n match: (path) => startsWithAny(path, ['/api/home']),\n load: async () => {\n const { registerHomeRoutes } = await import('./home.js');\n return { register: registerHomeRoutes };\n },\n },\n {\n id: 'workflows',\n match: (path) => startsWithAny(path, ['/api/workflows']),\n load: async () => {\n const { registerWorkflowRoutes } = await import('./workflows.js');\n return { register: registerWorkflowRoutes };\n },\n },\n {\n id: 'logs',\n match: (path) => startsWithAny(path, ['/api/logs']),\n load: async () => {\n const { registerLogsRoutes } = await import('./logs.js');\n return { register: registerLogsRoutes };\n },\n },\n {\n id: 'shares',\n match: (path) => startsWithAny(path, ['/api/shares']),\n load: async () => {\n const { registerShareRoutes } = await import('./shares.js');\n return { register: registerShareRoutes };\n },\n },\n {\n id: 'site-shares',\n match: (path) => startsWithAny(path, ['/api/site-shares']),\n load: async () => {\n const { registerSiteShareRoutes } = await import('./site-shares.js');\n return { register: registerSiteShareRoutes };\n },\n },\n {\n id: 'tunnel',\n match: (path) => startsWithAny(path, ['/api/tunnel']),\n load: async () => {\n const { registerTunnelRoutes } = await import('./tunnel.js');\n return { register: registerTunnelRoutes };\n },\n },\n {\n id: 'exposure',\n match: (path) => startsWithAny(path, ['/api/exposure']),\n load: async () => {\n const { registerExposureRoutes } = await import('./exposure.js');\n return { register: registerExposureRoutes };\n },\n },\n {\n id: 'extension-gateway',\n match: (path) => startsWithAny(path, ['/api/gateway']),\n load: async () => {\n const { registerExtensionGatewayRoutes } = await import('./extension-gateway.js');\n return { register: registerExtensionGatewayRoutes };\n },\n },\n {\n id: 'update',\n match: (path) => startsWithAny(path, ['/api/update']),\n load: async () => {\n const { registerUpdateRoutes } = await import('./update.js');\n return { register: registerUpdateRoutes };\n },\n },\n {\n id: 'voice',\n match: (path) => startsWithAny(path, ['/api/voice']) && path !== '/api/voice/models',\n load: async () => {\n const { registerVoiceRoutes } = await import('./voice.js');\n return { register: registerVoiceRoutes };\n },\n },\n {\n id: 'connectors',\n match: (path) => startsWithAny(path, ['/api/connectors']),\n load: async () => {\n const { registerConnectorRoutes } = await import('./connectors.js');\n return { register: registerConnectorRoutes };\n },\n },\n];\n\nexport const APP_LAZY_ROUTE_BUNDLES: readonly AppLazyRouteBundle[] = [\n {\n id: 'shares-public',\n prefixes: ['/s'],\n match: (path) => startsWithAny(path, ['/s']),\n load: async () => {\n const { registerSharePublicRoutes } = await import('./shares.js');\n return { registerOnApp: registerSharePublicRoutes };\n },\n },\n {\n id: 'tunnel-public',\n prefixes: [\n '/api/tunnel/pair/ping',\n '/api/tunnel/pair/validate-url',\n '/api/tunnel/exchange-token',\n ],\n match: (path) =>\n path === '/api/tunnel/exchange-token' ||\n path === '/api/tunnel/pair/ping' ||\n path === '/api/tunnel/pair/validate-url',\n load: async () => {\n const { registerTunnelPublicRoutes } = await import('./tunnel.js');\n return { registerOnApp: registerTunnelPublicRoutes };\n },\n },\n];\n\nexport function findAuthenticatedLazyRouteBundle(path: string): AuthenticatedLazyRouteBundle | undefined {\n return AUTHENTICATED_LAZY_ROUTE_BUNDLES.find((bundle) => bundle.match(path));\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { resolveModelsJsonPath } from "../../../config/paths.js";
|
|
2
|
+
import { CredentialResolver, init_credentials } from "../../../auth/credentials.js";
|
|
2
3
|
import { init_resolve_config_value, testApiKeyResolution } from "../../../config/resolve-config-value.js";
|
|
3
4
|
import { init_models_json, loadModelsJson, saveModelsJson, validateModelsConfig } from "../../../config/models-json.js";
|
|
4
5
|
import { getModelRegistry } from "../../../providers/model-registry.js";
|
|
5
|
-
import { CredentialResolver, init_credentials } from "../../../auth/credentials.js";
|
|
6
6
|
import { getProviderRegistry, init_plugin_registry } from "../../../providers/plugin-registry.js";
|
|
7
7
|
import { PROVIDER_META, getAllModels, getAllProviders, getAvailableModels, getProviderAuthState, init_providers, isProviderConfigured } from "../../../providers/index.js";
|
|
8
8
|
import { getImageGenerationProvider } from "../../../agent/image/generation/provider-registry.js";
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
+
import { buildSessionKey, init_session_key } from "../../../routing/session-key.js";
|
|
2
|
+
import { agentExists, getDefaultAgentId, init_resolve_route } from "../../../routing/resolve-route.js";
|
|
1
3
|
import { createReadStream } from "node:fs";
|
|
2
4
|
import { access, stat } from "node:fs/promises";
|
|
3
5
|
import { Readable } from "node:stream";
|
|
4
6
|
import { stream } from "hono/streaming";
|
|
5
7
|
//#region src/gateway/hono/routes/notes.ts
|
|
8
|
+
init_session_key();
|
|
9
|
+
init_resolve_route();
|
|
6
10
|
const VALID_KINDS = new Set([
|
|
7
11
|
"thought",
|
|
8
12
|
"todo",
|
|
9
13
|
"voice",
|
|
10
14
|
"media",
|
|
11
15
|
"bookmark",
|
|
12
|
-
"mixed"
|
|
16
|
+
"mixed",
|
|
17
|
+
"task"
|
|
13
18
|
]);
|
|
14
19
|
const VALID_STATUSES = new Set([
|
|
15
20
|
"inbox",
|
|
@@ -56,6 +61,18 @@ function buildNotePatch(body) {
|
|
|
56
61
|
if (body.aiDeep && typeof body.aiDeep === "object") patch.aiDeep = body.aiDeep;
|
|
57
62
|
return patch;
|
|
58
63
|
}
|
|
64
|
+
function buildNoteThreadContext(note) {
|
|
65
|
+
const title = note.title?.trim() || "未命名笔记";
|
|
66
|
+
const body = note.text?.trim() || "这条笔记暂无正文。";
|
|
67
|
+
return [
|
|
68
|
+
`来源 Note:${title}`,
|
|
69
|
+
"",
|
|
70
|
+
body
|
|
71
|
+
].join("\n");
|
|
72
|
+
}
|
|
73
|
+
function noteThreadName(note) {
|
|
74
|
+
return `讨论:${note.title?.trim() || note.text?.trim()?.slice(0, 28) || "未命名笔记"}`;
|
|
75
|
+
}
|
|
59
76
|
function registerNotesRoutes(authenticated, deps) {
|
|
60
77
|
const { service } = deps;
|
|
61
78
|
authenticated.post("/api/notes/quick-capture", async (c) => {
|
|
@@ -164,6 +181,93 @@ function registerNotesRoutes(authenticated, deps) {
|
|
|
164
181
|
note: result.note
|
|
165
182
|
});
|
|
166
183
|
});
|
|
184
|
+
authenticated.post("/api/notes/:id/catalyze", async (c) => {
|
|
185
|
+
const result = await service.notesServiceInstance.catalyzeNote(c.req.param("id"), service.currentConfig);
|
|
186
|
+
if (!result) return c.json({ error: "Note not found" }, 404);
|
|
187
|
+
return c.json(result);
|
|
188
|
+
});
|
|
189
|
+
authenticated.post("/api/notes/:id/catalysis-feedback", async (c) => {
|
|
190
|
+
const feedback = (await c.req.json().catch(() => ({}))).feedback;
|
|
191
|
+
if (feedback !== "helpful" && feedback !== "not_helpful" && feedback !== "neutral") return c.json({ error: "Invalid feedback" }, 400);
|
|
192
|
+
const note = await service.notesServiceInstance.recordCatalysisFeedback(c.req.param("id"), feedback);
|
|
193
|
+
if (!note) return c.json({ error: "Note not found" }, 404);
|
|
194
|
+
return c.json({ note });
|
|
195
|
+
});
|
|
196
|
+
authenticated.post("/api/notes/:id/chat", async (c) => {
|
|
197
|
+
const noteId = c.req.param("id");
|
|
198
|
+
const note = await service.notesServiceInstance.getNote(noteId);
|
|
199
|
+
if (!note) return c.json({ error: "Note not found" }, 404);
|
|
200
|
+
const body = await c.req.json().catch(() => ({}));
|
|
201
|
+
const routingCfg = service.currentConfig;
|
|
202
|
+
let agentId = typeof body.agentId === "string" && body.agentId.trim() ? body.agentId.trim().toLowerCase() : getDefaultAgentId(routingCfg);
|
|
203
|
+
if (!agentExists(agentId, routingCfg)) agentId = getDefaultAgentId(routingCfg);
|
|
204
|
+
const existingKey = note.aiDeep?.catalysis?.sourceSessionKey;
|
|
205
|
+
if (existingKey) {
|
|
206
|
+
const existingSession = await service.sessions.getSession(existingKey);
|
|
207
|
+
if (existingSession) return c.json({
|
|
208
|
+
session: existingSession,
|
|
209
|
+
sessionKey: existingKey,
|
|
210
|
+
reused: true
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
const sessionKey = buildSessionKey({
|
|
214
|
+
agentId,
|
|
215
|
+
source: "webchat",
|
|
216
|
+
accountId: "default",
|
|
217
|
+
peerKind: "direct",
|
|
218
|
+
peerId: `note_${noteId}_${Date.now()}`
|
|
219
|
+
});
|
|
220
|
+
await service.sessionIndexInstance.saveMessages(sessionKey, []);
|
|
221
|
+
await service.sessionIndexInstance.appendTranscriptContextEntry(sessionKey, {
|
|
222
|
+
id: `source-note:${noteId}`,
|
|
223
|
+
text: buildNoteThreadContext(note),
|
|
224
|
+
data: {
|
|
225
|
+
kind: "source_note",
|
|
226
|
+
noteId,
|
|
227
|
+
title: note.title ?? ""
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
const meta = await service.sessionIndexInstance.getSessionMetadata(sessionKey);
|
|
231
|
+
await service.sessionIndexInstance.updateSessionMetadata(sessionKey, {
|
|
232
|
+
name: noteThreadName(note),
|
|
233
|
+
tags: Array.from(new Set([...meta?.tags ?? [], "note"])),
|
|
234
|
+
customData: {
|
|
235
|
+
...meta?.customData ?? {},
|
|
236
|
+
sourceNoteId: noteId,
|
|
237
|
+
sourceNoteTitle: note.title ?? ""
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
await service.notesServiceInstance.linkNoteThread(noteId, sessionKey);
|
|
241
|
+
const session = await service.sessions.getSession(sessionKey);
|
|
242
|
+
return c.json({
|
|
243
|
+
session,
|
|
244
|
+
sessionKey,
|
|
245
|
+
reused: false
|
|
246
|
+
}, 201);
|
|
247
|
+
});
|
|
248
|
+
authenticated.get("/api/notes/:id/threads", async (c) => {
|
|
249
|
+
const noteId = c.req.param("id");
|
|
250
|
+
const keys = await service.notesServiceInstance.listNoteThreads(noteId);
|
|
251
|
+
if (!keys) return c.json({ error: "Note not found" }, 404);
|
|
252
|
+
const sessions = [];
|
|
253
|
+
for (const key of keys) {
|
|
254
|
+
const session = await service.sessions.getSession(key);
|
|
255
|
+
if (session) sessions.push(session);
|
|
256
|
+
}
|
|
257
|
+
return c.json({
|
|
258
|
+
items: sessions,
|
|
259
|
+
total: sessions.length
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
authenticated.post("/api/notes/:id/append", async (c) => {
|
|
263
|
+
const body = await c.req.json().catch(() => ({}));
|
|
264
|
+
const content = typeof body.content === "string" ? body.content.trim() : "";
|
|
265
|
+
const heading = typeof body.heading === "string" && body.heading.trim() ? body.heading.trim() : void 0;
|
|
266
|
+
if (!content) return c.json({ error: "Missing required field: content" }, 400);
|
|
267
|
+
const note = await service.notesServiceInstance.appendTextToNote(c.req.param("id"), content, heading);
|
|
268
|
+
if (!note) return c.json({ error: "Note not found" }, 404);
|
|
269
|
+
return c.json({ note });
|
|
270
|
+
});
|
|
167
271
|
authenticated.get("/api/notes/:id", async (c) => {
|
|
168
272
|
const id = c.req.param("id");
|
|
169
273
|
const note = await service.notesServiceInstance.getNote(id);
|
|
@@ -267,6 +371,37 @@ function registerNotesRoutes(authenticated, deps) {
|
|
|
267
371
|
await s.pipe(readable);
|
|
268
372
|
});
|
|
269
373
|
});
|
|
374
|
+
authenticated.post("/api/notes/task", async (c) => {
|
|
375
|
+
const body = await c.req.json().catch(() => ({}));
|
|
376
|
+
const title = typeof body.title === "string" ? body.title.trim() : "";
|
|
377
|
+
if (!title) return c.json({ error: "Missing required field: title" }, 400);
|
|
378
|
+
const source = parseCaptureSource(body);
|
|
379
|
+
const note = await service.notesServiceInstance.createTask(title, source, {
|
|
380
|
+
dueAt: typeof body.dueAt === "number" ? body.dueAt : void 0,
|
|
381
|
+
priority: body.priority === "high" || body.priority === "medium" || body.priority === "low" ? body.priority : void 0,
|
|
382
|
+
sourceSessionKey: typeof body.sourceSessionKey === "string" ? body.sourceSessionKey : void 0,
|
|
383
|
+
sourceNoteId: typeof body.sourceNoteId === "string" ? body.sourceNoteId : void 0,
|
|
384
|
+
groupId: typeof body.groupId === "string" ? body.groupId : void 0
|
|
385
|
+
});
|
|
386
|
+
return c.json({ note }, 201);
|
|
387
|
+
});
|
|
388
|
+
authenticated.post("/api/notes/:id/toggle-done", async (c) => {
|
|
389
|
+
const note = await service.notesServiceInstance.toggleTaskDone(c.req.param("id"));
|
|
390
|
+
if (!note) return c.json({ error: "Not found or not a task" }, 404);
|
|
391
|
+
return c.json({ note });
|
|
392
|
+
});
|
|
393
|
+
authenticated.post("/api/notes/:id/open", async (c) => {
|
|
394
|
+
const note = await service.notesServiceInstance.recordOpen(c.req.param("id"));
|
|
395
|
+
if (!note) return c.json({ error: "Not found" }, 404);
|
|
396
|
+
return c.json({ note });
|
|
397
|
+
});
|
|
398
|
+
authenticated.post("/api/notes/:id/move", async (c) => {
|
|
399
|
+
const body = await c.req.json().catch(() => ({}));
|
|
400
|
+
const groupId = typeof body.groupId === "string" ? body.groupId : null;
|
|
401
|
+
const note = await service.notesServiceInstance.moveToGroup(c.req.param("id"), groupId);
|
|
402
|
+
if (!note) return c.json({ error: "Not found" }, 404);
|
|
403
|
+
return c.json({ note });
|
|
404
|
+
});
|
|
270
405
|
}
|
|
271
406
|
//#endregion
|
|
272
407
|
export { registerNotesRoutes };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notes.js","names":[],"sources":["../../../../../src/gateway/hono/routes/notes.ts"],"sourcesContent":["import { createReadStream } from 'node:fs';\nimport { access, stat } from 'node:fs/promises';\nimport { Readable } from 'node:stream';\n\nimport type { Hono } from 'hono';\nimport { stream } from 'hono/streaming';\n\nimport type { CaptureChannel, CaptureSource, Note, NoteBlock, NoteKind, NoteStatus, SnapshotTrigger } from '../../../notes/types.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nconst VALID_KINDS = new Set<NoteKind>(['thought', 'todo', 'voice', 'media', 'bookmark', 'mixed']);\nconst VALID_STATUSES = new Set<NoteStatus>(['inbox', 'processed', 'archived', 'trashed']);\nconst VALID_CHANNELS = new Set<CaptureChannel>(['app', 'web', 'electron', 'tui', 'telegram', 'wechat', 'feishu']);\n\nfunction parseCaptureSource(body: Record<string, unknown>): CaptureSource {\n const channel = typeof body.channel === 'string' && VALID_CHANNELS.has(body.channel as CaptureChannel)\n ? (body.channel as CaptureChannel)\n : 'web';\n const platform = body.platform === 'ios' || body.platform === 'android' ? body.platform : undefined;\n return { channel, platform };\n}\n\nfunction parseBlocks(value: unknown): NoteBlock[] | undefined {\n if (!Array.isArray(value)) return undefined;\n return value.filter((block): block is NoteBlock => {\n if (!block || typeof block !== 'object') return false;\n const candidate = block as Record<string, unknown>;\n if (typeof candidate.id !== 'string' || typeof candidate.type !== 'string') return false;\n if (candidate.type === 'image') {\n return typeof candidate.attachmentId === 'string';\n }\n return true;\n });\n}\n\nfunction buildNotePatch(body: Record<string, unknown>): Partial<Note> {\n const patch: Partial<Note> = {};\n if (typeof body.title === 'string') patch.title = body.title;\n if (typeof body.text === 'string') patch.text = body.text;\n if (Array.isArray(body.blocks)) patch.blocks = parseBlocks(body.blocks);\n if (typeof body.kind === 'string' && VALID_KINDS.has(body.kind as NoteKind)) patch.kind = body.kind as NoteKind;\n if (typeof body.status === 'string' && VALID_STATUSES.has(body.status as NoteStatus)) patch.status = body.status as NoteStatus;\n if (Array.isArray(body.tags)) patch.tags = body.tags.filter((tag): tag is string => typeof tag === 'string');\n if (typeof body.pinned === 'boolean') patch.pinned = body.pinned;\n if (typeof body.localVersion === 'number') patch.localVersion = body.localVersion;\n if (body.ai && typeof body.ai === 'object') patch.ai = body.ai as Note['ai'];\n if (body.aiDeep && typeof body.aiDeep === 'object') patch.aiDeep = body.aiDeep as Note['aiDeep'];\n return patch;\n}\n\nexport function registerNotesRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // POST /api/notes/quick-capture — minimal text capture\n authenticated.post('/api/notes/quick-capture', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const text = typeof body.text === 'string' ? body.text.trim() : '';\n if (!text) {\n return c.json({ error: 'Missing required field: text' }, 400);\n }\n const source = parseCaptureSource(body);\n const note = await service.notesServiceInstance.quickCapture(text, source);\n return c.json({ note }, 201);\n });\n\n // GET /api/notes — list with filters\n authenticated.get('/api/notes', async (c) => {\n const status = c.req.query('status') as NoteStatus | undefined;\n const kind = c.req.query('kind') as NoteKind | undefined;\n const tag = c.req.query('tag');\n const search = c.req.query('search');\n const pinnedRaw = c.req.query('pinned');\n const limitRaw = c.req.query('limit');\n const offsetRaw = c.req.query('offset');\n const sortBy = c.req.query('sortBy') as 'createdAt' | 'updatedAt' | undefined;\n const sortOrder = c.req.query('sortOrder') as 'asc' | 'desc' | undefined;\n\n const result = await service.notesServiceInstance.listNotes({\n status: status && VALID_STATUSES.has(status) ? status : undefined,\n kind: kind && VALID_KINDS.has(kind) ? kind : undefined,\n tag: tag || undefined,\n search: search || undefined,\n pinned: pinnedRaw === 'true' ? true : pinnedRaw === 'false' ? false : undefined,\n limit: limitRaw ? parseInt(limitRaw, 10) : undefined,\n offset: offsetRaw ? parseInt(offsetRaw, 10) : undefined,\n sortBy: sortBy === 'createdAt' || sortBy === 'updatedAt' ? sortBy : undefined,\n sortOrder: sortOrder === 'asc' || sortOrder === 'desc' ? sortOrder : undefined,\n });\n return c.json(result);\n });\n\n // POST /api/notes — full create (JSON or multipart)\n authenticated.post('/api/notes', async (c) => {\n const contentType = c.req.header('content-type') || '';\n\n if (contentType.includes('multipart/form-data')) {\n let body: Record<string, unknown>;\n try {\n body = await c.req.parseBody({ all: true });\n } catch {\n return c.json({ error: 'Invalid multipart body' }, 400);\n }\n\n const text = typeof body.text === 'string' ? body.text.trim() : undefined;\n const kindRaw = typeof body.kind === 'string' ? body.kind : undefined;\n const tagsRaw = typeof body.tags === 'string' ? body.tags : undefined;\n const source = parseCaptureSource(body as Record<string, unknown>);\n\n const note = await service.notesServiceInstance.createNote({\n text,\n kind: kindRaw && VALID_KINDS.has(kindRaw as NoteKind) ? (kindRaw as NoteKind) : undefined,\n tags: tagsRaw ? tagsRaw.split(',').map((t) => t.trim()).filter(Boolean) : undefined,\n capturedVia: source,\n });\n\n const file = body.file;\n if (file && typeof file === 'object') {\n let buf: Buffer | null = null;\n let fileName = 'upload';\n let mimeType = 'application/octet-stream';\n\n if (file instanceof File) {\n buf = Buffer.from(await file.arrayBuffer());\n fileName = file.name || fileName;\n mimeType = file.type || mimeType;\n } else if (typeof (file as Blob).arrayBuffer === 'function') {\n buf = Buffer.from(await (file as Blob).arrayBuffer());\n }\n\n if (buf) {\n const durationRaw = body.duration;\n const duration =\n typeof durationRaw === 'string'\n ? parseInt(durationRaw, 10)\n : typeof durationRaw === 'number'\n ? durationRaw\n : undefined;\n await service.notesServiceInstance.addAttachment(note.id, {\n name: fileName,\n buffer: buf,\n mimeType,\n duration: Number.isFinite(duration) ? duration : undefined,\n });\n }\n }\n\n const full = await service.notesServiceInstance.getNote(note.id);\n return c.json({ note: full }, 201);\n }\n\n // JSON body\n const body = await c.req.json().catch(() => ({}));\n const text = typeof body.text === 'string' ? body.text.trim() : undefined;\n const blocks = parseBlocks(body.blocks);\n const kindRaw = typeof body.kind === 'string' ? body.kind : undefined;\n const tagsRaw = Array.isArray(body.tags) ? body.tags.filter((t: unknown) => typeof t === 'string') : undefined;\n const source = parseCaptureSource(body);\n\n const note = await service.notesServiceInstance.createNote({\n text,\n blocks,\n kind: kindRaw && VALID_KINDS.has(kindRaw as NoteKind) ? (kindRaw as NoteKind) : undefined,\n tags: tagsRaw,\n capturedVia: source,\n pinned: body.pinned === true,\n });\n return c.json({ note }, 201);\n });\n\n // POST /api/notes/sync — local-first block sync with optimistic conflict check\n authenticated.post('/api/notes/sync', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const noteId = typeof body.noteId === 'string' ? body.noteId : '';\n if (!noteId) {\n return c.json({ error: 'Missing required field: noteId' }, 400);\n }\n\n const baseRemoteVersion = typeof body.baseRemoteVersion === 'number' ? body.baseRemoteVersion : undefined;\n const patch = buildNotePatch(body);\n const result = await service.notesServiceInstance.syncNote(noteId, patch, baseRemoteVersion);\n if (!result.note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n if (result.conflict) {\n return c.json({ conflict: true, note: result.note }, 409);\n }\n return c.json({ conflict: false, note: result.note });\n });\n\n // GET /api/notes/:id — single note\n authenticated.get('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const note = await service.notesServiceInstance.getNote(id);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // PATCH /api/notes/:id — update\n authenticated.patch('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n\n const patch = buildNotePatch(body);\n const trigger: SnapshotTrigger =\n body.trigger === 'ai_edit' || body.trigger === 'sync' || body.trigger === 'restore'\n ? body.trigger\n : 'edit';\n\n const updated = await service.notesServiceInstance.updateNote(id, patch, trigger);\n if (!updated) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note: updated });\n });\n\n // DELETE /api/notes/:id — delete note\n authenticated.delete('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const removed = await service.notesServiceInstance.deleteNote(id);\n if (!removed) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ deleted: true });\n });\n\n // GET /api/notes/:id/history — list version snapshots\n authenticated.get('/api/notes/:id/history', async (c) => {\n const id = c.req.param('id');\n const entries = await service.notesServiceInstance.listNoteHistory(id);\n return c.json({ entries });\n });\n\n // GET /api/notes/:id/history/:timestamp — get full snapshot\n authenticated.get('/api/notes/:id/history/:timestamp', async (c) => {\n const id = c.req.param('id');\n const timestamp = parseInt(c.req.param('timestamp'), 10);\n if (!Number.isFinite(timestamp)) {\n return c.json({ error: 'Invalid timestamp' }, 400);\n }\n const snapshot = await service.notesServiceInstance.getNoteSnapshot(id, timestamp);\n if (!snapshot) {\n return c.json({ error: 'Snapshot not found' }, 404);\n }\n return c.json({ snapshot });\n });\n\n // POST /api/notes/:id/history/restore — restore a snapshot\n authenticated.post('/api/notes/:id/history/restore', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n const timestamp = typeof body.timestamp === 'number' ? body.timestamp : 0;\n if (!timestamp) {\n return c.json({ error: 'Missing required field: timestamp' }, 400);\n }\n const note = await service.notesServiceInstance.restoreNoteSnapshot(id, timestamp);\n if (!note) {\n return c.json({ error: 'Snapshot or note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // POST /api/notes/:id/ai/edit — generate previewable block-level AI patch\n authenticated.post('/api/notes/:id/ai/edit', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n const instruction = typeof body.instruction === 'string' ? body.instruction.trim() : '';\n if (!instruction) {\n return c.json({ error: 'Missing required field: instruction' }, 400);\n }\n\n const blocks = parseBlocks(body.blocks);\n const result = await service.notesServiceInstance.createAiEditPatch(id, instruction, blocks);\n if (!result) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json(result);\n });\n\n // POST /api/notes/:id/media — upload attachment to existing note\n authenticated.post('/api/notes/:id/media', async (c) => {\n const noteId = c.req.param('id');\n let body: Record<string, unknown>;\n try {\n body = await c.req.parseBody({ all: true });\n } catch {\n return c.json({ error: 'Invalid multipart body' }, 400);\n }\n\n const file = body.file;\n if (!file || typeof file !== 'object') {\n return c.json({ error: 'Missing file field' }, 400);\n }\n\n let buf: Buffer;\n let fileName = 'upload';\n let mimeType = 'application/octet-stream';\n\n if (file instanceof File) {\n buf = Buffer.from(await file.arrayBuffer());\n fileName = file.name || fileName;\n mimeType = file.type || mimeType;\n } else if (typeof (file as Blob).arrayBuffer === 'function') {\n buf = Buffer.from(await (file as Blob).arrayBuffer());\n } else {\n return c.json({ error: 'Invalid file upload' }, 400);\n }\n\n const durationRaw = body.duration;\n const duration = typeof durationRaw === 'string' ? parseInt(durationRaw, 10) : undefined;\n\n const attachment = await service.notesServiceInstance.addAttachment(noteId, {\n name: fileName,\n buffer: buf,\n mimeType,\n duration: Number.isFinite(duration) ? duration : undefined,\n });\n\n if (!attachment) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ attachment }, 201);\n });\n\n // GET /api/notes/:id/media/:attachmentId — serve attachment file\n authenticated.get('/api/notes/:id/media/:attachmentId', async (c) => {\n const noteId = c.req.param('id');\n const attachmentId = c.req.param('attachmentId');\n\n const result = await service.notesServiceInstance.getAttachmentPath(noteId, attachmentId);\n if (!result) {\n return c.json({ error: 'Attachment not found' }, 404);\n }\n\n const { filePath, mimeType, fileName } = result;\n\n try {\n await access(filePath);\n } catch {\n return c.json({ error: 'Attachment file missing' }, 404);\n }\n\n const fileStat = await stat(filePath);\n\n c.header('Content-Type', mimeType);\n c.header('Content-Length', String(fileStat.size));\n c.header('Content-Disposition', `inline; filename=\"${encodeURIComponent(fileName)}\"`);\n c.header('Cache-Control', 'private, max-age=31536000, immutable');\n\n return stream(c, async (s) => {\n const readable = Readable.toWeb(createReadStream(filePath)) as ReadableStream<Uint8Array>;\n await s.pipe(readable);\n });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"notes.js","names":[],"sources":["../../../../../src/gateway/hono/routes/notes.ts"],"sourcesContent":["import { createReadStream } from 'node:fs';\nimport { access, stat } from 'node:fs/promises';\nimport { Readable } from 'node:stream';\n\nimport type { Hono } from 'hono';\nimport { stream } from 'hono/streaming';\n\nimport { buildSessionKey } from '../../../routing/session-key.js';\nimport { agentExists, getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { CaptureChannel, CaptureSource, Note, NoteBlock, NoteKind, NoteStatus, SnapshotTrigger } from '../../../notes/types.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nconst VALID_KINDS = new Set<NoteKind>(['thought', 'todo', 'voice', 'media', 'bookmark', 'mixed', 'task']);\nconst VALID_STATUSES = new Set<NoteStatus>(['inbox', 'processed', 'archived', 'trashed']);\nconst VALID_CHANNELS = new Set<CaptureChannel>(['app', 'web', 'electron', 'tui', 'telegram', 'wechat', 'feishu']);\n\nfunction parseCaptureSource(body: Record<string, unknown>): CaptureSource {\n const channel = typeof body.channel === 'string' && VALID_CHANNELS.has(body.channel as CaptureChannel)\n ? (body.channel as CaptureChannel)\n : 'web';\n const platform = body.platform === 'ios' || body.platform === 'android' ? body.platform : undefined;\n return { channel, platform };\n}\n\nfunction parseBlocks(value: unknown): NoteBlock[] | undefined {\n if (!Array.isArray(value)) return undefined;\n return value.filter((block): block is NoteBlock => {\n if (!block || typeof block !== 'object') return false;\n const candidate = block as Record<string, unknown>;\n if (typeof candidate.id !== 'string' || typeof candidate.type !== 'string') return false;\n if (candidate.type === 'image') {\n return typeof candidate.attachmentId === 'string';\n }\n return true;\n });\n}\n\nfunction buildNotePatch(body: Record<string, unknown>): Partial<Note> {\n const patch: Partial<Note> = {};\n if (typeof body.title === 'string') patch.title = body.title;\n if (typeof body.text === 'string') patch.text = body.text;\n if (Array.isArray(body.blocks)) patch.blocks = parseBlocks(body.blocks);\n if (typeof body.kind === 'string' && VALID_KINDS.has(body.kind as NoteKind)) patch.kind = body.kind as NoteKind;\n if (typeof body.status === 'string' && VALID_STATUSES.has(body.status as NoteStatus)) patch.status = body.status as NoteStatus;\n if (Array.isArray(body.tags)) patch.tags = body.tags.filter((tag): tag is string => typeof tag === 'string');\n if (typeof body.pinned === 'boolean') patch.pinned = body.pinned;\n if (typeof body.localVersion === 'number') patch.localVersion = body.localVersion;\n if (body.ai && typeof body.ai === 'object') patch.ai = body.ai as Note['ai'];\n if (body.aiDeep && typeof body.aiDeep === 'object') patch.aiDeep = body.aiDeep as Note['aiDeep'];\n return patch;\n}\n\nfunction buildNoteThreadContext(note: Note): string {\n const title = note.title?.trim() || '未命名笔记';\n const body = note.text?.trim() || '这条笔记暂无正文。';\n return [`来源 Note:${title}`, '', body].join('\\n');\n}\n\nfunction noteThreadName(note: Note): string {\n const title = note.title?.trim() || note.text?.trim()?.slice(0, 28) || '未命名笔记';\n return `讨论:${title}`;\n}\n\nexport function registerNotesRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // POST /api/notes/quick-capture — minimal text capture\n authenticated.post('/api/notes/quick-capture', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const text = typeof body.text === 'string' ? body.text.trim() : '';\n if (!text) {\n return c.json({ error: 'Missing required field: text' }, 400);\n }\n const source = parseCaptureSource(body);\n const note = await service.notesServiceInstance.quickCapture(text, source);\n return c.json({ note }, 201);\n });\n\n // GET /api/notes — list with filters\n authenticated.get('/api/notes', async (c) => {\n const status = c.req.query('status') as NoteStatus | undefined;\n const kind = c.req.query('kind') as NoteKind | undefined;\n const tag = c.req.query('tag');\n const search = c.req.query('search');\n const pinnedRaw = c.req.query('pinned');\n const limitRaw = c.req.query('limit');\n const offsetRaw = c.req.query('offset');\n const sortBy = c.req.query('sortBy') as 'createdAt' | 'updatedAt' | undefined;\n const sortOrder = c.req.query('sortOrder') as 'asc' | 'desc' | undefined;\n\n const result = await service.notesServiceInstance.listNotes({\n status: status && VALID_STATUSES.has(status) ? status : undefined,\n kind: kind && VALID_KINDS.has(kind) ? kind : undefined,\n tag: tag || undefined,\n search: search || undefined,\n pinned: pinnedRaw === 'true' ? true : pinnedRaw === 'false' ? false : undefined,\n limit: limitRaw ? parseInt(limitRaw, 10) : undefined,\n offset: offsetRaw ? parseInt(offsetRaw, 10) : undefined,\n sortBy: sortBy === 'createdAt' || sortBy === 'updatedAt' ? sortBy : undefined,\n sortOrder: sortOrder === 'asc' || sortOrder === 'desc' ? sortOrder : undefined,\n });\n return c.json(result);\n });\n\n // POST /api/notes — full create (JSON or multipart)\n authenticated.post('/api/notes', async (c) => {\n const contentType = c.req.header('content-type') || '';\n\n if (contentType.includes('multipart/form-data')) {\n let body: Record<string, unknown>;\n try {\n body = await c.req.parseBody({ all: true });\n } catch {\n return c.json({ error: 'Invalid multipart body' }, 400);\n }\n\n const text = typeof body.text === 'string' ? body.text.trim() : undefined;\n const kindRaw = typeof body.kind === 'string' ? body.kind : undefined;\n const tagsRaw = typeof body.tags === 'string' ? body.tags : undefined;\n const source = parseCaptureSource(body as Record<string, unknown>);\n\n const note = await service.notesServiceInstance.createNote({\n text,\n kind: kindRaw && VALID_KINDS.has(kindRaw as NoteKind) ? (kindRaw as NoteKind) : undefined,\n tags: tagsRaw ? tagsRaw.split(',').map((t) => t.trim()).filter(Boolean) : undefined,\n capturedVia: source,\n });\n\n const file = body.file;\n if (file && typeof file === 'object') {\n let buf: Buffer | null = null;\n let fileName = 'upload';\n let mimeType = 'application/octet-stream';\n\n if (file instanceof File) {\n buf = Buffer.from(await file.arrayBuffer());\n fileName = file.name || fileName;\n mimeType = file.type || mimeType;\n } else if (typeof (file as Blob).arrayBuffer === 'function') {\n buf = Buffer.from(await (file as Blob).arrayBuffer());\n }\n\n if (buf) {\n const durationRaw = body.duration;\n const duration =\n typeof durationRaw === 'string'\n ? parseInt(durationRaw, 10)\n : typeof durationRaw === 'number'\n ? durationRaw\n : undefined;\n await service.notesServiceInstance.addAttachment(note.id, {\n name: fileName,\n buffer: buf,\n mimeType,\n duration: Number.isFinite(duration) ? duration : undefined,\n });\n }\n }\n\n const full = await service.notesServiceInstance.getNote(note.id);\n return c.json({ note: full }, 201);\n }\n\n // JSON body\n const body = await c.req.json().catch(() => ({}));\n const text = typeof body.text === 'string' ? body.text.trim() : undefined;\n const blocks = parseBlocks(body.blocks);\n const kindRaw = typeof body.kind === 'string' ? body.kind : undefined;\n const tagsRaw = Array.isArray(body.tags) ? body.tags.filter((t: unknown) => typeof t === 'string') : undefined;\n const source = parseCaptureSource(body);\n\n const note = await service.notesServiceInstance.createNote({\n text,\n blocks,\n kind: kindRaw && VALID_KINDS.has(kindRaw as NoteKind) ? (kindRaw as NoteKind) : undefined,\n tags: tagsRaw,\n capturedVia: source,\n pinned: body.pinned === true,\n });\n return c.json({ note }, 201);\n });\n\n // POST /api/notes/sync — local-first block sync with optimistic conflict check\n authenticated.post('/api/notes/sync', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const noteId = typeof body.noteId === 'string' ? body.noteId : '';\n if (!noteId) {\n return c.json({ error: 'Missing required field: noteId' }, 400);\n }\n\n const baseRemoteVersion = typeof body.baseRemoteVersion === 'number' ? body.baseRemoteVersion : undefined;\n const patch = buildNotePatch(body);\n const result = await service.notesServiceInstance.syncNote(noteId, patch, baseRemoteVersion);\n if (!result.note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n if (result.conflict) {\n return c.json({ conflict: true, note: result.note }, 409);\n }\n return c.json({ conflict: false, note: result.note });\n });\n\n // POST /api/notes/:id/catalyze — generate an AI catalysis report and write it back\n authenticated.post('/api/notes/:id/catalyze', async (c) => {\n const result = await service.notesServiceInstance.catalyzeNote(c.req.param('id'), service.currentConfig);\n if (!result) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json(result);\n });\n\n // POST /api/notes/:id/catalysis-feedback — record whether the catalysis was useful\n authenticated.post('/api/notes/:id/catalysis-feedback', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const feedback = body.feedback;\n if (feedback !== 'helpful' && feedback !== 'not_helpful' && feedback !== 'neutral') {\n return c.json({ error: 'Invalid feedback' }, 400);\n }\n const note = await service.notesServiceInstance.recordCatalysisFeedback(c.req.param('id'), feedback);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // POST /api/notes/:id/chat — create or reuse a note-bound web chat thread\n authenticated.post('/api/notes/:id/chat', async (c) => {\n const noteId = c.req.param('id');\n const note = await service.notesServiceInstance.getNote(noteId);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n\n const body = await c.req.json().catch(() => ({}));\n const routingCfg = service.currentConfig;\n let agentId =\n typeof body.agentId === 'string' && body.agentId.trim()\n ? body.agentId.trim().toLowerCase()\n : getDefaultAgentId(routingCfg);\n if (!agentExists(agentId, routingCfg)) {\n agentId = getDefaultAgentId(routingCfg);\n }\n\n const existingKey = note.aiDeep?.catalysis?.sourceSessionKey;\n if (existingKey) {\n const existingSession = await service.sessions.getSession(existingKey);\n if (existingSession) {\n return c.json({ session: existingSession, sessionKey: existingKey, reused: true });\n }\n }\n\n const sessionKey = buildSessionKey({\n agentId,\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: `note_${noteId}_${Date.now()}`,\n });\n\n await service.sessionIndexInstance.saveMessages(sessionKey, []);\n await service.sessionIndexInstance.appendTranscriptContextEntry(sessionKey, {\n id: `source-note:${noteId}`,\n text: buildNoteThreadContext(note),\n data: {\n kind: 'source_note',\n noteId,\n title: note.title ?? '',\n },\n });\n\n const meta = await service.sessionIndexInstance.getSessionMetadata(sessionKey);\n await service.sessionIndexInstance.updateSessionMetadata(sessionKey, {\n name: noteThreadName(note),\n tags: Array.from(new Set([...(meta?.tags ?? []), 'note'])),\n customData: {\n ...(meta?.customData ?? {}),\n sourceNoteId: noteId,\n sourceNoteTitle: note.title ?? '',\n },\n });\n\n await service.notesServiceInstance.linkNoteThread(noteId, sessionKey);\n const session = await service.sessions.getSession(sessionKey);\n return c.json({ session, sessionKey, reused: false }, 201);\n });\n\n // GET /api/notes/:id/threads — list chat threads linked to a note\n authenticated.get('/api/notes/:id/threads', async (c) => {\n const noteId = c.req.param('id');\n const keys = await service.notesServiceInstance.listNoteThreads(noteId);\n if (!keys) {\n return c.json({ error: 'Note not found' }, 404);\n }\n const sessions = [];\n for (const key of keys) {\n const session = await service.sessions.getSession(key);\n if (session) sessions.push(session);\n }\n return c.json({ items: sessions, total: sessions.length });\n });\n\n // POST /api/notes/:id/append — append assistant output or selected text back to the note\n authenticated.post('/api/notes/:id/append', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const content = typeof body.content === 'string' ? body.content.trim() : '';\n const heading = typeof body.heading === 'string' && body.heading.trim() ? body.heading.trim() : undefined;\n if (!content) {\n return c.json({ error: 'Missing required field: content' }, 400);\n }\n const note = await service.notesServiceInstance.appendTextToNote(c.req.param('id'), content, heading);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // GET /api/notes/:id — single note\n authenticated.get('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const note = await service.notesServiceInstance.getNote(id);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // PATCH /api/notes/:id — update\n authenticated.patch('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n\n const patch = buildNotePatch(body);\n const trigger: SnapshotTrigger =\n body.trigger === 'ai_edit' || body.trigger === 'sync' || body.trigger === 'restore'\n ? body.trigger\n : 'edit';\n\n const updated = await service.notesServiceInstance.updateNote(id, patch, trigger);\n if (!updated) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note: updated });\n });\n\n // DELETE /api/notes/:id — delete note\n authenticated.delete('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const removed = await service.notesServiceInstance.deleteNote(id);\n if (!removed) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ deleted: true });\n });\n\n // GET /api/notes/:id/history — list version snapshots\n authenticated.get('/api/notes/:id/history', async (c) => {\n const id = c.req.param('id');\n const entries = await service.notesServiceInstance.listNoteHistory(id);\n return c.json({ entries });\n });\n\n // GET /api/notes/:id/history/:timestamp — get full snapshot\n authenticated.get('/api/notes/:id/history/:timestamp', async (c) => {\n const id = c.req.param('id');\n const timestamp = parseInt(c.req.param('timestamp'), 10);\n if (!Number.isFinite(timestamp)) {\n return c.json({ error: 'Invalid timestamp' }, 400);\n }\n const snapshot = await service.notesServiceInstance.getNoteSnapshot(id, timestamp);\n if (!snapshot) {\n return c.json({ error: 'Snapshot not found' }, 404);\n }\n return c.json({ snapshot });\n });\n\n // POST /api/notes/:id/history/restore — restore a snapshot\n authenticated.post('/api/notes/:id/history/restore', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n const timestamp = typeof body.timestamp === 'number' ? body.timestamp : 0;\n if (!timestamp) {\n return c.json({ error: 'Missing required field: timestamp' }, 400);\n }\n const note = await service.notesServiceInstance.restoreNoteSnapshot(id, timestamp);\n if (!note) {\n return c.json({ error: 'Snapshot or note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // POST /api/notes/:id/ai/edit — generate previewable block-level AI patch\n authenticated.post('/api/notes/:id/ai/edit', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n const instruction = typeof body.instruction === 'string' ? body.instruction.trim() : '';\n if (!instruction) {\n return c.json({ error: 'Missing required field: instruction' }, 400);\n }\n\n const blocks = parseBlocks(body.blocks);\n const result = await service.notesServiceInstance.createAiEditPatch(id, instruction, blocks);\n if (!result) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json(result);\n });\n\n // POST /api/notes/:id/media — upload attachment to existing note\n authenticated.post('/api/notes/:id/media', async (c) => {\n const noteId = c.req.param('id');\n let body: Record<string, unknown>;\n try {\n body = await c.req.parseBody({ all: true });\n } catch {\n return c.json({ error: 'Invalid multipart body' }, 400);\n }\n\n const file = body.file;\n if (!file || typeof file !== 'object') {\n return c.json({ error: 'Missing file field' }, 400);\n }\n\n let buf: Buffer;\n let fileName = 'upload';\n let mimeType = 'application/octet-stream';\n\n if (file instanceof File) {\n buf = Buffer.from(await file.arrayBuffer());\n fileName = file.name || fileName;\n mimeType = file.type || mimeType;\n } else if (typeof (file as Blob).arrayBuffer === 'function') {\n buf = Buffer.from(await (file as Blob).arrayBuffer());\n } else {\n return c.json({ error: 'Invalid file upload' }, 400);\n }\n\n const durationRaw = body.duration;\n const duration = typeof durationRaw === 'string' ? parseInt(durationRaw, 10) : undefined;\n\n const attachment = await service.notesServiceInstance.addAttachment(noteId, {\n name: fileName,\n buffer: buf,\n mimeType,\n duration: Number.isFinite(duration) ? duration : undefined,\n });\n\n if (!attachment) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ attachment }, 201);\n });\n\n // GET /api/notes/:id/media/:attachmentId — serve attachment file\n authenticated.get('/api/notes/:id/media/:attachmentId', async (c) => {\n const noteId = c.req.param('id');\n const attachmentId = c.req.param('attachmentId');\n\n const result = await service.notesServiceInstance.getAttachmentPath(noteId, attachmentId);\n if (!result) {\n return c.json({ error: 'Attachment not found' }, 404);\n }\n\n const { filePath, mimeType, fileName } = result;\n\n try {\n await access(filePath);\n } catch {\n return c.json({ error: 'Attachment file missing' }, 404);\n }\n\n const fileStat = await stat(filePath);\n\n c.header('Content-Type', mimeType);\n c.header('Content-Length', String(fileStat.size));\n c.header('Content-Disposition', `inline; filename=\"${encodeURIComponent(fileName)}\"`);\n c.header('Cache-Control', 'private, max-age=31536000, immutable');\n\n return stream(c, async (s) => {\n const readable = Readable.toWeb(createReadStream(filePath)) as ReadableStream<Uint8Array>;\n await s.pipe(readable);\n });\n });\n\n // ── Task / Space / Open tracking ────────────────────────────────────\n\n authenticated.post('/api/notes/task', async (c) => {\n const body = await c.req.json().catch(() => ({})) as Record<string, unknown>;\n const title = typeof body.title === 'string' ? body.title.trim() : '';\n if (!title) return c.json({ error: 'Missing required field: title' }, 400);\n\n const source = parseCaptureSource(body);\n const note = await service.notesServiceInstance.createTask(title, source, {\n dueAt: typeof body.dueAt === 'number' ? body.dueAt : undefined,\n priority: body.priority === 'high' || body.priority === 'medium' || body.priority === 'low' ? body.priority : undefined,\n sourceSessionKey: typeof body.sourceSessionKey === 'string' ? body.sourceSessionKey : undefined,\n sourceNoteId: typeof body.sourceNoteId === 'string' ? body.sourceNoteId : undefined,\n groupId: typeof body.groupId === 'string' ? body.groupId : undefined,\n });\n return c.json({ note }, 201);\n });\n\n authenticated.post('/api/notes/:id/toggle-done', async (c) => {\n const note = await service.notesServiceInstance.toggleTaskDone(c.req.param('id'));\n if (!note) return c.json({ error: 'Not found or not a task' }, 404);\n return c.json({ note });\n });\n\n authenticated.post('/api/notes/:id/open', async (c) => {\n const note = await service.notesServiceInstance.recordOpen(c.req.param('id'));\n if (!note) return c.json({ error: 'Not found' }, 404);\n return c.json({ note });\n });\n\n authenticated.post('/api/notes/:id/move', async (c) => {\n const body = await c.req.json().catch(() => ({})) as Record<string, unknown>;\n const groupId = typeof body.groupId === 'string' ? body.groupId : null;\n const note = await service.notesServiceInstance.moveToGroup(c.req.param('id'), groupId);\n if (!note) return c.json({ error: 'Not found' }, 404);\n return c.json({ note });\n });\n}\n"],"mappings":";;;;;;;kBAOkE;oBACiB;AAInF,MAAM,cAAc,IAAI,IAAc;CAAC;CAAW;CAAQ;CAAS;CAAS;CAAY;CAAS;CAAO,CAAC;AACzG,MAAM,iBAAiB,IAAI,IAAgB;CAAC;CAAS;CAAa;CAAY;CAAU,CAAC;AACzF,MAAM,iBAAiB,IAAI,IAAoB;CAAC;CAAO;CAAO;CAAY;CAAO;CAAY;CAAU;CAAS,CAAC;AAEjH,SAAS,mBAAmB,MAA8C;AAKxE,QAAO;EAAE,SAJO,OAAO,KAAK,YAAY,YAAY,eAAe,IAAI,KAAK,QAA0B,GACjG,KAAK,UACN;EAEc,UADD,KAAK,aAAa,SAAS,KAAK,aAAa,YAAY,KAAK,WAAW,KAAA;EAC9D;;AAG9B,SAAS,YAAY,OAAyC;AAC5D,KAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO,KAAA;AAClC,QAAO,MAAM,QAAQ,UAA8B;AACjD,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;EAChD,MAAM,YAAY;AAClB,MAAI,OAAO,UAAU,OAAO,YAAY,OAAO,UAAU,SAAS,SAAU,QAAO;AACnF,MAAI,UAAU,SAAS,QACrB,QAAO,OAAO,UAAU,iBAAiB;AAE3C,SAAO;GACP;;AAGJ,SAAS,eAAe,MAA8C;CACpE,MAAM,QAAuB,EAAE;AAC/B,KAAI,OAAO,KAAK,UAAU,SAAU,OAAM,QAAQ,KAAK;AACvD,KAAI,OAAO,KAAK,SAAS,SAAU,OAAM,OAAO,KAAK;AACrD,KAAI,MAAM,QAAQ,KAAK,OAAO,CAAE,OAAM,SAAS,YAAY,KAAK,OAAO;AACvE,KAAI,OAAO,KAAK,SAAS,YAAY,YAAY,IAAI,KAAK,KAAiB,CAAE,OAAM,OAAO,KAAK;AAC/F,KAAI,OAAO,KAAK,WAAW,YAAY,eAAe,IAAI,KAAK,OAAqB,CAAE,OAAM,SAAS,KAAK;AAC1G,KAAI,MAAM,QAAQ,KAAK,KAAK,CAAE,OAAM,OAAO,KAAK,KAAK,QAAQ,QAAuB,OAAO,QAAQ,SAAS;AAC5G,KAAI,OAAO,KAAK,WAAW,UAAW,OAAM,SAAS,KAAK;AAC1D,KAAI,OAAO,KAAK,iBAAiB,SAAU,OAAM,eAAe,KAAK;AACrE,KAAI,KAAK,MAAM,OAAO,KAAK,OAAO,SAAU,OAAM,KAAK,KAAK;AAC5D,KAAI,KAAK,UAAU,OAAO,KAAK,WAAW,SAAU,OAAM,SAAS,KAAK;AACxE,QAAO;;AAGT,SAAS,uBAAuB,MAAoB;CAClD,MAAM,QAAQ,KAAK,OAAO,MAAM,IAAI;CACpC,MAAM,OAAO,KAAK,MAAM,MAAM,IAAI;AAClC,QAAO;EAAC,WAAW;EAAS;EAAI;EAAK,CAAC,KAAK,KAAK;;AAGlD,SAAS,eAAe,MAAoB;AAE1C,QAAO,MADO,KAAK,OAAO,MAAM,IAAI,KAAK,MAAM,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI;;AAIzE,SAAgB,oBAAoB,eAAqB,MAAoC;CAC3F,MAAM,EAAE,YAAY;AAGpB,eAAc,KAAK,4BAA4B,OAAO,MAAM;EAC1D,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,KAAK,MAAM,GAAG;AAChE,MAAI,CAAC,KACH,QAAO,EAAE,KAAK,EAAE,OAAO,gCAAgC,EAAE,IAAI;EAE/D,MAAM,SAAS,mBAAmB,KAAK;EACvC,MAAM,OAAO,MAAM,QAAQ,qBAAqB,aAAa,MAAM,OAAO;AAC1E,SAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI;GAC5B;AAGF,eAAc,IAAI,cAAc,OAAO,MAAM;EAC3C,MAAM,SAAS,EAAE,IAAI,MAAM,SAAS;EACpC,MAAM,OAAO,EAAE,IAAI,MAAM,OAAO;EAChC,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,SAAS,EAAE,IAAI,MAAM,SAAS;EACpC,MAAM,YAAY,EAAE,IAAI,MAAM,SAAS;EACvC,MAAM,WAAW,EAAE,IAAI,MAAM,QAAQ;EACrC,MAAM,YAAY,EAAE,IAAI,MAAM,SAAS;EACvC,MAAM,SAAS,EAAE,IAAI,MAAM,SAAS;EACpC,MAAM,YAAY,EAAE,IAAI,MAAM,YAAY;EAE1C,MAAM,SAAS,MAAM,QAAQ,qBAAqB,UAAU;GAC1D,QAAQ,UAAU,eAAe,IAAI,OAAO,GAAG,SAAS,KAAA;GACxD,MAAM,QAAQ,YAAY,IAAI,KAAK,GAAG,OAAO,KAAA;GAC7C,KAAK,OAAO,KAAA;GACZ,QAAQ,UAAU,KAAA;GAClB,QAAQ,cAAc,SAAS,OAAO,cAAc,UAAU,QAAQ,KAAA;GACtE,OAAO,WAAW,SAAS,UAAU,GAAG,GAAG,KAAA;GAC3C,QAAQ,YAAY,SAAS,WAAW,GAAG,GAAG,KAAA;GAC9C,QAAQ,WAAW,eAAe,WAAW,cAAc,SAAS,KAAA;GACpE,WAAW,cAAc,SAAS,cAAc,SAAS,YAAY,KAAA;GACtE,CAAC;AACF,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,KAAK,cAAc,OAAO,MAAM;AAG5C,OAFoB,EAAE,IAAI,OAAO,eAAe,IAAI,IAEpC,SAAS,sBAAsB,EAAE;GAC/C,IAAI;AACJ,OAAI;AACF,WAAO,MAAM,EAAE,IAAI,UAAU,EAAE,KAAK,MAAM,CAAC;WACrC;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,0BAA0B,EAAE,IAAI;;GAGzD,MAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,KAAK,MAAM,GAAG,KAAA;GAChE,MAAM,UAAU,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAA;GAC5D,MAAM,UAAU,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAA;GAC5D,MAAM,SAAS,mBAAmB,KAAgC;GAElE,MAAM,OAAO,MAAM,QAAQ,qBAAqB,WAAW;IACzD;IACA,MAAM,WAAW,YAAY,IAAI,QAAoB,GAAI,UAAuB,KAAA;IAChF,MAAM,UAAU,QAAQ,MAAM,IAAI,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC,OAAO,QAAQ,GAAG,KAAA;IAC1E,aAAa;IACd,CAAC;GAEF,MAAM,OAAO,KAAK;AAClB,OAAI,QAAQ,OAAO,SAAS,UAAU;IACpC,IAAI,MAAqB;IACzB,IAAI,WAAW;IACf,IAAI,WAAW;AAEf,QAAI,gBAAgB,MAAM;AACxB,WAAM,OAAO,KAAK,MAAM,KAAK,aAAa,CAAC;AAC3C,gBAAW,KAAK,QAAQ;AACxB,gBAAW,KAAK,QAAQ;eACf,OAAQ,KAAc,gBAAgB,WAC/C,OAAM,OAAO,KAAK,MAAO,KAAc,aAAa,CAAC;AAGvD,QAAI,KAAK;KACP,MAAM,cAAc,KAAK;KACzB,MAAM,WACJ,OAAO,gBAAgB,WACnB,SAAS,aAAa,GAAG,GACzB,OAAO,gBAAgB,WACrB,cACA,KAAA;AACR,WAAM,QAAQ,qBAAqB,cAAc,KAAK,IAAI;MACxD,MAAM;MACN,QAAQ;MACR;MACA,UAAU,OAAO,SAAS,SAAS,GAAG,WAAW,KAAA;MAClD,CAAC;;;GAIN,MAAM,OAAO,MAAM,QAAQ,qBAAqB,QAAQ,KAAK,GAAG;AAChE,UAAO,EAAE,KAAK,EAAE,MAAM,MAAM,EAAE,IAAI;;EAIpC,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,KAAK,MAAM,GAAG,KAAA;EAChE,MAAM,SAAS,YAAY,KAAK,OAAO;EACvC,MAAM,UAAU,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAA;EAC5D,MAAM,UAAU,MAAM,QAAQ,KAAK,KAAK,GAAG,KAAK,KAAK,QAAQ,MAAe,OAAO,MAAM,SAAS,GAAG,KAAA;EACrG,MAAM,SAAS,mBAAmB,KAAK;EAEvC,MAAM,OAAO,MAAM,QAAQ,qBAAqB,WAAW;GACzD;GACA;GACA,MAAM,WAAW,YAAY,IAAI,QAAoB,GAAI,UAAuB,KAAA;GAChF,MAAM;GACN,aAAa;GACb,QAAQ,KAAK,WAAW;GACzB,CAAC;AACF,SAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI;GAC5B;AAGF,eAAc,KAAK,mBAAmB,OAAO,MAAM;EACjD,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,SAAS,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;AAC/D,MAAI,CAAC,OACH,QAAO,EAAE,KAAK,EAAE,OAAO,kCAAkC,EAAE,IAAI;EAGjE,MAAM,oBAAoB,OAAO,KAAK,sBAAsB,WAAW,KAAK,oBAAoB,KAAA;EAChG,MAAM,QAAQ,eAAe,KAAK;EAClC,MAAM,SAAS,MAAM,QAAQ,qBAAqB,SAAS,QAAQ,OAAO,kBAAkB;AAC5F,MAAI,CAAC,OAAO,KACV,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;AAEjD,MAAI,OAAO,SACT,QAAO,EAAE,KAAK;GAAE,UAAU;GAAM,MAAM,OAAO;GAAM,EAAE,IAAI;AAE3D,SAAO,EAAE,KAAK;GAAE,UAAU;GAAO,MAAM,OAAO;GAAM,CAAC;GACrD;AAGF,eAAc,KAAK,2BAA2B,OAAO,MAAM;EACzD,MAAM,SAAS,MAAM,QAAQ,qBAAqB,aAAa,EAAE,IAAI,MAAM,KAAK,EAAE,QAAQ,cAAc;AACxG,MAAI,CAAC,OACH,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;AAEjD,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,KAAK,qCAAqC,OAAO,MAAM;EAEnE,MAAM,YAAW,MADE,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE,EAC3B;AACtB,MAAI,aAAa,aAAa,aAAa,iBAAiB,aAAa,UACvE,QAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,EAAE,IAAI;EAEnD,MAAM,OAAO,MAAM,QAAQ,qBAAqB,wBAAwB,EAAE,IAAI,MAAM,KAAK,EAAE,SAAS;AACpG,MAAI,CAAC,KACH,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;AAEjD,SAAO,EAAE,KAAK,EAAE,MAAM,CAAC;GACvB;AAGF,eAAc,KAAK,uBAAuB,OAAO,MAAM;EACrD,MAAM,SAAS,EAAE,IAAI,MAAM,KAAK;EAChC,MAAM,OAAO,MAAM,QAAQ,qBAAqB,QAAQ,OAAO;AAC/D,MAAI,CAAC,KACH,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;EAGjD,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,aAAa,QAAQ;EAC3B,IAAI,UACF,OAAO,KAAK,YAAY,YAAY,KAAK,QAAQ,MAAM,GACnD,KAAK,QAAQ,MAAM,CAAC,aAAa,GACjC,kBAAkB,WAAW;AACnC,MAAI,CAAC,YAAY,SAAS,WAAW,CACnC,WAAU,kBAAkB,WAAW;EAGzC,MAAM,cAAc,KAAK,QAAQ,WAAW;AAC5C,MAAI,aAAa;GACf,MAAM,kBAAkB,MAAM,QAAQ,SAAS,WAAW,YAAY;AACtE,OAAI,gBACF,QAAO,EAAE,KAAK;IAAE,SAAS;IAAiB,YAAY;IAAa,QAAQ;IAAM,CAAC;;EAItF,MAAM,aAAa,gBAAgB;GACjC;GACA,QAAQ;GACR,WAAW;GACX,UAAU;GACV,QAAQ,QAAQ,OAAO,GAAG,KAAK,KAAK;GACrC,CAAC;AAEF,QAAM,QAAQ,qBAAqB,aAAa,YAAY,EAAE,CAAC;AAC/D,QAAM,QAAQ,qBAAqB,6BAA6B,YAAY;GAC1E,IAAI,eAAe;GACnB,MAAM,uBAAuB,KAAK;GAClC,MAAM;IACJ,MAAM;IACN;IACA,OAAO,KAAK,SAAS;IACtB;GACF,CAAC;EAEF,MAAM,OAAO,MAAM,QAAQ,qBAAqB,mBAAmB,WAAW;AAC9E,QAAM,QAAQ,qBAAqB,sBAAsB,YAAY;GACnE,MAAM,eAAe,KAAK;GAC1B,MAAM,MAAM,KAAK,IAAI,IAAI,CAAC,GAAI,MAAM,QAAQ,EAAE,EAAG,OAAO,CAAC,CAAC;GAC1D,YAAY;IACV,GAAI,MAAM,cAAc,EAAE;IAC1B,cAAc;IACd,iBAAiB,KAAK,SAAS;IAChC;GACF,CAAC;AAEF,QAAM,QAAQ,qBAAqB,eAAe,QAAQ,WAAW;EACrE,MAAM,UAAU,MAAM,QAAQ,SAAS,WAAW,WAAW;AAC7D,SAAO,EAAE,KAAK;GAAE;GAAS;GAAY,QAAQ;GAAO,EAAE,IAAI;GAC1D;AAGF,eAAc,IAAI,0BAA0B,OAAO,MAAM;EACvD,MAAM,SAAS,EAAE,IAAI,MAAM,KAAK;EAChC,MAAM,OAAO,MAAM,QAAQ,qBAAqB,gBAAgB,OAAO;AACvE,MAAI,CAAC,KACH,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;EAEjD,MAAM,WAAW,EAAE;AACnB,OAAK,MAAM,OAAO,MAAM;GACtB,MAAM,UAAU,MAAM,QAAQ,SAAS,WAAW,IAAI;AACtD,OAAI,QAAS,UAAS,KAAK,QAAQ;;AAErC,SAAO,EAAE,KAAK;GAAE,OAAO;GAAU,OAAO,SAAS;GAAQ,CAAC;GAC1D;AAGF,eAAc,KAAK,yBAAyB,OAAO,MAAM;EACvD,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,UAAU,OAAO,KAAK,YAAY,WAAW,KAAK,QAAQ,MAAM,GAAG;EACzE,MAAM,UAAU,OAAO,KAAK,YAAY,YAAY,KAAK,QAAQ,MAAM,GAAG,KAAK,QAAQ,MAAM,GAAG,KAAA;AAChG,MAAI,CAAC,QACH,QAAO,EAAE,KAAK,EAAE,OAAO,mCAAmC,EAAE,IAAI;EAElE,MAAM,OAAO,MAAM,QAAQ,qBAAqB,iBAAiB,EAAE,IAAI,MAAM,KAAK,EAAE,SAAS,QAAQ;AACrG,MAAI,CAAC,KACH,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;AAEjD,SAAO,EAAE,KAAK,EAAE,MAAM,CAAC;GACvB;AAGF,eAAc,IAAI,kBAAkB,OAAO,MAAM;EAC/C,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;EAC5B,MAAM,OAAO,MAAM,QAAQ,qBAAqB,QAAQ,GAAG;AAC3D,MAAI,CAAC,KACH,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;AAEjD,SAAO,EAAE,KAAK,EAAE,MAAM,CAAC;GACvB;AAGF,eAAc,MAAM,kBAAkB,OAAO,MAAM;EACjD,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;EAC5B,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EAEjD,MAAM,QAAQ,eAAe,KAAK;EAClC,MAAM,UACJ,KAAK,YAAY,aAAa,KAAK,YAAY,UAAU,KAAK,YAAY,YACtE,KAAK,UACL;EAEN,MAAM,UAAU,MAAM,QAAQ,qBAAqB,WAAW,IAAI,OAAO,QAAQ;AACjF,MAAI,CAAC,QACH,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;AAEjD,SAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;GAChC;AAGF,eAAc,OAAO,kBAAkB,OAAO,MAAM;EAClD,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;AAE5B,MAAI,CAAC,MADiB,QAAQ,qBAAqB,WAAW,GAAG,CAE/D,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;AAEjD,SAAO,EAAE,KAAK,EAAE,SAAS,MAAM,CAAC;GAChC;AAGF,eAAc,IAAI,0BAA0B,OAAO,MAAM;EACvD,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;EAC5B,MAAM,UAAU,MAAM,QAAQ,qBAAqB,gBAAgB,GAAG;AACtE,SAAO,EAAE,KAAK,EAAE,SAAS,CAAC;GAC1B;AAGF,eAAc,IAAI,qCAAqC,OAAO,MAAM;EAClE,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;EAC5B,MAAM,YAAY,SAAS,EAAE,IAAI,MAAM,YAAY,EAAE,GAAG;AACxD,MAAI,CAAC,OAAO,SAAS,UAAU,CAC7B,QAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,EAAE,IAAI;EAEpD,MAAM,WAAW,MAAM,QAAQ,qBAAqB,gBAAgB,IAAI,UAAU;AAClF,MAAI,CAAC,SACH,QAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,EAAE,IAAI;AAErD,SAAO,EAAE,KAAK,EAAE,UAAU,CAAC;GAC3B;AAGF,eAAc,KAAK,kCAAkC,OAAO,MAAM;EAChE,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;EAC5B,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,YAAY,OAAO,KAAK,cAAc,WAAW,KAAK,YAAY;AACxE,MAAI,CAAC,UACH,QAAO,EAAE,KAAK,EAAE,OAAO,qCAAqC,EAAE,IAAI;EAEpE,MAAM,OAAO,MAAM,QAAQ,qBAAqB,oBAAoB,IAAI,UAAU;AAClF,MAAI,CAAC,KACH,QAAO,EAAE,KAAK,EAAE,OAAO,8BAA8B,EAAE,IAAI;AAE7D,SAAO,EAAE,KAAK,EAAE,MAAM,CAAC;GACvB;AAGF,eAAc,KAAK,0BAA0B,OAAO,MAAM;EACxD,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;EAC5B,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,cAAc,OAAO,KAAK,gBAAgB,WAAW,KAAK,YAAY,MAAM,GAAG;AACrF,MAAI,CAAC,YACH,QAAO,EAAE,KAAK,EAAE,OAAO,uCAAuC,EAAE,IAAI;EAGtE,MAAM,SAAS,YAAY,KAAK,OAAO;EACvC,MAAM,SAAS,MAAM,QAAQ,qBAAqB,kBAAkB,IAAI,aAAa,OAAO;AAC5F,MAAI,CAAC,OACH,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;AAEjD,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,KAAK,wBAAwB,OAAO,MAAM;EACtD,MAAM,SAAS,EAAE,IAAI,MAAM,KAAK;EAChC,IAAI;AACJ,MAAI;AACF,UAAO,MAAM,EAAE,IAAI,UAAU,EAAE,KAAK,MAAM,CAAC;UACrC;AACN,UAAO,EAAE,KAAK,EAAE,OAAO,0BAA0B,EAAE,IAAI;;EAGzD,MAAM,OAAO,KAAK;AAClB,MAAI,CAAC,QAAQ,OAAO,SAAS,SAC3B,QAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,EAAE,IAAI;EAGrD,IAAI;EACJ,IAAI,WAAW;EACf,IAAI,WAAW;AAEf,MAAI,gBAAgB,MAAM;AACxB,SAAM,OAAO,KAAK,MAAM,KAAK,aAAa,CAAC;AAC3C,cAAW,KAAK,QAAQ;AACxB,cAAW,KAAK,QAAQ;aACf,OAAQ,KAAc,gBAAgB,WAC/C,OAAM,OAAO,KAAK,MAAO,KAAc,aAAa,CAAC;MAErD,QAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,EAAE,IAAI;EAGtD,MAAM,cAAc,KAAK;EACzB,MAAM,WAAW,OAAO,gBAAgB,WAAW,SAAS,aAAa,GAAG,GAAG,KAAA;EAE/E,MAAM,aAAa,MAAM,QAAQ,qBAAqB,cAAc,QAAQ;GAC1E,MAAM;GACN,QAAQ;GACR;GACA,UAAU,OAAO,SAAS,SAAS,GAAG,WAAW,KAAA;GAClD,CAAC;AAEF,MAAI,CAAC,WACH,QAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,EAAE,IAAI;AAEjD,SAAO,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI;GAClC;AAGF,eAAc,IAAI,sCAAsC,OAAO,MAAM;EACnE,MAAM,SAAS,EAAE,IAAI,MAAM,KAAK;EAChC,MAAM,eAAe,EAAE,IAAI,MAAM,eAAe;EAEhD,MAAM,SAAS,MAAM,QAAQ,qBAAqB,kBAAkB,QAAQ,aAAa;AACzF,MAAI,CAAC,OACH,QAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,EAAE,IAAI;EAGvD,MAAM,EAAE,UAAU,UAAU,aAAa;AAEzC,MAAI;AACF,SAAM,OAAO,SAAS;UAChB;AACN,UAAO,EAAE,KAAK,EAAE,OAAO,2BAA2B,EAAE,IAAI;;EAG1D,MAAM,WAAW,MAAM,KAAK,SAAS;AAErC,IAAE,OAAO,gBAAgB,SAAS;AAClC,IAAE,OAAO,kBAAkB,OAAO,SAAS,KAAK,CAAC;AACjD,IAAE,OAAO,uBAAuB,qBAAqB,mBAAmB,SAAS,CAAC,GAAG;AACrF,IAAE,OAAO,iBAAiB,uCAAuC;AAEjE,SAAO,OAAO,GAAG,OAAO,MAAM;GAC5B,MAAM,WAAW,SAAS,MAAM,iBAAiB,SAAS,CAAC;AAC3D,SAAM,EAAE,KAAK,SAAS;IACtB;GACF;AAIF,eAAc,KAAK,mBAAmB,OAAO,MAAM;EACjD,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,MAAM,MAAM,GAAG;AACnE,MAAI,CAAC,MAAO,QAAO,EAAE,KAAK,EAAE,OAAO,iCAAiC,EAAE,IAAI;EAE1E,MAAM,SAAS,mBAAmB,KAAK;EACvC,MAAM,OAAO,MAAM,QAAQ,qBAAqB,WAAW,OAAO,QAAQ;GACxE,OAAO,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAA;GACrD,UAAU,KAAK,aAAa,UAAU,KAAK,aAAa,YAAY,KAAK,aAAa,QAAQ,KAAK,WAAW,KAAA;GAC9G,kBAAkB,OAAO,KAAK,qBAAqB,WAAW,KAAK,mBAAmB,KAAA;GACtF,cAAc,OAAO,KAAK,iBAAiB,WAAW,KAAK,eAAe,KAAA;GAC1E,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,KAAA;GAC5D,CAAC;AACF,SAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI;GAC5B;AAEF,eAAc,KAAK,8BAA8B,OAAO,MAAM;EAC5D,MAAM,OAAO,MAAM,QAAQ,qBAAqB,eAAe,EAAE,IAAI,MAAM,KAAK,CAAC;AACjF,MAAI,CAAC,KAAM,QAAO,EAAE,KAAK,EAAE,OAAO,2BAA2B,EAAE,IAAI;AACnE,SAAO,EAAE,KAAK,EAAE,MAAM,CAAC;GACvB;AAEF,eAAc,KAAK,uBAAuB,OAAO,MAAM;EACrD,MAAM,OAAO,MAAM,QAAQ,qBAAqB,WAAW,EAAE,IAAI,MAAM,KAAK,CAAC;AAC7E,MAAI,CAAC,KAAM,QAAO,EAAE,KAAK,EAAE,OAAO,aAAa,EAAE,IAAI;AACrD,SAAO,EAAE,KAAK,EAAE,MAAM,CAAC;GACvB;AAEF,eAAc,KAAK,uBAAuB,OAAO,MAAM;EACrD,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,UAAU,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;EAClE,MAAM,OAAO,MAAM,QAAQ,qBAAqB,YAAY,EAAE,IAAI,MAAM,KAAK,EAAE,QAAQ;AACvF,MAAI,CAAC,KAAM,QAAO,EAAE,KAAK,EAAE,OAAO,aAAa,EAAE,IAAI;AACrD,SAAO,EAAE,KAAK,EAAE,MAAM,CAAC;GACvB"}
|
|
@@ -13,8 +13,8 @@ import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
|
13
13
|
import { renderFolderLandingPage, renderShareExpiredPage, renderShareLandingPage } from "../../../share/share-landing.js";
|
|
14
14
|
import { consumeSharePublicLimit } from "../../../share/share-rate-limit.js";
|
|
15
15
|
import { createZipStream, planDirectoryFiles } from "../../../share/share-zip.js";
|
|
16
|
-
import { createReadStream } from "node:fs";
|
|
17
16
|
import { createHash } from "node:crypto";
|
|
17
|
+
import { createReadStream } from "node:fs";
|
|
18
18
|
import { stat } from "node:fs/promises";
|
|
19
19
|
import { Readable } from "node:stream";
|
|
20
20
|
//#region src/gateway/hono/routes/shares.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentHomeDir, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
|
|
2
|
-
import { extractProfileAgentId } from "../../../config/agent-profile.js";
|
|
3
1
|
import { createLogger } from "../../../utils/logger/index.js";
|
|
4
2
|
import { init_logger } from "../../../utils/logger.js";
|
|
3
|
+
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentHomeDir, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
|
|
4
|
+
import { extractProfileAgentId } from "../../../config/agent-profile.js";
|
|
5
5
|
import { validateWritePath } from "../../../agent/sandbox/path-policy.js";
|
|
6
6
|
import { isPathUnderWorkspace, resolveWorkspaceSafePath, toWorkspaceRelativePosix } from "../../workspace-editor-path.js";
|
|
7
7
|
import { resolveSafeInboundFilePath } from "../../../channels/attachments/inbound-persist.js";
|
|
@@ -12,10 +12,10 @@ import { fileReferenceRegistry } from "../../file-reference-registry.js";
|
|
|
12
12
|
import { resolveHeartbeatMdPath } from "../../workspace-heartbeat-path.js";
|
|
13
13
|
import { listWorkspaceRelativeFilesFsFallback } from "../../workspace-fs-file-list.js";
|
|
14
14
|
import { runRipgrepInDirectory, runRipgrepListFiles } from "../../workspace-ripgrep.js";
|
|
15
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
16
|
-
import { constants } from "node:fs";
|
|
17
15
|
import { randomUUID } from "node:crypto";
|
|
16
|
+
import { constants } from "node:fs";
|
|
18
17
|
import { copyFile, link, mkdir, readFile, readdir, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
18
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
19
19
|
//#region src/gateway/hono/routes/workspace.ts
|
|
20
20
|
init_agent_scope();
|
|
21
21
|
init_logger();
|
|
@@ -4,6 +4,8 @@ export declare function isLoopbackHost(host: string | undefined): boolean;
|
|
|
4
4
|
export declare function isAllInterfacesHost(host: string | undefined): boolean;
|
|
5
5
|
/** Vite dev server origins for the gateway console (`web/` defaults to port 3000). */
|
|
6
6
|
export declare const GATEWAY_DEV_CONSOLE_ORIGINS: readonly ["http://localhost:3000", "http://127.0.0.1:3000"];
|
|
7
|
+
/** Expo / React Native web dev server (Metro defaults to port 8081). */
|
|
8
|
+
export declare const GATEWAY_EXPO_DEV_ORIGINS: readonly ["http://localhost:8081", "http://127.0.0.1:8081"];
|
|
7
9
|
/** Effective HTTP listen port: CLI `--port` override wins over config (default 18790). */
|
|
8
10
|
export declare function resolveEffectiveGatewayPort(config: {
|
|
9
11
|
gateway?: {
|