profclaw 2.0.0 → 2.3.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 +37 -0
- package/CONTRIBUTING.md +20 -0
- package/Dockerfile +39 -23
- package/README.md +174 -40
- 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/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.d.ts +35 -1
- package/dist/agents/executor.js +573 -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/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/result-store.d.ts +37 -0
- package/dist/agents/result-store.js +104 -0
- package/dist/agents/session-diff.d.ts +43 -0
- package/dist/agents/session-diff.js +258 -0
- package/dist/agents/tool-loader.d.ts +65 -0
- package/dist/agents/tool-loader.js +273 -0
- package/dist/agents/transcript.d.ts +96 -0
- package/dist/agents/transcript.js +267 -0
- package/dist/agents/worktree-manager.d.ts +80 -0
- package/dist/agents/worktree-manager.js +203 -0
- package/dist/auth/middleware.js +14 -0
- package/dist/chat/agentic-executor.d.ts +7 -0
- package/dist/chat/agentic-executor.js +253 -30
- 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/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/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/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 +116 -61
- 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/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 +19 -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/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 +78 -19
- package/dist/providers/core/models.js +67 -1
- package/dist/providers/core/types.d.ts +3 -0
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.js +1 -0
- package/dist/providers/smart-router.d.ts +118 -0
- package/dist/providers/smart-router.js +685 -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 +259 -14
- 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 +310 -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,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-File Patch Tool
|
|
3
|
+
*
|
|
4
|
+
* Applies OpenAI-style multi-file patches that can add, update, and delete
|
|
5
|
+
* multiple files in a single operation.
|
|
6
|
+
*
|
|
7
|
+
* Format:
|
|
8
|
+
* *** Begin Patch
|
|
9
|
+
* *** Add File: path/to/new.ts
|
|
10
|
+
* [file content]
|
|
11
|
+
* *** Update File: path/to/existing.ts
|
|
12
|
+
* @@ context @@
|
|
13
|
+
* -old line
|
|
14
|
+
* +new line
|
|
15
|
+
* *** Delete File: path/to/remove.ts
|
|
16
|
+
* *** End Patch
|
|
17
|
+
*/
|
|
18
|
+
import { z } from 'zod';
|
|
19
|
+
import fs from 'fs/promises';
|
|
20
|
+
import path from 'path';
|
|
21
|
+
import { getFsGuard } from '../../../security/fs-guard.js';
|
|
22
|
+
import { logger } from '../../../utils/logger.js';
|
|
23
|
+
// ---- Schema ----------------------------------------------------------------
|
|
24
|
+
const MultiPatchParamsSchema = z.object({
|
|
25
|
+
patch: z.string().min(1).describe('Multi-file patch in OpenAI patch format. Must start with "*** Begin Patch" and end with "*** End Patch".'),
|
|
26
|
+
workdir: z.string().optional().describe('Override workspace root for path resolution. Defaults to the session workdir.'),
|
|
27
|
+
});
|
|
28
|
+
// ---- Parsing ---------------------------------------------------------------
|
|
29
|
+
const BEGIN_MARKER = '*** Begin Patch';
|
|
30
|
+
const END_MARKER = '*** End Patch';
|
|
31
|
+
const ADD_PREFIX = '*** Add File: ';
|
|
32
|
+
const UPDATE_PREFIX = '*** Update File: ';
|
|
33
|
+
const DELETE_PREFIX = '*** Delete File: ';
|
|
34
|
+
/**
|
|
35
|
+
* Parse the multi-file patch string into ordered segments.
|
|
36
|
+
* Throws with a descriptive message on format errors.
|
|
37
|
+
*/
|
|
38
|
+
function parsePatch(patch) {
|
|
39
|
+
const lines = patch.split('\n');
|
|
40
|
+
// Find begin/end markers
|
|
41
|
+
const beginIdx = lines.findIndex((l) => l.trim() === BEGIN_MARKER);
|
|
42
|
+
const endIdx = lines.findIndex((l) => l.trim() === END_MARKER);
|
|
43
|
+
if (beginIdx === -1) {
|
|
44
|
+
throw new Error(`Patch must start with "${BEGIN_MARKER}"`);
|
|
45
|
+
}
|
|
46
|
+
if (endIdx === -1) {
|
|
47
|
+
throw new Error(`Patch must end with "${END_MARKER}"`);
|
|
48
|
+
}
|
|
49
|
+
if (endIdx <= beginIdx) {
|
|
50
|
+
throw new Error(`"${END_MARKER}" must appear after "${BEGIN_MARKER}"`);
|
|
51
|
+
}
|
|
52
|
+
const body = lines.slice(beginIdx + 1, endIdx);
|
|
53
|
+
const segments = [];
|
|
54
|
+
let current = null;
|
|
55
|
+
for (const line of body) {
|
|
56
|
+
if (line.startsWith(ADD_PREFIX)) {
|
|
57
|
+
if (current)
|
|
58
|
+
segments.push(current);
|
|
59
|
+
current = { operation: 'add', filePath: line.slice(ADD_PREFIX.length).trim(), lines: [] };
|
|
60
|
+
}
|
|
61
|
+
else if (line.startsWith(UPDATE_PREFIX)) {
|
|
62
|
+
if (current)
|
|
63
|
+
segments.push(current);
|
|
64
|
+
current = { operation: 'update', filePath: line.slice(UPDATE_PREFIX.length).trim(), lines: [] };
|
|
65
|
+
}
|
|
66
|
+
else if (line.startsWith(DELETE_PREFIX)) {
|
|
67
|
+
if (current)
|
|
68
|
+
segments.push(current);
|
|
69
|
+
// Delete segments have no body lines - push immediately.
|
|
70
|
+
segments.push({ operation: 'delete', filePath: line.slice(DELETE_PREFIX.length).trim(), lines: [] });
|
|
71
|
+
current = null;
|
|
72
|
+
}
|
|
73
|
+
else if (current) {
|
|
74
|
+
current.lines.push(line);
|
|
75
|
+
}
|
|
76
|
+
// Lines before the first directive are ignored (e.g. blank lines after Begin Patch).
|
|
77
|
+
}
|
|
78
|
+
if (current)
|
|
79
|
+
segments.push(current);
|
|
80
|
+
if (segments.length === 0) {
|
|
81
|
+
throw new Error('Patch contains no file operations');
|
|
82
|
+
}
|
|
83
|
+
return segments;
|
|
84
|
+
}
|
|
85
|
+
// ---- Unified diff application ----------------------------------------------
|
|
86
|
+
/**
|
|
87
|
+
* Apply unified-diff hunks to file content.
|
|
88
|
+
* Supports the @@ -L,N +L,N @@ header format used in standard and OpenAI patches.
|
|
89
|
+
*/
|
|
90
|
+
function applyHunks(content, diffLines) {
|
|
91
|
+
const fileLines = content.split('\n');
|
|
92
|
+
let hunks = 0;
|
|
93
|
+
let offset = 0;
|
|
94
|
+
for (let i = 0; i < diffLines.length; i++) {
|
|
95
|
+
const line = diffLines[i];
|
|
96
|
+
const hunkMatch = line.match(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
|
|
97
|
+
if (!hunkMatch)
|
|
98
|
+
continue;
|
|
99
|
+
hunks++;
|
|
100
|
+
const startLine = parseInt(hunkMatch[1], 10) - 1 + offset;
|
|
101
|
+
const removals = [];
|
|
102
|
+
const additions = [];
|
|
103
|
+
for (let j = i + 1; j < diffLines.length; j++) {
|
|
104
|
+
const dl = diffLines[j];
|
|
105
|
+
// Next hunk header - stop consuming, back up so outer loop sees it
|
|
106
|
+
if (dl.match(/^@@ -\d/)) {
|
|
107
|
+
i = j - 1;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
const prefix = dl[0];
|
|
111
|
+
const text = dl.slice(1);
|
|
112
|
+
if (prefix === '-') {
|
|
113
|
+
// Find this line near the expected position
|
|
114
|
+
const searchStart = startLine + removals.length + additions.length;
|
|
115
|
+
let found = -1;
|
|
116
|
+
for (let s = Math.max(0, searchStart - 3); s < Math.min(fileLines.length, searchStart + 4); s++) {
|
|
117
|
+
if (fileLines[s] === text && !removals.includes(s)) {
|
|
118
|
+
found = s;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (found === -1) {
|
|
123
|
+
throw new Error(`Hunk failed: could not find line "${text}" near line ${searchStart + 1}`);
|
|
124
|
+
}
|
|
125
|
+
removals.push(found);
|
|
126
|
+
}
|
|
127
|
+
else if (prefix === '+') {
|
|
128
|
+
additions.push(text);
|
|
129
|
+
}
|
|
130
|
+
// Context lines (space or no prefix) are skipped
|
|
131
|
+
}
|
|
132
|
+
// Remove in reverse order to preserve indices, then insert
|
|
133
|
+
removals.sort((a, b) => b - a);
|
|
134
|
+
for (const idx of removals) {
|
|
135
|
+
fileLines.splice(idx, 1);
|
|
136
|
+
}
|
|
137
|
+
const insertAt = removals.length > 0 ? Math.min(...removals) : startLine;
|
|
138
|
+
fileLines.splice(insertAt, 0, ...additions);
|
|
139
|
+
offset += additions.length - removals.length;
|
|
140
|
+
}
|
|
141
|
+
if (hunks === 0) {
|
|
142
|
+
throw new Error('No valid hunks found in update segment');
|
|
143
|
+
}
|
|
144
|
+
return { result: fileLines.join('\n'), hunks };
|
|
145
|
+
}
|
|
146
|
+
// ---- Security helpers ------------------------------------------------------
|
|
147
|
+
const BLOCKED_PATH_FRAGMENTS = [
|
|
148
|
+
'/etc/passwd',
|
|
149
|
+
'/etc/shadow',
|
|
150
|
+
'.ssh',
|
|
151
|
+
'.gnupg',
|
|
152
|
+
'.env',
|
|
153
|
+
];
|
|
154
|
+
function isBlockedPath(filePath) {
|
|
155
|
+
const normalized = filePath.toLowerCase();
|
|
156
|
+
return BLOCKED_PATH_FRAGMENTS.some((fragment) => normalized.includes(fragment.toLowerCase()));
|
|
157
|
+
}
|
|
158
|
+
function resolveSafePath(inputPath, workdir) {
|
|
159
|
+
const resolved = path.isAbsolute(inputPath)
|
|
160
|
+
? inputPath
|
|
161
|
+
: path.resolve(workdir, inputPath);
|
|
162
|
+
// Ensure the resolved path stays within the workspace root
|
|
163
|
+
const relative = path.relative(workdir, resolved);
|
|
164
|
+
if (relative.startsWith('..')) {
|
|
165
|
+
throw new Error(`Path "${inputPath}" resolves outside the workspace root`);
|
|
166
|
+
}
|
|
167
|
+
return resolved;
|
|
168
|
+
}
|
|
169
|
+
// ---- Segment execution -----------------------------------------------------
|
|
170
|
+
async function applySegment(segment, workdir) {
|
|
171
|
+
let filePath;
|
|
172
|
+
try {
|
|
173
|
+
filePath = resolveSafePath(segment.filePath, workdir);
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
return {
|
|
177
|
+
path: segment.filePath,
|
|
178
|
+
operation: segment.operation,
|
|
179
|
+
success: false,
|
|
180
|
+
error: err instanceof Error ? err.message : 'Path resolution failed',
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
// Blocked path check (FsGuard with fallback)
|
|
184
|
+
const fsGuard = getFsGuard();
|
|
185
|
+
if (fsGuard) {
|
|
186
|
+
const mode = segment.operation === 'delete' ? 'delete' : 'write';
|
|
187
|
+
const guardResult = await fsGuard.validatePath(filePath, mode);
|
|
188
|
+
if (!guardResult.allowed) {
|
|
189
|
+
return {
|
|
190
|
+
path: segment.filePath,
|
|
191
|
+
operation: segment.operation,
|
|
192
|
+
success: false,
|
|
193
|
+
error: guardResult.reason ?? 'Path access denied',
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else if (isBlockedPath(filePath)) {
|
|
198
|
+
return {
|
|
199
|
+
path: segment.filePath,
|
|
200
|
+
operation: segment.operation,
|
|
201
|
+
success: false,
|
|
202
|
+
error: 'Access to this path is not allowed',
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
switch (segment.operation) {
|
|
207
|
+
case 'add': {
|
|
208
|
+
// Fail if file already exists to prevent accidental overwrites
|
|
209
|
+
try {
|
|
210
|
+
await fs.stat(filePath);
|
|
211
|
+
return {
|
|
212
|
+
path: segment.filePath,
|
|
213
|
+
operation: 'add',
|
|
214
|
+
success: false,
|
|
215
|
+
error: 'File already exists - use Update File to modify existing files',
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
// Expected: file does not exist
|
|
220
|
+
}
|
|
221
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
222
|
+
// Strip trailing blank line added by patch format if present
|
|
223
|
+
const content = segment.lines.join('\n').replace(/\n$/, '');
|
|
224
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
225
|
+
logger.debug(`[MultiPatch] Added ${segment.filePath}`, { component: 'MultiPatch' });
|
|
226
|
+
return { path: segment.filePath, operation: 'add', success: true };
|
|
227
|
+
}
|
|
228
|
+
case 'update': {
|
|
229
|
+
let existing;
|
|
230
|
+
try {
|
|
231
|
+
existing = await fs.readFile(filePath, 'utf-8');
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return {
|
|
235
|
+
path: segment.filePath,
|
|
236
|
+
operation: 'update',
|
|
237
|
+
success: false,
|
|
238
|
+
error: 'File does not exist - use Add File to create new files',
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
const { result, hunks } = applyHunks(existing, segment.lines);
|
|
242
|
+
await fs.writeFile(filePath, result, 'utf-8');
|
|
243
|
+
logger.debug(`[MultiPatch] Updated ${segment.filePath} (${hunks} hunk(s))`, { component: 'MultiPatch' });
|
|
244
|
+
return { path: segment.filePath, operation: 'update', success: true, hunks };
|
|
245
|
+
}
|
|
246
|
+
case 'delete': {
|
|
247
|
+
try {
|
|
248
|
+
await fs.unlink(filePath);
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
252
|
+
return {
|
|
253
|
+
path: segment.filePath,
|
|
254
|
+
operation: 'delete',
|
|
255
|
+
success: false,
|
|
256
|
+
error: `Could not delete file: ${msg}`,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
logger.debug(`[MultiPatch] Deleted ${segment.filePath}`, { component: 'MultiPatch' });
|
|
260
|
+
return { path: segment.filePath, operation: 'delete', success: true };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
266
|
+
return {
|
|
267
|
+
path: segment.filePath,
|
|
268
|
+
operation: segment.operation,
|
|
269
|
+
success: false,
|
|
270
|
+
error: message,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// ---- Tool definition -------------------------------------------------------
|
|
275
|
+
export const multiPatchTool = {
|
|
276
|
+
name: 'multi_patch',
|
|
277
|
+
description: `Apply a multi-file patch in OpenAI patch format. Supports adding new files,
|
|
278
|
+
updating existing files (unified diff hunks), and deleting files in a single operation.
|
|
279
|
+
|
|
280
|
+
Format:
|
|
281
|
+
*** Begin Patch
|
|
282
|
+
*** Add File: path/to/new.ts
|
|
283
|
+
[full file content]
|
|
284
|
+
*** Update File: path/to/existing.ts
|
|
285
|
+
@@ -10,7 +10,7 @@
|
|
286
|
+
context line
|
|
287
|
+
-removed line
|
|
288
|
+
+added line
|
|
289
|
+
context line
|
|
290
|
+
*** Delete File: path/to/obsolete.ts
|
|
291
|
+
*** End Patch
|
|
292
|
+
|
|
293
|
+
All paths are resolved relative to the workspace root. Paths that escape the workspace
|
|
294
|
+
root or match blocked patterns (e.g. .env, .ssh) are rejected.`,
|
|
295
|
+
category: 'filesystem',
|
|
296
|
+
securityLevel: 'moderate',
|
|
297
|
+
requiresApproval: true,
|
|
298
|
+
allowedHosts: ['sandbox', 'gateway', 'local'],
|
|
299
|
+
parameters: MultiPatchParamsSchema,
|
|
300
|
+
examples: [
|
|
301
|
+
{
|
|
302
|
+
description: 'Add a new file and update an existing one',
|
|
303
|
+
params: {
|
|
304
|
+
patch: [
|
|
305
|
+
'*** Begin Patch',
|
|
306
|
+
'*** Add File: src/utils/helper.ts',
|
|
307
|
+
'export function add(a: number, b: number): number {',
|
|
308
|
+
' return a + b;',
|
|
309
|
+
'}',
|
|
310
|
+
'*** Update File: src/index.ts',
|
|
311
|
+
'@@ -1,3 +1,4 @@',
|
|
312
|
+
' import { something } from "./other.js";',
|
|
313
|
+
"+import { add } from './utils/helper.js';",
|
|
314
|
+
' ',
|
|
315
|
+
' export default {};',
|
|
316
|
+
'*** End Patch',
|
|
317
|
+
].join('\n'),
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
async execute(context, params) {
|
|
322
|
+
const workdir = params.workdir ?? context.workdir;
|
|
323
|
+
// Parse the patch
|
|
324
|
+
let segments;
|
|
325
|
+
try {
|
|
326
|
+
segments = parsePatch(params.patch);
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
330
|
+
return {
|
|
331
|
+
success: false,
|
|
332
|
+
error: { code: 'PARSE_ERROR', message: `Failed to parse patch: ${message}` },
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
// Apply each segment (sequentially - order matters for dependencies)
|
|
336
|
+
const results = [];
|
|
337
|
+
for (const segment of segments) {
|
|
338
|
+
const result = await applySegment(segment, workdir);
|
|
339
|
+
results.push(result);
|
|
340
|
+
}
|
|
341
|
+
const applied = results.filter((r) => r.success).length;
|
|
342
|
+
const failed = results.filter((r) => !r.success).length;
|
|
343
|
+
// Build a human-readable summary
|
|
344
|
+
const summaryLines = [
|
|
345
|
+
`Multi-patch applied: ${applied} succeeded, ${failed} failed`,
|
|
346
|
+
'',
|
|
347
|
+
];
|
|
348
|
+
for (const r of results) {
|
|
349
|
+
const icon = r.success ? '+' : 'x';
|
|
350
|
+
const opLabel = r.operation.toUpperCase().padEnd(6);
|
|
351
|
+
const detail = r.hunks !== undefined ? ` (${r.hunks} hunk${r.hunks !== 1 ? 's' : ''})` : '';
|
|
352
|
+
const errorNote = r.error ? ` - ${r.error}` : '';
|
|
353
|
+
summaryLines.push(` [${icon}] ${opLabel} ${r.path}${detail}${errorNote}`);
|
|
354
|
+
}
|
|
355
|
+
const output = summaryLines.join('\n');
|
|
356
|
+
if (failed > 0 && applied === 0) {
|
|
357
|
+
return {
|
|
358
|
+
success: false,
|
|
359
|
+
data: { files: results, applied, failed },
|
|
360
|
+
error: {
|
|
361
|
+
code: 'PATCH_FAILED',
|
|
362
|
+
message: `All ${failed} operation(s) failed. See data.files for details.`,
|
|
363
|
+
},
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
success: true,
|
|
368
|
+
data: { files: results, applied, failed },
|
|
369
|
+
output,
|
|
370
|
+
};
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
//# sourceMappingURL=multi-patch.js.map
|
|
@@ -15,14 +15,14 @@ declare const ImageGenParamsSchema: z.ZodObject<{
|
|
|
15
15
|
}, "strip", z.ZodTypeAny, {
|
|
16
16
|
prompt: string;
|
|
17
17
|
model: "dall-e-3" | "dall-e-2";
|
|
18
|
-
quality: "standard" | "hd";
|
|
19
18
|
size: "1024x1024" | "1792x1024" | "1024x1792";
|
|
19
|
+
quality: "standard" | "hd";
|
|
20
20
|
style: "vivid" | "natural";
|
|
21
21
|
}, {
|
|
22
22
|
prompt: string;
|
|
23
23
|
model?: "dall-e-3" | "dall-e-2" | undefined;
|
|
24
|
-
quality?: "standard" | "hd" | undefined;
|
|
25
24
|
size?: "1024x1024" | "1792x1024" | "1024x1792" | undefined;
|
|
25
|
+
quality?: "standard" | "hd" | undefined;
|
|
26
26
|
style?: "vivid" | "natural" | undefined;
|
|
27
27
|
}>;
|
|
28
28
|
export type ImageGenParams = z.infer<typeof ImageGenParamsSchema>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Mode Tools
|
|
3
|
+
*
|
|
4
|
+
* Two tools the agent can call to create a plan and mark steps as completed.
|
|
5
|
+
* Plans go through a draft → approved/rejected → in_progress → completed lifecycle.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { ToolDefinition } from '../types.js';
|
|
9
|
+
declare const CreatePlanParamsSchema: z.ZodObject<{
|
|
10
|
+
title: z.ZodString;
|
|
11
|
+
steps: z.ZodArray<z.ZodObject<{
|
|
12
|
+
description: z.ZodString;
|
|
13
|
+
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
14
|
+
estimatedEffort: z.ZodOptional<z.ZodEnum<["small", "medium", "large"]>>;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
description: string;
|
|
17
|
+
files?: string[] | undefined;
|
|
18
|
+
estimatedEffort?: "small" | "medium" | "large" | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
description: string;
|
|
21
|
+
files?: string[] | undefined;
|
|
22
|
+
estimatedEffort?: "small" | "medium" | "large" | undefined;
|
|
23
|
+
}>, "many">;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
title: string;
|
|
26
|
+
steps: {
|
|
27
|
+
description: string;
|
|
28
|
+
files?: string[] | undefined;
|
|
29
|
+
estimatedEffort?: "small" | "medium" | "large" | undefined;
|
|
30
|
+
}[];
|
|
31
|
+
}, {
|
|
32
|
+
title: string;
|
|
33
|
+
steps: {
|
|
34
|
+
description: string;
|
|
35
|
+
files?: string[] | undefined;
|
|
36
|
+
estimatedEffort?: "small" | "medium" | "large" | undefined;
|
|
37
|
+
}[];
|
|
38
|
+
}>;
|
|
39
|
+
export type CreatePlanParams = z.infer<typeof CreatePlanParamsSchema>;
|
|
40
|
+
interface CreatePlanResult {
|
|
41
|
+
planId: string;
|
|
42
|
+
status: 'awaiting_approval';
|
|
43
|
+
message: string;
|
|
44
|
+
stepCount: number;
|
|
45
|
+
}
|
|
46
|
+
export declare const createPlanTool: ToolDefinition<CreatePlanParams, CreatePlanResult>;
|
|
47
|
+
declare const CompletePlanStepParamsSchema: z.ZodObject<{
|
|
48
|
+
stepIndex: z.ZodNumber;
|
|
49
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
50
|
+
}, "strip", z.ZodTypeAny, {
|
|
51
|
+
stepIndex: number;
|
|
52
|
+
summary?: string | undefined;
|
|
53
|
+
}, {
|
|
54
|
+
stepIndex: number;
|
|
55
|
+
summary?: string | undefined;
|
|
56
|
+
}>;
|
|
57
|
+
export type CompletePlanStepParams = z.infer<typeof CompletePlanStepParamsSchema>;
|
|
58
|
+
interface CompletePlanStepResult {
|
|
59
|
+
status: 'step_completed' | 'plan_completed';
|
|
60
|
+
completedStep: number;
|
|
61
|
+
nextStep?: {
|
|
62
|
+
index: number;
|
|
63
|
+
description: string;
|
|
64
|
+
};
|
|
65
|
+
planId: string;
|
|
66
|
+
}
|
|
67
|
+
export declare const completePlanStepTool: ToolDefinition<CompletePlanStepParams, CompletePlanStepResult>;
|
|
68
|
+
export declare const planTools: readonly [ToolDefinition<{
|
|
69
|
+
title: string;
|
|
70
|
+
steps: {
|
|
71
|
+
description: string;
|
|
72
|
+
files?: string[] | undefined;
|
|
73
|
+
estimatedEffort?: "small" | "medium" | "large" | undefined;
|
|
74
|
+
}[];
|
|
75
|
+
}, CreatePlanResult>, ToolDefinition<{
|
|
76
|
+
stepIndex: number;
|
|
77
|
+
summary?: string | undefined;
|
|
78
|
+
}, CompletePlanStepResult>];
|
|
79
|
+
export {};
|
|
80
|
+
//# sourceMappingURL=plan-tools.d.ts.map
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Mode Tools
|
|
3
|
+
*
|
|
4
|
+
* Two tools the agent can call to create a plan and mark steps as completed.
|
|
5
|
+
* Plans go through a draft → approved/rejected → in_progress → completed lifecycle.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { planManager } from '../../../agents/plan-mode.js';
|
|
9
|
+
import { logger } from '../../../utils/logger.js';
|
|
10
|
+
// ─── create_plan ────────────────────────────────────────────────────────────
|
|
11
|
+
const CreatePlanParamsSchema = z.object({
|
|
12
|
+
title: z.string().min(1).describe('Short title for the plan'),
|
|
13
|
+
steps: z
|
|
14
|
+
.array(z.object({
|
|
15
|
+
description: z.string().min(1).describe('What this step does'),
|
|
16
|
+
files: z.array(z.string()).optional().describe('Files this step will touch'),
|
|
17
|
+
estimatedEffort: z
|
|
18
|
+
.enum(['small', 'medium', 'large'])
|
|
19
|
+
.optional()
|
|
20
|
+
.describe('Rough effort estimate'),
|
|
21
|
+
}))
|
|
22
|
+
.min(1)
|
|
23
|
+
.describe('Ordered list of implementation steps'),
|
|
24
|
+
});
|
|
25
|
+
export const createPlanTool = {
|
|
26
|
+
name: 'create_plan',
|
|
27
|
+
description: `Create an implementation plan before making changes.
|
|
28
|
+
|
|
29
|
+
Use this for any multi-step task. Write out every discrete step you intend to
|
|
30
|
+
take. The user will review the plan and approve or reject it before you begin
|
|
31
|
+
any implementation.
|
|
32
|
+
|
|
33
|
+
**When to call this:**
|
|
34
|
+
- Task requires changes to 2 or more files
|
|
35
|
+
- Task has distinct phases (e.g., data model → API → tests)
|
|
36
|
+
- User asks you to plan before coding
|
|
37
|
+
|
|
38
|
+
**After calling this tool, STOP and wait.** Do not proceed until the user runs
|
|
39
|
+
\`profclaw plan approve <id>\` or tells you the plan is approved.`,
|
|
40
|
+
category: 'profclaw',
|
|
41
|
+
securityLevel: 'safe',
|
|
42
|
+
allowedHosts: ['sandbox', 'gateway', 'local'],
|
|
43
|
+
parameters: CreatePlanParamsSchema,
|
|
44
|
+
examples: [
|
|
45
|
+
{
|
|
46
|
+
description: 'Plan a feature implementation',
|
|
47
|
+
params: {
|
|
48
|
+
title: 'Add rate limiting to API endpoints',
|
|
49
|
+
steps: [
|
|
50
|
+
{ description: 'Add rate-limit middleware in src/middleware/rate-limit.ts', estimatedEffort: 'medium', files: ['src/middleware/rate-limit.ts'] },
|
|
51
|
+
{ description: 'Apply middleware to all /api/* routes in src/routes/index.ts', estimatedEffort: 'small', files: ['src/routes/index.ts'] },
|
|
52
|
+
{ description: 'Write unit tests for rate-limit middleware', estimatedEffort: 'medium', files: ['src/middleware/rate-limit.test.ts'] },
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
async execute(_context, params) {
|
|
58
|
+
logger.info('[PlanTool] Creating plan:', { title: params.title, stepCount: params.steps.length });
|
|
59
|
+
const stepsWithIndex = params.steps.map((s, i) => ({
|
|
60
|
+
index: i + 1,
|
|
61
|
+
description: s.description,
|
|
62
|
+
files: s.files,
|
|
63
|
+
estimatedEffort: s.estimatedEffort,
|
|
64
|
+
}));
|
|
65
|
+
const plan = planManager.create(params.title, stepsWithIndex);
|
|
66
|
+
return {
|
|
67
|
+
success: true,
|
|
68
|
+
data: {
|
|
69
|
+
planId: plan.id,
|
|
70
|
+
status: 'awaiting_approval',
|
|
71
|
+
message: `Plan created with ${plan.steps.length} step(s). Waiting for user approval. Run: profclaw plan approve ${plan.id}`,
|
|
72
|
+
stepCount: plan.steps.length,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
// ─── complete_plan_step ─────────────────────────────────────────────────────
|
|
78
|
+
const CompletePlanStepParamsSchema = z.object({
|
|
79
|
+
stepIndex: z.number().int().min(1).describe('The 1-based index of the completed step'),
|
|
80
|
+
summary: z.string().optional().describe('Optional summary of what was done in this step'),
|
|
81
|
+
});
|
|
82
|
+
export const completePlanStepTool = {
|
|
83
|
+
name: 'complete_plan_step',
|
|
84
|
+
description: `Mark a plan step as completed after implementing it.
|
|
85
|
+
|
|
86
|
+
Call this after finishing each step in an approved plan. The tool will tell you
|
|
87
|
+
what the next pending step is so you can proceed in order.
|
|
88
|
+
|
|
89
|
+
**When to call this:**
|
|
90
|
+
- You have fully implemented the current step
|
|
91
|
+
- All files for the step are written/edited and working
|
|
92
|
+
|
|
93
|
+
**Do not call this:**
|
|
94
|
+
- Before the step is actually done
|
|
95
|
+
- If there is no active plan`,
|
|
96
|
+
category: 'profclaw',
|
|
97
|
+
securityLevel: 'safe',
|
|
98
|
+
allowedHosts: ['sandbox', 'gateway', 'local'],
|
|
99
|
+
parameters: CompletePlanStepParamsSchema,
|
|
100
|
+
async execute(_context, params) {
|
|
101
|
+
const plan = planManager.getActive();
|
|
102
|
+
if (!plan) {
|
|
103
|
+
return {
|
|
104
|
+
success: false,
|
|
105
|
+
error: {
|
|
106
|
+
code: 'NO_ACTIVE_PLAN',
|
|
107
|
+
message: 'No active (in_progress) plan found. Approve a plan first.',
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
logger.info('[PlanTool] Completing step:', {
|
|
112
|
+
planId: plan.id,
|
|
113
|
+
stepIndex: params.stepIndex,
|
|
114
|
+
summary: params.summary,
|
|
115
|
+
});
|
|
116
|
+
const updated = planManager.updateStep(plan.id, params.stepIndex, 'completed');
|
|
117
|
+
const nextStep = updated.steps.find((s) => s.status === 'pending');
|
|
118
|
+
const planDone = updated.status === 'completed';
|
|
119
|
+
return {
|
|
120
|
+
success: true,
|
|
121
|
+
data: {
|
|
122
|
+
status: planDone ? 'plan_completed' : 'step_completed',
|
|
123
|
+
completedStep: params.stepIndex,
|
|
124
|
+
nextStep: nextStep
|
|
125
|
+
? { index: nextStep.index, description: nextStep.description }
|
|
126
|
+
: undefined,
|
|
127
|
+
planId: plan.id,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
// ─── Exports ─────────────────────────────────────────────────────────────────
|
|
133
|
+
export const planTools = [createPlanTool, completePlanStepTool];
|
|
134
|
+
//# sourceMappingURL=plan-tools.js.map
|
|
@@ -18,7 +18,7 @@ declare const CreateTicketParamsSchema: z.ZodObject<{
|
|
|
18
18
|
storyPoints: z.ZodOptional<z.ZodNumber>;
|
|
19
19
|
}, "strip", z.ZodTypeAny, {
|
|
20
20
|
title: string;
|
|
21
|
-
priority: "critical" | "medium" | "none" | "
|
|
21
|
+
priority: "critical" | "medium" | "none" | "low" | "high";
|
|
22
22
|
type: "task" | "feature" | "bug" | "story" | "epic" | "subtask" | "improvement";
|
|
23
23
|
projectKey: string;
|
|
24
24
|
description?: string | undefined;
|
|
@@ -28,7 +28,7 @@ declare const CreateTicketParamsSchema: z.ZodObject<{
|
|
|
28
28
|
title: string;
|
|
29
29
|
projectKey: string;
|
|
30
30
|
description?: string | undefined;
|
|
31
|
-
priority?: "critical" | "medium" | "none" | "
|
|
31
|
+
priority?: "critical" | "medium" | "none" | "low" | "high" | undefined;
|
|
32
32
|
type?: "task" | "feature" | "bug" | "story" | "epic" | "subtask" | "improvement" | undefined;
|
|
33
33
|
labels?: string[] | undefined;
|
|
34
34
|
storyPoints?: number | undefined;
|
|
@@ -94,7 +94,7 @@ declare const UpdateTicketParamsSchema: z.ZodObject<{
|
|
|
94
94
|
ticketKey: string;
|
|
95
95
|
title?: string | undefined;
|
|
96
96
|
description?: string | undefined;
|
|
97
|
-
priority?: "critical" | "medium" | "none" | "
|
|
97
|
+
priority?: "critical" | "medium" | "none" | "low" | "high" | undefined;
|
|
98
98
|
type?: "task" | "feature" | "bug" | "story" | "epic" | "subtask" | "improvement" | undefined;
|
|
99
99
|
status?: "in_progress" | "cancelled" | "backlog" | "done" | "todo" | "in_review" | undefined;
|
|
100
100
|
labels?: string[] | undefined;
|
|
@@ -103,7 +103,7 @@ declare const UpdateTicketParamsSchema: z.ZodObject<{
|
|
|
103
103
|
ticketKey: string;
|
|
104
104
|
title?: string | undefined;
|
|
105
105
|
description?: string | undefined;
|
|
106
|
-
priority?: "critical" | "medium" | "none" | "
|
|
106
|
+
priority?: "critical" | "medium" | "none" | "low" | "high" | undefined;
|
|
107
107
|
type?: "task" | "feature" | "bug" | "story" | "epic" | "subtask" | "improvement" | undefined;
|
|
108
108
|
status?: "in_progress" | "cancelled" | "backlog" | "done" | "todo" | "in_review" | undefined;
|
|
109
109
|
labels?: string[] | undefined;
|
|
@@ -161,7 +161,7 @@ export declare const updateTicketTool: ToolDefinition<UpdateTicketParams, Ticket
|
|
|
161
161
|
export declare const getTicketTool: ToolDefinition<GetTicketParams, TicketResult>;
|
|
162
162
|
export declare const profclawTools: (ToolDefinition<{
|
|
163
163
|
title: string;
|
|
164
|
-
priority: "critical" | "medium" | "none" | "
|
|
164
|
+
priority: "critical" | "medium" | "none" | "low" | "high";
|
|
165
165
|
type: "task" | "feature" | "bug" | "story" | "epic" | "subtask" | "improvement";
|
|
166
166
|
projectKey: string;
|
|
167
167
|
description?: string | undefined;
|
|
@@ -192,7 +192,7 @@ export declare const profclawTools: (ToolDefinition<{
|
|
|
192
192
|
ticketKey: string;
|
|
193
193
|
title?: string | undefined;
|
|
194
194
|
description?: string | undefined;
|
|
195
|
-
priority?: "critical" | "medium" | "none" | "
|
|
195
|
+
priority?: "critical" | "medium" | "none" | "low" | "high" | undefined;
|
|
196
196
|
type?: "task" | "feature" | "bug" | "story" | "epic" | "subtask" | "improvement" | undefined;
|
|
197
197
|
status?: "in_progress" | "cancelled" | "backlog" | "done" | "todo" | "in_review" | undefined;
|
|
198
198
|
labels?: string[] | undefined;
|