@xopcai/xopc 0.0.82 → 0.0.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +2 -3
- package/dist/extensions/feishu/src/outbound/media-load.js.map +1 -1
- package/dist/extensions/feishu/src/schema/config-schema.d.ts +6 -6
- package/dist/extensions/telegram/src/config-schema.d.ts +6 -6
- package/dist/extensions/telegram/src/plugin.d.ts +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/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +3 -3
- 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/config-schema.d.ts +3 -3
- 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/gateway/static/root/assets/agents-CrpYTHJS.js +222 -0
- package/dist/gateway/static/root/assets/{apps-page-pJ27dsqn.js → apps-page-1mcKh5Rh.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-zd6QNKPx.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-D1KYmOmi.js → channels-status-swr-uRAuhiUo.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-api-Y2wfSJVI.js → cron-api-O2Q_ruV6.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-B97KU_RG.js → cron-page-By09AQD-.js} +1 -1
- package/dist/gateway/static/root/assets/{dist-CboA_Css.js → dist-BpQxde0t.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DN_zNmpo.js → extension-debug-page-CY27wj_p.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BUXtOzv5.js → extension-page-C-Ed5ZmP.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-C2dX4KCW.js → extension-settings-page-raLux7E7.js} +1 -1
- package/dist/gateway/static/root/assets/fetch-2iRFmd3n.js +3 -0
- package/dist/gateway/static/root/assets/{field-primitives-B9rOLqdm.js → field-primitives-fa_hiQcX.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-DvfiRVrc.js → heartbeat-config-api-BVl5VHvL.js} +1 -1
- package/dist/gateway/static/root/assets/index-BuFldCsB.css +1 -0
- package/dist/gateway/static/root/assets/{index-DQuaMye9.js → index-Y-iqo-gL.js} +94 -85
- package/dist/gateway/static/root/assets/{logs-page-BQuBpHcc.js → logs-page-BdH2n7ZW.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-Vpchzdp-.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-2Yu-FASs.js → settings-form-section-Kk1yAGBl.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-KBm0u6Dz.js +3 -0
- package/dist/gateway/static/root/assets/skills-page-BjeXXaOn.js +2 -0
- package/dist/gateway/static/root/assets/{theme-store-DnwYutiX.js → theme-store-D01dJt95.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-D2Gn2qod.js → utils-DpTxN4AF.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-CwO8Cf01.js +1 -0
- package/dist/gateway/static/root/index.html +4 -4
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-instance-gateway.d.ts +50 -0
- package/dist/src/agent/agent-instance-gateway.js +1 -0
- package/dist/src/agent/agent-manager.d.ts +20 -14
- package/dist/src/agent/agent-manager.js +74 -186
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/background-review/coordinator.d.ts +61 -0
- package/dist/src/agent/background-review/coordinator.js +120 -0
- package/dist/src/agent/background-review/coordinator.js.map +1 -0
- package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
- package/dist/src/agent/child-agent-factory.d.ts +14 -0
- package/dist/src/agent/child-agent-factory.js +2 -8
- package/dist/src/agent/child-agent-factory.js.map +1 -1
- package/dist/src/agent/context/workspace-seed.js +3 -3
- package/dist/src/agent/embedded/index.d.ts +1 -2
- package/dist/src/agent/embedded/index.js +2 -3
- package/dist/src/agent/embedded/run-for-session.d.ts +2 -2
- package/dist/src/agent/embedded/run-for-session.js.map +1 -1
- package/dist/src/agent/embedded/runs.d.ts +32 -0
- package/dist/src/agent/embedded/runs.js +79 -19
- package/dist/src/agent/embedded/runs.js.map +1 -1
- package/dist/src/agent/embedded/session-manager-cache.d.ts +14 -0
- package/dist/src/agent/embedded/session-manager-cache.js +32 -11
- package/dist/src/agent/embedded/session-manager-cache.js.map +1 -1
- package/dist/src/agent/embedded/session-runner.d.ts +37 -7
- package/dist/src/agent/embedded/session-runner.js +184 -153
- package/dist/src/agent/embedded/session-runner.js.map +1 -1
- package/dist/src/agent/embedded/session-tool-result-guard.d.ts +57 -9
- package/dist/src/agent/embedded/session-tool-result-guard.js +159 -67
- package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
- package/dist/src/agent/goals/goal-run-store.js +4 -4
- package/dist/src/agent/goals/persistent-goal-service.d.ts +84 -0
- package/dist/src/agent/goals/persistent-goal-service.js +139 -0
- package/dist/src/agent/goals/persistent-goal-service.js.map +1 -0
- package/dist/src/agent/goals/post-turn.js +2 -2
- package/dist/src/agent/goals/state.d.ts +1 -1
- package/dist/src/agent/goals/state.js.map +1 -1
- package/dist/src/agent/image/load-image-media.js +1 -1
- package/dist/src/agent/inbound/inbound-loop.d.ts +77 -0
- package/dist/src/agent/inbound/inbound-loop.js +226 -0
- package/dist/src/agent/inbound/inbound-loop.js.map +1 -0
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +80 -0
- package/dist/src/agent/inbound/turn-dispatcher.js +138 -0
- package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -0
- 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/lifecycle/handlers/compaction.d.ts +1 -1
- package/dist/src/agent/lifecycle/handlers/compaction.js.map +1 -1
- package/dist/src/agent/lifecycle/manager.d.ts +1 -1
- package/dist/src/agent/lifecycle/manager.js.map +1 -1
- package/dist/src/agent/lifecycle/types.d.ts +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.d.ts +12 -2
- package/dist/src/agent/memory/dreaming/utils.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.js.map +1 -1
- package/dist/src/agent/memory/index.js +3 -3
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/memory/prefetch-coordinator.d.ts +37 -0
- package/dist/src/agent/memory/prefetch-coordinator.js +45 -0
- package/dist/src/agent/memory/prefetch-coordinator.js.map +1 -0
- package/dist/src/agent/messaging/command-handler.d.ts +5 -1
- package/dist/src/agent/messaging/command-handler.js +24 -96
- package/dist/src/agent/messaging/command-handler.js.map +1 -1
- package/dist/src/agent/messaging/index.d.ts +1 -0
- package/dist/src/agent/messaging/index.js +2 -1
- package/dist/src/agent/messaging/message-router.d.ts +1 -1
- package/dist/src/agent/messaging/message-router.js.map +1 -1
- package/dist/src/agent/messaging/outbound-coordinator.d.ts +82 -0
- package/dist/src/agent/messaging/outbound-coordinator.js +123 -0
- package/dist/src/agent/messaging/outbound-coordinator.js.map +1 -0
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/orchestration/agent-event-handler.d.ts +36 -33
- package/dist/src/agent/orchestration/agent-event-handler.js +212 -174
- package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.d.ts +4 -4
- package/dist/src/agent/orchestration/agent-orchestrator.js +4 -8
- package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
- package/dist/src/agent/orchestration/index.d.ts +1 -1
- package/dist/src/agent/orchestration/index.js +2 -2
- package/dist/src/agent/prompt/service-prompt-builder.js +4 -4
- 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 +1 -1
- package/dist/src/agent/service/async-queue.d.ts +20 -0
- package/dist/src/agent/service/async-queue.js +53 -0
- package/dist/src/agent/service/async-queue.js.map +1 -0
- package/dist/src/agent/service/build-direct-message-content.d.ts +2 -2
- package/dist/src/agent/service/build-direct-message-content.js.map +1 -1
- package/dist/src/agent/service/direct-turn-helpers.d.ts +70 -0
- package/dist/src/agent/service/direct-turn-helpers.js +90 -0
- package/dist/src/agent/service/direct-turn-helpers.js.map +1 -0
- package/dist/src/agent/service/process-direct-one-shot.d.ts +3 -3
- package/dist/src/agent/service/process-direct-one-shot.js +17 -34
- package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.d.ts +2 -2
- package/dist/src/agent/service/process-direct-streaming.js +122 -168
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service/webchat-tts.d.ts +2 -2
- package/dist/src/agent/service/webchat-tts.js +1 -1
- package/dist/src/agent/service/webchat-tts.js.map +1 -1
- package/dist/src/agent/service.d.ts +62 -167
- package/dist/src/agent/service.js +177 -786
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/session/index.d.ts +4 -0
- package/dist/src/agent/session/index.js +5 -1
- package/dist/src/agent/session/session-config-service.d.ts +68 -0
- package/dist/src/agent/session/session-config-service.js +172 -0
- package/dist/src/agent/session/session-config-service.js.map +1 -0
- package/dist/src/agent/session/session-context.d.ts +27 -19
- package/dist/src/agent/session/session-context.js +39 -24
- package/dist/src/agent/session/session-context.js.map +1 -1
- package/dist/src/agent/session/session-hydrator.d.ts +42 -0
- package/dist/src/agent/session/session-hydrator.js +66 -0
- package/dist/src/agent/session/session-hydrator.js.map +1 -0
- package/dist/src/agent/session/session-inspector.d.ts +80 -0
- package/dist/src/agent/session/session-inspector.js +119 -0
- package/dist/src/agent/session/session-inspector.js.map +1 -0
- package/dist/src/agent/session/session-state-bag.d.ts +83 -0
- package/dist/src/agent/session/session-state-bag.js +192 -0
- package/dist/src/agent/session/session-state-bag.js.map +1 -0
- 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.d.ts +0 -2
- package/dist/src/agent/skills/index.js +3 -5
- package/dist/src/agent/skills/index.js.map +1 -1
- package/dist/src/agent/skills/managed-store.js +1 -1
- package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +11 -6
- package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js.map +1 -1
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +35 -7
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
- package/dist/src/agent/skills/scanner.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +2 -2
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +7 -0
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +37 -0
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
- package/dist/src/agent/tools/delegate-tool.d.ts +7 -0
- package/dist/src/agent/tools/delegate-tool.js +2 -1
- package/dist/src/agent/tools/delegate-tool.js.map +1 -1
- package/dist/src/agent/tools/dreaming-tool.js +1 -1
- package/dist/src/agent/tools/executor.d.ts +34 -15
- package/dist/src/agent/tools/executor.js +44 -79
- package/dist/src/agent/tools/executor.js.map +1 -1
- package/dist/src/agent/tools/factory.d.ts +6 -0
- package/dist/src/agent/tools/factory.js +63 -4
- package/dist/src/agent/tools/factory.js.map +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/skills-tools.js +1 -1
- package/dist/src/agent/tools/tts-tool.js +1 -1
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/agent/workspace-runtime/registry.d.ts +48 -0
- package/dist/src/agent/workspace-runtime/registry.js +59 -0
- package/dist/src/agent/workspace-runtime/registry.js.map +1 -0
- 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/cdp-local-launcher.js +4 -3
- package/dist/src/browser/cdp-local-launcher.js.map +1 -1
- package/dist/src/browser/index.d.ts +1 -0
- package/dist/src/browser/index.js +2 -1
- package/dist/src/browser/manager.js +3 -2
- package/dist/src/browser/manager.js.map +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +4 -4
- package/dist/src/browser/providers/browser-use.js +2 -1
- package/dist/src/browser/providers/browser-use.js.map +1 -1
- package/dist/src/browser/providers/browserbase.js +2 -1
- package/dist/src/browser/providers/browserbase.js.map +1 -1
- package/dist/src/browser/providers/cloakbrowser.js +7 -6
- package/dist/src/browser/providers/cloakbrowser.js.map +1 -1
- package/dist/src/browser/providers/playwright-doctor.d.ts +2 -0
- package/dist/src/browser/providers/playwright-doctor.js +7 -3
- package/dist/src/browser/providers/playwright-doctor.js.map +1 -1
- package/dist/src/browser/readiness.d.ts +33 -0
- package/dist/src/browser/readiness.js +138 -0
- package/dist/src/browser/readiness.js.map +1 -0
- package/dist/src/browser/stealth.js +2 -2
- 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/channel-domain.d.ts +1 -1
- package/dist/src/channels/config-helpers.d.ts +1 -1
- package/dist/src/channels/config-helpers.js.map +1 -1
- package/dist/src/channels/heartbeat-scheduler.d.ts +40 -0
- package/dist/src/channels/heartbeat-scheduler.js +94 -0
- package/dist/src/channels/heartbeat-scheduler.js.map +1 -0
- package/dist/src/channels/lifecycle-supervisor.d.ts +81 -0
- package/dist/src/channels/lifecycle-supervisor.js +263 -0
- package/dist/src/channels/lifecycle-supervisor.js.map +1 -0
- package/dist/src/channels/manager.d.ts +34 -68
- package/dist/src/channels/manager.js +107 -477
- package/dist/src/channels/manager.js.map +1 -1
- package/dist/src/channels/outbound/deliver.d.ts +1 -1
- package/dist/src/channels/outbound/deliver.js.map +1 -1
- package/dist/src/channels/outbound/persist-store.js +1 -1
- package/dist/src/channels/outbound-sender.d.ts +51 -0
- package/dist/src/channels/outbound-sender.js +125 -0
- package/dist/src/channels/outbound-sender.js.map +1 -0
- package/dist/src/channels/pairing/allow-from-file.js +1 -1
- package/dist/src/channels/pairing/pairing-service.d.ts +3 -10
- package/dist/src/channels/pairing/pairing-service.js.map +1 -1
- package/dist/src/channels/pairing/pairing-store.js +2 -2
- package/dist/src/channels/pairing/pairing-types.d.ts +15 -0
- package/dist/src/channels/pairing/pairing-types.js +1 -0
- package/dist/src/channels/plugin-registry.d.ts +22 -0
- package/dist/src/channels/plugin-registry.js +44 -0
- package/dist/src/channels/plugin-registry.js.map +1 -0
- package/dist/src/channels/plugin-types.d.ts +1 -1
- package/dist/src/channels/plugins/types.adapters.d.ts +2 -2
- package/dist/src/channels/security-helpers.d.ts +1 -1
- package/dist/src/channels/security-helpers.js.map +1 -1
- package/dist/src/channels/setup-wizard.d.ts +1 -1
- package/dist/src/chat-commands/builtins/config.js +2 -2
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/cli/commands/agent/stream-renderer.js +1 -1
- package/dist/src/cli/commands/agent/stream-renderer.js.map +1 -1
- package/dist/src/cli/commands/agent.js +4 -4
- package/dist/src/cli/commands/agent.js.map +1 -1
- package/dist/src/cli/commands/browser-cli-helpers.js +2 -1
- package/dist/src/cli/commands/browser-cli-helpers.js.map +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 +1 -1
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
- package/dist/src/cli/commands/extension-dev.js +2 -2
- package/dist/src/cli/commands/extension-dev.js.map +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +2 -2
- package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
- package/dist/src/cli/commands/extension-pack.js +1 -1
- package/dist/src/cli/commands/gateway/call.js +1 -1
- package/dist/src/cli/commands/gateway/call.js.map +1 -1
- package/dist/src/cli/commands/gateway/health.js +1 -1
- package/dist/src/cli/commands/gateway/health.js.map +1 -1
- package/dist/src/cli/commands/gateway/lifecycle-core.d.ts +31 -12
- package/dist/src/cli/commands/gateway/lifecycle-core.js +167 -116
- package/dist/src/cli/commands/gateway/lifecycle-core.js.map +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.d.ts +11 -0
- package/dist/src/cli/commands/gateway/lifecycle.js +102 -0
- package/dist/src/cli/commands/gateway/lifecycle.js.map +1 -0
- package/dist/src/cli/commands/gateway/logs.js +1 -1
- package/dist/src/cli/commands/gateway/logs.js.map +1 -1
- package/dist/src/cli/commands/gateway/probe.js +1 -1
- package/dist/src/cli/commands/gateway/probe.js.map +1 -1
- package/dist/src/cli/commands/gateway/restart-health.d.ts +12 -0
- package/dist/src/cli/commands/gateway/restart-health.js +45 -1
- package/dist/src/cli/commands/gateway/restart-health.js.map +1 -1
- package/dist/src/cli/commands/gateway/restart.js +3 -3
- package/dist/src/cli/commands/gateway/restart.js.map +1 -1
- package/dist/src/cli/commands/gateway/run-foreground.d.ts +0 -1
- package/dist/src/cli/commands/gateway/run-foreground.js +0 -35
- package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
- package/dist/src/cli/commands/gateway/service.js +1 -1
- package/dist/src/cli/commands/gateway/service.js.map +1 -1
- package/dist/src/cli/commands/gateway/shared.d.ts +3 -0
- package/dist/src/cli/commands/gateway/shared.js +54 -0
- package/dist/src/cli/commands/gateway/shared.js.map +1 -0
- package/dist/src/cli/commands/gateway/status.js +1 -1
- package/dist/src/cli/commands/gateway/status.js.map +1 -1
- package/dist/src/cli/commands/gateway/stop.js +2 -2
- package/dist/src/cli/commands/gateway/stop.js.map +1 -1
- package/dist/src/cli/commands/gateway/token.js +1 -1
- package/dist/src/cli/commands/gateway/token.js.map +1 -1
- package/dist/src/cli/commands/gateway.js +5 -5
- package/dist/src/cli/commands/gateway.js.map +1 -1
- package/dist/src/cli/commands/image.js +2 -2
- package/dist/src/cli/commands/image.js.map +1 -1
- package/dist/src/cli/commands/init.js +4 -4
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/models.js.map +1 -1
- package/dist/src/cli/commands/onboard/gateway.d.ts +0 -8
- package/dist/src/cli/commands/onboard/gateway.js +48 -49
- package/dist/src/cli/commands/onboard/gateway.js.map +1 -1
- package/dist/src/cli/commands/onboard.js +9 -64
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/session/utils.js +1 -1
- package/dist/src/cli/commands/session/utils.js.map +1 -1
- package/dist/src/cli/commands/skills.js +1 -1
- package/dist/src/cli/commands/tailscale.js +1 -1
- package/dist/src/cli/commands/tailscale.js.map +1 -1
- package/dist/src/cli/context.d.ts +20 -0
- package/dist/src/cli/context.js +23 -0
- package/dist/src/cli/context.js.map +1 -0
- package/dist/src/cli/extension-cli-register.js +3 -3
- package/dist/src/cli/gateway-run-argv.js +1 -4
- package/dist/src/cli/gateway-run-argv.js.map +1 -1
- package/dist/src/cli/gateway-run-fast-path.js +1 -1
- package/dist/src/cli/gateway-run-fast-path.js.map +1 -1
- package/dist/src/cli/index.d.ts +1 -7
- package/dist/src/cli/index.js +4 -6
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +2 -2
- package/dist/src/config/commands.flags.d.ts +3 -0
- package/dist/src/config/commands.flags.js +11 -0
- package/dist/src/config/commands.flags.js.map +1 -0
- package/dist/src/config/index.d.ts +1 -0
- package/dist/src/config/index.js +6 -5
- 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/profile.js +2 -2
- package/dist/src/config/schema.d.ts +11 -4
- package/dist/src/config/schema.js +13 -12
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/workspace-path-helpers.d.ts +15 -0
- package/dist/src/config/workspace-path-helpers.js +14 -0
- package/dist/src/config/workspace-path-helpers.js.map +1 -0
- package/dist/src/cron/executor.js +4 -4
- package/dist/src/cron/executor.js.map +1 -1
- package/dist/src/cron/persistence.js +1 -1
- package/dist/src/cron/run-log-store.js +1 -1
- package/dist/src/daemon/index.d.ts +0 -1
- package/dist/src/daemon/index.js +1 -2
- package/dist/src/daemon/install-plan.js +3 -2
- package/dist/src/daemon/install-plan.js.map +1 -1
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/daemon/types.d.ts +0 -6
- package/dist/src/extensions/api.d.ts +1 -1
- package/dist/src/extensions/api.js +2 -2
- package/dist/src/extensions/api.js.map +1 -1
- package/dist/src/extensions/bundle-mcp.js +1 -1
- package/dist/src/extensions/discover-extensions.js +1 -1
- package/dist/src/extensions/extension-registry-impl.d.ts +51 -0
- package/dist/src/extensions/extension-registry-impl.js +117 -0
- package/dist/src/extensions/extension-registry-impl.js.map +1 -0
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/index.js +3 -2
- package/dist/src/extensions/loader.d.ts +3 -43
- package/dist/src/extensions/loader.js +3 -110
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/lockfile.js +2 -2
- package/dist/src/extensions/sdk/index.js +2 -1
- package/dist/src/extensions/sdk/index.js.map +1 -1
- package/dist/src/extensions/types/events.d.ts +7 -1
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/file-path-classifier.js +2 -2
- package/dist/src/gateway/heartbeat/service.js +2 -2
- package/dist/src/gateway/heartbeat/service.js.map +1 -1
- package/dist/src/gateway/hono/app.js +5 -53
- package/dist/src/gateway/hono/app.js.map +1 -1
- package/dist/src/gateway/hono/lib/extension-store.js +1 -1
- package/dist/src/gateway/hono/lib/static-ui.js +2 -2
- package/dist/src/gateway/hono/middleware/auth.d.ts +5 -14
- package/dist/src/gateway/hono/middleware/auth.js +89 -126
- package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
- package/dist/src/gateway/hono/middleware/logger.js +1 -1
- package/dist/src/gateway/hono/middleware/logger.js.map +1 -1
- package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +14 -0
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js +62 -0
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js.map +1 -0
- package/dist/src/gateway/hono/oauth.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +4 -4
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js.map +1 -1
- package/dist/src/gateway/hono/routes/browser.d.ts +20 -0
- package/dist/src/gateway/hono/routes/browser.js +626 -0
- package/dist/src/gateway/hono/routes/browser.js.map +1 -0
- package/dist/src/gateway/hono/routes/commands-skills.js +13 -13
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/agents.d.ts +18 -0
- package/dist/src/gateway/hono/routes/config-patch/agents.js +418 -0
- package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -0
- package/dist/src/gateway/hono/routes/config-patch/channels.d.ts +12 -0
- package/dist/src/gateway/hono/routes/config-patch/channels.js +186 -0
- package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +18 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.js +264 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -0
- package/dist/src/gateway/hono/routes/config-patch/index.d.ts +9 -0
- package/dist/src/gateway/hono/routes/config-patch/index.js +6 -0
- package/dist/src/gateway/hono/routes/config-patch/misc.d.ts +23 -0
- package/dist/src/gateway/hono/routes/config-patch/misc.js +139 -0
- package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -0
- package/dist/src/gateway/hono/routes/config-patch/result.d.ts +18 -0
- package/dist/src/gateway/hono/routes/config-patch/result.js +13 -0
- package/dist/src/gateway/hono/routes/config-patch/result.js.map +1 -0
- package/dist/src/gateway/hono/routes/config.js +20 -1764
- package/dist/src/gateway/hono/routes/config.js.map +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +2 -3
- package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
- package/dist/src/gateway/hono/routes/host-fs.js +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +10 -5
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/mcp.js +1 -2
- package/dist/src/gateway/hono/routes/mcp.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +32 -32
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/shares.js +4 -4
- package/dist/src/gateway/hono/routes/shares.js.map +1 -1
- package/dist/src/gateway/hono/routes/tunnel.js +1 -1
- package/dist/src/gateway/hono/routes/tunnel.js.map +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +6 -7
- package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
- package/dist/src/gateway/hono/sse.js +2 -2
- package/dist/src/gateway/index.d.ts +1 -1
- package/dist/src/gateway/index.js +4 -2
- package/dist/src/gateway/lock.js +3 -3
- package/dist/src/gateway/rate-limit/auth-policy.d.ts +34 -0
- package/dist/src/gateway/rate-limit/auth-policy.js +49 -0
- package/dist/src/gateway/rate-limit/auth-policy.js.map +1 -0
- package/dist/src/gateway/rate-limit/buckets.d.ts +63 -0
- package/dist/src/gateway/rate-limit/buckets.js +143 -0
- package/dist/src/gateway/rate-limit/buckets.js.map +1 -0
- package/dist/src/gateway/rate-limit/env-flags.d.ts +13 -0
- package/dist/src/gateway/rate-limit/env-flags.js +16 -0
- package/dist/src/gateway/rate-limit/env-flags.js.map +1 -0
- package/dist/src/gateway/rate-limit/index.d.ts +3 -0
- package/dist/src/gateway/rate-limit/index.js +4 -0
- package/dist/src/gateway/run-loop.d.ts +1 -1
- package/dist/src/gateway/run-loop.js +24 -4
- package/dist/src/gateway/run-loop.js.map +1 -1
- package/dist/src/gateway/runtime-config.js +2 -1
- package/dist/src/gateway/runtime-config.js.map +1 -1
- package/dist/src/gateway/security/audit.js +2 -1
- package/dist/src/gateway/security/audit.js.map +1 -1
- package/dist/src/gateway/security/index.d.ts +0 -1
- package/dist/src/gateway/security/index.js +1 -2
- package/dist/src/gateway/security/loopback.d.ts +13 -0
- package/dist/src/gateway/security/loopback.js +45 -0
- package/dist/src/gateway/security/loopback.js.map +1 -0
- package/dist/src/gateway/service/agent-runner.d.ts +108 -0
- package/dist/src/gateway/service/agent-runner.js +184 -0
- package/dist/src/gateway/service/agent-runner.js.map +1 -0
- package/dist/src/gateway/service/config-coordinator.d.ts +119 -0
- package/dist/src/gateway/service/config-coordinator.js +351 -0
- package/dist/src/gateway/service/config-coordinator.js.map +1 -0
- package/dist/src/gateway/service/marketplace-service.d.ts +85 -0
- package/dist/src/gateway/service/marketplace-service.js +239 -0
- package/dist/src/gateway/service/marketplace-service.js.map +1 -0
- package/dist/src/gateway/service/run-gateway-agent.js +5 -5
- package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +125 -0
- package/dist/src/gateway/service/sessions-api.js +135 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -0
- package/dist/src/gateway/service.d.ts +30 -360
- package/dist/src/gateway/service.js +121 -903
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/gateway/workspace-heartbeat-path.js +1 -2
- package/dist/src/gateway/workspace-heartbeat-path.js.map +1 -1
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/gateway-process-argv.d.ts +4 -0
- package/dist/src/infra/gateway-process-argv.js +26 -0
- package/dist/src/infra/gateway-process-argv.js.map +1 -0
- package/dist/src/infra/gateway-processes.d.ts +5 -0
- package/dist/src/infra/gateway-processes.js +65 -0
- package/dist/src/infra/gateway-processes.js.map +1 -0
- package/dist/src/infra/rate-limit/failure-limiter.d.ts +50 -0
- package/dist/src/infra/rate-limit/failure-limiter.js +100 -0
- package/dist/src/infra/rate-limit/failure-limiter.js.map +1 -0
- package/dist/src/infra/rate-limit/index.d.ts +5 -0
- package/dist/src/infra/rate-limit/index.js +3 -0
- package/dist/src/infra/rate-limit/keyed-store.d.ts +34 -0
- package/dist/src/infra/rate-limit/keyed-store.js +44 -0
- package/dist/src/infra/rate-limit/keyed-store.js.map +1 -0
- package/dist/src/infra/rate-limit/rate-limiter.d.ts +39 -0
- package/dist/src/infra/rate-limit/rate-limiter.js +65 -0
- package/dist/src/infra/rate-limit/rate-limiter.js.map +1 -0
- package/dist/src/infra/restart.d.ts +21 -0
- package/dist/src/infra/restart.js +122 -0
- package/dist/src/infra/restart.js.map +1 -0
- package/dist/src/infra/update-check.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.d.ts +0 -6
- package/dist/src/mcp/channel-bridge.js +1 -5
- package/dist/src/mcp/channel-bridge.js.map +1 -1
- package/dist/src/media-shared/http/ssrf-guard.js +1 -1
- package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/session/config-store.js +2 -2
- package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
- package/dist/src/session/parity/sessions-json-file-read.d.ts +2 -1
- package/dist/src/session/parity/sessions-json-file-read.js.map +1 -1
- 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/search-index-cache.js +1 -1
- package/dist/src/session/search-index.js +1 -1
- package/dist/src/session/session-title.js +1 -1
- package/dist/src/session/store.js +5 -5
- package/dist/src/share/share-rate-limit.d.ts +10 -2
- package/dist/src/share/share-rate-limit.js +33 -42
- package/dist/src/share/share-rate-limit.js.map +1 -1
- package/dist/src/share/share-store.js +3 -3
- package/dist/src/tui/backends/embedded-backend.js +16 -12
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/clipboard-image.js +2 -2
- package/dist/src/tui/extension-host/load-extensions.js +1 -1
- package/dist/src/tui/format-tui-hotkeys.js +1 -1
- 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 +1 -1
- package/dist/src/tui/tui-settings.js +1 -1
- package/dist/src/tui/tui-skills-autocomplete.js +1 -1
- package/dist/src/tui/tui.js +1 -2
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/tui/xopc-tui-keybindings.d.ts +0 -1
- package/dist/src/tui/xopc-tui-keybindings.js +1 -2
- package/dist/src/tui/xopc-tui-keybindings.js.map +1 -1
- package/dist/src/tunnel/frpc-binary.js +2 -2
- package/dist/src/tunnel/frpc-config.js +1 -1
- package/dist/src/tunnel/frpc-extract.js +1 -1
- package/dist/src/tunnel/pairing-rate-limit.d.ts +10 -2
- package/dist/src/tunnel/pairing-rate-limit.js +19 -15
- package/dist/src/tunnel/pairing-rate-limit.js.map +1 -1
- package/dist/src/tunnel/tunnel-rate-limit.d.ts +6 -3
- package/dist/src/tunnel/tunnel-rate-limit.js +11 -22
- package/dist/src/tunnel/tunnel-rate-limit.js.map +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/utils/logger/stats.d.ts +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/dist/src/voice/tts/factory.js +1 -1
- package/dist/src/voice/tts/index.js +2 -2
- package/dist/src/voice/tts/merge-config.js +1 -1
- package/dist/src/voice/tts/providers/edge-speech.js +1 -1
- package/dist/src/voice/tts/service.js +1 -1
- package/dist/src/voice/tts/service.js.map +1 -1
- package/dist/src/voice/tts/speak-core.js +1 -1
- package/package.json +10 -5
- package/dist/gateway/static/root/assets/agents-Cqh1ts38.js +0 -222
- package/dist/gateway/static/root/assets/channels-settings-wTiWStg9.js +0 -1
- package/dist/gateway/static/root/assets/fetch-BAAh_kXG.js +0 -3
- package/dist/gateway/static/root/assets/index-C8yHX-AA.css +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BeiFm0Ms.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-RPAz_Wg_.js +0 -3
- package/dist/gateway/static/root/assets/skills-page-Wu4aNWDx.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-BxIGhhEL.js +0 -1
- package/dist/src/agent/embedded/session-raw-append-message.d.ts +0 -11
- package/dist/src/agent/embedded/session-raw-append-message.js +0 -15
- package/dist/src/agent/embedded/session-raw-append-message.js.map +0 -1
- package/dist/src/agent/embedded/session-tool-result-guard-wrapper.d.ts +0 -15
- package/dist/src/agent/embedded/session-tool-result-guard-wrapper.js +0 -24
- package/dist/src/agent/embedded/session-tool-result-guard-wrapper.js.map +0 -1
- package/dist/src/agent/embedded/session-tool-result-state.d.ts +0 -17
- package/dist/src/agent/embedded/session-tool-result-state.js +0 -26
- package/dist/src/agent/embedded/session-tool-result-state.js.map +0 -1
- package/dist/src/daemon/launchd-restart-handoff.d.ts +0 -25
- package/dist/src/daemon/launchd-restart-handoff.js +0 -132
- package/dist/src/daemon/launchd-restart-handoff.js.map +0 -1
- package/dist/src/gateway/auth-rate-limit.d.ts +0 -71
- package/dist/src/gateway/auth-rate-limit.js +0 -192
- package/dist/src/gateway/auth-rate-limit.js.map +0 -1
- package/dist/src/gateway/restart-handler.d.ts +0 -14
- package/dist/src/gateway/restart-handler.js +0 -64
- package/dist/src/gateway/restart-handler.js.map +0 -1
- package/dist/src/gateway/security/flood-guard.d.ts +0 -28
- package/dist/src/gateway/security/flood-guard.js +0 -42
- package/dist/src/gateway/security/flood-guard.js.map +0 -1
- package/dist/src/infra/rate-limit.d.ts +0 -38
- package/dist/src/infra/rate-limit.js +0 -60
- package/dist/src/infra/rate-limit.js.map +0 -1
- package/dist/src/infra/restart-intent.d.ts +0 -13
- package/dist/src/infra/restart-intent.js +0 -40
- package/dist/src/infra/restart-intent.js.map +0 -1
- package/dist/src/infra/restart-sentinel.d.ts +0 -23
- package/dist/src/infra/restart-sentinel.js +0 -75
- package/dist/src/infra/restart-sentinel.js.map +0 -1
- package/skills/creative/canvas-design/LICENSE.txt +0 -202
- package/skills/creative/canvas-design/SKILL-zh.md +0 -130
- package/skills/creative/canvas-design/SKILL.md +0 -130
- package/skills/creative/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
- package/skills/creative/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/skills/creative/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
- package/skills/creative/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.js","names":[],"sources":["../../../../../src/gateway/hono/routes/mcp.ts"],"sourcesContent":["import type { Hono } from 'hono';\nimport { getWorkspacePath } from '../../../config/
|
|
1
|
+
{"version":3,"file":"mcp.js","names":[],"sources":["../../../../../src/gateway/hono/routes/mcp.ts"],"sourcesContent":["import type { Hono } from 'hono';\nimport { getWorkspacePath } from '../../../config/workspace-path-helpers.js';\nimport { normalizeConfiguredMcpServers, canonicalizeConfiguredMcpServer } from '../../../config/mcp-config-normalize.js';\nimport { loadMergedBundleMcpConfig } from '../../../agent/mcp/bundle-mcp-config.js';\nimport {\n createBundleMcpToolRuntime,\n listBundleMcpServerToolsForGateway,\n mapBundleMcpToolsForGateway,\n} from '../../../agent/mcp/bundle-mcp-materialize.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nexport function registerMcpRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n authenticated.get('/api/mcp/servers', (c) => {\n const cfg = deps.service.currentConfig;\n const workspaceDir = getWorkspacePath(cfg) || './workspace';\n const merged = loadMergedBundleMcpConfig({\n workspaceDir,\n cfg,\n });\n return c.json({\n ok: true,\n payload: {\n servers: Object.keys(merged.config.mcpServers).sort(),\n configured: normalizeConfiguredMcpServers(cfg.mcp?.servers),\n },\n });\n });\n\n authenticated.get('/api/mcp/servers/:id/tools', async (c) => {\n const id = c.req.param('id');\n const cfg = deps.service.currentConfig;\n const workspaceDir = getWorkspacePath(cfg) || './workspace';\n try {\n const tools = await listBundleMcpServerToolsForGateway({\n workspaceDir,\n cfg,\n serverId: id,\n });\n return c.json({ ok: true, payload: { tools } });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : String(err) },\n 500,\n );\n }\n });\n\n authenticated.post('/api/mcp/servers/:id/test', async (c) => {\n const id = c.req.param('id');\n const cfg = deps.service.currentConfig;\n const workspaceDir = getWorkspacePath(cfg) || './workspace';\n const body = await c.req.json().catch(() => ({}));\n const inlineServer =\n body && typeof body === 'object' && !Array.isArray(body) && body.server && typeof body.server === 'object'\n ? (body.server as Record<string, unknown>)\n : undefined;\n const servers = normalizeConfiguredMcpServers(cfg.mcp?.servers);\n const mergedServers = loadMergedBundleMcpConfig({ workspaceDir, cfg }).config.mcpServers;\n const knownServer =\n inlineServer ??\n (servers[id] as Record<string, unknown> | undefined) ??\n (mergedServers[id] as Record<string, unknown> | undefined);\n if (!knownServer) {\n return c.json({ ok: false, error: `Unknown MCP server: ${id}` }, 404);\n }\n try {\n const testCfg: typeof cfg = inlineServer\n ? {\n ...cfg,\n mcp: {\n ...cfg.mcp,\n servers: {\n [id]: canonicalizeConfiguredMcpServer(inlineServer),\n },\n },\n }\n : cfg;\n const runtime = await createBundleMcpToolRuntime({\n workspaceDir,\n cfg: testCfg,\n });\n const tools = mapBundleMcpToolsForGateway(runtime.tools, id);\n await runtime.dispose();\n return c.json({ ok: true, payload: { serverId: id, toolCount: tools.length, tools } });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : String(err) },\n 500,\n );\n }\n });\n\n authenticated.post('/api/mcp/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"],"mappings":";;;;;AAWA,SAAgB,kBAAkB,eAAqB,MAAoC;AACzF,eAAc,IAAI,qBAAqB,MAAM;EAC3C,MAAM,MAAM,KAAK,QAAQ;EAEzB,MAAM,SAAS,0BAA0B;GACvC,cAFmB,iBAAiB,IAAI,IAAI;GAG5C;GACD,CAAC;AACF,SAAO,EAAE,KAAK;GACZ,IAAI;GACJ,SAAS;IACP,SAAS,OAAO,KAAK,OAAO,OAAO,WAAW,CAAC,MAAM;IACrD,YAAY,8BAA8B,IAAI,KAAK,QAAQ;IAC5D;GACF,CAAC;GACF;AAEF,eAAc,IAAI,8BAA8B,OAAO,MAAM;EAC3D,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;EAC5B,MAAM,MAAM,KAAK,QAAQ;EACzB,MAAM,eAAe,iBAAiB,IAAI,IAAI;AAC9C,MAAI;GACF,MAAM,QAAQ,MAAM,mCAAmC;IACrD;IACA;IACA,UAAU;IACX,CAAC;AACF,UAAO,EAAE,KAAK;IAAE,IAAI;IAAM,SAAS,EAAE,OAAO;IAAE,CAAC;WACxC,KAAK;AACZ,UAAO,EAAE,KACP;IAAE,IAAI;IAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;IAAE,EACtE,IACD;;GAEH;AAEF,eAAc,KAAK,6BAA6B,OAAO,MAAM;EAC3D,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;EAC5B,MAAM,MAAM,KAAK,QAAQ;EACzB,MAAM,eAAe,iBAAiB,IAAI,IAAI;EAC9C,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,eACJ,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAI,KAAK,UAAU,OAAO,KAAK,WAAW,WAC7F,KAAK,SACN,KAAA;EACN,MAAM,UAAU,8BAA8B,IAAI,KAAK,QAAQ;EAC/D,MAAM,gBAAgB,0BAA0B;GAAE;GAAc;GAAK,CAAC,CAAC,OAAO;AAK9E,MAAI,EAHF,gBACC,QAAQ,OACR,cAAc,KAEf,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO,uBAAuB;GAAM,EAAE,IAAI;AAEvE,MAAI;GAYF,MAAM,UAAU,MAAM,2BAA2B;IAC/C;IACA,KAb0B,eACxB;KACE,GAAG;KACH,KAAK;MACH,GAAG,IAAI;MACP,SAAS,GACN,KAAK,gCAAgC,aAAa,EACpD;MACF;KACF,GACD;IAIH,CAAC;GACF,MAAM,QAAQ,4BAA4B,QAAQ,OAAO,GAAG;AAC5D,SAAM,QAAQ,SAAS;AACvB,UAAO,EAAE,KAAK;IAAE,IAAI;IAAM,SAAS;KAAE,UAAU;KAAI,WAAW,MAAM;KAAQ;KAAO;IAAE,CAAC;WAC/E,KAAK;AACZ,UAAO,EAAE,KACP;IAAE,IAAI;IAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;IAAE,EACtE,IACD;;GAEH;AAEF,eAAc,KAAK,8BAA8B,OAAO,MAAM;EAC5D,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;AACjD,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM,SAAS;IAAE,cAAc;IAAM;IAAM;GAAE,CAAC;GAClE"}
|
|
@@ -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, getProviderActiveKeySource, init_providers, isProviderConfigured } from "../../../providers/index.js";
|
|
8
8
|
import { getImageGenerationProvider } from "../../../agent/image/generation/provider-registry.js";
|
|
@@ -27,10 +27,10 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
27
27
|
peerId: body.chat_id
|
|
28
28
|
});
|
|
29
29
|
await service.sessionManagerInstance.saveMessages(sessionKey, []);
|
|
30
|
-
const session = await service.getSession(sessionKey);
|
|
30
|
+
const session = await service.sessions.getSession(sessionKey);
|
|
31
31
|
return c.json({ session }, 201);
|
|
32
32
|
}
|
|
33
|
-
const emptySession = (await service.listSessions({
|
|
33
|
+
const emptySession = (await service.sessions.listSessions({
|
|
34
34
|
channel,
|
|
35
35
|
limit: 50,
|
|
36
36
|
sortBy: "updatedAt",
|
|
@@ -40,7 +40,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
40
40
|
return parseSessionKey(s.key)?.agentId === agentId;
|
|
41
41
|
});
|
|
42
42
|
if (emptySession) {
|
|
43
|
-
const session = await service.getSession(emptySession.key);
|
|
43
|
+
const session = await service.sessions.getSession(emptySession.key);
|
|
44
44
|
return c.json({
|
|
45
45
|
session,
|
|
46
46
|
reused: true
|
|
@@ -55,14 +55,14 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
55
55
|
peerId: chatId
|
|
56
56
|
});
|
|
57
57
|
await service.sessionManagerInstance.saveMessages(sessionKey, []);
|
|
58
|
-
const session = await service.getSession(sessionKey);
|
|
58
|
+
const session = await service.sessions.getSession(sessionKey);
|
|
59
59
|
return c.json({ session }, 201);
|
|
60
60
|
});
|
|
61
61
|
authenticated.get("/api/sessions", async (c) => {
|
|
62
62
|
const blocked = ensureGatewayReadyForSessions(c, service, "sessions.list");
|
|
63
63
|
if (blocked) return blocked;
|
|
64
64
|
const query = c.req.query();
|
|
65
|
-
const result = await service.listSessions({
|
|
65
|
+
const result = await service.sessions.listSessions({
|
|
66
66
|
status: query.status,
|
|
67
67
|
search: query.search,
|
|
68
68
|
channel: query.channel,
|
|
@@ -72,12 +72,12 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
72
72
|
return c.json(result);
|
|
73
73
|
});
|
|
74
74
|
authenticated.get("/api/sessions/stats", async (c) => {
|
|
75
|
-
const result = await service.
|
|
75
|
+
const result = await service.sessions.stats();
|
|
76
76
|
return c.json(result);
|
|
77
77
|
});
|
|
78
78
|
authenticated.get("/api/sessions/chat-ids", async (c) => {
|
|
79
79
|
const channel = c.req.query("channel");
|
|
80
|
-
const chatIds = await service.
|
|
80
|
+
const chatIds = await service.sessions.chatIds(channel || void 0);
|
|
81
81
|
return c.json({
|
|
82
82
|
ok: true,
|
|
83
83
|
payload: { chatIds }
|
|
@@ -87,18 +87,18 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
87
87
|
const blocked = ensureGatewayReadyForSessions(c, service, "sessions.run");
|
|
88
88
|
if (blocked) return blocked;
|
|
89
89
|
const key = c.req.param("key");
|
|
90
|
-
if (!await service.getSession(key)) return c.json({
|
|
90
|
+
if (!await service.sessions.getSession(key)) return c.json({
|
|
91
91
|
ok: false,
|
|
92
92
|
error: "Session not found"
|
|
93
93
|
}, 404);
|
|
94
94
|
return c.json({
|
|
95
95
|
ok: true,
|
|
96
|
-
payload: service.
|
|
96
|
+
payload: service.sessions.getActiveRun(key)
|
|
97
97
|
});
|
|
98
98
|
});
|
|
99
99
|
authenticated.get("/api/sessions/:key/agent-config", async (c) => {
|
|
100
100
|
const key = c.req.param("key");
|
|
101
|
-
const payload = await service.
|
|
101
|
+
const payload = await service.sessions.getAgentConfig(key);
|
|
102
102
|
return c.json({
|
|
103
103
|
ok: true,
|
|
104
104
|
payload
|
|
@@ -107,7 +107,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
107
107
|
authenticated.patch("/api/sessions/:key/agent-config", async (c) => {
|
|
108
108
|
const key = c.req.param("key");
|
|
109
109
|
const body = await c.req.json().catch(() => ({}));
|
|
110
|
-
const result = await service.
|
|
110
|
+
const result = await service.sessions.patchAgentConfig(key, body);
|
|
111
111
|
if (!result.ok) return c.json({
|
|
112
112
|
ok: false,
|
|
113
113
|
error: result.error
|
|
@@ -125,7 +125,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
125
125
|
const offsetRaw = c.req.query("offset");
|
|
126
126
|
const parsedOffset = offsetRaw ? Number.parseInt(offsetRaw, 10) : 0;
|
|
127
127
|
const offset = Number.isFinite(parsedOffset) ? Math.max(0, parsedOffset) : 0;
|
|
128
|
-
const result = await service.
|
|
128
|
+
const result = await service.sessions.getMessagePage(key, {
|
|
129
129
|
limit,
|
|
130
130
|
offset,
|
|
131
131
|
...before ? { before } : {}
|
|
@@ -152,7 +152,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
152
152
|
const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : 50;
|
|
153
153
|
const offset = Number.isFinite(parsedOffset) ? Math.max(0, parsedOffset) : 0;
|
|
154
154
|
const limit = Number.isFinite(parsedLimit) ? Math.min(200, Math.max(1, parsedLimit)) : 50;
|
|
155
|
-
const result = await service.
|
|
155
|
+
const result = await service.sessions.getMessagePage(key, {
|
|
156
156
|
offset,
|
|
157
157
|
limit,
|
|
158
158
|
...before ? { before } : {}
|
|
@@ -183,7 +183,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
183
183
|
ok: false,
|
|
184
184
|
error: "Session not found"
|
|
185
185
|
}, 404);
|
|
186
|
-
const checkpoints = await service.
|
|
186
|
+
const checkpoints = await service.sessions.listCompactionCheckpoints(key);
|
|
187
187
|
return c.json({
|
|
188
188
|
ok: true,
|
|
189
189
|
payload: { checkpoints }
|
|
@@ -192,7 +192,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
192
192
|
authenticated.get("/api/sessions/:key/compaction/checkpoints/:checkpointId", async (c) => {
|
|
193
193
|
const key = c.req.param("key");
|
|
194
194
|
const checkpointId = c.req.param("checkpointId");
|
|
195
|
-
const checkpoint = await service.
|
|
195
|
+
const checkpoint = await service.sessions.getCompactionCheckpoint(key, checkpointId);
|
|
196
196
|
if (!checkpoint) return c.json({
|
|
197
197
|
ok: false,
|
|
198
198
|
error: "Checkpoint not found"
|
|
@@ -211,7 +211,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
211
211
|
error: "checkpointId required"
|
|
212
212
|
}, 400);
|
|
213
213
|
try {
|
|
214
|
-
await service.
|
|
214
|
+
await service.sessions.restoreCompactionCheckpoint(key, checkpointId);
|
|
215
215
|
} catch (err) {
|
|
216
216
|
const msg = err instanceof Error ? err.message : String(err);
|
|
217
217
|
if (msg.includes("not found") || msg.includes("Invalid")) return c.json({
|
|
@@ -223,7 +223,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
223
223
|
error: msg
|
|
224
224
|
}, 500);
|
|
225
225
|
}
|
|
226
|
-
const session = await service.getSession(key);
|
|
226
|
+
const session = await service.sessions.getSession(key);
|
|
227
227
|
if (!session) return c.json({
|
|
228
228
|
ok: false,
|
|
229
229
|
error: "Session not found"
|
|
@@ -235,14 +235,14 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
235
235
|
});
|
|
236
236
|
authenticated.post("/api/sessions/:key/compaction/run", async (c) => {
|
|
237
237
|
const key = c.req.param("key");
|
|
238
|
-
if (!await service.getSession(key)) return c.json({
|
|
238
|
+
if (!await service.sessions.getSession(key)) return c.json({
|
|
239
239
|
ok: false,
|
|
240
240
|
error: "Session not found"
|
|
241
241
|
}, 404);
|
|
242
242
|
const body = await c.req.json().catch(() => ({}));
|
|
243
243
|
const instructions = typeof body.instructions === "string" ? body.instructions : void 0;
|
|
244
244
|
const force = typeof body.force === "boolean" ? body.force : true;
|
|
245
|
-
const result = await service.
|
|
245
|
+
const result = await service.sessions.runCompaction(key, {
|
|
246
246
|
instructions,
|
|
247
247
|
force
|
|
248
248
|
});
|
|
@@ -266,7 +266,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
266
266
|
const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : 50;
|
|
267
267
|
const offset = Number.isFinite(parsedOffset) ? Math.max(0, parsedOffset) : 0;
|
|
268
268
|
const limit = Number.isFinite(parsedLimit) ? Math.min(200, Math.max(1, parsedLimit)) : 50;
|
|
269
|
-
const result = await service.
|
|
269
|
+
const result = await service.sessions.getMessagePage(key, {
|
|
270
270
|
offset,
|
|
271
271
|
limit,
|
|
272
272
|
includeTranscriptSummary: includeTranscript,
|
|
@@ -275,7 +275,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
275
275
|
if (!result) return c.json({ error: "Session not found" }, 404);
|
|
276
276
|
return c.json(result);
|
|
277
277
|
}
|
|
278
|
-
const session = await service.getSession(key, {
|
|
278
|
+
const session = await service.sessions.getSession(key, {
|
|
279
279
|
includeTranscriptSummary: includeTranscript,
|
|
280
280
|
includeTranscriptRows
|
|
281
281
|
});
|
|
@@ -290,12 +290,12 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
290
290
|
if (Array.isArray(body.tags)) patch.tags = body.tags;
|
|
291
291
|
if (typeof body.replaceTags === "boolean") patch.replaceTags = body.replaceTags;
|
|
292
292
|
if (body.customData !== void 0 && typeof body.customData === "object" && body.customData !== null) patch.customData = body.customData;
|
|
293
|
-
const result = await service.
|
|
293
|
+
const result = await service.sessions.patch(key, patch);
|
|
294
294
|
if (result.ok === false) return c.json({
|
|
295
295
|
ok: false,
|
|
296
296
|
error: result.error
|
|
297
297
|
}, 404);
|
|
298
|
-
const session = await service.getSession(key);
|
|
298
|
+
const session = await service.sessions.getSession(key);
|
|
299
299
|
return c.json({
|
|
300
300
|
ok: true,
|
|
301
301
|
session
|
|
@@ -304,7 +304,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
304
304
|
authenticated.get("/api/sessions/:key/export", async (c) => {
|
|
305
305
|
const key = c.req.param("key");
|
|
306
306
|
const format = c.req.query("format") || "json";
|
|
307
|
-
const result = await service.
|
|
307
|
+
const result = await service.sessions.export(key, format);
|
|
308
308
|
return c.json(result);
|
|
309
309
|
});
|
|
310
310
|
authenticated.delete("/api/sessions/:key/messages", async (c) => {
|
|
@@ -333,38 +333,38 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
333
333
|
});
|
|
334
334
|
authenticated.delete("/api/sessions/:key", async (c) => {
|
|
335
335
|
const key = c.req.param("key");
|
|
336
|
-
const result = await service.
|
|
336
|
+
const result = await service.sessions.delete(key);
|
|
337
337
|
return c.json(result);
|
|
338
338
|
});
|
|
339
339
|
authenticated.post("/api/sessions/:key/archive", async (c) => {
|
|
340
340
|
const key = c.req.param("key");
|
|
341
|
-
const result = await service.
|
|
341
|
+
const result = await service.sessions.archive(key);
|
|
342
342
|
return c.json(result);
|
|
343
343
|
});
|
|
344
344
|
authenticated.post("/api/sessions/:key/unarchive", async (c) => {
|
|
345
345
|
const key = c.req.param("key");
|
|
346
|
-
const result = await service.
|
|
346
|
+
const result = await service.sessions.unarchive(key);
|
|
347
347
|
return c.json(result);
|
|
348
348
|
});
|
|
349
349
|
authenticated.post("/api/sessions/:key/pin", async (c) => {
|
|
350
350
|
const key = c.req.param("key");
|
|
351
|
-
const result = await service.
|
|
351
|
+
const result = await service.sessions.pin(key);
|
|
352
352
|
return c.json(result);
|
|
353
353
|
});
|
|
354
354
|
authenticated.post("/api/sessions/:key/unpin", async (c) => {
|
|
355
355
|
const key = c.req.param("key");
|
|
356
|
-
const result = await service.
|
|
356
|
+
const result = await service.sessions.unpin(key);
|
|
357
357
|
return c.json(result);
|
|
358
358
|
});
|
|
359
359
|
authenticated.post("/api/sessions/:key/rename", async (c) => {
|
|
360
360
|
const key = c.req.param("key");
|
|
361
361
|
const { name } = await c.req.json();
|
|
362
|
-
const result = await service.
|
|
362
|
+
const result = await service.sessions.rename(key, name);
|
|
363
363
|
return c.json(result);
|
|
364
364
|
});
|
|
365
365
|
authenticated.get("/api/subagents", async (c) => {
|
|
366
366
|
const query = c.req.query();
|
|
367
|
-
const result = await service.listSubagents({
|
|
367
|
+
const result = await service.sessions.listSubagents({
|
|
368
368
|
limit: query.limit ? parseInt(query.limit) : void 0,
|
|
369
369
|
offset: query.offset ? parseInt(query.offset) : void 0
|
|
370
370
|
});
|
|
@@ -375,7 +375,7 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
375
375
|
if (!key.startsWith("subagent:")) return c.json({ error: "Not a subagent session" }, 400);
|
|
376
376
|
const includeRaw = c.req.query("include") ?? "";
|
|
377
377
|
const includeSet = new Set(includeRaw.split(",").map((s) => s.trim()).filter(Boolean));
|
|
378
|
-
const session = await service.getSession(key, {
|
|
378
|
+
const session = await service.sessions.getSession(key, {
|
|
379
379
|
includeTranscriptSummary: includeSet.has("transcript"),
|
|
380
380
|
includeTranscriptRows: includeSet.has("transcriptRows")
|
|
381
381
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.js","names":[],"sources":["../../../../../src/gateway/hono/routes/sessions.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { buildSessionKey, parseSessionKey } from '../../../routing/session-key.js';\nimport { agentExists, getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\nimport { messagesToClientHistory } from '../../../session/client-history.js';\nimport { computeUserRoundDeleteRange } from '../../../session/user-round-delete.js';\nimport { respondStartupUnavailable } from '../lib/startup-unavailable.js';\nimport type { StartupUnavailableGatewayMethod } from '../../startup-readiness.js';\n\ntype SessionsStartupMethod = StartupUnavailableGatewayMethod;\n\nfunction ensureGatewayReadyForSessions(\n c: Parameters<typeof respondStartupUnavailable>[0],\n service: AuthenticatedRouteDeps['service'],\n method: SessionsStartupMethod,\n): Response | null {\n if (service.isGatewayReady()) {\n return null;\n }\n return respondStartupUnavailable(c, method);\n}\n\nexport function registerSessionsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // ========== Session REST API (/api/sessions) ==========\n\n // POST /api/sessions - Create new session (reuses empty sessions)\n authenticated.post('/api/sessions', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const channel = body.channel || 'webchat';\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 // If a specific chat_id is provided, use it (for advanced use cases)\n // Otherwise, try to find and reuse an existing empty session\n if (body.chat_id) {\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: body.chat_id,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n const session = await service.getSession(sessionKey);\n return c.json({ session }, 201);\n }\n \n // Look for existing empty sessions to reuse\n const existingSessions = await service.listSessions({\n channel,\n limit: 50,\n sortBy: 'updatedAt',\n sortOrder: 'desc',\n });\n \n // Reuse an empty session only when it matches the requested agent (session key embeds agent id).\n const emptySession = existingSessions.items.find((s) => {\n if (s.messageCount !== 0) return false;\n const parsed = parseSessionKey(s.key);\n return parsed?.agentId === agentId;\n });\n \n if (emptySession) {\n // Return existing empty session instead of creating a new one\n const session = await service.getSession(emptySession.key);\n return c.json({ session, reused: true }, 200);\n }\n \n // No empty session found, create a new one\n const chatId = `chat_${Date.now()}`;\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: chatId,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n\n const session = await service.getSession(sessionKey);\n return c.json({ session }, 201);\n });\n\n // GET /api/sessions - List sessions\n authenticated.get('/api/sessions', async (c) => {\n const blocked = ensureGatewayReadyForSessions(c, service, 'sessions.list');\n if (blocked) {\n return blocked;\n }\n const query = c.req.query();\n const result = await service.listSessions({\n status: query.status as any,\n search: query.search,\n channel: query.channel,\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/sessions/stats - Get session stats (must be before /:key)\n authenticated.get('/api/sessions/stats', async (c) => {\n const result = await service.getSessionStats();\n return c.json(result);\n });\n\n // GET /api/sessions/chat-ids - Get unique chat IDs from sessions (must be before /:key)\n authenticated.get('/api/sessions/chat-ids', async (c) => {\n const channel = c.req.query('channel');\n const chatIds = await service.getSessionChatIds(channel || undefined);\n return c.json({ ok: true, payload: { chatIds } });\n });\n\n // GET /api/sessions/:key/run — read-only active webchat agent run (for UI resume)\n authenticated.get('/api/sessions/:key/run', async (c) => {\n const blocked = ensureGatewayReadyForSessions(c, service, 'sessions.run');\n if (blocked) {\n return blocked;\n }\n const key = c.req.param('key');\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n return c.json({ ok: true, payload: service.getSessionActiveRun(key) });\n });\n\n // GET /api/sessions/:key/agent-config — resolved session agent settings (thinking, etc.)\n authenticated.get('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const payload = await service.getSessionAgentConfig(key);\n return c.json({ ok: true, payload });\n });\n\n authenticated.patch('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const result = await service.patchSessionAgentConfig(key, body);\n if (!result.ok) {\n return c.json({ ok: false, error: result.error }, 400);\n }\n return c.json({ ok: true });\n });\n\n // GET /api/sessions/:key/messages — flattened transcript for TUI / clients\n authenticated.get('/api/sessions/:key/messages', async (c) => {\n const blocked = ensureGatewayReadyForSessions(c, service, 'sessions.messages');\n if (blocked) {\n return blocked;\n }\n const key = c.req.param('key');\n const limitRaw = c.req.query('limit');\n const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : undefined;\n const limit =\n parsedLimit !== undefined && Number.isFinite(parsedLimit)\n ? Math.min(500, Math.max(1, parsedLimit))\n : undefined;\n\n const before = c.req.query('before')?.trim();\n const offsetRaw = c.req.query('offset');\n const parsedOffset = offsetRaw ? Number.parseInt(offsetRaw, 10) : 0;\n const offset = Number.isFinite(parsedOffset) ? Math.max(0, parsedOffset) : 0;\n\n const result = await service.getSessionMessagePage(key, {\n limit,\n offset,\n ...(before ? { before } : {}),\n });\n if (!result) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n\n const messages = messagesToClientHistory(result.session.messages, { limit });\n return c.json({\n ok: true,\n payload: { messages },\n pagination: result.pagination,\n });\n });\n\n // GET /api/sessions/:key/history — UI chat history page from the newest tail.\n authenticated.get('/api/sessions/:key/history', async (c) => {\n const blocked = ensureGatewayReadyForSessions(c, service, 'sessions.history');\n if (blocked) {\n return blocked;\n }\n const key = c.req.param('key');\n const offsetRaw = c.req.query('offset');\n const limitRaw = c.req.query('limit');\n const before = c.req.query('before')?.trim();\n const parsedOffset = offsetRaw ? Number.parseInt(offsetRaw, 10) : 0;\n const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : 50;\n const offset = Number.isFinite(parsedOffset) ? Math.max(0, parsedOffset) : 0;\n const limit = Number.isFinite(parsedLimit) ? Math.min(200, Math.max(1, parsedLimit)) : 50;\n const result = await service.getSessionMessagePage(key, {\n offset,\n limit,\n ...(before ? { before } : {}),\n });\n\n if (!result) {\n return c.json({ error: 'Session not found' }, 404);\n }\n\n return c.json(result);\n });\n\n // POST /api/sessions/:key/transcript/context — append persisted-only `kind: 'context'` row (not in LLM context)\n authenticated.post('/api/sessions/:key/transcript/context', async (c) => {\n const key = c.req.param('key');\n const meta = await service.sessionManagerInstance.getSessionMetadata(key);\n if (!meta) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n const body = await c.req.json().catch(() => ({}));\n const id = typeof body.id === 'string' && body.id.trim() ? body.id.trim() : undefined;\n const text = typeof body.text === 'string' ? body.text : undefined;\n const data =\n body.data !== undefined && typeof body.data === 'object' && body.data !== null && !Array.isArray(body.data)\n ? (body.data as Record<string, unknown>)\n : undefined;\n await service.sessionManagerInstance.appendTranscriptContextEntry(key, { id, text, data });\n return c.json({ ok: true });\n });\n\n // GET /api/sessions/:key/compaction/checkpoints — list pre-compaction snapshots (OpenClaw-style)\n authenticated.get('/api/sessions/:key/compaction/checkpoints', async (c) => {\n const key = c.req.param('key');\n const meta = await service.sessionManagerInstance.getSessionMetadata(key);\n if (!meta) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n const checkpoints = await service.listSessionCompactionCheckpoints(key);\n return c.json({ ok: true, payload: { checkpoints } });\n });\n\n authenticated.get('/api/sessions/:key/compaction/checkpoints/:checkpointId', async (c) => {\n const key = c.req.param('key');\n const checkpointId = c.req.param('checkpointId');\n const checkpoint = await service.getSessionCompactionCheckpoint(key, checkpointId);\n if (!checkpoint) {\n return c.json({ ok: false, error: 'Checkpoint not found' }, 404);\n }\n return c.json({ ok: true, payload: { checkpoint } });\n });\n\n authenticated.post('/api/sessions/:key/compaction/restore', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const checkpointId = typeof body.checkpointId === 'string' ? body.checkpointId.trim() : '';\n if (!checkpointId) {\n return c.json({ ok: false, error: 'checkpointId required' }, 400);\n }\n try {\n await service.restoreSessionCompactionCheckpoint(key, checkpointId);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes('not found') || msg.includes('Invalid')) {\n return c.json({ ok: false, error: msg }, 404);\n }\n return c.json({ ok: false, error: msg }, 500);\n }\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n return c.json({ ok: true, session });\n });\n\n authenticated.post('/api/sessions/:key/compaction/run', async (c) => {\n const key = c.req.param('key');\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n const body = await c.req.json().catch(() => ({}));\n const instructions = typeof body.instructions === 'string' ? body.instructions : undefined;\n const force = typeof body.force === 'boolean' ? body.force : true;\n const result = await service.runSessionCompaction(key, { instructions, force });\n return c.json({ ok: true, payload: { result } });\n });\n\n // GET /api/sessions/:key - Get single session (must be after /stats and /chat-ids)\n authenticated.get('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const includeRaw = c.req.query('include') ?? '';\n const includeSet = new Set(\n includeRaw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n );\n const includeTranscript = includeSet.has('transcript');\n const includeTranscriptRows = includeSet.has('transcriptRows');\n const offsetRaw = c.req.query('offset');\n const limitRaw = c.req.query('limit');\n const hasPagingQuery = offsetRaw !== undefined || limitRaw !== undefined;\n\n if (hasPagingQuery) {\n const blocked = ensureGatewayReadyForSessions(c, service, 'sessions.history');\n if (blocked) {\n return blocked;\n }\n const parsedOffset = offsetRaw ? Number.parseInt(offsetRaw, 10) : 0;\n const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : 50;\n const offset = Number.isFinite(parsedOffset) ? Math.max(0, parsedOffset) : 0;\n const limit = Number.isFinite(parsedLimit) ? Math.min(200, Math.max(1, parsedLimit)) : 50;\n const result = await service.getSessionMessagePage(key, {\n offset,\n limit,\n includeTranscriptSummary: includeTranscript,\n includeTranscriptRows,\n });\n if (!result) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json(result);\n }\n\n const session = await service.getSession(key, {\n includeTranscriptSummary: includeTranscript,\n includeTranscriptRows,\n });\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json({ session });\n });\n\n // PATCH /api/sessions/:key - Partial metadata (name, tags, customData); OpenClaw-style patch subset\n authenticated.patch('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const patch: {\n name?: string;\n tags?: string[];\n replaceTags?: boolean;\n customData?: Record<string, unknown>;\n } = {};\n if (typeof body.name === 'string') {\n patch.name = body.name;\n }\n if (Array.isArray(body.tags)) {\n patch.tags = body.tags;\n }\n if (typeof body.replaceTags === 'boolean') {\n patch.replaceTags = body.replaceTags;\n }\n if (body.customData !== undefined && typeof body.customData === 'object' && body.customData !== null) {\n patch.customData = body.customData as Record<string, unknown>;\n }\n const result = await service.patchSession(key, patch);\n if (result.ok === false) {\n return c.json({ ok: false, error: result.error }, 404);\n }\n const session = await service.getSession(key);\n return c.json({ ok: true, session });\n });\n\n // GET /api/sessions/:key/export - Export session (must be before /:key)\n authenticated.get('/api/sessions/:key/export', async (c) => {\n const key = c.req.param('key');\n const format = c.req.query('format') as any || 'json';\n const result = await service.exportSession(key, format);\n return c.json(result);\n });\n\n // DELETE /api/sessions/:key/messages — delete LLM rows by range or by user turn.\n // `userRoundIndex` (0-based among user messages) removes the user row and every following\n // assistant / tool / toolResult row until the next user. Prefer this from the web console so\n // tool loops are not left orphaned after retry/delete.\n authenticated.delete('/api/sessions/:key/messages', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const loaded = await service.sessionManagerInstance.loadMessages(key);\n if (!loaded) {\n return c.json({ error: 'Session not found' }, 404);\n }\n\n let startIndex = typeof body.startIndex === 'number' ? body.startIndex : -1;\n let count = typeof body.count === 'number' ? body.count : 0;\n const userRoundIndex =\n typeof body.userRoundIndex === 'number' ? body.userRoundIndex : undefined;\n\n if (userRoundIndex !== undefined) {\n const range = computeUserRoundDeleteRange(loaded, userRoundIndex);\n if (!range) {\n return c.json({ error: 'User round index out of range' }, 400);\n }\n startIndex = range.startIndex;\n count = range.count;\n }\n\n if (startIndex < 0 || count <= 0) {\n return c.json({ error: 'Invalid startIndex or count' }, 400);\n }\n if (startIndex >= loaded.length) {\n return c.json({ error: 'Index out of range' }, 400);\n }\n const deleteCount = Math.min(count, loaded.length - startIndex);\n const next = loaded.slice(0, startIndex).concat(loaded.slice(startIndex + deleteCount));\n await service.sessionManagerInstance.saveMessages(key, next);\n return c.json({ ok: true, deleted: deleteCount });\n });\n\n // DELETE /api/sessions/:key - Delete session\n authenticated.delete('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const result = await service.deleteSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/archive - Archive session\n authenticated.post('/api/sessions/:key/archive', async (c) => {\n const key = c.req.param('key');\n const result = await service.archiveSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unarchive - Unarchive session\n authenticated.post('/api/sessions/:key/unarchive', async (c) => {\n const key = c.req.param('key');\n const result = await service.unarchiveSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/pin - Pin session\n authenticated.post('/api/sessions/:key/pin', async (c) => {\n const key = c.req.param('key');\n const result = await service.pinSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unpin - Unpin session\n authenticated.post('/api/sessions/:key/unpin', async (c) => {\n const key = c.req.param('key');\n const result = await service.unpinSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/rename - Rename session\n authenticated.post('/api/sessions/:key/rename', async (c) => {\n const key = c.req.param('key');\n\n const body = await c.req.json();\n const { name } = body;\n const result = await service.renameSession(key, name);\n return c.json(result);\n });\n\n // ========== Subagent REST API (/api/subagents) ==========\n\n // GET /api/subagents - List subagent sessions\n authenticated.get('/api/subagents', async (c) => {\n const query = c.req.query();\n const result = await service.listSubagents({\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/subagents/:key - Get subagent session detail\n authenticated.get('/api/subagents/:key', async (c) => {\n const key = c.req.param('key');\n // Verify it's a subagent session\n if (!key.startsWith('subagent:')) {\n return c.json({ error: 'Not a subagent session' }, 400);\n }\n const includeRaw = c.req.query('include') ?? '';\n const includeSet = new Set(\n includeRaw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n );\n const session = await service.getSession(key, {\n includeTranscriptSummary: includeSet.has('transcript'),\n includeTranscriptRows: includeSet.has('transcriptRows'),\n });\n if (!session) {\n return c.json({ error: 'Subagent session not found' }, 404);\n }\n return c.json({ session });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sessions.js","names":[],"sources":["../../../../../src/gateway/hono/routes/sessions.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { buildSessionKey, parseSessionKey } from '../../../routing/session-key.js';\nimport { agentExists, getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\nimport { messagesToClientHistory } from '../../../session/client-history.js';\nimport { computeUserRoundDeleteRange } from '../../../session/user-round-delete.js';\nimport { respondStartupUnavailable } from '../lib/startup-unavailable.js';\nimport type { StartupUnavailableGatewayMethod } from '../../startup-readiness.js';\n\ntype SessionsStartupMethod = StartupUnavailableGatewayMethod;\n\nfunction ensureGatewayReadyForSessions(\n c: Parameters<typeof respondStartupUnavailable>[0],\n service: AuthenticatedRouteDeps['service'],\n method: SessionsStartupMethod,\n): Response | null {\n if (service.isGatewayReady()) {\n return null;\n }\n return respondStartupUnavailable(c, method);\n}\n\nexport function registerSessionsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // ========== Session REST API (/api/sessions) ==========\n\n // POST /api/sessions - Create new session (reuses empty sessions)\n authenticated.post('/api/sessions', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const channel = body.channel || 'webchat';\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 // If a specific chat_id is provided, use it (for advanced use cases)\n // Otherwise, try to find and reuse an existing empty session\n if (body.chat_id) {\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: body.chat_id,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n const session = await service.sessions.getSession(sessionKey);\n return c.json({ session }, 201);\n }\n\n // Look for existing empty sessions to reuse\n const existingSessions = await service.sessions.listSessions({\n channel,\n limit: 50,\n sortBy: 'updatedAt',\n sortOrder: 'desc',\n });\n \n // Reuse an empty session only when it matches the requested agent (session key embeds agent id).\n const emptySession = existingSessions.items.find((s) => {\n if (s.messageCount !== 0) return false;\n const parsed = parseSessionKey(s.key);\n return parsed?.agentId === agentId;\n });\n \n if (emptySession) {\n // Return existing empty session instead of creating a new one\n const session = await service.sessions.getSession(emptySession.key);\n return c.json({ session, reused: true }, 200);\n }\n \n // No empty session found, create a new one\n const chatId = `chat_${Date.now()}`;\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: chatId,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n\n const session = await service.sessions.getSession(sessionKey);\n return c.json({ session }, 201);\n });\n\n // GET /api/sessions - List sessions\n authenticated.get('/api/sessions', async (c) => {\n const blocked = ensureGatewayReadyForSessions(c, service, 'sessions.list');\n if (blocked) {\n return blocked;\n }\n const query = c.req.query();\n const result = await service.sessions.listSessions({\n status: query.status as any,\n search: query.search,\n channel: query.channel,\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/sessions/stats - Get session stats (must be before /:key)\n authenticated.get('/api/sessions/stats', async (c) => {\n const result = await service.sessions.stats();\n return c.json(result);\n });\n\n // GET /api/sessions/chat-ids - Get unique chat IDs from sessions (must be before /:key)\n authenticated.get('/api/sessions/chat-ids', async (c) => {\n const channel = c.req.query('channel');\n const chatIds = await service.sessions.chatIds(channel || undefined);\n return c.json({ ok: true, payload: { chatIds } });\n });\n\n // GET /api/sessions/:key/run — read-only active webchat agent run (for UI resume)\n authenticated.get('/api/sessions/:key/run', async (c) => {\n const blocked = ensureGatewayReadyForSessions(c, service, 'sessions.run');\n if (blocked) {\n return blocked;\n }\n const key = c.req.param('key');\n const session = await service.sessions.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n return c.json({ ok: true, payload: service.sessions.getActiveRun(key) });\n });\n\n // GET /api/sessions/:key/agent-config — resolved session agent settings (thinking, etc.)\n authenticated.get('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const payload = await service.sessions.getAgentConfig(key);\n return c.json({ ok: true, payload });\n });\n\n authenticated.patch('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const result = await service.sessions.patchAgentConfig(key, body);\n if (!result.ok) {\n return c.json({ ok: false, error: result.error }, 400);\n }\n return c.json({ ok: true });\n });\n\n // GET /api/sessions/:key/messages — flattened transcript for TUI / clients\n authenticated.get('/api/sessions/:key/messages', async (c) => {\n const blocked = ensureGatewayReadyForSessions(c, service, 'sessions.messages');\n if (blocked) {\n return blocked;\n }\n const key = c.req.param('key');\n const limitRaw = c.req.query('limit');\n const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : undefined;\n const limit =\n parsedLimit !== undefined && Number.isFinite(parsedLimit)\n ? Math.min(500, Math.max(1, parsedLimit))\n : undefined;\n\n const before = c.req.query('before')?.trim();\n const offsetRaw = c.req.query('offset');\n const parsedOffset = offsetRaw ? Number.parseInt(offsetRaw, 10) : 0;\n const offset = Number.isFinite(parsedOffset) ? Math.max(0, parsedOffset) : 0;\n\n const result = await service.sessions.getMessagePage(key, {\n limit,\n offset,\n ...(before ? { before } : {}),\n });\n if (!result) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n\n const messages = messagesToClientHistory(result.session.messages, { limit });\n return c.json({\n ok: true,\n payload: { messages },\n pagination: result.pagination,\n });\n });\n\n // GET /api/sessions/:key/history — UI chat history page from the newest tail.\n authenticated.get('/api/sessions/:key/history', async (c) => {\n const blocked = ensureGatewayReadyForSessions(c, service, 'sessions.history');\n if (blocked) {\n return blocked;\n }\n const key = c.req.param('key');\n const offsetRaw = c.req.query('offset');\n const limitRaw = c.req.query('limit');\n const before = c.req.query('before')?.trim();\n const parsedOffset = offsetRaw ? Number.parseInt(offsetRaw, 10) : 0;\n const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : 50;\n const offset = Number.isFinite(parsedOffset) ? Math.max(0, parsedOffset) : 0;\n const limit = Number.isFinite(parsedLimit) ? Math.min(200, Math.max(1, parsedLimit)) : 50;\n const result = await service.sessions.getMessagePage(key, {\n offset,\n limit,\n ...(before ? { before } : {}),\n });\n\n if (!result) {\n return c.json({ error: 'Session not found' }, 404);\n }\n\n return c.json(result);\n });\n\n // POST /api/sessions/:key/transcript/context — append persisted-only `kind: 'context'` row (not in LLM context)\n authenticated.post('/api/sessions/:key/transcript/context', async (c) => {\n const key = c.req.param('key');\n const meta = await service.sessionManagerInstance.getSessionMetadata(key);\n if (!meta) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n const body = await c.req.json().catch(() => ({}));\n const id = typeof body.id === 'string' && body.id.trim() ? body.id.trim() : undefined;\n const text = typeof body.text === 'string' ? body.text : undefined;\n const data =\n body.data !== undefined && typeof body.data === 'object' && body.data !== null && !Array.isArray(body.data)\n ? (body.data as Record<string, unknown>)\n : undefined;\n await service.sessionManagerInstance.appendTranscriptContextEntry(key, { id, text, data });\n return c.json({ ok: true });\n });\n\n // GET /api/sessions/:key/compaction/checkpoints — list pre-compaction snapshots (OpenClaw-style)\n authenticated.get('/api/sessions/:key/compaction/checkpoints', async (c) => {\n const key = c.req.param('key');\n const meta = await service.sessionManagerInstance.getSessionMetadata(key);\n if (!meta) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n const checkpoints = await service.sessions.listCompactionCheckpoints(key);\n return c.json({ ok: true, payload: { checkpoints } });\n });\n\n authenticated.get('/api/sessions/:key/compaction/checkpoints/:checkpointId', async (c) => {\n const key = c.req.param('key');\n const checkpointId = c.req.param('checkpointId');\n const checkpoint = await service.sessions.getCompactionCheckpoint(key, checkpointId);\n if (!checkpoint) {\n return c.json({ ok: false, error: 'Checkpoint not found' }, 404);\n }\n return c.json({ ok: true, payload: { checkpoint } });\n });\n\n authenticated.post('/api/sessions/:key/compaction/restore', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const checkpointId = typeof body.checkpointId === 'string' ? body.checkpointId.trim() : '';\n if (!checkpointId) {\n return c.json({ ok: false, error: 'checkpointId required' }, 400);\n }\n try {\n await service.sessions.restoreCompactionCheckpoint(key, checkpointId);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes('not found') || msg.includes('Invalid')) {\n return c.json({ ok: false, error: msg }, 404);\n }\n return c.json({ ok: false, error: msg }, 500);\n }\n const session = await service.sessions.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n return c.json({ ok: true, session });\n });\n\n authenticated.post('/api/sessions/:key/compaction/run', async (c) => {\n const key = c.req.param('key');\n const session = await service.sessions.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n const body = await c.req.json().catch(() => ({}));\n const instructions = typeof body.instructions === 'string' ? body.instructions : undefined;\n const force = typeof body.force === 'boolean' ? body.force : true;\n const result = await service.sessions.runCompaction(key, { instructions, force });\n return c.json({ ok: true, payload: { result } });\n });\n\n // GET /api/sessions/:key - Get single session (must be after /stats and /chat-ids)\n authenticated.get('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const includeRaw = c.req.query('include') ?? '';\n const includeSet = new Set(\n includeRaw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n );\n const includeTranscript = includeSet.has('transcript');\n const includeTranscriptRows = includeSet.has('transcriptRows');\n const offsetRaw = c.req.query('offset');\n const limitRaw = c.req.query('limit');\n const hasPagingQuery = offsetRaw !== undefined || limitRaw !== undefined;\n\n if (hasPagingQuery) {\n const blocked = ensureGatewayReadyForSessions(c, service, 'sessions.history');\n if (blocked) {\n return blocked;\n }\n const parsedOffset = offsetRaw ? Number.parseInt(offsetRaw, 10) : 0;\n const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : 50;\n const offset = Number.isFinite(parsedOffset) ? Math.max(0, parsedOffset) : 0;\n const limit = Number.isFinite(parsedLimit) ? Math.min(200, Math.max(1, parsedLimit)) : 50;\n const result = await service.sessions.getMessagePage(key, {\n offset,\n limit,\n includeTranscriptSummary: includeTranscript,\n includeTranscriptRows,\n });\n if (!result) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json(result);\n }\n\n const session = await service.sessions.getSession(key, {\n includeTranscriptSummary: includeTranscript,\n includeTranscriptRows,\n });\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json({ session });\n });\n\n // PATCH /api/sessions/:key - Partial metadata (name, tags, customData); OpenClaw-style patch subset\n authenticated.patch('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const patch: {\n name?: string;\n tags?: string[];\n replaceTags?: boolean;\n customData?: Record<string, unknown>;\n } = {};\n if (typeof body.name === 'string') {\n patch.name = body.name;\n }\n if (Array.isArray(body.tags)) {\n patch.tags = body.tags;\n }\n if (typeof body.replaceTags === 'boolean') {\n patch.replaceTags = body.replaceTags;\n }\n if (body.customData !== undefined && typeof body.customData === 'object' && body.customData !== null) {\n patch.customData = body.customData as Record<string, unknown>;\n }\n const result = await service.sessions.patch(key, patch);\n if (result.ok === false) {\n return c.json({ ok: false, error: result.error }, 404);\n }\n const session = await service.sessions.getSession(key);\n return c.json({ ok: true, session });\n });\n\n // GET /api/sessions/:key/export - Export session (must be before /:key)\n authenticated.get('/api/sessions/:key/export', async (c) => {\n const key = c.req.param('key');\n const format = c.req.query('format') as any || 'json';\n const result = await service.sessions.export(key, format);\n return c.json(result);\n });\n\n // DELETE /api/sessions/:key/messages — delete LLM rows by range or by user turn.\n // `userRoundIndex` (0-based among user messages) removes the user row and every following\n // assistant / tool / toolResult row until the next user. Prefer this from the web console so\n // tool loops are not left orphaned after retry/delete.\n authenticated.delete('/api/sessions/:key/messages', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const loaded = await service.sessionManagerInstance.loadMessages(key);\n if (!loaded) {\n return c.json({ error: 'Session not found' }, 404);\n }\n\n let startIndex = typeof body.startIndex === 'number' ? body.startIndex : -1;\n let count = typeof body.count === 'number' ? body.count : 0;\n const userRoundIndex =\n typeof body.userRoundIndex === 'number' ? body.userRoundIndex : undefined;\n\n if (userRoundIndex !== undefined) {\n const range = computeUserRoundDeleteRange(loaded, userRoundIndex);\n if (!range) {\n return c.json({ error: 'User round index out of range' }, 400);\n }\n startIndex = range.startIndex;\n count = range.count;\n }\n\n if (startIndex < 0 || count <= 0) {\n return c.json({ error: 'Invalid startIndex or count' }, 400);\n }\n if (startIndex >= loaded.length) {\n return c.json({ error: 'Index out of range' }, 400);\n }\n const deleteCount = Math.min(count, loaded.length - startIndex);\n const next = loaded.slice(0, startIndex).concat(loaded.slice(startIndex + deleteCount));\n await service.sessionManagerInstance.saveMessages(key, next);\n return c.json({ ok: true, deleted: deleteCount });\n });\n\n // DELETE /api/sessions/:key - Delete session\n authenticated.delete('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const result = await service.sessions.delete(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/archive - Archive session\n authenticated.post('/api/sessions/:key/archive', async (c) => {\n const key = c.req.param('key');\n const result = await service.sessions.archive(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unarchive - Unarchive session\n authenticated.post('/api/sessions/:key/unarchive', async (c) => {\n const key = c.req.param('key');\n const result = await service.sessions.unarchive(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/pin - Pin session\n authenticated.post('/api/sessions/:key/pin', async (c) => {\n const key = c.req.param('key');\n const result = await service.sessions.pin(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unpin - Unpin session\n authenticated.post('/api/sessions/:key/unpin', async (c) => {\n const key = c.req.param('key');\n const result = await service.sessions.unpin(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/rename - Rename session\n authenticated.post('/api/sessions/:key/rename', async (c) => {\n const key = c.req.param('key');\n\n const body = await c.req.json();\n const { name } = body;\n const result = await service.sessions.rename(key, name);\n return c.json(result);\n });\n\n // ========== Subagent REST API (/api/subagents) ==========\n\n // GET /api/subagents - List subagent sessions\n authenticated.get('/api/subagents', async (c) => {\n const query = c.req.query();\n const result = await service.sessions.listSubagents({\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/subagents/:key - Get subagent session detail\n authenticated.get('/api/subagents/:key', async (c) => {\n const key = c.req.param('key');\n // Verify it's a subagent session\n if (!key.startsWith('subagent:')) {\n return c.json({ error: 'Not a subagent session' }, 400);\n }\n const includeRaw = c.req.query('include') ?? '';\n const includeSet = new Set(\n includeRaw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n );\n const session = await service.sessions.getSession(key, {\n includeTranscriptSummary: includeSet.has('transcript'),\n includeTranscriptRows: includeSet.has('transcriptRows'),\n });\n if (!session) {\n return c.json({ error: 'Subagent session not found' }, 404);\n }\n return c.json({ session });\n });\n}\n"],"mappings":";;;;;;kBAEmF;oBACA;AASnF,SAAS,8BACP,GACA,SACA,QACiB;AACjB,KAAI,QAAQ,gBAAgB,CAC1B,QAAO;AAET,QAAO,0BAA0B,GAAG,OAAO;;AAG7C,SAAgB,uBAAuB,eAAqB,MAAoC;CAC9F,MAAM,EAAE,YAAY;AAKpB,eAAc,KAAK,iBAAiB,OAAO,MAAM;EAC/C,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,UAAU,KAAK,WAAW;EAChC,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;AAKzC,MAAI,KAAK,SAAS;GAChB,MAAM,aAAa,gBAAgB;IACjC;IACA,QAAQ;IACR,WAAW;IACX,UAAU;IACV,QAAQ,KAAK;IACd,CAAC;AAEF,SAAM,QAAQ,uBAAuB,aAAa,YAAY,EAAE,CAAC;GACjE,MAAM,UAAU,MAAM,QAAQ,SAAS,WAAW,WAAW;AAC7D,UAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI;;EAYjC,MAAM,gBAAe,MARU,QAAQ,SAAS,aAAa;GAC3D;GACA,OAAO;GACP,QAAQ;GACR,WAAW;GACZ,CAAC,EAGoC,MAAM,MAAM,MAAM;AACtD,OAAI,EAAE,iBAAiB,EAAG,QAAO;AAEjC,UADe,gBAAgB,EAAE,IACpB,EAAE,YAAY;IAC3B;AAEF,MAAI,cAAc;GAEhB,MAAM,UAAU,MAAM,QAAQ,SAAS,WAAW,aAAa,IAAI;AACnE,UAAO,EAAE,KAAK;IAAE;IAAS,QAAQ;IAAM,EAAE,IAAI;;EAI/C,MAAM,SAAS,QAAQ,KAAK,KAAK;EACjC,MAAM,aAAa,gBAAgB;GACjC;GACA,QAAQ;GACR,WAAW;GACX,UAAU;GACV,QAAQ;GACT,CAAC;AAEF,QAAM,QAAQ,uBAAuB,aAAa,YAAY,EAAE,CAAC;EAEjE,MAAM,UAAU,MAAM,QAAQ,SAAS,WAAW,WAAW;AAC7D,SAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI;GAC/B;AAGF,eAAc,IAAI,iBAAiB,OAAO,MAAM;EAC9C,MAAM,UAAU,8BAA8B,GAAG,SAAS,gBAAgB;AAC1E,MAAI,QACF,QAAO;EAET,MAAM,QAAQ,EAAE,IAAI,OAAO;EAC3B,MAAM,SAAS,MAAM,QAAQ,SAAS,aAAa;GACjD,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,SAAS,MAAM;GACf,OAAO,MAAM,QAAQ,SAAS,MAAM,MAAM,GAAG,KAAA;GAC7C,QAAQ,MAAM,SAAS,SAAS,MAAM,OAAO,GAAG,KAAA;GACjD,CAAC;AACF,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,IAAI,uBAAuB,OAAO,MAAM;EACpD,MAAM,SAAS,MAAM,QAAQ,SAAS,OAAO;AAC7C,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,IAAI,0BAA0B,OAAO,MAAM;EACvD,MAAM,UAAU,EAAE,IAAI,MAAM,UAAU;EACtC,MAAM,UAAU,MAAM,QAAQ,SAAS,QAAQ,WAAW,KAAA,EAAU;AACpE,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM,SAAS,EAAE,SAAS;GAAE,CAAC;GACjD;AAGF,eAAc,IAAI,0BAA0B,OAAO,MAAM;EACvD,MAAM,UAAU,8BAA8B,GAAG,SAAS,eAAe;AACzE,MAAI,QACF,QAAO;EAET,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;AAE9B,MAAI,CAAC,MADiB,QAAQ,SAAS,WAAW,IAAI,CAEpD,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO;GAAqB,EAAE,IAAI;AAE/D,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM,SAAS,QAAQ,SAAS,aAAa,IAAI;GAAE,CAAC;GACxE;AAGF,eAAc,IAAI,mCAAmC,OAAO,MAAM;EAChE,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,UAAU,MAAM,QAAQ,SAAS,eAAe,IAAI;AAC1D,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM;GAAS,CAAC;GACpC;AAEF,eAAc,MAAM,mCAAmC,OAAO,MAAM;EAClE,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,SAAS,MAAM,QAAQ,SAAS,iBAAiB,KAAK,KAAK;AACjE,MAAI,CAAC,OAAO,GACV,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO,OAAO;GAAO,EAAE,IAAI;AAExD,SAAO,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC;GAC3B;AAGF,eAAc,IAAI,+BAA+B,OAAO,MAAM;EAC5D,MAAM,UAAU,8BAA8B,GAAG,SAAS,oBAAoB;AAC9E,MAAI,QACF,QAAO;EAET,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,WAAW,EAAE,IAAI,MAAM,QAAQ;EACrC,MAAM,cAAc,WAAW,OAAO,SAAS,UAAU,GAAG,GAAG,KAAA;EAC/D,MAAM,QACJ,gBAAgB,KAAA,KAAa,OAAO,SAAS,YAAY,GACrD,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,YAAY,CAAC,GACvC,KAAA;EAEN,MAAM,SAAS,EAAE,IAAI,MAAM,SAAS,EAAE,MAAM;EAC5C,MAAM,YAAY,EAAE,IAAI,MAAM,SAAS;EACvC,MAAM,eAAe,YAAY,OAAO,SAAS,WAAW,GAAG,GAAG;EAClE,MAAM,SAAS,OAAO,SAAS,aAAa,GAAG,KAAK,IAAI,GAAG,aAAa,GAAG;EAE3E,MAAM,SAAS,MAAM,QAAQ,SAAS,eAAe,KAAK;GACxD;GACA;GACA,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;GAC7B,CAAC;AACF,MAAI,CAAC,OACH,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO;GAAqB,EAAE,IAAI;EAG/D,MAAM,WAAW,wBAAwB,OAAO,QAAQ,UAAU,EAAE,OAAO,CAAC;AAC5E,SAAO,EAAE,KAAK;GACZ,IAAI;GACJ,SAAS,EAAE,UAAU;GACrB,YAAY,OAAO;GACpB,CAAC;GACF;AAGF,eAAc,IAAI,8BAA8B,OAAO,MAAM;EAC3D,MAAM,UAAU,8BAA8B,GAAG,SAAS,mBAAmB;AAC7E,MAAI,QACF,QAAO;EAET,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,YAAY,EAAE,IAAI,MAAM,SAAS;EACvC,MAAM,WAAW,EAAE,IAAI,MAAM,QAAQ;EACrC,MAAM,SAAS,EAAE,IAAI,MAAM,SAAS,EAAE,MAAM;EAC5C,MAAM,eAAe,YAAY,OAAO,SAAS,WAAW,GAAG,GAAG;EAClE,MAAM,cAAc,WAAW,OAAO,SAAS,UAAU,GAAG,GAAG;EAC/D,MAAM,SAAS,OAAO,SAAS,aAAa,GAAG,KAAK,IAAI,GAAG,aAAa,GAAG;EAC3E,MAAM,QAAQ,OAAO,SAAS,YAAY,GAAG,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,YAAY,CAAC,GAAG;EACvF,MAAM,SAAS,MAAM,QAAQ,SAAS,eAAe,KAAK;GACxD;GACA;GACA,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;GAC7B,CAAC;AAEF,MAAI,CAAC,OACH,QAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,EAAE,IAAI;AAGpD,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,KAAK,yCAAyC,OAAO,MAAM;EACvE,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;AAE9B,MAAI,CAAC,MADc,QAAQ,uBAAuB,mBAAmB,IAAI,CAEvE,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO;GAAqB,EAAE,IAAI;EAE/D,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,KAAK,OAAO,KAAK,OAAO,YAAY,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAA;EAC5E,MAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAA;EACzD,MAAM,OACJ,KAAK,SAAS,KAAA,KAAa,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,QAAQ,CAAC,MAAM,QAAQ,KAAK,KAAK,GACtG,KAAK,OACN,KAAA;AACN,QAAM,QAAQ,uBAAuB,6BAA6B,KAAK;GAAE;GAAI;GAAM;GAAM,CAAC;AAC1F,SAAO,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC;GAC3B;AAGF,eAAc,IAAI,6CAA6C,OAAO,MAAM;EAC1E,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;AAE9B,MAAI,CAAC,MADc,QAAQ,uBAAuB,mBAAmB,IAAI,CAEvE,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO;GAAqB,EAAE,IAAI;EAE/D,MAAM,cAAc,MAAM,QAAQ,SAAS,0BAA0B,IAAI;AACzE,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM,SAAS,EAAE,aAAa;GAAE,CAAC;GACrD;AAEF,eAAc,IAAI,2DAA2D,OAAO,MAAM;EACxF,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,eAAe,EAAE,IAAI,MAAM,eAAe;EAChD,MAAM,aAAa,MAAM,QAAQ,SAAS,wBAAwB,KAAK,aAAa;AACpF,MAAI,CAAC,WACH,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO;GAAwB,EAAE,IAAI;AAElE,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM,SAAS,EAAE,YAAY;GAAE,CAAC;GACpD;AAEF,eAAc,KAAK,yCAAyC,OAAO,MAAM;EACvE,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,eAAe,OAAO,KAAK,iBAAiB,WAAW,KAAK,aAAa,MAAM,GAAG;AACxF,MAAI,CAAC,aACH,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO;GAAyB,EAAE,IAAI;AAEnE,MAAI;AACF,SAAM,QAAQ,SAAS,4BAA4B,KAAK,aAAa;WAC9D,KAAK;GACZ,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC5D,OAAI,IAAI,SAAS,YAAY,IAAI,IAAI,SAAS,UAAU,CACtD,QAAO,EAAE,KAAK;IAAE,IAAI;IAAO,OAAO;IAAK,EAAE,IAAI;AAE/C,UAAO,EAAE,KAAK;IAAE,IAAI;IAAO,OAAO;IAAK,EAAE,IAAI;;EAE/C,MAAM,UAAU,MAAM,QAAQ,SAAS,WAAW,IAAI;AACtD,MAAI,CAAC,QACH,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO;GAAqB,EAAE,IAAI;AAE/D,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM;GAAS,CAAC;GACpC;AAEF,eAAc,KAAK,qCAAqC,OAAO,MAAM;EACnE,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;AAE9B,MAAI,CAAC,MADiB,QAAQ,SAAS,WAAW,IAAI,CAEpD,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO;GAAqB,EAAE,IAAI;EAE/D,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,eAAe,OAAO,KAAK,iBAAiB,WAAW,KAAK,eAAe,KAAA;EACjF,MAAM,QAAQ,OAAO,KAAK,UAAU,YAAY,KAAK,QAAQ;EAC7D,MAAM,SAAS,MAAM,QAAQ,SAAS,cAAc,KAAK;GAAE;GAAc;GAAO,CAAC;AACjF,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM,SAAS,EAAE,QAAQ;GAAE,CAAC;GAChD;AAGF,eAAc,IAAI,sBAAsB,OAAO,MAAM;EACnD,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,aAAa,EAAE,IAAI,MAAM,UAAU,IAAI;EAC7C,MAAM,aAAa,IAAI,IACrB,WACG,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ,CACnB;EACD,MAAM,oBAAoB,WAAW,IAAI,aAAa;EACtD,MAAM,wBAAwB,WAAW,IAAI,iBAAiB;EAC9D,MAAM,YAAY,EAAE,IAAI,MAAM,SAAS;EACvC,MAAM,WAAW,EAAE,IAAI,MAAM,QAAQ;AAGrC,MAFuB,cAAc,KAAA,KAAa,aAAa,KAAA,GAE3C;GAClB,MAAM,UAAU,8BAA8B,GAAG,SAAS,mBAAmB;AAC7E,OAAI,QACF,QAAO;GAET,MAAM,eAAe,YAAY,OAAO,SAAS,WAAW,GAAG,GAAG;GAClE,MAAM,cAAc,WAAW,OAAO,SAAS,UAAU,GAAG,GAAG;GAC/D,MAAM,SAAS,OAAO,SAAS,aAAa,GAAG,KAAK,IAAI,GAAG,aAAa,GAAG;GAC3E,MAAM,QAAQ,OAAO,SAAS,YAAY,GAAG,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,YAAY,CAAC,GAAG;GACvF,MAAM,SAAS,MAAM,QAAQ,SAAS,eAAe,KAAK;IACxD;IACA;IACA,0BAA0B;IAC1B;IACD,CAAC;AACF,OAAI,CAAC,OACH,QAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,EAAE,IAAI;AAEpD,UAAO,EAAE,KAAK,OAAO;;EAGvB,MAAM,UAAU,MAAM,QAAQ,SAAS,WAAW,KAAK;GACrD,0BAA0B;GAC1B;GACD,CAAC;AACF,MAAI,CAAC,QACH,QAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,EAAE,IAAI;AAEpD,SAAO,EAAE,KAAK,EAAE,SAAS,CAAC;GAC1B;AAGF,eAAc,MAAM,sBAAsB,OAAO,MAAM;EACrD,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,QAKF,EAAE;AACN,MAAI,OAAO,KAAK,SAAS,SACvB,OAAM,OAAO,KAAK;AAEpB,MAAI,MAAM,QAAQ,KAAK,KAAK,CAC1B,OAAM,OAAO,KAAK;AAEpB,MAAI,OAAO,KAAK,gBAAgB,UAC9B,OAAM,cAAc,KAAK;AAE3B,MAAI,KAAK,eAAe,KAAA,KAAa,OAAO,KAAK,eAAe,YAAY,KAAK,eAAe,KAC9F,OAAM,aAAa,KAAK;EAE1B,MAAM,SAAS,MAAM,QAAQ,SAAS,MAAM,KAAK,MAAM;AACvD,MAAI,OAAO,OAAO,MAChB,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO,OAAO;GAAO,EAAE,IAAI;EAExD,MAAM,UAAU,MAAM,QAAQ,SAAS,WAAW,IAAI;AACtD,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM;GAAS,CAAC;GACpC;AAGF,eAAc,IAAI,6BAA6B,OAAO,MAAM;EAC1D,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,SAAS,EAAE,IAAI,MAAM,SAAS,IAAW;EAC/C,MAAM,SAAS,MAAM,QAAQ,SAAS,OAAO,KAAK,OAAO;AACzD,SAAO,EAAE,KAAK,OAAO;GACrB;AAMF,eAAc,OAAO,+BAA+B,OAAO,MAAM;EAC/D,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,SAAS,MAAM,QAAQ,uBAAuB,aAAa,IAAI;AACrE,MAAI,CAAC,OACH,QAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,EAAE,IAAI;EAGpD,IAAI,aAAa,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa;EACzE,IAAI,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;EAC1D,MAAM,iBACJ,OAAO,KAAK,mBAAmB,WAAW,KAAK,iBAAiB,KAAA;AAElE,MAAI,mBAAmB,KAAA,GAAW;GAChC,MAAM,QAAQ,4BAA4B,QAAQ,eAAe;AACjE,OAAI,CAAC,MACH,QAAO,EAAE,KAAK,EAAE,OAAO,iCAAiC,EAAE,IAAI;AAEhE,gBAAa,MAAM;AACnB,WAAQ,MAAM;;AAGhB,MAAI,aAAa,KAAK,SAAS,EAC7B,QAAO,EAAE,KAAK,EAAE,OAAO,+BAA+B,EAAE,IAAI;AAE9D,MAAI,cAAc,OAAO,OACvB,QAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,EAAE,IAAI;EAErD,MAAM,cAAc,KAAK,IAAI,OAAO,OAAO,SAAS,WAAW;EAC/D,MAAM,OAAO,OAAO,MAAM,GAAG,WAAW,CAAC,OAAO,OAAO,MAAM,aAAa,YAAY,CAAC;AACvF,QAAM,QAAQ,uBAAuB,aAAa,KAAK,KAAK;AAC5D,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM,SAAS;GAAa,CAAC;GACjD;AAGF,eAAc,OAAO,sBAAsB,OAAO,MAAM;EACtD,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,SAAS,MAAM,QAAQ,SAAS,OAAO,IAAI;AACjD,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,KAAK,8BAA8B,OAAO,MAAM;EAC5D,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,SAAS,MAAM,QAAQ,SAAS,QAAQ,IAAI;AAClD,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,KAAK,gCAAgC,OAAO,MAAM;EAC9D,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,SAAS,MAAM,QAAQ,SAAS,UAAU,IAAI;AACpD,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,KAAK,0BAA0B,OAAO,MAAM;EACxD,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,SAAS,MAAM,QAAQ,SAAS,IAAI,IAAI;AAC9C,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,KAAK,4BAA4B,OAAO,MAAM;EAC1D,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAC9B,MAAM,SAAS,MAAM,QAAQ,SAAS,MAAM,IAAI;AAChD,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,KAAK,6BAA6B,OAAO,MAAM;EAC3D,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;EAG9B,MAAM,EAAE,SAAS,MADE,EAAE,IAAI,MAAM;EAE/B,MAAM,SAAS,MAAM,QAAQ,SAAS,OAAO,KAAK,KAAK;AACvD,SAAO,EAAE,KAAK,OAAO;GACrB;AAKF,eAAc,IAAI,kBAAkB,OAAO,MAAM;EAC/C,MAAM,QAAQ,EAAE,IAAI,OAAO;EAC3B,MAAM,SAAS,MAAM,QAAQ,SAAS,cAAc;GAClD,OAAO,MAAM,QAAQ,SAAS,MAAM,MAAM,GAAG,KAAA;GAC7C,QAAQ,MAAM,SAAS,SAAS,MAAM,OAAO,GAAG,KAAA;GACjD,CAAC;AACF,SAAO,EAAE,KAAK,OAAO;GACrB;AAGF,eAAc,IAAI,uBAAuB,OAAO,MAAM;EACpD,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;AAE9B,MAAI,CAAC,IAAI,WAAW,YAAY,CAC9B,QAAO,EAAE,KAAK,EAAE,OAAO,0BAA0B,EAAE,IAAI;EAEzD,MAAM,aAAa,EAAE,IAAI,MAAM,UAAU,IAAI;EAC7C,MAAM,aAAa,IAAI,IACrB,WACG,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ,CACnB;EACD,MAAM,UAAU,MAAM,QAAQ,SAAS,WAAW,KAAK;GACrD,0BAA0B,WAAW,IAAI,aAAa;GACtD,uBAAuB,WAAW,IAAI,iBAAiB;GACxD,CAAC;AACF,MAAI,CAAC,QACH,QAAO,EAAE,KAAK,EAAE,OAAO,8BAA8B,EAAE,IAAI;AAE7D,SAAO,EAAE,KAAK,EAAE,SAAS,CAAC;GAC1B"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { resolveGatewayEffectiveHost } from "../../../config/gateway-bind.js";
|
|
2
|
-
import { getClientIpFromHeaders } from "../../auth-rate-limit.js";
|
|
3
2
|
import { extractToken } from "../../auth.js";
|
|
3
|
+
import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
4
4
|
import { logShareAudit } from "../../../share/share-audit.js";
|
|
5
5
|
import { SHARE_CONFIG_DEFAULTS } from "../../../share/share-types.js";
|
|
6
6
|
import { renderShareExpiredPage, renderShareLandingPage } from "../../../share/share-landing.js";
|
|
7
7
|
import { consumeSharePublicLimit } from "../../../share/share-rate-limit.js";
|
|
8
8
|
import { getShareStore } from "../../../share/share-store.js";
|
|
9
9
|
import { resolveShareUrl } from "../../../share/share-url.js";
|
|
10
|
-
import { createReadStream } from "node:fs";
|
|
11
10
|
import { createHash } from "node:crypto";
|
|
11
|
+
import { createReadStream } from "node:fs";
|
|
12
12
|
import { stat } from "node:fs/promises";
|
|
13
13
|
import { Readable } from "node:stream";
|
|
14
14
|
//#region src/gateway/hono/routes/shares.ts
|
|
@@ -322,9 +322,9 @@ function registerShareRoutes(authenticated, deps) {
|
|
|
322
322
|
async function resolveWorkspaceRootForShare(service, sessionKey, agentId) {
|
|
323
323
|
const cfg = service.currentConfig;
|
|
324
324
|
if (sessionKey) try {
|
|
325
|
-
return await service.
|
|
325
|
+
return await service.sessions.getEffectiveWorkspacePath(sessionKey);
|
|
326
326
|
} catch {}
|
|
327
|
-
const { getWorkspacePath } = await import("../../../config/
|
|
327
|
+
const { getWorkspacePath } = await import("../../../config/workspace-path-helpers.js");
|
|
328
328
|
const { resolveAgentWorkspaceDir, normalizeAgentId, resolveDefaultAgentId } = await import("../../../agent/agent-scope.js");
|
|
329
329
|
if (agentId) return resolveAgentWorkspaceDir(cfg, normalizeAgentId(agentId));
|
|
330
330
|
const root = getWorkspacePath(cfg);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shares.js","names":[],"sources":["../../../../../src/gateway/hono/routes/shares.ts"],"sourcesContent":["import type { Hono } from 'hono';\nimport { createReadStream } from 'node:fs';\nimport { stat } from 'node:fs/promises';\nimport { createHash } from 'node:crypto';\nimport { Readable } from 'node:stream';\n\nimport { extractToken } from '../../auth.js';\nimport { getClientIpFromHeaders } from '../../auth-rate-limit.js';\nimport { getShareStore } from '../../../share/share-store.js';\nimport { resolveShareUrl } from '../../../share/share-url.js';\nimport { consumeSharePublicLimit } from '../../../share/share-rate-limit.js';\nimport { logShareAudit } from '../../../share/share-audit.js';\nimport { renderShareLandingPage, renderShareExpiredPage } from '../../../share/share-landing.js';\nimport type { ShareExpiredReason } from '../../../share/share-landing.js';\nimport type { ShareConfig } from '../../../share/share-types.js';\nimport { resolveGatewayEffectiveHost } from '../../../config/gateway-bind.js';\nimport { SHARE_CONFIG_DEFAULTS } from '../../../share/share-types.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\nimport type { GatewayService } from '../../service.js';\n\nfunction getShareUrlContext(service: GatewayService) {\n const gateway = service.currentConfig.gateway;\n return {\n gatewayHost: resolveGatewayEffectiveHost(service.currentConfig),\n gatewayPort: gateway.port ?? 18790,\n };\n}\n\nfunction resolveShareConfig(service: GatewayService): Partial<ShareConfig> {\n const raw = (service.currentConfig.gateway as Record<string, unknown>)?.share;\n if (!raw || typeof raw !== 'object') return {};\n return raw as Partial<ShareConfig>;\n}\n\nfunction hashGatewayToken(token: string): string {\n return createHash('sha256').update(token, 'utf8').digest('hex').slice(0, 12);\n}\n\nconst MAX_CONCURRENT_DOWNLOADS_PER_TOKEN = 5;\nconst activeDownloads = new Map<string, number>();\n\nfunction acquireDownloadSlot(token: string): boolean {\n const current = activeDownloads.get(token) ?? 0;\n if (current >= MAX_CONCURRENT_DOWNLOADS_PER_TOKEN) return false;\n activeDownloads.set(token, current + 1);\n return true;\n}\n\nfunction releaseDownloadSlot(token: string): void {\n const current = activeDownloads.get(token) ?? 0;\n if (current <= 1) {\n activeDownloads.delete(token);\n } else {\n activeDownloads.set(token, current - 1);\n }\n}\n\n// ── Public routes (no auth required) ──────────────────────────────────────────\n\nexport function registerSharePublicRoutes(app: Hono, service: GatewayService): void {\n const store = getShareStore(resolveShareConfig(service));\n\n /** Landing page — does NOT consume viewCount (prevents link unfurl from wasting views). */\n app.get('/s/:token', async (c) => {\n const clientIp = getClientIpFromHeaders({ get: (n: string) => c.req.header(n) ?? undefined });\n const rateResult = consumeSharePublicLimit(clientIp);\n if (!rateResult.allowed) {\n c.header('Retry-After', String(Math.ceil(rateResult.retryAfterMs / 1000)));\n return c.text('Too many requests', 429);\n }\n\n const token = c.req.param('token');\n const record = store.getByToken(token);\n\n if (!record) {\n return c.html(renderShareExpiredPage('not_found'), 404);\n }\n\n const validation = store.validateAccess(record);\n if (!validation.valid) {\n logShareAudit(\n 'share.access_denied',\n { shareId: record.id, tokenPrefix: token.slice(0, 8), reason: validation.reason, clientIp },\n `Share access denied: ${validation.reason}`,\n );\n return c.html(renderShareExpiredPage(validation.reason as ShareExpiredReason), 410);\n }\n\n // Direct download shortcut: ?dl=1\n if (c.req.query('dl') === '1') {\n return handleDownload(c, store, record, clientIp);\n }\n\n // Inline preview for whitelisted MIME types: ?inline=1\n if (c.req.query('inline') === '1') {\n const cfg = { ...SHARE_CONFIG_DEFAULTS, ...resolveShareConfig(service) };\n if (cfg.inlinePreviewMimes.includes(record.mimeType)) {\n return handleDownload(c, store, record, clientIp, true);\n }\n }\n\n const downloadPath = `/s/${token}/download`;\n return c.html(renderShareLandingPage(record, downloadPath));\n });\n\n /** Actual file download — consumes viewCount. */\n app.post('/s/:token/download', async (c) => {\n const clientIp = getClientIpFromHeaders({ get: (n: string) => c.req.header(n) ?? undefined });\n const rateResult = consumeSharePublicLimit(clientIp);\n if (!rateResult.allowed) {\n c.header('Retry-After', String(Math.ceil(rateResult.retryAfterMs / 1000)));\n return c.text('Too many requests', 429);\n }\n\n const token = c.req.param('token');\n const record = store.getByToken(token);\n\n if (!record) {\n return c.html(renderShareExpiredPage('not_found'), 404);\n }\n\n const validation = store.validateAccess(record);\n if (!validation.valid) {\n logShareAudit(\n 'share.access_denied',\n { shareId: record.id, tokenPrefix: token.slice(0, 8), reason: validation.reason, clientIp },\n `Share download denied: ${validation.reason}`,\n );\n return c.html(renderShareExpiredPage(validation.reason as ShareExpiredReason), 410);\n }\n\n return handleDownload(c, store, record, clientIp);\n });\n\n /** File metadata (for link preview cards). */\n app.get('/s/:token/meta', async (c) => {\n const clientIp = getClientIpFromHeaders({ get: (n: string) => c.req.header(n) ?? undefined });\n const rateResult = consumeSharePublicLimit(clientIp);\n if (!rateResult.allowed) {\n c.header('Retry-After', String(Math.ceil(rateResult.retryAfterMs / 1000)));\n return c.text('Too many requests', 429);\n }\n\n const token = c.req.param('token');\n const record = store.getByToken(token);\n if (!record) {\n return c.json({ valid: false }, 404);\n }\n\n const validation = store.validateAccess(record);\n const remainingViews = record.maxViews !== null ? Math.max(0, record.maxViews - record.viewCount) : null;\n\n return c.json({\n fileName: record.fileName,\n fileSize: record.fileSize,\n mimeType: record.mimeType,\n description: record.description ?? null,\n expiresAt: record.expiresAt,\n remainingViews,\n valid: validation.valid,\n });\n });\n\n /** HEAD check (Hono uses .on() for HEAD method). */\n app.on('HEAD', '/s/:token', async (c) => {\n const token = c.req.param('token');\n const record = store.getByToken(token);\n if (!record) return c.body(null, 404);\n const validation = store.validateAccess(record);\n return c.body(null, validation.valid ? 200 : 410);\n });\n}\n\n// ── Authenticated routes ──────────────────────────────────────────────────────\n\nexport function registerShareRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n const store = getShareStore(resolveShareConfig(service));\n\n /** Create a share. */\n authenticated.post('/api/shares', async (c) => {\n const gatewayToken = extractToken({ authorization: c.req.header('authorization') ?? undefined });\n if (!gatewayToken) return c.json({ ok: false, error: { message: 'Token required' } }, 401);\n\n let body: Record<string, unknown>;\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n\n const path = typeof body.path === 'string' ? body.path.trim() : '';\n if (!path) {\n return c.json({ ok: false, error: { message: 'Missing path' } }, 400);\n }\n\n const sessionKey = typeof body.sessionKey === 'string' ? body.sessionKey.trim() : undefined;\n const agentId = typeof body.agentId === 'string' ? body.agentId.trim() : undefined;\n\n // Resolve workspace root (same logic as workspace editor routes)\n const workspaceRoot = await resolveWorkspaceRootForShare(service, sessionKey, agentId);\n if (!workspaceRoot) {\n return c.json({ ok: false, error: { message: 'Workspace not configured' } }, 400);\n }\n\n const ttlMs = typeof body.ttlMs === 'number' ? body.ttlMs : undefined;\n const maxViews = body.maxViews === null ? null : typeof body.maxViews === 'number' ? body.maxViews : undefined;\n const description = typeof body.description === 'string' ? body.description.trim() || undefined : undefined;\n\n try {\n store.updateConfig(resolveShareConfig(service));\n const record = await store.create({\n path,\n ttlMs,\n maxViews,\n description,\n sessionKey,\n agentId,\n workspaceRoot,\n gatewayTokenHash: hashGatewayToken(gatewayToken),\n });\n\n const urlCtx = getShareUrlContext(service);\n const resolved = resolveShareUrl(record.token, urlCtx);\n\n return c.json({\n ok: true,\n payload: {\n id: record.id,\n token: record.token,\n shareUrl: resolved.shareUrl,\n lanUrl: resolved.lanUrl,\n reachability: resolved.reachability,\n reachabilityHint: resolved.reachabilityHint,\n expiresAt: record.expiresAt,\n maxViews: record.maxViews,\n fileName: record.fileName,\n fileSize: record.fileSize,\n },\n }, 201);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return c.json({ ok: false, error: { message } }, 400);\n }\n });\n\n /** List all shares. */\n authenticated.get('/api/shares', async (c) => {\n store.updateConfig(resolveShareConfig(service));\n const shares = store.getAllShares();\n const urlCtx = getShareUrlContext(service);\n const now = Date.now();\n\n const items = shares.map((r) => {\n const resolved = resolveShareUrl(r.token, urlCtx);\n const expired = now >= new Date(r.expiresAt).getTime();\n return {\n id: r.id,\n fileName: r.fileName,\n workspaceRelativePath: r.workspaceRelativePath,\n shareUrl: resolved.shareUrl,\n lanUrl: resolved.lanUrl,\n reachability: resolved.reachability,\n createdAt: r.createdAt,\n expiresAt: r.expiresAt,\n viewCount: r.viewCount,\n maxViews: r.maxViews,\n revoked: r.revoked,\n expired,\n description: r.description ?? null,\n fileSize: r.fileSize,\n mimeType: r.mimeType,\n };\n });\n\n return c.json({ ok: true, payload: { shares: items } });\n });\n\n /** Get single share details. */\n authenticated.get('/api/shares/:id', async (c) => {\n const id = c.req.param('id');\n const record = store.getById(id);\n if (!record) return c.json({ ok: false, error: { message: 'Not found' } }, 404);\n\n const urlCtx = getShareUrlContext(service);\n const resolved = resolveShareUrl(record.token, urlCtx);\n const expired = Date.now() >= new Date(record.expiresAt).getTime();\n\n return c.json({\n ok: true,\n payload: {\n ...record,\n token: undefined,\n shareUrl: resolved.shareUrl,\n lanUrl: resolved.lanUrl,\n reachability: resolved.reachability,\n expired,\n },\n });\n });\n\n /** Revoke a share. */\n authenticated.delete('/api/shares/:id', async (c) => {\n const id = c.req.param('id');\n const success = store.revoke(id);\n if (!success) return c.json({ ok: false, error: { message: 'Not found' } }, 404);\n return c.json({ ok: true });\n });\n\n /** Batch revoke. */\n authenticated.delete('/api/shares', async (c) => {\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n /* empty body = no-op */\n }\n\n if (body.expired === true) {\n const count = store.revokeExpired();\n return c.json({ ok: true, payload: { revokedCount: count } });\n }\n\n const ids = Array.isArray(body.ids) ? (body.ids as string[]).filter((x) => typeof x === 'string') : [];\n if (ids.length === 0) {\n return c.json({ ok: false, error: { message: 'Provide ids array or expired: true' } }, 400);\n }\n const count = store.revokeMany(ids);\n return c.json({ ok: true, payload: { revokedCount: count } });\n });\n\n /** Update a share (extend TTL or change maxViews). */\n authenticated.patch('/api/shares/:id', async (c) => {\n const id = c.req.param('id');\n let body: Record<string, unknown>;\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n\n const patch: { extendTtlMs?: number; maxViews?: number | null } = {};\n if (typeof body.extendTtlMs === 'number') patch.extendTtlMs = body.extendTtlMs;\n if (body.maxViews === null || typeof body.maxViews === 'number') patch.maxViews = body.maxViews as number | null;\n\n const updated = store.update(id, patch);\n if (!updated) return c.json({ ok: false, error: { message: 'Not found' } }, 404);\n\n const urlCtx = getShareUrlContext(service);\n const resolved = resolveShareUrl(updated.token, urlCtx);\n\n return c.json({\n ok: true,\n payload: {\n id: updated.id,\n expiresAt: updated.expiresAt,\n maxViews: updated.maxViews,\n shareUrl: resolved.shareUrl,\n },\n });\n });\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nasync function resolveWorkspaceRootForShare(\n service: GatewayService,\n sessionKey: string | undefined,\n agentId: string | undefined,\n): Promise<string | null> {\n const cfg = service.currentConfig;\n\n if (sessionKey) {\n try {\n return await service.getEffectiveWorkspacePathForSession(sessionKey);\n } catch {\n /* fall through to agentId */\n }\n }\n\n // Import dynamically to avoid circular dependency at module load time\n const { getWorkspacePath } = await import('../../../config/schema.js');\n const { resolveAgentWorkspaceDir, normalizeAgentId, resolveDefaultAgentId } = await import(\n '../../../agent/agent-scope.js'\n );\n\n if (agentId) {\n const normalized = normalizeAgentId(agentId);\n return resolveAgentWorkspaceDir(cfg, normalized);\n }\n\n const root = getWorkspacePath(cfg);\n if (root) return root;\n\n const defaultId = resolveDefaultAgentId(cfg);\n return resolveAgentWorkspaceDir(cfg, defaultId);\n}\n\nasync function handleDownload(\n c: { header: (n: string, v: string) => void; body: (b: unknown, s?: number) => Response },\n store: ReturnType<typeof getShareStore>,\n record: ReturnType<ReturnType<typeof getShareStore>['getByToken']> & {},\n clientIp: string,\n inline = false,\n): Promise<Response> {\n // Concurrency check\n if (!acquireDownloadSlot(record.token)) {\n return c.body('Too many concurrent downloads for this share', 429) as unknown as Response;\n }\n\n try {\n // File integrity check (inode + path)\n const integrity = await store.validateFileIntegrity(record);\n if (!integrity.valid) {\n logShareAudit(\n 'share.access_denied',\n { shareId: record.id, tokenPrefix: record.token.slice(0, 8), reason: integrity.reason, clientIp },\n `Share file integrity check failed: ${integrity.reason}`,\n );\n const { renderShareExpiredPage: render } = await import('../../../share/share-landing.js');\n return new Response(render(integrity.reason as ShareExpiredReason), {\n status: 410,\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\n });\n }\n\n // Consume viewCount\n store.incrementViewCount(record.id);\n\n logShareAudit(\n 'share.access',\n { shareId: record.id, tokenPrefix: record.token.slice(0, 8), clientIp, viewCount: record.viewCount },\n `Share downloaded: ${record.fileName}`,\n );\n\n // Stream file\n const fileStat = await stat(record.absolutePath);\n const stream = createReadStream(record.absolutePath);\n const webStream = Readable.toWeb(stream) as ReadableStream;\n\n const disposition = inline ? `inline; filename=\"${encodeURIComponent(record.fileName)}\"` : `attachment; filename=\"${encodeURIComponent(record.fileName)}\"`;\n\n return new Response(webStream, {\n status: 200,\n headers: {\n 'Content-Type': record.mimeType,\n 'Content-Disposition': disposition,\n 'Content-Length': String(fileStat.size),\n 'Cache-Control': 'private, no-store',\n 'X-Content-Type-Options': 'nosniff',\n 'X-Frame-Options': 'DENY',\n 'Referrer-Policy': 'no-referrer',\n },\n });\n } finally {\n releaseDownloadSlot(record.token);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shares.js","names":[],"sources":["../../../../../src/gateway/hono/routes/shares.ts"],"sourcesContent":["import type { Hono } from 'hono';\nimport { createReadStream } from 'node:fs';\nimport { stat } from 'node:fs/promises';\nimport { createHash } from 'node:crypto';\nimport { Readable } from 'node:stream';\n\nimport { extractToken } from '../../auth.js';\nimport { getClientIpFromHeaders } from '../../security/loopback.js';\nimport { getShareStore } from '../../../share/share-store.js';\nimport { resolveShareUrl } from '../../../share/share-url.js';\nimport { consumeSharePublicLimit } from '../../../share/share-rate-limit.js';\nimport { logShareAudit } from '../../../share/share-audit.js';\nimport { renderShareLandingPage, renderShareExpiredPage } from '../../../share/share-landing.js';\nimport type { ShareExpiredReason } from '../../../share/share-landing.js';\nimport type { ShareConfig } from '../../../share/share-types.js';\nimport { resolveGatewayEffectiveHost } from '../../../config/gateway-bind.js';\nimport { SHARE_CONFIG_DEFAULTS } from '../../../share/share-types.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\nimport type { GatewayService } from '../../service.js';\n\nfunction getShareUrlContext(service: GatewayService) {\n const gateway = service.currentConfig.gateway;\n return {\n gatewayHost: resolveGatewayEffectiveHost(service.currentConfig),\n gatewayPort: gateway.port ?? 18790,\n };\n}\n\nfunction resolveShareConfig(service: GatewayService): Partial<ShareConfig> {\n const raw = (service.currentConfig.gateway as Record<string, unknown>)?.share;\n if (!raw || typeof raw !== 'object') return {};\n return raw as Partial<ShareConfig>;\n}\n\nfunction hashGatewayToken(token: string): string {\n return createHash('sha256').update(token, 'utf8').digest('hex').slice(0, 12);\n}\n\nconst MAX_CONCURRENT_DOWNLOADS_PER_TOKEN = 5;\nconst activeDownloads = new Map<string, number>();\n\nfunction acquireDownloadSlot(token: string): boolean {\n const current = activeDownloads.get(token) ?? 0;\n if (current >= MAX_CONCURRENT_DOWNLOADS_PER_TOKEN) return false;\n activeDownloads.set(token, current + 1);\n return true;\n}\n\nfunction releaseDownloadSlot(token: string): void {\n const current = activeDownloads.get(token) ?? 0;\n if (current <= 1) {\n activeDownloads.delete(token);\n } else {\n activeDownloads.set(token, current - 1);\n }\n}\n\n// ── Public routes (no auth required) ──────────────────────────────────────────\n\nexport function registerSharePublicRoutes(app: Hono, service: GatewayService): void {\n const store = getShareStore(resolveShareConfig(service));\n\n /** Landing page — does NOT consume viewCount (prevents link unfurl from wasting views). */\n app.get('/s/:token', async (c) => {\n const clientIp = getClientIpFromHeaders({ get: (n: string) => c.req.header(n) ?? undefined });\n const rateResult = consumeSharePublicLimit(clientIp);\n if (!rateResult.allowed) {\n c.header('Retry-After', String(Math.ceil(rateResult.retryAfterMs / 1000)));\n return c.text('Too many requests', 429);\n }\n\n const token = c.req.param('token');\n const record = store.getByToken(token);\n\n if (!record) {\n return c.html(renderShareExpiredPage('not_found'), 404);\n }\n\n const validation = store.validateAccess(record);\n if (!validation.valid) {\n logShareAudit(\n 'share.access_denied',\n { shareId: record.id, tokenPrefix: token.slice(0, 8), reason: validation.reason, clientIp },\n `Share access denied: ${validation.reason}`,\n );\n return c.html(renderShareExpiredPage(validation.reason as ShareExpiredReason), 410);\n }\n\n // Direct download shortcut: ?dl=1\n if (c.req.query('dl') === '1') {\n return handleDownload(c, store, record, clientIp);\n }\n\n // Inline preview for whitelisted MIME types: ?inline=1\n if (c.req.query('inline') === '1') {\n const cfg = { ...SHARE_CONFIG_DEFAULTS, ...resolveShareConfig(service) };\n if (cfg.inlinePreviewMimes.includes(record.mimeType)) {\n return handleDownload(c, store, record, clientIp, true);\n }\n }\n\n const downloadPath = `/s/${token}/download`;\n return c.html(renderShareLandingPage(record, downloadPath));\n });\n\n /** Actual file download — consumes viewCount. */\n app.post('/s/:token/download', async (c) => {\n const clientIp = getClientIpFromHeaders({ get: (n: string) => c.req.header(n) ?? undefined });\n const rateResult = consumeSharePublicLimit(clientIp);\n if (!rateResult.allowed) {\n c.header('Retry-After', String(Math.ceil(rateResult.retryAfterMs / 1000)));\n return c.text('Too many requests', 429);\n }\n\n const token = c.req.param('token');\n const record = store.getByToken(token);\n\n if (!record) {\n return c.html(renderShareExpiredPage('not_found'), 404);\n }\n\n const validation = store.validateAccess(record);\n if (!validation.valid) {\n logShareAudit(\n 'share.access_denied',\n { shareId: record.id, tokenPrefix: token.slice(0, 8), reason: validation.reason, clientIp },\n `Share download denied: ${validation.reason}`,\n );\n return c.html(renderShareExpiredPage(validation.reason as ShareExpiredReason), 410);\n }\n\n return handleDownload(c, store, record, clientIp);\n });\n\n /** File metadata (for link preview cards). */\n app.get('/s/:token/meta', async (c) => {\n const clientIp = getClientIpFromHeaders({ get: (n: string) => c.req.header(n) ?? undefined });\n const rateResult = consumeSharePublicLimit(clientIp);\n if (!rateResult.allowed) {\n c.header('Retry-After', String(Math.ceil(rateResult.retryAfterMs / 1000)));\n return c.text('Too many requests', 429);\n }\n\n const token = c.req.param('token');\n const record = store.getByToken(token);\n if (!record) {\n return c.json({ valid: false }, 404);\n }\n\n const validation = store.validateAccess(record);\n const remainingViews = record.maxViews !== null ? Math.max(0, record.maxViews - record.viewCount) : null;\n\n return c.json({\n fileName: record.fileName,\n fileSize: record.fileSize,\n mimeType: record.mimeType,\n description: record.description ?? null,\n expiresAt: record.expiresAt,\n remainingViews,\n valid: validation.valid,\n });\n });\n\n /** HEAD check (Hono uses .on() for HEAD method). */\n app.on('HEAD', '/s/:token', async (c) => {\n const token = c.req.param('token');\n const record = store.getByToken(token);\n if (!record) return c.body(null, 404);\n const validation = store.validateAccess(record);\n return c.body(null, validation.valid ? 200 : 410);\n });\n}\n\n// ── Authenticated routes ──────────────────────────────────────────────────────\n\nexport function registerShareRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n const store = getShareStore(resolveShareConfig(service));\n\n /** Create a share. */\n authenticated.post('/api/shares', async (c) => {\n const gatewayToken = extractToken({ authorization: c.req.header('authorization') ?? undefined });\n if (!gatewayToken) return c.json({ ok: false, error: { message: 'Token required' } }, 401);\n\n let body: Record<string, unknown>;\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n\n const path = typeof body.path === 'string' ? body.path.trim() : '';\n if (!path) {\n return c.json({ ok: false, error: { message: 'Missing path' } }, 400);\n }\n\n const sessionKey = typeof body.sessionKey === 'string' ? body.sessionKey.trim() : undefined;\n const agentId = typeof body.agentId === 'string' ? body.agentId.trim() : undefined;\n\n // Resolve workspace root (same logic as workspace editor routes)\n const workspaceRoot = await resolveWorkspaceRootForShare(service, sessionKey, agentId);\n if (!workspaceRoot) {\n return c.json({ ok: false, error: { message: 'Workspace not configured' } }, 400);\n }\n\n const ttlMs = typeof body.ttlMs === 'number' ? body.ttlMs : undefined;\n const maxViews = body.maxViews === null ? null : typeof body.maxViews === 'number' ? body.maxViews : undefined;\n const description = typeof body.description === 'string' ? body.description.trim() || undefined : undefined;\n\n try {\n store.updateConfig(resolveShareConfig(service));\n const record = await store.create({\n path,\n ttlMs,\n maxViews,\n description,\n sessionKey,\n agentId,\n workspaceRoot,\n gatewayTokenHash: hashGatewayToken(gatewayToken),\n });\n\n const urlCtx = getShareUrlContext(service);\n const resolved = resolveShareUrl(record.token, urlCtx);\n\n return c.json({\n ok: true,\n payload: {\n id: record.id,\n token: record.token,\n shareUrl: resolved.shareUrl,\n lanUrl: resolved.lanUrl,\n reachability: resolved.reachability,\n reachabilityHint: resolved.reachabilityHint,\n expiresAt: record.expiresAt,\n maxViews: record.maxViews,\n fileName: record.fileName,\n fileSize: record.fileSize,\n },\n }, 201);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return c.json({ ok: false, error: { message } }, 400);\n }\n });\n\n /** List all shares. */\n authenticated.get('/api/shares', async (c) => {\n store.updateConfig(resolveShareConfig(service));\n const shares = store.getAllShares();\n const urlCtx = getShareUrlContext(service);\n const now = Date.now();\n\n const items = shares.map((r) => {\n const resolved = resolveShareUrl(r.token, urlCtx);\n const expired = now >= new Date(r.expiresAt).getTime();\n return {\n id: r.id,\n fileName: r.fileName,\n workspaceRelativePath: r.workspaceRelativePath,\n shareUrl: resolved.shareUrl,\n lanUrl: resolved.lanUrl,\n reachability: resolved.reachability,\n createdAt: r.createdAt,\n expiresAt: r.expiresAt,\n viewCount: r.viewCount,\n maxViews: r.maxViews,\n revoked: r.revoked,\n expired,\n description: r.description ?? null,\n fileSize: r.fileSize,\n mimeType: r.mimeType,\n };\n });\n\n return c.json({ ok: true, payload: { shares: items } });\n });\n\n /** Get single share details. */\n authenticated.get('/api/shares/:id', async (c) => {\n const id = c.req.param('id');\n const record = store.getById(id);\n if (!record) return c.json({ ok: false, error: { message: 'Not found' } }, 404);\n\n const urlCtx = getShareUrlContext(service);\n const resolved = resolveShareUrl(record.token, urlCtx);\n const expired = Date.now() >= new Date(record.expiresAt).getTime();\n\n return c.json({\n ok: true,\n payload: {\n ...record,\n token: undefined,\n shareUrl: resolved.shareUrl,\n lanUrl: resolved.lanUrl,\n reachability: resolved.reachability,\n expired,\n },\n });\n });\n\n /** Revoke a share. */\n authenticated.delete('/api/shares/:id', async (c) => {\n const id = c.req.param('id');\n const success = store.revoke(id);\n if (!success) return c.json({ ok: false, error: { message: 'Not found' } }, 404);\n return c.json({ ok: true });\n });\n\n /** Batch revoke. */\n authenticated.delete('/api/shares', async (c) => {\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n /* empty body = no-op */\n }\n\n if (body.expired === true) {\n const count = store.revokeExpired();\n return c.json({ ok: true, payload: { revokedCount: count } });\n }\n\n const ids = Array.isArray(body.ids) ? (body.ids as string[]).filter((x) => typeof x === 'string') : [];\n if (ids.length === 0) {\n return c.json({ ok: false, error: { message: 'Provide ids array or expired: true' } }, 400);\n }\n const count = store.revokeMany(ids);\n return c.json({ ok: true, payload: { revokedCount: count } });\n });\n\n /** Update a share (extend TTL or change maxViews). */\n authenticated.patch('/api/shares/:id', async (c) => {\n const id = c.req.param('id');\n let body: Record<string, unknown>;\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n\n const patch: { extendTtlMs?: number; maxViews?: number | null } = {};\n if (typeof body.extendTtlMs === 'number') patch.extendTtlMs = body.extendTtlMs;\n if (body.maxViews === null || typeof body.maxViews === 'number') patch.maxViews = body.maxViews as number | null;\n\n const updated = store.update(id, patch);\n if (!updated) return c.json({ ok: false, error: { message: 'Not found' } }, 404);\n\n const urlCtx = getShareUrlContext(service);\n const resolved = resolveShareUrl(updated.token, urlCtx);\n\n return c.json({\n ok: true,\n payload: {\n id: updated.id,\n expiresAt: updated.expiresAt,\n maxViews: updated.maxViews,\n shareUrl: resolved.shareUrl,\n },\n });\n });\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nasync function resolveWorkspaceRootForShare(\n service: GatewayService,\n sessionKey: string | undefined,\n agentId: string | undefined,\n): Promise<string | null> {\n const cfg = service.currentConfig;\n\n if (sessionKey) {\n try {\n return await service.sessions.getEffectiveWorkspacePath(sessionKey);\n } catch {\n /* fall through to agentId */\n }\n }\n\n // Import dynamically to avoid circular dependency at module load time\n const { getWorkspacePath } = await import('../../../config/workspace-path-helpers.js');\n const { resolveAgentWorkspaceDir, normalizeAgentId, resolveDefaultAgentId } = await import(\n '../../../agent/agent-scope.js'\n );\n\n if (agentId) {\n const normalized = normalizeAgentId(agentId);\n return resolveAgentWorkspaceDir(cfg, normalized);\n }\n\n const root = getWorkspacePath(cfg);\n if (root) return root;\n\n const defaultId = resolveDefaultAgentId(cfg);\n return resolveAgentWorkspaceDir(cfg, defaultId);\n}\n\nasync function handleDownload(\n c: { header: (n: string, v: string) => void; body: (b: unknown, s?: number) => Response },\n store: ReturnType<typeof getShareStore>,\n record: ReturnType<ReturnType<typeof getShareStore>['getByToken']> & {},\n clientIp: string,\n inline = false,\n): Promise<Response> {\n // Concurrency check\n if (!acquireDownloadSlot(record.token)) {\n return c.body('Too many concurrent downloads for this share', 429) as unknown as Response;\n }\n\n try {\n // File integrity check (inode + path)\n const integrity = await store.validateFileIntegrity(record);\n if (!integrity.valid) {\n logShareAudit(\n 'share.access_denied',\n { shareId: record.id, tokenPrefix: record.token.slice(0, 8), reason: integrity.reason, clientIp },\n `Share file integrity check failed: ${integrity.reason}`,\n );\n const { renderShareExpiredPage: render } = await import('../../../share/share-landing.js');\n return new Response(render(integrity.reason as ShareExpiredReason), {\n status: 410,\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\n });\n }\n\n // Consume viewCount\n store.incrementViewCount(record.id);\n\n logShareAudit(\n 'share.access',\n { shareId: record.id, tokenPrefix: record.token.slice(0, 8), clientIp, viewCount: record.viewCount },\n `Share downloaded: ${record.fileName}`,\n );\n\n // Stream file\n const fileStat = await stat(record.absolutePath);\n const stream = createReadStream(record.absolutePath);\n const webStream = Readable.toWeb(stream) as ReadableStream;\n\n const disposition = inline ? `inline; filename=\"${encodeURIComponent(record.fileName)}\"` : `attachment; filename=\"${encodeURIComponent(record.fileName)}\"`;\n\n return new Response(webStream, {\n status: 200,\n headers: {\n 'Content-Type': record.mimeType,\n 'Content-Disposition': disposition,\n 'Content-Length': String(fileStat.size),\n 'Cache-Control': 'private, no-store',\n 'X-Content-Type-Options': 'nosniff',\n 'X-Frame-Options': 'DENY',\n 'Referrer-Policy': 'no-referrer',\n },\n });\n } finally {\n releaseDownloadSlot(record.token);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { resolveGatewayEffectiveHost } from "../../../config/gateway-bind.js";
|
|
2
|
-
import { getClientIpFromHeaders } from "../../auth-rate-limit.js";
|
|
3
2
|
import { extractToken } from "../../auth.js";
|
|
4
3
|
import { TUNNEL_CONSENT_REQUIRED_CODE, TunnelConsentError, assertTunnelMayStart, getTunnelConsentState } from "../../../tunnel/consent.js";
|
|
5
4
|
import { getTunnelRegistrationSecretMeta, readTunnelRegistrationSecretFromConfigOnly, resolveTunnelBrokerUrl } from "../../../tunnel/env.js";
|
|
@@ -9,6 +8,7 @@ import { logTunnelAudit } from "../../../tunnel/tunnel-audit.js";
|
|
|
9
8
|
import { getTunnelService, hashGatewayToken } from "../../../tunnel/tunnel-service.js";
|
|
10
9
|
import { configureTunnelFromGatewayConfig } from "../../../tunnel/gateway-lifecycle.js";
|
|
11
10
|
import { applyTunnelConsentToConfig, setTunnelEnabledInConfig } from "../../../tunnel/tunnel-config.js";
|
|
11
|
+
import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
12
12
|
import { applyLanPairingGatewayPatch } from "../../../tunnel/enable-lan-pairing.js";
|
|
13
13
|
import { consumeTunnelMutationLimit } from "../../../tunnel/tunnel-rate-limit.js";
|
|
14
14
|
import "../../../tunnel/index.js";
|