@xopcai/xopc 0.0.113 → 0.0.115
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/feishu/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
- package/dist/extensions/telegram/src/inbound-processor.js +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/src/update-offset-store.js +1 -1
- package/dist/extensions/telegram/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +2 -2
- package/dist/extensions/weixin/src/auth/accounts.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/media/data-url.js +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
- package/dist/extensions/weixin/src/workflow-progress.js +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CBlklyNr.js → agent-avatar-dicebear-DVnBfANm.js} +1 -1
- package/dist/gateway/static/root/assets/agent-browser-settings-page-DPXc4hz8.js +6 -0
- package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-CTJ0YnRQ.js +1 -0
- package/dist/gateway/static/root/assets/agents-zJXQfJ_W.js +71 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-28E_WfMe.js → app-management-settings-panel-DzGbdr04.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-Do1z0XgJ.js → appearance-settings-BQpPSTHD.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-CPjfyzSD.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BAFlsov_.js → archive-plugin-CXu-Csep.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-V3qGPC3x.js → attachment-load-BAjgOoGY.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-DT8NvA6W.js → binary-plugins-BSBgB2hO.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CdLMEcHd.js → block-editor-BpXw9TTR.js} +3 -3
- package/dist/gateway/static/root/assets/channels-settings-BbPUpzWB.js +1 -0
- package/dist/gateway/static/root/assets/{config-api-Bf5mjpu7.js → config-api-NOoPiIYz.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-settings-CAXYMOdp.js +2 -0
- package/dist/gateway/static/root/assets/{cron-api--pAB_rps.js → cron-api-C9BOqAXd.js} +1 -1
- package/dist/gateway/static/root/assets/cron-page-DuUbBeKI.js +3 -0
- package/dist/gateway/static/root/assets/{dreaming-settings-6UZE1FSK.js → dreaming-settings-DQ4DtiK1.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BGhE7msg.js → extension-debug-page-D9kgUHCc.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CvpI45WG.js → extension-page-CGyhXqzR.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DAmR5FUe.js → extension-settings-page-DL8Xquqd.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-NZmjSXLl.js → fetch-D0VXA932.js} +1 -1
- package/dist/gateway/static/root/assets/{format-interval-label-qhth3BMV.js → format-interval-label-Be8SmgUw.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-CaXBt-9R.js → gateway-config-api-C-xjn__h.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-DphpbLBc.js → gateway-settings-BMPwIjKI.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-Be1omjh3.js → gateway-startup-retry-DERUH61L.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-BJsyjJnF.js +1 -0
- package/dist/gateway/static/root/assets/goals-config-api-BPmqWk90.js +1 -0
- package/dist/gateway/static/root/assets/goals-page-BerDgIhw.js +2 -0
- package/dist/gateway/static/root/assets/goals-settings-ByTjeAto.js +1 -0
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BzO6G4fD.js → heartbeat-config-api-Bfdzr8oV.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-DCST9-du.js → heartbeat-settings-TbHgcjTn.js} +1 -1
- package/dist/gateway/static/root/assets/index-AkTrf6Pb.js +122 -0
- package/dist/gateway/static/root/assets/index-fh5sXTj9.css +1 -0
- package/dist/gateway/static/root/assets/{interval-presets-DJmshV8n.js → interval-presets-utKbuCRY.js} +1 -1
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-9AUUlQ5Q.js → keyboard-shortcuts-settings-CjqS6c6V.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-DGXuPf5B.js +2 -0
- package/dist/gateway/static/root/assets/{markdown-split-CYYELqAr.js → markdown-split-DW8C47iB.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-BEcMR2M8.js → media-plugins-D6HwDhDT.js} +1 -1
- package/dist/gateway/static/root/assets/messages-upgxw6Ub.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-Bot16nn7.js +2 -0
- package/dist/gateway/static/root/assets/note-detail-page-Brlyou8M.js +2 -0
- package/dist/gateway/static/root/assets/{note-image-lightbox-DNAoPcmm.js → note-image-lightbox-pJM35Pz5.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-DvZ4pwc-.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-BPLz0AIv.js → preview-open-alternatives-CVwHuyN6.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BZEDmxbZ.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-CrWwWRVK.js → save-bar-controls-Ba-UEk7x.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-CF2sadvN.js → schedule-field-CNN9595U.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-Di5cKjYE.js → schema-form-DnNMmtD5.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DdGGlsfn.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-DlkEkPf9.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-Chh282jW.js → settings-collapsible-section-CmOz80i5.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-Dq-83cQd.js → settings-form-section-BmK7JJOV.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-DFPTrsPF.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-CYCCfgh4.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-0FXYnSUA.js → share-preview-page-Dp2qGrHC.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-Bff1pGd0.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-CJGKpBur.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-C6ocduTD.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-W1pTcojB.js → system-settings-panel-5jrIEr5b.js} +1 -1
- package/dist/gateway/static/root/assets/{use-agent-defaults-form-BVRvkK7m.js → use-agent-defaults-form-BuiXLIs5.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-CgJibfMM.js → use-channel-catalog-CHlO8J9G.js} +1 -1
- package/dist/gateway/static/root/assets/{use-settings-tab-guard-Bw_qkRQE.js → use-settings-tab-guard-CW5JORnl.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-DDoQyghO.js +1 -0
- package/dist/gateway/static/root/assets/{voice-player-store-C7lziaAx.js → voice-player-store-DDDWYHvg.js} +1 -1
- package/dist/gateway/static/root/assets/workflow-page.utils-CKjeEGqx.js +1 -0
- package/dist/gateway/static/root/assets/workflows-page-B604ehHG.js +18 -0
- package/dist/gateway/static/root/index.html +5 -5
- package/dist/gateway/static/root/logo.svg +4 -3
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +8 -0
- package/dist/src/agent/agent-manager.js +63 -28
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/agent-scope.js +1 -1
- package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
- package/dist/src/agent/bootstrap/project-agents-context.d.ts +2 -0
- package/dist/src/agent/bootstrap/project-agents-context.js +32 -0
- package/dist/src/agent/bootstrap/project-agents-context.js.map +1 -0
- package/dist/src/agent/context/workspace-seed.js +2 -2
- package/dist/src/agent/context/workspace-state.js +1 -1
- package/dist/src/agent/context/workspace.js +1 -1
- package/dist/src/agent/embedded/session-tool-result-guard.js +8 -1
- package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
- package/dist/src/agent/goals/checklist-judge.d.ts +1 -0
- package/dist/src/agent/goals/checklist-judge.js +3 -2
- package/dist/src/agent/goals/checklist-judge.js.map +1 -1
- package/dist/src/agent/goals/evaluate-turn.d.ts +1 -1
- package/dist/src/agent/goals/evaluate-turn.js +1 -0
- package/dist/src/agent/goals/evaluate-turn.js.map +1 -1
- package/dist/src/agent/goals/goal-locale.js +2 -2
- package/dist/src/agent/goals/persistent-goal-service.js +2 -4
- package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
- package/dist/src/agent/goals/post-turn.d.ts +6 -1
- package/dist/src/agent/goals/post-turn.js +15 -6
- package/dist/src/agent/goals/post-turn.js.map +1 -1
- package/dist/src/agent/image/load-image-media.js +2 -2
- package/dist/src/agent/inbound/inbound-loop.js +5 -1
- package/dist/src/agent/inbound/inbound-loop.js.map +1 -1
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +2 -2
- package/dist/src/agent/inbound/turn-dispatcher.js +2 -2
- package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
- package/dist/src/agent/ipc/inbox.js +3 -3
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.d.ts +27 -0
- package/dist/src/agent/mcp/bundle-mcp-materialize.js +50 -2
- package/dist/src/agent/mcp/bundle-mcp-materialize.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +79 -4
- package/dist/src/agent/mcp/bundle-mcp-runtime.js.map +1 -1
- package/dist/src/agent/mcp/bundle-mcp-types.d.ts +19 -0
- package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
- package/dist/src/agent/mcp/mcp-transport.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
- package/dist/src/agent/memory/dreaming/events.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
- package/dist/src/agent/memory/dreaming/preview.js +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.js +1 -1
- package/dist/src/agent/memory/memory-flush.js +1 -1
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/memory/index.js +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
- package/dist/src/agent/reply/post-compaction-context.js +1 -1
- package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
- package/dist/src/agent/sandbox/path-policy.js +2 -2
- package/dist/src/agent/service/btw-query.js +11 -3
- package/dist/src/agent/service/btw-query.js.map +1 -1
- package/dist/src/agent/service/parse-outbound-session-key.js +13 -8
- package/dist/src/agent/service/parse-outbound-session-key.js.map +1 -1
- package/dist/src/agent/service/process-direct-one-shot.d.ts +2 -2
- package/dist/src/agent/service/process-direct-one-shot.js +1 -1
- package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.d.ts +2 -2
- package/dist/src/agent/service/process-direct-streaming.js +1 -1
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.d.ts +1 -1
- package/dist/src/agent/service.js +13 -9
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/service.types.d.ts +5 -0
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/config.js +2 -2
- package/dist/src/agent/skills/filesystem-watcher.js +5 -4
- package/dist/src/agent/skills/filesystem-watcher.js.map +1 -1
- package/dist/src/agent/skills/hub-hash.js +2 -2
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +2 -2
- package/dist/src/agent/skills/index.js +4 -3
- package/dist/src/agent/skills/index.js.map +1 -1
- package/dist/src/agent/skills/installer.js +2 -2
- package/dist/src/agent/skills/managed-store.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +3 -2
- package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/skills/skill-view-path.js +1 -1
- package/dist/src/agent/skills/test-framework.js +1 -1
- package/dist/src/agent/skills/types.d.ts +1 -1
- package/dist/src/agent/skills/watcher.js +2 -5
- package/dist/src/agent/skills/watcher.js.map +1 -1
- package/dist/src/agent/skills/workspace-skills-dir.d.ts +1 -0
- package/dist/src/agent/skills/workspace-skills-dir.js +11 -0
- package/dist/src/agent/skills/workspace-skills-dir.js.map +1 -0
- package/dist/src/agent/starter-agents.js +1 -1
- package/dist/src/agent/tool-manuals/browser.d.ts +1 -1
- package/dist/src/agent/tool-manuals/browser.js +62 -3
- package/dist/src/agent/tool-manuals/browser.js.map +1 -1
- package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +4 -1
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +13 -4
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
- package/dist/src/agent/tools/browser/tool/schemas.d.ts +0 -2
- package/dist/src/agent/tools/browser/tool/schemas.js +1 -2
- package/dist/src/agent/tools/browser/tool/schemas.js.map +1 -1
- package/dist/src/agent/tools/dreaming-tool.js +1 -1
- package/dist/src/agent/tools/factory.js +1 -10
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/find.js +1 -1
- package/dist/src/agent/tools/grep.js +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +2 -2
- package/dist/src/agent/tools/skill-manage-tool.js.map +1 -1
- package/dist/src/agent/tools/workflow-tool.js +1 -1
- package/dist/src/agent/workflow/catalog.js +1 -1
- package/dist/src/agent/workflow/snapshot.d.ts +10 -0
- package/dist/src/agent/workflow/snapshot.js +136 -1
- package/dist/src/agent/workflow/snapshot.js.map +1 -1
- package/dist/src/agent/workflow/subagent-runner.js +18 -1
- package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
- package/dist/src/ai-assist/text-assist.js +1 -1
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/profiles/store.js +2 -2
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/browser/actions/extension-registry-bridge.js +91 -7
- package/dist/src/browser/actions/extension-registry-bridge.js.map +1 -1
- package/dist/src/browser/actions/registry.js +383 -7
- package/dist/src/browser/actions/registry.js.map +1 -1
- package/dist/src/browser/actions/types.d.ts +11 -3
- package/dist/src/browser/cache-dir-policy.js +1 -1
- package/dist/src/browser/cdp-local-launcher.js +2 -2
- package/dist/src/browser/index.js +2 -2
- package/dist/src/browser/pipeline/output.d.ts +18 -16
- package/dist/src/browser/pipeline/output.js +28 -20
- package/dist/src/browser/pipeline/output.js.map +1 -1
- package/dist/src/browser/pipeline/runner.d.ts +7 -14
- package/dist/src/browser/pipeline/runner.js +349 -102
- package/dist/src/browser/pipeline/runner.js.map +1 -1
- package/dist/src/browser/pipeline/schema.d.ts +1 -0
- package/dist/src/browser/pipeline/schema.js +35 -58
- package/dist/src/browser/pipeline/schema.js.map +1 -1
- package/dist/src/browser/pipeline/source.d.ts +2 -0
- package/dist/src/browser/pipeline/source.js +10 -1
- package/dist/src/browser/pipeline/source.js.map +1 -1
- package/dist/src/browser/pipeline/template.d.ts +10 -2
- package/dist/src/browser/pipeline/template.js +50 -8
- package/dist/src/browser/pipeline/template.js.map +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +4 -4
- package/dist/src/browser/providers/cloakbrowser.js +5 -5
- package/dist/src/browser/providers/playwright-doctor.js +1 -1
- package/dist/src/browser/stealth.js +1 -1
- package/dist/src/channels/catalog/channel-catalog-service.d.ts +2 -1
- package/dist/src/channels/catalog/channel-catalog-service.js +133 -16
- package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -1
- package/dist/src/channels/catalog/channel-catalog-types.d.ts +13 -0
- package/dist/src/channels/outbound/persist-store.js +1 -1
- package/dist/src/channels/pairing/allow-from-file.js +1 -1
- package/dist/src/channels/pairing/pairing-store.js +2 -2
- package/dist/src/chat-commands/agent-edit.js +2 -2
- package/dist/src/chat-commands/builtins/config.js +5 -7
- package/dist/src/chat-commands/builtins/config.js.map +1 -1
- package/dist/src/chat-commands/context.d.ts +5 -0
- package/dist/src/chat-commands/context.js +18 -9
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/chat-commands/index.d.ts +1 -1
- package/dist/src/chat-commands/index.js +2 -2
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/chat-commands/processor.js +22 -21
- package/dist/src/chat-commands/processor.js.map +1 -1
- package/dist/src/chat-commands/session-key.d.ts +3 -15
- package/dist/src/chat-commands/session-key.js +3 -49
- package/dist/src/chat-commands/session-key.js.map +1 -1
- package/dist/src/chat-commands/types.d.ts +4 -0
- package/dist/src/cli/commands/browser-cli-helpers.js +11 -5
- package/dist/src/cli/commands/browser-cli-helpers.js.map +1 -1
- package/dist/src/cli/commands/config.js +1 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.js +14 -1
- package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +8 -8
- package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
- package/dist/src/cli/commands/extension-create.js +1 -1
- package/dist/src/cli/commands/extension-dev.js +2 -2
- package/dist/src/cli/commands/extension-marketplace.js +2 -2
- package/dist/src/cli/commands/extension-pack.js +2 -2
- package/dist/src/cli/commands/extension.js +3 -3
- package/dist/src/cli/commands/gateway/logs.js +1 -1
- package/dist/src/cli/commands/image.js +1 -1
- package/dist/src/cli/commands/init.js +2 -2
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/skills-test.js +1 -1
- package/dist/src/cli/templates.js +1 -1
- package/dist/src/cli/utils/gateway-client.js +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +2 -2
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/agent-typed-models.js +1 -1
- package/dist/src/config/gateway-bind.js +1 -1
- package/dist/src/config/index.js +7 -7
- package/dist/src/config/loader.js +4 -4
- package/dist/src/config/models-json.js +2 -2
- package/dist/src/config/paths-state.js +1 -1
- package/dist/src/config/paths.js +1 -1
- package/dist/src/config/profile.js +1 -1
- package/dist/src/config/reload.js +1 -1
- package/dist/src/config/rules.js +5 -0
- package/dist/src/config/rules.js.map +1 -1
- package/dist/src/config/schema.d.ts +8 -0
- package/dist/src/config/schema.js +7 -0
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/web-patch.d.ts +1 -0
- package/dist/src/config/web-patch.js +1 -0
- package/dist/src/config/web-patch.js.map +1 -1
- package/dist/src/config/workspace-path.js +1 -1
- package/dist/src/connectors/builtin-catalog.js +180 -1
- package/dist/src/connectors/builtin-catalog.js.map +1 -1
- package/dist/src/connectors/health.js +18 -9
- package/dist/src/connectors/health.js.map +1 -1
- package/dist/src/connectors/types.d.ts +19 -0
- package/dist/src/connectors/usage.js +12 -4
- package/dist/src/connectors/usage.js.map +1 -1
- package/dist/src/cron/executor.js +1 -1
- package/dist/src/cron/service.js +1 -1
- package/dist/src/daemon/constants.js +1 -1
- package/dist/src/daemon/install-plan.js +2 -2
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/schtasks.js +2 -2
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/extensions/bundle-mcp.js +1 -1
- package/dist/src/extensions/discover-extensions.js +2 -2
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/install.js +2 -2
- package/dist/src/extensions/loader.js +2 -2
- package/dist/src/extensions/lockfile.js +3 -3
- package/dist/src/extensions/security.js +1 -1
- package/dist/src/extensions/types/tui.d.ts +2 -0
- package/dist/src/extensions/update.js +2 -2
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/file-path-classifier.js +2 -2
- package/dist/src/gateway/heartbeat/service.js +13 -1
- package/dist/src/gateway/heartbeat/service.js.map +1 -1
- package/dist/src/gateway/hono/app.js +18 -5
- package/dist/src/gateway/hono/app.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -1
- package/dist/src/gateway/hono/lib/config-payload.js +7 -4
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/lib/extension-store.js +2 -2
- package/dist/src/gateway/hono/lib/static-ui.js +2 -2
- package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +4 -0
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js +19 -5
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js.map +1 -1
- package/dist/src/gateway/hono/oauth-async.js +1 -1
- package/dist/src/gateway/hono/routes/agent-stream.js +6 -6
- package/dist/src/gateway/hono/routes/agent-stream.js.map +1 -1
- package/dist/src/gateway/hono/routes/agents.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/channels.js +18 -14
- package/dist/src/gateway/hono/routes/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +1 -1
- package/dist/src/gateway/hono/routes/config-patch/gateway.js +6 -0
- package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
- package/dist/src/gateway/hono/routes/deps.d.ts +1 -0
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/goals.js +16 -3
- package/dist/src/gateway/hono/routes/goals.js.map +1 -1
- package/dist/src/gateway/hono/routes/host-fs.js +2 -2
- package/dist/src/gateway/hono/routes/logs.js +1 -0
- package/dist/src/gateway/hono/routes/logs.js.map +1 -1
- package/dist/src/gateway/hono/routes/mcp.js +27 -8
- package/dist/src/gateway/hono/routes/mcp.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/notes.js +14 -2
- package/dist/src/gateway/hono/routes/notes.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +62 -4
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/shares.js +1 -1
- package/dist/src/gateway/hono/routes/workflows.js +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +5 -68
- package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
- package/dist/src/gateway/hono/sse.d.ts +2 -2
- package/dist/src/gateway/hono/sse.js +7 -15
- package/dist/src/gateway/hono/sse.js.map +1 -1
- package/dist/src/gateway/lock.js +3 -3
- package/dist/src/gateway/ports.js +1 -1
- package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
- package/dist/src/gateway/rate-limit/buckets.js +12 -0
- package/dist/src/gateway/rate-limit/buckets.js.map +1 -1
- package/dist/src/gateway/resolve-webchat-session-key.d.ts +2 -6
- package/dist/src/gateway/resolve-webchat-session-key.js +5 -31
- package/dist/src/gateway/resolve-webchat-session-key.js.map +1 -1
- package/dist/src/gateway/service/agent-runner.d.ts +2 -3
- package/dist/src/gateway/service/agent-runner.js +9 -22
- package/dist/src/gateway/service/agent-runner.js.map +1 -1
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service/marketplace-service.js +2 -2
- package/dist/src/gateway/service/run-gateway-agent.js +9 -7
- package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +9 -0
- package/dist/src/gateway/service/sessions-api.js +11 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.d.ts +1 -1
- package/dist/src/gateway/service.js +23 -9
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-file-search.d.ts +9 -0
- package/dist/src/gateway/workspace-file-search.js +76 -0
- package/dist/src/gateway/workspace-file-search.js.map +1 -0
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/goals/goal-notifications.d.ts +2 -0
- package/dist/src/goals/goal-notifications.js +16 -11
- package/dist/src/goals/goal-notifications.js.map +1 -1
- package/dist/src/goals/goal-service.js +1 -6
- package/dist/src/goals/goal-service.js.map +1 -1
- package/dist/src/goals/goal-workflow-judge.js +2 -2
- package/dist/src/i18n/goals-bundle.js +1 -1
- package/dist/src/i18n/index.js +1 -1
- package/dist/src/i18n/share-tool-bundle.js +2 -2
- package/dist/src/infra/brew.js +1 -1
- package/dist/src/infra/package-json.js +1 -1
- package/dist/src/infra/package-update-steps.js +1 -1
- package/dist/src/infra/path-env.js +2 -2
- package/dist/src/infra/restart.js +1 -1
- package/dist/src/infra/stable-node-path.js +1 -1
- package/dist/src/infra/update-check.js +1 -1
- package/dist/src/infra/update-global.js +1 -1
- package/dist/src/infra/update-lock.js +2 -2
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/infra/update-startup.js +1 -1
- package/dist/src/infra/write-file-atomic.js +2 -2
- package/dist/src/media/store.js +1 -1
- package/dist/src/notes/agent-context.js +1 -1
- package/dist/src/notes/service.js +1 -1
- package/dist/src/notes/store.js +2 -2
- package/dist/src/project-trust/trust-store.js +4 -2
- package/dist/src/project-trust/trust-store.js.map +1 -1
- package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
- package/dist/src/providers/index.js +1 -1
- package/dist/src/providers/model-registry.js +4 -4
- package/dist/src/session/index.d.ts +1 -1
- package/dist/src/session/index.js +2 -2
- package/dist/src/session/init-session-turn.js +7 -10
- package/dist/src/session/init-session-turn.js.map +1 -1
- package/dist/src/session/manager.d.ts +5 -1
- package/dist/src/session/manager.js +5 -2
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/reset-type.d.ts +0 -2
- package/dist/src/session/reset-type.js +3 -9
- package/dist/src/session/reset-type.js.map +1 -1
- package/dist/src/session/resolve-session.js +10 -21
- package/dist/src/session/resolve-session.js.map +1 -1
- package/dist/src/session/session-title.js +2 -2
- package/dist/src/session/store.d.ts +11 -3
- package/dist/src/session/store.js +30 -14
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/types.d.ts +2 -4
- package/dist/src/session/types.js.map +1 -1
- package/dist/src/share/share-auto.js +2 -2
- package/dist/src/share/share-store.js +3 -3
- package/dist/src/share/share-thumbnail.js +2 -2
- package/dist/src/share/share-zip.js +1 -1
- package/dist/src/share/site-share-store.js +3 -3
- package/dist/src/share/site-static-serve.js +1 -1
- package/dist/src/storage/sqlite/connection.js +1 -1
- package/dist/src/storage/sqlite/index.d.ts +2 -2
- package/dist/src/storage/sqlite/index.js +3 -3
- package/dist/src/storage/sqlite/memory-index-repository.js +2 -2
- package/dist/src/storage/sqlite/migrations/010_session_id_identity.sql +30 -0
- package/dist/src/storage/sqlite/migrations/discover.js +1 -1
- package/dist/src/storage/sqlite/migrations/runner.d.ts +2 -2
- package/dist/src/storage/sqlite/migrations/runner.js +5 -5
- package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +2 -2
- package/dist/src/storage/sqlite/row-mappers.d.ts +4 -4
- package/dist/src/storage/sqlite/row-mappers.js +11 -14
- package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
- package/dist/src/storage/sqlite/schema.js +4 -4
- package/dist/src/storage/sqlite/schema.js.map +1 -1
- package/dist/src/storage/sqlite/schema.sql +37 -10
- package/dist/src/storage/sqlite/session-metadata.d.ts +2 -7
- package/dist/src/storage/sqlite/session-metadata.js +18 -72
- package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
- package/dist/src/storage/sqlite/session-repository.d.ts +6 -5
- package/dist/src/storage/sqlite/session-repository.js +34 -40
- package/dist/src/storage/sqlite/session-repository.js.map +1 -1
- package/dist/src/storage/sqlite/transcript-repository.d.ts +2 -2
- package/dist/src/storage/sqlite/transcript-repository.js +52 -52
- package/dist/src/storage/sqlite/transcript-repository.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +18 -4
- package/dist/src/tui/backends/embedded-backend.js +100 -1
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +5 -1
- package/dist/src/tui/backends/gateway-sse-backend.js +45 -2
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/clipboard-image.js +3 -3
- package/dist/src/tui/components/chat-log.d.ts +2 -0
- package/dist/src/tui/components/chat-log.js +19 -0
- package/dist/src/tui/components/chat-log.js.map +1 -1
- package/dist/src/tui/extension-host/autocomplete.d.ts +3 -2
- package/dist/src/tui/extension-host/autocomplete.js +29 -12
- package/dist/src/tui/extension-host/autocomplete.js.map +1 -1
- package/dist/src/tui/extension-host/load-extensions.js +1 -1
- package/dist/src/tui/extension-host/runtime.d.ts +12 -0
- package/dist/src/tui/extension-host/runtime.js +6 -4
- package/dist/src/tui/extension-host/runtime.js.map +1 -1
- package/dist/src/tui/theme-manager.js +1 -1
- package/dist/src/tui/tui-backend.d.ts +23 -0
- package/dist/src/tui/tui-command-formatters.js +4 -4
- package/dist/src/tui/tui-commands.d.ts +16 -3
- package/dist/src/tui/tui-commands.js +134 -27
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-file-autocomplete.d.ts +5 -0
- package/dist/src/tui/tui-file-autocomplete.js +26 -0
- package/dist/src/tui/tui-file-autocomplete.js.map +1 -0
- package/dist/src/tui/tui-keybindings-file.js +1 -1
- package/dist/src/tui/tui-picker-overlay.js +1 -1
- package/dist/src/tui/tui-scoped-models.js +2 -2
- package/dist/src/tui/tui-settings.js +1 -1
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/tui-startup-text.js +1 -1
- package/dist/src/tui/tui-startup-text.js.map +1 -1
- package/dist/src/tui/tui.js +106 -17
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/tunnel/frpc-binary.js +4 -4
- package/dist/src/tunnel/frpc-config.js +1 -1
- package/dist/src/tunnel/frpc-extract.js +1 -1
- package/dist/src/tunnel/tunnel-state.js +1 -1
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/context.d.ts +2 -2
- package/dist/src/utils/logger/context.js +2 -1
- package/dist/src/utils/logger/context.js.map +1 -1
- package/dist/src/utils/logger/log-store.js +2 -1
- package/dist/src/utils/logger/log-store.js.map +1 -1
- package/dist/src/utils/logger/pino-record.js +3 -0
- package/dist/src/utils/logger/pino-record.js.map +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/utils/logger/streams.js +1 -1
- package/dist/src/utils/logger/types.d.ts +5 -0
- package/dist/src/utils/logger/types.js.map +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/dist/src/voice/tts/providers/edge-speech.js +2 -2
- package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
- package/dist/src/workflows/service/workflow-run-service.js +1 -1
- package/dist/src/workflows/service/workflow-session-bridge.js +13 -1
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
- package/dist/src/workflows/store/event-store.js +1 -1
- package/dist/src/workflows/store/run-store.js +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agent-browser-settings-page-rGbKc2Hh.js +0 -6
- package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-CtwVbjOA.js +0 -1
- package/dist/gateway/static/root/assets/agents-CCBmGcwc.js +0 -71
- package/dist/gateway/static/root/assets/apps-page-xwCsJS15.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-C044DcYk.js +0 -1
- package/dist/gateway/static/root/assets/connectors-settings-8VEWUOTj.js +0 -2
- package/dist/gateway/static/root/assets/cron-page-DqmNGNOy.js +0 -3
- package/dist/gateway/static/root/assets/goal-detail-page-bv0VRDaf.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-1Ywnt4Cb.js +0 -2
- package/dist/gateway/static/root/assets/goals-settings-ceEBjnfc.js +0 -1
- package/dist/gateway/static/root/assets/index-Cxm6xsps.js +0 -122
- package/dist/gateway/static/root/assets/index-b_R4tKqt.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-B_wrxhee.js +0 -2
- package/dist/gateway/static/root/assets/messages-CkT-lcgP.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-D0JDSbNu.js +0 -2
- package/dist/gateway/static/root/assets/note-detail-page-DpFV-EO6.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-CdkjTch8.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DSYVAi96.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CenkcVjF.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-D9sva86V.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-DL35U0x0.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Ctwbp9Er.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-DIM3JNsr.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DAlNaNzL.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-CLrHVzAt.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-vYAO71Gn.js +0 -1
- package/dist/gateway/static/root/assets/workflow-page.utils-sgHjOXOm.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-DYyOTmFx.js +0 -18
|
@@ -2,8 +2,9 @@ import { init_paths, resolveSkillsDir } from "../../config/paths.js";
|
|
|
2
2
|
import { parseFrontmatter } from "../../markdown/frontmatter.js";
|
|
3
3
|
import { fuzzyFindText, normalizeForFuzzyMatch, normalizeToLF, restoreLineEndings } from "../tools/edit-diff.js";
|
|
4
4
|
import { formatScanSummary, scanSkillDirectory } from "./scanner.js";
|
|
5
|
-
import {
|
|
5
|
+
import { resolveWorkspaceSkillsDir } from "./workspace-skills-dir.js";
|
|
6
6
|
import { join, resolve, sep } from "path";
|
|
7
|
+
import { existsSync, realpathSync } from "fs";
|
|
7
8
|
import { mkdir, writeFile } from "fs/promises";
|
|
8
9
|
//#region src/agent/skills/skill-manage-ops.ts
|
|
9
10
|
/**
|
|
@@ -97,7 +98,7 @@ function resolveGlobalSkillsRoot() {
|
|
|
97
98
|
return resolveSkillsDir();
|
|
98
99
|
}
|
|
99
100
|
function resolveWorkspaceSkillsRoot(workspace) {
|
|
100
|
-
return
|
|
101
|
+
return resolveWorkspaceSkillsDir(workspace);
|
|
101
102
|
}
|
|
102
103
|
function canWriteToPath(skillBaseDir, workspace, policy) {
|
|
103
104
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-manage-ops.js","names":[],"sources":["../../../../src/agent/skills/skill-manage-ops.ts"],"sourcesContent":["/**\n * Shared logic for the skill_manage agent tool (create / edit / patch / delete / write_file / remove_file).\n */\n\nimport { existsSync, realpathSync } from 'fs';\nimport { join, resolve, sep } from 'path';\nimport { mkdir, writeFile } from 'fs/promises';\n\nimport { parseFrontmatter } from '../../markdown/frontmatter.js';\nimport { resolveSkillsDir } from '../../config/paths.js';\nimport type { Skill } from './types.js';\nimport type { SkillsConfig } from './types.js';\nimport { scanSkillDirectory, formatScanSummary } from './scanner.js';\n\nexport const SKILL_MANAGE_ALLOWED_SUBDIRS = new Set(['references', 'templates', 'scripts', 'assets']);\n\nexport const SKILL_MANAGE_NAME_RE = /^[a-z0-9][a-z0-9._-]*$/;\nexport const DEFAULT_MAX_SKILL_MD_CHARS = 100_000;\nexport const DEFAULT_MAX_SUPPORT_FILE_BYTES = 1_048_576;\n\nexport type AgentWritePolicy = 'global' | 'workspace' | 'both';\n\nexport function effectiveAgentWritePolicy(cfg?: SkillsConfig): AgentWritePolicy {\n const p = cfg?.agentWritePolicy;\n if (p === 'workspace' || p === 'both') return p;\n return 'global';\n}\n\nexport function maxSkillMdChars(_cfg?: SkillsConfig): number {\n return DEFAULT_MAX_SKILL_MD_CHARS;\n}\n\nexport function maxSupportFileBytes(cfg?: SkillsConfig): number {\n const n = cfg?.limits?.maxSkillFileBytes;\n if (typeof n === 'number' && n > 0) return n;\n return DEFAULT_MAX_SUPPORT_FILE_BYTES;\n}\n\nexport function validateSkillNameSegment(name: string, label: string): string | null {\n if (!name?.trim()) return `${label} is required.`;\n if (name.length > 64) return `${label} must be at most 64 characters.`;\n if (!SKILL_MANAGE_NAME_RE.test(name)) {\n return `${label} must match ${SKILL_MANAGE_NAME_RE}: lowercase letters, digits, ., _, -`;\n }\n return null;\n}\n\nexport function validateSkillMdContent(\n content: string,\n expectedName: string,\n maxChars: number,\n): { ok: true } | { ok: false; error: string } {\n if (!content.trim()) return { ok: false, error: 'Content cannot be empty.' };\n if (content.length > maxChars) {\n return { ok: false, error: `SKILL.md exceeds limit (${maxChars} characters).` };\n }\n if (!content.startsWith('---')) {\n return { ok: false, error: 'SKILL.md must start with YAML frontmatter (---).' };\n }\n const close = /\\r?\\n---\\s*\\r?\\n/.exec(content.slice(3));\n if (!close) {\n return { ok: false, error: 'Frontmatter must be closed with a line --- before the body.' };\n }\n const { frontmatter, content: body } = parseFrontmatter<Record<string, unknown>>(content);\n const name = frontmatter.name;\n const desc = frontmatter.description;\n if (typeof name !== 'string' || !name.trim()) {\n return { ok: false, error: 'Frontmatter must include a string name field.' };\n }\n if (typeof desc !== 'string' || !desc.trim()) {\n return { ok: false, error: 'Frontmatter must include a string description field.' };\n }\n if (name.trim() !== expectedName) {\n return {\n ok: false,\n error: `Frontmatter name \"${name.trim()}\" must match skill name \"${expectedName}\".`,\n };\n }\n if (!body?.trim()) {\n return { ok: false, error: 'SKILL.md must have a non-empty body after frontmatter.' };\n }\n return { ok: true };\n}\n\nfunction resolvedPathPrefix(dir: string): string {\n const r = resolve(dir);\n return r.endsWith(sep) ? r : r + sep;\n}\n\n/** Whether `filePath` is equal to `dir` or strictly inside it (resolved). */\nexport function isPathInsideDir(dir: string, filePath: string): boolean {\n try {\n const base = resolve(dir);\n const target = resolve(filePath);\n const baseReal = existsSync(base) ? realpathSync(base) : base;\n const targetReal = existsSync(target) ? realpathSync(target) : target;\n const prefix = resolvedPathPrefix(baseReal);\n return targetReal === baseReal || targetReal.startsWith(prefix);\n } catch {\n return false;\n }\n}\n\nexport function resolveGlobalSkillsRoot(): string {\n return resolveSkillsDir();\n}\n\nexport function resolveWorkspaceSkillsRoot(workspace: string): string {\n return resolve(workspace, 'skills');\n}\n\nexport function canWriteToPath(\n skillBaseDir: string,\n workspace: string,\n policy: AgentWritePolicy,\n): boolean {\n try {\n const baseResolved = existsSync(skillBaseDir) ? realpathSync(skillBaseDir) : resolve(skillBaseDir);\n const globalRoot = resolveGlobalSkillsRoot();\n const wsRoot = resolveWorkspaceSkillsRoot(workspace);\n const underGlobal = isPathInsideDir(globalRoot, baseResolved);\n const underWs = isPathInsideDir(wsRoot, baseResolved);\n if (policy === 'global') return underGlobal;\n if (policy === 'workspace') return underWs;\n return underGlobal || underWs;\n } catch {\n return false;\n }\n}\n\nexport function mutatableSkillOrNull(\n skill: Skill | undefined,\n workspace: string,\n policy: AgentWritePolicy,\n): Skill | null {\n if (!skill) return null;\n if (skill.source === 'builtin' || skill.source === 'extra') return null;\n if (!canWriteToPath(skill.baseDir, workspace, policy)) return null;\n return skill;\n}\n\nexport function validateSupportingRelativePath(filePath: string): string | null {\n if (!filePath?.trim()) return 'file_path is required.';\n const norm = filePath.replace(/\\\\/g, '/');\n if (norm.includes('..')) return \"Path traversal ('..') is not allowed.\";\n if (norm.startsWith('/') || /^[A-Za-z]:/.test(norm)) {\n return 'file_path must be relative to the skill directory.';\n }\n const parts = norm.split('/').filter(Boolean);\n if (parts.length < 2) {\n return 'Provide a file path with a subdirectory, e.g. references/notes.md';\n }\n if (!SKILL_MANAGE_ALLOWED_SUBDIRS.has(parts[0]!)) {\n return `File must be under one of: ${[...SKILL_MANAGE_ALLOWED_SUBDIRS].join(', ')}.`;\n }\n return null;\n}\n\nexport async function atomicWriteUtf8(filePath: string, content: string): Promise<void> {\n const dir = resolve(filePath, '..');\n await mkdir(dir, { recursive: true });\n await writeFile(filePath, content, 'utf-8');\n}\n\n/** Scan skill dir; returns error message if critical findings (caller rolls back). */\nexport async function scanSkillDirOrError(skillDir: string, skillName: string): Promise<string | null> {\n const summary = await scanSkillDirectory(skillDir);\n if (summary.critical > 0) {\n return `Security scan blocked this change:\\n${formatScanSummary(summary, skillName)}`;\n }\n return null;\n}\n\nexport function resolveCreateSkillDir(\n name: string,\n category: string | undefined,\n writeTarget: 'global' | 'workspace',\n workspace: string,\n policy: AgentWritePolicy,\n): { ok: true; dir: string } | { ok: false; error: string } {\n if (writeTarget === 'global' && policy === 'workspace') {\n return { ok: false, error: 'Creating under global skills is not allowed (skills.agentWritePolicy).' };\n }\n if (writeTarget === 'workspace' && policy === 'global') {\n return { ok: false, error: 'Creating under workspace skills is not allowed (skills.agentWritePolicy).' };\n }\n const root =\n writeTarget === 'global' ? resolveGlobalSkillsRoot() : resolveWorkspaceSkillsRoot(workspace);\n const dir = category?.trim() ? join(root, category.trim(), name) : join(root, name);\n return { ok: true, dir };\n}\n\nexport function ensureCategorySegment(category: string | undefined): string | null {\n if (category === undefined || category === null || category === '') return null;\n if (typeof category !== 'string') return 'category must be a string.';\n const c = category.trim();\n if (!c) return null;\n if (c.includes('/') || c.includes('\\\\')) return 'category must be a single path segment.';\n return validateSkillNameSegment(c, 'category');\n}\n\nimport { normalizeToLF, restoreLineEndings, fuzzyFindText, normalizeForFuzzyMatch } from '../tools/edit-diff.js';\n\nfunction detectLineEnding(content: string): '\\r\\n' | '\\n' {\n const crlfIdx = content.indexOf('\\r\\n');\n const lfIdx = content.indexOf('\\n');\n if (lfIdx === -1) return '\\n';\n if (crlfIdx === -1) return '\\n';\n return crlfIdx < lfIdx ? '\\r\\n' : '\\n';\n}\n\nexport function applyPatchToContent(\n content: string,\n oldString: string,\n newString: string,\n replaceAll: boolean,\n): { ok: true; next: string; replacements: number } | { ok: false; error: string } {\n if (!oldString) return { ok: false, error: 'old_string is required for patch.' };\n if (newString === undefined) {\n return { ok: false, error: 'new_string is required (use empty string to delete matched text).' };\n }\n\n const lineEnding = detectLineEnding(content);\n const normalized = normalizeToLF(content);\n const oldN = normalizeToLF(oldString);\n const newN = normalizeToLF(newString);\n\n if (replaceAll) {\n const parts = normalized.split(oldN);\n const count = parts.length - 1;\n if (count === 0) {\n return { ok: false, error: 'old_string not found for replace_all.' };\n }\n const merged = parts.join(newN);\n return { ok: true, next: restoreLineEndings(merged, lineEnding), replacements: count };\n }\n\n const match = fuzzyFindText(normalized, oldN);\n if (!match.found) {\n return { ok: false, error: 'old_string not found in file.' };\n }\n const base = match.contentForReplacement;\n const fuzzyContent = normalizeForFuzzyMatch(normalizeToLF(base));\n const fuzzyOld = normalizeForFuzzyMatch(oldN);\n const occurrences = fuzzyOld ? fuzzyContent.split(fuzzyOld).length - 1 : 0;\n if (occurrences > 1) {\n return { ok: false, error: `Found ${occurrences} matches; narrow old_string or use replace_all.` };\n }\n const next =\n base.slice(0, match.index) + newN + base.slice(match.index + match.matchLength);\n return { ok: true, next: restoreLineEndings(next, lineEnding), replacements: 1 };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"skill-manage-ops.js","names":[],"sources":["../../../../src/agent/skills/skill-manage-ops.ts"],"sourcesContent":["/**\n * Shared logic for the skill_manage agent tool (create / edit / patch / delete / write_file / remove_file).\n */\n\nimport { existsSync, realpathSync } from 'fs';\nimport { join, resolve, sep } from 'path';\nimport { mkdir, writeFile } from 'fs/promises';\n\nimport { parseFrontmatter } from '../../markdown/frontmatter.js';\nimport { resolveSkillsDir } from '../../config/paths.js';\nimport type { Skill } from './types.js';\nimport type { SkillsConfig } from './types.js';\nimport { scanSkillDirectory, formatScanSummary } from './scanner.js';\nimport { resolveWorkspaceSkillsDir } from './workspace-skills-dir.js';\n\nexport const SKILL_MANAGE_ALLOWED_SUBDIRS = new Set(['references', 'templates', 'scripts', 'assets']);\n\nexport const SKILL_MANAGE_NAME_RE = /^[a-z0-9][a-z0-9._-]*$/;\nexport const DEFAULT_MAX_SKILL_MD_CHARS = 100_000;\nexport const DEFAULT_MAX_SUPPORT_FILE_BYTES = 1_048_576;\n\nexport type AgentWritePolicy = 'global' | 'workspace' | 'both';\n\nexport function effectiveAgentWritePolicy(cfg?: SkillsConfig): AgentWritePolicy {\n const p = cfg?.agentWritePolicy;\n if (p === 'workspace' || p === 'both') return p;\n return 'global';\n}\n\nexport function maxSkillMdChars(_cfg?: SkillsConfig): number {\n return DEFAULT_MAX_SKILL_MD_CHARS;\n}\n\nexport function maxSupportFileBytes(cfg?: SkillsConfig): number {\n const n = cfg?.limits?.maxSkillFileBytes;\n if (typeof n === 'number' && n > 0) return n;\n return DEFAULT_MAX_SUPPORT_FILE_BYTES;\n}\n\nexport function validateSkillNameSegment(name: string, label: string): string | null {\n if (!name?.trim()) return `${label} is required.`;\n if (name.length > 64) return `${label} must be at most 64 characters.`;\n if (!SKILL_MANAGE_NAME_RE.test(name)) {\n return `${label} must match ${SKILL_MANAGE_NAME_RE}: lowercase letters, digits, ., _, -`;\n }\n return null;\n}\n\nexport function validateSkillMdContent(\n content: string,\n expectedName: string,\n maxChars: number,\n): { ok: true } | { ok: false; error: string } {\n if (!content.trim()) return { ok: false, error: 'Content cannot be empty.' };\n if (content.length > maxChars) {\n return { ok: false, error: `SKILL.md exceeds limit (${maxChars} characters).` };\n }\n if (!content.startsWith('---')) {\n return { ok: false, error: 'SKILL.md must start with YAML frontmatter (---).' };\n }\n const close = /\\r?\\n---\\s*\\r?\\n/.exec(content.slice(3));\n if (!close) {\n return { ok: false, error: 'Frontmatter must be closed with a line --- before the body.' };\n }\n const { frontmatter, content: body } = parseFrontmatter<Record<string, unknown>>(content);\n const name = frontmatter.name;\n const desc = frontmatter.description;\n if (typeof name !== 'string' || !name.trim()) {\n return { ok: false, error: 'Frontmatter must include a string name field.' };\n }\n if (typeof desc !== 'string' || !desc.trim()) {\n return { ok: false, error: 'Frontmatter must include a string description field.' };\n }\n if (name.trim() !== expectedName) {\n return {\n ok: false,\n error: `Frontmatter name \"${name.trim()}\" must match skill name \"${expectedName}\".`,\n };\n }\n if (!body?.trim()) {\n return { ok: false, error: 'SKILL.md must have a non-empty body after frontmatter.' };\n }\n return { ok: true };\n}\n\nfunction resolvedPathPrefix(dir: string): string {\n const r = resolve(dir);\n return r.endsWith(sep) ? r : r + sep;\n}\n\n/** Whether `filePath` is equal to `dir` or strictly inside it (resolved). */\nexport function isPathInsideDir(dir: string, filePath: string): boolean {\n try {\n const base = resolve(dir);\n const target = resolve(filePath);\n const baseReal = existsSync(base) ? realpathSync(base) : base;\n const targetReal = existsSync(target) ? realpathSync(target) : target;\n const prefix = resolvedPathPrefix(baseReal);\n return targetReal === baseReal || targetReal.startsWith(prefix);\n } catch {\n return false;\n }\n}\n\nexport function resolveGlobalSkillsRoot(): string {\n return resolveSkillsDir();\n}\n\nexport function resolveWorkspaceSkillsRoot(workspace: string): string {\n return resolveWorkspaceSkillsDir(workspace);\n}\n\nexport function canWriteToPath(\n skillBaseDir: string,\n workspace: string,\n policy: AgentWritePolicy,\n): boolean {\n try {\n const baseResolved = existsSync(skillBaseDir) ? realpathSync(skillBaseDir) : resolve(skillBaseDir);\n const globalRoot = resolveGlobalSkillsRoot();\n const wsRoot = resolveWorkspaceSkillsRoot(workspace);\n const underGlobal = isPathInsideDir(globalRoot, baseResolved);\n const underWs = isPathInsideDir(wsRoot, baseResolved);\n if (policy === 'global') return underGlobal;\n if (policy === 'workspace') return underWs;\n return underGlobal || underWs;\n } catch {\n return false;\n }\n}\n\nexport function mutatableSkillOrNull(\n skill: Skill | undefined,\n workspace: string,\n policy: AgentWritePolicy,\n): Skill | null {\n if (!skill) return null;\n if (skill.source === 'builtin' || skill.source === 'extra') return null;\n if (!canWriteToPath(skill.baseDir, workspace, policy)) return null;\n return skill;\n}\n\nexport function validateSupportingRelativePath(filePath: string): string | null {\n if (!filePath?.trim()) return 'file_path is required.';\n const norm = filePath.replace(/\\\\/g, '/');\n if (norm.includes('..')) return \"Path traversal ('..') is not allowed.\";\n if (norm.startsWith('/') || /^[A-Za-z]:/.test(norm)) {\n return 'file_path must be relative to the skill directory.';\n }\n const parts = norm.split('/').filter(Boolean);\n if (parts.length < 2) {\n return 'Provide a file path with a subdirectory, e.g. references/notes.md';\n }\n if (!SKILL_MANAGE_ALLOWED_SUBDIRS.has(parts[0]!)) {\n return `File must be under one of: ${[...SKILL_MANAGE_ALLOWED_SUBDIRS].join(', ')}.`;\n }\n return null;\n}\n\nexport async function atomicWriteUtf8(filePath: string, content: string): Promise<void> {\n const dir = resolve(filePath, '..');\n await mkdir(dir, { recursive: true });\n await writeFile(filePath, content, 'utf-8');\n}\n\n/** Scan skill dir; returns error message if critical findings (caller rolls back). */\nexport async function scanSkillDirOrError(skillDir: string, skillName: string): Promise<string | null> {\n const summary = await scanSkillDirectory(skillDir);\n if (summary.critical > 0) {\n return `Security scan blocked this change:\\n${formatScanSummary(summary, skillName)}`;\n }\n return null;\n}\n\nexport function resolveCreateSkillDir(\n name: string,\n category: string | undefined,\n writeTarget: 'global' | 'workspace',\n workspace: string,\n policy: AgentWritePolicy,\n): { ok: true; dir: string } | { ok: false; error: string } {\n if (writeTarget === 'global' && policy === 'workspace') {\n return { ok: false, error: 'Creating under global skills is not allowed (skills.agentWritePolicy).' };\n }\n if (writeTarget === 'workspace' && policy === 'global') {\n return { ok: false, error: 'Creating under workspace skills is not allowed (skills.agentWritePolicy).' };\n }\n const root =\n writeTarget === 'global' ? resolveGlobalSkillsRoot() : resolveWorkspaceSkillsRoot(workspace);\n const dir = category?.trim() ? join(root, category.trim(), name) : join(root, name);\n return { ok: true, dir };\n}\n\nexport function ensureCategorySegment(category: string | undefined): string | null {\n if (category === undefined || category === null || category === '') return null;\n if (typeof category !== 'string') return 'category must be a string.';\n const c = category.trim();\n if (!c) return null;\n if (c.includes('/') || c.includes('\\\\')) return 'category must be a single path segment.';\n return validateSkillNameSegment(c, 'category');\n}\n\nimport { normalizeToLF, restoreLineEndings, fuzzyFindText, normalizeForFuzzyMatch } from '../tools/edit-diff.js';\n\nfunction detectLineEnding(content: string): '\\r\\n' | '\\n' {\n const crlfIdx = content.indexOf('\\r\\n');\n const lfIdx = content.indexOf('\\n');\n if (lfIdx === -1) return '\\n';\n if (crlfIdx === -1) return '\\n';\n return crlfIdx < lfIdx ? '\\r\\n' : '\\n';\n}\n\nexport function applyPatchToContent(\n content: string,\n oldString: string,\n newString: string,\n replaceAll: boolean,\n): { ok: true; next: string; replacements: number } | { ok: false; error: string } {\n if (!oldString) return { ok: false, error: 'old_string is required for patch.' };\n if (newString === undefined) {\n return { ok: false, error: 'new_string is required (use empty string to delete matched text).' };\n }\n\n const lineEnding = detectLineEnding(content);\n const normalized = normalizeToLF(content);\n const oldN = normalizeToLF(oldString);\n const newN = normalizeToLF(newString);\n\n if (replaceAll) {\n const parts = normalized.split(oldN);\n const count = parts.length - 1;\n if (count === 0) {\n return { ok: false, error: 'old_string not found for replace_all.' };\n }\n const merged = parts.join(newN);\n return { ok: true, next: restoreLineEndings(merged, lineEnding), replacements: count };\n }\n\n const match = fuzzyFindText(normalized, oldN);\n if (!match.found) {\n return { ok: false, error: 'old_string not found in file.' };\n }\n const base = match.contentForReplacement;\n const fuzzyContent = normalizeForFuzzyMatch(normalizeToLF(base));\n const fuzzyOld = normalizeForFuzzyMatch(oldN);\n const occurrences = fuzzyOld ? fuzzyContent.split(fuzzyOld).length - 1 : 0;\n if (occurrences > 1) {\n return { ok: false, error: `Found ${occurrences} matches; narrow old_string or use replace_all.` };\n }\n const next =\n base.slice(0, match.index) + newN + base.slice(match.index + match.matchLength);\n return { ok: true, next: restoreLineEndings(next, lineEnding), replacements: 1 };\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolveStateDir } from "../../config/paths-state.js";
|
|
2
|
-
import { init_paths, resolveBundledSkillsDir } from "../../config/paths.js";
|
|
3
2
|
import { createLogger } from "../../utils/logger/index.js";
|
|
4
3
|
import { init_logger } from "../../utils/logger.js";
|
|
4
|
+
import { init_paths, resolveBundledSkillsDir } from "../../config/paths.js";
|
|
5
5
|
import { createSkillConfigManager, isSkillEnabled } from "./config.js";
|
|
6
6
|
import { formatSkillsForPrompt, selectSkillsVisibleInPrompt } from "./format-skills-prompt.js";
|
|
7
7
|
import { createSkillLoader } from "./index.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync, realpathSync } from "fs";
|
|
2
1
|
import { resolve, sep } from "path";
|
|
2
|
+
import { existsSync, realpathSync } from "fs";
|
|
3
3
|
//#region src/agent/skills/skill-view-path.ts
|
|
4
4
|
/**
|
|
5
5
|
* Resolve safe paths for skill_view: only SKILL.md (default) or files under allowlisted subdirs.
|
|
@@ -4,8 +4,8 @@ import { parseFrontmatter } from "../../markdown/frontmatter.js";
|
|
|
4
4
|
import { hasBinary } from "./installer.js";
|
|
5
5
|
import { scanSkillDirectory } from "./scanner.js";
|
|
6
6
|
import { parseSkillMetadata } from "./parse-skill-metadata.js";
|
|
7
|
-
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
8
7
|
import { basename, join, relative } from "path";
|
|
8
|
+
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
9
9
|
//#region src/agent/skills/test-framework.ts
|
|
10
10
|
/**
|
|
11
11
|
* Skill Test Framework
|
|
@@ -114,7 +114,7 @@ export interface SkillsConfig {
|
|
|
114
114
|
*/
|
|
115
115
|
toolGating?: boolean;
|
|
116
116
|
/**
|
|
117
|
-
* Where `skill_manage` may create or edit skills: global `~/.xopc/skills`, workspace
|
|
117
|
+
* Where `skill_manage` may create or edit skills: global `~/.xopc/skills`, workspace `.xopc/skills/`, or both.
|
|
118
118
|
* Default `global`.
|
|
119
119
|
*/
|
|
120
120
|
agentWritePolicy?: 'global' | 'workspace' | 'both';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { resolveWorkspaceSkillsDir } from "./workspace-skills-dir.js";
|
|
3
4
|
import { watch } from "fs";
|
|
4
|
-
import { join } from "path";
|
|
5
5
|
//#region src/agent/skills/watcher.ts
|
|
6
6
|
/**
|
|
7
7
|
* Skill Watcher
|
|
@@ -102,10 +102,7 @@ function createSkillWatcher(loader, options) {
|
|
|
102
102
|
*/
|
|
103
103
|
function createWatcherFromLoader(loader, options) {
|
|
104
104
|
const watchDirs = [];
|
|
105
|
-
if (options.workspaceDir)
|
|
106
|
-
const workspaceSkillsDir = join(options.workspaceDir, "skills");
|
|
107
|
-
watchDirs.push(workspaceSkillsDir);
|
|
108
|
-
}
|
|
105
|
+
if (options.workspaceDir) watchDirs.push(resolveWorkspaceSkillsDir(options.workspaceDir));
|
|
109
106
|
if (options.builtinDir) watchDirs.push(options.builtinDir);
|
|
110
107
|
if (options.globalDirs) watchDirs.push(...options.globalDirs);
|
|
111
108
|
if (options.extraDirs) watchDirs.push(...options.extraDirs);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.js","names":[],"sources":["../../../../src/agent/skills/watcher.ts"],"sourcesContent":["/**\n * Skill Watcher\n * \n * Watches skill directories for changes and triggers reloads.\n *\n */\n\nimport { watch } from 'fs';\nimport {
|
|
1
|
+
{"version":3,"file":"watcher.js","names":[],"sources":["../../../../src/agent/skills/watcher.ts"],"sourcesContent":["/**\n * Skill Watcher\n * \n * Watches skill directories for changes and triggers reloads.\n *\n */\n\nimport { watch } from 'fs';\nimport { createLogger } from '../../utils/logger.js';\nimport type { SkillLoader } from './index.js';\nimport { resolveWorkspaceSkillsDir } from './workspace-skills-dir.js';\n\nconst log = createLogger('SkillWatcher');\n\nexport interface SkillWatcherOptions {\n /** Debounce time in milliseconds */\n debounceMs?: number;\n /** Watch these directories */\n watchDirs: string[];\n}\n\nexport interface SkillWatcher {\n /** Start watching */\n start: () => void;\n /** Stop watching */\n stop: () => void;\n /** Check if watching is active */\n isWatching: () => boolean;\n /** Get last refresh time */\n getLastRefreshTime: () => number;\n}\n\n/**\n * Create a debounced reload function\n */\nfunction createDebouncedReload(\n loader: SkillLoader,\n debounceMs: number\n): () => void {\n let timeout: NodeJS.Timeout | null = null;\n let pendingReload = false;\n\n return () => {\n if (timeout) {\n pendingReload = true;\n return;\n }\n\n timeout = setTimeout(() => {\n timeout = null;\n \n if (pendingReload) {\n pendingReload = false;\n loader.reload();\n log.info('Skills reloaded after directory changes');\n }\n }, debounceMs);\n };\n}\n\n/**\n * Create a skill watcher\n */\nexport function createSkillWatcher(\n loader: SkillLoader,\n options: SkillWatcherOptions\n): SkillWatcher {\n const { watchDirs, debounceMs = 1000 } = options;\n \n const watchers: Array<{ watcher: ReturnType<typeof watch>; dir: string }> = [];\n const debouncedReload = createDebouncedReload(loader, debounceMs);\n let isWatching = false;\n let lastRefreshTime = Date.now();\n\n function watchDirectory(dir: string): void {\n try {\n const watcher = watch(dir, { recursive: true }, (eventType, filename) => {\n if (!filename) return;\n\n // Only care about SKILL.md files\n if (filename.toLowerCase() === 'skill.md') {\n log.debug({ eventType, filename, dir }, 'Skill file changed');\n lastRefreshTime = Date.now();\n debouncedReload();\n }\n\n // Also watch for new directories (potential new skills)\n if (eventType === 'rename') {\n log.debug({ eventType, filename, dir }, 'Directory changed, may be new skill');\n lastRefreshTime = Date.now();\n debouncedReload();\n }\n });\n\n watchers.push({ watcher, dir });\n log.info({ dir }, 'Watching skill directory');\n } catch (err) {\n log.warn({ dir, error: err }, 'Failed to watch skill directory');\n }\n }\n\n return {\n start: () => {\n if (isWatching) {\n log.warn('Watcher already started');\n return;\n }\n\n for (const dir of watchDirs) {\n watchDirectory(dir);\n }\n\n isWatching = true;\n log.info({ dirs: watchDirs }, 'Skill watcher started');\n },\n\n stop: () => {\n if (!isWatching) {\n return;\n }\n\n for (const { watcher } of watchers) {\n watcher.close();\n }\n\n watchers.length = 0;\n isWatching = false;\n log.info('Skill watcher stopped');\n },\n\n isWatching: () => isWatching,\n\n getLastRefreshTime: () => lastRefreshTime,\n };\n}\n\n/**\n * Create a skill watcher from loader configuration\n */\nexport function createWatcherFromLoader(\n loader: SkillLoader,\n options: {\n workspaceDir?: string;\n builtinDir?: string;\n globalDirs?: string[];\n extraDirs?: string[];\n debounceMs?: number;\n }\n): SkillWatcher | null {\n const watchDirs: string[] = [];\n\n // Add project-local workspace skills directory\n if (options.workspaceDir) {\n watchDirs.push(resolveWorkspaceSkillsDir(options.workspaceDir));\n }\n\n // Add builtin directory\n if (options.builtinDir) {\n watchDirs.push(options.builtinDir);\n }\n\n // Add global directories\n if (options.globalDirs) {\n watchDirs.push(...options.globalDirs);\n }\n\n // Add extra directories\n if (options.extraDirs) {\n watchDirs.push(...options.extraDirs);\n }\n\n if (watchDirs.length === 0) {\n log.warn('No directories to watch');\n return null;\n }\n\n return createSkillWatcher(loader, {\n watchDirs,\n debounceMs: options.debounceMs ?? 1000,\n });\n}\n"],"mappings":";;;;;;;;;;;aAQqD;AAIrD,MAAM,MAAM,aAAa,eAAe;;;;AAuBxC,SAAS,sBACP,QACA,YACY;CACZ,IAAI,UAAiC;CACrC,IAAI,gBAAgB;AAEpB,cAAa;AACX,MAAI,SAAS;AACX,mBAAgB;AAChB;;AAGF,YAAU,iBAAiB;AACzB,aAAU;AAEV,OAAI,eAAe;AACjB,oBAAgB;AAChB,WAAO,QAAQ;AACf,QAAI,KAAK,0CAA0C;;KAEpD,WAAW;;;;;;AAOlB,SAAgB,mBACd,QACA,SACc;CACd,MAAM,EAAE,WAAW,aAAa,QAAS;CAEzC,MAAM,WAAsE,EAAE;CAC9E,MAAM,kBAAkB,sBAAsB,QAAQ,WAAW;CACjE,IAAI,aAAa;CACjB,IAAI,kBAAkB,KAAK,KAAK;CAEhC,SAAS,eAAe,KAAmB;AACzC,MAAI;GACF,MAAM,UAAU,MAAM,KAAK,EAAE,WAAW,MAAM,GAAG,WAAW,aAAa;AACvE,QAAI,CAAC,SAAU;AAGf,QAAI,SAAS,aAAa,KAAK,YAAY;AACzC,SAAI,MAAM;MAAE;MAAW;MAAU;MAAK,EAAE,qBAAqB;AAC7D,uBAAkB,KAAK,KAAK;AAC5B,sBAAiB;;AAInB,QAAI,cAAc,UAAU;AAC1B,SAAI,MAAM;MAAE;MAAW;MAAU;MAAK,EAAE,sCAAsC;AAC9E,uBAAkB,KAAK,KAAK;AAC5B,sBAAiB;;KAEnB;AAEF,YAAS,KAAK;IAAE;IAAS;IAAK,CAAC;AAC/B,OAAI,KAAK,EAAE,KAAK,EAAE,2BAA2B;WACtC,KAAK;AACZ,OAAI,KAAK;IAAE;IAAK,OAAO;IAAK,EAAE,kCAAkC;;;AAIpE,QAAO;EACL,aAAa;AACX,OAAI,YAAY;AACd,QAAI,KAAK,0BAA0B;AACnC;;AAGF,QAAK,MAAM,OAAO,UAChB,gBAAe,IAAI;AAGrB,gBAAa;AACb,OAAI,KAAK,EAAE,MAAM,WAAW,EAAE,wBAAwB;;EAGxD,YAAY;AACV,OAAI,CAAC,WACH;AAGF,QAAK,MAAM,EAAE,aAAa,SACxB,SAAQ,OAAO;AAGjB,YAAS,SAAS;AAClB,gBAAa;AACb,OAAI,KAAK,wBAAwB;;EAGnC,kBAAkB;EAElB,0BAA0B;EAC3B;;;;;AAMH,SAAgB,wBACd,QACA,SAOqB;CACrB,MAAM,YAAsB,EAAE;AAG9B,KAAI,QAAQ,aACV,WAAU,KAAK,0BAA0B,QAAQ,aAAa,CAAC;AAIjE,KAAI,QAAQ,WACV,WAAU,KAAK,QAAQ,WAAW;AAIpC,KAAI,QAAQ,WACV,WAAU,KAAK,GAAG,QAAQ,WAAW;AAIvC,KAAI,QAAQ,UACV,WAAU,KAAK,GAAG,QAAQ,UAAU;AAGtC,KAAI,UAAU,WAAW,GAAG;AAC1B,MAAI,KAAK,0BAA0B;AACnC,SAAO;;AAGT,QAAO,mBAAmB,QAAQ;EAChC;EACA,YAAY,QAAQ,cAAc;EACnC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolveWorkspaceSkillsDir(workspaceDir: string): string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
//#region src/agent/skills/workspace-skills-dir.ts
|
|
3
|
+
const PROJECT_XOPC_DIR = ".xopc";
|
|
4
|
+
const PROJECT_SKILLS_DIR = "skills";
|
|
5
|
+
function resolveWorkspaceSkillsDir(workspaceDir) {
|
|
6
|
+
return join(workspaceDir, PROJECT_XOPC_DIR, PROJECT_SKILLS_DIR);
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { resolveWorkspaceSkillsDir };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=workspace-skills-dir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-skills-dir.js","names":[],"sources":["../../../../src/agent/skills/workspace-skills-dir.ts"],"sourcesContent":["import { join } from 'node:path';\n\nconst PROJECT_XOPC_DIR = '.xopc';\nconst PROJECT_SKILLS_DIR = 'skills';\n\nexport function resolveWorkspaceSkillsDir(workspaceDir: string): string {\n return join(workspaceDir, PROJECT_XOPC_DIR, PROJECT_SKILLS_DIR);\n}\n"],"mappings":";;AAEA,MAAM,mBAAmB;AACzB,MAAM,qBAAqB;AAE3B,SAAgB,0BAA0B,cAA8B;AACtE,QAAO,KAAK,cAAc,kBAAkB,mBAAmB"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentProfileDir, resolveAgentWorkspaceDir } from "./agent-scope.js";
|
|
2
2
|
import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
|
|
3
3
|
import { applyAgentConfig } from "../commands/agents.config.js";
|
|
4
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
5
4
|
import { join } from "node:path";
|
|
5
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
6
6
|
//#region src/agent/starter-agents.ts
|
|
7
7
|
init_paths();
|
|
8
8
|
init_agent_scope();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const browserUseManual = "# Browser Tool Manual\n\n## Overview\n\n`browser_use` is XOPC's unified browser tool. It supports four modes:\n\n| Mode | Purpose |\n|------|---------|\n| `command` | Run a single browser action |\n| `pipeline` | Run a multi-step YAML flow |\n| `inspect` | Read current page state |\n| `close` | Close the browser session |\n\n## When to use\n\n- Open pages, click controls, fill forms\n- Capture screenshots or page content\n- Run multi-step automation flows\n- Extract data from pages\n\n## Command mode\n\n### Basic shape\n\n```json\n{\n \"mode\": \"command\",\n \"command\": \"<action>\",\n \"args\": { ... }\n}\n```\n\n### Available commands\n\n| Command | Description | Key arguments |\n|---------|-------------|---------------|\n| `open` / `navigate` | Open a URL | `url`, `wait_until` |\n| `state` / `snapshot` | ARIA snapshot of the page | `selector`, `maxLength` |\n| `click` | Click an element | `selector` / `text` / `role` |\n| `type` / `input` | Type text | `selector` / `label`, `text`, `pressEnter` |\n| `scroll` | Scroll the page | `direction`, `amount` |\n| `screenshot` | Screenshot | `selector`, `full_page`, `path` |\n| `back` | Go back | `waitFor` |\n| `keys` / `press` | Keyboard input | `key` |\n| `console` / `eval` | Run JavaScript | `javascript` |\n| `images` | Collect images on the page | `selector`, `maxImages` |\n| `wait` | Wait for element/time | `selector` / `text` / `ms`, `timeout_ms` |\n| `dialog` | Handle dialogs | `action` (accept/dismiss) |\n| `close` | Close the current page | \u2014 |\n\n### Element targeting\n\nPrefer, in order:\n\n1. **ARIA role**: most stable, e.g. `\"role\": \"button:Submit\"`\n2. **Visible text**, e.g. `\"text\": \"Sign In\"`\n3. **CSS selector**, e.g. `\"selector\": \"#login-btn\"`\n\nGuidelines:\n\n- Use `inspect` or `state` first to get a snapshot\n- Pick locators from ARIA info in the snapshot\n- Avoid dynamic class names when possible\n\n## Inspect mode\n\nBefore acting, understand the current page:\n\n```json\n{ \"mode\": \"inspect\" }\n```\n\nReturns: current URL, title, ARIA snapshot.\n\n**Best practice**: after each navigation, inspect, then choose the next step.\n\n## Pipeline mode\n\nFor multi-step, reusable flows. Uses a brocli-style YAML DSL.\n\n### Run from file\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"path\": \"./browser-flow.yaml\",\n \"args\": { \"url\": \"https://example.com\" }\n }\n}\n```\n\n### Run inline YAML\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"name: quick-check\\npipeline:\\n - navigate:\\n url: https://example.com\\n - screenshot:\\n full_page: true\",\n \"dryRun\": false\n }\n}\n```\n\n### YAML layout\n\n```yaml\nname: pipeline-name\ndescription: What this flow does\nargs:\n url:\n type: string\n required: true\n query:\n type: string\n default: \"hello\"\npipeline:\n - navigate:\n url: ${{ args.url }}\n wait_until: domcontentloaded\n - wait:\n selector: input[name=\"q\"]\n - type:\n selector: input[name=\"q\"]\n text: ${{ args.query }}\n - press:\n key: Enter\n - wait:\n selector: body\n timeout_ms: 10000\n - screenshot:\n path: ./artifacts/result.png\n full_page: true\n - output:\n value:\n screenshot: ./artifacts/result.png\non_error:\n - screenshot:\n path: ./artifacts/error.png\n full_page: true\n```\n\n### Authoring rules\n\n1. One action per step\n2. Use `${{ args.xxx }}` for parameters\n3. Use `${{
|
|
1
|
+
export declare const browserUseManual = "# Browser Tool Manual\n\n## Overview\n\n`browser_use` is XOPC's unified browser tool. It supports four modes:\n\n| Mode | Purpose |\n|------|---------|\n| `command` | Run a single browser action |\n| `pipeline` | Run a multi-step YAML flow |\n| `inspect` | Read current page state |\n| `close` | Close the browser session |\n\n## When to use\n\n- Open pages, click controls, fill forms\n- Capture screenshots or page content\n- Run multi-step automation flows\n- Extract data from pages\n\n## Command mode\n\n### Basic shape\n\n```json\n{\n \"mode\": \"command\",\n \"command\": \"<action>\",\n \"args\": { ... }\n}\n```\n\n### Available commands\n\n| Command | Description | Key arguments |\n|---------|-------------|---------------|\n| `open` / `navigate` | Open a URL | `url`, `wait_until` |\n| `state` / `snapshot` | ARIA snapshot of the page | `selector`, `maxLength` |\n| `click` | Click an element | `selector` / `text` / `role` |\n| `type` / `input` | Type text | `selector` / `label`, `text`, `pressEnter` |\n| `scroll` | Scroll the page | `direction`, `amount` |\n| `screenshot` | Screenshot | `selector`, `full_page`, `path` |\n| `back` | Go back | `waitFor` |\n| `keys` / `press` | Keyboard input | `key` |\n| `console` / `eval` | Run JavaScript | `javascript` |\n| `images` | Collect images on the page | `selector`, `maxImages` |\n| `wait` | Wait for element/text/function/time | `selector` / `text` / `function` / `ms`, `state`, `timeout_ms` |\n| `wait_for_navigation` | Wait for page load state | `wait_until`, `timeout_ms` |\n| `wait_for_network_idle` | Wait until network is idle | `timeout_ms` |\n| `element_text` | Read element text | `selector` |\n| `element_attribute` | Read element attribute | `selector`, `attribute` |\n| `bounding_box` | Read element box | `selector` |\n| `network_start` / `network_events` / `network_stop` | Capture network events | `url_pattern`, `include_body` |\n| `dialog` | Handle dialogs | `action` (accept/dismiss) |\n| `close` | Close the current page | \u2014 |\n\n### Element targeting\n\nPrefer, in order:\n\n1. **ARIA role**: most stable, e.g. `\"role\": \"button:Submit\"`\n2. **Visible text**, e.g. `\"text\": \"Sign In\"`\n3. **CSS selector**, e.g. `\"selector\": \"#login-btn\"`\n\nGuidelines:\n\n- Use `inspect` or `state` first to get a snapshot\n- Pick locators from ARIA info in the snapshot\n- Avoid dynamic class names when possible\n\n## Inspect mode\n\nBefore acting, understand the current page:\n\n```json\n{ \"mode\": \"inspect\" }\n```\n\nReturns: current URL, title, ARIA snapshot.\n\n**Best practice**: after each navigation, inspect, then choose the next step.\n\n## Pipeline mode\n\nFor multi-step, reusable flows. Uses a brocli-style YAML DSL.\n\n### Run from file\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"path\": \"./browser-flow.yaml\",\n \"args\": { \"url\": \"https://example.com\" }\n }\n}\n```\n\n### Run inline YAML\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"name: quick-check\\npipeline:\\n - navigate:\\n url: https://example.com\\n - screenshot:\\n full_page: true\",\n \"dryRun\": false\n }\n}\n```\n\n### YAML layout\n\n```yaml\nname: pipeline-name\ndescription: What this flow does\ntimeoutSeconds: 60\ninclude:\n - ./shared-login.yaml\nargs:\n url:\n type: string\n required: true\n query:\n type: string\n default: \"hello\"\npipeline:\n - navigate:\n url: ${{ args.url }}\n wait_until: domcontentloaded\n - wait:\n selector: input[name=\"q\"]\n - type:\n selector: input[name=\"q\"]\n text: ${{ args.query }}\n - press:\n key: Enter\n - wait:\n selector: body\n timeout_ms: 10000\n - element_text:\n selector: h1\n - assert:\n contains: Results\n - screenshot:\n path: ./artifacts/result.png\n full_page: true\n - output:\n value:\n screenshot: ./artifacts/result.png\non_error:\n - screenshot:\n path: ./artifacts/error.png\n full_page: true\n```\n\n### Authoring rules\n\n1. One action per step\n2. Use `${{ args.xxx }}` for parameters\n3. Use `${{ last }}` or `${{ last | json }}` for the previous step result\n4. Use `${{ outputs.0 }}` for prior `output` values and `${{ vars.name }}` for values from `set_var`\n5. Use `include` for shared YAML fragments; relative includes resolve from the current pipeline file\n6. Use `on_error` to collect diagnostics after failure\n\n### Stable pipeline actions\n\n```yaml\npipeline:\n - network_start:\n url_pattern: /api/search\n include_body: true\n - click:\n text: Search\n - wait_for_network_idle:\n timeout_ms: 10000\n - collect: {}\n - filter:\n path: type\n equals: response\n - limit:\n count: 3\n - output:\n value: ${{ last }}\n```\n\nControl flow:\n\n```yaml\npipeline:\n - retry:\n times: 3\n delay_ms: 500\n pipeline:\n - wait:\n selector: button.submit\n timeout_ms: 3000\n - click:\n selector: button.submit\n - if:\n condition: ${{ last }}\n then:\n - output:\n value: clicked\n else:\n - output:\n value: missing\n```\n\n### Validate without running\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"...\",\n \"dryRun\": true\n }\n}\n```\n\n## Recovery when something fails\n\n1. `inspect` to see current state\n2. Confirm the URL (redirects may have changed it)\n3. Use the snapshot to see if the page finished loading\n4. `screenshot` for visual debugging\n5. `wait` for elements, then retry\n\n## Safety\n\n- Do not put API keys or tokens in URLs\n- Do not target private IPs / localhost unless configuration allows it\n- Cloud metadata endpoints are always blocked\n- For destructive actions (submit forms, delete data), confirm intent with the user first\n";
|
|
@@ -45,7 +45,13 @@ const browserUseManual = `# Browser Tool Manual
|
|
|
45
45
|
| \`keys\` / \`press\` | Keyboard input | \`key\` |
|
|
46
46
|
| \`console\` / \`eval\` | Run JavaScript | \`javascript\` |
|
|
47
47
|
| \`images\` | Collect images on the page | \`selector\`, \`maxImages\` |
|
|
48
|
-
| \`wait\` | Wait for element/time | \`selector\` / \`text\` / \`ms\`, \`timeout_ms\` |
|
|
48
|
+
| \`wait\` | Wait for element/text/function/time | \`selector\` / \`text\` / \`function\` / \`ms\`, \`state\`, \`timeout_ms\` |
|
|
49
|
+
| \`wait_for_navigation\` | Wait for page load state | \`wait_until\`, \`timeout_ms\` |
|
|
50
|
+
| \`wait_for_network_idle\` | Wait until network is idle | \`timeout_ms\` |
|
|
51
|
+
| \`element_text\` | Read element text | \`selector\` |
|
|
52
|
+
| \`element_attribute\` | Read element attribute | \`selector\`, \`attribute\` |
|
|
53
|
+
| \`bounding_box\` | Read element box | \`selector\` |
|
|
54
|
+
| \`network_start\` / \`network_events\` / \`network_stop\` | Capture network events | \`url_pattern\`, \`include_body\` |
|
|
49
55
|
| \`dialog\` | Handle dialogs | \`action\` (accept/dismiss) |
|
|
50
56
|
| \`close\` | Close the current page | — |
|
|
51
57
|
|
|
@@ -108,6 +114,9 @@ For multi-step, reusable flows. Uses a brocli-style YAML DSL.
|
|
|
108
114
|
\`\`\`yaml
|
|
109
115
|
name: pipeline-name
|
|
110
116
|
description: What this flow does
|
|
117
|
+
timeoutSeconds: 60
|
|
118
|
+
include:
|
|
119
|
+
- ./shared-login.yaml
|
|
111
120
|
args:
|
|
112
121
|
url:
|
|
113
122
|
type: string
|
|
@@ -129,6 +138,10 @@ pipeline:
|
|
|
129
138
|
- wait:
|
|
130
139
|
selector: body
|
|
131
140
|
timeout_ms: 10000
|
|
141
|
+
- element_text:
|
|
142
|
+
selector: h1
|
|
143
|
+
- assert:
|
|
144
|
+
contains: Results
|
|
132
145
|
- screenshot:
|
|
133
146
|
path: ./artifacts/result.png
|
|
134
147
|
full_page: true
|
|
@@ -145,8 +158,54 @@ on_error:
|
|
|
145
158
|
|
|
146
159
|
1. One action per step
|
|
147
160
|
2. Use \`\${{ args.xxx }}\` for parameters
|
|
148
|
-
3. Use \`\${{
|
|
149
|
-
4. Use \`
|
|
161
|
+
3. Use \`\${{ last }}\` or \`\${{ last | json }}\` for the previous step result
|
|
162
|
+
4. Use \`\${{ outputs.0 }}\` for prior \`output\` values and \`\${{ vars.name }}\` for values from \`set_var\`
|
|
163
|
+
5. Use \`include\` for shared YAML fragments; relative includes resolve from the current pipeline file
|
|
164
|
+
6. Use \`on_error\` to collect diagnostics after failure
|
|
165
|
+
|
|
166
|
+
### Stable pipeline actions
|
|
167
|
+
|
|
168
|
+
\`\`\`yaml
|
|
169
|
+
pipeline:
|
|
170
|
+
- network_start:
|
|
171
|
+
url_pattern: /api/search
|
|
172
|
+
include_body: true
|
|
173
|
+
- click:
|
|
174
|
+
text: Search
|
|
175
|
+
- wait_for_network_idle:
|
|
176
|
+
timeout_ms: 10000
|
|
177
|
+
- collect: {}
|
|
178
|
+
- filter:
|
|
179
|
+
path: type
|
|
180
|
+
equals: response
|
|
181
|
+
- limit:
|
|
182
|
+
count: 3
|
|
183
|
+
- output:
|
|
184
|
+
value: \${{ last }}
|
|
185
|
+
\`\`\`
|
|
186
|
+
|
|
187
|
+
Control flow:
|
|
188
|
+
|
|
189
|
+
\`\`\`yaml
|
|
190
|
+
pipeline:
|
|
191
|
+
- retry:
|
|
192
|
+
times: 3
|
|
193
|
+
delay_ms: 500
|
|
194
|
+
pipeline:
|
|
195
|
+
- wait:
|
|
196
|
+
selector: button.submit
|
|
197
|
+
timeout_ms: 3000
|
|
198
|
+
- click:
|
|
199
|
+
selector: button.submit
|
|
200
|
+
- if:
|
|
201
|
+
condition: \${{ last }}
|
|
202
|
+
then:
|
|
203
|
+
- output:
|
|
204
|
+
value: clicked
|
|
205
|
+
else:
|
|
206
|
+
- output:
|
|
207
|
+
value: missing
|
|
208
|
+
\`\`\`
|
|
150
209
|
|
|
151
210
|
### Validate without running
|
|
152
211
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","names":[],"sources":["../../../../src/agent/tool-manuals/browser.ts"],"sourcesContent":["export const browserUseManual = `# Browser Tool Manual\n\n## Overview\n\n\\`browser_use\\` is XOPC's unified browser tool. It supports four modes:\n\n| Mode | Purpose |\n|------|---------|\n| \\`command\\` | Run a single browser action |\n| \\`pipeline\\` | Run a multi-step YAML flow |\n| \\`inspect\\` | Read current page state |\n| \\`close\\` | Close the browser session |\n\n## When to use\n\n- Open pages, click controls, fill forms\n- Capture screenshots or page content\n- Run multi-step automation flows\n- Extract data from pages\n\n## Command mode\n\n### Basic shape\n\n\\`\\`\\`json\n{\n \"mode\": \"command\",\n \"command\": \"<action>\",\n \"args\": { ... }\n}\n\\`\\`\\`\n\n### Available commands\n\n| Command | Description | Key arguments |\n|---------|-------------|---------------|\n| \\`open\\` / \\`navigate\\` | Open a URL | \\`url\\`, \\`wait_until\\` |\n| \\`state\\` / \\`snapshot\\` | ARIA snapshot of the page | \\`selector\\`, \\`maxLength\\` |\n| \\`click\\` | Click an element | \\`selector\\` / \\`text\\` / \\`role\\` |\n| \\`type\\` / \\`input\\` | Type text | \\`selector\\` / \\`label\\`, \\`text\\`, \\`pressEnter\\` |\n| \\`scroll\\` | Scroll the page | \\`direction\\`, \\`amount\\` |\n| \\`screenshot\\` | Screenshot | \\`selector\\`, \\`full_page\\`, \\`path\\` |\n| \\`back\\` | Go back | \\`waitFor\\` |\n| \\`keys\\` / \\`press\\` | Keyboard input | \\`key\\` |\n| \\`console\\` / \\`eval\\` | Run JavaScript | \\`javascript\\` |\n| \\`images\\` | Collect images on the page | \\`selector\\`, \\`maxImages\\` |\n| \\`wait\\` | Wait for element/time | \\`selector\\` / \\`text\\` / \\`ms\\`, \\`timeout_ms\\` |\n| \\`dialog\\` | Handle dialogs | \\`action\\` (accept/dismiss) |\n| \\`close\\` | Close the current page | — |\n\n### Element targeting\n\nPrefer, in order:\n\n1. **ARIA role**: most stable, e.g. \\`\"role\": \"button:Submit\"\\`\n2. **Visible text**, e.g. \\`\"text\": \"Sign In\"\\`\n3. **CSS selector**, e.g. \\`\"selector\": \"#login-btn\"\\`\n\nGuidelines:\n\n- Use \\`inspect\\` or \\`state\\` first to get a snapshot\n- Pick locators from ARIA info in the snapshot\n- Avoid dynamic class names when possible\n\n## Inspect mode\n\nBefore acting, understand the current page:\n\n\\`\\`\\`json\n{ \"mode\": \"inspect\" }\n\\`\\`\\`\n\nReturns: current URL, title, ARIA snapshot.\n\n**Best practice**: after each navigation, inspect, then choose the next step.\n\n## Pipeline mode\n\nFor multi-step, reusable flows. Uses a brocli-style YAML DSL.\n\n### Run from file\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"path\": \"./browser-flow.yaml\",\n \"args\": { \"url\": \"https://example.com\" }\n }\n}\n\\`\\`\\`\n\n### Run inline YAML\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"name: quick-check\\\\npipeline:\\\\n - navigate:\\\\n url: https://example.com\\\\n - screenshot:\\\\n full_page: true\",\n \"dryRun\": false\n }\n}\n\\`\\`\\`\n\n### YAML layout\n\n\\`\\`\\`yaml\nname: pipeline-name\ndescription: What this flow does\nargs:\n url:\n type: string\n required: true\n query:\n type: string\n default: \"hello\"\npipeline:\n - navigate:\n url: \\${{ args.url }}\n wait_until: domcontentloaded\n - wait:\n selector: input[name=\"q\"]\n - type:\n selector: input[name=\"q\"]\n text: \\${{ args.query }}\n - press:\n key: Enter\n - wait:\n selector: body\n timeout_ms: 10000\n - screenshot:\n path: ./artifacts/result.png\n full_page: true\n - output:\n value:\n screenshot: ./artifacts/result.png\non_error:\n - screenshot:\n path: ./artifacts/error.png\n full_page: true\n\\`\\`\\`\n\n### Authoring rules\n\n1. One action per step\n2. Use \\`\\${{ args.xxx }}\\` for parameters\n3. Use \\`\\${{
|
|
1
|
+
{"version":3,"file":"browser.js","names":[],"sources":["../../../../src/agent/tool-manuals/browser.ts"],"sourcesContent":["export const browserUseManual = `# Browser Tool Manual\n\n## Overview\n\n\\`browser_use\\` is XOPC's unified browser tool. It supports four modes:\n\n| Mode | Purpose |\n|------|---------|\n| \\`command\\` | Run a single browser action |\n| \\`pipeline\\` | Run a multi-step YAML flow |\n| \\`inspect\\` | Read current page state |\n| \\`close\\` | Close the browser session |\n\n## When to use\n\n- Open pages, click controls, fill forms\n- Capture screenshots or page content\n- Run multi-step automation flows\n- Extract data from pages\n\n## Command mode\n\n### Basic shape\n\n\\`\\`\\`json\n{\n \"mode\": \"command\",\n \"command\": \"<action>\",\n \"args\": { ... }\n}\n\\`\\`\\`\n\n### Available commands\n\n| Command | Description | Key arguments |\n|---------|-------------|---------------|\n| \\`open\\` / \\`navigate\\` | Open a URL | \\`url\\`, \\`wait_until\\` |\n| \\`state\\` / \\`snapshot\\` | ARIA snapshot of the page | \\`selector\\`, \\`maxLength\\` |\n| \\`click\\` | Click an element | \\`selector\\` / \\`text\\` / \\`role\\` |\n| \\`type\\` / \\`input\\` | Type text | \\`selector\\` / \\`label\\`, \\`text\\`, \\`pressEnter\\` |\n| \\`scroll\\` | Scroll the page | \\`direction\\`, \\`amount\\` |\n| \\`screenshot\\` | Screenshot | \\`selector\\`, \\`full_page\\`, \\`path\\` |\n| \\`back\\` | Go back | \\`waitFor\\` |\n| \\`keys\\` / \\`press\\` | Keyboard input | \\`key\\` |\n| \\`console\\` / \\`eval\\` | Run JavaScript | \\`javascript\\` |\n| \\`images\\` | Collect images on the page | \\`selector\\`, \\`maxImages\\` |\n| \\`wait\\` | Wait for element/text/function/time | \\`selector\\` / \\`text\\` / \\`function\\` / \\`ms\\`, \\`state\\`, \\`timeout_ms\\` |\n| \\`wait_for_navigation\\` | Wait for page load state | \\`wait_until\\`, \\`timeout_ms\\` |\n| \\`wait_for_network_idle\\` | Wait until network is idle | \\`timeout_ms\\` |\n| \\`element_text\\` | Read element text | \\`selector\\` |\n| \\`element_attribute\\` | Read element attribute | \\`selector\\`, \\`attribute\\` |\n| \\`bounding_box\\` | Read element box | \\`selector\\` |\n| \\`network_start\\` / \\`network_events\\` / \\`network_stop\\` | Capture network events | \\`url_pattern\\`, \\`include_body\\` |\n| \\`dialog\\` | Handle dialogs | \\`action\\` (accept/dismiss) |\n| \\`close\\` | Close the current page | — |\n\n### Element targeting\n\nPrefer, in order:\n\n1. **ARIA role**: most stable, e.g. \\`\"role\": \"button:Submit\"\\`\n2. **Visible text**, e.g. \\`\"text\": \"Sign In\"\\`\n3. **CSS selector**, e.g. \\`\"selector\": \"#login-btn\"\\`\n\nGuidelines:\n\n- Use \\`inspect\\` or \\`state\\` first to get a snapshot\n- Pick locators from ARIA info in the snapshot\n- Avoid dynamic class names when possible\n\n## Inspect mode\n\nBefore acting, understand the current page:\n\n\\`\\`\\`json\n{ \"mode\": \"inspect\" }\n\\`\\`\\`\n\nReturns: current URL, title, ARIA snapshot.\n\n**Best practice**: after each navigation, inspect, then choose the next step.\n\n## Pipeline mode\n\nFor multi-step, reusable flows. Uses a brocli-style YAML DSL.\n\n### Run from file\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"path\": \"./browser-flow.yaml\",\n \"args\": { \"url\": \"https://example.com\" }\n }\n}\n\\`\\`\\`\n\n### Run inline YAML\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"name: quick-check\\\\npipeline:\\\\n - navigate:\\\\n url: https://example.com\\\\n - screenshot:\\\\n full_page: true\",\n \"dryRun\": false\n }\n}\n\\`\\`\\`\n\n### YAML layout\n\n\\`\\`\\`yaml\nname: pipeline-name\ndescription: What this flow does\ntimeoutSeconds: 60\ninclude:\n - ./shared-login.yaml\nargs:\n url:\n type: string\n required: true\n query:\n type: string\n default: \"hello\"\npipeline:\n - navigate:\n url: \\${{ args.url }}\n wait_until: domcontentloaded\n - wait:\n selector: input[name=\"q\"]\n - type:\n selector: input[name=\"q\"]\n text: \\${{ args.query }}\n - press:\n key: Enter\n - wait:\n selector: body\n timeout_ms: 10000\n - element_text:\n selector: h1\n - assert:\n contains: Results\n - screenshot:\n path: ./artifacts/result.png\n full_page: true\n - output:\n value:\n screenshot: ./artifacts/result.png\non_error:\n - screenshot:\n path: ./artifacts/error.png\n full_page: true\n\\`\\`\\`\n\n### Authoring rules\n\n1. One action per step\n2. Use \\`\\${{ args.xxx }}\\` for parameters\n3. Use \\`\\${{ last }}\\` or \\`\\${{ last | json }}\\` for the previous step result\n4. Use \\`\\${{ outputs.0 }}\\` for prior \\`output\\` values and \\`\\${{ vars.name }}\\` for values from \\`set_var\\`\n5. Use \\`include\\` for shared YAML fragments; relative includes resolve from the current pipeline file\n6. Use \\`on_error\\` to collect diagnostics after failure\n\n### Stable pipeline actions\n\n\\`\\`\\`yaml\npipeline:\n - network_start:\n url_pattern: /api/search\n include_body: true\n - click:\n text: Search\n - wait_for_network_idle:\n timeout_ms: 10000\n - collect: {}\n - filter:\n path: type\n equals: response\n - limit:\n count: 3\n - output:\n value: \\${{ last }}\n\\`\\`\\`\n\nControl flow:\n\n\\`\\`\\`yaml\npipeline:\n - retry:\n times: 3\n delay_ms: 500\n pipeline:\n - wait:\n selector: button.submit\n timeout_ms: 3000\n - click:\n selector: button.submit\n - if:\n condition: \\${{ last }}\n then:\n - output:\n value: clicked\n else:\n - output:\n value: missing\n\\`\\`\\`\n\n### Validate without running\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"...\",\n \"dryRun\": true\n }\n}\n\\`\\`\\`\n\n## Recovery when something fails\n\n1. \\`inspect\\` to see current state\n2. Confirm the URL (redirects may have changed it)\n3. Use the snapshot to see if the page finished loading\n4. \\`screenshot\\` for visual debugging\n5. \\`wait\\` for elements, then retry\n\n## Safety\n\n- Do not put API keys or tokens in URLs\n- Do not target private IPs / localhost unless configuration allows it\n- Cloud metadata endpoints are always blocked\n- For destructive actions (submit forms, delete data), confirm intent with the user first\n`;\n"],"mappings":";AAAA,MAAa,mBAAmB"}
|
|
@@ -25,6 +25,9 @@ export interface CreateBrowserUseToolDeps {
|
|
|
25
25
|
*/
|
|
26
26
|
getReadiness?: () => Promise<BrowserNotReadyError | null>;
|
|
27
27
|
/** Pipeline runner (injected to avoid circular deps; lazy-loaded if not provided). */
|
|
28
|
-
runPipeline?: (yaml: string, args: Record<string, unknown>, ctx: BrowserActionContext,
|
|
28
|
+
runPipeline?: (yaml: string, args: Record<string, unknown>, ctx: BrowserActionContext, options: {
|
|
29
|
+
dryRun?: boolean;
|
|
30
|
+
sourceLocation?: string;
|
|
31
|
+
}) => Promise<BrowserActionResult>;
|
|
29
32
|
}
|
|
30
33
|
export declare function createBrowserUseTool(deps: CreateBrowserUseToolDeps): AgentTool<any, any>;
|
|
@@ -185,9 +185,12 @@ function createBrowserUseTool(deps) {
|
|
|
185
185
|
mode: "pipeline"
|
|
186
186
|
}
|
|
187
187
|
};
|
|
188
|
-
let yamlSource = pipelineParams.yaml ??
|
|
188
|
+
let yamlSource = pipelineParams.yaml ?? "";
|
|
189
|
+
let sourceLocation;
|
|
189
190
|
if (!yamlSource && pipelineParams.path) try {
|
|
190
|
-
|
|
191
|
+
const loaded = await loadBrowserPipelineSource(pipelineParams.path);
|
|
192
|
+
yamlSource = loaded.source;
|
|
193
|
+
sourceLocation = loaded.location;
|
|
191
194
|
} catch (e) {
|
|
192
195
|
const msg = e instanceof Error ? e.message : String(e);
|
|
193
196
|
return {
|
|
@@ -215,10 +218,16 @@ function createBrowserUseTool(deps) {
|
|
|
215
218
|
const pipelineArgs = pipelineParams.args ?? {};
|
|
216
219
|
const dryRun = pipelineParams.dryRun === true;
|
|
217
220
|
const ctx = buildContext(await deps.getPageForTask(), signal);
|
|
218
|
-
if (deps.runPipeline) return formatResult(await deps.runPipeline(yamlSource, pipelineArgs, ctx,
|
|
221
|
+
if (deps.runPipeline) return formatResult(await deps.runPipeline(yamlSource, pipelineArgs, ctx, {
|
|
222
|
+
dryRun,
|
|
223
|
+
sourceLocation
|
|
224
|
+
}));
|
|
219
225
|
try {
|
|
220
226
|
const { runBrowserPipeline } = await import("../../../../browser/pipeline/runner.js");
|
|
221
|
-
return formatResult(await runBrowserPipeline(yamlSource, pipelineArgs, ctx, registry,
|
|
227
|
+
return formatResult(await runBrowserPipeline(yamlSource, pipelineArgs, ctx, registry, {
|
|
228
|
+
dryRun,
|
|
229
|
+
sourceLocation
|
|
230
|
+
}));
|
|
222
231
|
} catch (e) {
|
|
223
232
|
const msg = e instanceof Error ? e.message : String(e);
|
|
224
233
|
log.error({ err: e }, `Pipeline execution failed: ${msg}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-use-tool.js","names":[],"sources":["../../../../../../src/agent/tools/browser/tool/browser-use-tool.ts"],"sourcesContent":["/**\n * browser_use — unified browser AgentTool.\n *\n * Modes: command | pipeline | inspect | close.\n * Replaces the 14 fine-grained browser_* tools with a single entry point.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\n\nimport { createLogger } from '../../../../utils/logger.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { BrowserManager } from '../../../../browser/manager.js';\nimport type { CdpSupervisor } from '../../../../browser/cdp-supervisor.js';\nimport type { Page } from 'playwright-core';\n\nimport { BrowserUseSchema } from './schemas.js';\nimport { createBrowserActionRegistry } from '../../../../browser/actions/registry.js';\nimport type { BrowserActionContext, BrowserActionResult } from '../../../../browser/actions/types.js';\nimport { loadBrowserPipelineSource } from '../../../../browser/pipeline/source.js';\nimport type { BrowserNotReadyError, BrowserSetupHint } from '../../../../browser/readiness.js';\n\nconst log = createLogger('Agent:BrowserUse');\n\nexport interface CreateBrowserUseToolDeps {\n getManager: () => BrowserManager;\n getPageForTask: () => Promise<Page>;\n getTaskId: () => string;\n getConfig: () => Config | undefined;\n getSupervisor?: () => CdpSupervisor | undefined;\n notifyBrowserPageClosed?: (taskId: string) => void;\n /**\n * Preflight readiness check. Returns `null` when the configured backend is\n * usable, otherwise a structured hint the chat surface renders as a setup\n * card. Cache the result upstream (~30s) so back-to-back calls don't reprobe.\n */\n getReadiness?: () => Promise<BrowserNotReadyError | null>;\n /** Pipeline runner (injected to avoid circular deps; lazy-loaded if not provided). */\n runPipeline?: (yaml: string, args: Record<string, unknown>, ctx: BrowserActionContext, dryRun: boolean) => Promise<BrowserActionResult>;\n}\n\nexport function createBrowserUseTool(deps: CreateBrowserUseToolDeps): AgentTool<any, any> {\n const registry = createBrowserActionRegistry();\n\n function buildContext(page: Page, signal?: AbortSignal): BrowserActionContext {\n return {\n page,\n manager: deps.getManager(),\n config: deps.getConfig(),\n taskId: deps.getTaskId(),\n supervisor: deps.getSupervisor?.(),\n signal,\n };\n }\n\n /**\n * Render a {@link BrowserSetupHint} as a tool result. The text body is a\n * JSON envelope (`kind: 'browser_setup_required'`) so the chat surface can\n * detect it and render a Setup card; the embedded `message` keeps the\n * payload human-readable for the LLM so it stops the browser attempt and\n * tells the user to finish setup.\n */\n function formatNotReady(hint: BrowserSetupHint): { content: { type: 'text'; text: string }[]; details: Record<string, unknown> } {\n const message =\n `⚠ Browser is not ready (backend=${hint.backend}, reason=${hint.reason}). ` +\n `Do NOT retry. Tell the user to open Settings → Browser to finish setup, ` +\n `then ask them to confirm before running any browser action again.`;\n const payload = {\n kind: 'browser_setup_required' as const,\n backend: hint.backend,\n reason: hint.reason,\n deepLink: hint.deepLink,\n detail: hint.detail,\n message,\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(payload) }],\n details: {\n ok: false,\n kind: 'browser_setup_required',\n backend: hint.backend,\n reason: hint.reason,\n deepLink: hint.deepLink,\n },\n };\n }\n\n function formatResult(result: BrowserActionResult): { content: { type: 'text'; text: string }[]; details: Record<string, unknown> } {\n if (result.ok) {\n const parts: string[] = [];\n if (result.text) parts.push(result.text);\n if (result.data && !result.text) parts.push(JSON.stringify(result.data, null, 2));\n return {\n content: [{ type: 'text', text: parts.join('\\n') || 'OK' }],\n details: { ok: true, action: result.action, ...(result.artifacts?.length ? { artifacts: result.artifacts.length } : {}) },\n };\n }\n const parts: string[] = [];\n if (result.error) parts.push(`[${result.error.code}] ${result.error.message}`);\n if (result.diagnostics?.url) parts.push(`URL: ${result.diagnostics.url}`);\n if (result.diagnostics?.snapshot) parts.push(`Snapshot: ${result.diagnostics.snapshot.slice(0, 2000)}`);\n return {\n content: [{ type: 'text', text: parts.join('\\n') || 'Failed' }],\n details: { ok: false, action: result.action, error: result.error },\n };\n }\n\n const tool: any = {\n name: 'browser_use',\n label: '🌐 Browser',\n description:\n 'Use a persistent browser for web navigation, page inspection, interaction, screenshots, network capture, and scripted browser pipelines. For non-trivial browser tasks, load the built-in manual first with tool_manual({ tool: \"browser_use\" }).',\n parameters: BrowserUseSchema,\n\n async execute(_toolCallId, params: any, signal, _onUpdate) {\n const { mode, command, args: cmdArgs, pipeline: pipelineParams, options: _options } = params as {\n mode: string;\n command?: string;\n args?: Record<string, unknown>;\n pipeline?: { yaml?: string; script?: string; path?: string; args?: Record<string, unknown>; dryRun?: boolean };\n options?: { timeout?: number; headless?: boolean };\n };\n\n // ─── readiness preflight ────────────────────────────────────────────\n // Probes the configured backend (doctor + WS bridge / CDP / cloud key)\n // before any launch attempt. On failure we short-circuit with a setup\n // hint the chat renders as a card — the agent should stop and ask the\n // user to finish setup instead of looping on launch errors.\n if (deps.getReadiness) {\n try {\n const notReady = await deps.getReadiness();\n if (notReady) {\n return formatNotReady(notReady.hint);\n }\n } catch (e) {\n log.warn({ err: e }, 'Readiness preflight threw; continuing with launch attempt');\n }\n }\n\n // ─── inspect ────────────────────────────────────────────────────────\n if (mode === 'inspect') {\n const mgr = deps.getManager();\n await mgr.ensureConnected();\n const ext = mgr.getExtensionProvider();\n if (ext) {\n const timeout = deps.getConfig?.()?.agents?.defaults?.browser?.commandTimeout;\n const timeoutMs =\n typeof timeout === 'number' && Number.isFinite(timeout) && timeout > 0\n ? Math.floor(timeout * 1000)\n : 30_000;\n const urlRes = await ext.sendCommand('get_url', {}, { timeout: timeoutMs });\n const titleRes = await ext.sendCommand('get_title', {}, { timeout: timeoutMs });\n const snapRes = await ext.sendCommand('snapshot', {}, { timeout: timeoutMs });\n const url = urlRes.ok && urlRes.data ? String((urlRes.data as { url?: string }).url ?? '') : '';\n const title =\n titleRes.ok && titleRes.data ? String((titleRes.data as { title?: string }).title ?? '') : '';\n let snapText = '';\n if (snapRes.ok && snapRes.data) {\n const nodes = (snapRes.data as { nodes?: Array<{ role?: string; name?: string }> }).nodes ?? [];\n snapText = nodes.map((n) => `${n.role ?? '?'}: ${n.name ?? ''}`).join('\\n');\n if (snapText.length > 8000) snapText = `${snapText.slice(0, 8000)}\\n... (truncated)`;\n }\n const text = `URL: ${url}\\nTitle: ${title}\\n${snapText ? `--- Page Snapshot ---\\n${snapText}` : ''}`;\n return {\n content: [{ type: 'text', text }],\n details: { ok: true, mode: 'inspect', url, title },\n };\n }\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n const result = await registry.execute('state', ctx, {});\n // Augment with URL / title\n const url = page.url();\n const title = await page.title().catch(() => '');\n const text = `URL: ${url}\\nTitle: ${title}\\n${result.text ?? ''}`;\n return {\n content: [{ type: 'text', text }],\n details: { ok: true, mode: 'inspect', url, title },\n };\n }\n\n // ─── close ──────────────────────────────────────────────────────────\n if (mode === 'close') {\n const taskId = deps.getTaskId();\n await deps.getManager().ensureConnected();\n await deps.getManager().closePage(taskId);\n deps.notifyBrowserPageClosed?.(taskId);\n return {\n content: [{ type: 'text', text: 'Browser page closed.' }],\n details: { ok: true, mode: 'close' },\n };\n }\n\n // ─── command ────────────────────────────────────────────────────────\n if (mode === 'command') {\n if (!command) {\n return {\n content: [{ type: 'text', text: 'Missing `command` parameter for command mode.' }],\n details: { ok: false, mode: 'command' },\n };\n }\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n const args = cmdArgs ?? {};\n const result = await registry.execute(command, ctx, args);\n return formatResult(result);\n }\n\n // ─── pipeline ──────────────────────────────────────────────────────\n if (mode === 'pipeline') {\n if (!pipelineParams) {\n return {\n content: [{ type: 'text', text: 'Missing `pipeline` parameter for pipeline mode.' }],\n details: { ok: false, mode: 'pipeline' },\n };\n }\n\n // Resolve YAML source\n let yamlSource = pipelineParams.yaml ?? pipelineParams.script ?? '';\n\n if (!yamlSource && pipelineParams.path) {\n try {\n yamlSource = (await loadBrowserPipelineSource(pipelineParams.path)).source;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n content: [{ type: 'text', text: `Failed to read pipeline source: ${msg}` }],\n details: { ok: false, mode: 'pipeline', error: msg },\n };\n }\n }\n\n if (!yamlSource) {\n return {\n content: [{ type: 'text', text: 'Pipeline mode requires `yaml`, `script`, or `path`.' }],\n details: { ok: false, mode: 'pipeline' },\n };\n }\n\n const pipelineArgs = (pipelineParams.args as Record<string, unknown>) ?? {};\n const dryRun = pipelineParams.dryRun === true;\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n\n // Use injected runner or lazy-load\n if (deps.runPipeline) {\n const result = await deps.runPipeline(yamlSource, pipelineArgs, ctx, dryRun);\n return formatResult(result);\n }\n\n // Lazy import pipeline runner\n try {\n const { runBrowserPipeline } = await import('../../../../browser/pipeline/runner.js');\n const result = await runBrowserPipeline(yamlSource, pipelineArgs, ctx, registry, dryRun);\n return formatResult(result);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n log.error({ err: e }, `Pipeline execution failed: ${msg}`);\n return {\n content: [{ type: 'text', text: `Pipeline failed: ${msg}` }],\n details: { ok: false, mode: 'pipeline', error: msg },\n };\n }\n }\n\n return {\n content: [{ type: 'text', text: `Unknown mode: ${mode}` }],\n details: { ok: false },\n };\n },\n };\n return tool;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"browser-use-tool.js","names":[],"sources":["../../../../../../src/agent/tools/browser/tool/browser-use-tool.ts"],"sourcesContent":["/**\n * browser_use — unified browser AgentTool.\n *\n * Modes: command | pipeline | inspect | close.\n * Replaces the 14 fine-grained browser_* tools with a single entry point.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\n\nimport { createLogger } from '../../../../utils/logger.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { BrowserManager } from '../../../../browser/manager.js';\nimport type { CdpSupervisor } from '../../../../browser/cdp-supervisor.js';\nimport type { Page } from 'playwright-core';\n\nimport { BrowserUseSchema } from './schemas.js';\nimport { createBrowserActionRegistry } from '../../../../browser/actions/registry.js';\nimport type { BrowserActionContext, BrowserActionResult } from '../../../../browser/actions/types.js';\nimport { loadBrowserPipelineSource } from '../../../../browser/pipeline/source.js';\nimport type { BrowserNotReadyError, BrowserSetupHint } from '../../../../browser/readiness.js';\n\nconst log = createLogger('Agent:BrowserUse');\n\nexport interface CreateBrowserUseToolDeps {\n getManager: () => BrowserManager;\n getPageForTask: () => Promise<Page>;\n getTaskId: () => string;\n getConfig: () => Config | undefined;\n getSupervisor?: () => CdpSupervisor | undefined;\n notifyBrowserPageClosed?: (taskId: string) => void;\n /**\n * Preflight readiness check. Returns `null` when the configured backend is\n * usable, otherwise a structured hint the chat surface renders as a setup\n * card. Cache the result upstream (~30s) so back-to-back calls don't reprobe.\n */\n getReadiness?: () => Promise<BrowserNotReadyError | null>;\n /** Pipeline runner (injected to avoid circular deps; lazy-loaded if not provided). */\n runPipeline?: (\n yaml: string,\n args: Record<string, unknown>,\n ctx: BrowserActionContext,\n options: { dryRun?: boolean; sourceLocation?: string },\n ) => Promise<BrowserActionResult>;\n}\n\nexport function createBrowserUseTool(deps: CreateBrowserUseToolDeps): AgentTool<any, any> {\n const registry = createBrowserActionRegistry();\n\n function buildContext(page: Page, signal?: AbortSignal): BrowserActionContext {\n return {\n page,\n manager: deps.getManager(),\n config: deps.getConfig(),\n taskId: deps.getTaskId(),\n supervisor: deps.getSupervisor?.(),\n signal,\n };\n }\n\n /**\n * Render a {@link BrowserSetupHint} as a tool result. The text body is a\n * JSON envelope (`kind: 'browser_setup_required'`) so the chat surface can\n * detect it and render a Setup card; the embedded `message` keeps the\n * payload human-readable for the LLM so it stops the browser attempt and\n * tells the user to finish setup.\n */\n function formatNotReady(hint: BrowserSetupHint): { content: { type: 'text'; text: string }[]; details: Record<string, unknown> } {\n const message =\n `⚠ Browser is not ready (backend=${hint.backend}, reason=${hint.reason}). ` +\n `Do NOT retry. Tell the user to open Settings → Browser to finish setup, ` +\n `then ask them to confirm before running any browser action again.`;\n const payload = {\n kind: 'browser_setup_required' as const,\n backend: hint.backend,\n reason: hint.reason,\n deepLink: hint.deepLink,\n detail: hint.detail,\n message,\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(payload) }],\n details: {\n ok: false,\n kind: 'browser_setup_required',\n backend: hint.backend,\n reason: hint.reason,\n deepLink: hint.deepLink,\n },\n };\n }\n\n function formatResult(result: BrowserActionResult): { content: { type: 'text'; text: string }[]; details: Record<string, unknown> } {\n if (result.ok) {\n const parts: string[] = [];\n if (result.text) parts.push(result.text);\n if (result.data && !result.text) parts.push(JSON.stringify(result.data, null, 2));\n return {\n content: [{ type: 'text', text: parts.join('\\n') || 'OK' }],\n details: { ok: true, action: result.action, ...(result.artifacts?.length ? { artifacts: result.artifacts.length } : {}) },\n };\n }\n const parts: string[] = [];\n if (result.error) parts.push(`[${result.error.code}] ${result.error.message}`);\n if (result.diagnostics?.url) parts.push(`URL: ${result.diagnostics.url}`);\n if (result.diagnostics?.snapshot) parts.push(`Snapshot: ${result.diagnostics.snapshot.slice(0, 2000)}`);\n return {\n content: [{ type: 'text', text: parts.join('\\n') || 'Failed' }],\n details: { ok: false, action: result.action, error: result.error },\n };\n }\n\n const tool: any = {\n name: 'browser_use',\n label: '🌐 Browser',\n description:\n 'Use a persistent browser for web navigation, page inspection, interaction, screenshots, network capture, and scripted browser pipelines. For non-trivial browser tasks, load the built-in manual first with tool_manual({ tool: \"browser_use\" }).',\n parameters: BrowserUseSchema,\n\n async execute(_toolCallId, params: any, signal, _onUpdate) {\n const { mode, command, args: cmdArgs, pipeline: pipelineParams, options: _options } = params as {\n mode: string;\n command?: string;\n args?: Record<string, unknown>;\n pipeline?: { yaml?: string; path?: string; args?: Record<string, unknown>; dryRun?: boolean };\n options?: { timeout?: number; headless?: boolean };\n };\n\n // ─── readiness preflight ────────────────────────────────────────────\n // Probes the configured backend (doctor + WS bridge / CDP / cloud key)\n // before any launch attempt. On failure we short-circuit with a setup\n // hint the chat renders as a card — the agent should stop and ask the\n // user to finish setup instead of looping on launch errors.\n if (deps.getReadiness) {\n try {\n const notReady = await deps.getReadiness();\n if (notReady) {\n return formatNotReady(notReady.hint);\n }\n } catch (e) {\n log.warn({ err: e }, 'Readiness preflight threw; continuing with launch attempt');\n }\n }\n\n // ─── inspect ────────────────────────────────────────────────────────\n if (mode === 'inspect') {\n const mgr = deps.getManager();\n await mgr.ensureConnected();\n const ext = mgr.getExtensionProvider();\n if (ext) {\n const timeout = deps.getConfig?.()?.agents?.defaults?.browser?.commandTimeout;\n const timeoutMs =\n typeof timeout === 'number' && Number.isFinite(timeout) && timeout > 0\n ? Math.floor(timeout * 1000)\n : 30_000;\n const urlRes = await ext.sendCommand('get_url', {}, { timeout: timeoutMs });\n const titleRes = await ext.sendCommand('get_title', {}, { timeout: timeoutMs });\n const snapRes = await ext.sendCommand('snapshot', {}, { timeout: timeoutMs });\n const url = urlRes.ok && urlRes.data ? String((urlRes.data as { url?: string }).url ?? '') : '';\n const title =\n titleRes.ok && titleRes.data ? String((titleRes.data as { title?: string }).title ?? '') : '';\n let snapText = '';\n if (snapRes.ok && snapRes.data) {\n const nodes = (snapRes.data as { nodes?: Array<{ role?: string; name?: string }> }).nodes ?? [];\n snapText = nodes.map((n) => `${n.role ?? '?'}: ${n.name ?? ''}`).join('\\n');\n if (snapText.length > 8000) snapText = `${snapText.slice(0, 8000)}\\n... (truncated)`;\n }\n const text = `URL: ${url}\\nTitle: ${title}\\n${snapText ? `--- Page Snapshot ---\\n${snapText}` : ''}`;\n return {\n content: [{ type: 'text', text }],\n details: { ok: true, mode: 'inspect', url, title },\n };\n }\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n const result = await registry.execute('state', ctx, {});\n // Augment with URL / title\n const url = page.url();\n const title = await page.title().catch(() => '');\n const text = `URL: ${url}\\nTitle: ${title}\\n${result.text ?? ''}`;\n return {\n content: [{ type: 'text', text }],\n details: { ok: true, mode: 'inspect', url, title },\n };\n }\n\n // ─── close ──────────────────────────────────────────────────────────\n if (mode === 'close') {\n const taskId = deps.getTaskId();\n await deps.getManager().ensureConnected();\n await deps.getManager().closePage(taskId);\n deps.notifyBrowserPageClosed?.(taskId);\n return {\n content: [{ type: 'text', text: 'Browser page closed.' }],\n details: { ok: true, mode: 'close' },\n };\n }\n\n // ─── command ────────────────────────────────────────────────────────\n if (mode === 'command') {\n if (!command) {\n return {\n content: [{ type: 'text', text: 'Missing `command` parameter for command mode.' }],\n details: { ok: false, mode: 'command' },\n };\n }\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n const args = cmdArgs ?? {};\n const result = await registry.execute(command, ctx, args);\n return formatResult(result);\n }\n\n // ─── pipeline ──────────────────────────────────────────────────────\n if (mode === 'pipeline') {\n if (!pipelineParams) {\n return {\n content: [{ type: 'text', text: 'Missing `pipeline` parameter for pipeline mode.' }],\n details: { ok: false, mode: 'pipeline' },\n };\n }\n\n let yamlSource = pipelineParams.yaml ?? '';\n let sourceLocation: string | undefined;\n\n if (!yamlSource && pipelineParams.path) {\n try {\n const loaded = await loadBrowserPipelineSource(pipelineParams.path);\n yamlSource = loaded.source;\n sourceLocation = loaded.location;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n content: [{ type: 'text', text: `Failed to read pipeline source: ${msg}` }],\n details: { ok: false, mode: 'pipeline', error: msg },\n };\n }\n }\n\n if (!yamlSource) {\n return {\n content: [{ type: 'text', text: 'Pipeline mode requires `yaml`, `script`, or `path`.' }],\n details: { ok: false, mode: 'pipeline' },\n };\n }\n\n const pipelineArgs = (pipelineParams.args as Record<string, unknown>) ?? {};\n const dryRun = pipelineParams.dryRun === true;\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n\n // Use injected runner or lazy-load\n if (deps.runPipeline) {\n const result = await deps.runPipeline(yamlSource, pipelineArgs, ctx, { dryRun, sourceLocation });\n return formatResult(result);\n }\n\n // Lazy import pipeline runner\n try {\n const { runBrowserPipeline } = await import('../../../../browser/pipeline/runner.js');\n const result = await runBrowserPipeline(yamlSource, pipelineArgs, ctx, registry, { dryRun, sourceLocation });\n return formatResult(result);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n log.error({ err: e }, `Pipeline execution failed: ${msg}`);\n return {\n content: [{ type: 'text', text: `Pipeline failed: ${msg}` }],\n details: { ok: false, mode: 'pipeline', error: msg },\n };\n }\n }\n\n return {\n content: [{ type: 'text', text: `Unknown mode: ${mode}` }],\n details: { ok: false },\n };\n },\n };\n return tool;\n}\n"],"mappings":"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"}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export declare const BrowserUsePipelineSchema: import("@sinclair/typebox/build/cjs").TObject<{
|
|
5
5
|
yaml: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
|
|
6
|
-
script: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
|
|
7
6
|
path: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
|
|
8
7
|
args: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TRecord<import("@sinclair/typebox/build/cjs").TString, import("@sinclair/typebox/build/cjs").TUnknown>>;
|
|
9
8
|
dryRun: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TBoolean>;
|
|
@@ -18,7 +17,6 @@ export declare const BrowserUseSchema: import("@sinclair/typebox/build/cjs").TOb
|
|
|
18
17
|
args: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TRecord<import("@sinclair/typebox/build/cjs").TString, import("@sinclair/typebox/build/cjs").TUnknown>>;
|
|
19
18
|
pipeline: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TObject<{
|
|
20
19
|
yaml: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
|
|
21
|
-
script: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
|
|
22
20
|
path: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
|
|
23
21
|
args: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TRecord<import("@sinclair/typebox/build/cjs").TString, import("@sinclair/typebox/build/cjs").TUnknown>>;
|
|
24
22
|
dryRun: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TBoolean>;
|
|
@@ -4,8 +4,7 @@ import { Type } from "@sinclair/typebox";
|
|
|
4
4
|
* BrowserUseSchema — Typebox schema for the unified `browser_use` AgentTool.
|
|
5
5
|
*/
|
|
6
6
|
const BrowserUsePipelineSchema = Type.Object({
|
|
7
|
-
yaml: Type.Optional(Type.String({ description: "Inline YAML pipeline
|
|
8
|
-
script: Type.Optional(Type.String({ description: "Alias for `yaml` — inline brocli YAML script." })),
|
|
7
|
+
yaml: Type.Optional(Type.String({ description: "Inline YAML browser pipeline." })),
|
|
9
8
|
path: Type.Optional(Type.String({ description: "Path or http(s) URL to a .yaml pipeline file." })),
|
|
10
9
|
args: Type.Optional(Type.Record(Type.String(), Type.Unknown(), { description: "Override pipeline arg defaults." })),
|
|
11
10
|
dryRun: Type.Optional(Type.Boolean({ description: "Only parse & validate, do not execute." }))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","names":[],"sources":["../../../../../../src/agent/tools/browser/tool/schemas.ts"],"sourcesContent":["/**\n * BrowserUseSchema — Typebox schema for the unified `browser_use` AgentTool.\n */\n\nimport { Type } from '@sinclair/typebox';\n\nexport const BrowserUsePipelineSchema = Type.Object({\n yaml: Type.Optional(Type.String({ description: 'Inline YAML pipeline
|
|
1
|
+
{"version":3,"file":"schemas.js","names":[],"sources":["../../../../../../src/agent/tools/browser/tool/schemas.ts"],"sourcesContent":["/**\n * BrowserUseSchema — Typebox schema for the unified `browser_use` AgentTool.\n */\n\nimport { Type } from '@sinclair/typebox';\n\nexport const BrowserUsePipelineSchema = Type.Object({\n yaml: Type.Optional(Type.String({ description: 'Inline YAML browser pipeline.' })),\n path: Type.Optional(Type.String({ description: 'Path or http(s) URL to a .yaml pipeline file.' })),\n args: Type.Optional(\n Type.Record(Type.String(), Type.Unknown(), { description: 'Override pipeline arg defaults.' }),\n ),\n dryRun: Type.Optional(Type.Boolean({ description: 'Only parse & validate, do not execute.' })),\n});\n\nexport const BrowserUseOptionsSchema = Type.Object({\n timeout: Type.Optional(Type.Number({ description: 'Action timeout override (ms).' })),\n headless: Type.Optional(Type.Boolean({ description: 'Override headless mode for this call.' })),\n});\n\nexport const BrowserUseSchema = Type.Object({\n mode: Type.Union(\n [\n Type.Literal('command'),\n Type.Literal('pipeline'),\n Type.Literal('inspect'),\n Type.Literal('close'),\n ],\n { description: 'Execution mode.' },\n ),\n command: Type.Optional(\n Type.String({ description: 'Browser action name (command mode). E.g. open, click, type, screenshot.' }),\n ),\n args: Type.Optional(\n Type.Record(Type.String(), Type.Unknown(), { description: 'Action arguments (command mode).' }),\n ),\n pipeline: Type.Optional(BrowserUsePipelineSchema),\n options: Type.Optional(BrowserUseOptionsSchema),\n});\n"],"mappings":";;;;;AAMA,MAAa,2BAA2B,KAAK,OAAO;CAClD,MAAM,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,iCAAiC,CAAC,CAAC;CAClF,MAAM,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,iDAAiD,CAAC,CAAC;CAClG,MAAM,KAAK,SACT,KAAK,OAAO,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,EAAE,aAAa,mCAAmC,CAAC,CAC/F;CACD,QAAQ,KAAK,SAAS,KAAK,QAAQ,EAAE,aAAa,0CAA0C,CAAC,CAAC;CAC/F,CAAC;AAEF,MAAa,0BAA0B,KAAK,OAAO;CACjD,SAAS,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,iCAAiC,CAAC,CAAC;CACrF,UAAU,KAAK,SAAS,KAAK,QAAQ,EAAE,aAAa,yCAAyC,CAAC,CAAC;CAChG,CAAC;AAEF,MAAa,mBAAmB,KAAK,OAAO;CAC1C,MAAM,KAAK,MACT;EACE,KAAK,QAAQ,UAAU;EACvB,KAAK,QAAQ,WAAW;EACxB,KAAK,QAAQ,UAAU;EACvB,KAAK,QAAQ,QAAQ;EACtB,EACD,EAAE,aAAa,mBAAmB,CACnC;CACD,SAAS,KAAK,SACZ,KAAK,OAAO,EAAE,aAAa,2EAA2E,CAAC,CACxG;CACD,MAAM,KAAK,SACT,KAAK,OAAO,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,EAAE,aAAa,oCAAoC,CAAC,CAChG;CACD,UAAU,KAAK,SAAS,yBAAyB;CACjD,SAAS,KAAK,SAAS,wBAAwB;CAChD,CAAC"}
|
|
@@ -3,8 +3,8 @@ import { init_logger } from "../../utils/logger.js";
|
|
|
3
3
|
import { SHORT_TERM_PROMOTION_LOCK_RELATIVE, SHORT_TERM_RECALL_STORE_RELATIVE } from "../memory/dreaming/constants.js";
|
|
4
4
|
import { loadDreamingStore, saveDreamingStore } from "../memory/dreaming/short-term-store.js";
|
|
5
5
|
import { resolveDreamingConfig } from "../memory/dreaming/config.js";
|
|
6
|
-
import fs from "node:fs/promises";
|
|
7
6
|
import path from "node:path";
|
|
7
|
+
import fs from "node:fs/promises";
|
|
8
8
|
import { Type } from "@sinclair/typebox";
|
|
9
9
|
//#region src/agent/tools/dreaming-tool.ts
|
|
10
10
|
init_logger();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
-
import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
|
|
4
3
|
import { createReadFileTool } from "./read.js";
|
|
5
4
|
import { createWriteFileTool } from "./write.js";
|
|
6
5
|
import { createEditFileTool } from "./edit.js";
|
|
@@ -45,7 +44,6 @@ import { mergeTtsConfigFromAppConfig } from "../../voice/tts/merge-config.js";
|
|
|
45
44
|
import { createTextToSpeechTool } from "./tts-tool.js";
|
|
46
45
|
import { createGoalEvidenceRecorder } from "./goal-evidence-recorder.js";
|
|
47
46
|
//#region src/agent/tools/factory.ts
|
|
48
|
-
init_session_key();
|
|
49
47
|
init_logger();
|
|
50
48
|
const log = createLogger("AgentToolsFactory");
|
|
51
49
|
/** Channels where `clarify` can block for a user answer (web UI, Telegram, CLI readline). */
|
|
@@ -54,12 +52,6 @@ const CLARIFY_SUPPORTED_CHANNELS = new Set([
|
|
|
54
52
|
"telegram",
|
|
55
53
|
"cli"
|
|
56
54
|
]);
|
|
57
|
-
function clarifyTransportSource(sessionKey) {
|
|
58
|
-
const parsed = parseSessionKey(sessionKey);
|
|
59
|
-
if (parsed) return parsed.source;
|
|
60
|
-
const first = sessionKey.split(":").filter(Boolean)[0] ?? "";
|
|
61
|
-
if (first === "cli" || first === "webchat") return first;
|
|
62
|
-
}
|
|
63
55
|
var AgentToolsFactory = class AgentToolsFactory {
|
|
64
56
|
browserManager = null;
|
|
65
57
|
/** One dialog/console supervisor per chat session (browser tab). */
|
|
@@ -195,8 +187,7 @@ var AgentToolsFactory = class AgentToolsFactory {
|
|
|
195
187
|
if (!req) return null;
|
|
196
188
|
const ctx = this.deps.getCurrentContext();
|
|
197
189
|
if (!ctx?.sessionKey) return null;
|
|
198
|
-
|
|
199
|
-
if (!source || !CLARIFY_SUPPORTED_CHANNELS.has(source)) return null;
|
|
190
|
+
if (!CLARIFY_SUPPORTED_CHANNELS.has(ctx.channel)) return null;
|
|
200
191
|
return (r) => req(ctx.sessionKey, r);
|
|
201
192
|
} }),
|
|
202
193
|
createTodoTool({ getSessionKey: () => this.deps.getCurrentContext()?.sessionKey }),
|