profclaw 0.0.1-beta.3 → 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 +54 -34
- package/CONTRIBUTING.md +23 -5
- package/Dockerfile +39 -23
- package/README.md +271 -72
- 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 +15 -3
- package/dist/chat/execution/tools/index.js +125 -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/slack/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/models.js +39 -26
- package/dist/cli/commands/onboard.js +263 -98
- 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 +375 -91
- 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 -6
- 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/providers.d.ts +15 -0
- package/dist/cli/providers.js +41 -0
- package/dist/cli/utils/api.d.ts +9 -0
- package/dist/cli/utils/api.js +58 -2
- package/dist/core/deployment.js +2 -0
- 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 +97 -18
- 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/channels.d.ts +12 -0
- package/dist/routes/channels.js +166 -0
- 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 +4 -1
- package/dist/server/stream-bridge.d.ts +19 -0
- package/dist/server/stream-bridge.js +38 -0
- package/dist/server.js +421 -141
- 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/git-workflow/SKILL.md +3 -3
- 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-DlYUcOss.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-CgPqzUvj.js → Settings-xA8Zhi3p.js} +3 -3
- package/ui/dist/assets/StatusIndicator-B8vfFAxg.js +1 -0
- package/ui/dist/assets/{SummaryDetail-CwLAfHgJ.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-CGck7gxR.js → archive-CX7UvZpf.js} +1 -1
- package/ui/dist/assets/badge-BbfnwDJP.js +1 -0
- package/ui/dist/assets/{bug-DqSGPUUE.js → bug-3WX0394-.js} +1 -1
- package/ui/dist/assets/{calendar-BuZ4zbPW.js → calendar-buq77TaS.js} +1 -1
- package/ui/dist/assets/{chevron-up-DcJ4LL_N.js → chevron-up-4ymsBJRo.js} +1 -1
- package/ui/dist/assets/{circle-x-C78PNZjF.js → circle-x-ByXtwR6Y.js} +1 -1
- package/ui/dist/assets/constants-CVdDh7p0.js +1 -0
- package/ui/dist/assets/{cpu-Ck6AoG8c.js → cpu-CiuoCeDY.js} +1 -1
- package/ui/dist/assets/{database-CA2w8Lvt.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-FhHKRbfl.js → ellipsis-vT-5SVIp.js} +1 -1
- package/ui/dist/assets/{ellipsis-vertical-CO0UqE4-.js → ellipsis-vertical-B4tAX_bL.js} +1 -1
- package/ui/dist/assets/feature-markdown-DBo5Q7uq.js +289 -0
- package/ui/dist/assets/{file-code-ChnhYYj1.js → file-code-ChOWdKXf.js} +1 -1
- package/ui/dist/assets/{folder-open-CHwA1-ve.js → folder-open-CkOUbIiP.js} +1 -1
- package/ui/dist/assets/{funnel-ByEjRFNB.js → funnel-uZkoSPP-.js} +1 -1
- package/ui/dist/assets/{git-branch-GTOPQgU4.js → git-branch-CwvUxj7C.js} +1 -1
- package/ui/dist/assets/{git-commit-horizontal-F5M84Kut.js → git-commit-horizontal-lxPzCvhD.js} +1 -1
- package/ui/dist/assets/{globe-CQWfr7hT.js → globe-D_WpJdsj.js} +1 -1
- package/ui/dist/assets/{hash-nKC9gtLg.js → hash-CA0hJ7vh.js} +1 -1
- package/ui/dist/assets/{history-DfFSA9xJ.js → history-CEWMLELs.js} +1 -1
- package/ui/dist/assets/inbox-ehtOptTV.js +1 -0
- package/ui/dist/assets/{index-a4Fxq0Hb.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-WmgjMhWF.js → layout-dashboard-BRUM0kpT.js} +1 -1
- package/ui/dist/assets/{lightbulb-Bo8hEr7B.js → lightbulb-CN2q1O5l.js} +1 -1
- package/ui/dist/assets/{link-2-YqrpQXBH.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-CD0H5hot.js → message-square-Bbb241am.js} +1 -1
- package/ui/dist/assets/package-CwT3IzFx.js +1 -0
- package/ui/dist/assets/{pencil-DpFnj5dn.js → pencil-CDmiHzoj.js} +1 -1
- package/ui/dist/assets/{play-DVgea_jT.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-BFxPYGx9.js → rocket--8ZHgdXJ.js} +1 -1
- package/ui/dist/assets/select-n108rXny.js +1 -0
- package/ui/dist/assets/{send-eYnW_7n-.js → send-Cu7MR2Qh.js} +1 -1
- package/ui/dist/assets/server-DmodxZp-.js +1 -0
- package/ui/dist/assets/{settings-2-scXUOuE_.js → settings-2-CkRNqkxj.js} +1 -1
- package/ui/dist/assets/sheet-7aUJkyzU.js +1 -0
- package/ui/dist/assets/{shield-check-PEr7nmVw.js → shield-check-ViI3nMKE.js} +1 -1
- package/ui/dist/assets/{shield-off-CLtXio62.js → shield-off-DN3tagkn.js} +1 -1
- package/ui/dist/assets/skeleton-C0E1Nfro.js +1 -0
- package/ui/dist/assets/{smartphone-DusFfY0U.js → smartphone-5FghiXpA.js} +1 -1
- package/ui/dist/assets/{square-e1yxB2eR.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-tAwMmQ9G.js → tag-CH_vQliw.js} +1 -1
- package/ui/dist/assets/textarea-CxDiKFXZ.js +1 -0
- package/ui/dist/assets/{timer-Vel1N3RP.js → timer-CdGVTb60.js} +1 -1
- package/ui/dist/assets/tooltip-BuW9A5UO.js +1 -0
- package/ui/dist/assets/{trash-2-eM-CNwsZ.js → trash-2-CucZJL0N.js} +1 -1
- package/ui/dist/assets/trending-down-BCezC1z2.js +1 -0
- package/ui/dist/assets/{trending-up-BGafmjRo.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-DPvcd9Pi.js → wand-sparkles-BaH6pJnc.js} +1 -1
- package/ui/dist/assets/{wrench-B8s3zYVV.js → wrench-CjxjP6ok.js} +1 -1
- package/ui/dist/index.html +5 -2
- package/dist/chat/auto-reply.d.ts +0 -90
- package/dist/chat/auto-reply.js +0 -272
- package/dist/chat/execution/pty.d.ts +0 -92
- package/dist/chat/execution/pty.js +0 -285
- package/dist/chat/execution/tools/glinr-ops.d.ts +0 -202
- package/dist/chat/execution/tools/glinr-ops.js +0 -694
- package/dist/cli/commands/browser.d.ts +0 -3
- package/dist/cli/commands/browser.js +0 -138
- package/dist/cli/commands/canvas.d.ts +0 -3
- package/dist/cli/commands/canvas.js +0 -155
- package/dist/cli/commands/nodes.d.ts +0 -3
- package/dist/cli/commands/nodes.js +0 -193
- package/dist/diagnostics/exporters.d.ts +0 -21
- package/dist/diagnostics/exporters.js +0 -138
- package/dist/diagnostics/index.d.ts +0 -10
- package/dist/diagnostics/index.js +0 -9
- package/dist/diagnostics/middleware.d.ts +0 -12
- package/dist/diagnostics/middleware.js +0 -58
- package/dist/diagnostics/tracer.d.ts +0 -133
- package/dist/diagnostics/tracer.js +0 -257
- package/dist/discovery/index.d.ts +0 -8
- package/dist/discovery/index.js +0 -7
- package/dist/discovery/mdns.d.ts +0 -40
- package/dist/discovery/mdns.js +0 -249
- package/dist/plugins/registry.d.ts +0 -122
- package/dist/plugins/registry.js +0 -352
- package/dist/plugins/sandbox.d.ts +0 -77
- package/dist/plugins/sandbox.js +0 -287
- package/dist/plugins/search/brave.d.ts +0 -9
- package/dist/plugins/search/brave.js +0 -157
- package/dist/plugins/search/duckduckgo.d.ts +0 -9
- package/dist/plugins/search/duckduckgo.js +0 -171
- package/dist/plugins/search/index.d.ts +0 -13
- package/dist/plugins/search/index.js +0 -23
- package/dist/plugins/search/searxng.d.ts +0 -9
- package/dist/plugins/search/searxng.js +0 -170
- package/dist/plugins/search/serper.d.ts +0 -9
- package/dist/plugins/search/serper.js +0 -135
- package/dist/plugins/search/tavily.d.ts +0 -9
- package/dist/plugins/search/tavily.js +0 -146
- package/dist/providers/adapters/anthropic.d.ts +0 -26
- package/dist/providers/adapters/anthropic.js +0 -306
- package/dist/providers/adapters/base.d.ts +0 -53
- package/dist/providers/adapters/base.js +0 -99
- package/dist/providers/adapters/ollama.d.ts +0 -30
- package/dist/providers/adapters/ollama.js +0 -292
- package/dist/utils/ai-cache.d.ts +0 -72
- package/dist/utils/ai-cache.js +0 -204
- package/dist/utils/file-lock.d.ts +0 -85
- package/dist/utils/file-lock.js +0 -204
- package/ui/dist/assets/ActivityView-DIPQSJ_d.js +0 -1
- package/ui/dist/assets/AgentList-CqyaYrcq.js +0 -1
- package/ui/dist/assets/AnalyticsDashboard-C-mjuGHT.js +0 -1
- package/ui/dist/assets/AreaChart-CfYWmbtr.js +0 -1
- package/ui/dist/assets/CartesianChart-BaQ3It0c.js +0 -36
- package/ui/dist/assets/ChatView-DxxQy6pl.js +0 -10
- package/ui/dist/assets/CostsDashboard-CDBBcGkg.js +0 -1
- package/ui/dist/assets/EstimateSelect-CDjf5qKl.js +0 -1
- package/ui/dist/assets/FloatingChatbot-CZHjvJIe.js +0 -2
- package/ui/dist/assets/InviteCodeManagement-DTm-IPTm.js +0 -2
- package/ui/dist/assets/ProjectIcon-BMRpnM04.js +0 -1
- package/ui/dist/assets/ProjectList-D85TN0i0.js +0 -4
- package/ui/dist/assets/StatusIndicator-yig0uZEA.js +0 -1
- package/ui/dist/assets/SummaryList-BvS5Idnu.js +0 -1
- package/ui/dist/assets/TaskDetail-zarC1fOt.js +0 -1
- package/ui/dist/assets/TaskList-CyJq3ANE.js +0 -1
- package/ui/dist/assets/TicketBoard-BlWr3-iH.js +0 -1
- package/ui/dist/assets/TicketDetail-DmqWKj2W.js +0 -1
- package/ui/dist/assets/TicketList-Scj4pMWa.js +0 -1
- package/ui/dist/assets/UserManagement-BH7uG7dw.js +0 -2
- package/ui/dist/assets/ViewSwitcher-3HzZUdWn.js +0 -1
- package/ui/dist/assets/alert-dialog-DWPb2IfQ.js +0 -7
- package/ui/dist/assets/badge-DEmc3Z_l.js +0 -1
- package/ui/dist/assets/brain-CfFdLVqb.js +0 -1
- package/ui/dist/assets/constants-DhDjZe4P.js +0 -1
- package/ui/dist/assets/dialog-BOdGWhgE.js +0 -1
- package/ui/dist/assets/index--JkIxVXb.js +0 -67
- package/ui/dist/assets/index-Ca3vk7Gq.js +0 -1
- package/ui/dist/assets/index-DHGvP9mp.js +0 -1
- package/ui/dist/assets/index-DeI8lKRR.js +0 -1
- package/ui/dist/assets/index-WclMPci1.css +0 -1
- package/ui/dist/assets/index-Z4-RtZcs.js +0 -1
- package/ui/dist/assets/layers-DFeLExSa.js +0 -1
- package/ui/dist/assets/markdown-renderer-Croje6Xe.js +0 -36
- package/ui/dist/assets/popover-JXecfWG5.js +0 -1
- package/ui/dist/assets/progress-C1ghf1Fu.js +0 -1
- package/ui/dist/assets/select-MADP8m6Q.js +0 -1
- package/ui/dist/assets/server-CPMaysH8.js +0 -1
- package/ui/dist/assets/sheet-r6NSOxi-.js +0 -1
- package/ui/dist/assets/skeleton-C9oEzNlU.js +0 -1
- package/ui/dist/assets/switch-tNs0n-kz.js +0 -1
- package/ui/dist/assets/table-CXxtLicg.js +0 -1
- package/ui/dist/assets/textarea-BjiEeIWh.js +0 -1
- package/ui/dist/assets/tooltip-ZMwtfr1J.js +0 -1
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Circuit Breaker
|
|
3
|
+
*
|
|
4
|
+
* Prevents tools from being called repeatedly when they are failing.
|
|
5
|
+
* Implements the standard circuit breaker pattern:
|
|
6
|
+
* closed → (3 failures in 2 min) → open → (cooldown expires) → half-open
|
|
7
|
+
* half-open → (1 success) → closed
|
|
8
|
+
* half-open → (1 failure) → open (doubled cooldown)
|
|
9
|
+
*/
|
|
10
|
+
import { logger } from '../utils/logger.js';
|
|
11
|
+
// Constants
|
|
12
|
+
const DEFAULT_FAILURE_THRESHOLD = 3;
|
|
13
|
+
const DEFAULT_WINDOW_MS = 120_000; // 2 minutes
|
|
14
|
+
const INITIAL_COOLDOWN_MS = 5_000;
|
|
15
|
+
const MAX_COOLDOWN_MS = 60_000;
|
|
16
|
+
function defaultBreakerState() {
|
|
17
|
+
return {
|
|
18
|
+
state: 'closed',
|
|
19
|
+
failureCount: 0,
|
|
20
|
+
lastFailureAt: 0,
|
|
21
|
+
cooldownMs: INITIAL_COOLDOWN_MS,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
// Circuit Breaker
|
|
25
|
+
export class ToolCircuitBreaker {
|
|
26
|
+
breakers;
|
|
27
|
+
failureThreshold;
|
|
28
|
+
windowMs;
|
|
29
|
+
constructor(failureThreshold = DEFAULT_FAILURE_THRESHOLD, windowMs = DEFAULT_WINDOW_MS) {
|
|
30
|
+
this.breakers = new Map();
|
|
31
|
+
this.failureThreshold = failureThreshold;
|
|
32
|
+
this.windowMs = windowMs;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check whether a tool is allowed to execute.
|
|
36
|
+
* Transitions open → half-open when the cooldown has expired.
|
|
37
|
+
*/
|
|
38
|
+
canExecute(toolName) {
|
|
39
|
+
const breaker = this.getOrCreate(toolName);
|
|
40
|
+
const now = Date.now();
|
|
41
|
+
if (breaker.state === 'closed') {
|
|
42
|
+
return { allowed: true };
|
|
43
|
+
}
|
|
44
|
+
if (breaker.state === 'open') {
|
|
45
|
+
const elapsed = now - breaker.lastFailureAt;
|
|
46
|
+
if (elapsed >= breaker.cooldownMs) {
|
|
47
|
+
// Transition to half-open to allow a probe call
|
|
48
|
+
breaker.state = 'half-open';
|
|
49
|
+
logger.debug('[CircuitBreaker] Transitioning to half-open', {
|
|
50
|
+
tool: toolName,
|
|
51
|
+
elapsed,
|
|
52
|
+
cooldownMs: breaker.cooldownMs,
|
|
53
|
+
});
|
|
54
|
+
return { allowed: true };
|
|
55
|
+
}
|
|
56
|
+
const remainingMs = breaker.cooldownMs - elapsed;
|
|
57
|
+
return {
|
|
58
|
+
allowed: false,
|
|
59
|
+
reason: `Circuit breaker open for ${toolName}: too many recent failures. Retry in ${Math.ceil(remainingMs / 1000)}s.`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// half-open: allow one probe through
|
|
63
|
+
return { allowed: true };
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Record a successful tool execution.
|
|
67
|
+
* In half-open state this closes the circuit.
|
|
68
|
+
*/
|
|
69
|
+
recordSuccess(toolName) {
|
|
70
|
+
const breaker = this.getOrCreate(toolName);
|
|
71
|
+
if (breaker.state === 'half-open') {
|
|
72
|
+
logger.info('[CircuitBreaker] Probe succeeded, closing circuit', { tool: toolName });
|
|
73
|
+
breaker.state = 'closed';
|
|
74
|
+
breaker.failureCount = 0;
|
|
75
|
+
breaker.cooldownMs = INITIAL_COOLDOWN_MS;
|
|
76
|
+
}
|
|
77
|
+
else if (breaker.state === 'closed') {
|
|
78
|
+
// Reset failure count on success within the window
|
|
79
|
+
breaker.failureCount = 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Record a failed tool execution.
|
|
84
|
+
* Counts failures within the time window and trips the breaker when the
|
|
85
|
+
* threshold is reached. In half-open state it immediately re-opens with
|
|
86
|
+
* a doubled cooldown.
|
|
87
|
+
*/
|
|
88
|
+
recordFailure(toolName) {
|
|
89
|
+
const breaker = this.getOrCreate(toolName);
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
if (breaker.state === 'half-open') {
|
|
92
|
+
// Probe failed — re-open with doubled cooldown
|
|
93
|
+
breaker.cooldownMs = Math.min(breaker.cooldownMs * 2, MAX_COOLDOWN_MS);
|
|
94
|
+
breaker.state = 'open';
|
|
95
|
+
breaker.lastFailureAt = now;
|
|
96
|
+
logger.warn('[CircuitBreaker] Probe failed, re-opening circuit', {
|
|
97
|
+
tool: toolName,
|
|
98
|
+
cooldownMs: breaker.cooldownMs,
|
|
99
|
+
});
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// In closed state, check if previous failures are still within the window
|
|
103
|
+
const withinWindow = breaker.lastFailureAt > 0 && now - breaker.lastFailureAt <= this.windowMs;
|
|
104
|
+
if (withinWindow) {
|
|
105
|
+
breaker.failureCount++;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// Failures outside the window don't count; start a fresh count
|
|
109
|
+
breaker.failureCount = 1;
|
|
110
|
+
}
|
|
111
|
+
breaker.lastFailureAt = now;
|
|
112
|
+
if (breaker.failureCount >= this.failureThreshold) {
|
|
113
|
+
breaker.state = 'open';
|
|
114
|
+
logger.warn('[CircuitBreaker] Threshold reached, opening circuit', {
|
|
115
|
+
tool: toolName,
|
|
116
|
+
failureCount: breaker.failureCount,
|
|
117
|
+
cooldownMs: breaker.cooldownMs,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Reset the circuit breaker for a specific tool, or all tools if no name is given.
|
|
123
|
+
*/
|
|
124
|
+
reset(toolName) {
|
|
125
|
+
if (toolName !== undefined) {
|
|
126
|
+
this.breakers.set(toolName, defaultBreakerState());
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.breakers.clear();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Return a deep snapshot of all breaker states.
|
|
134
|
+
* Mutations to the live breakers do not affect the returned map.
|
|
135
|
+
*/
|
|
136
|
+
getStatus() {
|
|
137
|
+
const snapshot = new Map();
|
|
138
|
+
for (const [key, value] of this.breakers) {
|
|
139
|
+
snapshot.set(key, { ...value });
|
|
140
|
+
}
|
|
141
|
+
return snapshot;
|
|
142
|
+
}
|
|
143
|
+
// Private helpers
|
|
144
|
+
getOrCreate(toolName) {
|
|
145
|
+
let breaker = this.breakers.get(toolName);
|
|
146
|
+
if (!breaker) {
|
|
147
|
+
breaker = defaultBreakerState();
|
|
148
|
+
this.breakers.set(toolName, breaker);
|
|
149
|
+
}
|
|
150
|
+
return breaker;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=circuit-breaker.js.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Compactor
|
|
3
|
+
*
|
|
4
|
+
* Compresses old conversation turns into a structured markdown summary when
|
|
5
|
+
* the estimated token count crosses a configurable threshold.
|
|
6
|
+
*
|
|
7
|
+
* Two modes:
|
|
8
|
+
* - Local heuristic (default): pure extraction, no LLM calls.
|
|
9
|
+
* - LLM-powered (opt-in): uses an injected apiCall function to produce a
|
|
10
|
+
* richer natural-language summary.
|
|
11
|
+
*/
|
|
12
|
+
import type { ModelMessage } from "ai";
|
|
13
|
+
export interface CompactionConfig {
|
|
14
|
+
/** Total token budget for the context window. Default: 100_000 */
|
|
15
|
+
maxContextTokens: number;
|
|
16
|
+
/** Trigger compaction once estimated tokens exceed this value. Default: 70_000 */
|
|
17
|
+
compactionThreshold: number;
|
|
18
|
+
/** Number of most-recent turns (user+assistant pairs) to preserve verbatim. Default: 5 */
|
|
19
|
+
preserveRecentTurns: number;
|
|
20
|
+
/** Maximum tokens for the generated summary message. Default: 2_000 */
|
|
21
|
+
summaryMaxTokens: number;
|
|
22
|
+
/**
|
|
23
|
+
* When true, `compact()` will delegate to `compactWithLLM()` if an
|
|
24
|
+
* `apiCall` function is provided at call time. Default: false.
|
|
25
|
+
*/
|
|
26
|
+
useLLM?: boolean;
|
|
27
|
+
/** Cheap model to use for LLM summarisation (e.g. 'llama3.2'). */
|
|
28
|
+
summaryModel?: string;
|
|
29
|
+
/** Provider for the summarisation model (e.g. 'ollama'). */
|
|
30
|
+
summaryProvider?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface CompactionResult {
|
|
33
|
+
messages: ModelMessage[];
|
|
34
|
+
compacted: boolean;
|
|
35
|
+
originalTokens: number;
|
|
36
|
+
compactedTokens: number;
|
|
37
|
+
turnsCompacted: number;
|
|
38
|
+
}
|
|
39
|
+
export declare class ContextCompactor {
|
|
40
|
+
private config;
|
|
41
|
+
constructor(config?: Partial<CompactionConfig>);
|
|
42
|
+
/**
|
|
43
|
+
* Estimate the token count for a list of messages using the 4-chars-per-token
|
|
44
|
+
* heuristic.
|
|
45
|
+
*/
|
|
46
|
+
estimateTokens(messages: ModelMessage[]): number;
|
|
47
|
+
/**
|
|
48
|
+
* Compact the message list if it exceeds the compaction threshold.
|
|
49
|
+
*
|
|
50
|
+
* Strategy:
|
|
51
|
+
* 1. Identify the most-recent N turns to preserve verbatim.
|
|
52
|
+
* 2. Summarise all older messages into a single system-role summary message.
|
|
53
|
+
* 3. Return the summary + preserved recent messages.
|
|
54
|
+
*
|
|
55
|
+
* When `config.useLLM` is true and `apiCall` is provided, delegates to
|
|
56
|
+
* `compactWithLLM()` for a richer natural-language summary.
|
|
57
|
+
* Falls back to local heuristic summarisation if the LLM call fails.
|
|
58
|
+
*/
|
|
59
|
+
compact(messages: ModelMessage[], apiCall?: (prompt: string) => Promise<string>): Promise<CompactionResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Compact using an injected LLM call for richer summarisation.
|
|
62
|
+
*
|
|
63
|
+
* The `apiCall` function is supplied by the caller so this class remains
|
|
64
|
+
* free of any specific API client dependency.
|
|
65
|
+
*/
|
|
66
|
+
compactWithLLM(messages: ModelMessage[], apiCall: (prompt: string) => Promise<string>): Promise<CompactionResult>;
|
|
67
|
+
/** Local heuristic compaction (no LLM). */
|
|
68
|
+
private _compactLocal;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=context-compactor.d.ts.map
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Compactor
|
|
3
|
+
*
|
|
4
|
+
* Compresses old conversation turns into a structured markdown summary when
|
|
5
|
+
* the estimated token count crosses a configurable threshold.
|
|
6
|
+
*
|
|
7
|
+
* Two modes:
|
|
8
|
+
* - Local heuristic (default): pure extraction, no LLM calls.
|
|
9
|
+
* - LLM-powered (opt-in): uses an injected apiCall function to produce a
|
|
10
|
+
* richer natural-language summary.
|
|
11
|
+
*/
|
|
12
|
+
// ─── Internals ────────────────────────────────────────────────────────────────
|
|
13
|
+
const DEFAULT_CONFIG = {
|
|
14
|
+
maxContextTokens: 100_000,
|
|
15
|
+
compactionThreshold: 70_000,
|
|
16
|
+
preserveRecentTurns: 5,
|
|
17
|
+
summaryMaxTokens: 2_000,
|
|
18
|
+
};
|
|
19
|
+
/** Rough character-to-token ratio used throughout (4 chars ≈ 1 token). */
|
|
20
|
+
const CHARS_PER_TOKEN = 4;
|
|
21
|
+
// ─── Helper utilities ─────────────────────────────────────────────────────────
|
|
22
|
+
function messageToText(message) {
|
|
23
|
+
if (typeof message.content === "string") {
|
|
24
|
+
return message.content;
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(message.content)) {
|
|
27
|
+
return message.content
|
|
28
|
+
.map((part) => {
|
|
29
|
+
if (typeof part === "string")
|
|
30
|
+
return part;
|
|
31
|
+
// TextPart
|
|
32
|
+
if (typeof part === "object" &&
|
|
33
|
+
part !== null &&
|
|
34
|
+
"type" in part &&
|
|
35
|
+
part.type === "text" &&
|
|
36
|
+
"text" in part) {
|
|
37
|
+
return String(part.text);
|
|
38
|
+
}
|
|
39
|
+
// ToolCallPart
|
|
40
|
+
if (typeof part === "object" &&
|
|
41
|
+
part !== null &&
|
|
42
|
+
"type" in part &&
|
|
43
|
+
part.type === "tool-call") {
|
|
44
|
+
const tc = part;
|
|
45
|
+
return `[tool_call: ${tc.toolName}(${JSON.stringify(tc.args ?? {})})]`;
|
|
46
|
+
}
|
|
47
|
+
// ToolResultPart
|
|
48
|
+
if (typeof part === "object" &&
|
|
49
|
+
part !== null &&
|
|
50
|
+
"type" in part &&
|
|
51
|
+
part.type === "tool-result") {
|
|
52
|
+
const tr = part;
|
|
53
|
+
return `[tool_result: ${tr.toolName ?? "unknown"} → ${JSON.stringify(tr.result ?? null)}]`;
|
|
54
|
+
}
|
|
55
|
+
return JSON.stringify(part);
|
|
56
|
+
})
|
|
57
|
+
.join(" ");
|
|
58
|
+
}
|
|
59
|
+
return "";
|
|
60
|
+
}
|
|
61
|
+
/** Extract file paths that were read or written during a set of messages. */
|
|
62
|
+
function extractFilePaths(messages) {
|
|
63
|
+
const paths = new Set();
|
|
64
|
+
const filePattern = /(?:read|write|edit|create|modify)\s+([`"']?[\w./\-_]+\.[a-zA-Z]+[`"']?)/gi;
|
|
65
|
+
for (const msg of messages) {
|
|
66
|
+
const text = messageToText(msg);
|
|
67
|
+
let match;
|
|
68
|
+
while ((match = filePattern.exec(text)) !== null) {
|
|
69
|
+
paths.add(match[1].replace(/[`"']/g, ""));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return Array.from(paths);
|
|
73
|
+
}
|
|
74
|
+
function extractToolCalls(messages) {
|
|
75
|
+
const calls = [];
|
|
76
|
+
for (const msg of messages) {
|
|
77
|
+
if (!Array.isArray(msg.content))
|
|
78
|
+
continue;
|
|
79
|
+
for (const part of msg.content) {
|
|
80
|
+
if (typeof part !== "object" ||
|
|
81
|
+
part === null ||
|
|
82
|
+
!("type" in part)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const typed = part;
|
|
86
|
+
if (typed.type === "tool-call") {
|
|
87
|
+
const tc = part;
|
|
88
|
+
const argKeys = Object.keys(tc.args ?? {}).slice(0, 3).join(", ");
|
|
89
|
+
calls.push({
|
|
90
|
+
name: tc.toolName,
|
|
91
|
+
argsSummary: argKeys ? `{${argKeys}}` : "(no args)",
|
|
92
|
+
outcome: "called",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (typed.type === "tool-result") {
|
|
96
|
+
const tr = part;
|
|
97
|
+
const last = [...calls].reverse().find((c) => c.name === (tr.toolName ?? ""));
|
|
98
|
+
const resultText = typeof tr.result === "string"
|
|
99
|
+
? tr.result.slice(0, 120)
|
|
100
|
+
: JSON.stringify(tr.result ?? null).slice(0, 120);
|
|
101
|
+
if (last) {
|
|
102
|
+
last.outcome = tr.isError === true ? `error: ${resultText}` : `ok: ${resultText}`;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
calls.push({
|
|
106
|
+
name: tr.toolName ?? "unknown",
|
|
107
|
+
argsSummary: "",
|
|
108
|
+
outcome: tr.isError === true ? `error: ${resultText}` : `ok: ${resultText}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return calls;
|
|
115
|
+
}
|
|
116
|
+
/** Extract the apparent user goals from user-role messages. */
|
|
117
|
+
function extractUserGoals(messages) {
|
|
118
|
+
const goals = [];
|
|
119
|
+
for (const msg of messages) {
|
|
120
|
+
if (msg.role !== "user")
|
|
121
|
+
continue;
|
|
122
|
+
const text = messageToText(msg).trim();
|
|
123
|
+
if (text.length > 0) {
|
|
124
|
+
// Keep only the first 200 chars per turn to stay concise
|
|
125
|
+
goals.push(text.slice(0, 200) + (text.length > 200 ? "…" : ""));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return goals;
|
|
129
|
+
}
|
|
130
|
+
/** Build a structured markdown summary capped at approximately maxTokens. */
|
|
131
|
+
function buildSummary(messages, maxTokens) {
|
|
132
|
+
const maxChars = maxTokens * CHARS_PER_TOKEN;
|
|
133
|
+
const userGoals = extractUserGoals(messages);
|
|
134
|
+
const toolCalls = extractToolCalls(messages);
|
|
135
|
+
const filePaths = extractFilePaths(messages);
|
|
136
|
+
const lines = [
|
|
137
|
+
"# Conversation Summary (compacted context)",
|
|
138
|
+
"",
|
|
139
|
+
"## User Requests / Goals",
|
|
140
|
+
];
|
|
141
|
+
if (userGoals.length > 0) {
|
|
142
|
+
for (const goal of userGoals) {
|
|
143
|
+
lines.push(`- ${goal}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
lines.push("- (no explicit user messages in compacted range)");
|
|
148
|
+
}
|
|
149
|
+
lines.push("", "## Tool Calls & Outcomes");
|
|
150
|
+
if (toolCalls.length > 0) {
|
|
151
|
+
for (const tc of toolCalls) {
|
|
152
|
+
lines.push(`- **${tc.name}** ${tc.argsSummary} → ${tc.outcome}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
lines.push("- (no tool calls in compacted range)");
|
|
157
|
+
}
|
|
158
|
+
lines.push("", "## Files Read / Written / Modified");
|
|
159
|
+
if (filePaths.length > 0) {
|
|
160
|
+
for (const fp of filePaths) {
|
|
161
|
+
lines.push(`- \`${fp}\``);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
lines.push("- (no file operations detected)");
|
|
166
|
+
}
|
|
167
|
+
lines.push("", "## Key Decisions");
|
|
168
|
+
// Look for assistant messages that contain decision-like keywords
|
|
169
|
+
const decisions = [];
|
|
170
|
+
for (const msg of messages) {
|
|
171
|
+
if (msg.role !== "assistant")
|
|
172
|
+
continue;
|
|
173
|
+
const text = messageToText(msg).trim();
|
|
174
|
+
if (/decided|chosen|using|selected|approach|strategy|plan/i.test(text) &&
|
|
175
|
+
text.length > 20) {
|
|
176
|
+
decisions.push(text.slice(0, 200) + (text.length > 200 ? "…" : ""));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (decisions.length > 0) {
|
|
180
|
+
for (const d of decisions) {
|
|
181
|
+
lines.push(`- ${d}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
lines.push("- (no explicit decisions recorded)");
|
|
186
|
+
}
|
|
187
|
+
const full = lines.join("\n");
|
|
188
|
+
// Trim to maxChars if necessary
|
|
189
|
+
return full.length > maxChars ? full.slice(0, maxChars) + "\n…(truncated)" : full;
|
|
190
|
+
}
|
|
191
|
+
// ─── ContextCompactor ─────────────────────────────────────────────────────────
|
|
192
|
+
export class ContextCompactor {
|
|
193
|
+
config;
|
|
194
|
+
constructor(config) {
|
|
195
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Estimate the token count for a list of messages using the 4-chars-per-token
|
|
199
|
+
* heuristic.
|
|
200
|
+
*/
|
|
201
|
+
estimateTokens(messages) {
|
|
202
|
+
let totalChars = 0;
|
|
203
|
+
for (const msg of messages) {
|
|
204
|
+
totalChars += messageToText(msg).length;
|
|
205
|
+
// Add a small overhead per message for role + formatting
|
|
206
|
+
totalChars += 10;
|
|
207
|
+
}
|
|
208
|
+
return Math.ceil(totalChars / CHARS_PER_TOKEN);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Compact the message list if it exceeds the compaction threshold.
|
|
212
|
+
*
|
|
213
|
+
* Strategy:
|
|
214
|
+
* 1. Identify the most-recent N turns to preserve verbatim.
|
|
215
|
+
* 2. Summarise all older messages into a single system-role summary message.
|
|
216
|
+
* 3. Return the summary + preserved recent messages.
|
|
217
|
+
*
|
|
218
|
+
* When `config.useLLM` is true and `apiCall` is provided, delegates to
|
|
219
|
+
* `compactWithLLM()` for a richer natural-language summary.
|
|
220
|
+
* Falls back to local heuristic summarisation if the LLM call fails.
|
|
221
|
+
*/
|
|
222
|
+
async compact(messages, apiCall) {
|
|
223
|
+
if (this.config.useLLM && apiCall !== undefined) {
|
|
224
|
+
try {
|
|
225
|
+
return await this.compactWithLLM(messages, apiCall);
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
console.error("[ContextCompactor] LLM compaction failed, falling back to local:", err);
|
|
229
|
+
// Fall through to local compaction below
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return this._compactLocal(messages);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Compact using an injected LLM call for richer summarisation.
|
|
236
|
+
*
|
|
237
|
+
* The `apiCall` function is supplied by the caller so this class remains
|
|
238
|
+
* free of any specific API client dependency.
|
|
239
|
+
*/
|
|
240
|
+
async compactWithLLM(messages, apiCall) {
|
|
241
|
+
const originalTokens = this.estimateTokens(messages);
|
|
242
|
+
if (originalTokens < this.config.compactionThreshold) {
|
|
243
|
+
return {
|
|
244
|
+
messages,
|
|
245
|
+
compacted: false,
|
|
246
|
+
originalTokens,
|
|
247
|
+
compactedTokens: originalTokens,
|
|
248
|
+
turnsCompacted: 0,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
const systemMessages = messages.filter((m) => m.role === "system");
|
|
252
|
+
const conversational = messages.filter((m) => m.role !== "system");
|
|
253
|
+
const turnsToPreserve = this.config.preserveRecentTurns * 2;
|
|
254
|
+
const splitAt = Math.max(0, conversational.length - turnsToPreserve);
|
|
255
|
+
const toCompact = conversational.slice(0, splitAt);
|
|
256
|
+
const toPreserve = conversational.slice(splitAt);
|
|
257
|
+
const turnsCompacted = toCompact.length;
|
|
258
|
+
if (turnsCompacted === 0) {
|
|
259
|
+
return {
|
|
260
|
+
messages,
|
|
261
|
+
compacted: false,
|
|
262
|
+
originalTokens,
|
|
263
|
+
compactedTokens: originalTokens,
|
|
264
|
+
turnsCompacted: 0,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
// Build a transcript of the messages to be compacted
|
|
268
|
+
const transcript = toCompact
|
|
269
|
+
.map((m) => {
|
|
270
|
+
const role = m.role.toUpperCase();
|
|
271
|
+
const text = messageToText(m);
|
|
272
|
+
return `[${role}]: ${text}`;
|
|
273
|
+
})
|
|
274
|
+
.join("\n\n");
|
|
275
|
+
const prompt = [
|
|
276
|
+
"Summarize this conversation concisely. Include:",
|
|
277
|
+
"- Key decisions made",
|
|
278
|
+
"- Files modified and why",
|
|
279
|
+
"- Tool results and outcomes",
|
|
280
|
+
"- Current task status",
|
|
281
|
+
"Keep it under 500 words.",
|
|
282
|
+
"",
|
|
283
|
+
"--- CONVERSATION START ---",
|
|
284
|
+
transcript,
|
|
285
|
+
"--- CONVERSATION END ---",
|
|
286
|
+
].join("\n");
|
|
287
|
+
const llmSummary = await apiCall(prompt);
|
|
288
|
+
const summaryText = `# Conversation Summary (LLM-compacted context)\n\n${llmSummary}`;
|
|
289
|
+
const summaryMessage = {
|
|
290
|
+
role: "system",
|
|
291
|
+
content: summaryText,
|
|
292
|
+
};
|
|
293
|
+
const compactedMessages = [
|
|
294
|
+
...systemMessages,
|
|
295
|
+
summaryMessage,
|
|
296
|
+
...toPreserve,
|
|
297
|
+
];
|
|
298
|
+
const compactedTokens = this.estimateTokens(compactedMessages);
|
|
299
|
+
return {
|
|
300
|
+
messages: compactedMessages,
|
|
301
|
+
compacted: true,
|
|
302
|
+
originalTokens,
|
|
303
|
+
compactedTokens,
|
|
304
|
+
turnsCompacted,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/** Local heuristic compaction (no LLM). */
|
|
308
|
+
_compactLocal(messages) {
|
|
309
|
+
const originalTokens = this.estimateTokens(messages);
|
|
310
|
+
if (originalTokens < this.config.compactionThreshold) {
|
|
311
|
+
return {
|
|
312
|
+
messages,
|
|
313
|
+
compacted: false,
|
|
314
|
+
originalTokens,
|
|
315
|
+
compactedTokens: originalTokens,
|
|
316
|
+
turnsCompacted: 0,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
// Separate system messages (always kept verbatim at the front) from the
|
|
320
|
+
// conversational messages that can be compacted.
|
|
321
|
+
const systemMessages = messages.filter((m) => m.role === "system");
|
|
322
|
+
const conversational = messages.filter((m) => m.role !== "system");
|
|
323
|
+
// A "turn" is a contiguous user+assistant exchange. For simplicity we treat
|
|
324
|
+
// each individual message as one turn unit here; the preserve count is in
|
|
325
|
+
// terms of individual messages (not user+assistant pairs).
|
|
326
|
+
const turnsToPreserve = this.config.preserveRecentTurns * 2; // user + assistant per turn
|
|
327
|
+
const splitAt = Math.max(0, conversational.length - turnsToPreserve);
|
|
328
|
+
const toCompact = conversational.slice(0, splitAt);
|
|
329
|
+
const toPreserve = conversational.slice(splitAt);
|
|
330
|
+
const turnsCompacted = toCompact.length;
|
|
331
|
+
if (turnsCompacted === 0) {
|
|
332
|
+
// Nothing old enough to compact
|
|
333
|
+
return {
|
|
334
|
+
messages,
|
|
335
|
+
compacted: false,
|
|
336
|
+
originalTokens,
|
|
337
|
+
compactedTokens: originalTokens,
|
|
338
|
+
turnsCompacted: 0,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
const summaryText = buildSummary(toCompact, this.config.summaryMaxTokens);
|
|
342
|
+
const summaryMessage = {
|
|
343
|
+
role: "system",
|
|
344
|
+
content: summaryText,
|
|
345
|
+
};
|
|
346
|
+
const compactedMessages = [
|
|
347
|
+
...systemMessages,
|
|
348
|
+
summaryMessage,
|
|
349
|
+
...toPreserve,
|
|
350
|
+
];
|
|
351
|
+
const compactedTokens = this.estimateTokens(compactedMessages);
|
|
352
|
+
return {
|
|
353
|
+
messages: compactedMessages,
|
|
354
|
+
compacted: true,
|
|
355
|
+
originalTokens,
|
|
356
|
+
compactedTokens,
|
|
357
|
+
turnsCompacted,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=context-compactor.js.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation Branching
|
|
3
|
+
*
|
|
4
|
+
* Allows forking a conversation at any turn to explore alternative paths.
|
|
5
|
+
* Branches are persisted to .profclaw/branches/branches.json.
|
|
6
|
+
* The transcript for the parent conversation is read from the existing
|
|
7
|
+
* TranscriptStore (JSONL files at .profclaw/transcripts/).
|
|
8
|
+
*/
|
|
9
|
+
export interface Branch {
|
|
10
|
+
id: string;
|
|
11
|
+
parentId: string;
|
|
12
|
+
forkTurnIndex: number;
|
|
13
|
+
title?: string;
|
|
14
|
+
createdAt: number;
|
|
15
|
+
}
|
|
16
|
+
interface BranchMessage {
|
|
17
|
+
role: string;
|
|
18
|
+
content: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class ConversationBrancher {
|
|
21
|
+
private branches;
|
|
22
|
+
private branchDir;
|
|
23
|
+
private transcriptStore;
|
|
24
|
+
constructor(projectRoot?: string);
|
|
25
|
+
/**
|
|
26
|
+
* Fork a conversation at a specific turn index.
|
|
27
|
+
* The new Branch records which turn we branched from so the caller
|
|
28
|
+
* can replay context up to that point.
|
|
29
|
+
*/
|
|
30
|
+
fork(conversationId: string, turnIndex: number, title?: string): Branch;
|
|
31
|
+
/**
|
|
32
|
+
* List all branches whose parentId matches `conversationId`,
|
|
33
|
+
* sorted newest first.
|
|
34
|
+
*/
|
|
35
|
+
listBranches(conversationId: string): Branch[];
|
|
36
|
+
/**
|
|
37
|
+
* Return the messages from the parent conversation up to (and including)
|
|
38
|
+
* `branch.forkTurnIndex`. Only user/assistant entries are included.
|
|
39
|
+
*
|
|
40
|
+
* "Turn" here means a user+assistant exchange pair, so turn N covers
|
|
41
|
+
* transcript entries 0..2N+1. We expose the raw forkTurnIndex as a
|
|
42
|
+
* transcript entry index for simplicity.
|
|
43
|
+
*/
|
|
44
|
+
getBaseMessages(branch: Branch): BranchMessage[];
|
|
45
|
+
save(): void;
|
|
46
|
+
load(): void;
|
|
47
|
+
private ensureDir;
|
|
48
|
+
private indexPath;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Returns the shared singleton ConversationBrancher instance.
|
|
52
|
+
*/
|
|
53
|
+
export declare function getConversationBrancher(): ConversationBrancher;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=conversation-branch.d.ts.map
|