@xopcai/xopc 0.0.113 → 0.0.114
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CBlklyNr.js → agent-avatar-dicebear-Fp-p7bP1.js} +1 -1
- package/dist/gateway/static/root/assets/agent-browser-settings-page-CWh7trjd.js +6 -0
- package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-kC8OuLoj.js +1 -0
- package/dist/gateway/static/root/assets/agents-DJWG26Si.js +71 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-28E_WfMe.js → app-management-settings-panel-v24i25Oj.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-Do1z0XgJ.js → appearance-settings-ycbdJRuZ.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-0V3DXZ7J.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BAFlsov_.js → archive-plugin-CJzSADJo.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-V3qGPC3x.js → attachment-load-BTAB4zGS.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-DT8NvA6W.js → binary-plugins-DXR1-mct.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CdLMEcHd.js → block-editor-CzQri9h2.js} +44 -44
- package/dist/gateway/static/root/assets/channels-settings-CIKOkYdO.js +1 -0
- package/dist/gateway/static/root/assets/{config-api-Bf5mjpu7.js → config-api-DRqjEvAx.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-settings-ClrDS5jH.js +2 -0
- package/dist/gateway/static/root/assets/{cron-api--pAB_rps.js → cron-api-BXaZXv1o.js} +1 -1
- package/dist/gateway/static/root/assets/cron-page-Chi_4u4P.js +3 -0
- package/dist/gateway/static/root/assets/dreaming-settings-B0_rs2tj.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-BGhE7msg.js → extension-debug-page-DSkqMYo7.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CvpI45WG.js → extension-page-h2dGDbMN.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DAmR5FUe.js → extension-settings-page-hN99RhOi.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-NZmjSXLl.js → fetch-D9QqUtzZ.js} +1 -1
- package/dist/gateway/static/root/assets/{format-interval-label-qhth3BMV.js → format-interval-label-D6E687rG.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-CaXBt-9R.js → gateway-config-api-CLt_SKTC.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-DphpbLBc.js → gateway-settings-1PDi4lI0.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-Be1omjh3.js → gateway-startup-retry-N7Z_sz7p.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-D_wwXL-t.js +1 -0
- package/dist/gateway/static/root/assets/goals-page-DZ2toZ8y.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-ceEBjnfc.js → goals-settings-LFlwtIKE.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BzO6G4fD.js → heartbeat-config-api-DGPadTw-.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-DCST9-du.js → heartbeat-settings-BHHAs8ZX.js} +1 -1
- package/dist/gateway/static/root/assets/index-DefIdW9q.js +122 -0
- package/dist/gateway/static/root/assets/index-DzmWBkq-.css +1 -0
- package/dist/gateway/static/root/assets/{interval-presets-DJmshV8n.js → interval-presets-CEklPQ_r.js} +1 -1
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-9AUUlQ5Q.js → keyboard-shortcuts-settings-Ce_aQ8Iv.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-j_D2QTuQ.js +2 -0
- package/dist/gateway/static/root/assets/{markdown-split-CYYELqAr.js → markdown-split-BMz3xPXO.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-BEcMR2M8.js → media-plugins-BalOSoz9.js} +1 -1
- package/dist/gateway/static/root/assets/messages-BN_WiUg0.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-CMH_TmZz.js +2 -0
- package/dist/gateway/static/root/assets/note-detail-page-O18BrQPq.js +2 -0
- package/dist/gateway/static/root/assets/{note-image-lightbox-DNAoPcmm.js → note-image-lightbox-C5D1Q5mY.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-B_ZYCmY9.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-BPLz0AIv.js → preview-open-alternatives-CYFR5U9l.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CwKgWixY.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-CrWwWRVK.js → save-bar-controls-BQ79Z5IP.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-CF2sadvN.js → schedule-field-Bgk6Emue.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-Di5cKjYE.js → schema-form-DzS36TMa.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-C4fcD-7B.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-Ad2OJ86w.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-Chh282jW.js → settings-collapsible-section-CdjFnSAy.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-Dq-83cQd.js → settings-form-section-DZLy_exu.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-D2BMY5wo.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-aWwxl_E1.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-0FXYnSUA.js → share-preview-page-_qRDr4g_.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-DUE83uIf.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-mWKJcrog.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-0Sx1Q58n.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-W1pTcojB.js → system-settings-panel-hqaBF5aG.js} +1 -1
- package/dist/gateway/static/root/assets/{use-agent-defaults-form-BVRvkK7m.js → use-agent-defaults-form-zbVIQLOA.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-CgJibfMM.js → use-channel-catalog-CbXq97rT.js} +1 -1
- package/dist/gateway/static/root/assets/{use-settings-tab-guard-Bw_qkRQE.js → use-settings-tab-guard-DwS3drWK.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-D6HR0hR2.js +1 -0
- package/dist/gateway/static/root/assets/{voice-player-store-C7lziaAx.js → voice-player-store-DSuOd9zy.js} +1 -1
- package/dist/gateway/static/root/assets/workflow-page.utils-C0Uq3xyq.js +1 -0
- package/dist/gateway/static/root/assets/workflows-page-DW0fmWhQ.js +18 -0
- package/dist/gateway/static/root/index.html +5 -5
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +8 -0
- package/dist/src/agent/agent-manager.js +57 -22
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/bootstrap/project-agents-context.d.ts +2 -0
- package/dist/src/agent/bootstrap/project-agents-context.js +32 -0
- package/dist/src/agent/bootstrap/project-agents-context.js.map +1 -0
- package/dist/src/agent/goals/persistent-goal-service.js +2 -4
- package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
- package/dist/src/agent/inbound/inbound-loop.js +5 -1
- package/dist/src/agent/inbound/inbound-loop.js.map +1 -1
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +2 -2
- package/dist/src/agent/inbound/turn-dispatcher.js +2 -2
- package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.d.ts +27 -0
- package/dist/src/agent/mcp/bundle-mcp-materialize.js +49 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +78 -3
- package/dist/src/agent/mcp/bundle-mcp-runtime.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-types.d.ts +19 -0
- package/dist/src/agent/service/btw-query.js +11 -3
- package/dist/src/agent/service/btw-query.js.map +1 -1
- package/dist/src/agent/service/parse-outbound-session-key.js +13 -8
- package/dist/src/agent/service/parse-outbound-session-key.js.map +1 -1
- package/dist/src/agent/service/process-direct-one-shot.d.ts +2 -2
- package/dist/src/agent/service/process-direct-one-shot.js +1 -1
- 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 +1 -1
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.d.ts +1 -1
- package/dist/src/agent/service.js +9 -5
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/service.types.d.ts +5 -0
- package/dist/src/agent/skills/filesystem-watcher.js +4 -3
- package/dist/src/agent/skills/filesystem-watcher.js.map +1 -1
- package/dist/src/agent/skills/index.js +2 -1
- package/dist/src/agent/skills/index.js.map +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +2 -1
- package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
- package/dist/src/agent/skills/types.d.ts +1 -1
- package/dist/src/agent/skills/watcher.js +2 -5
- package/dist/src/agent/skills/watcher.js.map +1 -1
- package/dist/src/agent/skills/workspace-skills-dir.d.ts +1 -0
- package/dist/src/agent/skills/workspace-skills-dir.js +11 -0
- package/dist/src/agent/skills/workspace-skills-dir.js.map +1 -0
- package/dist/src/agent/tool-manuals/browser.d.ts +1 -1
- package/dist/src/agent/tool-manuals/browser.js +62 -3
- package/dist/src/agent/tool-manuals/browser.js.map +1 -1
- package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +4 -1
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +13 -4
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
- package/dist/src/agent/tools/browser/tool/schemas.d.ts +0 -2
- package/dist/src/agent/tools/browser/tool/schemas.js +1 -2
- package/dist/src/agent/tools/browser/tool/schemas.js.map +1 -1
- package/dist/src/agent/tools/factory.js +1 -10
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js.map +1 -1
- package/dist/src/agent/workflow/subagent-runner.js +18 -1
- package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
- package/dist/src/browser/actions/extension-registry-bridge.js +91 -7
- package/dist/src/browser/actions/extension-registry-bridge.js.map +1 -1
- package/dist/src/browser/actions/registry.js +383 -7
- package/dist/src/browser/actions/registry.js.map +1 -1
- package/dist/src/browser/actions/types.d.ts +11 -3
- package/dist/src/browser/index.js +2 -2
- package/dist/src/browser/pipeline/output.d.ts +18 -16
- package/dist/src/browser/pipeline/output.js +28 -20
- package/dist/src/browser/pipeline/output.js.map +1 -1
- package/dist/src/browser/pipeline/runner.d.ts +7 -14
- package/dist/src/browser/pipeline/runner.js +349 -102
- package/dist/src/browser/pipeline/runner.js.map +1 -1
- package/dist/src/browser/pipeline/schema.d.ts +1 -0
- package/dist/src/browser/pipeline/schema.js +35 -58
- package/dist/src/browser/pipeline/schema.js.map +1 -1
- package/dist/src/browser/pipeline/source.d.ts +2 -0
- package/dist/src/browser/pipeline/source.js +10 -1
- package/dist/src/browser/pipeline/source.js.map +1 -1
- package/dist/src/browser/pipeline/template.d.ts +10 -2
- package/dist/src/browser/pipeline/template.js +50 -8
- package/dist/src/browser/pipeline/template.js.map +1 -1
- package/dist/src/chat-commands/builtins/config.js +3 -5
- package/dist/src/chat-commands/builtins/config.js.map +1 -1
- package/dist/src/chat-commands/context.d.ts +5 -0
- package/dist/src/chat-commands/context.js +18 -9
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/chat-commands/index.d.ts +1 -1
- package/dist/src/chat-commands/index.js +2 -2
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/chat-commands/processor.js +22 -21
- package/dist/src/chat-commands/processor.js.map +1 -1
- package/dist/src/chat-commands/session-key.d.ts +3 -15
- package/dist/src/chat-commands/session-key.js +3 -49
- package/dist/src/chat-commands/session-key.js.map +1 -1
- package/dist/src/chat-commands/types.d.ts +4 -0
- package/dist/src/cli/commands/browser-cli-helpers.js +11 -5
- package/dist/src/cli/commands/browser-cli-helpers.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +8 -8
- package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -1
- package/dist/src/config/rules.js +5 -0
- package/dist/src/config/rules.js.map +1 -1
- package/dist/src/connectors/builtin-catalog.js +180 -1
- package/dist/src/connectors/builtin-catalog.js.map +1 -1
- package/dist/src/connectors/health.js +18 -9
- package/dist/src/connectors/health.js.map +1 -1
- package/dist/src/connectors/types.d.ts +19 -0
- package/dist/src/connectors/usage.js +12 -4
- package/dist/src/connectors/usage.js.map +1 -1
- package/dist/src/extensions/types/tui.d.ts +2 -0
- package/dist/src/gateway/heartbeat/service.js +13 -1
- package/dist/src/gateway/heartbeat/service.js.map +1 -1
- package/dist/src/gateway/hono/app.js +13 -4
- package/dist/src/gateway/hono/app.js.map +1 -1
- package/dist/src/gateway/hono/oauth-async.js +1 -1
- package/dist/src/gateway/hono/routes/agent-stream.js +6 -6
- package/dist/src/gateway/hono/routes/agent-stream.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +1 -1
- package/dist/src/gateway/hono/routes/config-patch/gateway.js +6 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/goals.js +16 -3
- package/dist/src/gateway/hono/routes/goals.js.map +1 -1
- package/dist/src/gateway/hono/routes/logs.js +1 -0
- package/dist/src/gateway/hono/routes/logs.js.map +1 -1
- package/dist/src/gateway/hono/routes/mcp.js +27 -8
- package/dist/src/gateway/hono/routes/mcp.js.map +1 -1
- package/dist/src/gateway/hono/routes/notes.js +14 -2
- package/dist/src/gateway/hono/routes/notes.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +62 -4
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +3 -66
- package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
- package/dist/src/gateway/hono/sse.d.ts +2 -2
- package/dist/src/gateway/hono/sse.js +7 -15
- package/dist/src/gateway/hono/sse.js.map +1 -1
- package/dist/src/gateway/resolve-webchat-session-key.d.ts +2 -6
- package/dist/src/gateway/resolve-webchat-session-key.js +5 -31
- package/dist/src/gateway/resolve-webchat-session-key.js.map +1 -1
- package/dist/src/gateway/service/agent-runner.d.ts +2 -3
- package/dist/src/gateway/service/agent-runner.js +9 -22
- package/dist/src/gateway/service/agent-runner.js.map +1 -1
- package/dist/src/gateway/service/run-gateway-agent.js +9 -7
- package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +9 -0
- package/dist/src/gateway/service/sessions-api.js +11 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.d.ts +1 -1
- package/dist/src/gateway/service.js +19 -5
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-file-search.d.ts +9 -0
- package/dist/src/gateway/workspace-file-search.js +76 -0
- package/dist/src/gateway/workspace-file-search.js.map +1 -0
- package/dist/src/goals/goal-notifications.d.ts +2 -0
- package/dist/src/goals/goal-notifications.js +16 -11
- package/dist/src/goals/goal-notifications.js.map +1 -1
- package/dist/src/goals/goal-service.js +1 -6
- package/dist/src/goals/goal-service.js.map +1 -1
- package/dist/src/project-trust/trust-store.js +2 -0
- package/dist/src/project-trust/trust-store.js.map +1 -1
- package/dist/src/session/index.d.ts +1 -1
- package/dist/src/session/index.js +2 -2
- package/dist/src/session/init-session-turn.js +6 -9
- package/dist/src/session/init-session-turn.js.map +1 -1
- package/dist/src/session/manager.d.ts +5 -1
- package/dist/src/session/manager.js +5 -2
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/reset-type.d.ts +0 -2
- package/dist/src/session/reset-type.js +3 -9
- package/dist/src/session/reset-type.js.map +1 -1
- package/dist/src/session/resolve-session.js +9 -20
- package/dist/src/session/resolve-session.js.map +1 -1
- package/dist/src/session/store.d.ts +11 -3
- package/dist/src/session/store.js +29 -13
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/types.d.ts +2 -4
- package/dist/src/session/types.js.map +1 -1
- package/dist/src/storage/sqlite/index.d.ts +2 -2
- package/dist/src/storage/sqlite/index.js +3 -3
- package/dist/src/storage/sqlite/migrations/010_session_id_identity.sql +30 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +2 -2
- package/dist/src/storage/sqlite/migrations/runner.js +4 -4
- package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +2 -2
- package/dist/src/storage/sqlite/row-mappers.d.ts +4 -4
- package/dist/src/storage/sqlite/row-mappers.js +11 -14
- package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
- package/dist/src/storage/sqlite/schema.js +3 -3
- package/dist/src/storage/sqlite/schema.js.map +1 -1
- package/dist/src/storage/sqlite/schema.sql +37 -10
- package/dist/src/storage/sqlite/session-metadata.d.ts +2 -7
- package/dist/src/storage/sqlite/session-metadata.js +18 -72
- package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
- package/dist/src/storage/sqlite/session-repository.d.ts +6 -5
- package/dist/src/storage/sqlite/session-repository.js +34 -40
- package/dist/src/storage/sqlite/session-repository.js.map +1 -1
- package/dist/src/storage/sqlite/transcript-repository.d.ts +2 -2
- package/dist/src/storage/sqlite/transcript-repository.js +52 -52
- package/dist/src/storage/sqlite/transcript-repository.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +11 -4
- package/dist/src/tui/backends/embedded-backend.js +27 -1
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +4 -1
- package/dist/src/tui/backends/gateway-sse-backend.js +21 -2
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/extension-host/autocomplete.js +13 -10
- package/dist/src/tui/extension-host/autocomplete.js.map +1 -1
- package/dist/src/tui/extension-host/runtime.d.ts +7 -0
- package/dist/src/tui/extension-host/runtime.js +6 -4
- package/dist/src/tui/extension-host/runtime.js.map +1 -1
- package/dist/src/tui/tui-backend.d.ts +9 -0
- package/dist/src/tui/tui-commands.js +85 -6
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-file-autocomplete.d.ts +5 -0
- package/dist/src/tui/tui-file-autocomplete.js +26 -0
- package/dist/src/tui/tui-file-autocomplete.js.map +1 -0
- package/dist/src/tui/tui-picker-overlay.js +1 -1
- package/dist/src/tui/tui.js +29 -11
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/utils/logger/context.d.ts +2 -2
- package/dist/src/utils/logger/context.js +2 -1
- package/dist/src/utils/logger/context.js.map +1 -1
- package/dist/src/utils/logger/log-store.js +1 -0
- package/dist/src/utils/logger/log-store.js.map +1 -1
- package/dist/src/utils/logger/pino-record.js +3 -0
- package/dist/src/utils/logger/pino-record.js.map +1 -1
- package/dist/src/utils/logger/types.d.ts +5 -0
- package/dist/src/utils/logger/types.js.map +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.js +13 -1
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agent-browser-settings-page-rGbKc2Hh.js +0 -6
- package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-CtwVbjOA.js +0 -1
- package/dist/gateway/static/root/assets/agents-CCBmGcwc.js +0 -71
- package/dist/gateway/static/root/assets/apps-page-xwCsJS15.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-C044DcYk.js +0 -1
- package/dist/gateway/static/root/assets/connectors-settings-8VEWUOTj.js +0 -2
- package/dist/gateway/static/root/assets/cron-page-DqmNGNOy.js +0 -3
- package/dist/gateway/static/root/assets/dreaming-settings-6UZE1FSK.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-bv0VRDaf.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-1Ywnt4Cb.js +0 -2
- package/dist/gateway/static/root/assets/index-Cxm6xsps.js +0 -122
- package/dist/gateway/static/root/assets/index-b_R4tKqt.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-B_wrxhee.js +0 -2
- package/dist/gateway/static/root/assets/messages-CkT-lcgP.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-D0JDSbNu.js +0 -2
- package/dist/gateway/static/root/assets/note-detail-page-DpFV-EO6.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-CdkjTch8.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DSYVAi96.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CenkcVjF.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-D9sva86V.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-DL35U0x0.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Ctwbp9Er.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-DIM3JNsr.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DAlNaNzL.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-CLrHVzAt.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-vYAO71Gn.js +0 -1
- package/dist/gateway/static/root/assets/workflow-page.utils-sgHjOXOm.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-DYyOTmFx.js +0 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","names":[],"sources":["../../../../src/gateway/hono/app.ts"],"sourcesContent":["import { Hono } from 'hono';\nimport type { Context } from 'hono';\nimport { cors } from 'hono/cors';\nimport { createMiddleware } from 'hono/factory';\nimport { bodyLimit } from 'hono/body-limit';\nimport { getConnInfo } from '@hono/node-server/conninfo';\n\nimport { resolveGatewayEffectiveHost } from '../../config/gateway-bind.js';\nimport { createLogger } from '../../utils/logger.js';\nimport type { GatewayService } from '../service.js';\nimport { resolveAllowedBrowserOrigins, resolveGatewayServiceListenPort } from '../host.js';\nimport { loadTunnelState } from '../../tunnel/tunnel-state.js';\nimport { maxWebchatAgentRequestBodyBytes } from '../chat-limits.js';\nimport { buildGatewayConsoleCspHeader } from '../security/csp.js';\nimport { checkBrowserOrigin } from '../security/origin-check.js';\nimport { isLoopbackIpAddress, isTrustedProxyAddress } from '../client-ip.js';\nimport { resolveReverseProxyPublicUrl } from '../public-url.js';\nimport { auth } from './middleware/auth.js';\nimport { operatorScopes } from './middleware/scopes.js';\nimport { createStrictRateLimitMiddleware } from './middleware/strict-rate-limit.js';\nimport { logContextMiddleware } from './middleware/log-context.js';\nimport { logger } from './middleware/logger.js';\nimport { routeErrorMiddleware } from './middleware/route-errors.js';\nimport { registerPublicExtensionAssetRoutes } from './routes/auth-registry-extensions.js';\nimport { registerAuthenticatedRoutes } from './routes/index.js';\nimport { registerPublicGatewayRoutes } from './routes/public-gateway.js';\nimport { resetLazyRouteBundlesForTests } from './routes/lazy-fallback.js';\nimport { prewarmStaticUiCache } from './lib/static-ui.js';\nimport { registerSiteShareMiddleware } from '../../share/site-share-router.js';\nconst log = createLogger('Gateway:App');\n\nexport interface HonoAppConfig {\n service: GatewayService;\n token?: string;\n}\n\n/**\n * Extension sandbox HTML under `/api/extensions/:id/assets/*` ships its own CSP\n * (`frame-ancestors 'self'`). The global gateway middleware must not overwrite it\n * with `frame-ancestors 'none'` / `X-Frame-Options: DENY`, or the console cannot embed iframes.\n */\nexport function isExtensionGatewayUiAssetPath(path: string): boolean {\n return /^\\/api\\/extensions\\/[^/]+\\/assets\\//.test(path);\n}\n\nexport function createHonoApp(config: HonoAppConfig): Hono {\n if (process.env.VITEST) {\n resetLazyRouteBundlesForTests();\n }\n const { service, token } = config;\n const app = new Hono();\n\n const gatewayPort = resolveGatewayServiceListenPort(service);\n\n const resolveBrowserOrigins = (): string[] =>\n resolveAllowedBrowserOrigins({\n configuredOrigins: service.currentConfig.gateway.corsOrigins,\n port: gatewayPort,\n bindHost: resolveGatewayEffectiveHost(service.currentConfig),\n tunnelPublicUrl: loadTunnelState()?.publicUrl,\n reverseProxyPublicUrl: resolveReverseProxyPublicUrl(service.currentConfig),\n });\n\n /**\n * TCP source for the in-flight request, normalized for trusted-proxy checks.\n * Returns undefined when the runtime doesn't expose conninfo (tests, mocks).\n */\n const resolveRequestRemoteAddress = (c: Context): string | undefined => {\n try {\n return getConnInfo(c).remote.address;\n } catch {\n return undefined;\n }\n };\n\n /**\n * A request's TCP source qualifies as a \"trusted proxy hop\" when it's\n * loopback (the user's own machine, where any reverse proxy lives) or\n * listed in `gateway.trustedProxies`. We use this signal to safely\n * auto-allow same-host Origins through CSRF without requiring a manual\n * `corsOrigins` entry for every reverse-proxy hostname.\n */\n const isRequestFromTrustedProxy = (c: Context): boolean => {\n const remote = resolveRequestRemoteAddress(c);\n if (!remote) return false;\n if (isLoopbackIpAddress(remote)) return true;\n return isTrustedProxyAddress(remote, service.currentConfig.gateway?.trustedProxies);\n };\n\n app.use(logContextMiddleware());\n app.use(logger({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }));\n\n // Site-share middleware runs BEFORE CORS/CSP — it owns the request when the\n // Host header matches `*.<publicHostSuffix>` (default `*.share.xopc.ai`) or\n // the path starts with `/site/:token/`. Otherwise it falls through.\n registerSiteShareMiddleware(app, service);\n app.use(\n cors({\n origin: (origin) => {\n const allowed = resolveBrowserOrigins();\n if (!origin) {\n return allowed[0] ?? `http://127.0.0.1:${gatewayPort}`;\n }\n const normalized = origin.toLowerCase();\n const hit = allowed.find((entry) => entry.toLowerCase() === normalized);\n if (hit) return origin;\n return allowed.includes('*') ? '*' : '';\n },\n allowMethods: ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS'],\n allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'X-Session-Id', 'Last-Event-ID'],\n credentials: true,\n maxAge: 86400,\n }),\n );\n\n // Build CSP header once at startup (no inline script hashes needed for SPA)\n const gatewayConsoleCsp = buildGatewayConsoleCspHeader();\n\n // Security headers middleware\n app.use(createMiddleware(async (c, next) => {\n await next();\n if (isExtensionGatewayUiAssetPath(c.req.path)) {\n return;\n }\n c.header('X-Frame-Options', 'DENY');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Referrer-Policy', 'strict-origin-when-cross-origin');\n c.header('X-XSS-Protection', '1; mode=block');\n // microphone=(self): allow same-origin chat voice (composer). microphone=() breaks packaged Electron loading the gateway SPA.\n c.header('Permissions-Policy', 'camera=(), microphone=(self), geolocation=()');\n c.header('Content-Security-Policy', gatewayConsoleCsp);\n }));\n\n // Browser Origin check middleware for API routes (CSRF protection).\n // Non-browser requests (no Origin header) pass through — they are\n // authenticated by the token middleware instead.\n const allowHostHeaderOriginFallback =\n service.currentConfig.gateway?.dangerouslyAllowHostHeaderOriginFallback === true;\n app.use('/api/*', createMiddleware(async (c, next) => {\n // Sandboxed extension iframes (no allow-same-origin) send `Origin: null`.\n // `checkBrowserOrigin` rejects that; these routes rely on CSP instead\n // (`registerPublicExtensionAssetRoutes`).\n if (isExtensionGatewayUiAssetPath(c.req.path)) {\n return next();\n }\n\n const origin = c.req.header('origin');\n if (!origin || origin.trim().toLowerCase() === 'null') {\n // Native apps / opaque origins — authenticated via Bearer token\n return next();\n }\n\n const result = checkBrowserOrigin({\n requestHost: c.req.header('host'),\n origin,\n allowedOrigins: resolveBrowserOrigins(),\n allowHostHeaderOriginFallback,\n autoAllowSameHostFromTrustedProxy: isRequestFromTrustedProxy(c),\n isLocalClient: false,\n });\n\n if (!result.ok) {\n log.warn(\n {\n origin,\n requestHost: c.req.header('host'),\n reason: 'reason' in result ? result.reason : 'unknown',\n path: c.req.path,\n method: c.req.method,\n },\n `Browser origin check failed: ${origin} not in allowed list`,\n );\n return c.json({ error: 'Forbidden', message: 'Origin not allowed' }, 403);\n }\n\n return next();\n }));\n\n app.use('/api/skills/upload', bodyLimit({\n maxSize: 10 * 1024 * 1024,\n onError: (c) => {\n log.warn({ path: c.req.path, maxSizeMb: 10 }, 'Request body too large: skills upload exceeds 10MB limit');\n return c.json({ error: 'Skill package too large', maxSize: '10MB' }, 413);\n },\n }));\n\n const DEFAULT_API_BODY_MAX = 1 * 1024 * 1024;\n const WEBCHAT_AGENT_BODY_MAX = maxWebchatAgentRequestBodyBytes();\n\n app.use('/api/*', async (c, next) => {\n const maxSize = c.req.path === '/api/agent' ? WEBCHAT_AGENT_BODY_MAX : DEFAULT_API_BODY_MAX;\n const maxSizeMb = Math.ceil(maxSize / (1024 * 1024));\n return bodyLimit({\n maxSize,\n onError: (ctx) => {\n log.warn({ path: ctx.req.path, maxSizeMb }, `Request body too large: exceeds ${maxSizeMb}MB limit`);\n return ctx.json({ error: 'Request body too large', maxSize: `${maxSizeMb}MB` }, 413);\n },\n })(c, next);\n });\n\n registerPublicGatewayRoutes(app, service);\n\n // Extension UI assets are served without auth: sandboxed iframes (no allow-same-origin)\n // have an opaque origin of `null` and cannot forward the ?token= from the parent HTML URL.\n // Security is enforced by the strict CSP (frame-ancestors 'self') on every response.\n registerPublicExtensionAssetRoutes(app, service);\n\n const authenticated = new Hono();\n authenticated.use(routeErrorMiddleware());\n authenticated.use(\n auth({\n token,\n getGatewayAuth: () => service.currentConfig.gateway?.auth,\n getResolvedAuth: () => {\n if (typeof service.getResolvedAuth === 'function') {\n return service.getResolvedAuth();\n }\n return token ? { mode: 'token', token } : { mode: 'none' };\n },\n getTrustedProxyContext: () => ({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }),\n }),\n );\n authenticated.use(operatorScopes());\n\n const strictRateLimitMiddleware = createStrictRateLimitMiddleware({\n getTrustedProxyContext: () => ({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }),\n });\n\n const sseConfig = {\n service,\n maxSseConnections: service.currentConfig.gateway.maxSseConnections,\n };\n\n registerAuthenticatedRoutes(app, authenticated, {\n service,\n strictRateLimitMiddleware,\n sseConfig,\n });\n\n const prewarm = prewarmStaticUiCache();\n if (prewarm.loaded > 0) {\n log.debug({ loaded: prewarm.loaded, missing: prewarm.missing }, 'Static UI cache prewarmed');\n }\n\n app.route('/', authenticated);\n\n app.notFound((c) => {\n const isApiRoute = c.req.path.startsWith('/api/');\n const fields = { path: c.req.path, method: c.req.method };\n if (isApiRoute) {\n log.warn(fields, 'Route not found');\n } else {\n log.debug(fields, 'Route not found');\n }\n return c.json({ error: 'Not found' }, 404);\n });\n\n app.onError((err, c) => {\n log.error(\n {\n err,\n phase: 'gateway.http.unhandled',\n path: c.req.path,\n method: c.req.method,\n userAgent: c.req.header('user-agent'),\n },\n `Hono error on ${c.req.method} ${c.req.path}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return c.json({ error: 'Internal server error' }, 500);\n });\n\n return app;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app.js","names":[],"sources":["../../../../src/gateway/hono/app.ts"],"sourcesContent":["import { Hono } from 'hono';\nimport type { Context } from 'hono';\nimport { cors } from 'hono/cors';\nimport { createMiddleware } from 'hono/factory';\nimport { bodyLimit } from 'hono/body-limit';\nimport { getConnInfo } from '@hono/node-server/conninfo';\n\nimport { resolveGatewayEffectiveHost } from '../../config/gateway-bind.js';\nimport { createLogger } from '../../utils/logger.js';\nimport type { GatewayService } from '../service.js';\nimport { resolveAllowedBrowserOrigins, resolveGatewayServiceListenPort } from '../host.js';\nimport { loadTunnelState } from '../../tunnel/tunnel-state.js';\nimport { maxWebchatAgentRequestBodyBytes } from '../chat-limits.js';\nimport { buildGatewayConsoleCspHeader } from '../security/csp.js';\nimport { checkBrowserOrigin } from '../security/origin-check.js';\nimport { isLoopbackIpAddress, isTrustedProxyAddress } from '../client-ip.js';\nimport { resolveReverseProxyPublicUrl } from '../public-url.js';\nimport { auth } from './middleware/auth.js';\nimport { operatorScopes } from './middleware/scopes.js';\nimport { createStrictRateLimitMiddleware } from './middleware/strict-rate-limit.js';\nimport { logContextMiddleware } from './middleware/log-context.js';\nimport { logger } from './middleware/logger.js';\nimport { routeErrorMiddleware } from './middleware/route-errors.js';\nimport { registerPublicExtensionAssetRoutes } from './routes/auth-registry-extensions.js';\nimport { registerAuthenticatedRoutes } from './routes/index.js';\nimport { registerPublicGatewayRoutes } from './routes/public-gateway.js';\nimport { resetLazyRouteBundlesForTests } from './routes/lazy-fallback.js';\nimport { prewarmStaticUiCache } from './lib/static-ui.js';\nimport { registerSiteShareMiddleware } from '../../share/site-share-router.js';\nconst log = createLogger('Gateway:App');\n\nexport interface HonoAppConfig {\n service: GatewayService;\n token?: string;\n}\n\n/**\n * Extension sandbox HTML under `/api/extensions/:id/assets/*` ships its own CSP\n * (`frame-ancestors 'self'`). The global gateway middleware must not overwrite it\n * with `frame-ancestors 'none'` / `X-Frame-Options: DENY`, or the console cannot embed iframes.\n */\nexport function isExtensionGatewayUiAssetPath(path: string): boolean {\n return /^\\/api\\/extensions\\/[^/]+\\/assets\\//.test(path);\n}\n\nexport function createHonoApp(config: HonoAppConfig): Hono {\n if (process.env.VITEST) {\n resetLazyRouteBundlesForTests();\n }\n const { service, token } = config;\n const app = new Hono();\n\n const gatewayPort = resolveGatewayServiceListenPort(service);\n\n const resolveBrowserOrigins = (): string[] =>\n resolveAllowedBrowserOrigins({\n configuredOrigins: service.currentConfig.gateway.corsOrigins,\n port: gatewayPort,\n bindHost: resolveGatewayEffectiveHost(service.currentConfig),\n tunnelPublicUrl: loadTunnelState()?.publicUrl,\n reverseProxyPublicUrl: resolveReverseProxyPublicUrl(service.currentConfig),\n });\n\n /**\n * TCP source for the in-flight request, normalized for trusted-proxy checks.\n * Returns undefined when the runtime doesn't expose conninfo (tests, mocks).\n */\n const resolveRequestRemoteAddress = (c: Context): string | undefined => {\n try {\n return getConnInfo(c).remote.address;\n } catch {\n return undefined;\n }\n };\n\n /**\n * A request's TCP source qualifies as a \"trusted proxy hop\" when it's\n * loopback (the user's own machine, where any reverse proxy lives) or\n * listed in `gateway.trustedProxies`. We use this signal to safely\n * auto-allow same-host Origins through CSRF without requiring a manual\n * `corsOrigins` entry for every reverse-proxy hostname.\n */\n const isRequestFromTrustedProxy = (c: Context): boolean => {\n const remote = resolveRequestRemoteAddress(c);\n if (!remote) return false;\n if (isLoopbackIpAddress(remote)) return true;\n return isTrustedProxyAddress(remote, service.currentConfig.gateway?.trustedProxies);\n };\n\n app.use(logContextMiddleware());\n app.use(logger({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }));\n\n // Site-share middleware runs BEFORE CORS/CSP — it owns the request when the\n // Host header matches `*.<publicHostSuffix>` (default `*.share.xopc.ai`) or\n // the path starts with `/site/:token/`. Otherwise it falls through.\n registerSiteShareMiddleware(app, service);\n app.use(\n cors({\n origin: (origin) => {\n const allowed = resolveBrowserOrigins();\n if (!origin) {\n return allowed[0] ?? `http://127.0.0.1:${gatewayPort}`;\n }\n const normalized = origin.toLowerCase();\n const hit = allowed.find((entry) => entry.toLowerCase() === normalized);\n if (hit) return origin;\n return allowed.includes('*') ? '*' : '';\n },\n allowMethods: ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS'],\n allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'X-Session-Id', 'Last-Event-ID'],\n credentials: true,\n maxAge: 86400,\n }),\n );\n\n // Build CSP header once at startup (no inline script hashes needed for SPA)\n const gatewayConsoleCsp = buildGatewayConsoleCspHeader();\n\n // Security headers middleware\n app.use(createMiddleware(async (c, next) => {\n await next();\n if (isExtensionGatewayUiAssetPath(c.req.path)) {\n return;\n }\n c.header('X-Frame-Options', 'DENY');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Referrer-Policy', 'strict-origin-when-cross-origin');\n c.header('X-XSS-Protection', '1; mode=block');\n // microphone=(self): allow same-origin chat voice (composer). microphone=() breaks packaged Electron loading the gateway SPA.\n c.header('Permissions-Policy', 'camera=(), microphone=(self), geolocation=()');\n c.header('Content-Security-Policy', gatewayConsoleCsp);\n }));\n\n // Browser Origin check middleware for API routes (CSRF protection).\n // Non-browser requests (no Origin header) pass through — they are\n // authenticated by the token middleware instead.\n const allowHostHeaderOriginFallback =\n service.currentConfig.gateway?.dangerouslyAllowHostHeaderOriginFallback === true;\n app.use('/api/*', createMiddleware(async (c, next) => {\n // Sandboxed extension iframes (no allow-same-origin) send `Origin: null`.\n // `checkBrowserOrigin` rejects that; these routes rely on CSP instead\n // (`registerPublicExtensionAssetRoutes`).\n if (isExtensionGatewayUiAssetPath(c.req.path)) {\n return next();\n }\n\n const origin = c.req.header('origin');\n if (!origin || origin.trim().toLowerCase() === 'null') {\n // Native apps / opaque origins — authenticated via Bearer token\n return next();\n }\n\n const result = checkBrowserOrigin({\n requestHost: c.req.header('host'),\n origin,\n allowedOrigins: resolveBrowserOrigins(),\n allowHostHeaderOriginFallback,\n autoAllowSameHostFromTrustedProxy: isRequestFromTrustedProxy(c),\n isLocalClient: false,\n });\n\n if (!result.ok) {\n log.warn(\n {\n origin,\n requestHost: c.req.header('host'),\n reason: 'reason' in result ? result.reason : 'unknown',\n path: c.req.path,\n method: c.req.method,\n },\n `Browser origin check failed: ${origin} not in allowed list`,\n );\n return c.json({ error: 'Forbidden', message: 'Origin not allowed' }, 403);\n }\n\n return next();\n }));\n\n const DEFAULT_API_BODY_MAX = 1 * 1024 * 1024;\n const SKILL_UPLOAD_BODY_MAX = 10 * 1024 * 1024;\n const NOTE_MEDIA_BODY_MAX = 25 * 1024 * 1024;\n const VOICE_TRANSCRIBE_BODY_MAX = 35 * 1024 * 1024;\n const WEBCHAT_AGENT_BODY_MAX = maxWebchatAgentRequestBodyBytes();\n\n const isNoteMediaUploadRequest = (path: string, method: string, contentType: string | undefined): boolean => {\n if (method !== 'POST') return false;\n if (/^\\/api\\/notes\\/[^/]+\\/media$/.test(path)) return true;\n return path === '/api/notes' && contentType?.includes('multipart/form-data') === true;\n };\n\n app.use('/api/skills/upload', bodyLimit({\n maxSize: SKILL_UPLOAD_BODY_MAX,\n onError: (c) => {\n log.warn({ path: c.req.path, maxSizeMb: 10 }, 'Request body too large: skills upload exceeds 10MB limit');\n return c.json({ error: 'Skill package too large', maxSize: '10MB' }, 413);\n },\n }));\n\n app.use('/api/*', async (c, next) => {\n const contentType = c.req.header('content-type');\n const maxSize = c.req.path === '/api/agent'\n ? WEBCHAT_AGENT_BODY_MAX\n : c.req.path === '/api/skills/upload'\n ? SKILL_UPLOAD_BODY_MAX\n : c.req.path === '/api/voice/transcribe'\n ? VOICE_TRANSCRIBE_BODY_MAX\n : isNoteMediaUploadRequest(c.req.path, c.req.method, contentType)\n ? NOTE_MEDIA_BODY_MAX\n : DEFAULT_API_BODY_MAX;\n const maxSizeMb = Math.ceil(maxSize / (1024 * 1024));\n return bodyLimit({\n maxSize,\n onError: (ctx) => {\n log.warn({ path: ctx.req.path, maxSizeMb }, `Request body too large: exceeds ${maxSizeMb}MB limit`);\n return ctx.json({ error: 'Request body too large', maxSize: `${maxSizeMb}MB` }, 413);\n },\n })(c, next);\n });\n\n registerPublicGatewayRoutes(app, service);\n\n // Extension UI assets are served without auth: sandboxed iframes (no allow-same-origin)\n // have an opaque origin of `null` and cannot forward the ?token= from the parent HTML URL.\n // Security is enforced by the strict CSP (frame-ancestors 'self') on every response.\n registerPublicExtensionAssetRoutes(app, service);\n\n const authenticated = new Hono();\n authenticated.use(routeErrorMiddleware());\n authenticated.use(\n auth({\n token,\n getGatewayAuth: () => service.currentConfig.gateway?.auth,\n getResolvedAuth: () => {\n if (typeof service.getResolvedAuth === 'function') {\n return service.getResolvedAuth();\n }\n return token ? { mode: 'token', token } : { mode: 'none' };\n },\n getTrustedProxyContext: () => ({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }),\n }),\n );\n authenticated.use(operatorScopes());\n\n const strictRateLimitMiddleware = createStrictRateLimitMiddleware({\n getTrustedProxyContext: () => ({\n trustedProxies: service.currentConfig.gateway?.trustedProxies,\n allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true,\n }),\n });\n\n const sseConfig = {\n service,\n maxSseConnections: service.currentConfig.gateway.maxSseConnections,\n };\n\n registerAuthenticatedRoutes(app, authenticated, {\n service,\n strictRateLimitMiddleware,\n sseConfig,\n });\n\n const prewarm = prewarmStaticUiCache();\n if (prewarm.loaded > 0) {\n log.debug({ loaded: prewarm.loaded, missing: prewarm.missing }, 'Static UI cache prewarmed');\n }\n\n app.route('/', authenticated);\n\n app.notFound((c) => {\n const isApiRoute = c.req.path.startsWith('/api/');\n const fields = { path: c.req.path, method: c.req.method };\n if (isApiRoute) {\n log.warn(fields, 'Route not found');\n } else {\n log.debug(fields, 'Route not found');\n }\n return c.json({ error: 'Not found' }, 404);\n });\n\n app.onError((err, c) => {\n log.error(\n {\n err,\n phase: 'gateway.http.unhandled',\n path: c.req.path,\n method: c.req.method,\n userAgent: c.req.header('user-agent'),\n },\n `Hono error on ${c.req.method} ${c.req.path}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return c.json({ error: 'Internal server error' }, 500);\n });\n\n return app;\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { CredentialResolver, init_credentials } from "../../auth/credentials.js";
|
|
4
|
-
import { anthropicOAuthProvider } from "../../auth/oauth/anthropic.js";
|
|
5
4
|
import { isLoopbackHost } from "../host.js";
|
|
6
5
|
import { resolveReverseProxyPublicUrl } from "../public-url.js";
|
|
6
|
+
import { anthropicOAuthProvider } from "../../auth/oauth/anthropic.js";
|
|
7
7
|
import { minimaxOAuthProvider } from "../../auth/oauth/minimax.js";
|
|
8
8
|
import { minimaxCnOAuthProvider } from "../../auth/oauth/minimax-cn.js";
|
|
9
9
|
import { kimiCodingOAuthProvider } from "../../auth/oauth/kimi-coding.js";
|
|
@@ -31,24 +31,24 @@ function registerAgentStreamRoutes(authenticated, deps) {
|
|
|
31
31
|
message: "Invalid JSON body"
|
|
32
32
|
}
|
|
33
33
|
}, 400);
|
|
34
|
-
const
|
|
34
|
+
const sessionKey = typeof body.sessionKey === "string" ? body.sessionKey.trim() : "";
|
|
35
35
|
const message = typeof body.message === "string" ? body.message : "";
|
|
36
|
-
if (!
|
|
36
|
+
if (!sessionKey) return c.json({
|
|
37
37
|
ok: false,
|
|
38
38
|
error: {
|
|
39
39
|
code: "BAD_REQUEST",
|
|
40
|
-
message: "Missing
|
|
40
|
+
message: "Missing sessionKey"
|
|
41
41
|
}
|
|
42
42
|
}, 400);
|
|
43
|
-
const result = await service.steerWebchatAgent(
|
|
43
|
+
const result = await service.steerWebchatAgent(sessionKey, message);
|
|
44
44
|
if (result.ok === false) {
|
|
45
45
|
logRouteWarn(log, c, `Agent steer failed: ${result.code}`, "gateway.route.agent", {
|
|
46
|
-
|
|
46
|
+
sessionKey,
|
|
47
47
|
code: result.code
|
|
48
48
|
});
|
|
49
49
|
const code = result.code;
|
|
50
50
|
const status = code === "BAD_REQUEST" ? 400 : code === "NO_ACTIVE_RUN" ? 409 : 500;
|
|
51
|
-
const msg = code === "NO_ACTIVE_RUN" ? "No active agent run for this
|
|
51
|
+
const msg = code === "NO_ACTIVE_RUN" ? "No active agent run for this session" : code === "STEER_FAILED" ? "Steer failed" : "Message required";
|
|
52
52
|
return c.json({
|
|
53
53
|
ok: false,
|
|
54
54
|
error: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-stream.js","names":[],"sources":["../../../../../src/gateway/hono/routes/agent-stream.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport {\n createAgentResumeHandler,\n createAgentSSEHandler,\n createEventsSSEHandler,\n createSendHandler,\n} from '../sse.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\nimport { createGatewayRouteLogger, logRouteWarn } from '../lib/route-logger.js';\n\nconst log = createGatewayRouteLogger('AgentStream');\n\nexport function registerAgentStreamRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware, sseConfig } = deps;\n\n authenticated.post('/api/agent', strictRateLimitMiddleware, createAgentSSEHandler(sseConfig));\n\n authenticated.post('/api/agent/resume', strictRateLimitMiddleware, createAgentResumeHandler(sseConfig));\n\n authenticated.post('/api/agent/abort', strictRateLimitMiddleware, async (c) => {\n const body = await c.req.json().catch(() => null);\n const runId =\n body && typeof body === 'object' && typeof (body as { runId?: unknown }).runId === 'string'\n ? (body as { runId: string }).runId.trim()\n : '';\n if (!runId) {\n return c.json(\n { ok: false, error: { code: 'BAD_REQUEST', message: 'Missing runId' } },\n 400,\n );\n }\n const aborted = service.abortAgentRun(runId);\n return c.json({ ok: true, payload: { aborted } });\n });\n\n authenticated.post('/api/agent/steer', strictRateLimitMiddleware, async (c) => {\n const body = await c.req.json().catch(() => null);\n if (!body || typeof body !== 'object') {\n return c.json(\n { ok: false, error: { code: 'BAD_REQUEST', message: 'Invalid JSON body' } },\n 400,\n );\n }\n const
|
|
1
|
+
{"version":3,"file":"agent-stream.js","names":[],"sources":["../../../../../src/gateway/hono/routes/agent-stream.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport {\n createAgentResumeHandler,\n createAgentSSEHandler,\n createEventsSSEHandler,\n createSendHandler,\n} from '../sse.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\nimport { createGatewayRouteLogger, logRouteWarn } from '../lib/route-logger.js';\n\nconst log = createGatewayRouteLogger('AgentStream');\n\nexport function registerAgentStreamRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware, sseConfig } = deps;\n\n authenticated.post('/api/agent', strictRateLimitMiddleware, createAgentSSEHandler(sseConfig));\n\n authenticated.post('/api/agent/resume', strictRateLimitMiddleware, createAgentResumeHandler(sseConfig));\n\n authenticated.post('/api/agent/abort', strictRateLimitMiddleware, async (c) => {\n const body = await c.req.json().catch(() => null);\n const runId =\n body && typeof body === 'object' && typeof (body as { runId?: unknown }).runId === 'string'\n ? (body as { runId: string }).runId.trim()\n : '';\n if (!runId) {\n return c.json(\n { ok: false, error: { code: 'BAD_REQUEST', message: 'Missing runId' } },\n 400,\n );\n }\n const aborted = service.abortAgentRun(runId);\n return c.json({ ok: true, payload: { aborted } });\n });\n\n authenticated.post('/api/agent/steer', strictRateLimitMiddleware, async (c) => {\n const body = await c.req.json().catch(() => null);\n if (!body || typeof body !== 'object') {\n return c.json(\n { ok: false, error: { code: 'BAD_REQUEST', message: 'Invalid JSON body' } },\n 400,\n );\n }\n const sessionKey =\n typeof (body as { sessionKey?: unknown }).sessionKey === 'string'\n ? (body as { sessionKey: string }).sessionKey.trim()\n : '';\n const message =\n typeof (body as { message?: unknown }).message === 'string'\n ? (body as { message: string }).message\n : '';\n if (!sessionKey) {\n return c.json(\n { ok: false, error: { code: 'BAD_REQUEST', message: 'Missing sessionKey' } },\n 400,\n );\n }\n const result = await service.steerWebchatAgent(sessionKey, message);\n if (result.ok === false) {\n logRouteWarn(log, c, `Agent steer failed: ${result.code}`, 'gateway.route.agent', { sessionKey, code: result.code });\n const code = result.code;\n const status = code === 'BAD_REQUEST' ? 400 : code === 'NO_ACTIVE_RUN' ? 409 : 500;\n const msg =\n code === 'NO_ACTIVE_RUN'\n ? 'No active agent run for this session'\n : code === 'STEER_FAILED'\n ? 'Steer failed'\n : 'Message required';\n return c.json({ ok: false, error: { code, message: msg } }, status);\n }\n return c.json({ ok: true, payload: { steered: true } });\n });\n\n authenticated.post('/api/clarify/:requestId', strictRateLimitMiddleware, async (c) => {\n const requestId = c.req.param('requestId')?.trim() ?? '';\n if (!requestId) {\n return c.json(\n { ok: false, error: { code: 'BAD_REQUEST', message: 'Missing requestId' } },\n 400,\n );\n }\n const body = await c.req.json().catch(() => null);\n const skip =\n body &&\n typeof body === 'object' &&\n (body as { skip?: unknown }).skip === true;\n const rawAnswer =\n body && typeof body === 'object' && typeof (body as { answer?: unknown }).answer === 'string'\n ? (body as { answer: string }).answer\n : '';\n const answer = typeof rawAnswer === 'string' ? rawAnswer.trim() : '';\n if (!skip && !answer) {\n return c.json(\n { ok: false, error: { code: 'BAD_REQUEST', message: 'Missing answer field' } },\n 400,\n );\n }\n const handled = service.submitClarifyResponse(requestId, skip ? '' : answer);\n if (!handled) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: 'No pending clarification with this ID' } },\n 404,\n );\n }\n return c.json({ ok: true, payload: { received: true } });\n });\n\n authenticated.post('/api/send', strictRateLimitMiddleware, createSendHandler(sseConfig));\n\n authenticated.get('/api/events', createEventsSSEHandler(sseConfig));\n}\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Covers heartbeat, bind/customBindHost/port, tailscale, auth (mode + token +
|
|
5
5
|
* password + rateLimit + trustedProxy), trustedProxies, allowRealIpFallback,
|
|
6
|
-
* dangerouslyAllowHostHeaderOriginFallback, security, share, publicUrl,
|
|
6
|
+
* dangerouslyAllowHostHeaderOriginFallback, security, share, siteShare, publicUrl,
|
|
7
7
|
* corsOrigins, maxSseConnections, and channelConnectDefer{Mode,Ids,SkipIds}.
|
|
8
8
|
*
|
|
9
9
|
* Validation policy: each subsection that can reject rejects with a 400 and a
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { init_public_url, validatePublicUrl } from "../../../../config/public-url.js";
|
|
2
2
|
import { isValidIPv4 } from "../../../../config/gateway-bind.js";
|
|
3
3
|
import { mergeShareConfigPatch } from "../../../../share/share-config.js";
|
|
4
|
+
import { mergeSiteShareConfigPatch } from "../../../../share/site-share-config.js";
|
|
4
5
|
import { isMaskedSecretPatchValue } from "../../lib/mask-secret-length.js";
|
|
5
6
|
import { PATCH_OK, patchError } from "./result.js";
|
|
6
7
|
//#region src/gateway/hono/routes/config-patch/gateway.ts
|
|
@@ -221,6 +222,11 @@ function applyGatewayPatch(config, body) {
|
|
|
221
222
|
const shareResult = mergeShareConfigPatch(config, body.gateway.share);
|
|
222
223
|
if (shareResult.ok === false) return patchError(shareResult.message);
|
|
223
224
|
}
|
|
225
|
+
if (body.gateway?.siteShare !== void 0) {
|
|
226
|
+
if (typeof body.gateway.siteShare !== "object" || body.gateway.siteShare === null || Array.isArray(body.gateway.siteShare)) return patchError("gateway.siteShare must be an object");
|
|
227
|
+
const siteShareResult = mergeSiteShareConfigPatch(config, body.gateway.siteShare);
|
|
228
|
+
if (siteShareResult.ok === false) return patchError(siteShareResult.message);
|
|
229
|
+
}
|
|
224
230
|
if (body.gateway?.publicUrl !== void 0) {
|
|
225
231
|
const gw = ensureGateway(config);
|
|
226
232
|
if (body.gateway.publicUrl === null || body.gateway.publicUrl === "") delete gw.publicUrl;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.js","names":[],"sources":["../../../../../../src/gateway/hono/routes/config-patch/gateway.ts"],"sourcesContent":["/**\n * `PATCH /api/config` — `body.gateway.*` section.\n *\n * Covers heartbeat, bind/customBindHost/port, tailscale, auth (mode + token +\n * password + rateLimit + trustedProxy), trustedProxies, allowRealIpFallback,\n * dangerouslyAllowHostHeaderOriginFallback, security, share, publicUrl,\n * corsOrigins, maxSseConnections, and channelConnectDefer{Mode,Ids,SkipIds}.\n *\n * Validation policy: each subsection that can reject rejects with a 400 and a\n * specific `message`. The dispatcher converts these into `c.json(...)`.\n *\n * Initial-state branches use the same literal defaults the inline code did\n * (loopback + port 18790 + 1800s heartbeat + 100 SSE conn + empty CORS) so\n * a brand-new install gets a working gateway after the first PATCH.\n */\nimport type { Config, GatewayBindMode } from '../../../../config/schema.js';\nimport { isValidIPv4 } from '../../../../config/gateway-bind.js';\nimport { validatePublicUrl } from '../../../../config/public-url.js';\nimport { mergeShareConfigPatch } from '../../../../share/share-config.js';\nimport { isMaskedSecretPatchValue } from '../../lib/mask-secret-length.js';\nimport { type PatchResult, PATCH_OK, patchError } from './result.js';\n\n/**\n * Shared default for \"user PATCH'd a gateway subsection but `config.gateway`\n * was never initialised\". Identical to the inline literal repeated in the\n * pre-extraction handler so this is behavior-preserving.\n */\nfunction ensureGateway(config: Config): NonNullable<Config['gateway']> {\n if (!config.gateway) {\n config.gateway = {\n bind: 'loopback',\n port: 18790,\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: [],\n };\n }\n return config.gateway;\n}\n\nfunction parseDeferIdList(raw: unknown): string[] | null {\n if (!Array.isArray(raw)) return null;\n const ids = raw\n .filter((x): x is string => typeof x === 'string' && x.trim().length > 0)\n .map((x) => x.trim());\n if (ids.length > 24) return null;\n return ids;\n}\n\nexport function applyGatewayPatch(config: Config, body: any): PatchResult {\n if (body.gateway?.heartbeat !== undefined && typeof body.gateway.heartbeat === 'object') {\n const gw = ensureGateway(config);\n if (!gw.heartbeat) {\n gw.heartbeat = { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false };\n }\n const h = gw.heartbeat;\n const p = body.gateway.heartbeat as Record<string, unknown>;\n if (p.enabled !== undefined) h.enabled = Boolean(p.enabled);\n if (p.intervalMs !== undefined && typeof p.intervalMs === 'number' && Number.isFinite(p.intervalMs)) {\n h.intervalMs = p.intervalMs;\n }\n if (p.includeSystemPromptSection !== undefined) {\n h.includeSystemPromptSection = Boolean(p.includeSystemPromptSection);\n }\n if (p.target !== undefined) {\n if (p.target === null || p.target === '') delete (h as { target?: string }).target;\n else (h as { target?: string }).target = String(p.target);\n }\n if (p.targetChatId !== undefined) {\n if (p.targetChatId === null || p.targetChatId === '') delete (h as { targetChatId?: string }).targetChatId;\n else (h as { targetChatId?: string }).targetChatId = String(p.targetChatId);\n }\n if (p.prompt !== undefined) {\n if (p.prompt === null || p.prompt === '') delete (h as { prompt?: string }).prompt;\n else (h as { prompt?: string }).prompt = String(p.prompt);\n }\n if (p.ackMaxChars !== undefined) {\n if (p.ackMaxChars === null || p.ackMaxChars === '') delete (h as { ackMaxChars?: number }).ackMaxChars;\n else if (typeof p.ackMaxChars === 'number' && Number.isFinite(p.ackMaxChars)) {\n (h as { ackMaxChars?: number }).ackMaxChars = p.ackMaxChars;\n }\n }\n if (p.isolatedSession !== undefined) {\n if (p.isolatedSession === null || p.isolatedSession === false) {\n delete (h as { isolatedSession?: boolean }).isolatedSession;\n } else {\n (h as { isolatedSession?: boolean }).isolatedSession = Boolean(p.isolatedSession);\n }\n }\n if (p.activeHours !== undefined) {\n if (p.activeHours === null) {\n delete (h as { activeHours?: unknown }).activeHours;\n } else if (typeof p.activeHours === 'object' && p.activeHours !== null) {\n const ah = p.activeHours as Record<string, unknown>;\n const start = typeof ah.start === 'string' ? ah.start : '';\n const end = typeof ah.end === 'string' ? ah.end : '';\n if (start && end) {\n (h as { activeHours?: { start: string; end: string; timezone?: string } }).activeHours = {\n start,\n end,\n ...(typeof ah.timezone === 'string' && ah.timezone.trim() ? { timezone: ah.timezone } : {}),\n };\n } else {\n delete (h as { activeHours?: unknown }).activeHours;\n }\n }\n }\n }\n\n if (body.gateway?.bind !== undefined) {\n const bindModes = new Set(['auto', 'loopback', 'lan', 'tailnet', 'custom']);\n const bind = body.gateway.bind;\n if (typeof bind !== 'string' || !bindModes.has(bind)) {\n return patchError('gateway.bind must be one of: auto, loopback, lan, tailnet, custom');\n }\n if (!config.gateway) {\n config.gateway = {\n bind: bind as GatewayBindMode,\n port: 18790,\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: [],\n };\n } else {\n config.gateway.bind = bind as GatewayBindMode;\n }\n if (bind !== 'custom') {\n delete config.gateway.customBindHost;\n }\n }\n\n if (body.gateway?.customBindHost !== undefined) {\n if (body.gateway.customBindHost === null || body.gateway.customBindHost === '') {\n if (config.gateway) {\n delete config.gateway.customBindHost;\n }\n } else if (typeof body.gateway.customBindHost !== 'string' || !isValidIPv4(body.gateway.customBindHost.trim())) {\n return patchError('gateway.customBindHost must be a valid IPv4 address');\n } else if (config.gateway) {\n config.gateway.customBindHost = body.gateway.customBindHost.trim();\n config.gateway.bind = 'custom';\n }\n }\n\n if (body.gateway?.port !== undefined) {\n if (\n typeof body.gateway.port !== 'number' ||\n !Number.isFinite(body.gateway.port) ||\n body.gateway.port < 1 ||\n body.gateway.port > 65535\n ) {\n return patchError('gateway.port must be an integer from 1 to 65535');\n }\n if (!config.gateway) {\n config.gateway = {\n bind: 'loopback',\n port: Math.floor(body.gateway.port),\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: [],\n };\n } else {\n config.gateway.port = Math.floor(body.gateway.port);\n }\n }\n\n if (body.gateway?.tailscale !== undefined && typeof body.gateway.tailscale === 'object') {\n const ts = body.gateway.tailscale as Record<string, unknown>;\n if (!config.gateway) {\n config.gateway = {\n bind: 'loopback',\n port: 18790,\n auth: { mode: 'token' },\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: [],\n };\n }\n config.gateway.tailscale = {\n ...(config.gateway.tailscale ?? { mode: 'off', resetOnExit: true }),\n };\n if (ts.mode !== undefined) {\n if (ts.mode !== 'off' && ts.mode !== 'serve' && ts.mode !== 'funnel') {\n return patchError('gateway.tailscale.mode must be off, serve, or funnel');\n }\n config.gateway.tailscale.mode = ts.mode as 'off' | 'serve' | 'funnel';\n }\n if (ts.resetOnExit !== undefined) {\n config.gateway.tailscale.resetOnExit = ts.resetOnExit === true;\n }\n }\n\n if (body.gateway?.auth !== undefined) {\n const gw = ensureGateway(config);\n if (!gw.auth) gw.auth = { mode: 'token' };\n const a = body.gateway.auth;\n if (a.mode !== undefined) {\n if (\n a.mode !== 'none' &&\n a.mode !== 'token' &&\n a.mode !== 'password' &&\n a.mode !== 'trusted-proxy'\n ) {\n return patchError('gateway.auth.mode must be none, token, password, or trusted-proxy');\n }\n gw.auth.mode = a.mode;\n }\n if (a.token !== undefined) {\n if (a.token === null || (typeof a.token === 'string' && !a.token.trim())) {\n delete gw.auth.token;\n } else if (typeof a.token === 'string' && !isMaskedSecretPatchValue(a.token)) {\n gw.auth.token = a.token;\n }\n }\n if (a.password !== undefined) {\n if (a.password === null || (typeof a.password === 'string' && !a.password.trim())) {\n delete gw.auth.password;\n } else if (typeof a.password === 'string' && !isMaskedSecretPatchValue(a.password)) {\n gw.auth.password = a.password;\n }\n }\n if (a.rateLimit !== undefined && typeof a.rateLimit === 'object' && a.rateLimit !== null) {\n const rlIn = a.rateLimit as Record<string, unknown>;\n if (!gw.auth.rateLimit) {\n gw.auth.rateLimit = {\n enabled: true,\n maxAttempts: 5,\n windowMs: 900_000,\n blockDurationMs: 300_000,\n burstCoalesceMs: 1000,\n exemptLoopback: true,\n };\n }\n const rl = gw.auth.rateLimit!;\n if (rlIn.enabled !== undefined) rl.enabled = Boolean(rlIn.enabled);\n if (typeof rlIn.maxAttempts === 'number' && Number.isFinite(rlIn.maxAttempts)) {\n rl.maxAttempts = Math.max(1, Math.floor(rlIn.maxAttempts));\n }\n if (typeof rlIn.windowMs === 'number' && Number.isFinite(rlIn.windowMs) && rlIn.windowMs > 0) {\n rl.windowMs = Math.floor(rlIn.windowMs);\n }\n if (\n typeof rlIn.blockDurationMs === 'number' &&\n Number.isFinite(rlIn.blockDurationMs) &&\n rlIn.blockDurationMs > 0\n ) {\n rl.blockDurationMs = Math.floor(rlIn.blockDurationMs);\n }\n if (\n typeof rlIn.lockoutMs === 'number' &&\n Number.isFinite(rlIn.lockoutMs) &&\n rlIn.lockoutMs > 0\n ) {\n rl.blockDurationMs = Math.floor(rlIn.lockoutMs);\n }\n if (rlIn.exemptLoopback !== undefined) {\n rl.exemptLoopback = Boolean(rlIn.exemptLoopback);\n }\n }\n if (a.trustedProxy !== undefined) {\n if (a.trustedProxy === null) {\n delete gw.auth.trustedProxy;\n } else if (typeof a.trustedProxy === 'object' && a.trustedProxy !== null) {\n const tpIn = a.trustedProxy as Record<string, unknown>;\n const userHeader =\n typeof tpIn.userHeader === 'string' ? tpIn.userHeader.trim() : '';\n if (!userHeader) {\n return patchError('gateway.auth.trustedProxy.userHeader is required');\n }\n const trustedProxy: NonNullable<(typeof gw.auth)['trustedProxy']> = {\n userHeader,\n };\n if (tpIn.requiredHeaders !== undefined) {\n if (!Array.isArray(tpIn.requiredHeaders)) {\n return patchError('gateway.auth.trustedProxy.requiredHeaders must be an array');\n }\n trustedProxy.requiredHeaders = tpIn.requiredHeaders\n .filter((x): x is string => typeof x === 'string' && x.trim().length > 0)\n .map((x) => x.trim());\n }\n if (tpIn.allowUsers !== undefined) {\n if (!Array.isArray(tpIn.allowUsers)) {\n return patchError('gateway.auth.trustedProxy.allowUsers must be an array');\n }\n trustedProxy.allowUsers = tpIn.allowUsers\n .filter((x): x is string => typeof x === 'string' && x.trim().length > 0)\n .map((x) => x.trim());\n }\n if (tpIn.allowLoopback !== undefined) {\n trustedProxy.allowLoopback = Boolean(tpIn.allowLoopback);\n }\n gw.auth.trustedProxy = trustedProxy;\n }\n }\n }\n\n if (body.gateway?.trustedProxies !== undefined) {\n if (!Array.isArray(body.gateway.trustedProxies)) {\n return patchError('gateway.trustedProxies must be an array');\n }\n const gw = ensureGateway(config);\n gw.trustedProxies = body.gateway.trustedProxies\n .filter((x: unknown): x is string => typeof x === 'string' && x.trim().length > 0)\n .map((x: string) => x.trim());\n }\n\n if (body.gateway?.allowRealIpFallback !== undefined) {\n const gw = ensureGateway(config);\n gw.allowRealIpFallback = Boolean(body.gateway.allowRealIpFallback);\n }\n\n if (body.gateway?.dangerouslyAllowHostHeaderOriginFallback !== undefined) {\n const gw = ensureGateway(config);\n gw.dangerouslyAllowHostHeaderOriginFallback = Boolean(\n body.gateway.dangerouslyAllowHostHeaderOriginFallback,\n );\n }\n\n if (body.gateway?.security !== undefined) {\n if (typeof body.gateway.security !== 'object' || body.gateway.security === null) {\n return patchError('gateway.security must be an object');\n }\n const gw = ensureGateway(config);\n const secIn = body.gateway.security as Record<string, unknown>;\n if (!gw.security) {\n gw.security = {};\n }\n if (secIn.strict !== undefined) {\n gw.security.strict = Boolean(secIn.strict);\n }\n }\n\n if (body.gateway?.share !== undefined) {\n if (typeof body.gateway.share !== 'object' || body.gateway.share === null || Array.isArray(body.gateway.share)) {\n return patchError('gateway.share must be an object');\n }\n const shareResult = mergeShareConfigPatch(config, body.gateway.share as Record<string, unknown>);\n if (shareResult.ok === false) {\n return patchError(shareResult.message);\n }\n }\n\n if (body.gateway?.publicUrl !== undefined) {\n const gw = ensureGateway(config);\n if (body.gateway.publicUrl === null || body.gateway.publicUrl === '') {\n delete gw.publicUrl;\n } else if (typeof body.gateway.publicUrl !== 'string') {\n return patchError('gateway.publicUrl must be a string or null');\n } else {\n const validation = validatePublicUrl(body.gateway.publicUrl);\n if (validation.ok === false) {\n return patchError(`gateway.publicUrl: ${validation.message}`);\n }\n gw.publicUrl = validation.url;\n }\n }\n\n if (body.gateway?.corsOrigins !== undefined) {\n if (!Array.isArray(body.gateway.corsOrigins)) {\n return patchError('gateway.corsOrigins must be an array');\n }\n const gw = ensureGateway(config);\n gw.corsOrigins = body.gateway.corsOrigins\n .filter((x: unknown): x is string => typeof x === 'string' && x.trim().length > 0)\n .map((x: string) => x.trim());\n }\n\n if (body.gateway?.maxSseConnections !== undefined) {\n if (\n typeof body.gateway.maxSseConnections !== 'number' ||\n !Number.isFinite(body.gateway.maxSseConnections) ||\n body.gateway.maxSseConnections < 1\n ) {\n return patchError('gateway.maxSseConnections must be a positive integer');\n }\n if (!config.gateway) {\n config.gateway = {\n bind: 'loopback',\n port: 18790,\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: Math.floor(body.gateway.maxSseConnections),\n corsOrigins: [],\n };\n } else {\n config.gateway.maxSseConnections = Math.floor(body.gateway.maxSseConnections);\n }\n }\n\n if (body.gateway?.channelConnectDeferMode !== undefined) {\n const mode = body.gateway.channelConnectDeferMode;\n if (mode !== 'auto' && mode !== 'off' && mode !== 'explicit') {\n return patchError('gateway.channelConnectDeferMode must be auto, off, or explicit');\n }\n const gw = ensureGateway(config);\n gw.channelConnectDeferMode = mode;\n }\n\n if (body.gateway?.channelConnectDeferIds !== undefined) {\n const ids = parseDeferIdList(body.gateway.channelConnectDeferIds);\n if (ids === null) {\n return patchError('gateway.channelConnectDeferIds must be an array of up to 24 strings');\n }\n const gw = ensureGateway(config);\n gw.channelConnectDeferIds = ids;\n }\n\n if (body.gateway?.channelConnectDeferSkipIds !== undefined) {\n const ids = parseDeferIdList(body.gateway.channelConnectDeferSkipIds);\n if (ids === null) {\n return patchError('gateway.channelConnectDeferSkipIds must be an array of up to 24 strings');\n }\n const gw = ensureGateway(config);\n gw.channelConnectDeferSkipIds = ids;\n }\n\n return PATCH_OK;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gateway.js","names":[],"sources":["../../../../../../src/gateway/hono/routes/config-patch/gateway.ts"],"sourcesContent":["/**\n * `PATCH /api/config` — `body.gateway.*` section.\n *\n * Covers heartbeat, bind/customBindHost/port, tailscale, auth (mode + token +\n * password + rateLimit + trustedProxy), trustedProxies, allowRealIpFallback,\n * dangerouslyAllowHostHeaderOriginFallback, security, share, siteShare, publicUrl,\n * corsOrigins, maxSseConnections, and channelConnectDefer{Mode,Ids,SkipIds}.\n *\n * Validation policy: each subsection that can reject rejects with a 400 and a\n * specific `message`. The dispatcher converts these into `c.json(...)`.\n *\n * Initial-state branches use the same literal defaults the inline code did\n * (loopback + port 18790 + 1800s heartbeat + 100 SSE conn + empty CORS) so\n * a brand-new install gets a working gateway after the first PATCH.\n */\nimport type { Config, GatewayBindMode } from '../../../../config/schema.js';\nimport { isValidIPv4 } from '../../../../config/gateway-bind.js';\nimport { validatePublicUrl } from '../../../../config/public-url.js';\nimport { mergeShareConfigPatch } from '../../../../share/share-config.js';\nimport { mergeSiteShareConfigPatch } from '../../../../share/site-share-config.js';\nimport { isMaskedSecretPatchValue } from '../../lib/mask-secret-length.js';\nimport { type PatchResult, PATCH_OK, patchError } from './result.js';\n\n/**\n * Shared default for \"user PATCH'd a gateway subsection but `config.gateway`\n * was never initialised\". Identical to the inline literal repeated in the\n * pre-extraction handler so this is behavior-preserving.\n */\nfunction ensureGateway(config: Config): NonNullable<Config['gateway']> {\n if (!config.gateway) {\n config.gateway = {\n bind: 'loopback',\n port: 18790,\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: [],\n };\n }\n return config.gateway;\n}\n\nfunction parseDeferIdList(raw: unknown): string[] | null {\n if (!Array.isArray(raw)) return null;\n const ids = raw\n .filter((x): x is string => typeof x === 'string' && x.trim().length > 0)\n .map((x) => x.trim());\n if (ids.length > 24) return null;\n return ids;\n}\n\nexport function applyGatewayPatch(config: Config, body: any): PatchResult {\n if (body.gateway?.heartbeat !== undefined && typeof body.gateway.heartbeat === 'object') {\n const gw = ensureGateway(config);\n if (!gw.heartbeat) {\n gw.heartbeat = { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false };\n }\n const h = gw.heartbeat;\n const p = body.gateway.heartbeat as Record<string, unknown>;\n if (p.enabled !== undefined) h.enabled = Boolean(p.enabled);\n if (p.intervalMs !== undefined && typeof p.intervalMs === 'number' && Number.isFinite(p.intervalMs)) {\n h.intervalMs = p.intervalMs;\n }\n if (p.includeSystemPromptSection !== undefined) {\n h.includeSystemPromptSection = Boolean(p.includeSystemPromptSection);\n }\n if (p.target !== undefined) {\n if (p.target === null || p.target === '') delete (h as { target?: string }).target;\n else (h as { target?: string }).target = String(p.target);\n }\n if (p.targetChatId !== undefined) {\n if (p.targetChatId === null || p.targetChatId === '') delete (h as { targetChatId?: string }).targetChatId;\n else (h as { targetChatId?: string }).targetChatId = String(p.targetChatId);\n }\n if (p.prompt !== undefined) {\n if (p.prompt === null || p.prompt === '') delete (h as { prompt?: string }).prompt;\n else (h as { prompt?: string }).prompt = String(p.prompt);\n }\n if (p.ackMaxChars !== undefined) {\n if (p.ackMaxChars === null || p.ackMaxChars === '') delete (h as { ackMaxChars?: number }).ackMaxChars;\n else if (typeof p.ackMaxChars === 'number' && Number.isFinite(p.ackMaxChars)) {\n (h as { ackMaxChars?: number }).ackMaxChars = p.ackMaxChars;\n }\n }\n if (p.isolatedSession !== undefined) {\n if (p.isolatedSession === null || p.isolatedSession === false) {\n delete (h as { isolatedSession?: boolean }).isolatedSession;\n } else {\n (h as { isolatedSession?: boolean }).isolatedSession = Boolean(p.isolatedSession);\n }\n }\n if (p.activeHours !== undefined) {\n if (p.activeHours === null) {\n delete (h as { activeHours?: unknown }).activeHours;\n } else if (typeof p.activeHours === 'object' && p.activeHours !== null) {\n const ah = p.activeHours as Record<string, unknown>;\n const start = typeof ah.start === 'string' ? ah.start : '';\n const end = typeof ah.end === 'string' ? ah.end : '';\n if (start && end) {\n (h as { activeHours?: { start: string; end: string; timezone?: string } }).activeHours = {\n start,\n end,\n ...(typeof ah.timezone === 'string' && ah.timezone.trim() ? { timezone: ah.timezone } : {}),\n };\n } else {\n delete (h as { activeHours?: unknown }).activeHours;\n }\n }\n }\n }\n\n if (body.gateway?.bind !== undefined) {\n const bindModes = new Set(['auto', 'loopback', 'lan', 'tailnet', 'custom']);\n const bind = body.gateway.bind;\n if (typeof bind !== 'string' || !bindModes.has(bind)) {\n return patchError('gateway.bind must be one of: auto, loopback, lan, tailnet, custom');\n }\n if (!config.gateway) {\n config.gateway = {\n bind: bind as GatewayBindMode,\n port: 18790,\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: [],\n };\n } else {\n config.gateway.bind = bind as GatewayBindMode;\n }\n if (bind !== 'custom') {\n delete config.gateway.customBindHost;\n }\n }\n\n if (body.gateway?.customBindHost !== undefined) {\n if (body.gateway.customBindHost === null || body.gateway.customBindHost === '') {\n if (config.gateway) {\n delete config.gateway.customBindHost;\n }\n } else if (typeof body.gateway.customBindHost !== 'string' || !isValidIPv4(body.gateway.customBindHost.trim())) {\n return patchError('gateway.customBindHost must be a valid IPv4 address');\n } else if (config.gateway) {\n config.gateway.customBindHost = body.gateway.customBindHost.trim();\n config.gateway.bind = 'custom';\n }\n }\n\n if (body.gateway?.port !== undefined) {\n if (\n typeof body.gateway.port !== 'number' ||\n !Number.isFinite(body.gateway.port) ||\n body.gateway.port < 1 ||\n body.gateway.port > 65535\n ) {\n return patchError('gateway.port must be an integer from 1 to 65535');\n }\n if (!config.gateway) {\n config.gateway = {\n bind: 'loopback',\n port: Math.floor(body.gateway.port),\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: [],\n };\n } else {\n config.gateway.port = Math.floor(body.gateway.port);\n }\n }\n\n if (body.gateway?.tailscale !== undefined && typeof body.gateway.tailscale === 'object') {\n const ts = body.gateway.tailscale as Record<string, unknown>;\n if (!config.gateway) {\n config.gateway = {\n bind: 'loopback',\n port: 18790,\n auth: { mode: 'token' },\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: [],\n };\n }\n config.gateway.tailscale = {\n ...(config.gateway.tailscale ?? { mode: 'off', resetOnExit: true }),\n };\n if (ts.mode !== undefined) {\n if (ts.mode !== 'off' && ts.mode !== 'serve' && ts.mode !== 'funnel') {\n return patchError('gateway.tailscale.mode must be off, serve, or funnel');\n }\n config.gateway.tailscale.mode = ts.mode as 'off' | 'serve' | 'funnel';\n }\n if (ts.resetOnExit !== undefined) {\n config.gateway.tailscale.resetOnExit = ts.resetOnExit === true;\n }\n }\n\n if (body.gateway?.auth !== undefined) {\n const gw = ensureGateway(config);\n if (!gw.auth) gw.auth = { mode: 'token' };\n const a = body.gateway.auth;\n if (a.mode !== undefined) {\n if (\n a.mode !== 'none' &&\n a.mode !== 'token' &&\n a.mode !== 'password' &&\n a.mode !== 'trusted-proxy'\n ) {\n return patchError('gateway.auth.mode must be none, token, password, or trusted-proxy');\n }\n gw.auth.mode = a.mode;\n }\n if (a.token !== undefined) {\n if (a.token === null || (typeof a.token === 'string' && !a.token.trim())) {\n delete gw.auth.token;\n } else if (typeof a.token === 'string' && !isMaskedSecretPatchValue(a.token)) {\n gw.auth.token = a.token;\n }\n }\n if (a.password !== undefined) {\n if (a.password === null || (typeof a.password === 'string' && !a.password.trim())) {\n delete gw.auth.password;\n } else if (typeof a.password === 'string' && !isMaskedSecretPatchValue(a.password)) {\n gw.auth.password = a.password;\n }\n }\n if (a.rateLimit !== undefined && typeof a.rateLimit === 'object' && a.rateLimit !== null) {\n const rlIn = a.rateLimit as Record<string, unknown>;\n if (!gw.auth.rateLimit) {\n gw.auth.rateLimit = {\n enabled: true,\n maxAttempts: 5,\n windowMs: 900_000,\n blockDurationMs: 300_000,\n burstCoalesceMs: 1000,\n exemptLoopback: true,\n };\n }\n const rl = gw.auth.rateLimit!;\n if (rlIn.enabled !== undefined) rl.enabled = Boolean(rlIn.enabled);\n if (typeof rlIn.maxAttempts === 'number' && Number.isFinite(rlIn.maxAttempts)) {\n rl.maxAttempts = Math.max(1, Math.floor(rlIn.maxAttempts));\n }\n if (typeof rlIn.windowMs === 'number' && Number.isFinite(rlIn.windowMs) && rlIn.windowMs > 0) {\n rl.windowMs = Math.floor(rlIn.windowMs);\n }\n if (\n typeof rlIn.blockDurationMs === 'number' &&\n Number.isFinite(rlIn.blockDurationMs) &&\n rlIn.blockDurationMs > 0\n ) {\n rl.blockDurationMs = Math.floor(rlIn.blockDurationMs);\n }\n if (\n typeof rlIn.lockoutMs === 'number' &&\n Number.isFinite(rlIn.lockoutMs) &&\n rlIn.lockoutMs > 0\n ) {\n rl.blockDurationMs = Math.floor(rlIn.lockoutMs);\n }\n if (rlIn.exemptLoopback !== undefined) {\n rl.exemptLoopback = Boolean(rlIn.exemptLoopback);\n }\n }\n if (a.trustedProxy !== undefined) {\n if (a.trustedProxy === null) {\n delete gw.auth.trustedProxy;\n } else if (typeof a.trustedProxy === 'object' && a.trustedProxy !== null) {\n const tpIn = a.trustedProxy as Record<string, unknown>;\n const userHeader =\n typeof tpIn.userHeader === 'string' ? tpIn.userHeader.trim() : '';\n if (!userHeader) {\n return patchError('gateway.auth.trustedProxy.userHeader is required');\n }\n const trustedProxy: NonNullable<(typeof gw.auth)['trustedProxy']> = {\n userHeader,\n };\n if (tpIn.requiredHeaders !== undefined) {\n if (!Array.isArray(tpIn.requiredHeaders)) {\n return patchError('gateway.auth.trustedProxy.requiredHeaders must be an array');\n }\n trustedProxy.requiredHeaders = tpIn.requiredHeaders\n .filter((x): x is string => typeof x === 'string' && x.trim().length > 0)\n .map((x) => x.trim());\n }\n if (tpIn.allowUsers !== undefined) {\n if (!Array.isArray(tpIn.allowUsers)) {\n return patchError('gateway.auth.trustedProxy.allowUsers must be an array');\n }\n trustedProxy.allowUsers = tpIn.allowUsers\n .filter((x): x is string => typeof x === 'string' && x.trim().length > 0)\n .map((x) => x.trim());\n }\n if (tpIn.allowLoopback !== undefined) {\n trustedProxy.allowLoopback = Boolean(tpIn.allowLoopback);\n }\n gw.auth.trustedProxy = trustedProxy;\n }\n }\n }\n\n if (body.gateway?.trustedProxies !== undefined) {\n if (!Array.isArray(body.gateway.trustedProxies)) {\n return patchError('gateway.trustedProxies must be an array');\n }\n const gw = ensureGateway(config);\n gw.trustedProxies = body.gateway.trustedProxies\n .filter((x: unknown): x is string => typeof x === 'string' && x.trim().length > 0)\n .map((x: string) => x.trim());\n }\n\n if (body.gateway?.allowRealIpFallback !== undefined) {\n const gw = ensureGateway(config);\n gw.allowRealIpFallback = Boolean(body.gateway.allowRealIpFallback);\n }\n\n if (body.gateway?.dangerouslyAllowHostHeaderOriginFallback !== undefined) {\n const gw = ensureGateway(config);\n gw.dangerouslyAllowHostHeaderOriginFallback = Boolean(\n body.gateway.dangerouslyAllowHostHeaderOriginFallback,\n );\n }\n\n if (body.gateway?.security !== undefined) {\n if (typeof body.gateway.security !== 'object' || body.gateway.security === null) {\n return patchError('gateway.security must be an object');\n }\n const gw = ensureGateway(config);\n const secIn = body.gateway.security as Record<string, unknown>;\n if (!gw.security) {\n gw.security = {};\n }\n if (secIn.strict !== undefined) {\n gw.security.strict = Boolean(secIn.strict);\n }\n }\n\n if (body.gateway?.share !== undefined) {\n if (typeof body.gateway.share !== 'object' || body.gateway.share === null || Array.isArray(body.gateway.share)) {\n return patchError('gateway.share must be an object');\n }\n const shareResult = mergeShareConfigPatch(config, body.gateway.share as Record<string, unknown>);\n if (shareResult.ok === false) {\n return patchError(shareResult.message);\n }\n }\n\n if (body.gateway?.siteShare !== undefined) {\n if (\n typeof body.gateway.siteShare !== 'object' ||\n body.gateway.siteShare === null ||\n Array.isArray(body.gateway.siteShare)\n ) {\n return patchError('gateway.siteShare must be an object');\n }\n const siteShareResult = mergeSiteShareConfigPatch(config, body.gateway.siteShare as Record<string, unknown>);\n if (siteShareResult.ok === false) {\n return patchError(siteShareResult.message);\n }\n }\n\n if (body.gateway?.publicUrl !== undefined) {\n const gw = ensureGateway(config);\n if (body.gateway.publicUrl === null || body.gateway.publicUrl === '') {\n delete gw.publicUrl;\n } else if (typeof body.gateway.publicUrl !== 'string') {\n return patchError('gateway.publicUrl must be a string or null');\n } else {\n const validation = validatePublicUrl(body.gateway.publicUrl);\n if (validation.ok === false) {\n return patchError(`gateway.publicUrl: ${validation.message}`);\n }\n gw.publicUrl = validation.url;\n }\n }\n\n if (body.gateway?.corsOrigins !== undefined) {\n if (!Array.isArray(body.gateway.corsOrigins)) {\n return patchError('gateway.corsOrigins must be an array');\n }\n const gw = ensureGateway(config);\n gw.corsOrigins = body.gateway.corsOrigins\n .filter((x: unknown): x is string => typeof x === 'string' && x.trim().length > 0)\n .map((x: string) => x.trim());\n }\n\n if (body.gateway?.maxSseConnections !== undefined) {\n if (\n typeof body.gateway.maxSseConnections !== 'number' ||\n !Number.isFinite(body.gateway.maxSseConnections) ||\n body.gateway.maxSseConnections < 1\n ) {\n return patchError('gateway.maxSseConnections must be a positive integer');\n }\n if (!config.gateway) {\n config.gateway = {\n bind: 'loopback',\n port: 18790,\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: Math.floor(body.gateway.maxSseConnections),\n corsOrigins: [],\n };\n } else {\n config.gateway.maxSseConnections = Math.floor(body.gateway.maxSseConnections);\n }\n }\n\n if (body.gateway?.channelConnectDeferMode !== undefined) {\n const mode = body.gateway.channelConnectDeferMode;\n if (mode !== 'auto' && mode !== 'off' && mode !== 'explicit') {\n return patchError('gateway.channelConnectDeferMode must be auto, off, or explicit');\n }\n const gw = ensureGateway(config);\n gw.channelConnectDeferMode = mode;\n }\n\n if (body.gateway?.channelConnectDeferIds !== undefined) {\n const ids = parseDeferIdList(body.gateway.channelConnectDeferIds);\n if (ids === null) {\n return patchError('gateway.channelConnectDeferIds must be an array of up to 24 strings');\n }\n const gw = ensureGateway(config);\n gw.channelConnectDeferIds = ids;\n }\n\n if (body.gateway?.channelConnectDeferSkipIds !== undefined) {\n const ids = parseDeferIdList(body.gateway.channelConnectDeferSkipIds);\n if (ids === null) {\n return patchError('gateway.channelConnectDeferSkipIds must be an array of up to 24 strings');\n }\n const gw = ensureGateway(config);\n gw.channelConnectDeferSkipIds = ids;\n }\n\n return PATCH_OK;\n}\n"],"mappings":"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"}
|
|
@@ -413,14 +413,27 @@ function registerGoalsRoutes(authenticated, deps) {
|
|
|
413
413
|
}, 404);
|
|
414
414
|
let sessionKey = typeof body.sessionKey === "string" && body.sessionKey.trim() ? body.sessionKey.trim() : goal.activeSessionKey;
|
|
415
415
|
if (!sessionKey) {
|
|
416
|
+
const agentId = goal.agentId || getDefaultAgentId(cfg());
|
|
417
|
+
const peerId = `goal-${sanitizeSegment(goal.id) || Date.now()}`;
|
|
416
418
|
sessionKey = buildSessionKey({
|
|
417
|
-
agentId
|
|
419
|
+
agentId,
|
|
418
420
|
source: "webchat",
|
|
419
421
|
accountId: "default",
|
|
420
422
|
peerKind: "direct",
|
|
421
|
-
peerId
|
|
423
|
+
peerId
|
|
422
424
|
});
|
|
423
|
-
await deps.service.sessionIndexInstance.saveMessages(sessionKey, []
|
|
425
|
+
await deps.service.sessionIndexInstance.saveMessages(sessionKey, [], { metadata: {
|
|
426
|
+
sourceChannel: "webchat",
|
|
427
|
+
sourceChatId: `default:direct:${peerId}`,
|
|
428
|
+
sessionType: "chat",
|
|
429
|
+
routing: {
|
|
430
|
+
agentId,
|
|
431
|
+
source: "webchat",
|
|
432
|
+
accountId: "default",
|
|
433
|
+
peerKind: "direct",
|
|
434
|
+
peerId
|
|
435
|
+
}
|
|
436
|
+
} });
|
|
424
437
|
goals.attachSession(goalId, sessionKey);
|
|
425
438
|
}
|
|
426
439
|
const queued = deps.service.enqueueGoalRun(goalId, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goals.js","names":[],"sources":["../../../../../src/gateway/hono/routes/goals.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { createWorkflowCatalog } from '../../../agent/workflow/catalog.js';\nimport {\n GoalService,\n normalizeGoalUiLocale,\n type GoalChecklistItem,\n type GoalEvent,\n type GoalEvidence,\n type GoalQueueItemSnapshot,\n type GoalRun,\n type GoalStatus,\n} from '../../../goals/index.js';\nimport { buildSessionKey, sanitizeSegment } from '../../../routing/session-key.js';\nimport { getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { WorkflowRunSummary } from '../../../workflows/domain/index.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nfunction parseLimit(raw: string | undefined, fallback = 50): number {\n if (!raw) return fallback;\n const n = Number.parseInt(raw, 10);\n return Number.isFinite(n) ? Math.min(500, Math.max(1, n)) : fallback;\n}\n\nfunction parseStatuses(raw: string | undefined): GoalStatus[] | undefined {\n if (!raw?.trim()) return undefined;\n const statuses = raw\n .split(',')\n .map((s) => s.trim())\n .filter((s): s is GoalStatus =>\n s === 'active' ||\n s === 'paused' ||\n s === 'blocked' ||\n s === 'needs_input' ||\n s === 'done' ||\n s === 'archived',\n );\n return statuses.length ? statuses : undefined;\n}\n\nfunction parseBodyGoalStatus(raw: unknown): GoalStatus | null {\n return raw === 'active' ||\n raw === 'paused' ||\n raw === 'blocked' ||\n raw === 'needs_input' ||\n raw === 'done' ||\n raw === 'archived'\n ? raw\n : null;\n}\n\nfunction parsePriority(raw: unknown): 'low' | 'normal' | 'high' | undefined {\n return raw === 'low' || raw === 'normal' || raw === 'high' ? raw : undefined;\n}\n\ntype GoalActivityItem = {\n id: string;\n kind: 'queue' | 'goal_run' | 'workflow_run' | 'event' | 'evidence';\n status?: string;\n title: string;\n summary?: string;\n createdAt: number;\n link?: { type: 'chat' | 'workflow_run'; value: string };\n data?: unknown;\n};\n\ntype GoalWorkflowSuggestion = {\n definitionId: string;\n name: string;\n title: string;\n description: string;\n score: number;\n reasons: string[];\n tags: string[];\n successRate?: number;\n lastRunStatus?: WorkflowRunSummary['status'];\n};\n\nconst STOP_WORDS = new Set([\n 'a',\n 'an',\n 'and',\n 'are',\n 'as',\n 'for',\n 'in',\n 'is',\n 'of',\n 'on',\n 'or',\n 'the',\n 'to',\n 'with',\n '一个',\n '这个',\n '需要',\n '进行',\n '推进',\n]);\n\nfunction tokenizeForWorkflowMatch(text: string): string[] {\n const normalized = text.toLowerCase();\n const tokens = normalized.match(/[\\p{L}\\p{N}_-]+/gu) ?? [];\n return tokens\n .map((token) => token.trim())\n .filter((token) => token.length >= 2 && !STOP_WORDS.has(token));\n}\n\nfunction goalSearchText(goal: NonNullable<ReturnType<GoalService['get']>>): string {\n return [\n goal.title,\n goal.description,\n goal.nextAction,\n goal.blockedReason,\n ...goal.checklist.map((item: GoalChecklistItem) => `${item.text} ${item.evidenceSummary ?? ''}`),\n ].filter(Boolean).join('\\n');\n}\n\nfunction buildGoalWorkflowSuggestions(params: {\n goal: NonNullable<ReturnType<GoalService['get']>>;\n workflowRuns: WorkflowRunSummary[];\n}): GoalWorkflowSuggestion[] {\n const goalTokens = new Set(tokenizeForWorkflowMatch(goalSearchText(params.goal)));\n const runsByDefinition = new Map<string, WorkflowRunSummary[]>();\n for (const run of params.workflowRuns) {\n const list = runsByDefinition.get(run.definitionId) ?? [];\n list.push(run);\n runsByDefinition.set(run.definitionId, list);\n }\n\n const suggestions: GoalWorkflowSuggestion[] = [];\n for (const entry of createWorkflowCatalog().list()) {\n const candidateText = [\n entry.name,\n entry.title,\n entry.description,\n entry.whenToUse,\n ...(entry.tags ?? []),\n ].filter(Boolean).join('\\n');\n const candidateTokens = new Set(tokenizeForWorkflowMatch(candidateText));\n const matched = [...goalTokens].filter((token) => candidateTokens.has(token));\n const relatedRuns = runsByDefinition.get(entry.name) ?? [];\n const terminalRuns = relatedRuns.filter((run) => run.status !== 'queued' && run.status !== 'running');\n const succeededRuns = terminalRuns.filter((run) => run.status === 'succeeded');\n const successRate = terminalRuns.length ? succeededRuns.length / terminalRuns.length : undefined;\n const lastRun = relatedRuns.toSorted((left, right) => right.createdAtMs - left.createdAtMs)[0];\n\n let score = matched.length * 8;\n if (entry.tags?.some((tag) => goalTokens.has(tag.toLowerCase()))) score += 8;\n if (entry.whenToUse && matched.length > 0) score += 4;\n if (successRate != null) score += Math.round(successRate * 10);\n if (lastRun?.status === 'succeeded') score += 4;\n if (lastRun?.status === 'failed' || lastRun?.status === 'timeout') score -= 3;\n if (score <= 0) score = entry.source === 'builtin' ? 1 : 0;\n\n const reasons: string[] = [];\n if (matched.length) reasons.push(`matches ${matched.slice(0, 4).join(', ')}`);\n if (successRate != null) reasons.push(`${Math.round(successRate * 100)}% success rate`);\n if (lastRun) reasons.push(`last run ${lastRun.status}`);\n if (!reasons.length && entry.whenToUse) reasons.push('general workflow fit');\n\n if (score > 0) {\n suggestions.push({\n definitionId: entry.name,\n name: entry.name,\n title: entry.title || entry.name,\n description: entry.description,\n score,\n reasons,\n tags: entry.tags ?? [],\n successRate,\n lastRunStatus: lastRun?.status,\n });\n }\n }\n\n return suggestions\n .sort((left, right) => right.score - left.score || left.name.localeCompare(right.name))\n .slice(0, 5);\n}\n\nfunction buildGoalActivities(input: {\n goalId: string;\n queue: GoalQueueItemSnapshot[];\n runs: GoalRun[];\n workflowRuns: WorkflowRunSummary[];\n events: GoalEvent[];\n evidence: GoalEvidence[];\n limit: number;\n}): GoalActivityItem[] {\n const activities: GoalActivityItem[] = [];\n\n for (const item of input.queue.filter((queueItem) => queueItem.goalId === input.goalId)) {\n activities.push({\n id: `queue:${item.id}`,\n kind: 'queue',\n status: item.status,\n title: 'Goal queued',\n summary: item.lastError || item.message || undefined,\n createdAt: item.finishedAt ?? item.startedAt ?? item.nextRunAt ?? item.enqueuedAt,\n link: item.sessionKey ? { type: 'chat', value: item.sessionKey } : undefined,\n data: item,\n });\n }\n\n for (const run of input.runs) {\n activities.push({\n id: `goal_run:${run.id}`,\n kind: 'goal_run',\n status: run.verdict ?? run.status,\n title: 'Goal run judged',\n summary: run.reason || run.assistantPreview || run.nextAction,\n createdAt: run.finishedAt ?? run.startedAt,\n data: run,\n });\n }\n\n for (const run of input.workflowRuns) {\n activities.push({\n id: `workflow_run:${run.id}`,\n kind: 'workflow_run',\n status: run.status,\n title: run.title || run.definitionId,\n summary: run.definitionId,\n createdAt: run.completedAtMs ?? run.startedAtMs ?? run.createdAtMs,\n link: { type: 'workflow_run', value: run.id },\n data: run,\n });\n }\n\n for (const event of input.events) {\n activities.push({\n id: `event:${event.id}`,\n kind: 'event',\n status: event.kind,\n title: event.kind,\n summary: event.message,\n createdAt: event.createdAt,\n data: event,\n });\n }\n\n for (const item of input.evidence) {\n activities.push({\n id: `evidence:${item.id}`,\n kind: 'evidence',\n status: item.kind,\n title: item.title,\n summary: item.summary || item.uri,\n createdAt: item.createdAt,\n data: item,\n });\n }\n\n return activities\n .sort((left, right) => right.createdAt - left.createdAt)\n .slice(0, input.limit);\n}\n\nfunction abortActiveWebchatRunForGoal(\n deps: AuthenticatedRouteDeps,\n goal: NonNullable<ReturnType<GoalService['get']>>,\n): { aborted?: boolean; abortedRunId?: string } {\n const sessionKey = goal.activeSessionKey?.trim();\n if (!sessionKey) return {};\n const runId = deps.service.getActiveWebchatRunId(sessionKey);\n if (!runId) return {};\n return {\n abortedRunId: runId,\n aborted: deps.service.abortAgentRun(runId),\n };\n}\n\n/** First-class Goal API. Sessions are execution context; goals are durable product objects. */\nexport function registerGoalsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const goals = new GoalService();\n const cfg = () => deps.service.currentConfig;\n const workflowRunService = deps.service.createWorkflowRunService();\n\n authenticated.get('/api/goals/current', async (c) => {\n const sessionKey = c.req.query('sessionKey')?.trim();\n if (!sessionKey) return c.json({ ok: false, error: 'Missing sessionKey' }, 400);\n return c.json({ ok: true, goal: goals.getActiveForSession(sessionKey) });\n });\n\n authenticated.get('/api/goals', async (c) => {\n const status = parseStatuses(c.req.query('status'));\n const agentId = c.req.query('agentId')?.trim() || undefined;\n const sessionKey = c.req.query('sessionKey')?.trim() || undefined;\n const limit = parseLimit(c.req.query('limit'));\n const offsetRaw = c.req.query('offset')?.trim();\n const offset = offsetRaw ? Math.max(0, Number.parseInt(offsetRaw, 10) || 0) : 0;\n return c.json({ ok: true, goals: goals.list({ status, agentId, sessionKey, limit, offset }) });\n });\n\n authenticated.get('/api/goals/queue', async (c) => {\n return c.json({ ok: true, queue: deps.service.getGoalQueueSnapshot() });\n });\n\n authenticated.post('/api/goals', async (c) => {\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const title = typeof body.title === 'string' ? body.title.trim() : '';\n if (!title) return c.json({ ok: false, error: 'Missing title' }, 400);\n\n const sessionKey = typeof body.sessionKey === 'string' && body.sessionKey.trim() ? body.sessionKey.trim() : undefined;\n const agentId =\n typeof body.agentId === 'string' && body.agentId.trim()\n ? body.agentId.trim()\n : sessionKey\n ? undefined\n : getDefaultAgentId(cfg());\n const maxTurns =\n typeof body.maxTurns === 'number' && Number.isFinite(body.maxTurns)\n ? Math.max(1, Math.min(500, Math.floor(body.maxTurns)))\n : undefined;\n const goal = goals.create({\n title,\n description: typeof body.description === 'string' ? body.description : undefined,\n sessionKey,\n agentId,\n priority: body.priority === 'low' || body.priority === 'high' ? body.priority : 'normal',\n deadlineAt: typeof body.deadlineAt === 'number' && Number.isFinite(body.deadlineAt) ? body.deadlineAt : undefined,\n judgeModelRef: typeof body.judgeModelRef === 'string' ? body.judgeModelRef : undefined,\n maxTurns,\n uiLocale: normalizeGoalUiLocale(body.uiLocale),\n source: body.source === 'cli' || body.source === 'cron' || body.source === 'workflow' || body.source === 'channel' || body.source === 'api'\n ? body.source\n : 'chat',\n config: cfg(),\n });\n\n if (sessionKey) {\n deps.service.enqueueWebchatPersistentGoalKickoff(sessionKey, title);\n }\n\n return c.json({ ok: true, goal: goals.get(goal.id) });\n });\n\n authenticated.get('/api/goals/:goalId/workflow-runs', async (c) => {\n const goalId = c.req.param('goalId');\n const goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const runStore = workflowRunService.createRunStore(goal.agentId || getDefaultAgentId(cfg()));\n const runs = await runStore.listRunSummariesForGoal(goalId, parseLimit(c.req.query('limit')));\n return c.json({ ok: true, runs });\n });\n\n authenticated.post('/api/goals/:goalId/workflows/run', async (c) => {\n const goalId = c.req.param('goalId');\n const goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (goal.status === 'done' || goal.status === 'archived') {\n return c.json({ ok: false, error: `Goal is ${goal.status}` }, 409);\n }\n\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const definitionId = typeof body.definitionId === 'string' ? body.definitionId.trim() : '';\n if (!definitionId) return c.json({ ok: false, error: 'Missing definitionId' }, 400);\n\n try {\n createWorkflowCatalog().load(definitionId);\n } catch {\n return c.json({ ok: false, error: 'Workflow definition not found' }, 404);\n }\n\n const result = await workflowRunService.startWorkflowRun({\n agentId: goal.agentId || getDefaultAgentId(cfg()),\n definitionId,\n goalId,\n goal: typeof body.goal === 'string' && body.goal.trim() ? body.goal.trim() : goal.nextAction || goal.title,\n input: body.input ?? {\n goal: goal.title,\n description: goal.description,\n nextAction: goal.nextAction,\n checklist: goal.checklist.map((item) => ({\n text: item.text,\n status: item.status,\n evidenceSummary: item.evidenceSummary,\n })),\n },\n parentSessionKey: goal.activeSessionKey,\n source: { kind: 'webui' },\n concurrency: typeof body.concurrency === 'number' ? body.concurrency : undefined,\n maxSubagents: typeof body.maxSubagents === 'number' ? body.maxSubagents : undefined,\n });\n if (result.ok === false) {\n return c.json({ ok: false, error: result.message, code: result.code }, result.httpStatus);\n }\n return c.json({ ok: true, runId: result.runId, sessionKey: result.sessionKey }, 202);\n });\n\n authenticated.get('/api/goals/:goalId/activity', async (c) => {\n const goalId = c.req.param('goalId');\n const goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n\n const limit = parseLimit(c.req.query('limit'), 100);\n const runStore = workflowRunService.createRunStore(goal.agentId || getDefaultAgentId(cfg()));\n const workflowRuns = await runStore.listRunSummariesForGoal(goalId, limit);\n const activities = buildGoalActivities({\n goalId,\n queue: deps.service.getGoalQueueSnapshot(),\n runs: goals.listRuns(goalId, limit),\n workflowRuns,\n events: goals.listEvents(goalId, limit),\n evidence: goals.listEvidence(goalId, limit),\n limit,\n });\n return c.json({ ok: true, activities });\n });\n\n authenticated.get('/api/goals/:goalId/workflow-suggestions', async (c) => {\n const goalId = c.req.param('goalId');\n const goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n\n const runStore = workflowRunService.createRunStore(goal.agentId || getDefaultAgentId(cfg()));\n const workflowRuns = await runStore.listRunSummaries(500);\n return c.json({\n ok: true,\n suggestions: buildGoalWorkflowSuggestions({ goal, workflowRuns }),\n });\n });\n\n authenticated.get('/api/goals/:goalId', async (c) => {\n const goal = goals.get(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, goal });\n });\n\n authenticated.patch('/api/goals/:goalId', async (c) => {\n const goalId = c.req.param('goalId');\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const status = parseBodyGoalStatus(body.status);\n let goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const patch: Parameters<GoalService['update']>[1] = {};\n if (typeof body.title === 'string') patch.title = body.title;\n if ('description' in body) patch.description = typeof body.description === 'string' ? body.description : undefined;\n const priority = parsePriority(body.priority);\n if (priority) patch.priority = priority;\n if ('deadlineAt' in body) {\n patch.deadlineAt = typeof body.deadlineAt === 'number' && Number.isFinite(body.deadlineAt) ? body.deadlineAt : undefined;\n }\n if (typeof body.maxTurns === 'number' && Number.isFinite(body.maxTurns)) patch.maxTurns = body.maxTurns;\n if ('judgeModelRef' in body) patch.judgeModelRef = typeof body.judgeModelRef === 'string' ? body.judgeModelRef : undefined;\n if ('nextAction' in body) patch.nextAction = typeof body.nextAction === 'string' ? body.nextAction : undefined;\n if ('blockedReason' in body) patch.blockedReason = typeof body.blockedReason === 'string' ? body.blockedReason : undefined;\n const locale = normalizeGoalUiLocale(body.uiLocale);\n if (locale) patch.uiLocale = locale;\n if (Object.keys(patch).length > 0) {\n goal = goals.update(goalId, patch);\n }\n if (status) {\n const previousStatus = goal?.status;\n goal = goals.setStatus(goalId, status, {\n reason: typeof body.reason === 'string' ? body.reason : undefined,\n });\n const abortResult = goal && status === 'archived' ? abortActiveWebchatRunForGoal(deps, goal) : {};\n if (goal && previousStatus !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId,\n previousStatus,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal, ...abortResult });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/continue', async (c) => {\n const goalId = c.req.param('goalId');\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n let sessionKey =\n typeof body.sessionKey === 'string' && body.sessionKey.trim()\n ? body.sessionKey.trim()\n : goal.activeSessionKey;\n\n if (!sessionKey) {\n sessionKey = buildSessionKey({\n agentId: goal.agentId || getDefaultAgentId(cfg()),\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: `goal-${sanitizeSegment(goal.id) || Date.now()}`,\n });\n await deps.service.sessionIndexInstance.saveMessages(sessionKey, []);\n goals.attachSession(goalId, sessionKey);\n }\n\n const queued = deps.service.enqueueGoalRun(goalId, {\n message: typeof body.message === 'string' ? body.message : undefined,\n maxRetries: typeof body.maxRetries === 'number' && Number.isFinite(body.maxRetries) ? body.maxRetries : undefined,\n source: 'api',\n });\n const nextGoal = goals.get(goalId);\n return c.json({ ok: true, goal: nextGoal, sessionKey, queued });\n });\n\n authenticated.post('/api/goals/:goalId/enqueue', async (c) => {\n const goalId = c.req.param('goalId');\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const item = deps.service.enqueueGoalRun(goalId, {\n message: typeof body.message === 'string' ? body.message : undefined,\n maxRetries: typeof body.maxRetries === 'number' && Number.isFinite(body.maxRetries) ? body.maxRetries : undefined,\n source: 'api',\n });\n return c.json({ ok: true, item });\n });\n\n authenticated.post('/api/goals/:goalId/pause', async (c) => {\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.pause(\n c.req.param('goalId'),\n typeof body.reason === 'string' && body.reason.trim() ? body.reason.trim() : 'user-paused',\n );\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/resume', async (c) => {\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.resume(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/reopen', async (c) => {\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.reopen(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/complete', async (c) => {\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.complete(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/archive', async (c) => {\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.archive(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const abortResult = abortActiveWebchatRunForGoal(deps, goal);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal, ...abortResult });\n });\n\n authenticated.post('/api/goals/:goalId/unarchive', async (c) => {\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.unarchive(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/attach', async (c) => {\n const goalId = c.req.param('goalId');\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const sessionKey = typeof body.sessionKey === 'string' ? body.sessionKey.trim() : '';\n if (!sessionKey) return c.json({ ok: false, error: 'Missing sessionKey' }, 400);\n const goal = goals.attachSession(goalId, sessionKey);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/detach', async (c) => {\n const goal = goals.update(c.req.param('goalId'), { activeSessionKey: undefined });\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, goal });\n });\n\n authenticated.get('/api/goals/:goalId/runs', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, runs: goals.listRuns(goalId, parseLimit(c.req.query('limit'))) });\n });\n\n authenticated.get('/api/goals/:goalId/events', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, events: goals.listEvents(goalId, parseLimit(c.req.query('limit'), 100)) });\n });\n\n authenticated.get('/api/goals/:goalId/evidence', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, evidence: goals.listEvidence(goalId, parseLimit(c.req.query('limit'), 100)) });\n });\n\n authenticated.post('/api/goals/:goalId/evidence', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const title = typeof body.title === 'string' ? body.title.trim() : '';\n const kind = body.kind;\n if (!title) return c.json({ ok: false, error: 'Missing title' }, 400);\n if (kind !== 'file' && kind !== 'diff' && kind !== 'command' && kind !== 'test' && kind !== 'link' && kind !== 'message' && kind !== 'artifact') {\n return c.json({ ok: false, error: 'Invalid evidence kind' }, 400);\n }\n const evidence = goals.addEvidence({\n goalId,\n runId: typeof body.runId === 'string' ? body.runId : undefined,\n kind,\n title,\n summary: typeof body.summary === 'string' ? body.summary : undefined,\n uri: typeof body.uri === 'string' ? body.uri : undefined,\n data: body.data,\n });\n return c.json({ ok: true, evidence });\n });\n\n authenticated.post('/api/goals/:goalId/checklist', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const text = typeof body.text === 'string' ? body.text.trim() : '';\n if (!text) return c.json({ ok: false, error: 'Missing text' }, 400);\n const goal = goals.updateChecklist(goalId, { type: 'add', text, addedBy: 'user' });\n return c.json({ ok: true, goal });\n });\n\n authenticated.patch('/api/goals/:goalId/checklist/:itemId', async (c) => {\n const goalId = c.req.param('goalId');\n const itemId = c.req.param('itemId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const status = body.status;\n if (status !== 'pending' && status !== 'completed' && status !== 'impossible') {\n return c.json({ ok: false, error: 'Invalid checklist status' }, 400);\n }\n const goal = goals.updateChecklist(goalId, {\n type: 'mark',\n itemId,\n status,\n evidenceSummary: typeof body.evidenceSummary === 'string' ? body.evidenceSummary : undefined,\n });\n return c.json({ ok: true, goal });\n });\n\n authenticated.delete('/api/goals/:goalId/checklist/:itemId', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const goal = goals.updateChecklist(goalId, { type: 'remove', itemId: c.req.param('itemId') });\n return c.json({ ok: true, goal });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"goals.js","names":[],"sources":["../../../../../src/gateway/hono/routes/goals.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { createWorkflowCatalog } from '../../../agent/workflow/catalog.js';\nimport {\n GoalService,\n normalizeGoalUiLocale,\n type GoalChecklistItem,\n type GoalEvent,\n type GoalEvidence,\n type GoalQueueItemSnapshot,\n type GoalRun,\n type GoalStatus,\n} from '../../../goals/index.js';\nimport { buildSessionKey, sanitizeSegment } from '../../../routing/session-key.js';\nimport { getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { WorkflowRunSummary } from '../../../workflows/domain/index.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nfunction parseLimit(raw: string | undefined, fallback = 50): number {\n if (!raw) return fallback;\n const n = Number.parseInt(raw, 10);\n return Number.isFinite(n) ? Math.min(500, Math.max(1, n)) : fallback;\n}\n\nfunction parseStatuses(raw: string | undefined): GoalStatus[] | undefined {\n if (!raw?.trim()) return undefined;\n const statuses = raw\n .split(',')\n .map((s) => s.trim())\n .filter((s): s is GoalStatus =>\n s === 'active' ||\n s === 'paused' ||\n s === 'blocked' ||\n s === 'needs_input' ||\n s === 'done' ||\n s === 'archived',\n );\n return statuses.length ? statuses : undefined;\n}\n\nfunction parseBodyGoalStatus(raw: unknown): GoalStatus | null {\n return raw === 'active' ||\n raw === 'paused' ||\n raw === 'blocked' ||\n raw === 'needs_input' ||\n raw === 'done' ||\n raw === 'archived'\n ? raw\n : null;\n}\n\nfunction parsePriority(raw: unknown): 'low' | 'normal' | 'high' | undefined {\n return raw === 'low' || raw === 'normal' || raw === 'high' ? raw : undefined;\n}\n\ntype GoalActivityItem = {\n id: string;\n kind: 'queue' | 'goal_run' | 'workflow_run' | 'event' | 'evidence';\n status?: string;\n title: string;\n summary?: string;\n createdAt: number;\n link?: { type: 'chat' | 'workflow_run'; value: string };\n data?: unknown;\n};\n\ntype GoalWorkflowSuggestion = {\n definitionId: string;\n name: string;\n title: string;\n description: string;\n score: number;\n reasons: string[];\n tags: string[];\n successRate?: number;\n lastRunStatus?: WorkflowRunSummary['status'];\n};\n\nconst STOP_WORDS = new Set([\n 'a',\n 'an',\n 'and',\n 'are',\n 'as',\n 'for',\n 'in',\n 'is',\n 'of',\n 'on',\n 'or',\n 'the',\n 'to',\n 'with',\n '一个',\n '这个',\n '需要',\n '进行',\n '推进',\n]);\n\nfunction tokenizeForWorkflowMatch(text: string): string[] {\n const normalized = text.toLowerCase();\n const tokens = normalized.match(/[\\p{L}\\p{N}_-]+/gu) ?? [];\n return tokens\n .map((token) => token.trim())\n .filter((token) => token.length >= 2 && !STOP_WORDS.has(token));\n}\n\nfunction goalSearchText(goal: NonNullable<ReturnType<GoalService['get']>>): string {\n return [\n goal.title,\n goal.description,\n goal.nextAction,\n goal.blockedReason,\n ...goal.checklist.map((item: GoalChecklistItem) => `${item.text} ${item.evidenceSummary ?? ''}`),\n ].filter(Boolean).join('\\n');\n}\n\nfunction buildGoalWorkflowSuggestions(params: {\n goal: NonNullable<ReturnType<GoalService['get']>>;\n workflowRuns: WorkflowRunSummary[];\n}): GoalWorkflowSuggestion[] {\n const goalTokens = new Set(tokenizeForWorkflowMatch(goalSearchText(params.goal)));\n const runsByDefinition = new Map<string, WorkflowRunSummary[]>();\n for (const run of params.workflowRuns) {\n const list = runsByDefinition.get(run.definitionId) ?? [];\n list.push(run);\n runsByDefinition.set(run.definitionId, list);\n }\n\n const suggestions: GoalWorkflowSuggestion[] = [];\n for (const entry of createWorkflowCatalog().list()) {\n const candidateText = [\n entry.name,\n entry.title,\n entry.description,\n entry.whenToUse,\n ...(entry.tags ?? []),\n ].filter(Boolean).join('\\n');\n const candidateTokens = new Set(tokenizeForWorkflowMatch(candidateText));\n const matched = [...goalTokens].filter((token) => candidateTokens.has(token));\n const relatedRuns = runsByDefinition.get(entry.name) ?? [];\n const terminalRuns = relatedRuns.filter((run) => run.status !== 'queued' && run.status !== 'running');\n const succeededRuns = terminalRuns.filter((run) => run.status === 'succeeded');\n const successRate = terminalRuns.length ? succeededRuns.length / terminalRuns.length : undefined;\n const lastRun = relatedRuns.toSorted((left, right) => right.createdAtMs - left.createdAtMs)[0];\n\n let score = matched.length * 8;\n if (entry.tags?.some((tag) => goalTokens.has(tag.toLowerCase()))) score += 8;\n if (entry.whenToUse && matched.length > 0) score += 4;\n if (successRate != null) score += Math.round(successRate * 10);\n if (lastRun?.status === 'succeeded') score += 4;\n if (lastRun?.status === 'failed' || lastRun?.status === 'timeout') score -= 3;\n if (score <= 0) score = entry.source === 'builtin' ? 1 : 0;\n\n const reasons: string[] = [];\n if (matched.length) reasons.push(`matches ${matched.slice(0, 4).join(', ')}`);\n if (successRate != null) reasons.push(`${Math.round(successRate * 100)}% success rate`);\n if (lastRun) reasons.push(`last run ${lastRun.status}`);\n if (!reasons.length && entry.whenToUse) reasons.push('general workflow fit');\n\n if (score > 0) {\n suggestions.push({\n definitionId: entry.name,\n name: entry.name,\n title: entry.title || entry.name,\n description: entry.description,\n score,\n reasons,\n tags: entry.tags ?? [],\n successRate,\n lastRunStatus: lastRun?.status,\n });\n }\n }\n\n return suggestions\n .sort((left, right) => right.score - left.score || left.name.localeCompare(right.name))\n .slice(0, 5);\n}\n\nfunction buildGoalActivities(input: {\n goalId: string;\n queue: GoalQueueItemSnapshot[];\n runs: GoalRun[];\n workflowRuns: WorkflowRunSummary[];\n events: GoalEvent[];\n evidence: GoalEvidence[];\n limit: number;\n}): GoalActivityItem[] {\n const activities: GoalActivityItem[] = [];\n\n for (const item of input.queue.filter((queueItem) => queueItem.goalId === input.goalId)) {\n activities.push({\n id: `queue:${item.id}`,\n kind: 'queue',\n status: item.status,\n title: 'Goal queued',\n summary: item.lastError || item.message || undefined,\n createdAt: item.finishedAt ?? item.startedAt ?? item.nextRunAt ?? item.enqueuedAt,\n link: item.sessionKey ? { type: 'chat', value: item.sessionKey } : undefined,\n data: item,\n });\n }\n\n for (const run of input.runs) {\n activities.push({\n id: `goal_run:${run.id}`,\n kind: 'goal_run',\n status: run.verdict ?? run.status,\n title: 'Goal run judged',\n summary: run.reason || run.assistantPreview || run.nextAction,\n createdAt: run.finishedAt ?? run.startedAt,\n data: run,\n });\n }\n\n for (const run of input.workflowRuns) {\n activities.push({\n id: `workflow_run:${run.id}`,\n kind: 'workflow_run',\n status: run.status,\n title: run.title || run.definitionId,\n summary: run.definitionId,\n createdAt: run.completedAtMs ?? run.startedAtMs ?? run.createdAtMs,\n link: { type: 'workflow_run', value: run.id },\n data: run,\n });\n }\n\n for (const event of input.events) {\n activities.push({\n id: `event:${event.id}`,\n kind: 'event',\n status: event.kind,\n title: event.kind,\n summary: event.message,\n createdAt: event.createdAt,\n data: event,\n });\n }\n\n for (const item of input.evidence) {\n activities.push({\n id: `evidence:${item.id}`,\n kind: 'evidence',\n status: item.kind,\n title: item.title,\n summary: item.summary || item.uri,\n createdAt: item.createdAt,\n data: item,\n });\n }\n\n return activities\n .sort((left, right) => right.createdAt - left.createdAt)\n .slice(0, input.limit);\n}\n\nfunction abortActiveWebchatRunForGoal(\n deps: AuthenticatedRouteDeps,\n goal: NonNullable<ReturnType<GoalService['get']>>,\n): { aborted?: boolean; abortedRunId?: string } {\n const sessionKey = goal.activeSessionKey?.trim();\n if (!sessionKey) return {};\n const runId = deps.service.getActiveWebchatRunId(sessionKey);\n if (!runId) return {};\n return {\n abortedRunId: runId,\n aborted: deps.service.abortAgentRun(runId),\n };\n}\n\n/** First-class Goal API. Sessions are execution context; goals are durable product objects. */\nexport function registerGoalsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const goals = new GoalService();\n const cfg = () => deps.service.currentConfig;\n const workflowRunService = deps.service.createWorkflowRunService();\n\n authenticated.get('/api/goals/current', async (c) => {\n const sessionKey = c.req.query('sessionKey')?.trim();\n if (!sessionKey) return c.json({ ok: false, error: 'Missing sessionKey' }, 400);\n return c.json({ ok: true, goal: goals.getActiveForSession(sessionKey) });\n });\n\n authenticated.get('/api/goals', async (c) => {\n const status = parseStatuses(c.req.query('status'));\n const agentId = c.req.query('agentId')?.trim() || undefined;\n const sessionKey = c.req.query('sessionKey')?.trim() || undefined;\n const limit = parseLimit(c.req.query('limit'));\n const offsetRaw = c.req.query('offset')?.trim();\n const offset = offsetRaw ? Math.max(0, Number.parseInt(offsetRaw, 10) || 0) : 0;\n return c.json({ ok: true, goals: goals.list({ status, agentId, sessionKey, limit, offset }) });\n });\n\n authenticated.get('/api/goals/queue', async (c) => {\n return c.json({ ok: true, queue: deps.service.getGoalQueueSnapshot() });\n });\n\n authenticated.post('/api/goals', async (c) => {\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const title = typeof body.title === 'string' ? body.title.trim() : '';\n if (!title) return c.json({ ok: false, error: 'Missing title' }, 400);\n\n const sessionKey = typeof body.sessionKey === 'string' && body.sessionKey.trim() ? body.sessionKey.trim() : undefined;\n const agentId =\n typeof body.agentId === 'string' && body.agentId.trim()\n ? body.agentId.trim()\n : sessionKey\n ? undefined\n : getDefaultAgentId(cfg());\n const maxTurns =\n typeof body.maxTurns === 'number' && Number.isFinite(body.maxTurns)\n ? Math.max(1, Math.min(500, Math.floor(body.maxTurns)))\n : undefined;\n const goal = goals.create({\n title,\n description: typeof body.description === 'string' ? body.description : undefined,\n sessionKey,\n agentId,\n priority: body.priority === 'low' || body.priority === 'high' ? body.priority : 'normal',\n deadlineAt: typeof body.deadlineAt === 'number' && Number.isFinite(body.deadlineAt) ? body.deadlineAt : undefined,\n judgeModelRef: typeof body.judgeModelRef === 'string' ? body.judgeModelRef : undefined,\n maxTurns,\n uiLocale: normalizeGoalUiLocale(body.uiLocale),\n source: body.source === 'cli' || body.source === 'cron' || body.source === 'workflow' || body.source === 'channel' || body.source === 'api'\n ? body.source\n : 'chat',\n config: cfg(),\n });\n\n if (sessionKey) {\n deps.service.enqueueWebchatPersistentGoalKickoff(sessionKey, title);\n }\n\n return c.json({ ok: true, goal: goals.get(goal.id) });\n });\n\n authenticated.get('/api/goals/:goalId/workflow-runs', async (c) => {\n const goalId = c.req.param('goalId');\n const goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const runStore = workflowRunService.createRunStore(goal.agentId || getDefaultAgentId(cfg()));\n const runs = await runStore.listRunSummariesForGoal(goalId, parseLimit(c.req.query('limit')));\n return c.json({ ok: true, runs });\n });\n\n authenticated.post('/api/goals/:goalId/workflows/run', async (c) => {\n const goalId = c.req.param('goalId');\n const goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (goal.status === 'done' || goal.status === 'archived') {\n return c.json({ ok: false, error: `Goal is ${goal.status}` }, 409);\n }\n\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const definitionId = typeof body.definitionId === 'string' ? body.definitionId.trim() : '';\n if (!definitionId) return c.json({ ok: false, error: 'Missing definitionId' }, 400);\n\n try {\n createWorkflowCatalog().load(definitionId);\n } catch {\n return c.json({ ok: false, error: 'Workflow definition not found' }, 404);\n }\n\n const result = await workflowRunService.startWorkflowRun({\n agentId: goal.agentId || getDefaultAgentId(cfg()),\n definitionId,\n goalId,\n goal: typeof body.goal === 'string' && body.goal.trim() ? body.goal.trim() : goal.nextAction || goal.title,\n input: body.input ?? {\n goal: goal.title,\n description: goal.description,\n nextAction: goal.nextAction,\n checklist: goal.checklist.map((item) => ({\n text: item.text,\n status: item.status,\n evidenceSummary: item.evidenceSummary,\n })),\n },\n parentSessionKey: goal.activeSessionKey,\n source: { kind: 'webui' },\n concurrency: typeof body.concurrency === 'number' ? body.concurrency : undefined,\n maxSubagents: typeof body.maxSubagents === 'number' ? body.maxSubagents : undefined,\n });\n if (result.ok === false) {\n return c.json({ ok: false, error: result.message, code: result.code }, result.httpStatus);\n }\n return c.json({ ok: true, runId: result.runId, sessionKey: result.sessionKey }, 202);\n });\n\n authenticated.get('/api/goals/:goalId/activity', async (c) => {\n const goalId = c.req.param('goalId');\n const goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n\n const limit = parseLimit(c.req.query('limit'), 100);\n const runStore = workflowRunService.createRunStore(goal.agentId || getDefaultAgentId(cfg()));\n const workflowRuns = await runStore.listRunSummariesForGoal(goalId, limit);\n const activities = buildGoalActivities({\n goalId,\n queue: deps.service.getGoalQueueSnapshot(),\n runs: goals.listRuns(goalId, limit),\n workflowRuns,\n events: goals.listEvents(goalId, limit),\n evidence: goals.listEvidence(goalId, limit),\n limit,\n });\n return c.json({ ok: true, activities });\n });\n\n authenticated.get('/api/goals/:goalId/workflow-suggestions', async (c) => {\n const goalId = c.req.param('goalId');\n const goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n\n const runStore = workflowRunService.createRunStore(goal.agentId || getDefaultAgentId(cfg()));\n const workflowRuns = await runStore.listRunSummaries(500);\n return c.json({\n ok: true,\n suggestions: buildGoalWorkflowSuggestions({ goal, workflowRuns }),\n });\n });\n\n authenticated.get('/api/goals/:goalId', async (c) => {\n const goal = goals.get(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, goal });\n });\n\n authenticated.patch('/api/goals/:goalId', async (c) => {\n const goalId = c.req.param('goalId');\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const status = parseBodyGoalStatus(body.status);\n let goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const patch: Parameters<GoalService['update']>[1] = {};\n if (typeof body.title === 'string') patch.title = body.title;\n if ('description' in body) patch.description = typeof body.description === 'string' ? body.description : undefined;\n const priority = parsePriority(body.priority);\n if (priority) patch.priority = priority;\n if ('deadlineAt' in body) {\n patch.deadlineAt = typeof body.deadlineAt === 'number' && Number.isFinite(body.deadlineAt) ? body.deadlineAt : undefined;\n }\n if (typeof body.maxTurns === 'number' && Number.isFinite(body.maxTurns)) patch.maxTurns = body.maxTurns;\n if ('judgeModelRef' in body) patch.judgeModelRef = typeof body.judgeModelRef === 'string' ? body.judgeModelRef : undefined;\n if ('nextAction' in body) patch.nextAction = typeof body.nextAction === 'string' ? body.nextAction : undefined;\n if ('blockedReason' in body) patch.blockedReason = typeof body.blockedReason === 'string' ? body.blockedReason : undefined;\n const locale = normalizeGoalUiLocale(body.uiLocale);\n if (locale) patch.uiLocale = locale;\n if (Object.keys(patch).length > 0) {\n goal = goals.update(goalId, patch);\n }\n if (status) {\n const previousStatus = goal?.status;\n goal = goals.setStatus(goalId, status, {\n reason: typeof body.reason === 'string' ? body.reason : undefined,\n });\n const abortResult = goal && status === 'archived' ? abortActiveWebchatRunForGoal(deps, goal) : {};\n if (goal && previousStatus !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId,\n previousStatus,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal, ...abortResult });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/continue', async (c) => {\n const goalId = c.req.param('goalId');\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const goal = goals.get(goalId);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n let sessionKey =\n typeof body.sessionKey === 'string' && body.sessionKey.trim()\n ? body.sessionKey.trim()\n : goal.activeSessionKey;\n\n if (!sessionKey) {\n const agentId = goal.agentId || getDefaultAgentId(cfg());\n const peerId = `goal-${sanitizeSegment(goal.id) || Date.now()}`;\n sessionKey = buildSessionKey({\n agentId,\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId,\n });\n await deps.service.sessionIndexInstance.saveMessages(sessionKey, [], {\n metadata: {\n sourceChannel: 'webchat',\n sourceChatId: `default:direct:${peerId}`,\n sessionType: 'chat',\n routing: {\n agentId,\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId,\n },\n },\n });\n goals.attachSession(goalId, sessionKey);\n }\n\n const queued = deps.service.enqueueGoalRun(goalId, {\n message: typeof body.message === 'string' ? body.message : undefined,\n maxRetries: typeof body.maxRetries === 'number' && Number.isFinite(body.maxRetries) ? body.maxRetries : undefined,\n source: 'api',\n });\n const nextGoal = goals.get(goalId);\n return c.json({ ok: true, goal: nextGoal, sessionKey, queued });\n });\n\n authenticated.post('/api/goals/:goalId/enqueue', async (c) => {\n const goalId = c.req.param('goalId');\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const item = deps.service.enqueueGoalRun(goalId, {\n message: typeof body.message === 'string' ? body.message : undefined,\n maxRetries: typeof body.maxRetries === 'number' && Number.isFinite(body.maxRetries) ? body.maxRetries : undefined,\n source: 'api',\n });\n return c.json({ ok: true, item });\n });\n\n authenticated.post('/api/goals/:goalId/pause', async (c) => {\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.pause(\n c.req.param('goalId'),\n typeof body.reason === 'string' && body.reason.trim() ? body.reason.trim() : 'user-paused',\n );\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/resume', async (c) => {\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.resume(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/reopen', async (c) => {\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.reopen(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/complete', async (c) => {\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.complete(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/archive', async (c) => {\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.archive(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const abortResult = abortActiveWebchatRunForGoal(deps, goal);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal, ...abortResult });\n });\n\n authenticated.post('/api/goals/:goalId/unarchive', async (c) => {\n const before = goals.get(c.req.param('goalId'));\n const goal = goals.unarchive(c.req.param('goalId'));\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n if (before?.status !== goal.status) {\n deps.service.emit('goal.status.updated', {\n goalId: goal.id,\n previousStatus: before?.status,\n status: goal.status,\n goal,\n });\n }\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/attach', async (c) => {\n const goalId = c.req.param('goalId');\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const sessionKey = typeof body.sessionKey === 'string' ? body.sessionKey.trim() : '';\n if (!sessionKey) return c.json({ ok: false, error: 'Missing sessionKey' }, 400);\n const goal = goals.attachSession(goalId, sessionKey);\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, goal });\n });\n\n authenticated.post('/api/goals/:goalId/detach', async (c) => {\n const goal = goals.update(c.req.param('goalId'), { activeSessionKey: undefined });\n if (!goal) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, goal });\n });\n\n authenticated.get('/api/goals/:goalId/runs', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, runs: goals.listRuns(goalId, parseLimit(c.req.query('limit'))) });\n });\n\n authenticated.get('/api/goals/:goalId/events', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, events: goals.listEvents(goalId, parseLimit(c.req.query('limit'), 100)) });\n });\n\n authenticated.get('/api/goals/:goalId/evidence', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n return c.json({ ok: true, evidence: goals.listEvidence(goalId, parseLimit(c.req.query('limit'), 100)) });\n });\n\n authenticated.post('/api/goals/:goalId/evidence', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const title = typeof body.title === 'string' ? body.title.trim() : '';\n const kind = body.kind;\n if (!title) return c.json({ ok: false, error: 'Missing title' }, 400);\n if (kind !== 'file' && kind !== 'diff' && kind !== 'command' && kind !== 'test' && kind !== 'link' && kind !== 'message' && kind !== 'artifact') {\n return c.json({ ok: false, error: 'Invalid evidence kind' }, 400);\n }\n const evidence = goals.addEvidence({\n goalId,\n runId: typeof body.runId === 'string' ? body.runId : undefined,\n kind,\n title,\n summary: typeof body.summary === 'string' ? body.summary : undefined,\n uri: typeof body.uri === 'string' ? body.uri : undefined,\n data: body.data,\n });\n return c.json({ ok: true, evidence });\n });\n\n authenticated.post('/api/goals/:goalId/checklist', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const text = typeof body.text === 'string' ? body.text.trim() : '';\n if (!text) return c.json({ ok: false, error: 'Missing text' }, 400);\n const goal = goals.updateChecklist(goalId, { type: 'add', text, addedBy: 'user' });\n return c.json({ ok: true, goal });\n });\n\n authenticated.patch('/api/goals/:goalId/checklist/:itemId', async (c) => {\n const goalId = c.req.param('goalId');\n const itemId = c.req.param('itemId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const status = body.status;\n if (status !== 'pending' && status !== 'completed' && status !== 'impossible') {\n return c.json({ ok: false, error: 'Invalid checklist status' }, 400);\n }\n const goal = goals.updateChecklist(goalId, {\n type: 'mark',\n itemId,\n status,\n evidenceSummary: typeof body.evidenceSummary === 'string' ? body.evidenceSummary : undefined,\n });\n return c.json({ ok: true, goal });\n });\n\n authenticated.delete('/api/goals/:goalId/checklist/:itemId', async (c) => {\n const goalId = c.req.param('goalId');\n if (!goals.get(goalId)) return c.json({ ok: false, error: 'Goal not found' }, 404);\n const goal = goals.updateChecklist(goalId, { type: 'remove', itemId: c.req.param('itemId') });\n return c.json({ ok: true, goal });\n });\n}\n"],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@ function registerLogsRoutes(authenticated, _deps) {
|
|
|
12
12
|
q: query.q,
|
|
13
13
|
module: query.module,
|
|
14
14
|
requestId: query.requestId,
|
|
15
|
+
sessionKey: query.sessionKey,
|
|
15
16
|
sessionId: query.sessionId,
|
|
16
17
|
limit: query.limit ? parseInt(query.limit) : 100,
|
|
17
18
|
offset: query.offset ? parseInt(query.offset) : 0
|