profclaw 2.0.0 → 2.4.0
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/.env.example +14 -2
- package/CHANGELOG.md +52 -0
- package/CONTRIBUTING.md +20 -0
- package/Dockerfile +39 -23
- package/README.md +178 -41
- package/config/pricing.yml +26 -2
- package/dist/agents/agent-summary.d.ts +44 -0
- package/dist/agents/agent-summary.js +176 -0
- package/dist/agents/auto-memory.d.ts +59 -0
- package/dist/agents/auto-memory.js +310 -0
- package/dist/agents/checkpoint-manager.d.ts +76 -0
- package/dist/agents/checkpoint-manager.js +156 -0
- package/dist/agents/circuit-breaker.d.ts +54 -0
- package/dist/agents/circuit-breaker.js +153 -0
- package/dist/agents/command-sandbox.d.ts +93 -0
- package/dist/agents/command-sandbox.js +235 -0
- package/dist/agents/context-compactor.d.ts +70 -0
- package/dist/agents/context-compactor.js +361 -0
- package/dist/agents/conversation-branch.d.ts +55 -0
- package/dist/agents/conversation-branch.js +115 -0
- package/dist/agents/error-recovery.d.ts +44 -0
- package/dist/agents/error-recovery.js +197 -0
- package/dist/agents/events.d.ts +76 -0
- package/dist/agents/events.js +8 -0
- package/dist/agents/executor-runner.d.ts +135 -0
- package/dist/agents/executor-runner.js +303 -0
- package/dist/agents/executor.d.ts +37 -1
- package/dist/agents/executor.js +606 -124
- package/dist/agents/file-snapshots.d.ts +72 -0
- package/dist/agents/file-snapshots.js +182 -0
- package/dist/agents/index.d.ts +2 -0
- package/dist/agents/orchestrator.d.ts +183 -0
- package/dist/agents/orchestrator.js +495 -0
- package/dist/agents/output-truncator.d.ts +59 -0
- package/dist/agents/output-truncator.js +128 -0
- package/dist/agents/permissions.d.ts +63 -0
- package/dist/agents/permissions.js +138 -0
- package/dist/agents/plan-mode.d.ts +71 -0
- package/dist/agents/plan-mode.js +186 -0
- package/dist/agents/prompt-suggestions.d.ts +33 -0
- package/dist/agents/prompt-suggestions.js +208 -0
- package/dist/agents/rate-limit-monitor.d.ts +56 -0
- package/dist/agents/rate-limit-monitor.js +224 -0
- package/dist/agents/receipt/receipt-cli.d.ts +43 -0
- package/dist/agents/receipt/receipt-cli.js +82 -0
- package/dist/agents/receipt/receipt-types.d.ts +136 -0
- package/dist/agents/receipt/receipt-types.js +19 -0
- package/dist/agents/receipt/receipt-verify.d.ts +19 -0
- package/dist/agents/receipt/receipt-verify.js +176 -0
- package/dist/agents/receipt/receipt-view.d.ts +29 -0
- package/dist/agents/receipt/receipt-view.js +227 -0
- package/dist/agents/receipt/receipt-writer.d.ts +47 -0
- package/dist/agents/receipt/receipt-writer.js +186 -0
- package/dist/agents/result-store.d.ts +43 -0
- package/dist/agents/result-store.js +145 -0
- package/dist/agents/session-diff.d.ts +49 -0
- package/dist/agents/session-diff.js +249 -0
- package/dist/agents/tool-loader.d.ts +65 -0
- package/dist/agents/tool-loader.js +273 -0
- package/dist/agents/tool-selector.d.ts +123 -0
- package/dist/agents/tool-selector.js +321 -0
- package/dist/agents/transcript.d.ts +96 -0
- package/dist/agents/transcript.js +267 -0
- package/dist/agents/verified-run-git.d.ts +49 -0
- package/dist/agents/verified-run-git.js +82 -0
- package/dist/agents/verified-run.d.ts +149 -0
- package/dist/agents/verified-run.js +402 -0
- package/dist/agents/verifier.d.ts +64 -0
- package/dist/agents/verifier.js +186 -0
- package/dist/agents/worktree-manager.d.ts +80 -0
- package/dist/agents/worktree-manager.js +203 -0
- package/dist/agents/worktree-tools.d.ts +47 -0
- package/dist/agents/worktree-tools.js +246 -0
- package/dist/auth/middleware.js +14 -0
- package/dist/chat/agentic-executor.d.ts +7 -0
- package/dist/chat/agentic-executor.js +263 -32
- package/dist/chat/conversations.d.ts +2 -0
- package/dist/chat/conversations.js +8 -0
- package/dist/chat/execution/executor.d.ts +8 -0
- package/dist/chat/execution/executor.js +157 -103
- package/dist/chat/execution/index.js +5 -1
- package/dist/chat/execution/sandbox.d.ts +8 -0
- package/dist/chat/execution/sandbox.js +25 -1
- package/dist/chat/execution/tool-router.js +40 -14
- package/dist/chat/execution/tools/canvas.d.ts +2 -2
- package/dist/chat/execution/tools/code-tools.d.ts +66 -0
- package/dist/chat/execution/tools/code-tools.js +353 -0
- package/dist/chat/execution/tools/complete-task.d.ts +2 -2
- package/dist/chat/execution/tools/cron-tool.d.ts +26 -10
- package/dist/chat/execution/tools/cron-tool.js +48 -3
- package/dist/chat/execution/tools/decompose-task.d.ts +58 -0
- package/dist/chat/execution/tools/decompose-task.js +166 -0
- package/dist/chat/execution/tools/exec.d.ts +5 -2
- package/dist/chat/execution/tools/exec.js +294 -155
- package/dist/chat/execution/tools/feed-tools.d.ts +77 -0
- package/dist/chat/execution/tools/feed-tools.js +142 -0
- package/dist/chat/execution/tools/file-ops.d.ts +1 -1
- package/dist/chat/execution/tools/github.d.ts +2 -2
- package/dist/chat/execution/tools/index.d.ts +14 -2
- package/dist/chat/execution/tools/index.js +86 -12
- package/dist/chat/execution/tools/integrations.d.ts +8 -8
- package/dist/chat/execution/tools/multi-patch.d.ts +53 -0
- package/dist/chat/execution/tools/multi-patch.js +373 -0
- package/dist/chat/execution/tools/openai-image-gen.d.ts +2 -2
- package/dist/chat/execution/tools/plan-tools.d.ts +80 -0
- package/dist/chat/execution/tools/plan-tools.js +134 -0
- package/dist/chat/execution/tools/profclaw-ops.d.ts +6 -6
- package/dist/chat/execution/tools/repl-tool.d.ts +46 -0
- package/dist/chat/execution/tools/repl-tool.js +207 -0
- package/dist/chat/execution/tools/sessions-send.d.ts +2 -2
- package/dist/chat/execution/tools/slack-actions.d.ts +2 -2
- package/dist/chat/execution/tools/system.d.ts +4 -4
- package/dist/chat/execution/tools/todo-tool.d.ts +72 -0
- package/dist/chat/execution/tools/todo-tool.js +152 -0
- package/dist/chat/execution/tools/tool-search.d.ts +50 -0
- package/dist/chat/execution/tools/tool-search.js +155 -0
- package/dist/chat/execution/tools/tts-speak.d.ts +2 -2
- package/dist/chat/execution/types.d.ts +21 -14
- package/dist/chat/execution/workflows/executor.d.ts +11 -0
- package/dist/chat/execution/workflows/executor.js +99 -1
- package/dist/chat/execution/workflows/types.d.ts +35 -2
- package/dist/chat/format/index.d.ts +1 -0
- package/dist/chat/format/index.js +1 -0
- package/dist/chat/format/markdown-convert.d.ts +23 -0
- package/dist/chat/format/markdown-convert.js +149 -0
- package/dist/chat/index.d.ts +1 -1
- package/dist/chat/index.js +1 -1
- package/dist/chat/message-handler.js +58 -6
- package/dist/chat/meta-tool-handlers.d.ts +18 -0
- package/dist/chat/meta-tool-handlers.js +51 -0
- package/dist/chat/proactive/index.d.ts +62 -0
- package/dist/chat/proactive/index.js +147 -0
- package/dist/chat/prompt-adapter.js +2 -0
- package/dist/chat/providers/irc/index.d.ts +2 -2
- package/dist/chat/providers/telegram/index.d.ts +2 -0
- package/dist/chat/providers/telegram/index.js +21 -2
- package/dist/chat/system-prompts.d.ts +3 -3
- package/dist/chat/system-prompts.js +121 -61
- package/dist/chat/tool-handler.d.ts +2 -0
- package/dist/chat/tool-handler.js +47 -3
- package/dist/chat/tools.d.ts +6 -6
- package/dist/cli/commands/auth.js +64 -1
- package/dist/cli/commands/chat.js +1327 -138
- package/dist/cli/commands/doctor.js +222 -16
- package/dist/cli/commands/history.d.ts +3 -0
- package/dist/cli/commands/history.js +138 -0
- package/dist/cli/commands/import.d.ts +44 -0
- package/dist/cli/commands/import.js +526 -0
- package/dist/cli/commands/init.d.ts +13 -0
- package/dist/cli/commands/init.js +381 -0
- package/dist/cli/commands/onboard.js +210 -30
- package/dist/cli/commands/plan.d.ts +13 -0
- package/dist/cli/commands/plan.js +184 -0
- package/dist/cli/commands/receipt.d.ts +7 -0
- package/dist/cli/commands/receipt.js +90 -0
- package/dist/cli/commands/run.d.ts +28 -0
- package/dist/cli/commands/run.js +204 -0
- package/dist/cli/commands/serve.d.ts +7 -0
- package/dist/cli/commands/serve.js +77 -18
- package/dist/cli/commands/setup.js +84 -3
- package/dist/cli/commands/status.js +54 -0
- package/dist/cli/commands/tools.js +13 -13
- package/dist/cli/commands/tui.js +26 -1
- package/dist/cli/index.js +23 -0
- package/dist/cli/ink/App.d.ts +13 -0
- package/dist/cli/ink/App.js +6 -0
- package/dist/cli/ink/ChatApp.d.ts +60 -0
- package/dist/cli/ink/ChatApp.js +325 -0
- package/dist/cli/ink/DashboardApp.d.ts +3 -0
- package/dist/cli/ink/DashboardApp.js +143 -0
- package/dist/cli/ink/components/AgentStatus.d.ts +17 -0
- package/dist/cli/ink/components/AgentStatus.js +33 -0
- package/dist/cli/ink/components/ChannelList.d.ts +17 -0
- package/dist/cli/ink/components/ChannelList.js +33 -0
- package/dist/cli/ink/components/ConnectionStatus.d.ts +19 -0
- package/dist/cli/ink/components/ConnectionStatus.js +50 -0
- package/dist/cli/ink/components/CostBar.d.ts +19 -0
- package/dist/cli/ink/components/CostBar.js +35 -0
- package/dist/cli/ink/components/HookStatus.d.ts +15 -0
- package/dist/cli/ink/components/HookStatus.js +7 -0
- package/dist/cli/ink/components/PermissionPrompt.d.ts +21 -0
- package/dist/cli/ink/components/PermissionPrompt.js +51 -0
- package/dist/cli/ink/components/PlanView.d.ts +23 -0
- package/dist/cli/ink/components/PlanView.js +26 -0
- package/dist/cli/ink/components/ProviderList.d.ts +16 -0
- package/dist/cli/ink/components/ProviderList.js +16 -0
- package/dist/cli/ink/components/SessionHeader.d.ts +15 -0
- package/dist/cli/ink/components/SessionHeader.js +15 -0
- package/dist/cli/ink/components/StreamingMessage.d.ts +20 -0
- package/dist/cli/ink/components/StreamingMessage.js +27 -0
- package/dist/cli/ink/components/SuggestionBar.d.ts +15 -0
- package/dist/cli/ink/components/SuggestionBar.js +28 -0
- package/dist/cli/ink/components/SystemHealth.d.ts +20 -0
- package/dist/cli/ink/components/SystemHealth.js +39 -0
- package/dist/cli/ink/components/TaskList.d.ts +17 -0
- package/dist/cli/ink/components/TaskList.js +59 -0
- package/dist/cli/ink/components/ToolCall.d.ts +17 -0
- package/dist/cli/ink/components/ToolCall.js +43 -0
- package/dist/cli/ink/index.d.ts +23 -0
- package/dist/cli/ink/index.js +15 -0
- package/dist/cli/ink/keybindings.d.ts +35 -0
- package/dist/cli/ink/keybindings.js +105 -0
- package/dist/cli/ink/markdown-renderer.d.ts +47 -0
- package/dist/cli/ink/markdown-renderer.js +380 -0
- package/dist/cli/ink/output-styles.d.ts +39 -0
- package/dist/cli/ink/output-styles.js +119 -0
- package/dist/cli/interactive/auto-serve.d.ts +38 -0
- package/dist/cli/interactive/auto-serve.js +209 -0
- package/dist/cli/interactive/index.d.ts +25 -0
- package/dist/cli/interactive/index.js +23 -0
- package/dist/cli/interactive/picker.d.ts +28 -0
- package/dist/cli/interactive/picker.js +153 -0
- package/dist/cli/interactive/renderer.d.ts +26 -0
- package/dist/cli/interactive/renderer.js +555 -0
- package/dist/cli/interactive/repl.d.ts +14 -0
- package/dist/cli/interactive/repl.js +1516 -0
- package/dist/cli/interactive/stream-client.d.ts +59 -0
- package/dist/cli/interactive/stream-client.js +506 -0
- package/dist/cli/interactive/types.d.ts +121 -0
- package/dist/cli/interactive/types.js +10 -0
- package/dist/cli/utils/api.d.ts +9 -0
- package/dist/cli/utils/api.js +58 -2
- package/dist/costs/token-tracker.d.ts +10 -1
- package/dist/costs/token-tracker.js +37 -5
- package/dist/cron/natural-language.d.ts +54 -0
- package/dist/cron/natural-language.js +569 -0
- package/dist/cron/scheduler.d.ts +34 -4
- package/dist/cron/scheduler.js +141 -9
- package/dist/cron/templates.d.ts +1 -1
- package/dist/cron/templates.js +219 -0
- package/dist/feeds/feed-engine.d.ts +149 -0
- package/dist/feeds/feed-engine.js +600 -0
- package/dist/feeds/index.d.ts +9 -0
- package/dist/feeds/index.js +8 -0
- package/dist/gateway/router.js +6 -1
- package/dist/hooks/built-in/audit-log.d.ts +11 -0
- package/dist/hooks/built-in/audit-log.js +84 -0
- package/dist/hooks/built-in/cost-warning.d.ts +10 -0
- package/dist/hooks/built-in/cost-warning.js +59 -0
- package/dist/hooks/built-in/dangerous-tool.d.ts +32 -0
- package/dist/hooks/built-in/dangerous-tool.js +80 -0
- package/dist/hooks/built-in/index.d.ts +14 -0
- package/dist/hooks/built-in/index.js +20 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.js +6 -0
- package/dist/hooks/loader.d.ts +17 -0
- package/dist/hooks/loader.js +142 -0
- package/dist/hooks/registry.d.ts +62 -0
- package/dist/hooks/registry.js +127 -0
- package/dist/integrations/web-search.js +6 -3
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.js +2 -0
- package/dist/memory/memory-service.js +14 -13
- package/dist/memory/observational.d.ts +62 -0
- package/dist/memory/observational.js +396 -0
- package/dist/middleware/content-filter.d.ts +22 -0
- package/dist/middleware/content-filter.js +69 -0
- package/dist/middleware/request-validator.d.ts +159 -0
- package/dist/middleware/request-validator.js +93 -0
- package/dist/plugins/sdk.d.ts +22 -0
- package/dist/plugins/sdk.js +17 -1
- package/dist/projects/types.d.ts +10 -10
- package/dist/providers/ai-sdk.d.ts +11 -0
- package/dist/providers/ai-sdk.js +111 -56
- package/dist/providers/core/models.js +114 -6
- package/dist/providers/core/types.d.ts +7 -0
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.js +1 -0
- package/dist/providers/prompt-cache.d.ts +68 -0
- package/dist/providers/prompt-cache.js +165 -0
- package/dist/providers/smart-router.d.ts +118 -0
- package/dist/providers/smart-router.js +693 -0
- package/dist/providers/types.d.ts +16 -16
- package/dist/routes/agents.js +50 -0
- package/dist/routes/auth.js +8 -1
- package/dist/routes/chat.js +280 -18
- package/dist/routes/costs.js +32 -0
- package/dist/routes/cron.js +80 -5
- package/dist/routes/feeds.d.ts +10 -0
- package/dist/routes/feeds.js +168 -0
- package/dist/routes/mcp.js +21 -0
- package/dist/routes/memory.js +130 -0
- package/dist/routes/skills.js +129 -0
- package/dist/routes/teams.d.ts +9 -0
- package/dist/routes/teams.js +210 -0
- package/dist/routes/tools.js +14 -0
- package/dist/routes/users.js +2 -0
- package/dist/server/route-loader.js +3 -1
- package/dist/server/stream-bridge.d.ts +19 -0
- package/dist/server/stream-bridge.js +38 -0
- package/dist/server.js +313 -36
- package/dist/skills/marketplace.d.ts +87 -0
- package/dist/skills/marketplace.js +268 -0
- package/dist/storage/index.d.ts +14 -0
- package/dist/storage/index.js +64 -3
- package/dist/storage/schema.d.ts +4 -4
- package/dist/storage/schema.js +1 -1
- package/dist/teams/index.d.ts +110 -0
- package/dist/teams/index.js +365 -0
- package/dist/tickets/types.d.ts +39 -39
- package/dist/types/summary.d.ts +5 -5
- package/dist/utils/auto-update.d.ts +23 -0
- package/dist/utils/auto-update.js +157 -0
- package/dist/utils/offline-detect.d.ts +55 -0
- package/dist/utils/offline-detect.js +121 -0
- package/dist/utils/pid-file.d.ts +36 -0
- package/dist/utils/pid-file.js +125 -0
- package/dist/utils/prevent-sleep.d.ts +27 -0
- package/dist/utils/prevent-sleep.js +95 -0
- package/dist/utils/sanitizer.d.ts +57 -0
- package/dist/utils/sanitizer.js +174 -0
- package/docker-compose.yml +13 -137
- package/package.json +31 -6
- package/skills/deploy-cloudflare/SKILL.md +62 -0
- package/skills/deploy-vercel/SKILL.md +67 -0
- package/skills/docker-deploy/SKILL.md +158 -0
- package/skills/full-stack-builder/SKILL.md +92 -0
- package/skills/humanizer/SKILL.md +488 -0
- package/skills/profclaw-assistant/SKILL.md +85 -56
- package/ui/dist/assets/ActivityView-Da6HQ8ws.js +1 -0
- package/ui/dist/assets/AgentList-H58R0kX3.js +1 -0
- package/ui/dist/assets/AnalyticsDashboard-B28AeRsc.js +1 -0
- package/ui/dist/assets/AreaChart-DwLzeAQ8.js +1 -0
- package/ui/dist/assets/CartesianChart-piKQsTAR.js +36 -0
- package/ui/dist/assets/ChatView-Dbj8rxU5.js +10 -0
- package/ui/dist/assets/CostsDashboard-C6F5df0F.js +1 -0
- package/ui/dist/assets/EstimateSelect-wga0rUKX.js +1 -0
- package/ui/dist/assets/FeedDashboard-Ef6FEzEf.js +1 -0
- package/ui/dist/assets/FloatingChatbot-0yhkUeCq.js +2 -0
- package/ui/dist/assets/InviteCodeManagement-tUXfx4Bc.js +2 -0
- package/ui/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/ui/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/ui/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/ui/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/ui/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/ui/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/ui/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/ui/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/ui/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/ui/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/ui/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/ui/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/ui/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/ui/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/ui/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/ui/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/ui/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/ui/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/ui/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/ui/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/ui/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/ui/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/ui/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/ui/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/ui/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/ui/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/ui/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/ui/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/ui/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/ui/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/ui/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/ui/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/ui/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/ui/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/ui/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/ui/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/ui/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/ui/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/ui/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/ui/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/ui/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/ui/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/ui/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/ui/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/ui/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/ui/dist/assets/MarketplacePage-DGrLtolR.js +1 -0
- package/ui/dist/assets/{ProjectDetail--gPfvATB.js → ProjectDetail-BgWvA6UP.js} +2 -2
- package/ui/dist/assets/ProjectIcon-TDuliqwg.js +1 -0
- package/ui/dist/assets/ProjectList-DXgM4187.js +1 -0
- package/ui/dist/assets/{Settings-1kaf7VHE.js → Settings-xA8Zhi3p.js} +3 -3
- package/ui/dist/assets/StatusIndicator-B8vfFAxg.js +1 -0
- package/ui/dist/assets/{SummaryDetail-DV3AmONk.js → SummaryDetail-eedRfTtF.js} +2 -2
- package/ui/dist/assets/SummaryList-CLNX2P84.js +1 -0
- package/ui/dist/assets/TaskDetail-BtWclNiR.js +1 -0
- package/ui/dist/assets/TaskList-JjODAgSc.js +1 -0
- package/ui/dist/assets/TeamsPage-CBK5iAyx.js +1 -0
- package/ui/dist/assets/TicketBoard-C9aJNNYp.js +1 -0
- package/ui/dist/assets/TicketDetail-CV5JmL31.js +1 -0
- package/ui/dist/assets/TicketList-68V4lzUz.js +1 -0
- package/ui/dist/assets/UserManagement-DKTb6UpE.js +2 -0
- package/ui/dist/assets/ViewSwitcher-BvdQht2Y.js +1 -0
- package/ui/dist/assets/alert-dialog-O6qBOv_f.js +1 -0
- package/ui/dist/assets/{archive-BsLa7brF.js → archive-CX7UvZpf.js} +1 -1
- package/ui/dist/assets/badge-BbfnwDJP.js +1 -0
- package/ui/dist/assets/{bug-CmZI7jqM.js → bug-3WX0394-.js} +1 -1
- package/ui/dist/assets/{calendar-Bf0t2B82.js → calendar-buq77TaS.js} +1 -1
- package/ui/dist/assets/{chevron-up-CoUsOvZj.js → chevron-up-4ymsBJRo.js} +1 -1
- package/ui/dist/assets/{circle-x-Dgw11LgT.js → circle-x-ByXtwR6Y.js} +1 -1
- package/ui/dist/assets/constants-CVdDh7p0.js +1 -0
- package/ui/dist/assets/{cpu-DiPMQICV.js → cpu-CiuoCeDY.js} +1 -1
- package/ui/dist/assets/{database-BwTfupDi.js → database-BWXSBg5a.js} +1 -1
- package/ui/dist/assets/dialog-lDg4NvMV.js +1 -0
- package/ui/dist/assets/dollar-sign-Dmijd6DP.js +1 -0
- package/ui/dist/assets/{ellipsis-UJx4Xnf6.js → ellipsis-vT-5SVIp.js} +1 -1
- package/ui/dist/assets/{ellipsis-vertical-DoULYEKn.js → ellipsis-vertical-B4tAX_bL.js} +1 -1
- package/ui/dist/assets/feature-markdown-DBo5Q7uq.js +289 -0
- package/ui/dist/assets/{file-code-B2UrJLwi.js → file-code-ChOWdKXf.js} +1 -1
- package/ui/dist/assets/{folder-open-BJi577JH.js → folder-open-CkOUbIiP.js} +1 -1
- package/ui/dist/assets/{funnel-PkaD_HSR.js → funnel-uZkoSPP-.js} +1 -1
- package/ui/dist/assets/{git-branch-C_K30am0.js → git-branch-CwvUxj7C.js} +1 -1
- package/ui/dist/assets/{git-commit-horizontal-IT6ecxWQ.js → git-commit-horizontal-lxPzCvhD.js} +1 -1
- package/ui/dist/assets/{globe-f-jjCa_g.js → globe-D_WpJdsj.js} +1 -1
- package/ui/dist/assets/{hash-DNEv8Elo.js → hash-CA0hJ7vh.js} +1 -1
- package/ui/dist/assets/{history-BQSBo_1Q.js → history-CEWMLELs.js} +1 -1
- package/ui/dist/assets/inbox-ehtOptTV.js +1 -0
- package/ui/dist/assets/{index-nS3EErDg.js → index-C1rhbml4.js} +3 -3
- package/ui/dist/assets/index-CR8gfCHv.js +1 -0
- package/ui/dist/assets/index-DVXMpWai.js +1 -0
- package/ui/dist/assets/index-DaDJMM2v.js +1 -0
- package/ui/dist/assets/index-Djdq_0xu.js +1 -0
- package/ui/dist/assets/index-M46Gcb8K.css +1 -0
- package/ui/dist/assets/index-sEBN7w8J.js +109 -0
- package/ui/dist/assets/layers-C6Mhf8Nk.js +1 -0
- package/ui/dist/assets/{layout-dashboard-CcKt1hXw.js → layout-dashboard-BRUM0kpT.js} +1 -1
- package/ui/dist/assets/{lightbulb-Jhp7FvbU.js → lightbulb-CN2q1O5l.js} +1 -1
- package/ui/dist/assets/{link-2-DdO7ostF.js → link-2-CC4E28yJ.js} +1 -1
- package/ui/dist/assets/markdown-renderer-C6ENbB0u.js +10 -0
- package/ui/dist/assets/markdown-renderer-CfVKi3_s.css +1 -0
- package/ui/dist/assets/{message-square-CBgH65X7.js → message-square-Bbb241am.js} +1 -1
- package/ui/dist/assets/package-CwT3IzFx.js +1 -0
- package/ui/dist/assets/{pencil-CYXCEPQh.js → pencil-CDmiHzoj.js} +1 -1
- package/ui/dist/assets/{play-d1ONaH0-.js → play-tjy5jMQX.js} +1 -1
- package/ui/dist/assets/popover-CFHZf3pE.js +1 -0
- package/ui/dist/assets/progress-BboUHuLf.js +1 -0
- package/ui/dist/assets/{rocket-DhvUetsk.js → rocket--8ZHgdXJ.js} +1 -1
- package/ui/dist/assets/select-n108rXny.js +1 -0
- package/ui/dist/assets/{send-P0r5D7td.js → send-Cu7MR2Qh.js} +1 -1
- package/ui/dist/assets/server-DmodxZp-.js +1 -0
- package/ui/dist/assets/{settings-2-ocj5uHGx.js → settings-2-CkRNqkxj.js} +1 -1
- package/ui/dist/assets/sheet-7aUJkyzU.js +1 -0
- package/ui/dist/assets/{shield-check-DfVdE34l.js → shield-check-ViI3nMKE.js} +1 -1
- package/ui/dist/assets/{shield-off-8l0J6R-8.js → shield-off-DN3tagkn.js} +1 -1
- package/ui/dist/assets/skeleton-C0E1Nfro.js +1 -0
- package/ui/dist/assets/{smartphone-77_g3SQn.js → smartphone-5FghiXpA.js} +1 -1
- package/ui/dist/assets/{square-Ckzsr3Rn.js → square-DiNSx8K7.js} +1 -1
- package/ui/dist/assets/star-DhdFVidS.js +1 -0
- package/ui/dist/assets/switch-CIgVbZqQ.js +1 -0
- package/ui/dist/assets/table-BC56FVMV.js +1 -0
- package/ui/dist/assets/{tag-C35mgoEv.js → tag-CH_vQliw.js} +1 -1
- package/ui/dist/assets/textarea-CxDiKFXZ.js +1 -0
- package/ui/dist/assets/{timer-DHJBS2w1.js → timer-CdGVTb60.js} +1 -1
- package/ui/dist/assets/tooltip-BuW9A5UO.js +1 -0
- package/ui/dist/assets/{trash-2-keO5tKPE.js → trash-2-CucZJL0N.js} +1 -1
- package/ui/dist/assets/trending-down-BCezC1z2.js +1 -0
- package/ui/dist/assets/{trending-up-BBv8KbrY.js → trending-up-C5OYX2k2.js} +1 -1
- package/ui/dist/assets/vendor-query-C0p7b53x.js +4 -0
- package/ui/dist/assets/vendor-react-Mc5_kfYG.js +12 -0
- package/ui/dist/assets/vendor-ui-CXPAUBFv.js +51 -0
- package/ui/dist/assets/{wand-sparkles-BusQ52ZK.js → wand-sparkles-BaH6pJnc.js} +1 -1
- package/ui/dist/assets/{wrench-02YaOSiK.js → wrench-CjxjP6ok.js} +1 -1
- package/ui/dist/index.html +5 -2
- package/ui/dist/assets/ActivityView-BeshZXmE.js +0 -1
- package/ui/dist/assets/AgentList-QVHeldPi.js +0 -1
- package/ui/dist/assets/AnalyticsDashboard-C9R97dXE.js +0 -1
- package/ui/dist/assets/AreaChart-B73gaiVQ.js +0 -1
- package/ui/dist/assets/CartesianChart-CXYL2R-A.js +0 -36
- package/ui/dist/assets/ChatView-qjZErlrp.js +0 -10
- package/ui/dist/assets/CostsDashboard-O4DCLy1i.js +0 -1
- package/ui/dist/assets/EstimateSelect-1hQf4Osk.js +0 -1
- package/ui/dist/assets/FloatingChatbot-BZBzrJxd.js +0 -2
- package/ui/dist/assets/InviteCodeManagement-LEoGqYeA.js +0 -2
- package/ui/dist/assets/ProjectIcon-Chd_ofsw.js +0 -1
- package/ui/dist/assets/ProjectList-BvUfVB6c.js +0 -4
- package/ui/dist/assets/StatusIndicator-pRfkNcdV.js +0 -1
- package/ui/dist/assets/SummaryList-B6kXiTxL.js +0 -1
- package/ui/dist/assets/TaskDetail-CV6CzbOS.js +0 -1
- package/ui/dist/assets/TaskList-DL7brQKd.js +0 -1
- package/ui/dist/assets/TicketBoard-CrkkFj7C.js +0 -1
- package/ui/dist/assets/TicketDetail-hnnYclpD.js +0 -1
- package/ui/dist/assets/TicketList-CsDAyQCL.js +0 -1
- package/ui/dist/assets/UserManagement-BGFQyTSr.js +0 -2
- package/ui/dist/assets/ViewSwitcher-CnL0OqA8.js +0 -1
- package/ui/dist/assets/alert-dialog-SKM6Gjz4.js +0 -7
- package/ui/dist/assets/badge-CVHH1a-v.js +0 -1
- package/ui/dist/assets/brain-6o_RHVpe.js +0 -1
- package/ui/dist/assets/constants-Q5Zivl-a.js +0 -1
- package/ui/dist/assets/dialog-BUqN9Psj.js +0 -1
- package/ui/dist/assets/index-BUmnwPQr.js +0 -1
- package/ui/dist/assets/index-BfF5G4Cw.js +0 -1
- package/ui/dist/assets/index-C8N375c2.js +0 -1
- package/ui/dist/assets/index-CuxnqVVz.css +0 -1
- package/ui/dist/assets/index-CzMM3QOk.js +0 -1
- package/ui/dist/assets/index-lJlNPFVJ.js +0 -67
- package/ui/dist/assets/layers-jFqVrWMD.js +0 -1
- package/ui/dist/assets/markdown-renderer-n1ToC4XQ.js +0 -36
- package/ui/dist/assets/popover-CrmZgoWu.js +0 -1
- package/ui/dist/assets/progress-uv4SPkL5.js +0 -1
- package/ui/dist/assets/select-CeQ8AHGy.js +0 -1
- package/ui/dist/assets/server-CVHTZB72.js +0 -1
- package/ui/dist/assets/sheet-DuQExSho.js +0 -1
- package/ui/dist/assets/skeleton-TFiFJ3nB.js +0 -1
- package/ui/dist/assets/switch-CAePkd6k.js +0 -1
- package/ui/dist/assets/table-ZjAZ7hkt.js +0 -1
- package/ui/dist/assets/textarea-DsVPnSgR.js +0 -1
- package/ui/dist/assets/tooltip-BYmQ331W.js +0 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verifier
|
|
3
|
+
*
|
|
4
|
+
* Runs a user-provided verification command (tests, typecheck, lint, build or
|
|
5
|
+
* anything custom) as an objective judge of "done". The command is the only
|
|
6
|
+
* shell input: goal text and model output are never interpolated into it.
|
|
7
|
+
*
|
|
8
|
+
* Safety conventions:
|
|
9
|
+
* - runs with cwd pinned to the run's worktree
|
|
10
|
+
* - hard timeout, process group is killed on expiry
|
|
11
|
+
* - captured output is capped in memory and trimmed for feedback
|
|
12
|
+
* - a small denylist rejects commands that publish or destroy (git push,
|
|
13
|
+
* gh pr create, rm -rf /, curl | sh) because a verifier must only observe
|
|
14
|
+
*/
|
|
15
|
+
import type { PlanOptions } from './command-sandbox.js';
|
|
16
|
+
export interface VerifierResult {
|
|
17
|
+
passed: boolean;
|
|
18
|
+
/** Exit code, or null when killed by timeout or signal */
|
|
19
|
+
exitCode: number | null;
|
|
20
|
+
timedOut: boolean;
|
|
21
|
+
durationMs: number;
|
|
22
|
+
/** Trimmed combined stdout + stderr, suitable for feeding back to an agent */
|
|
23
|
+
output: string;
|
|
24
|
+
/** True when the raw output was longer than the trimmed output */
|
|
25
|
+
truncated: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface VerifierOptions {
|
|
28
|
+
cwd: string;
|
|
29
|
+
timeoutMs: number;
|
|
30
|
+
/** Max characters of output kept for feedback (head and tail are kept) */
|
|
31
|
+
maxOutputChars: number;
|
|
32
|
+
env?: NodeJS.ProcessEnv;
|
|
33
|
+
/**
|
|
34
|
+
* Run the command under the OS sandbox (see command-sandbox.ts). Off by
|
|
35
|
+
* default: user supplied verify commands often need network or write
|
|
36
|
+
* outside the worktree (package caches).
|
|
37
|
+
*/
|
|
38
|
+
sandbox?: PlanOptions & {
|
|
39
|
+
allowNetwork?: boolean;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** Anything that can judge a workspace. Tests inject fakes. */
|
|
43
|
+
export interface Verifier {
|
|
44
|
+
verify(): Promise<VerifierResult>;
|
|
45
|
+
}
|
|
46
|
+
/** Returns a rejection reason, or null when the command is acceptable. */
|
|
47
|
+
export declare function validateVerifyCommand(command: string): string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Keep the head and tail of long output (failures usually name the problem
|
|
50
|
+
* at the top and summarise at the bottom) and drop the middle.
|
|
51
|
+
*/
|
|
52
|
+
export declare function trimOutput(raw: string, maxChars: number): {
|
|
53
|
+
text: string;
|
|
54
|
+
truncated: boolean;
|
|
55
|
+
};
|
|
56
|
+
export declare class CommandVerifier implements Verifier {
|
|
57
|
+
private readonly command;
|
|
58
|
+
private readonly options;
|
|
59
|
+
constructor(command: string, options: VerifierOptions);
|
|
60
|
+
verify(): Promise<VerifierResult>;
|
|
61
|
+
}
|
|
62
|
+
/** Format a result as feedback text for the next agent attempt. */
|
|
63
|
+
export declare function formatFailureFeedback(result: VerifierResult, command: string): string;
|
|
64
|
+
//# sourceMappingURL=verifier.d.ts.map
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verifier
|
|
3
|
+
*
|
|
4
|
+
* Runs a user-provided verification command (tests, typecheck, lint, build or
|
|
5
|
+
* anything custom) as an objective judge of "done". The command is the only
|
|
6
|
+
* shell input: goal text and model output are never interpolated into it.
|
|
7
|
+
*
|
|
8
|
+
* Safety conventions:
|
|
9
|
+
* - runs with cwd pinned to the run's worktree
|
|
10
|
+
* - hard timeout, process group is killed on expiry
|
|
11
|
+
* - captured output is capped in memory and trimmed for feedback
|
|
12
|
+
* - a small denylist rejects commands that publish or destroy (git push,
|
|
13
|
+
* gh pr create, rm -rf /, curl | sh) because a verifier must only observe
|
|
14
|
+
*/
|
|
15
|
+
import { spawn } from 'node:child_process';
|
|
16
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
17
|
+
import { tmpdir } from 'node:os';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
import { planSandboxedCommand, resolveAllowNetwork, resolveExtraWritable } from './command-sandbox.js';
|
|
20
|
+
// Command policy
|
|
21
|
+
const FORBIDDEN_PATTERNS = [
|
|
22
|
+
{ pattern: /\bgit\b[^;&|\n]*\bpush\b/, reason: 'git push is not allowed in a verifier' },
|
|
23
|
+
{ pattern: /\bgh\s+pr\s+(?:create|merge)\b/, reason: 'opening or merging PRs is not allowed in a verifier' },
|
|
24
|
+
{ pattern: /\brm\s+(?:-\S*\s+)*-\S*[rR]\S*\s+(?:-\S+\s+)*(?:\/|~|\$HOME)(?:\s|$)/, reason: 'destructive rm is not allowed in a verifier' },
|
|
25
|
+
{ pattern: /\b(?:curl|wget)\b[^|;&]*\|\s*(?:sudo\s+)?(?:sh|bash|zsh)\b/, reason: 'piping downloads into a shell is not allowed' },
|
|
26
|
+
{ pattern: /\bsudo\b/, reason: 'sudo is not allowed in a verifier' },
|
|
27
|
+
];
|
|
28
|
+
/** Returns a rejection reason, or null when the command is acceptable. */
|
|
29
|
+
export function validateVerifyCommand(command) {
|
|
30
|
+
if (command.trim().length === 0)
|
|
31
|
+
return 'verify command is empty';
|
|
32
|
+
if (command.includes('\0'))
|
|
33
|
+
return 'verify command contains a NUL byte';
|
|
34
|
+
for (const { pattern, reason } of FORBIDDEN_PATTERNS) {
|
|
35
|
+
if (pattern.test(command))
|
|
36
|
+
return reason;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
// Output trimming
|
|
41
|
+
/**
|
|
42
|
+
* Keep the head and tail of long output (failures usually name the problem
|
|
43
|
+
* at the top and summarise at the bottom) and drop the middle.
|
|
44
|
+
*/
|
|
45
|
+
export function trimOutput(raw, maxChars) {
|
|
46
|
+
const cleaned = stripAnsi(raw).trim();
|
|
47
|
+
if (cleaned.length <= maxChars)
|
|
48
|
+
return { text: cleaned, truncated: false };
|
|
49
|
+
const marker = '\n... [output trimmed] ...\n';
|
|
50
|
+
const budget = Math.max(0, maxChars - marker.length);
|
|
51
|
+
const head = Math.ceil(budget * 0.4);
|
|
52
|
+
const tail = budget - head;
|
|
53
|
+
return {
|
|
54
|
+
text: cleaned.slice(0, head) + marker + (tail > 0 ? cleaned.slice(-tail) : ''),
|
|
55
|
+
truncated: true,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function stripAnsi(text) {
|
|
59
|
+
// eslint-disable-next-line no-control-regex
|
|
60
|
+
return text.replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, '');
|
|
61
|
+
}
|
|
62
|
+
// Command verifier
|
|
63
|
+
export class CommandVerifier {
|
|
64
|
+
command;
|
|
65
|
+
options;
|
|
66
|
+
constructor(command, options) {
|
|
67
|
+
this.command = command;
|
|
68
|
+
this.options = options;
|
|
69
|
+
}
|
|
70
|
+
async verify() {
|
|
71
|
+
const rejection = validateVerifyCommand(this.command);
|
|
72
|
+
if (rejection) {
|
|
73
|
+
return {
|
|
74
|
+
passed: false,
|
|
75
|
+
exitCode: null,
|
|
76
|
+
timedOut: false,
|
|
77
|
+
durationMs: 0,
|
|
78
|
+
output: `Verifier rejected: ${rejection}`,
|
|
79
|
+
truncated: false,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return runCommand(this.command, this.options);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Cap on raw bytes retained in memory regardless of trim setting.
|
|
86
|
+
const RAW_CAPTURE_LIMIT = 2_000_000;
|
|
87
|
+
async function runCommand(command, options) {
|
|
88
|
+
if (!options.sandbox)
|
|
89
|
+
return spawnCommand({ file: '/bin/sh', args: ['-c', command], env: {}, backend: 'none' }, options);
|
|
90
|
+
const tempDir = await mkdtemp(join(tmpdir(), 'profclaw-verify-'));
|
|
91
|
+
try {
|
|
92
|
+
const plan = planSandboxedCommand(command, {
|
|
93
|
+
workdir: options.cwd,
|
|
94
|
+
tempDir,
|
|
95
|
+
allowNetwork: options.sandbox.allowNetwork ?? resolveAllowNetwork(),
|
|
96
|
+
extraWritable: resolveExtraWritable(),
|
|
97
|
+
}, options.sandbox);
|
|
98
|
+
return await spawnCommand(plan, options);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
return {
|
|
102
|
+
passed: false,
|
|
103
|
+
exitCode: null,
|
|
104
|
+
timedOut: false,
|
|
105
|
+
durationMs: 0,
|
|
106
|
+
output: `Verifier sandbox error: ${error instanceof Error ? error.message : String(error)}`,
|
|
107
|
+
truncated: false,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function spawnCommand(plan, options) {
|
|
115
|
+
return new Promise((resolve) => {
|
|
116
|
+
const started = Date.now();
|
|
117
|
+
let buffer = '';
|
|
118
|
+
let rawTruncated = false;
|
|
119
|
+
let timedOut = false;
|
|
120
|
+
let settled = false;
|
|
121
|
+
const child = spawn(plan.file, plan.args, {
|
|
122
|
+
cwd: options.cwd,
|
|
123
|
+
env: { ...process.env, ...options.env, ...plan.env, CI: process.env.CI ?? '1' },
|
|
124
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
125
|
+
detached: true,
|
|
126
|
+
});
|
|
127
|
+
const append = (chunk) => {
|
|
128
|
+
if (buffer.length >= RAW_CAPTURE_LIMIT) {
|
|
129
|
+
rawTruncated = true;
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
buffer += chunk.toString('utf-8');
|
|
133
|
+
};
|
|
134
|
+
child.stdout.on('data', append);
|
|
135
|
+
child.stderr.on('data', append);
|
|
136
|
+
const killGroup = () => {
|
|
137
|
+
if (child.pid === undefined)
|
|
138
|
+
return;
|
|
139
|
+
try {
|
|
140
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
child.kill('SIGKILL');
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const timer = setTimeout(() => {
|
|
147
|
+
timedOut = true;
|
|
148
|
+
killGroup();
|
|
149
|
+
}, options.timeoutMs);
|
|
150
|
+
const finish = (exitCode, extra) => {
|
|
151
|
+
if (settled)
|
|
152
|
+
return;
|
|
153
|
+
settled = true;
|
|
154
|
+
clearTimeout(timer);
|
|
155
|
+
const trimmed = trimOutput(buffer + (extra ?? ''), options.maxOutputChars);
|
|
156
|
+
const output = timedOut
|
|
157
|
+
? `${trimmed.text}\n[verifier timed out after ${options.timeoutMs}ms]`.trim()
|
|
158
|
+
: trimmed.text;
|
|
159
|
+
resolve({
|
|
160
|
+
passed: exitCode === 0 && !timedOut,
|
|
161
|
+
exitCode,
|
|
162
|
+
timedOut,
|
|
163
|
+
durationMs: Date.now() - started,
|
|
164
|
+
output,
|
|
165
|
+
truncated: trimmed.truncated || rawTruncated,
|
|
166
|
+
});
|
|
167
|
+
};
|
|
168
|
+
child.on('error', (err) => finish(null, `\n${err.message}`));
|
|
169
|
+
child.on('close', (code) => finish(code));
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/** Format a result as feedback text for the next agent attempt. */
|
|
173
|
+
export function formatFailureFeedback(result, command) {
|
|
174
|
+
const status = result.timedOut
|
|
175
|
+
? 'timed out'
|
|
176
|
+
: `exited with code ${result.exitCode === null ? 'unknown' : result.exitCode}`;
|
|
177
|
+
return [
|
|
178
|
+
`The verification command \`${command}\` ${status}.`,
|
|
179
|
+
'Output (trimmed):',
|
|
180
|
+
'```',
|
|
181
|
+
result.output,
|
|
182
|
+
'```',
|
|
183
|
+
'Fix the underlying problem so the command passes. Do not edit the verification command or weaken tests to force a pass.',
|
|
184
|
+
].join('\n');
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=verifier.js.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worktree Manager
|
|
3
|
+
*
|
|
4
|
+
* Provides git worktree isolation for agent tasks. Each task can optionally
|
|
5
|
+
* run in its own git worktree so concurrent agents don't create dirty-tree
|
|
6
|
+
* conflicts on the main working tree.
|
|
7
|
+
*
|
|
8
|
+
* All git operations use execFile (not shell) to avoid injection risks.
|
|
9
|
+
*/
|
|
10
|
+
export interface WorktreeInfo {
|
|
11
|
+
/** Absolute path to the worktree directory */
|
|
12
|
+
path: string;
|
|
13
|
+
/** Branch checked out in this worktree */
|
|
14
|
+
branch: string;
|
|
15
|
+
/** Branch the worktree was created from */
|
|
16
|
+
baseBranch: string;
|
|
17
|
+
/** Unix timestamp (ms) when this worktree was created */
|
|
18
|
+
createdAt: number;
|
|
19
|
+
/** Optional task identifier that owns this worktree */
|
|
20
|
+
taskId?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface MergeResult {
|
|
23
|
+
success: boolean;
|
|
24
|
+
/** Conflicting file paths when success is false */
|
|
25
|
+
conflicts?: string[];
|
|
26
|
+
}
|
|
27
|
+
export declare class WorktreeManager {
|
|
28
|
+
private readonly worktrees;
|
|
29
|
+
/** Absolute path to the directory that holds all created worktrees */
|
|
30
|
+
private readonly baseDir;
|
|
31
|
+
/** Resolved project root (the main git working tree) */
|
|
32
|
+
private readonly projectRoot;
|
|
33
|
+
constructor(projectRoot?: string);
|
|
34
|
+
/**
|
|
35
|
+
* Create an isolated worktree for a task.
|
|
36
|
+
*
|
|
37
|
+
* Runs: git worktree add <path> -b <branch> [baseBranch]
|
|
38
|
+
*/
|
|
39
|
+
create(options: {
|
|
40
|
+
taskId: string;
|
|
41
|
+
/** Branch to base the new worktree on (defaults to current HEAD branch) */
|
|
42
|
+
baseBranch?: string;
|
|
43
|
+
/** Name for the new branch (defaults to profclaw/task-{taskId}) */
|
|
44
|
+
branchName?: string;
|
|
45
|
+
}): Promise<WorktreeInfo>;
|
|
46
|
+
/** Return all active worktrees tracked by this manager instance. */
|
|
47
|
+
list(): WorktreeInfo[];
|
|
48
|
+
/** Return the WorktreeInfo for a specific task, or undefined if unknown. */
|
|
49
|
+
get(taskId: string): WorktreeInfo | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Merge the worktree's branch back into its base branch.
|
|
52
|
+
*
|
|
53
|
+
* Runs: git merge [--squash] <branch> (executed from the base worktree)
|
|
54
|
+
*/
|
|
55
|
+
merge(taskId: string, options?: {
|
|
56
|
+
squash?: boolean;
|
|
57
|
+
message?: string;
|
|
58
|
+
}): Promise<MergeResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Remove a worktree from disk and deregister it.
|
|
61
|
+
*
|
|
62
|
+
* Runs: git worktree remove <path>
|
|
63
|
+
*/
|
|
64
|
+
remove(taskId: string): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Prune stale worktree metadata that git is tracking but whose paths no
|
|
67
|
+
* longer exist on disk.
|
|
68
|
+
*
|
|
69
|
+
* Runs: git worktree prune
|
|
70
|
+
*
|
|
71
|
+
* @returns Number of pruned entries as reported by git
|
|
72
|
+
*/
|
|
73
|
+
prune(): Promise<number>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Return a shared WorktreeManager rooted at the current working directory.
|
|
77
|
+
* Use the WorktreeManager constructor directly if you need a different root.
|
|
78
|
+
*/
|
|
79
|
+
export declare function getWorktreeManager(): WorktreeManager;
|
|
80
|
+
//# sourceMappingURL=worktree-manager.d.ts.map
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worktree Manager
|
|
3
|
+
*
|
|
4
|
+
* Provides git worktree isolation for agent tasks. Each task can optionally
|
|
5
|
+
* run in its own git worktree so concurrent agents don't create dirty-tree
|
|
6
|
+
* conflicts on the main working tree.
|
|
7
|
+
*
|
|
8
|
+
* All git operations use execFile (not shell) to avoid injection risks.
|
|
9
|
+
*/
|
|
10
|
+
import { execFile as execFileCb } from "node:child_process";
|
|
11
|
+
import { promisify } from "node:util";
|
|
12
|
+
import { mkdir, rm } from "node:fs/promises";
|
|
13
|
+
import { join, resolve } from "node:path";
|
|
14
|
+
import { logger } from '../utils/logger.js';
|
|
15
|
+
const execFile = promisify(execFileCb);
|
|
16
|
+
// Helpers
|
|
17
|
+
function sanitizeBranchName(name) {
|
|
18
|
+
// Strip characters that are not safe in git branch names
|
|
19
|
+
return name.replace(/[^a-zA-Z0-9/_.-]/g, "-").replace(/^[-.]|[-.]$/g, "");
|
|
20
|
+
}
|
|
21
|
+
async function getCurrentBranch(cwd) {
|
|
22
|
+
const { stdout } = await execFile("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd });
|
|
23
|
+
return stdout.trim();
|
|
24
|
+
}
|
|
25
|
+
async function isGitRepo(dir) {
|
|
26
|
+
try {
|
|
27
|
+
await execFile("git", ["rev-parse", "--git-dir"], { cwd: dir });
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// WorktreeManager
|
|
35
|
+
export class WorktreeManager {
|
|
36
|
+
worktrees = new Map();
|
|
37
|
+
/** Absolute path to the directory that holds all created worktrees */
|
|
38
|
+
baseDir;
|
|
39
|
+
/** Resolved project root (the main git working tree) */
|
|
40
|
+
projectRoot;
|
|
41
|
+
constructor(projectRoot) {
|
|
42
|
+
this.projectRoot = resolve(projectRoot ?? process.cwd());
|
|
43
|
+
this.baseDir = join(this.projectRoot, ".profclaw", "worktrees");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create an isolated worktree for a task.
|
|
47
|
+
*
|
|
48
|
+
* Runs: git worktree add <path> -b <branch> [baseBranch]
|
|
49
|
+
*/
|
|
50
|
+
async create(options) {
|
|
51
|
+
const { taskId } = options;
|
|
52
|
+
if (!(await isGitRepo(this.projectRoot))) {
|
|
53
|
+
throw new Error(`[WorktreeManager] ${this.projectRoot} is not a git repository`);
|
|
54
|
+
}
|
|
55
|
+
const baseBranch = options.baseBranch ?? (await getCurrentBranch(this.projectRoot));
|
|
56
|
+
const rawBranch = options.branchName ?? `profclaw/task-${taskId}`;
|
|
57
|
+
const branch = sanitizeBranchName(rawBranch);
|
|
58
|
+
const worktreePath = join(this.baseDir, taskId);
|
|
59
|
+
// Ensure the base directory exists
|
|
60
|
+
await mkdir(this.baseDir, { recursive: true });
|
|
61
|
+
try {
|
|
62
|
+
await execFile("git", ["worktree", "add", worktreePath, "-b", branch, baseBranch], { cwd: this.projectRoot });
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
throw new Error(`[WorktreeManager] Failed to create worktree for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
66
|
+
}
|
|
67
|
+
const info = {
|
|
68
|
+
path: worktreePath,
|
|
69
|
+
branch,
|
|
70
|
+
baseBranch,
|
|
71
|
+
createdAt: Date.now(),
|
|
72
|
+
taskId,
|
|
73
|
+
};
|
|
74
|
+
this.worktrees.set(taskId, info);
|
|
75
|
+
logger.info(`[WorktreeManager] Created worktree for task ${taskId} at ${worktreePath}`);
|
|
76
|
+
return info;
|
|
77
|
+
}
|
|
78
|
+
/** Return all active worktrees tracked by this manager instance. */
|
|
79
|
+
list() {
|
|
80
|
+
return Array.from(this.worktrees.values());
|
|
81
|
+
}
|
|
82
|
+
/** Return the WorktreeInfo for a specific task, or undefined if unknown. */
|
|
83
|
+
get(taskId) {
|
|
84
|
+
return this.worktrees.get(taskId);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Merge the worktree's branch back into its base branch.
|
|
88
|
+
*
|
|
89
|
+
* Runs: git merge [--squash] <branch> (executed from the base worktree)
|
|
90
|
+
*/
|
|
91
|
+
async merge(taskId, options) {
|
|
92
|
+
const info = this.worktrees.get(taskId);
|
|
93
|
+
if (!info) {
|
|
94
|
+
throw new Error(`[WorktreeManager] No worktree found for task ${taskId}`);
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
// Ensure we're on the correct base branch before merging
|
|
98
|
+
await execFile("git", ["checkout", info.baseBranch], {
|
|
99
|
+
cwd: this.projectRoot,
|
|
100
|
+
});
|
|
101
|
+
if (options?.squash) {
|
|
102
|
+
// Squash merge requires separate commit step
|
|
103
|
+
await execFile("git", ["merge", "--squash", info.branch], {
|
|
104
|
+
cwd: this.projectRoot,
|
|
105
|
+
});
|
|
106
|
+
const commitMsg = options.message || `Squash merge branch '${info.branch}'`;
|
|
107
|
+
await execFile("git", ["commit", "-m", commitMsg], {
|
|
108
|
+
cwd: this.projectRoot,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const mergeArgs = ["merge", info.branch];
|
|
113
|
+
if (options?.message) {
|
|
114
|
+
mergeArgs.push("-m", options.message);
|
|
115
|
+
}
|
|
116
|
+
await execFile("git", mergeArgs, { cwd: this.projectRoot });
|
|
117
|
+
}
|
|
118
|
+
logger.info(`[WorktreeManager] Merged branch ${info.branch} into ${info.baseBranch}`);
|
|
119
|
+
return { success: true };
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
123
|
+
// Extract conflicting file names from git's error/stdout output
|
|
124
|
+
const conflicts = message
|
|
125
|
+
.split("\n")
|
|
126
|
+
.filter((line) => line.startsWith("CONFLICT"))
|
|
127
|
+
.map((line) => line.replace(/^CONFLICT[^:]*:\s*/i, "").trim())
|
|
128
|
+
.filter(Boolean);
|
|
129
|
+
logger.error(`[WorktreeManager] Merge conflicts for task ${taskId}:`, error instanceof Error ? error : new Error(String(error)));
|
|
130
|
+
return { success: false, conflicts };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Remove a worktree from disk and deregister it.
|
|
135
|
+
*
|
|
136
|
+
* Runs: git worktree remove <path>
|
|
137
|
+
*/
|
|
138
|
+
async remove(taskId) {
|
|
139
|
+
const info = this.worktrees.get(taskId);
|
|
140
|
+
if (!info) {
|
|
141
|
+
throw new Error(`[WorktreeManager] No worktree found for task ${taskId}`);
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
await execFile("git", ["worktree", "remove", info.path, "--force"], {
|
|
145
|
+
cwd: this.projectRoot,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
// If git worktree remove fails (e.g. path already gone) try to clean up
|
|
150
|
+
// the directory ourselves so we stay consistent.
|
|
151
|
+
logger.error(`[WorktreeManager] git worktree remove failed for task ${taskId}, attempting manual rm:`, error instanceof Error ? error : new Error(String(error)));
|
|
152
|
+
try {
|
|
153
|
+
await rm(info.path, { recursive: true, force: true });
|
|
154
|
+
}
|
|
155
|
+
catch (rmError) {
|
|
156
|
+
logger.error(`[WorktreeManager] Manual rm also failed for ${info.path}:`, rmError instanceof Error ? rmError : new Error(String(rmError)));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
this.worktrees.delete(taskId);
|
|
160
|
+
logger.info(`[WorktreeManager] Removed worktree for task ${taskId}`);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Prune stale worktree metadata that git is tracking but whose paths no
|
|
164
|
+
* longer exist on disk.
|
|
165
|
+
*
|
|
166
|
+
* Runs: git worktree prune
|
|
167
|
+
*
|
|
168
|
+
* @returns Number of pruned entries as reported by git
|
|
169
|
+
*/
|
|
170
|
+
async prune() {
|
|
171
|
+
if (!(await isGitRepo(this.projectRoot))) {
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
const { stderr } = await execFile("git", ["worktree", "prune", "--verbose"], { cwd: this.projectRoot });
|
|
176
|
+
// git prints one line per pruned entry to stderr when --verbose is given
|
|
177
|
+
const pruned = stderr
|
|
178
|
+
.split("\n")
|
|
179
|
+
.filter((line) => line.trim().length > 0).length;
|
|
180
|
+
if (pruned > 0) {
|
|
181
|
+
logger.info(`[WorktreeManager] Pruned ${pruned} stale worktree(s)`);
|
|
182
|
+
}
|
|
183
|
+
return pruned;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
logger.error(`[WorktreeManager] Failed to prune worktrees:`, error instanceof Error ? error : new Error(String(error)));
|
|
187
|
+
return 0;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Singleton
|
|
192
|
+
let _manager;
|
|
193
|
+
/**
|
|
194
|
+
* Return a shared WorktreeManager rooted at the current working directory.
|
|
195
|
+
* Use the WorktreeManager constructor directly if you need a different root.
|
|
196
|
+
*/
|
|
197
|
+
export function getWorktreeManager() {
|
|
198
|
+
if (!_manager) {
|
|
199
|
+
_manager = new WorktreeManager();
|
|
200
|
+
}
|
|
201
|
+
return _manager;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=worktree-manager.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worktree-confined tools for the verified-run agent.
|
|
3
|
+
*
|
|
4
|
+
* A small coding toolset (read, write, list, shell, complete) whose every file
|
|
5
|
+
* operation is resolved against a single root directory, the run's git
|
|
6
|
+
* worktree. Paths that escape the root (via `..`, absolute paths or symlinks)
|
|
7
|
+
* are rejected, writes into `.git` are refused, and shell commands that push
|
|
8
|
+
* or open pull requests are denied. Cautious and dangerous tools also go
|
|
9
|
+
* through the existing PermissionManager (src/agents/permissions.ts).
|
|
10
|
+
*
|
|
11
|
+
* The shell tool runs with the worktree as cwd and a scrubbed environment,
|
|
12
|
+
* confined by an OS sandbox when available (src/agents/command-sandbox.ts).
|
|
13
|
+
* Without one it falls back to pattern screening, a guard rail, not a jail.
|
|
14
|
+
*/
|
|
15
|
+
import type { ToolSet } from 'ai';
|
|
16
|
+
import { PermissionManager } from './permissions.js';
|
|
17
|
+
import type { ToolExecuteHandler } from './executor.js';
|
|
18
|
+
import type { PlanOptions } from './command-sandbox.js';
|
|
19
|
+
export interface WorktreeToolsOptions {
|
|
20
|
+
/** Root every file operation is confined to */
|
|
21
|
+
workdir: string;
|
|
22
|
+
permissions?: PermissionManager;
|
|
23
|
+
/** Kill shell commands after this long */
|
|
24
|
+
commandTimeoutMs: number;
|
|
25
|
+
/** Cap on text returned to the model per tool call */
|
|
26
|
+
maxOutputChars: number;
|
|
27
|
+
/** Sandbox overrides (mode, availability check); defaults come from PROFCLAW_RUN_SANDBOX */
|
|
28
|
+
sandbox?: PlanOptions;
|
|
29
|
+
/** Override PROFCLAW_RUN_ALLOW_NETWORK */
|
|
30
|
+
allowNetwork?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface WorktreeToolset {
|
|
33
|
+
tools: ToolSet;
|
|
34
|
+
execute: ToolExecuteHandler;
|
|
35
|
+
/** Remove the per-run sandbox temp dir */
|
|
36
|
+
dispose: () => Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
export declare function isBlockedCommand(command: string): boolean;
|
|
39
|
+
/** Non-interactive policy: allow everything except publishing actions. */
|
|
40
|
+
export declare function createRunPermissionManager(): PermissionManager;
|
|
41
|
+
/**
|
|
42
|
+
* Resolve `requested` against `root` and guarantee the result stays inside it,
|
|
43
|
+
* including through symlinks (checked on the deepest existing ancestor).
|
|
44
|
+
*/
|
|
45
|
+
export declare function confinePath(root: string, requested: string): Promise<string>;
|
|
46
|
+
export declare function createWorktreeToolset(options: WorktreeToolsOptions): WorktreeToolset;
|
|
47
|
+
//# sourceMappingURL=worktree-tools.d.ts.map
|