orquesta-cli 0.1.12
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/.eslintrc.json +26 -0
- package/.prettierrc.json +10 -0
- package/CLAUDE.md +199 -0
- package/LICENSE +21 -0
- package/README.md +280 -0
- package/SECURITY.md +290 -0
- package/TEST_LOCAL.md +245 -0
- package/dist/agents/base/base-agent.d.ts +38 -0
- package/dist/agents/base/base-agent.d.ts.map +1 -0
- package/dist/agents/base/base-agent.js +69 -0
- package/dist/agents/base/base-agent.js.map +1 -0
- package/dist/agents/docs-search/index.d.ts +33 -0
- package/dist/agents/docs-search/index.d.ts.map +1 -0
- package/dist/agents/docs-search/index.js +244 -0
- package/dist/agents/docs-search/index.js.map +1 -0
- package/dist/agents/index.d.ts +4 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +4 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/planner/index.d.ts +17 -0
- package/dist/agents/planner/index.d.ts.map +1 -0
- package/dist/agents/planner/index.js +250 -0
- package/dist/agents/planner/index.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +144 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +10 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/compact/compact-manager.d.ts +22 -0
- package/dist/core/compact/compact-manager.d.ts.map +1 -0
- package/dist/core/compact/compact-manager.js +75 -0
- package/dist/core/compact/compact-manager.js.map +1 -0
- package/dist/core/compact/compact-prompts.d.ts +11 -0
- package/dist/core/compact/compact-prompts.d.ts.map +1 -0
- package/dist/core/compact/compact-prompts.js +90 -0
- package/dist/core/compact/compact-prompts.js.map +1 -0
- package/dist/core/compact/context-tracker.d.ts +28 -0
- package/dist/core/compact/context-tracker.d.ts.map +1 -0
- package/dist/core/compact/context-tracker.js +71 -0
- package/dist/core/compact/context-tracker.js.map +1 -0
- package/dist/core/compact/index.d.ts +4 -0
- package/dist/core/compact/index.d.ts.map +1 -0
- package/dist/core/compact/index.js +4 -0
- package/dist/core/compact/index.js.map +1 -0
- package/dist/core/config/config-manager.d.ts +44 -0
- package/dist/core/config/config-manager.d.ts.map +1 -0
- package/dist/core/config/config-manager.js +259 -0
- package/dist/core/config/config-manager.js.map +1 -0
- package/dist/core/config/index.d.ts +2 -0
- package/dist/core/config/index.d.ts.map +1 -0
- package/dist/core/config/index.js +2 -0
- package/dist/core/config/index.js.map +1 -0
- package/dist/core/docs-manager.d.ts +46 -0
- package/dist/core/docs-manager.d.ts.map +1 -0
- package/dist/core/docs-manager.js +475 -0
- package/dist/core/docs-manager.js.map +1 -0
- package/dist/core/git-auto-updater.d.ts +58 -0
- package/dist/core/git-auto-updater.d.ts.map +1 -0
- package/dist/core/git-auto-updater.js +374 -0
- package/dist/core/git-auto-updater.js.map +1 -0
- package/dist/core/llm/index.d.ts +2 -0
- package/dist/core/llm/index.d.ts.map +1 -0
- package/dist/core/llm/index.js +2 -0
- package/dist/core/llm/index.js.map +1 -0
- package/dist/core/llm/llm-client.d.ts +97 -0
- package/dist/core/llm/llm-client.d.ts.map +1 -0
- package/dist/core/llm/llm-client.js +1000 -0
- package/dist/core/llm/llm-client.js.map +1 -0
- package/dist/core/session/index.d.ts +2 -0
- package/dist/core/session/index.d.ts.map +1 -0
- package/dist/core/session/index.js +2 -0
- package/dist/core/session/index.js.map +1 -0
- package/dist/core/session/session-manager.d.ts +71 -0
- package/dist/core/session/session-manager.d.ts.map +1 -0
- package/dist/core/session/session-manager.js +250 -0
- package/dist/core/session/session-manager.js.map +1 -0
- package/dist/core/slash-command-handler.d.ts +31 -0
- package/dist/core/slash-command-handler.d.ts.map +1 -0
- package/dist/core/slash-command-handler.js +302 -0
- package/dist/core/slash-command-handler.js.map +1 -0
- package/dist/core/usage-tracker.d.ts +70 -0
- package/dist/core/usage-tracker.d.ts.map +1 -0
- package/dist/core/usage-tracker.js +251 -0
- package/dist/core/usage-tracker.js.map +1 -0
- package/dist/errors/base.d.ts +22 -0
- package/dist/errors/base.d.ts.map +1 -0
- package/dist/errors/base.js +43 -0
- package/dist/errors/base.js.map +1 -0
- package/dist/errors/file.d.ts +31 -0
- package/dist/errors/file.d.ts.map +1 -0
- package/dist/errors/file.js +110 -0
- package/dist/errors/file.js.map +1 -0
- package/dist/errors/index.d.ts +10 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +41 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/llm.d.ts +26 -0
- package/dist/errors/llm.d.ts.map +1 -0
- package/dist/errors/llm.js +86 -0
- package/dist/errors/llm.js.map +1 -0
- package/dist/errors/network.d.ts +19 -0
- package/dist/errors/network.d.ts.map +1 -0
- package/dist/errors/network.js +82 -0
- package/dist/errors/network.js.map +1 -0
- package/dist/errors/validation.d.ts +19 -0
- package/dist/errors/validation.d.ts.map +1 -0
- package/dist/errors/validation.js +62 -0
- package/dist/errors/validation.js.map +1 -0
- package/dist/eval/eval-runner.d.ts +24 -0
- package/dist/eval/eval-runner.d.ts.map +1 -0
- package/dist/eval/eval-runner.js +309 -0
- package/dist/eval/eval-runner.js.map +1 -0
- package/dist/eval/index.d.ts +3 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +3 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/types.d.ts +77 -0
- package/dist/eval/types.d.ts.map +1 -0
- package/dist/eval/types.js +2 -0
- package/dist/eval/types.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestration/index.d.ts +4 -0
- package/dist/orchestration/index.d.ts.map +1 -0
- package/dist/orchestration/index.js +3 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/orchestration/plan-executor.d.ts +28 -0
- package/dist/orchestration/plan-executor.d.ts.map +1 -0
- package/dist/orchestration/plan-executor.js +382 -0
- package/dist/orchestration/plan-executor.js.map +1 -0
- package/dist/orchestration/types.d.ts +66 -0
- package/dist/orchestration/types.d.ts.map +1 -0
- package/dist/orchestration/types.js +2 -0
- package/dist/orchestration/types.js.map +1 -0
- package/dist/orchestration/utils.d.ts +13 -0
- package/dist/orchestration/utils.d.ts.map +1 -0
- package/dist/orchestration/utils.js +78 -0
- package/dist/orchestration/utils.js.map +1 -0
- package/dist/orquesta/connection.d.ts +35 -0
- package/dist/orquesta/connection.d.ts.map +1 -0
- package/dist/orquesta/connection.js +189 -0
- package/dist/orquesta/connection.js.map +1 -0
- package/dist/prompts/agents/docs-search-decision.d.ts +6 -0
- package/dist/prompts/agents/docs-search-decision.d.ts.map +1 -0
- package/dist/prompts/agents/docs-search-decision.js +46 -0
- package/dist/prompts/agents/docs-search-decision.js.map +1 -0
- package/dist/prompts/agents/docs-search.d.ts +4 -0
- package/dist/prompts/agents/docs-search.d.ts.map +1 -0
- package/dist/prompts/agents/docs-search.js +70 -0
- package/dist/prompts/agents/docs-search.js.map +1 -0
- package/dist/prompts/agents/planning.d.ts +4 -0
- package/dist/prompts/agents/planning.d.ts.map +1 -0
- package/dist/prompts/agents/planning.js +119 -0
- package/dist/prompts/agents/planning.js.map +1 -0
- package/dist/prompts/index.d.ts +10 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +10 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/shared/codebase-rules.d.ts +4 -0
- package/dist/prompts/shared/codebase-rules.d.ts.map +1 -0
- package/dist/prompts/shared/codebase-rules.js +16 -0
- package/dist/prompts/shared/codebase-rules.js.map +1 -0
- package/dist/prompts/shared/git-rules.d.ts +2 -0
- package/dist/prompts/shared/git-rules.d.ts.map +1 -0
- package/dist/prompts/shared/git-rules.js +87 -0
- package/dist/prompts/shared/git-rules.js.map +1 -0
- package/dist/prompts/shared/language-rules.d.ts +4 -0
- package/dist/prompts/shared/language-rules.d.ts.map +1 -0
- package/dist/prompts/shared/language-rules.js +22 -0
- package/dist/prompts/shared/language-rules.js.map +1 -0
- package/dist/prompts/shared/tool-usage.d.ts +12 -0
- package/dist/prompts/shared/tool-usage.d.ts.map +1 -0
- package/dist/prompts/shared/tool-usage.js +51 -0
- package/dist/prompts/shared/tool-usage.js.map +1 -0
- package/dist/prompts/system/compact.d.ts +3 -0
- package/dist/prompts/system/compact.d.ts.map +1 -0
- package/dist/prompts/system/compact.js +73 -0
- package/dist/prompts/system/compact.js.map +1 -0
- package/dist/prompts/system/plan-execute.d.ts +3 -0
- package/dist/prompts/system/plan-execute.d.ts.map +1 -0
- package/dist/prompts/system/plan-execute.js +83 -0
- package/dist/prompts/system/plan-execute.js.map +1 -0
- package/dist/tools/browser/browser-client.d.ts +107 -0
- package/dist/tools/browser/browser-client.d.ts.map +1 -0
- package/dist/tools/browser/browser-client.js +958 -0
- package/dist/tools/browser/browser-client.js.map +1 -0
- package/dist/tools/browser/browser-tools.d.ts +17 -0
- package/dist/tools/browser/browser-tools.d.ts.map +1 -0
- package/dist/tools/browser/browser-tools.js +972 -0
- package/dist/tools/browser/browser-tools.js.map +1 -0
- package/dist/tools/browser/index.d.ts +7 -0
- package/dist/tools/browser/index.d.ts.map +1 -0
- package/dist/tools/browser/index.js +17 -0
- package/dist/tools/browser/index.js.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/llm/agents/docs-search-tools.d.ts +17 -0
- package/dist/tools/llm/agents/docs-search-tools.d.ts.map +1 -0
- package/dist/tools/llm/agents/docs-search-tools.js +265 -0
- package/dist/tools/llm/agents/docs-search-tools.js.map +1 -0
- package/dist/tools/llm/agents/index.d.ts +4 -0
- package/dist/tools/llm/agents/index.d.ts.map +1 -0
- package/dist/tools/llm/agents/index.js +3 -0
- package/dist/tools/llm/agents/index.js.map +1 -0
- package/dist/tools/llm/index.d.ts +3 -0
- package/dist/tools/llm/index.d.ts.map +1 -0
- package/dist/tools/llm/index.js +3 -0
- package/dist/tools/llm/index.js.map +1 -0
- package/dist/tools/llm/simple/ask-user-tool.d.ts +5 -0
- package/dist/tools/llm/simple/ask-user-tool.d.ts.map +1 -0
- package/dist/tools/llm/simple/ask-user-tool.js +7 -0
- package/dist/tools/llm/simple/ask-user-tool.js.map +1 -0
- package/dist/tools/llm/simple/background-bash-tool.d.ts +30 -0
- package/dist/tools/llm/simple/background-bash-tool.d.ts.map +1 -0
- package/dist/tools/llm/simple/background-bash-tool.js +323 -0
- package/dist/tools/llm/simple/background-bash-tool.js.map +1 -0
- package/dist/tools/llm/simple/background-powershell-tool.d.ts +30 -0
- package/dist/tools/llm/simple/background-powershell-tool.d.ts.map +1 -0
- package/dist/tools/llm/simple/background-powershell-tool.js +305 -0
- package/dist/tools/llm/simple/background-powershell-tool.js.map +1 -0
- package/dist/tools/llm/simple/bash-tool.d.ts +4 -0
- package/dist/tools/llm/simple/bash-tool.d.ts.map +1 -0
- package/dist/tools/llm/simple/bash-tool.js +178 -0
- package/dist/tools/llm/simple/bash-tool.js.map +1 -0
- package/dist/tools/llm/simple/docs-search-agent-tool.d.ts +6 -0
- package/dist/tools/llm/simple/docs-search-agent-tool.d.ts.map +1 -0
- package/dist/tools/llm/simple/docs-search-agent-tool.js +104 -0
- package/dist/tools/llm/simple/docs-search-agent-tool.js.map +1 -0
- package/dist/tools/llm/simple/file-tools.d.ts +13 -0
- package/dist/tools/llm/simple/file-tools.d.ts.map +1 -0
- package/dist/tools/llm/simple/file-tools.js +785 -0
- package/dist/tools/llm/simple/file-tools.js.map +1 -0
- package/dist/tools/llm/simple/final-response-tool.d.ts +12 -0
- package/dist/tools/llm/simple/final-response-tool.d.ts.map +1 -0
- package/dist/tools/llm/simple/final-response-tool.js +107 -0
- package/dist/tools/llm/simple/final-response-tool.js.map +1 -0
- package/dist/tools/llm/simple/index.d.ts +11 -0
- package/dist/tools/llm/simple/index.d.ts.map +1 -0
- package/dist/tools/llm/simple/index.js +20 -0
- package/dist/tools/llm/simple/index.js.map +1 -0
- package/dist/tools/llm/simple/planning-tools.d.ts +5 -0
- package/dist/tools/llm/simple/planning-tools.d.ts.map +1 -0
- package/dist/tools/llm/simple/planning-tools.js +117 -0
- package/dist/tools/llm/simple/planning-tools.js.map +1 -0
- package/dist/tools/llm/simple/powershell-tool.d.ts +4 -0
- package/dist/tools/llm/simple/powershell-tool.d.ts.map +1 -0
- package/dist/tools/llm/simple/powershell-tool.js +178 -0
- package/dist/tools/llm/simple/powershell-tool.js.map +1 -0
- package/dist/tools/llm/simple/simple-tool-executor.d.ts +38 -0
- package/dist/tools/llm/simple/simple-tool-executor.d.ts.map +1 -0
- package/dist/tools/llm/simple/simple-tool-executor.js +134 -0
- package/dist/tools/llm/simple/simple-tool-executor.js.map +1 -0
- package/dist/tools/llm/simple/todo-tools.d.ts +15 -0
- package/dist/tools/llm/simple/todo-tools.d.ts.map +1 -0
- package/dist/tools/llm/simple/todo-tools.js +145 -0
- package/dist/tools/llm/simple/todo-tools.js.map +1 -0
- package/dist/tools/llm/simple/user-interaction-tools.d.ts +22 -0
- package/dist/tools/llm/simple/user-interaction-tools.d.ts.map +1 -0
- package/dist/tools/llm/simple/user-interaction-tools.js +168 -0
- package/dist/tools/llm/simple/user-interaction-tools.js.map +1 -0
- package/dist/tools/office/common/constants.d.ts +194 -0
- package/dist/tools/office/common/constants.d.ts.map +1 -0
- package/dist/tools/office/common/constants.js +169 -0
- package/dist/tools/office/common/constants.js.map +1 -0
- package/dist/tools/office/common/index.d.ts +4 -0
- package/dist/tools/office/common/index.d.ts.map +1 -0
- package/dist/tools/office/common/index.js +3 -0
- package/dist/tools/office/common/index.js.map +1 -0
- package/dist/tools/office/common/types.d.ts +82 -0
- package/dist/tools/office/common/types.d.ts.map +1 -0
- package/dist/tools/office/common/types.js +2 -0
- package/dist/tools/office/common/types.js.map +1 -0
- package/dist/tools/office/common/utils.d.ts +14 -0
- package/dist/tools/office/common/utils.d.ts.map +1 -0
- package/dist/tools/office/common/utils.js +58 -0
- package/dist/tools/office/common/utils.js.map +1 -0
- package/dist/tools/office/excel-client.d.ts +123 -0
- package/dist/tools/office/excel-client.d.ts.map +1 -0
- package/dist/tools/office/excel-client.js +1037 -0
- package/dist/tools/office/excel-client.js.map +1 -0
- package/dist/tools/office/excel-tools/cells.d.ts +10 -0
- package/dist/tools/office/excel-tools/cells.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/cells.js +279 -0
- package/dist/tools/office/excel-tools/cells.js.map +1 -0
- package/dist/tools/office/excel-tools/charts.d.ts +6 -0
- package/dist/tools/office/excel-tools/charts.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/charts.js +124 -0
- package/dist/tools/office/excel-tools/charts.js.map +1 -0
- package/dist/tools/office/excel-tools/comments.d.ts +6 -0
- package/dist/tools/office/excel-tools/comments.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/comments.js +114 -0
- package/dist/tools/office/excel-tools/comments.js.map +1 -0
- package/dist/tools/office/excel-tools/data-ops.d.ts +10 -0
- package/dist/tools/office/excel-tools/data-ops.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/data-ops.js +266 -0
- package/dist/tools/office/excel-tools/data-ops.js.map +1 -0
- package/dist/tools/office/excel-tools/export.d.ts +5 -0
- package/dist/tools/office/excel-tools/export.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/export.js +75 -0
- package/dist/tools/office/excel-tools/export.js.map +1 -0
- package/dist/tools/office/excel-tools/formatting.d.ts +10 -0
- package/dist/tools/office/excel-tools/formatting.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/formatting.js +276 -0
- package/dist/tools/office/excel-tools/formatting.js.map +1 -0
- package/dist/tools/office/excel-tools/index.d.ts +16 -0
- package/dist/tools/office/excel-tools/index.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/index.js +42 -0
- package/dist/tools/office/excel-tools/index.js.map +1 -0
- package/dist/tools/office/excel-tools/launch.d.ts +10 -0
- package/dist/tools/office/excel-tools/launch.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/launch.js +248 -0
- package/dist/tools/office/excel-tools/launch.js.map +1 -0
- package/dist/tools/office/excel-tools/media.d.ts +5 -0
- package/dist/tools/office/excel-tools/media.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/media.js +84 -0
- package/dist/tools/office/excel-tools/media.js.map +1 -0
- package/dist/tools/office/excel-tools/named-ranges.d.ts +6 -0
- package/dist/tools/office/excel-tools/named-ranges.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/named-ranges.js +113 -0
- package/dist/tools/office/excel-tools/named-ranges.js.map +1 -0
- package/dist/tools/office/excel-tools/protection.d.ts +5 -0
- package/dist/tools/office/excel-tools/protection.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/protection.js +75 -0
- package/dist/tools/office/excel-tools/protection.js.map +1 -0
- package/dist/tools/office/excel-tools/rows-columns.d.ts +11 -0
- package/dist/tools/office/excel-tools/rows-columns.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/rows-columns.js +293 -0
- package/dist/tools/office/excel-tools/rows-columns.js.map +1 -0
- package/dist/tools/office/excel-tools/sheets.d.ts +8 -0
- package/dist/tools/office/excel-tools/sheets.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/sheets.js +177 -0
- package/dist/tools/office/excel-tools/sheets.js.map +1 -0
- package/dist/tools/office/excel-tools/validation.d.ts +7 -0
- package/dist/tools/office/excel-tools/validation.d.ts.map +1 -0
- package/dist/tools/office/excel-tools/validation.js +175 -0
- package/dist/tools/office/excel-tools/validation.js.map +1 -0
- package/dist/tools/office/excel-tools.d.ts +3 -0
- package/dist/tools/office/excel-tools.d.ts.map +1 -0
- package/dist/tools/office/excel-tools.js +3 -0
- package/dist/tools/office/excel-tools.js.map +1 -0
- package/dist/tools/office/index.d.ts +6 -0
- package/dist/tools/office/index.d.ts.map +1 -0
- package/dist/tools/office/index.js +9 -0
- package/dist/tools/office/index.js.map +1 -0
- package/dist/tools/office/office-client-base.d.ts +31 -0
- package/dist/tools/office/office-client-base.d.ts.map +1 -0
- package/dist/tools/office/office-client-base.js +154 -0
- package/dist/tools/office/office-client-base.js.map +1 -0
- package/dist/tools/office/office-client.d.ts +196 -0
- package/dist/tools/office/office-client.d.ts.map +1 -0
- package/dist/tools/office/office-client.js +200 -0
- package/dist/tools/office/office-client.js.map +1 -0
- package/dist/tools/office/powerpoint-client.d.ts +135 -0
- package/dist/tools/office/powerpoint-client.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-client.js +1136 -0
- package/dist/tools/office/powerpoint-client.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/effects.d.ts +9 -0
- package/dist/tools/office/powerpoint-tools/effects.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/effects.js +246 -0
- package/dist/tools/office/powerpoint-tools/effects.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/export.d.ts +6 -0
- package/dist/tools/office/powerpoint-tools/export.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/export.js +108 -0
- package/dist/tools/office/powerpoint-tools/export.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/index.d.ts +13 -0
- package/dist/tools/office/powerpoint-tools/index.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/index.js +33 -0
- package/dist/tools/office/powerpoint-tools/index.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/launch.d.ts +9 -0
- package/dist/tools/office/powerpoint-tools/launch.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/launch.js +214 -0
- package/dist/tools/office/powerpoint-tools/launch.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/media.d.ts +8 -0
- package/dist/tools/office/powerpoint-tools/media.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/media.js +211 -0
- package/dist/tools/office/powerpoint-tools/media.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/notes.d.ts +8 -0
- package/dist/tools/office/powerpoint-tools/notes.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/notes.js +171 -0
- package/dist/tools/office/powerpoint-tools/notes.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/sections.d.ts +6 -0
- package/dist/tools/office/powerpoint-tools/sections.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/sections.js +104 -0
- package/dist/tools/office/powerpoint-tools/sections.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/shapes.d.ts +22 -0
- package/dist/tools/office/powerpoint-tools/shapes.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/shapes.js +681 -0
- package/dist/tools/office/powerpoint-tools/shapes.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/slides.d.ts +11 -0
- package/dist/tools/office/powerpoint-tools/slides.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/slides.js +283 -0
- package/dist/tools/office/powerpoint-tools/slides.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/tables.d.ts +6 -0
- package/dist/tools/office/powerpoint-tools/tables.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/tables.js +132 -0
- package/dist/tools/office/powerpoint-tools/tables.js.map +1 -0
- package/dist/tools/office/powerpoint-tools/text.d.ts +12 -0
- package/dist/tools/office/powerpoint-tools/text.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools/text.js +366 -0
- package/dist/tools/office/powerpoint-tools/text.js.map +1 -0
- package/dist/tools/office/powerpoint-tools.d.ts +3 -0
- package/dist/tools/office/powerpoint-tools.d.ts.map +1 -0
- package/dist/tools/office/powerpoint-tools.js +3 -0
- package/dist/tools/office/powerpoint-tools.js.map +1 -0
- package/dist/tools/office/word-client.d.ts +147 -0
- package/dist/tools/office/word-client.d.ts.map +1 -0
- package/dist/tools/office/word-client.js +1341 -0
- package/dist/tools/office/word-client.js.map +1 -0
- package/dist/tools/office/word-tools/bookmarks.d.ts +7 -0
- package/dist/tools/office/word-tools/bookmarks.d.ts.map +1 -0
- package/dist/tools/office/word-tools/bookmarks.js +146 -0
- package/dist/tools/office/word-tools/bookmarks.js.map +1 -0
- package/dist/tools/office/word-tools/comments.d.ts +7 -0
- package/dist/tools/office/word-tools/comments.d.ts.map +1 -0
- package/dist/tools/office/word-tools/comments.js +146 -0
- package/dist/tools/office/word-tools/comments.js.map +1 -0
- package/dist/tools/office/word-tools/content.d.ts +7 -0
- package/dist/tools/office/word-tools/content.d.ts.map +1 -0
- package/dist/tools/office/word-tools/content.js +168 -0
- package/dist/tools/office/word-tools/content.js.map +1 -0
- package/dist/tools/office/word-tools/export.d.ts +5 -0
- package/dist/tools/office/word-tools/export.d.ts.map +1 -0
- package/dist/tools/office/word-tools/export.js +73 -0
- package/dist/tools/office/word-tools/export.js.map +1 -0
- package/dist/tools/office/word-tools/formatting.d.ts +6 -0
- package/dist/tools/office/word-tools/formatting.d.ts.map +1 -0
- package/dist/tools/office/word-tools/formatting.js +129 -0
- package/dist/tools/office/word-tools/formatting.js.map +1 -0
- package/dist/tools/office/word-tools/headers-footers.d.ts +6 -0
- package/dist/tools/office/word-tools/headers-footers.d.ts.map +1 -0
- package/dist/tools/office/word-tools/headers-footers.js +117 -0
- package/dist/tools/office/word-tools/headers-footers.js.map +1 -0
- package/dist/tools/office/word-tools/index.d.ts +16 -0
- package/dist/tools/office/word-tools/index.d.ts.map +1 -0
- package/dist/tools/office/word-tools/index.js +45 -0
- package/dist/tools/office/word-tools/index.js.map +1 -0
- package/dist/tools/office/word-tools/launch.d.ts +10 -0
- package/dist/tools/office/word-tools/launch.d.ts.map +1 -0
- package/dist/tools/office/word-tools/launch.js +255 -0
- package/dist/tools/office/word-tools/launch.js.map +1 -0
- package/dist/tools/office/word-tools/lists.d.ts +5 -0
- package/dist/tools/office/word-tools/lists.d.ts.map +1 -0
- package/dist/tools/office/word-tools/lists.js +73 -0
- package/dist/tools/office/word-tools/lists.js.map +1 -0
- package/dist/tools/office/word-tools/navigation.d.ts +5 -0
- package/dist/tools/office/word-tools/navigation.d.ts.map +1 -0
- package/dist/tools/office/word-tools/navigation.js +85 -0
- package/dist/tools/office/word-tools/navigation.js.map +1 -0
- package/dist/tools/office/word-tools/page-setup.d.ts +7 -0
- package/dist/tools/office/word-tools/page-setup.d.ts.map +1 -0
- package/dist/tools/office/word-tools/page-setup.js +152 -0
- package/dist/tools/office/word-tools/page-setup.js.map +1 -0
- package/dist/tools/office/word-tools/tables.d.ts +8 -0
- package/dist/tools/office/word-tools/tables.d.ts.map +1 -0
- package/dist/tools/office/word-tools/tables.js +197 -0
- package/dist/tools/office/word-tools/tables.js.map +1 -0
- package/dist/tools/office/word-tools/text.d.ts +9 -0
- package/dist/tools/office/word-tools/text.d.ts.map +1 -0
- package/dist/tools/office/word-tools/text.js +235 -0
- package/dist/tools/office/word-tools/text.js.map +1 -0
- package/dist/tools/office/word-tools/undo-redo.d.ts +5 -0
- package/dist/tools/office/word-tools/undo-redo.d.ts.map +1 -0
- package/dist/tools/office/word-tools/undo-redo.js +73 -0
- package/dist/tools/office/word-tools/undo-redo.js.map +1 -0
- package/dist/tools/office/word-tools/watermarks.d.ts +5 -0
- package/dist/tools/office/word-tools/watermarks.d.ts.map +1 -0
- package/dist/tools/office/word-tools/watermarks.js +81 -0
- package/dist/tools/office/word-tools/watermarks.js.map +1 -0
- package/dist/tools/office/word-tools.d.ts +3 -0
- package/dist/tools/office/word-tools.d.ts.map +1 -0
- package/dist/tools/office/word-tools.js +3 -0
- package/dist/tools/office/word-tools.js.map +1 -0
- package/dist/tools/registry.d.ts +53 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +278 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +88 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +19 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/types/index.d.ts +126 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/PlanExecuteView.d.ts +11 -0
- package/dist/ui/PlanExecuteView.d.ts.map +1 -0
- package/dist/ui/PlanExecuteView.js +29 -0
- package/dist/ui/PlanExecuteView.js.map +1 -0
- package/dist/ui/TodoPanel.d.ts +13 -0
- package/dist/ui/TodoPanel.d.ts.map +1 -0
- package/dist/ui/TodoPanel.js +135 -0
- package/dist/ui/TodoPanel.js.map +1 -0
- package/dist/ui/UpdateNotification.d.ts +13 -0
- package/dist/ui/UpdateNotification.d.ts.map +1 -0
- package/dist/ui/UpdateNotification.js +42 -0
- package/dist/ui/UpdateNotification.js.map +1 -0
- package/dist/ui/components/ActivityIndicator.d.ts +25 -0
- package/dist/ui/components/ActivityIndicator.d.ts.map +1 -0
- package/dist/ui/components/ActivityIndicator.js +115 -0
- package/dist/ui/components/ActivityIndicator.js.map +1 -0
- package/dist/ui/components/CommandBrowser.d.ts +10 -0
- package/dist/ui/components/CommandBrowser.d.ts.map +1 -0
- package/dist/ui/components/CommandBrowser.js +53 -0
- package/dist/ui/components/CommandBrowser.js.map +1 -0
- package/dist/ui/components/CustomTextInput.d.ts +13 -0
- package/dist/ui/components/CustomTextInput.d.ts.map +1 -0
- package/dist/ui/components/CustomTextInput.js +245 -0
- package/dist/ui/components/CustomTextInput.js.map +1 -0
- package/dist/ui/components/DocsSearchProgress.d.ts +13 -0
- package/dist/ui/components/DocsSearchProgress.d.ts.map +1 -0
- package/dist/ui/components/DocsSearchProgress.js +37 -0
- package/dist/ui/components/DocsSearchProgress.js.map +1 -0
- package/dist/ui/components/FileBrowser.d.ts +11 -0
- package/dist/ui/components/FileBrowser.d.ts.map +1 -0
- package/dist/ui/components/FileBrowser.js +45 -0
- package/dist/ui/components/FileBrowser.js.map +1 -0
- package/dist/ui/components/LLMSetupWizard.d.ts +8 -0
- package/dist/ui/components/LLMSetupWizard.d.ts.map +1 -0
- package/dist/ui/components/LLMSetupWizard.js +192 -0
- package/dist/ui/components/LLMSetupWizard.js.map +1 -0
- package/dist/ui/components/Logo.d.ts +19 -0
- package/dist/ui/components/Logo.d.ts.map +1 -0
- package/dist/ui/components/Logo.js +55 -0
- package/dist/ui/components/Logo.js.map +1 -0
- package/dist/ui/components/MarkdownRenderer.d.ts +9 -0
- package/dist/ui/components/MarkdownRenderer.d.ts.map +1 -0
- package/dist/ui/components/MarkdownRenderer.js +198 -0
- package/dist/ui/components/MarkdownRenderer.js.map +1 -0
- package/dist/ui/components/ModelSelector.d.ts +8 -0
- package/dist/ui/components/ModelSelector.d.ts.map +1 -0
- package/dist/ui/components/ModelSelector.js +111 -0
- package/dist/ui/components/ModelSelector.js.map +1 -0
- package/dist/ui/components/PlanExecuteApp.d.ts +23 -0
- package/dist/ui/components/PlanExecuteApp.d.ts.map +1 -0
- package/dist/ui/components/PlanExecuteApp.js +1324 -0
- package/dist/ui/components/PlanExecuteApp.js.map +1 -0
- package/dist/ui/components/ProgressBar.d.ts +10 -0
- package/dist/ui/components/ProgressBar.d.ts.map +1 -0
- package/dist/ui/components/ProgressBar.js +26 -0
- package/dist/ui/components/ProgressBar.js.map +1 -0
- package/dist/ui/components/StatusBar.d.ts +23 -0
- package/dist/ui/components/StatusBar.d.ts.map +1 -0
- package/dist/ui/components/StatusBar.js +162 -0
- package/dist/ui/components/StatusBar.js.map +1 -0
- package/dist/ui/components/ThinkingIndicator.d.ts +14 -0
- package/dist/ui/components/ThinkingIndicator.d.ts.map +1 -0
- package/dist/ui/components/ThinkingIndicator.js +63 -0
- package/dist/ui/components/ThinkingIndicator.js.map +1 -0
- package/dist/ui/components/TodoListView.d.ts +11 -0
- package/dist/ui/components/TodoListView.d.ts.map +1 -0
- package/dist/ui/components/TodoListView.js +69 -0
- package/dist/ui/components/TodoListView.js.map +1 -0
- package/dist/ui/components/ToolSelector.d.ts +7 -0
- package/dist/ui/components/ToolSelector.d.ts.map +1 -0
- package/dist/ui/components/ToolSelector.js +111 -0
- package/dist/ui/components/ToolSelector.js.map +1 -0
- package/dist/ui/components/dialogs/ApprovalDialog.d.ts +13 -0
- package/dist/ui/components/dialogs/ApprovalDialog.d.ts.map +1 -0
- package/dist/ui/components/dialogs/ApprovalDialog.js +173 -0
- package/dist/ui/components/dialogs/ApprovalDialog.js.map +1 -0
- package/dist/ui/components/dialogs/AskUserDialog.d.ts +9 -0
- package/dist/ui/components/dialogs/AskUserDialog.d.ts.map +1 -0
- package/dist/ui/components/dialogs/AskUserDialog.js +111 -0
- package/dist/ui/components/dialogs/AskUserDialog.js.map +1 -0
- package/dist/ui/components/dialogs/DocsBrowser.d.ts +8 -0
- package/dist/ui/components/dialogs/DocsBrowser.d.ts.map +1 -0
- package/dist/ui/components/dialogs/DocsBrowser.js +127 -0
- package/dist/ui/components/dialogs/DocsBrowser.js.map +1 -0
- package/dist/ui/components/dialogs/SettingsDialog.d.ts +10 -0
- package/dist/ui/components/dialogs/SettingsDialog.d.ts.map +1 -0
- package/dist/ui/components/dialogs/SettingsDialog.js +563 -0
- package/dist/ui/components/dialogs/SettingsDialog.js.map +1 -0
- package/dist/ui/components/dialogs/index.d.ts +4 -0
- package/dist/ui/components/dialogs/index.d.ts.map +1 -0
- package/dist/ui/components/dialogs/index.js +4 -0
- package/dist/ui/components/dialogs/index.js.map +1 -0
- package/dist/ui/components/index.d.ts +12 -0
- package/dist/ui/components/index.d.ts.map +1 -0
- package/dist/ui/components/index.js +9 -0
- package/dist/ui/components/index.js.map +1 -0
- package/dist/ui/components/panels/LogPanel.d.ts +7 -0
- package/dist/ui/components/panels/LogPanel.d.ts.map +1 -0
- package/dist/ui/components/panels/LogPanel.js +280 -0
- package/dist/ui/components/panels/LogPanel.js.map +1 -0
- package/dist/ui/components/panels/SessionPanel.d.ts +8 -0
- package/dist/ui/components/panels/SessionPanel.d.ts.map +1 -0
- package/dist/ui/components/panels/SessionPanel.js +81 -0
- package/dist/ui/components/panels/SessionPanel.js.map +1 -0
- package/dist/ui/components/panels/index.d.ts +4 -0
- package/dist/ui/components/panels/index.d.ts.map +1 -0
- package/dist/ui/components/panels/index.js +4 -0
- package/dist/ui/components/panels/index.js.map +1 -0
- package/dist/ui/components/views/ChatView.d.ts +12 -0
- package/dist/ui/components/views/ChatView.d.ts.map +1 -0
- package/dist/ui/components/views/ChatView.js +289 -0
- package/dist/ui/components/views/ChatView.js.map +1 -0
- package/dist/ui/components/views/index.d.ts +2 -0
- package/dist/ui/components/views/index.d.ts.map +1 -0
- package/dist/ui/components/views/index.js +2 -0
- package/dist/ui/components/views/index.js.map +1 -0
- package/dist/ui/contexts/TokenContext.d.ts +29 -0
- package/dist/ui/contexts/TokenContext.d.ts.map +1 -0
- package/dist/ui/contexts/TokenContext.js +79 -0
- package/dist/ui/contexts/TokenContext.js.map +1 -0
- package/dist/ui/hooks/atFileProcessor.d.ts +15 -0
- package/dist/ui/hooks/atFileProcessor.d.ts.map +1 -0
- package/dist/ui/hooks/atFileProcessor.js +88 -0
- package/dist/ui/hooks/atFileProcessor.js.map +1 -0
- package/dist/ui/hooks/index.d.ts +8 -0
- package/dist/ui/hooks/index.d.ts.map +1 -0
- package/dist/ui/hooks/index.js +8 -0
- package/dist/ui/hooks/index.js.map +1 -0
- package/dist/ui/hooks/slashCommandProcessor.d.ts +21 -0
- package/dist/ui/hooks/slashCommandProcessor.d.ts.map +1 -0
- package/dist/ui/hooks/slashCommandProcessor.js +100 -0
- package/dist/ui/hooks/slashCommandProcessor.js.map +1 -0
- package/dist/ui/hooks/useCommandBrowserState.d.ts +12 -0
- package/dist/ui/hooks/useCommandBrowserState.d.ts.map +1 -0
- package/dist/ui/hooks/useCommandBrowserState.js +66 -0
- package/dist/ui/hooks/useCommandBrowserState.js.map +1 -0
- package/dist/ui/hooks/useFileBrowserState.d.ts +15 -0
- package/dist/ui/hooks/useFileBrowserState.d.ts.map +1 -0
- package/dist/ui/hooks/useFileBrowserState.js +80 -0
- package/dist/ui/hooks/useFileBrowserState.js.map +1 -0
- package/dist/ui/hooks/useFileList.d.ts +20 -0
- package/dist/ui/hooks/useFileList.d.ts.map +1 -0
- package/dist/ui/hooks/useFileList.js +57 -0
- package/dist/ui/hooks/useFileList.js.map +1 -0
- package/dist/ui/hooks/useInputHistory.d.ts +9 -0
- package/dist/ui/hooks/useInputHistory.d.ts.map +1 -0
- package/dist/ui/hooks/useInputHistory.js +68 -0
- package/dist/ui/hooks/useInputHistory.js.map +1 -0
- package/dist/ui/hooks/usePlanExecution.d.ts +8 -0
- package/dist/ui/hooks/usePlanExecution.d.ts.map +1 -0
- package/dist/ui/hooks/usePlanExecution.js +214 -0
- package/dist/ui/hooks/usePlanExecution.js.map +1 -0
- package/dist/ui/index.d.ts +7 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +7 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/ink-entry.d.ts +3 -0
- package/dist/ui/ink-entry.d.ts.map +1 -0
- package/dist/ui/ink-entry.js +22 -0
- package/dist/ui/ink-entry.js.map +1 -0
- package/dist/utils/env-filter.d.ts +4 -0
- package/dist/utils/env-filter.d.ts.map +1 -0
- package/dist/utils/env-filter.js +101 -0
- package/dist/utils/env-filter.js.map +1 -0
- package/dist/utils/file-system.d.ts +9 -0
- package/dist/utils/file-system.d.ts.map +1 -0
- package/dist/utils/file-system.js +99 -0
- package/dist/utils/file-system.js.map +1 -0
- package/dist/utils/git-utils.d.ts +2 -0
- package/dist/utils/git-utils.d.ts.map +1 -0
- package/dist/utils/git-utils.js +16 -0
- package/dist/utils/git-utils.js.map +1 -0
- package/dist/utils/json-stream-logger.d.ts +74 -0
- package/dist/utils/json-stream-logger.d.ts.map +1 -0
- package/dist/utils/json-stream-logger.js +808 -0
- package/dist/utils/json-stream-logger.js.map +1 -0
- package/dist/utils/logger.d.ts +152 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +1672 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/platform-utils.d.ts +19 -0
- package/dist/utils/platform-utils.d.ts.map +1 -0
- package/dist/utils/platform-utils.js +134 -0
- package/dist/utils/platform-utils.js.map +1 -0
- package/dist/utils/wsl-utils.d.ts +4 -0
- package/dist/utils/wsl-utils.d.ts.map +1 -0
- package/dist/utils/wsl-utils.js +72 -0
- package/dist/utils/wsl-utils.js.map +1 -0
- package/electron.vite.config.ts +63 -0
- package/google374b9eba0c52b043.html +1 -0
- package/package.json +122 -0
- package/src/agents/base/base-agent.ts +159 -0
- package/src/agents/docs-search/index.ts +365 -0
- package/src/agents/index.ts +34 -0
- package/src/agents/planner/index.ts +544 -0
- package/src/cli.ts +201 -0
- package/src/constants.ts +47 -0
- package/src/core/compact/compact-manager.ts +160 -0
- package/src/core/compact/compact-prompts.ts +150 -0
- package/src/core/compact/context-tracker.ts +164 -0
- package/src/core/compact/index.ts +25 -0
- package/src/core/config/config-manager.ts +460 -0
- package/src/core/config/index.ts +5 -0
- package/src/core/docs-manager.ts +678 -0
- package/src/core/llm/index.ts +7 -0
- package/src/core/llm/llm-client.ts +1550 -0
- package/src/core/session/index.ts +5 -0
- package/src/core/session/session-manager.ts +464 -0
- package/src/core/slash-command-handler.ts +410 -0
- package/src/core/usage-tracker.ts +438 -0
- package/src/errors/base.ts +81 -0
- package/src/errors/file.ts +183 -0
- package/src/errors/index.ts +95 -0
- package/src/errors/llm.ts +151 -0
- package/src/errors/network.ts +124 -0
- package/src/errors/validation.ts +111 -0
- package/src/eval/eval-runner.ts +456 -0
- package/src/eval/index.ts +8 -0
- package/src/eval/types.ts +139 -0
- package/src/index.ts +22 -0
- package/src/orchestration/index.ts +30 -0
- package/src/orchestration/plan-executor.ts +652 -0
- package/src/orchestration/types.ts +127 -0
- package/src/orchestration/utils.ts +119 -0
- package/src/orquesta/connection.ts +291 -0
- package/src/prompts/agents/docs-search-decision.ts +74 -0
- package/src/prompts/agents/docs-search.ts +84 -0
- package/src/prompts/agents/planning.ts +143 -0
- package/src/prompts/index.ts +31 -0
- package/src/prompts/shared/codebase-rules.ts +29 -0
- package/src/prompts/shared/git-rules.ts +94 -0
- package/src/prompts/shared/language-rules.ts +36 -0
- package/src/prompts/shared/tool-usage.ts +72 -0
- package/src/prompts/system/compact.ts +80 -0
- package/src/prompts/system/plan-execute.ts +89 -0
- package/src/tools/browser/browser-client.ts +1363 -0
- package/src/tools/browser/browser-tools.ts +1139 -0
- package/src/tools/browser/index.ts +65 -0
- package/src/tools/index.ts +23 -0
- package/src/tools/llm/agents/docs-search-tools.ts +368 -0
- package/src/tools/llm/agents/index.ts +22 -0
- package/src/tools/llm/index.ts +11 -0
- package/src/tools/llm/simple/ask-user-tool.ts +25 -0
- package/src/tools/llm/simple/background-bash-tool.ts +443 -0
- package/src/tools/llm/simple/background-powershell-tool.ts +421 -0
- package/src/tools/llm/simple/bash-tool.ts +238 -0
- package/src/tools/llm/simple/docs-search-agent-tool.ts +146 -0
- package/src/tools/llm/simple/file-tools.ts +1051 -0
- package/src/tools/llm/simple/final-response-tool.ts +180 -0
- package/src/tools/llm/simple/index.ts +42 -0
- package/src/tools/llm/simple/planning-tools.ts +143 -0
- package/src/tools/llm/simple/powershell-tool.ts +241 -0
- package/src/tools/llm/simple/simple-tool-executor.ts +279 -0
- package/src/tools/llm/simple/todo-tools.ts +207 -0
- package/src/tools/llm/simple/user-interaction-tools.ts +277 -0
- package/src/tools/office/common/constants.ts +335 -0
- package/src/tools/office/common/index.ts +133 -0
- package/src/tools/office/common/types.ts +286 -0
- package/src/tools/office/common/utils.ts +116 -0
- package/src/tools/office/excel-client.ts +1336 -0
- package/src/tools/office/excel-tools/cells.ts +359 -0
- package/src/tools/office/excel-tools/charts.ts +166 -0
- package/src/tools/office/excel-tools/comments.ts +155 -0
- package/src/tools/office/excel-tools/data-ops.ts +349 -0
- package/src/tools/office/excel-tools/export.ts +105 -0
- package/src/tools/office/excel-tools/formatting.ts +357 -0
- package/src/tools/office/excel-tools/index.ts +55 -0
- package/src/tools/office/excel-tools/launch.ts +303 -0
- package/src/tools/office/excel-tools/media.ts +117 -0
- package/src/tools/office/excel-tools/named-ranges.ts +148 -0
- package/src/tools/office/excel-tools/protection.ts +105 -0
- package/src/tools/office/excel-tools/rows-columns.ts +386 -0
- package/src/tools/office/excel-tools/sheets.ts +228 -0
- package/src/tools/office/excel-tools/validation.ts +226 -0
- package/src/tools/office/excel-tools.ts +9 -0
- package/src/tools/office/index.ts +259 -0
- package/src/tools/office/office-client-base.ts +242 -0
- package/src/tools/office/office-client.ts +377 -0
- package/src/tools/office/powerpoint-client.ts +1498 -0
- package/src/tools/office/powerpoint-tools/effects.ts +315 -0
- package/src/tools/office/powerpoint-tools/export.ts +138 -0
- package/src/tools/office/powerpoint-tools/index.ts +45 -0
- package/src/tools/office/powerpoint-tools/launch.ts +263 -0
- package/src/tools/office/powerpoint-tools/media.ts +291 -0
- package/src/tools/office/powerpoint-tools/notes.ts +220 -0
- package/src/tools/office/powerpoint-tools/sections.ts +140 -0
- package/src/tools/office/powerpoint-tools/shapes.ts +870 -0
- package/src/tools/office/powerpoint-tools/slides.ts +350 -0
- package/src/tools/office/powerpoint-tools/tables.ts +182 -0
- package/src/tools/office/powerpoint-tools/text.ts +473 -0
- package/src/tools/office/powerpoint-tools.ts +9 -0
- package/src/tools/office/word-client.ts +1697 -0
- package/src/tools/office/word-tools/bookmarks.ts +186 -0
- package/src/tools/office/word-tools/comments.ts +185 -0
- package/src/tools/office/word-tools/content.ts +229 -0
- package/src/tools/office/word-tools/export.ts +97 -0
- package/src/tools/office/word-tools/formatting.ts +161 -0
- package/src/tools/office/word-tools/headers-footers.ts +155 -0
- package/src/tools/office/word-tools/index.ts +57 -0
- package/src/tools/office/word-tools/launch.ts +312 -0
- package/src/tools/office/word-tools/lists.ts +97 -0
- package/src/tools/office/word-tools/navigation.ts +114 -0
- package/src/tools/office/word-tools/page-setup.ts +195 -0
- package/src/tools/office/word-tools/tables.ts +262 -0
- package/src/tools/office/word-tools/text.ts +294 -0
- package/src/tools/office/word-tools/undo-redo.ts +97 -0
- package/src/tools/office/word-tools/watermarks.ts +105 -0
- package/src/tools/office/word-tools.ts +9 -0
- package/src/tools/registry.ts +527 -0
- package/src/tools/types.ts +231 -0
- package/src/types/index.ts +181 -0
- package/src/ui/PlanExecuteView.tsx +119 -0
- package/src/ui/TodoPanel.tsx +240 -0
- package/src/ui/UpdateNotification.tsx +105 -0
- package/src/ui/components/ActivityIndicator.tsx +234 -0
- package/src/ui/components/CommandBrowser.tsx +114 -0
- package/src/ui/components/CustomTextInput.tsx +389 -0
- package/src/ui/components/DocsSearchProgress.tsx +85 -0
- package/src/ui/components/FileBrowser.tsx +93 -0
- package/src/ui/components/LLMSetupWizard.tsx +333 -0
- package/src/ui/components/Logo.tsx +125 -0
- package/src/ui/components/MarkdownRenderer.tsx +358 -0
- package/src/ui/components/ModelSelector.tsx +203 -0
- package/src/ui/components/PlanExecuteApp.tsx +2007 -0
- package/src/ui/components/ProgressBar.tsx +51 -0
- package/src/ui/components/StatusBar.tsx +302 -0
- package/src/ui/components/ThinkingIndicator.tsx +120 -0
- package/src/ui/components/TodoListView.tsx +140 -0
- package/src/ui/components/ToolSelector.tsx +215 -0
- package/src/ui/components/dialogs/ApprovalDialog.tsx +259 -0
- package/src/ui/components/dialogs/AskUserDialog.tsx +159 -0
- package/src/ui/components/dialogs/DocsBrowser.tsx +222 -0
- package/src/ui/components/dialogs/SettingsDialog.tsx +939 -0
- package/src/ui/components/dialogs/index.ts +13 -0
- package/src/ui/components/index.ts +27 -0
- package/src/ui/components/panels/LogPanel.tsx +385 -0
- package/src/ui/components/panels/SessionPanel.tsx +146 -0
- package/src/ui/components/panels/index.ts +13 -0
- package/src/ui/components/views/ChatView.tsx +447 -0
- package/src/ui/components/views/index.ts +5 -0
- package/src/ui/contexts/TokenContext.tsx +139 -0
- package/src/ui/hooks/atFileProcessor.ts +167 -0
- package/src/ui/hooks/index.ts +11 -0
- package/src/ui/hooks/slashCommandProcessor.ts +174 -0
- package/src/ui/hooks/useCommandBrowserState.ts +97 -0
- package/src/ui/hooks/useFileBrowserState.ts +116 -0
- package/src/ui/hooks/useFileList.ts +132 -0
- package/src/ui/hooks/useInputHistory.ts +89 -0
- package/src/ui/hooks/usePlanExecution.ts +339 -0
- package/src/ui/index.ts +10 -0
- package/src/ui/ink-entry.tsx +36 -0
- package/src/utils/env-filter.ts +164 -0
- package/src/utils/file-system.ts +133 -0
- package/src/utils/git-utils.ts +30 -0
- package/src/utils/json-stream-logger.ts +1259 -0
- package/src/utils/logger.ts +2767 -0
- package/src/utils/platform-utils.ts +256 -0
- package/src/utils/wsl-utils.ts +113 -0
- package/tsconfig.electron.json +39 -0
- package/tsconfig.json +64 -0
|
@@ -0,0 +1,2007 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan & Execute Interactive App
|
|
3
|
+
*
|
|
4
|
+
* Enhanced interactive mode with Plan-and-Execute Architecture
|
|
5
|
+
* Refactored to use modular hooks and components
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { useState, useCallback, useEffect, useMemo } from 'react';
|
|
9
|
+
import { Box, Text, useInput, useApp, Static } from 'ink';
|
|
10
|
+
import Spinner from 'ink-spinner';
|
|
11
|
+
import os from 'os';
|
|
12
|
+
import { spawn } from 'child_process';
|
|
13
|
+
import { detectGitRepo } from '../../utils/git-utils.js';
|
|
14
|
+
import { getShellConfig, isNativeWindows } from '../../utils/platform-utils.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Log entry types for Static scrollable output
|
|
18
|
+
*/
|
|
19
|
+
export type LogEntryType =
|
|
20
|
+
| 'logo'
|
|
21
|
+
| 'user_input'
|
|
22
|
+
| 'assistant_message'
|
|
23
|
+
| 'tool_start'
|
|
24
|
+
| 'tool_result'
|
|
25
|
+
| 'shell_result'
|
|
26
|
+
| 'tell_user'
|
|
27
|
+
| 'plan_created'
|
|
28
|
+
| 'todo_start'
|
|
29
|
+
| 'todo_complete'
|
|
30
|
+
| 'todo_fail'
|
|
31
|
+
| 'compact'
|
|
32
|
+
| 'approval_request'
|
|
33
|
+
| 'approval_response'
|
|
34
|
+
| 'interrupt'
|
|
35
|
+
| 'session_restored'
|
|
36
|
+
| 'docs_search'
|
|
37
|
+
| 'reasoning'
|
|
38
|
+
| 'git_info';
|
|
39
|
+
|
|
40
|
+
export interface LogEntry {
|
|
41
|
+
id: string;
|
|
42
|
+
type: LogEntryType;
|
|
43
|
+
content: string;
|
|
44
|
+
details?: string;
|
|
45
|
+
toolArgs?: Record<string, unknown>; // For tool_start (all args)
|
|
46
|
+
success?: boolean;
|
|
47
|
+
items?: string[]; // For plan_created (todo list)
|
|
48
|
+
diff?: string[]; // For tool_result with diff
|
|
49
|
+
}
|
|
50
|
+
import { CustomTextInput } from './CustomTextInput.js';
|
|
51
|
+
import { LLMClient, createLLMClient } from '../../core/llm/llm-client.js';
|
|
52
|
+
import { Message } from '../../types/index.js';
|
|
53
|
+
import { TodoPanel, TodoStatusBar } from '../TodoPanel.js';
|
|
54
|
+
import { sessionManager } from '../../core/session/session-manager.js';
|
|
55
|
+
import { initializeDocsDirectory, setDocsSearchProgressCallback } from '../../agents/docs-search/index.js';
|
|
56
|
+
import { DocsSearchProgress, type DocsSearchLog } from './DocsSearchProgress.js';
|
|
57
|
+
import { FileBrowser } from './FileBrowser.js';
|
|
58
|
+
import { SessionBrowser, LogBrowser } from './panels/index.js';
|
|
59
|
+
import { SettingsBrowser } from './dialogs/SettingsDialog.js';
|
|
60
|
+
import { LLMSetupWizard } from './LLMSetupWizard.js';
|
|
61
|
+
import { ModelSelector } from './ModelSelector.js';
|
|
62
|
+
import { ToolSelector } from './ToolSelector.js';
|
|
63
|
+
import { AskUserDialog } from './dialogs/AskUserDialog.js';
|
|
64
|
+
import { ApprovalDialog } from './dialogs/ApprovalDialog.js';
|
|
65
|
+
// DISABLED: DocsBrowser removed - docs feature disabled
|
|
66
|
+
// import { DocsBrowser } from './dialogs/DocsBrowser.js';
|
|
67
|
+
import { CommandBrowser } from './CommandBrowser.js';
|
|
68
|
+
// ChatView removed - using Static log instead
|
|
69
|
+
import { Logo } from './Logo.js';
|
|
70
|
+
import { MarkdownRenderer } from './MarkdownRenderer.js';
|
|
71
|
+
import { ActivityIndicator, type ActivityType, type SubActivity } from './ActivityIndicator.js';
|
|
72
|
+
import { useFileBrowserState } from '../hooks/useFileBrowserState.js';
|
|
73
|
+
import { useCommandBrowserState } from '../hooks/useCommandBrowserState.js';
|
|
74
|
+
import { usePlanExecution } from '../hooks/usePlanExecution.js';
|
|
75
|
+
import { useInputHistory } from '../hooks/useInputHistory.js';
|
|
76
|
+
import { isValidCommand } from '../hooks/slashCommandProcessor.js';
|
|
77
|
+
import { processFileReferences } from '../hooks/atFileProcessor.js';
|
|
78
|
+
import {
|
|
79
|
+
executeSlashCommand,
|
|
80
|
+
isSlashCommand,
|
|
81
|
+
type CommandHandlerContext,
|
|
82
|
+
type PlanningMode,
|
|
83
|
+
} from '../../core/slash-command-handler.js';
|
|
84
|
+
import { closeJsonStreamLogger } from '../../utils/json-stream-logger.js';
|
|
85
|
+
import { configManager } from '../../core/config/config-manager.js';
|
|
86
|
+
import { logger } from '../../utils/logger.js';
|
|
87
|
+
import { usageTracker } from '../../core/usage-tracker.js';
|
|
88
|
+
import {
|
|
89
|
+
setToolExecutionCallback,
|
|
90
|
+
setTellToUserCallback,
|
|
91
|
+
setToolResponseCallback,
|
|
92
|
+
setPlanCreatedCallback,
|
|
93
|
+
setTodoStartCallback,
|
|
94
|
+
setTodoCompleteCallback,
|
|
95
|
+
setTodoFailCallback,
|
|
96
|
+
setCompactCallback,
|
|
97
|
+
setAssistantResponseCallback,
|
|
98
|
+
setToolApprovalCallback,
|
|
99
|
+
setReasoningCallback,
|
|
100
|
+
type ToolApprovalResult,
|
|
101
|
+
} from '../../tools/llm/simple/file-tools.js';
|
|
102
|
+
import { createRequire } from 'module';
|
|
103
|
+
|
|
104
|
+
// Get version from package.json
|
|
105
|
+
const require = createRequire(import.meta.url);
|
|
106
|
+
const pkg = require('../../../package.json') as { version: string };
|
|
107
|
+
const VERSION = pkg.version;
|
|
108
|
+
|
|
109
|
+
// Initialization steps for detailed progress display
|
|
110
|
+
type InitStep = 'health' | 'docs' | 'config' | 'done';
|
|
111
|
+
|
|
112
|
+
// Tools that require user approval in Supervised Mode
|
|
113
|
+
// File-modifying tools and bash commands need approval (read-only and internal tools are auto-approved)
|
|
114
|
+
const TOOLS_REQUIRING_APPROVAL = new Set(['create_file', 'edit_file', 'bash']);
|
|
115
|
+
|
|
116
|
+
// Clean startup tip - shown once at start
|
|
117
|
+
const STARTUP_TIP = 'Type /help for available commands. Type /model to switch models.';
|
|
118
|
+
|
|
119
|
+
// Helper function to shorten path with ~ for home directory
|
|
120
|
+
function shortenPath(fullPath: string): string {
|
|
121
|
+
const homeDir = os.homedir();
|
|
122
|
+
if (fullPath.startsWith(homeDir)) {
|
|
123
|
+
return fullPath.replace(homeDir, '~');
|
|
124
|
+
}
|
|
125
|
+
return fullPath;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Helper functions for status bar
|
|
129
|
+
function formatElapsedTime(seconds: number): string {
|
|
130
|
+
if (seconds < 60) {
|
|
131
|
+
return `${seconds}s`;
|
|
132
|
+
}
|
|
133
|
+
const mins = Math.floor(seconds / 60);
|
|
134
|
+
const secs = seconds % 60;
|
|
135
|
+
return `${mins}m ${secs}s`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function formatTokensCompact(count: number): string {
|
|
139
|
+
if (count < 1000) return count.toString();
|
|
140
|
+
if (count < 1000000) return `${(count / 1000).toFixed(1)}k`;
|
|
141
|
+
return `${(count / 1000000).toFixed(2)}M`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Helper function for status bar text
|
|
145
|
+
interface StatusTextParams {
|
|
146
|
+
phase: string;
|
|
147
|
+
todos: { status: string }[];
|
|
148
|
+
currentToolName: string | null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function getStatusText({ phase, todos, currentToolName }: StatusTextParams): string {
|
|
152
|
+
const completedCount = todos.filter(t => t.status === 'completed').length;
|
|
153
|
+
const totalCount = todos.length;
|
|
154
|
+
const allTodosCompleted = totalCount > 0 && todos.every(t => t.status === 'completed' || t.status === 'failed');
|
|
155
|
+
|
|
156
|
+
// Build progress prefix (only show when tasks exist)
|
|
157
|
+
const progressPrefix = totalCount > 0 ? `${completedCount}/${totalCount} tasks · ` : '';
|
|
158
|
+
|
|
159
|
+
// Compacting
|
|
160
|
+
if (phase === 'compacting') {
|
|
161
|
+
return 'Compacting conversation';
|
|
162
|
+
}
|
|
163
|
+
// All TODOs completed, generating final response
|
|
164
|
+
if (phase === 'executing' && allTodosCompleted) {
|
|
165
|
+
return `${progressPrefix}Generating response`;
|
|
166
|
+
}
|
|
167
|
+
// Planning/Thinking
|
|
168
|
+
if (phase === 'planning') {
|
|
169
|
+
return 'Thinking';
|
|
170
|
+
}
|
|
171
|
+
// Tool is running - show tool name
|
|
172
|
+
if (currentToolName) {
|
|
173
|
+
return `${progressPrefix}${currentToolName}`;
|
|
174
|
+
}
|
|
175
|
+
// Default: processing
|
|
176
|
+
return `${progressPrefix}Processing`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Status bar uses ink-spinner for animation (avoids custom render issues)
|
|
180
|
+
|
|
181
|
+
interface PlanExecuteAppProps {
|
|
182
|
+
llmClient: LLMClient | null;
|
|
183
|
+
modelInfo: {
|
|
184
|
+
model: string;
|
|
185
|
+
endpoint: string;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export const PlanExecuteApp: React.FC<PlanExecuteAppProps> = ({ llmClient: initialLlmClient, modelInfo }) => {
|
|
190
|
+
const { exit } = useApp();
|
|
191
|
+
const [messages, setMessages] = useState<Message[]>([]);
|
|
192
|
+
const { input, setInput, handleHistoryPrev, handleHistoryNext, addToHistory } = useInputHistory();
|
|
193
|
+
const [isProcessing, setIsProcessing] = useState(false);
|
|
194
|
+
// Planning mode is always 'auto' - mode selection has been removed
|
|
195
|
+
const planningMode: PlanningMode = 'auto';
|
|
196
|
+
|
|
197
|
+
// LLM Client state - replace with new client when model changes
|
|
198
|
+
const [llmClient, setLlmClient] = useState<LLMClient | null>(initialLlmClient);
|
|
199
|
+
|
|
200
|
+
// Activity tracking for detailed status display
|
|
201
|
+
const [activityType, setActivityType] = useState<ActivityType>('thinking');
|
|
202
|
+
const [activityStartTime, setActivityStartTime] = useState<number>(Date.now());
|
|
203
|
+
const [activityDetail, setActivityDetail] = useState<string>('');
|
|
204
|
+
const [subActivities, setSubActivities] = useState<SubActivity[]>([]);
|
|
205
|
+
|
|
206
|
+
// Session usage tracking for Claude Code style status bar
|
|
207
|
+
const [sessionTokens, setSessionTokens] = useState(0);
|
|
208
|
+
const [sessionElapsed, setSessionElapsed] = useState(0);
|
|
209
|
+
|
|
210
|
+
// Current tool being executed (for status bar)
|
|
211
|
+
const [currentToolName, setCurrentToolName] = useState<string | null>(null);
|
|
212
|
+
|
|
213
|
+
// Session browser state
|
|
214
|
+
const [showSessionBrowser, setShowSessionBrowser] = useState(false);
|
|
215
|
+
|
|
216
|
+
// Settings browser state
|
|
217
|
+
const [showSettings, setShowSettings] = useState(false);
|
|
218
|
+
|
|
219
|
+
// LLM Setup Wizard state
|
|
220
|
+
const [showSetupWizard, setShowSetupWizard] = useState(false);
|
|
221
|
+
const [isInitializing, setIsInitializing] = useState(true);
|
|
222
|
+
const [initStep, setInitStep] = useState<InitStep>('docs');
|
|
223
|
+
const [healthStatus, setHealthStatus] = useState<'checking' | 'healthy' | 'unhealthy' | 'unknown'>('checking');
|
|
224
|
+
|
|
225
|
+
// Model Selector state
|
|
226
|
+
const [showModelSelector, setShowModelSelector] = useState(false);
|
|
227
|
+
const [currentModelInfo, setCurrentModelInfo] = useState(modelInfo);
|
|
228
|
+
|
|
229
|
+
// DISABLED: Docs Browser state removed - docs feature disabled
|
|
230
|
+
// const [showDocsBrowser, setShowDocsBrowser] = useState(false);
|
|
231
|
+
const showDocsBrowser = false; // Always false - docs feature disabled
|
|
232
|
+
|
|
233
|
+
// Tool Selector state
|
|
234
|
+
const [showToolSelector, setShowToolSelector] = useState(false);
|
|
235
|
+
|
|
236
|
+
// Log files visibility (Ctrl+O toggle)
|
|
237
|
+
const [showLogFiles, setShowLogFiles] = useState(false);
|
|
238
|
+
|
|
239
|
+
// Execution mode: 'auto' (autonomous) or 'supervised' (requires user approval)
|
|
240
|
+
const [executionMode, setExecutionMode] = useState<'auto' | 'supervised'>('auto');
|
|
241
|
+
|
|
242
|
+
// Auto-approved tools for this session (only in supervised mode)
|
|
243
|
+
const [autoApprovedTools, setAutoApprovedTools] = useState<Set<string>>(new Set());
|
|
244
|
+
|
|
245
|
+
// Pending tool approval state
|
|
246
|
+
const [pendingToolApproval, setPendingToolApproval] = useState<{
|
|
247
|
+
toolName: string;
|
|
248
|
+
args: Record<string, unknown>;
|
|
249
|
+
reason?: string;
|
|
250
|
+
resolve: (result: 'approve' | 'always' | { reject: true; comment: string }) => void;
|
|
251
|
+
} | null>(null);
|
|
252
|
+
|
|
253
|
+
// Static log entries for scrollable history
|
|
254
|
+
const [logEntries, setLogEntries] = useState<LogEntry[]>([]);
|
|
255
|
+
const logIdCounter = React.useRef(0);
|
|
256
|
+
const lastToolArgsRef = React.useRef<Record<string, unknown> | null>(null);
|
|
257
|
+
|
|
258
|
+
// Docs search progress state
|
|
259
|
+
const [docsSearchLogs, setDocsSearchLogs] = useState<DocsSearchLog[]>([]);
|
|
260
|
+
const [isDocsSearching, setIsDocsSearching] = useState(false);
|
|
261
|
+
|
|
262
|
+
// Pending user message queue (for messages entered during LLM processing)
|
|
263
|
+
const [pendingUserMessage, setPendingUserMessage] = useState<string | null>(null);
|
|
264
|
+
const pendingUserMessageRef = React.useRef<string | null>(null);
|
|
265
|
+
|
|
266
|
+
// Keep ref in sync with state for synchronous access in LLM loop
|
|
267
|
+
useEffect(() => {
|
|
268
|
+
pendingUserMessageRef.current = pendingUserMessage;
|
|
269
|
+
}, [pendingUserMessage]);
|
|
270
|
+
|
|
271
|
+
// Pending message callbacks for mid-execution injection
|
|
272
|
+
const pendingMessageCallbacks = useMemo(() => ({
|
|
273
|
+
getPendingMessage: () => pendingUserMessageRef.current,
|
|
274
|
+
clearPendingMessage: () => {
|
|
275
|
+
pendingUserMessageRef.current = null;
|
|
276
|
+
setPendingUserMessage(null);
|
|
277
|
+
},
|
|
278
|
+
}), []);
|
|
279
|
+
|
|
280
|
+
// Ctrl+C double-tap tracking for exit
|
|
281
|
+
const lastCtrlCTimeRef = React.useRef<number>(0);
|
|
282
|
+
const DOUBLE_TAP_THRESHOLD = 1500; // 1.5 seconds
|
|
283
|
+
|
|
284
|
+
// Helper: add log entry (skip if content is empty/whitespace only)
|
|
285
|
+
const addLog = useCallback((entry: Omit<LogEntry, 'id'>) => {
|
|
286
|
+
// Skip empty content to prevent blank lines
|
|
287
|
+
if (!entry.content || entry.content.trim() === '') {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const id = `log-${++logIdCounter.current}`;
|
|
291
|
+
setLogEntries(prev => [...prev, { ...entry, id }]);
|
|
292
|
+
}, []);
|
|
293
|
+
|
|
294
|
+
// Helper: clear logs (for compact)
|
|
295
|
+
const clearLogs = useCallback(() => {
|
|
296
|
+
setLogEntries([]);
|
|
297
|
+
logIdCounter.current = 0;
|
|
298
|
+
}, []);
|
|
299
|
+
|
|
300
|
+
// Sync log entries to session manager for auto-save
|
|
301
|
+
useEffect(() => {
|
|
302
|
+
sessionManager.setLogEntries(logEntries);
|
|
303
|
+
}, [logEntries]);
|
|
304
|
+
|
|
305
|
+
// Use modular hooks
|
|
306
|
+
const fileBrowserState = useFileBrowserState(input, isProcessing);
|
|
307
|
+
const commandBrowserState = useCommandBrowserState(input, isProcessing);
|
|
308
|
+
const planExecutionState = usePlanExecution(pendingMessageCallbacks);
|
|
309
|
+
|
|
310
|
+
// Sync todos to session manager for auto-save (only in-progress/pending)
|
|
311
|
+
useEffect(() => {
|
|
312
|
+
sessionManager.setTodos(planExecutionState.todos);
|
|
313
|
+
}, [planExecutionState.todos]);
|
|
314
|
+
|
|
315
|
+
// Print logo at startup
|
|
316
|
+
useEffect(() => {
|
|
317
|
+
addLog({
|
|
318
|
+
type: 'logo',
|
|
319
|
+
content: `v${VERSION} │ ${modelInfo.model}`,
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// Check for .git and show notification
|
|
323
|
+
const isGitRepo = detectGitRepo();
|
|
324
|
+
if (isGitRepo) {
|
|
325
|
+
addLog({
|
|
326
|
+
type: 'git_info',
|
|
327
|
+
content: 'Git repository detected! Commit assistance enabled.',
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}, []);
|
|
331
|
+
|
|
332
|
+
// Log component mount
|
|
333
|
+
useEffect(() => {
|
|
334
|
+
logger.enter('PlanExecuteApp', { modelInfo });
|
|
335
|
+
return () => {
|
|
336
|
+
logger.exit('PlanExecuteApp', { messageCount: messages.length });
|
|
337
|
+
};
|
|
338
|
+
}, []);
|
|
339
|
+
|
|
340
|
+
// Setup tool execution callback - adds to Static log
|
|
341
|
+
useEffect(() => {
|
|
342
|
+
setToolExecutionCallback((toolName, reason, args) => {
|
|
343
|
+
// Save args for tool_result to use (for create_file content display)
|
|
344
|
+
lastToolArgsRef.current = args;
|
|
345
|
+
// Track current tool for status bar
|
|
346
|
+
setCurrentToolName(toolName);
|
|
347
|
+
addLog({
|
|
348
|
+
type: 'tool_start',
|
|
349
|
+
content: toolName,
|
|
350
|
+
details: reason, // don't truncate reason
|
|
351
|
+
toolArgs: args,
|
|
352
|
+
});
|
|
353
|
+
logger.debug('Tool execution started', { toolName, reason, args });
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
return () => {
|
|
357
|
+
setToolExecutionCallback(null);
|
|
358
|
+
};
|
|
359
|
+
}, [addLog]);
|
|
360
|
+
|
|
361
|
+
// Setup tool response callback - adds to Static log
|
|
362
|
+
useEffect(() => {
|
|
363
|
+
setToolResponseCallback((toolName, success, result) => {
|
|
364
|
+
// Clear current tool when done
|
|
365
|
+
setCurrentToolName(null);
|
|
366
|
+
|
|
367
|
+
// Try parsing diff content
|
|
368
|
+
let diff: string[] | undefined;
|
|
369
|
+
try {
|
|
370
|
+
const parsed = JSON.parse(result);
|
|
371
|
+
if (parsed.diff && Array.isArray(parsed.diff)) {
|
|
372
|
+
diff = parsed.diff;
|
|
373
|
+
}
|
|
374
|
+
} catch {
|
|
375
|
+
// not JSON, use as-is
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Get saved args for create_file content display
|
|
379
|
+
const savedArgs = lastToolArgsRef.current;
|
|
380
|
+
lastToolArgsRef.current = null;
|
|
381
|
+
|
|
382
|
+
addLog({
|
|
383
|
+
type: 'tool_result',
|
|
384
|
+
content: toolName,
|
|
385
|
+
details: result, // preserve full content
|
|
386
|
+
success,
|
|
387
|
+
diff,
|
|
388
|
+
toolArgs: savedArgs || undefined, // Pass args for create_file
|
|
389
|
+
});
|
|
390
|
+
logger.debug('Tool execution completed', { toolName, success, result });
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
return () => {
|
|
394
|
+
setToolResponseCallback(null);
|
|
395
|
+
};
|
|
396
|
+
}, [addLog]);
|
|
397
|
+
|
|
398
|
+
// Setup tell_to_user callback - adds to Static log
|
|
399
|
+
useEffect(() => {
|
|
400
|
+
setTellToUserCallback((message) => {
|
|
401
|
+
addLog({
|
|
402
|
+
type: 'tell_user',
|
|
403
|
+
content: message, // don't truncate
|
|
404
|
+
});
|
|
405
|
+
logger.debug('Message to user', { message });
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
return () => {
|
|
409
|
+
setTellToUserCallback(null);
|
|
410
|
+
};
|
|
411
|
+
}, [addLog]);
|
|
412
|
+
|
|
413
|
+
// Setup assistant response callback - adds to Static log
|
|
414
|
+
useEffect(() => {
|
|
415
|
+
setAssistantResponseCallback((content) => {
|
|
416
|
+
addLog({
|
|
417
|
+
type: 'assistant_message',
|
|
418
|
+
content,
|
|
419
|
+
});
|
|
420
|
+
logger.debug('Assistant response received', { contentLength: content.length });
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
return () => {
|
|
424
|
+
setAssistantResponseCallback(null);
|
|
425
|
+
};
|
|
426
|
+
}, [addLog]);
|
|
427
|
+
|
|
428
|
+
// Setup reasoning callback - adds to Static log (non-streaming only)
|
|
429
|
+
// Note: Streaming updates to Static items cause render issues, so we only support non-streaming
|
|
430
|
+
useEffect(() => {
|
|
431
|
+
setReasoningCallback((content, _isStreaming) => {
|
|
432
|
+
// Always add as new entry (don't update existing Static items)
|
|
433
|
+
addLog({
|
|
434
|
+
type: 'reasoning',
|
|
435
|
+
content,
|
|
436
|
+
});
|
|
437
|
+
logger.debug('Reasoning received', { contentLength: content.length });
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
return () => {
|
|
441
|
+
setReasoningCallback(null);
|
|
442
|
+
};
|
|
443
|
+
}, [addLog]);
|
|
444
|
+
|
|
445
|
+
// Setup tool approval callback (Supervised Mode)
|
|
446
|
+
useEffect(() => {
|
|
447
|
+
setToolApprovalCallback(async (toolName, args, reason) => {
|
|
448
|
+
// Auto mode: no approval needed
|
|
449
|
+
if (executionMode === 'auto') {
|
|
450
|
+
return 'approve';
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Only file-modifying tools require approval
|
|
454
|
+
if (!TOOLS_REQUIRING_APPROVAL.has(toolName)) {
|
|
455
|
+
return 'approve';
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Check if this tool is already auto-approved for this session
|
|
459
|
+
if (autoApprovedTools.has(toolName)) {
|
|
460
|
+
logger.debug('Tool auto-approved from session', { toolName });
|
|
461
|
+
return 'approve';
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// Add approval request to log
|
|
465
|
+
addLog({
|
|
466
|
+
type: 'approval_request',
|
|
467
|
+
content: toolName,
|
|
468
|
+
details: reason,
|
|
469
|
+
toolArgs: args,
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// Request approval from user via dialog
|
|
473
|
+
return new Promise<ToolApprovalResult>((resolve) => {
|
|
474
|
+
setPendingToolApproval({
|
|
475
|
+
toolName,
|
|
476
|
+
args,
|
|
477
|
+
reason,
|
|
478
|
+
resolve,
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
return () => {
|
|
484
|
+
setToolApprovalCallback(null);
|
|
485
|
+
};
|
|
486
|
+
}, [executionMode, autoApprovedTools, addLog]);
|
|
487
|
+
|
|
488
|
+
// Setup docs search progress callback
|
|
489
|
+
useEffect(() => {
|
|
490
|
+
setDocsSearchProgressCallback((type, message, data) => {
|
|
491
|
+
// Handle completion
|
|
492
|
+
if (type === 'complete') {
|
|
493
|
+
// Add result to static log with summary
|
|
494
|
+
addLog({
|
|
495
|
+
type: 'docs_search',
|
|
496
|
+
content: data?.summary || message,
|
|
497
|
+
details: data?.findings,
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
// Clear progress state
|
|
501
|
+
setIsDocsSearching(false);
|
|
502
|
+
setDocsSearchLogs([]);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Start docs search on first log
|
|
507
|
+
setIsDocsSearching(true);
|
|
508
|
+
|
|
509
|
+
// Map callback type to log type
|
|
510
|
+
const logType: DocsSearchLog['type'] = type === 'tell_user' ? 'result' : 'info';
|
|
511
|
+
|
|
512
|
+
// Add log entry (max 8, remove oldest if exceeding)
|
|
513
|
+
setDocsSearchLogs(prev => {
|
|
514
|
+
const newLog: DocsSearchLog = {
|
|
515
|
+
type: logType,
|
|
516
|
+
message,
|
|
517
|
+
timestamp: Date.now(),
|
|
518
|
+
};
|
|
519
|
+
const updated = [...prev, newLog];
|
|
520
|
+
return updated.slice(-8); // Keep only last 8
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
return () => {
|
|
525
|
+
setDocsSearchProgressCallback(null);
|
|
526
|
+
};
|
|
527
|
+
}, [addLog]);
|
|
528
|
+
|
|
529
|
+
// Handle approval dialog response
|
|
530
|
+
const handleApprovalResponse = useCallback((result: ToolApprovalResult) => {
|
|
531
|
+
if (!pendingToolApproval) return;
|
|
532
|
+
|
|
533
|
+
const { toolName, resolve } = pendingToolApproval;
|
|
534
|
+
|
|
535
|
+
// Log the approval response
|
|
536
|
+
if (result === 'approve') {
|
|
537
|
+
addLog({
|
|
538
|
+
type: 'approval_response',
|
|
539
|
+
content: toolName,
|
|
540
|
+
details: 'approved',
|
|
541
|
+
success: true,
|
|
542
|
+
});
|
|
543
|
+
} else if (result === 'always') {
|
|
544
|
+
setAutoApprovedTools(prev => new Set([...prev, toolName]));
|
|
545
|
+
addLog({
|
|
546
|
+
type: 'approval_response',
|
|
547
|
+
content: toolName,
|
|
548
|
+
details: 'always_approved',
|
|
549
|
+
success: true,
|
|
550
|
+
});
|
|
551
|
+
} else if (typeof result === 'object' && result.reject) {
|
|
552
|
+
addLog({
|
|
553
|
+
type: 'approval_response',
|
|
554
|
+
content: toolName,
|
|
555
|
+
details: result.comment || 'rejected',
|
|
556
|
+
success: false,
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// Resolve the promise
|
|
561
|
+
resolve(result);
|
|
562
|
+
setPendingToolApproval(null);
|
|
563
|
+
|
|
564
|
+
logger.debug('Approval response', { toolName, result });
|
|
565
|
+
}, [pendingToolApproval, addLog]);
|
|
566
|
+
|
|
567
|
+
// Setup plan/todo callbacks - adds to Static log
|
|
568
|
+
useEffect(() => {
|
|
569
|
+
setPlanCreatedCallback((todoTitles) => {
|
|
570
|
+
// Reset session time and tokens when new TODO plan is created
|
|
571
|
+
// Note: /usage still shows cumulative total (stored in usageTracker.data)
|
|
572
|
+
usageTracker.resetSession();
|
|
573
|
+
setSessionTokens(0);
|
|
574
|
+
setSessionElapsed(0);
|
|
575
|
+
|
|
576
|
+
addLog({
|
|
577
|
+
type: 'plan_created',
|
|
578
|
+
content: `Created ${todoTitles.length} task${todoTitles.length > 1 ? 's' : ''}`,
|
|
579
|
+
items: todoTitles,
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
setTodoStartCallback((title) => {
|
|
584
|
+
addLog({
|
|
585
|
+
type: 'todo_start',
|
|
586
|
+
content: title,
|
|
587
|
+
});
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
// Remove todo_complete log - TodoPanel already shows status, avoiding duplication
|
|
591
|
+
setTodoCompleteCallback(() => {
|
|
592
|
+
// No-op: TodoPanel handles visual feedback
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
setTodoFailCallback((title) => {
|
|
596
|
+
addLog({
|
|
597
|
+
type: 'todo_fail',
|
|
598
|
+
content: title,
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
setCompactCallback((originalCount, newCount) => {
|
|
603
|
+
// Clear existing logs and add compact entry
|
|
604
|
+
clearLogs();
|
|
605
|
+
addLog({
|
|
606
|
+
type: 'compact',
|
|
607
|
+
content: `Conversation compacted: ${originalCount} → ${newCount} messages`,
|
|
608
|
+
});
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
return () => {
|
|
612
|
+
setPlanCreatedCallback(null);
|
|
613
|
+
setTodoStartCallback(null);
|
|
614
|
+
setTodoCompleteCallback(null);
|
|
615
|
+
setTodoFailCallback(null);
|
|
616
|
+
setCompactCallback(null);
|
|
617
|
+
};
|
|
618
|
+
}, [addLog, clearLogs]);
|
|
619
|
+
|
|
620
|
+
// Update session usage and elapsed time in real-time
|
|
621
|
+
useEffect(() => {
|
|
622
|
+
if (!isProcessing) {
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const interval = setInterval(() => {
|
|
627
|
+
const sessionUsage = usageTracker.getSessionUsage();
|
|
628
|
+
setSessionTokens(sessionUsage.totalTokens);
|
|
629
|
+
setSessionElapsed(usageTracker.getSessionElapsedSeconds());
|
|
630
|
+
}, 500); // Update every 500ms
|
|
631
|
+
|
|
632
|
+
return () => clearInterval(interval);
|
|
633
|
+
}, [isProcessing]);
|
|
634
|
+
|
|
635
|
+
// Initialize on startup: git update check -> health check -> docs -> config
|
|
636
|
+
useEffect(() => {
|
|
637
|
+
const initialize = async () => {
|
|
638
|
+
logger.flow('Starting initialization');
|
|
639
|
+
logger.startTimer('app-init');
|
|
640
|
+
|
|
641
|
+
try {
|
|
642
|
+
// Step 1: Run health check (only if endpoints configured)
|
|
643
|
+
setInitStep('health');
|
|
644
|
+
logger.flow('Running health check');
|
|
645
|
+
setHealthStatus('checking');
|
|
646
|
+
|
|
647
|
+
if (configManager.hasEndpoints()) {
|
|
648
|
+
const healthResults = await LLMClient.healthCheckAll();
|
|
649
|
+
|
|
650
|
+
// Check if any model is healthy
|
|
651
|
+
let hasHealthy = false;
|
|
652
|
+
for (const [endpointId, modelResults] of healthResults) {
|
|
653
|
+
logger.vars(
|
|
654
|
+
{ name: 'endpointId', value: endpointId },
|
|
655
|
+
{ name: 'healthyModels', value: modelResults.filter(r => r.healthy).length }
|
|
656
|
+
);
|
|
657
|
+
if (modelResults.some((r) => r.healthy)) {
|
|
658
|
+
hasHealthy = true;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
logger.state('Health status', 'checking', hasHealthy ? 'healthy' : 'unhealthy');
|
|
663
|
+
setHealthStatus(hasHealthy ? 'healthy' : 'unhealthy');
|
|
664
|
+
|
|
665
|
+
// Update health status in config
|
|
666
|
+
await configManager.updateAllHealthStatus(healthResults);
|
|
667
|
+
} else {
|
|
668
|
+
setHealthStatus('unknown');
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// Step 2: Initialize docs directory
|
|
672
|
+
setInitStep('docs');
|
|
673
|
+
logger.flow('Initializing docs directory');
|
|
674
|
+
await initializeDocsDirectory().catch((err) => {
|
|
675
|
+
logger.warn('Docs directory initialization warning', { error: err });
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
// Step 3: Check config (show setup wizard if no endpoints)
|
|
679
|
+
setInitStep('config');
|
|
680
|
+
logger.flow('Checking configuration');
|
|
681
|
+
if (!configManager.hasEndpoints()) {
|
|
682
|
+
logger.debug('No endpoints configured, showing setup wizard');
|
|
683
|
+
setShowSetupWizard(true);
|
|
684
|
+
setIsInitializing(false);
|
|
685
|
+
logger.endTimer('app-init');
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
setInitStep('done');
|
|
690
|
+
} catch (error) {
|
|
691
|
+
logger.error('Initialization failed', error as Error);
|
|
692
|
+
setHealthStatus('unknown');
|
|
693
|
+
} finally {
|
|
694
|
+
setIsInitializing(false);
|
|
695
|
+
logger.endTimer('app-init');
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
initialize();
|
|
700
|
+
}, []);
|
|
701
|
+
|
|
702
|
+
// Wrapped exit function to ensure cleanup
|
|
703
|
+
const handleExit = useCallback(async () => {
|
|
704
|
+
logger.flow('Exiting application');
|
|
705
|
+
await closeJsonStreamLogger();
|
|
706
|
+
exit();
|
|
707
|
+
}, [exit]);
|
|
708
|
+
|
|
709
|
+
// Keyboard shortcuts
|
|
710
|
+
useInput((inputChar: string, key: { ctrl: boolean; shift: boolean; meta: boolean; escape: boolean; tab?: boolean }) => {
|
|
711
|
+
// Ctrl+C: Smart handling (clear input / cancel task / double-tap exit)
|
|
712
|
+
if (key.ctrl && inputChar === 'c') {
|
|
713
|
+
const now = Date.now();
|
|
714
|
+
const timeSinceLastCtrlC = now - lastCtrlCTimeRef.current;
|
|
715
|
+
|
|
716
|
+
// Case 1: AI is processing - interrupt the task
|
|
717
|
+
if (isProcessing) {
|
|
718
|
+
logger.flow('Ctrl+C pressed - interrupting execution');
|
|
719
|
+
|
|
720
|
+
// Abort any active LLM request
|
|
721
|
+
if (llmClient) {
|
|
722
|
+
llmClient.abort();
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Set interrupt flag
|
|
726
|
+
planExecutionState.handleInterrupt();
|
|
727
|
+
|
|
728
|
+
// Add red "Interrupted" message to log immediately
|
|
729
|
+
addLog({
|
|
730
|
+
type: 'interrupt',
|
|
731
|
+
content: '⎿ Interrupted',
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
// Force stop processing state
|
|
735
|
+
setIsProcessing(false);
|
|
736
|
+
lastCtrlCTimeRef.current = now;
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// Case 2: Input has content - clear the input
|
|
741
|
+
if (input.length > 0) {
|
|
742
|
+
logger.debug('Ctrl+C pressed - clearing input');
|
|
743
|
+
setInput('');
|
|
744
|
+
lastCtrlCTimeRef.current = now;
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Case 3: Input is empty - check for double-tap to exit
|
|
749
|
+
if (timeSinceLastCtrlC < DOUBLE_TAP_THRESHOLD) {
|
|
750
|
+
// Double-tap detected - exit
|
|
751
|
+
logger.flow('Ctrl+C double-tap detected - exiting');
|
|
752
|
+
handleExit().catch((err) => logger.error('Exit failed', err));
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// First tap with empty input - show exit hint
|
|
757
|
+
lastCtrlCTimeRef.current = now;
|
|
758
|
+
addLog({
|
|
759
|
+
type: 'assistant_message',
|
|
760
|
+
content: '^C again to exit',
|
|
761
|
+
});
|
|
762
|
+
logger.debug('Ctrl+C pressed - waiting for double-tap to exit');
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
// ESC: First = pause, Second = complete stop
|
|
766
|
+
if (key.escape && (isProcessing || planExecutionState.isInterrupted)) {
|
|
767
|
+
logger.flow('ESC pressed');
|
|
768
|
+
|
|
769
|
+
// Abort any active LLM request
|
|
770
|
+
if (llmClient) {
|
|
771
|
+
llmClient.abort();
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// Handle interrupt (returns 'paused', 'stopped', or 'none')
|
|
775
|
+
const result = planExecutionState.handleInterrupt();
|
|
776
|
+
|
|
777
|
+
if (result === 'paused') {
|
|
778
|
+
// First ESC - pause
|
|
779
|
+
addLog({
|
|
780
|
+
type: 'interrupt',
|
|
781
|
+
content: '⏸️ Paused (type message to resume, ESC to stop completely)',
|
|
782
|
+
});
|
|
783
|
+
} else if (result === 'stopped') {
|
|
784
|
+
// Second ESC - complete stop
|
|
785
|
+
addLog({
|
|
786
|
+
type: 'interrupt',
|
|
787
|
+
content: '⏹️ Stopped - TODO list cleared',
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// Force stop processing state
|
|
792
|
+
setIsProcessing(false);
|
|
793
|
+
}
|
|
794
|
+
// Tab key: toggle execution mode (auto/supervised) - only when no dropdown is open
|
|
795
|
+
if (key.tab && !isProcessing && !pendingToolApproval && !fileBrowserState.showFileBrowser && !commandBrowserState.showCommandBrowser) {
|
|
796
|
+
const newMode = executionMode === 'auto' ? 'supervised' : 'auto';
|
|
797
|
+
setExecutionMode(newMode);
|
|
798
|
+
// Clear auto-approved tools when switching to auto mode
|
|
799
|
+
if (newMode === 'auto') {
|
|
800
|
+
setAutoApprovedTools(new Set());
|
|
801
|
+
}
|
|
802
|
+
addLog({
|
|
803
|
+
type: 'assistant_message',
|
|
804
|
+
content: `Execution mode changed: ${newMode === 'auto' ? '🚀 Auto Mode (autonomous execution)' : '👁️ Supervised Mode (approval required)'}`,
|
|
805
|
+
});
|
|
806
|
+
logger.debug('Execution mode toggled', { newMode });
|
|
807
|
+
}
|
|
808
|
+
// Ctrl+O: toggle log files visibility
|
|
809
|
+
if (key.ctrl && inputChar === 'o') {
|
|
810
|
+
setShowLogFiles(prev => !prev);
|
|
811
|
+
}
|
|
812
|
+
}); // Ctrl+C must always work, other keys have internal conditions
|
|
813
|
+
|
|
814
|
+
// Handle file selection from browser
|
|
815
|
+
const handleFileSelect = useCallback((filePaths: string[]) => {
|
|
816
|
+
logger.debug('File selected', { filePaths });
|
|
817
|
+
const newInput = fileBrowserState.handleFileSelect(filePaths, input);
|
|
818
|
+
setInput(newInput);
|
|
819
|
+
}, [fileBrowserState, input]);
|
|
820
|
+
|
|
821
|
+
// Handle command selection from browser
|
|
822
|
+
const handleCommandSelect = useCallback((command: string, shouldSubmit: boolean) => {
|
|
823
|
+
logger.debug('Command selected', { command, shouldSubmit });
|
|
824
|
+
const result = commandBrowserState.handleCommandSelect(command, shouldSubmit, input, handleSubmit);
|
|
825
|
+
if (result !== null) {
|
|
826
|
+
setInput(result);
|
|
827
|
+
}
|
|
828
|
+
}, [commandBrowserState, input]);
|
|
829
|
+
|
|
830
|
+
// Handle session selection from browser
|
|
831
|
+
const handleSessionSelect = useCallback(async (sessionId: string) => {
|
|
832
|
+
logger.enter('handleSessionSelect', { sessionId });
|
|
833
|
+
setShowSessionBrowser(false);
|
|
834
|
+
|
|
835
|
+
try {
|
|
836
|
+
const sessionData = await sessionManager.loadSession(sessionId);
|
|
837
|
+
|
|
838
|
+
if (!sessionData) {
|
|
839
|
+
const errorMessage = `Session not found: ${sessionId}`;
|
|
840
|
+
logger.warn('Session not found', { sessionId });
|
|
841
|
+
setMessages(prev => [
|
|
842
|
+
...prev,
|
|
843
|
+
{ role: 'assistant' as const, content: errorMessage },
|
|
844
|
+
]);
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
const hasTodos = sessionData.todos && sessionData.todos.length > 0;
|
|
849
|
+
|
|
850
|
+
logger.debug('Session loaded', {
|
|
851
|
+
sessionId,
|
|
852
|
+
messageCount: sessionData.messages.length,
|
|
853
|
+
logEntryCount: sessionData.logEntries?.length || 0,
|
|
854
|
+
todoCount: hasTodos ? sessionData.todos!.length : 0,
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
// Restore messages
|
|
858
|
+
setMessages(sessionData.messages);
|
|
859
|
+
|
|
860
|
+
// Reset auto-approved tools (Supervised mode security)
|
|
861
|
+
setAutoApprovedTools(new Set());
|
|
862
|
+
logger.debug('Auto-approved tools cleared on session load');
|
|
863
|
+
|
|
864
|
+
// Restore in-progress TODOs if available
|
|
865
|
+
if (hasTodos) {
|
|
866
|
+
// Convert SessionTodoItem to TodoItem format (add required fields with defaults)
|
|
867
|
+
const restoredTodos = sessionData.todos!.map(todo => ({
|
|
868
|
+
id: todo.id,
|
|
869
|
+
title: todo.title,
|
|
870
|
+
description: todo.description || '',
|
|
871
|
+
status: todo.status,
|
|
872
|
+
requiresDocsSearch: todo.requiresDocsSearch ?? false,
|
|
873
|
+
dependencies: todo.dependencies ?? [],
|
|
874
|
+
result: todo.result,
|
|
875
|
+
error: todo.error,
|
|
876
|
+
}));
|
|
877
|
+
planExecutionState.setTodos(restoredTodos);
|
|
878
|
+
logger.debug('Restored in-progress TODOs', { count: restoredTodos.length });
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// Build restore details message
|
|
882
|
+
const detailParts: string[] = [];
|
|
883
|
+
detailParts.push(`${sessionData.messages.length} messages`);
|
|
884
|
+
if (sessionData.logEntries?.length) {
|
|
885
|
+
detailParts.push(`${sessionData.logEntries.length} logs`);
|
|
886
|
+
}
|
|
887
|
+
if (hasTodos) {
|
|
888
|
+
detailParts.push(`${sessionData.todos!.length} TODOs restored`);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// Restore log entries if available
|
|
892
|
+
if (sessionData.logEntries && sessionData.logEntries.length > 0) {
|
|
893
|
+
// Clear current logs and add session restored header
|
|
894
|
+
const restoredLogs: LogEntry[] = [
|
|
895
|
+
{
|
|
896
|
+
id: `log-restored-header`,
|
|
897
|
+
type: 'session_restored',
|
|
898
|
+
content: `Session restored: ${new Date(sessionData.metadata.updatedAt).toLocaleString('en-US')}`,
|
|
899
|
+
details: detailParts.join(', '),
|
|
900
|
+
},
|
|
901
|
+
...sessionData.logEntries.map((entry, idx) => ({
|
|
902
|
+
...entry,
|
|
903
|
+
id: `log-restored-${idx}`,
|
|
904
|
+
})) as LogEntry[],
|
|
905
|
+
];
|
|
906
|
+
setLogEntries(restoredLogs);
|
|
907
|
+
logIdCounter.current = restoredLogs.length;
|
|
908
|
+
} else {
|
|
909
|
+
// No log entries saved, show session restored message only
|
|
910
|
+
clearLogs();
|
|
911
|
+
addLog({
|
|
912
|
+
type: 'session_restored',
|
|
913
|
+
content: `Session restored: ${new Date(sessionData.metadata.updatedAt).toLocaleString('en-US')}`,
|
|
914
|
+
details: detailParts.join(', ') + (sessionData.logEntries?.length ? '' : ' (no log history)'),
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
} catch (error) {
|
|
918
|
+
const errorMessage = `Session load failed: ${error instanceof Error ? error.message : 'Unknown error'}`;
|
|
919
|
+
logger.error(`Session load failed (sessionId: ${sessionId})`, error as Error);
|
|
920
|
+
setMessages(prev => [
|
|
921
|
+
...prev,
|
|
922
|
+
{ role: 'assistant' as const, content: errorMessage },
|
|
923
|
+
]);
|
|
924
|
+
}
|
|
925
|
+
logger.exit('handleSessionSelect', { sessionId });
|
|
926
|
+
}, [addLog, clearLogs]);
|
|
927
|
+
|
|
928
|
+
// Planning mode change handler removed - always auto mode
|
|
929
|
+
// Kept for backward compatibility with SettingsBrowser interface
|
|
930
|
+
const handleSettingsPlanningModeChange = useCallback((_mode: PlanningMode) => {
|
|
931
|
+
// No-op: planning mode is always 'auto'
|
|
932
|
+
logger.debug('Planning mode change ignored - always auto');
|
|
933
|
+
}, []);
|
|
934
|
+
|
|
935
|
+
// Handle settings close
|
|
936
|
+
const handleSettingsClose = useCallback(() => {
|
|
937
|
+
logger.debug('Settings closed');
|
|
938
|
+
setShowSettings(false);
|
|
939
|
+
}, []);
|
|
940
|
+
|
|
941
|
+
// Handle setup wizard completion
|
|
942
|
+
const handleSetupComplete = useCallback(() => {
|
|
943
|
+
logger.debug('Setup wizard completed');
|
|
944
|
+
setShowSetupWizard(false);
|
|
945
|
+
|
|
946
|
+
// Reload config and create LLMClient
|
|
947
|
+
try {
|
|
948
|
+
const endpoint = configManager.getCurrentEndpoint();
|
|
949
|
+
const model = configManager.getCurrentModel();
|
|
950
|
+
|
|
951
|
+
if (endpoint && model) {
|
|
952
|
+
setCurrentModelInfo({
|
|
953
|
+
model: model.name,
|
|
954
|
+
endpoint: endpoint.baseUrl,
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
const newClient = createLLMClient();
|
|
958
|
+
setLlmClient(newClient);
|
|
959
|
+
logger.debug('LLMClient created after setup', { modelId: model.id, modelName: model.name });
|
|
960
|
+
}
|
|
961
|
+
} catch (error) {
|
|
962
|
+
logger.error('Failed to create LLMClient after setup', error as Error);
|
|
963
|
+
}
|
|
964
|
+
}, []);
|
|
965
|
+
|
|
966
|
+
// Handle setup wizard skip
|
|
967
|
+
const handleSetupSkip = useCallback(() => {
|
|
968
|
+
logger.debug('Setup wizard skipped');
|
|
969
|
+
setShowSetupWizard(false);
|
|
970
|
+
}, []);
|
|
971
|
+
|
|
972
|
+
// Handle model selection
|
|
973
|
+
const handleModelSelect = useCallback(
|
|
974
|
+
(endpointId: string, modelId: string) => {
|
|
975
|
+
logger.enter('handleModelSelect', { endpointId, modelId });
|
|
976
|
+
const endpoint = configManager.getAllEndpoints().find((ep) => ep.id === endpointId);
|
|
977
|
+
const model = endpoint?.models.find((m) => m.id === modelId);
|
|
978
|
+
|
|
979
|
+
if (endpoint && model) {
|
|
980
|
+
logger.state('Current model', currentModelInfo.model, model.name);
|
|
981
|
+
setCurrentModelInfo({
|
|
982
|
+
model: model.name,
|
|
983
|
+
endpoint: endpoint.baseUrl,
|
|
984
|
+
});
|
|
985
|
+
|
|
986
|
+
// Create new LLMClient (already saved in configManager, just recreate)
|
|
987
|
+
try {
|
|
988
|
+
const newClient = createLLMClient();
|
|
989
|
+
setLlmClient(newClient);
|
|
990
|
+
logger.debug('LLMClient recreated with new model', { modelId, modelName: model.name });
|
|
991
|
+
} catch (error) {
|
|
992
|
+
logger.error('Failed to create new LLMClient', error as Error);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
setShowModelSelector(false);
|
|
997
|
+
|
|
998
|
+
// Add confirmation message
|
|
999
|
+
setMessages((prev) => [
|
|
1000
|
+
...prev,
|
|
1001
|
+
{
|
|
1002
|
+
role: 'assistant' as const,
|
|
1003
|
+
content: `Model changed: ${model?.name || modelId} (${endpoint?.name || endpointId})`,
|
|
1004
|
+
},
|
|
1005
|
+
]);
|
|
1006
|
+
logger.exit('handleModelSelect', { model: model?.name });
|
|
1007
|
+
},
|
|
1008
|
+
[currentModelInfo.model]
|
|
1009
|
+
);
|
|
1010
|
+
|
|
1011
|
+
// Handle model selector cancel
|
|
1012
|
+
const handleModelSelectorCancel = useCallback(() => {
|
|
1013
|
+
logger.debug('Model selector cancelled');
|
|
1014
|
+
setShowModelSelector(false);
|
|
1015
|
+
}, []);
|
|
1016
|
+
|
|
1017
|
+
// Handle tool selector close
|
|
1018
|
+
const handleToolSelectorClose = useCallback(() => {
|
|
1019
|
+
logger.debug('Tool selector closed');
|
|
1020
|
+
setShowToolSelector(false);
|
|
1021
|
+
}, []);
|
|
1022
|
+
|
|
1023
|
+
const handleSubmit = useCallback(async (value: string) => {
|
|
1024
|
+
// If processing and user submits a message, queue it for injection at next LLM invoke
|
|
1025
|
+
if (isProcessing && value.trim()) {
|
|
1026
|
+
const queuedMessage = value.trim();
|
|
1027
|
+
setPendingUserMessage(queuedMessage);
|
|
1028
|
+
logger.flow('User message queued for mid-execution injection', { message: queuedMessage });
|
|
1029
|
+
addLog({
|
|
1030
|
+
type: 'user_input',
|
|
1031
|
+
content: `(→ passing to next call) ${queuedMessage}`,
|
|
1032
|
+
});
|
|
1033
|
+
setInput('');
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
if (!value.trim() || fileBrowserState.showFileBrowser || showSessionBrowser || showSettings || showSetupWizard || showDocsBrowser) {
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
logger.enter('handleSubmit', { valueLength: value.length });
|
|
1042
|
+
|
|
1043
|
+
const userMessage = value.trim();
|
|
1044
|
+
|
|
1045
|
+
// Allow /settings command even without LLM configured
|
|
1046
|
+
const isSettingsCommand = userMessage === '/settings';
|
|
1047
|
+
|
|
1048
|
+
if (!llmClient && !isSettingsCommand) {
|
|
1049
|
+
logger.warn('LLM client not configured');
|
|
1050
|
+
setMessages((prev) => [
|
|
1051
|
+
...prev,
|
|
1052
|
+
{ role: 'assistant' as const, content: 'LLM not configured. Please configure in /settings → LLMs.' },
|
|
1053
|
+
]);
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
if (commandBrowserState.showCommandBrowser && !isValidCommand(userMessage)) {
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
if (commandBrowserState.showCommandBrowser) {
|
|
1062
|
+
commandBrowserState.resetCommandBrowser();
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
setInput('');
|
|
1066
|
+
addToHistory(userMessage);
|
|
1067
|
+
|
|
1068
|
+
// Handle shell commands (! prefix)
|
|
1069
|
+
if (userMessage.startsWith('!')) {
|
|
1070
|
+
const shellCommand = userMessage.slice(1).trim();
|
|
1071
|
+
if (!shellCommand) {
|
|
1072
|
+
addLog({
|
|
1073
|
+
type: 'assistant_message',
|
|
1074
|
+
content: 'Usage: !<command> (e.g., !ls -la, !dir)',
|
|
1075
|
+
});
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
addLog({
|
|
1080
|
+
type: 'user_input',
|
|
1081
|
+
content: userMessage,
|
|
1082
|
+
});
|
|
1083
|
+
|
|
1084
|
+
const shellConfig = getShellConfig();
|
|
1085
|
+
const shellLabel = isNativeWindows() ? 'PowerShell' : 'Bash';
|
|
1086
|
+
|
|
1087
|
+
addLog({
|
|
1088
|
+
type: 'tool_start',
|
|
1089
|
+
content: `${shellLabel}: ${shellCommand}`,
|
|
1090
|
+
});
|
|
1091
|
+
|
|
1092
|
+
try {
|
|
1093
|
+
const child = spawn(shellConfig.shell, shellConfig.args(shellCommand), {
|
|
1094
|
+
cwd: process.cwd(),
|
|
1095
|
+
env: process.env,
|
|
1096
|
+
});
|
|
1097
|
+
|
|
1098
|
+
let stdout = '';
|
|
1099
|
+
let stderr = '';
|
|
1100
|
+
|
|
1101
|
+
child.stdout?.on('data', (data: Buffer) => {
|
|
1102
|
+
stdout += data.toString();
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
child.stderr?.on('data', (data: Buffer) => {
|
|
1106
|
+
stderr += data.toString();
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1109
|
+
child.on('close', (code: number | null) => {
|
|
1110
|
+
const output = stdout + (stderr ? `\n${stderr}` : '');
|
|
1111
|
+
const success = code === 0;
|
|
1112
|
+
|
|
1113
|
+
addLog({
|
|
1114
|
+
type: 'shell_result',
|
|
1115
|
+
content: output.trim() || (success ? '(no output)' : `Exit code: ${code}`),
|
|
1116
|
+
success,
|
|
1117
|
+
});
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
child.on('error', (err: Error) => {
|
|
1121
|
+
addLog({
|
|
1122
|
+
type: 'shell_result',
|
|
1123
|
+
content: `Error: ${err.message}`,
|
|
1124
|
+
success: false,
|
|
1125
|
+
});
|
|
1126
|
+
});
|
|
1127
|
+
} catch (err) {
|
|
1128
|
+
addLog({
|
|
1129
|
+
type: 'shell_result',
|
|
1130
|
+
content: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
1131
|
+
success: false,
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
logger.exit('handleSubmit', { shellCommand: true });
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
// Handle slash commands
|
|
1140
|
+
if (isSlashCommand(userMessage)) {
|
|
1141
|
+
logger.flow('Executing slash command');
|
|
1142
|
+
|
|
1143
|
+
// Add user input to log for slash commands
|
|
1144
|
+
addLog({
|
|
1145
|
+
type: 'user_input',
|
|
1146
|
+
content: userMessage,
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
const commandContext: CommandHandlerContext = {
|
|
1150
|
+
planningMode,
|
|
1151
|
+
messages,
|
|
1152
|
+
todos: planExecutionState.todos,
|
|
1153
|
+
setPlanningMode: () => {}, // No-op: planning mode is always 'auto'
|
|
1154
|
+
setMessages,
|
|
1155
|
+
setTodos: planExecutionState.setTodos,
|
|
1156
|
+
exit: handleExit,
|
|
1157
|
+
onShowSessionBrowser: () => setShowSessionBrowser(true),
|
|
1158
|
+
onShowSettings: () => setShowSettings(true),
|
|
1159
|
+
onShowModelSelector: () => setShowModelSelector(true),
|
|
1160
|
+
// DISABLED: onShowDocsBrowser removed - docs feature disabled
|
|
1161
|
+
onShowToolSelector: () => setShowToolSelector(true),
|
|
1162
|
+
onCompact: llmClient
|
|
1163
|
+
? () => planExecutionState.performCompact(llmClient, messages, setMessages)
|
|
1164
|
+
: undefined,
|
|
1165
|
+
};
|
|
1166
|
+
|
|
1167
|
+
const result = await executeSlashCommand(userMessage, commandContext);
|
|
1168
|
+
|
|
1169
|
+
if (result.handled) {
|
|
1170
|
+
// If the command added an assistant message, display it in the log
|
|
1171
|
+
if (result.updatedContext?.messages) {
|
|
1172
|
+
const lastMessage = result.updatedContext.messages[result.updatedContext.messages.length - 1];
|
|
1173
|
+
if (lastMessage && lastMessage.role === 'assistant') {
|
|
1174
|
+
addLog({
|
|
1175
|
+
type: 'assistant_message',
|
|
1176
|
+
content: lastMessage.content,
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
logger.exit('handleSubmit', { handled: true });
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
// Add user input to Static log (show original message)
|
|
1186
|
+
addLog({
|
|
1187
|
+
type: 'user_input',
|
|
1188
|
+
content: userMessage,
|
|
1189
|
+
});
|
|
1190
|
+
|
|
1191
|
+
// Process @file references - read file contents and include in message
|
|
1192
|
+
const processedResult = await processFileReferences(userMessage);
|
|
1193
|
+
const processedMessage = processedResult.content;
|
|
1194
|
+
|
|
1195
|
+
// Log if files were included
|
|
1196
|
+
if (processedResult.includedFiles.length > 0) {
|
|
1197
|
+
logger.debug('Files included in message', {
|
|
1198
|
+
files: processedResult.includedFiles,
|
|
1199
|
+
failedFiles: processedResult.failedFiles,
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
// Add processed message to messages (with file contents for LLM)
|
|
1204
|
+
let updatedMessages: Message[] = [...messages, { role: 'user' as const, content: processedMessage }];
|
|
1205
|
+
setMessages(updatedMessages);
|
|
1206
|
+
|
|
1207
|
+
setIsProcessing(true);
|
|
1208
|
+
setActivityStartTime(Date.now());
|
|
1209
|
+
setSubActivities([]);
|
|
1210
|
+
|
|
1211
|
+
// Reset interrupt flag for new operation
|
|
1212
|
+
if (llmClient) {
|
|
1213
|
+
llmClient.resetInterrupt();
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
// Reset session usage for new task
|
|
1217
|
+
usageTracker.resetSession();
|
|
1218
|
+
setSessionTokens(0);
|
|
1219
|
+
setSessionElapsed(0);
|
|
1220
|
+
|
|
1221
|
+
logger.startTimer('message-processing');
|
|
1222
|
+
|
|
1223
|
+
try {
|
|
1224
|
+
// Check for auto-compact before processing (70% threshold)
|
|
1225
|
+
if (planExecutionState.shouldAutoCompact()) {
|
|
1226
|
+
logger.flow('Auto-compact triggered');
|
|
1227
|
+
setActivityType('thinking');
|
|
1228
|
+
setActivityDetail('Compacting conversation...');
|
|
1229
|
+
|
|
1230
|
+
const compactResult = await planExecutionState.performCompact(llmClient!, updatedMessages, setMessages);
|
|
1231
|
+
if (compactResult.success && compactResult.compactedMessages) {
|
|
1232
|
+
// Update local variable with compacted messages for subsequent LLM calls
|
|
1233
|
+
updatedMessages = compactResult.compactedMessages;
|
|
1234
|
+
logger.debug('Auto-compact completed', {
|
|
1235
|
+
originalCount: compactResult.originalMessageCount,
|
|
1236
|
+
newCount: compactResult.newMessageCount,
|
|
1237
|
+
});
|
|
1238
|
+
} else if (!compactResult.success) {
|
|
1239
|
+
logger.warn('Auto-compact failed, continuing without compact', { error: compactResult.error });
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
// Check if we should resume TODO execution instead of starting fresh
|
|
1244
|
+
const hasPendingTodos = planExecutionState.todos.some(
|
|
1245
|
+
t => t.status === 'pending' || t.status === 'in_progress'
|
|
1246
|
+
);
|
|
1247
|
+
|
|
1248
|
+
if (hasPendingTodos && planExecutionState.isInterrupted) {
|
|
1249
|
+
// Resume TODO execution with the new message
|
|
1250
|
+
logger.flow('Resuming TODO execution after pause');
|
|
1251
|
+
setActivityType('executing');
|
|
1252
|
+
setActivityDetail('Resuming...');
|
|
1253
|
+
await planExecutionState.resumeTodoExecution(processedMessage, llmClient!, messages, setMessages);
|
|
1254
|
+
} else {
|
|
1255
|
+
// Phase 1: Use auto mode with LLM-based request classification
|
|
1256
|
+
setActivityType('thinking');
|
|
1257
|
+
setActivityDetail('Analyzing request...');
|
|
1258
|
+
|
|
1259
|
+
logger.vars(
|
|
1260
|
+
{ name: 'planningMode', value: planningMode },
|
|
1261
|
+
{ name: 'messageLength', value: processedMessage.length }
|
|
1262
|
+
);
|
|
1263
|
+
|
|
1264
|
+
// Use executeAutoMode which handles classification internally
|
|
1265
|
+
await planExecutionState.executeAutoMode(processedMessage, llmClient!, updatedMessages, setMessages);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
} catch (error) {
|
|
1269
|
+
logger.error('Message processing failed', error as Error);
|
|
1270
|
+
} finally {
|
|
1271
|
+
setIsProcessing(false);
|
|
1272
|
+
logger.endTimer('message-processing');
|
|
1273
|
+
logger.exit('handleSubmit', { success: true });
|
|
1274
|
+
}
|
|
1275
|
+
}, [
|
|
1276
|
+
isProcessing,
|
|
1277
|
+
fileBrowserState.showFileBrowser,
|
|
1278
|
+
showSessionBrowser,
|
|
1279
|
+
showSettings,
|
|
1280
|
+
showSetupWizard,
|
|
1281
|
+
showDocsBrowser,
|
|
1282
|
+
commandBrowserState,
|
|
1283
|
+
planningMode,
|
|
1284
|
+
messages,
|
|
1285
|
+
planExecutionState,
|
|
1286
|
+
llmClient,
|
|
1287
|
+
handleExit,
|
|
1288
|
+
addLog,
|
|
1289
|
+
]);
|
|
1290
|
+
|
|
1291
|
+
// Process pending user message after LLM processing completes
|
|
1292
|
+
// This handles the edge case where execution finishes before the pending message could be injected
|
|
1293
|
+
useEffect(() => {
|
|
1294
|
+
if (!isProcessing && pendingUserMessage && llmClient) {
|
|
1295
|
+
logger.flow('Processing remaining pending user message after execution complete');
|
|
1296
|
+
|
|
1297
|
+
// Clear the pending message
|
|
1298
|
+
const queuedMessage = pendingUserMessage;
|
|
1299
|
+
setPendingUserMessage(null);
|
|
1300
|
+
pendingUserMessageRef.current = null;
|
|
1301
|
+
|
|
1302
|
+
// Check if we have pending TODOs to resume
|
|
1303
|
+
const hasPendingTodos = planExecutionState.todos.some(
|
|
1304
|
+
t => t.status === 'pending' || t.status === 'in_progress'
|
|
1305
|
+
);
|
|
1306
|
+
|
|
1307
|
+
// Add to log
|
|
1308
|
+
addLog({
|
|
1309
|
+
type: 'user_input',
|
|
1310
|
+
content: `📩 ${queuedMessage}`,
|
|
1311
|
+
});
|
|
1312
|
+
|
|
1313
|
+
// Process @file references and then execute
|
|
1314
|
+
const processAndExecute = async () => {
|
|
1315
|
+
// Process file references
|
|
1316
|
+
const processedResult = await processFileReferences(queuedMessage);
|
|
1317
|
+
const processedMessage = processedResult.content;
|
|
1318
|
+
|
|
1319
|
+
// Start processing
|
|
1320
|
+
setIsProcessing(true);
|
|
1321
|
+
setActivityStartTime(Date.now());
|
|
1322
|
+
|
|
1323
|
+
try {
|
|
1324
|
+
if (hasPendingTodos) {
|
|
1325
|
+
// Resume TODO execution with the new message
|
|
1326
|
+
logger.flow('Resuming TODO execution with user message');
|
|
1327
|
+
await planExecutionState.resumeTodoExecution(processedMessage, llmClient, messages, setMessages);
|
|
1328
|
+
} else {
|
|
1329
|
+
// No pending TODOs - start fresh with executeAutoMode
|
|
1330
|
+
logger.flow('No pending TODOs - starting fresh execution');
|
|
1331
|
+
const updatedMessages: Message[] = [...messages, { role: 'user' as const, content: processedMessage }];
|
|
1332
|
+
setMessages(updatedMessages);
|
|
1333
|
+
await planExecutionState.executeAutoMode(processedMessage, llmClient, updatedMessages, setMessages);
|
|
1334
|
+
}
|
|
1335
|
+
} catch (error) {
|
|
1336
|
+
logger.error('Queued message processing failed', error as Error);
|
|
1337
|
+
} finally {
|
|
1338
|
+
setIsProcessing(false);
|
|
1339
|
+
}
|
|
1340
|
+
};
|
|
1341
|
+
|
|
1342
|
+
processAndExecute();
|
|
1343
|
+
}
|
|
1344
|
+
}, [isProcessing, pendingUserMessage, llmClient, messages, planExecutionState, addLog]);
|
|
1345
|
+
|
|
1346
|
+
// Show loading screen - DEXTER style (clean, no animations)
|
|
1347
|
+
if (isInitializing) {
|
|
1348
|
+
const getInitStepText = () => {
|
|
1349
|
+
switch (initStep) {
|
|
1350
|
+
case 'health':
|
|
1351
|
+
return 'Checking model health';
|
|
1352
|
+
case 'docs':
|
|
1353
|
+
return 'Initializing documentation';
|
|
1354
|
+
case 'config':
|
|
1355
|
+
return 'Loading configuration';
|
|
1356
|
+
default:
|
|
1357
|
+
return 'Ready';
|
|
1358
|
+
}
|
|
1359
|
+
};
|
|
1360
|
+
|
|
1361
|
+
return (
|
|
1362
|
+
<Box flexDirection="column" paddingX={2} paddingY={1}>
|
|
1363
|
+
<Logo showVersion={true} showTagline={true} />
|
|
1364
|
+
<Box marginTop={1}>
|
|
1365
|
+
<Text color="gray">{getInitStepText()}...</Text>
|
|
1366
|
+
</Box>
|
|
1367
|
+
</Box>
|
|
1368
|
+
);
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
// Show setup wizard if no endpoints configured
|
|
1372
|
+
if (showSetupWizard) {
|
|
1373
|
+
return (
|
|
1374
|
+
<Box flexDirection="column" padding={1}>
|
|
1375
|
+
<LLMSetupWizard onComplete={handleSetupComplete} onSkip={handleSetupSkip} />
|
|
1376
|
+
</Box>
|
|
1377
|
+
);
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
// Get health status indicator
|
|
1381
|
+
const getHealthIndicator = () => {
|
|
1382
|
+
switch (healthStatus) {
|
|
1383
|
+
case 'checking':
|
|
1384
|
+
return <Text color="yellow">⋯</Text>;
|
|
1385
|
+
case 'healthy':
|
|
1386
|
+
return <Text color="green">●</Text>;
|
|
1387
|
+
case 'unhealthy':
|
|
1388
|
+
return <Text color="red">●</Text>;
|
|
1389
|
+
default:
|
|
1390
|
+
return <Text color="gray">○</Text>;
|
|
1391
|
+
}
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
// Get activity type based on execution phase
|
|
1395
|
+
const getCurrentActivityType = (): ActivityType => {
|
|
1396
|
+
if (planExecutionState.executionPhase === 'planning') return 'planning';
|
|
1397
|
+
if (planExecutionState.executionPhase === 'executing') return 'executing';
|
|
1398
|
+
return activityType;
|
|
1399
|
+
};
|
|
1400
|
+
|
|
1401
|
+
// Check if any panel is open (for disabling history navigation)
|
|
1402
|
+
const isAnyPanelOpen =
|
|
1403
|
+
fileBrowserState.showFileBrowser ||
|
|
1404
|
+
commandBrowserState.showCommandBrowser ||
|
|
1405
|
+
showToolSelector ||
|
|
1406
|
+
showSettings ||
|
|
1407
|
+
showModelSelector ||
|
|
1408
|
+
showSessionBrowser ||
|
|
1409
|
+
showDocsBrowser ||
|
|
1410
|
+
showLogFiles;
|
|
1411
|
+
|
|
1412
|
+
// Render a single log entry
|
|
1413
|
+
const renderLogEntry = (entry: LogEntry) => {
|
|
1414
|
+
switch (entry.type) {
|
|
1415
|
+
case 'logo': {
|
|
1416
|
+
return (
|
|
1417
|
+
<Box key={entry.id} flexDirection="column" marginBottom={1}>
|
|
1418
|
+
<Logo
|
|
1419
|
+
showVersion={true}
|
|
1420
|
+
showTagline={false}
|
|
1421
|
+
animate={false}
|
|
1422
|
+
modelName={currentModelInfo.model}
|
|
1423
|
+
workingDirectory={shortenPath(process.cwd())}
|
|
1424
|
+
/>
|
|
1425
|
+
<Text>{' '}</Text>
|
|
1426
|
+
<Box>
|
|
1427
|
+
<Text color="gray">{STARTUP_TIP}</Text>
|
|
1428
|
+
</Box>
|
|
1429
|
+
</Box>
|
|
1430
|
+
);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
case 'user_input':
|
|
1434
|
+
return (
|
|
1435
|
+
<Box key={entry.id} marginTop={1}>
|
|
1436
|
+
<Text color="green" bold>❯ </Text>
|
|
1437
|
+
<Text>{entry.content}</Text>
|
|
1438
|
+
</Box>
|
|
1439
|
+
);
|
|
1440
|
+
|
|
1441
|
+
case 'assistant_message':
|
|
1442
|
+
return (
|
|
1443
|
+
<Box key={entry.id} marginTop={1} marginBottom={1} flexDirection="column">
|
|
1444
|
+
<Text color="magenta" bold>● Assistant</Text>
|
|
1445
|
+
<Box paddingLeft={2}>
|
|
1446
|
+
<MarkdownRenderer content={entry.content} />
|
|
1447
|
+
</Box>
|
|
1448
|
+
</Box>
|
|
1449
|
+
);
|
|
1450
|
+
|
|
1451
|
+
case 'interrupt':
|
|
1452
|
+
return (
|
|
1453
|
+
<Box key={entry.id} marginTop={1}>
|
|
1454
|
+
<Text color="red" bold>{entry.content}</Text>
|
|
1455
|
+
</Box>
|
|
1456
|
+
);
|
|
1457
|
+
|
|
1458
|
+
case 'session_restored':
|
|
1459
|
+
return (
|
|
1460
|
+
<Box key={entry.id} marginTop={1} flexDirection="column">
|
|
1461
|
+
<Text color="cyan" bold>📂 {entry.content}</Text>
|
|
1462
|
+
{entry.details && <Text color="gray" dimColor> {entry.details}</Text>}
|
|
1463
|
+
</Box>
|
|
1464
|
+
);
|
|
1465
|
+
|
|
1466
|
+
case 'git_info':
|
|
1467
|
+
return (
|
|
1468
|
+
<Box key={entry.id} marginTop={0} marginBottom={0} flexDirection="column">
|
|
1469
|
+
<Text color="yellow"> 🔀 {entry.content}</Text>
|
|
1470
|
+
</Box>
|
|
1471
|
+
);
|
|
1472
|
+
|
|
1473
|
+
case 'docs_search': {
|
|
1474
|
+
// Truncate both content and details if more than 5 lines (UI only)
|
|
1475
|
+
// Handle both actual newlines and literal \n strings
|
|
1476
|
+
const truncateText = (text: string, maxLines: number = 5): string => {
|
|
1477
|
+
const lines = text.split(/\\n|\n/);
|
|
1478
|
+
if (lines.length > maxLines) {
|
|
1479
|
+
return lines.slice(0, maxLines).join('\n') + `\n... (${lines.length - maxLines} more lines)`;
|
|
1480
|
+
}
|
|
1481
|
+
return lines.join('\n');
|
|
1482
|
+
};
|
|
1483
|
+
|
|
1484
|
+
const displayContent = truncateText(entry.content);
|
|
1485
|
+
const displayDetails = entry.details ? truncateText(entry.details) : undefined;
|
|
1486
|
+
|
|
1487
|
+
return (
|
|
1488
|
+
<Box key={entry.id} marginTop={1} flexDirection="column">
|
|
1489
|
+
<Text color="yellow" bold>📚 Document Search Complete</Text>
|
|
1490
|
+
{displayDetails && <Text color="gray" dimColor> {displayDetails}</Text>}
|
|
1491
|
+
<Box paddingLeft={3} marginTop={0}>
|
|
1492
|
+
<Text color="gray">{displayContent}</Text>
|
|
1493
|
+
</Box>
|
|
1494
|
+
</Box>
|
|
1495
|
+
);
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
case 'tool_start': {
|
|
1499
|
+
// Tool icon mapping
|
|
1500
|
+
const getToolIcon = (toolName: string): string => {
|
|
1501
|
+
// Office tools (prefix matching)
|
|
1502
|
+
if (toolName.startsWith('word_')) return '📄'; // Word
|
|
1503
|
+
if (toolName.startsWith('excel_')) return '📊'; // Excel
|
|
1504
|
+
if (toolName.startsWith('powerpoint_')) return '📽️'; // PowerPoint
|
|
1505
|
+
if (toolName.startsWith('browser_')) return '🌐'; // Browser
|
|
1506
|
+
|
|
1507
|
+
switch (toolName) {
|
|
1508
|
+
case 'read_file':
|
|
1509
|
+
return '📖'; // Read
|
|
1510
|
+
case 'create_file':
|
|
1511
|
+
return '📝'; // Create file
|
|
1512
|
+
case 'edit_file':
|
|
1513
|
+
return '✏️'; // Edit
|
|
1514
|
+
case 'list_files':
|
|
1515
|
+
return '📂'; // Folder list
|
|
1516
|
+
case 'find_files':
|
|
1517
|
+
return '🔍'; // Search
|
|
1518
|
+
case 'tell_to_user':
|
|
1519
|
+
return '💬'; // Message
|
|
1520
|
+
case 'bash':
|
|
1521
|
+
return '⚡'; // Terminal/shell command
|
|
1522
|
+
default:
|
|
1523
|
+
return '🔧'; // Default tool
|
|
1524
|
+
}
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1527
|
+
// Extract key parameters per tool
|
|
1528
|
+
const getToolParams = (toolName: string, args: Record<string, unknown> | undefined): string => {
|
|
1529
|
+
if (!args) return '';
|
|
1530
|
+
|
|
1531
|
+
// Office tool parameters (prefix matching)
|
|
1532
|
+
if (toolName.startsWith('word_') || toolName.startsWith('excel_') || toolName.startsWith('powerpoint_')) {
|
|
1533
|
+
// Show file path if available
|
|
1534
|
+
const filePath = args['file_path'] as string;
|
|
1535
|
+
if (filePath) return filePath;
|
|
1536
|
+
// Show cell/range if available
|
|
1537
|
+
const cell = args['cell'] as string;
|
|
1538
|
+
const range = args['range'] as string;
|
|
1539
|
+
if (cell) return cell;
|
|
1540
|
+
if (range) return range;
|
|
1541
|
+
// Show slide number if available
|
|
1542
|
+
const slideNumber = args['slide_number'] as number;
|
|
1543
|
+
if (slideNumber) return `slide ${slideNumber}`;
|
|
1544
|
+
return '';
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
switch (toolName) {
|
|
1548
|
+
case 'read_file':
|
|
1549
|
+
return args['file_path'] as string || '';
|
|
1550
|
+
case 'create_file':
|
|
1551
|
+
return args['file_path'] as string || '';
|
|
1552
|
+
case 'edit_file': {
|
|
1553
|
+
const filePath = args['file_path'] as string || '';
|
|
1554
|
+
const edits = args['edits'] as Array<unknown> || [];
|
|
1555
|
+
return `${filePath}, ${edits.length} edits`;
|
|
1556
|
+
}
|
|
1557
|
+
case 'list_files': {
|
|
1558
|
+
const dir = args['directory_path'] as string || '.';
|
|
1559
|
+
const recursive = args['recursive'] ? ', recursive' : '';
|
|
1560
|
+
return `${dir}${recursive}`;
|
|
1561
|
+
}
|
|
1562
|
+
case 'find_files': {
|
|
1563
|
+
const pattern = args['pattern'] as string || '';
|
|
1564
|
+
const dir = args['directory_path'] as string;
|
|
1565
|
+
return dir ? `${pattern} in ${dir}` : pattern;
|
|
1566
|
+
}
|
|
1567
|
+
case 'tell_to_user':
|
|
1568
|
+
return ''; // tell_to_user doesn't show parameters
|
|
1569
|
+
case 'bash':
|
|
1570
|
+
return args['command'] as string || '';
|
|
1571
|
+
default:
|
|
1572
|
+
return '';
|
|
1573
|
+
}
|
|
1574
|
+
};
|
|
1575
|
+
|
|
1576
|
+
const icon = getToolIcon(entry.content);
|
|
1577
|
+
const params = getToolParams(entry.content, entry.toolArgs);
|
|
1578
|
+
const toolName = entry.content;
|
|
1579
|
+
|
|
1580
|
+
// Truncate reason if too long
|
|
1581
|
+
const reason = entry.details || '';
|
|
1582
|
+
const maxReasonLen = 80;
|
|
1583
|
+
const truncatedReason = reason.length > maxReasonLen
|
|
1584
|
+
? reason.substring(0, maxReasonLen) + '...'
|
|
1585
|
+
: reason;
|
|
1586
|
+
|
|
1587
|
+
// Unified 2-line format for all tools
|
|
1588
|
+
return (
|
|
1589
|
+
<Box key={entry.id} flexDirection="column" marginTop={1}>
|
|
1590
|
+
<Box>
|
|
1591
|
+
<Text color="cyan" bold>{icon} {toolName}</Text>
|
|
1592
|
+
{params && <Text color="gray"> ({params})</Text>}
|
|
1593
|
+
</Box>
|
|
1594
|
+
{truncatedReason && (
|
|
1595
|
+
<Box marginLeft={2}>
|
|
1596
|
+
<Text color="gray">⎿ </Text>
|
|
1597
|
+
<Text color="yellow">💭 </Text>
|
|
1598
|
+
<Text color="gray">{truncatedReason}</Text>
|
|
1599
|
+
</Box>
|
|
1600
|
+
)}
|
|
1601
|
+
</Box>
|
|
1602
|
+
);
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
case 'tool_result':
|
|
1606
|
+
// Remove tool_result display - only show reason in tool_start
|
|
1607
|
+
return null;
|
|
1608
|
+
|
|
1609
|
+
case 'shell_result':
|
|
1610
|
+
return (
|
|
1611
|
+
<Box key={entry.id} marginLeft={2}>
|
|
1612
|
+
<Text color="gray">⎿ </Text>
|
|
1613
|
+
<Text color={entry.success ? 'white' : 'red'}>{entry.content}</Text>
|
|
1614
|
+
</Box>
|
|
1615
|
+
);
|
|
1616
|
+
|
|
1617
|
+
case 'tell_user':
|
|
1618
|
+
return (
|
|
1619
|
+
<Box key={entry.id} marginTop={1}>
|
|
1620
|
+
<Text color="yellow" bold>● </Text>
|
|
1621
|
+
<Text>{entry.content}</Text>
|
|
1622
|
+
</Box>
|
|
1623
|
+
);
|
|
1624
|
+
|
|
1625
|
+
case 'plan_created':
|
|
1626
|
+
return (
|
|
1627
|
+
<Box key={entry.id} flexDirection="column" marginTop={1}>
|
|
1628
|
+
<Text color="magenta" bold>● 📋 {entry.content}</Text>
|
|
1629
|
+
{entry.items?.map((item, idx) => (
|
|
1630
|
+
<Box key={idx} marginLeft={2}>
|
|
1631
|
+
<Text color="gray">⎿ </Text>
|
|
1632
|
+
<Text>{idx + 1}. {item}</Text>
|
|
1633
|
+
</Box>
|
|
1634
|
+
))}
|
|
1635
|
+
</Box>
|
|
1636
|
+
);
|
|
1637
|
+
|
|
1638
|
+
case 'todo_start':
|
|
1639
|
+
return (
|
|
1640
|
+
<Box key={entry.id} marginTop={1}>
|
|
1641
|
+
<Text color="blue" bold>● ▶ </Text>
|
|
1642
|
+
<Text bold>{entry.content}</Text>
|
|
1643
|
+
</Box>
|
|
1644
|
+
);
|
|
1645
|
+
|
|
1646
|
+
case 'todo_complete':
|
|
1647
|
+
return (
|
|
1648
|
+
<Box key={entry.id} marginLeft={2}>
|
|
1649
|
+
<Text color="gray">⎿ </Text>
|
|
1650
|
+
<Text color="green">✓ Complete</Text>
|
|
1651
|
+
</Box>
|
|
1652
|
+
);
|
|
1653
|
+
|
|
1654
|
+
case 'todo_fail':
|
|
1655
|
+
return (
|
|
1656
|
+
<Box key={entry.id} marginLeft={2}>
|
|
1657
|
+
<Text color="gray">⎿ </Text>
|
|
1658
|
+
<Text color="red">✗ Failed</Text>
|
|
1659
|
+
</Box>
|
|
1660
|
+
);
|
|
1661
|
+
|
|
1662
|
+
case 'compact':
|
|
1663
|
+
return (
|
|
1664
|
+
<Box key={entry.id} flexDirection="column" marginTop={1}>
|
|
1665
|
+
<Logo
|
|
1666
|
+
showVersion={true}
|
|
1667
|
+
showTagline={false}
|
|
1668
|
+
animate={false}
|
|
1669
|
+
modelName={currentModelInfo.model}
|
|
1670
|
+
workingDirectory={shortenPath(process.cwd())}
|
|
1671
|
+
/>
|
|
1672
|
+
<Text color="gray">── {entry.content} ──</Text>
|
|
1673
|
+
</Box>
|
|
1674
|
+
);
|
|
1675
|
+
|
|
1676
|
+
case 'approval_request': {
|
|
1677
|
+
// Format tool args for display
|
|
1678
|
+
const formatArg = (_key: string, value: unknown): string => {
|
|
1679
|
+
if (typeof value === 'string') {
|
|
1680
|
+
if (value.length > 100) return value.substring(0, 100) + '...';
|
|
1681
|
+
return value;
|
|
1682
|
+
}
|
|
1683
|
+
return JSON.stringify(value);
|
|
1684
|
+
};
|
|
1685
|
+
|
|
1686
|
+
return (
|
|
1687
|
+
<Box key={entry.id} flexDirection="column" marginTop={1}>
|
|
1688
|
+
<Box>
|
|
1689
|
+
<Text color="yellow" bold>⚠️ Approval request: </Text>
|
|
1690
|
+
<Text color="cyan" bold>{entry.content}</Text>
|
|
1691
|
+
</Box>
|
|
1692
|
+
{entry.details && (
|
|
1693
|
+
<Box marginLeft={2}>
|
|
1694
|
+
<Text color="gray">⎿ </Text>
|
|
1695
|
+
<Text>{entry.details}</Text>
|
|
1696
|
+
</Box>
|
|
1697
|
+
)}
|
|
1698
|
+
{entry.toolArgs && Object.entries(entry.toolArgs).map(([key, value], idx) => {
|
|
1699
|
+
if (key === 'reason') return null;
|
|
1700
|
+
return (
|
|
1701
|
+
<Box key={idx} marginLeft={2}>
|
|
1702
|
+
<Text color="gray">⎿ </Text>
|
|
1703
|
+
<Text color="magenta">{key}: </Text>
|
|
1704
|
+
<Text color="gray">{formatArg(key, value)}</Text>
|
|
1705
|
+
</Box>
|
|
1706
|
+
);
|
|
1707
|
+
})}
|
|
1708
|
+
</Box>
|
|
1709
|
+
);
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
case 'approval_response':
|
|
1713
|
+
return (
|
|
1714
|
+
<Box key={entry.id} marginLeft={2}>
|
|
1715
|
+
<Text color="gray">⎿ </Text>
|
|
1716
|
+
{entry.success ? (
|
|
1717
|
+
<Text color="green">
|
|
1718
|
+
✓ {entry.details === 'always_approved' ? 'Always approved' : 'Approved'}
|
|
1719
|
+
</Text>
|
|
1720
|
+
) : (
|
|
1721
|
+
<Text color="red">
|
|
1722
|
+
✗ Rejected{entry.details && entry.details !== 'rejected' ? `: ${entry.details}` : ''}
|
|
1723
|
+
</Text>
|
|
1724
|
+
)}
|
|
1725
|
+
</Box>
|
|
1726
|
+
);
|
|
1727
|
+
|
|
1728
|
+
case 'reasoning':
|
|
1729
|
+
// Hide reasoning content - just show indicator
|
|
1730
|
+
return (
|
|
1731
|
+
<Box key={entry.id} marginTop={1}>
|
|
1732
|
+
<Text color="gray">💭 Thinking...</Text>
|
|
1733
|
+
</Box>
|
|
1734
|
+
);
|
|
1735
|
+
|
|
1736
|
+
default:
|
|
1737
|
+
return null;
|
|
1738
|
+
}
|
|
1739
|
+
};
|
|
1740
|
+
|
|
1741
|
+
return (
|
|
1742
|
+
<Box flexDirection="column" height="100%">
|
|
1743
|
+
{/* Static: Scrollable log history (logo, user input, tool calls, etc.) */}
|
|
1744
|
+
<Static items={logEntries}>
|
|
1745
|
+
{(entry) => renderLogEntry(entry)}
|
|
1746
|
+
</Static>
|
|
1747
|
+
|
|
1748
|
+
{/* Tool Approval Dialog (Supervised Mode) - shown in scrollable area */}
|
|
1749
|
+
{pendingToolApproval && (
|
|
1750
|
+
<Box marginY={1}>
|
|
1751
|
+
<ApprovalDialog
|
|
1752
|
+
toolName={pendingToolApproval.toolName}
|
|
1753
|
+
args={pendingToolApproval.args}
|
|
1754
|
+
reason={pendingToolApproval.reason}
|
|
1755
|
+
onResponse={handleApprovalResponse}
|
|
1756
|
+
/>
|
|
1757
|
+
</Box>
|
|
1758
|
+
)}
|
|
1759
|
+
|
|
1760
|
+
{/* Activity Indicator (shown when processing/planning, regardless of TODO count) */}
|
|
1761
|
+
{isProcessing && (planExecutionState.executionPhase === 'planning' || planExecutionState.todos.length === 0) && !pendingToolApproval && !isDocsSearching && (
|
|
1762
|
+
<Box marginY={1}>
|
|
1763
|
+
<ActivityIndicator
|
|
1764
|
+
activity={getCurrentActivityType()}
|
|
1765
|
+
startTime={activityStartTime}
|
|
1766
|
+
detail={activityDetail}
|
|
1767
|
+
subActivities={subActivities}
|
|
1768
|
+
modelName={currentModelInfo.model}
|
|
1769
|
+
/>
|
|
1770
|
+
</Box>
|
|
1771
|
+
)}
|
|
1772
|
+
|
|
1773
|
+
{/* Docs Search Progress (shown when searching documents) */}
|
|
1774
|
+
{isDocsSearching && (
|
|
1775
|
+
<DocsSearchProgress
|
|
1776
|
+
logs={docsSearchLogs}
|
|
1777
|
+
isSearching={isDocsSearching}
|
|
1778
|
+
/>
|
|
1779
|
+
)}
|
|
1780
|
+
|
|
1781
|
+
{/* TODO Panel (always visible when there are todos) */}
|
|
1782
|
+
{planExecutionState.todos.length > 0 && (
|
|
1783
|
+
<Box marginTop={2} marginBottom={1}>
|
|
1784
|
+
<TodoPanel
|
|
1785
|
+
todos={planExecutionState.todos}
|
|
1786
|
+
currentTodoId={planExecutionState.currentTodoId}
|
|
1787
|
+
isProcessing={isProcessing}
|
|
1788
|
+
/>
|
|
1789
|
+
</Box>
|
|
1790
|
+
)}
|
|
1791
|
+
|
|
1792
|
+
{/* Input Area */}
|
|
1793
|
+
<Box borderStyle="single" borderColor="gray" paddingX={1} flexDirection="column">
|
|
1794
|
+
<Box>
|
|
1795
|
+
<Text color="green" bold>> </Text>
|
|
1796
|
+
<Box flexGrow={1}>
|
|
1797
|
+
<CustomTextInput
|
|
1798
|
+
value={input}
|
|
1799
|
+
onChange={(value) => {
|
|
1800
|
+
if (showSessionBrowser || showSettings || showDocsBrowser) {
|
|
1801
|
+
return;
|
|
1802
|
+
}
|
|
1803
|
+
setInput(value);
|
|
1804
|
+
}}
|
|
1805
|
+
onSubmit={handleSubmit}
|
|
1806
|
+
onHistoryPrev={isAnyPanelOpen ? undefined : handleHistoryPrev}
|
|
1807
|
+
onHistoryNext={isAnyPanelOpen ? undefined : handleHistoryNext}
|
|
1808
|
+
placeholder={
|
|
1809
|
+
isProcessing
|
|
1810
|
+
? "AI is working..."
|
|
1811
|
+
: showSessionBrowser
|
|
1812
|
+
? "Select a session or press ESC..."
|
|
1813
|
+
: showSettings
|
|
1814
|
+
? "Press ESC to close settings..."
|
|
1815
|
+
: showDocsBrowser
|
|
1816
|
+
? "Select a doc source or press ESC..."
|
|
1817
|
+
: "Type your message... (@ files, / commands, Alt+Enter newline)"
|
|
1818
|
+
}
|
|
1819
|
+
focus={!showSessionBrowser && !showSettings && !showDocsBrowser && !planExecutionState.askUserRequest}
|
|
1820
|
+
/>
|
|
1821
|
+
</Box>
|
|
1822
|
+
{/* Character counter */}
|
|
1823
|
+
{input.length > 0 && (
|
|
1824
|
+
<Text color={input.length > 4000 ? 'red' : input.length > 2000 ? 'yellow' : 'gray'} dimColor>
|
|
1825
|
+
{input.length.toLocaleString()}
|
|
1826
|
+
</Text>
|
|
1827
|
+
)}
|
|
1828
|
+
</Box>
|
|
1829
|
+
</Box>
|
|
1830
|
+
|
|
1831
|
+
{/* File Browser (shown when '@' is typed) */}
|
|
1832
|
+
{fileBrowserState.showFileBrowser && !isProcessing && (
|
|
1833
|
+
<Box marginTop={0}>
|
|
1834
|
+
{fileBrowserState.isLoadingFiles ? (
|
|
1835
|
+
<Box borderStyle="single" borderColor="yellow" paddingX={1}>
|
|
1836
|
+
<Spinner type="dots" />
|
|
1837
|
+
<Text color="yellow"> Loading files...</Text>
|
|
1838
|
+
</Box>
|
|
1839
|
+
) : (
|
|
1840
|
+
<FileBrowser
|
|
1841
|
+
filter={fileBrowserState.filterText}
|
|
1842
|
+
onSelect={handleFileSelect}
|
|
1843
|
+
onCancel={fileBrowserState.handleFileBrowserCancel}
|
|
1844
|
+
cachedFiles={fileBrowserState.cachedFileList}
|
|
1845
|
+
/>
|
|
1846
|
+
)}
|
|
1847
|
+
</Box>
|
|
1848
|
+
)}
|
|
1849
|
+
|
|
1850
|
+
{/* Command Browser (shown when '/' is typed at start) */}
|
|
1851
|
+
{commandBrowserState.showCommandBrowser && !isProcessing && !fileBrowserState.showFileBrowser && (
|
|
1852
|
+
<Box marginTop={0}>
|
|
1853
|
+
<CommandBrowser
|
|
1854
|
+
partialCommand={commandBrowserState.partialCommand}
|
|
1855
|
+
args={commandBrowserState.commandArgs}
|
|
1856
|
+
onSelect={handleCommandSelect}
|
|
1857
|
+
onCancel={commandBrowserState.handleCommandBrowserCancel}
|
|
1858
|
+
/>
|
|
1859
|
+
</Box>
|
|
1860
|
+
)}
|
|
1861
|
+
|
|
1862
|
+
{/* Session Browser (shown when /load command is submitted) */}
|
|
1863
|
+
{showSessionBrowser && !isProcessing && (
|
|
1864
|
+
<Box marginTop={0}>
|
|
1865
|
+
<SessionBrowser
|
|
1866
|
+
onSelect={handleSessionSelect}
|
|
1867
|
+
onCancel={() => setShowSessionBrowser(false)}
|
|
1868
|
+
/>
|
|
1869
|
+
</Box>
|
|
1870
|
+
)}
|
|
1871
|
+
|
|
1872
|
+
{/* Settings Browser (shown when /settings command is submitted) */}
|
|
1873
|
+
{showSettings && !isProcessing && (
|
|
1874
|
+
<Box marginTop={0}>
|
|
1875
|
+
<SettingsBrowser
|
|
1876
|
+
currentPlanningMode={planningMode}
|
|
1877
|
+
onPlanningModeChange={handleSettingsPlanningModeChange}
|
|
1878
|
+
onClose={handleSettingsClose}
|
|
1879
|
+
/>
|
|
1880
|
+
</Box>
|
|
1881
|
+
)}
|
|
1882
|
+
|
|
1883
|
+
{/* Model Selector (shown when /model command is submitted) */}
|
|
1884
|
+
{showModelSelector && !isProcessing && (
|
|
1885
|
+
<Box marginTop={0}>
|
|
1886
|
+
<ModelSelector
|
|
1887
|
+
onSelect={handleModelSelect}
|
|
1888
|
+
onCancel={handleModelSelectorCancel}
|
|
1889
|
+
/>
|
|
1890
|
+
</Box>
|
|
1891
|
+
)}
|
|
1892
|
+
|
|
1893
|
+
{/* DISABLED: Docs Browser removed - docs feature disabled */}
|
|
1894
|
+
|
|
1895
|
+
{/* Tool Selector (shown when /tool command is submitted) */}
|
|
1896
|
+
{showToolSelector && !isProcessing && (
|
|
1897
|
+
<Box marginTop={0}>
|
|
1898
|
+
<ToolSelector
|
|
1899
|
+
onClose={handleToolSelectorClose}
|
|
1900
|
+
/>
|
|
1901
|
+
</Box>
|
|
1902
|
+
)}
|
|
1903
|
+
|
|
1904
|
+
{/* Ask User Dialog */}
|
|
1905
|
+
{planExecutionState.askUserRequest && (
|
|
1906
|
+
<Box marginTop={1}>
|
|
1907
|
+
<AskUserDialog
|
|
1908
|
+
request={planExecutionState.askUserRequest}
|
|
1909
|
+
onResponse={planExecutionState.handleAskUserResponse}
|
|
1910
|
+
/>
|
|
1911
|
+
</Box>
|
|
1912
|
+
)}
|
|
1913
|
+
|
|
1914
|
+
{/* Status Bar - Claude Code style when processing */}
|
|
1915
|
+
<Box justifyContent="space-between" paddingX={1}>
|
|
1916
|
+
{isProcessing || planExecutionState.executionPhase === 'compacting' ? (
|
|
1917
|
+
// Claude Code style with pulsing star animation (shark for compacting)
|
|
1918
|
+
<>
|
|
1919
|
+
<Box flexDirection="column">
|
|
1920
|
+
{planExecutionState.executionPhase === 'compacting' ? (
|
|
1921
|
+
// Shark spinner for compacting (full width)
|
|
1922
|
+
<Box>
|
|
1923
|
+
<Text color="cyan"><Spinner type="shark" /></Text>
|
|
1924
|
+
</Box>
|
|
1925
|
+
) : null}
|
|
1926
|
+
<Box>
|
|
1927
|
+
<Text color="magenta">
|
|
1928
|
+
<Spinner type="star" />
|
|
1929
|
+
</Text>
|
|
1930
|
+
<Text color="white">{' '}
|
|
1931
|
+
{getStatusText({
|
|
1932
|
+
phase: planExecutionState.executionPhase,
|
|
1933
|
+
todos: planExecutionState.todos,
|
|
1934
|
+
currentToolName,
|
|
1935
|
+
})}…
|
|
1936
|
+
</Text>
|
|
1937
|
+
<Text color="gray">
|
|
1938
|
+
{' '}(esc to interrupt · {formatElapsedTime(sessionElapsed)}
|
|
1939
|
+
{sessionTokens > 0 && ` · ↑ ${formatTokensCompact(sessionTokens)} tokens`})
|
|
1940
|
+
</Text>
|
|
1941
|
+
</Box>
|
|
1942
|
+
</Box>
|
|
1943
|
+
<Box>
|
|
1944
|
+
{/* Context usage indicator (tokens / percent) */}
|
|
1945
|
+
{(() => {
|
|
1946
|
+
const ctxInfo = planExecutionState.getContextUsageInfo();
|
|
1947
|
+
const ctxColor = ctxInfo.percent < 50 ? 'green' : ctxInfo.percent < 80 ? 'yellow' : 'red';
|
|
1948
|
+
return (
|
|
1949
|
+
<>
|
|
1950
|
+
<Text color={ctxColor}>Context ({formatTokensCompact(ctxInfo.tokens)} / {ctxInfo.percent}%)</Text>
|
|
1951
|
+
<Text color="gray"> │ </Text>
|
|
1952
|
+
</>
|
|
1953
|
+
);
|
|
1954
|
+
})()}
|
|
1955
|
+
<Text color="cyan">{currentModelInfo.model}</Text>
|
|
1956
|
+
</Box>
|
|
1957
|
+
</>
|
|
1958
|
+
) : (
|
|
1959
|
+
// Default status bar
|
|
1960
|
+
<>
|
|
1961
|
+
<Box>
|
|
1962
|
+
{/* Execution mode indicator */}
|
|
1963
|
+
<Text color={executionMode === 'auto' ? 'green' : 'yellow'} bold>
|
|
1964
|
+
[{executionMode === 'auto' ? 'Auto' : 'Supervised'}]
|
|
1965
|
+
</Text>
|
|
1966
|
+
<Text color="gray"> │ </Text>
|
|
1967
|
+
{/* Context usage indicator (tokens / percent) */}
|
|
1968
|
+
{(() => {
|
|
1969
|
+
const ctxInfo = planExecutionState.getContextUsageInfo();
|
|
1970
|
+
const ctxColor = ctxInfo.percent < 50 ? 'green' : ctxInfo.percent < 80 ? 'yellow' : 'red';
|
|
1971
|
+
return (
|
|
1972
|
+
<>
|
|
1973
|
+
<Text color={ctxColor}>Context ({formatTokensCompact(ctxInfo.tokens)} / {ctxInfo.percent}%)</Text>
|
|
1974
|
+
<Text color="gray"> │ </Text>
|
|
1975
|
+
</>
|
|
1976
|
+
);
|
|
1977
|
+
})()}
|
|
1978
|
+
{/* Model info - always visible */}
|
|
1979
|
+
<Text color="gray">{getHealthIndicator()} </Text>
|
|
1980
|
+
<Text color="cyan">{currentModelInfo.model}</Text>
|
|
1981
|
+
<Text color="gray"> │ </Text>
|
|
1982
|
+
<Text color="gray">{shortenPath(process.cwd())}</Text>
|
|
1983
|
+
{planExecutionState.todos.length > 0 && (
|
|
1984
|
+
<>
|
|
1985
|
+
<Text color="gray"> │ </Text>
|
|
1986
|
+
<TodoStatusBar todos={planExecutionState.todos} />
|
|
1987
|
+
</>
|
|
1988
|
+
)}
|
|
1989
|
+
</Box>
|
|
1990
|
+
<Text color="gray" dimColor>
|
|
1991
|
+
Tab: mode │ /help
|
|
1992
|
+
</Text>
|
|
1993
|
+
</>
|
|
1994
|
+
)}
|
|
1995
|
+
</Box>
|
|
1996
|
+
|
|
1997
|
+
{/* Log Browser (Ctrl+O to toggle) */}
|
|
1998
|
+
{showLogFiles && (
|
|
1999
|
+
<Box marginTop={0}>
|
|
2000
|
+
<LogBrowser onClose={() => setShowLogFiles(false)} />
|
|
2001
|
+
</Box>
|
|
2002
|
+
)}
|
|
2003
|
+
</Box>
|
|
2004
|
+
);
|
|
2005
|
+
};
|
|
2006
|
+
|
|
2007
|
+
export default PlanExecuteApp;
|