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,555 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Renderer - Polished CLI Output
|
|
3
|
+
*
|
|
4
|
+
* Design inspired by Claude Code, OpenClaw, Charm.sh, and clig.dev:
|
|
5
|
+
*
|
|
6
|
+
* - Response text indented 2 spaces for visual separation from prompt
|
|
7
|
+
* - Tool calls framed with thin Unicode box-drawing lines
|
|
8
|
+
* - Markdown rendered inline (bold, code, lists, headings, quotes)
|
|
9
|
+
* - Streaming markdown: lines formatted as they complete
|
|
10
|
+
* - Syntax highlighting for common languages in code blocks
|
|
11
|
+
* - Word-wrap respects terminal width
|
|
12
|
+
* - Color used intentionally: cyan for links, gold for code, dim for chrome
|
|
13
|
+
* - Progress within 100ms (spinner starts immediately)
|
|
14
|
+
* - Errors are actionable, not cryptic
|
|
15
|
+
* - Respects NO_COLOR env var
|
|
16
|
+
* - Cost/time shown only when meaningful
|
|
17
|
+
*
|
|
18
|
+
* @package profclaw-interactive (future standalone)
|
|
19
|
+
*/
|
|
20
|
+
import chalk from 'chalk';
|
|
21
|
+
// Unicode box-drawing and symbols
|
|
22
|
+
const H_LINE = '\u2500'; // -
|
|
23
|
+
const V_LINE = '\u2502'; // |
|
|
24
|
+
const T_LEFT = '\u251c'; // |-
|
|
25
|
+
const B_LEFT = '\u2514'; // |_
|
|
26
|
+
const DOT = '\u00b7'; // .
|
|
27
|
+
const ARROW = '\u25b8'; // >
|
|
28
|
+
const CHECK = '\u2713'; // v
|
|
29
|
+
const CROSS = '\u2717'; // x
|
|
30
|
+
const CIRCLE = '\u25cf'; // o
|
|
31
|
+
const GEAR = '\u2699'; // gear
|
|
32
|
+
const ELLIP = '\u2026'; // ...
|
|
33
|
+
const LINK_ICON = '\u2197'; // arrow NE (link indicator)
|
|
34
|
+
// Respect NO_COLOR (clig.dev recommendation)
|
|
35
|
+
const noColor = !!process.env.NO_COLOR;
|
|
36
|
+
// Get terminal width
|
|
37
|
+
function getWidth() {
|
|
38
|
+
return process.stdout.columns || 80;
|
|
39
|
+
}
|
|
40
|
+
// Strip ANSI escape sequences for measuring visible length
|
|
41
|
+
function stripAnsi(str) {
|
|
42
|
+
return str.replace(/\x1b\[[0-9;]*m/g, '');
|
|
43
|
+
}
|
|
44
|
+
// Themed colors (OpenClaw-inspired palette, dark mode focused)
|
|
45
|
+
const theme = {
|
|
46
|
+
gold: noColor ? (s) => s : chalk.hex('#F6C453'),
|
|
47
|
+
mint: noColor ? (s) => s : chalk.hex('#7DD3A5'),
|
|
48
|
+
coral: noColor ? (s) => s : chalk.hex('#F97066'),
|
|
49
|
+
cream: noColor ? (s) => s : chalk.hex('#E8E3D5'),
|
|
50
|
+
code: noColor ? (s) => s : chalk.hex('#F0C987'),
|
|
51
|
+
link: noColor ? (s) => s : chalk.hex('#8CC8FF'),
|
|
52
|
+
border: noColor ? (s) => s : chalk.hex('#3C414B'),
|
|
53
|
+
dim: noColor ? (s) => s : chalk.dim,
|
|
54
|
+
bold: noColor ? (s) => s : chalk.bold,
|
|
55
|
+
italic: noColor ? (s) => s : chalk.italic,
|
|
56
|
+
// Syntax highlighting colors
|
|
57
|
+
keyword: noColor ? (s) => s : chalk.hex('#C792EA'),
|
|
58
|
+
string: noColor ? (s) => s : chalk.hex('#C3E88D'),
|
|
59
|
+
number: noColor ? (s) => s : chalk.hex('#F78C6C'),
|
|
60
|
+
comment: noColor ? (s) => s : chalk.hex('#546E7A'),
|
|
61
|
+
func: noColor ? (s) => s : chalk.hex('#82AAFF'),
|
|
62
|
+
type: noColor ? (s) => s : chalk.hex('#FFCB6B'),
|
|
63
|
+
};
|
|
64
|
+
// Word-wrap a single visible line at terminal width
|
|
65
|
+
function wrapText(text, indent) {
|
|
66
|
+
const maxWidth = getWidth() - indent - 2; // 2 for safety margin
|
|
67
|
+
if (maxWidth <= 20)
|
|
68
|
+
return text; // Don't wrap on tiny terminals
|
|
69
|
+
const visibleLen = stripAnsi(text).length;
|
|
70
|
+
if (visibleLen <= maxWidth)
|
|
71
|
+
return text;
|
|
72
|
+
// Simple word-boundary wrap for plain text
|
|
73
|
+
const words = text.split(/(\s+)/);
|
|
74
|
+
const lines = [];
|
|
75
|
+
let currentLine = '';
|
|
76
|
+
let currentLen = 0;
|
|
77
|
+
for (const word of words) {
|
|
78
|
+
const wordLen = stripAnsi(word).length;
|
|
79
|
+
if (currentLen + wordLen > maxWidth && currentLine.length > 0) {
|
|
80
|
+
lines.push(currentLine);
|
|
81
|
+
currentLine = word.trimStart();
|
|
82
|
+
currentLen = stripAnsi(currentLine).length;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
currentLine += word;
|
|
86
|
+
currentLen += wordLen;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (currentLine)
|
|
90
|
+
lines.push(currentLine);
|
|
91
|
+
const pad = ' '.repeat(indent);
|
|
92
|
+
return lines.join(`\n${pad}`);
|
|
93
|
+
}
|
|
94
|
+
// Draw separator lines
|
|
95
|
+
function separator(label) {
|
|
96
|
+
const w = Math.min(getWidth() - 4, 68);
|
|
97
|
+
const line = theme.border(H_LINE.repeat(w));
|
|
98
|
+
if (!label)
|
|
99
|
+
return ` ${line}`;
|
|
100
|
+
const padded = ` ${label} `;
|
|
101
|
+
const plainLen = stripAnsi(padded).length;
|
|
102
|
+
const side = Math.max(2, Math.floor((w - plainLen) / 2));
|
|
103
|
+
const right = Math.max(2, w - side - plainLen);
|
|
104
|
+
return ` ${theme.border(H_LINE.repeat(side))}${padded}${theme.border(H_LINE.repeat(right))}`;
|
|
105
|
+
}
|
|
106
|
+
// Syntax highlighting for code blocks (built-in, no external deps)
|
|
107
|
+
const JS_KEYWORDS = /\b(const|let|var|function|async|await|return|if|else|for|while|do|switch|case|break|continue|try|catch|finally|throw|new|delete|typeof|instanceof|import|export|from|default|class|extends|super|this|yield|of|in|static|get|set|enum|interface|type|implements|declare|abstract|readonly|as|is|keyof|infer|satisfies)\b/g;
|
|
108
|
+
const PY_KEYWORDS = /\b(def|class|if|elif|else|for|while|try|except|finally|with|as|import|from|return|yield|raise|pass|break|continue|and|or|not|in|is|lambda|global|nonlocal|True|False|None|async|await|self)\b/g;
|
|
109
|
+
const COMMON_TYPES = /\b(string|number|boolean|void|null|undefined|any|never|unknown|object|Array|Map|Set|Promise|Record|Partial|Required|Readonly|Pick|Omit|int|float|str|bool|list|dict|tuple)\b/g;
|
|
110
|
+
export function highlightCode(line, lang) {
|
|
111
|
+
if (noColor)
|
|
112
|
+
return line;
|
|
113
|
+
let result = line;
|
|
114
|
+
// Comments (single-line)
|
|
115
|
+
const commentMatch = result.match(/^(\s*)(\/\/.*|#.*)$/);
|
|
116
|
+
if (commentMatch) {
|
|
117
|
+
return commentMatch[1] + theme.comment(commentMatch[2]);
|
|
118
|
+
}
|
|
119
|
+
// Strings (simple - single/double/backtick quoted)
|
|
120
|
+
result = result.replace(/(["'`])(?:(?!\1|\\).|\\.)*?\1/g, (m) => theme.string(m));
|
|
121
|
+
// Numbers
|
|
122
|
+
result = result.replace(/\b(\d+\.?\d*)\b/g, (m) => theme.number(m));
|
|
123
|
+
// Keywords based on language
|
|
124
|
+
const isPython = lang === 'python' || lang === 'py';
|
|
125
|
+
const keywordRe = isPython ? PY_KEYWORDS : JS_KEYWORDS;
|
|
126
|
+
result = result.replace(keywordRe, (m) => theme.keyword(m));
|
|
127
|
+
// Types
|
|
128
|
+
result = result.replace(COMMON_TYPES, (m) => theme.type(m));
|
|
129
|
+
// Function calls
|
|
130
|
+
result = result.replace(/\b([a-zA-Z_]\w*)\s*\(/g, (_, name) => theme.func(name) + '(');
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
// Link rendering constants
|
|
134
|
+
const LINK_BRACKET_L = '\u276a'; // box bracket left (heavy)
|
|
135
|
+
const LINK_BRACKET_R = '\u276b'; // box bracket right (heavy)
|
|
136
|
+
/**
|
|
137
|
+
* OSC 8 clickable hyperlink for terminals that support it.
|
|
138
|
+
* Format: ESC ] 8 ; params ; uri ST text ESC ] 8 ; ; ST
|
|
139
|
+
* Supported: iTerm2, Windows Terminal, GNOME Terminal, Konsole, foot, WezTerm, etc.
|
|
140
|
+
* Falls back to plain text + URL for non-TTY or NO_COLOR.
|
|
141
|
+
*/
|
|
142
|
+
function hyperlink(url, displayText) {
|
|
143
|
+
// Ensure full URL
|
|
144
|
+
const fullUrl = url.startsWith('http') ? url : `https://${url}`;
|
|
145
|
+
if (noColor || !process.stdout.isTTY)
|
|
146
|
+
return displayText;
|
|
147
|
+
return `\x1b]8;;${fullUrl}\x07${displayText}\x1b]8;;\x07`;
|
|
148
|
+
}
|
|
149
|
+
/** Extract readable domain + path from a URL */
|
|
150
|
+
function shortDomain(url) {
|
|
151
|
+
try {
|
|
152
|
+
const fullUrl = url.startsWith('http') ? url : `https://${url}`;
|
|
153
|
+
const parsed = new URL(fullUrl);
|
|
154
|
+
const host = parsed.hostname.replace(/^www\./, '');
|
|
155
|
+
const path = parsed.pathname;
|
|
156
|
+
if (path && path !== '/') {
|
|
157
|
+
// Shorten long paths: show first + last segment
|
|
158
|
+
const segments = path.split('/').filter(Boolean);
|
|
159
|
+
if (segments.length > 2) {
|
|
160
|
+
return `${host}/${segments[0]}/${ELLIP}/${segments[segments.length - 1]}`;
|
|
161
|
+
}
|
|
162
|
+
if (path.length < 40)
|
|
163
|
+
return `${host}${path}`;
|
|
164
|
+
return `${host}/${segments[0]}/${ELLIP}`;
|
|
165
|
+
}
|
|
166
|
+
return host;
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return url.length > 40 ? url.slice(0, 37) + ELLIP : url;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Render a link with a clear visual box treatment.
|
|
174
|
+
* Output: ` [link icon] Label domain.com/path `
|
|
175
|
+
* The entire label is an OSC 8 clickable hyperlink in supporting terminals.
|
|
176
|
+
*/
|
|
177
|
+
function renderLink(label, url) {
|
|
178
|
+
const domain = shortDomain(url);
|
|
179
|
+
// Clickable label text
|
|
180
|
+
const styledLabel = hyperlink(url, theme.link(chalk.bold.underline(label)));
|
|
181
|
+
// Domain hint - dimmed, with link arrow icon
|
|
182
|
+
const domainHint = theme.dim(`${LINK_ICON} ${domain}`);
|
|
183
|
+
// Visual bracket treatment to make links pop
|
|
184
|
+
return `${theme.link(LINK_BRACKET_L)} ${styledLabel} ${domainHint} ${theme.link(LINK_BRACKET_R)}`;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Render a bare URL with clickable domain display.
|
|
188
|
+
* Output: ` [link icon] domain.com/path `
|
|
189
|
+
*/
|
|
190
|
+
function renderBareUrl(url) {
|
|
191
|
+
const domain = shortDomain(url);
|
|
192
|
+
const styledDomain = hyperlink(url, theme.link(chalk.underline(domain)));
|
|
193
|
+
return `${theme.link(LINK_ICON)} ${styledDomain}`;
|
|
194
|
+
}
|
|
195
|
+
// Inline markdown formatting
|
|
196
|
+
function fmt(text) {
|
|
197
|
+
if (noColor)
|
|
198
|
+
return text;
|
|
199
|
+
// Bold
|
|
200
|
+
text = text.replace(/\*\*(.+?)\*\*/g, (_, c) => chalk.bold(c));
|
|
201
|
+
// Italic
|
|
202
|
+
text = text.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, (_, c) => chalk.italic(c));
|
|
203
|
+
text = text.replace(/(?<!_)_([^_]+)_(?!_)/g, (_, c) => chalk.italic(c));
|
|
204
|
+
// Inline code
|
|
205
|
+
text = text.replace(/`([^`]+)`/g, (_, c) => theme.code(c));
|
|
206
|
+
// Strikethrough
|
|
207
|
+
text = text.replace(/~~(.+?)~~/g, (_, c) => chalk.strikethrough.dim(c));
|
|
208
|
+
// Use a placeholder to prevent double-matching URLs in markdown links vs bare URLs
|
|
209
|
+
const linkPlaceholders = [];
|
|
210
|
+
// 1. Markdown links [text](url) - highest priority
|
|
211
|
+
text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, label, url) => {
|
|
212
|
+
const idx = linkPlaceholders.length;
|
|
213
|
+
linkPlaceholders.push(renderLink(label, url));
|
|
214
|
+
return `\x00LINK${idx}\x00`;
|
|
215
|
+
});
|
|
216
|
+
// 2. Contextual phrase + URL patterns:
|
|
217
|
+
// "details here https://..." / "view it here: https://..." / "click here https://..."
|
|
218
|
+
// Merge the phrase and URL into one styled link
|
|
219
|
+
text = text.replace(/((?:click |view |see |read |check |visit |details |full details |more )?here|this (?:link|page|article|site|resource))([.:,]?\s*)(https?:\/\/[^\s,;)>\]"']+[^\s,;)>\]"'.!?])/gi, (_match, phrase, sep, url) => {
|
|
220
|
+
const idx = linkPlaceholders.length;
|
|
221
|
+
linkPlaceholders.push(renderLink(phrase.trim(), url));
|
|
222
|
+
return `\x00LINK${idx}\x00`;
|
|
223
|
+
});
|
|
224
|
+
// 3. URL + contextual phrase patterns (reversed):
|
|
225
|
+
// "https://... (here)" / "https://... - click here"
|
|
226
|
+
text = text.replace(/(https?:\/\/[^\s,;)>\]"']+[^\s,;)>\]"'.!?])\s*[-(\s]*\b(here|this (?:link|page))\b[)\s]*/gi, (_match, url, phrase) => {
|
|
227
|
+
const idx = linkPlaceholders.length;
|
|
228
|
+
linkPlaceholders.push(renderLink(phrase.trim(), url));
|
|
229
|
+
return `\x00LINK${idx}\x00`;
|
|
230
|
+
});
|
|
231
|
+
// 4. Bare URLs with protocol: https://... http://...
|
|
232
|
+
text = text.replace(/(https?:\/\/[^\s,;)>\]"']+[^\s,;)>\]"'.!?])/g, (url) => {
|
|
233
|
+
const idx = linkPlaceholders.length;
|
|
234
|
+
linkPlaceholders.push(renderBareUrl(url));
|
|
235
|
+
return `\x00LINK${idx}\x00`;
|
|
236
|
+
});
|
|
237
|
+
// 5. Common bare domains without protocol: example.com/path
|
|
238
|
+
text = text.replace(/(?<=\s|^)((?:[a-zA-Z0-9-]+\.)+(?:com|org|net|io|dev|ai|co|app|gov|edu|info|me)(?:\/[^\s,;)>\]"']*[^\s,;)>\]"'.!?])?)/g, (url) => {
|
|
239
|
+
const idx = linkPlaceholders.length;
|
|
240
|
+
linkPlaceholders.push(renderBareUrl(url));
|
|
241
|
+
return `\x00LINK${idx}\x00`;
|
|
242
|
+
});
|
|
243
|
+
// 6. Orphan link phrases with no URL - highlight as missing/broken link
|
|
244
|
+
// "You can view the full details here." where "here" has no URL nearby
|
|
245
|
+
text = text.replace(/\b((?:click |view |see |read |check (?:it )?|visit )?here|this (?:link|page|article))\b(?!\x00)/gi, (phrase) => {
|
|
246
|
+
// Only style if no placeholder follows (i.e., no URL was found nearby)
|
|
247
|
+
return theme.link(chalk.underline(phrase)) + theme.dim(` ${LINK_ICON}?`);
|
|
248
|
+
});
|
|
249
|
+
// Restore placeholders
|
|
250
|
+
for (let i = 0; i < linkPlaceholders.length; i++) {
|
|
251
|
+
text = text.replace(`\x00LINK${i}\x00`, linkPlaceholders[i]);
|
|
252
|
+
}
|
|
253
|
+
return text;
|
|
254
|
+
}
|
|
255
|
+
// Render a single line with markdown
|
|
256
|
+
function renderLine(line, inCode, codeLang) {
|
|
257
|
+
if (inCode) {
|
|
258
|
+
const highlighted = highlightCode(line, codeLang || '');
|
|
259
|
+
return ` ${theme.border(V_LINE)} ${highlighted}`;
|
|
260
|
+
}
|
|
261
|
+
// Headings
|
|
262
|
+
if (line.startsWith('### '))
|
|
263
|
+
return ` ${theme.bold(fmt(line.slice(4)))}`;
|
|
264
|
+
if (line.startsWith('## '))
|
|
265
|
+
return ` ${theme.bold(fmt(line.slice(3)))}`;
|
|
266
|
+
if (line.startsWith('# '))
|
|
267
|
+
return ` ${theme.bold(chalk.underline(fmt(line.slice(2))))}`;
|
|
268
|
+
// Block quotes
|
|
269
|
+
if (line.startsWith('> ')) {
|
|
270
|
+
return ` ${theme.border(V_LINE)} ${theme.italic(fmt(line.slice(2)))}`;
|
|
271
|
+
}
|
|
272
|
+
// Bullet lists
|
|
273
|
+
const bullet = line.match(/^(\s*)([-*])\s(.*)/);
|
|
274
|
+
if (bullet) {
|
|
275
|
+
const indent = bullet[1];
|
|
276
|
+
return ` ${indent}${theme.dim(ARROW)} ${wrapText(fmt(bullet[3]), 4 + indent.length)}`;
|
|
277
|
+
}
|
|
278
|
+
// Numbered lists
|
|
279
|
+
const num = line.match(/^(\s*)(\d+\.)\s(.*)/);
|
|
280
|
+
if (num) {
|
|
281
|
+
return ` ${num[1]}${theme.dim(num[2])} ${wrapText(fmt(num[3]), 4 + num[1].length + num[2].length)}`;
|
|
282
|
+
}
|
|
283
|
+
// Horizontal rule
|
|
284
|
+
if (line.match(/^[-*_]{3,}$/))
|
|
285
|
+
return separator();
|
|
286
|
+
// Empty line
|
|
287
|
+
if (line.trim() === '')
|
|
288
|
+
return '';
|
|
289
|
+
// Normal text with word-wrap
|
|
290
|
+
return ` ${wrapText(fmt(line), 2)}`;
|
|
291
|
+
}
|
|
292
|
+
// Public helpers
|
|
293
|
+
export function formatElapsed(ms) {
|
|
294
|
+
if (ms < 1000)
|
|
295
|
+
return `${ms}ms`;
|
|
296
|
+
if (ms < 60000)
|
|
297
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
298
|
+
const mins = Math.floor(ms / 60000);
|
|
299
|
+
const secs = Math.floor((ms % 60000) / 1000);
|
|
300
|
+
return `${mins}m ${secs}s`;
|
|
301
|
+
}
|
|
302
|
+
export function formatTokens(count) {
|
|
303
|
+
if (count >= 1000000)
|
|
304
|
+
return `${(count / 1000000).toFixed(1)}M`;
|
|
305
|
+
if (count >= 1000)
|
|
306
|
+
return `${(count / 1000).toFixed(1)}K`;
|
|
307
|
+
return count.toString();
|
|
308
|
+
}
|
|
309
|
+
function truncStr(str, max) {
|
|
310
|
+
if (str.length <= max)
|
|
311
|
+
return str;
|
|
312
|
+
return str.slice(0, max - 1) + ELLIP;
|
|
313
|
+
}
|
|
314
|
+
// Full markdown block rendering (for post-stream fallback)
|
|
315
|
+
export function renderMarkdownLite(text) {
|
|
316
|
+
const lines = text.split('\n');
|
|
317
|
+
const out = [];
|
|
318
|
+
let inCode = false;
|
|
319
|
+
let codeLang = '';
|
|
320
|
+
for (const line of lines) {
|
|
321
|
+
if (line.startsWith('```')) {
|
|
322
|
+
if (inCode) {
|
|
323
|
+
inCode = false;
|
|
324
|
+
out.push(` ${theme.border(B_LEFT + H_LINE.repeat(3))}`);
|
|
325
|
+
codeLang = '';
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
inCode = true;
|
|
329
|
+
codeLang = line.slice(3).trim();
|
|
330
|
+
out.push(` ${theme.border(T_LEFT + H_LINE.repeat(3))} ${theme.dim(codeLang)}`);
|
|
331
|
+
}
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
out.push(renderLine(line, inCode, codeLang));
|
|
335
|
+
}
|
|
336
|
+
return out.join('\n');
|
|
337
|
+
}
|
|
338
|
+
// Renderer Implementation
|
|
339
|
+
export function createRenderer() {
|
|
340
|
+
// Streaming markdown state
|
|
341
|
+
let streamBuf = '';
|
|
342
|
+
let streamLineCount = 0;
|
|
343
|
+
let partialLine = ''; // Incomplete line being streamed
|
|
344
|
+
let inCodeBlock = false; // Track code block state across lines
|
|
345
|
+
let codeLang = ''; // Current code block language
|
|
346
|
+
let firstLineDone = false; // Track if we've started outputting
|
|
347
|
+
// Thinking state
|
|
348
|
+
let thinkingBuf = '';
|
|
349
|
+
return {
|
|
350
|
+
userMessage() {
|
|
351
|
+
// Don't echo - user knows what they typed
|
|
352
|
+
},
|
|
353
|
+
assistantStart() {
|
|
354
|
+
console.log('');
|
|
355
|
+
streamBuf = '';
|
|
356
|
+
streamLineCount = 0;
|
|
357
|
+
partialLine = '';
|
|
358
|
+
inCodeBlock = false;
|
|
359
|
+
codeLang = '';
|
|
360
|
+
firstLineDone = false;
|
|
361
|
+
},
|
|
362
|
+
assistantDelta(chunk) {
|
|
363
|
+
streamBuf += chunk;
|
|
364
|
+
// Streaming markdown: process complete lines immediately
|
|
365
|
+
const combined = partialLine + chunk;
|
|
366
|
+
const lines = combined.split('\n');
|
|
367
|
+
// Last element is the incomplete line (may be empty string if chunk ended with \n)
|
|
368
|
+
partialLine = lines.pop() || '';
|
|
369
|
+
// Render each complete line with markdown formatting
|
|
370
|
+
for (const line of lines) {
|
|
371
|
+
// Code block fence detection
|
|
372
|
+
if (line.startsWith('```')) {
|
|
373
|
+
if (inCodeBlock) {
|
|
374
|
+
inCodeBlock = false;
|
|
375
|
+
process.stdout.write(` ${theme.border(B_LEFT + H_LINE.repeat(3))}\n`);
|
|
376
|
+
codeLang = '';
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
inCodeBlock = true;
|
|
380
|
+
codeLang = line.slice(3).trim();
|
|
381
|
+
process.stdout.write(` ${theme.border(T_LEFT + H_LINE.repeat(3))} ${theme.dim(codeLang)}\n`);
|
|
382
|
+
}
|
|
383
|
+
streamLineCount++;
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
const rendered = renderLine(line, inCodeBlock, codeLang);
|
|
387
|
+
process.stdout.write(rendered + '\n');
|
|
388
|
+
streamLineCount++;
|
|
389
|
+
firstLineDone = true;
|
|
390
|
+
}
|
|
391
|
+
// Write partial line raw (will be overwritten when line completes)
|
|
392
|
+
if (partialLine) {
|
|
393
|
+
if (inCodeBlock) {
|
|
394
|
+
process.stdout.write(`\r\x1b[K ${theme.border(V_LINE)} ${highlightCode(partialLine, codeLang)}`);
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
process.stdout.write(`\r\x1b[K ${fmt(partialLine)}`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
assistantEnd() {
|
|
402
|
+
if (streamBuf.length === 0)
|
|
403
|
+
return;
|
|
404
|
+
// Flush any remaining partial line
|
|
405
|
+
if (partialLine) {
|
|
406
|
+
const rendered = renderLine(partialLine, inCodeBlock, codeLang);
|
|
407
|
+
process.stdout.write(`\r\x1b[K${rendered}\n`);
|
|
408
|
+
partialLine = '';
|
|
409
|
+
}
|
|
410
|
+
else if (firstLineDone) {
|
|
411
|
+
// Just ensure we end with a newline
|
|
412
|
+
}
|
|
413
|
+
streamBuf = '';
|
|
414
|
+
streamLineCount = 0;
|
|
415
|
+
inCodeBlock = false;
|
|
416
|
+
codeLang = '';
|
|
417
|
+
},
|
|
418
|
+
thinkingStart() {
|
|
419
|
+
thinkingBuf = '';
|
|
420
|
+
process.stdout.write(theme.dim(` ${CIRCLE} thinking`));
|
|
421
|
+
},
|
|
422
|
+
thinkingDelta(chunk) {
|
|
423
|
+
if (!chunk || chunk.trim() === '') {
|
|
424
|
+
process.stdout.write(theme.dim('.'));
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
// First real content - clear the "thinking..." line
|
|
428
|
+
if (thinkingBuf === '') {
|
|
429
|
+
process.stdout.write('\r\x1b[K');
|
|
430
|
+
console.log(theme.dim(` ${CIRCLE} thinking:`));
|
|
431
|
+
}
|
|
432
|
+
thinkingBuf += chunk;
|
|
433
|
+
const lines = chunk.split('\n');
|
|
434
|
+
for (let i = 0; i < lines.length; i++) {
|
|
435
|
+
if (i > 0)
|
|
436
|
+
process.stdout.write('\n');
|
|
437
|
+
if (lines[i]) {
|
|
438
|
+
process.stdout.write(theme.dim(theme.italic(` ${lines[i]}`)));
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
thinkingEnd() {
|
|
443
|
+
process.stdout.write('\n');
|
|
444
|
+
if (thinkingBuf) {
|
|
445
|
+
console.log(theme.dim(` ${CIRCLE} done thinking`));
|
|
446
|
+
}
|
|
447
|
+
thinkingBuf = '';
|
|
448
|
+
},
|
|
449
|
+
toolCall(name, args) {
|
|
450
|
+
const firstVal = Object.values(args)[0];
|
|
451
|
+
const preview = firstVal ? truncStr(String(firstVal), 36) : '';
|
|
452
|
+
const label = preview
|
|
453
|
+
? `${theme.gold(GEAR + ' ' + name)} ${theme.dim(preview)}`
|
|
454
|
+
: theme.gold(GEAR + ' ' + name);
|
|
455
|
+
console.log(separator(label));
|
|
456
|
+
// Show key arguments for common tools
|
|
457
|
+
const entries = Object.entries(args);
|
|
458
|
+
if (entries.length > 1) {
|
|
459
|
+
const maxArgs = 3;
|
|
460
|
+
for (let i = 0; i < Math.min(entries.length, maxArgs); i++) {
|
|
461
|
+
const [key, val] = entries[i];
|
|
462
|
+
const valStr = truncStr(String(val), 50);
|
|
463
|
+
console.log(theme.dim(` ${theme.border(V_LINE)} ${key}: ${valStr}`));
|
|
464
|
+
}
|
|
465
|
+
if (entries.length > maxArgs) {
|
|
466
|
+
console.log(theme.dim(` ${theme.border(V_LINE)} +${entries.length - maxArgs} more`));
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
},
|
|
470
|
+
toolResult(name, result, success, durationMs) {
|
|
471
|
+
const icon = success ? theme.mint(CHECK) : theme.coral(CROSS);
|
|
472
|
+
const dur = durationMs ? theme.dim(` ${formatElapsed(durationMs)}`) : '';
|
|
473
|
+
const statusText = success ? '' : theme.coral(' failed');
|
|
474
|
+
// Show result preview for verbose mode
|
|
475
|
+
if (result !== undefined && result !== null) {
|
|
476
|
+
const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
|
|
477
|
+
if (!success) {
|
|
478
|
+
// Show error details
|
|
479
|
+
const errPreview = truncStr(resultStr, 80);
|
|
480
|
+
console.log(` ${icon}${statusText}${dur}`);
|
|
481
|
+
console.log(theme.coral(` ${theme.border(V_LINE)} ${errPreview}`));
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
// Show success with brief preview
|
|
485
|
+
const preview = truncStr(resultStr, 60);
|
|
486
|
+
if (preview.length > 5 && resultStr.length > 10) {
|
|
487
|
+
console.log(` ${icon}${dur} ${theme.dim(preview)}`);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
console.log(` ${icon}${dur}`);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
console.log(` ${icon}${statusText}${dur}`);
|
|
496
|
+
}
|
|
497
|
+
console.log(separator());
|
|
498
|
+
},
|
|
499
|
+
usage(usage, durationMs) {
|
|
500
|
+
const parts = [];
|
|
501
|
+
if (durationMs)
|
|
502
|
+
parts.push(formatElapsed(durationMs));
|
|
503
|
+
if (usage.totalTokens) {
|
|
504
|
+
parts.push(`${formatTokens(usage.promptTokens)} in ${DOT} ${formatTokens(usage.completionTokens)} out`);
|
|
505
|
+
}
|
|
506
|
+
if (usage.cost !== undefined && usage.cost > 0)
|
|
507
|
+
parts.push(`$${usage.cost.toFixed(4)}`);
|
|
508
|
+
if (parts.length > 0) {
|
|
509
|
+
console.log('');
|
|
510
|
+
console.log(theme.dim(` ${parts.join(` ${DOT} `)}`));
|
|
511
|
+
}
|
|
512
|
+
},
|
|
513
|
+
error(message) {
|
|
514
|
+
console.log(` ${theme.coral(CROSS)} ${message}`);
|
|
515
|
+
},
|
|
516
|
+
info(message) {
|
|
517
|
+
console.log(theme.dim(` ${message}`));
|
|
518
|
+
},
|
|
519
|
+
success(message) {
|
|
520
|
+
console.log(` ${theme.mint(CHECK)} ${message}`);
|
|
521
|
+
},
|
|
522
|
+
warn(message) {
|
|
523
|
+
console.log(` ${theme.gold('!')} ${message}`);
|
|
524
|
+
},
|
|
525
|
+
divider() {
|
|
526
|
+
console.log(separator());
|
|
527
|
+
},
|
|
528
|
+
clear() {
|
|
529
|
+
console.clear();
|
|
530
|
+
},
|
|
531
|
+
statusLine(text) {
|
|
532
|
+
// Write to bottom of terminal using ANSI save/restore cursor
|
|
533
|
+
if (process.stdout.isTTY) {
|
|
534
|
+
const rows = process.stdout.rows || 24;
|
|
535
|
+
process.stdout.write(`\x1b7`); // Save cursor
|
|
536
|
+
process.stdout.write(`\x1b[${rows};1H`); // Move to bottom row
|
|
537
|
+
process.stdout.write(`\x1b[2K`); // Clear line
|
|
538
|
+
process.stdout.write(theme.dim(text));
|
|
539
|
+
process.stdout.write(`\x1b8`); // Restore cursor
|
|
540
|
+
}
|
|
541
|
+
},
|
|
542
|
+
sessionFooter(state) {
|
|
543
|
+
const parts = [];
|
|
544
|
+
if (state.sessionTokens > 0)
|
|
545
|
+
parts.push(`${formatTokens(state.sessionTokens)} tokens`);
|
|
546
|
+
if (state.sessionCost > 0)
|
|
547
|
+
parts.push(`$${state.sessionCost.toFixed(4)}`);
|
|
548
|
+
parts.push(`${state.messageCount} msg${state.messageCount !== 1 ? 's' : ''}`);
|
|
549
|
+
if (state.model)
|
|
550
|
+
parts.push(state.model);
|
|
551
|
+
console.log(theme.dim(` ${parts.join(` ${DOT} `)}`));
|
|
552
|
+
},
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive REPL Engine
|
|
3
|
+
*
|
|
4
|
+
* Claude-like interactive chat with streaming, tool display,
|
|
5
|
+
* slash commands, and session management.
|
|
6
|
+
*
|
|
7
|
+
* Self-contained module - depends only on Node.js builtins,
|
|
8
|
+
* chalk, ora, and the stream-client/renderer siblings.
|
|
9
|
+
*
|
|
10
|
+
* @package profclaw-interactive (future standalone)
|
|
11
|
+
*/
|
|
12
|
+
import type { InteractiveOptions } from './types.js';
|
|
13
|
+
export declare function startInteractiveREPL(options: InteractiveOptions): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=repl.d.ts.map
|