@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
|
@@ -33,6 +33,7 @@ function parseBrowserPipeline(yamlSource) {
|
|
|
33
33
|
const description = typeof doc.description === "string" ? doc.description : void 0;
|
|
34
34
|
const provider = typeof doc.provider === "string" ? doc.provider : void 0;
|
|
35
35
|
const include = Array.isArray(doc.include) ? doc.include.filter((x) => typeof x === "string") : void 0;
|
|
36
|
+
const timeoutSeconds = typeof doc.timeoutSeconds === "number" ? doc.timeoutSeconds : void 0;
|
|
36
37
|
const argsRaw = doc.args && typeof doc.args === "object" && !Array.isArray(doc.args) ? doc.args : {};
|
|
37
38
|
const args = {};
|
|
38
39
|
for (const [k, v] of Object.entries(argsRaw)) if (v && typeof v === "object" && !Array.isArray(v)) {
|
|
@@ -48,81 +49,56 @@ function parseBrowserPipeline(yamlSource) {
|
|
|
48
49
|
type: "string",
|
|
49
50
|
default: v
|
|
50
51
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
});
|
|
57
|
-
return {
|
|
58
|
-
ok: false,
|
|
59
|
-
errors
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
const pipeline = [];
|
|
63
|
-
for (let i = 0; i < pipelineRaw.length; i++) {
|
|
64
|
-
const step = pipelineRaw[i];
|
|
65
|
-
if (!step || typeof step !== "object" || Array.isArray(step)) {
|
|
66
|
-
errors.push({
|
|
67
|
-
path: `pipeline[${i}]`,
|
|
68
|
-
message: "Each step must be a YAML mapping."
|
|
52
|
+
function parseSteps(rawSteps, path, required) {
|
|
53
|
+
if (!Array.isArray(rawSteps)) {
|
|
54
|
+
if (required) errors.push({
|
|
55
|
+
path,
|
|
56
|
+
message: `\`${path}\` must be an array of steps.`
|
|
69
57
|
});
|
|
70
|
-
|
|
58
|
+
return [];
|
|
71
59
|
}
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const actionArgs = stepObj[action];
|
|
83
|
-
if (typeof actionArgs === "string") pipeline.push({
|
|
84
|
-
action,
|
|
85
|
-
args: actionArgs
|
|
86
|
-
});
|
|
87
|
-
else if (actionArgs && typeof actionArgs === "object" && !Array.isArray(actionArgs)) pipeline.push({
|
|
88
|
-
action,
|
|
89
|
-
args: actionArgs
|
|
90
|
-
});
|
|
91
|
-
else if (actionArgs === null || actionArgs === void 0) pipeline.push({
|
|
92
|
-
action,
|
|
93
|
-
args: {}
|
|
94
|
-
});
|
|
95
|
-
else pipeline.push({
|
|
96
|
-
action,
|
|
97
|
-
args: { value: actionArgs }
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
const onErrorRaw = doc.on_error;
|
|
101
|
-
let onError;
|
|
102
|
-
if (Array.isArray(onErrorRaw)) {
|
|
103
|
-
onError = [];
|
|
104
|
-
for (let i = 0; i < onErrorRaw.length; i++) {
|
|
105
|
-
const step = onErrorRaw[i];
|
|
106
|
-
if (!step || typeof step !== "object" || Array.isArray(step)) continue;
|
|
60
|
+
const pipeline = [];
|
|
61
|
+
for (let i = 0; i < rawSteps.length; i++) {
|
|
62
|
+
const step = rawSteps[i];
|
|
63
|
+
if (!step || typeof step !== "object" || Array.isArray(step)) {
|
|
64
|
+
errors.push({
|
|
65
|
+
path: `${path}[${i}]`,
|
|
66
|
+
message: "Each step must be a YAML mapping."
|
|
67
|
+
});
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
107
70
|
const stepObj = step;
|
|
108
71
|
const actionKeys = Object.keys(stepObj);
|
|
109
|
-
if (actionKeys.length !== 1)
|
|
72
|
+
if (actionKeys.length !== 1) {
|
|
73
|
+
errors.push({
|
|
74
|
+
path: `${path}[${i}]`,
|
|
75
|
+
message: `Each step must have exactly one action key, found ${actionKeys.length}: [${actionKeys.join(", ")}].`
|
|
76
|
+
});
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
110
79
|
const action = actionKeys[0];
|
|
111
80
|
const actionArgs = stepObj[action];
|
|
112
|
-
if (typeof actionArgs === "string")
|
|
81
|
+
if (typeof actionArgs === "string") pipeline.push({
|
|
113
82
|
action,
|
|
114
83
|
args: actionArgs
|
|
115
84
|
});
|
|
116
|
-
else if (actionArgs && typeof actionArgs === "object" && !Array.isArray(actionArgs))
|
|
85
|
+
else if (actionArgs && typeof actionArgs === "object" && !Array.isArray(actionArgs)) pipeline.push({
|
|
117
86
|
action,
|
|
118
87
|
args: actionArgs
|
|
119
88
|
});
|
|
120
|
-
else
|
|
89
|
+
else if (actionArgs === null || actionArgs === void 0) pipeline.push({
|
|
121
90
|
action,
|
|
122
91
|
args: {}
|
|
123
92
|
});
|
|
93
|
+
else pipeline.push({
|
|
94
|
+
action,
|
|
95
|
+
args: { value: actionArgs }
|
|
96
|
+
});
|
|
124
97
|
}
|
|
98
|
+
return pipeline;
|
|
125
99
|
}
|
|
100
|
+
const pipeline = parseSteps(doc.pipeline, "pipeline", true);
|
|
101
|
+
const onError = doc.on_error === void 0 ? void 0 : parseSteps(doc.on_error, "on_error", false);
|
|
126
102
|
if (errors.length > 0) return {
|
|
127
103
|
ok: false,
|
|
128
104
|
errors
|
|
@@ -134,6 +110,7 @@ function parseBrowserPipeline(yamlSource) {
|
|
|
134
110
|
description,
|
|
135
111
|
provider,
|
|
136
112
|
include,
|
|
113
|
+
timeoutSeconds,
|
|
137
114
|
args,
|
|
138
115
|
pipeline,
|
|
139
116
|
onError
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","names":[],"sources":["../../../../src/browser/pipeline/schema.ts"],"sourcesContent":["/**\n * Pipeline YAML schema — parse and validate brocli-style browser pipeline documents.\n */\n\nimport yaml from 'js-yaml';\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport interface PipelineArgDef {\n type: string;\n required?: boolean;\n default?: unknown;\n description?: string;\n choices?: unknown[];\n}\n\nexport interface PipelineStep {\n /** The single action name (key of the step object). */\n action: string;\n /** Action arguments (value of that key), or raw string for shorthand like `evaluate: |`. */\n args: Record<string, unknown> | string;\n}\n\nexport interface PipelineDocument {\n name: string;\n description?: string;\n provider?: string;\n include?: string[];\n args: Record<string, PipelineArgDef>;\n pipeline: PipelineStep[];\n onError?: PipelineStep[];\n}\n\nexport interface PipelineValidationError {\n path: string;\n message: string;\n}\n\nexport interface PipelineParseResult {\n ok: boolean;\n document?: PipelineDocument;\n errors: PipelineValidationError[];\n}\n\n// ─── Parse ──────────────────────────────────────────────────────────────────\n\nexport function parseBrowserPipeline(yamlSource: string): PipelineParseResult {\n const errors: PipelineValidationError[] = [];\n\n let raw: unknown;\n try {\n raw = yaml.load(yamlSource);\n } catch (e) {\n return { ok: false, errors: [{ path: '', message: `YAML parse error: ${e instanceof Error ? e.message : String(e)}` }] };\n }\n\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n return { ok: false, errors: [{ path: '', message: 'Pipeline must be a YAML mapping (object).' }] };\n }\n\n const doc = raw as Record<string, unknown>;\n\n // name\n const name = typeof doc.name === 'string' ? doc.name.trim() : '';\n if (!name) errors.push({ path: 'name', message: '`name` is required.' });\n\n // description\n const description = typeof doc.description === 'string' ? doc.description : undefined;\n\n // provider\n const provider = typeof doc.provider === 'string' ? doc.provider : undefined;\n\n // include\n const include = Array.isArray(doc.include)\n ? doc.include.filter((x): x is string => typeof x === 'string')\n : undefined;\n\n // args\n const argsRaw = (doc.args && typeof doc.args === 'object' && !Array.isArray(doc.args)) ? doc.args as Record<string, unknown> : {};\n const args: Record<string, PipelineArgDef> = {};\n for (const [k, v] of Object.entries(argsRaw)) {\n if (v && typeof v === 'object' && !Array.isArray(v)) {\n const def = v as Record<string, unknown>;\n args[k] = {\n type: typeof def.type === 'string' ? def.type : 'string',\n required: def.required === true,\n default: def.default,\n description: typeof def.description === 'string' ? def.description : undefined,\n choices: Array.isArray(def.choices) ? def.choices : undefined,\n };\n } else {\n args[k] = { type: 'string', default: v };\n }\n }\n\n
|
|
1
|
+
{"version":3,"file":"schema.js","names":[],"sources":["../../../../src/browser/pipeline/schema.ts"],"sourcesContent":["/**\n * Pipeline YAML schema — parse and validate brocli-style browser pipeline documents.\n */\n\nimport yaml from 'js-yaml';\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport interface PipelineArgDef {\n type: string;\n required?: boolean;\n default?: unknown;\n description?: string;\n choices?: unknown[];\n}\n\nexport interface PipelineStep {\n /** The single action name (key of the step object). */\n action: string;\n /** Action arguments (value of that key), or raw string for shorthand like `evaluate: |`. */\n args: Record<string, unknown> | string;\n}\n\nexport interface PipelineDocument {\n name: string;\n description?: string;\n provider?: string;\n include?: string[];\n timeoutSeconds?: number;\n args: Record<string, PipelineArgDef>;\n pipeline: PipelineStep[];\n onError?: PipelineStep[];\n}\n\nexport interface PipelineValidationError {\n path: string;\n message: string;\n}\n\nexport interface PipelineParseResult {\n ok: boolean;\n document?: PipelineDocument;\n errors: PipelineValidationError[];\n}\n\n// ─── Parse ──────────────────────────────────────────────────────────────────\n\nexport function parseBrowserPipeline(yamlSource: string): PipelineParseResult {\n const errors: PipelineValidationError[] = [];\n\n let raw: unknown;\n try {\n raw = yaml.load(yamlSource);\n } catch (e) {\n return { ok: false, errors: [{ path: '', message: `YAML parse error: ${e instanceof Error ? e.message : String(e)}` }] };\n }\n\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n return { ok: false, errors: [{ path: '', message: 'Pipeline must be a YAML mapping (object).' }] };\n }\n\n const doc = raw as Record<string, unknown>;\n\n // name\n const name = typeof doc.name === 'string' ? doc.name.trim() : '';\n if (!name) errors.push({ path: 'name', message: '`name` is required.' });\n\n // description\n const description = typeof doc.description === 'string' ? doc.description : undefined;\n\n // provider\n const provider = typeof doc.provider === 'string' ? doc.provider : undefined;\n\n // include\n const include = Array.isArray(doc.include)\n ? doc.include.filter((x): x is string => typeof x === 'string')\n : undefined;\n\n const timeoutSeconds = typeof doc.timeoutSeconds === 'number' ? doc.timeoutSeconds : undefined;\n\n // args\n const argsRaw = (doc.args && typeof doc.args === 'object' && !Array.isArray(doc.args)) ? doc.args as Record<string, unknown> : {};\n const args: Record<string, PipelineArgDef> = {};\n for (const [k, v] of Object.entries(argsRaw)) {\n if (v && typeof v === 'object' && !Array.isArray(v)) {\n const def = v as Record<string, unknown>;\n args[k] = {\n type: typeof def.type === 'string' ? def.type : 'string',\n required: def.required === true,\n default: def.default,\n description: typeof def.description === 'string' ? def.description : undefined,\n choices: Array.isArray(def.choices) ? def.choices : undefined,\n };\n } else {\n args[k] = { type: 'string', default: v };\n }\n }\n\n function parseSteps(rawSteps: unknown, path: string, required: boolean): PipelineStep[] {\n if (!Array.isArray(rawSteps)) {\n if (required) errors.push({ path, message: `\\`${path}\\` must be an array of steps.` });\n return [];\n }\n const pipeline: PipelineStep[] = [];\n for (let i = 0; i < rawSteps.length; i++) {\n const step = rawSteps[i];\n if (!step || typeof step !== 'object' || Array.isArray(step)) {\n errors.push({ path: `${path}[${i}]`, message: 'Each step must be a YAML mapping.' });\n continue;\n }\n const stepObj = step as Record<string, unknown>;\n const actionKeys = Object.keys(stepObj);\n if (actionKeys.length !== 1) {\n errors.push({ path: `${path}[${i}]`, message: `Each step must have exactly one action key, found ${actionKeys.length}: [${actionKeys.join(', ')}].` });\n continue;\n }\n const action = actionKeys[0];\n const actionArgs = stepObj[action];\n if (typeof actionArgs === 'string') {\n pipeline.push({ action, args: actionArgs });\n } else if (actionArgs && typeof actionArgs === 'object' && !Array.isArray(actionArgs)) {\n pipeline.push({ action, args: actionArgs as Record<string, unknown> });\n } else if (actionArgs === null || actionArgs === undefined) {\n pipeline.push({ action, args: {} });\n } else {\n pipeline.push({ action, args: { value: actionArgs } });\n }\n }\n return pipeline;\n }\n\n const pipeline = parseSteps(doc.pipeline, 'pipeline', true);\n const onError = doc.on_error === undefined ? undefined : parseSteps(doc.on_error, 'on_error', false);\n\n if (errors.length > 0) {\n return { ok: false, errors };\n }\n\n return {\n ok: true,\n document: { name, description, provider, include, timeoutSeconds, args, pipeline, onError },\n errors: [],\n };\n}\n"],"mappings":"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"}
|
|
@@ -4,4 +4,6 @@ export interface BrowserPipelineSource {
|
|
|
4
4
|
location: string;
|
|
5
5
|
}
|
|
6
6
|
export declare function isRemotePipelineSource(location: string): boolean;
|
|
7
|
+
export declare function fetchPipelineSource(url: string): Promise<string>;
|
|
7
8
|
export declare function loadBrowserPipelineSource(location: string): Promise<BrowserPipelineSource>;
|
|
9
|
+
export declare function resolvePipelineIncludeLocation(includePath: string, parentLocation: string | undefined): string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
2
3
|
//#region src/browser/pipeline/source.ts
|
|
3
4
|
const DEFAULT_PIPELINE_SOURCE_TIMEOUT_MS = 3e4;
|
|
4
5
|
const MAX_PIPELINE_SOURCE_BYTES = 1024 * 1024;
|
|
@@ -64,7 +65,15 @@ async function loadBrowserPipelineSource(location) {
|
|
|
64
65
|
location: normalizedLocation
|
|
65
66
|
};
|
|
66
67
|
}
|
|
68
|
+
function resolvePipelineIncludeLocation(includePath, parentLocation) {
|
|
69
|
+
const normalized = includePath.trim();
|
|
70
|
+
if (!normalized) throw new Error("Pipeline include path is empty");
|
|
71
|
+
if (isRemotePipelineSource(normalized)) return normalized;
|
|
72
|
+
if (!parentLocation) return resolve(normalized);
|
|
73
|
+
if (isRemotePipelineSource(parentLocation)) return new URL(normalized, parentLocation).toString();
|
|
74
|
+
return resolve(dirname(parentLocation), normalized);
|
|
75
|
+
}
|
|
67
76
|
//#endregion
|
|
68
|
-
export { isRemotePipelineSource, loadBrowserPipelineSource };
|
|
77
|
+
export { fetchPipelineSource, isRemotePipelineSource, loadBrowserPipelineSource, resolvePipelineIncludeLocation };
|
|
69
78
|
|
|
70
79
|
//# sourceMappingURL=source.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source.js","names":[],"sources":["../../../../src/browser/pipeline/source.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\n\nconst DEFAULT_PIPELINE_SOURCE_TIMEOUT_MS = 30_000;\nconst MAX_PIPELINE_SOURCE_BYTES = 1024 * 1024;\n\nexport interface BrowserPipelineSource {\n source: string;\n origin: 'file' | 'url';\n location: string;\n}\n\nexport function isRemotePipelineSource(location: string): boolean {\n try {\n const url = new URL(location);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nasync function readLimitedResponseText(response: Response, url: string): Promise<string> {\n const contentLength = response.headers.get('content-length');\n if (contentLength) {\n const expectedBytes = Number.parseInt(contentLength, 10);\n if (Number.isFinite(expectedBytes) && expectedBytes > MAX_PIPELINE_SOURCE_BYTES) {\n throw new Error(`Pipeline URL is too large: ${expectedBytes} bytes`);\n }\n }\n\n if (!response.body) {\n return await response.text();\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let totalBytes = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n totalBytes += value.byteLength;\n if (totalBytes > MAX_PIPELINE_SOURCE_BYTES) {\n await reader.cancel().catch(() => {});\n throw new Error(`Pipeline URL is too large: ${url}`);\n }\n chunks.push(value);\n }\n\n const payload = new Uint8Array(totalBytes);\n let offset = 0;\n for (const chunk of chunks) {\n payload.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return new TextDecoder().decode(payload);\n}\n\
|
|
1
|
+
{"version":3,"file":"source.js","names":[],"sources":["../../../../src/browser/pipeline/source.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\n\nconst DEFAULT_PIPELINE_SOURCE_TIMEOUT_MS = 30_000;\nconst MAX_PIPELINE_SOURCE_BYTES = 1024 * 1024;\n\nexport interface BrowserPipelineSource {\n source: string;\n origin: 'file' | 'url';\n location: string;\n}\n\nexport function isRemotePipelineSource(location: string): boolean {\n try {\n const url = new URL(location);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nasync function readLimitedResponseText(response: Response, url: string): Promise<string> {\n const contentLength = response.headers.get('content-length');\n if (contentLength) {\n const expectedBytes = Number.parseInt(contentLength, 10);\n if (Number.isFinite(expectedBytes) && expectedBytes > MAX_PIPELINE_SOURCE_BYTES) {\n throw new Error(`Pipeline URL is too large: ${expectedBytes} bytes`);\n }\n }\n\n if (!response.body) {\n return await response.text();\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let totalBytes = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n totalBytes += value.byteLength;\n if (totalBytes > MAX_PIPELINE_SOURCE_BYTES) {\n await reader.cancel().catch(() => {});\n throw new Error(`Pipeline URL is too large: ${url}`);\n }\n chunks.push(value);\n }\n\n const payload = new Uint8Array(totalBytes);\n let offset = 0;\n for (const chunk of chunks) {\n payload.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return new TextDecoder().decode(payload);\n}\n\nexport async function fetchPipelineSource(url: string): Promise<string> {\n const response = await fetch(url, {\n headers: {\n accept: 'application/yaml, text/yaml, text/plain, */*',\n },\n signal: AbortSignal.timeout(DEFAULT_PIPELINE_SOURCE_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n const statusText = response.statusText ? ` ${response.statusText}` : '';\n throw new Error(`Pipeline URL returned HTTP ${response.status}${statusText}`);\n }\n\n return await readLimitedResponseText(response, url);\n}\n\nexport async function loadBrowserPipelineSource(location: string): Promise<BrowserPipelineSource> {\n const normalizedLocation = location.trim();\n if (!normalizedLocation) {\n throw new Error('Pipeline path is empty');\n }\n\n if (isRemotePipelineSource(normalizedLocation)) {\n return {\n source: await fetchPipelineSource(normalizedLocation),\n origin: 'url',\n location: normalizedLocation,\n };\n }\n\n return {\n source: await readFile(normalizedLocation, 'utf-8'),\n origin: 'file',\n location: normalizedLocation,\n };\n}\n\nexport function resolvePipelineIncludeLocation(includePath: string, parentLocation: string | undefined): string {\n const normalized = includePath.trim();\n if (!normalized) {\n throw new Error('Pipeline include path is empty');\n }\n if (isRemotePipelineSource(normalized)) {\n return normalized;\n }\n if (!parentLocation) {\n return resolve(normalized);\n }\n if (isRemotePipelineSource(parentLocation)) {\n return new URL(normalized, parentLocation).toString();\n }\n return resolve(dirname(parentLocation), normalized);\n}\n"],"mappings":";;;AAGA,MAAM,qCAAqC;AAC3C,MAAM,4BAA4B,OAAO;AAQzC,SAAgB,uBAAuB,UAA2B;AAChE,KAAI;EACF,MAAM,MAAM,IAAI,IAAI,SAAS;AAC7B,SAAO,IAAI,aAAa,WAAW,IAAI,aAAa;SAC9C;AACN,SAAO;;;AAIX,eAAe,wBAAwB,UAAoB,KAA8B;CACvF,MAAM,gBAAgB,SAAS,QAAQ,IAAI,iBAAiB;AAC5D,KAAI,eAAe;EACjB,MAAM,gBAAgB,OAAO,SAAS,eAAe,GAAG;AACxD,MAAI,OAAO,SAAS,cAAc,IAAI,gBAAgB,0BACpD,OAAM,IAAI,MAAM,8BAA8B,cAAc,QAAQ;;AAIxE,KAAI,CAAC,SAAS,KACZ,QAAO,MAAM,SAAS,MAAM;CAG9B,MAAM,SAAS,SAAS,KAAK,WAAW;CACxC,MAAM,SAAuB,EAAE;CAC/B,IAAI,aAAa;AAEjB,QAAO,MAAM;EACX,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,MAAI,KACF;AAEF,MAAI,CAAC,MACH;AAEF,gBAAc,MAAM;AACpB,MAAI,aAAa,2BAA2B;AAC1C,SAAM,OAAO,QAAQ,CAAC,YAAY,GAAG;AACrC,SAAM,IAAI,MAAM,8BAA8B,MAAM;;AAEtD,SAAO,KAAK,MAAM;;CAGpB,MAAM,UAAU,IAAI,WAAW,WAAW;CAC1C,IAAI,SAAS;AACb,MAAK,MAAM,SAAS,QAAQ;AAC1B,UAAQ,IAAI,OAAO,OAAO;AAC1B,YAAU,MAAM;;AAGlB,QAAO,IAAI,aAAa,CAAC,OAAO,QAAQ;;AAG1C,eAAsB,oBAAoB,KAA8B;CACtE,MAAM,WAAW,MAAM,MAAM,KAAK;EAChC,SAAS,EACP,QAAQ,gDACT;EACD,QAAQ,YAAY,QAAQ,mCAAmC;EAChE,CAAC;AAEF,KAAI,CAAC,SAAS,IAAI;EAChB,MAAM,aAAa,SAAS,aAAa,IAAI,SAAS,eAAe;AACrE,QAAM,IAAI,MAAM,8BAA8B,SAAS,SAAS,aAAa;;AAG/E,QAAO,MAAM,wBAAwB,UAAU,IAAI;;AAGrD,eAAsB,0BAA0B,UAAkD;CAChG,MAAM,qBAAqB,SAAS,MAAM;AAC1C,KAAI,CAAC,mBACH,OAAM,IAAI,MAAM,yBAAyB;AAG3C,KAAI,uBAAuB,mBAAmB,CAC5C,QAAO;EACL,QAAQ,MAAM,oBAAoB,mBAAmB;EACrD,QAAQ;EACR,UAAU;EACX;AAGH,QAAO;EACL,QAAQ,MAAM,SAAS,oBAAoB,QAAQ;EACnD,QAAQ;EACR,UAAU;EACX;;AAGH,SAAgB,+BAA+B,aAAqB,gBAA4C;CAC9G,MAAM,aAAa,YAAY,MAAM;AACrC,KAAI,CAAC,WACH,OAAM,IAAI,MAAM,iCAAiC;AAEnD,KAAI,uBAAuB,WAAW,CACpC,QAAO;AAET,KAAI,CAAC,eACH,QAAO,QAAQ,WAAW;AAE5B,KAAI,uBAAuB,eAAe,CACxC,QAAO,IAAI,IAAI,YAAY,eAAe,CAAC,UAAU;AAEvD,QAAO,QAAQ,QAAQ,eAAe,EAAE,WAAW"}
|
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pipeline template expression engine.
|
|
3
3
|
*
|
|
4
|
-
* Supports: ${{ args.xxx }}, ${{
|
|
4
|
+
* Supports: ${{ args.xxx }}, ${{ last }}, ${{ outputs.0 }}, ${{ vars.name }},
|
|
5
|
+
* ${{ error.message }} and simple pipe filters.
|
|
5
6
|
* Does NOT execute arbitrary JavaScript — only whitelisted expressions.
|
|
6
7
|
*/
|
|
7
8
|
export interface TemplateContext {
|
|
8
9
|
args: Record<string, unknown>;
|
|
9
|
-
|
|
10
|
+
last: unknown;
|
|
11
|
+
outputs: unknown[];
|
|
12
|
+
vars: Record<string, unknown>;
|
|
10
13
|
error?: {
|
|
11
14
|
code?: string;
|
|
12
15
|
message?: string;
|
|
13
16
|
};
|
|
14
17
|
}
|
|
18
|
+
export declare function resolvePath(obj: unknown, path: string): unknown;
|
|
19
|
+
export declare function isTruthyValue(value: unknown): boolean;
|
|
20
|
+
export declare function valueContains(actual: unknown, expected: unknown): boolean;
|
|
21
|
+
export declare function evaluateRawExpression(expr: string, ctx: TemplateContext): unknown;
|
|
15
22
|
/**
|
|
16
23
|
* Resolve all `${{ ... }}` expressions in a string.
|
|
17
24
|
*/
|
|
18
25
|
export declare function resolveTemplate(template: string, ctx: TemplateContext): string;
|
|
26
|
+
export declare function resolveTemplateValue(value: string, ctx: TemplateContext): unknown;
|
|
19
27
|
/**
|
|
20
28
|
* Deep-resolve templates in an object/array/string value.
|
|
21
29
|
*/
|
|
@@ -2,16 +2,24 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Pipeline template expression engine.
|
|
4
4
|
*
|
|
5
|
-
* Supports: ${{ args.xxx }}, ${{
|
|
5
|
+
* Supports: ${{ args.xxx }}, ${{ last }}, ${{ outputs.0 }}, ${{ vars.name }},
|
|
6
|
+
* ${{ error.message }} and simple pipe filters.
|
|
6
7
|
* Does NOT execute arbitrary JavaScript — only whitelisted expressions.
|
|
7
8
|
*/
|
|
8
9
|
const TEMPLATE_RE = /\$\{\{\s*(.+?)\s*\}\}/g;
|
|
10
|
+
function parsePath(path) {
|
|
11
|
+
return path.replace(/\[(\d+)\]/g, ".$1").split(".").map((part) => part.trim()).filter(Boolean);
|
|
12
|
+
}
|
|
9
13
|
function resolvePath(obj, path) {
|
|
10
|
-
const parts = path
|
|
14
|
+
const parts = parsePath(path);
|
|
11
15
|
let current = obj;
|
|
12
16
|
for (const part of parts) {
|
|
13
17
|
if (current === null || current === void 0) return void 0;
|
|
14
|
-
if (
|
|
18
|
+
if (Array.isArray(current)) {
|
|
19
|
+
const index = Number(part);
|
|
20
|
+
if (!Number.isInteger(index)) return void 0;
|
|
21
|
+
current = current[index];
|
|
22
|
+
} else if (typeof current === "object") current = current[part];
|
|
15
23
|
else return;
|
|
16
24
|
}
|
|
17
25
|
return current;
|
|
@@ -22,10 +30,24 @@ function applyFilter(value, filter) {
|
|
|
22
30
|
case "string": return String(value ?? "");
|
|
23
31
|
case "number": return String(Number(value));
|
|
24
32
|
case "boolean": return String(Boolean(value));
|
|
33
|
+
case "urlencode": return encodeURIComponent(String(value ?? ""));
|
|
25
34
|
default: return String(value ?? "");
|
|
26
35
|
}
|
|
27
36
|
}
|
|
28
|
-
function
|
|
37
|
+
function isTruthyValue(value) {
|
|
38
|
+
if (value === null || value === void 0 || value === false) return false;
|
|
39
|
+
if (typeof value === "number") return Number.isFinite(value) && value !== 0;
|
|
40
|
+
if (typeof value === "string") return value.length > 0 && value !== "false" && value !== "0";
|
|
41
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
function valueContains(actual, expected) {
|
|
45
|
+
if (typeof actual === "string") return actual.includes(String(expected));
|
|
46
|
+
if (Array.isArray(actual)) return actual.some((item) => JSON.stringify(item) === JSON.stringify(expected));
|
|
47
|
+
if (actual && typeof actual === "object") return JSON.stringify(actual).includes(String(expected));
|
|
48
|
+
return String(actual ?? "").includes(String(expected));
|
|
49
|
+
}
|
|
50
|
+
function evaluateRawExpression(expr, ctx) {
|
|
29
51
|
const pipeIdx = expr.indexOf("|");
|
|
30
52
|
let path = expr;
|
|
31
53
|
let filter;
|
|
@@ -34,17 +56,31 @@ function evaluateExpression(expr, ctx) {
|
|
|
34
56
|
filter = expr.slice(pipeIdx + 1).trim();
|
|
35
57
|
}
|
|
36
58
|
let value;
|
|
37
|
-
if (path === "
|
|
59
|
+
if (path === "last") value = ctx.last;
|
|
60
|
+
else if (path.startsWith("last.")) value = resolvePath(ctx.last, path.slice(5));
|
|
38
61
|
else if (path.startsWith("args.")) value = resolvePath(ctx.args, path.slice(5));
|
|
62
|
+
else if (path === "outputs") value = ctx.outputs;
|
|
63
|
+
else if (path.startsWith("outputs.")) value = resolvePath(ctx.outputs, path.slice(8));
|
|
64
|
+
else if (path === "vars") value = ctx.vars;
|
|
65
|
+
else if (path.startsWith("vars.")) value = resolvePath(ctx.vars, path.slice(5));
|
|
39
66
|
else if (path.startsWith("error.")) value = resolvePath(ctx.error, path.slice(6));
|
|
40
67
|
else if (path === "error") value = ctx.error?.message ?? "";
|
|
41
|
-
else
|
|
68
|
+
else {
|
|
69
|
+
value = resolvePath(ctx.args, path);
|
|
70
|
+
if (value === void 0) return `\${{ ${expr} }}`;
|
|
71
|
+
}
|
|
42
72
|
if (filter) return applyFilter(value, filter);
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
function stringifyTemplateValue(value) {
|
|
43
76
|
if (value === void 0 || value === null) return "";
|
|
44
77
|
if (typeof value === "string") return value;
|
|
45
78
|
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
46
79
|
return JSON.stringify(value);
|
|
47
80
|
}
|
|
81
|
+
function evaluateExpression(expr, ctx) {
|
|
82
|
+
return stringifyTemplateValue(evaluateRawExpression(expr, ctx));
|
|
83
|
+
}
|
|
48
84
|
/**
|
|
49
85
|
* Resolve all `${{ ... }}` expressions in a string.
|
|
50
86
|
*/
|
|
@@ -53,11 +89,17 @@ function resolveTemplate(template, ctx) {
|
|
|
53
89
|
return evaluateExpression(expr.trim(), ctx);
|
|
54
90
|
});
|
|
55
91
|
}
|
|
92
|
+
function resolveTemplateValue(value, ctx) {
|
|
93
|
+
const trimmed = value.trim();
|
|
94
|
+
const match = /^\$\{\{\s*(.+?)\s*\}\}$/.exec(trimmed);
|
|
95
|
+
if (!match) return resolveTemplate(value, ctx);
|
|
96
|
+
return evaluateRawExpression(match[1].trim(), ctx);
|
|
97
|
+
}
|
|
56
98
|
/**
|
|
57
99
|
* Deep-resolve templates in an object/array/string value.
|
|
58
100
|
*/
|
|
59
101
|
function resolveTemplateDeep(value, ctx) {
|
|
60
|
-
if (typeof value === "string") return
|
|
102
|
+
if (typeof value === "string") return resolveTemplateValue(value, ctx);
|
|
61
103
|
if (Array.isArray(value)) return value.map((item) => resolveTemplateDeep(item, ctx));
|
|
62
104
|
if (value && typeof value === "object") {
|
|
63
105
|
const result = {};
|
|
@@ -67,6 +109,6 @@ function resolveTemplateDeep(value, ctx) {
|
|
|
67
109
|
return value;
|
|
68
110
|
}
|
|
69
111
|
//#endregion
|
|
70
|
-
export { resolveTemplate, resolveTemplateDeep };
|
|
112
|
+
export { evaluateRawExpression, isTruthyValue, resolvePath, resolveTemplate, resolveTemplateDeep, resolveTemplateValue, valueContains };
|
|
71
113
|
|
|
72
114
|
//# sourceMappingURL=template.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.js","names":[],"sources":["../../../../src/browser/pipeline/template.ts"],"sourcesContent":["/**\n * Pipeline template expression engine.\n *\n * Supports: ${{ args.xxx }}, ${{
|
|
1
|
+
{"version":3,"file":"template.js","names":[],"sources":["../../../../src/browser/pipeline/template.ts"],"sourcesContent":["/**\n * Pipeline template expression engine.\n *\n * Supports: ${{ args.xxx }}, ${{ last }}, ${{ outputs.0 }}, ${{ vars.name }},\n * ${{ error.message }} and simple pipe filters.\n * Does NOT execute arbitrary JavaScript — only whitelisted expressions.\n */\n\nconst TEMPLATE_RE = /\\$\\{\\{\\s*(.+?)\\s*\\}\\}/g;\n\nexport interface TemplateContext {\n args: Record<string, unknown>;\n last: unknown;\n outputs: unknown[];\n vars: Record<string, unknown>;\n error?: { code?: string; message?: string };\n}\n\nfunction parsePath(path: string): string[] {\n return path\n .replace(/\\[(\\d+)\\]/g, '.$1')\n .split('.')\n .map((part) => part.trim())\n .filter(Boolean);\n}\n\nexport function resolvePath(obj: unknown, path: string): unknown {\n const parts = parsePath(path);\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n if (Array.isArray(current)) {\n const index = Number(part);\n if (!Number.isInteger(index)) return undefined;\n current = current[index];\n } else if (typeof current === 'object') {\n current = (current as Record<string, unknown>)[part];\n } else {\n return undefined;\n }\n }\n return current;\n}\n\nfunction applyFilter(value: unknown, filter: string): string {\n switch (filter.trim()) {\n case 'json':\n return JSON.stringify(value, null, 2) ?? 'null';\n case 'string':\n return String(value ?? '');\n case 'number':\n return String(Number(value));\n case 'boolean':\n return String(Boolean(value));\n case 'urlencode':\n return encodeURIComponent(String(value ?? ''));\n default:\n return String(value ?? '');\n }\n}\n\nexport function isTruthyValue(value: unknown): boolean {\n if (value === null || value === undefined || value === false) return false;\n if (typeof value === 'number') return Number.isFinite(value) && value !== 0;\n if (typeof value === 'string') return value.length > 0 && value !== 'false' && value !== '0';\n if (Array.isArray(value)) return value.length > 0;\n return true;\n}\n\nexport function valueContains(actual: unknown, expected: unknown): boolean {\n if (typeof actual === 'string') return actual.includes(String(expected));\n if (Array.isArray(actual)) return actual.some((item) => JSON.stringify(item) === JSON.stringify(expected));\n if (actual && typeof actual === 'object') return JSON.stringify(actual).includes(String(expected));\n return String(actual ?? '').includes(String(expected));\n}\n\nexport function evaluateRawExpression(expr: string, ctx: TemplateContext): unknown {\n // Check for pipe filter: `last | json`\n const pipeIdx = expr.indexOf('|');\n let path = expr;\n let filter: string | undefined;\n if (pipeIdx > 0) {\n path = expr.slice(0, pipeIdx).trim();\n filter = expr.slice(pipeIdx + 1).trim();\n }\n\n let value: unknown;\n\n if (path === 'last') {\n value = ctx.last;\n } else if (path.startsWith('last.')) {\n value = resolvePath(ctx.last, path.slice(5));\n } else if (path.startsWith('args.')) {\n value = resolvePath(ctx.args, path.slice(5));\n } else if (path === 'outputs') {\n value = ctx.outputs;\n } else if (path.startsWith('outputs.')) {\n value = resolvePath(ctx.outputs, path.slice(8));\n } else if (path === 'vars') {\n value = ctx.vars;\n } else if (path.startsWith('vars.')) {\n value = resolvePath(ctx.vars, path.slice(5));\n } else if (path.startsWith('error.')) {\n value = resolvePath(ctx.error, path.slice(6));\n } else if (path === 'error') {\n value = ctx.error?.message ?? '';\n } else {\n value = resolvePath(ctx.args, path);\n if (value === undefined) return `\\${{ ${expr} }}`;\n }\n\n if (filter) {\n return applyFilter(value, filter);\n }\n\n return value;\n}\n\nfunction stringifyTemplateValue(value: unknown): string {\n if (value === undefined || value === null) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n return JSON.stringify(value);\n}\n\nfunction evaluateExpression(expr: string, ctx: TemplateContext): string {\n return stringifyTemplateValue(evaluateRawExpression(expr, ctx));\n}\n\n/**\n * Resolve all `${{ ... }}` expressions in a string.\n */\nexport function resolveTemplate(template: string, ctx: TemplateContext): string {\n return template.replace(TEMPLATE_RE, (_match, expr: string) => {\n return evaluateExpression(expr.trim(), ctx);\n });\n}\n\nexport function resolveTemplateValue(value: string, ctx: TemplateContext): unknown {\n const trimmed = value.trim();\n const match = /^\\$\\{\\{\\s*(.+?)\\s*\\}\\}$/.exec(trimmed);\n if (!match) return resolveTemplate(value, ctx);\n return evaluateRawExpression(match[1].trim(), ctx);\n}\n\n/**\n * Deep-resolve templates in an object/array/string value.\n */\nexport function resolveTemplateDeep(value: unknown, ctx: TemplateContext): unknown {\n if (typeof value === 'string') {\n return resolveTemplateValue(value, ctx);\n }\n if (Array.isArray(value)) {\n return value.map((item) => resolveTemplateDeep(item, ctx));\n }\n if (value && typeof value === 'object') {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n result[resolveTemplate(k, ctx)] = resolveTemplateDeep(v, ctx);\n }\n return result;\n }\n return value;\n}\n"],"mappings":";;;;;;;;AAQA,MAAM,cAAc;AAUpB,SAAS,UAAU,MAAwB;AACzC,QAAO,KACJ,QAAQ,cAAc,MAAM,CAC5B,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ;;AAGpB,SAAgB,YAAY,KAAc,MAAuB;CAC/D,MAAM,QAAQ,UAAU,KAAK;CAC7B,IAAI,UAAmB;AACvB,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,YAAY,QAAQ,YAAY,KAAA,EAAW,QAAO,KAAA;AACtD,MAAI,MAAM,QAAQ,QAAQ,EAAE;GAC1B,MAAM,QAAQ,OAAO,KAAK;AAC1B,OAAI,CAAC,OAAO,UAAU,MAAM,CAAE,QAAO,KAAA;AACrC,aAAU,QAAQ;aACT,OAAO,YAAY,SAC5B,WAAW,QAAoC;MAE/C;;AAGJ,QAAO;;AAGT,SAAS,YAAY,OAAgB,QAAwB;AAC3D,SAAQ,OAAO,MAAM,EAArB;EACE,KAAK,OACH,QAAO,KAAK,UAAU,OAAO,MAAM,EAAE,IAAI;EAC3C,KAAK,SACH,QAAO,OAAO,SAAS,GAAG;EAC5B,KAAK,SACH,QAAO,OAAO,OAAO,MAAM,CAAC;EAC9B,KAAK,UACH,QAAO,OAAO,QAAQ,MAAM,CAAC;EAC/B,KAAK,YACH,QAAO,mBAAmB,OAAO,SAAS,GAAG,CAAC;EAChD,QACE,QAAO,OAAO,SAAS,GAAG;;;AAIhC,SAAgB,cAAc,OAAyB;AACrD,KAAI,UAAU,QAAQ,UAAU,KAAA,KAAa,UAAU,MAAO,QAAO;AACrE,KAAI,OAAO,UAAU,SAAU,QAAO,OAAO,SAAS,MAAM,IAAI,UAAU;AAC1E,KAAI,OAAO,UAAU,SAAU,QAAO,MAAM,SAAS,KAAK,UAAU,WAAW,UAAU;AACzF,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,MAAM,SAAS;AAChD,QAAO;;AAGT,SAAgB,cAAc,QAAiB,UAA4B;AACzE,KAAI,OAAO,WAAW,SAAU,QAAO,OAAO,SAAS,OAAO,SAAS,CAAC;AACxE,KAAI,MAAM,QAAQ,OAAO,CAAE,QAAO,OAAO,MAAM,SAAS,KAAK,UAAU,KAAK,KAAK,KAAK,UAAU,SAAS,CAAC;AAC1G,KAAI,UAAU,OAAO,WAAW,SAAU,QAAO,KAAK,UAAU,OAAO,CAAC,SAAS,OAAO,SAAS,CAAC;AAClG,QAAO,OAAO,UAAU,GAAG,CAAC,SAAS,OAAO,SAAS,CAAC;;AAGxD,SAAgB,sBAAsB,MAAc,KAA+B;CAEjF,MAAM,UAAU,KAAK,QAAQ,IAAI;CACjC,IAAI,OAAO;CACX,IAAI;AACJ,KAAI,UAAU,GAAG;AACf,SAAO,KAAK,MAAM,GAAG,QAAQ,CAAC,MAAM;AACpC,WAAS,KAAK,MAAM,UAAU,EAAE,CAAC,MAAM;;CAGzC,IAAI;AAEJ,KAAI,SAAS,OACX,SAAQ,IAAI;UACH,KAAK,WAAW,QAAQ,CACjC,SAAQ,YAAY,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;UACnC,KAAK,WAAW,QAAQ,CACjC,SAAQ,YAAY,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;UACnC,SAAS,UAClB,SAAQ,IAAI;UACH,KAAK,WAAW,WAAW,CACpC,SAAQ,YAAY,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;UACtC,SAAS,OAClB,SAAQ,IAAI;UACH,KAAK,WAAW,QAAQ,CACjC,SAAQ,YAAY,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;UACnC,KAAK,WAAW,SAAS,CAClC,SAAQ,YAAY,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;UACpC,SAAS,QAClB,SAAQ,IAAI,OAAO,WAAW;MACzB;AACL,UAAQ,YAAY,IAAI,MAAM,KAAK;AACnC,MAAI,UAAU,KAAA,EAAW,QAAO,QAAQ,KAAK;;AAG/C,KAAI,OACF,QAAO,YAAY,OAAO,OAAO;AAGnC,QAAO;;AAGT,SAAS,uBAAuB,OAAwB;AACtD,KAAI,UAAU,KAAA,KAAa,UAAU,KAAM,QAAO;AAClD,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,KAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO,OAAO,MAAM;AACjF,QAAO,KAAK,UAAU,MAAM;;AAG9B,SAAS,mBAAmB,MAAc,KAA8B;AACtE,QAAO,uBAAuB,sBAAsB,MAAM,IAAI,CAAC;;;;;AAMjE,SAAgB,gBAAgB,UAAkB,KAA8B;AAC9E,QAAO,SAAS,QAAQ,cAAc,QAAQ,SAAiB;AAC7D,SAAO,mBAAmB,KAAK,MAAM,EAAE,IAAI;GAC3C;;AAGJ,SAAgB,qBAAqB,OAAe,KAA+B;CACjF,MAAM,UAAU,MAAM,MAAM;CAC5B,MAAM,QAAQ,0BAA0B,KAAK,QAAQ;AACrD,KAAI,CAAC,MAAO,QAAO,gBAAgB,OAAO,IAAI;AAC9C,QAAO,sBAAsB,MAAM,GAAG,MAAM,EAAE,IAAI;;;;;AAMpD,SAAgB,oBAAoB,OAAgB,KAA+B;AACjF,KAAI,OAAO,UAAU,SACnB,QAAO,qBAAqB,OAAO,IAAI;AAEzC,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,MAAM,KAAK,SAAS,oBAAoB,MAAM,IAAI,CAAC;AAE5D,KAAI,SAAS,OAAO,UAAU,UAAU;EACtC,MAAM,SAAkC,EAAE;AAC1C,OAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,MAAM,CACxC,QAAO,gBAAgB,GAAG,IAAI,IAAI,oBAAoB,GAAG,IAAI;AAE/D,SAAO;;AAET,QAAO"}
|
|
@@ -3,7 +3,6 @@ import { createLogger } from "../../utils/logger/index.js";
|
|
|
3
3
|
import { init_logger } from "../../utils/logger.js";
|
|
4
4
|
import { ConfigSchema, init_schema } from "../../config/schema.js";
|
|
5
5
|
import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
|
|
6
|
-
import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
|
|
7
6
|
import { commandRegistry } from "../registry.js";
|
|
8
7
|
import { parseConfigValue } from "../config-value.js";
|
|
9
8
|
import { getConfigValueAtPath, parseConfigPath, setConfigValueAtPath, unsetConfigValueAtPath } from "../config-paths.js";
|
|
@@ -13,7 +12,6 @@ init_schema();
|
|
|
13
12
|
init_loader();
|
|
14
13
|
init_paths();
|
|
15
14
|
init_logger();
|
|
16
|
-
init_session_key();
|
|
17
15
|
const log = createLogger("ConfigCommand");
|
|
18
16
|
const BLOCKED_WRITE_PATHS = new Set(["gateway.auth.token", "providers"]);
|
|
19
17
|
function isBlockedPath(path) {
|
|
@@ -29,13 +27,13 @@ function redactConfigForDisplay(plain) {
|
|
|
29
27
|
if (plain.providers !== void 0) plain.providers = "[redacted]";
|
|
30
28
|
}
|
|
31
29
|
function senderMayWritePersistentConfig(ctx) {
|
|
32
|
-
const { source, senderId, isGroup
|
|
30
|
+
const { source, senderId, isGroup } = ctx;
|
|
33
31
|
if (source !== "telegram" && source !== "weixin") return true;
|
|
34
32
|
const cfg = ctx.getConfig?.() ?? ctx.config;
|
|
35
33
|
if (source === "weixin") {
|
|
36
34
|
const wx = cfg.channels?.weixin;
|
|
37
35
|
if (!wx?.enabled) return false;
|
|
38
|
-
const accountId =
|
|
36
|
+
const accountId = ctx.accountId ?? "default";
|
|
39
37
|
let allowFrom = [];
|
|
40
38
|
if (wx.accounts && Object.keys(wx.accounts).length > 0) {
|
|
41
39
|
const acc = wx.accounts[accountId] ?? wx.accounts["default"];
|
|
@@ -50,7 +48,7 @@ function senderMayWritePersistentConfig(ctx) {
|
|
|
50
48
|
}
|
|
51
49
|
const tg = cfg.channels?.telegram;
|
|
52
50
|
if (!tg?.enabled) return false;
|
|
53
|
-
const accountId =
|
|
51
|
+
const accountId = ctx.accountId ?? "default";
|
|
54
52
|
const acc = tg.accounts?.[accountId] ?? tg.accounts?.["default"];
|
|
55
53
|
if (!acc || acc.enabled === false) return false;
|
|
56
54
|
const allowFrom = [...acc.allowFrom ?? []];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"sources":["../../../../src/chat-commands/builtins/config.ts"],"sourcesContent":["/**\n * /config — read and write persistent config (~/.xopc/xopc.json) from chat.\n */\n\nimport type { CommandDefinition, CommandContext } from '../types.js';\nimport { commandRegistry } from '../registry.js';\nimport { parseConfigValue } from '../config-value.js';\nimport {\n parseConfigPath,\n getConfigValueAtPath,\n setConfigValueAtPath,\n unsetConfigValueAtPath,\n} from '../config-paths.js';\nimport { ConfigSchema, type TelegramConfig, type WeixinConfig } from '../../config/schema.js';\nimport { loadConfig, saveConfig } from '../../config/loader.js';\nimport { resolveConfigPath } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { parseSessionKey } from '../../routing/session-key.js';\nimport { resolveAllowlistMatchSimple } from '../../channels/security.js';\n\nconst log = createLogger('ConfigCommand');\n\nconst BLOCKED_WRITE_PATHS = new Set(['gateway.auth.token', 'providers']);\n\nfunction isBlockedPath(path: string[]): boolean {\n const joined = path.join('.');\n for (const blocked of BLOCKED_WRITE_PATHS) {\n if (joined === blocked || joined.startsWith(`${blocked}.`)) return true;\n }\n return false;\n}\n\nfunction redactConfigForDisplay(plain: Record<string, unknown>): void {\n if (plain.gateway && typeof plain.gateway === 'object') {\n const gw = plain.gateway as Record<string, unknown>;\n if (gw.auth && typeof gw.auth === 'object') {\n (gw.auth as Record<string, unknown>).token = '[redacted]';\n }\n }\n if (plain.providers !== undefined) plain.providers = '[redacted]';\n}\n\nfunction senderMayWritePersistentConfig(ctx: CommandContext): boolean {\n const { source, senderId, isGroup, sessionKey } = ctx;\n if (source !== 'telegram' && source !== 'weixin') {\n return true;\n }\n\n const cfg = ctx.getConfig?.() ?? ctx.config;\n\n if (source === 'weixin') {\n const wx = cfg.channels?.weixin as WeixinConfig | undefined;\n if (!wx?.enabled) return false;\n const parsed = parseSessionKey(sessionKey);\n const accountId = parsed?.accountId ?? 'default';\n let allowFrom: Array<string | number> = [];\n if (wx.accounts && Object.keys(wx.accounts).length > 0) {\n const acc = wx.accounts[accountId] ?? wx.accounts['default'];\n if (!acc || acc.enabled === false) return false;\n allowFrom = [...(acc.allowFrom ?? [])];\n } else {\n allowFrom = [...(wx.allowFrom ?? [])];\n }\n if (allowFrom.length === 0) return false;\n return resolveAllowlistMatchSimple({ allowFrom, senderId }).allowed;\n }\n\n const tg = cfg.channels?.telegram as TelegramConfig | undefined;\n if (!tg?.enabled) return false;\n const parsed = parseSessionKey(sessionKey);\n const accountId = parsed?.accountId ?? 'default';\n const acc = tg.accounts?.[accountId] ?? tg.accounts?.['default'];\n if (!acc || acc.enabled === false) return false;\n const allowFrom = [...(acc.allowFrom ?? [])];\n const groupAllowFrom = [...(acc.groupAllowFrom ?? [])];\n const list = isGroup && groupAllowFrom.length > 0 ? groupAllowFrom : allowFrom;\n if (list.length === 0) return false;\n return resolveAllowlistMatchSimple({ allowFrom: list, senderId }).allowed;\n}\n\nconst configCommand: CommandDefinition = {\n id: 'system.config',\n name: 'config',\n aliases: ['cfg'],\n description:\n 'Show or update configuration. Usage: /config show [path] | /config set path=value | /config unset path',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: [\n '/config show',\n '/config show agents.defaults.models.chat',\n '/config set agents.defaults.models.chat.primary=anthropic/claude-opus-4-5',\n '/config set agents.defaults.temperature=0.5',\n '/config unset tts',\n ],\n handler: async (ctx: CommandContext, args: string) => {\n const parts = args.trim().split(/\\s+/);\n const action = parts[0]?.toLowerCase();\n const rest = parts.slice(1).join(' ').trim();\n\n if (!action || action === 'show' || action === 'get') {\n const config = ctx.getConfig?.() ?? loadConfig(resolveConfigPath());\n const plain = JSON.parse(JSON.stringify(config)) as Record<string, unknown>;\n redactConfigForDisplay(plain);\n\n if (rest) {\n const parsed = parseConfigPath(rest);\n if (!parsed.ok || !parsed.path) {\n return { content: `⚠️ ${parsed.error ?? 'Invalid path.'}`, success: false };\n }\n const value = getConfigValueAtPath(plain, parsed.path);\n const rendered = JSON.stringify(value ?? null, null, 2);\n return { content: `⚙️ \\`${rest}\\`:\\n\\`\\`\\`json\\n${rendered}\\n\\`\\`\\`` };\n }\n\n const json = JSON.stringify(plain, null, 2);\n return { content: `⚙️ Current config:\\n\\`\\`\\`json\\n${json}\\n\\`\\`\\`` };\n }\n\n if (action === 'set') {\n if (!senderMayWritePersistentConfig(ctx)) {\n return {\n content: '⚠️ You are not allowed to change config from this chat surface.',\n success: false,\n };\n }\n const eqIndex = rest.indexOf('=');\n if (eqIndex <= 0) {\n return { content: '⚠️ Usage: /config set path=value', success: false };\n }\n const pathRaw = rest.slice(0, eqIndex).trim();\n const valueRaw = rest.slice(eqIndex + 1);\n\n const parsedPath = parseConfigPath(pathRaw);\n if (!parsedPath.ok || !parsedPath.path) {\n return { content: `⚠️ ${parsedPath.error}`, success: false };\n }\n if (isBlockedPath(parsedPath.path)) {\n return {\n content: `⚠️ Path \\`${pathRaw}\\` cannot be modified via chat for security reasons.`,\n success: false,\n };\n }\n\n const parsedValue = parseConfigValue(valueRaw);\n if (parsedValue.ok === false) {\n return { content: `⚠️ ${parsedValue.error}`, success: false };\n }\n\n const configPath = resolveConfigPath();\n const currentConfig = loadConfig(configPath) as Record<string, unknown>;\n setConfigValueAtPath(currentConfig, parsedPath.path, parsedValue.value);\n\n const validated = ConfigSchema.safeParse(currentConfig);\n if (!validated.success) {\n const firstIssue = validated.error.issues[0];\n const fieldPath = firstIssue.path.join('.');\n return {\n content: `⚠️ Config invalid after set (${fieldPath}: ${firstIssue.message}). Change not saved.`,\n success: false,\n };\n }\n\n await saveConfig(validated.data);\n log.info({ path: pathRaw, value: parsedValue.value }, 'Config updated via /config set');\n\n const valueLabel =\n typeof parsedValue.value === 'string'\n ? `\"${parsedValue.value}\"`\n : JSON.stringify(parsedValue.value);\n return { content: `⚙️ Config updated: \\`${pathRaw}\\` = ${valueLabel}` };\n }\n\n if (action === 'unset') {\n if (!senderMayWritePersistentConfig(ctx)) {\n return {\n content: '⚠️ You are not allowed to change config from this chat surface.',\n success: false,\n };\n }\n if (!rest) {\n return { content: '⚠️ Usage: /config unset path', success: false };\n }\n const parsedPath = parseConfigPath(rest);\n if (!parsedPath.ok || !parsedPath.path) {\n return { content: `⚠️ ${parsedPath.error}`, success: false };\n }\n if (isBlockedPath(parsedPath.path)) {\n return {\n content: `⚠️ Path \\`${rest}\\` cannot be modified via chat for security reasons.`,\n success: false,\n };\n }\n\n const configPath = resolveConfigPath();\n const currentConfig = loadConfig(configPath) as Record<string, unknown>;\n const removed = unsetConfigValueAtPath(currentConfig, parsedPath.path);\n if (!removed) {\n return { content: `⚙️ No config value found at \\`${rest}\\`.`, success: false };\n }\n\n const validated = ConfigSchema.safeParse(currentConfig);\n if (!validated.success) {\n const firstIssue = validated.error.issues[0];\n const fieldPath = firstIssue.path.join('.');\n return {\n content: `⚠️ Config invalid after unset (${fieldPath}: ${firstIssue.message}). Change not saved.`,\n success: false,\n };\n }\n\n await saveConfig(validated.data);\n log.info({ path: rest }, 'Config key removed via /config unset');\n return { content: `⚙️ Config updated: \\`${rest}\\` removed.` };\n }\n\n return {\n content:\n '⚙️ *Config Command*\\n\\n' +\n '`/config show [path]` — view config (or a specific path)\\n' +\n '`/config set path=value` — update a config value\\n' +\n '`/config unset path` — remove a config key\\n\\n' +\n 'Examples:\\n' +\n '`/config show agents.defaults.models.chat`\\n' +\n '`/config set agents.defaults.temperature=0.5`\\n' +\n '`/config set agents.defaults.thinkingDefault=medium`\\n' +\n '`/config unset tts`',\n };\n },\n};\n\nexport function registerConfigCommand(): void {\n commandRegistry.register(configCommand);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../../../../src/chat-commands/builtins/config.ts"],"sourcesContent":["/**\n * /config — read and write persistent config (~/.xopc/xopc.json) from chat.\n */\n\nimport type { CommandDefinition, CommandContext } from '../types.js';\nimport { commandRegistry } from '../registry.js';\nimport { parseConfigValue } from '../config-value.js';\nimport {\n parseConfigPath,\n getConfigValueAtPath,\n setConfigValueAtPath,\n unsetConfigValueAtPath,\n} from '../config-paths.js';\nimport { ConfigSchema, type TelegramConfig, type WeixinConfig } from '../../config/schema.js';\nimport { loadConfig, saveConfig } from '../../config/loader.js';\nimport { resolveConfigPath } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { resolveAllowlistMatchSimple } from '../../channels/security.js';\n\nconst log = createLogger('ConfigCommand');\n\nconst BLOCKED_WRITE_PATHS = new Set(['gateway.auth.token', 'providers']);\n\nfunction isBlockedPath(path: string[]): boolean {\n const joined = path.join('.');\n for (const blocked of BLOCKED_WRITE_PATHS) {\n if (joined === blocked || joined.startsWith(`${blocked}.`)) return true;\n }\n return false;\n}\n\nfunction redactConfigForDisplay(plain: Record<string, unknown>): void {\n if (plain.gateway && typeof plain.gateway === 'object') {\n const gw = plain.gateway as Record<string, unknown>;\n if (gw.auth && typeof gw.auth === 'object') {\n (gw.auth as Record<string, unknown>).token = '[redacted]';\n }\n }\n if (plain.providers !== undefined) plain.providers = '[redacted]';\n}\n\nfunction senderMayWritePersistentConfig(ctx: CommandContext): boolean {\n const { source, senderId, isGroup } = ctx;\n if (source !== 'telegram' && source !== 'weixin') {\n return true;\n }\n\n const cfg = ctx.getConfig?.() ?? ctx.config;\n\n if (source === 'weixin') {\n const wx = cfg.channels?.weixin as WeixinConfig | undefined;\n if (!wx?.enabled) return false;\n const accountId = ctx.accountId ?? 'default';\n let allowFrom: Array<string | number> = [];\n if (wx.accounts && Object.keys(wx.accounts).length > 0) {\n const acc = wx.accounts[accountId] ?? wx.accounts['default'];\n if (!acc || acc.enabled === false) return false;\n allowFrom = [...(acc.allowFrom ?? [])];\n } else {\n allowFrom = [...(wx.allowFrom ?? [])];\n }\n if (allowFrom.length === 0) return false;\n return resolveAllowlistMatchSimple({ allowFrom, senderId }).allowed;\n }\n\n const tg = cfg.channels?.telegram as TelegramConfig | undefined;\n if (!tg?.enabled) return false;\n const accountId = ctx.accountId ?? 'default';\n const acc = tg.accounts?.[accountId] ?? tg.accounts?.['default'];\n if (!acc || acc.enabled === false) return false;\n const allowFrom = [...(acc.allowFrom ?? [])];\n const groupAllowFrom = [...(acc.groupAllowFrom ?? [])];\n const list = isGroup && groupAllowFrom.length > 0 ? groupAllowFrom : allowFrom;\n if (list.length === 0) return false;\n return resolveAllowlistMatchSimple({ allowFrom: list, senderId }).allowed;\n}\n\nconst configCommand: CommandDefinition = {\n id: 'system.config',\n name: 'config',\n aliases: ['cfg'],\n description:\n 'Show or update configuration. Usage: /config show [path] | /config set path=value | /config unset path',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: [\n '/config show',\n '/config show agents.defaults.models.chat',\n '/config set agents.defaults.models.chat.primary=anthropic/claude-opus-4-5',\n '/config set agents.defaults.temperature=0.5',\n '/config unset tts',\n ],\n handler: async (ctx: CommandContext, args: string) => {\n const parts = args.trim().split(/\\s+/);\n const action = parts[0]?.toLowerCase();\n const rest = parts.slice(1).join(' ').trim();\n\n if (!action || action === 'show' || action === 'get') {\n const config = ctx.getConfig?.() ?? loadConfig(resolveConfigPath());\n const plain = JSON.parse(JSON.stringify(config)) as Record<string, unknown>;\n redactConfigForDisplay(plain);\n\n if (rest) {\n const parsed = parseConfigPath(rest);\n if (!parsed.ok || !parsed.path) {\n return { content: `⚠️ ${parsed.error ?? 'Invalid path.'}`, success: false };\n }\n const value = getConfigValueAtPath(plain, parsed.path);\n const rendered = JSON.stringify(value ?? null, null, 2);\n return { content: `⚙️ \\`${rest}\\`:\\n\\`\\`\\`json\\n${rendered}\\n\\`\\`\\`` };\n }\n\n const json = JSON.stringify(plain, null, 2);\n return { content: `⚙️ Current config:\\n\\`\\`\\`json\\n${json}\\n\\`\\`\\`` };\n }\n\n if (action === 'set') {\n if (!senderMayWritePersistentConfig(ctx)) {\n return {\n content: '⚠️ You are not allowed to change config from this chat surface.',\n success: false,\n };\n }\n const eqIndex = rest.indexOf('=');\n if (eqIndex <= 0) {\n return { content: '⚠️ Usage: /config set path=value', success: false };\n }\n const pathRaw = rest.slice(0, eqIndex).trim();\n const valueRaw = rest.slice(eqIndex + 1);\n\n const parsedPath = parseConfigPath(pathRaw);\n if (!parsedPath.ok || !parsedPath.path) {\n return { content: `⚠️ ${parsedPath.error}`, success: false };\n }\n if (isBlockedPath(parsedPath.path)) {\n return {\n content: `⚠️ Path \\`${pathRaw}\\` cannot be modified via chat for security reasons.`,\n success: false,\n };\n }\n\n const parsedValue = parseConfigValue(valueRaw);\n if (parsedValue.ok === false) {\n return { content: `⚠️ ${parsedValue.error}`, success: false };\n }\n\n const configPath = resolveConfigPath();\n const currentConfig = loadConfig(configPath) as Record<string, unknown>;\n setConfigValueAtPath(currentConfig, parsedPath.path, parsedValue.value);\n\n const validated = ConfigSchema.safeParse(currentConfig);\n if (!validated.success) {\n const firstIssue = validated.error.issues[0];\n const fieldPath = firstIssue.path.join('.');\n return {\n content: `⚠️ Config invalid after set (${fieldPath}: ${firstIssue.message}). Change not saved.`,\n success: false,\n };\n }\n\n await saveConfig(validated.data);\n log.info({ path: pathRaw, value: parsedValue.value }, 'Config updated via /config set');\n\n const valueLabel =\n typeof parsedValue.value === 'string'\n ? `\"${parsedValue.value}\"`\n : JSON.stringify(parsedValue.value);\n return { content: `⚙️ Config updated: \\`${pathRaw}\\` = ${valueLabel}` };\n }\n\n if (action === 'unset') {\n if (!senderMayWritePersistentConfig(ctx)) {\n return {\n content: '⚠️ You are not allowed to change config from this chat surface.',\n success: false,\n };\n }\n if (!rest) {\n return { content: '⚠️ Usage: /config unset path', success: false };\n }\n const parsedPath = parseConfigPath(rest);\n if (!parsedPath.ok || !parsedPath.path) {\n return { content: `⚠️ ${parsedPath.error}`, success: false };\n }\n if (isBlockedPath(parsedPath.path)) {\n return {\n content: `⚠️ Path \\`${rest}\\` cannot be modified via chat for security reasons.`,\n success: false,\n };\n }\n\n const configPath = resolveConfigPath();\n const currentConfig = loadConfig(configPath) as Record<string, unknown>;\n const removed = unsetConfigValueAtPath(currentConfig, parsedPath.path);\n if (!removed) {\n return { content: `⚙️ No config value found at \\`${rest}\\`.`, success: false };\n }\n\n const validated = ConfigSchema.safeParse(currentConfig);\n if (!validated.success) {\n const firstIssue = validated.error.issues[0];\n const fieldPath = firstIssue.path.join('.');\n return {\n content: `⚠️ Config invalid after unset (${fieldPath}: ${firstIssue.message}). Change not saved.`,\n success: false,\n };\n }\n\n await saveConfig(validated.data);\n log.info({ path: rest }, 'Config key removed via /config unset');\n return { content: `⚙️ Config updated: \\`${rest}\\` removed.` };\n }\n\n return {\n content:\n '⚙️ *Config Command*\\n\\n' +\n '`/config show [path]` — view config (or a specific path)\\n' +\n '`/config set path=value` — update a config value\\n' +\n '`/config unset path` — remove a config key\\n\\n' +\n 'Examples:\\n' +\n '`/config show agents.defaults.models.chat`\\n' +\n '`/config set agents.defaults.temperature=0.5`\\n' +\n '`/config set agents.defaults.thinkingDefault=medium`\\n' +\n '`/config unset tts`',\n };\n },\n};\n\nexport function registerConfigCommand(): void {\n commandRegistry.register(configCommand);\n}\n"],"mappings":"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"}
|
|
@@ -20,6 +20,8 @@ export interface CommandContextDeps {
|
|
|
20
20
|
chatId: string;
|
|
21
21
|
senderId: string;
|
|
22
22
|
isGroup: boolean;
|
|
23
|
+
accountId?: string;
|
|
24
|
+
threadId?: string;
|
|
23
25
|
config: Config;
|
|
24
26
|
bus: MessageBus;
|
|
25
27
|
sessionStore: SessionStore;
|
|
@@ -61,6 +63,8 @@ export declare class CommandContextImpl implements CommandContext {
|
|
|
61
63
|
readonly chatId: string;
|
|
62
64
|
readonly senderId: string;
|
|
63
65
|
readonly isGroup: boolean;
|
|
66
|
+
readonly accountId?: string;
|
|
67
|
+
readonly threadId?: string;
|
|
64
68
|
readonly config: Config;
|
|
65
69
|
readonly abortCurrentTurn?: () => Promise<void>;
|
|
66
70
|
readonly reloadSkills?: () => Promise<void>;
|
|
@@ -68,6 +72,7 @@ export declare class CommandContextImpl implements CommandContext {
|
|
|
68
72
|
readonly workflowRunApis?: CommandContext['workflowRunApis'];
|
|
69
73
|
private deps;
|
|
70
74
|
constructor(deps: CommandContextDeps);
|
|
75
|
+
private outboundMetadata;
|
|
71
76
|
reply(text: string, options?: ReplyOptions): Promise<void>;
|
|
72
77
|
replyComponent(component: UIComponent): Promise<void>;
|
|
73
78
|
setTyping(typing: boolean): Promise<void>;
|
|
@@ -2,7 +2,7 @@ import { createLogger } from "../utils/logger/index.js";
|
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
3
|
import { init_loader, saveConfig } from "../config/loader.js";
|
|
4
4
|
import { effectiveWorkspacePathForSession } from "../session/session-workspace.js";
|
|
5
|
-
import {
|
|
5
|
+
import { getSessionDisplayName } from "./session-key.js";
|
|
6
6
|
import { wrapMarkdownExportAsHtml } from "../session/chat-export.js";
|
|
7
7
|
import { join } from "path";
|
|
8
8
|
import { mkdir, writeFile } from "fs/promises";
|
|
@@ -17,6 +17,8 @@ var CommandContextImpl = class {
|
|
|
17
17
|
chatId;
|
|
18
18
|
senderId;
|
|
19
19
|
isGroup;
|
|
20
|
+
accountId;
|
|
21
|
+
threadId;
|
|
20
22
|
config;
|
|
21
23
|
abortCurrentTurn;
|
|
22
24
|
reloadSkills;
|
|
@@ -30,6 +32,8 @@ var CommandContextImpl = class {
|
|
|
30
32
|
this.chatId = deps.chatId;
|
|
31
33
|
this.senderId = deps.senderId;
|
|
32
34
|
this.isGroup = deps.isGroup;
|
|
35
|
+
this.accountId = deps.accountId;
|
|
36
|
+
this.threadId = deps.threadId;
|
|
33
37
|
this.config = deps.config;
|
|
34
38
|
this.deps = deps;
|
|
35
39
|
if (deps.abortCurrentTurn) {
|
|
@@ -50,6 +54,13 @@ var CommandContextImpl = class {
|
|
|
50
54
|
startWorkflowRun: (params) => deps.workflowRunService.startWorkflowRun(params)
|
|
51
55
|
};
|
|
52
56
|
}
|
|
57
|
+
outboundMetadata(extra) {
|
|
58
|
+
return {
|
|
59
|
+
accountId: this.deps.accountId,
|
|
60
|
+
threadId: this.deps.threadId,
|
|
61
|
+
...extra
|
|
62
|
+
};
|
|
63
|
+
}
|
|
53
64
|
async reply(text, options) {
|
|
54
65
|
await this.deps.replyHandler(text, options);
|
|
55
66
|
}
|
|
@@ -72,13 +83,12 @@ var CommandContextImpl = class {
|
|
|
72
83
|
await this.clearSession();
|
|
73
84
|
return;
|
|
74
85
|
}
|
|
75
|
-
const routing = getRoutingInfo(this.sessionKey);
|
|
76
86
|
await this.deps.bus.publishOutbound({
|
|
77
|
-
channel:
|
|
78
|
-
chat_id:
|
|
87
|
+
channel: this.source,
|
|
88
|
+
chat_id: this.chatId,
|
|
79
89
|
content: "✅ New session started. Previous transcript archived; model and session overrides kept.",
|
|
80
90
|
type: "message",
|
|
81
|
-
metadata:
|
|
91
|
+
metadata: this.outboundMetadata()
|
|
82
92
|
});
|
|
83
93
|
log.info({ sessionKey: this.sessionKey }, "Session reset");
|
|
84
94
|
}
|
|
@@ -93,13 +103,12 @@ var CommandContextImpl = class {
|
|
|
93
103
|
}
|
|
94
104
|
await this.deps.sessionStore.deleteSession(this.sessionKey);
|
|
95
105
|
this.deps.invalidateAgentSession?.(this.sessionKey);
|
|
96
|
-
const routing = getRoutingInfo(this.sessionKey);
|
|
97
106
|
await this.deps.bus.publishOutbound({
|
|
98
|
-
channel:
|
|
99
|
-
chat_id:
|
|
107
|
+
channel: this.source,
|
|
108
|
+
chat_id: this.chatId,
|
|
100
109
|
content: "✅ Session cleared.",
|
|
101
110
|
type: "message",
|
|
102
|
-
metadata:
|
|
111
|
+
metadata: this.outboundMetadata()
|
|
103
112
|
});
|
|
104
113
|
log.info({ sessionKey: this.sessionKey }, "Session cleared");
|
|
105
114
|
}
|