@xopcai/xopc 0.0.188 → 0.0.189
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store--QoUGhiS.js → activity-store-DTFKTPs8.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B0yweLNQ.js → agent-avatar-dicebear-DqO25Qe5.js} +1 -1
- package/dist/gateway/static/root/assets/agents-BvdqdER9.js +2 -0
- package/dist/gateway/static/root/assets/{api-5laWqfiE.js → api-DWeXfwVU.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BXJ8Jiv_.js → app-management-settings-panel-BRpV8PXG.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DG9n9D1M.js → appearance-settings-3ntKM9nQ.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-nKLsfy6C.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-Ceh5qrZf.js → archive-plugin-Df7Ycj_7.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-jFW7uYf7.js → attachment-load-UHgfZYtj.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-Dh5bdZiN.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-XDlkI1r4.js → binary-plugins-BJah99wE.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-kyKc2IhE.js → block-editor-DNlY5KqF.js} +46 -46
- package/dist/gateway/static/root/assets/browser-settings-page-CRJ_nAuh.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-BJa5Iz_v.js → browser-workflow-inputs-vyUfdzAd.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-CTQQOsn5.js → browser-workflows-page-C1cKZjx-.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-DeQR5BZt.js +7 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-Dn-7MMEo.js → capability-presets-api-D7tkhDMv.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-D7uK3q1p.js +1 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-BgIkWq01.js → channel-recipient-api-BGG2kpJB.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-Bw6Dniyq.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-BrUTz4uU.js +1 -0
- package/dist/gateway/static/root/assets/{connector-logo-TRr9ybf6.js → connector-logo-8YU53RUT.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-k9tMiOL5.js +2 -0
- package/dist/gateway/static/root/assets/{desktop-pet-CSwd00CV.js → desktop-pet-BUuBEJuP.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-CuNQvHGu.js → desktop-pet-settings-BGfVIJM3.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-ct0n5Rje.js → directory-picker-path-field-DrQFfHH_.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BeRBuMUU.js → extension-debug-page-CEnIFOX-.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DbK-Cwao.js → extension-page-CCqHbexs.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-C9ag5tb5.js → extension-settings-page-DEZw_7zN.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-CC7EvEFp.js → gateway-config-api-CgUE2Ii1.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-Dg8qCiIp.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-B2DmdlwO.js → gateway-startup-retry-DxhKNiCF.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-fl1oC_-5.js → heartbeat-settings-27tRzDEo.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-VA511kMr.js +3 -0
- package/dist/gateway/static/root/assets/{image-generation-api-GMTaS6eI.js → image-generation-api-DCFdc-HD.js} +1 -1
- package/dist/gateway/static/root/assets/index-BvR-i-m6.js +216 -0
- package/dist/gateway/static/root/assets/index-zybP34zk.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DhGYddbI.js → keyboard-shortcuts-settings-Bf2VLtXW.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-CaJq4-wV.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-CmnrBmWi.js → local-apps-page-Ca1RuI13.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-D6hs74o5.js → locale-store-DUW5YE3R.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-BLTCg69e.js +2 -0
- package/dist/gateway/static/root/assets/management-settings-B3Eop1zn.js +1 -0
- package/dist/gateway/static/root/assets/{markdown-split-CZaBPOVn.js → markdown-split-BGOYjgnM.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-CiKvSgCv.js → media-plugins-CT0txyM4.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CMjnbdbn.js +3 -0
- package/dist/gateway/static/root/assets/{notes-page-Bisbzqlz.js → notes-page-DfKgAe78.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-Bp1w9UM1.js +4 -0
- package/dist/gateway/static/root/assets/{page-tabs-BxlwhAbH.js → page-tabs-DNrbCgmC.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-RM8wXxfT.js → preview-open-alternatives-BTqViDOR.js} +1 -1
- package/dist/gateway/static/root/assets/product-delivery-tRr-7IxY.js +1 -0
- package/dist/gateway/static/root/assets/{product-open-page-DdBlibek.js → product-open-page-C_2L4_Iu.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-CZmbPDQN.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-D5pzqfm5.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-CC-XhVGI.js +1 -0
- package/dist/gateway/static/root/assets/{schema-form-BDKbpmXv.js → schema-form-BFLfkDGG.js} +1 -1
- package/dist/gateway/static/root/assets/{schemas-C6onAggk.js → schemas-zIBW3wiV.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-B2eTLVDV.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-CRuZ_bl0.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-zxo5ZGOu.js → settings-form-section-C4GXGeA4.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-DgIp8_S6.js → settings-loading-skeleton-C9a-EbTZ.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-DI9qDH5x.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-layout-97LmwrzC.js → settings-page-layout-D-LWQdI5.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-CJwmPvgs.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-BH7i3g1S.js → share-preview-page-BKSMG9r5.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-YzSDS4G_.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-CwOo8zZk.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-xd1cgSGN.js +2 -0
- package/dist/gateway/static/root/assets/{skills-page.utils-s-a5WV9j.js → skills-page.utils-zsz2HIlZ.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-BxjeMT5k.js → system-settings-panel-IWNDBI1O.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-BahycnfW.js → task-detail-page-CgtK02kP.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-BRxdsmic.js → theme-store-BkJe7UDo.js} +1 -1
- package/dist/gateway/static/root/assets/time-picker-CstQ___Y.js +1 -0
- package/dist/gateway/static/root/assets/{typed-models-lib-39MjwPSq.js → typed-models-lib-C07LGthO.js} +1 -1
- package/dist/gateway/static/root/assets/{use-save-bar-registration-5aVSjTjO.js → use-save-bar-registration-CQYE0l6z.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-BnQAWS_B.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-XU-7sBSg.js → voice-api-key-field-Boue1D46.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-CJqu8UHq.js → work-discovery-overlay-bbmvCmc8.js} +1 -1
- package/dist/gateway/static/root/assets/work-discovery-page-CAszL1y8.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DXtg8Qxl.js → workflow-run-setup-panel-DlHv-GZC.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-DxGzo3-x.js +11 -0
- package/dist/gateway/static/root/index.html +9 -9
- package/dist/package.js +1 -1
- package/dist/packages/endpoint-tools-protocol/src/index.js +184 -0
- package/dist/packages/realtime-client/src/index.js +199 -0
- package/dist/packages/realtime-protocol/src/index.js +83 -0
- package/dist/src/agent/agent-manager.d.ts +1 -0
- package/dist/src/agent/agent-manager.js +1 -0
- package/dist/src/agent/background-review/prompts.d.ts +1 -1
- package/dist/src/agent/background-review/prompts.js +3 -1
- package/dist/src/agent/background-review/run-background-review.d.ts +2 -0
- package/dist/src/agent/background-review/run-background-review.js +5 -2
- package/dist/src/agent/client-error-format.d.ts +1 -1
- package/dist/src/agent/client-error-format.js +1 -1
- package/dist/src/agent/external-tools/endpoint-provider.d.ts +17 -0
- package/dist/src/agent/external-tools/endpoint-provider.js +93 -0
- package/dist/src/agent/external-tools/gateway-tools.js +1 -1
- package/dist/src/agent/external-tools/index.d.ts +4 -5
- package/dist/src/agent/external-tools/index.js +8 -2
- package/dist/src/agent/external-tools/types.d.ts +8 -1
- package/dist/src/agent/external-tools/types.js +2 -1
- package/dist/src/agent/inbound/inbound-loop.js +4 -0
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +9 -8
- package/dist/src/agent/inbound/turn-dispatcher.js +13 -11
- package/dist/src/agent/messaging/command-handler.d.ts +2 -2
- package/dist/src/agent/messaging/command-handler.js +3 -3
- package/dist/src/agent/service/async-queue.d.ts +1 -1
- package/dist/src/agent/service/async-queue.js +1 -1
- package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -1
- package/dist/src/agent/service/direct-turn-helpers.js +1 -1
- package/dist/src/agent/service/process-direct-one-shot.d.ts +3 -1
- package/dist/src/agent/service/process-direct-one-shot.js +1 -1
- package/dist/src/agent/service/process-direct-streaming.d.ts +7 -5
- package/dist/src/agent/service/process-direct-streaming.js +5 -5
- package/dist/src/agent/service.d.ts +1 -1
- package/dist/src/agent/service.js +6 -4
- package/dist/src/agent/service.types.d.ts +2 -0
- package/dist/src/agent/session/index.d.ts +1 -1
- package/dist/src/agent/session/session-context.d.ts +2 -0
- package/dist/src/agent/session/session-context.js +4 -0
- package/dist/src/agent/session/session-state-bag.d.ts +4 -4
- package/dist/src/agent/session/session-state-bag.js +1 -1
- package/dist/src/agent/streaming/reasoning-visibility.d.ts +6 -0
- package/dist/src/agent/streaming/{reasoning-visibility-sse.js → reasoning-visibility.js} +3 -6
- package/dist/src/agent/tools/factory.d.ts +4 -0
- package/dist/src/agent/tools/factory.js +1 -0
- package/dist/src/automations/domain/types.d.ts +2 -1
- package/dist/src/automations/domain/validation.d.ts +1 -1
- package/dist/src/automations/service/action-executor.js +4 -1
- package/dist/src/channels/pairing/pairing-challenge.d.ts +1 -1
- package/dist/src/channels/pairing/pairing-challenge.js +1 -1
- package/dist/src/cli/commands/agent/stream-renderer.js +4 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/config/rules.js +0 -5
- package/dist/src/config/schema.d.ts +3 -5
- package/dist/src/config/schema.js +0 -3
- package/dist/src/config/web-patch.js +0 -1
- package/dist/src/endpoint-tools/auth.d.ts +20 -0
- package/dist/src/endpoint-tools/auth.js +51 -0
- package/dist/src/endpoint-tools/index.d.ts +5 -0
- package/dist/src/endpoint-tools/index.js +6 -0
- package/dist/src/endpoint-tools/invocation-service.d.ts +68 -0
- package/dist/src/endpoint-tools/invocation-service.js +190 -0
- package/dist/src/endpoint-tools/policy.d.ts +10 -0
- package/dist/src/endpoint-tools/policy.js +18 -0
- package/dist/src/endpoint-tools/registry.d.ts +45 -0
- package/dist/src/endpoint-tools/registry.js +121 -0
- package/dist/src/endpoint-tools/runtime.d.ts +23 -0
- package/dist/src/endpoint-tools/runtime.js +86 -0
- package/dist/src/endpoint-tools/upload-service.d.ts +41 -0
- package/dist/src/endpoint-tools/upload-service.js +103 -0
- package/dist/src/extensions/types/hooks.d.ts +1 -1
- package/dist/src/extensions/update.js +1 -1
- package/dist/src/gateway/chat-stream/protocol.d.ts +0 -1
- package/dist/src/gateway/clarify-bridge.d.ts +5 -4
- package/dist/src/gateway/clarify-bridge.js +3 -4
- package/dist/src/gateway/heartbeat/service.js +4 -1
- package/dist/src/gateway/hono/app.js +1 -5
- package/dist/src/gateway/hono/index.d.ts +0 -1
- package/dist/src/gateway/hono/index.js +1 -2
- package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -2
- package/dist/src/gateway/hono/lib/config-payload.js +0 -1
- package/dist/src/gateway/hono/middleware/auth.js +3 -5
- package/dist/src/gateway/hono/routes/agent-stream.js +49 -6
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +2 -2
- package/dist/src/gateway/hono/routes/config-patch/gateway.js +0 -19
- package/dist/src/gateway/hono/routes/deps.d.ts +0 -2
- package/dist/src/gateway/hono/routes/endpoint-tools.d.ts +3 -0
- package/dist/src/gateway/hono/routes/endpoint-tools.js +196 -0
- package/dist/src/gateway/hono/routes/index.js +4 -0
- package/dist/src/gateway/hono/routes/logs.js +0 -4
- package/dist/src/gateway/hono/routes/public-gateway.js +2 -2
- package/dist/src/gateway/hono/routes/realtime.d.ts +3 -0
- package/dist/src/gateway/hono/routes/realtime.js +35 -0
- package/dist/src/gateway/hono/routes/workflows.js +1 -1
- package/dist/src/gateway/hono/routes/you.d.ts +0 -9
- package/dist/src/gateway/hono/routes/you.js +78 -125
- package/dist/src/gateway/index.d.ts +1 -1
- package/dist/src/gateway/index.js +1 -2
- package/dist/src/gateway/protocol.d.ts +1 -7
- package/dist/src/gateway/security/index.js +1 -1
- package/dist/src/gateway/security/operator-scopes.js +1 -1
- package/dist/src/gateway/server.js +4 -4
- package/dist/src/gateway/service/agent-runner.d.ts +11 -9
- package/dist/src/gateway/service/agent-runner.js +18 -18
- package/dist/src/gateway/service/config-coordinator.d.ts +2 -2
- package/dist/src/gateway/service/run-gateway-agent.d.ts +4 -3
- package/dist/src/gateway/service/run-gateway-agent.js +13 -13
- package/dist/src/gateway/service/session-input-coordinator.d.ts +3 -0
- package/dist/src/gateway/service/session-input-coordinator.js +4 -2
- package/dist/src/gateway/service/types.d.ts +0 -5
- package/dist/src/gateway/service.d.ts +7 -6
- package/dist/src/gateway/service.js +43 -26
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/mcp/channel-bridge.d.ts +6 -9
- package/dist/src/mcp/channel-bridge.js +48 -76
- package/dist/src/mcp/channel-server.js +2 -6
- package/dist/src/realtime/broker.d.ts +30 -0
- package/dist/src/realtime/broker.js +97 -0
- package/dist/src/realtime/runtime.d.ts +20 -0
- package/dist/src/realtime/runtime.js +258 -0
- package/dist/src/realtime/tickets.d.ts +15 -0
- package/dist/src/realtime/tickets.js +38 -0
- package/dist/src/realtime/writer.d.ts +15 -0
- package/dist/src/realtime/writer.js +78 -0
- package/dist/src/share/share-config.js +0 -1
- package/dist/src/share/site-share-config.js +0 -1
- package/dist/src/storage/sqlite/endpoint-principal-repository.d.ts +17 -0
- package/dist/src/storage/sqlite/endpoint-principal-repository.js +54 -0
- package/dist/src/storage/sqlite/endpoint-tool-invocation-repository.d.ts +25 -0
- package/dist/src/storage/sqlite/endpoint-tool-invocation-repository.js +42 -0
- package/dist/src/storage/sqlite/index.d.ts +2 -0
- package/dist/src/storage/sqlite/index.js +3 -1
- package/dist/src/storage/sqlite/migrations/109_endpoint_principals.sql +14 -0
- package/dist/src/storage/sqlite/migrations/110_session_input_origin.sql +43 -0
- package/dist/src/storage/sqlite/migrations/111_endpoint_tool_invocations.sql +18 -0
- package/dist/src/storage/sqlite/migrations/112_endpoint_instance_bindings.sql +8 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/session-input-repository.d.ts +3 -0
- package/dist/src/storage/sqlite/session-input-repository.js +5 -3
- package/dist/src/tasks/home-query-service.d.ts +1 -1
- package/dist/src/tui/backends/embedded-backend.js +5 -2
- package/dist/src/tui/backends/{gateway-sse-backend.d.ts → gateway-realtime-backend.d.ts} +13 -10
- package/dist/src/tui/backends/{gateway-sse-backend.js → gateway-realtime-backend.js} +114 -151
- package/dist/src/tui/tui-agent-events.d.ts +0 -1
- package/dist/src/tui/tui-agent-events.js +2 -15
- package/dist/src/tui/tui-backend.d.ts +4 -4
- package/dist/src/tui/tui-run-state.js +0 -4
- package/dist/src/tui/tui-types.d.ts +2 -9
- package/dist/src/tui/tui-types.js +0 -1
- package/dist/src/tui/tui.js +5 -5
- package/dist/src/tunnel/gateway-lifecycle.d.ts +1 -1
- package/dist/src/tunnel/gateway-lifecycle.js +1 -1
- package/dist/src/user-context/actionableInsights.d.ts +14 -0
- package/dist/src/user-context/actionableInsights.js +34 -0
- package/dist/src/user-context/manual-understanding.js +6 -1
- package/dist/src/user-context/projection.d.ts +1 -1
- package/dist/src/user-context/understandingQuality.d.ts +5 -0
- package/dist/src/user-context/understandingQuality.js +44 -0
- package/dist/src/utils/logger/log-stream.d.ts +3 -10
- package/dist/src/utils/logger/log-stream.js +2 -73
- package/dist/src/utils/logger/pino-record.d.ts +1 -1
- package/dist/src/utils/logger/streams.js +1 -1
- package/package.json +6 -3
- package/dist/gateway/static/root/assets/agents-C6OV-gMm.js +0 -2
- package/dist/gateway/static/root/assets/apps-page-Ci14lDeO.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-Q1xmb4Rh.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-DbowrHXD.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-DoZPFdKF.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-Bt8Hnx0h.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-Bpsebsru.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-DFmdYRE5.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-Tg5kl22i.js +0 -2
- package/dist/gateway/static/root/assets/gateway-settings-9g8uIry9.js +0 -1
- package/dist/gateway/static/root/assets/home-page-Bao9jq_z.js +0 -3
- package/dist/gateway/static/root/assets/index-Cl5n1f_U.css +0 -1
- package/dist/gateway/static/root/assets/index-OJgiMh07.js +0 -223
- package/dist/gateway/static/root/assets/local-app-workbench-page-B69NvtvH.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-Cq3cABqg.js +0 -7
- package/dist/gateway/static/root/assets/messages-D02NNLCZ.js +0 -3
- package/dist/gateway/static/root/assets/notes-workbench-BOZfJFhE.js +0 -4
- package/dist/gateway/static/root/assets/product-delivery-C8JbSj5Y.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-TSKFb2tN.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-BokeBrTT.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-C56anxCX.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-C7TQADrD.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BDOPKeAX.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-BUPSIa9P.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-BRg766eW.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-DhEAviQ_.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-Ct7AV8ls.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-DoVuprZm.js +0 -2
- package/dist/gateway/static/root/assets/time-picker-BGk_Tbsj.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-B9K41qmy.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page-BBVnRHju.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-Bs_tYfst.js +0 -11
- package/dist/src/agent/streaming/reasoning-visibility-sse.d.ts +0 -15
- package/dist/src/gateway/agent-run-relay.d.ts +0 -19
- package/dist/src/gateway/agent-run-relay.js +0 -169
- package/dist/src/gateway/hono/sse.d.ts +0 -53
- package/dist/src/gateway/hono/sse.js +0 -207
- package/dist/src/gateway/service/sse-hub.d.ts +0 -10
- package/dist/src/gateway/service/sse-hub.js +0 -53
- package/dist/src/tui/sse-consumer.d.ts +0 -15
- package/dist/src/tui/sse-consumer.js +0 -73
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/endpoint-tools/policy.ts
|
|
2
|
+
var EndpointToolPolicyError = class extends Error {};
|
|
3
|
+
var EndpointToolPolicy = class {
|
|
4
|
+
validateDescriptor(kind, descriptor) {
|
|
5
|
+
if (!descriptor.name.startsWith(`${kind}.`)) throw new EndpointToolPolicyError(`Tool ${descriptor.name} does not belong to ${kind}`);
|
|
6
|
+
if (descriptor.effect !== "read") {
|
|
7
|
+
if (descriptor.confirmation !== "always") throw new EndpointToolPolicyError(`Mutating tool ${descriptor.name} must always require confirmation`);
|
|
8
|
+
if (!descriptor.requiresForeground) throw new EndpointToolPolicyError(`Mutating tool ${descriptor.name} must require foreground`);
|
|
9
|
+
if (descriptor.requiredPermissions.length === 0) throw new EndpointToolPolicyError(`Mutating tool ${descriptor.name} must declare a permission`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
evaluate(descriptor, availability) {
|
|
13
|
+
if (descriptor.requiresForeground && availability !== "foreground") throw new EndpointToolPolicyError("Endpoint is not in the foreground");
|
|
14
|
+
return { confirmationRequired: descriptor.confirmation === "always" || descriptor.effect !== "read" };
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { EndpointToolPolicy, EndpointToolPolicyError };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type EndpointAvailability, type EndpointHelloPayload, type EndpointKind, type EndpointToolDescriptor } from '@xopcai/endpoint-tools-protocol';
|
|
2
|
+
import { EndpointToolPolicy } from './policy.js';
|
|
3
|
+
export interface EndpointTransport {
|
|
4
|
+
readonly readyState: number;
|
|
5
|
+
send(data: string): void;
|
|
6
|
+
close(code?: number, reason?: string): void;
|
|
7
|
+
}
|
|
8
|
+
export interface RegisteredEndpointTool {
|
|
9
|
+
descriptor: EndpointToolDescriptor;
|
|
10
|
+
revision: string;
|
|
11
|
+
}
|
|
12
|
+
export interface EndpointConnectionSnapshot {
|
|
13
|
+
principalId: string;
|
|
14
|
+
endpointId: string;
|
|
15
|
+
connectionId: string;
|
|
16
|
+
displayName: string;
|
|
17
|
+
kind: EndpointKind;
|
|
18
|
+
platform: string;
|
|
19
|
+
appVersion: string;
|
|
20
|
+
availability: EndpointAvailability;
|
|
21
|
+
lastHeartbeatAt: number;
|
|
22
|
+
tools: RegisteredEndpointTool[];
|
|
23
|
+
}
|
|
24
|
+
export interface EndpointRegistration {
|
|
25
|
+
connection: EndpointConnectionSnapshot;
|
|
26
|
+
turnToken: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function endpointToolRevision(descriptor: EndpointToolDescriptor): string;
|
|
29
|
+
export declare class EndpointRegistry {
|
|
30
|
+
private readonly policy;
|
|
31
|
+
private readonly connectionByEndpointId;
|
|
32
|
+
constructor(policy?: EndpointToolPolicy);
|
|
33
|
+
register(hello: EndpointHelloPayload, connectionId: string, transport: EndpointTransport, now?: number): EndpointRegistration;
|
|
34
|
+
remove(endpointId: string, connectionId: string): boolean;
|
|
35
|
+
heartbeat(endpointId: string, connectionId: string, availability: EndpointAvailability, now?: number): void;
|
|
36
|
+
get(endpointId: string): EndpointConnectionSnapshot | undefined;
|
|
37
|
+
isCurrentConnection(endpointId: string, connectionId: string): boolean;
|
|
38
|
+
list(): EndpointConnectionSnapshot[];
|
|
39
|
+
getTool(endpointId: string, toolName: string): RegisteredEndpointTool | undefined;
|
|
40
|
+
verifyTurnClaim(endpointId: string, turnToken: string): boolean;
|
|
41
|
+
send(endpointId: string, type: 'tool.invoke' | 'tool.cancel', payload: unknown): void;
|
|
42
|
+
disconnect(endpointId: string, code?: number, reason?: string): boolean;
|
|
43
|
+
closeAll(code?: number, reason?: string): void;
|
|
44
|
+
private requireConnection;
|
|
45
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { canonicalJson } from "../../packages/endpoint-tools-protocol/src/index.js";
|
|
2
|
+
import { EndpointToolPolicy } from "./policy.js";
|
|
3
|
+
import crypto from "node:crypto";
|
|
4
|
+
//#region src/endpoint-tools/registry.ts
|
|
5
|
+
function endpointToolRevision(descriptor) {
|
|
6
|
+
return crypto.createHash("sha256").update(canonicalJson(descriptor)).digest("hex");
|
|
7
|
+
}
|
|
8
|
+
function snapshot(connection) {
|
|
9
|
+
return {
|
|
10
|
+
principalId: connection.principalId,
|
|
11
|
+
endpointId: connection.endpointId,
|
|
12
|
+
connectionId: connection.connectionId,
|
|
13
|
+
displayName: connection.displayName,
|
|
14
|
+
kind: connection.kind,
|
|
15
|
+
platform: connection.platform,
|
|
16
|
+
appVersion: connection.appVersion,
|
|
17
|
+
availability: connection.availability,
|
|
18
|
+
lastHeartbeatAt: connection.lastHeartbeatAt,
|
|
19
|
+
tools: [...connection.toolByName.values()]
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
var EndpointRegistry = class {
|
|
23
|
+
connectionByEndpointId = /* @__PURE__ */ new Map();
|
|
24
|
+
constructor(policy = new EndpointToolPolicy()) {
|
|
25
|
+
this.policy = policy;
|
|
26
|
+
}
|
|
27
|
+
register(hello, connectionId, transport, now = Date.now()) {
|
|
28
|
+
const toolByName = /* @__PURE__ */ new Map();
|
|
29
|
+
for (const descriptor of hello.tools) {
|
|
30
|
+
this.policy.validateDescriptor(hello.kind, descriptor);
|
|
31
|
+
if (toolByName.has(descriptor.name)) throw new Error(`Endpoint catalog contains duplicate tool: ${descriptor.name}`);
|
|
32
|
+
toolByName.set(descriptor.name, {
|
|
33
|
+
descriptor,
|
|
34
|
+
revision: endpointToolRevision(descriptor)
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const previous = this.connectionByEndpointId.get(hello.endpointId);
|
|
38
|
+
if (previous && previous.principalId !== hello.principalId) throw new Error("Endpoint instance belongs to another principal");
|
|
39
|
+
if (previous) previous.transport.close(4001, "Endpoint connected elsewhere");
|
|
40
|
+
const connection = {
|
|
41
|
+
principalId: hello.principalId,
|
|
42
|
+
endpointId: hello.endpointId,
|
|
43
|
+
connectionId,
|
|
44
|
+
displayName: hello.displayName,
|
|
45
|
+
kind: hello.kind,
|
|
46
|
+
platform: hello.platform,
|
|
47
|
+
appVersion: hello.appVersion,
|
|
48
|
+
availability: hello.availability,
|
|
49
|
+
lastHeartbeatAt: now,
|
|
50
|
+
tools: [],
|
|
51
|
+
transport,
|
|
52
|
+
turnToken: crypto.randomBytes(32).toString("base64url"),
|
|
53
|
+
toolByName
|
|
54
|
+
};
|
|
55
|
+
this.connectionByEndpointId.set(connection.endpointId, connection);
|
|
56
|
+
return {
|
|
57
|
+
connection: snapshot(connection),
|
|
58
|
+
turnToken: connection.turnToken
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
remove(endpointId, connectionId) {
|
|
62
|
+
const connection = this.connectionByEndpointId.get(endpointId);
|
|
63
|
+
if (!connection || connection.connectionId !== connectionId) return false;
|
|
64
|
+
this.connectionByEndpointId.delete(endpointId);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
heartbeat(endpointId, connectionId, availability, now = Date.now()) {
|
|
68
|
+
const connection = this.requireConnection(endpointId, connectionId);
|
|
69
|
+
connection.availability = availability;
|
|
70
|
+
connection.lastHeartbeatAt = now;
|
|
71
|
+
}
|
|
72
|
+
get(endpointId) {
|
|
73
|
+
const connection = this.connectionByEndpointId.get(endpointId);
|
|
74
|
+
return connection ? snapshot(connection) : void 0;
|
|
75
|
+
}
|
|
76
|
+
isCurrentConnection(endpointId, connectionId) {
|
|
77
|
+
return this.connectionByEndpointId.get(endpointId)?.connectionId === connectionId;
|
|
78
|
+
}
|
|
79
|
+
list() {
|
|
80
|
+
return [...this.connectionByEndpointId.values()].map(snapshot);
|
|
81
|
+
}
|
|
82
|
+
getTool(endpointId, toolName) {
|
|
83
|
+
return this.connectionByEndpointId.get(endpointId)?.toolByName.get(toolName);
|
|
84
|
+
}
|
|
85
|
+
verifyTurnClaim(endpointId, turnToken) {
|
|
86
|
+
const connection = this.connectionByEndpointId.get(endpointId);
|
|
87
|
+
if (!connection || connection.transport.readyState !== 1) return false;
|
|
88
|
+
const expected = Buffer.from(connection.turnToken);
|
|
89
|
+
const actual = Buffer.from(turnToken);
|
|
90
|
+
return expected.length === actual.length && crypto.timingSafeEqual(expected, actual);
|
|
91
|
+
}
|
|
92
|
+
send(endpointId, type, payload) {
|
|
93
|
+
const connection = this.connectionByEndpointId.get(endpointId);
|
|
94
|
+
if (!connection || connection.transport.readyState !== 1) throw new Error(`Endpoint is offline: ${endpointId}`);
|
|
95
|
+
const message = {
|
|
96
|
+
protocolVersion: 1,
|
|
97
|
+
messageId: crypto.randomUUID(),
|
|
98
|
+
type,
|
|
99
|
+
sentAt: Date.now(),
|
|
100
|
+
payload
|
|
101
|
+
};
|
|
102
|
+
connection.transport.send(JSON.stringify(message));
|
|
103
|
+
}
|
|
104
|
+
disconnect(endpointId, code = 4003, reason = "Endpoint disconnected") {
|
|
105
|
+
const connection = this.connectionByEndpointId.get(endpointId);
|
|
106
|
+
if (!connection) return false;
|
|
107
|
+
connection.transport.close(code, reason);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
closeAll(code = 1001, reason = "Gateway stopping") {
|
|
111
|
+
for (const connection of this.connectionByEndpointId.values()) connection.transport.close(code, reason);
|
|
112
|
+
this.connectionByEndpointId.clear();
|
|
113
|
+
}
|
|
114
|
+
requireConnection(endpointId, connectionId) {
|
|
115
|
+
const connection = this.connectionByEndpointId.get(endpointId);
|
|
116
|
+
if (!connection || connection.connectionId !== connectionId) throw new Error("Endpoint connection is no longer active");
|
|
117
|
+
return connection;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
//#endregion
|
|
121
|
+
export { EndpointRegistry, endpointToolRevision };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ClientEndpointMessage, type EndpointHelloPayload } from '@xopcai/endpoint-tools-protocol';
|
|
2
|
+
import { type EndpointAuthenticatorDeps } from './auth.js';
|
|
3
|
+
import { EndpointInvocationService, type EndpointInvocationAuditSink } from './invocation-service.js';
|
|
4
|
+
import { EndpointRegistry, type EndpointRegistration, type EndpointTransport } from './registry.js';
|
|
5
|
+
import { EndpointUploadService } from './upload-service.js';
|
|
6
|
+
export declare class EndpointToolRuntime {
|
|
7
|
+
readonly registry: EndpointRegistry;
|
|
8
|
+
readonly invocations: EndpointInvocationService;
|
|
9
|
+
readonly uploads: EndpointUploadService;
|
|
10
|
+
private readonly authenticator;
|
|
11
|
+
private closed;
|
|
12
|
+
constructor(options?: {
|
|
13
|
+
auth?: EndpointAuthenticatorDeps;
|
|
14
|
+
audit?: EndpointInvocationAuditSink;
|
|
15
|
+
uploadRoot?: string;
|
|
16
|
+
});
|
|
17
|
+
connect(hello: EndpointHelloPayload, connectionId: string, transport: EndpointTransport): EndpointRegistration;
|
|
18
|
+
handleMessage(endpointId: string, connectionId: string, message: ClientEndpointMessage): void;
|
|
19
|
+
touch(endpointId: string, connectionId: string): void;
|
|
20
|
+
remove(endpointId: string, connectionId: string): void;
|
|
21
|
+
disconnect(endpointId: string, reason: string): void;
|
|
22
|
+
close(): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { resolveStateDir } from "../config/paths-state.js";
|
|
2
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
3
|
+
import { init_logger } from "../utils/logger.js";
|
|
4
|
+
import { bindEndpointPrincipal, getEndpointPrincipal, touchEndpointPrincipal } from "../storage/sqlite/endpoint-principal-repository.js";
|
|
5
|
+
import { finishEndpointToolInvocationAudit, startEndpointToolInvocationAudit } from "../storage/sqlite/endpoint-tool-invocation-repository.js";
|
|
6
|
+
import "../storage/sqlite/index.js";
|
|
7
|
+
import { init_paths } from "../config/paths.js";
|
|
8
|
+
import { EndpointAuthenticator } from "./auth.js";
|
|
9
|
+
import { EndpointToolPolicy } from "./policy.js";
|
|
10
|
+
import { EndpointInvocationService } from "./invocation-service.js";
|
|
11
|
+
import { EndpointRegistry } from "./registry.js";
|
|
12
|
+
import { EndpointUploadService } from "./upload-service.js";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
//#region src/endpoint-tools/runtime.ts
|
|
15
|
+
init_paths();
|
|
16
|
+
init_logger();
|
|
17
|
+
const log = createLogger("EndpointTools");
|
|
18
|
+
const MAX_MESSAGE_CLOCK_SKEW_MS = 6e4;
|
|
19
|
+
var EndpointToolRuntime = class {
|
|
20
|
+
registry;
|
|
21
|
+
invocations;
|
|
22
|
+
uploads;
|
|
23
|
+
authenticator;
|
|
24
|
+
closed = false;
|
|
25
|
+
constructor(options = {}) {
|
|
26
|
+
const policy = new EndpointToolPolicy();
|
|
27
|
+
this.registry = new EndpointRegistry(policy);
|
|
28
|
+
this.authenticator = new EndpointAuthenticator(options.auth ?? {
|
|
29
|
+
getPrincipal: getEndpointPrincipal,
|
|
30
|
+
bindEndpoint: bindEndpointPrincipal,
|
|
31
|
+
touchPrincipal: touchEndpointPrincipal
|
|
32
|
+
});
|
|
33
|
+
this.uploads = new EndpointUploadService(options.uploadRoot ?? join(resolveStateDir(), "endpoint-tool-files"));
|
|
34
|
+
this.invocations = new EndpointInvocationService(this.registry, {
|
|
35
|
+
audit: options.audit ?? {
|
|
36
|
+
started: startEndpointToolInvocationAudit,
|
|
37
|
+
finished: finishEndpointToolInvocationAudit
|
|
38
|
+
},
|
|
39
|
+
uploads: this.uploads,
|
|
40
|
+
policy
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
connect(hello, connectionId, transport) {
|
|
44
|
+
if (this.closed) throw new Error("Endpoint runtime is closed");
|
|
45
|
+
this.authenticator.authenticate(hello);
|
|
46
|
+
const registration = this.registry.register(hello, connectionId, transport);
|
|
47
|
+
log.info({
|
|
48
|
+
endpointId: hello.endpointId,
|
|
49
|
+
connectionId,
|
|
50
|
+
kind: hello.kind
|
|
51
|
+
}, "Endpoint connected");
|
|
52
|
+
return registration;
|
|
53
|
+
}
|
|
54
|
+
handleMessage(endpointId, connectionId, message) {
|
|
55
|
+
if (!this.registry.isCurrentConnection(endpointId, connectionId)) throw new Error("Endpoint connection is no longer active");
|
|
56
|
+
if (Math.abs(Date.now() - message.sentAt) > MAX_MESSAGE_CLOCK_SKEW_MS) throw new Error("Endpoint message timestamp is outside the allowed window");
|
|
57
|
+
if (message.type === "endpoint.availability_changed") {
|
|
58
|
+
this.registry.heartbeat(endpointId, connectionId, message.payload.availability);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.invocations.handleMessage(endpointId, message);
|
|
62
|
+
}
|
|
63
|
+
touch(endpointId, connectionId) {
|
|
64
|
+
const endpoint = this.registry.get(endpointId);
|
|
65
|
+
if (endpoint?.connectionId === connectionId) this.registry.heartbeat(endpointId, connectionId, endpoint.availability);
|
|
66
|
+
}
|
|
67
|
+
remove(endpointId, connectionId) {
|
|
68
|
+
if (!this.registry.remove(endpointId, connectionId)) return;
|
|
69
|
+
this.invocations.failEndpoint(endpointId);
|
|
70
|
+
log.info({
|
|
71
|
+
endpointId,
|
|
72
|
+
connectionId
|
|
73
|
+
}, "Endpoint disconnected");
|
|
74
|
+
}
|
|
75
|
+
disconnect(endpointId, reason) {
|
|
76
|
+
this.registry.disconnect(endpointId, 4003, reason);
|
|
77
|
+
}
|
|
78
|
+
close() {
|
|
79
|
+
if (this.closed) return;
|
|
80
|
+
this.closed = true;
|
|
81
|
+
this.invocations.close();
|
|
82
|
+
this.registry.closeAll();
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
//#endregion
|
|
86
|
+
export { EndpointToolRuntime };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type EndpointToolContent } from '@xopcai/endpoint-tools-protocol';
|
|
2
|
+
export declare const ENDPOINT_UPLOAD_MAX_BYTES: number;
|
|
3
|
+
export interface EndpointUploadedFile {
|
|
4
|
+
fileId: string;
|
|
5
|
+
invocationId: string;
|
|
6
|
+
name: string;
|
|
7
|
+
mimeType: string;
|
|
8
|
+
size: number;
|
|
9
|
+
sha256: string;
|
|
10
|
+
path: string;
|
|
11
|
+
}
|
|
12
|
+
export interface EndpointUploadGrant {
|
|
13
|
+
path: string;
|
|
14
|
+
token: string;
|
|
15
|
+
maxBytes: number;
|
|
16
|
+
maxFiles: number;
|
|
17
|
+
expiresAt: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class EndpointUploadError extends Error {
|
|
20
|
+
}
|
|
21
|
+
export declare class EndpointUploadService {
|
|
22
|
+
private readonly rootDir;
|
|
23
|
+
private readonly grants;
|
|
24
|
+
private readonly files;
|
|
25
|
+
constructor(rootDir: string);
|
|
26
|
+
createGrant(invocationId: string, endpointId: string, now?: number): EndpointUploadGrant;
|
|
27
|
+
upload(params: {
|
|
28
|
+
invocationId: string;
|
|
29
|
+
endpointId: string;
|
|
30
|
+
token: string;
|
|
31
|
+
name: string;
|
|
32
|
+
mimeType: string;
|
|
33
|
+
bytes: Uint8Array;
|
|
34
|
+
now?: number;
|
|
35
|
+
}): EndpointUploadedFile;
|
|
36
|
+
validateAndClose(invocationId: string, content: EndpointToolContent[]): void;
|
|
37
|
+
abort(invocationId: string): void;
|
|
38
|
+
getFile(fileId: string): EndpointUploadedFile | undefined;
|
|
39
|
+
readFile(fileId: string): Uint8Array | undefined;
|
|
40
|
+
private deleteFile;
|
|
41
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { ENDPOINT_MAX_FILE_BYTES } from "../../packages/endpoint-tools-protocol/src/index.js";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import crypto from "node:crypto";
|
|
5
|
+
//#region src/endpoint-tools/upload-service.ts
|
|
6
|
+
const GRANT_TTL_MS = 5 * 6e4;
|
|
7
|
+
const ENDPOINT_UPLOAD_MAX_BYTES = ENDPOINT_MAX_FILE_BYTES;
|
|
8
|
+
const DEFAULT_MAX_FILES = 8;
|
|
9
|
+
var EndpointUploadError = class extends Error {};
|
|
10
|
+
var EndpointUploadService = class {
|
|
11
|
+
grants = /* @__PURE__ */ new Map();
|
|
12
|
+
files = /* @__PURE__ */ new Map();
|
|
13
|
+
constructor(rootDir) {
|
|
14
|
+
this.rootDir = rootDir;
|
|
15
|
+
mkdirSync(rootDir, {
|
|
16
|
+
recursive: true,
|
|
17
|
+
mode: 448
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
createGrant(invocationId, endpointId, now = Date.now()) {
|
|
21
|
+
const token = crypto.randomUUID();
|
|
22
|
+
const grant = {
|
|
23
|
+
invocationId,
|
|
24
|
+
endpointId,
|
|
25
|
+
token,
|
|
26
|
+
expiresAt: now + GRANT_TTL_MS,
|
|
27
|
+
maxBytes: ENDPOINT_UPLOAD_MAX_BYTES,
|
|
28
|
+
maxFiles: DEFAULT_MAX_FILES,
|
|
29
|
+
uploadedFileIds: []
|
|
30
|
+
};
|
|
31
|
+
this.grants.set(invocationId, grant);
|
|
32
|
+
return {
|
|
33
|
+
path: `/api/endpoint-tools/invocations/${encodeURIComponent(invocationId)}/files`,
|
|
34
|
+
token,
|
|
35
|
+
maxBytes: grant.maxBytes,
|
|
36
|
+
maxFiles: grant.maxFiles,
|
|
37
|
+
expiresAt: grant.expiresAt
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
upload(params) {
|
|
41
|
+
const grant = this.grants.get(params.invocationId);
|
|
42
|
+
const now = params.now ?? Date.now();
|
|
43
|
+
const expectedToken = grant ? Buffer.from(grant.token) : void 0;
|
|
44
|
+
const receivedToken = Buffer.from(params.token);
|
|
45
|
+
if (!grant || grant.endpointId !== params.endpointId || expectedToken?.byteLength !== receivedToken.byteLength || !crypto.timingSafeEqual(expectedToken, receivedToken)) throw new EndpointUploadError("Upload grant is invalid");
|
|
46
|
+
if (grant.expiresAt <= now) throw new EndpointUploadError("Upload grant expired");
|
|
47
|
+
if (grant.uploadedFileIds.length >= grant.maxFiles) throw new EndpointUploadError("Upload grant file limit exceeded");
|
|
48
|
+
if (params.bytes.byteLength > grant.maxBytes) throw new EndpointUploadError("Uploaded file is too large");
|
|
49
|
+
if (!params.name || params.name.length > 255 || !params.mimeType || params.mimeType.length > 255) throw new EndpointUploadError("Uploaded file metadata is invalid");
|
|
50
|
+
const fileId = crypto.randomUUID();
|
|
51
|
+
const path = join(this.rootDir, fileId);
|
|
52
|
+
const sha256 = crypto.createHash("sha256").update(params.bytes).digest("hex");
|
|
53
|
+
writeFileSync(path, params.bytes, {
|
|
54
|
+
flag: "wx",
|
|
55
|
+
mode: 384
|
|
56
|
+
});
|
|
57
|
+
const file = {
|
|
58
|
+
fileId,
|
|
59
|
+
invocationId: params.invocationId,
|
|
60
|
+
name: params.name,
|
|
61
|
+
mimeType: params.mimeType,
|
|
62
|
+
size: params.bytes.byteLength,
|
|
63
|
+
sha256,
|
|
64
|
+
path
|
|
65
|
+
};
|
|
66
|
+
this.files.set(fileId, file);
|
|
67
|
+
grant.uploadedFileIds.push(fileId);
|
|
68
|
+
return file;
|
|
69
|
+
}
|
|
70
|
+
validateAndClose(invocationId, content) {
|
|
71
|
+
const grant = this.grants.get(invocationId);
|
|
72
|
+
const referenced = content.filter((item) => item.type === "file");
|
|
73
|
+
for (const item of referenced) {
|
|
74
|
+
const file = this.files.get(item.fileId);
|
|
75
|
+
if (!file || file.invocationId !== invocationId || file.name !== item.name || file.mimeType !== item.mimeType || file.size !== item.size || file.sha256 !== item.sha256) throw new EndpointUploadError(`Endpoint file is not valid for invocation: ${item.fileId}`);
|
|
76
|
+
}
|
|
77
|
+
if (grant) {
|
|
78
|
+
for (const fileId of grant.uploadedFileIds) if (!referenced.some((item) => item.fileId === fileId)) this.deleteFile(fileId);
|
|
79
|
+
this.grants.delete(invocationId);
|
|
80
|
+
} else if (referenced.length > 0) throw new EndpointUploadError("Invocation did not have an upload grant");
|
|
81
|
+
}
|
|
82
|
+
abort(invocationId) {
|
|
83
|
+
const grant = this.grants.get(invocationId);
|
|
84
|
+
if (!grant) return;
|
|
85
|
+
for (const fileId of grant.uploadedFileIds) this.deleteFile(fileId);
|
|
86
|
+
this.grants.delete(invocationId);
|
|
87
|
+
}
|
|
88
|
+
getFile(fileId) {
|
|
89
|
+
return this.files.get(fileId);
|
|
90
|
+
}
|
|
91
|
+
readFile(fileId) {
|
|
92
|
+
const file = this.files.get(fileId);
|
|
93
|
+
return file ? readFileSync(file.path) : void 0;
|
|
94
|
+
}
|
|
95
|
+
deleteFile(fileId) {
|
|
96
|
+
const file = this.files.get(fileId);
|
|
97
|
+
if (!file) return;
|
|
98
|
+
rmSync(file.path, { force: true });
|
|
99
|
+
this.files.delete(fileId);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
//#endregion
|
|
103
|
+
export { ENDPOINT_UPLOAD_MAX_BYTES, EndpointUploadError, EndpointUploadService };
|
|
@@ -246,7 +246,7 @@ export interface WebchatTurnCompleteEvent extends HookContext {
|
|
|
246
246
|
inboundUserText: string;
|
|
247
247
|
/** Last assistant visible text after persistence (may be empty). */
|
|
248
248
|
assistantPlainText: string;
|
|
249
|
-
/** User aborted the
|
|
249
|
+
/** User aborted the realtime run. */
|
|
250
250
|
aborted: boolean;
|
|
251
251
|
/** Set when the direct stream threw before normal completion. */
|
|
252
252
|
streamError?: string;
|
|
@@ -4,8 +4,8 @@ import { init_paths, resolveBundledExtensionsDir, resolveExtensionsDir } from ".
|
|
|
4
4
|
import { init_loader, loadConfig } from "../config/loader.js";
|
|
5
5
|
import { downloadExtensionStoreZipBuffer, resolveExtensionZipDownloadUrl, resolveExtensionsStoreBaseUrl, verifyStoreArtifactSha256 } from "../agent/skills/marketplace/adapters/store/store-api-client.js";
|
|
6
6
|
import { getExtensionLockfileManager } from "./lockfile.js";
|
|
7
|
-
import { findExtension } from "./marketplace.js";
|
|
8
7
|
import { installExtensionFromStoreZip, installFromNpm } from "./install.js";
|
|
8
|
+
import { findExtension } from "./marketplace.js";
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
|
11
11
|
import semver from "semver";
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
export type ClarifyStreamEvent = {
|
|
2
|
+
type: string;
|
|
3
|
+
} & Record<string, unknown>;
|
|
2
4
|
/** User inactivity window before pending clarification is rejected (web/Telegram, etc.). */
|
|
3
5
|
export declare const CLARIFY_USER_RESPONSE_TIMEOUT_MS: number;
|
|
4
6
|
export interface ClarifyBridgeRequest {
|
|
@@ -8,10 +10,9 @@ export interface ClarifyBridgeRequest {
|
|
|
8
10
|
}
|
|
9
11
|
export interface StartClarifyRequestOptions {
|
|
10
12
|
sessionKey: string;
|
|
11
|
-
/** Present for in-flight webchat runs
|
|
13
|
+
/** Present for in-flight webchat runs. */
|
|
12
14
|
runId?: string;
|
|
13
|
-
|
|
14
|
-
publishSse?: (event: RelayEvent) => void;
|
|
15
|
+
publishStream?: (event: ClarifyStreamEvent) => void;
|
|
15
16
|
request: ClarifyBridgeRequest;
|
|
16
17
|
/** e.g. Telegram inline keyboard + prompt message */
|
|
17
18
|
deliver?: (ctx: {
|
|
@@ -14,7 +14,7 @@ var ClarifyBridge = class {
|
|
|
14
14
|
/** sessionKey → requestId when waiting for a free-text reply (no multiple-choice). */
|
|
15
15
|
pendingFreeTextBySession = /* @__PURE__ */ new Map();
|
|
16
16
|
startRequest(opts) {
|
|
17
|
-
const { sessionKey, runId,
|
|
17
|
+
const { sessionKey, runId, publishStream, request, deliver } = opts;
|
|
18
18
|
const requestId = crypto.randomUUID();
|
|
19
19
|
const hasChoices = Array.isArray(request.choices) && request.choices.length >= 2;
|
|
20
20
|
const needsFreeText = !hasChoices;
|
|
@@ -44,14 +44,13 @@ var ClarifyBridge = class {
|
|
|
44
44
|
default: request.default,
|
|
45
45
|
petFeedback: createPetFeedback("clarify")
|
|
46
46
|
};
|
|
47
|
-
if (runId) relay.publish(runId, payload);
|
|
48
47
|
try {
|
|
49
|
-
|
|
48
|
+
if (runId) publishStream?.(payload);
|
|
50
49
|
} catch (err) {
|
|
51
50
|
log.warn({
|
|
52
51
|
err,
|
|
53
52
|
requestId
|
|
54
|
-
}, "
|
|
53
|
+
}, "Clarify stream publication failed");
|
|
55
54
|
}
|
|
56
55
|
if (deliver) deliver({
|
|
57
56
|
sessionKey,
|
|
@@ -138,7 +138,10 @@ var HeartbeatService = class {
|
|
|
138
138
|
}
|
|
139
139
|
let reply;
|
|
140
140
|
try {
|
|
141
|
-
reply = await this.deps.agentService.turnDispatcher.processDirect(prompt, sessionKey
|
|
141
|
+
reply = await this.deps.agentService.turnDispatcher.processDirect(prompt, sessionKey, {
|
|
142
|
+
type: "system",
|
|
143
|
+
source: "heartbeat"
|
|
144
|
+
});
|
|
142
145
|
} catch (error) {
|
|
143
146
|
log.error({ err: error }, "Heartbeat: agent call failed");
|
|
144
147
|
return;
|
|
@@ -223,11 +223,7 @@ function createHonoApp(config) {
|
|
|
223
223
|
trustedProxies: service.currentConfig.gateway?.trustedProxies,
|
|
224
224
|
allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true
|
|
225
225
|
}) }),
|
|
226
|
-
channelRateLimitMiddleware
|
|
227
|
-
sseConfig: {
|
|
228
|
-
service,
|
|
229
|
-
maxSseConnections: service.currentConfig.gateway.maxSseConnections
|
|
230
|
-
}
|
|
226
|
+
channelRateLimitMiddleware
|
|
231
227
|
});
|
|
232
228
|
const prewarm = prewarmStaticUiCache();
|
|
233
229
|
if (prewarm.loaded > 0) log.debug({
|
|
@@ -209,7 +209,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
|
|
|
209
209
|
/** Masked `cfg.providers` for capability keys (image / STT / etc.). */
|
|
210
210
|
providersConfig: Record<string, import("./safe-providers-config.js").SafeProviderAuthEntry>;
|
|
211
211
|
gateway: {
|
|
212
|
-
bind: "
|
|
212
|
+
bind: "custom" | "auto" | "loopback" | "lan" | "tailnet";
|
|
213
213
|
customBindHost: string;
|
|
214
214
|
port: number;
|
|
215
215
|
corsOrigins: string[];
|
|
@@ -255,7 +255,6 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
|
|
|
255
255
|
webchat: {
|
|
256
256
|
activityDetailDefault: "stream" | "on" | "off";
|
|
257
257
|
};
|
|
258
|
-
maxSseConnections: number;
|
|
259
258
|
channelConnectDeferMode: "explicit" | "off" | "auto";
|
|
260
259
|
channelConnectDeferIds: string[];
|
|
261
260
|
channelConnectDeferSkipIds: string[];
|
|
@@ -166,7 +166,6 @@ async function buildSafeWebConfigPayload(service, options = {}) {
|
|
|
166
166
|
activeHours: config.gateway?.heartbeat?.activeHours
|
|
167
167
|
},
|
|
168
168
|
webchat: { activityDetailDefault: config.gateway?.webchat?.activityDetailDefault ?? "on" },
|
|
169
|
-
maxSseConnections: typeof config.gateway?.maxSseConnections === "number" ? config.gateway.maxSseConnections : 100,
|
|
170
169
|
channelConnectDeferMode: config.gateway?.channelConnectDeferMode ?? "auto",
|
|
171
170
|
channelConnectDeferIds: Array.isArray(config.gateway?.channelConnectDeferIds) ? config.gateway.channelConnectDeferIds : [],
|
|
172
171
|
channelConnectDeferSkipIds: Array.isArray(config.gateway?.channelConnectDeferSkipIds) ? config.gateway.channelConnectDeferSkipIds : [],
|
|
@@ -29,18 +29,16 @@ function extractTokenFromHeader(authHeader) {
|
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* SECURITY: query-string tokens leak into server logs, Referer headers, and
|
|
32
|
-
* browser history. We accept them only
|
|
33
|
-
* be set
|
|
34
|
-
*
|
|
32
|
+
* browser history. We accept them only for agent avatar `<img>` loads, where an
|
|
33
|
+
* Authorization header cannot be set. Realtime WebSocket authentication uses a
|
|
34
|
+
* one-time ticket acquired over authenticated HTTP.
|
|
35
35
|
*/
|
|
36
36
|
function extractTokenFromQuery(url) {
|
|
37
37
|
return new URL(url).searchParams.get("token");
|
|
38
38
|
}
|
|
39
|
-
const QUERY_TOKEN_ALLOWED_PATHS = new Set(["/api/events", "/api/ws"]);
|
|
40
39
|
const AGENT_AVATAR_GET_PATH = /^\/api\/agents\/[^/]+\/avatar$/;
|
|
41
40
|
/** Exported for gateway security tests. */
|
|
42
41
|
function isQueryTokenAllowedPath(path, method) {
|
|
43
|
-
if (QUERY_TOKEN_ALLOWED_PATHS.has(path) || path.startsWith("/api/events")) return true;
|
|
44
42
|
if (method === "GET" && AGENT_AVATAR_GET_PATH.test(path)) return true;
|
|
45
43
|
return false;
|
|
46
44
|
}
|