@travisennis/acai 0.0.1
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/.acai/acai.json +9 -0
- package/.acai/prompts/add-openrouter-model.md +13 -0
- package/.acai/prompts/project-status.md +4 -0
- package/.acai/prompts/update-architecture-document.md +9 -0
- package/.acai/rules/learned-rules.md +9 -0
- package/.ai/docs/available-tools.txt +3 -0
- package/.ai/docs/cognitive_complexity_refactoring_progress.md +65 -0
- package/.ai/docs/deleted_tools.md +168 -0
- package/.ai/docs/deleted_tools_88ced9ef.md +56 -0
- package/.ai/docs/image-pasting.md +46 -0
- package/.ai/docs/initialize-app.md +117 -0
- package/.ai/docs/issue-4-plan.md +44 -0
- package/.ai/docs/marked-renderer-debug.md +15 -0
- package/.ai/docs/marked-renderer-refactor-plan.md +64 -0
- package/.ai/docs/memory-use-cases.md +55 -0
- package/.ai/docs/prompt-consistency.md +31 -0
- package/.ai/docs/refactoring-tools.md +98 -0
- package/.ai/docs/system-prompt-update.md +174 -0
- package/.ai/docs/system_prompt.txt +210 -0
- package/.ai/docs/tasks.md +49 -0
- package/.ai/plan.md +131 -0
- package/.ai/prompt.md +1 -0
- package/.ai/scripts/fetch_models.js +27 -0
- package/.ai/scripts/generateSystemPrompt.ts +15 -0
- package/.ai/scripts/list-tools.mjs +4 -0
- package/.ai/scripts/p5_geometric_shapes.js +149 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +3 -0
- package/.husky/pre-push +1 -0
- package/.ignore +4 -0
- package/AGENTS.md +25 -0
- package/ARCHITECTURE.md +304 -0
- package/LICENSE +21 -0
- package/README.md +392 -0
- package/TODO.md +2 -0
- package/biome.json +61 -0
- package/commitlint.config.js +3 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.js +116 -0
- package/dist/commands/application-log-command.d.ts +2 -0
- package/dist/commands/application-log-command.js +43 -0
- package/dist/commands/clear-command.d.ts +2 -0
- package/dist/commands/clear-command.js +12 -0
- package/dist/commands/compact-command.d.ts +2 -0
- package/dist/commands/compact-command.js +51 -0
- package/dist/commands/copy-command.d.ts +2 -0
- package/dist/commands/copy-command.js +51 -0
- package/dist/commands/edit-command.d.ts +2 -0
- package/dist/commands/edit-command.js +53 -0
- package/dist/commands/edit-prompt-command.d.ts +2 -0
- package/dist/commands/edit-prompt-command.js +25 -0
- package/dist/commands/exit-command.d.ts +2 -0
- package/dist/commands/exit-command.js +14 -0
- package/dist/commands/files-command.d.ts +2 -0
- package/dist/commands/files-command.js +63 -0
- package/dist/commands/generate-rules-command.d.ts +2 -0
- package/dist/commands/generate-rules-command.js +61 -0
- package/dist/commands/help-command.d.ts +2 -0
- package/dist/commands/help-command.js +19 -0
- package/dist/commands/init-command.d.ts +2 -0
- package/dist/commands/init-command.js +40 -0
- package/dist/commands/last-log-command.d.ts +2 -0
- package/dist/commands/last-log-command.js +76 -0
- package/dist/commands/manager.d.ts +22 -0
- package/dist/commands/manager.js +123 -0
- package/dist/commands/model-command.d.ts +2 -0
- package/dist/commands/model-command.js +84 -0
- package/dist/commands/paste-command.d.ts +2 -0
- package/dist/commands/paste-command.js +40 -0
- package/dist/commands/prompt-command.d.ts +2 -0
- package/dist/commands/prompt-command.js +111 -0
- package/dist/commands/reset-command.d.ts +2 -0
- package/dist/commands/reset-command.js +16 -0
- package/dist/commands/rules-command.d.ts +2 -0
- package/dist/commands/rules-command.js +68 -0
- package/dist/commands/save-command.d.ts +2 -0
- package/dist/commands/save-command.js +14 -0
- package/dist/commands/types.d.ts +26 -0
- package/dist/commands/types.js +1 -0
- package/dist/commands/usage-command.d.ts +2 -0
- package/dist/commands/usage-command.js +21 -0
- package/dist/config.d.ts +60 -0
- package/dist/config.js +193 -0
- package/dist/conversation-analyzer.d.ts +10 -0
- package/dist/conversation-analyzer.js +88 -0
- package/dist/dedent.d.ts +3 -0
- package/dist/dedent.js +38 -0
- package/dist/formatting.d.ts +17 -0
- package/dist/formatting.js +103 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +213 -0
- package/dist/logger.d.ts +2 -0
- package/dist/logger.js +24 -0
- package/dist/mentions.d.ts +9 -0
- package/dist/mentions.js +182 -0
- package/dist/messages.d.ts +69 -0
- package/dist/messages.js +261 -0
- package/dist/middleware/audit-message.d.ts +5 -0
- package/dist/middleware/audit-message.js +95 -0
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.js +2 -0
- package/dist/middleware/rate-limit.d.ts +4 -0
- package/dist/middleware/rate-limit.js +17 -0
- package/dist/models/ai-config.d.ts +12 -0
- package/dist/models/ai-config.js +87 -0
- package/dist/models/anthropic-provider.d.ts +25 -0
- package/dist/models/anthropic-provider.js +184 -0
- package/dist/models/deepseek-provider.d.ts +20 -0
- package/dist/models/deepseek-provider.js +42 -0
- package/dist/models/google-provider.d.ts +19 -0
- package/dist/models/google-provider.js +56 -0
- package/dist/models/manager.d.ts +15 -0
- package/dist/models/manager.js +48 -0
- package/dist/models/openai-provider.d.ts +22 -0
- package/dist/models/openai-provider.js +70 -0
- package/dist/models/openrouter-provider.d.ts +36 -0
- package/dist/models/openrouter-provider.js +276 -0
- package/dist/models/providers.d.ts +33 -0
- package/dist/models/providers.js +116 -0
- package/dist/models/xai-provider.d.ts +20 -0
- package/dist/models/xai-provider.js +47 -0
- package/dist/parsing.d.ts +2 -0
- package/dist/parsing.js +18 -0
- package/dist/prompts/manager.d.ts +19 -0
- package/dist/prompts/manager.js +71 -0
- package/dist/prompts.d.ts +4 -0
- package/dist/prompts.js +158 -0
- package/dist/repl-prompt.d.ts +14 -0
- package/dist/repl-prompt.js +147 -0
- package/dist/repl.d.ts +27 -0
- package/dist/repl.js +431 -0
- package/dist/source/cli.d.ts +19 -0
- package/dist/source/cli.js +116 -0
- package/dist/source/commands/application-log-command.d.ts +2 -0
- package/dist/source/commands/application-log-command.js +43 -0
- package/dist/source/commands/clear-command.d.ts +2 -0
- package/dist/source/commands/clear-command.js +12 -0
- package/dist/source/commands/compact-command.d.ts +2 -0
- package/dist/source/commands/compact-command.js +51 -0
- package/dist/source/commands/copy-command.d.ts +2 -0
- package/dist/source/commands/copy-command.js +51 -0
- package/dist/source/commands/edit-command.d.ts +2 -0
- package/dist/source/commands/edit-command.js +53 -0
- package/dist/source/commands/edit-prompt-command.d.ts +2 -0
- package/dist/source/commands/edit-prompt-command.js +25 -0
- package/dist/source/commands/exit-command.d.ts +2 -0
- package/dist/source/commands/exit-command.js +14 -0
- package/dist/source/commands/files-command.d.ts +2 -0
- package/dist/source/commands/files-command.js +63 -0
- package/dist/source/commands/generate-rules-command.d.ts +2 -0
- package/dist/source/commands/generate-rules-command.js +61 -0
- package/dist/source/commands/help-command.d.ts +2 -0
- package/dist/source/commands/help-command.js +19 -0
- package/dist/source/commands/init-command.d.ts +2 -0
- package/dist/source/commands/init-command.js +40 -0
- package/dist/source/commands/last-log-command.d.ts +2 -0
- package/dist/source/commands/last-log-command.js +76 -0
- package/dist/source/commands/manager.d.ts +22 -0
- package/dist/source/commands/manager.js +123 -0
- package/dist/source/commands/model-command.d.ts +2 -0
- package/dist/source/commands/model-command.js +84 -0
- package/dist/source/commands/paste-command.d.ts +2 -0
- package/dist/source/commands/paste-command.js +40 -0
- package/dist/source/commands/prompt-command.d.ts +2 -0
- package/dist/source/commands/prompt-command.js +111 -0
- package/dist/source/commands/reset-command.d.ts +2 -0
- package/dist/source/commands/reset-command.js +16 -0
- package/dist/source/commands/rules-command.d.ts +2 -0
- package/dist/source/commands/rules-command.js +68 -0
- package/dist/source/commands/save-command.d.ts +2 -0
- package/dist/source/commands/save-command.js +14 -0
- package/dist/source/commands/types.d.ts +26 -0
- package/dist/source/commands/types.js +1 -0
- package/dist/source/commands/usage-command.d.ts +2 -0
- package/dist/source/commands/usage-command.js +21 -0
- package/dist/source/config.d.ts +60 -0
- package/dist/source/config.js +193 -0
- package/dist/source/conversation-analyzer.d.ts +10 -0
- package/dist/source/conversation-analyzer.js +88 -0
- package/dist/source/dedent.d.ts +3 -0
- package/dist/source/dedent.js +38 -0
- package/dist/source/formatting.d.ts +17 -0
- package/dist/source/formatting.js +103 -0
- package/dist/source/index.d.ts +18 -0
- package/dist/source/index.js +213 -0
- package/dist/source/logger.d.ts +2 -0
- package/dist/source/logger.js +24 -0
- package/dist/source/mentions.d.ts +9 -0
- package/dist/source/mentions.js +182 -0
- package/dist/source/messages.d.ts +69 -0
- package/dist/source/messages.js +261 -0
- package/dist/source/middleware/audit-message.d.ts +5 -0
- package/dist/source/middleware/audit-message.js +95 -0
- package/dist/source/middleware/index.d.ts +2 -0
- package/dist/source/middleware/index.js +2 -0
- package/dist/source/middleware/rate-limit.d.ts +4 -0
- package/dist/source/middleware/rate-limit.js +17 -0
- package/dist/source/models/ai-config.d.ts +12 -0
- package/dist/source/models/ai-config.js +87 -0
- package/dist/source/models/anthropic-provider.d.ts +25 -0
- package/dist/source/models/anthropic-provider.js +184 -0
- package/dist/source/models/deepseek-provider.d.ts +20 -0
- package/dist/source/models/deepseek-provider.js +42 -0
- package/dist/source/models/google-provider.d.ts +19 -0
- package/dist/source/models/google-provider.js +56 -0
- package/dist/source/models/manager.d.ts +15 -0
- package/dist/source/models/manager.js +48 -0
- package/dist/source/models/openai-provider.d.ts +22 -0
- package/dist/source/models/openai-provider.js +70 -0
- package/dist/source/models/openrouter-provider.d.ts +36 -0
- package/dist/source/models/openrouter-provider.js +276 -0
- package/dist/source/models/providers.d.ts +33 -0
- package/dist/source/models/providers.js +116 -0
- package/dist/source/models/xai-provider.d.ts +20 -0
- package/dist/source/models/xai-provider.js +47 -0
- package/dist/source/parsing.d.ts +2 -0
- package/dist/source/parsing.js +18 -0
- package/dist/source/prompts/manager.d.ts +19 -0
- package/dist/source/prompts/manager.js +71 -0
- package/dist/source/prompts.d.ts +4 -0
- package/dist/source/prompts.js +158 -0
- package/dist/source/repl-prompt.d.ts +14 -0
- package/dist/source/repl-prompt.js +147 -0
- package/dist/source/repl.d.ts +27 -0
- package/dist/source/repl.js +431 -0
- package/dist/source/terminal/formatting.d.ts +37 -0
- package/dist/source/terminal/formatting.js +106 -0
- package/dist/source/terminal/index.d.ts +94 -0
- package/dist/source/terminal/index.js +420 -0
- package/dist/source/terminal/markdown-utils.d.ts +2 -0
- package/dist/source/terminal/markdown-utils.js +81 -0
- package/dist/source/terminal/markdown.d.ts +1 -0
- package/dist/source/terminal/markdown.js +111 -0
- package/dist/source/terminal/types.d.ts +71 -0
- package/dist/source/terminal/types.js +1 -0
- package/dist/source/terminal-output.d.ts +8 -0
- package/dist/source/terminal-output.js +213 -0
- package/dist/source/terminal-output.test.d.ts +8 -0
- package/dist/source/terminal-output.test.js +213 -0
- package/dist/source/token-tracker.d.ts +14 -0
- package/dist/source/token-tracker.js +53 -0
- package/dist/source/token-utils.d.ts +7 -0
- package/dist/source/token-utils.js +13 -0
- package/dist/source/tools/agent.d.ts +17 -0
- package/dist/source/tools/agent.js +87 -0
- package/dist/source/tools/bash.d.ts +19 -0
- package/dist/source/tools/bash.js +294 -0
- package/dist/source/tools/code-interpreter.d.ts +12 -0
- package/dist/source/tools/code-interpreter.js +131 -0
- package/dist/source/tools/command-validation.d.ts +8 -0
- package/dist/source/tools/command-validation.js +69 -0
- package/dist/source/tools/delete-file.d.ts +12 -0
- package/dist/source/tools/delete-file.js +56 -0
- package/dist/source/tools/directory-tree.d.ts +12 -0
- package/dist/source/tools/directory-tree.js +38 -0
- package/dist/source/tools/edit-file.d.ts +19 -0
- package/dist/source/tools/edit-file.js +107 -0
- package/dist/source/tools/filesystem-utils.d.ts +22 -0
- package/dist/source/tools/filesystem-utils.js +191 -0
- package/dist/source/tools/git-utils.d.ts +14 -0
- package/dist/source/tools/git-utils.js +64 -0
- package/dist/source/tools/grep.d.ts +17 -0
- package/dist/source/tools/grep.js +138 -0
- package/dist/source/tools/index.d.ts +161 -0
- package/dist/source/tools/index.js +209 -0
- package/dist/source/tools/memory-read.d.ts +13 -0
- package/dist/source/tools/memory-read.js +135 -0
- package/dist/source/tools/memory-write.d.ts +12 -0
- package/dist/source/tools/memory-write.js +83 -0
- package/dist/source/tools/move-file.d.ts +13 -0
- package/dist/source/tools/move-file.js +44 -0
- package/dist/source/tools/read-file.d.ts +17 -0
- package/dist/source/tools/read-file.js +86 -0
- package/dist/source/tools/read-multiple-files.d.ts +14 -0
- package/dist/source/tools/read-multiple-files.js +55 -0
- package/dist/source/tools/save-file.d.ts +17 -0
- package/dist/source/tools/save-file.js +98 -0
- package/dist/source/tools/think.d.ts +11 -0
- package/dist/source/tools/think.js +45 -0
- package/dist/source/tools/types.d.ts +29 -0
- package/dist/source/tools/types.js +14 -0
- package/dist/source/tools/web-fetch.d.ts +47 -0
- package/dist/source/tools/web-fetch.js +246 -0
- package/dist/source/tools/web-search.d.ts +13 -0
- package/dist/source/tools/web-search.js +80 -0
- package/dist/source/utils/process.d.ts +36 -0
- package/dist/source/utils/process.js +75 -0
- package/dist/source/version.d.ts +1 -0
- package/dist/source/version.js +21 -0
- package/dist/terminal/formatting.d.ts +37 -0
- package/dist/terminal/formatting.js +106 -0
- package/dist/terminal/index.d.ts +94 -0
- package/dist/terminal/index.js +420 -0
- package/dist/terminal/markdown-utils.d.ts +2 -0
- package/dist/terminal/markdown-utils.js +81 -0
- package/dist/terminal/markdown.d.ts +1 -0
- package/dist/terminal/markdown.js +111 -0
- package/dist/terminal/types.d.ts +71 -0
- package/dist/terminal/types.js +1 -0
- package/dist/terminal-output.d.ts +8 -0
- package/dist/terminal-output.js +213 -0
- package/dist/token-tracker.d.ts +14 -0
- package/dist/token-tracker.js +53 -0
- package/dist/token-utils.d.ts +7 -0
- package/dist/token-utils.js +13 -0
- package/dist/tools/agent.d.ts +17 -0
- package/dist/tools/agent.js +87 -0
- package/dist/tools/bash.d.ts +19 -0
- package/dist/tools/bash.js +294 -0
- package/dist/tools/code-interpreter.d.ts +12 -0
- package/dist/tools/code-interpreter.js +131 -0
- package/dist/tools/command-validation.d.ts +8 -0
- package/dist/tools/command-validation.js +69 -0
- package/dist/tools/delete-file.d.ts +12 -0
- package/dist/tools/delete-file.js +56 -0
- package/dist/tools/directory-tree.d.ts +12 -0
- package/dist/tools/directory-tree.js +38 -0
- package/dist/tools/edit-file.d.ts +19 -0
- package/dist/tools/edit-file.js +107 -0
- package/dist/tools/filesystem-utils.d.ts +22 -0
- package/dist/tools/filesystem-utils.js +191 -0
- package/dist/tools/git-utils.d.ts +14 -0
- package/dist/tools/git-utils.js +64 -0
- package/dist/tools/grep.d.ts +17 -0
- package/dist/tools/grep.js +138 -0
- package/dist/tools/index.d.ts +161 -0
- package/dist/tools/index.js +209 -0
- package/dist/tools/memory-read.d.ts +13 -0
- package/dist/tools/memory-read.js +135 -0
- package/dist/tools/memory-write.d.ts +12 -0
- package/dist/tools/memory-write.js +83 -0
- package/dist/tools/move-file.d.ts +13 -0
- package/dist/tools/move-file.js +44 -0
- package/dist/tools/read-file.d.ts +17 -0
- package/dist/tools/read-file.js +86 -0
- package/dist/tools/read-multiple-files.d.ts +14 -0
- package/dist/tools/read-multiple-files.js +55 -0
- package/dist/tools/save-file.d.ts +17 -0
- package/dist/tools/save-file.js +98 -0
- package/dist/tools/think.d.ts +11 -0
- package/dist/tools/think.js +45 -0
- package/dist/tools/types.d.ts +29 -0
- package/dist/tools/types.js +14 -0
- package/dist/tools/web-fetch.d.ts +47 -0
- package/dist/tools/web-fetch.js +246 -0
- package/dist/tools/web-search.d.ts +13 -0
- package/dist/tools/web-search.js +80 -0
- package/dist/utils/process.d.ts +36 -0
- package/dist/utils/process.js +75 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +21 -0
- package/knip.json +5 -0
- package/package.json +83 -0
- package/source/cli.ts +172 -0
- package/source/commands/application-log-command.ts +53 -0
- package/source/commands/clear-command.ts +14 -0
- package/source/commands/compact-command.ts +64 -0
- package/source/commands/copy-command.ts +55 -0
- package/source/commands/edit-command.ts +63 -0
- package/source/commands/edit-prompt-command.ts +31 -0
- package/source/commands/exit-command.ts +18 -0
- package/source/commands/files-command.ts +85 -0
- package/source/commands/generate-rules-command.ts +82 -0
- package/source/commands/help-command.ts +27 -0
- package/source/commands/init-command.ts +48 -0
- package/source/commands/last-log-command.ts +88 -0
- package/source/commands/manager.ts +151 -0
- package/source/commands/model-command.ts +123 -0
- package/source/commands/paste-command.ts +62 -0
- package/source/commands/prompt-command.ts +150 -0
- package/source/commands/reset-command.ts +22 -0
- package/source/commands/rules-command.ts +76 -0
- package/source/commands/save-command.ts +20 -0
- package/source/commands/types.ts +28 -0
- package/source/commands/usage-command.ts +26 -0
- package/source/config.ts +223 -0
- package/source/conversation-analyzer.ts +115 -0
- package/source/dedent.ts +53 -0
- package/source/formatting.ts +132 -0
- package/source/index.ts +240 -0
- package/source/logger.ts +29 -0
- package/source/mentions.ts +227 -0
- package/source/messages.ts +360 -0
- package/source/middleware/audit-message.ts +133 -0
- package/source/middleware/index.ts +2 -0
- package/source/middleware/rate-limit.ts +24 -0
- package/source/models/ai-config.ts +109 -0
- package/source/models/anthropic-provider.ts +199 -0
- package/source/models/deepseek-provider.ts +53 -0
- package/source/models/google-provider.ts +68 -0
- package/source/models/manager.ts +84 -0
- package/source/models/openai-provider.ts +81 -0
- package/source/models/openrouter-provider.ts +288 -0
- package/source/models/providers.ts +197 -0
- package/source/models/xai-provider.ts +59 -0
- package/source/parsing.ts +20 -0
- package/source/prompts/manager.ts +90 -0
- package/source/prompts.ts +172 -0
- package/source/repl-prompt.ts +196 -0
- package/source/repl.ts +572 -0
- package/source/terminal/formatting.ts +121 -0
- package/source/terminal/index.ts +518 -0
- package/source/terminal/markdown-utils.ts +89 -0
- package/source/terminal/markdown.ts +155 -0
- package/source/terminal/types.ts +84 -0
- package/source/terminal-output.test.ts +266 -0
- package/source/token-tracker.ts +78 -0
- package/source/token-utils.ts +17 -0
- package/source/tools/agent.ts +107 -0
- package/source/tools/bash.ts +367 -0
- package/source/tools/code-interpreter.ts +172 -0
- package/source/tools/command-validation.ts +81 -0
- package/source/tools/delete-file.ts +71 -0
- package/source/tools/directory-tree.ts +54 -0
- package/source/tools/edit-file.ts +155 -0
- package/source/tools/filesystem-utils.ts +265 -0
- package/source/tools/git-utils.ts +70 -0
- package/source/tools/grep.ts +184 -0
- package/source/tools/index.ts +278 -0
- package/source/tools/memory-read.ts +174 -0
- package/source/tools/memory-write.ts +105 -0
- package/source/tools/move-file.ts +59 -0
- package/source/tools/read-file.ts +129 -0
- package/source/tools/read-multiple-files.ts +80 -0
- package/source/tools/save-file.ts +147 -0
- package/source/tools/think.ts +51 -0
- package/source/tools/types.ts +58 -0
- package/source/tools/web-fetch.ts +327 -0
- package/source/tools/web-search.ts +101 -0
- package/source/utils/process.ts +121 -0
- package/source/version.ts +21 -0
- package/test/commands/copy-command.test.ts +69 -0
- package/test/config.test.ts +200 -0
- package/test/terminal/markdown-utils.test.ts +124 -0
- package/test/tools/bash-tool.test.ts +58 -0
- package/test/tools/code-interpreter.test.ts +91 -0
- package/test/tools/command-validation.test.ts +48 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Interface Module
|
|
3
|
+
*
|
|
4
|
+
* Provides a user interface for interacting with Claude Code in the terminal.
|
|
5
|
+
* Handles input/output, formatting, and display.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import Table from "cli-table3";
|
|
9
|
+
import ora from "ora";
|
|
10
|
+
import wrapAnsi from "wrap-ansi";
|
|
11
|
+
import { logger } from "../logger.js";
|
|
12
|
+
import { getPackageVersion } from "../version.js";
|
|
13
|
+
import { clearTerminal, getTerminalSize, setTerminalTitle, link as terminalLink, } from "./formatting.js";
|
|
14
|
+
import { applyMarkdown } from "./markdown.js";
|
|
15
|
+
/**
|
|
16
|
+
* Initialize the terminal interface
|
|
17
|
+
*/
|
|
18
|
+
export function initTerminal(config = {}) {
|
|
19
|
+
logger.debug("Initializing terminal interface");
|
|
20
|
+
const terminalConfig = {
|
|
21
|
+
theme: config.theme || "system",
|
|
22
|
+
useColors: config.useColors !== false,
|
|
23
|
+
showProgressIndicators: config.showProgressIndicators !== false,
|
|
24
|
+
codeHighlighting: config.codeHighlighting !== false,
|
|
25
|
+
maxHeight: config.maxHeight,
|
|
26
|
+
maxWidth: config.maxWidth,
|
|
27
|
+
};
|
|
28
|
+
const terminal = new Terminal(terminalConfig);
|
|
29
|
+
try {
|
|
30
|
+
// Detect terminal capabilities
|
|
31
|
+
terminal.detectCapabilities();
|
|
32
|
+
return terminal;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
logger.warn(error, "Error initializing terminal interface:");
|
|
36
|
+
// Return a basic terminal interface even if there was an error
|
|
37
|
+
return terminal;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Terminal class for handling user interaction
|
|
42
|
+
*/
|
|
43
|
+
export class Terminal {
|
|
44
|
+
config;
|
|
45
|
+
activeSpinners = new Map();
|
|
46
|
+
terminalWidth;
|
|
47
|
+
terminalHeight;
|
|
48
|
+
isInteractive;
|
|
49
|
+
constructor(config) {
|
|
50
|
+
this.config = config;
|
|
51
|
+
// Get initial terminal size
|
|
52
|
+
const { rows, columns } = getTerminalSize();
|
|
53
|
+
this.terminalHeight = config.maxHeight || rows;
|
|
54
|
+
this.terminalWidth = config.maxWidth || columns;
|
|
55
|
+
// Assume interactive by default
|
|
56
|
+
this.isInteractive = process.stdout.isTTY && process.stdin.isTTY;
|
|
57
|
+
// Listen for terminal resize events
|
|
58
|
+
process.stdout.on("resize", () => {
|
|
59
|
+
const { rows, columns } = getTerminalSize();
|
|
60
|
+
this.terminalHeight = config.maxHeight || rows;
|
|
61
|
+
this.terminalWidth = config.maxWidth || columns;
|
|
62
|
+
logger.debug(`Terminal resized to ${columns}x${rows}`);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Detect terminal capabilities
|
|
67
|
+
*/
|
|
68
|
+
detectCapabilities() {
|
|
69
|
+
// Check if the terminal is interactive
|
|
70
|
+
this.isInteractive = Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
71
|
+
logger.debug({
|
|
72
|
+
isInteractive: this.isInteractive,
|
|
73
|
+
colorSupport: this.config.useColors ? "yes" : "no",
|
|
74
|
+
size: `${this.terminalWidth}x${this.terminalHeight}`,
|
|
75
|
+
}, "Terminal capabilities detected");
|
|
76
|
+
}
|
|
77
|
+
setTitle(title) {
|
|
78
|
+
setTerminalTitle(title);
|
|
79
|
+
}
|
|
80
|
+
getLogo() {
|
|
81
|
+
return `
|
|
82
|
+
█████╗ ██████╗ █████╗ ██╗
|
|
83
|
+
██╔══██╗██╔════╝██╔══██╗██║
|
|
84
|
+
███████║██║ ███████║██║
|
|
85
|
+
██╔══██║██║ ██╔══██║██║
|
|
86
|
+
██║ ██║╚██████╗██║ ██║██║
|
|
87
|
+
╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝
|
|
88
|
+
`;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Display the welcome message
|
|
92
|
+
*/
|
|
93
|
+
displayWelcome() {
|
|
94
|
+
this.clear();
|
|
95
|
+
const version = getPackageVersion();
|
|
96
|
+
this.writeln(chalk.magenta(this.getLogo()));
|
|
97
|
+
this.lineBreak();
|
|
98
|
+
this.writeln(chalk.magenta("Greetings! I am acai."));
|
|
99
|
+
this.writeln(chalk.gray(` Version ${version}`));
|
|
100
|
+
this.lineBreak();
|
|
101
|
+
this.writeln(chalk.white(` Type ${chalk.cyan("/help")} to see available commands.`));
|
|
102
|
+
this.writeln(chalk.white(" You can ask acai to explain code, fix issues, or perform tasks."));
|
|
103
|
+
this.writeln(chalk.white(` Example: "${chalk.italic("Please analyze this codebase and explain its structure.")}"`));
|
|
104
|
+
this.writeln(chalk.dim(" Use Ctrl+C to interrupt acai and exit."));
|
|
105
|
+
this.lineBreak();
|
|
106
|
+
this.writeln(chalk.yellow(`The current working directory is ${process.cwd()}`));
|
|
107
|
+
this.lineBreak();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Clear the terminal screen
|
|
111
|
+
*/
|
|
112
|
+
clear() {
|
|
113
|
+
if (this.isInteractive) {
|
|
114
|
+
clearTerminal();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Display formatted content
|
|
119
|
+
*/
|
|
120
|
+
display(content, wrap = false) {
|
|
121
|
+
this.writeln(this.formatMarkdown(content, wrap));
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Display a message with emphasis
|
|
125
|
+
*/
|
|
126
|
+
emphasize(message) {
|
|
127
|
+
if (this.config.useColors) {
|
|
128
|
+
this.writeln(chalk.cyan.bold(message));
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
this.writeln(message.toUpperCase());
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Display an informational message
|
|
136
|
+
*/
|
|
137
|
+
info(message) {
|
|
138
|
+
if (this.config.useColors) {
|
|
139
|
+
this.writeln(chalk.blue(`ℹ ${message}`));
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
this.writeln(`INFO: ${message}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Display a success message
|
|
147
|
+
*/
|
|
148
|
+
success(message) {
|
|
149
|
+
if (this.config.useColors) {
|
|
150
|
+
this.writeln(chalk.green(`✓ ${message}`));
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.writeln(`SUCCESS: ${message}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Display a warning message
|
|
158
|
+
*/
|
|
159
|
+
warn(message) {
|
|
160
|
+
if (this.config.useColors) {
|
|
161
|
+
this.writeln(chalk.yellow(`⚠ ${message}`));
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
this.writeln(`WARNING: ${message}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Display an error message
|
|
169
|
+
*/
|
|
170
|
+
error(message) {
|
|
171
|
+
if (this.config.useColors) {
|
|
172
|
+
this.writeln(chalk.red(`✗ ${message}`));
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
this.writeln(`ERROR: ${message}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Emits an alert.
|
|
180
|
+
*/
|
|
181
|
+
alert() {
|
|
182
|
+
if (!this.isInteractive) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const t = "acai";
|
|
186
|
+
const b = "";
|
|
187
|
+
try {
|
|
188
|
+
process.stdout.write("\x07");
|
|
189
|
+
const esc = "\u001b";
|
|
190
|
+
const bel = "\u0007";
|
|
191
|
+
const safe = (s) => s.replaceAll("\u0007", "").replaceAll("\u001b", "");
|
|
192
|
+
const payload = `${esc}]777;notify;${safe(t)};${safe(b)}${bel}`;
|
|
193
|
+
process.stdout.write(payload);
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
logger.warn({ err }, "Failed to emit alert");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
write(input) {
|
|
200
|
+
process.stdout.write(input);
|
|
201
|
+
}
|
|
202
|
+
writeln(input) {
|
|
203
|
+
process.stdout.write(`${input}\n`);
|
|
204
|
+
}
|
|
205
|
+
lineBreak() {
|
|
206
|
+
this.writeln("");
|
|
207
|
+
}
|
|
208
|
+
header(header, chalkFn = chalk.green) {
|
|
209
|
+
const cols = this.terminalWidth > 0 ? this.terminalWidth : 80;
|
|
210
|
+
const width = Math.max(0, cols - header.length - 4);
|
|
211
|
+
this.writeln(chalkFn(`\n── ${header} ${"─".repeat(width)} `));
|
|
212
|
+
}
|
|
213
|
+
async box(header, content) {
|
|
214
|
+
const cols = this.terminalWidth > 0 ? this.terminalWidth : 80;
|
|
215
|
+
const width = Math.max(4, cols - 4);
|
|
216
|
+
// Helper to strip ANSI sequences for accurate visible-width calculation
|
|
217
|
+
const stripAnsi = (s) =>
|
|
218
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: need to detect ansi control characters
|
|
219
|
+
s.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "");
|
|
220
|
+
const paddedHeader = ` ${header} `;
|
|
221
|
+
const headerVisibleLen = stripAnsi(paddedHeader).length;
|
|
222
|
+
const headerStartPos = 1;
|
|
223
|
+
// Top border with header (use visible header length)
|
|
224
|
+
const leftDashes = headerStartPos;
|
|
225
|
+
const rightDashes = Math.max(0, width - leftDashes - headerVisibleLen);
|
|
226
|
+
const topBorder = `┌${"─".repeat(leftDashes)}${paddedHeader}${"─".repeat(rightDashes)}┐`;
|
|
227
|
+
// Prepare inner content: format markdown first, then wrap to inner width
|
|
228
|
+
const innerWidth = Math.max(1, width - 2);
|
|
229
|
+
const formatted = applyMarkdown(content);
|
|
230
|
+
const wrapped = wrapAnsi(formatted, innerWidth, { trim: false });
|
|
231
|
+
const contentLines = wrapped
|
|
232
|
+
.split("\n")
|
|
233
|
+
.map((line) => {
|
|
234
|
+
const visibleLen = stripAnsi(line).length;
|
|
235
|
+
const padCount = Math.max(0, innerWidth - visibleLen);
|
|
236
|
+
return `│ ${line}${" ".repeat(padCount)} │`;
|
|
237
|
+
})
|
|
238
|
+
.join("\n");
|
|
239
|
+
// Bottom border
|
|
240
|
+
const bottomBorder = `└${"─".repeat(width)}┘`;
|
|
241
|
+
// Write the box
|
|
242
|
+
this.writeln(`${topBorder}\n${contentLines}\n${bottomBorder}`);
|
|
243
|
+
}
|
|
244
|
+
hr(chalkFn = chalk.gray) {
|
|
245
|
+
const cols = this.terminalWidth > 0 ? this.terminalWidth : 80;
|
|
246
|
+
this.writeln(chalkFn(`${"─".repeat(Math.max(1, cols - 1))} `));
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Create a clickable link in the terminal if supported
|
|
250
|
+
*/
|
|
251
|
+
link(text, url) {
|
|
252
|
+
return terminalLink(text, url);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Display a table of data
|
|
256
|
+
*/
|
|
257
|
+
table(data, options = {}) {
|
|
258
|
+
const { header, colWidths } = options;
|
|
259
|
+
// Calculate column widths based on terminal width
|
|
260
|
+
const padding = 5; // Account for table borders and padding
|
|
261
|
+
const availableWidth = Math.max(10, this.terminalWidth - padding);
|
|
262
|
+
const colCount = header?.length ?? 1;
|
|
263
|
+
const width = Math.max(10, Math.floor(availableWidth / Math.max(1, colCount)));
|
|
264
|
+
const computedColWidths = colWidths
|
|
265
|
+
? colWidths.map((percent) => Math.max(10, Math.floor((percent / 100) * availableWidth)))
|
|
266
|
+
: new Array(colCount).fill(width);
|
|
267
|
+
const table = new Table({
|
|
268
|
+
head: header,
|
|
269
|
+
colWidths: computedColWidths,
|
|
270
|
+
wordWrap: true, // Enable word wrapping for the description column
|
|
271
|
+
});
|
|
272
|
+
table.push(...data);
|
|
273
|
+
this.writeln(table.toString());
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Create a spinner for showing progress
|
|
277
|
+
*/
|
|
278
|
+
spinner(text, id = "default") {
|
|
279
|
+
// Clean up existing spinner with the same ID
|
|
280
|
+
if (this.activeSpinners.has(id)) {
|
|
281
|
+
this.activeSpinners.get(id)?.stop();
|
|
282
|
+
this.activeSpinners.delete(id);
|
|
283
|
+
}
|
|
284
|
+
// Create spinner only if progress indicators are enabled and terminal is interactive
|
|
285
|
+
if (this.config.showProgressIndicators && this.isInteractive) {
|
|
286
|
+
const spinner = ora({
|
|
287
|
+
text,
|
|
288
|
+
spinner: "dots",
|
|
289
|
+
color: "cyan",
|
|
290
|
+
}).start();
|
|
291
|
+
const spinnerInstance = {
|
|
292
|
+
id,
|
|
293
|
+
update: (newText) => {
|
|
294
|
+
spinner.text = newText;
|
|
295
|
+
return spinnerInstance;
|
|
296
|
+
},
|
|
297
|
+
succeed: (text) => {
|
|
298
|
+
spinner.succeed(text);
|
|
299
|
+
this.activeSpinners.delete(id);
|
|
300
|
+
return spinnerInstance;
|
|
301
|
+
},
|
|
302
|
+
fail: (text) => {
|
|
303
|
+
spinner.fail(text);
|
|
304
|
+
this.activeSpinners.delete(id);
|
|
305
|
+
return spinnerInstance;
|
|
306
|
+
},
|
|
307
|
+
warn: (text) => {
|
|
308
|
+
spinner.warn(text);
|
|
309
|
+
this.activeSpinners.delete(id);
|
|
310
|
+
return spinnerInstance;
|
|
311
|
+
},
|
|
312
|
+
info: (text) => {
|
|
313
|
+
spinner.info(text);
|
|
314
|
+
this.activeSpinners.delete(id);
|
|
315
|
+
return spinnerInstance;
|
|
316
|
+
},
|
|
317
|
+
clear: () => {
|
|
318
|
+
spinner.clear();
|
|
319
|
+
this.activeSpinners.delete(id);
|
|
320
|
+
return spinnerInstance;
|
|
321
|
+
},
|
|
322
|
+
stop: () => {
|
|
323
|
+
spinner.stop();
|
|
324
|
+
this.activeSpinners.delete(id);
|
|
325
|
+
return spinnerInstance;
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
this.activeSpinners.set(id, spinnerInstance);
|
|
329
|
+
return spinnerInstance;
|
|
330
|
+
}
|
|
331
|
+
// Fallback for non-interactive terminals or when progress indicators are disabled
|
|
332
|
+
console.info(text);
|
|
333
|
+
// Return a dummy spinner
|
|
334
|
+
const dummySpinner = {
|
|
335
|
+
id,
|
|
336
|
+
update: (newText) => {
|
|
337
|
+
if (newText !== text) {
|
|
338
|
+
console.info(newText);
|
|
339
|
+
}
|
|
340
|
+
return dummySpinner;
|
|
341
|
+
},
|
|
342
|
+
succeed: (text) => {
|
|
343
|
+
if (text) {
|
|
344
|
+
this.success(text);
|
|
345
|
+
}
|
|
346
|
+
return dummySpinner;
|
|
347
|
+
},
|
|
348
|
+
fail: (text) => {
|
|
349
|
+
if (text) {
|
|
350
|
+
this.error(text);
|
|
351
|
+
}
|
|
352
|
+
return dummySpinner;
|
|
353
|
+
},
|
|
354
|
+
warn: (text) => {
|
|
355
|
+
if (text) {
|
|
356
|
+
this.warn(text);
|
|
357
|
+
}
|
|
358
|
+
return dummySpinner;
|
|
359
|
+
},
|
|
360
|
+
info: (text) => {
|
|
361
|
+
if (text) {
|
|
362
|
+
this.info(text);
|
|
363
|
+
}
|
|
364
|
+
return dummySpinner;
|
|
365
|
+
},
|
|
366
|
+
clear: () => {
|
|
367
|
+
return dummySpinner;
|
|
368
|
+
},
|
|
369
|
+
stop: () => {
|
|
370
|
+
return dummySpinner;
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
return dummySpinner;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Displays a horizontal progress bar in the console.
|
|
377
|
+
* @param current The current value.
|
|
378
|
+
* @param total The target value.
|
|
379
|
+
*/
|
|
380
|
+
displayProgressBar(current, total) {
|
|
381
|
+
const terminalWidth = this.terminalWidth > 0 ? this.terminalWidth : 80; // Default to 80 if columns not available
|
|
382
|
+
// Function to format numbers concisely (e.g., 1.2K, 5M)
|
|
383
|
+
const formatNumber = (num) => {
|
|
384
|
+
if (num < 1000) {
|
|
385
|
+
return num.toString();
|
|
386
|
+
}
|
|
387
|
+
if (num < 1_000_000) {
|
|
388
|
+
return `${(num / 1000).toFixed(1)}K`;
|
|
389
|
+
}
|
|
390
|
+
if (num < 1_000_000_000) {
|
|
391
|
+
return `${(num / 1_000_000).toFixed(1)}M`;
|
|
392
|
+
}
|
|
393
|
+
return `${(num / 1_000_000_000).toFixed(1)}G`;
|
|
394
|
+
};
|
|
395
|
+
const currentFormatted = formatNumber(current);
|
|
396
|
+
const totalFormatted = formatNumber(total);
|
|
397
|
+
const progressText = `${currentFormatted}/${totalFormatted}`;
|
|
398
|
+
const progressTextLength = progressText.length + 1; // Add 1 for space
|
|
399
|
+
const progressBarMaxWidth = Math.max(1, terminalWidth - progressTextLength - 1);
|
|
400
|
+
const percentage = total === 0 ? 1 : current / total;
|
|
401
|
+
const filledWidth = Math.max(0, Math.min(progressBarMaxWidth, Math.floor(percentage * progressBarMaxWidth)));
|
|
402
|
+
const emptyWidth = Math.max(0, progressBarMaxWidth - filledWidth);
|
|
403
|
+
const a = chalk.yellow("─"); //"█"
|
|
404
|
+
const b = chalk.gray("─"); // "░"
|
|
405
|
+
const filledBar = a.repeat(filledWidth);
|
|
406
|
+
const emptyBar = b.repeat(emptyWidth);
|
|
407
|
+
// Use \r to move cursor to the beginning of the line for updates
|
|
408
|
+
this.writeln(`\r${filledBar}${emptyBar} ${progressText} `);
|
|
409
|
+
}
|
|
410
|
+
formatMarkdown(content, wrap = false) {
|
|
411
|
+
const columns = this.terminalWidth;
|
|
412
|
+
const formatted = applyMarkdown(content);
|
|
413
|
+
if (wrap) {
|
|
414
|
+
return wrapAnsi(formatted, columns - 6, { trim: false });
|
|
415
|
+
}
|
|
416
|
+
return formatted;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
// Re-export the types
|
|
420
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const markdownHeaderRegex = /^#{1,6}\s/m;
|
|
2
|
+
const markdownBoldRegex = /(\*\*|__)(.*?)\1/;
|
|
3
|
+
const markdownItalicRegex = /(\*|_)(.*?)\1/;
|
|
4
|
+
const markdownCodeRegex = /`{1,3}[^`]+`{1,3}/;
|
|
5
|
+
const markdownLinkRegex = /\((.*?)\]\((.*?)\)/;
|
|
6
|
+
const markdownBlockquoteRegex = /^>\s/m;
|
|
7
|
+
const markdownUnorderedListRegex = /^-\s|\*\s|\+\s/m;
|
|
8
|
+
const markdownOrderedListRegex = /^\d+\.\s/m;
|
|
9
|
+
const markdownHorizontalRuleRegex = /^---$/m;
|
|
10
|
+
const markdownImageRegex = /!\[(.*?)\]\((.*?)\)/;
|
|
11
|
+
export function isMarkdown(input) {
|
|
12
|
+
// Simple heuristics: look for common markdown syntax
|
|
13
|
+
const markdownPatterns = [
|
|
14
|
+
markdownHeaderRegex, // headings
|
|
15
|
+
markdownBoldRegex, // bold
|
|
16
|
+
markdownItalicRegex, // italic
|
|
17
|
+
markdownCodeRegex, // inline code or code block
|
|
18
|
+
markdownLinkRegex, // links
|
|
19
|
+
markdownBlockquoteRegex, // blockquote
|
|
20
|
+
markdownUnorderedListRegex, // unordered list
|
|
21
|
+
markdownOrderedListRegex, // ordered list
|
|
22
|
+
markdownHorizontalRuleRegex, // horizontal rule
|
|
23
|
+
markdownImageRegex, // images
|
|
24
|
+
];
|
|
25
|
+
return markdownPatterns.some((pattern) => pattern.test(input));
|
|
26
|
+
}
|
|
27
|
+
function getDepth1ListNumber(i) {
|
|
28
|
+
if (i <= 0) {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
const letters = [];
|
|
32
|
+
let num = i;
|
|
33
|
+
while (num > 0) {
|
|
34
|
+
num--; // Adjust for 0-indexing
|
|
35
|
+
letters.unshift(String.fromCharCode(97 + (num % 26)));
|
|
36
|
+
num = Math.floor(num / 26);
|
|
37
|
+
}
|
|
38
|
+
return letters.join("");
|
|
39
|
+
}
|
|
40
|
+
function getDepth2ListNumber(i) {
|
|
41
|
+
if (i <= 0) {
|
|
42
|
+
return "";
|
|
43
|
+
}
|
|
44
|
+
const romanNumerals = [
|
|
45
|
+
["m", 1000],
|
|
46
|
+
["cm", 900],
|
|
47
|
+
["d", 500],
|
|
48
|
+
["cd", 400],
|
|
49
|
+
["c", 100],
|
|
50
|
+
["xc", 90],
|
|
51
|
+
["l", 50],
|
|
52
|
+
["xl", 40],
|
|
53
|
+
["x", 10],
|
|
54
|
+
["ix", 9],
|
|
55
|
+
["v", 5],
|
|
56
|
+
["iv", 4],
|
|
57
|
+
["i", 1],
|
|
58
|
+
];
|
|
59
|
+
let num = i;
|
|
60
|
+
let result = "";
|
|
61
|
+
for (const [roman, value] of romanNumerals) {
|
|
62
|
+
while (num >= value) {
|
|
63
|
+
result += roman;
|
|
64
|
+
num -= value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
export function getListNumber(listDepth, orderedListNumber) {
|
|
70
|
+
switch (listDepth) {
|
|
71
|
+
case 0:
|
|
72
|
+
case 1:
|
|
73
|
+
return orderedListNumber.toString();
|
|
74
|
+
case 2:
|
|
75
|
+
return getDepth1ListNumber(orderedListNumber);
|
|
76
|
+
case 3:
|
|
77
|
+
return getDepth2ListNumber(orderedListNumber);
|
|
78
|
+
default:
|
|
79
|
+
return orderedListNumber.toString();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function applyMarkdown(content: string): string;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { EOL } from "node:os";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { highlight, supportsLanguage } from "cli-highlight";
|
|
4
|
+
import Table from "cli-table3";
|
|
5
|
+
import { marked } from "marked";
|
|
6
|
+
import { logger } from "../logger.js";
|
|
7
|
+
import { link as terminalLink } from "./formatting.js";
|
|
8
|
+
import { getListNumber } from "./markdown-utils.js";
|
|
9
|
+
function logError(msg) {
|
|
10
|
+
logger.error(msg);
|
|
11
|
+
}
|
|
12
|
+
export function applyMarkdown(content) {
|
|
13
|
+
return marked
|
|
14
|
+
.lexer(content)
|
|
15
|
+
.map((token) => format(token))
|
|
16
|
+
.join("")
|
|
17
|
+
.trim();
|
|
18
|
+
}
|
|
19
|
+
function format(token, listDepth = 0, orderedListNumber = null, parent = null) {
|
|
20
|
+
switch (token.type) {
|
|
21
|
+
case "blockquote":
|
|
22
|
+
return chalk.dim.italic((token.tokens ?? [])
|
|
23
|
+
.map((_) => format(_))
|
|
24
|
+
.map((l) => ` ${l}`)
|
|
25
|
+
.join(""));
|
|
26
|
+
case "code": {
|
|
27
|
+
if (token.lang && supportsLanguage(token.lang)) {
|
|
28
|
+
return highlight(token.text, { language: token.lang }) + EOL;
|
|
29
|
+
}
|
|
30
|
+
logError(`Language not supported while highlighting code, falling back to markdown: ${token.lang}`);
|
|
31
|
+
return highlight(token.text, { language: "markdown" }) + EOL;
|
|
32
|
+
}
|
|
33
|
+
case "codespan":
|
|
34
|
+
// inline code
|
|
35
|
+
return chalk.blue(token.text);
|
|
36
|
+
case "em":
|
|
37
|
+
return chalk.italic((token.tokens ?? []).map((_) => format(_)).join(""));
|
|
38
|
+
case "strong":
|
|
39
|
+
return chalk.bold((token.tokens ?? []).map((_) => format(_)).join(""));
|
|
40
|
+
case "heading":
|
|
41
|
+
switch (token.depth) {
|
|
42
|
+
case 1: // h1
|
|
43
|
+
return (chalk.bold.italic.underline((token.tokens ?? []).map((_) => format(_)).join("")) +
|
|
44
|
+
EOL +
|
|
45
|
+
EOL);
|
|
46
|
+
case 2: // h2
|
|
47
|
+
return (chalk.bold((token.tokens ?? []).map((_) => format(_)).join("")) +
|
|
48
|
+
EOL +
|
|
49
|
+
EOL);
|
|
50
|
+
default: // h3+
|
|
51
|
+
return (chalk.bold.dim((token.tokens ?? []).map((_) => format(_)).join("")) +
|
|
52
|
+
EOL +
|
|
53
|
+
EOL);
|
|
54
|
+
}
|
|
55
|
+
case "hr":
|
|
56
|
+
return "---";
|
|
57
|
+
case "image": {
|
|
58
|
+
const alt = (token.title ?? token.text ?? "").toString().trim();
|
|
59
|
+
if (alt.length > 0) {
|
|
60
|
+
return `[Image: ${alt} (${token.href})]`;
|
|
61
|
+
}
|
|
62
|
+
return `[Image: ${token.href}]`;
|
|
63
|
+
}
|
|
64
|
+
case "link":
|
|
65
|
+
return terminalLink(token.text, token.href);
|
|
66
|
+
case "list": {
|
|
67
|
+
return token.items
|
|
68
|
+
.map((_, index) => format(_, listDepth, token.ordered ? token.start + index : null, token))
|
|
69
|
+
.join("");
|
|
70
|
+
}
|
|
71
|
+
case "list_item":
|
|
72
|
+
return (token.tokens ?? [])
|
|
73
|
+
.map((_) => `${" ".repeat(listDepth)}${format(_, listDepth + 1, orderedListNumber, token)}`)
|
|
74
|
+
.join("");
|
|
75
|
+
case "paragraph":
|
|
76
|
+
return (token.tokens ?? []).map((_) => format(_)).join("") + EOL;
|
|
77
|
+
case "space":
|
|
78
|
+
return EOL;
|
|
79
|
+
case "text": {
|
|
80
|
+
if (parent?.type === "list_item") {
|
|
81
|
+
return `${orderedListNumber === null ? "-" : `${getListNumber(listDepth, orderedListNumber)}.`} ${token.tokens ? token.tokens.map((_) => format(_, listDepth, orderedListNumber, token)).join("") : token.text}${EOL}`;
|
|
82
|
+
}
|
|
83
|
+
return token.text;
|
|
84
|
+
}
|
|
85
|
+
case "table": {
|
|
86
|
+
const header = Array.isArray(token.header)
|
|
87
|
+
? token.header
|
|
88
|
+
: [token.header];
|
|
89
|
+
const rows = Array.isArray(token.rows) ? token.rows : [token.rows];
|
|
90
|
+
// Calculate column widths based on terminal width
|
|
91
|
+
const padding = 5; // Account for table borders and padding
|
|
92
|
+
const availableWidth = Math.max(10, (process.stdout.columns || 80) - padding);
|
|
93
|
+
const colCount = header?.length ?? 1;
|
|
94
|
+
const width = Math.max(10, Math.floor(availableWidth / Math.max(1, colCount)));
|
|
95
|
+
const computedColWidths = new Array(colCount).fill(width);
|
|
96
|
+
const table = new Table({
|
|
97
|
+
head: header.map((h) => h.text),
|
|
98
|
+
colWidths: computedColWidths,
|
|
99
|
+
wordWrap: true, // Enable word wrapping for the description column
|
|
100
|
+
});
|
|
101
|
+
table.push(...rows.map((row) => row.map((c) => c.text)));
|
|
102
|
+
return `${table.toString()}\n`;
|
|
103
|
+
}
|
|
104
|
+
case "del": {
|
|
105
|
+
return chalk.strikethrough(token.text);
|
|
106
|
+
}
|
|
107
|
+
default:
|
|
108
|
+
console.log(token.type);
|
|
109
|
+
return "";
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal theme options
|
|
3
|
+
*/
|
|
4
|
+
type TerminalTheme = "dark" | "light" | "system";
|
|
5
|
+
/**
|
|
6
|
+
* Terminal configuration
|
|
7
|
+
*/
|
|
8
|
+
export interface TerminalConfig {
|
|
9
|
+
/**
|
|
10
|
+
* Terminal color theme
|
|
11
|
+
*/
|
|
12
|
+
theme: TerminalTheme;
|
|
13
|
+
/**
|
|
14
|
+
* Whether to use colors in output
|
|
15
|
+
*/
|
|
16
|
+
useColors: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether to show progress indicators
|
|
19
|
+
*/
|
|
20
|
+
showProgressIndicators: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Whether to enable syntax highlighting for code
|
|
23
|
+
*/
|
|
24
|
+
codeHighlighting: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Maximum terminal height (rows)
|
|
27
|
+
*/
|
|
28
|
+
maxHeight?: number | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Maximum terminal width (columns)
|
|
31
|
+
*/
|
|
32
|
+
maxWidth?: number | undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Spinner instance for progress indicators
|
|
36
|
+
*/
|
|
37
|
+
export interface SpinnerInstance {
|
|
38
|
+
/**
|
|
39
|
+
* Spinner identifier
|
|
40
|
+
*/
|
|
41
|
+
id: string;
|
|
42
|
+
/**
|
|
43
|
+
* Update spinner text
|
|
44
|
+
*/
|
|
45
|
+
update(text: string): SpinnerInstance;
|
|
46
|
+
/**
|
|
47
|
+
* Mark spinner as successful and stop
|
|
48
|
+
*/
|
|
49
|
+
succeed(text?: string): SpinnerInstance;
|
|
50
|
+
/**
|
|
51
|
+
* Mark spinner as failed and stop
|
|
52
|
+
*/
|
|
53
|
+
fail(text?: string): SpinnerInstance;
|
|
54
|
+
/**
|
|
55
|
+
* Mark spinner with warning and stop
|
|
56
|
+
*/
|
|
57
|
+
warn(text?: string): SpinnerInstance;
|
|
58
|
+
/**
|
|
59
|
+
* Mark spinner with info and stop
|
|
60
|
+
*/
|
|
61
|
+
info(text?: string): SpinnerInstance;
|
|
62
|
+
/**
|
|
63
|
+
* Clear spinner without any indicator
|
|
64
|
+
*/
|
|
65
|
+
clear(): SpinnerInstance;
|
|
66
|
+
/**
|
|
67
|
+
* Stop spinner without any indicator
|
|
68
|
+
*/
|
|
69
|
+
stop(): SpinnerInstance;
|
|
70
|
+
}
|
|
71
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|