@xopcai/xopc 0.0.123 → 0.0.125
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 +28 -11
- package/README.zh-CN.md +28 -11
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +41 -0
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Bicr3ZBg.js → agent-avatar-dicebear-BKDKICZV.js} +1 -1
- package/dist/gateway/static/root/assets/agents-BnTB7-c5.js +2 -0
- package/dist/gateway/static/root/assets/app-management-settings-panel-DI4BqHKW.js +1 -0
- package/dist/gateway/static/root/assets/appearance-settings-6_ie3NQ4.js +1 -0
- package/dist/gateway/static/root/assets/apps-page-B6bG65SW.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-Bpy64GjU.js → archive-plugin-kUHEJ1HK.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-DMkp4xSb.js → attachment-load-Dm-9prpU.js} +1 -1
- package/dist/gateway/static/root/assets/automation-suggestion-card-OTxQTPnC.js +1 -0
- package/dist/gateway/static/root/assets/automations-page-1lVbo0dS.js +1 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DA9C5mCw.js → binary-plugins-DllA_jQ0.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CiSXk_YC.js → block-editor-Cm6CWNj1.js} +5 -5
- package/dist/gateway/static/root/assets/browser-settings-page-CzDBlOK0.js +8 -0
- package/dist/gateway/static/root/assets/capability-presets-api-VJ89b6I2.js +1 -0
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-BaPj8wC2.js +1 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-CDhrhfhN.js → channel-recipient-api-B5PwBEUx.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-Df4m7p1k.js +1 -0
- package/dist/gateway/static/root/assets/code-editor-gbRgS14t.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-BMTphmHS.js +2 -0
- package/dist/gateway/static/root/assets/{directory-picker-path-field-7jKfbH0J.js → directory-picker-path-field-DySMzOF6.js} +1 -1
- package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +1 -0
- package/dist/gateway/static/root/assets/dist-CkobR7mk.js +1 -0
- package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +1 -0
- package/dist/gateway/static/root/assets/dreaming-settings-D_AjSnV_.js +3 -0
- package/dist/gateway/static/root/assets/extension-debug-page-BaM0FpW7.js +1 -0
- package/dist/gateway/static/root/assets/extension-page-DuZWVOGA.js +1 -0
- package/dist/gateway/static/root/assets/extension-settings-page-DarVtbmJ.js +1 -0
- package/dist/gateway/static/root/assets/{fetch-Dtpbbe0s.js → fetch-NFKfkqrd.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-BN6pyX2c.js → gateway-config-api-CFEm9rgy.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-BMk2S5td.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-BIET2x3y.js → gateway-startup-retry-Dtwh_yGg.js} +1 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-BKP7ylcG.js +1 -0
- package/dist/gateway/static/root/assets/goal-detail-page-C2cTxf71.js +1 -0
- package/dist/gateway/static/root/assets/{goals-config-api-CQm2r1Ty.js → goals-config-api-DTWZNA_Y.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-CTmA3hWK.js +2 -0
- package/dist/gateway/static/root/assets/goals-settings-Bhct0ZT-.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-settings-C-UxSU4a.js +1 -0
- package/dist/gateway/static/root/assets/{html-workspace-editor-CQLWDiwE.js → html-workspace-editor-DV90ddkE.js} +1 -1
- package/dist/gateway/static/root/assets/index-BNHDd2j1.css +1 -0
- package/dist/gateway/static/root/assets/index-BPXLPMuY.js +193 -0
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-DCjy2y4d.js +1 -0
- package/dist/gateway/static/root/assets/logs-page-CGc3_CQU.js +2 -0
- package/dist/gateway/static/root/assets/{markdown-editor-AssmZFx4.js → markdown-editor-BFOjBBla.js} +2 -2
- package/dist/gateway/static/root/assets/markdown-split-BaqxP-GQ.js +1 -0
- package/dist/gateway/static/root/assets/{media-plugins-DS44pJzr.js → media-plugins-DQ_EXloK.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CjuIJcZl.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-Drz4UQMb.js +2 -0
- package/dist/gateway/static/root/assets/notes-page-CY1ylng1.js +1 -0
- package/dist/gateway/static/root/assets/notes-workbench-X7IaD--t.js +2 -0
- package/dist/gateway/static/root/assets/page-tabs-EIZhLppK.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-Dej6zHnr.js → preview-open-alternatives-r_uB4Epr.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-DE5adRBE.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-CuOb1k6F.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-BOxNrUVA.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-Zu1FzH6z.js → save-bar-controls-B132Uf-2.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-BW78mKc0.js → schedule-field-B5qshALm.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-Cc-IOydE.js → schema-form-CvLmkdS9.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-CY0IQcGW.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-D4NBNVCB.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-DIpIYht_.js → settings-collapsible-section-pRlvqsAf.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-BFxBNxOG.js → settings-form-section-BBYUDLVd.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-C4fivemT.js → settings-page-DaO7zYZM.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-layout-CLx4o2PN.js → settings-page-layout-D8g9PAek.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Bks0CLLT.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-ZswWCrDu.js → share-preview-page-v6-IOp8t.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-CEZsKm9r.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-oTkHbb9W.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-DigsbZ6K.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-3ZNcGRhS.js → system-settings-panel-HUU2FFjM.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-bpzZjiVF.js → typed-models-lib-AH160QHh.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-BCjZLZ3O.js → use-channel-catalog-BXzDmjCQ.js} +1 -1
- package/dist/gateway/static/root/assets/{user-profile-settings-panel-CIXafITi.js → user-profile-settings-panel-DxwnQvQ3.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-DXMtz5j_.js → utils-i5POEtqd.js} +1 -1
- package/dist/gateway/static/root/assets/{vendor-codemirror-CNP1wPe7.js → vendor-codemirror-BvNgyE1Q.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-CEJklEgb.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-CD6FL_Rs.js +1 -0
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-ClVVMgN-.js +3 -0
- package/dist/gateway/static/root/assets/{workflow-start-dialog-B4sZpTDQ.js → workflow-start-dialog-Dv4ZA1T0.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-OLQiUpoW.js +18 -0
- package/dist/gateway/static/root/index.html +8 -7
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +6 -1
- package/dist/src/agent/agent-manager.js +34 -14
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/child-agent-factory.d.ts +2 -0
- package/dist/src/agent/child-agent-factory.js +2 -0
- package/dist/src/agent/child-agent-factory.js.map +1 -1
- package/dist/src/agent/coding/index.d.ts +1 -0
- package/dist/src/agent/coding/index.js +2 -0
- package/dist/src/agent/coding/turn-diff-tracker.d.ts +67 -0
- package/dist/src/agent/coding/turn-diff-tracker.js +233 -0
- package/dist/src/agent/coding/turn-diff-tracker.js.map +1 -0
- package/dist/src/agent/context/workspace-templates/AGENTS.md +1 -1
- package/dist/src/agent/embedded/xopc-tools-bridge.js +11 -7
- package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
- package/dist/src/agent/lifecycle/progress.js +3 -1
- package/dist/src/agent/lifecycle/progress.js.map +1 -1
- package/dist/src/agent/lifecycle/timeout-wrapper.d.ts +2 -2
- package/dist/src/agent/lifecycle/timeout-wrapper.js +4 -4
- package/dist/src/agent/lifecycle/timeout-wrapper.js.map +1 -1
- package/dist/src/agent/memory/dreaming/config.d.ts +2 -2
- package/dist/src/agent/memory/dreaming/config.js +3 -3
- package/dist/src/agent/memory/dreaming/config.js.map +1 -1
- package/dist/src/agent/memory/dreaming/constants.d.ts +1 -1
- package/dist/src/agent/memory/dreaming/constants.js +1 -1
- package/dist/src/agent/memory/dreaming/constants.js.map +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +1 -0
- package/dist/src/agent/memory/dreaming/deep-promotion.js +11 -20
- package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
- package/dist/src/agent/memory/dreaming/events.d.ts +3 -3
- package/dist/src/agent/memory/dreaming/events.js +6 -6
- package/dist/src/agent/memory/dreaming/events.js.map +1 -1
- package/dist/src/agent/memory/dreaming/last-run.d.ts +2 -2
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js.map +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.d.ts +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +3 -3
- package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
- package/dist/src/agent/memory/dreaming/preview.d.ts +1 -0
- package/dist/src/agent/memory/dreaming/preview.js +2 -2
- package/dist/src/agent/memory/dreaming/preview.js.map +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +13 -13
- package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
- package/dist/src/agent/memory/dreaming/scope.d.ts +14 -0
- package/dist/src/agent/memory/dreaming/scope.js +27 -0
- package/dist/src/agent/memory/dreaming/scope.js.map +1 -0
- package/dist/src/agent/memory/dreaming/short-term-store.d.ts +4 -4
- package/dist/src/agent/memory/dreaming/short-term-store.js +17 -17
- package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
- package/dist/src/agent/memory/summary-generator.d.ts +1 -1
- package/dist/src/agent/memory/summary-generator.js +1 -2
- package/dist/src/agent/memory/summary-generator.js.map +1 -1
- package/dist/src/agent/middleware/index.d.ts +1 -1
- package/dist/src/agent/middleware/self-verify.d.ts +44 -14
- package/dist/src/agent/middleware/self-verify.js +214 -44
- package/dist/src/agent/middleware/self-verify.js.map +1 -1
- package/dist/src/agent/orchestration/agent-event-handler.d.ts +2 -0
- package/dist/src/agent/orchestration/agent-event-handler.js +69 -14
- package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.js +22 -12
- package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
- package/dist/src/agent/prompt/sections/tooling.js +18 -13
- package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
- package/dist/src/agent/prompt/system-reminder.js +2 -2
- package/dist/src/agent/prompt/system-reminder.js.map +1 -1
- package/dist/src/agent/sandbox/command-validator.js +12 -0
- package/dist/src/agent/sandbox/command-validator.js.map +1 -1
- package/dist/src/agent/sandbox/sanitize-env-vars.d.ts +2 -2
- package/dist/src/agent/sandbox/sanitize-env-vars.js +2 -2
- package/dist/src/agent/sandbox/sanitize-env-vars.js.map +1 -1
- package/dist/src/agent/sandbox/types.d.ts +2 -2
- package/dist/src/agent/sandbox/types.js.map +1 -1
- package/dist/src/agent/service/btw-query.js +1 -1
- package/dist/src/agent/service/btw-query.js.map +1 -1
- package/dist/src/agent/service/process-direct-one-shot.js +6 -2
- package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.js +12 -7
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.d.ts +2 -1
- package/dist/src/agent/service.js +19 -6
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/session/session-inspector.d.ts +5 -3
- package/dist/src/agent/session/session-inspector.js +16 -7
- package/dist/src/agent/session/session-inspector.js.map +1 -1
- package/dist/src/agent/skills/skill-tool-gating.js +1 -1
- package/dist/src/agent/skills/skill-tool-gating.js.map +1 -1
- package/dist/src/agent/source-context/types.d.ts +1 -1
- package/dist/src/agent/source-context/types.js +1 -1
- package/dist/src/agent/source-context/types.js.map +1 -1
- package/dist/src/agent/starter-agents.js +9 -9
- package/dist/src/agent/starter-agents.js.map +1 -1
- package/dist/src/agent/tools/apply-patch.d.ts +25 -0
- package/dist/src/agent/tools/apply-patch.js +310 -0
- package/dist/src/agent/tools/apply-patch.js.map +1 -0
- package/dist/src/agent/tools/concurrency.d.ts +8 -0
- package/dist/src/agent/tools/concurrency.js +31 -0
- package/dist/src/agent/tools/concurrency.js.map +1 -0
- package/dist/src/agent/tools/delegate-tool.d.ts +1 -1
- package/dist/src/agent/tools/delegate-tool.js +3 -3
- package/dist/src/agent/tools/delegate-tool.js.map +1 -1
- package/dist/src/agent/tools/dreaming-tool.d.ts +2 -0
- package/dist/src/agent/tools/dreaming-tool.js +13 -10
- package/dist/src/agent/tools/dreaming-tool.js.map +1 -1
- package/dist/src/agent/tools/exec-command.d.ts +30 -0
- package/dist/src/agent/tools/exec-command.js +228 -0
- package/dist/src/agent/tools/exec-command.js.map +1 -0
- package/dist/src/agent/tools/execute-code-tool.js +7 -4
- package/dist/src/agent/tools/execute-code-tool.js.map +1 -1
- package/dist/src/agent/tools/executor.d.ts +6 -4
- package/dist/src/agent/tools/executor.js +7 -4
- package/dist/src/agent/tools/executor.js.map +1 -1
- package/dist/src/agent/tools/factory.d.ts +6 -3
- package/dist/src/agent/tools/factory.js +14 -9
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/find.js +2 -0
- package/dist/src/agent/tools/find.js.map +1 -1
- package/dist/src/agent/tools/grep.js +2 -0
- package/dist/src/agent/tools/grep.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +5 -2
- package/dist/src/agent/tools/index.js +7 -4
- package/dist/src/agent/tools/list-dir.js +2 -0
- package/dist/src/agent/tools/list-dir.js.map +1 -1
- package/dist/src/agent/tools/memory-tool.d.ts +1 -0
- package/dist/src/agent/tools/memory-tool.js +2 -2
- package/dist/src/agent/tools/memory-tool.js.map +1 -1
- package/dist/src/agent/tools/metadata.d.ts +15 -0
- package/dist/src/agent/tools/metadata.js +26 -0
- package/dist/src/agent/tools/metadata.js.map +1 -0
- package/dist/src/agent/tools/read.js +2 -0
- package/dist/src/agent/tools/read.js.map +1 -1
- package/dist/src/agent/tools/skills-tools.d.ts +1 -1
- package/dist/src/agent/tools/skills-tools.js.map +1 -1
- package/dist/src/agent/tools/update-plan-tool.d.ts +11 -0
- package/dist/src/agent/tools/update-plan-tool.js +72 -0
- package/dist/src/agent/tools/update-plan-tool.js.map +1 -0
- package/dist/src/agent/tools/write.js +6 -0
- package/dist/src/agent/tools/write.js.map +1 -1
- package/dist/src/agent/workflow/builtins/debug-incident.d.ts +1 -1
- package/dist/src/agent/workflow/builtins/debug-incident.js +1 -1
- package/dist/src/agent/workflow/builtins/debug-incident.js.map +1 -1
- package/dist/src/agent/workflow/builtins/pr-review.d.ts +1 -1
- package/dist/src/agent/workflow/builtins/pr-review.js +1 -1
- package/dist/src/agent/workflow/builtins/pr-review.js.map +1 -1
- package/dist/src/agent/workflow/builtins/release-check.d.ts +1 -1
- package/dist/src/agent/workflow/builtins/release-check.js +1 -1
- package/dist/src/agent/workflow/builtins/release-check.js.map +1 -1
- package/dist/src/agent/workflow/step-labels.js +7 -3
- package/dist/src/agent/workflow/step-labels.js.map +1 -1
- package/dist/src/agent/workflow/subagent-runner.d.ts +1 -0
- package/dist/src/agent/workflow/subagent-runner.js +5 -1
- package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
- package/dist/src/agent/workflow/workflow-child-tools.js +5 -0
- package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -1
- package/dist/src/chat-commands/agent-edit.js +1 -1
- package/dist/src/chat-commands/agent-edit.js.map +1 -1
- package/dist/src/chat-commands/builtins/review.d.ts +1 -0
- package/dist/src/chat-commands/builtins/review.js +167 -0
- package/dist/src/chat-commands/builtins/review.js.map +1 -0
- package/dist/src/chat-commands/index.d.ts +1 -0
- package/dist/src/chat-commands/index.js +3 -1
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/connectors/health.d.ts +2 -1
- package/dist/src/connectors/health.js +59 -1
- package/dist/src/connectors/health.js.map +1 -1
- package/dist/src/connectors/install.d.ts +1 -0
- package/dist/src/connectors/install.js +28 -1
- package/dist/src/connectors/install.js.map +1 -1
- package/dist/src/connectors/instances.js +7 -0
- package/dist/src/connectors/instances.js.map +1 -1
- package/dist/src/connectors/materialize.js +2 -1
- package/dist/src/connectors/materialize.js.map +1 -1
- package/dist/src/connectors/registries/modelscope.js +38 -13
- package/dist/src/connectors/registries/modelscope.js.map +1 -1
- package/dist/src/connectors/types.d.ts +2 -0
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agent-builtin-tools.js +3 -2
- package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
- package/dist/src/gateway/chat-stream/mapper.d.ts +6 -0
- package/dist/src/gateway/chat-stream/mapper.js +149 -6
- package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
- package/dist/src/gateway/chat-stream/protocol.d.ts +51 -1
- package/dist/src/gateway/dreaming-automation-reconciler.d.ts +1 -0
- package/dist/src/gateway/dreaming-automation-reconciler.js +62 -42
- package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -1
- package/dist/src/gateway/hono/app.js +7 -1
- package/dist/src/gateway/hono/app.js.map +1 -1
- package/dist/src/gateway/hono/routes/commands-skills.js +21 -0
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/connectors.js +46 -2
- package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +111 -66
- package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
- package/dist/src/gateway/hono/routes/index.js +2 -0
- package/dist/src/gateway/hono/routes/index.js.map +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +1 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/projects.js +886 -45
- package/dist/src/gateway/hono/routes/projects.js.map +1 -1
- package/dist/src/gateway/hono/routes/search.d.ts +3 -0
- package/dist/src/gateway/hono/routes/search.js +47 -0
- package/dist/src/gateway/hono/routes/search.js.map +1 -0
- package/dist/src/gateway/hono/routes/sessions.js +1 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/security/dangerous-tools.js +1 -1
- package/dist/src/gateway/security/dangerous-tools.js.map +1 -1
- package/dist/src/gateway/service.js +17 -8
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/media/store.js +1 -1
- package/dist/src/media/store.js.map +1 -1
- package/dist/src/media/types.d.ts +1 -1
- package/dist/src/media/uri.js +2 -1
- package/dist/src/media/uri.js.map +1 -1
- package/dist/src/projects/index.d.ts +2 -0
- package/dist/src/projects/index.js +3 -1
- package/dist/src/projects/project-agent-suggestion.d.ts +14 -0
- package/dist/src/projects/project-agent-suggestion.js +19 -0
- package/dist/src/projects/project-agent-suggestion.js.map +1 -0
- package/dist/src/projects/project-kind.d.ts +13 -0
- package/dist/src/projects/project-kind.js +147 -0
- package/dist/src/projects/project-kind.js.map +1 -0
- package/dist/src/projects/project-service.d.ts +1 -0
- package/dist/src/projects/project-service.js +1 -1
- package/dist/src/projects/project-service.js.map +1 -1
- package/dist/src/projects/project-store.js +32 -8
- package/dist/src/projects/project-store.js.map +1 -1
- package/dist/src/projects/types.d.ts +1 -0
- package/dist/src/review/review-git.d.ts +48 -0
- package/dist/src/review/review-git.js +333 -0
- package/dist/src/review/review-git.js.map +1 -0
- package/dist/src/review/review-types.d.ts +22 -0
- package/dist/src/review/review-types.js +29 -0
- package/dist/src/review/review-types.js.map +1 -0
- package/dist/src/session/session-context-for-llm.d.ts +2 -0
- package/dist/src/session/session-context-for-llm.js +165 -1
- package/dist/src/session/session-context-for-llm.js.map +1 -1
- package/dist/src/session/store.js +2 -2
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/021_projects_fts.sql +21 -0
- package/dist/src/storage/sqlite/migrations/022_work_items.sql +61 -0
- package/dist/src/storage/sqlite/migrations/023_work_item_attachments.sql +15 -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.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +78 -0
- package/dist/src/tui/backends/embedded-backend.d.ts +1 -0
- package/dist/src/tui/backends/embedded-backend.js +20 -0
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +2 -0
- package/dist/src/tui/backends/gateway-sse-backend.js +7 -0
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/components/assistant-message.js +47 -2
- package/dist/src/tui/components/assistant-message.js.map +1 -1
- package/dist/src/tui/components/tool-execution.d.ts +8 -0
- package/dist/src/tui/components/tool-execution.js +87 -77
- package/dist/src/tui/components/tool-execution.js.map +1 -1
- package/dist/src/tui/components/visual-truncate.d.ts +1 -0
- package/dist/src/tui/components/visual-truncate.js +28 -1
- package/dist/src/tui/components/visual-truncate.js.map +1 -1
- package/dist/src/tui/tool-summary.d.ts +22 -0
- package/dist/src/tui/tool-summary.js +212 -0
- package/dist/src/tui/tool-summary.js.map +1 -0
- package/dist/src/tui/tui-agent-events.js +25 -0
- package/dist/src/tui/tui-agent-events.js.map +1 -1
- package/dist/src/tui/tui-backend.d.ts +4 -0
- package/dist/src/tui/tui-commands.d.ts +1 -0
- package/dist/src/tui/tui-commands.js +110 -4
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-picker-overlay.d.ts +2 -0
- package/dist/src/tui/tui-picker-overlay.js +153 -1
- package/dist/src/tui/tui-picker-overlay.js.map +1 -1
- package/dist/src/tui/tui-tool-diff.d.ts +15 -0
- package/dist/src/tui/tui-tool-diff.js +178 -7
- package/dist/src/tui/tui-tool-diff.js.map +1 -1
- package/dist/src/tui/tui.js +16 -3
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/work-items/agent-context.d.ts +3 -0
- package/dist/src/work-items/agent-context.js +39 -0
- package/dist/src/work-items/agent-context.js.map +1 -0
- package/dist/src/work-items/index.d.ts +4 -0
- package/dist/src/work-items/index.js +4 -0
- package/dist/src/work-items/types.d.ts +112 -0
- package/dist/src/work-items/types.js +1 -0
- package/dist/src/work-items/work-item-service.d.ts +33 -0
- package/dist/src/work-items/work-item-service.js +180 -0
- package/dist/src/work-items/work-item-service.js.map +1 -0
- package/dist/src/work-items/work-item-store.d.ts +21 -0
- package/dist/src/work-items/work-item-store.js +302 -0
- package/dist/src/work-items/work-item-store.js.map +1 -0
- package/dist/src/workflows/service/workflow-run-service.js +4 -3
- package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.js +3 -0
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
- package/dist/gateway/static/root/assets/agents-CxDSFHGx.js +0 -2
- package/dist/gateway/static/root/assets/app-management-settings-panel-CbEy9sR1.js +0 -1
- package/dist/gateway/static/root/assets/appearance-settings-CTHja6n9.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-CyZdgqvm.js +0 -1
- package/dist/gateway/static/root/assets/automation-suggestion-card-KnYaP7NT.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-8VLKM4au.js +0 -1
- package/dist/gateway/static/root/assets/browser-settings-page-5tPg0DcP.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-api-CEJ44WCU.js +0 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-BJW3aVST.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-CorUCTrs.js +0 -1
- package/dist/gateway/static/root/assets/code-editor-dZTY2dRW.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-VKstC3sP.js +0 -2
- package/dist/gateway/static/root/assets/dist-Mys7eFJ5.js +0 -1
- package/dist/gateway/static/root/assets/dist-wO9a2_ID.js +0 -1
- package/dist/gateway/static/root/assets/dreaming-settings-m1-wmz4o.js +0 -1
- package/dist/gateway/static/root/assets/extension-debug-page-C9qQQrBS.js +0 -1
- package/dist/gateway/static/root/assets/extension-page-DcBBMEGl.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-BQ-jMMP9.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-hQtgVmSR.js +0 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-BuIMDx6C.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-FEypCq74.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-C4-2_MLG.js +0 -2
- package/dist/gateway/static/root/assets/goals-settings-DDrdRMxB.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-BJVok3Sl.js +0 -1
- package/dist/gateway/static/root/assets/index-CBDr5xjB.css +0 -1
- package/dist/gateway/static/root/assets/index-T0SaNd5a.js +0 -191
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-C2TuQppb.js +0 -1
- package/dist/gateway/static/root/assets/logs-page-DwkwPgid.js +0 -2
- package/dist/gateway/static/root/assets/markdown-split-DhONQ81k.js +0 -1
- package/dist/gateway/static/root/assets/messages-avfvyZuQ.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-huNY4A1G.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-DdfGuEZ1.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-B0bT9Hqa.js +0 -2
- package/dist/gateway/static/root/assets/project-detail-page-CjxhPorG.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-C4Z5OJMF.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CVCOPUVd.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-B4qExXHC.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-Ce8yLTBi.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Kyc4eUf0.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-Bu76CMiC.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-D-CFg86j.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-CUU4f6Ss.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-C1MrQD8R.js +0 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-DqizIcY5.js +0 -3
- package/dist/gateway/static/root/assets/workflows-page-B3sVNPFk.js +0 -18
- package/dist/src/agent/tools/edit.d.ts +0 -14
- package/dist/src/agent/tools/edit.js +0 -132
- package/dist/src/agent/tools/edit.js.map +0 -1
- package/dist/src/agent/tools/shell.d.ts +0 -15
- package/dist/src/agent/tools/shell.js +0 -158
- package/dist/src/agent/tools/shell.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-runner.js","names":[],"sources":["../../../../src/agent/workflow/subagent-runner.ts"],"sourcesContent":["/**\n * Adapter: spawns one isolated child agent per `agent()` call from a workflow.\n *\n * Wraps the existing `createDelegateChildHandle` so the workflow runtime stays\n * decoupled from the LLM stack (it sees only the `SubagentRunner` interface).\n *\n * Key behaviour:\n * - When `opts.schema` is provided, we inject `structured_output` into the child\n * tool set and unwrap the captured value on success. If the subagent finishes\n * without ever calling `structured_output`, we treat it as failure (`null`).\n * - Failures and aborts resolve to `null`. The workflow runtime continues — this\n * matches the pi-dynamic-workflows contract and keeps fan-out pipelines robust.\n * - We do NOT mutate `createDelegateChildHandle` — we just leverage its\n * `buildChildTools` injection point.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\nimport type { Api, Model } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { SessionStore } from '../../session/store.js';\nimport { emitSessionTranscriptUpdate } from '../../session/transcript-events.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport {\n type BuildChildToolsOptions,\n createDelegateChildHandle,\n type DelegateChildHandleOptions,\n} from '../child-agent-factory.js';\nimport {\n DEFAULT_DELEGATE_TOOLS,\n DELEGATE_BLOCKED_TOOLS,\n} from '../tools/delegate-tool.js';\nimport type { ToolExecutorConfig } from '../tools/executor.js';\n\nimport {\n createStructuredOutputTool,\n STRUCTURED_OUTPUT_TOOL_NAME,\n type StructuredOutputCapture,\n} from './structured-output-tool.js';\nimport type { SubagentRunOptions, SubagentRunner, SubagentProgressEvent } from './types.js';\n\nconst log = createLogger('Agent:WorkflowSubagent');\n\nconst DEFAULT_MAX_ITERATIONS = 30;\n\nexport interface DelegateSubagentRunnerDeps {\n workspace: string;\n bus: MessageBus;\n /** Resolves the default subagent model (typically the parent agent's primary model). */\n getDefaultModel: () => Model<Api>;\n getConfig: () => Config | undefined;\n toolExecutorConfig?: Partial<ToolExecutorConfig>;\n sessionStore?: SessionStore;\n /**\n * Provided by the workflow tool from `AgentToolsFactory` — mirrors how\n * `delegate-tool` is wired (avoids importing `tools/factory.ts` here and\n * breaking the existing factory ↔ delegate-tool ↔ child-agent-factory\n * dependency contract).\n */\n buildChildTools: (opts: BuildChildToolsOptions) => AgentTool<any, any>[];\n}\n\nexport class DelegateSubagentRunner implements SubagentRunner {\n constructor(private readonly deps: DelegateSubagentRunnerDeps) {}\n\n async run<T = string>(prompt: string, opts: SubagentRunOptions<T>): Promise<T | null> {\n if (opts.signal?.aborted) return null;\n\n const capture: StructuredOutputCapture<T> = { called: false, value: undefined };\n const wantStructured = Boolean(opts.schema);\n\n const allowed = resolveAllowedToolNames(opts.allowedToolNames, wantStructured);\n const model = opts.model ?? safeResolveDefaultModel(this.deps.getDefaultModel);\n if (!model) {\n log.warn({ label: opts.label }, 'subagent run skipped: no primary model resolved');\n return null;\n }\n\n const fullPrompt = buildPrompt(prompt, opts, wantStructured);\n const streamMode = resolveSubagentStreamMode(this.deps.getConfig);\n\n let transcriptPersistQueue: Promise<void> = Promise.resolve();\n const persistTranscriptSnapshot = opts.sessionKey && this.deps.sessionStore\n ? (messages: Parameters<SessionStore['saveMessages']>[1]) => {\n const store = this.deps.sessionStore;\n const key = opts.sessionKey;\n if (!store || !key) return;\n const snapshot = cloneAgentMessages(messages);\n transcriptPersistQueue = transcriptPersistQueue\n .then(async () => {\n await store.saveMessages(key, snapshot);\n emitSessionTranscriptUpdate({ sessionKey: key });\n })\n .catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, sessionKey: key, errorMessage: msg },\n `Failed to persist workflow subagent transcript snapshot: ${msg}`,\n );\n });\n }\n : undefined;\n\n const childOptions: DelegateChildHandleOptions = {\n workspace: this.deps.workspace,\n goal: fullPrompt,\n allowedToolNames: allowed,\n maxIterations: opts.maxIterations ?? DEFAULT_MAX_ITERATIONS,\n model,\n bus: this.deps.bus,\n getConfig: this.deps.getConfig,\n toolExecutorConfig: this.deps.toolExecutorConfig,\n buildChildTools: (childOpts) => {\n const base = this.deps.buildChildTools(childOpts);\n if (!wantStructured || !opts.schema) return base;\n // Replace any existing tool with the same name so the per-run capture wins.\n const filtered = base.filter((t) => t.name !== STRUCTURED_OUTPUT_TOOL_NAME);\n return [\n ...filtered,\n createStructuredOutputTool({ schema: opts.schema, capture }) as unknown as AgentTool<any, any>,\n ];\n },\n progressHooks:\n opts.onProgress && streamMode !== 'off'\n ? {\n mode: streamMode === 'full' ? 'full' : 'steps',\n onProgress: (event) => {\n opts.onProgress?.(mapChildProgressEvent(event));\n },\n }\n : undefined,\n onTranscriptSnapshot: persistTranscriptSnapshot,\n };\n\n if (opts.sessionKey && opts.sessionMetadata && this.deps.sessionStore) {\n await this.preparePersistentSubagentSession(opts.sessionKey, opts.sessionMetadata);\n }\n\n const handle = createDelegateChildHandle(childOptions);\n const onAbort = () => handle.abort();\n opts.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n const { summary, messages } = await handle.run();\n await transcriptPersistQueue;\n if (opts.sessionKey && this.deps.sessionStore) {\n await this.deps.sessionStore.saveMessages(opts.sessionKey, messages);\n emitSessionTranscriptUpdate({ sessionKey: opts.sessionKey });\n }\n if (opts.signal?.aborted) return null;\n\n if (wantStructured) {\n if (!capture.called) {\n log.warn({ label: opts.label }, 'subagent finished without calling structured_output');\n return null;\n }\n return capture.value as T;\n }\n return summary as unknown as T;\n } catch (e) {\n if (opts.rethrow) throw e;\n const msg = e instanceof Error ? e.message : String(e);\n log.warn({ err: e, label: opts.label, errorMessage: msg }, `subagent run failed: ${msg}`);\n return null;\n } finally {\n opts.signal?.removeEventListener('abort', onAbort);\n }\n }\n\n private async preparePersistentSubagentSession(\n sessionKey: string,\n metadata: NonNullable<SubagentRunOptions['sessionMetadata']>,\n ): Promise<void> {\n const store = this.deps.sessionStore;\n if (!store) return;\n await store.resolveTranscriptPath(sessionKey, {\n metadata: {\n sessionType: 'workflow-subagent',\n hiddenFromSessionList: true,\n parentSessionKey: metadata.parentSessionKey,\n workflowRunId: metadata.workflowRunId,\n workflowDefinitionId: metadata.workflowDefinitionId,\n workflowAgentId: metadata.workflowAgentId,\n workflowAgentLabel: metadata.workflowAgentLabel,\n sourceChannel: 'workflow',\n sourceChatId: metadata.workflowRunId,\n routing: {\n agentId: metadata.workflowAgentId || 'main',\n source: 'workflow',\n accountId: 'default',\n peerKind: 'subagent',\n peerId: metadata.workflowRunId,\n },\n },\n });\n await store.updateMetadata(sessionKey, {\n sessionType: 'workflow-subagent',\n hiddenFromSessionList: true,\n parentSessionKey: metadata.parentSessionKey,\n workflowRunId: metadata.workflowRunId,\n workflowDefinitionId: metadata.workflowDefinitionId,\n workflowAgentId: metadata.workflowAgentId,\n workflowAgentLabel: metadata.workflowAgentLabel,\n name: metadata.workflowAgentLabel,\n tags: ['workflow-subagent', metadata.workflowDefinitionId],\n });\n }\n}\n\nfunction cloneAgentMessages(messages: Parameters<SessionStore['saveMessages']>[1]): Parameters<SessionStore['saveMessages']>[1] {\n return messages.map((message) => structuredClone(message));\n}\n\nfunction resolveAllowedToolNames(\n requested: string[] | undefined,\n wantStructured: boolean,\n): string[] {\n const base = requested && requested.length > 0 ? requested : [...DEFAULT_DELEGATE_TOOLS];\n const filtered = base\n .map((s) => String(s).trim())\n .filter((s) => s.length > 0)\n .filter((s) => !DELEGATE_BLOCKED_TOOLS.has(s));\n if (wantStructured && !filtered.includes(STRUCTURED_OUTPUT_TOOL_NAME)) {\n filtered.push(STRUCTURED_OUTPUT_TOOL_NAME);\n }\n return [...new Set(filtered)];\n}\n\nfunction buildPrompt(prompt: string, opts: SubagentRunOptions<unknown>, structured: boolean): string {\n const parts: string[] = [];\n if (opts.instructions?.trim()) parts.push(opts.instructions.trim());\n if (opts.label) parts.push(`Task label: ${opts.label}`);\n if (opts.phase) parts.push(`Workflow phase: ${opts.phase}`);\n parts.push(prompt);\n if (structured) {\n parts.push(\n [\n 'Final output contract:',\n '- Your final action MUST be a structured_output tool call.',\n '- The structured_output arguments are the return value of this subagent.',\n '- Do not emit a prose final answer instead of structured_output.',\n '- If you need to inspect files or run commands first, do so, then call structured_output exactly once.',\n ].join('\\n'),\n );\n }\n return parts.join('\\n\\n');\n}\n\nfunction safeResolveDefaultModel(get: () => Model<Api>): Model<Api> | null {\n try {\n return get();\n } catch (e) {\n log.warn({ err: e }, 'failed to resolve default subagent model');\n return null;\n }\n}\n\nfunction resolveSubagentStreamMode(\n _getConfig: () => Config | undefined,\n): 'off' | 'steps' | 'full' {\n return 'steps';\n}\n\nfunction mapChildProgressEvent(event: {\n type: 'tool_start' | 'tool_end' | 'iteration' | 'text_delta' | 'thinking_delta';\n toolCallId?: string;\n toolName?: string;\n args?: Record<string, unknown>;\n isError?: boolean;\n resultPreview?: string;\n error?: string;\n count?: number;\n max?: number;\n delta?: string;\n}): SubagentProgressEvent {\n switch (event.type) {\n case 'tool_start':\n return {\n type: 'tool_start',\n toolCallId: event.toolCallId ?? '',\n toolName: event.toolName ?? 'tool',\n args: event.args ?? {},\n };\n case 'tool_end':\n return {\n type: 'tool_end',\n toolCallId: event.toolCallId ?? '',\n toolName: event.toolName ?? 'tool',\n isError: Boolean(event.isError),\n resultPreview: event.resultPreview,\n error: event.error,\n };\n case 'iteration':\n return {\n type: 'iteration',\n count: event.count ?? 0,\n max: event.max ?? 0,\n };\n case 'text_delta':\n return { type: 'text_delta', delta: event.delta ?? '' };\n case 'thinking_delta':\n return { type: 'thinking_delta', delta: event.delta ?? '' };\n default:\n return { type: 'text_delta', delta: '' };\n }\n}\n"],"mappings":";;;;;;;aAuBqD;AAoBrD,MAAM,MAAM,aAAa,yBAAyB;AAElD,MAAM,yBAAyB;AAmB/B,IAAa,yBAAb,MAA8D;CAC5D,YAAY,MAAmD;AAAlC,OAAA,OAAA;;CAE7B,MAAM,IAAgB,QAAgB,MAAgD;AACpF,MAAI,KAAK,QAAQ,QAAS,QAAO;EAEjC,MAAM,UAAsC;GAAE,QAAQ;GAAO,OAAO,KAAA;GAAW;EAC/E,MAAM,iBAAiB,QAAQ,KAAK,OAAO;EAE3C,MAAM,UAAU,wBAAwB,KAAK,kBAAkB,eAAe;EAC9E,MAAM,QAAQ,KAAK,SAAS,wBAAwB,KAAK,KAAK,gBAAgB;AAC9E,MAAI,CAAC,OAAO;AACV,OAAI,KAAK,EAAE,OAAO,KAAK,OAAO,EAAE,kDAAkD;AAClF,UAAO;;EAGT,MAAM,aAAa,YAAY,QAAQ,MAAM,eAAe;EAC5D,MAAM,aAAa,0BAA0B,KAAK,KAAK,UAAU;EAEjE,IAAI,yBAAwC,QAAQ,SAAS;EAC7D,MAAM,4BAA4B,KAAK,cAAc,KAAK,KAAK,gBAC1D,aAA0D;GACzD,MAAM,QAAQ,KAAK,KAAK;GACxB,MAAM,MAAM,KAAK;AACjB,OAAI,CAAC,SAAS,CAAC,IAAK;GACpB,MAAM,WAAW,mBAAmB,SAAS;AAC7C,4BAAyB,uBACtB,KAAK,YAAY;AAChB,UAAM,MAAM,aAAa,KAAK,SAAS;AACvC,gCAA4B,EAAE,YAAY,KAAK,CAAC;KAChD,CACD,OAAO,QAAQ;IACd,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC5D,QAAI,KACF;KAAE;KAAK,YAAY;KAAK,cAAc;KAAK,EAC3C,4DAA4D,MAC7D;KACD;MAEN,KAAA;EAEJ,MAAM,eAA2C;GAC/C,WAAW,KAAK,KAAK;GACrB,MAAM;GACN,kBAAkB;GAClB,eAAe,KAAK,iBAAiB;GACrC;GACA,KAAK,KAAK,KAAK;GACf,WAAW,KAAK,KAAK;GACrB,oBAAoB,KAAK,KAAK;GAC9B,kBAAkB,cAAc;IAC9B,MAAM,OAAO,KAAK,KAAK,gBAAgB,UAAU;AACjD,QAAI,CAAC,kBAAkB,CAAC,KAAK,OAAQ,QAAO;AAG5C,WAAO,CACL,GAFe,KAAK,QAAQ,MAAM,EAAE,SAAS,4BAElC,EACX,2BAA2B;KAAE,QAAQ,KAAK;KAAQ;KAAS,CAAC,CAC7D;;GAEH,eACE,KAAK,cAAc,eAAe,QAC9B;IACE,MAAM,eAAe,SAAS,SAAS;IACvC,aAAa,UAAU;AACrB,UAAK,aAAa,sBAAsB,MAAM,CAAC;;IAElD,GACD,KAAA;GACN,sBAAsB;GACvB;AAED,MAAI,KAAK,cAAc,KAAK,mBAAmB,KAAK,KAAK,aACvD,OAAM,KAAK,iCAAiC,KAAK,YAAY,KAAK,gBAAgB;EAGpF,MAAM,SAAS,0BAA0B,aAAa;EACtD,MAAM,gBAAgB,OAAO,OAAO;AACpC,OAAK,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;AAE/D,MAAI;GACF,MAAM,EAAE,SAAS,aAAa,MAAM,OAAO,KAAK;AAChD,SAAM;AACN,OAAI,KAAK,cAAc,KAAK,KAAK,cAAc;AAC7C,UAAM,KAAK,KAAK,aAAa,aAAa,KAAK,YAAY,SAAS;AACpE,gCAA4B,EAAE,YAAY,KAAK,YAAY,CAAC;;AAE9D,OAAI,KAAK,QAAQ,QAAS,QAAO;AAEjC,OAAI,gBAAgB;AAClB,QAAI,CAAC,QAAQ,QAAQ;AACnB,SAAI,KAAK,EAAE,OAAO,KAAK,OAAO,EAAE,sDAAsD;AACtF,YAAO;;AAET,WAAO,QAAQ;;AAEjB,UAAO;WACA,GAAG;AACV,OAAI,KAAK,QAAS,OAAM;GACxB,MAAM,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;AACtD,OAAI,KAAK;IAAE,KAAK;IAAG,OAAO,KAAK;IAAO,cAAc;IAAK,EAAE,wBAAwB,MAAM;AACzF,UAAO;YACC;AACR,QAAK,QAAQ,oBAAoB,SAAS,QAAQ;;;CAItD,MAAc,iCACZ,YACA,UACe;EACf,MAAM,QAAQ,KAAK,KAAK;AACxB,MAAI,CAAC,MAAO;AACZ,QAAM,MAAM,sBAAsB,YAAY,EAC5C,UAAU;GACR,aAAa;GACb,uBAAuB;GACvB,kBAAkB,SAAS;GAC3B,eAAe,SAAS;GACxB,sBAAsB,SAAS;GAC/B,iBAAiB,SAAS;GAC1B,oBAAoB,SAAS;GAC7B,eAAe;GACf,cAAc,SAAS;GACvB,SAAS;IACP,SAAS,SAAS,mBAAmB;IACrC,QAAQ;IACR,WAAW;IACX,UAAU;IACV,QAAQ,SAAS;IAClB;GACF,EACF,CAAC;AACF,QAAM,MAAM,eAAe,YAAY;GACrC,aAAa;GACb,uBAAuB;GACvB,kBAAkB,SAAS;GAC3B,eAAe,SAAS;GACxB,sBAAsB,SAAS;GAC/B,iBAAiB,SAAS;GAC1B,oBAAoB,SAAS;GAC7B,MAAM,SAAS;GACf,MAAM,CAAC,qBAAqB,SAAS,qBAAqB;GAC3D,CAAC;;;AAIN,SAAS,mBAAmB,UAAoG;AAC9H,QAAO,SAAS,KAAK,YAAY,gBAAgB,QAAQ,CAAC;;AAG5D,SAAS,wBACP,WACA,gBACU;CAEV,MAAM,YADO,aAAa,UAAU,SAAS,IAAI,YAAY,CAAC,GAAG,uBAAuB,EAErF,KAAK,MAAM,OAAO,EAAE,CAAC,MAAM,CAAC,CAC5B,QAAQ,MAAM,EAAE,SAAS,EAAE,CAC3B,QAAQ,MAAM,CAAC,uBAAuB,IAAI,EAAE,CAAC;AAChD,KAAI,kBAAkB,CAAC,SAAS,SAAA,oBAAqC,CACnE,UAAS,KAAK,4BAA4B;AAE5C,QAAO,CAAC,GAAG,IAAI,IAAI,SAAS,CAAC;;AAG/B,SAAS,YAAY,QAAgB,MAAmC,YAA6B;CACnG,MAAM,QAAkB,EAAE;AAC1B,KAAI,KAAK,cAAc,MAAM,CAAE,OAAM,KAAK,KAAK,aAAa,MAAM,CAAC;AACnE,KAAI,KAAK,MAAO,OAAM,KAAK,eAAe,KAAK,QAAQ;AACvD,KAAI,KAAK,MAAO,OAAM,KAAK,mBAAmB,KAAK,QAAQ;AAC3D,OAAM,KAAK,OAAO;AAClB,KAAI,WACF,OAAM,KACJ;EACE;EACA;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK,CACb;AAEH,QAAO,MAAM,KAAK,OAAO;;AAG3B,SAAS,wBAAwB,KAA0C;AACzE,KAAI;AACF,SAAO,KAAK;UACL,GAAG;AACV,MAAI,KAAK,EAAE,KAAK,GAAG,EAAE,2CAA2C;AAChE,SAAO;;;AAIX,SAAS,0BACP,YAC0B;AAC1B,QAAO;;AAGT,SAAS,sBAAsB,OAWL;AACxB,SAAQ,MAAM,MAAd;EACE,KAAK,aACH,QAAO;GACL,MAAM;GACN,YAAY,MAAM,cAAc;GAChC,UAAU,MAAM,YAAY;GAC5B,MAAM,MAAM,QAAQ,EAAE;GACvB;EACH,KAAK,WACH,QAAO;GACL,MAAM;GACN,YAAY,MAAM,cAAc;GAChC,UAAU,MAAM,YAAY;GAC5B,SAAS,QAAQ,MAAM,QAAQ;GAC/B,eAAe,MAAM;GACrB,OAAO,MAAM;GACd;EACH,KAAK,YACH,QAAO;GACL,MAAM;GACN,OAAO,MAAM,SAAS;GACtB,KAAK,MAAM,OAAO;GACnB;EACH,KAAK,aACH,QAAO;GAAE,MAAM;GAAc,OAAO,MAAM,SAAS;GAAI;EACzD,KAAK,iBACH,QAAO;GAAE,MAAM;GAAkB,OAAO,MAAM,SAAS;GAAI;EAC7D,QACE,QAAO;GAAE,MAAM;GAAc,OAAO;GAAI"}
|
|
1
|
+
{"version":3,"file":"subagent-runner.js","names":[],"sources":["../../../../src/agent/workflow/subagent-runner.ts"],"sourcesContent":["/**\n * Adapter: spawns one isolated child agent per `agent()` call from a workflow.\n *\n * Wraps the existing `createDelegateChildHandle` so the workflow runtime stays\n * decoupled from the LLM stack (it sees only the `SubagentRunner` interface).\n *\n * Key behaviour:\n * - When `opts.schema` is provided, we inject `structured_output` into the child\n * tool set and unwrap the captured value on success. If the subagent finishes\n * without ever calling `structured_output`, we treat it as failure (`null`).\n * - Failures and aborts resolve to `null`. The workflow runtime continues — this\n * matches the pi-dynamic-workflows contract and keeps fan-out pipelines robust.\n * - We do NOT mutate `createDelegateChildHandle` — we just leverage its\n * `buildChildTools` injection point.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\nimport type { Api, Model } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { SessionStore } from '../../session/store.js';\nimport { emitSessionTranscriptUpdate } from '../../session/transcript-events.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport {\n type BuildChildToolsOptions,\n createDelegateChildHandle,\n type DelegateChildHandleOptions,\n} from '../child-agent-factory.js';\nimport {\n DEFAULT_DELEGATE_TOOLS,\n DELEGATE_BLOCKED_TOOLS,\n} from '../tools/delegate-tool.js';\nimport type { ToolExecutorConfig } from '../tools/executor.js';\n\nimport {\n createStructuredOutputTool,\n STRUCTURED_OUTPUT_TOOL_NAME,\n type StructuredOutputCapture,\n} from './structured-output-tool.js';\nimport type { SubagentRunOptions, SubagentRunner, SubagentProgressEvent } from './types.js';\n\nconst log = createLogger('Agent:WorkflowSubagent');\n\nconst DEFAULT_MAX_ITERATIONS = 30;\n\nexport interface DelegateSubagentRunnerDeps {\n workspace: string;\n bus: MessageBus;\n agentId?: string;\n /** Resolves the default subagent model (typically the parent agent's primary model). */\n getDefaultModel: () => Model<Api>;\n getConfig: () => Config | undefined;\n toolExecutorConfig?: Partial<ToolExecutorConfig>;\n sessionStore?: SessionStore;\n /**\n * Provided by the workflow tool from `AgentToolsFactory` — mirrors how\n * `delegate-tool` is wired (avoids importing `tools/factory.ts` here and\n * breaking the existing factory ↔ delegate-tool ↔ child-agent-factory\n * dependency contract).\n */\n buildChildTools: (opts: BuildChildToolsOptions) => AgentTool<any, any>[];\n}\n\nexport class DelegateSubagentRunner implements SubagentRunner {\n constructor(private readonly deps: DelegateSubagentRunnerDeps) {}\n\n async run<T = string>(prompt: string, opts: SubagentRunOptions<T>): Promise<T | null> {\n if (opts.signal?.aborted) return null;\n\n const capture: StructuredOutputCapture<T> = { called: false, value: undefined };\n const wantStructured = Boolean(opts.schema);\n\n const allowed = resolveAllowedToolNames(opts.allowedToolNames, wantStructured);\n const model = opts.model ?? safeResolveDefaultModel(this.deps.getDefaultModel);\n if (!model) {\n log.warn({ label: opts.label }, 'subagent run skipped: no primary model resolved');\n return null;\n }\n\n const fullPrompt = buildPrompt(prompt, opts, wantStructured);\n const streamMode = resolveSubagentStreamMode(this.deps.getConfig);\n\n let transcriptPersistQueue: Promise<void> = Promise.resolve();\n const persistTranscriptSnapshot = opts.sessionKey && this.deps.sessionStore\n ? (messages: Parameters<SessionStore['saveMessages']>[1]) => {\n const store = this.deps.sessionStore;\n const key = opts.sessionKey;\n if (!store || !key) return;\n const snapshot = cloneAgentMessages(messages);\n transcriptPersistQueue = transcriptPersistQueue\n .then(async () => {\n await store.saveMessages(key, snapshot);\n emitSessionTranscriptUpdate({ sessionKey: key });\n })\n .catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, sessionKey: key, errorMessage: msg },\n `Failed to persist workflow subagent transcript snapshot: ${msg}`,\n );\n });\n }\n : undefined;\n\n const childOptions: DelegateChildHandleOptions = {\n workspace: this.deps.workspace,\n goal: fullPrompt,\n allowedToolNames: allowed,\n maxIterations: opts.maxIterations ?? DEFAULT_MAX_ITERATIONS,\n model,\n bus: this.deps.bus,\n agentId: this.deps.agentId,\n getConfig: this.deps.getConfig,\n toolExecutorConfig: this.deps.toolExecutorConfig,\n buildChildTools: (childOpts) => {\n const base = this.deps.buildChildTools({ ...childOpts, agentId: this.deps.agentId ?? childOpts.agentId });\n if (!wantStructured || !opts.schema) return base;\n // Replace any existing tool with the same name so the per-run capture wins.\n const filtered = base.filter((t) => t.name !== STRUCTURED_OUTPUT_TOOL_NAME);\n return [\n ...filtered,\n createStructuredOutputTool({ schema: opts.schema, capture }) as unknown as AgentTool<any, any>,\n ];\n },\n progressHooks:\n opts.onProgress && streamMode !== 'off'\n ? {\n mode: streamMode === 'full' ? 'full' : 'steps',\n onProgress: (event) => {\n opts.onProgress?.(mapChildProgressEvent(event));\n },\n }\n : undefined,\n onTranscriptSnapshot: persistTranscriptSnapshot,\n };\n\n if (opts.sessionKey && opts.sessionMetadata && this.deps.sessionStore) {\n await this.preparePersistentSubagentSession(opts.sessionKey, opts.sessionMetadata);\n }\n\n const handle = createDelegateChildHandle(childOptions);\n const onAbort = () => handle.abort();\n opts.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n const { summary, messages } = await handle.run();\n await transcriptPersistQueue;\n if (opts.sessionKey && this.deps.sessionStore) {\n await this.deps.sessionStore.saveMessages(opts.sessionKey, messages);\n emitSessionTranscriptUpdate({ sessionKey: opts.sessionKey });\n }\n if (opts.signal?.aborted) return null;\n\n if (wantStructured) {\n if (!capture.called) {\n log.warn({ label: opts.label }, 'subagent finished without calling structured_output');\n return null;\n }\n return capture.value as T;\n }\n return summary as unknown as T;\n } catch (e) {\n if (opts.rethrow) throw e;\n const msg = e instanceof Error ? e.message : String(e);\n log.warn({ err: e, label: opts.label, errorMessage: msg }, `subagent run failed: ${msg}`);\n return null;\n } finally {\n opts.signal?.removeEventListener('abort', onAbort);\n }\n }\n\n private async preparePersistentSubagentSession(\n sessionKey: string,\n metadata: NonNullable<SubagentRunOptions['sessionMetadata']>,\n ): Promise<void> {\n const store = this.deps.sessionStore;\n if (!store) return;\n await store.resolveTranscriptPath(sessionKey, {\n metadata: {\n sessionType: 'workflow-subagent',\n hiddenFromSessionList: true,\n parentSessionKey: metadata.parentSessionKey,\n workflowRunId: metadata.workflowRunId,\n workflowDefinitionId: metadata.workflowDefinitionId,\n workflowAgentId: metadata.workflowAgentId,\n workflowAgentLabel: metadata.workflowAgentLabel,\n sourceChannel: 'workflow',\n sourceChatId: metadata.workflowRunId,\n routing: {\n agentId: metadata.workflowAgentId || 'main',\n source: 'workflow',\n accountId: 'default',\n peerKind: 'subagent',\n peerId: metadata.workflowRunId,\n },\n },\n });\n await store.updateMetadata(sessionKey, {\n sessionType: 'workflow-subagent',\n hiddenFromSessionList: true,\n parentSessionKey: metadata.parentSessionKey,\n workflowRunId: metadata.workflowRunId,\n workflowDefinitionId: metadata.workflowDefinitionId,\n workflowAgentId: metadata.workflowAgentId,\n workflowAgentLabel: metadata.workflowAgentLabel,\n name: metadata.workflowAgentLabel,\n tags: ['workflow-subagent', metadata.workflowDefinitionId],\n });\n }\n}\n\nfunction cloneAgentMessages(messages: Parameters<SessionStore['saveMessages']>[1]): Parameters<SessionStore['saveMessages']>[1] {\n return messages.map((message) => structuredClone(message));\n}\n\nfunction resolveAllowedToolNames(\n requested: string[] | undefined,\n wantStructured: boolean,\n): string[] {\n const base = requested && requested.length > 0 ? requested : [...DEFAULT_DELEGATE_TOOLS];\n const filtered = base\n .map((s) => String(s).trim())\n .filter((s) => s.length > 0)\n .filter((s) => !DELEGATE_BLOCKED_TOOLS.has(s));\n if (wantStructured && !filtered.includes(STRUCTURED_OUTPUT_TOOL_NAME)) {\n filtered.push(STRUCTURED_OUTPUT_TOOL_NAME);\n }\n return [...new Set(filtered)];\n}\n\nfunction buildPrompt(prompt: string, opts: SubagentRunOptions<unknown>, structured: boolean): string {\n const parts: string[] = [];\n if (opts.instructions?.trim()) parts.push(opts.instructions.trim());\n if (opts.label) parts.push(`Task label: ${opts.label}`);\n if (opts.phase) parts.push(`Workflow phase: ${opts.phase}`);\n parts.push(prompt);\n if (structured) {\n parts.push(\n [\n 'Final output contract:',\n '- Your final action MUST be a structured_output tool call.',\n '- The structured_output arguments are the return value of this subagent.',\n '- Do not emit a prose final answer instead of structured_output.',\n '- If you need to inspect files or run commands first, do so, then call structured_output exactly once.',\n ].join('\\n'),\n );\n }\n return parts.join('\\n\\n');\n}\n\nfunction safeResolveDefaultModel(get: () => Model<Api>): Model<Api> | null {\n try {\n return get();\n } catch (e) {\n log.warn({ err: e }, 'failed to resolve default subagent model');\n return null;\n }\n}\n\nfunction resolveSubagentStreamMode(\n _getConfig: () => Config | undefined,\n): 'off' | 'steps' | 'full' {\n return 'steps';\n}\n\nfunction mapChildProgressEvent(event: {\n type: 'tool_start' | 'tool_end' | 'iteration' | 'text_delta' | 'thinking_delta';\n toolCallId?: string;\n toolName?: string;\n args?: Record<string, unknown>;\n isError?: boolean;\n resultPreview?: string;\n error?: string;\n count?: number;\n max?: number;\n delta?: string;\n}): SubagentProgressEvent {\n switch (event.type) {\n case 'tool_start':\n return {\n type: 'tool_start',\n toolCallId: event.toolCallId ?? '',\n toolName: event.toolName ?? 'tool',\n args: event.args ?? {},\n };\n case 'tool_end':\n return {\n type: 'tool_end',\n toolCallId: event.toolCallId ?? '',\n toolName: event.toolName ?? 'tool',\n isError: Boolean(event.isError),\n resultPreview: event.resultPreview,\n error: event.error,\n };\n case 'iteration':\n return {\n type: 'iteration',\n count: event.count ?? 0,\n max: event.max ?? 0,\n };\n case 'text_delta':\n return { type: 'text_delta', delta: event.delta ?? '' };\n case 'thinking_delta':\n return { type: 'thinking_delta', delta: event.delta ?? '' };\n default:\n return { type: 'text_delta', delta: '' };\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { resolveDreamingRootForAgent } from "../memory/dreaming/scope.js";
|
|
1
2
|
import { AgentToolsFactory } from "../tools/factory.js";
|
|
2
3
|
//#region src/agent/workflow/workflow-child-tools.ts
|
|
3
4
|
/** Builds the tool set for workflow child agents (wired from gateway to avoid cycles). */
|
|
4
5
|
function buildWorkflowChildTools(childOptions) {
|
|
6
|
+
const config = childOptions.getConfig();
|
|
7
|
+
const dreamingRoot = config && childOptions.agentId ? resolveDreamingRootForAgent(config, childOptions.agentId) : void 0;
|
|
5
8
|
return new AgentToolsFactory({
|
|
6
9
|
workspace: childOptions.workspace,
|
|
7
10
|
bus: childOptions.bus,
|
|
@@ -12,6 +15,8 @@ function buildWorkflowChildTools(childOptions) {
|
|
|
12
15
|
}).createAllTools({
|
|
13
16
|
workspace: childOptions.workspace,
|
|
14
17
|
getPrimaryModel: () => childOptions.model,
|
|
18
|
+
agentId: childOptions.agentId,
|
|
19
|
+
dreamingRoot,
|
|
15
20
|
disabledTools: new Set(["extensions"])
|
|
16
21
|
});
|
|
17
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-child-tools.js","names":[],"sources":["../../../../src/agent/workflow/workflow-child-tools.ts"],"sourcesContent":["import type { AgentTool } from '@earendil-works/pi-agent-core';\n\nimport type { BuildChildToolsOptions } from '../child-agent-factory.js';\nimport { AgentToolsFactory } from '../tools/factory.js';\n\n/** Builds the tool set for workflow child agents (wired from gateway to avoid cycles). */\nexport function buildWorkflowChildTools(childOptions: BuildChildToolsOptions): AgentTool<any, any>[] {\n const childFactory = new AgentToolsFactory({\n workspace: childOptions.workspace,\n bus: childOptions.bus,\n getCurrentContext: () => null,\n getConfig: childOptions.getConfig,\n getPrimaryModel: () => childOptions.model,\n toolExecutorConfig: childOptions.toolExecutorConfig,\n });\n return childFactory.createAllTools({\n workspace: childOptions.workspace,\n getPrimaryModel: () => childOptions.model,\n disabledTools: new Set(['extensions']),\n });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"workflow-child-tools.js","names":[],"sources":["../../../../src/agent/workflow/workflow-child-tools.ts"],"sourcesContent":["import type { AgentTool } from '@earendil-works/pi-agent-core';\n\nimport type { BuildChildToolsOptions } from '../child-agent-factory.js';\nimport { resolveDreamingRootForAgent } from '../memory/dreaming/scope.js';\nimport { AgentToolsFactory } from '../tools/factory.js';\n\n/** Builds the tool set for workflow child agents (wired from gateway to avoid cycles). */\nexport function buildWorkflowChildTools(childOptions: BuildChildToolsOptions): AgentTool<any, any>[] {\n const config = childOptions.getConfig();\n const dreamingRoot = config && childOptions.agentId\n ? resolveDreamingRootForAgent(config, childOptions.agentId)\n : undefined;\n const childFactory = new AgentToolsFactory({\n workspace: childOptions.workspace,\n bus: childOptions.bus,\n getCurrentContext: () => null,\n getConfig: childOptions.getConfig,\n getPrimaryModel: () => childOptions.model,\n toolExecutorConfig: childOptions.toolExecutorConfig,\n });\n return childFactory.createAllTools({\n workspace: childOptions.workspace,\n getPrimaryModel: () => childOptions.model,\n agentId: childOptions.agentId,\n dreamingRoot,\n disabledTools: new Set(['extensions']),\n });\n}\n"],"mappings":";;;;AAOA,SAAgB,wBAAwB,cAA6D;CACnG,MAAM,SAAS,aAAa,WAAW;CACvC,MAAM,eAAe,UAAU,aAAa,UACxC,4BAA4B,QAAQ,aAAa,QAAQ,GACzD,KAAA;AASJ,QAAO,IARkB,kBAAkB;EACzC,WAAW,aAAa;EACxB,KAAK,aAAa;EAClB,yBAAyB;EACzB,WAAW,aAAa;EACxB,uBAAuB,aAAa;EACpC,oBAAoB,aAAa;EAClC,CACkB,CAAC,eAAe;EACjC,WAAW,aAAa;EACxB,uBAAuB,aAAa;EACpC,SAAS,aAAa;EACtB;EACA,eAAe,IAAI,IAAI,CAAC,aAAa,CAAC;EACvC,CAAC"}
|
|
@@ -74,7 +74,7 @@ function buildEditInstructions(agentId, fileNames) {
|
|
|
74
74
|
"- “Read `SOUL.md` first, propose changes, then write them back.”",
|
|
75
75
|
"",
|
|
76
76
|
`Editable profile files: ${files}.`,
|
|
77
|
-
"I can read and update these by bare filename with `read_file`, `
|
|
77
|
+
"I can read and update these by bare filename with `read_file`, `apply_patch`, and `write_file`."
|
|
78
78
|
].join("\n");
|
|
79
79
|
}
|
|
80
80
|
const agentEditCommand = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-edit.js","names":[],"sources":["../../../src/chat-commands/agent-edit.ts"],"sourcesContent":["/**\n * /agent-edit — open the current chat as an agent profile editing session.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport type { CommandContext, CommandDefinition } from './types.js';\nimport { commandRegistry } from './registry.js';\nimport { resolveAgentIdFromSessionKey } from '../routing/agent-session-key.js';\nimport { normalizeAgentId, resolveAgentProfileDir } from '../agent/agent-scope.js';\nimport { WORKSPACE_FILES } from '../config/paths.js';\n\nconst PROFILE_FILE_NAMES = [\n WORKSPACE_FILES.SOUL,\n WORKSPACE_FILES.IDENTITY,\n WORKSPACE_FILES.TOOLS,\n WORKSPACE_FILES.AGENTS,\n WORKSPACE_FILES.HEARTBEAT,\n WORKSPACE_FILES.MEMORY,\n] as const;\n\nconst DEFAULT_PREVIEW_CHARS = 900;\nconst MAX_PREVIEW_CHARS = 4_000;\n\nfunction parseArgs(args: string): { fileName?: string; previewChars: number } {\n const trimmed = args.trim();\n if (!trimmed) {\n return { previewChars: DEFAULT_PREVIEW_CHARS };\n }\n\n const parts = trimmed.split(/\\s+/);\n let fileName: string | undefined;\n let previewChars = DEFAULT_PREVIEW_CHARS;\n\n for (const part of parts) {\n const limitMatch = /^--limit=(\\d+)$/.exec(part);\n if (limitMatch) {\n previewChars = Math.min(Number(limitMatch[1]), MAX_PREVIEW_CHARS);\n continue;\n }\n if (!fileName) {\n fileName = part;\n }\n }\n\n return { fileName, previewChars };\n}\n\nfunction normalizeProfileFileName(input: string | undefined): string | undefined {\n if (!input) {\n return undefined;\n }\n const basename = input.trim().replace(/\\\\/g, '/').split('/').pop();\n const matched = PROFILE_FILE_NAMES.find((name) => name.toLowerCase() === basename?.toLowerCase());\n return matched;\n}\n\nasync function readPreview(path: string, limit: number): Promise<{ content: string; missing: boolean }> {\n try {\n const content = await readFile(path, 'utf-8');\n const trimmed = content.trimEnd();\n if (trimmed.length <= limit) {\n return { content: trimmed, missing: false };\n }\n return {\n content: `${trimmed.slice(0, limit)}\\n\\n… truncated, ask me to read the full file before editing …`,\n missing: false,\n };\n } catch {\n return { content: '', missing: true };\n }\n}\n\nfunction buildEditInstructions(agentId: string, fileNames: readonly string[]): string {\n const files = fileNames.map((name) => `\\`${name}\\``).join(', ');\n return [\n `You are editing agent \\`${agentId}\\`.`,\n '',\n 'Tell me what to change, or say things like:',\n '- “Refine `SOUL.md` to sound warmer and more concise.”',\n '- “Update `IDENTITY.md` so this agent is focused on data analysis.”',\n '- “Read `SOUL.md` first, propose changes, then write them back.”',\n '',\n `Editable profile files: ${files}.`,\n 'I can read and update these by bare filename with `read_file`, `
|
|
1
|
+
{"version":3,"file":"agent-edit.js","names":[],"sources":["../../../src/chat-commands/agent-edit.ts"],"sourcesContent":["/**\n * /agent-edit — open the current chat as an agent profile editing session.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport type { CommandContext, CommandDefinition } from './types.js';\nimport { commandRegistry } from './registry.js';\nimport { resolveAgentIdFromSessionKey } from '../routing/agent-session-key.js';\nimport { normalizeAgentId, resolveAgentProfileDir } from '../agent/agent-scope.js';\nimport { WORKSPACE_FILES } from '../config/paths.js';\n\nconst PROFILE_FILE_NAMES = [\n WORKSPACE_FILES.SOUL,\n WORKSPACE_FILES.IDENTITY,\n WORKSPACE_FILES.TOOLS,\n WORKSPACE_FILES.AGENTS,\n WORKSPACE_FILES.HEARTBEAT,\n WORKSPACE_FILES.MEMORY,\n] as const;\n\nconst DEFAULT_PREVIEW_CHARS = 900;\nconst MAX_PREVIEW_CHARS = 4_000;\n\nfunction parseArgs(args: string): { fileName?: string; previewChars: number } {\n const trimmed = args.trim();\n if (!trimmed) {\n return { previewChars: DEFAULT_PREVIEW_CHARS };\n }\n\n const parts = trimmed.split(/\\s+/);\n let fileName: string | undefined;\n let previewChars = DEFAULT_PREVIEW_CHARS;\n\n for (const part of parts) {\n const limitMatch = /^--limit=(\\d+)$/.exec(part);\n if (limitMatch) {\n previewChars = Math.min(Number(limitMatch[1]), MAX_PREVIEW_CHARS);\n continue;\n }\n if (!fileName) {\n fileName = part;\n }\n }\n\n return { fileName, previewChars };\n}\n\nfunction normalizeProfileFileName(input: string | undefined): string | undefined {\n if (!input) {\n return undefined;\n }\n const basename = input.trim().replace(/\\\\/g, '/').split('/').pop();\n const matched = PROFILE_FILE_NAMES.find((name) => name.toLowerCase() === basename?.toLowerCase());\n return matched;\n}\n\nasync function readPreview(path: string, limit: number): Promise<{ content: string; missing: boolean }> {\n try {\n const content = await readFile(path, 'utf-8');\n const trimmed = content.trimEnd();\n if (trimmed.length <= limit) {\n return { content: trimmed, missing: false };\n }\n return {\n content: `${trimmed.slice(0, limit)}\\n\\n… truncated, ask me to read the full file before editing …`,\n missing: false,\n };\n } catch {\n return { content: '', missing: true };\n }\n}\n\nfunction buildEditInstructions(agentId: string, fileNames: readonly string[]): string {\n const files = fileNames.map((name) => `\\`${name}\\``).join(', ');\n return [\n `You are editing agent \\`${agentId}\\`.`,\n '',\n 'Tell me what to change, or say things like:',\n '- “Refine `SOUL.md` to sound warmer and more concise.”',\n '- “Update `IDENTITY.md` so this agent is focused on data analysis.”',\n '- “Read `SOUL.md` first, propose changes, then write them back.”',\n '',\n `Editable profile files: ${files}.`,\n 'I can read and update these by bare filename with `read_file`, `apply_patch`, and `write_file`.',\n ].join('\\n');\n}\n\nconst agentEditCommand: CommandDefinition = {\n id: 'agent.edit',\n name: 'agent-edit',\n aliases: ['agentedit'],\n description: 'Show editable profile files for the current agent and prepare this chat for profile edits.',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/agent-edit', '/agent-edit SOUL.md', '/agent-edit IDENTITY.md --limit=2000'],\n handler: async (ctx: CommandContext, args: string) => {\n await ctx.setTyping(true);\n\n const { fileName: rawFileName, previewChars } = parseArgs(args);\n const fileName = normalizeProfileFileName(rawFileName);\n if (rawFileName && !fileName) {\n return {\n content: `⚠️ Unsupported profile file: \\`${rawFileName}\\`. Use one of: ${PROFILE_FILE_NAMES.map((name) => `\\`${name}\\``).join(', ')}.`,\n success: false,\n };\n }\n\n const agentId = normalizeAgentId(resolveAgentIdFromSessionKey(ctx.sessionKey));\n const profileDir = resolveAgentProfileDir(ctx.config, agentId);\n const namesToShow = fileName ? [fileName] : [WORKSPACE_FILES.SOUL, WORKSPACE_FILES.IDENTITY];\n\n const sections: string[] = [];\n for (const name of namesToShow) {\n const preview = await readPreview(join(profileDir, name), previewChars);\n if (preview.missing) {\n sections.push(`## ${name}\\n_missing_`);\n } else {\n sections.push(`## ${name}\\n\\`\\`\\`markdown\\n${preview.content}\\n\\`\\`\\``);\n }\n }\n\n return {\n content: [\n '🛠️ Agent editor mode',\n '',\n buildEditInstructions(agentId, PROFILE_FILE_NAMES),\n '',\n `Profile directory: \\`${profileDir}\\``,\n '',\n ...sections,\n ].join('\\n'),\n success: true,\n };\n },\n};\n\nexport function registerAgentEditCommand(): void {\n commandRegistry.register(agentEditCommand);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerReviewCommand(): void;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { effectiveWorkspacePathForSession } from "../../session/session-workspace.js";
|
|
2
|
+
import { getProjectForSession } from "../../projects/workspace.js";
|
|
3
|
+
import { commandRegistry } from "../registry.js";
|
|
4
|
+
import { buildReviewDiffBundle, parseReviewTargetArgs, resolveGitRoot } from "../../review/review-git.js";
|
|
5
|
+
import { formatReviewMarkdown } from "../../review/review-types.js";
|
|
6
|
+
//#region src/chat-commands/builtins/review.ts
|
|
7
|
+
const MAX_DIFF_CHARS = 6e4;
|
|
8
|
+
function truncateForPrompt(text) {
|
|
9
|
+
if (text.length <= MAX_DIFF_CHARS) return {
|
|
10
|
+
text,
|
|
11
|
+
truncated: false
|
|
12
|
+
};
|
|
13
|
+
return {
|
|
14
|
+
text: text.slice(0, MAX_DIFF_CHARS) + "\n\n[diff truncated]",
|
|
15
|
+
truncated: true
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function extractJsonObject(raw) {
|
|
19
|
+
const text = (raw.match(/```(?:json)?\s*([\s\S]*?)```/i)?.[1] ?? raw).trim();
|
|
20
|
+
const start = text.indexOf("{");
|
|
21
|
+
const end = text.lastIndexOf("}");
|
|
22
|
+
if (start < 0 || end <= start) throw new Error("review response did not contain JSON");
|
|
23
|
+
return JSON.parse(text.slice(start, end + 1));
|
|
24
|
+
}
|
|
25
|
+
function priorityFrom(raw) {
|
|
26
|
+
const n = typeof raw === "number" ? raw : Number.parseInt(String(raw ?? ""), 10);
|
|
27
|
+
if (n === 0 || n === 1 || n === 2 || n === 3) return n;
|
|
28
|
+
return 2;
|
|
29
|
+
}
|
|
30
|
+
function numberFrom(raw) {
|
|
31
|
+
return typeof raw === "number" && Number.isFinite(raw) ? raw : void 0;
|
|
32
|
+
}
|
|
33
|
+
function stringFrom(raw) {
|
|
34
|
+
return typeof raw === "string" ? raw.trim() : "";
|
|
35
|
+
}
|
|
36
|
+
function parseReviewJson(raw, target) {
|
|
37
|
+
const parsed = extractJsonObject(raw);
|
|
38
|
+
const rec = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
39
|
+
const findings = (Array.isArray(rec.findings) ? rec.findings : []).map((item) => {
|
|
40
|
+
const f = item && typeof item === "object" && !Array.isArray(item) ? item : {};
|
|
41
|
+
const loc = f.code_location && typeof f.code_location === "object" ? f.code_location : {};
|
|
42
|
+
const range = loc.line_range && typeof loc.line_range === "object" ? loc.line_range : {};
|
|
43
|
+
const title = stringFrom(f.title);
|
|
44
|
+
const body = stringFrom(f.body);
|
|
45
|
+
if (!title && !body) return void 0;
|
|
46
|
+
const finding = {
|
|
47
|
+
title: title || body.slice(0, 80),
|
|
48
|
+
body,
|
|
49
|
+
priority: priorityFrom(f.priority)
|
|
50
|
+
};
|
|
51
|
+
const confidenceScore = numberFrom(f.confidence_score ?? f.confidenceScore);
|
|
52
|
+
const filePath = stringFrom(loc.file_path ?? f.filePath);
|
|
53
|
+
const lineStart = numberFrom(range.start ?? f.lineStart);
|
|
54
|
+
const lineEnd = numberFrom(range.end ?? f.lineEnd);
|
|
55
|
+
if (confidenceScore !== void 0) finding.confidenceScore = confidenceScore;
|
|
56
|
+
if (filePath) finding.filePath = filePath;
|
|
57
|
+
if (lineStart !== void 0) finding.lineStart = lineStart;
|
|
58
|
+
if (lineEnd !== void 0) finding.lineEnd = lineEnd;
|
|
59
|
+
return finding;
|
|
60
|
+
}).filter((item) => Boolean(item));
|
|
61
|
+
const correctness = stringFrom(rec.overall_correctness ?? rec.overallCorrectness);
|
|
62
|
+
const overallCorrectness = correctness === "patch is correct" || correctness === "patch is incorrect" ? correctness : "unknown";
|
|
63
|
+
return {
|
|
64
|
+
type: "review",
|
|
65
|
+
target,
|
|
66
|
+
summary: stringFrom(rec.summary) || `${findings.length} finding${findings.length === 1 ? "" : "s"}`,
|
|
67
|
+
findings,
|
|
68
|
+
overallCorrectness,
|
|
69
|
+
overallExplanation: stringFrom(rec.overall_explanation ?? rec.overallExplanation),
|
|
70
|
+
overallConfidenceScore: numberFrom(rec.overall_confidence_score ?? rec.overallConfidenceScore),
|
|
71
|
+
generatedAt: Date.now(),
|
|
72
|
+
source: "model"
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function buildReviewPrompt(params) {
|
|
76
|
+
return [
|
|
77
|
+
"You are a senior code reviewer. Review the provided git diff for correctness bugs only.",
|
|
78
|
+
"Prioritize concrete regressions, broken behavior, missing required tests for changed behavior, data loss, security issues, and runtime/type errors.",
|
|
79
|
+
"Do not mention style, broad refactors, praise, or speculative improvements.",
|
|
80
|
+
"Return strict JSON only with this shape:",
|
|
81
|
+
"{\"findings\":[{\"title\":\"...\",\"body\":\"...\",\"priority\":1,\"confidence_score\":0.9,\"code_location\":{\"file_path\":\"path\",\"line_range\":{\"start\":12,\"end\":12}}}],\"overall_correctness\":\"patch is correct\",\"overall_explanation\":\"...\",\"overall_confidence_score\":0.8,\"summary\":\"...\"}",
|
|
82
|
+
"Use priority 0 for release-blocking, 1 for high, 2 for medium, 3 for low.",
|
|
83
|
+
params.instructions ? `Extra reviewer instructions: ${params.instructions}` : "",
|
|
84
|
+
`Target: ${params.target}`,
|
|
85
|
+
params.truncated ? "The diff was truncated; only report findings supported by visible lines." : "",
|
|
86
|
+
"Git status:",
|
|
87
|
+
params.status || "(clean)",
|
|
88
|
+
"Diff stat:",
|
|
89
|
+
params.stat || "(none)",
|
|
90
|
+
"Diff:",
|
|
91
|
+
params.diff || "(none)"
|
|
92
|
+
].filter(Boolean).join("\n\n");
|
|
93
|
+
}
|
|
94
|
+
async function resolveWorkspace(ctx) {
|
|
95
|
+
const sessionConfigStore = ctx.getSessionConfigStore?.();
|
|
96
|
+
const sessionConfig = sessionConfigStore ? await sessionConfigStore.get(ctx.sessionKey).catch(() => null) : null;
|
|
97
|
+
return effectiveWorkspacePathForSession(ctx.config, ctx.sessionKey, sessionConfig, getProjectForSession(ctx.sessionKey));
|
|
98
|
+
}
|
|
99
|
+
async function buildReview(ctx, args) {
|
|
100
|
+
const cwd = await resolveGitRoot(await resolveWorkspace(ctx));
|
|
101
|
+
const reviewTarget = parseReviewTargetArgs(args);
|
|
102
|
+
const bundle = await buildReviewDiffBundle(cwd, reviewTarget);
|
|
103
|
+
const { text: diff, truncated } = truncateForPrompt(bundle.diff);
|
|
104
|
+
const target = bundle.targetLabel;
|
|
105
|
+
const instructions = reviewTarget.instructions ?? "";
|
|
106
|
+
if (!bundle.status.trim() && !bundle.diff.trim()) return {
|
|
107
|
+
type: "review",
|
|
108
|
+
target,
|
|
109
|
+
summary: "Working tree is clean.",
|
|
110
|
+
findings: [],
|
|
111
|
+
overallCorrectness: "patch is correct",
|
|
112
|
+
overallExplanation: "No uncommitted changes were found to review.",
|
|
113
|
+
generatedAt: Date.now(),
|
|
114
|
+
source: "local"
|
|
115
|
+
};
|
|
116
|
+
const prompt = buildReviewPrompt({
|
|
117
|
+
target,
|
|
118
|
+
status: bundle.status,
|
|
119
|
+
stat: bundle.stat,
|
|
120
|
+
diff,
|
|
121
|
+
truncated,
|
|
122
|
+
instructions
|
|
123
|
+
});
|
|
124
|
+
const answer = await ctx.btwQuery?.(prompt);
|
|
125
|
+
if (answer?.text && !answer.error) try {
|
|
126
|
+
return parseReviewJson(answer.text, target);
|
|
127
|
+
} catch {}
|
|
128
|
+
return {
|
|
129
|
+
type: "review",
|
|
130
|
+
target,
|
|
131
|
+
summary: "Review model was unavailable; returned a local diff summary.",
|
|
132
|
+
findings: [],
|
|
133
|
+
overallCorrectness: "unknown",
|
|
134
|
+
overallExplanation: [answer?.error ? `Reviewer model error: ${answer.error}` : "Reviewer model output could not be parsed.", bundle.stat.trim() ? `Changed files:\n${bundle.stat.trim()}` : "No textual diff stat was available."].join("\n\n"),
|
|
135
|
+
generatedAt: Date.now(),
|
|
136
|
+
source: "local"
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const reviewCommand = {
|
|
140
|
+
id: "coding.review",
|
|
141
|
+
name: "review",
|
|
142
|
+
description: "Review current workspace changes for correctness issues",
|
|
143
|
+
category: "tool",
|
|
144
|
+
scope: [
|
|
145
|
+
"global",
|
|
146
|
+
"private",
|
|
147
|
+
"group"
|
|
148
|
+
],
|
|
149
|
+
acceptsArgs: true,
|
|
150
|
+
examples: ["/review", "/review focus on auth and persistence"],
|
|
151
|
+
handler: async (ctx, args) => {
|
|
152
|
+
await ctx.setTyping(true);
|
|
153
|
+
const review = await buildReview(ctx, args);
|
|
154
|
+
return {
|
|
155
|
+
content: formatReviewMarkdown(review),
|
|
156
|
+
success: true,
|
|
157
|
+
metadata: { review }
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
function registerReviewCommand() {
|
|
162
|
+
commandRegistry.register(reviewCommand);
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
165
|
+
export { registerReviewCommand };
|
|
166
|
+
|
|
167
|
+
//# sourceMappingURL=review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.js","names":[],"sources":["../../../../src/chat-commands/builtins/review.ts"],"sourcesContent":["import type { CommandDefinition, CommandContext } from '../types.js';\nimport { commandRegistry } from '../registry.js';\nimport { effectiveWorkspacePathForSession } from '../../session/session-workspace.js';\nimport { getProjectForSession } from '../../projects/workspace.js';\nimport {\n buildReviewDiffBundle,\n parseReviewTargetArgs,\n resolveGitRoot,\n} from '../../review/review-git.js';\nimport {\n formatReviewMarkdown,\n type ReviewFinding,\n type ReviewOutput,\n type ReviewPriority,\n} from '../../review/review-types.js';\n\nconst MAX_DIFF_CHARS = 60_000;\n\nfunction truncateForPrompt(text: string): { text: string; truncated: boolean } {\n if (text.length <= MAX_DIFF_CHARS) return { text, truncated: false };\n return {\n text: text.slice(0, MAX_DIFF_CHARS) + '\\n\\n[diff truncated]',\n truncated: true,\n };\n}\n\nfunction extractJsonObject(raw: string): unknown {\n const fenced = raw.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n const text = (fenced?.[1] ?? raw).trim();\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start < 0 || end <= start) throw new Error('review response did not contain JSON');\n return JSON.parse(text.slice(start, end + 1));\n}\n\nfunction priorityFrom(raw: unknown): ReviewPriority {\n const n = typeof raw === 'number' ? raw : Number.parseInt(String(raw ?? ''), 10);\n if (n === 0 || n === 1 || n === 2 || n === 3) return n;\n return 2;\n}\n\nfunction numberFrom(raw: unknown): number | undefined {\n return typeof raw === 'number' && Number.isFinite(raw) ? raw : undefined;\n}\n\nfunction stringFrom(raw: unknown): string {\n return typeof raw === 'string' ? raw.trim() : '';\n}\n\nfunction parseReviewJson(raw: string, target: string): ReviewOutput {\n const parsed = extractJsonObject(raw);\n const rec = parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? parsed as Record<string, unknown>\n : {};\n const rawFindings = Array.isArray(rec.findings) ? rec.findings : [];\n const findings: ReviewFinding[] = rawFindings\n .map((item) => {\n const f = item && typeof item === 'object' && !Array.isArray(item)\n ? item as Record<string, unknown>\n : {};\n const loc = f.code_location && typeof f.code_location === 'object'\n ? f.code_location as Record<string, unknown>\n : {};\n const range = loc.line_range && typeof loc.line_range === 'object'\n ? loc.line_range as Record<string, unknown>\n : {};\n const title = stringFrom(f.title);\n const body = stringFrom(f.body);\n if (!title && !body) return undefined;\n const finding: ReviewFinding = {\n title: title || body.slice(0, 80),\n body,\n priority: priorityFrom(f.priority),\n };\n const confidenceScore = numberFrom(f.confidence_score ?? f.confidenceScore);\n const filePath = stringFrom(loc.file_path ?? f.filePath);\n const lineStart = numberFrom(range.start ?? f.lineStart);\n const lineEnd = numberFrom(range.end ?? f.lineEnd);\n if (confidenceScore !== undefined) finding.confidenceScore = confidenceScore;\n if (filePath) finding.filePath = filePath;\n if (lineStart !== undefined) finding.lineStart = lineStart;\n if (lineEnd !== undefined) finding.lineEnd = lineEnd;\n return finding;\n })\n .filter((item): item is ReviewFinding => Boolean(item));\n\n const correctness = stringFrom(rec.overall_correctness ?? rec.overallCorrectness);\n const overallCorrectness =\n correctness === 'patch is correct' || correctness === 'patch is incorrect'\n ? correctness\n : 'unknown';\n return {\n type: 'review',\n target,\n summary: stringFrom(rec.summary) || `${findings.length} finding${findings.length === 1 ? '' : 's'}`,\n findings,\n overallCorrectness,\n overallExplanation: stringFrom(rec.overall_explanation ?? rec.overallExplanation),\n overallConfidenceScore: numberFrom(rec.overall_confidence_score ?? rec.overallConfidenceScore),\n generatedAt: Date.now(),\n source: 'model',\n };\n}\n\nfunction buildReviewPrompt(params: {\n target: string;\n status: string;\n stat: string;\n diff: string;\n truncated: boolean;\n instructions: string;\n}): string {\n return [\n 'You are a senior code reviewer. Review the provided git diff for correctness bugs only.',\n 'Prioritize concrete regressions, broken behavior, missing required tests for changed behavior, data loss, security issues, and runtime/type errors.',\n 'Do not mention style, broad refactors, praise, or speculative improvements.',\n 'Return strict JSON only with this shape:',\n '{\"findings\":[{\"title\":\"...\",\"body\":\"...\",\"priority\":1,\"confidence_score\":0.9,\"code_location\":{\"file_path\":\"path\",\"line_range\":{\"start\":12,\"end\":12}}}],\"overall_correctness\":\"patch is correct\",\"overall_explanation\":\"...\",\"overall_confidence_score\":0.8,\"summary\":\"...\"}',\n 'Use priority 0 for release-blocking, 1 for high, 2 for medium, 3 for low.',\n params.instructions ? `Extra reviewer instructions: ${params.instructions}` : '',\n `Target: ${params.target}`,\n params.truncated ? 'The diff was truncated; only report findings supported by visible lines.' : '',\n 'Git status:',\n params.status || '(clean)',\n 'Diff stat:',\n params.stat || '(none)',\n 'Diff:',\n params.diff || '(none)',\n ].filter(Boolean).join('\\n\\n');\n}\n\nasync function resolveWorkspace(ctx: CommandContext): Promise<string> {\n const sessionConfigStore = ctx.getSessionConfigStore?.();\n const sessionConfig = sessionConfigStore\n ? await sessionConfigStore.get(ctx.sessionKey).catch(() => null)\n : null;\n return effectiveWorkspacePathForSession(\n ctx.config,\n ctx.sessionKey,\n sessionConfig,\n getProjectForSession(ctx.sessionKey),\n );\n}\n\nasync function buildReview(ctx: CommandContext, args: string): Promise<ReviewOutput> {\n const workspace = await resolveWorkspace(ctx);\n const cwd = await resolveGitRoot(workspace);\n const reviewTarget = parseReviewTargetArgs(args);\n const bundle = await buildReviewDiffBundle(cwd, reviewTarget);\n const { text: diff, truncated } = truncateForPrompt(bundle.diff);\n const target = bundle.targetLabel;\n const instructions = reviewTarget.instructions ?? '';\n\n if (!bundle.status.trim() && !bundle.diff.trim()) {\n return {\n type: 'review',\n target,\n summary: 'Working tree is clean.',\n findings: [],\n overallCorrectness: 'patch is correct',\n overallExplanation: 'No uncommitted changes were found to review.',\n generatedAt: Date.now(),\n source: 'local',\n };\n }\n\n const prompt = buildReviewPrompt({\n target,\n status: bundle.status,\n stat: bundle.stat,\n diff,\n truncated,\n instructions,\n });\n const answer = await ctx.btwQuery?.(prompt);\n if (answer?.text && !answer.error) {\n try {\n return parseReviewJson(answer.text, target);\n } catch {\n // Fall through to a deterministic local summary when model output is not parseable.\n }\n }\n\n return {\n type: 'review',\n target,\n summary: 'Review model was unavailable; returned a local diff summary.',\n findings: [],\n overallCorrectness: 'unknown',\n overallExplanation: [\n answer?.error ? `Reviewer model error: ${answer.error}` : 'Reviewer model output could not be parsed.',\n bundle.stat.trim() ? `Changed files:\\n${bundle.stat.trim()}` : 'No textual diff stat was available.',\n ].join('\\n\\n'),\n generatedAt: Date.now(),\n source: 'local',\n };\n}\n\nconst reviewCommand: CommandDefinition = {\n id: 'coding.review',\n name: 'review',\n description: 'Review current workspace changes for correctness issues',\n category: 'tool',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/review', '/review focus on auth and persistence'],\n handler: async (ctx: CommandContext, args: string) => {\n await ctx.setTyping(true);\n const review = await buildReview(ctx, args);\n return {\n content: formatReviewMarkdown(review),\n success: true,\n metadata: { review },\n };\n },\n};\n\nexport function registerReviewCommand(): void {\n commandRegistry.register(reviewCommand);\n}\n"],"mappings":";;;;;;AAgBA,MAAM,iBAAiB;AAEvB,SAAS,kBAAkB,MAAoD;AAC7E,KAAI,KAAK,UAAU,eAAgB,QAAO;EAAE;EAAM,WAAW;EAAO;AACpE,QAAO;EACL,MAAM,KAAK,MAAM,GAAG,eAAe,GAAG;EACtC,WAAW;EACZ;;AAGH,SAAS,kBAAkB,KAAsB;CAE/C,MAAM,QADS,IAAI,MAAM,gCACL,GAAG,MAAM,KAAK,MAAM;CACxC,MAAM,QAAQ,KAAK,QAAQ,IAAI;CAC/B,MAAM,MAAM,KAAK,YAAY,IAAI;AACjC,KAAI,QAAQ,KAAK,OAAO,MAAO,OAAM,IAAI,MAAM,uCAAuC;AACtF,QAAO,KAAK,MAAM,KAAK,MAAM,OAAO,MAAM,EAAE,CAAC;;AAG/C,SAAS,aAAa,KAA8B;CAClD,MAAM,IAAI,OAAO,QAAQ,WAAW,MAAM,OAAO,SAAS,OAAO,OAAO,GAAG,EAAE,GAAG;AAChF,KAAI,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,EAAG,QAAO;AACrD,QAAO;;AAGT,SAAS,WAAW,KAAkC;AACpD,QAAO,OAAO,QAAQ,YAAY,OAAO,SAAS,IAAI,GAAG,MAAM,KAAA;;AAGjE,SAAS,WAAW,KAAsB;AACxC,QAAO,OAAO,QAAQ,WAAW,IAAI,MAAM,GAAG;;AAGhD,SAAS,gBAAgB,KAAa,QAA8B;CAClE,MAAM,SAAS,kBAAkB,IAAI;CACrC,MAAM,MAAM,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,OAAO,GACtE,SACA,EAAE;CAEN,MAAM,YADc,MAAM,QAAQ,IAAI,SAAS,GAAG,IAAI,WAAW,EAAE,EAEhE,KAAK,SAAS;EACb,MAAM,IAAI,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,KAAK,GAC9D,OACA,EAAE;EACN,MAAM,MAAM,EAAE,iBAAiB,OAAO,EAAE,kBAAkB,WACtD,EAAE,gBACF,EAAE;EACN,MAAM,QAAQ,IAAI,cAAc,OAAO,IAAI,eAAe,WACtD,IAAI,aACJ,EAAE;EACN,MAAM,QAAQ,WAAW,EAAE,MAAM;EACjC,MAAM,OAAO,WAAW,EAAE,KAAK;AAC/B,MAAI,CAAC,SAAS,CAAC,KAAM,QAAO,KAAA;EAC5B,MAAM,UAAyB;GAC7B,OAAO,SAAS,KAAK,MAAM,GAAG,GAAG;GACjC;GACA,UAAU,aAAa,EAAE,SAAS;GACnC;EACD,MAAM,kBAAkB,WAAW,EAAE,oBAAoB,EAAE,gBAAgB;EAC3E,MAAM,WAAW,WAAW,IAAI,aAAa,EAAE,SAAS;EACxD,MAAM,YAAY,WAAW,MAAM,SAAS,EAAE,UAAU;EACxD,MAAM,UAAU,WAAW,MAAM,OAAO,EAAE,QAAQ;AAClD,MAAI,oBAAoB,KAAA,EAAW,SAAQ,kBAAkB;AAC7D,MAAI,SAAU,SAAQ,WAAW;AACjC,MAAI,cAAc,KAAA,EAAW,SAAQ,YAAY;AACjD,MAAI,YAAY,KAAA,EAAW,SAAQ,UAAU;AAC7C,SAAO;GACP,CACD,QAAQ,SAAgC,QAAQ,KAAK,CAAC;CAEzD,MAAM,cAAc,WAAW,IAAI,uBAAuB,IAAI,mBAAmB;CACjF,MAAM,qBACJ,gBAAgB,sBAAsB,gBAAgB,uBAClD,cACA;AACN,QAAO;EACL,MAAM;EACN;EACA,SAAS,WAAW,IAAI,QAAQ,IAAI,GAAG,SAAS,OAAO,UAAU,SAAS,WAAW,IAAI,KAAK;EAC9F;EACA;EACA,oBAAoB,WAAW,IAAI,uBAAuB,IAAI,mBAAmB;EACjF,wBAAwB,WAAW,IAAI,4BAA4B,IAAI,uBAAuB;EAC9F,aAAa,KAAK,KAAK;EACvB,QAAQ;EACT;;AAGH,SAAS,kBAAkB,QAOhB;AACT,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA,OAAO,eAAe,gCAAgC,OAAO,iBAAiB;EAC9E,WAAW,OAAO;EAClB,OAAO,YAAY,6EAA6E;EAChG;EACA,OAAO,UAAU;EACjB;EACA,OAAO,QAAQ;EACf;EACA,OAAO,QAAQ;EAChB,CAAC,OAAO,QAAQ,CAAC,KAAK,OAAO;;AAGhC,eAAe,iBAAiB,KAAsC;CACpE,MAAM,qBAAqB,IAAI,yBAAyB;CACxD,MAAM,gBAAgB,qBAClB,MAAM,mBAAmB,IAAI,IAAI,WAAW,CAAC,YAAY,KAAK,GAC9D;AACJ,QAAO,iCACL,IAAI,QACJ,IAAI,YACJ,eACA,qBAAqB,IAAI,WAAW,CACrC;;AAGH,eAAe,YAAY,KAAqB,MAAqC;CAEnF,MAAM,MAAM,MAAM,eAAe,MADT,iBAAiB,IAAI,CACF;CAC3C,MAAM,eAAe,sBAAsB,KAAK;CAChD,MAAM,SAAS,MAAM,sBAAsB,KAAK,aAAa;CAC7D,MAAM,EAAE,MAAM,MAAM,cAAc,kBAAkB,OAAO,KAAK;CAChE,MAAM,SAAS,OAAO;CACtB,MAAM,eAAe,aAAa,gBAAgB;AAElD,KAAI,CAAC,OAAO,OAAO,MAAM,IAAI,CAAC,OAAO,KAAK,MAAM,CAC9C,QAAO;EACL,MAAM;EACN;EACA,SAAS;EACT,UAAU,EAAE;EACZ,oBAAoB;EACpB,oBAAoB;EACpB,aAAa,KAAK,KAAK;EACvB,QAAQ;EACT;CAGH,MAAM,SAAS,kBAAkB;EAC/B;EACA,QAAQ,OAAO;EACf,MAAM,OAAO;EACb;EACA;EACA;EACD,CAAC;CACF,MAAM,SAAS,MAAM,IAAI,WAAW,OAAO;AAC3C,KAAI,QAAQ,QAAQ,CAAC,OAAO,MAC1B,KAAI;AACF,SAAO,gBAAgB,OAAO,MAAM,OAAO;SACrC;AAKV,QAAO;EACL,MAAM;EACN;EACA,SAAS;EACT,UAAU,EAAE;EACZ,oBAAoB;EACpB,oBAAoB,CAClB,QAAQ,QAAQ,yBAAyB,OAAO,UAAU,8CAC1D,OAAO,KAAK,MAAM,GAAG,mBAAmB,OAAO,KAAK,MAAM,KAAK,sCAChE,CAAC,KAAK,OAAO;EACd,aAAa,KAAK,KAAK;EACvB,QAAQ;EACT;;AAGH,MAAM,gBAAmC;CACvC,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,aAAa;CACb,UAAU,CAAC,WAAW,wCAAwC;CAC9D,SAAS,OAAO,KAAqB,SAAiB;AACpD,QAAM,IAAI,UAAU,KAAK;EACzB,MAAM,SAAS,MAAM,YAAY,KAAK,KAAK;AAC3C,SAAO;GACL,SAAS,qBAAqB,OAAO;GACrC,SAAS;GACT,UAAU,EAAE,QAAQ;GACrB;;CAEJ;AAED,SAAgB,wBAA8B;AAC5C,iBAAgB,SAAS,cAAc"}
|
|
@@ -20,6 +20,7 @@ export { registerContextCommands } from './builtins/context.js';
|
|
|
20
20
|
export { registerGoalCommand } from './builtins/goal.js';
|
|
21
21
|
export { registerSubgoalCommand } from './builtins/subgoal.js';
|
|
22
22
|
export { registerWorkflowCommands } from './builtins/workflow.js';
|
|
23
|
+
export { registerReviewCommand } from './builtins/review.js';
|
|
23
24
|
export { registerAgentEditCommand } from './agent-edit.js';
|
|
24
25
|
/**
|
|
25
26
|
* Initialize the command system with all built-in commands
|
|
@@ -11,6 +11,7 @@ import { registerContextCommands } from "./builtins/context.js";
|
|
|
11
11
|
import { registerGoalCommand } from "./builtins/goal.js";
|
|
12
12
|
import { registerSubgoalCommand } from "./builtins/subgoal.js";
|
|
13
13
|
import { registerWorkflowCommands } from "./builtins/workflow.js";
|
|
14
|
+
import { registerReviewCommand } from "./builtins/review.js";
|
|
14
15
|
import { registerAgentEditCommand } from "./agent-edit.js";
|
|
15
16
|
import { CommandContextImpl, createCommandContext } from "./context.js";
|
|
16
17
|
//#region src/chat-commands/index.ts
|
|
@@ -34,9 +35,10 @@ function initializeCommands() {
|
|
|
34
35
|
registerGoalCommand();
|
|
35
36
|
registerSubgoalCommand();
|
|
36
37
|
registerWorkflowCommands();
|
|
38
|
+
registerReviewCommand();
|
|
37
39
|
registerAgentEditCommand();
|
|
38
40
|
}
|
|
39
41
|
//#endregion
|
|
40
|
-
export { CommandContextImpl, CommandRegistry, commandRegistry, createCommandContext, generateSessionKey, getSessionDisplayName, initializeCommands, normalizeTelegramCommandName, parseSlashCommand, registerAgentEditCommand, registerConfigCommand, registerContextCommands, registerGoalCommand, registerModelCommands, registerSessionCommands, registerSubgoalCommand, registerSystemCommands, registerTTSCommands, registerThinkingCommands, registerWorkflowCommands };
|
|
42
|
+
export { CommandContextImpl, CommandRegistry, commandRegistry, createCommandContext, generateSessionKey, getSessionDisplayName, initializeCommands, normalizeTelegramCommandName, parseSlashCommand, registerAgentEditCommand, registerConfigCommand, registerContextCommands, registerGoalCommand, registerModelCommands, registerReviewCommand, registerSessionCommands, registerSubgoalCommand, registerSystemCommands, registerTTSCommands, registerThinkingCommands, registerWorkflowCommands };
|
|
41
43
|
|
|
42
44
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/chat-commands/index.ts"],"sourcesContent":["/**\n * Unified Command System\n *\n * Provides a platform-agnostic command system that works across\n * Telegram, Feishu, Web UI, CLI, and other channel surfaces.\n */\n\n// Built-in Commands (import first to avoid circular deps)\nimport { registerSessionCommands } from './builtins/session.js';\nimport { registerModelCommands } from './builtins/model.js';\nimport { registerSystemCommands } from './builtins/system.js';\nimport { registerTTSCommands } from './builtins/tts.js';\nimport { registerThinkingCommands } from './builtins/thinking.js';\nimport { registerConfigCommand } from './builtins/config.js';\nimport { registerContextCommands } from './builtins/context.js';\nimport { registerGoalCommand } from './builtins/goal.js';\nimport { registerSubgoalCommand } from './builtins/subgoal.js';\nimport { registerWorkflowCommands } from './builtins/workflow.js';\nimport { registerAgentEditCommand } from './agent-edit.js';\n\n// Types\nexport type {\n MessageSource,\n UnifiedMessage,\n PlatformMetadata,\n MessageAttachment,\n CommandDefinition,\n CommandCategory,\n CommandScope,\n CommandHandler,\n CommandResult,\n CommandContext,\n ReplyOptions,\n UIComponent,\n ButtonGroup,\n SelectMenu,\n ModelPicker,\n UsageDisplay,\n SessionList,\n TextInput,\n ProviderInfo,\n ModelInfo,\n UsageStats,\n SessionInfo,\n PlatformFeature,\n ChannelAdapter,\n ReplyPayload,\n} from './types.js';\n\n// Session display helpers\nexport { generateSessionKey, getSessionDisplayName, type SessionKeyContext } from './session-key.js';\n\n// Command parsing helpers\nexport { normalizeTelegramCommandName, parseSlashCommand } from './command-parse.js';\n\n// Registry\nexport { CommandRegistry, commandRegistry } from './registry.js';\nexport type { CommandRegistry as CommandRegistryType } from './types.js';\n\n// Context\nexport { CommandContextImpl, createCommandContext } from './context.js';\n\n// Built-in Commands\nexport { registerSessionCommands } from './builtins/session.js';\nexport { registerModelCommands } from './builtins/model.js';\nexport { registerSystemCommands } from './builtins/system.js';\nexport { registerTTSCommands } from './builtins/tts.js';\nexport { registerThinkingCommands } from './builtins/thinking.js';\nexport { registerConfigCommand } from './builtins/config.js';\nexport { registerContextCommands } from './builtins/context.js';\nexport { registerGoalCommand } from './builtins/goal.js';\nexport { registerSubgoalCommand } from './builtins/subgoal.js';\nexport { registerWorkflowCommands } from './builtins/workflow.js';\nexport { registerAgentEditCommand } from './agent-edit.js';\n\n/**\n * Initialize the command system with all built-in commands\n */\nexport function initializeCommands(): void {\n registerSessionCommands();\n registerModelCommands();\n registerSystemCommands();\n registerConfigCommand();\n registerContextCommands();\n registerTTSCommands();\n registerThinkingCommands();\n registerGoalCommand();\n registerSubgoalCommand();\n registerWorkflowCommands();\n registerAgentEditCommand();\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/chat-commands/index.ts"],"sourcesContent":["/**\n * Unified Command System\n *\n * Provides a platform-agnostic command system that works across\n * Telegram, Feishu, Web UI, CLI, and other channel surfaces.\n */\n\n// Built-in Commands (import first to avoid circular deps)\nimport { registerSessionCommands } from './builtins/session.js';\nimport { registerModelCommands } from './builtins/model.js';\nimport { registerSystemCommands } from './builtins/system.js';\nimport { registerTTSCommands } from './builtins/tts.js';\nimport { registerThinkingCommands } from './builtins/thinking.js';\nimport { registerConfigCommand } from './builtins/config.js';\nimport { registerContextCommands } from './builtins/context.js';\nimport { registerGoalCommand } from './builtins/goal.js';\nimport { registerSubgoalCommand } from './builtins/subgoal.js';\nimport { registerWorkflowCommands } from './builtins/workflow.js';\nimport { registerReviewCommand } from './builtins/review.js';\nimport { registerAgentEditCommand } from './agent-edit.js';\n\n// Types\nexport type {\n MessageSource,\n UnifiedMessage,\n PlatformMetadata,\n MessageAttachment,\n CommandDefinition,\n CommandCategory,\n CommandScope,\n CommandHandler,\n CommandResult,\n CommandContext,\n ReplyOptions,\n UIComponent,\n ButtonGroup,\n SelectMenu,\n ModelPicker,\n UsageDisplay,\n SessionList,\n TextInput,\n ProviderInfo,\n ModelInfo,\n UsageStats,\n SessionInfo,\n PlatformFeature,\n ChannelAdapter,\n ReplyPayload,\n} from './types.js';\n\n// Session display helpers\nexport { generateSessionKey, getSessionDisplayName, type SessionKeyContext } from './session-key.js';\n\n// Command parsing helpers\nexport { normalizeTelegramCommandName, parseSlashCommand } from './command-parse.js';\n\n// Registry\nexport { CommandRegistry, commandRegistry } from './registry.js';\nexport type { CommandRegistry as CommandRegistryType } from './types.js';\n\n// Context\nexport { CommandContextImpl, createCommandContext } from './context.js';\n\n// Built-in Commands\nexport { registerSessionCommands } from './builtins/session.js';\nexport { registerModelCommands } from './builtins/model.js';\nexport { registerSystemCommands } from './builtins/system.js';\nexport { registerTTSCommands } from './builtins/tts.js';\nexport { registerThinkingCommands } from './builtins/thinking.js';\nexport { registerConfigCommand } from './builtins/config.js';\nexport { registerContextCommands } from './builtins/context.js';\nexport { registerGoalCommand } from './builtins/goal.js';\nexport { registerSubgoalCommand } from './builtins/subgoal.js';\nexport { registerWorkflowCommands } from './builtins/workflow.js';\nexport { registerReviewCommand } from './builtins/review.js';\nexport { registerAgentEditCommand } from './agent-edit.js';\n\n/**\n * Initialize the command system with all built-in commands\n */\nexport function initializeCommands(): void {\n registerSessionCommands();\n registerModelCommands();\n registerSystemCommands();\n registerConfigCommand();\n registerContextCommands();\n registerTTSCommands();\n registerThinkingCommands();\n registerGoalCommand();\n registerSubgoalCommand();\n registerWorkflowCommands();\n registerReviewCommand();\n registerAgentEditCommand();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAgFA,SAAgB,qBAA2B;AACzC,0BAAyB;AACzB,wBAAuB;AACvB,yBAAwB;AACxB,wBAAuB;AACvB,0BAAyB;AACzB,sBAAqB;AACrB,2BAA0B;AAC1B,sBAAqB;AACrB,yBAAwB;AACxB,2BAA0B;AAC1B,wBAAuB;AACvB,2BAA0B"}
|
|
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
|
|
|
52
52
|
id: "database-schema",
|
|
53
53
|
label: "Database schema",
|
|
54
54
|
status: "pass",
|
|
55
|
-
message: `SQLite schema v${status.dbVersion} (current release
|
|
55
|
+
message: `SQLite schema v${status.dbVersion} (current release v23).`,
|
|
56
56
|
hints: []
|
|
57
57
|
};
|
|
58
58
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { init_paths, resolveConfigPath } from "../../../config/paths.js";
|
|
2
2
|
import { loadConfig } from "../../../config/loader.js";
|
|
3
3
|
import "../../../config/index.js";
|
|
4
|
-
import { isRestartEnabled } from "../../../config/commands.flags.js";
|
|
5
4
|
import { resolveGatewayService } from "../../../daemon/service.js";
|
|
5
|
+
import { isRestartEnabled } from "../../../config/commands.flags.js";
|
|
6
6
|
import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "../../../infra/restart.js";
|
|
7
7
|
import { findVerifiedGatewayListenerPidsOnPortSync, formatGatewayPidList, signalVerifiedGatewayPidSync } from "../../../infra/gateway-processes.js";
|
|
8
8
|
import { runServiceRestart, runServiceStop } from "./lifecycle-core.js";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { Config } from '../config/schema.js';
|
|
2
|
-
import type { ConnectorHealthResult } from './types.js';
|
|
2
|
+
import type { ConnectorDefinition, ConnectorHealthResult, ConnectorInstallInput } from './types.js';
|
|
3
3
|
export declare function testConnectorInstance(config: Config, serverId: string): Promise<ConnectorHealthResult>;
|
|
4
|
+
export declare function previewConnectorDefinition(config: Config, definition: ConnectorDefinition, input?: ConnectorInstallInput): Promise<ConnectorHealthResult>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { listBundleMcpServerCapabilitiesForGateway } from "../agent/mcp/bundle-mcp-materialize.js";
|
|
2
2
|
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
3
|
+
import { materializeConnectorMcpServer } from "./materialize.js";
|
|
3
4
|
import { getConnectorInstance } from "./instances.js";
|
|
4
5
|
//#region src/connectors/health.ts
|
|
5
6
|
function classifyConnectorHealthError(error) {
|
|
@@ -79,7 +80,64 @@ async function testConnectorInstance(config, serverId) {
|
|
|
79
80
|
};
|
|
80
81
|
}
|
|
81
82
|
}
|
|
83
|
+
async function previewConnectorDefinition(config, definition, input = {}) {
|
|
84
|
+
if (definition.runtime.type !== "mcp") return {
|
|
85
|
+
serverId: definition.id,
|
|
86
|
+
ok: false,
|
|
87
|
+
status: "unknown_error",
|
|
88
|
+
toolCount: 0,
|
|
89
|
+
resourceCount: 0,
|
|
90
|
+
promptCount: 0,
|
|
91
|
+
tools: [],
|
|
92
|
+
resources: [],
|
|
93
|
+
prompts: [],
|
|
94
|
+
error: `Connector type "${definition.runtime.type}" does not support MCP capability preview.`
|
|
95
|
+
};
|
|
96
|
+
try {
|
|
97
|
+
const { serverId, server } = materializeConnectorMcpServer(definition, input);
|
|
98
|
+
const capabilities = await listBundleMcpServerCapabilitiesForGateway({
|
|
99
|
+
workspaceDir: getWorkspacePath(config) || "./workspace",
|
|
100
|
+
cfg: {
|
|
101
|
+
...config,
|
|
102
|
+
mcp: {
|
|
103
|
+
...config.mcp ?? {},
|
|
104
|
+
servers: {
|
|
105
|
+
...config.mcp?.servers ?? {},
|
|
106
|
+
[serverId]: server
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
serverId
|
|
111
|
+
});
|
|
112
|
+
return {
|
|
113
|
+
serverId,
|
|
114
|
+
ok: true,
|
|
115
|
+
status: "ok",
|
|
116
|
+
toolCount: capabilities.toolCount,
|
|
117
|
+
resourceCount: capabilities.resourceCount,
|
|
118
|
+
promptCount: capabilities.promptCount,
|
|
119
|
+
tools: capabilities.tools,
|
|
120
|
+
resources: capabilities.resources,
|
|
121
|
+
prompts: capabilities.prompts
|
|
122
|
+
};
|
|
123
|
+
} catch (error) {
|
|
124
|
+
const status = classifyConnectorHealthError(error);
|
|
125
|
+
return {
|
|
126
|
+
serverId: definition.id,
|
|
127
|
+
ok: false,
|
|
128
|
+
status,
|
|
129
|
+
toolCount: 0,
|
|
130
|
+
resourceCount: 0,
|
|
131
|
+
promptCount: 0,
|
|
132
|
+
tools: [],
|
|
133
|
+
resources: [],
|
|
134
|
+
prompts: [],
|
|
135
|
+
error: error instanceof Error ? error.message : String(error),
|
|
136
|
+
action: healthActionForStatus(status)
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
82
140
|
//#endregion
|
|
83
|
-
export { testConnectorInstance };
|
|
141
|
+
export { previewConnectorDefinition, testConnectorInstance };
|
|
84
142
|
|
|
85
143
|
//# sourceMappingURL=health.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health.js","names":[],"sources":["../../../src/connectors/health.ts"],"sourcesContent":["import { getWorkspacePath } from '../config/workspace-path-helpers.js';\nimport {\n listBundleMcpServerCapabilitiesForGateway,\n} from '../agent/mcp/bundle-mcp-materialize.js';\nimport type { Config } from '../config/schema.js';\nimport { getConnectorInstance } from './instances.js';\nimport type { ConnectorHealthResult, ConnectorHealthStatus } from './types.js';\n\nfunction classifyConnectorHealthError(error: unknown): ConnectorHealthStatus {\n const message = error instanceof Error ? error.message : String(error);\n if (/timed out|timeout/i.test(message)) {\n return 'timeout';\n }\n if (/ECONN|ENOTFOUND|network|fetch failed/i.test(message)) {\n return 'network_failed';\n }\n if (/401|unauthorized|forbidden|permission denied/i.test(message)) {\n return 'unauthorized';\n }\n if (/missing|required|credential|api key|token/i.test(message)) {\n return 'missing_secret';\n }\n if (/tools|listTools/i.test(message)) {\n return 'tools_list_failed';\n }\n if (/spawn|command|start|connect/i.test(message)) {\n return 'startup_failed';\n }\n return 'unknown_error';\n}\n\nfunction healthActionForStatus(status: ConnectorHealthStatus): string | undefined {\n if (status === 'missing_secret') {\n return 'Reconnect the connector and provide the required secret.';\n }\n if (status === 'timeout' || status === 'network_failed') {\n return 'Check network access and retry the connector health check.';\n }\n if (status === 'startup_failed') {\n return 'Verify the connector runtime dependency is installed and reachable.';\n }\n if (status === 'unauthorized') {\n return 'Reconnect the connector or refresh its credentials.';\n }\n return undefined;\n}\n\nexport async function testConnectorInstance(config: Config, serverId: string): Promise<ConnectorHealthResult> {\n const instance = getConnectorInstance(config, serverId);\n if (!instance) {\n return {\n serverId,\n ok: false,\n status: 'server_not_found',\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: `Connector instance not found: ${serverId}`,\n };\n }\n\n if (!instance.enabled) {\n return {\n serverId,\n ok: false,\n status: 'disabled',\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n action: 'Enable the connector before running a health check.',\n };\n }\n\n const workspaceDir = getWorkspacePath(config) || './workspace';\n try {\n const capabilities = await listBundleMcpServerCapabilitiesForGateway({\n workspaceDir,\n cfg: config,\n serverId,\n });\n return {\n serverId,\n ok: true,\n status: 'ok',\n toolCount: capabilities.toolCount,\n resourceCount: capabilities.resourceCount,\n promptCount: capabilities.promptCount,\n tools: capabilities.tools,\n resources: capabilities.resources,\n prompts: capabilities.prompts,\n };\n } catch (error) {\n const status = classifyConnectorHealthError(error);\n return {\n serverId,\n ok: false,\n status,\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: error instanceof Error ? error.message : String(error),\n action: healthActionForStatus(status),\n };\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"health.js","names":[],"sources":["../../../src/connectors/health.ts"],"sourcesContent":["import { getWorkspacePath } from '../config/workspace-path-helpers.js';\nimport {\n listBundleMcpServerCapabilitiesForGateway,\n} from '../agent/mcp/bundle-mcp-materialize.js';\nimport type { Config } from '../config/schema.js';\nimport { getConnectorInstance } from './instances.js';\nimport { materializeConnectorMcpServer } from './materialize.js';\nimport type { ConnectorDefinition, ConnectorHealthResult, ConnectorHealthStatus, ConnectorInstallInput } from './types.js';\n\nfunction classifyConnectorHealthError(error: unknown): ConnectorHealthStatus {\n const message = error instanceof Error ? error.message : String(error);\n if (/timed out|timeout/i.test(message)) {\n return 'timeout';\n }\n if (/ECONN|ENOTFOUND|network|fetch failed/i.test(message)) {\n return 'network_failed';\n }\n if (/401|unauthorized|forbidden|permission denied/i.test(message)) {\n return 'unauthorized';\n }\n if (/missing|required|credential|api key|token/i.test(message)) {\n return 'missing_secret';\n }\n if (/tools|listTools/i.test(message)) {\n return 'tools_list_failed';\n }\n if (/spawn|command|start|connect/i.test(message)) {\n return 'startup_failed';\n }\n return 'unknown_error';\n}\n\nfunction healthActionForStatus(status: ConnectorHealthStatus): string | undefined {\n if (status === 'missing_secret') {\n return 'Reconnect the connector and provide the required secret.';\n }\n if (status === 'timeout' || status === 'network_failed') {\n return 'Check network access and retry the connector health check.';\n }\n if (status === 'startup_failed') {\n return 'Verify the connector runtime dependency is installed and reachable.';\n }\n if (status === 'unauthorized') {\n return 'Reconnect the connector or refresh its credentials.';\n }\n return undefined;\n}\n\nexport async function testConnectorInstance(config: Config, serverId: string): Promise<ConnectorHealthResult> {\n const instance = getConnectorInstance(config, serverId);\n if (!instance) {\n return {\n serverId,\n ok: false,\n status: 'server_not_found',\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: `Connector instance not found: ${serverId}`,\n };\n }\n\n if (!instance.enabled) {\n return {\n serverId,\n ok: false,\n status: 'disabled',\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n action: 'Enable the connector before running a health check.',\n };\n }\n\n const workspaceDir = getWorkspacePath(config) || './workspace';\n try {\n const capabilities = await listBundleMcpServerCapabilitiesForGateway({\n workspaceDir,\n cfg: config,\n serverId,\n });\n return {\n serverId,\n ok: true,\n status: 'ok',\n toolCount: capabilities.toolCount,\n resourceCount: capabilities.resourceCount,\n promptCount: capabilities.promptCount,\n tools: capabilities.tools,\n resources: capabilities.resources,\n prompts: capabilities.prompts,\n };\n } catch (error) {\n const status = classifyConnectorHealthError(error);\n return {\n serverId,\n ok: false,\n status,\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: error instanceof Error ? error.message : String(error),\n action: healthActionForStatus(status),\n };\n }\n}\n\nexport async function previewConnectorDefinition(\n config: Config,\n definition: ConnectorDefinition,\n input: ConnectorInstallInput = {},\n): Promise<ConnectorHealthResult> {\n if (definition.runtime.type !== 'mcp') {\n return {\n serverId: definition.id,\n ok: false,\n status: 'unknown_error',\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: `Connector type \"${definition.runtime.type}\" does not support MCP capability preview.`,\n };\n }\n\n try {\n const { serverId, server } = materializeConnectorMcpServer(definition, input);\n const workspaceDir = getWorkspacePath(config) || './workspace';\n const previewConfig: Config = {\n ...config,\n mcp: {\n ...(config.mcp ?? {}),\n servers: {\n ...(config.mcp?.servers ?? {}),\n [serverId]: server,\n },\n },\n };\n const capabilities = await listBundleMcpServerCapabilitiesForGateway({\n workspaceDir,\n cfg: previewConfig,\n serverId,\n });\n return {\n serverId,\n ok: true,\n status: 'ok',\n toolCount: capabilities.toolCount,\n resourceCount: capabilities.resourceCount,\n promptCount: capabilities.promptCount,\n tools: capabilities.tools,\n resources: capabilities.resources,\n prompts: capabilities.prompts,\n };\n } catch (error) {\n const status = classifyConnectorHealthError(error);\n return {\n serverId: definition.id,\n ok: false,\n status,\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: error instanceof Error ? error.message : String(error),\n action: healthActionForStatus(status),\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -3,4 +3,5 @@ import type { Config } from '../config/schema.js';
|
|
|
3
3
|
import type { ConnectorDefinition, ConnectorInstallInput, ConnectorInstance } from './types.js';
|
|
4
4
|
export declare function installConnectorDefinition(config: Config, definition: ConnectorDefinition, input: ConnectorInstallInput, resolver?: CredentialResolver): Promise<ConnectorInstance>;
|
|
5
5
|
export declare function installConnector(config: Config, connectorId: string, input: ConnectorInstallInput, resolver?: CredentialResolver): Promise<ConnectorInstance>;
|
|
6
|
+
export declare function updateConnectorConfig(config: Config, instanceId: string, input: ConnectorInstallInput): ConnectorInstance;
|
|
6
7
|
export declare function uninstallConnector(config: Config, instanceId: string): ConnectorInstance;
|
|
@@ -51,6 +51,33 @@ async function installConnector(config, connectorId, input, resolver = new Crede
|
|
|
51
51
|
if (!definition) throw new Error(`Unknown connector: ${connectorId}`);
|
|
52
52
|
return installConnectorDefinition(config, definition, input, resolver);
|
|
53
53
|
}
|
|
54
|
+
function updateConnectorConfig(config, instanceId, input) {
|
|
55
|
+
const existingServer = config.mcp?.servers?.[instanceId];
|
|
56
|
+
if (!existingServer || !isManagedConnectorServer(existingServer)) throw new Error(`MCP server "${instanceId}" is not managed by Connectors.`);
|
|
57
|
+
const definition = getConnectorDefinition(existingServer.xopcConnector.connectorId);
|
|
58
|
+
if (!definition) throw new Error(`Unknown connector: ${existingServer.xopcConnector.connectorId}`);
|
|
59
|
+
if (definition.runtime.type !== "mcp") throw new Error(`Connector type "${definition.runtime.type}" does not support config updates.`);
|
|
60
|
+
if ((definition.setup.secrets ?? []).length > 0) throw new Error("Connectors with secrets must be reinstalled to change configuration.");
|
|
61
|
+
const { serverId, server } = materializeConnectorMcpServer(definition, input);
|
|
62
|
+
if (serverId !== instanceId) throw new Error(`Connector config update cannot change server id from "${instanceId}" to "${serverId}".`);
|
|
63
|
+
config.mcp = config.mcp ?? {};
|
|
64
|
+
config.mcp.servers = {
|
|
65
|
+
...config.mcp.servers ?? {},
|
|
66
|
+
[serverId]: {
|
|
67
|
+
...server,
|
|
68
|
+
xopcConnector: {
|
|
69
|
+
...existingServer.xopcConnector,
|
|
70
|
+
...server.xopcConnector,
|
|
71
|
+
enabled: existingServer.xopcConnector.enabled,
|
|
72
|
+
lastConnectedAt: existingServer.xopcConnector.lastConnectedAt,
|
|
73
|
+
lastError: existingServer.xopcConnector.lastError
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const instance = listConnectorInstances(config).find((candidate) => candidate.instanceId === serverId);
|
|
78
|
+
if (!instance) throw new Error(`Connector "${definition.id}" was updated but could not be resolved.`);
|
|
79
|
+
return instance;
|
|
80
|
+
}
|
|
54
81
|
function uninstallConnector(config, instanceId) {
|
|
55
82
|
const server = config.mcp?.servers?.[instanceId];
|
|
56
83
|
const connectorRecord = config.connectors?.instances?.[instanceId];
|
|
@@ -78,6 +105,6 @@ function uninstallConnector(config, instanceId) {
|
|
|
78
105
|
return instance;
|
|
79
106
|
}
|
|
80
107
|
//#endregion
|
|
81
|
-
export { installConnector, installConnectorDefinition, uninstallConnector };
|
|
108
|
+
export { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig };
|
|
82
109
|
|
|
83
110
|
//# sourceMappingURL=install.js.map
|