lonny-agent 0.2.6 → 0.2.7
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/.github/workflows/ci.yml +21 -0
- package/AGENTS.md +106 -0
- package/CHANGELOG.md +24 -0
- package/dist/agent/__tests__/session-restore.test.d.ts +2 -0
- package/dist/agent/__tests__/session-restore.test.d.ts.map +1 -0
- package/dist/agent/__tests__/session-restore.test.js +260 -0
- package/dist/agent/__tests__/session-restore.test.js.map +1 -0
- package/dist/agent/commands.d.ts +26 -0
- package/dist/agent/commands.d.ts.map +1 -0
- package/dist/agent/commands.js +253 -0
- package/dist/agent/commands.js.map +1 -0
- package/dist/agent/compaction.js +8 -1
- package/dist/agent/compaction.js.map +1 -1
- package/dist/agent/index.d.ts +2 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +2 -2
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/memory.d.ts +12 -0
- package/dist/agent/memory.d.ts.map +1 -0
- package/dist/agent/memory.js +51 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/prompt-builder.d.ts +6 -1
- package/dist/agent/prompt-builder.d.ts.map +1 -1
- package/dist/agent/prompt-builder.js +89 -26
- package/dist/agent/prompt-builder.js.map +1 -1
- package/dist/agent/providers/openai.d.ts +1 -0
- package/dist/agent/providers/openai.d.ts.map +1 -1
- package/dist/agent/providers/openai.js +16 -3
- package/dist/agent/providers/openai.js.map +1 -1
- package/dist/agent/session-chat.d.ts +3 -0
- package/dist/agent/session-chat.d.ts.map +1 -0
- package/dist/agent/session-chat.js +384 -0
- package/dist/agent/session-chat.js.map +1 -0
- package/dist/agent/session-display.d.ts +29 -0
- package/dist/agent/session-display.d.ts.map +1 -0
- package/dist/agent/session-display.js +179 -0
- package/dist/agent/session-display.js.map +1 -0
- package/dist/agent/session-persistence.d.ts +55 -0
- package/dist/agent/session-persistence.d.ts.map +1 -0
- package/dist/agent/session-persistence.js +101 -0
- package/dist/agent/session-persistence.js.map +1 -0
- package/dist/agent/session-utils.d.ts +5 -0
- package/dist/agent/session-utils.d.ts.map +1 -0
- package/dist/agent/session-utils.js +51 -0
- package/dist/agent/session-utils.js.map +1 -0
- package/dist/agent/session.d.ts +15 -17
- package/dist/agent/session.d.ts.map +1 -1
- package/dist/agent/session.js +226 -608
- package/dist/agent/session.js.map +1 -1
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +67 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.d.ts.map +1 -1
- package/dist/index.js +24 -3
- package/dist/index.js.map +1 -1
- package/dist/tools/__tests__/bash.test.js +168 -1
- package/dist/tools/__tests__/bash.test.js.map +1 -1
- package/dist/tools/__tests__/edit.test.js +253 -6
- package/dist/tools/__tests__/edit.test.js.map +1 -1
- package/dist/tools/__tests__/fetch.test.js +1 -1
- package/dist/tools/__tests__/fetch.test.js.map +1 -1
- package/dist/tools/__tests__/glob.test.js +1 -1
- package/dist/tools/__tests__/glob.test.js.map +1 -1
- package/dist/tools/__tests__/grep.test.js +1 -1
- package/dist/tools/__tests__/grep.test.js.map +1 -1
- package/dist/tools/__tests__/ls.test.js +1 -1
- package/dist/tools/__tests__/ls.test.js.map +1 -1
- package/dist/tools/__tests__/read.test.js +1 -1
- package/dist/tools/__tests__/read.test.js.map +1 -1
- package/dist/tools/__tests__/registry.test.js +313 -0
- package/dist/tools/__tests__/registry.test.js.map +1 -1
- package/dist/tools/__tests__/write_plan.test.js +1 -1
- package/dist/tools/__tests__/write_plan.test.js.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +659 -39
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/codebase/ast/__tests__/ast-edit-demo.d.ts +2 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-demo.d.ts.map +1 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-demo.js +7 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-demo.js.map +1 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-final.d.ts +6 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-final.d.ts.map +1 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-final.js +11 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-final.js.map +1 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-test.d.ts +2 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-test.d.ts.map +1 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-test.js +9 -0
- package/dist/tools/codebase/ast/__tests__/ast-edit-test.js.map +1 -0
- package/dist/tools/codebase/ast/__tests__/integration.test.d.ts +2 -0
- package/dist/tools/codebase/ast/__tests__/integration.test.d.ts.map +1 -0
- package/dist/tools/codebase/ast/__tests__/integration.test.js +415 -0
- package/dist/tools/codebase/ast/__tests__/integration.test.js.map +1 -0
- package/dist/tools/codebase/ast/__tests__/tree-sitter.test.d.ts +2 -0
- package/dist/tools/codebase/ast/__tests__/tree-sitter.test.d.ts.map +1 -0
- package/dist/tools/codebase/ast/__tests__/tree-sitter.test.js +414 -0
- package/dist/tools/codebase/ast/__tests__/tree-sitter.test.js.map +1 -0
- package/dist/tools/codebase/ast/adapter.d.ts +23 -0
- package/dist/tools/codebase/ast/adapter.d.ts.map +1 -0
- package/dist/tools/codebase/ast/adapter.js +11 -0
- package/dist/tools/codebase/ast/adapter.js.map +1 -0
- package/dist/tools/codebase/ast/tools.d.ts +3 -0
- package/dist/tools/codebase/ast/tools.d.ts.map +1 -0
- package/dist/tools/codebase/ast/tools.js +286 -0
- package/dist/tools/codebase/ast/tools.js.map +1 -0
- package/dist/tools/codebase/ast/tree-sitter-adapter.d.ts +3 -0
- package/dist/tools/codebase/ast/tree-sitter-adapter.d.ts.map +1 -0
- package/dist/tools/codebase/ast/tree-sitter-adapter.js +412 -0
- package/dist/tools/codebase/ast/tree-sitter-adapter.js.map +1 -0
- package/dist/tools/codebase/ast/tree-sitter-converters.d.ts +4 -0
- package/dist/tools/codebase/ast/tree-sitter-converters.d.ts.map +1 -0
- package/dist/tools/codebase/ast/tree-sitter-converters.js +447 -0
- package/dist/tools/codebase/ast/tree-sitter-converters.js.map +1 -0
- package/dist/tools/codebase/ast/types.d.ts +103 -0
- package/dist/tools/codebase/ast/types.d.ts.map +1 -0
- package/dist/tools/codebase/ast/types.js +2 -0
- package/dist/tools/codebase/ast/types.js.map +1 -0
- package/dist/tools/codebase/ast/wasm/tree-sitter-python.wasm +0 -0
- package/dist/tools/codebase/ast/wasm/tree-sitter-tsx.wasm +0 -0
- package/dist/tools/codebase/ast/wasm/tree-sitter-typescript.wasm +0 -0
- package/dist/tools/codebase/ast/wasm/tree-sitter.wasm +0 -0
- package/dist/tools/codebase/ast/wasm/web-tree-sitter.wasm +0 -0
- package/dist/tools/codebase/find.d.ts +3 -0
- package/dist/tools/codebase/find.d.ts.map +1 -0
- package/dist/tools/codebase/find.js +61 -0
- package/dist/tools/codebase/find.js.map +1 -0
- package/dist/tools/codebase/glob.d.ts +3 -0
- package/dist/tools/codebase/glob.d.ts.map +1 -0
- package/dist/tools/codebase/glob.js +37 -0
- package/dist/tools/codebase/glob.js.map +1 -0
- package/dist/tools/codebase/grep.d.ts +3 -0
- package/dist/tools/codebase/grep.d.ts.map +1 -0
- package/dist/tools/codebase/grep.js +169 -0
- package/dist/tools/codebase/grep.js.map +1 -0
- package/dist/tools/codebase/ls.d.ts +3 -0
- package/dist/tools/codebase/ls.d.ts.map +1 -0
- package/dist/tools/codebase/ls.js +39 -0
- package/dist/tools/codebase/ls.js.map +1 -0
- package/dist/tools/codebase/read.d.ts +10 -0
- package/dist/tools/codebase/read.d.ts.map +1 -0
- package/dist/tools/codebase/read.js +81 -0
- package/dist/tools/codebase/read.js.map +1 -0
- package/dist/tools/delete_memory.d.ts +3 -0
- package/dist/tools/delete_memory.d.ts.map +1 -0
- package/dist/tools/delete_memory.js +46 -0
- package/dist/tools/delete_memory.js.map +1 -0
- package/dist/tools/edit/diff-compute.d.ts +4 -0
- package/dist/tools/edit/diff-compute.d.ts.map +1 -0
- package/dist/tools/edit/diff-compute.js +18 -0
- package/dist/tools/edit/diff-compute.js.map +1 -0
- package/dist/tools/edit/diff-render.d.ts +18 -0
- package/dist/tools/edit/diff-render.d.ts.map +1 -0
- package/dist/tools/edit/diff-render.js +128 -0
- package/dist/tools/edit/diff-render.js.map +1 -0
- package/dist/tools/edit/edit.d.ts +4 -0
- package/dist/tools/edit/edit.d.ts.map +1 -0
- package/dist/tools/edit/edit.js +440 -0
- package/dist/tools/edit/edit.js.map +1 -0
- package/dist/tools/edit/matcher.d.ts +24 -0
- package/dist/tools/edit/matcher.d.ts.map +1 -0
- package/dist/tools/edit/matcher.js +66 -0
- package/dist/tools/edit/matcher.js.map +1 -0
- package/dist/tools/edit/parser.d.ts +10 -0
- package/dist/tools/edit/parser.d.ts.map +1 -0
- package/dist/tools/edit/parser.js +120 -0
- package/dist/tools/edit/parser.js.map +1 -0
- package/dist/tools/edit/types.d.ts +16 -0
- package/dist/tools/edit/types.d.ts.map +1 -0
- package/dist/tools/edit/types.js +2 -0
- package/dist/tools/edit/types.js.map +1 -0
- package/dist/tools/edit/write_plan.d.ts +5 -0
- package/dist/tools/edit/write_plan.d.ts.map +1 -0
- package/dist/tools/edit/write_plan.js +98 -0
- package/dist/tools/edit/write_plan.js.map +1 -0
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +66 -1
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/execute/bash/constants.d.ts +24 -0
- package/dist/tools/execute/bash/constants.d.ts.map +1 -0
- package/dist/tools/execute/bash/constants.js +88 -0
- package/dist/tools/execute/bash/constants.js.map +1 -0
- package/dist/tools/execute/bash/errors.d.ts +39 -0
- package/dist/tools/execute/bash/errors.d.ts.map +1 -0
- package/dist/tools/execute/bash/errors.js +249 -0
- package/dist/tools/execute/bash/errors.js.map +1 -0
- package/dist/tools/execute/bash/execution.d.ts +18 -0
- package/dist/tools/execute/bash/execution.d.ts.map +1 -0
- package/dist/tools/execute/bash/execution.js +207 -0
- package/dist/tools/execute/bash/execution.js.map +1 -0
- package/dist/tools/execute/bash/index.d.ts +3 -0
- package/dist/tools/execute/bash/index.d.ts.map +1 -0
- package/dist/tools/execute/bash/index.js +117 -0
- package/dist/tools/execute/bash/index.js.map +1 -0
- package/dist/tools/execute/bash/platform.d.ts +6 -0
- package/dist/tools/execute/bash/platform.d.ts.map +1 -0
- package/dist/tools/execute/bash/platform.js +64 -0
- package/dist/tools/execute/bash/platform.js.map +1 -0
- package/dist/tools/execute/bash/security.d.ts +12 -0
- package/dist/tools/execute/bash/security.d.ts.map +1 -0
- package/dist/tools/execute/bash/security.js +26 -0
- package/dist/tools/execute/bash/security.js.map +1 -0
- package/dist/tools/execute/bash/validation.d.ts +16 -0
- package/dist/tools/execute/bash/validation.d.ts.map +1 -0
- package/dist/tools/execute/bash/validation.js +57 -0
- package/dist/tools/execute/bash/validation.js.map +1 -0
- package/dist/tools/execute/bash.d.ts +3 -0
- package/dist/tools/execute/bash.d.ts.map +1 -0
- package/dist/tools/execute/bash.js +728 -0
- package/dist/tools/execute/bash.js.map +1 -0
- package/dist/tools/execute/git.d.ts +3 -0
- package/dist/tools/execute/git.d.ts.map +1 -0
- package/dist/tools/execute/git.js +183 -0
- package/dist/tools/execute/git.js.map +1 -0
- package/dist/tools/execute/task_complete.d.ts +7 -0
- package/dist/tools/execute/task_complete.d.ts.map +1 -0
- package/dist/tools/execute/task_complete.js +38 -0
- package/dist/tools/execute/task_complete.js.map +1 -0
- package/dist/tools/fetch.d.ts.map +1 -1
- package/dist/tools/fetch.js +2 -0
- package/dist/tools/fetch.js.map +1 -1
- package/dist/tools/find.d.ts.map +1 -1
- package/dist/tools/find.js +2 -0
- package/dist/tools/find.js.map +1 -1
- package/dist/tools/git.d.ts.map +1 -1
- package/dist/tools/git.js +2 -0
- package/dist/tools/git.js.map +1 -1
- package/dist/tools/glob.d.ts.map +1 -1
- package/dist/tools/glob.js +2 -0
- package/dist/tools/glob.js.map +1 -1
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +2 -0
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/install/clawhub.d.ts +26 -0
- package/dist/tools/install/clawhub.d.ts.map +1 -0
- package/dist/tools/install/clawhub.js +182 -0
- package/dist/tools/install/clawhub.js.map +1 -0
- package/dist/tools/install/constants.d.ts +5 -0
- package/dist/tools/install/constants.d.ts.map +1 -0
- package/dist/tools/install/constants.js +5 -0
- package/dist/tools/install/constants.js.map +1 -0
- package/dist/tools/install/install_skill.d.ts +3 -0
- package/dist/tools/install/install_skill.d.ts.map +1 -0
- package/dist/tools/install/install_skill.js +132 -0
- package/dist/tools/install/install_skill.js.map +1 -0
- package/dist/tools/install/npm.d.ts +8 -0
- package/dist/tools/install/npm.d.ts.map +1 -0
- package/dist/tools/install/npm.js +52 -0
- package/dist/tools/install/npm.js.map +1 -0
- package/dist/tools/install/skill-content.d.ts +9 -0
- package/dist/tools/install/skill-content.d.ts.map +1 -0
- package/dist/tools/install/skill-content.js +89 -0
- package/dist/tools/install/skill-content.js.map +1 -0
- package/dist/tools/install_skill.d.ts.map +1 -1
- package/dist/tools/install_skill.js +2 -0
- package/dist/tools/install_skill.js.map +1 -1
- package/dist/tools/list_memory.d.ts +3 -0
- package/dist/tools/list_memory.d.ts.map +1 -0
- package/dist/tools/list_memory.js +55 -0
- package/dist/tools/list_memory.js.map +1 -0
- package/dist/tools/ls.d.ts.map +1 -1
- package/dist/tools/ls.js +2 -0
- package/dist/tools/ls.js.map +1 -1
- package/dist/tools/memory/delete_memory.d.ts +3 -0
- package/dist/tools/memory/delete_memory.d.ts.map +1 -0
- package/dist/tools/memory/delete_memory.js +46 -0
- package/dist/tools/memory/delete_memory.js.map +1 -0
- package/dist/tools/memory/list_memory.d.ts +3 -0
- package/dist/tools/memory/list_memory.d.ts.map +1 -0
- package/dist/tools/memory/list_memory.js +55 -0
- package/dist/tools/memory/list_memory.js.map +1 -0
- package/dist/tools/memory/save_memory.d.ts +3 -0
- package/dist/tools/memory/save_memory.d.ts.map +1 -0
- package/dist/tools/memory/save_memory.js +45 -0
- package/dist/tools/memory/save_memory.js.map +1 -0
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +2 -0
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/registry.d.ts +7 -2
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +112 -17
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/save_memory.d.ts +3 -0
- package/dist/tools/save_memory.d.ts.map +1 -0
- package/dist/tools/save_memory.js +45 -0
- package/dist/tools/save_memory.js.map +1 -0
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +2 -0
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/tree.d.ts +12 -0
- package/dist/tools/tree.d.ts.map +1 -0
- package/dist/tools/tree.js +87 -0
- package/dist/tools/tree.js.map +1 -0
- package/dist/tools/types.d.ts +12 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/web/fetch.d.ts +3 -0
- package/dist/tools/web/fetch.d.ts.map +1 -0
- package/dist/tools/web/fetch.js +49 -0
- package/dist/tools/web/fetch.js.map +1 -0
- package/dist/tools/web/search.d.ts +3 -0
- package/dist/tools/web/search.d.ts.map +1 -0
- package/dist/tools/web/search.js +134 -0
- package/dist/tools/web/search.js.map +1 -0
- package/dist/tools/write_plan.d.ts.map +1 -1
- package/dist/tools/write_plan.js +2 -0
- package/dist/tools/write_plan.js.map +1 -1
- package/dist/tui/commands.d.ts +4 -0
- package/dist/tui/commands.d.ts.map +1 -0
- package/dist/tui/commands.js +118 -0
- package/dist/tui/commands.js.map +1 -0
- package/dist/tui/components/colors.d.ts +36 -0
- package/dist/tui/components/colors.d.ts.map +1 -0
- package/dist/tui/components/colors.js +48 -0
- package/dist/tui/components/colors.js.map +1 -0
- package/dist/tui/components/header-bar.d.ts +26 -0
- package/dist/tui/components/header-bar.d.ts.map +1 -0
- package/dist/tui/components/header-bar.js +78 -0
- package/dist/tui/components/header-bar.js.map +1 -0
- package/dist/tui/components/index.d.ts +9 -0
- package/dist/tui/components/index.d.ts.map +1 -0
- package/dist/tui/components/index.js +9 -0
- package/dist/tui/components/index.js.map +1 -0
- package/dist/tui/components/landing-screen.d.ts +12 -0
- package/dist/tui/components/landing-screen.d.ts.map +1 -0
- package/dist/tui/components/landing-screen.js +53 -0
- package/dist/tui/components/landing-screen.js.map +1 -0
- package/dist/tui/components/pixel-logo.d.ts +5 -0
- package/dist/tui/components/pixel-logo.d.ts.map +1 -0
- package/dist/tui/components/pixel-logo.js +27 -0
- package/dist/tui/components/pixel-logo.js.map +1 -0
- package/dist/tui/components/plan-utils.d.ts +11 -0
- package/dist/tui/components/plan-utils.d.ts.map +1 -0
- package/dist/tui/components/plan-utils.js +62 -0
- package/dist/tui/components/plan-utils.js.map +1 -0
- package/dist/tui/components/plans-list.d.ts +18 -0
- package/dist/tui/components/plans-list.d.ts.map +1 -0
- package/dist/tui/components/plans-list.js +46 -0
- package/dist/tui/components/plans-list.js.map +1 -0
- package/dist/tui/components/rich-footer.d.ts +29 -0
- package/dist/tui/components/rich-footer.d.ts.map +1 -0
- package/dist/tui/components/rich-footer.js +124 -0
- package/dist/tui/components/rich-footer.js.map +1 -0
- package/dist/tui/components/todo-panel.d.ts +14 -0
- package/dist/tui/components/todo-panel.d.ts.map +1 -0
- package/dist/tui/components/todo-panel.js +83 -0
- package/dist/tui/components/todo-panel.js.map +1 -0
- package/dist/tui/components.d.ts.map +1 -1
- package/dist/tui/components.js +14 -7
- package/dist/tui/components.js.map +1 -1
- package/dist/tui/index.d.ts +2 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +99 -505
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/overlays.d.ts +28 -0
- package/dist/tui/overlays.d.ts.map +1 -0
- package/dist/tui/overlays.js +154 -0
- package/dist/tui/overlays.js.map +1 -0
- package/dist/tui/themes.d.ts +5 -0
- package/dist/tui/themes.d.ts.map +1 -0
- package/dist/tui/themes.js +38 -0
- package/dist/tui/themes.js.map +1 -0
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +60 -122
- package/dist/web/index.js.map +1 -1
- package/dist/web/public/index.html +1 -1
- package/dist/web/public/messages.js +41 -25
- package/dist/web/public/state.js +72 -72
- package/dist/web/public/style.css +1126 -996
- package/dist/web/public/websocket.js +267 -267
- package/dist/web/session-bridge.d.ts.map +1 -1
- package/dist/web/session-bridge.js +82 -3
- package/dist/web/session-bridge.js.map +1 -1
- package/docs/ast-tools.md +117 -0
- package/package.json +60 -55
- package/scripts/check-line-count.mjs +53 -0
- package/scripts/copy-ast-wasm.mjs +32 -0
- package/src/agent/__tests__/session-restore.test.ts +284 -0
- package/src/agent/commands.ts +274 -0
- package/src/agent/compaction.ts +9 -2
- package/src/agent/index.ts +30 -25
- package/src/agent/memory.ts +60 -0
- package/src/agent/prompt-builder.ts +100 -26
- package/src/agent/providers/anthropic.ts +179 -179
- package/src/agent/providers/google.ts +210 -210
- package/src/agent/providers/ollama.ts +186 -186
- package/src/agent/providers/openai.ts +18 -3
- package/src/agent/session-chat.ts +480 -0
- package/src/agent/session-display.ts +195 -0
- package/src/agent/session-persistence.ts +146 -0
- package/src/agent/session-utils.ts +54 -0
- package/src/agent/session.ts +261 -718
- package/src/cli/index.ts +73 -4
- package/src/config/index.ts +342 -342
- package/src/index.ts +30 -3
- package/src/tools/__tests__/bash.test.ts +187 -1
- package/src/tools/__tests__/edit.test.ts +275 -11
- package/src/tools/__tests__/fetch.test.ts +1 -1
- package/src/tools/__tests__/glob.test.ts +1 -1
- package/src/tools/__tests__/grep.test.ts +1 -1
- package/src/tools/__tests__/ls.test.ts +1 -1
- package/src/tools/__tests__/read.test.ts +1 -1
- package/src/tools/__tests__/registry.test.ts +332 -0
- package/src/tools/__tests__/write_plan.test.ts +1 -1
- package/src/tools/codebase/ast/__tests__/integration.test.ts +452 -0
- package/src/tools/codebase/ast/__tests__/tree-sitter.test.ts +466 -0
- package/src/tools/codebase/ast/adapter.ts +44 -0
- package/src/tools/codebase/ast/tools.ts +322 -0
- package/src/tools/codebase/ast/tree-sitter-adapter.ts +468 -0
- package/src/tools/codebase/ast/tree-sitter-converters.ts +480 -0
- package/src/tools/codebase/ast/types.ts +102 -0
- package/src/tools/codebase/ast/wasm/tree-sitter-python.wasm +0 -0
- package/src/tools/codebase/ast/wasm/tree-sitter-tsx.wasm +0 -0
- package/src/tools/codebase/ast/wasm/tree-sitter-typescript.wasm +0 -0
- package/src/tools/codebase/ast/wasm/tree-sitter.wasm +0 -0
- package/src/tools/codebase/ast/wasm/web-tree-sitter.wasm +0 -0
- package/src/tools/{find.ts → codebase/find.ts} +4 -2
- package/src/tools/{glob.ts → codebase/glob.ts} +4 -2
- package/src/tools/{grep.ts → codebase/grep.ts} +4 -2
- package/src/tools/{ls.ts → codebase/ls.ts} +4 -2
- package/src/tools/{read.ts → codebase/read.ts} +5 -3
- package/src/tools/edit/diff-compute.ts +21 -0
- package/src/tools/edit/diff-render.ts +145 -0
- package/src/tools/edit/edit.ts +468 -0
- package/src/tools/edit/matcher.ts +70 -0
- package/src/tools/edit/parser.ts +131 -0
- package/src/tools/edit/types.ts +19 -0
- package/src/tools/{write_plan.ts → edit/write_plan.ts} +4 -2
- package/src/tools/execute/bash/constants.ts +93 -0
- package/src/tools/execute/bash/errors.ts +304 -0
- package/src/tools/execute/bash/execution.ts +211 -0
- package/src/tools/execute/bash/index.ts +131 -0
- package/src/tools/execute/bash/platform.ts +65 -0
- package/src/tools/execute/bash/security.ts +28 -0
- package/src/tools/execute/bash/validation.ts +78 -0
- package/src/tools/execute/git.ts +209 -0
- package/src/tools/execute/task_complete.ts +40 -0
- package/src/tools/install/clawhub.ts +222 -0
- package/src/tools/install/constants.ts +4 -0
- package/src/tools/install/install_skill.ts +150 -0
- package/src/tools/install/npm.ts +60 -0
- package/src/tools/install/skill-content.ts +108 -0
- package/src/tools/memory/delete_memory.ts +46 -0
- package/src/tools/memory/list_memory.ts +53 -0
- package/src/tools/memory/save_memory.ts +45 -0
- package/src/tools/registry.ts +119 -19
- package/src/tools/tree.ts +103 -0
- package/src/tools/types.ts +13 -0
- package/src/tools/{fetch.ts → web/fetch.ts} +4 -2
- package/src/tools/{search.ts → web/search.ts} +4 -2
- package/src/tui/commands.ts +135 -0
- package/src/tui/components/colors.ts +52 -0
- package/src/tui/components/header-bar.ts +88 -0
- package/src/tui/components/index.ts +8 -0
- package/src/tui/components/landing-screen.ts +67 -0
- package/src/tui/components/pixel-logo.ts +33 -0
- package/src/tui/components/plan-utils.ts +69 -0
- package/src/tui/components/plans-list.ts +55 -0
- package/src/tui/components/rich-footer.ts +146 -0
- package/src/tui/components/todo-panel.ts +95 -0
- package/src/tui/index.ts +335 -786
- package/src/tui/overlays.ts +203 -0
- package/src/tui/themes.ts +41 -0
- package/src/web/index.ts +64 -127
- package/src/web/public/index.html +1 -1
- package/src/web/public/messages.js +41 -25
- package/src/web/public/state.js +72 -72
- package/src/web/public/style.css +1126 -996
- package/src/web/public/websocket.js +267 -267
- package/src/web/session-bridge.ts +272 -193
- package/AGENT.md +0 -99
- package/src/tools/bash.ts +0 -125
- package/src/tools/edit.ts +0 -747
- package/src/tools/git.ts +0 -76
- package/src/tools/install_skill.ts +0 -539
- package/src/tui/components.ts +0 -635
package/dist/tui/index.js
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
import { resetGlobalEventBus } from '../agent/event-bus.js';
|
|
2
|
-
import { ensurePromptsDir, loadPromptTemplates } from '../agent/prompt-templates.js';
|
|
3
1
|
import { formatToolInput, Session } from '../agent/session.js';
|
|
4
|
-
import {
|
|
5
|
-
import { loadTokenUsage, resetTokenUsage } from '../config/tokens.js';
|
|
6
|
-
import { Box, CombinedAutocompleteProvider, Container, Editor, Loader, Markdown, ProcessTerminal, Text, TUI, } from '../pi-tui/index.js';
|
|
7
|
-
import { fmtErr } from '../tools/errors.js';
|
|
2
|
+
import { Box, CombinedAutocompleteProvider, Editor, Loader, Markdown, ProcessTerminal, TUI, } from '../pi-tui/index.js';
|
|
8
3
|
import { fetchDeepSeekBalance, isDeepSeekOfficial } from './balance.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* Used to reserve space at the bottom of the chat area so the editor
|
|
14
|
-
* overlay doesn't cover the last lines of command output.
|
|
15
|
-
*/
|
|
4
|
+
import { handleConfirmInput, sendMessage } from './commands.js';
|
|
5
|
+
import { colors, LandingScreen, listPlans, PlansList, RichFooter, TodoPanel, } from './components/index.js';
|
|
6
|
+
import { refreshPlans, showHelpOverlay, showPlanDetail, showPlansOverlay, showTodoPanel, updateFooter, } from './overlays.js';
|
|
7
|
+
import { editorTheme, markdownTheme, selectTheme } from './themes.js';
|
|
16
8
|
class Spacer {
|
|
17
9
|
height;
|
|
18
10
|
constructor(height) {
|
|
@@ -23,84 +15,43 @@ class Spacer {
|
|
|
23
15
|
}
|
|
24
16
|
invalidate() { }
|
|
25
17
|
}
|
|
26
|
-
export async function startTui(config) {
|
|
27
|
-
|
|
28
|
-
let isRunning = false;
|
|
29
|
-
let session;
|
|
30
|
-
// ── Create markdown theme (OpenCode-style, clean colors, with syntax highlighting) ──
|
|
31
|
-
const markdownTheme = {
|
|
32
|
-
heading: t => `\x1b[38;2;0;170;255m\x1b[1m${t}\x1b[0m`,
|
|
33
|
-
link: t => `\x1b[38;2;0;170;255m\x1b[4m${t}\x1b[0m`,
|
|
34
|
-
linkUrl: t => `\x1b[38;2;90;90;90m\x1b[4m${t}\x1b[0m`,
|
|
35
|
-
code: t => `\x1b[38;2;255;180;50m${t}\x1b[0m`,
|
|
36
|
-
codeBlock: t => `\x1b[38;2;200;200;200m${t}\x1b[0m`,
|
|
37
|
-
codeBlockBorder: t => `\x1b[38;2;60;60;60m${t}\x1b[0m`,
|
|
38
|
-
highlightCode: (code, lang) => {
|
|
39
|
-
if (lang && lang.trim()) {
|
|
40
|
-
const lines = code.split('\n');
|
|
41
|
-
return lines.map(line => highlightLine(line, lang));
|
|
42
|
-
}
|
|
43
|
-
return code.split('\n');
|
|
44
|
-
},
|
|
45
|
-
codeBlockIndent: ' ',
|
|
46
|
-
quote: t => `\x1b[38;2;130;130;130m${t}\x1b[0m`,
|
|
47
|
-
quoteBorder: t => `\x1b[38;2;60;60;60m${t}\x1b[0m`,
|
|
48
|
-
hr: t => `\x1b[38;2;60;60;60m${t}\x1b[0m`,
|
|
49
|
-
listBullet: t => `\x1b[38;2;130;130;130m${t}\x1b[0m`,
|
|
50
|
-
bold: t => `\x1b[1m${t}\x1b[0m`,
|
|
51
|
-
italic: t => `\x1b[3m${t}\x1b[0m`,
|
|
52
|
-
strikethrough: t => `\x1b[9m${t}\x1b[0m`,
|
|
53
|
-
underline: t => `\x1b[4m${t}\x1b[0m`,
|
|
54
|
-
};
|
|
55
|
-
// ── Create select list theme ──
|
|
56
|
-
const selectTheme = {
|
|
57
|
-
selectedPrefix: t => `\x1b[38;2;255;255;255m\x1b[48;2;0;128;255m ${t}\x1b[0m`,
|
|
58
|
-
selectedText: t => `\x1b[38;2;255;255;255m\x1b[48;2;0;128;255m${t}\x1b[0m`,
|
|
59
|
-
description: t => `\x1b[90m${t}\x1b[0m`,
|
|
60
|
-
scrollInfo: t => `\x1b[90m${t}\x1b[0m`,
|
|
61
|
-
noMatch: t => `\x1b[38;2;255;100;100m${t}\x1b[0m`,
|
|
62
|
-
};
|
|
63
|
-
// ── Create editor theme (used by Editor component) ────────────────────
|
|
64
|
-
const editorTheme = {
|
|
65
|
-
borderColor: (str) => colors.accent(str),
|
|
66
|
-
selectList: selectTheme,
|
|
67
|
-
};
|
|
18
|
+
export async function startTui(config, preloadedSession) {
|
|
19
|
+
const ctx = {};
|
|
68
20
|
// ── Create terminal and TUI ────────────────────────────────────────────
|
|
69
21
|
const terminal = new ProcessTerminal();
|
|
70
|
-
// Patch terminal.write to suppress alternate screen buffer sequences.
|
|
71
|
-
// Without this, pi-tui disables the terminal's native scrollback/scrollbar,
|
|
72
|
-
// making it impossible to scroll through past conversation history.
|
|
73
22
|
const origWrite = terminal.write.bind(terminal);
|
|
74
23
|
terminal.write = (data) => {
|
|
75
24
|
const filtered = data.replace(/\x1b\[\?1049[hl]/g, '');
|
|
76
25
|
if (filtered)
|
|
77
26
|
origWrite(filtered);
|
|
78
27
|
};
|
|
79
|
-
// Show hardware cursor by default so IME (Chinese input method) can
|
|
80
|
-
// position its candidate window at the correct cursor location.
|
|
81
|
-
// The cursor is hidden during agent execution via setShowHardwareCursor(false).
|
|
82
|
-
// Note: on some terminals (Windows Terminal), showing the hardware cursor
|
|
83
|
-
// can interfere with editor rendering layout. If you see editor border gap,
|
|
84
|
-
// set this to false and use PI_HARDWARE_CURSOR=1 env var to enable.
|
|
85
28
|
const tui = new TUI(terminal, true);
|
|
86
29
|
tui.setClearOnShrink(true);
|
|
87
30
|
terminal.setTitle(`lonny ${config.model} ${config.provider}`);
|
|
31
|
+
ctx.tui = tui;
|
|
88
32
|
// ── Create components ──────────────────────────────────────────────────
|
|
89
|
-
// Chat area (full width, no side panel) — created upfront but only added
|
|
90
|
-
// to the TUI after the landing screen transitions to chat mode.
|
|
91
33
|
const chatMarkdown = new Markdown('', 1, 0, markdownTheme);
|
|
34
|
+
ctx.chatMarkdown = chatMarkdown;
|
|
92
35
|
const chatBox = new Box(1, 0);
|
|
93
36
|
chatBox.addChild(chatMarkdown);
|
|
94
|
-
// Reserve space at the bottom so the editor overlay doesn't cover
|
|
95
|
-
// the last lines of command output. 13 = maxHeight(12) + offsetY(1).
|
|
96
37
|
chatBox.addChild(new Spacer(13));
|
|
97
|
-
// Chat input — Editor with multi-line support, history, and autocomplete
|
|
98
38
|
const slashCommands = [
|
|
99
|
-
{
|
|
39
|
+
{
|
|
40
|
+
name: 'mode',
|
|
41
|
+
description: 'Switch mode (code|plan|ask|loop)',
|
|
42
|
+
argumentHint: 'code|plan|ask|loop',
|
|
43
|
+
},
|
|
100
44
|
{ name: 'model', description: 'Switch model', argumentHint: '<name>' },
|
|
101
45
|
{ name: 'plans', description: 'Show plans overlay' },
|
|
102
46
|
{ name: 'prompts', description: 'List prompt templates' },
|
|
103
47
|
{ name: 'skills', description: 'List active skills' },
|
|
48
|
+
{ name: 'sessions', description: 'List all saved sessions' },
|
|
49
|
+
{
|
|
50
|
+
name: 'session',
|
|
51
|
+
description: 'Show current session info',
|
|
52
|
+
argumentHint: '[title <name>|delete]',
|
|
53
|
+
},
|
|
54
|
+
{ name: 'fork', description: 'Fork a new session from current context' },
|
|
104
55
|
{ name: 'new', description: 'Start a new session' },
|
|
105
56
|
{ name: 'init', description: 'Create .lonny/skills/ & prompts/' },
|
|
106
57
|
{ name: 'help', description: 'Show help' },
|
|
@@ -109,98 +60,76 @@ export async function startTui(config) {
|
|
|
109
60
|
{ name: 'filter', description: 'Filter plans', argumentHint: '<query>' },
|
|
110
61
|
];
|
|
111
62
|
const editor = new Editor(tui, editorTheme);
|
|
63
|
+
ctx.editor = editor;
|
|
112
64
|
editor.setAutocompleteProvider(new CombinedAutocompleteProvider(slashCommands, config.cwd));
|
|
113
|
-
// Loader (thinking indicator)
|
|
114
65
|
const loader = new Loader(tui, colors.running, colors.idle, 'thinking...', { intervalMs: 80 });
|
|
115
|
-
|
|
116
|
-
// input always stays at the bottom of the terminal, regardless of how
|
|
117
|
-
// much chat content has accumulated.
|
|
66
|
+
ctx.loader = loader;
|
|
118
67
|
let inputOverlayHandle = null;
|
|
119
|
-
// Rich footer (cwd | mode | tokens | model | version + command hints)
|
|
120
68
|
const footer = new RichFooter(config.cwd, config.model, config.provider);
|
|
121
|
-
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
69
|
+
ctx.footer = footer;
|
|
70
|
+
// ── Init mutable state ─────────────────────────────────────────────────
|
|
71
|
+
ctx.chatContent = '';
|
|
72
|
+
ctx.isRunning = false;
|
|
73
|
+
ctx.pendingConfirmResolve = null;
|
|
74
|
+
ctx.plansOverlayHandle = null;
|
|
75
|
+
ctx.helpOverlayHandle = null;
|
|
76
|
+
ctx.todoPanelHandle = null;
|
|
77
|
+
ctx.plansDetailMode = false;
|
|
78
|
+
ctx.config = config;
|
|
79
|
+
// ── Plan written callback ──────────────────────────────────────────────
|
|
129
80
|
const planCb = () => {
|
|
130
|
-
refreshPlans();
|
|
131
|
-
todoPanel.refresh();
|
|
132
|
-
if (plansOverlayHandle?.isHidden() === false) {
|
|
133
|
-
showPlansOverlay();
|
|
81
|
+
refreshPlans(ctx);
|
|
82
|
+
ctx.todoPanel.refresh();
|
|
83
|
+
if (ctx.plansOverlayHandle?.isHidden() === false) {
|
|
84
|
+
showPlansOverlay(ctx);
|
|
134
85
|
}
|
|
135
86
|
};
|
|
136
|
-
|
|
137
|
-
//
|
|
138
|
-
// with assistant text in the correct order (just like non-TUI mode).
|
|
139
|
-
// ── Tool confirmation state ──
|
|
140
|
-
let pendingConfirmResolve = null;
|
|
141
|
-
function handleConfirmInput(data) {
|
|
142
|
-
if (!pendingConfirmResolve)
|
|
143
|
-
return false;
|
|
144
|
-
const key = data.trim().toLowerCase();
|
|
145
|
-
if (key === 'y' || key === 'yes') {
|
|
146
|
-
pendingConfirmResolve(true);
|
|
147
|
-
pendingConfirmResolve = null;
|
|
148
|
-
chatContent += 'y\n';
|
|
149
|
-
chatMarkdown.setText(chatContent);
|
|
150
|
-
tui.requestRender(true);
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
else if (key === 'n' || key === 'no' || key === '\r' || key === '') {
|
|
154
|
-
pendingConfirmResolve(false);
|
|
155
|
-
pendingConfirmResolve = null;
|
|
156
|
-
chatContent += 'N\n';
|
|
157
|
-
chatMarkdown.setText(chatContent);
|
|
158
|
-
tui.requestRender(true);
|
|
159
|
-
return true;
|
|
160
|
-
}
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
87
|
+
ctx.planCb = planCb;
|
|
88
|
+
// ── Session output ─────────────────────────────────────────────────────
|
|
163
89
|
const output = {
|
|
164
90
|
write: (text) => {
|
|
165
|
-
chatContent += text;
|
|
166
|
-
chatMarkdown.setText(chatContent);
|
|
91
|
+
ctx.chatContent += text;
|
|
92
|
+
ctx.chatMarkdown.setText(ctx.chatContent);
|
|
167
93
|
},
|
|
168
94
|
suppressToolOutput: false,
|
|
169
95
|
confirmTool: async (toolCalls) => {
|
|
170
|
-
chatContent += `\n ${colors.warn('Allow these tool calls?')}\n`;
|
|
96
|
+
ctx.chatContent += `\n ${colors.warn('Allow these tool calls?')}\n`;
|
|
171
97
|
for (const tc of toolCalls) {
|
|
172
98
|
const detail = formatToolInput(tc);
|
|
173
|
-
chatContent += ` ${colors.dim('\u2022')} ${colors.accent(tc.name)}${detail ? ` ${colors.dim(detail)}` : ''}\n`;
|
|
99
|
+
ctx.chatContent += ` ${colors.dim('\u2022')} ${colors.accent(tc.name)}${detail ? ` ${colors.dim(detail)}` : ''}\n`;
|
|
174
100
|
}
|
|
175
|
-
chatContent += ` ${colors.inputPrompt('(y/N)')} `;
|
|
176
|
-
chatMarkdown.setText(chatContent);
|
|
177
|
-
tui.requestRender(true);
|
|
101
|
+
ctx.chatContent += ` ${colors.inputPrompt('(y/N)')} `;
|
|
102
|
+
ctx.chatMarkdown.setText(ctx.chatContent);
|
|
103
|
+
ctx.tui.requestRender(true);
|
|
178
104
|
return new Promise(resolve => {
|
|
179
|
-
pendingConfirmResolve = resolve;
|
|
105
|
+
ctx.pendingConfirmResolve = resolve;
|
|
180
106
|
});
|
|
181
107
|
},
|
|
182
108
|
};
|
|
183
|
-
|
|
109
|
+
ctx.output = output;
|
|
110
|
+
// ── Session restore ────────────────────────────────────────────────────
|
|
184
111
|
let restored = false;
|
|
185
|
-
|
|
112
|
+
let restoredSession = preloadedSession ?? null;
|
|
113
|
+
if (!restoredSession) {
|
|
114
|
+
restoredSession = await Session.load(config, output);
|
|
115
|
+
}
|
|
186
116
|
if (restoredSession) {
|
|
187
117
|
restored = true;
|
|
188
|
-
session = restoredSession;
|
|
189
|
-
session.onPlanWritten = planCb;
|
|
190
|
-
|
|
191
|
-
const lastUserMsg = [...session.messages].reverse().find(m => m.role === 'user');
|
|
118
|
+
ctx.session = restoredSession;
|
|
119
|
+
ctx.session.onPlanWritten = planCb;
|
|
120
|
+
const lastUserMsg = [...ctx.session.messages].reverse().find(m => m.role === 'user');
|
|
192
121
|
const lastQuestion = lastUserMsg && typeof lastUserMsg.content === 'string' ? lastUserMsg.content : null;
|
|
193
|
-
chatContent = `\n${colors.dim('\u21BA Resumed previous session')}`;
|
|
122
|
+
ctx.chatContent = `\n${colors.dim('\u21BA Resumed previous session')}`;
|
|
194
123
|
if (lastQuestion) {
|
|
195
124
|
const preview = lastQuestion.length > 80 ? `${lastQuestion.slice(0, 80)}\u2026` : lastQuestion;
|
|
196
|
-
chatContent += ` \u2014 ${colors.userLabel(preview)}`;
|
|
125
|
+
ctx.chatContent += ` \u2014 ${colors.userLabel(preview)}`;
|
|
197
126
|
}
|
|
198
|
-
chatContent += '\n\n';
|
|
199
|
-
chatMarkdown.setText(chatContent);
|
|
127
|
+
ctx.chatContent += '\n\n';
|
|
128
|
+
ctx.chatMarkdown.setText(ctx.chatContent);
|
|
200
129
|
}
|
|
201
130
|
else {
|
|
202
|
-
session = new Session(config, output);
|
|
203
|
-
session.onPlanWritten = planCb;
|
|
131
|
+
ctx.session = new Session(config, output);
|
|
132
|
+
ctx.session.onPlanWritten = planCb;
|
|
204
133
|
}
|
|
205
134
|
// ── Fetch DeepSeek balance at startup (non-blocking)
|
|
206
135
|
;
|
|
@@ -214,8 +143,8 @@ export async function startTui(config) {
|
|
|
214
143
|
tui.requestRender(true);
|
|
215
144
|
}
|
|
216
145
|
else if (balance.error) {
|
|
217
|
-
chatContent += `\n${colors.warn('\u26A0')} Balance fetch failed: ${balance.error}\n`;
|
|
218
|
-
chatMarkdown.setText(chatContent);
|
|
146
|
+
ctx.chatContent += `\n${colors.warn('\u26A0')} Balance fetch failed: ${balance.error}\n`;
|
|
147
|
+
ctx.chatMarkdown.setText(ctx.chatContent);
|
|
219
148
|
}
|
|
220
149
|
}
|
|
221
150
|
}
|
|
@@ -223,10 +152,9 @@ export async function startTui(config) {
|
|
|
223
152
|
// Silently ignore balance fetch errors
|
|
224
153
|
}
|
|
225
154
|
})();
|
|
226
|
-
// ── Landing screen
|
|
155
|
+
// ── Landing screen ────────────────────────────────────────────────────
|
|
227
156
|
const landingScreen = new LandingScreen(config.model, config.provider);
|
|
228
157
|
let landingOverlayHandle = null;
|
|
229
|
-
// Only show the landing screen if no session was restored
|
|
230
158
|
if (!restored) {
|
|
231
159
|
landingOverlayHandle = tui.showOverlay(landingScreen, {
|
|
232
160
|
anchor: 'center',
|
|
@@ -235,9 +163,7 @@ export async function startTui(config) {
|
|
|
235
163
|
});
|
|
236
164
|
tui.setFocus(landingScreen);
|
|
237
165
|
}
|
|
238
|
-
// ── Rich footer bar
|
|
239
|
-
// NOTE: must be added AFTER the landing screen overlay so it renders on
|
|
240
|
-
// top and is not covered by the centered overlay.
|
|
166
|
+
// ── Rich footer bar ────────────────────────────────────────────────────
|
|
241
167
|
const footerWidth = terminal.columns ?? process.stdout.columns ?? 120;
|
|
242
168
|
const footerHandle = tui.showOverlay(footer, {
|
|
243
169
|
anchor: 'bottom-left',
|
|
@@ -246,21 +172,7 @@ export async function startTui(config) {
|
|
|
246
172
|
});
|
|
247
173
|
// ── Persistent Todo Side Panel ────────────────────────────────────────
|
|
248
174
|
const todoPanel = new TodoPanel(config.cwd);
|
|
249
|
-
|
|
250
|
-
function showTodoPanel() {
|
|
251
|
-
todoPanel.refresh();
|
|
252
|
-
const box = new Box(0, 0, colors.bgDark);
|
|
253
|
-
box.addChild(todoPanel);
|
|
254
|
-
todoPanelHandle = tui.showOverlay(box, {
|
|
255
|
-
anchor: 'top-right',
|
|
256
|
-
offsetY: 2,
|
|
257
|
-
width: 36,
|
|
258
|
-
maxHeight: '70%',
|
|
259
|
-
offsetX: -1,
|
|
260
|
-
nonCapturing: true,
|
|
261
|
-
visible: (w) => w >= 110,
|
|
262
|
-
});
|
|
263
|
-
}
|
|
175
|
+
ctx.todoPanel = todoPanel;
|
|
264
176
|
// If a session was restored, immediately transition to chat layout
|
|
265
177
|
// (skip the landing screen)
|
|
266
178
|
if (restored) {
|
|
@@ -274,332 +186,23 @@ export async function startTui(config) {
|
|
|
274
186
|
maxHeight: 12,
|
|
275
187
|
nonCapturing: false,
|
|
276
188
|
});
|
|
277
|
-
showTodoPanel();
|
|
189
|
+
showTodoPanel(ctx);
|
|
278
190
|
tui.setFocus(editor);
|
|
279
191
|
}
|
|
280
192
|
// ── Plans overlay components ──────────────────────────────────────────
|
|
281
193
|
const plansList = new PlansList([], 15, selectTheme);
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
function showPlansOverlay() {
|
|
285
|
-
if (plansOverlayHandle?.isHidden() === false) {
|
|
286
|
-
plansOverlayHandle.hide();
|
|
287
|
-
plansOverlayHandle = null;
|
|
288
|
-
plansDetailMode = false;
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
plansDetailMode = false;
|
|
292
|
-
const plans = listPlans(config.cwd);
|
|
293
|
-
plansList.refresh(plansToItems(plans));
|
|
294
|
-
const headerText = new Text(` ${colors.accent('\u25B6')} Plans (${plans.length}) ${colors.dim('Enter=view')}`, 1, 0, colors.headerBg);
|
|
295
|
-
const container = new Container();
|
|
296
|
-
container.addChild(headerText);
|
|
297
|
-
if (plans.length > 0) {
|
|
298
|
-
container.addChild(plansList);
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
container.addChild(new Text(' (no plans yet)', 1, 0, colors.dim));
|
|
302
|
-
}
|
|
303
|
-
const box = new Box(1, 1, colors.bgDark);
|
|
304
|
-
box.addChild(container);
|
|
305
|
-
plansOverlayHandle = tui.showOverlay(box, {
|
|
306
|
-
anchor: 'right-center',
|
|
307
|
-
width: 45,
|
|
308
|
-
maxHeight: '70%',
|
|
309
|
-
offsetX: -1,
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
function showPlanDetail() {
|
|
313
|
-
if (!plansOverlayHandle || plansOverlayHandle.isHidden())
|
|
314
|
-
return;
|
|
315
|
-
const sel = plansList.getSelectedItem();
|
|
316
|
-
if (!sel)
|
|
317
|
-
return;
|
|
318
|
-
plansDetailMode = true;
|
|
319
|
-
const plans = listPlans(config.cwd);
|
|
320
|
-
const plan = plans.find(p => p.name === sel.value);
|
|
321
|
-
if (!plan)
|
|
322
|
-
return;
|
|
323
|
-
const todos = loadTodos(plan.fullPath);
|
|
324
|
-
const headerText = new Text(` ${colors.accent('\u25B6')} ${colors.warn(plan.name)} ${colors.dim('Esc=back')}`, 1, 0, colors.headerBg);
|
|
325
|
-
const todosText = new Text(`\n ${todos}\n`, 1, 0);
|
|
326
|
-
const container = new Container();
|
|
327
|
-
container.addChild(headerText);
|
|
328
|
-
container.addChild(todosText);
|
|
329
|
-
const box = new Box(1, 1, colors.bgDark);
|
|
330
|
-
box.addChild(container);
|
|
331
|
-
// Hide current and show detail
|
|
332
|
-
plansOverlayHandle.hide();
|
|
333
|
-
plansOverlayHandle = tui.showOverlay(box, {
|
|
334
|
-
anchor: 'right-center',
|
|
335
|
-
width: 50,
|
|
336
|
-
maxHeight: '80%',
|
|
337
|
-
offsetX: -1,
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
// ── Help overlay ──────────────────────────────────────────────────────────
|
|
341
|
-
let helpOverlayHandle = null;
|
|
342
|
-
function showHelpOverlay() {
|
|
343
|
-
if (helpOverlayHandle?.isHidden() === false) {
|
|
344
|
-
helpOverlayHandle.hide();
|
|
345
|
-
helpOverlayHandle = null;
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
const helpContent = colors.accent('\u2501').repeat(20) +
|
|
349
|
-
'\n' +
|
|
350
|
-
` ${colors.accent('lonny')} ${colors.dim('TUI Help')}\n` +
|
|
351
|
-
colors.accent('\u2501').repeat(20) +
|
|
352
|
-
'\n\n' +
|
|
353
|
-
` ${colors.dim('Commands:')}\n` +
|
|
354
|
-
` ${colors.inputPrompt('/mode')} code|plan|ask ${colors.dim('Switch mode')}\n` +
|
|
355
|
-
` ${colors.inputPrompt('/model')} <name> ${colors.dim('Switch model')}\n` +
|
|
356
|
-
` ${colors.inputPrompt('/plans')} ${colors.dim('Show plans overlay')}\n` +
|
|
357
|
-
` ${colors.inputPrompt('/new')} ${colors.dim('Start a new session')}\n` +
|
|
358
|
-
` ${colors.inputPrompt('/prompts')} ${colors.dim('List prompt templates')}\n` +
|
|
359
|
-
` ${colors.inputPrompt('/skills')} ${colors.dim('List active skills')}\n` +
|
|
360
|
-
` ${colors.inputPrompt('/init')} ${colors.dim('Create .lonny/skills/ & prompts/')}\n` +
|
|
361
|
-
` ${colors.inputPrompt('/stop')} ${colors.dim('Stop the running agent')}\n` +
|
|
362
|
-
` ${colors.inputPrompt('/exit')} ${colors.dim('Exit')}\n` +
|
|
363
|
-
` ${colors.inputPrompt('/help')} ${colors.dim('This help')}\n\n` +
|
|
364
|
-
` ${colors.dim('Keyboard:')}\n` +
|
|
365
|
-
` ${colors.dim('Enter')} ${colors.dim('Send message')}\n` +
|
|
366
|
-
` ${colors.dim('↑/↓')} ${colors.dim('Navigate history')}\n` +
|
|
367
|
-
` ${colors.dim('Tab')} ${colors.dim('Autocomplete')}\n` +
|
|
368
|
-
` ${colors.dim('?')} ${colors.dim('Toggle this help')}\n\n` +
|
|
369
|
-
colors.accent('\u2501').repeat(20);
|
|
370
|
-
const helpText = new Text(helpContent, 1, 0);
|
|
371
|
-
const helpBox = new Box(1, 1, colors.bgDark);
|
|
372
|
-
helpBox.addChild(helpText);
|
|
373
|
-
helpOverlayHandle = tui.showOverlay(helpBox, {
|
|
374
|
-
anchor: 'center',
|
|
375
|
-
width: 46,
|
|
376
|
-
maxHeight: 22,
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
// ── Update helpers ──────────────────────────────────────────────────────
|
|
380
|
-
function updateFooter() {
|
|
381
|
-
const plans = listPlans(config.cwd);
|
|
382
|
-
footer.setAgentStatus(isRunning ? 'running' : 'idle');
|
|
383
|
-
footer.setMode(session?.config.mode === 'plan' ? 'plan' : session?.config.mode === 'ask' ? 'ask' : 'code');
|
|
384
|
-
footer.setModel(config.model, config.provider);
|
|
385
|
-
const tokenStats = loadTokenUsage(config.cwd);
|
|
386
|
-
footer.setTokenUsage(tokenStats.totalInputTokens, tokenStats.totalOutputTokens, tokenStats.totalApiCalls);
|
|
387
|
-
tui.requestRender(true);
|
|
388
|
-
}
|
|
389
|
-
function refreshPlans() {
|
|
390
|
-
const plans = listPlans(config.cwd);
|
|
391
|
-
plansList.refresh(plansToItems(plans));
|
|
392
|
-
todoPanel.refresh();
|
|
393
|
-
updateFooter();
|
|
394
|
-
}
|
|
395
|
-
async function refreshBalance() {
|
|
396
|
-
try {
|
|
397
|
-
if (isDeepSeekOfficial(config.baseUrl) && config.apiKey) {
|
|
398
|
-
const balance = await fetchDeepSeekBalance(config.apiKey);
|
|
399
|
-
if (balance.isAvailable && balance.display) {
|
|
400
|
-
footer.setBalance(balance.display);
|
|
401
|
-
footer.setWebBalance(balance.webDisplay);
|
|
402
|
-
}
|
|
403
|
-
else {
|
|
404
|
-
footer.setBalance('');
|
|
405
|
-
footer.setWebBalance('');
|
|
406
|
-
}
|
|
407
|
-
tui.requestRender(true);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
catch {
|
|
411
|
-
// Silently ignore
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
// ── Input handling ──────────────────────────────────────────────────────
|
|
415
|
-
async function sendMessage(text) {
|
|
416
|
-
const trimmed = text.trim();
|
|
417
|
-
if (!trimmed)
|
|
418
|
-
return;
|
|
419
|
-
editor.setText('');
|
|
420
|
-
editor.addToHistory(trimmed);
|
|
421
|
-
// Allow slash commands even when agent is running (critical for /stop)
|
|
422
|
-
if (trimmed.startsWith('/')) {
|
|
423
|
-
const parts = trimmed.slice(1).split(/\s+/);
|
|
424
|
-
const cmd = parts[0];
|
|
425
|
-
const arg = parts.slice(1).join(' ');
|
|
426
|
-
if (cmd === 'exit' || cmd === 'quit') {
|
|
427
|
-
chatContent += `\n${colors.dim('Goodbye!')}\n`;
|
|
428
|
-
chatMarkdown.setText(chatContent);
|
|
429
|
-
tui.stop();
|
|
430
|
-
process.exit(0);
|
|
431
|
-
return;
|
|
432
|
-
}
|
|
433
|
-
if (cmd === 'new') {
|
|
434
|
-
// If the agent is running, stop the old session gracefully first.
|
|
435
|
-
// Without this, the pending chat() promise would continue consuming
|
|
436
|
-
// tokens and write stale output into the freshly cleared chat display.
|
|
437
|
-
if (isRunning) {
|
|
438
|
-
session.stop();
|
|
439
|
-
isRunning = false;
|
|
440
|
-
loader.setMessage('');
|
|
441
|
-
tui.setShowHardwareCursor(true);
|
|
442
|
-
}
|
|
443
|
-
Session.clearSavedSession(config.cwd);
|
|
444
|
-
resetTokenUsage(config.cwd);
|
|
445
|
-
resetGlobalEventBus();
|
|
446
|
-
session = new Session(config, output);
|
|
447
|
-
session.onPlanWritten = planCb;
|
|
448
|
-
chatContent = '';
|
|
449
|
-
chatMarkdown.setText('');
|
|
450
|
-
plansList.clearFilter();
|
|
451
|
-
editor.undoStack.clear();
|
|
452
|
-
editor.history = [];
|
|
453
|
-
editor.killRing.ring = [];
|
|
454
|
-
updateFooter();
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
if (cmd === 'mode') {
|
|
458
|
-
if (arg === 'code' || arg === 'plan' || arg === 'ask') {
|
|
459
|
-
await session.setMode(arg);
|
|
460
|
-
chatContent += `\n${colors.warn('\u21E8')} Switched to ${arg === 'ask' ? colors.success(arg) : colors.warn(arg)} mode\n`;
|
|
461
|
-
chatMarkdown.setText(chatContent);
|
|
462
|
-
updateFooter();
|
|
463
|
-
}
|
|
464
|
-
else {
|
|
465
|
-
chatContent += `\n${colors.error('\u2716')} Usage: ${colors.inputPrompt('/mode code|plan|ask')} (current: ${session.config.mode})\n`;
|
|
466
|
-
chatMarkdown.setText(chatContent);
|
|
467
|
-
}
|
|
468
|
-
return;
|
|
469
|
-
}
|
|
470
|
-
if (cmd === 'model') {
|
|
471
|
-
if (arg) {
|
|
472
|
-
session.config.model = arg;
|
|
473
|
-
// Rebuild system prompt with new model context
|
|
474
|
-
await session.setMode(session.config.mode); // triggers rebuild
|
|
475
|
-
chatContent += `\n${colors.warn('\u21E8')} Model switched to ${colors.warn(arg)}\n`;
|
|
476
|
-
chatMarkdown.setText(chatContent);
|
|
477
|
-
updateFooter();
|
|
478
|
-
}
|
|
479
|
-
else {
|
|
480
|
-
chatContent += `\n${colors.inputPrompt('Current model:')} ${colors.dim(session.config.model)}\n`;
|
|
481
|
-
chatMarkdown.setText(chatContent);
|
|
482
|
-
}
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
if (cmd === 'prompts') {
|
|
486
|
-
const templates = loadPromptTemplates(config.cwd);
|
|
487
|
-
if (templates.length === 0) {
|
|
488
|
-
chatContent += `\n${colors.warn('No prompt templates found.')} ${colors.dim('Create .md files in .lonny/prompts/')}\n`;
|
|
489
|
-
}
|
|
490
|
-
else {
|
|
491
|
-
chatContent += `\n${colors.accent('\u25B6')} ${colors.warn(`Prompt Templates (${templates.length})`)}\n`;
|
|
492
|
-
for (const t of templates) {
|
|
493
|
-
chatContent += ` ${colors.dim('\u2022')} ${colors.inputPrompt(t.name)}`;
|
|
494
|
-
if (t.description)
|
|
495
|
-
chatContent += ` ${colors.dim(`\u2014 ${t.description}`)}`;
|
|
496
|
-
chatContent += '\n';
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
chatMarkdown.setText(chatContent);
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
if (cmd === 'skills') {
|
|
503
|
-
const skills = loadSkills(config.cwd);
|
|
504
|
-
if (skills.length === 0) {
|
|
505
|
-
chatContent += `\n${colors.warn('No skills loaded.')} ${colors.dim('Create .md files in .lonny/skills/')}\n`;
|
|
506
|
-
}
|
|
507
|
-
else {
|
|
508
|
-
chatContent += `\n${colors.accent('\u25B6')} ${colors.warn(`Active Skills (${skills.length})`)}\n`;
|
|
509
|
-
for (const s of skills) {
|
|
510
|
-
chatContent += ` ${colors.dim('\u2022')} ${colors.inputPrompt(s.name)}`;
|
|
511
|
-
if (s.description)
|
|
512
|
-
chatContent += ` ${colors.dim(`\u2014 ${s.description}`)}`;
|
|
513
|
-
chatContent += '\n';
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
chatMarkdown.setText(chatContent);
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
if (cmd === 'plans') {
|
|
520
|
-
showPlansOverlay();
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
|
-
if (cmd === 'filter') {
|
|
524
|
-
plansList.setFilter(arg);
|
|
525
|
-
tui.requestRender(true);
|
|
526
|
-
return;
|
|
527
|
-
}
|
|
528
|
-
if (cmd === 'help' || cmd === '?') {
|
|
529
|
-
showHelpOverlay();
|
|
530
|
-
return;
|
|
531
|
-
}
|
|
532
|
-
if (cmd === 'init') {
|
|
533
|
-
ensureSkillsDir(config.cwd);
|
|
534
|
-
ensurePromptsDir(config.cwd);
|
|
535
|
-
chatContent += `\n${colors.success('\u2714')} Initialized .lonny/skills/ and .lonny/prompts/\n`;
|
|
536
|
-
chatMarkdown.setText(chatContent);
|
|
537
|
-
return;
|
|
538
|
-
}
|
|
539
|
-
if (cmd === 'stop') {
|
|
540
|
-
if (!isRunning) {
|
|
541
|
-
chatContent += `\n${colors.dim('Agent is not running.')}\n`;
|
|
542
|
-
chatMarkdown.setText(chatContent);
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
// Tell the session to stop gracefully
|
|
546
|
-
session.stop();
|
|
547
|
-
chatContent += `\n${colors.warn('\u23F9')} Stopping agent...\n`;
|
|
548
|
-
chatMarkdown.setText(chatContent);
|
|
549
|
-
isRunning = false;
|
|
550
|
-
loader.stop();
|
|
551
|
-
loader.setMessage('');
|
|
552
|
-
tui.setShowHardwareCursor(true);
|
|
553
|
-
updateFooter();
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
chatContent += `\n${colors.error('\u2716')} Unknown command: /${cmd}. ${colors.dim('Type /help for available commands.')}\n`;
|
|
557
|
-
chatMarkdown.setText(chatContent);
|
|
558
|
-
return;
|
|
559
|
-
}
|
|
560
|
-
// Block regular messages when agent is already running
|
|
561
|
-
if (isRunning)
|
|
562
|
-
return;
|
|
563
|
-
isRunning = true;
|
|
564
|
-
loader.setMessage('thinking...');
|
|
565
|
-
tui.setShowHardwareCursor(false);
|
|
566
|
-
updateFooter();
|
|
567
|
-
session
|
|
568
|
-
.chat(trimmed)
|
|
569
|
-
.then(() => {
|
|
570
|
-
isRunning = false;
|
|
571
|
-
loader.setMessage('');
|
|
572
|
-
refreshPlans();
|
|
573
|
-
tui.setShowHardwareCursor(true);
|
|
574
|
-
updateFooter();
|
|
575
|
-
refreshBalance();
|
|
576
|
-
})
|
|
577
|
-
.catch((err) => {
|
|
578
|
-
isRunning = false;
|
|
579
|
-
loader.setMessage('');
|
|
580
|
-
const errMsg = fmtErr(err);
|
|
581
|
-
chatContent += `\n${colors.error('\u2716 Error:')} ${errMsg}\n`;
|
|
582
|
-
chatMarkdown.setText(chatContent);
|
|
583
|
-
tui.setShowHardwareCursor(true);
|
|
584
|
-
updateFooter();
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
// Wire up submit on editor (after landing transition)
|
|
194
|
+
ctx.plansList = plansList;
|
|
195
|
+
// ── Wire up submit on editor ─────────────────────────────────────────-
|
|
588
196
|
editor.onSubmit = (value) => {
|
|
589
|
-
sendMessage(value);
|
|
197
|
+
sendMessage(ctx, value);
|
|
590
198
|
};
|
|
591
|
-
// ── Landing screen transition
|
|
592
|
-
// When the user presses any key on the landing screen, transition to the
|
|
593
|
-
// full chat layout (editor + chat area).
|
|
199
|
+
// ── Landing screen transition ──────────────────────────────────────────
|
|
594
200
|
landingScreen.onSubmit = () => {
|
|
595
|
-
if (isRunning)
|
|
201
|
+
if (ctx.isRunning)
|
|
596
202
|
return;
|
|
597
|
-
// Hide the landing overlay
|
|
598
203
|
if (landingOverlayHandle)
|
|
599
204
|
landingOverlayHandle.hide();
|
|
600
205
|
footer.setPhase('chat');
|
|
601
|
-
// Add chat components to the main TUI
|
|
602
|
-
// (footer is already an overlay anchored to bottom-left, no need to addChild)
|
|
603
206
|
tui.addChild(chatBox);
|
|
604
207
|
tui.addChild(loader);
|
|
605
208
|
inputOverlayHandle = tui.showOverlay(editor, {
|
|
@@ -609,86 +212,77 @@ export async function startTui(config) {
|
|
|
609
212
|
maxHeight: 12,
|
|
610
213
|
nonCapturing: false,
|
|
611
214
|
});
|
|
612
|
-
showTodoPanel();
|
|
613
|
-
// Focus the chat editor
|
|
215
|
+
showTodoPanel(ctx);
|
|
614
216
|
tui.setFocus(editor);
|
|
615
217
|
tui.requestRender(true);
|
|
616
218
|
};
|
|
617
219
|
// ── Input listener ──────────────────────────────────────────────────────
|
|
618
220
|
tui.addInputListener(data => {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
return { consume: handleConfirmInput(data) };
|
|
221
|
+
if (ctx.pendingConfirmResolve) {
|
|
222
|
+
return { consume: handleConfirmInput(ctx, data) };
|
|
622
223
|
}
|
|
623
|
-
|
|
624
|
-
if (helpOverlayHandle?.isHidden() === false) {
|
|
224
|
+
if (ctx.helpOverlayHandle?.isHidden() === false) {
|
|
625
225
|
if (data === '\x1b' || data === '\x1b[' || data === '?') {
|
|
626
|
-
helpOverlayHandle.hide();
|
|
627
|
-
helpOverlayHandle = null;
|
|
226
|
+
ctx.helpOverlayHandle.hide();
|
|
227
|
+
ctx.helpOverlayHandle = null;
|
|
628
228
|
}
|
|
629
229
|
return { consume: true };
|
|
630
230
|
}
|
|
631
|
-
|
|
632
|
-
if (plansOverlayHandle?.isHidden() === false) {
|
|
231
|
+
if (ctx.plansOverlayHandle?.isHidden() === false) {
|
|
633
232
|
if (data === '\x1b' || data === '\x1b[') {
|
|
634
|
-
if (plansDetailMode) {
|
|
635
|
-
|
|
636
|
-
plansOverlayHandle
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
showPlansOverlay();
|
|
233
|
+
if (ctx.plansDetailMode) {
|
|
234
|
+
ctx.plansOverlayHandle.hide();
|
|
235
|
+
ctx.plansOverlayHandle = null;
|
|
236
|
+
ctx.plansDetailMode = false;
|
|
237
|
+
showPlansOverlay(ctx);
|
|
640
238
|
}
|
|
641
239
|
else {
|
|
642
|
-
plansOverlayHandle.hide();
|
|
643
|
-
plansOverlayHandle = null;
|
|
240
|
+
ctx.plansOverlayHandle.hide();
|
|
241
|
+
ctx.plansOverlayHandle = null;
|
|
644
242
|
}
|
|
645
243
|
return { consume: true };
|
|
646
244
|
}
|
|
647
|
-
if (data === '\r' && !plansDetailMode) {
|
|
648
|
-
|
|
649
|
-
showPlanDetail();
|
|
245
|
+
if (data === '\r' && !ctx.plansDetailMode) {
|
|
246
|
+
showPlanDetail(ctx);
|
|
650
247
|
return { consume: true };
|
|
651
248
|
}
|
|
652
249
|
if (data === '\x1b[A') {
|
|
653
250
|
const plans = listPlans(config.cwd);
|
|
654
251
|
if (plans.length > 0) {
|
|
655
|
-
const sel = plansList.getSelectedItem();
|
|
252
|
+
const sel = ctx.plansList.getSelectedItem();
|
|
656
253
|
const idx = sel ? plans.findIndex(p => p.name === sel.value) : -1;
|
|
657
254
|
const nextIdx = idx <= 0 ? plans.length - 1 : idx - 1;
|
|
658
|
-
plansList.setSelectedIndex(nextIdx);
|
|
659
|
-
updateFooter();
|
|
255
|
+
ctx.plansList.setSelectedIndex(nextIdx);
|
|
256
|
+
updateFooter(ctx);
|
|
660
257
|
}
|
|
661
258
|
return { consume: true };
|
|
662
259
|
}
|
|
663
260
|
if (data === '\x1b[B') {
|
|
664
261
|
const plans = listPlans(config.cwd);
|
|
665
262
|
if (plans.length > 0) {
|
|
666
|
-
const sel = plansList.getSelectedItem();
|
|
263
|
+
const sel = ctx.plansList.getSelectedItem();
|
|
667
264
|
const idx = sel ? plans.findIndex(p => p.name === sel.value) : -1;
|
|
668
265
|
const nextIdx = idx === -1 ? 0 : (idx + 1) % plans.length;
|
|
669
|
-
plansList.setSelectedIndex(nextIdx);
|
|
670
|
-
updateFooter();
|
|
266
|
+
ctx.plansList.setSelectedIndex(nextIdx);
|
|
267
|
+
updateFooter(ctx);
|
|
671
268
|
}
|
|
672
269
|
return { consume: true };
|
|
673
270
|
}
|
|
674
271
|
return { consume: true };
|
|
675
272
|
}
|
|
676
273
|
if (data === '?') {
|
|
677
|
-
showHelpOverlay();
|
|
274
|
+
showHelpOverlay(ctx);
|
|
678
275
|
return { consume: true };
|
|
679
276
|
}
|
|
680
277
|
return undefined;
|
|
681
278
|
});
|
|
682
279
|
// ── Initial render ────────────────────────────────────────────────────
|
|
683
280
|
loader.setMessage('');
|
|
684
|
-
refreshPlans();
|
|
685
|
-
// If no session was restored, keep the landing screen and clear chat.
|
|
686
|
-
// If a session was restored, chatContent already has the resume message.
|
|
281
|
+
refreshPlans(ctx);
|
|
687
282
|
if (!restored) {
|
|
688
|
-
chatMarkdown.setText('');
|
|
283
|
+
ctx.chatMarkdown.setText('');
|
|
689
284
|
}
|
|
690
285
|
tui.start();
|
|
691
|
-
// Keep alive
|
|
692
286
|
await new Promise(() => { });
|
|
693
287
|
}
|
|
694
288
|
//# sourceMappingURL=index.js.map
|