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,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Hook: Audit Log
|
|
3
|
+
*
|
|
4
|
+
* Logs all tool executions after they complete (`afterToolCall`).
|
|
5
|
+
* Records: timestamp, sessionId, toolName, sanitized args, success/failure,
|
|
6
|
+
* and duration (if startedAt is provided via metadata).
|
|
7
|
+
*/
|
|
8
|
+
import { createContextualLogger } from '../../utils/logger.js';
|
|
9
|
+
const log = createContextualLogger('AuditLog');
|
|
10
|
+
/** Keys that should never appear in audit logs */
|
|
11
|
+
const SENSITIVE_ARG_KEYS = new Set([
|
|
12
|
+
'password',
|
|
13
|
+
'token',
|
|
14
|
+
'secret',
|
|
15
|
+
'apiKey',
|
|
16
|
+
'api_key',
|
|
17
|
+
'Authorization',
|
|
18
|
+
'authorization',
|
|
19
|
+
'credential',
|
|
20
|
+
'credentials',
|
|
21
|
+
'private_key',
|
|
22
|
+
'privateKey',
|
|
23
|
+
]);
|
|
24
|
+
function sanitizeArgs(args) {
|
|
25
|
+
if (args === null || typeof args !== 'object')
|
|
26
|
+
return args;
|
|
27
|
+
if (Array.isArray(args)) {
|
|
28
|
+
return args.map(sanitizeArgs);
|
|
29
|
+
}
|
|
30
|
+
const record = args;
|
|
31
|
+
const sanitized = {};
|
|
32
|
+
for (const [key, value] of Object.entries(record)) {
|
|
33
|
+
sanitized[key] = SENSITIVE_ARG_KEYS.has(key) ? '[REDACTED]' : sanitizeArgs(value);
|
|
34
|
+
}
|
|
35
|
+
return sanitized;
|
|
36
|
+
}
|
|
37
|
+
function isSuccessResult(result) {
|
|
38
|
+
if (result === null || result === undefined)
|
|
39
|
+
return true;
|
|
40
|
+
if (typeof result !== 'object')
|
|
41
|
+
return true;
|
|
42
|
+
const r = result;
|
|
43
|
+
if (typeof r.success === 'boolean')
|
|
44
|
+
return r.success;
|
|
45
|
+
if (r.error !== undefined)
|
|
46
|
+
return false;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
export const auditLogHook = {
|
|
50
|
+
name: 'built-in:audit-log',
|
|
51
|
+
point: 'afterToolCall',
|
|
52
|
+
priority: 200, // Run late so other hooks can modify before we record
|
|
53
|
+
handler: async (context) => {
|
|
54
|
+
const { toolName, toolArgs, toolResult, sessionId, metadata } = context;
|
|
55
|
+
const timestamp = new Date().toISOString();
|
|
56
|
+
const success = isSuccessResult(toolResult);
|
|
57
|
+
const sanitizedArgs = sanitizeArgs(toolArgs);
|
|
58
|
+
// Duration: caller may pass startedAt (epoch ms) in metadata
|
|
59
|
+
let durationMs;
|
|
60
|
+
if (typeof metadata.toolStartedAt === 'number') {
|
|
61
|
+
durationMs = Date.now() - metadata.toolStartedAt;
|
|
62
|
+
}
|
|
63
|
+
log.info('Tool executed', {
|
|
64
|
+
audit: true,
|
|
65
|
+
timestamp,
|
|
66
|
+
sessionId,
|
|
67
|
+
toolName,
|
|
68
|
+
args: sanitizedArgs,
|
|
69
|
+
success,
|
|
70
|
+
durationMs,
|
|
71
|
+
});
|
|
72
|
+
return {
|
|
73
|
+
proceed: true,
|
|
74
|
+
metadata: {
|
|
75
|
+
auditRecorded: true,
|
|
76
|
+
auditTimestamp: timestamp,
|
|
77
|
+
auditSuccess: success,
|
|
78
|
+
auditDurationMs: durationMs,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
export default auditLogHook;
|
|
84
|
+
//# sourceMappingURL=audit-log.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Hook: Cost Warning
|
|
3
|
+
*
|
|
4
|
+
* Fires on `onBudgetWarning` at 50%, 80%, and 100% of budget usage.
|
|
5
|
+
* At 100%, sets proceed: false to stop execution.
|
|
6
|
+
*/
|
|
7
|
+
import type { Hook } from '../registry.js';
|
|
8
|
+
export declare const costWarningHook: Hook;
|
|
9
|
+
export default costWarningHook;
|
|
10
|
+
//# sourceMappingURL=cost-warning.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Hook: Cost Warning
|
|
3
|
+
*
|
|
4
|
+
* Fires on `onBudgetWarning` at 50%, 80%, and 100% of budget usage.
|
|
5
|
+
* At 100%, sets proceed: false to stop execution.
|
|
6
|
+
*/
|
|
7
|
+
import { createContextualLogger } from '../../utils/logger.js';
|
|
8
|
+
const log = createContextualLogger('CostWarningHook');
|
|
9
|
+
const WARNING_THRESHOLDS = [0.5, 0.8, 1.0];
|
|
10
|
+
function getThresholdLabel(t) {
|
|
11
|
+
return `${Math.round(t * 100)}%`;
|
|
12
|
+
}
|
|
13
|
+
function crossedThreshold(previousRatio, currentRatio, threshold) {
|
|
14
|
+
return previousRatio < threshold && currentRatio >= threshold;
|
|
15
|
+
}
|
|
16
|
+
export const costWarningHook = {
|
|
17
|
+
name: 'built-in:cost-warning',
|
|
18
|
+
point: 'onBudgetWarning',
|
|
19
|
+
priority: 10,
|
|
20
|
+
handler: async (context) => {
|
|
21
|
+
const { budgetUsed, budgetMax, metadata } = context;
|
|
22
|
+
if (budgetUsed === undefined || budgetMax === undefined || budgetMax <= 0) {
|
|
23
|
+
return { proceed: true };
|
|
24
|
+
}
|
|
25
|
+
const currentRatio = budgetUsed / budgetMax;
|
|
26
|
+
const previousRatio = typeof metadata.previousBudgetRatio === 'number' ? metadata.previousBudgetRatio : 0;
|
|
27
|
+
// Hard stop at 100%
|
|
28
|
+
if (currentRatio >= 1.0) {
|
|
29
|
+
log.warn('Budget exhausted — stopping execution', {
|
|
30
|
+
budgetUsed,
|
|
31
|
+
budgetMax,
|
|
32
|
+
percentUsed: '100%',
|
|
33
|
+
sessionId: context.sessionId,
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
proceed: false,
|
|
37
|
+
metadata: { previousBudgetRatio: currentRatio, budgetExhausted: true },
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// Warn at soft thresholds (50%, 80%)
|
|
41
|
+
for (const threshold of WARNING_THRESHOLDS) {
|
|
42
|
+
if (crossedThreshold(previousRatio, currentRatio, threshold)) {
|
|
43
|
+
log.warn(`Budget warning: ${getThresholdLabel(threshold)} of limit used`, {
|
|
44
|
+
budgetUsed,
|
|
45
|
+
budgetMax,
|
|
46
|
+
threshold: getThresholdLabel(threshold),
|
|
47
|
+
sessionId: context.sessionId,
|
|
48
|
+
});
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
proceed: true,
|
|
54
|
+
metadata: { previousBudgetRatio: currentRatio },
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
export default costWarningHook;
|
|
59
|
+
//# sourceMappingURL=cost-warning.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Hook: Dangerous Tool Guard
|
|
3
|
+
*
|
|
4
|
+
* Intercepts `beforeToolCall` and delegates to a PermissionManager instance.
|
|
5
|
+
* If the manager denies the operation the hook returns `proceed: false`,
|
|
6
|
+
* halting the hook chain before the tool runs.
|
|
7
|
+
*
|
|
8
|
+
* In non-interactive mode (no prompt callback registered on the manager) all
|
|
9
|
+
* tools are allowed and the call is flagged with `metadata.requiresApproval`.
|
|
10
|
+
*/
|
|
11
|
+
import { PermissionManager } from '../../agents/permissions.js';
|
|
12
|
+
import type { Hook } from '../registry.js';
|
|
13
|
+
/**
|
|
14
|
+
* Tools that are considered dangerous and should require human approval
|
|
15
|
+
* before execution in interactive sessions.
|
|
16
|
+
*
|
|
17
|
+
* Exported for backwards-compatibility and convenience checks.
|
|
18
|
+
*/
|
|
19
|
+
export declare const DANGEROUS_TOOLS: Set<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Retrieve (or lazily create) the PermissionManager used by this hook.
|
|
22
|
+
* Use this to register a `setPromptCallback` in interactive sessions.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getPermissionManager(): PermissionManager;
|
|
25
|
+
/**
|
|
26
|
+
* Replace the PermissionManager used by this hook.
|
|
27
|
+
* Primarily useful in tests where you want full control over the manager.
|
|
28
|
+
*/
|
|
29
|
+
export declare function setPermissionManager(manager: PermissionManager): void;
|
|
30
|
+
export declare const dangerousToolHook: Hook;
|
|
31
|
+
export default dangerousToolHook;
|
|
32
|
+
//# sourceMappingURL=dangerous-tool.d.ts.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Hook: Dangerous Tool Guard
|
|
3
|
+
*
|
|
4
|
+
* Intercepts `beforeToolCall` and delegates to a PermissionManager instance.
|
|
5
|
+
* If the manager denies the operation the hook returns `proceed: false`,
|
|
6
|
+
* halting the hook chain before the tool runs.
|
|
7
|
+
*
|
|
8
|
+
* In non-interactive mode (no prompt callback registered on the manager) all
|
|
9
|
+
* tools are allowed and the call is flagged with `metadata.requiresApproval`.
|
|
10
|
+
*/
|
|
11
|
+
import { createContextualLogger } from '../../utils/logger.js';
|
|
12
|
+
import { PermissionManager, DEFAULT_PERMISSION_RULES } from '../../agents/permissions.js';
|
|
13
|
+
const log = createContextualLogger('DangerousToolHook');
|
|
14
|
+
/**
|
|
15
|
+
* Tools that are considered dangerous and should require human approval
|
|
16
|
+
* before execution in interactive sessions.
|
|
17
|
+
*
|
|
18
|
+
* Exported for backwards-compatibility and convenience checks.
|
|
19
|
+
*/
|
|
20
|
+
export const DANGEROUS_TOOLS = new Set(DEFAULT_PERMISSION_RULES.filter((r) => r.level === 'dangerous').map((r) => r.toolName));
|
|
21
|
+
/**
|
|
22
|
+
* Module-level PermissionManager shared by the hook.
|
|
23
|
+
* Callers can obtain a reference via `getPermissionManager()` to attach a
|
|
24
|
+
* prompt callback before the hook fires.
|
|
25
|
+
*/
|
|
26
|
+
let sharedManager = new PermissionManager();
|
|
27
|
+
/**
|
|
28
|
+
* Retrieve (or lazily create) the PermissionManager used by this hook.
|
|
29
|
+
* Use this to register a `setPromptCallback` in interactive sessions.
|
|
30
|
+
*/
|
|
31
|
+
export function getPermissionManager() {
|
|
32
|
+
return sharedManager;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Replace the PermissionManager used by this hook.
|
|
36
|
+
* Primarily useful in tests where you want full control over the manager.
|
|
37
|
+
*/
|
|
38
|
+
export function setPermissionManager(manager) {
|
|
39
|
+
sharedManager = manager;
|
|
40
|
+
}
|
|
41
|
+
export const dangerousToolHook = {
|
|
42
|
+
name: 'built-in:dangerous-tool',
|
|
43
|
+
point: 'beforeToolCall',
|
|
44
|
+
priority: 20,
|
|
45
|
+
handler: async (context) => {
|
|
46
|
+
const { toolName, toolArgs, sessionId } = context;
|
|
47
|
+
if (!toolName) {
|
|
48
|
+
return { proceed: true };
|
|
49
|
+
}
|
|
50
|
+
const level = sharedManager.getLevel(toolName);
|
|
51
|
+
// Safe tools (or unknown tools with no rule) are always allowed without prompting
|
|
52
|
+
if (level === 'safe') {
|
|
53
|
+
return { proceed: true };
|
|
54
|
+
}
|
|
55
|
+
log.debug('Checking permission for tool', { tool: toolName, level, sessionId });
|
|
56
|
+
const result = await sharedManager.check(toolName, toolArgs);
|
|
57
|
+
if (!result.allowed) {
|
|
58
|
+
log.warn('Tool call denied by permission manager', {
|
|
59
|
+
tool: toolName,
|
|
60
|
+
reason: result.reason,
|
|
61
|
+
sessionId,
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
proceed: false,
|
|
65
|
+
metadata: {
|
|
66
|
+
permissionDenied: true,
|
|
67
|
+
deniedTool: toolName,
|
|
68
|
+
reason: result.reason,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Allowed — flag with requiresApproval so callers remain aware
|
|
73
|
+
return {
|
|
74
|
+
proceed: true,
|
|
75
|
+
metadata: { requiresApproval: true, dangerousTool: toolName },
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
export default dangerousToolHook;
|
|
80
|
+
//# sourceMappingURL=dangerous-tool.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Hooks
|
|
3
|
+
*
|
|
4
|
+
* Export all built-in hooks and a helper to register them all at once.
|
|
5
|
+
*/
|
|
6
|
+
export { costWarningHook } from './cost-warning.js';
|
|
7
|
+
export { dangerousToolHook, DANGEROUS_TOOLS } from './dangerous-tool.js';
|
|
8
|
+
export { auditLogHook } from './audit-log.js';
|
|
9
|
+
import type { HookRegistry } from '../registry.js';
|
|
10
|
+
/**
|
|
11
|
+
* Register all built-in hooks on a registry.
|
|
12
|
+
*/
|
|
13
|
+
export declare function registerBuiltInHooks(registry: HookRegistry): void;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Hooks
|
|
3
|
+
*
|
|
4
|
+
* Export all built-in hooks and a helper to register them all at once.
|
|
5
|
+
*/
|
|
6
|
+
export { costWarningHook } from './cost-warning.js';
|
|
7
|
+
export { dangerousToolHook, DANGEROUS_TOOLS } from './dangerous-tool.js';
|
|
8
|
+
export { auditLogHook } from './audit-log.js';
|
|
9
|
+
import { costWarningHook } from './cost-warning.js';
|
|
10
|
+
import { dangerousToolHook } from './dangerous-tool.js';
|
|
11
|
+
import { auditLogHook } from './audit-log.js';
|
|
12
|
+
/**
|
|
13
|
+
* Register all built-in hooks on a registry.
|
|
14
|
+
*/
|
|
15
|
+
export function registerBuiltInHooks(registry) {
|
|
16
|
+
registry.register(costWarningHook);
|
|
17
|
+
registry.register(dangerousToolHook);
|
|
18
|
+
registry.register(auditLogHook);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -10,4 +10,7 @@ export { handlePostToolUse, getSessionEvents, getEvent, getSessionSummary, clear
|
|
|
10
10
|
export { handleSessionEnd, getSessionAggregate, getAllSessionAggregates, getRecentSessions, } from './session-end.js';
|
|
11
11
|
export { handlePromptSubmit, getSessionPrompts, getInitialPrompt, clearSessionPrompts, } from './prompt-submit.js';
|
|
12
12
|
export { handleOpenClawWebhook, handleGenericAgentWebhook, getAgentReport, getTaskReports, getRecentReports, getReportsByAgent, AgentCompletionSchema, OpenClawCompletionSchema, type AgentCompletion, type OpenClawCompletion, } from './agent-webhook.js';
|
|
13
|
+
export { HookRegistry, getHookRegistry, type HookPoint, type HookContext, type HookResult, type Hook, } from './registry.js';
|
|
14
|
+
export { loadHooks } from './loader.js';
|
|
15
|
+
export { costWarningHook, dangerousToolHook, auditLogHook, registerBuiltInHooks, DANGEROUS_TOOLS, } from './built-in/index.js';
|
|
13
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/hooks/index.js
CHANGED
|
@@ -12,4 +12,10 @@ export { handleSessionEnd, getSessionAggregate, getAllSessionAggregates, getRece
|
|
|
12
12
|
export { handlePromptSubmit, getSessionPrompts, getInitialPrompt, clearSessionPrompts, } from './prompt-submit.js';
|
|
13
13
|
// Agent webhook exports
|
|
14
14
|
export { handleOpenClawWebhook, handleGenericAgentWebhook, getAgentReport, getTaskReports, getRecentReports, getReportsByAgent, AgentCompletionSchema, OpenClawCompletionSchema, } from './agent-webhook.js';
|
|
15
|
+
// Hook Registry (WS-4.1)
|
|
16
|
+
export { HookRegistry, getHookRegistry, } from './registry.js';
|
|
17
|
+
// Hook Loader (WS-4.1)
|
|
18
|
+
export { loadHooks } from './loader.js';
|
|
19
|
+
// Built-in Hooks (WS-4.2)
|
|
20
|
+
export { costWarningHook, dangerousToolHook, auditLogHook, registerBuiltInHooks, DANGEROUS_TOOLS, } from './built-in/index.js';
|
|
15
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook Loader
|
|
3
|
+
*
|
|
4
|
+
* Dynamically loads hooks from a YAML config file or a hooks/ directory.
|
|
5
|
+
* Each hook file should export a `Hook` or `Hook[]` as its default export.
|
|
6
|
+
*/
|
|
7
|
+
import type { Hook } from './registry.js';
|
|
8
|
+
/**
|
|
9
|
+
* Load hooks from a YAML config file or hooks/ directory.
|
|
10
|
+
*
|
|
11
|
+
* Resolution order:
|
|
12
|
+
* 1. `configPath` if provided
|
|
13
|
+
* 2. `profclaw.hooks.yml` in the current working directory
|
|
14
|
+
* 3. `hooks/` directory in the current working directory
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadHooks(configPath?: string): Promise<Hook[]>;
|
|
17
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook Loader
|
|
3
|
+
*
|
|
4
|
+
* Dynamically loads hooks from a YAML config file or a hooks/ directory.
|
|
5
|
+
* Each hook file should export a `Hook` or `Hook[]` as its default export.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, existsSync, readdirSync } from 'node:fs';
|
|
8
|
+
import { resolve, join, extname } from 'node:path';
|
|
9
|
+
import { createContextualLogger } from '../utils/logger.js';
|
|
10
|
+
const log = createContextualLogger('HookLoader');
|
|
11
|
+
function parseSimpleYaml(content) {
|
|
12
|
+
const result = {};
|
|
13
|
+
const lines = content.split('\n');
|
|
14
|
+
let inHooks = false;
|
|
15
|
+
const hookEntries = [];
|
|
16
|
+
for (const rawLine of lines) {
|
|
17
|
+
const line = rawLine.trimEnd();
|
|
18
|
+
if (line.startsWith('hooksDir:')) {
|
|
19
|
+
result.hooksDir = line.replace('hooksDir:', '').trim().replace(/^['"]|['"]$/g, '');
|
|
20
|
+
inHooks = false;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (line.startsWith('hooks:')) {
|
|
24
|
+
inHooks = true;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (inHooks && line.match(/^\s+-\s+path:/)) {
|
|
28
|
+
const path = line.replace(/^\s+-\s+path:\s*/, '').replace(/^['"]|['"]$/g, '');
|
|
29
|
+
hookEntries.push({ path, enabled: true });
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (inHooks && line.match(/^\s+enabled:/)) {
|
|
33
|
+
const last = hookEntries[hookEntries.length - 1];
|
|
34
|
+
if (last) {
|
|
35
|
+
last.enabled = line.includes('true');
|
|
36
|
+
}
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (line && !line.startsWith(' ') && !line.startsWith('\t') && !line.startsWith('#')) {
|
|
40
|
+
inHooks = false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (hookEntries.length > 0) {
|
|
44
|
+
result.hooks = hookEntries;
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
async function loadHookFromPath(filePath) {
|
|
49
|
+
try {
|
|
50
|
+
const mod = await import(filePath);
|
|
51
|
+
const exported = mod.default ?? mod;
|
|
52
|
+
if (Array.isArray(exported)) {
|
|
53
|
+
return exported;
|
|
54
|
+
}
|
|
55
|
+
if (exported && typeof exported.handler === 'function') {
|
|
56
|
+
return [exported];
|
|
57
|
+
}
|
|
58
|
+
log.warn('Hook file did not export a Hook or Hook[]', { path: filePath });
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
log.error('[HookLoader] Failed to load hook file', {
|
|
63
|
+
path: filePath,
|
|
64
|
+
error: error instanceof Error ? error.message : String(error),
|
|
65
|
+
});
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Load hooks from a YAML config file or hooks/ directory.
|
|
71
|
+
*
|
|
72
|
+
* Resolution order:
|
|
73
|
+
* 1. `configPath` if provided
|
|
74
|
+
* 2. `profclaw.hooks.yml` in the current working directory
|
|
75
|
+
* 3. `hooks/` directory in the current working directory
|
|
76
|
+
*/
|
|
77
|
+
export async function loadHooks(configPath) {
|
|
78
|
+
const cwd = process.cwd();
|
|
79
|
+
const loaded = [];
|
|
80
|
+
// Resolve config path
|
|
81
|
+
const yamlPath = configPath ?? resolve(cwd, 'profclaw.hooks.yml');
|
|
82
|
+
if (existsSync(yamlPath)) {
|
|
83
|
+
log.info('Loading hooks from YAML config', { path: yamlPath });
|
|
84
|
+
try {
|
|
85
|
+
const content = readFileSync(yamlPath, 'utf-8');
|
|
86
|
+
const config = parseSimpleYaml(content);
|
|
87
|
+
// Load explicitly listed hook files
|
|
88
|
+
if (config.hooks) {
|
|
89
|
+
for (const entry of config.hooks) {
|
|
90
|
+
if (entry.enabled === false)
|
|
91
|
+
continue;
|
|
92
|
+
const absPath = resolve(cwd, entry.path);
|
|
93
|
+
const hooks = await loadHookFromPath(absPath);
|
|
94
|
+
loaded.push(...hooks);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Load from hooksDir if specified
|
|
98
|
+
if (config.hooksDir) {
|
|
99
|
+
const dir = resolve(cwd, config.hooksDir);
|
|
100
|
+
const dirHooks = await loadHooksFromDirectory(dir);
|
|
101
|
+
loaded.push(...dirHooks);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
log.error('[HookLoader] Failed to parse hooks YAML', {
|
|
106
|
+
path: yamlPath,
|
|
107
|
+
error: error instanceof Error ? error.message : String(error),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Fallback: scan hooks/ directory
|
|
113
|
+
const hooksDir = resolve(cwd, 'hooks');
|
|
114
|
+
if (existsSync(hooksDir)) {
|
|
115
|
+
log.info('Loading hooks from directory', { dir: hooksDir });
|
|
116
|
+
const dirHooks = await loadHooksFromDirectory(hooksDir);
|
|
117
|
+
loaded.push(...dirHooks);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
log.info('Hooks loaded', { count: loaded.length });
|
|
121
|
+
return loaded;
|
|
122
|
+
}
|
|
123
|
+
async function loadHooksFromDirectory(dir) {
|
|
124
|
+
const result = [];
|
|
125
|
+
if (!existsSync(dir))
|
|
126
|
+
return result;
|
|
127
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
128
|
+
for (const entry of entries) {
|
|
129
|
+
if (!entry.isFile())
|
|
130
|
+
continue;
|
|
131
|
+
const ext = extname(entry.name);
|
|
132
|
+
if (ext !== '.ts' && ext !== '.js' && ext !== '.mjs')
|
|
133
|
+
continue;
|
|
134
|
+
if (entry.name.endsWith('.test.ts') || entry.name.endsWith('.test.js'))
|
|
135
|
+
continue;
|
|
136
|
+
const filePath = join(dir, entry.name);
|
|
137
|
+
const hooks = await loadHookFromPath(filePath);
|
|
138
|
+
result.push(...hooks);
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages lifecycle hooks for the profClaw agent execution pipeline.
|
|
5
|
+
* Hooks run in priority order and can abort or modify the operation.
|
|
6
|
+
*/
|
|
7
|
+
export type HookPoint = 'beforeToolCall' | 'afterToolCall' | 'beforeApiCall' | 'afterResponse' | 'onSessionStart' | 'onSessionEnd' | 'onError' | 'onBudgetWarning';
|
|
8
|
+
export interface HookContext {
|
|
9
|
+
hookPoint: HookPoint;
|
|
10
|
+
sessionId?: string;
|
|
11
|
+
toolName?: string;
|
|
12
|
+
toolArgs?: unknown;
|
|
13
|
+
toolResult?: unknown;
|
|
14
|
+
error?: Error;
|
|
15
|
+
budgetUsed?: number;
|
|
16
|
+
budgetMax?: number;
|
|
17
|
+
metadata: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
export interface HookResult {
|
|
20
|
+
/** false = abort the operation */
|
|
21
|
+
proceed: boolean;
|
|
22
|
+
/** Override args/result if provided */
|
|
23
|
+
modified?: unknown;
|
|
24
|
+
metadata?: Record<string, unknown>;
|
|
25
|
+
}
|
|
26
|
+
export interface Hook {
|
|
27
|
+
name: string;
|
|
28
|
+
point: HookPoint;
|
|
29
|
+
/** Lower runs first, default 100 */
|
|
30
|
+
priority: number;
|
|
31
|
+
handler: (context: HookContext) => Promise<HookResult>;
|
|
32
|
+
}
|
|
33
|
+
export declare class HookRegistry {
|
|
34
|
+
private hooks;
|
|
35
|
+
constructor();
|
|
36
|
+
/**
|
|
37
|
+
* Register a hook. If a hook with the same name already exists it is replaced.
|
|
38
|
+
*/
|
|
39
|
+
register(hook: Hook): void;
|
|
40
|
+
/**
|
|
41
|
+
* Unregister a hook by name (searches all hook points).
|
|
42
|
+
*/
|
|
43
|
+
unregister(name: string): void;
|
|
44
|
+
/**
|
|
45
|
+
* Run all hooks for a given point in priority order.
|
|
46
|
+
*
|
|
47
|
+
* - If any hook returns `proceed: false`, the chain stops immediately.
|
|
48
|
+
* - If a hook returns `modified`, that value is forwarded to the next hook.
|
|
49
|
+
* - Returns `{ proceed: true }` when no hooks are registered for the point.
|
|
50
|
+
*/
|
|
51
|
+
run(point: HookPoint, context: HookContext): Promise<HookResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Return a flat list of all registered hooks across all points.
|
|
54
|
+
*/
|
|
55
|
+
getRegistered(): Hook[];
|
|
56
|
+
/**
|
|
57
|
+
* Remove all registered hooks.
|
|
58
|
+
*/
|
|
59
|
+
clear(): void;
|
|
60
|
+
}
|
|
61
|
+
export declare function getHookRegistry(): HookRegistry;
|
|
62
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages lifecycle hooks for the profClaw agent execution pipeline.
|
|
5
|
+
* Hooks run in priority order and can abort or modify the operation.
|
|
6
|
+
*/
|
|
7
|
+
import { createContextualLogger } from '../utils/logger.js';
|
|
8
|
+
const log = createContextualLogger('HookRegistry');
|
|
9
|
+
export class HookRegistry {
|
|
10
|
+
hooks;
|
|
11
|
+
constructor() {
|
|
12
|
+
this.hooks = new Map();
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Register a hook. If a hook with the same name already exists it is replaced.
|
|
16
|
+
*/
|
|
17
|
+
register(hook) {
|
|
18
|
+
if (!this.hooks.has(hook.point)) {
|
|
19
|
+
this.hooks.set(hook.point, []);
|
|
20
|
+
}
|
|
21
|
+
const list = this.hooks.get(hook.point);
|
|
22
|
+
// Remove existing hook with same name (idempotent registration)
|
|
23
|
+
const existingIdx = list.findIndex((h) => h.name === hook.name);
|
|
24
|
+
if (existingIdx !== -1) {
|
|
25
|
+
list.splice(existingIdx, 1);
|
|
26
|
+
}
|
|
27
|
+
list.push(hook);
|
|
28
|
+
// Keep sorted by priority ascending — lower number runs first
|
|
29
|
+
list.sort((a, b) => a.priority - b.priority);
|
|
30
|
+
log.debug('Hook registered', { name: hook.name, point: hook.point, priority: hook.priority });
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Unregister a hook by name (searches all hook points).
|
|
34
|
+
*/
|
|
35
|
+
unregister(name) {
|
|
36
|
+
for (const [point, list] of this.hooks) {
|
|
37
|
+
const idx = list.findIndex((h) => h.name === name);
|
|
38
|
+
if (idx !== -1) {
|
|
39
|
+
list.splice(idx, 1);
|
|
40
|
+
log.debug('Hook unregistered', { name, point });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Run all hooks for a given point in priority order.
|
|
46
|
+
*
|
|
47
|
+
* - If any hook returns `proceed: false`, the chain stops immediately.
|
|
48
|
+
* - If a hook returns `modified`, that value is forwarded to the next hook.
|
|
49
|
+
* - Returns `{ proceed: true }` when no hooks are registered for the point.
|
|
50
|
+
*/
|
|
51
|
+
async run(point, context) {
|
|
52
|
+
const list = this.hooks.get(point);
|
|
53
|
+
if (!list || list.length === 0) {
|
|
54
|
+
return { proceed: true };
|
|
55
|
+
}
|
|
56
|
+
let currentContext = { ...context };
|
|
57
|
+
let aggregatedMetadata = { ...context.metadata };
|
|
58
|
+
for (const hook of list) {
|
|
59
|
+
try {
|
|
60
|
+
const result = await hook.handler(currentContext);
|
|
61
|
+
if (result.metadata) {
|
|
62
|
+
aggregatedMetadata = { ...aggregatedMetadata, ...result.metadata };
|
|
63
|
+
}
|
|
64
|
+
if (!result.proceed) {
|
|
65
|
+
log.info('Hook chain aborted', { hook: hook.name, point });
|
|
66
|
+
return {
|
|
67
|
+
proceed: false,
|
|
68
|
+
modified: result.modified,
|
|
69
|
+
metadata: aggregatedMetadata,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Forward modified value to the next hook
|
|
73
|
+
if (result.modified !== undefined) {
|
|
74
|
+
currentContext = {
|
|
75
|
+
...currentContext,
|
|
76
|
+
toolArgs: result.modified,
|
|
77
|
+
toolResult: result.modified,
|
|
78
|
+
metadata: aggregatedMetadata,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
currentContext = { ...currentContext, metadata: aggregatedMetadata };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
log.error('[HookRegistry] Hook threw an error', {
|
|
87
|
+
hook: hook.name,
|
|
88
|
+
point,
|
|
89
|
+
error: error instanceof Error ? error.message : String(error),
|
|
90
|
+
});
|
|
91
|
+
// Non-fatal: log and continue the chain
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const finalModified = currentContext.toolArgs !== context.toolArgs ? currentContext.toolArgs : undefined;
|
|
95
|
+
return {
|
|
96
|
+
proceed: true,
|
|
97
|
+
modified: finalModified,
|
|
98
|
+
metadata: aggregatedMetadata,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Return a flat list of all registered hooks across all points.
|
|
103
|
+
*/
|
|
104
|
+
getRegistered() {
|
|
105
|
+
const all = [];
|
|
106
|
+
for (const list of this.hooks.values()) {
|
|
107
|
+
all.push(...list);
|
|
108
|
+
}
|
|
109
|
+
return all;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Remove all registered hooks.
|
|
113
|
+
*/
|
|
114
|
+
clear() {
|
|
115
|
+
this.hooks.clear();
|
|
116
|
+
log.debug('Hook registry cleared');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Module-level singleton registry */
|
|
120
|
+
let defaultRegistry = null;
|
|
121
|
+
export function getHookRegistry() {
|
|
122
|
+
if (!defaultRegistry) {
|
|
123
|
+
defaultRegistry = new HookRegistry();
|
|
124
|
+
}
|
|
125
|
+
return defaultRegistry;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=registry.js.map
|