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,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE Stream Client
|
|
3
|
+
*
|
|
4
|
+
* Connects to the profClaw chat API and streams events.
|
|
5
|
+
* Handles both simple streaming (content deltas) and agentic mode
|
|
6
|
+
* (tool calls, thinking, step progress).
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Exponential backoff reconnection (1s, 2s, 4s, 8s, max 3 retries)
|
|
10
|
+
* - 60-second idle timeout treated as disconnect
|
|
11
|
+
* - `lastEventId` tracking for potential server-side resume
|
|
12
|
+
* - `connection_lost` / `reconnected` synthetic events
|
|
13
|
+
*
|
|
14
|
+
* @package profclaw-interactive (future standalone)
|
|
15
|
+
*/
|
|
16
|
+
import type { ServerConfig, SSEEvent } from './types.js';
|
|
17
|
+
export interface StreamOptions {
|
|
18
|
+
conversationId: string;
|
|
19
|
+
content: string;
|
|
20
|
+
model?: string;
|
|
21
|
+
provider?: string;
|
|
22
|
+
agentic?: boolean;
|
|
23
|
+
showThinking?: boolean;
|
|
24
|
+
effort?: 'low' | 'medium' | 'high';
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
}
|
|
27
|
+
export type StreamEventHandler = (event: SSEEvent) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Send a message and stream the response via SSE.
|
|
30
|
+
* Yields parsed SSE events as they arrive, including synthetic
|
|
31
|
+
* `connection_lost` and `reconnected` events on reconnect attempts.
|
|
32
|
+
*/
|
|
33
|
+
export declare function streamChat(config: ServerConfig, options: StreamOptions): AsyncGenerator<SSEEvent>;
|
|
34
|
+
/**
|
|
35
|
+
* Create a new conversation on the server.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createConversation(config: ServerConfig, options: {
|
|
38
|
+
mode: 'chat' | 'agentic';
|
|
39
|
+
presetId?: string;
|
|
40
|
+
}): Promise<{
|
|
41
|
+
conversationId: string;
|
|
42
|
+
} | {
|
|
43
|
+
error: string;
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Send a non-streaming message (fallback).
|
|
47
|
+
*/
|
|
48
|
+
export declare function sendMessage(config: ServerConfig, conversationId: string, content: string, options?: {
|
|
49
|
+
model?: string;
|
|
50
|
+
tools?: boolean;
|
|
51
|
+
}): Promise<{
|
|
52
|
+
content: string;
|
|
53
|
+
model?: string;
|
|
54
|
+
usage?: Record<string, unknown>;
|
|
55
|
+
toolCalls?: unknown[];
|
|
56
|
+
} | {
|
|
57
|
+
error: string;
|
|
58
|
+
}>;
|
|
59
|
+
//# sourceMappingURL=stream-client.d.ts.map
|
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE Stream Client
|
|
3
|
+
*
|
|
4
|
+
* Connects to the profClaw chat API and streams events.
|
|
5
|
+
* Handles both simple streaming (content deltas) and agentic mode
|
|
6
|
+
* (tool calls, thinking, step progress).
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Exponential backoff reconnection (1s, 2s, 4s, 8s, max 3 retries)
|
|
10
|
+
* - 60-second idle timeout treated as disconnect
|
|
11
|
+
* - `lastEventId` tracking for potential server-side resume
|
|
12
|
+
* - `connection_lost` / `reconnected` synthetic events
|
|
13
|
+
*
|
|
14
|
+
* @package profclaw-interactive (future standalone)
|
|
15
|
+
*/
|
|
16
|
+
// ── Reconnect constants ────────────────────────────────────────────────────────
|
|
17
|
+
const MAX_RETRIES = 3;
|
|
18
|
+
const RETRY_DELAYS_MS = [1_000, 2_000, 4_000, 8_000];
|
|
19
|
+
const IDLE_TIMEOUT_MS = 60_000;
|
|
20
|
+
// ── Helpers ────────────────────────────────────────────────────────────────────
|
|
21
|
+
function sleep(ms) {
|
|
22
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Parse a raw SSE data line into an SSEEvent, returning null when the line
|
|
26
|
+
* should be skipped.
|
|
27
|
+
*/
|
|
28
|
+
function parseSseLine(line, rateLimitHeaders) {
|
|
29
|
+
const trimmed = line.trim();
|
|
30
|
+
if (!trimmed || trimmed.startsWith(':'))
|
|
31
|
+
return null;
|
|
32
|
+
if (!trimmed.startsWith('data: '))
|
|
33
|
+
return null;
|
|
34
|
+
const jsonStr = trimmed.slice(6);
|
|
35
|
+
let parsed;
|
|
36
|
+
try {
|
|
37
|
+
parsed = JSON.parse(jsonStr);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
// Handle simple streaming format (content deltas)
|
|
43
|
+
if ('content' in parsed && !('type' in parsed)) {
|
|
44
|
+
return {
|
|
45
|
+
type: 'content_delta',
|
|
46
|
+
data: { content: parsed.content },
|
|
47
|
+
timestamp: Date.now(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// Handle done event
|
|
51
|
+
if ('done' in parsed && parsed.done === true) {
|
|
52
|
+
return {
|
|
53
|
+
type: 'complete',
|
|
54
|
+
data: {
|
|
55
|
+
usage: parsed.usage,
|
|
56
|
+
finishReason: parsed.finishReason,
|
|
57
|
+
rateLimitHeaders: Object.keys(rateLimitHeaders).length > 0 ? rateLimitHeaders : undefined,
|
|
58
|
+
},
|
|
59
|
+
timestamp: Date.now(),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// Handle error event
|
|
63
|
+
if ('error' in parsed && !('type' in parsed)) {
|
|
64
|
+
return {
|
|
65
|
+
type: 'error',
|
|
66
|
+
data: { message: parsed.error },
|
|
67
|
+
timestamp: Date.now(),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// Handle typed events (agentic mode)
|
|
71
|
+
if ('type' in parsed) {
|
|
72
|
+
return {
|
|
73
|
+
type: parsed.type,
|
|
74
|
+
data: parsed.data || parsed,
|
|
75
|
+
timestamp: parsed.timestamp || Date.now(),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Read the response body and yield SSEEvents.
|
|
82
|
+
* Returns `false` when the stream ended normally with a `complete` or final
|
|
83
|
+
* event, or `true` when the connection dropped before the stream completed.
|
|
84
|
+
*/
|
|
85
|
+
async function* readSseBody(body, rateLimitHeaders, lastEventIdRef, idleTimeoutMs, signal) {
|
|
86
|
+
const reader = body.getReader();
|
|
87
|
+
const decoder = new TextDecoder();
|
|
88
|
+
let buffer = '';
|
|
89
|
+
let streamCompleted = false;
|
|
90
|
+
let idleTimer = null;
|
|
91
|
+
const resetIdle = (onTimeout) => {
|
|
92
|
+
if (idleTimer !== null)
|
|
93
|
+
clearTimeout(idleTimer);
|
|
94
|
+
idleTimer = setTimeout(onTimeout, idleTimeoutMs);
|
|
95
|
+
};
|
|
96
|
+
// We use a flag + error to break out when the idle timer fires.
|
|
97
|
+
let idleTimedOut = false;
|
|
98
|
+
try {
|
|
99
|
+
// Start the idle timer immediately
|
|
100
|
+
resetIdle(() => { idleTimedOut = true; });
|
|
101
|
+
while (true) {
|
|
102
|
+
if (signal?.aborted)
|
|
103
|
+
break;
|
|
104
|
+
if (idleTimedOut)
|
|
105
|
+
break;
|
|
106
|
+
let done;
|
|
107
|
+
let value;
|
|
108
|
+
try {
|
|
109
|
+
({ done, value } = await reader.read());
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Network error — connection dropped
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
if (done)
|
|
116
|
+
break;
|
|
117
|
+
// Activity received — reset idle timer
|
|
118
|
+
resetIdle(() => { idleTimedOut = true; });
|
|
119
|
+
buffer += decoder.decode(value, { stream: true });
|
|
120
|
+
// Parse SSE lines
|
|
121
|
+
const lines = buffer.split('\n');
|
|
122
|
+
buffer = lines.pop() ?? '';
|
|
123
|
+
// Track SSE id: fields for potential resume
|
|
124
|
+
for (const line of lines) {
|
|
125
|
+
const trimmedLine = line.trim();
|
|
126
|
+
if (trimmedLine.startsWith('id: ')) {
|
|
127
|
+
lastEventIdRef.value = trimmedLine.slice(4).trim();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
for (const line of lines) {
|
|
131
|
+
const event = parseSseLine(line, rateLimitHeaders);
|
|
132
|
+
if (event === null)
|
|
133
|
+
continue;
|
|
134
|
+
if (event.type === 'complete') {
|
|
135
|
+
streamCompleted = true;
|
|
136
|
+
}
|
|
137
|
+
yield event;
|
|
138
|
+
}
|
|
139
|
+
if (streamCompleted)
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
if (idleTimer !== null)
|
|
145
|
+
clearTimeout(idleTimer);
|
|
146
|
+
reader.releaseLock();
|
|
147
|
+
}
|
|
148
|
+
if (!streamCompleted) {
|
|
149
|
+
yield { __incomplete: true };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Send a message and stream the response via SSE.
|
|
154
|
+
* Yields parsed SSE events as they arrive, including synthetic
|
|
155
|
+
* `connection_lost` and `reconnected` events on reconnect attempts.
|
|
156
|
+
*/
|
|
157
|
+
export async function* streamChat(config, options) {
|
|
158
|
+
// Smart routing: simple messages use fast /completions, complex ones use agentic
|
|
159
|
+
const needsTools = /\b(search|find|build|create|deploy|fix|write|read|run|exec|check|test|git|install|fetch)\b|look up|what is|tell me about/i.test(options.content);
|
|
160
|
+
const isSimple = options.content.length < 30 && !needsTools;
|
|
161
|
+
// For simple messages, use fast streaming completions (no tools = ~100 tokens vs 75K)
|
|
162
|
+
if (isSimple) {
|
|
163
|
+
yield* streamSimpleChat(config, options);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Complex messages: use the full agentic endpoint with reconnect
|
|
167
|
+
yield* streamAgenticChatWithReconnect(config, options);
|
|
168
|
+
}
|
|
169
|
+
// ── Simple (completions) endpoint — no reconnect, straightforward ──────────────
|
|
170
|
+
async function* streamSimpleChat(config, options) {
|
|
171
|
+
const endpoint = `/api/chat/completions`;
|
|
172
|
+
const body = {
|
|
173
|
+
messages: [{ role: 'user', content: options.content }],
|
|
174
|
+
model: options.model,
|
|
175
|
+
stream: true,
|
|
176
|
+
conversationId: options.conversationId,
|
|
177
|
+
};
|
|
178
|
+
const headers = {
|
|
179
|
+
'Content-Type': 'application/json',
|
|
180
|
+
'Accept': 'text/event-stream',
|
|
181
|
+
};
|
|
182
|
+
if (config.apiToken)
|
|
183
|
+
headers['Authorization'] = `Bearer ${config.apiToken}`;
|
|
184
|
+
let response;
|
|
185
|
+
try {
|
|
186
|
+
response = await fetch(`${config.baseUrl}${endpoint}`, {
|
|
187
|
+
method: 'POST',
|
|
188
|
+
headers,
|
|
189
|
+
body: JSON.stringify(body),
|
|
190
|
+
signal: options.signal,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// Fallback to agentic on connect error
|
|
195
|
+
yield* streamAgenticChatWithReconnect(config, options);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (!response.ok || !response.body) {
|
|
199
|
+
// Fallback to agentic on error
|
|
200
|
+
yield* streamAgenticChatWithReconnect(config, options);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const reader = response.body.getReader();
|
|
204
|
+
const decoder = new TextDecoder();
|
|
205
|
+
let buffer = '';
|
|
206
|
+
try {
|
|
207
|
+
while (true) {
|
|
208
|
+
const { done, value } = await reader.read();
|
|
209
|
+
if (done)
|
|
210
|
+
break;
|
|
211
|
+
buffer += decoder.decode(value, { stream: true });
|
|
212
|
+
const lines = buffer.split('\n');
|
|
213
|
+
buffer = lines.pop() ?? '';
|
|
214
|
+
for (const line of lines) {
|
|
215
|
+
const trimmed = line.trim();
|
|
216
|
+
if (!trimmed || !trimmed.startsWith('data: '))
|
|
217
|
+
continue;
|
|
218
|
+
try {
|
|
219
|
+
const parsed = JSON.parse(trimmed.slice(6));
|
|
220
|
+
if (parsed.content) {
|
|
221
|
+
yield { type: 'content_delta', data: { content: parsed.content }, timestamp: Date.now() };
|
|
222
|
+
}
|
|
223
|
+
if (parsed.done) {
|
|
224
|
+
yield { type: 'complete', data: { usage: parsed.usage, finishReason: parsed.finishReason }, timestamp: Date.now() };
|
|
225
|
+
}
|
|
226
|
+
if (parsed.error) {
|
|
227
|
+
yield { type: 'error', data: { message: parsed.error }, timestamp: Date.now() };
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch { /* skip */ }
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
finally {
|
|
235
|
+
reader.releaseLock();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// ── Agentic endpoint with exponential-backoff reconnect ────────────────────────
|
|
239
|
+
async function* streamAgenticChatWithReconnect(config, options) {
|
|
240
|
+
const lastEventIdRef = { value: null };
|
|
241
|
+
const attempt = 0;
|
|
242
|
+
while (true) {
|
|
243
|
+
// On the first attempt the generator starts fresh.
|
|
244
|
+
// On subsequent attempts we have already emitted `connection_lost`.
|
|
245
|
+
yield* attemptAgenticStream(config, options, lastEventIdRef, attempt);
|
|
246
|
+
// If we get here the inner generator returned without a complete event —
|
|
247
|
+
// which means the stream ended prematurely (connection dropped or idle
|
|
248
|
+
// timeout). Check if we should retry.
|
|
249
|
+
// We detect incompleteness via the sentinel yielded by readSseBody —
|
|
250
|
+
// but the inner generator consumes it. So we rely on the fact that if
|
|
251
|
+
// the inner generator returns normally (not via `return`) the stream was
|
|
252
|
+
// incomplete; if it yielded a `complete` event it would have returned
|
|
253
|
+
// after that.
|
|
254
|
+
//
|
|
255
|
+
// The logic is handled by the sentinel check inside attemptAgenticStream
|
|
256
|
+
// which sets `streamCompletedNormally`. We use a shared ref below.
|
|
257
|
+
// NOTE: Because generator consumers cannot observe generator return
|
|
258
|
+
// values directly, we use a shared mutable object to communicate whether
|
|
259
|
+
// the stream completed normally.
|
|
260
|
+
break; // replaced by the implementation in attemptAgenticStream below
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// We use a wrapper that communicates completion state via ref.
|
|
264
|
+
async function* attemptAgenticStream(config, options, lastEventIdRef, _initialAttempt) {
|
|
265
|
+
let attempt = 0;
|
|
266
|
+
while (true) {
|
|
267
|
+
const result = await runAgenticAttempt(config, options, lastEventIdRef, attempt);
|
|
268
|
+
for (const event of result.events) {
|
|
269
|
+
yield event;
|
|
270
|
+
}
|
|
271
|
+
if (result.completed || options.signal?.aborted) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
// Stream dropped before completion
|
|
275
|
+
attempt++;
|
|
276
|
+
if (attempt > MAX_RETRIES) {
|
|
277
|
+
yield {
|
|
278
|
+
type: 'error',
|
|
279
|
+
data: { message: `Connection lost after ${MAX_RETRIES} retries` },
|
|
280
|
+
timestamp: Date.now(),
|
|
281
|
+
};
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
yield {
|
|
285
|
+
type: 'connection_lost',
|
|
286
|
+
data: {
|
|
287
|
+
attempt,
|
|
288
|
+
maxRetries: MAX_RETRIES,
|
|
289
|
+
lastEventId: lastEventIdRef.value,
|
|
290
|
+
},
|
|
291
|
+
timestamp: Date.now(),
|
|
292
|
+
};
|
|
293
|
+
const delayMs = RETRY_DELAYS_MS[attempt - 1] ?? RETRY_DELAYS_MS[RETRY_DELAYS_MS.length - 1];
|
|
294
|
+
await sleep(delayMs);
|
|
295
|
+
if (options.signal?.aborted)
|
|
296
|
+
return;
|
|
297
|
+
yield {
|
|
298
|
+
type: 'reconnected',
|
|
299
|
+
data: { attempt, lastEventId: lastEventIdRef.value },
|
|
300
|
+
timestamp: Date.now(),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
async function runAgenticAttempt(config, options, lastEventIdRef, attempt) {
|
|
305
|
+
const endpoint = `/api/chat/conversations/${options.conversationId}/messages/agentic`;
|
|
306
|
+
const effort = options.effort ?? 'medium';
|
|
307
|
+
const body = {
|
|
308
|
+
content: options.content,
|
|
309
|
+
model: options.model,
|
|
310
|
+
provider: options.provider,
|
|
311
|
+
showThinking: options.showThinking ?? false,
|
|
312
|
+
effort,
|
|
313
|
+
};
|
|
314
|
+
const headers = {
|
|
315
|
+
'Content-Type': 'application/json',
|
|
316
|
+
'Accept': 'text/event-stream',
|
|
317
|
+
};
|
|
318
|
+
if (config.apiToken) {
|
|
319
|
+
headers['Authorization'] = `Bearer ${config.apiToken}`;
|
|
320
|
+
}
|
|
321
|
+
// On reconnect attempts, include Last-Event-ID header if we have one
|
|
322
|
+
if (attempt > 0 && lastEventIdRef.value !== null) {
|
|
323
|
+
headers['Last-Event-ID'] = lastEventIdRef.value;
|
|
324
|
+
}
|
|
325
|
+
// Capture rate limit headers from the initial response for monitoring
|
|
326
|
+
const rateLimitHeaders = {};
|
|
327
|
+
const rateLimitHeaderNames = [
|
|
328
|
+
'x-ratelimit-limit-requests',
|
|
329
|
+
'x-ratelimit-remaining-requests',
|
|
330
|
+
'x-ratelimit-limit-tokens',
|
|
331
|
+
'x-ratelimit-remaining-tokens',
|
|
332
|
+
'x-ratelimit-reset-requests',
|
|
333
|
+
'x-ratelimit-reset-tokens',
|
|
334
|
+
];
|
|
335
|
+
let response;
|
|
336
|
+
try {
|
|
337
|
+
response = await fetch(`${config.baseUrl}${endpoint}`, {
|
|
338
|
+
method: 'POST',
|
|
339
|
+
headers,
|
|
340
|
+
body: JSON.stringify(body),
|
|
341
|
+
signal: options.signal,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
catch (err) {
|
|
345
|
+
if (options.signal?.aborted) {
|
|
346
|
+
return { events: [], completed: true };
|
|
347
|
+
}
|
|
348
|
+
const msg = err instanceof Error ? err.message : 'Connection failed';
|
|
349
|
+
return {
|
|
350
|
+
events: [{
|
|
351
|
+
type: 'error',
|
|
352
|
+
data: { message: msg },
|
|
353
|
+
timestamp: Date.now(),
|
|
354
|
+
}],
|
|
355
|
+
completed: false,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
for (const name of rateLimitHeaderNames) {
|
|
359
|
+
const value = response.headers.get(name);
|
|
360
|
+
if (value !== null)
|
|
361
|
+
rateLimitHeaders[name] = value;
|
|
362
|
+
}
|
|
363
|
+
if (!response.ok) {
|
|
364
|
+
const text = await response.text().catch(() => '');
|
|
365
|
+
let errorMsg = `HTTP ${response.status}`;
|
|
366
|
+
if (text.startsWith('<!DOCTYPE') || text.startsWith('<html')) {
|
|
367
|
+
errorMsg = `API route not found (got HTML). Is the server running at ${config.baseUrl}?`;
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
try {
|
|
371
|
+
const parsed = JSON.parse(text);
|
|
372
|
+
errorMsg = parsed.error || parsed.message || errorMsg;
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
if (text)
|
|
376
|
+
errorMsg = text.slice(0, 200);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
// 4xx errors are terminal — no point retrying
|
|
380
|
+
const isTerminal = response.status >= 400 && response.status < 500;
|
|
381
|
+
return {
|
|
382
|
+
events: [{
|
|
383
|
+
type: 'error',
|
|
384
|
+
data: { message: errorMsg, statusCode: response.status, rateLimitHeaders },
|
|
385
|
+
timestamp: Date.now(),
|
|
386
|
+
}],
|
|
387
|
+
completed: isTerminal,
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
if (!response.body) {
|
|
391
|
+
return {
|
|
392
|
+
events: [{
|
|
393
|
+
type: 'error',
|
|
394
|
+
data: { message: 'No response body (streaming not supported?)' },
|
|
395
|
+
timestamp: Date.now(),
|
|
396
|
+
}],
|
|
397
|
+
completed: false,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
const collected = [];
|
|
401
|
+
let completed = false;
|
|
402
|
+
for await (const item of readSseBody(response.body, rateLimitHeaders, lastEventIdRef, IDLE_TIMEOUT_MS, options.signal)) {
|
|
403
|
+
if ('__incomplete' in item) {
|
|
404
|
+
// Sentinel — stream dropped before complete
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
const event = item;
|
|
408
|
+
collected.push(event);
|
|
409
|
+
if (event.type === 'complete' || event.type === 'done') {
|
|
410
|
+
completed = true;
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return { events: collected, completed };
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Create a new conversation on the server.
|
|
418
|
+
*/
|
|
419
|
+
export async function createConversation(config, options) {
|
|
420
|
+
const headers = {
|
|
421
|
+
'Content-Type': 'application/json',
|
|
422
|
+
};
|
|
423
|
+
if (config.apiToken) {
|
|
424
|
+
headers['Authorization'] = `Bearer ${config.apiToken}`;
|
|
425
|
+
}
|
|
426
|
+
try {
|
|
427
|
+
const response = await fetch(`${config.baseUrl}/api/chat/conversations`, {
|
|
428
|
+
method: 'POST',
|
|
429
|
+
headers,
|
|
430
|
+
body: JSON.stringify({
|
|
431
|
+
presetId: options.presetId || (options.mode === 'agentic' ? 'agentic' : 'profclaw-assistant'),
|
|
432
|
+
}),
|
|
433
|
+
});
|
|
434
|
+
const text = await response.text();
|
|
435
|
+
// Check for HTML response (SPA fallback)
|
|
436
|
+
if (text.startsWith('<!DOCTYPE') || text.startsWith('<html')) {
|
|
437
|
+
return { error: `API route not available (got HTML). Check that profClaw server is running at ${config.baseUrl} with: profclaw serve` };
|
|
438
|
+
}
|
|
439
|
+
if (!response.ok) {
|
|
440
|
+
try {
|
|
441
|
+
const parsed = JSON.parse(text);
|
|
442
|
+
return { error: `Failed to create conversation: ${parsed.error || `HTTP ${response.status}`}` };
|
|
443
|
+
}
|
|
444
|
+
catch {
|
|
445
|
+
return { error: `Failed to create conversation: HTTP ${response.status}` };
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
try {
|
|
449
|
+
const data = JSON.parse(text);
|
|
450
|
+
if (!data.conversation?.id) {
|
|
451
|
+
return { error: 'Invalid response from server - no conversation ID returned' };
|
|
452
|
+
}
|
|
453
|
+
return { conversationId: data.conversation.id };
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
return { error: `Invalid JSON response from server: ${text.slice(0, 100)}` };
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
const msg = error instanceof Error ? error.message : 'Connection failed';
|
|
461
|
+
if (msg.includes('ECONNREFUSED') || msg.includes('fetch failed')) {
|
|
462
|
+
return { error: `Cannot connect to profClaw server at ${config.baseUrl}. Is it running? Try: profclaw serve` };
|
|
463
|
+
}
|
|
464
|
+
return { error: msg };
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Send a non-streaming message (fallback).
|
|
469
|
+
*/
|
|
470
|
+
export async function sendMessage(config, conversationId, content, options) {
|
|
471
|
+
const headers = {
|
|
472
|
+
'Content-Type': 'application/json',
|
|
473
|
+
};
|
|
474
|
+
if (config.apiToken) {
|
|
475
|
+
headers['Authorization'] = `Bearer ${config.apiToken}`;
|
|
476
|
+
}
|
|
477
|
+
const endpoint = options?.tools
|
|
478
|
+
? `/api/chat/conversations/${conversationId}/messages/with-tools`
|
|
479
|
+
: `/api/chat/conversations/${conversationId}/messages`;
|
|
480
|
+
try {
|
|
481
|
+
const response = await fetch(`${config.baseUrl}${endpoint}`, {
|
|
482
|
+
method: 'POST',
|
|
483
|
+
headers,
|
|
484
|
+
body: JSON.stringify({
|
|
485
|
+
content,
|
|
486
|
+
model: options?.model,
|
|
487
|
+
enableTools: options?.tools,
|
|
488
|
+
}),
|
|
489
|
+
});
|
|
490
|
+
if (!response.ok) {
|
|
491
|
+
return { error: `HTTP ${response.status}` };
|
|
492
|
+
}
|
|
493
|
+
const data = await response.json();
|
|
494
|
+
const assistantMessage = data.assistantMessage;
|
|
495
|
+
return {
|
|
496
|
+
content: assistantMessage?.content || data.content || '',
|
|
497
|
+
model: assistantMessage?.model || data.model,
|
|
498
|
+
usage: data.usage,
|
|
499
|
+
toolCalls: data.toolCalls,
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
catch (error) {
|
|
503
|
+
return { error: error instanceof Error ? error.message : 'Request failed' };
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
//# sourceMappingURL=stream-client.js.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive CLI Types
|
|
3
|
+
*
|
|
4
|
+
* Self-contained type definitions for the interactive REPL.
|
|
5
|
+
* This module is designed to be extractable as a standalone package.
|
|
6
|
+
*
|
|
7
|
+
* @package profclaw-interactive (future standalone)
|
|
8
|
+
*/
|
|
9
|
+
export interface ServerConfig {
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
apiToken?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface Session {
|
|
14
|
+
conversationId: string;
|
|
15
|
+
mode: 'chat' | 'agentic';
|
|
16
|
+
model?: string;
|
|
17
|
+
provider?: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
totalTokens: number;
|
|
20
|
+
totalCost: number;
|
|
21
|
+
messageCount: number;
|
|
22
|
+
createdAt: Date;
|
|
23
|
+
}
|
|
24
|
+
export interface ChatMessage {
|
|
25
|
+
role: 'user' | 'assistant' | 'system';
|
|
26
|
+
content: string;
|
|
27
|
+
model?: string;
|
|
28
|
+
provider?: string;
|
|
29
|
+
toolCalls?: ToolCallInfo[];
|
|
30
|
+
usage?: TokenUsage;
|
|
31
|
+
durationMs?: number;
|
|
32
|
+
timestamp: Date;
|
|
33
|
+
}
|
|
34
|
+
export interface ToolCallInfo {
|
|
35
|
+
id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
arguments: Record<string, unknown>;
|
|
38
|
+
result?: unknown;
|
|
39
|
+
status: 'pending' | 'running' | 'success' | 'error';
|
|
40
|
+
durationMs?: number;
|
|
41
|
+
}
|
|
42
|
+
export interface TokenUsage {
|
|
43
|
+
promptTokens: number;
|
|
44
|
+
completionTokens: number;
|
|
45
|
+
totalTokens: number;
|
|
46
|
+
cost?: number;
|
|
47
|
+
}
|
|
48
|
+
export type SSEEventType = 'user_message' | 'session_start' | 'session:start' | 'thinking_start' | 'thinking:start' | 'thinking_update' | 'thinking:update' | 'thinking_end' | 'thinking:end' | 'content_delta' | 'step_start' | 'step:start' | 'step_complete' | 'step:complete' | 'tool_call' | 'tool:call' | 'tool_result' | 'tool:result' | 'summary' | 'complete' | 'error' | 'fallback' | 'message_saved' | string;
|
|
49
|
+
export interface SSEEvent {
|
|
50
|
+
type: SSEEventType;
|
|
51
|
+
data: Record<string, unknown>;
|
|
52
|
+
timestamp: number;
|
|
53
|
+
}
|
|
54
|
+
export interface SlashCommand {
|
|
55
|
+
name: string;
|
|
56
|
+
aliases: string[];
|
|
57
|
+
description: string;
|
|
58
|
+
args?: string;
|
|
59
|
+
handler: (args: string[], state: REPLState) => Promise<void> | void;
|
|
60
|
+
}
|
|
61
|
+
export interface REPLState {
|
|
62
|
+
session: Session | null;
|
|
63
|
+
model?: string;
|
|
64
|
+
provider?: string;
|
|
65
|
+
agenticMode: boolean;
|
|
66
|
+
showThinking: boolean;
|
|
67
|
+
showTools: boolean;
|
|
68
|
+
showUsage: boolean;
|
|
69
|
+
effort: 'low' | 'medium' | 'high';
|
|
70
|
+
isStreaming: boolean;
|
|
71
|
+
streamStartTime?: number;
|
|
72
|
+
/** Total tokens used this REPL session */
|
|
73
|
+
sessionTokens: number;
|
|
74
|
+
sessionCost: number;
|
|
75
|
+
messageCount: number;
|
|
76
|
+
/** Server base URL for API calls */
|
|
77
|
+
serverUrl: string;
|
|
78
|
+
/** Last response model used (for /retry with different model) */
|
|
79
|
+
lastModel?: string;
|
|
80
|
+
/** Last response cached for comparison */
|
|
81
|
+
lastResponseCache?: {
|
|
82
|
+
content: string;
|
|
83
|
+
model: string;
|
|
84
|
+
durationMs: number;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export interface InteractiveOptions {
|
|
88
|
+
server: ServerConfig;
|
|
89
|
+
model?: string;
|
|
90
|
+
provider?: string;
|
|
91
|
+
sessionId?: string;
|
|
92
|
+
agentic?: boolean;
|
|
93
|
+
showThinking?: boolean;
|
|
94
|
+
effort?: 'low' | 'medium' | 'high';
|
|
95
|
+
}
|
|
96
|
+
export interface Renderer {
|
|
97
|
+
userMessage(content: string): void;
|
|
98
|
+
assistantStart(model?: string): void;
|
|
99
|
+
assistantDelta(chunk: string): void;
|
|
100
|
+
assistantEnd(): void;
|
|
101
|
+
thinkingStart(): void;
|
|
102
|
+
thinkingDelta(chunk: string): void;
|
|
103
|
+
thinkingEnd(): void;
|
|
104
|
+
toolCall(name: string, args: Record<string, unknown>): void;
|
|
105
|
+
toolResult(name: string, result: unknown, success: boolean, durationMs?: number): void;
|
|
106
|
+
usage(usage: TokenUsage, durationMs?: number): void;
|
|
107
|
+
error(message: string): void;
|
|
108
|
+
info(message: string): void;
|
|
109
|
+
success(message: string): void;
|
|
110
|
+
warn(message: string): void;
|
|
111
|
+
divider(): void;
|
|
112
|
+
clear(): void;
|
|
113
|
+
statusLine(text: string): void;
|
|
114
|
+
sessionFooter(state: {
|
|
115
|
+
sessionTokens: number;
|
|
116
|
+
sessionCost: number;
|
|
117
|
+
messageCount: number;
|
|
118
|
+
model?: string;
|
|
119
|
+
}): void;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive CLI Types
|
|
3
|
+
*
|
|
4
|
+
* Self-contained type definitions for the interactive REPL.
|
|
5
|
+
* This module is designed to be extractable as a standalone package.
|
|
6
|
+
*
|
|
7
|
+
* @package profclaw-interactive (future standalone)
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=types.js.map
|