@compilr-dev/cli 0.5.0 → 0.5.2
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/LICENSE +108 -0
- package/README.md +237 -69
- package/dist/.tsbuildinfo.app +1 -0
- package/dist/.tsbuildinfo.data +1 -0
- package/dist/.tsbuildinfo.domain +1 -0
- package/dist/.tsbuildinfo.foundation +1 -0
- package/dist/agent.d.ts +61 -4
- package/dist/agent.js +241 -245
- package/dist/anchors/index.d.ts +1 -1
- package/dist/anchors/index.js +1 -1
- package/dist/anchors/project-anchors.d.ts +2 -2
- package/dist/anchors/project-anchors.js +1 -1
- package/dist/auth/api-client.d.ts +124 -0
- package/dist/auth/api-client.js +261 -0
- package/dist/auth/index.d.ts +172 -0
- package/dist/auth/index.js +545 -0
- package/dist/auth/storage.d.ts +52 -0
- package/dist/auth/storage.js +118 -0
- package/dist/changelog/index.d.ts +16 -0
- package/dist/changelog/index.js +24 -0
- package/dist/changelog/releases.d.ts +17 -0
- package/dist/changelog/releases.js +63 -0
- package/dist/commands-v2/handlers/auth.d.ts +10 -0
- package/dist/commands-v2/handlers/auth.js +118 -0
- package/dist/commands-v2/handlers/background.d.ts +14 -0
- package/dist/commands-v2/handlers/background.js +276 -0
- package/dist/commands-v2/handlers/context.js +286 -81
- package/dist/commands-v2/handlers/core.d.ts +1 -0
- package/dist/commands-v2/handlers/core.js +133 -8
- package/dist/commands-v2/handlers/debug.js +18 -0
- package/dist/commands-v2/handlers/delegations.d.ts +8 -0
- package/dist/commands-v2/handlers/delegations.js +29 -0
- package/dist/commands-v2/handlers/files.d.ts +8 -0
- package/dist/commands-v2/handlers/files.js +162 -0
- package/dist/commands-v2/handlers/filter.d.ts +9 -0
- package/dist/commands-v2/handlers/filter.js +130 -0
- package/dist/commands-v2/handlers/games.d.ts +7 -0
- package/dist/commands-v2/handlers/games.js +57 -0
- package/dist/commands-v2/handlers/index.d.ts +13 -0
- package/dist/commands-v2/handlers/index.js +39 -0
- package/dist/commands-v2/handlers/mcp.d.ts +8 -0
- package/dist/commands-v2/handlers/mcp.js +39 -0
- package/dist/commands-v2/handlers/notifications.d.ts +9 -0
- package/dist/commands-v2/handlers/notifications.js +34 -0
- package/dist/commands-v2/handlers/project.js +295 -31
- package/dist/commands-v2/handlers/reset.d.ts +11 -0
- package/dist/commands-v2/handlers/reset.js +118 -0
- package/dist/commands-v2/handlers/session.d.ts +161 -0
- package/dist/commands-v2/handlers/session.js +805 -0
- package/dist/commands-v2/handlers/settings.d.ts +2 -0
- package/dist/commands-v2/handlers/settings.js +217 -35
- package/dist/commands-v2/handlers/tasks.d.ts +5 -0
- package/dist/commands-v2/handlers/tasks.js +36 -0
- package/dist/commands-v2/handlers/team.d.ts +9 -0
- package/dist/commands-v2/handlers/team.js +549 -0
- package/dist/commands-v2/handlers/terminals.d.ts +9 -0
- package/dist/commands-v2/handlers/terminals.js +34 -0
- package/dist/commands-v2/index.d.ts +3 -2
- package/dist/commands-v2/index.js +4 -1
- package/dist/commands-v2/registry.d.ts +15 -0
- package/dist/commands-v2/registry.js +34 -0
- package/dist/commands-v2/types.d.ts +81 -3
- package/dist/commands.js +13 -0
- package/dist/compilr-diff-companion.vsix +0 -0
- package/dist/db/index.js +98 -4
- package/dist/db/repositories/document-repository.d.ts +2 -0
- package/dist/db/repositories/document-repository.js +6 -1
- package/dist/db/repositories/index.d.ts +2 -0
- package/dist/db/repositories/index.js +1 -0
- package/dist/db/repositories/plan-repository.d.ts +101 -0
- package/dist/db/repositories/plan-repository.js +275 -0
- package/dist/db/repositories/project-repository.d.ts +6 -0
- package/dist/db/repositories/project-repository.js +41 -0
- package/dist/db/repositories/work-item-repository.d.ts +15 -0
- package/dist/db/repositories/work-item-repository.js +69 -4
- package/dist/db/schema.d.ts +40 -3
- package/dist/db/schema.js +66 -3
- package/dist/episodes/index.d.ts +20 -0
- package/dist/episodes/index.js +27 -0
- package/dist/episodes/recorder.d.ts +51 -0
- package/dist/episodes/recorder.js +195 -0
- package/dist/episodes/significant-work.d.ts +21 -0
- package/dist/episodes/significant-work.js +56 -0
- package/dist/episodes/store.d.ts +38 -0
- package/dist/episodes/store.js +199 -0
- package/dist/episodes/types.d.ts +35 -0
- package/dist/episodes/types.js +6 -0
- package/dist/episodes/work-at-risk.d.ts +12 -0
- package/dist/episodes/work-at-risk.js +38 -0
- package/dist/episodes/work-summary-anchor.d.ts +23 -0
- package/dist/episodes/work-summary-anchor.js +73 -0
- package/dist/games/coins.d.ts +66 -0
- package/dist/games/coins.js +165 -0
- package/dist/games/game-base.d.ts +84 -0
- package/dist/games/game-base.js +204 -0
- package/dist/games/index.d.ts +16 -0
- package/dist/games/index.js +49 -0
- package/dist/games/scores.d.ts +69 -0
- package/dist/games/scores.js +191 -0
- package/dist/games/tetris/board.d.ts +59 -0
- package/dist/games/tetris/board.js +170 -0
- package/dist/games/tetris/index.d.ts +109 -0
- package/dist/games/tetris/index.js +610 -0
- package/dist/games/tetris/pieces.d.ts +44 -0
- package/dist/games/tetris/pieces.js +271 -0
- package/dist/games/tetris/renderer.d.ts +26 -0
- package/dist/games/tetris/renderer.js +77 -0
- package/dist/guide/guide-content.d.ts +23 -0
- package/dist/guide/guide-content.js +196 -0
- package/dist/guide/index.d.ts +8 -0
- package/dist/guide/index.js +7 -0
- package/dist/guide/shared-content.d.ts +37 -0
- package/dist/guide/shared-content.js +1272 -0
- package/dist/guide/tutorial-helpers.d.ts +57 -0
- package/dist/guide/tutorial-helpers.js +147 -0
- package/dist/handlers/ask-user-handlers.d.ts +32 -0
- package/dist/handlers/ask-user-handlers.js +104 -0
- package/dist/handlers/delegation-handlers.d.ts +34 -0
- package/dist/handlers/delegation-handlers.js +291 -0
- package/dist/handlers/permission-handler.d.ts +30 -0
- package/dist/handlers/permission-handler.js +205 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.js +448 -271
- package/dist/input-handlers/memory-handler.d.ts +1 -1
- package/dist/input-handlers/memory-handler.js +2 -1
- package/dist/models/index.d.ts +10 -0
- package/dist/models/index.js +12 -0
- package/dist/models/model-registry.d.ts +38 -0
- package/dist/models/model-registry.js +69 -0
- package/dist/models/model-tiers.d.ts +28 -0
- package/dist/models/model-tiers.js +71 -0
- package/dist/models/model-validation.d.ts +25 -0
- package/dist/models/model-validation.js +291 -0
- package/dist/models/ollama-models.d.ts +73 -0
- package/dist/models/ollama-models.js +178 -0
- package/dist/models/provider-types.d.ts +6 -0
- package/dist/models/provider-types.js +1 -0
- package/dist/models/providers.d.ts +35 -0
- package/dist/models/providers.js +58 -0
- package/dist/models/types.d.ts +4 -0
- package/dist/models/types.js +4 -0
- package/dist/multi-agent/activity.d.ts +21 -0
- package/dist/multi-agent/activity.js +34 -0
- package/dist/multi-agent/agent-selection.d.ts +55 -0
- package/dist/multi-agent/agent-selection.js +90 -0
- package/dist/multi-agent/artifacts.d.ts +197 -0
- package/dist/multi-agent/artifacts.js +379 -0
- package/dist/multi-agent/checkpointer.d.ts +138 -0
- package/dist/multi-agent/checkpointer.js +471 -0
- package/dist/multi-agent/collision-utils.d.ts +16 -0
- package/dist/multi-agent/collision-utils.js +28 -0
- package/dist/multi-agent/context-resolver.d.ts +97 -0
- package/dist/multi-agent/context-resolver.js +316 -0
- package/dist/multi-agent/custom-agents.d.ts +83 -0
- package/dist/multi-agent/custom-agents.js +227 -0
- package/dist/multi-agent/delegation-tracker.d.ts +157 -0
- package/dist/multi-agent/delegation-tracker.js +243 -0
- package/dist/multi-agent/file-lock-hook.d.ts +29 -0
- package/dist/multi-agent/file-lock-hook.js +97 -0
- package/dist/multi-agent/file-locks.d.ts +58 -0
- package/dist/multi-agent/file-locks.js +194 -0
- package/dist/multi-agent/index.d.ts +24 -0
- package/dist/multi-agent/index.js +30 -0
- package/dist/multi-agent/mention-parser.d.ts +64 -0
- package/dist/multi-agent/mention-parser.js +146 -0
- package/dist/multi-agent/notification-manager.d.ts +84 -0
- package/dist/multi-agent/notification-manager.js +224 -0
- package/dist/multi-agent/pending-requests.d.ts +122 -0
- package/dist/multi-agent/pending-requests.js +155 -0
- package/dist/multi-agent/session-registry.d.ts +139 -0
- package/dist/multi-agent/session-registry.js +514 -0
- package/dist/multi-agent/shared-context.d.ts +293 -0
- package/dist/multi-agent/shared-context.js +671 -0
- package/dist/multi-agent/skill-requirements.d.ts +66 -0
- package/dist/multi-agent/skill-requirements.js +178 -0
- package/dist/multi-agent/task-assignment.d.ts +69 -0
- package/dist/multi-agent/task-assignment.js +123 -0
- package/dist/multi-agent/task-suggestion.d.ts +31 -0
- package/dist/multi-agent/task-suggestion.js +72 -0
- package/dist/multi-agent/team-agent.d.ts +201 -0
- package/dist/multi-agent/team-agent.js +488 -0
- package/dist/multi-agent/team.d.ts +286 -0
- package/dist/multi-agent/team.js +610 -0
- package/dist/multi-agent/tool-config.d.ts +110 -0
- package/dist/multi-agent/tool-config.js +661 -0
- package/dist/multi-agent/types.d.ts +211 -0
- package/dist/multi-agent/types.js +617 -0
- package/dist/prompts/plan-mode-prompt.d.ts +11 -0
- package/dist/prompts/plan-mode-prompt.js +95 -0
- package/dist/repl-helpers.js +5 -2
- package/dist/repl-v2.d.ts +401 -2
- package/dist/repl-v2.js +2588 -65
- package/dist/session/index.d.ts +6 -0
- package/dist/session/index.js +6 -0
- package/dist/session/project-session-manager.d.ts +158 -0
- package/dist/session/project-session-manager.js +650 -0
- package/dist/settings/index.d.ts +133 -13
- package/dist/settings/index.js +329 -24
- package/dist/settings/mcp-config.d.ts +76 -0
- package/dist/settings/mcp-config.js +143 -0
- package/dist/settings/paths.d.ts +4 -0
- package/dist/settings/paths.js +6 -0
- package/dist/shared-handlers.d.ts +62 -0
- package/dist/shared-handlers.js +48 -0
- package/dist/system-prompt/builder.d.ts +5 -0
- package/dist/system-prompt/builder.js +4 -0
- package/dist/system-prompt/index.d.ts +18 -0
- package/dist/system-prompt/index.js +18 -0
- package/dist/system-prompt/modules.d.ts +5 -0
- package/dist/system-prompt/modules.js +4 -0
- package/dist/tabbed-menu.js +2 -1
- package/dist/templates/compilr-md-import.d.ts +16 -0
- package/dist/templates/compilr-md-import.js +241 -0
- package/dist/templates/compilr-md.js +10 -61
- package/dist/templates/config-json.d.ts +1 -25
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates/index.js +34 -73
- package/dist/tool-names.d.ts +113 -0
- package/dist/tool-names.js +239 -0
- package/dist/tools/ask-user-simple.d.ts +1 -1
- package/dist/tools/ask-user-simple.js +2 -1
- package/dist/tools/ask-user.d.ts +1 -1
- package/dist/tools/ask-user.js +2 -1
- package/dist/tools/backlog.d.ts +2 -2
- package/dist/tools/backlog.js +1 -1
- package/dist/tools/db-tools.d.ts +13 -61
- package/dist/tools/db-tools.js +12 -13
- package/dist/tools/delegate-background.d.ts +27 -0
- package/dist/tools/delegate-background.js +115 -0
- package/dist/tools/delegate.d.ts +22 -0
- package/dist/tools/delegate.js +97 -0
- package/dist/tools/delegation-status.d.ts +16 -0
- package/dist/tools/delegation-status.js +128 -0
- package/dist/tools/guide-tool.d.ts +12 -0
- package/dist/tools/guide-tool.js +59 -0
- package/dist/tools/handoff.d.ts +25 -0
- package/dist/tools/handoff.js +99 -0
- package/dist/tools/meta-tools.d.ts +26 -0
- package/dist/tools/meta-tools.js +47 -0
- package/dist/tools/platform-adapter.d.ts +35 -0
- package/dist/tools/platform-adapter.js +404 -0
- package/dist/tools/project-db.d.ts +5 -73
- package/dist/tools/project-db.js +5 -336
- package/dist/tools.d.ts +67 -2
- package/dist/tools.js +240 -48
- package/dist/ui/autocomplete-controller.d.ts +42 -0
- package/dist/ui/autocomplete-controller.js +384 -0
- package/dist/ui/base/index.d.ts +1 -1
- package/dist/ui/base/index.js +1 -1
- package/dist/ui/base/overlay-base-v2.d.ts +10 -0
- package/dist/ui/base/overlay-base-v2.js +14 -0
- package/dist/ui/base/render-utils.d.ts +19 -0
- package/dist/ui/base/render-utils.js +25 -0
- package/dist/ui/base/tabbed-list-overlay-v2.d.ts +16 -1
- package/dist/ui/base/tabbed-list-overlay-v2.js +19 -1
- package/dist/ui/constants/labels.d.ts +14 -0
- package/dist/ui/constants/labels.js +52 -0
- package/dist/ui/conversation-store.d.ts +55 -0
- package/dist/ui/conversation-store.js +107 -0
- package/dist/ui/conversation.js +11 -13
- package/dist/ui/diff.d.ts +7 -1
- package/dist/ui/diff.js +85 -48
- package/dist/ui/ephemeral.js +3 -9
- package/dist/ui/file-autocomplete.d.ts +24 -0
- package/dist/ui/file-autocomplete.js +56 -0
- package/dist/ui/footer-renderer.d.ts +69 -0
- package/dist/ui/footer-renderer.js +431 -0
- package/dist/ui/footer.d.ts +74 -7
- package/dist/ui/footer.js +173 -16
- package/dist/ui/input-controller.d.ts +51 -0
- package/dist/ui/input-controller.js +176 -0
- package/dist/ui/input-prompt.d.ts +19 -0
- package/dist/ui/input-prompt.js +206 -14
- package/dist/ui/keyboard-handler.d.ts +57 -0
- package/dist/ui/keyboard-handler.js +557 -0
- package/dist/ui/live-region-facade.d.ts +42 -0
- package/dist/ui/live-region-facade.js +205 -0
- package/dist/ui/live-region.d.ts +0 -4
- package/dist/ui/live-region.js +6 -14
- package/dist/ui/mascot/renderer.d.ts +1 -1
- package/dist/ui/mascot/renderer.js +37 -2
- package/dist/ui/overlay/data/tutorial-content.d.ts +9 -0
- package/dist/ui/overlay/data/tutorial-content.js +9 -0
- package/dist/ui/overlay/data/tutorial-registry.d.ts +12 -0
- package/dist/ui/overlay/data/tutorial-registry.js +116 -0
- package/dist/ui/overlay/data/tutorial-types.d.ts +35 -0
- package/dist/ui/overlay/data/tutorial-types.js +6 -0
- package/dist/ui/overlay/data/tutorials/basics/first-conversation.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/basics/first-conversation.js +220 -0
- package/dist/ui/overlay/data/tutorials/basics/first-project.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/basics/first-project.js +284 -0
- package/dist/ui/overlay/data/tutorials/basics/navigation.d.ts +8 -0
- package/dist/ui/overlay/data/tutorials/basics/navigation.js +22 -0
- package/dist/ui/overlay/data/tutorials/basics/welcome.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/basics/welcome.js +174 -0
- package/dist/ui/overlay/data/tutorials/config/context-management.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/config/context-management.js +158 -0
- package/dist/ui/overlay/data/tutorials/config/mcp-servers.d.ts +8 -0
- package/dist/ui/overlay/data/tutorials/config/mcp-servers.js +155 -0
- package/dist/ui/overlay/data/tutorials/config/model-selection.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/config/model-selection.js +162 -0
- package/dist/ui/overlay/data/tutorials/config/permissions-safety.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/config/permissions-safety.js +163 -0
- package/dist/ui/overlay/data/tutorials/config/settings-config.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/config/settings-config.js +166 -0
- package/dist/ui/overlay/data/tutorials/planning/arch.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/arch.js +168 -0
- package/dist/ui/overlay/data/tutorials/planning/backlog.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/backlog.js +103 -0
- package/dist/ui/overlay/data/tutorials/planning/build.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/build.js +173 -0
- package/dist/ui/overlay/data/tutorials/planning/design.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/design.js +205 -0
- package/dist/ui/overlay/data/tutorials/planning/docs.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/docs.js +143 -0
- package/dist/ui/overlay/data/tutorials/planning/prd.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/prd.js +173 -0
- package/dist/ui/overlay/data/tutorials/planning/scaffold.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/scaffold.js +164 -0
- package/dist/ui/overlay/data/tutorials/planning/sketch.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/sketch.js +58 -0
- package/dist/ui/overlay/data/tutorials/projects/anchors.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/projects/anchors.js +248 -0
- package/dist/ui/overlay/data/tutorials/projects/import-project.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/projects/import-project.js +172 -0
- package/dist/ui/overlay/data/tutorials/projects/managing-projects.d.ts +8 -0
- package/dist/ui/overlay/data/tutorials/projects/managing-projects.js +212 -0
- package/dist/ui/overlay/data/tutorials/projects/new-project.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/projects/new-project.js +251 -0
- package/dist/ui/overlay/data/tutorials/projects/session-management.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/projects/session-management.js +169 -0
- package/dist/ui/overlay/data/tutorials/teams/background-execution.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/teams/background-execution.js +171 -0
- package/dist/ui/overlay/data/tutorials/teams/multi-terminal.d.ts +8 -0
- package/dist/ui/overlay/data/tutorials/teams/multi-terminal.js +147 -0
- package/dist/ui/overlay/data/tutorials/teams/task-assignment.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/teams/task-assignment.js +204 -0
- package/dist/ui/overlay/data/tutorials/teams/team-overview.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/teams/team-overview.js +165 -0
- package/dist/ui/overlay/data/tutorials/teams/working-with-agents.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/teams/working-with-agents.js +172 -0
- package/dist/ui/overlay/impl/agents-overlay-v2.js +6 -17
- package/dist/ui/overlay/impl/anchors-overlay-v2.js +30 -64
- package/dist/ui/overlay/impl/artifact-detail-overlay-v2.d.ts +43 -0
- package/dist/ui/overlay/impl/artifact-detail-overlay-v2.js +232 -0
- package/dist/ui/overlay/impl/artifact-overlay-v2.d.ts +40 -0
- package/dist/ui/overlay/impl/artifact-overlay-v2.js +115 -0
- package/dist/ui/overlay/impl/ask-user-overlay-v2.js +2 -5
- package/dist/ui/overlay/impl/background-overlay-v2.d.ts +40 -0
- package/dist/ui/overlay/impl/background-overlay-v2.js +147 -0
- package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +4 -1
- package/dist/ui/overlay/impl/backlog-overlay-v2.js +55 -16
- package/dist/ui/overlay/impl/changelog-overlay-v2.d.ts +44 -0
- package/dist/ui/overlay/impl/changelog-overlay-v2.js +165 -0
- package/dist/ui/overlay/impl/commands-overlay-v2.js +4 -6
- package/dist/ui/overlay/impl/config-overlay-v2.d.ts +12 -1
- package/dist/ui/overlay/impl/config-overlay-v2.js +164 -100
- package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.d.ts +83 -0
- package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.js +711 -0
- package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +2 -0
- package/dist/ui/overlay/impl/dashboard-overlay-v2.js +26 -3
- package/dist/ui/overlay/impl/delegations-overlay-v2.d.ts +28 -0
- package/dist/ui/overlay/impl/delegations-overlay-v2.js +279 -0
- package/dist/ui/overlay/impl/docs-overlay-v2.js +12 -9
- package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +7 -0
- package/dist/ui/overlay/impl/document-detail-overlay-v2.js +119 -78
- package/dist/ui/overlay/impl/filter-overlay-v2.d.ts +41 -0
- package/dist/ui/overlay/impl/filter-overlay-v2.js +110 -0
- package/dist/ui/overlay/impl/games-overlay-v2.d.ts +31 -0
- package/dist/ui/overlay/impl/games-overlay-v2.js +135 -0
- package/dist/ui/overlay/impl/help-overlay-v2.d.ts +26 -3
- package/dist/ui/overlay/impl/help-overlay-v2.js +20 -42
- package/dist/ui/overlay/impl/login-overlay-v2.d.ts +49 -0
- package/dist/ui/overlay/impl/login-overlay-v2.js +277 -0
- package/dist/ui/overlay/impl/mcp-overlay-v2.d.ts +63 -0
- package/dist/ui/overlay/impl/mcp-overlay-v2.js +907 -0
- package/dist/ui/overlay/impl/model-overlay-v2.d.ts +57 -13
- package/dist/ui/overlay/impl/model-overlay-v2.js +1086 -61
- package/dist/ui/overlay/impl/new-overlay-v2.d.ts +37 -6
- package/dist/ui/overlay/impl/new-overlay-v2.js +715 -65
- package/dist/ui/overlay/impl/notifications-overlay-v2.d.ts +20 -0
- package/dist/ui/overlay/impl/notifications-overlay-v2.js +116 -0
- package/dist/ui/overlay/impl/onboarding-wizard-overlay-v2.d.ts +76 -0
- package/dist/ui/overlay/impl/onboarding-wizard-overlay-v2.js +728 -0
- package/dist/ui/overlay/impl/pending-overlay-v2.d.ts +51 -0
- package/dist/ui/overlay/impl/pending-overlay-v2.js +445 -0
- package/dist/ui/overlay/impl/permission-overlay-v2.js +5 -5
- package/dist/ui/overlay/impl/permissions-overlay-v2.d.ts +85 -0
- package/dist/ui/overlay/impl/permissions-overlay-v2.js +820 -0
- package/dist/ui/overlay/impl/plan-approval-overlay-v2.d.ts +35 -0
- package/dist/ui/overlay/impl/plan-approval-overlay-v2.js +181 -0
- package/dist/ui/overlay/impl/project-edit-overlay-v2.d.ts +36 -0
- package/dist/ui/overlay/impl/project-edit-overlay-v2.js +195 -0
- package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +1 -0
- package/dist/ui/overlay/impl/projects-overlay-v2.js +278 -44
- package/dist/ui/overlay/impl/reset-overlay-v2.d.ts +39 -0
- package/dist/ui/overlay/impl/reset-overlay-v2.js +107 -0
- package/dist/ui/overlay/impl/resume-overlay-v2.d.ts +60 -0
- package/dist/ui/overlay/impl/resume-overlay-v2.js +414 -0
- package/dist/ui/overlay/impl/session-mode-overlay-v2.d.ts +43 -0
- package/dist/ui/overlay/impl/session-mode-overlay-v2.js +124 -0
- package/dist/ui/overlay/impl/tasks-overlay-v2.d.ts +28 -0
- package/dist/ui/overlay/impl/tasks-overlay-v2.js +283 -0
- package/dist/ui/overlay/impl/team-overlay-v2.d.ts +86 -0
- package/dist/ui/overlay/impl/team-overlay-v2.js +692 -0
- package/dist/ui/overlay/impl/terminals-overlay-v2.d.ts +26 -0
- package/dist/ui/overlay/impl/terminals-overlay-v2.js +217 -0
- package/dist/ui/overlay/impl/tools-overlay-v2.js +3 -7
- package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +30 -16
- package/dist/ui/overlay/impl/tutorial-overlay-v2.js +133 -956
- package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +1 -0
- package/dist/ui/overlay/impl/workflow-overlay-v2.js +10 -4
- package/dist/ui/overlay/index.d.ts +20 -1
- package/dist/ui/overlay/index.js +19 -0
- package/dist/ui/overlay/types.d.ts +5 -0
- package/dist/ui/overlay-manager.d.ts +43 -0
- package/dist/ui/overlay-manager.js +238 -0
- package/dist/ui/overlays.js +4 -16
- package/dist/ui/permission-overlay.js +6 -5
- package/dist/ui/status-bar-controller.d.ts +33 -0
- package/dist/ui/status-bar-controller.js +99 -0
- package/dist/ui/subagent-renderer.js +3 -19
- package/dist/ui/terminal-autocomplete-utils.d.ts +23 -0
- package/dist/ui/terminal-autocomplete-utils.js +83 -0
- package/dist/ui/terminal-line-builders.d.ts +17 -0
- package/dist/ui/terminal-line-builders.js +42 -0
- package/dist/ui/terminal-render-item.d.ts +16 -0
- package/dist/ui/terminal-render-item.js +267 -0
- package/dist/ui/terminal-renderer.d.ts +7 -8
- package/dist/ui/terminal-renderer.js +7 -8
- package/dist/ui/terminal-types.d.ts +179 -0
- package/dist/ui/terminal-types.js +34 -0
- package/dist/ui/terminal-ui.d.ts +144 -276
- package/dist/ui/terminal-ui.js +384 -1861
- package/dist/ui/todo-zone.d.ts +19 -1
- package/dist/ui/todo-zone.js +71 -13
- package/dist/ui/tool-formatters.js +696 -1
- package/dist/ui/turn-metrics.d.ts +56 -0
- package/dist/ui/turn-metrics.js +75 -0
- package/dist/ui/types.d.ts +28 -0
- package/dist/ui/types.js +1 -0
- package/dist/ui/vscode-diff-ipc.d.ts +102 -0
- package/dist/ui/vscode-diff-ipc.js +385 -0
- package/dist/utils/credentials.d.ts +24 -5
- package/dist/utils/credentials.js +123 -9
- package/dist/utils/format-tokens.d.ts +13 -0
- package/dist/utils/format-tokens.js +18 -0
- package/dist/utils/git-config.d.ts +26 -0
- package/dist/utils/git-config.js +54 -0
- package/dist/utils/message-utils.d.ts +61 -0
- package/dist/utils/message-utils.js +72 -0
- package/dist/utils/model-tiers.d.ts +8 -1
- package/dist/utils/model-tiers.js +38 -16
- package/dist/utils/open-browser.d.ts +5 -0
- package/dist/utils/open-browser.js +32 -0
- package/dist/utils/path-safety.js +3 -2
- package/dist/utils/project-detection.d.ts +58 -0
- package/dist/utils/project-detection.js +424 -0
- package/dist/utils/project-memory.js +2 -1
- package/dist/utils/project-status.d.ts +2 -2
- package/dist/utils/startup-perf.d.ts +18 -0
- package/dist/utils/startup-perf.js +60 -0
- package/dist/utils/token-tracker.d.ts +62 -0
- package/dist/utils/token-tracker.js +150 -0
- package/dist/utils/token-types.d.ts +23 -0
- package/dist/utils/token-types.js +18 -0
- package/dist/utils/types/config-types.d.ts +32 -0
- package/dist/utils/types/config-types.js +8 -0
- package/dist/utils/update-checker.d.ts +28 -0
- package/dist/utils/update-checker.js +106 -0
- package/dist/utils/version.d.ts +7 -0
- package/dist/utils/version.js +10 -0
- package/dist/utils/vscode-detect.d.ts +39 -0
- package/dist/utils/vscode-detect.js +137 -0
- package/package.json +27 -13
- package/dist/commands/handler-types.d.ts +0 -68
- package/dist/commands/handler-types.js +0 -8
- package/dist/commands/handlers/agent-commands.d.ts +0 -13
- package/dist/commands/handlers/agent-commands.js +0 -305
- package/dist/commands/handlers/design-commands.d.ts +0 -15
- package/dist/commands/handlers/design-commands.js +0 -334
- package/dist/commands/handlers/index.d.ts +0 -20
- package/dist/commands/handlers/index.js +0 -43
- package/dist/commands/handlers/overlay-commands.d.ts +0 -21
- package/dist/commands/handlers/overlay-commands.js +0 -287
- package/dist/commands/handlers/project-commands.d.ts +0 -11
- package/dist/commands/handlers/project-commands.js +0 -167
- package/dist/commands/handlers/simple-commands.d.ts +0 -19
- package/dist/commands/handlers/simple-commands.js +0 -144
- package/dist/commands/registry.d.ts +0 -50
- package/dist/commands/registry.js +0 -75
- package/dist/index.old.d.ts +0 -7
- package/dist/index.old.js +0 -1014
- package/dist/repl.d.ts +0 -149
- package/dist/repl.js +0 -1151
- package/dist/templates/claude-md.d.ts +0 -7
- package/dist/templates/claude-md.js +0 -189
- package/dist/test-autocomplete.d.ts +0 -7
- package/dist/test-autocomplete.js +0 -85
- package/dist/test-tabbed-menu.d.ts +0 -7
- package/dist/test-tabbed-menu.js +0 -25
- package/dist/tool-selector.d.ts +0 -71
- package/dist/tool-selector.js +0 -184
- package/dist/tools/anchor-tools.d.ts +0 -31
- package/dist/tools/anchor-tools.js +0 -255
- package/dist/tools/backlog-wrappers.d.ts +0 -54
- package/dist/tools/backlog-wrappers.js +0 -338
- package/dist/tools/document-db.d.ts +0 -43
- package/dist/tools/document-db.js +0 -220
- package/dist/tools/workitem-db.d.ts +0 -103
- package/dist/tools/workitem-db.js +0 -549
- package/dist/ui/agents-overlay-v2.d.ts +0 -43
- package/dist/ui/agents-overlay-v2.js +0 -809
- package/dist/ui/agents-overlay.d.ts +0 -12
- package/dist/ui/agents-overlay.js +0 -863
- package/dist/ui/anchors-overlay.d.ts +0 -12
- package/dist/ui/anchors-overlay.js +0 -775
- package/dist/ui/arch-type-overlay.d.ts +0 -15
- package/dist/ui/arch-type-overlay.js +0 -201
- package/dist/ui/ask-user-overlay-v2.d.ts +0 -26
- package/dist/ui/ask-user-overlay-v2.js +0 -555
- package/dist/ui/ask-user-simple-overlay-v2.d.ts +0 -25
- package/dist/ui/ask-user-simple-overlay-v2.js +0 -215
- package/dist/ui/backlog-overlay.d.ts +0 -32
- package/dist/ui/backlog-overlay.js +0 -652
- package/dist/ui/commands-overlay-v2.d.ts +0 -33
- package/dist/ui/commands-overlay-v2.js +0 -441
- package/dist/ui/commands-overlay.d.ts +0 -16
- package/dist/ui/commands-overlay.js +0 -439
- package/dist/ui/config-overlay.d.ts +0 -35
- package/dist/ui/config-overlay.js +0 -707
- package/dist/ui/docs-overlay.d.ts +0 -17
- package/dist/ui/docs-overlay.js +0 -303
- package/dist/ui/footer-v2.d.ts +0 -222
- package/dist/ui/footer-v2.js +0 -1349
- package/dist/ui/help-overlay-v2.d.ts +0 -34
- package/dist/ui/help-overlay-v2.js +0 -309
- package/dist/ui/help-overlay.d.ts +0 -16
- package/dist/ui/help-overlay.js +0 -316
- package/dist/ui/init-overlay-v2.d.ts +0 -34
- package/dist/ui/init-overlay-v2.js +0 -600
- package/dist/ui/init-overlay.d.ts +0 -34
- package/dist/ui/init-overlay.js +0 -604
- package/dist/ui/input-prompt-v2.d.ts +0 -180
- package/dist/ui/input-prompt-v2.js +0 -999
- package/dist/ui/iteration-limit-overlay-v2.d.ts +0 -21
- package/dist/ui/iteration-limit-overlay-v2.js +0 -114
- package/dist/ui/keys-overlay-v2.d.ts +0 -41
- package/dist/ui/keys-overlay-v2.js +0 -248
- package/dist/ui/mascot-overlay-v2.d.ts +0 -41
- package/dist/ui/mascot-overlay-v2.js +0 -138
- package/dist/ui/mascot-overlay.d.ts +0 -21
- package/dist/ui/mascot-overlay.js +0 -146
- package/dist/ui/model-overlay-v2.d.ts +0 -49
- package/dist/ui/model-overlay-v2.js +0 -118
- package/dist/ui/model-overlay.d.ts +0 -27
- package/dist/ui/model-overlay.js +0 -221
- package/dist/ui/model-warning-overlay.d.ts +0 -30
- package/dist/ui/model-warning-overlay.js +0 -169
- package/dist/ui/new-overlay.d.ts +0 -34
- package/dist/ui/new-overlay.js +0 -604
- package/dist/ui/overlay/impl/init-overlay-v2.d.ts +0 -77
- package/dist/ui/overlay/impl/init-overlay-v2.js +0 -593
- package/dist/ui/overlay/overlay-types.d.ts +0 -128
- package/dist/ui/overlay/overlay-types.js +0 -22
- package/dist/ui/overlays/help-overlay-v2.d.ts +0 -28
- package/dist/ui/overlays/help-overlay-v2.js +0 -198
- package/dist/ui/overlays/index.d.ts +0 -11
- package/dist/ui/overlays/index.js +0 -11
- package/dist/ui/permission-overlay-v2.d.ts +0 -36
- package/dist/ui/permission-overlay-v2.js +0 -380
- package/dist/ui/projects-overlay.d.ts +0 -19
- package/dist/ui/projects-overlay.js +0 -484
- package/dist/ui/theme-overlay-v2.d.ts +0 -42
- package/dist/ui/theme-overlay-v2.js +0 -135
- package/dist/ui/theme-overlay.d.ts +0 -24
- package/dist/ui/theme-overlay.js +0 -127
- package/dist/ui/tools-overlay-v2.d.ts +0 -47
- package/dist/ui/tools-overlay-v2.js +0 -218
- package/dist/ui/tools-overlay.d.ts +0 -34
- package/dist/ui/tools-overlay.js +0 -230
- package/dist/ui/tutorial-overlay-v2.d.ts +0 -31
- package/dist/ui/tutorial-overlay-v2.js +0 -1035
- package/dist/ui/tutorial-overlay.d.ts +0 -11
- package/dist/ui/tutorial-overlay.js +0 -1034
- package/dist/ui/workflow-overlay.d.ts +0 -22
- package/dist/ui/workflow-overlay.js +0 -636
package/dist/repl.js
DELETED
|
@@ -1,1151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* REPL (Read-Eval-Print Loop)
|
|
3
|
-
*
|
|
4
|
-
* Main orchestration for the interactive agent session.
|
|
5
|
-
* Coordinates between input, agent execution, and output.
|
|
6
|
-
*
|
|
7
|
-
* Uses event-driven architecture with Footer component for:
|
|
8
|
-
* - Persistent todo list while agent runs
|
|
9
|
-
* - Persistent input prompt (always visible)
|
|
10
|
-
* - Input queueing during agent execution
|
|
11
|
-
* - Esc to cancel running agent
|
|
12
|
-
*/
|
|
13
|
-
import { exec } from 'child_process';
|
|
14
|
-
import { getToolPermissionInfo } from './agent.js';
|
|
15
|
-
import * as fs from 'fs';
|
|
16
|
-
import * as path from 'path';
|
|
17
|
-
import pc from 'picocolors';
|
|
18
|
-
import { debug, debugError } from './debug.js';
|
|
19
|
-
import { debugLog } from './utils/debug-log.js';
|
|
20
|
-
import { getNextMode, MODE_INFO } from './ui/types.js';
|
|
21
|
-
import { createInitialState, updateTodos, setAgentRunning } from './state.js';
|
|
22
|
-
import { Footer } from './ui/footer.js';
|
|
23
|
-
import * as conversation from './ui/conversation.js';
|
|
24
|
-
import * as overlays from './ui/overlays.js';
|
|
25
|
-
import * as terminal from './ui/terminal.js';
|
|
26
|
-
import { TerminalRenderer, RenderMode } from './ui/terminal-renderer.js';
|
|
27
|
-
import { resolveCommand } from './commands.js';
|
|
28
|
-
// Note: All overlay imports (showConfigOverlay, showModelOverlay, showThemeOverlay, showMascotOverlay, etc.)
|
|
29
|
-
// are now handled by command handlers in ./commands/handlers/
|
|
30
|
-
import { showToolsOverlay } from './ui/tools-overlay.js';
|
|
31
|
-
import { registerFooterCallbacks } from './ui/overlay-controller.js';
|
|
32
|
-
import { getCustomCommandRegistry, commandRegistry, registerAllHandlers } from './commands/index.js';
|
|
33
|
-
import { getPermissionMode } from './settings/index.js';
|
|
34
|
-
// Note: findBacklogPath, parseBacklogItems moved to command handlers
|
|
35
|
-
import { isOverlayActive } from './shared-handlers.js';
|
|
36
|
-
import { getActiveProject } from './tools/project-db.js';
|
|
37
|
-
import { getAnchorManager } from './anchors/index.js';
|
|
38
|
-
import { isMemoryInput, handleMemoryInput } from './input-handlers/index.js';
|
|
39
|
-
// Helper functions extracted to reduce file size
|
|
40
|
-
import { selectToolNamesByIntent } from './repl-helpers.js';
|
|
41
|
-
// =============================================================================
|
|
42
|
-
// REPL Class
|
|
43
|
-
// =============================================================================
|
|
44
|
-
export class REPL {
|
|
45
|
-
agent;
|
|
46
|
-
model;
|
|
47
|
-
currentModel; // Can be hot-switched
|
|
48
|
-
provider;
|
|
49
|
-
version;
|
|
50
|
-
showFiltering;
|
|
51
|
-
onModeChange;
|
|
52
|
-
onAgentFinish;
|
|
53
|
-
clearSubagentTracking;
|
|
54
|
-
startTime;
|
|
55
|
-
initialCommand;
|
|
56
|
-
state;
|
|
57
|
-
footer;
|
|
58
|
-
renderer;
|
|
59
|
-
// Session stats
|
|
60
|
-
sessionInputTokens = 0;
|
|
61
|
-
sessionOutputTokens = 0;
|
|
62
|
-
sessionRequests = 0;
|
|
63
|
-
// Running state
|
|
64
|
-
isRunning = false;
|
|
65
|
-
shouldReturnToMenu = false;
|
|
66
|
-
agentRunning = false;
|
|
67
|
-
abortController = null;
|
|
68
|
-
// Promise for waiting on REPL exit
|
|
69
|
-
exitResolve = null;
|
|
70
|
-
// Text buffer flush function (set during processMessage, allows permission handler to flush)
|
|
71
|
-
textBufferFlusher = null;
|
|
72
|
-
constructor(options) {
|
|
73
|
-
this.agent = options.agent;
|
|
74
|
-
this.model = options.model;
|
|
75
|
-
this.currentModel = options.model; // Start with same model, can be hot-switched
|
|
76
|
-
this.provider = options.provider ?? 'unknown';
|
|
77
|
-
this.version = options.version ?? '0.0.1';
|
|
78
|
-
this.showFiltering = options.showFiltering ?? false;
|
|
79
|
-
this.onModeChange = options.onModeChange;
|
|
80
|
-
this.onAgentFinish = options.onAgentFinish;
|
|
81
|
-
this.clearSubagentTracking = options.clearSubagentTracking;
|
|
82
|
-
this.startTime = new Date();
|
|
83
|
-
this.initialCommand = options.initialCommand;
|
|
84
|
-
this.state = createInitialState(this.model);
|
|
85
|
-
// Map permission mode setting to AgentMode
|
|
86
|
-
const permissionMode = getPermissionMode();
|
|
87
|
-
const initialMode = permissionMode === 'bypass' ? 'auto-accept' :
|
|
88
|
-
permissionMode === 'plan' ? 'plan' : 'normal';
|
|
89
|
-
this.footer = new Footer({
|
|
90
|
-
showSeparators: true,
|
|
91
|
-
initialMode,
|
|
92
|
-
});
|
|
93
|
-
// Initialize TerminalRenderer in REPL mode
|
|
94
|
-
// TODO: Scroll regions disabled until incremental rebuild is complete
|
|
95
|
-
this.renderer = new TerminalRenderer({
|
|
96
|
-
initialMode: RenderMode.REPL,
|
|
97
|
-
useScrollRegions: false, // DISABLED: Use legacy mode for now
|
|
98
|
-
debug: false,
|
|
99
|
-
});
|
|
100
|
-
// Connect footer to renderer (enables external renderer mode on footer)
|
|
101
|
-
this.renderer.setFooter(this.footer);
|
|
102
|
-
// Connect conversation output to renderer
|
|
103
|
-
conversation.setRenderer(this.renderer);
|
|
104
|
-
// Note: renderer.start() is called in run(), not here
|
|
105
|
-
// This ensures proper startup sequence: footer.start() → renderer.start() → printWelcome()
|
|
106
|
-
// Notify external state handler of initial mode
|
|
107
|
-
if (this.onModeChange && initialMode !== 'normal') {
|
|
108
|
-
this.onModeChange(initialMode);
|
|
109
|
-
}
|
|
110
|
-
// Set up event handlers
|
|
111
|
-
this.setupEventHandlers();
|
|
112
|
-
// Notify that footer is ready with pause/resume/setSuggestion functions
|
|
113
|
-
if (options.onFooterReady) {
|
|
114
|
-
options.onFooterReady(() => { this.footer.pauseAnimation(); }, () => { this.footer.resumeAnimation(); }, (action) => { this.footer.setSuggestion(action); });
|
|
115
|
-
}
|
|
116
|
-
// Provide text buffer flush function (for permission handler to flush before overlay)
|
|
117
|
-
if (options.onTextBufferReady) {
|
|
118
|
-
options.onTextBufferReady(() => {
|
|
119
|
-
if (this.textBufferFlusher) {
|
|
120
|
-
this.textBufferFlusher();
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
// Provide subagent tracking callbacks (for agent to report subagent activity)
|
|
125
|
-
if (options.onSubagentReady) {
|
|
126
|
-
options.onSubagentReady({
|
|
127
|
-
onStart: (agentId, agentType, description) => {
|
|
128
|
-
this.footer.onSubagentStart(agentId, agentType, description);
|
|
129
|
-
},
|
|
130
|
-
onToolUse: (agentId, toolName, summary) => {
|
|
131
|
-
this.footer.onSubagentToolUse(agentId, toolName, summary);
|
|
132
|
-
},
|
|
133
|
-
onEnd: (agentId, success, tokenCount, error) => {
|
|
134
|
-
this.footer.onSubagentEnd(agentId, success, tokenCount, error);
|
|
135
|
-
},
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
// Register footer callbacks for overlay controller (used by tools like ask_user)
|
|
139
|
-
registerFooterCallbacks(() => { this.footer.pauseAnimation(); }, () => { this.footer.resumeAnimation(); });
|
|
140
|
-
// Register all command handlers (idempotent - safe to call multiple times)
|
|
141
|
-
registerAllHandlers();
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Reload project-specific anchors when switching projects
|
|
145
|
-
* Clears old project anchors and loads new project anchors
|
|
146
|
-
*/
|
|
147
|
-
reloadProjectAnchors(oldProjectId, newProjectId) {
|
|
148
|
-
// Clear old project anchors (if any)
|
|
149
|
-
if (oldProjectId) {
|
|
150
|
-
const clearedCount = this.agent.clearAnchors({ projectId: oldProjectId });
|
|
151
|
-
debug('anchors', `Cleared ${String(clearedCount)} anchors for project ${oldProjectId}`);
|
|
152
|
-
}
|
|
153
|
-
// Load new project anchors from disk
|
|
154
|
-
const newProjectAnchors = getAnchorManager(newProjectId).getAll({ scope: 'persistent' });
|
|
155
|
-
debug('anchors', `Loading ${String(newProjectAnchors.length)} anchors for project ${newProjectId}`);
|
|
156
|
-
// Add new project anchors to the agent
|
|
157
|
-
for (const anchor of newProjectAnchors) {
|
|
158
|
-
this.agent.addAnchor({
|
|
159
|
-
id: anchor.id,
|
|
160
|
-
content: anchor.content,
|
|
161
|
-
priority: anchor.priority,
|
|
162
|
-
scope: anchor.scope,
|
|
163
|
-
tags: anchor.tags,
|
|
164
|
-
projectId: newProjectId,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
if (newProjectAnchors.length > 0) {
|
|
168
|
-
conversation.printInfo(` Anchors: ${String(newProjectAnchors.length)} loaded for project`);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Set up Footer event handlers
|
|
173
|
-
*/
|
|
174
|
-
setupEventHandlers() {
|
|
175
|
-
// Handle submit - process message or it gets queued by Footer
|
|
176
|
-
this.footer.on('submit', (input) => {
|
|
177
|
-
if (!this.agentRunning && input.trim()) {
|
|
178
|
-
void this.handleSubmit(input);
|
|
179
|
-
}
|
|
180
|
-
// If agent is running, Footer automatically queues the input
|
|
181
|
-
});
|
|
182
|
-
// Handle slash commands
|
|
183
|
-
this.footer.on('command', (command, args) => {
|
|
184
|
-
debugLog('REPL:command', `received /${command}`);
|
|
185
|
-
// NOTE: Don't pause footer here - let overlays pause when ready to render
|
|
186
|
-
// This prevents blank screen flash when overlays have slow constructors
|
|
187
|
-
void this.handleCommand(command, args).then((shouldContinue) => {
|
|
188
|
-
debugLog('REPL:command', 'handler complete');
|
|
189
|
-
if (!shouldContinue) {
|
|
190
|
-
// Exiting - don't restart input, just resolve
|
|
191
|
-
this.isRunning = false;
|
|
192
|
-
if (this.exitResolve) {
|
|
193
|
-
this.exitResolve();
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
// Overlays handle their own pause/resume via lifecycle
|
|
198
|
-
// For non-overlay commands, we need to restart the input prompt
|
|
199
|
-
// (finishInput() stopped it when user pressed Enter)
|
|
200
|
-
this.footer.restartInput();
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
// Handle Esc - abort running agent
|
|
205
|
-
this.footer.on('escape', () => {
|
|
206
|
-
if (this.agentRunning && this.abortController) {
|
|
207
|
-
this.abortController.abort();
|
|
208
|
-
conversation.printWarning('Agent execution cancelled');
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
// Handle Ctrl+C - exit REPL
|
|
212
|
-
this.footer.on('cancel', () => {
|
|
213
|
-
this.isRunning = false;
|
|
214
|
-
if (this.exitResolve) {
|
|
215
|
-
this.exitResolve();
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
// Handle Shift+Tab - cycle modes
|
|
219
|
-
this.footer.on('modeChange', () => {
|
|
220
|
-
this.cycleMode();
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Cycle through agent modes (normal -> auto-accept -> plan -> normal)
|
|
225
|
-
*/
|
|
226
|
-
cycleMode() {
|
|
227
|
-
const currentMode = this.footer.getMode();
|
|
228
|
-
const nextMode = getNextMode(currentMode);
|
|
229
|
-
this.footer.setMode(nextMode);
|
|
230
|
-
// Notify external state handler
|
|
231
|
-
if (this.onModeChange) {
|
|
232
|
-
this.onModeChange(nextMode);
|
|
233
|
-
}
|
|
234
|
-
// Show feedback
|
|
235
|
-
const modeInfo = MODE_INFO[nextMode];
|
|
236
|
-
this.footer.clearForOutput();
|
|
237
|
-
conversation.printInfo(`Mode: ${modeInfo.label} - ${modeInfo.description}`);
|
|
238
|
-
this.footer.forceRender();
|
|
239
|
-
}
|
|
240
|
-
// ===========================================================================
|
|
241
|
-
// Public API
|
|
242
|
-
// ===========================================================================
|
|
243
|
-
/**
|
|
244
|
-
* Start the REPL (event-driven)
|
|
245
|
-
*/
|
|
246
|
-
async run() {
|
|
247
|
-
this.isRunning = true;
|
|
248
|
-
// Set terminal title, clear screen, and show welcome
|
|
249
|
-
terminal.setTitle('compilr');
|
|
250
|
-
terminal.clearScreen();
|
|
251
|
-
conversation.printWelcome(this.model, this.version, getActiveProject()?.displayName ?? null);
|
|
252
|
-
// Start footer (begins render loop and input capture)
|
|
253
|
-
this.footer.start();
|
|
254
|
-
// Start renderer (in legacy mode, this is mostly a no-op)
|
|
255
|
-
this.renderer.start();
|
|
256
|
-
// Set project name in footer
|
|
257
|
-
const activeProject = getActiveProject();
|
|
258
|
-
if (activeProject) {
|
|
259
|
-
this.footer.setProjectName(activeProject.displayName);
|
|
260
|
-
}
|
|
261
|
-
// Execute initial command if provided (e.g., /design from project menu)
|
|
262
|
-
if (this.initialCommand) {
|
|
263
|
-
const cmd = this.initialCommand;
|
|
264
|
-
// Give footer a moment to render before running command
|
|
265
|
-
setTimeout(() => {
|
|
266
|
-
void this.handleCommand(cmd, '');
|
|
267
|
-
}, 100);
|
|
268
|
-
}
|
|
269
|
-
// Wait for exit signal
|
|
270
|
-
await this.waitForExit();
|
|
271
|
-
// Cleanup
|
|
272
|
-
this.footer.stop();
|
|
273
|
-
this.renderer.stop();
|
|
274
|
-
// Only print goodbye when actually exiting (not when returning to menu)
|
|
275
|
-
if (!this.shouldReturnToMenu) {
|
|
276
|
-
terminal.writeLine('');
|
|
277
|
-
conversation.printInfo('Goodbye!');
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Wait for REPL exit
|
|
282
|
-
*/
|
|
283
|
-
waitForExit() {
|
|
284
|
-
return new Promise((resolve) => {
|
|
285
|
-
this.exitResolve = resolve;
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Get current model
|
|
290
|
-
*/
|
|
291
|
-
getCurrentModel() {
|
|
292
|
-
return this.currentModel;
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Get current provider
|
|
296
|
-
*/
|
|
297
|
-
getProvider() {
|
|
298
|
-
return this.provider;
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Set model for hot-switching (within same provider)
|
|
302
|
-
*/
|
|
303
|
-
setModel(model) {
|
|
304
|
-
this.currentModel = model;
|
|
305
|
-
conversation.printInfo(`Model switched to: ${model}`);
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Set the agent mode programmatically (e.g., from permission handler)
|
|
309
|
-
*/
|
|
310
|
-
setMode(mode) {
|
|
311
|
-
this.footer.setMode(mode);
|
|
312
|
-
// Notify external state handler
|
|
313
|
-
if (this.onModeChange) {
|
|
314
|
-
this.onModeChange(mode);
|
|
315
|
-
}
|
|
316
|
-
// Show feedback
|
|
317
|
-
const modeInfo = MODE_INFO[mode];
|
|
318
|
-
this.footer.clearForOutput();
|
|
319
|
-
conversation.printInfo(`Mode: ${modeInfo.label} - ${modeInfo.description}`);
|
|
320
|
-
this.footer.forceRender();
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Stop the REPL
|
|
324
|
-
*/
|
|
325
|
-
stop() {
|
|
326
|
-
this.isRunning = false;
|
|
327
|
-
this.footer.stop();
|
|
328
|
-
this.renderer.stop();
|
|
329
|
-
if (this.exitResolve) {
|
|
330
|
-
this.exitResolve();
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Check if the user requested to return to the startup menu
|
|
335
|
-
*/
|
|
336
|
-
wantsReturnToMenu() {
|
|
337
|
-
return this.shouldReturnToMenu;
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Handle submitted input (processes message and queued inputs)
|
|
341
|
-
*/
|
|
342
|
-
async handleSubmit(input) {
|
|
343
|
-
// Clear any previous suggestion when new input is submitted
|
|
344
|
-
this.footer.setSuggestion(null);
|
|
345
|
-
// Handle memory prefix: "# note" creates a persistent anchor
|
|
346
|
-
if (isMemoryInput(input)) {
|
|
347
|
-
handleMemoryInput(input, { agent: this.agent, footer: this.footer });
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
await this.processMessage(input);
|
|
351
|
-
// Process queued inputs (FIFO)
|
|
352
|
-
while (this.footer.hasQueuedInput() && this.isRunning) {
|
|
353
|
-
const queued = this.footer.popQueuedInput();
|
|
354
|
-
if (queued) {
|
|
355
|
-
await this.processMessage(queued);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
// ===========================================================================
|
|
360
|
-
// Command Handling
|
|
361
|
-
// ===========================================================================
|
|
362
|
-
/**
|
|
363
|
-
* Create command context for handler execution.
|
|
364
|
-
*/
|
|
365
|
-
getCommandContext() {
|
|
366
|
-
return {
|
|
367
|
-
// Agent and model
|
|
368
|
-
agent: this.agent,
|
|
369
|
-
model: this.model,
|
|
370
|
-
currentModel: this.currentModel,
|
|
371
|
-
provider: this.provider,
|
|
372
|
-
version: this.version,
|
|
373
|
-
// UI components
|
|
374
|
-
footer: this.footer,
|
|
375
|
-
state: this.state,
|
|
376
|
-
// Session info
|
|
377
|
-
startTime: this.startTime,
|
|
378
|
-
sessionInputTokens: this.sessionInputTokens,
|
|
379
|
-
sessionOutputTokens: this.sessionOutputTokens,
|
|
380
|
-
sessionRequests: this.sessionRequests,
|
|
381
|
-
// Callbacks
|
|
382
|
-
onModeChange: this.onModeChange,
|
|
383
|
-
setShouldReturnToMenu: (value) => {
|
|
384
|
-
this.shouldReturnToMenu = value;
|
|
385
|
-
},
|
|
386
|
-
// REPL methods (bound to this instance)
|
|
387
|
-
processMessage: (message, options) => this.processMessage(message, options),
|
|
388
|
-
handleCommand: (cmd, cmdArgs) => this.handleCommand(cmd, cmdArgs),
|
|
389
|
-
setModel: (model) => {
|
|
390
|
-
this.setModel(model);
|
|
391
|
-
},
|
|
392
|
-
// UI helper methods
|
|
393
|
-
showTools: () => this.showTools(),
|
|
394
|
-
showTokens: () => {
|
|
395
|
-
this.showTokens();
|
|
396
|
-
},
|
|
397
|
-
showContext: () => {
|
|
398
|
-
this.showContext();
|
|
399
|
-
},
|
|
400
|
-
showStatus: () => {
|
|
401
|
-
this.showStatus();
|
|
402
|
-
},
|
|
403
|
-
showTodos: () => {
|
|
404
|
-
this.showTodos();
|
|
405
|
-
},
|
|
406
|
-
handleCompact: () => this.handleCompact(),
|
|
407
|
-
handleExport: (exportArgs) => this.handleExport(exportArgs),
|
|
408
|
-
reloadProjectAnchors: (oldId, newId) => {
|
|
409
|
-
this.reloadProjectAnchors(oldId, newId);
|
|
410
|
-
},
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
/**
|
|
414
|
-
* Handle slash command
|
|
415
|
-
* Returns false if REPL should exit
|
|
416
|
-
*/
|
|
417
|
-
async handleCommand(command, args) {
|
|
418
|
-
// Resolve aliases to canonical command name
|
|
419
|
-
const resolved = resolveCommand(command);
|
|
420
|
-
if (!resolved) {
|
|
421
|
-
// Check if it's a custom command
|
|
422
|
-
const customRegistry = getCustomCommandRegistry();
|
|
423
|
-
if (customRegistry.has(command)) {
|
|
424
|
-
// Expand custom command and send as message
|
|
425
|
-
const customArgs = args ? args.split(' ').filter(a => a.trim()) : [];
|
|
426
|
-
const expanded = customRegistry.expand(command, customArgs);
|
|
427
|
-
if (expanded) {
|
|
428
|
-
// Resume animation before processing (it was paused for overlay commands)
|
|
429
|
-
this.footer.resumeAnimation();
|
|
430
|
-
// Process as a regular message
|
|
431
|
-
await this.processMessage(expanded);
|
|
432
|
-
return true;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
conversation.printWarning(`Unknown command: /${command}`);
|
|
436
|
-
conversation.printInfo('Type /help to see available commands');
|
|
437
|
-
return true;
|
|
438
|
-
}
|
|
439
|
-
// Try command registry first (for extracted handlers)
|
|
440
|
-
const ctx = this.getCommandContext();
|
|
441
|
-
const registryResult = await commandRegistry.execute(resolved, args, ctx);
|
|
442
|
-
if (registryResult !== null) {
|
|
443
|
-
return registryResult;
|
|
444
|
-
}
|
|
445
|
-
// All commands are now handled by the registry
|
|
446
|
-
// This shouldn't happen if resolveCommand works correctly
|
|
447
|
-
conversation.printWarning(`Unknown command: /${command}`);
|
|
448
|
-
return true;
|
|
449
|
-
}
|
|
450
|
-
// ===========================================================================
|
|
451
|
-
// Message Processing
|
|
452
|
-
// ===========================================================================
|
|
453
|
-
/**
|
|
454
|
-
* Strip '@' prefix from @path mentions before sending to agent
|
|
455
|
-
* The '@' is UI syntax for path autocomplete, not part of the actual path
|
|
456
|
-
* Only strips @ when it's at start of a word (not in middle like email@domain.com)
|
|
457
|
-
*/
|
|
458
|
-
stripAtMentions(input) {
|
|
459
|
-
// Match @ at start of string or after whitespace, followed by non-whitespace
|
|
460
|
-
return input.replace(/(^|\s)@(\S+)/g, '$1$2');
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* Process a message to the agent
|
|
464
|
-
* @param input - The full message to send to the agent
|
|
465
|
-
* @param options - Optional settings
|
|
466
|
-
* @param options.displayMessage - What to show the user (defaults to input)
|
|
467
|
-
* @param options.skipPlanModeCheck - Skip plan mode handling (for /design, /refine)
|
|
468
|
-
*/
|
|
469
|
-
async processMessage(input, options) {
|
|
470
|
-
// Print user message to conversation (show displayMessage or original)
|
|
471
|
-
this.footer.clearForOutput();
|
|
472
|
-
conversation.printUserMessage(options?.displayMessage ?? input);
|
|
473
|
-
this.footer.forceRender();
|
|
474
|
-
// Strip @ prefix from path mentions before sending to agent
|
|
475
|
-
const cleanedInput = this.stripAtMentions(input);
|
|
476
|
-
// Check current mode (unless skipped for skill-based commands)
|
|
477
|
-
const mode = this.footer.getMode();
|
|
478
|
-
// Plan mode - placeholder for now (skip for /design, /refine which handle their own flow)
|
|
479
|
-
if (mode === 'plan' && !options?.skipPlanModeCheck) {
|
|
480
|
-
this.footer.clearForOutput();
|
|
481
|
-
conversation.printInfo('📋 Plan Mode (coming soon)');
|
|
482
|
-
conversation.printInfo('In plan mode, the agent will analyze your request and create');
|
|
483
|
-
conversation.printInfo('a detailed execution plan without performing any actions.');
|
|
484
|
-
conversation.printInfo('');
|
|
485
|
-
conversation.printInfo('For now, switch to Normal or Auto-accept mode with Shift+Tab.');
|
|
486
|
-
terminal.writeLine('');
|
|
487
|
-
this.footer.forceRender();
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
// Get all tool names and filter based on intent (use cleaned input)
|
|
491
|
-
const allToolNames = this.agent.getToolDefinitions().map((t) => t.name);
|
|
492
|
-
const selectedNames = selectToolNamesByIntent(cleanedInput, allToolNames);
|
|
493
|
-
// Show filtering analysis if enabled
|
|
494
|
-
if (this.showFiltering) {
|
|
495
|
-
const saved = allToolNames.length - selectedNames.length;
|
|
496
|
-
const pct = Math.round((saved / allToolNames.length) * 100);
|
|
497
|
-
this.footer.clearForOutput();
|
|
498
|
-
conversation.printInfo(`[Tool Filtering] ${String(selectedNames.length)}/${String(allToolNames.length)} tools, ~${String(pct)}% reduction`);
|
|
499
|
-
this.footer.forceRender();
|
|
500
|
-
}
|
|
501
|
-
// Start agent running state
|
|
502
|
-
this.agentRunning = true;
|
|
503
|
-
setAgentRunning(this.state, true);
|
|
504
|
-
this.footer.setAgentRunning(true);
|
|
505
|
-
// Clear subagent tracking to prevent stale data from previous runs
|
|
506
|
-
// (both in agent.ts and in footer's SubagentRenderer)
|
|
507
|
-
this.clearSubagentTracking?.();
|
|
508
|
-
this.footer.clearSubagents();
|
|
509
|
-
this.abortController = new AbortController();
|
|
510
|
-
let totalInputTokens = 0;
|
|
511
|
-
let totalOutputTokens = 0;
|
|
512
|
-
let llmCalls = 0;
|
|
513
|
-
let hasTextOutput = false;
|
|
514
|
-
let usedTools = false;
|
|
515
|
-
let lastToolInput = null;
|
|
516
|
-
// Event-based rendering: accumulate text, render complete blocks
|
|
517
|
-
let textAccumulator = '';
|
|
518
|
-
// Set up text buffer flusher so permission handler can flush before showing overlay
|
|
519
|
-
this.textBufferFlusher = () => {
|
|
520
|
-
if (textAccumulator.trim()) {
|
|
521
|
-
this.footer.clearForOutput();
|
|
522
|
-
conversation.printAssistantResponse(textAccumulator.trim());
|
|
523
|
-
terminal.writeLine('');
|
|
524
|
-
this.footer.forceRender();
|
|
525
|
-
textAccumulator = '';
|
|
526
|
-
}
|
|
527
|
-
};
|
|
528
|
-
debug('processMessage', 'Starting agent stream', {
|
|
529
|
-
inputLength: cleanedInput.length,
|
|
530
|
-
toolCount: selectedNames.length,
|
|
531
|
-
model: this.currentModel,
|
|
532
|
-
});
|
|
533
|
-
try {
|
|
534
|
-
for await (const event of this.agent.stream(cleanedInput, {
|
|
535
|
-
toolFilter: selectedNames,
|
|
536
|
-
signal: this.abortController.signal,
|
|
537
|
-
chatOptions: { model: this.currentModel },
|
|
538
|
-
})) {
|
|
539
|
-
debug('processMessage', `Event received: ${event.type}`, event);
|
|
540
|
-
// Check if aborted
|
|
541
|
-
if (this.abortController.signal.aborted) {
|
|
542
|
-
debug('processMessage', 'Aborted');
|
|
543
|
-
break;
|
|
544
|
-
}
|
|
545
|
-
if (event.type === 'llm_chunk') {
|
|
546
|
-
if (event.chunk.type === 'text' && event.chunk.text) {
|
|
547
|
-
// Event-based rendering: accumulate text until tool_start or stream end
|
|
548
|
-
// This allows complete code blocks to be rendered with syntax highlighting
|
|
549
|
-
textAccumulator += event.chunk.text;
|
|
550
|
-
hasTextOutput = true;
|
|
551
|
-
}
|
|
552
|
-
else if (event.chunk.type === 'done' && event.chunk.usage) {
|
|
553
|
-
const tokens = event.chunk.usage.inputTokens + event.chunk.usage.outputTokens;
|
|
554
|
-
this.footer.addTokens(tokens);
|
|
555
|
-
totalInputTokens += event.chunk.usage.inputTokens;
|
|
556
|
-
totalOutputTokens += event.chunk.usage.outputTokens;
|
|
557
|
-
llmCalls++;
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
else if (event.type === 'tool_start') {
|
|
561
|
-
// Event-based rendering: flush accumulated text before tool output
|
|
562
|
-
// Exception: For ask_user/ask_user_simple tools, we'll buffer the text and print after overlay closes
|
|
563
|
-
// to avoid the text interfering with the overlay rendering
|
|
564
|
-
// Also skip if an overlay is currently active (e.g., permission overlay)
|
|
565
|
-
const isAskUserTool = event.name === 'ask_user' || event.name === 'ask_user_simple';
|
|
566
|
-
const shouldBuffer = isAskUserTool || isOverlayActive();
|
|
567
|
-
if (textAccumulator.trim() && !shouldBuffer) {
|
|
568
|
-
this.footer.clearForOutput();
|
|
569
|
-
conversation.printAssistantResponse(textAccumulator.trim());
|
|
570
|
-
terminal.writeLine('');
|
|
571
|
-
this.footer.forceRender();
|
|
572
|
-
textAccumulator = '';
|
|
573
|
-
}
|
|
574
|
-
usedTools = true;
|
|
575
|
-
lastToolInput = event.input;
|
|
576
|
-
// Show tool in spinner (but not silent tools)
|
|
577
|
-
if (event.name !== 'todo_read' && event.name !== 'todo_write' && event.name !== 'suggest') {
|
|
578
|
-
// For task tool, show subagent type
|
|
579
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
580
|
-
if (event.name === 'task' && event.input) {
|
|
581
|
-
const inputObj = event.input;
|
|
582
|
-
const subagentType = typeof inputObj.subagent_type === 'string' ? inputObj.subagent_type : 'general';
|
|
583
|
-
const description = typeof inputObj.description === 'string' ? inputObj.description : '';
|
|
584
|
-
this.footer.setCurrentTool(`task(${subagentType}): ${description}`);
|
|
585
|
-
}
|
|
586
|
-
else {
|
|
587
|
-
this.footer.setCurrentTool(event.name);
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
// Note: Diff is shown in the permission handler (index.ts) BEFORE the prompt
|
|
591
|
-
}
|
|
592
|
-
else if (event.type === 'tool_end') {
|
|
593
|
-
const toolName = event.name;
|
|
594
|
-
const toolInput = lastToolInput;
|
|
595
|
-
const result = event.result;
|
|
596
|
-
lastToolInput = null;
|
|
597
|
-
// Handle todo_write - update state and render
|
|
598
|
-
if (toolName === 'todo_write' && toolInput && Array.isArray(toolInput.todos)) {
|
|
599
|
-
const todos = toolInput.todos.map((t) => {
|
|
600
|
-
const content = typeof t.content === 'string' ? t.content :
|
|
601
|
-
typeof t.title === 'string' ? t.title :
|
|
602
|
-
typeof t.task === 'string' ? t.task :
|
|
603
|
-
typeof t.description === 'string' ? t.description :
|
|
604
|
-
typeof t.text === 'string' ? t.text : 'Untitled task';
|
|
605
|
-
const status = (typeof t.status === 'string' && ['pending', 'in_progress', 'completed'].includes(t.status)
|
|
606
|
-
? t.status
|
|
607
|
-
: 'pending');
|
|
608
|
-
const activeForm = typeof t.activeForm === 'string' ? t.activeForm : undefined;
|
|
609
|
-
return { content, status, activeForm };
|
|
610
|
-
});
|
|
611
|
-
updateTodos(this.state, todos);
|
|
612
|
-
this.footer.setTodos(todos);
|
|
613
|
-
this.footer.setCurrentTool(null);
|
|
614
|
-
continue;
|
|
615
|
-
}
|
|
616
|
-
// Skip todo_read display
|
|
617
|
-
if (toolName === 'todo_read') {
|
|
618
|
-
this.footer.setCurrentTool(null);
|
|
619
|
-
continue;
|
|
620
|
-
}
|
|
621
|
-
// Skip suggest tool display (suggestion is shown in input prompt)
|
|
622
|
-
if (toolName === 'suggest') {
|
|
623
|
-
this.footer.setCurrentTool(null);
|
|
624
|
-
this.footer.forceRender();
|
|
625
|
-
continue;
|
|
626
|
-
}
|
|
627
|
-
// Handle ask_user/ask_user_simple tools - print buffered text now that overlay is done
|
|
628
|
-
if (toolName === 'ask_user' || toolName === 'ask_user_simple') {
|
|
629
|
-
// Print any accumulated text that was buffered before the overlay
|
|
630
|
-
if (textAccumulator.trim()) {
|
|
631
|
-
this.footer.clearForOutput();
|
|
632
|
-
conversation.printAssistantResponse(textAccumulator.trim());
|
|
633
|
-
terminal.writeLine('');
|
|
634
|
-
textAccumulator = '';
|
|
635
|
-
}
|
|
636
|
-
this.footer.setCurrentTool(null);
|
|
637
|
-
this.footer.forceRender();
|
|
638
|
-
continue;
|
|
639
|
-
}
|
|
640
|
-
// Handle edit tool - diff was already shown on tool_start (no output needed)
|
|
641
|
-
if (toolName === 'edit') {
|
|
642
|
-
// Just clear the tool indicator, diff was shown before permission prompt
|
|
643
|
-
this.footer.setCurrentTool(null);
|
|
644
|
-
this.footer.forceRender();
|
|
645
|
-
continue;
|
|
646
|
-
}
|
|
647
|
-
// Handle task tool - print sub-agent completion summary to scrolling zone
|
|
648
|
-
// Format: ● Explore(description) \n ⎿ Done (stats)
|
|
649
|
-
if (toolName === 'task') {
|
|
650
|
-
this.footer.setCurrentTool(null);
|
|
651
|
-
// Get stats BEFORE clearing (so we have the data to print)
|
|
652
|
-
const stats = this.footer.getLastSubagentStats();
|
|
653
|
-
// Clear footer BEFORE clearing subagent data (so lastRenderHeight is still accurate)
|
|
654
|
-
this.footer.clearForOutput();
|
|
655
|
-
// Print the completion summary to scrolling zone
|
|
656
|
-
if (stats) {
|
|
657
|
-
conversation.printSubagentResponse(stats);
|
|
658
|
-
}
|
|
659
|
-
// Now clear the subagent data
|
|
660
|
-
this.footer.clearSubagents();
|
|
661
|
-
this.footer.forceRender();
|
|
662
|
-
continue;
|
|
663
|
-
}
|
|
664
|
-
// Clear footer for output (for tools that actually print output)
|
|
665
|
-
this.footer.clearForOutput();
|
|
666
|
-
// Build argument summary for other tools
|
|
667
|
-
let argSummary = '';
|
|
668
|
-
if (toolInput) {
|
|
669
|
-
const path = toolInput.path ?? toolInput.file_path ?? toolInput.filePath;
|
|
670
|
-
const command = toolInput.command;
|
|
671
|
-
const pattern = toolInput.pattern;
|
|
672
|
-
if (typeof path === 'string') {
|
|
673
|
-
argSummary = path.split('/').pop() ?? path;
|
|
674
|
-
}
|
|
675
|
-
else if (typeof command === 'string') {
|
|
676
|
-
argSummary = command.length > 40 ? command.slice(0, 40) + '...' : command;
|
|
677
|
-
}
|
|
678
|
-
else if (typeof pattern === 'string') {
|
|
679
|
-
argSummary = pattern;
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
// Format result summary
|
|
683
|
-
let resultSummary = '';
|
|
684
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
685
|
-
if (result && typeof result === 'object') {
|
|
686
|
-
const resultObj = result;
|
|
687
|
-
if (resultObj.error) {
|
|
688
|
-
const errorObj = resultObj.error;
|
|
689
|
-
const errorMsg = typeof errorObj.message === 'string' ? errorObj.message : JSON.stringify(resultObj.error);
|
|
690
|
-
resultSummary = pc.red(`Error: ${errorMsg.slice(0, 60)}`);
|
|
691
|
-
}
|
|
692
|
-
else if (resultObj.result !== undefined) {
|
|
693
|
-
resultSummary = conversation.formatToolResult(resultObj.result);
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
// Print tool log
|
|
697
|
-
conversation.printToolExecution(toolName, argSummary, resultSummary);
|
|
698
|
-
// Re-render footer after output
|
|
699
|
-
this.footer.setCurrentTool(null);
|
|
700
|
-
this.footer.forceRender();
|
|
701
|
-
}
|
|
702
|
-
else if (event.type === 'guardrail_warning') {
|
|
703
|
-
// Show guardrail warning to user (non-blocking)
|
|
704
|
-
const result = event.result;
|
|
705
|
-
const name = result.guardrail?.name ?? 'Unknown';
|
|
706
|
-
const message = event.message || result.guardrail?.message || 'Risky operation detected';
|
|
707
|
-
const category = result.guardrail?.tags?.[0] ?? 'general';
|
|
708
|
-
this.footer.clearForOutput();
|
|
709
|
-
conversation.printWarning(`[${category}] ${name}: ${message}`);
|
|
710
|
-
this.footer.forceRender();
|
|
711
|
-
}
|
|
712
|
-
else if (event.type === 'guardrail_blocked') {
|
|
713
|
-
// Show guardrail block message (operation was prevented)
|
|
714
|
-
const message = event.message || 'Operation blocked by guardrail';
|
|
715
|
-
this.footer.clearForOutput();
|
|
716
|
-
conversation.printError(`Blocked: ${message}`);
|
|
717
|
-
this.footer.forceRender();
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
debug('processMessage', 'Stream completed', {
|
|
721
|
-
hasTextOutput,
|
|
722
|
-
usedTools,
|
|
723
|
-
totalInputTokens,
|
|
724
|
-
totalOutputTokens,
|
|
725
|
-
llmCalls,
|
|
726
|
-
textAccumulatorLength: textAccumulator.length,
|
|
727
|
-
});
|
|
728
|
-
// Skip stats if aborted
|
|
729
|
-
if (this.abortController.signal.aborted) {
|
|
730
|
-
this.agentRunning = false;
|
|
731
|
-
setAgentRunning(this.state, false);
|
|
732
|
-
this.footer.setAgentRunning(false);
|
|
733
|
-
this.abortController = null;
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
// Event-based rendering: flush any remaining accumulated text
|
|
737
|
-
if (textAccumulator.trim()) {
|
|
738
|
-
this.footer.clearForOutput();
|
|
739
|
-
conversation.printAssistantResponse(textAccumulator.trim());
|
|
740
|
-
terminal.writeLine('');
|
|
741
|
-
textAccumulator = '';
|
|
742
|
-
}
|
|
743
|
-
// Warn if tools used but no text
|
|
744
|
-
if (usedTools && !hasTextOutput) {
|
|
745
|
-
this.footer.clearForOutput();
|
|
746
|
-
conversation.printWarning('No text response from model - try a more capable model');
|
|
747
|
-
}
|
|
748
|
-
// Update session stats
|
|
749
|
-
this.sessionInputTokens += totalInputTokens;
|
|
750
|
-
this.sessionOutputTokens += totalOutputTokens;
|
|
751
|
-
this.sessionRequests++;
|
|
752
|
-
// Clear subagents BEFORE printing stats so footer won't show them afterward
|
|
753
|
-
this.footer.clearSubagents();
|
|
754
|
-
// Show token usage
|
|
755
|
-
if (totalInputTokens > 0 || totalOutputTokens > 0) {
|
|
756
|
-
this.footer.clearForOutput();
|
|
757
|
-
const total = totalInputTokens + totalOutputTokens;
|
|
758
|
-
const sessionTotal = this.sessionInputTokens + this.sessionOutputTokens;
|
|
759
|
-
conversation.printInfo(`[Tokens: ${total.toLocaleString()} (${totalInputTokens.toLocaleString()} in / ${totalOutputTokens.toLocaleString()} out) - ${String(llmCalls)} LLM call(s)]`);
|
|
760
|
-
conversation.printInfo(`[Session: ${sessionTotal.toLocaleString()} total (${String(this.sessionRequests)} requests)]`);
|
|
761
|
-
terminal.writeLine('');
|
|
762
|
-
this.footer.forceRender();
|
|
763
|
-
}
|
|
764
|
-
// Stop spinner and re-render footer (AFTER all output is printed)
|
|
765
|
-
this.agentRunning = false;
|
|
766
|
-
setAgentRunning(this.state, false);
|
|
767
|
-
this.footer.setAgentRunning(false);
|
|
768
|
-
}
|
|
769
|
-
catch (error) {
|
|
770
|
-
debugError('processMessage', error);
|
|
771
|
-
if (error.name !== 'AbortError') {
|
|
772
|
-
this.footer.clearForOutput();
|
|
773
|
-
conversation.printError(error.message);
|
|
774
|
-
this.footer.forceRender();
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
finally {
|
|
778
|
-
// Ensure agent is stopped even on error
|
|
779
|
-
this.agentRunning = false;
|
|
780
|
-
setAgentRunning(this.state, false);
|
|
781
|
-
this.footer.setAgentRunning(false);
|
|
782
|
-
this.abortController = null;
|
|
783
|
-
// Clear text buffer flusher
|
|
784
|
-
this.textBufferFlusher = null;
|
|
785
|
-
// Ensure footer is rendered and isPaused is reset
|
|
786
|
-
// (clearForOutput sets isPaused=true, forceRender resets it)
|
|
787
|
-
this.footer.forceRender();
|
|
788
|
-
// Notify that agent has finished (for applying deferred suggestions)
|
|
789
|
-
this.onAgentFinish?.();
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
// ===========================================================================
|
|
793
|
-
// Helper Commands
|
|
794
|
-
// ===========================================================================
|
|
795
|
-
async handleCompact() {
|
|
796
|
-
const contextManager = this.agent.getContextManager();
|
|
797
|
-
if (!contextManager) {
|
|
798
|
-
this.footer.clearForOutput();
|
|
799
|
-
conversation.printWarning('Context manager not available');
|
|
800
|
-
this.footer.forceRender();
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
const history = this.agent.getHistory();
|
|
804
|
-
if (history.length === 0) {
|
|
805
|
-
this.footer.clearForOutput();
|
|
806
|
-
conversation.printInfo('No conversation history to compact');
|
|
807
|
-
this.footer.forceRender();
|
|
808
|
-
return;
|
|
809
|
-
}
|
|
810
|
-
const stats = contextManager.getStats(history.length);
|
|
811
|
-
this.footer.clearForOutput();
|
|
812
|
-
conversation.printInfo(`Current: ${stats.currentTokens.toLocaleString()} tokens, ${String(history.length)} messages`);
|
|
813
|
-
const confirmed = await overlays.showConfirmation('Compact conversation history?');
|
|
814
|
-
if (!confirmed) {
|
|
815
|
-
this.footer.forceRender();
|
|
816
|
-
return;
|
|
817
|
-
}
|
|
818
|
-
// Show spinner during compaction
|
|
819
|
-
this.footer.setSpinnerText('Compacting context');
|
|
820
|
-
setAgentRunning(this.state, true);
|
|
821
|
-
this.footer.setAgentRunning(true);
|
|
822
|
-
this.footer.forceRender(); // Render immediately before blocking operation
|
|
823
|
-
try {
|
|
824
|
-
// Use the agent's compact() method - handles summarization, tool pairing, and hints
|
|
825
|
-
const result = (await this.agent.compact());
|
|
826
|
-
// Stop spinner and clear for output
|
|
827
|
-
setAgentRunning(this.state, false);
|
|
828
|
-
this.footer.setAgentRunning(false);
|
|
829
|
-
this.footer.setSpinnerText(null);
|
|
830
|
-
this.footer.clearForOutput();
|
|
831
|
-
if (!result.success) {
|
|
832
|
-
conversation.printWarning('Compaction not available (no context manager)');
|
|
833
|
-
this.footer.forceRender();
|
|
834
|
-
return;
|
|
835
|
-
}
|
|
836
|
-
// Build status message
|
|
837
|
-
const newHistory = this.agent.getHistory();
|
|
838
|
-
const statusParts = [
|
|
839
|
-
`Compacted: ${String(result.originalTokens ?? 0).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} → ${String(result.summaryTokens ?? 0).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} tokens`,
|
|
840
|
-
`(${String(history.length)} → ${String(newHistory.length)} messages, ${String(result.messagesPreserved ?? 0)} preserved)`,
|
|
841
|
-
];
|
|
842
|
-
// Add smart compaction category info
|
|
843
|
-
if (result.categoryStats) {
|
|
844
|
-
const actions = [];
|
|
845
|
-
if (result.categoryStats.toolResults.action === 'compacted') {
|
|
846
|
-
actions.push('tool results → files');
|
|
847
|
-
}
|
|
848
|
-
if (result.categoryStats.history.action === 'summarized') {
|
|
849
|
-
actions.push('history → summary');
|
|
850
|
-
}
|
|
851
|
-
if (actions.length > 0) {
|
|
852
|
-
statusParts.push(`[${actions.join(', ')}]`);
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
// Add files created info
|
|
856
|
-
if (result.filesCreated && result.filesCreated.length > 0) {
|
|
857
|
-
statusParts.push(`[${String(result.filesCreated.length)} file(s) created]`);
|
|
858
|
-
}
|
|
859
|
-
// Add file tracking info
|
|
860
|
-
if (result.restorationHintsInjected) {
|
|
861
|
-
const fileTracker = this.agent.getFileTracker();
|
|
862
|
-
const trackerStats = fileTracker?.getStats();
|
|
863
|
-
const filesTracked = trackerStats ? trackerStats.total : 0;
|
|
864
|
-
statusParts.push(`[${String(filesTracked)} files tracked]`);
|
|
865
|
-
}
|
|
866
|
-
// Add repair info if tool_results were fixed
|
|
867
|
-
if (result.toolResultsRepaired && result.toolResultsRepaired > 0) {
|
|
868
|
-
statusParts.push(`[${String(result.toolResultsRepaired)} orphaned tool results removed]`);
|
|
869
|
-
}
|
|
870
|
-
conversation.printSuccess(statusParts.join(' '));
|
|
871
|
-
}
|
|
872
|
-
catch (error) {
|
|
873
|
-
// Stop spinner on error too
|
|
874
|
-
setAgentRunning(this.state, false);
|
|
875
|
-
this.footer.setAgentRunning(false);
|
|
876
|
-
this.footer.setSpinnerText(null);
|
|
877
|
-
this.footer.clearForOutput();
|
|
878
|
-
conversation.printError(`Compaction failed: ${error.message}`);
|
|
879
|
-
}
|
|
880
|
-
this.footer.forceRender();
|
|
881
|
-
}
|
|
882
|
-
async showTools() {
|
|
883
|
-
const tools = this.agent.getToolDefinitions().map((t) => {
|
|
884
|
-
// Extract parameters from inputSchema
|
|
885
|
-
const parameters = [];
|
|
886
|
-
const props = t.inputSchema.properties;
|
|
887
|
-
const required = t.inputSchema.required ?? [];
|
|
888
|
-
for (const [name, schema] of Object.entries(props)) {
|
|
889
|
-
parameters.push({
|
|
890
|
-
name,
|
|
891
|
-
type: schema.type ?? 'unknown',
|
|
892
|
-
description: schema.description,
|
|
893
|
-
required: required.includes(name),
|
|
894
|
-
});
|
|
895
|
-
}
|
|
896
|
-
// Look up permission info
|
|
897
|
-
const permissionInfo = getToolPermissionInfo(t.name);
|
|
898
|
-
const permission = permissionInfo
|
|
899
|
-
? { level: permissionInfo.level, description: permissionInfo.description }
|
|
900
|
-
: undefined;
|
|
901
|
-
// For task tool, extract just the intro (before verbose agent types list)
|
|
902
|
-
let description = t.description;
|
|
903
|
-
if (t.name === 'task' && description.includes('Available agent types:')) {
|
|
904
|
-
description = description.split('Available agent types:')[0].trim();
|
|
905
|
-
}
|
|
906
|
-
return {
|
|
907
|
-
name: t.name,
|
|
908
|
-
description,
|
|
909
|
-
parameters,
|
|
910
|
-
permission,
|
|
911
|
-
};
|
|
912
|
-
});
|
|
913
|
-
// Overlay lifecycle handles footer pause/resume
|
|
914
|
-
await showToolsOverlay(tools);
|
|
915
|
-
}
|
|
916
|
-
showTokens() {
|
|
917
|
-
this.footer.clearForOutput();
|
|
918
|
-
overlays.showTokenUsage({
|
|
919
|
-
inputTokens: this.sessionInputTokens,
|
|
920
|
-
outputTokens: this.sessionOutputTokens,
|
|
921
|
-
totalTokens: this.sessionInputTokens + this.sessionOutputTokens,
|
|
922
|
-
});
|
|
923
|
-
this.footer.forceRender();
|
|
924
|
-
}
|
|
925
|
-
showContext() {
|
|
926
|
-
const contextManager = this.agent.getContextManager();
|
|
927
|
-
const history = this.agent.getHistory();
|
|
928
|
-
this.footer.clearForOutput();
|
|
929
|
-
if (contextManager) {
|
|
930
|
-
const stats = contextManager.getStats(history.length);
|
|
931
|
-
overlays.showContextStats({
|
|
932
|
-
tokens: stats.currentTokens,
|
|
933
|
-
maxTokens: stats.maxTokens,
|
|
934
|
-
messages: stats.messageCount,
|
|
935
|
-
turns: stats.turnCount,
|
|
936
|
-
utilization: stats.utilization,
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
else {
|
|
940
|
-
// Fallback to session tracking
|
|
941
|
-
overlays.showContextStats({
|
|
942
|
-
tokens: this.sessionInputTokens + this.sessionOutputTokens,
|
|
943
|
-
maxTokens: 200000,
|
|
944
|
-
messages: history.length,
|
|
945
|
-
turns: Math.floor(history.filter((m) => m.role === 'user').length),
|
|
946
|
-
utilization: (this.sessionInputTokens + this.sessionOutputTokens) / 200000,
|
|
947
|
-
});
|
|
948
|
-
}
|
|
949
|
-
this.footer.forceRender();
|
|
950
|
-
}
|
|
951
|
-
showStatus() {
|
|
952
|
-
const contextManager = this.agent.getContextManager();
|
|
953
|
-
const history = this.agent.getHistory();
|
|
954
|
-
const mode = this.footer.getMode();
|
|
955
|
-
const modeInfo = MODE_INFO[mode];
|
|
956
|
-
this.footer.clearForOutput();
|
|
957
|
-
terminal.writeLine('');
|
|
958
|
-
terminal.writeLine(pc.bold('Status'));
|
|
959
|
-
terminal.writeLine(pc.dim('─'.repeat(40)));
|
|
960
|
-
terminal.writeLine(` Version: ${pc.cyan(this.version)}`);
|
|
961
|
-
terminal.writeLine(` Model: ${pc.cyan(this.model)}`);
|
|
962
|
-
terminal.writeLine(` Mode: ${pc.cyan(modeInfo.label)}`);
|
|
963
|
-
if (contextManager) {
|
|
964
|
-
const stats = contextManager.getStats(history.length);
|
|
965
|
-
const pct = (stats.utilization * 100).toFixed(1);
|
|
966
|
-
const bar = this.renderProgressBar(stats.utilization, 20);
|
|
967
|
-
terminal.writeLine(` Context: ${bar} ${pct}%`);
|
|
968
|
-
terminal.writeLine(` Messages: ${pc.cyan(String(stats.messageCount))}`);
|
|
969
|
-
}
|
|
970
|
-
else {
|
|
971
|
-
const total = this.sessionInputTokens + this.sessionOutputTokens;
|
|
972
|
-
terminal.writeLine(` Tokens: ${pc.cyan(total.toLocaleString())}`);
|
|
973
|
-
terminal.writeLine(` Messages: ${pc.cyan(String(history.length))}`);
|
|
974
|
-
}
|
|
975
|
-
terminal.writeLine(` Requests: ${pc.cyan(String(this.sessionRequests))}`);
|
|
976
|
-
terminal.writeLine('');
|
|
977
|
-
this.footer.forceRender();
|
|
978
|
-
}
|
|
979
|
-
renderProgressBar(ratio, width) {
|
|
980
|
-
const filled = Math.round(ratio * width);
|
|
981
|
-
const empty = width - filled;
|
|
982
|
-
const color = ratio > 0.9 ? pc.red : ratio > 0.7 ? pc.yellow : pc.green;
|
|
983
|
-
return color('█'.repeat(filled)) + pc.dim('░'.repeat(empty));
|
|
984
|
-
}
|
|
985
|
-
showTodos() {
|
|
986
|
-
const todos = this.state.todos;
|
|
987
|
-
this.footer.clearForOutput();
|
|
988
|
-
terminal.writeLine('');
|
|
989
|
-
if (todos.length === 0) {
|
|
990
|
-
terminal.writeLine(pc.dim('No todos. The agent will create todos when working on tasks.'));
|
|
991
|
-
terminal.writeLine('');
|
|
992
|
-
this.footer.forceRender();
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
|
-
terminal.writeLine(pc.bold('Todos'));
|
|
996
|
-
terminal.writeLine(pc.dim('─'.repeat(40)));
|
|
997
|
-
for (const todo of todos) {
|
|
998
|
-
let icon;
|
|
999
|
-
let style;
|
|
1000
|
-
switch (todo.status) {
|
|
1001
|
-
case 'completed':
|
|
1002
|
-
icon = pc.green('✓');
|
|
1003
|
-
style = pc.strikethrough;
|
|
1004
|
-
break;
|
|
1005
|
-
case 'in_progress':
|
|
1006
|
-
icon = pc.yellow('●');
|
|
1007
|
-
style = pc.bold;
|
|
1008
|
-
break;
|
|
1009
|
-
default:
|
|
1010
|
-
icon = pc.dim('○');
|
|
1011
|
-
style = (s) => s;
|
|
1012
|
-
}
|
|
1013
|
-
terminal.writeLine(` ${icon} ${style(todo.content)}`);
|
|
1014
|
-
}
|
|
1015
|
-
terminal.writeLine('');
|
|
1016
|
-
this.footer.forceRender();
|
|
1017
|
-
}
|
|
1018
|
-
async handleExport(args) {
|
|
1019
|
-
const history = this.agent.getHistory();
|
|
1020
|
-
if (history.length === 0) {
|
|
1021
|
-
this.footer.clearForOutput();
|
|
1022
|
-
conversation.printWarning('No conversation to export');
|
|
1023
|
-
this.footer.forceRender();
|
|
1024
|
-
return;
|
|
1025
|
-
}
|
|
1026
|
-
// Format conversation as markdown
|
|
1027
|
-
const markdown = this.formatConversationAsMarkdown(history);
|
|
1028
|
-
if (args.trim()) {
|
|
1029
|
-
// Export to file
|
|
1030
|
-
const filename = args.trim();
|
|
1031
|
-
const filepath = path.isAbsolute(filename) ? filename : path.join(process.cwd(), filename);
|
|
1032
|
-
try {
|
|
1033
|
-
fs.writeFileSync(filepath, markdown, 'utf-8');
|
|
1034
|
-
this.footer.clearForOutput();
|
|
1035
|
-
conversation.printSuccess(`Exported to ${filepath}`);
|
|
1036
|
-
this.footer.forceRender();
|
|
1037
|
-
}
|
|
1038
|
-
catch (error) {
|
|
1039
|
-
this.footer.clearForOutput();
|
|
1040
|
-
conversation.printError(`Failed to export: ${error.message}`);
|
|
1041
|
-
this.footer.forceRender();
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
else {
|
|
1045
|
-
// Export to clipboard
|
|
1046
|
-
try {
|
|
1047
|
-
await this.copyToClipboard(markdown);
|
|
1048
|
-
this.footer.clearForOutput();
|
|
1049
|
-
conversation.printSuccess(`Copied ${String(history.length)} messages to clipboard`);
|
|
1050
|
-
this.footer.forceRender();
|
|
1051
|
-
}
|
|
1052
|
-
catch (error) {
|
|
1053
|
-
this.footer.clearForOutput();
|
|
1054
|
-
conversation.printError(`Failed to copy to clipboard: ${error.message}`);
|
|
1055
|
-
this.footer.forceRender();
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
formatConversationAsMarkdown(history) {
|
|
1060
|
-
const lines = [];
|
|
1061
|
-
const timestamp = new Date().toISOString().split('T')[0];
|
|
1062
|
-
lines.push(`# Conversation Export`);
|
|
1063
|
-
lines.push('');
|
|
1064
|
-
lines.push(`**Model:** ${this.model}`);
|
|
1065
|
-
lines.push(`**Date:** ${timestamp}`);
|
|
1066
|
-
lines.push(`**Messages:** ${String(history.length)}`);
|
|
1067
|
-
lines.push('');
|
|
1068
|
-
lines.push('---');
|
|
1069
|
-
lines.push('');
|
|
1070
|
-
for (const msg of history) {
|
|
1071
|
-
const role = msg.role === 'user' ? '👤 User' : '🤖 Assistant';
|
|
1072
|
-
lines.push(`## ${role}`);
|
|
1073
|
-
lines.push('');
|
|
1074
|
-
if (typeof msg.content === 'string') {
|
|
1075
|
-
lines.push(msg.content);
|
|
1076
|
-
}
|
|
1077
|
-
else if (Array.isArray(msg.content)) {
|
|
1078
|
-
// Handle content blocks (tool calls, etc.)
|
|
1079
|
-
for (const block of msg.content) {
|
|
1080
|
-
if (typeof block === 'object' && block !== null) {
|
|
1081
|
-
const b = block;
|
|
1082
|
-
if (b.type === 'text' && typeof b.text === 'string') {
|
|
1083
|
-
lines.push(b.text);
|
|
1084
|
-
}
|
|
1085
|
-
else if (b.type === 'tool_use') {
|
|
1086
|
-
const toolName = typeof b.name === 'string' ? b.name : String(b.name);
|
|
1087
|
-
lines.push(`**Tool:** \`${toolName}\``);
|
|
1088
|
-
lines.push('```json');
|
|
1089
|
-
lines.push(JSON.stringify(b.input, null, 2));
|
|
1090
|
-
lines.push('```');
|
|
1091
|
-
}
|
|
1092
|
-
else if (b.type === 'tool_result') {
|
|
1093
|
-
lines.push(`**Tool Result:**`);
|
|
1094
|
-
const content = typeof b.content === 'string' ? b.content : JSON.stringify(b.content);
|
|
1095
|
-
if (content.length > 500) {
|
|
1096
|
-
lines.push('```');
|
|
1097
|
-
lines.push(content.slice(0, 500) + '...[truncated]');
|
|
1098
|
-
lines.push('```');
|
|
1099
|
-
}
|
|
1100
|
-
else {
|
|
1101
|
-
lines.push('```');
|
|
1102
|
-
lines.push(content);
|
|
1103
|
-
lines.push('```');
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
else {
|
|
1110
|
-
lines.push(JSON.stringify(msg.content, null, 2));
|
|
1111
|
-
}
|
|
1112
|
-
lines.push('');
|
|
1113
|
-
lines.push('---');
|
|
1114
|
-
lines.push('');
|
|
1115
|
-
}
|
|
1116
|
-
return lines.join('\n');
|
|
1117
|
-
}
|
|
1118
|
-
async copyToClipboard(text) {
|
|
1119
|
-
const platform = process.platform;
|
|
1120
|
-
let command;
|
|
1121
|
-
if (platform === 'darwin') {
|
|
1122
|
-
command = 'pbcopy';
|
|
1123
|
-
}
|
|
1124
|
-
else if (platform === 'linux') {
|
|
1125
|
-
// Try xclip first, fall back to xsel
|
|
1126
|
-
command = 'xclip -selection clipboard';
|
|
1127
|
-
}
|
|
1128
|
-
else if (platform === 'win32') {
|
|
1129
|
-
command = 'clip';
|
|
1130
|
-
}
|
|
1131
|
-
else {
|
|
1132
|
-
throw new Error(`Unsupported platform: ${platform}`);
|
|
1133
|
-
}
|
|
1134
|
-
const child = exec(command);
|
|
1135
|
-
if (child.stdin) {
|
|
1136
|
-
child.stdin.write(text);
|
|
1137
|
-
child.stdin.end();
|
|
1138
|
-
}
|
|
1139
|
-
await new Promise((resolve, reject) => {
|
|
1140
|
-
child.on('exit', (code) => {
|
|
1141
|
-
if (code === 0) {
|
|
1142
|
-
resolve();
|
|
1143
|
-
}
|
|
1144
|
-
else {
|
|
1145
|
-
reject(new Error(`Clipboard command exited with code ${String(code ?? 'unknown')}`));
|
|
1146
|
-
}
|
|
1147
|
-
});
|
|
1148
|
-
child.on('error', reject);
|
|
1149
|
-
});
|
|
1150
|
-
}
|
|
1151
|
-
}
|