erosolar-cli 1.0.2 → 1.0.5
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/README.md +80 -44
- package/agents/erosolar-code.rules.json +167 -0
- package/agents/general.rules.json +188 -0
- package/dist/adapters/browser/index.d.ts +12 -0
- package/dist/adapters/browser/index.d.ts.map +1 -0
- package/dist/adapters/browser/index.js +1 -0
- package/dist/adapters/browser/index.js.map +1 -0
- package/dist/adapters/node/index.d.ts +17 -0
- package/dist/adapters/node/index.d.ts.map +1 -0
- package/dist/adapters/node/index.js +1 -0
- package/dist/adapters/node/index.js.map +1 -0
- package/dist/adapters/remote/index.d.ts +13 -0
- package/dist/adapters/remote/index.d.ts.map +1 -0
- package/dist/adapters/remote/index.js +1 -0
- package/dist/adapters/remote/index.js.map +1 -0
- package/dist/adapters/types.d.ts +14 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +1 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/bin/erosolar.d.ts +3 -0
- package/dist/bin/erosolar.d.ts.map +1 -0
- package/dist/bin/erosolar.js +1 -0
- package/dist/bin/erosolar.js.map +1 -0
- package/dist/capabilities/bashCapability.d.ts +13 -0
- package/dist/capabilities/bashCapability.d.ts.map +1 -0
- package/dist/capabilities/bashCapability.js +1 -0
- package/dist/capabilities/bashCapability.js.map +1 -0
- package/dist/capabilities/codeAnalysisCapability.d.ts +13 -0
- package/dist/capabilities/codeAnalysisCapability.d.ts.map +1 -0
- package/dist/capabilities/codeAnalysisCapability.js +24 -0
- package/dist/capabilities/codeAnalysisCapability.js.map +1 -0
- package/dist/capabilities/codeGenerationCapability.d.ts +13 -0
- package/dist/capabilities/codeGenerationCapability.d.ts.map +1 -0
- package/dist/capabilities/codeGenerationCapability.js +25 -0
- package/dist/capabilities/codeGenerationCapability.js.map +1 -0
- package/dist/capabilities/codeQualityCapability.d.ts +13 -0
- package/dist/capabilities/codeQualityCapability.d.ts.map +1 -0
- package/dist/capabilities/codeQualityCapability.js +25 -0
- package/dist/capabilities/codeQualityCapability.js.map +1 -0
- package/dist/capabilities/dependencySecurityCapability.d.ts +13 -0
- package/dist/capabilities/dependencySecurityCapability.d.ts.map +1 -0
- package/dist/capabilities/dependencySecurityCapability.js +24 -0
- package/dist/capabilities/dependencySecurityCapability.js.map +1 -0
- package/dist/capabilities/devCapability.d.ts +13 -0
- package/dist/capabilities/devCapability.d.ts.map +1 -0
- package/dist/capabilities/devCapability.js +24 -0
- package/dist/capabilities/devCapability.js.map +1 -0
- package/dist/capabilities/filesystemCapability.d.ts +13 -0
- package/dist/capabilities/filesystemCapability.d.ts.map +1 -0
- package/dist/capabilities/filesystemCapability.js +1 -0
- package/dist/capabilities/filesystemCapability.js.map +1 -0
- package/dist/capabilities/index.d.ts +10 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +7 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/capabilities/refactoringCapability.d.ts +13 -0
- package/dist/capabilities/refactoringCapability.d.ts.map +1 -0
- package/dist/capabilities/refactoringCapability.js +25 -0
- package/dist/capabilities/refactoringCapability.js.map +1 -0
- package/dist/capabilities/repoChecksCapability.d.ts +10 -0
- package/dist/capabilities/repoChecksCapability.d.ts.map +1 -0
- package/dist/capabilities/repoChecksCapability.js +24 -0
- package/dist/capabilities/repoChecksCapability.js.map +1 -0
- package/dist/capabilities/searchCapability.d.ts +13 -0
- package/dist/capabilities/searchCapability.d.ts.map +1 -0
- package/dist/capabilities/searchCapability.js +1 -0
- package/dist/capabilities/searchCapability.js.map +1 -0
- package/dist/capabilities/testingCapability.d.ts +13 -0
- package/dist/capabilities/testingCapability.d.ts.map +1 -0
- package/dist/capabilities/testingCapability.js +25 -0
- package/dist/capabilities/testingCapability.js.map +1 -0
- package/dist/capabilities/toolManifest.d.ts +3 -0
- package/dist/capabilities/toolManifest.d.ts.map +1 -0
- package/dist/capabilities/toolManifest.js +160 -0
- package/dist/capabilities/toolManifest.js.map +1 -0
- package/dist/capabilities/toolRegistry.d.ts +22 -0
- package/dist/capabilities/toolRegistry.d.ts.map +1 -0
- package/dist/capabilities/toolRegistry.js +49 -32
- package/dist/capabilities/toolRegistry.js.map +1 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +103 -23
- package/dist/config.js.map +1 -0
- package/dist/contracts/agent-profiles.schema.json +43 -0
- package/dist/contracts/agent-schemas.json +293 -0
- package/dist/contracts/schemas/agent-profile.schema.json +157 -0
- package/dist/contracts/schemas/agent-rules.schema.json +238 -0
- package/dist/contracts/schemas/agent-schemas.schema.json +528 -0
- package/dist/contracts/schemas/agent.schema.json +89 -0
- package/dist/contracts/schemas/tool-selection.schema.json +174 -0
- package/dist/contracts/tools.schema.json +100 -0
- package/dist/contracts/v1/agent.d.ts +147 -0
- package/dist/contracts/v1/agent.d.ts.map +1 -0
- package/dist/contracts/v1/agent.js +1 -0
- package/dist/contracts/v1/agent.js.map +1 -0
- package/dist/contracts/v1/agentProfileManifest.d.ts +60 -0
- package/dist/contracts/v1/agentProfileManifest.d.ts.map +1 -0
- package/dist/contracts/v1/agentProfileManifest.js +9 -0
- package/dist/contracts/v1/agentProfileManifest.js.map +1 -0
- package/dist/contracts/v1/agentRules.d.ts +60 -0
- package/dist/contracts/v1/agentRules.d.ts.map +1 -0
- package/dist/contracts/v1/agentRules.js +10 -0
- package/dist/contracts/v1/agentRules.js.map +1 -0
- package/dist/contracts/v1/provider.d.ts +149 -0
- package/dist/contracts/v1/provider.d.ts.map +1 -0
- package/dist/contracts/v1/provider.js +1 -0
- package/dist/contracts/v1/provider.js.map +1 -0
- package/dist/contracts/v1/tool.d.ts +136 -0
- package/dist/contracts/v1/tool.d.ts.map +1 -0
- package/dist/contracts/v1/tool.js +1 -0
- package/dist/contracts/v1/tool.js.map +1 -0
- package/dist/contracts/v1/toolAccess.d.ts +43 -0
- package/dist/contracts/v1/toolAccess.d.ts.map +1 -0
- package/dist/contracts/v1/toolAccess.js +9 -0
- package/dist/contracts/v1/toolAccess.js.map +1 -0
- package/dist/core/agent.d.ts +35 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +17 -9
- package/dist/core/agent.js.map +1 -0
- package/dist/core/agentProfileManifest.d.ts +3 -0
- package/dist/core/agentProfileManifest.d.ts.map +1 -0
- package/dist/core/agentProfileManifest.js +188 -0
- package/dist/core/agentProfileManifest.js.map +1 -0
- package/dist/core/agentProfiles.d.ts +22 -0
- package/dist/core/agentProfiles.d.ts.map +1 -0
- package/dist/core/agentProfiles.js +1 -0
- package/dist/core/agentProfiles.js.map +1 -0
- package/dist/core/agentRulebook.d.ts +11 -0
- package/dist/core/agentRulebook.d.ts.map +1 -0
- package/dist/core/agentRulebook.js +136 -0
- package/dist/core/agentRulebook.js.map +1 -0
- package/dist/core/agentSchemaLoader.d.ts +131 -0
- package/dist/core/agentSchemaLoader.d.ts.map +1 -0
- package/dist/core/agentSchemaLoader.js +221 -0
- package/dist/core/agentSchemaLoader.js.map +1 -0
- package/dist/core/contextWindow.d.ts +6 -0
- package/dist/core/contextWindow.d.ts.map +1 -0
- package/dist/core/contextWindow.js +1 -0
- package/dist/core/contextWindow.js.map +1 -0
- package/dist/core/errors/apiKeyErrors.d.ts +11 -0
- package/dist/core/errors/apiKeyErrors.d.ts.map +1 -0
- package/dist/core/errors/apiKeyErrors.js +1 -0
- package/dist/core/errors/apiKeyErrors.js.map +1 -0
- package/dist/core/errors.d.ts +4 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +33 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/preferences.d.ts +21 -0
- package/dist/core/preferences.d.ts.map +1 -0
- package/dist/core/preferences.js +13 -7
- package/dist/core/preferences.js.map +1 -0
- package/dist/core/schemaValidator.d.ts +6 -0
- package/dist/core/schemaValidator.d.ts.map +1 -0
- package/dist/core/schemaValidator.js +93 -0
- package/dist/core/schemaValidator.js.map +1 -0
- package/dist/core/secretStore.d.ts +20 -0
- package/dist/core/secretStore.d.ts.map +1 -0
- package/dist/core/secretStore.js +3 -8
- package/dist/core/secretStore.js.map +1 -0
- package/dist/core/toolRuntime.d.ts +42 -0
- package/dist/core/toolRuntime.d.ts.map +1 -0
- package/dist/core/toolRuntime.js +25 -10
- package/dist/core/toolRuntime.js.map +1 -0
- package/dist/core/types.d.ts +86 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +1 -0
- package/dist/core/types.js.map +1 -0
- package/dist/plugins/providers/anthropic/index.d.ts +2 -0
- package/dist/plugins/providers/anthropic/index.d.ts.map +1 -0
- package/dist/plugins/providers/anthropic/index.js +6 -4
- package/dist/plugins/providers/anthropic/index.js.map +1 -0
- package/dist/plugins/providers/deepseek/index.d.ts +2 -0
- package/dist/plugins/providers/deepseek/index.d.ts.map +1 -0
- package/dist/plugins/providers/deepseek/index.js +1 -0
- package/dist/plugins/providers/deepseek/index.js.map +1 -0
- package/dist/plugins/providers/google/index.d.ts +2 -0
- package/dist/plugins/providers/google/index.d.ts.map +1 -0
- package/dist/plugins/providers/google/index.js +6 -4
- package/dist/plugins/providers/google/index.js.map +1 -0
- package/dist/plugins/providers/index.d.ts +2 -0
- package/dist/plugins/providers/index.d.ts.map +1 -0
- package/dist/plugins/providers/index.js +1 -0
- package/dist/plugins/providers/index.js.map +1 -0
- package/dist/plugins/providers/openai/index.d.ts +3 -0
- package/dist/plugins/providers/openai/index.d.ts.map +1 -0
- package/dist/plugins/providers/openai/index.js +6 -4
- package/dist/plugins/providers/openai/index.js.map +1 -0
- package/dist/plugins/providers/xai/index.d.ts +2 -0
- package/dist/plugins/providers/xai/index.d.ts.map +1 -0
- package/dist/plugins/providers/xai/index.js +1 -0
- package/dist/plugins/providers/xai/index.js.map +1 -0
- package/dist/plugins/tools/bash/localBashPlugin.d.ts +3 -0
- package/dist/plugins/tools/bash/localBashPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/bash/localBashPlugin.js +1 -0
- package/dist/plugins/tools/bash/localBashPlugin.js.map +1 -0
- package/dist/plugins/tools/checks/localRepoChecksPlugin.d.ts +3 -0
- package/dist/plugins/tools/checks/localRepoChecksPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/checks/localRepoChecksPlugin.js +14 -0
- package/dist/plugins/tools/checks/localRepoChecksPlugin.js.map +1 -0
- package/dist/plugins/tools/codeAnalysis/codeAnalysisPlugin.d.ts +3 -0
- package/dist/plugins/tools/codeAnalysis/codeAnalysisPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/codeAnalysis/codeAnalysisPlugin.js +14 -0
- package/dist/plugins/tools/codeAnalysis/codeAnalysisPlugin.js.map +1 -0
- package/dist/plugins/tools/codeQuality/codeQualityPlugin.d.ts +3 -0
- package/dist/plugins/tools/codeQuality/codeQualityPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/codeQuality/codeQualityPlugin.js +14 -0
- package/dist/plugins/tools/codeQuality/codeQualityPlugin.js.map +1 -0
- package/dist/plugins/tools/dependency/dependencyPlugin.d.ts +3 -0
- package/dist/plugins/tools/dependency/dependencyPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/dependency/dependencyPlugin.js +12 -0
- package/dist/plugins/tools/dependency/dependencyPlugin.js.map +1 -0
- package/dist/plugins/tools/development/devPlugin.d.ts +3 -0
- package/dist/plugins/tools/development/devPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/development/devPlugin.js +14 -0
- package/dist/plugins/tools/development/devPlugin.js.map +1 -0
- package/dist/plugins/tools/filesystem/localFilesystemPlugin.d.ts +3 -0
- package/dist/plugins/tools/filesystem/localFilesystemPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/filesystem/localFilesystemPlugin.js +1 -0
- package/dist/plugins/tools/filesystem/localFilesystemPlugin.js.map +1 -0
- package/dist/plugins/tools/index.d.ts +3 -0
- package/dist/plugins/tools/index.d.ts.map +1 -0
- package/dist/plugins/tools/index.js +1 -0
- package/dist/plugins/tools/index.js.map +1 -0
- package/dist/plugins/tools/nodeDefaults.d.ts +2 -0
- package/dist/plugins/tools/nodeDefaults.d.ts.map +1 -0
- package/dist/plugins/tools/nodeDefaults.js +15 -2
- package/dist/plugins/tools/nodeDefaults.js.map +1 -0
- package/dist/plugins/tools/refactoring/refactoringPlugin.d.ts +3 -0
- package/dist/plugins/tools/refactoring/refactoringPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/refactoring/refactoringPlugin.js +12 -0
- package/dist/plugins/tools/refactoring/refactoringPlugin.js.map +1 -0
- package/dist/plugins/tools/registry.d.ts +22 -0
- package/dist/plugins/tools/registry.d.ts.map +1 -0
- package/dist/plugins/tools/registry.js +1 -0
- package/dist/plugins/tools/registry.js.map +1 -0
- package/dist/plugins/tools/search/localSearchPlugin.d.ts +3 -0
- package/dist/plugins/tools/search/localSearchPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/search/localSearchPlugin.js +1 -0
- package/dist/plugins/tools/search/localSearchPlugin.js.map +1 -0
- package/dist/plugins/tools/testing/testingPlugin.d.ts +3 -0
- package/dist/plugins/tools/testing/testingPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/testing/testingPlugin.js +12 -0
- package/dist/plugins/tools/testing/testingPlugin.js.map +1 -0
- package/dist/providers/anthropicProvider.d.ts +23 -0
- package/dist/providers/anthropicProvider.d.ts.map +1 -0
- package/dist/providers/anthropicProvider.js +3 -2
- package/dist/providers/anthropicProvider.js.map +1 -0
- package/dist/providers/googleProvider.d.ts +19 -0
- package/dist/providers/googleProvider.d.ts.map +1 -0
- package/dist/providers/googleProvider.js +1 -1
- package/dist/providers/googleProvider.js.map +1 -0
- package/dist/providers/openaiChatCompletionsProvider.d.ts +16 -0
- package/dist/providers/openaiChatCompletionsProvider.d.ts.map +1 -0
- package/dist/providers/openaiChatCompletionsProvider.js +1 -0
- package/dist/providers/openaiChatCompletionsProvider.js.map +1 -0
- package/dist/providers/openaiResponsesProvider.d.ts +20 -0
- package/dist/providers/openaiResponsesProvider.d.ts.map +1 -0
- package/dist/providers/openaiResponsesProvider.js +1 -0
- package/dist/providers/openaiResponsesProvider.js.map +1 -0
- package/dist/providers/providerFactory.d.ts +18 -0
- package/dist/providers/providerFactory.d.ts.map +1 -0
- package/dist/providers/providerFactory.js +5 -1
- package/dist/providers/providerFactory.js.map +1 -0
- package/dist/runtime/agentHost.d.ts +61 -0
- package/dist/runtime/agentHost.d.ts.map +1 -0
- package/dist/runtime/agentHost.js +5 -1
- package/dist/runtime/agentHost.js.map +1 -0
- package/dist/runtime/agentSession.d.ts +32 -0
- package/dist/runtime/agentSession.d.ts.map +1 -0
- package/dist/runtime/agentSession.js +17 -1
- package/dist/runtime/agentSession.js.map +1 -0
- package/dist/runtime/browser.d.ts +7 -0
- package/dist/runtime/browser.d.ts.map +1 -0
- package/dist/runtime/browser.js +1 -0
- package/dist/runtime/browser.js.map +1 -0
- package/dist/runtime/cloud.d.ts +7 -0
- package/dist/runtime/cloud.d.ts.map +1 -0
- package/dist/runtime/cloud.js +1 -0
- package/dist/runtime/cloud.js.map +1 -0
- package/dist/runtime/node.d.ts +8 -0
- package/dist/runtime/node.d.ts.map +1 -0
- package/dist/runtime/node.js +1 -0
- package/dist/runtime/node.js.map +1 -0
- package/dist/runtime/universal.d.ts +21 -0
- package/dist/runtime/universal.d.ts.map +1 -0
- package/dist/runtime/universal.js +1 -0
- package/dist/runtime/universal.js.map +1 -0
- package/dist/shell/bracketedPasteManager.d.ts +23 -0
- package/dist/shell/bracketedPasteManager.d.ts.map +1 -0
- package/dist/shell/bracketedPasteManager.js +1 -0
- package/dist/shell/bracketedPasteManager.js.map +1 -0
- package/dist/shell/interactiveShell.d.ts +131 -0
- package/dist/shell/interactiveShell.d.ts.map +1 -0
- package/dist/shell/interactiveShell.js +325 -262
- package/dist/shell/interactiveShell.js.map +1 -0
- package/dist/shell/liveStatus.d.ts +29 -0
- package/dist/shell/liveStatus.d.ts.map +1 -0
- package/dist/shell/liveStatus.js +77 -0
- package/dist/shell/liveStatus.js.map +1 -0
- package/dist/shell/promptSkin.d.ts +43 -0
- package/dist/shell/promptSkin.d.ts.map +1 -0
- package/dist/shell/promptSkin.js +330 -0
- package/dist/shell/promptSkin.js.map +1 -0
- package/dist/shell/shellApp.d.ts +10 -0
- package/dist/shell/shellApp.d.ts.map +1 -0
- package/dist/shell/shellApp.js +149 -78
- package/dist/shell/shellApp.js.map +1 -0
- package/dist/shell/systemPrompt.d.ts +3 -0
- package/dist/shell/systemPrompt.d.ts.map +1 -0
- package/dist/shell/systemPrompt.js +64 -0
- package/dist/shell/systemPrompt.js.map +1 -0
- package/dist/shell/updateManager.d.ts +2 -0
- package/dist/shell/updateManager.d.ts.map +1 -0
- package/dist/shell/updateManager.js +109 -0
- package/dist/shell/updateManager.js.map +1 -0
- package/dist/tools/bashTools.d.ts +8 -0
- package/dist/tools/bashTools.d.ts.map +1 -0
- package/dist/tools/bashTools.js +18 -15
- package/dist/tools/bashTools.js.map +1 -0
- package/dist/tools/codeAnalysisTools.d.ts +74 -0
- package/dist/tools/codeAnalysisTools.d.ts.map +1 -0
- package/dist/tools/codeAnalysisTools.js +642 -0
- package/dist/tools/codeAnalysisTools.js.map +1 -0
- package/dist/tools/codeGenerationTools.d.ts +3 -0
- package/dist/tools/codeGenerationTools.d.ts.map +1 -0
- package/dist/tools/codeGenerationTools.js +369 -0
- package/dist/tools/codeGenerationTools.js.map +1 -0
- package/dist/tools/codeQualityTools.d.ts +3 -0
- package/dist/tools/codeQualityTools.d.ts.map +1 -0
- package/dist/tools/codeQualityTools.js +295 -0
- package/dist/tools/codeQualityTools.js.map +1 -0
- package/dist/tools/dependencyTools.d.ts +3 -0
- package/dist/tools/dependencyTools.d.ts.map +1 -0
- package/dist/tools/dependencyTools.js +283 -0
- package/dist/tools/dependencyTools.js.map +1 -0
- package/dist/tools/devTools.d.ts +10 -0
- package/dist/tools/devTools.d.ts.map +1 -0
- package/dist/tools/devTools.js +239 -0
- package/dist/tools/devTools.js.map +1 -0
- package/dist/tools/diffUtils.d.ts +8 -0
- package/dist/tools/diffUtils.d.ts.map +1 -0
- package/dist/tools/diffUtils.js +2 -1
- package/dist/tools/diffUtils.js.map +1 -0
- package/dist/tools/fileTools.d.ts +3 -0
- package/dist/tools/fileTools.d.ts.map +1 -0
- package/dist/tools/fileTools.js +72 -21
- package/dist/tools/fileTools.js.map +1 -0
- package/dist/tools/refactoringTools.d.ts +3 -0
- package/dist/tools/refactoringTools.d.ts.map +1 -0
- package/dist/tools/refactoringTools.js +294 -0
- package/dist/tools/refactoringTools.js.map +1 -0
- package/dist/tools/repoChecksTools.d.ts +3 -0
- package/dist/tools/repoChecksTools.d.ts.map +1 -0
- package/dist/tools/repoChecksTools.js +161 -0
- package/dist/tools/repoChecksTools.js.map +1 -0
- package/dist/tools/searchTools.d.ts +3 -0
- package/dist/tools/searchTools.d.ts.map +1 -0
- package/dist/tools/searchTools.js +50 -22
- package/dist/tools/searchTools.js.map +1 -0
- package/dist/tools/testingTools.d.ts +3 -0
- package/dist/tools/testingTools.d.ts.map +1 -0
- package/dist/tools/testingTools.js +233 -0
- package/dist/tools/testingTools.js.map +1 -0
- package/dist/ui/ShellUIAdapter.d.ts +96 -0
- package/dist/ui/ShellUIAdapter.d.ts.map +1 -0
- package/dist/ui/ShellUIAdapter.js +442 -0
- package/dist/ui/ShellUIAdapter.js.map +1 -0
- package/dist/ui/UnifiedUIController.d.ts +196 -0
- package/dist/ui/UnifiedUIController.d.ts.map +1 -0
- package/dist/ui/UnifiedUIController.js +640 -0
- package/dist/ui/UnifiedUIController.js.map +1 -0
- package/dist/ui/animation/AnimationScheduler.d.ts +192 -0
- package/dist/ui/animation/AnimationScheduler.d.ts.map +1 -0
- package/dist/ui/animation/AnimationScheduler.js +432 -0
- package/dist/ui/animation/AnimationScheduler.js.map +1 -0
- package/dist/ui/codeHighlighter.d.ts +6 -0
- package/dist/ui/codeHighlighter.d.ts.map +1 -0
- package/dist/ui/codeHighlighter.js +41 -29
- package/dist/ui/codeHighlighter.js.map +1 -0
- package/dist/ui/designSystem.d.ts +26 -0
- package/dist/ui/designSystem.d.ts.map +1 -0
- package/dist/ui/designSystem.js +17 -1
- package/dist/ui/designSystem.js.map +1 -0
- package/dist/ui/display.d.ts +160 -0
- package/dist/ui/display.d.ts.map +1 -0
- package/dist/ui/display.js +492 -231
- package/dist/ui/display.js.map +1 -0
- package/dist/ui/interrupts/InterruptManager.d.ts +142 -0
- package/dist/ui/interrupts/InterruptManager.d.ts.map +1 -0
- package/dist/ui/interrupts/InterruptManager.js +439 -0
- package/dist/ui/interrupts/InterruptManager.js.map +1 -0
- package/dist/ui/layout.d.ts +17 -0
- package/dist/ui/layout.d.ts.map +1 -0
- package/dist/ui/layout.js +12 -7
- package/dist/ui/layout.js.map +1 -0
- package/dist/ui/orchestration/StatusOrchestrator.d.ts +156 -0
- package/dist/ui/orchestration/StatusOrchestrator.d.ts.map +1 -0
- package/dist/ui/orchestration/StatusOrchestrator.js +405 -0
- package/dist/ui/orchestration/StatusOrchestrator.js.map +1 -0
- package/dist/ui/overlay/OverlayManager.d.ts +105 -0
- package/dist/ui/overlay/OverlayManager.d.ts.map +1 -0
- package/dist/ui/overlay/OverlayManager.js +291 -0
- package/dist/ui/overlay/OverlayManager.js.map +1 -0
- package/dist/ui/richText.d.ts +6 -0
- package/dist/ui/richText.d.ts.map +1 -0
- package/dist/ui/richText.js +13 -4
- package/dist/ui/richText.js.map +1 -0
- package/dist/ui/telemetry/UITelemetry.d.ts +181 -0
- package/dist/ui/telemetry/UITelemetry.d.ts.map +1 -0
- package/dist/ui/telemetry/UITelemetry.js +446 -0
- package/dist/ui/telemetry/UITelemetry.js.map +1 -0
- package/dist/ui/theme.d.ts +77 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +19 -6
- package/dist/ui/theme.js.map +1 -0
- package/dist/utils/errorUtils.d.ts +16 -0
- package/dist/utils/errorUtils.d.ts.map +1 -0
- package/dist/utils/errorUtils.js +66 -0
- package/dist/utils/errorUtils.js.map +1 -0
- package/dist/utils/nodeVersion.d.ts +3 -0
- package/dist/utils/nodeVersion.d.ts.map +1 -0
- package/dist/utils/nodeVersion.js +51 -0
- package/dist/utils/nodeVersion.js.map +1 -0
- package/dist/workspace.d.ts +8 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +72 -11
- package/dist/workspace.js.map +1 -0
- package/package.json +35 -16
- package/scripts/health-check.mjs +176 -0
- package/ARCHITECTURE.json +0 -157
- package/Agents.md +0 -207
- package/SOURCE_OF_TRUTH.json +0 -103
- package/dist/capabilities/tavilyCapability.js +0 -26
- package/dist/plugins/tools/tavily/tavilyPlugin.js +0 -16
- package/dist/shell/__tests__/bracketedPasteManager.test.js +0 -35
- package/dist/tools/tavilyTools.js +0 -176
- package/dist/ui/__tests__/richText.test.js +0 -36
package/dist/ui/display.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { createSpinner } from 'nanospinner';
|
|
2
2
|
import { cursorTo, moveCursor } from 'node:readline';
|
|
3
3
|
import { theme, icons } from './theme.js';
|
|
4
|
-
import { formatRichContent,
|
|
4
|
+
import { formatRichContent, renderMessagePanel } from './richText.js';
|
|
5
5
|
import { getTerminalColumns, wrapPreformatted } from './layout.js';
|
|
6
|
-
import { renderCallout, renderSectionHeading
|
|
6
|
+
import { renderCallout, renderSectionHeading } from './designSystem.js';
|
|
7
|
+
/**
|
|
8
|
+
* Tracks line output to stdout for banner rewriting and cursor positioning.
|
|
9
|
+
* Singleton pattern ensures consistent tracking across the application.
|
|
10
|
+
*/
|
|
7
11
|
class StdoutLineTracker {
|
|
8
12
|
static instance = null;
|
|
9
13
|
static getInstance() {
|
|
@@ -24,13 +28,18 @@ class StdoutLineTracker {
|
|
|
24
28
|
get totalLines() {
|
|
25
29
|
return this.linesWritten;
|
|
26
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Temporarily suspends line tracking while executing a function.
|
|
33
|
+
* Useful for rewriting content without incrementing line count.
|
|
34
|
+
*/
|
|
27
35
|
withSuspended(fn) {
|
|
36
|
+
const wasSuspended = this.suspended;
|
|
28
37
|
this.suspended = true;
|
|
29
38
|
try {
|
|
30
39
|
return fn();
|
|
31
40
|
}
|
|
32
41
|
finally {
|
|
33
|
-
this.suspended =
|
|
42
|
+
this.suspended = wasSuspended;
|
|
34
43
|
}
|
|
35
44
|
}
|
|
36
45
|
reset() {
|
|
@@ -39,86 +48,192 @@ class StdoutLineTracker {
|
|
|
39
48
|
patchStream() {
|
|
40
49
|
const tracker = this;
|
|
41
50
|
this.stream.write = function patched(chunk, encoding, callback) {
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
const actualEncoding = typeof encoding === 'function' ? undefined : encoding;
|
|
52
|
+
tracker.recordChunk(chunk, actualEncoding);
|
|
53
|
+
return tracker.originalWrite.call(this, chunk, encoding, callback);
|
|
44
54
|
};
|
|
45
55
|
}
|
|
46
56
|
recordChunk(chunk, encoding) {
|
|
47
57
|
if (this.suspended) {
|
|
48
58
|
return;
|
|
49
59
|
}
|
|
50
|
-
const text = this.
|
|
60
|
+
const text = this.chunkToString(chunk, encoding);
|
|
51
61
|
if (!text) {
|
|
52
62
|
return;
|
|
53
63
|
}
|
|
54
|
-
|
|
55
|
-
|
|
64
|
+
this.countNewlines(text);
|
|
65
|
+
}
|
|
66
|
+
countNewlines(text) {
|
|
67
|
+
for (const char of text) {
|
|
68
|
+
if (char === '\n') {
|
|
56
69
|
this.linesWritten += 1;
|
|
57
70
|
}
|
|
58
71
|
}
|
|
59
72
|
}
|
|
60
|
-
|
|
73
|
+
chunkToString(chunk, encoding) {
|
|
61
74
|
if (typeof chunk === 'string') {
|
|
62
75
|
return chunk;
|
|
63
76
|
}
|
|
64
77
|
if (chunk instanceof Uint8Array) {
|
|
65
|
-
const enc =
|
|
78
|
+
const enc = encoding ?? 'utf8';
|
|
66
79
|
return Buffer.from(chunk).toString(enc);
|
|
67
80
|
}
|
|
68
81
|
return null;
|
|
69
82
|
}
|
|
70
83
|
}
|
|
84
|
+
// Display configuration constants
|
|
85
|
+
const DISPLAY_CONSTANTS = {
|
|
86
|
+
MIN_BANNER_WIDTH: 32,
|
|
87
|
+
MAX_BANNER_WIDTH: 120,
|
|
88
|
+
BANNER_PADDING: 4,
|
|
89
|
+
MIN_MESSAGE_WIDTH: 42,
|
|
90
|
+
MAX_MESSAGE_WIDTH: 110,
|
|
91
|
+
MESSAGE_PADDING: 4,
|
|
92
|
+
MIN_ACTION_WIDTH: 40,
|
|
93
|
+
MAX_ACTION_WIDTH: 90,
|
|
94
|
+
MIN_THOUGHT_WIDTH: 48,
|
|
95
|
+
MAX_THOUGHT_WIDTH: 96,
|
|
96
|
+
MIN_CONTENT_WIDTH: 10,
|
|
97
|
+
MIN_WRAP_WIDTH: 12,
|
|
98
|
+
SPINNER_INTERVAL: 80,
|
|
99
|
+
};
|
|
100
|
+
const SPINNER_FRAMES = ['∴', 'ε', '∴', '✻', 'ε', '✻'];
|
|
101
|
+
/**
|
|
102
|
+
* Display class manages all terminal UI output for the application.
|
|
103
|
+
*
|
|
104
|
+
* Architecture:
|
|
105
|
+
* - Singleton pattern via StdoutLineTracker for consistent line tracking
|
|
106
|
+
* - Output interceptor pattern for live update integration
|
|
107
|
+
* - Banner state management for in-place updates
|
|
108
|
+
* - Configurable width constraints via DISPLAY_CONSTANTS
|
|
109
|
+
*
|
|
110
|
+
* Key responsibilities:
|
|
111
|
+
* - Welcome banners and session information display
|
|
112
|
+
* - Message formatting (assistant, system, errors, warnings)
|
|
113
|
+
* - Spinner/thinking indicators
|
|
114
|
+
* - Action and sub-action formatting with tree-style prefixes
|
|
115
|
+
* - Text wrapping and layout management
|
|
116
|
+
*
|
|
117
|
+
* Error handling:
|
|
118
|
+
* - Graceful degradation for non-TTY environments
|
|
119
|
+
* - Input validation on public methods
|
|
120
|
+
* - Safe cursor manipulation with fallback
|
|
121
|
+
*/
|
|
71
122
|
export class Display {
|
|
72
123
|
stdoutTracker = StdoutLineTracker.getInstance();
|
|
73
124
|
activeSpinner = null;
|
|
125
|
+
outputInterceptors = new Set();
|
|
126
|
+
registerOutputInterceptor(interceptor) {
|
|
127
|
+
if (!interceptor) {
|
|
128
|
+
return () => { };
|
|
129
|
+
}
|
|
130
|
+
this.outputInterceptors.add(interceptor);
|
|
131
|
+
return () => {
|
|
132
|
+
this.outputInterceptors.delete(interceptor);
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
withOutput(fn) {
|
|
136
|
+
this.notifyBeforeOutput();
|
|
137
|
+
try {
|
|
138
|
+
return fn();
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
this.notifyAfterOutput();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
notifyBeforeOutput() {
|
|
145
|
+
for (const interceptor of this.outputInterceptors) {
|
|
146
|
+
interceptor.beforeWrite?.();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
notifyAfterOutput() {
|
|
150
|
+
const interceptors = Array.from(this.outputInterceptors);
|
|
151
|
+
for (let index = interceptors.length - 1; index >= 0; index -= 1) {
|
|
152
|
+
interceptors[index]?.afterWrite?.();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
74
155
|
bannerState = null;
|
|
75
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Displays the welcome banner with session information.
|
|
158
|
+
* Stores banner state for potential in-place updates.
|
|
159
|
+
*/
|
|
160
|
+
showWelcome(profileLabel, profileName, model, provider, workingDir, version) {
|
|
161
|
+
// Validate required inputs
|
|
162
|
+
if (!model?.trim() || !provider?.trim() || !workingDir?.trim()) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
76
165
|
const width = this.getBannerWidth();
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
166
|
+
const banner = this.buildClaudeStyleBanner(profileLabel ?? '', model, provider, workingDir, width);
|
|
167
|
+
if (!banner) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
80
170
|
const startLine = this.stdoutTracker.totalLines;
|
|
81
|
-
|
|
82
|
-
|
|
171
|
+
this.withOutput(() => {
|
|
172
|
+
console.log(banner);
|
|
173
|
+
});
|
|
174
|
+
const nextState = {
|
|
83
175
|
startLine,
|
|
84
176
|
height: this.measureBannerHeight(banner),
|
|
85
177
|
width,
|
|
86
178
|
workingDir,
|
|
87
|
-
version,
|
|
88
179
|
model,
|
|
89
180
|
provider,
|
|
90
|
-
profileLabel,
|
|
91
|
-
profileName,
|
|
92
|
-
thoughtLevel,
|
|
181
|
+
profileLabel: profileLabel ?? '',
|
|
182
|
+
profileName: profileName ?? '',
|
|
93
183
|
};
|
|
184
|
+
if (version?.trim()) {
|
|
185
|
+
nextState.version = version.trim();
|
|
186
|
+
}
|
|
187
|
+
this.bannerState = nextState;
|
|
94
188
|
}
|
|
95
|
-
|
|
189
|
+
/**
|
|
190
|
+
* Updates the session information banner with new model/provider.
|
|
191
|
+
* Attempts in-place update if possible, otherwise re-renders.
|
|
192
|
+
*/
|
|
193
|
+
updateSessionInfo(model, provider) {
|
|
96
194
|
const state = this.bannerState;
|
|
97
195
|
if (!state) {
|
|
98
196
|
return;
|
|
99
197
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
198
|
+
// Validate inputs
|
|
199
|
+
if (!model?.trim() || !provider?.trim()) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const lines = this.buildSessionLines(state.profileLabel, state.profileName, model, provider, state.workingDir, state.width);
|
|
203
|
+
const banner = this.buildBanner('Erosolar CLI', state.width, lines, this.buildBannerOptions(state.version));
|
|
104
204
|
const height = this.measureBannerHeight(banner);
|
|
205
|
+
// If height changed or rewrite failed, do full re-render
|
|
105
206
|
if (height !== state.height || !this.tryRewriteBanner(state, banner)) {
|
|
106
|
-
this.renderAndStoreBanner(state, model, provider
|
|
207
|
+
this.renderAndStoreBanner(state, model, provider);
|
|
107
208
|
return;
|
|
108
209
|
}
|
|
210
|
+
// Update succeeded, update state
|
|
109
211
|
state.model = model;
|
|
110
212
|
state.provider = provider;
|
|
111
|
-
state.thoughtLevel = nextThoughtLevel;
|
|
112
213
|
}
|
|
113
214
|
showThinking(message = 'Thinking...') {
|
|
114
215
|
if (this.activeSpinner) {
|
|
115
216
|
this.activeSpinner.stop();
|
|
116
217
|
}
|
|
117
|
-
|
|
218
|
+
// Use Claude Code style spinner with epsilon: ∴, ε, and ✻
|
|
219
|
+
this.activeSpinner = createSpinner(message, {
|
|
220
|
+
spinner: {
|
|
221
|
+
interval: DISPLAY_CONSTANTS.SPINNER_INTERVAL,
|
|
222
|
+
frames: [...SPINNER_FRAMES],
|
|
223
|
+
},
|
|
224
|
+
}).start();
|
|
225
|
+
}
|
|
226
|
+
updateThinking(message) {
|
|
227
|
+
if (this.activeSpinner) {
|
|
228
|
+
this.activeSpinner.update({ text: message });
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
this.showThinking(message);
|
|
232
|
+
}
|
|
118
233
|
}
|
|
119
234
|
stopThinking() {
|
|
120
235
|
if (this.activeSpinner) {
|
|
121
|
-
this.activeSpinner.
|
|
236
|
+
this.activeSpinner.clear();
|
|
122
237
|
this.activeSpinner = null;
|
|
123
238
|
}
|
|
124
239
|
}
|
|
@@ -127,19 +242,23 @@ export class Display {
|
|
|
127
242
|
return;
|
|
128
243
|
}
|
|
129
244
|
const isThought = metadata?.isFinal === false;
|
|
130
|
-
const body = isThought ? this.
|
|
245
|
+
const body = isThought ? this.buildClaudeStyleThought(content) : this.buildChatBox(content, metadata);
|
|
131
246
|
if (!body.trim()) {
|
|
132
247
|
return;
|
|
133
248
|
}
|
|
134
|
-
|
|
135
|
-
|
|
249
|
+
this.withOutput(() => {
|
|
250
|
+
console.log(body);
|
|
251
|
+
console.log();
|
|
252
|
+
});
|
|
136
253
|
}
|
|
137
254
|
showAction(text, status = 'info') {
|
|
138
255
|
if (!text.trim()) {
|
|
139
256
|
return;
|
|
140
257
|
}
|
|
141
258
|
const icon = this.formatActionIcon(status);
|
|
142
|
-
|
|
259
|
+
this.withOutput(() => {
|
|
260
|
+
console.log(this.wrapWithPrefix(text, `${icon} `));
|
|
261
|
+
});
|
|
143
262
|
}
|
|
144
263
|
showSubAction(text, status = 'info') {
|
|
145
264
|
if (!text.trim()) {
|
|
@@ -153,8 +272,10 @@ export class Display {
|
|
|
153
272
|
if (!rendered.length) {
|
|
154
273
|
return;
|
|
155
274
|
}
|
|
156
|
-
|
|
157
|
-
|
|
275
|
+
this.withOutput(() => {
|
|
276
|
+
console.log(rendered.join('\n'));
|
|
277
|
+
console.log();
|
|
278
|
+
});
|
|
158
279
|
}
|
|
159
280
|
buildWrappedSubActionLines(text, status) {
|
|
160
281
|
const lines = text.split('\n').map((line) => line.trimEnd());
|
|
@@ -166,7 +287,7 @@ export class Display {
|
|
|
166
287
|
}
|
|
167
288
|
const rendered = [];
|
|
168
289
|
for (let index = 0; index < lines.length; index += 1) {
|
|
169
|
-
const segment = lines[index];
|
|
290
|
+
const segment = lines[index] ?? '';
|
|
170
291
|
const isLast = index === lines.length - 1;
|
|
171
292
|
const { prefix, continuation } = this.buildSubActionPrefixes(status, isLast);
|
|
172
293
|
rendered.push(this.wrapWithPrefix(segment, prefix, { continuationPrefix: continuation }));
|
|
@@ -178,9 +299,9 @@ export class Display {
|
|
|
178
299
|
if (!normalized) {
|
|
179
300
|
return [];
|
|
180
301
|
}
|
|
181
|
-
const width = Math.max(
|
|
302
|
+
const width = Math.max(DISPLAY_CONSTANTS.MIN_ACTION_WIDTH, Math.min(getTerminalColumns(), DISPLAY_CONSTANTS.MAX_ACTION_WIDTH));
|
|
182
303
|
const samplePrefix = this.buildSubActionPrefixes(status, true).prefix;
|
|
183
|
-
const contentWidth = Math.max(
|
|
304
|
+
const contentWidth = Math.max(DISPLAY_CONSTANTS.MIN_CONTENT_WIDTH, width - this.visibleLength(samplePrefix));
|
|
184
305
|
const blocks = formatRichContent(normalized, contentWidth);
|
|
185
306
|
if (!blocks.length) {
|
|
186
307
|
return [];
|
|
@@ -203,8 +324,10 @@ export class Display {
|
|
|
203
324
|
}
|
|
204
325
|
}
|
|
205
326
|
showSystemMessage(content) {
|
|
206
|
-
|
|
207
|
-
|
|
327
|
+
this.withOutput(() => {
|
|
328
|
+
console.log(content.trim());
|
|
329
|
+
console.log();
|
|
330
|
+
});
|
|
208
331
|
}
|
|
209
332
|
showError(message) {
|
|
210
333
|
const callout = renderCallout(message, {
|
|
@@ -213,7 +336,9 @@ export class Display {
|
|
|
213
336
|
title: 'Error',
|
|
214
337
|
width: this.getBannerWidth(),
|
|
215
338
|
});
|
|
216
|
-
|
|
339
|
+
this.withOutput(() => {
|
|
340
|
+
console.error(`\n${callout}\n`);
|
|
341
|
+
});
|
|
217
342
|
}
|
|
218
343
|
showWarning(message) {
|
|
219
344
|
const callout = renderCallout(message, {
|
|
@@ -222,7 +347,9 @@ export class Display {
|
|
|
222
347
|
title: 'Warning',
|
|
223
348
|
width: this.getBannerWidth(),
|
|
224
349
|
});
|
|
225
|
-
|
|
350
|
+
this.withOutput(() => {
|
|
351
|
+
console.warn(`${callout}`);
|
|
352
|
+
});
|
|
226
353
|
}
|
|
227
354
|
showInfo(message) {
|
|
228
355
|
const callout = renderCallout(message, {
|
|
@@ -231,80 +358,65 @@ export class Display {
|
|
|
231
358
|
title: 'Info',
|
|
232
359
|
width: this.getBannerWidth(),
|
|
233
360
|
});
|
|
234
|
-
|
|
361
|
+
this.withOutput(() => {
|
|
362
|
+
console.log(callout);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
showAvailableTools(_tools) {
|
|
366
|
+
// Hidden by default to match Claude Code style
|
|
367
|
+
// Tools are available but not listed verbosely on startup
|
|
368
|
+
// Parameter prefixed with underscore to indicate intentionally unused
|
|
235
369
|
}
|
|
236
370
|
showPlanningStep(step, index, total) {
|
|
371
|
+
// Validate inputs
|
|
372
|
+
if (!step?.trim()) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if (index < 1 || total < 1 || index > total) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const width = Math.max(DISPLAY_CONSTANTS.MIN_THOUGHT_WIDTH, Math.min(getTerminalColumns(), DISPLAY_CONSTANTS.MAX_MESSAGE_WIDTH));
|
|
237
379
|
const heading = renderSectionHeading(`Plan ${index}/${total}`, {
|
|
238
380
|
subtitle: step,
|
|
239
381
|
icon: icons.arrow,
|
|
240
382
|
tone: 'info',
|
|
241
|
-
width
|
|
383
|
+
width,
|
|
384
|
+
});
|
|
385
|
+
this.withOutput(() => {
|
|
386
|
+
console.log(heading);
|
|
242
387
|
});
|
|
243
|
-
console.log(heading);
|
|
244
388
|
}
|
|
245
389
|
clear() {
|
|
246
|
-
|
|
390
|
+
this.withOutput(() => {
|
|
391
|
+
console.clear();
|
|
392
|
+
});
|
|
247
393
|
this.stdoutTracker.reset();
|
|
248
394
|
if (this.bannerState) {
|
|
249
|
-
this.renderAndStoreBanner(this.bannerState, this.bannerState.model, this.bannerState.provider
|
|
395
|
+
this.renderAndStoreBanner(this.bannerState, this.bannerState.model, this.bannerState.provider);
|
|
250
396
|
}
|
|
251
397
|
}
|
|
252
398
|
newLine() {
|
|
253
|
-
|
|
399
|
+
this.withOutput(() => {
|
|
400
|
+
console.log();
|
|
401
|
+
});
|
|
254
402
|
}
|
|
255
403
|
getBannerWidth() {
|
|
256
404
|
const availableColumns = getTerminalColumns();
|
|
257
|
-
const effectiveWidth = Math.max(
|
|
258
|
-
return Math.min(Math.max(effectiveWidth,
|
|
405
|
+
const effectiveWidth = Math.max(DISPLAY_CONSTANTS.MIN_BANNER_WIDTH, availableColumns - DISPLAY_CONSTANTS.BANNER_PADDING);
|
|
406
|
+
return Math.min(Math.max(effectiveWidth, DISPLAY_CONSTANTS.MIN_BANNER_WIDTH), DISPLAY_CONSTANTS.MAX_BANNER_WIDTH);
|
|
259
407
|
}
|
|
260
|
-
buildSessionLines(profileLabel, profileName, model, provider, workingDir, width
|
|
261
|
-
const accent = `${theme.accent('◆')} ${theme.bold('Interactive Session Ready')}`;
|
|
408
|
+
buildSessionLines(profileLabel, profileName, model, provider, workingDir, width) {
|
|
262
409
|
const normalizedLabel = profileLabel ? profileLabel.trim() : '';
|
|
263
410
|
const normalizedProfile = profileName ? profileName.trim() : '';
|
|
264
411
|
const agentLabel = normalizedLabel || normalizedProfile || 'Active agent';
|
|
265
|
-
const
|
|
266
|
-
if (thoughtLevel) {
|
|
267
|
-
modelSegments.push(`${thoughtLevel} thought level`);
|
|
268
|
-
}
|
|
269
|
-
const modelSummary = modelSegments.join(' • ');
|
|
412
|
+
const modelSummary = [this.formatModelLabel(model), provider].join(' • ');
|
|
270
413
|
const lines = [
|
|
271
|
-
|
|
272
|
-
'',
|
|
273
|
-
...this.formatInfoBlock('Agent', agentLabel, width),
|
|
274
|
-
];
|
|
275
|
-
if (normalizedProfile) {
|
|
276
|
-
lines.push(...this.formatInfoBlock('Profile', normalizedProfile, width));
|
|
277
|
-
}
|
|
278
|
-
lines.push(...this.formatInfoBlock('Model', modelSummary, width), ...this.formatInfoBlock('Workspace', workingDir, width));
|
|
279
|
-
const statusSegments = [
|
|
280
|
-
{ label: 'Agent', value: agentLabel, tone: 'accent', icon: icons.assistant },
|
|
414
|
+
...this.formatInfoBlock('Agent', agentLabel, width, this.getInfoFieldStyle('agent')),
|
|
281
415
|
];
|
|
282
416
|
if (normalizedProfile) {
|
|
283
|
-
|
|
284
|
-
label: 'Profile',
|
|
285
|
-
value: normalizedProfile,
|
|
286
|
-
tone: 'neutral',
|
|
287
|
-
icon: icons.info,
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
statusSegments.push({
|
|
291
|
-
label: 'Model',
|
|
292
|
-
value: this.describeModelForStatus(model, thoughtLevel),
|
|
293
|
-
tone: 'info',
|
|
294
|
-
icon: icons.info,
|
|
295
|
-
}, {
|
|
296
|
-
label: 'Tool Budget',
|
|
297
|
-
value: 'Unlimited',
|
|
298
|
-
tone: 'success',
|
|
299
|
-
icon: icons.tool,
|
|
300
|
-
});
|
|
301
|
-
const statusBar = renderStatusBar(statusSegments, { width });
|
|
302
|
-
if (statusBar.trim().length) {
|
|
303
|
-
lines.push('');
|
|
304
|
-
for (const row of statusBar.split('\n')) {
|
|
305
|
-
lines.push(this.padLine(row, width));
|
|
306
|
-
}
|
|
417
|
+
lines.push(...this.formatInfoBlock('Profile', normalizedProfile, width, this.getInfoFieldStyle('profile')));
|
|
307
418
|
}
|
|
419
|
+
lines.push(...this.formatInfoBlock('Model', modelSummary, width, this.getInfoFieldStyle('model')), ...this.formatInfoBlock('Workspace', workingDir, width, this.getInfoFieldStyle('workspace')));
|
|
308
420
|
return lines;
|
|
309
421
|
}
|
|
310
422
|
measureBannerHeight(banner) {
|
|
@@ -314,53 +426,69 @@ export class Display {
|
|
|
314
426
|
const lines = banner.split('\n').length;
|
|
315
427
|
return lines;
|
|
316
428
|
}
|
|
429
|
+
/**
|
|
430
|
+
* Attempts to rewrite the banner in place using terminal cursor manipulation.
|
|
431
|
+
* Returns true if successful, false if rewrite is not possible.
|
|
432
|
+
*/
|
|
317
433
|
tryRewriteBanner(state, banner) {
|
|
434
|
+
// Validate TTY availability
|
|
318
435
|
if (!process.stdout.isTTY) {
|
|
319
436
|
return false;
|
|
320
437
|
}
|
|
438
|
+
// Validate banner state
|
|
439
|
+
if (!banner || state.height <= 0) {
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
321
442
|
const linesWritten = this.stdoutTracker.totalLines;
|
|
322
443
|
const linesAfterBanner = linesWritten - (state.startLine + state.height);
|
|
444
|
+
// Cannot rewrite if banner position is invalid
|
|
323
445
|
if (linesAfterBanner < 0) {
|
|
324
446
|
return false;
|
|
325
447
|
}
|
|
326
448
|
const totalOffset = linesAfterBanner + state.height;
|
|
327
449
|
const maxRows = process.stdout.rows;
|
|
328
|
-
|
|
450
|
+
// Cannot rewrite if offset exceeds terminal height
|
|
451
|
+
if (typeof maxRows === 'number' && maxRows > 0 && totalOffset > maxRows) {
|
|
329
452
|
return false;
|
|
330
453
|
}
|
|
331
454
|
try {
|
|
332
|
-
|
|
333
|
-
|
|
455
|
+
this.withOutput(() => {
|
|
456
|
+
// Move cursor up to banner start
|
|
457
|
+
moveCursor(process.stdout, 0, -totalOffset);
|
|
458
|
+
cursorTo(process.stdout, 0);
|
|
459
|
+
// Write new banner without tracking
|
|
460
|
+
this.stdoutTracker.withSuspended(() => {
|
|
461
|
+
process.stdout.write(`${banner}\n`);
|
|
462
|
+
});
|
|
463
|
+
// Restore cursor position
|
|
464
|
+
if (linesAfterBanner > 0) {
|
|
465
|
+
moveCursor(process.stdout, 0, linesAfterBanner);
|
|
466
|
+
}
|
|
467
|
+
cursorTo(process.stdout, 0);
|
|
468
|
+
});
|
|
469
|
+
return true;
|
|
334
470
|
}
|
|
335
|
-
catch {
|
|
471
|
+
catch (error) {
|
|
472
|
+
// Cursor manipulation failed (e.g., terminal doesn't support it)
|
|
473
|
+
if (error instanceof Error) {
|
|
474
|
+
// Could log error in debug mode if needed
|
|
475
|
+
}
|
|
336
476
|
return false;
|
|
337
477
|
}
|
|
338
|
-
this.stdoutTracker.withSuspended(() => {
|
|
339
|
-
process.stdout.write(`${banner}\n`);
|
|
340
|
-
});
|
|
341
|
-
if (linesAfterBanner > 0) {
|
|
342
|
-
moveCursor(process.stdout, 0, linesAfterBanner);
|
|
343
|
-
cursorTo(process.stdout, 0);
|
|
344
|
-
}
|
|
345
|
-
else {
|
|
346
|
-
cursorTo(process.stdout, 0);
|
|
347
|
-
}
|
|
348
|
-
return true;
|
|
349
478
|
}
|
|
350
|
-
renderAndStoreBanner(state, model, provider
|
|
479
|
+
renderAndStoreBanner(state, model, provider) {
|
|
351
480
|
const width = this.getBannerWidth();
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
const bannerOptions = state.version ? { badge: state.version } : undefined;
|
|
355
|
-
const banner = this.buildBanner('Erosolar CLI', width, lines, bannerOptions);
|
|
481
|
+
const lines = this.buildSessionLines(state.profileLabel, state.profileName, model, provider, state.workingDir, width);
|
|
482
|
+
const banner = this.buildBanner('Erosolar CLI', width, lines, this.buildBannerOptions(state.version));
|
|
356
483
|
const startLine = this.stdoutTracker.totalLines;
|
|
357
|
-
|
|
484
|
+
this.withOutput(() => {
|
|
485
|
+
console.log(banner);
|
|
486
|
+
});
|
|
358
487
|
state.startLine = startLine;
|
|
359
488
|
state.height = this.measureBannerHeight(banner);
|
|
360
489
|
state.width = width;
|
|
361
490
|
state.model = model;
|
|
362
491
|
state.provider = provider;
|
|
363
|
-
state.thoughtLevel = effectiveThought;
|
|
364
492
|
}
|
|
365
493
|
formatModelLabel(model) {
|
|
366
494
|
if (/gpt-5\.1-?codex/i.test(model)) {
|
|
@@ -389,55 +517,36 @@ export class Display {
|
|
|
389
517
|
}
|
|
390
518
|
return model;
|
|
391
519
|
}
|
|
392
|
-
describeModelForStatus(model, thoughtLevel) {
|
|
393
|
-
const base = this.formatModelLabel(model);
|
|
394
|
-
return thoughtLevel ? `${base} (${thoughtLevel})` : base;
|
|
395
|
-
}
|
|
396
520
|
buildChatBox(content, metadata) {
|
|
397
521
|
const normalized = content.trim();
|
|
398
522
|
if (!normalized) {
|
|
399
523
|
return '';
|
|
400
524
|
}
|
|
401
525
|
const width = this.resolveMessageWidth();
|
|
402
|
-
const
|
|
403
|
-
|
|
526
|
+
const panel = renderMessagePanel(normalized, {
|
|
527
|
+
width,
|
|
528
|
+
title: 'Assistant',
|
|
529
|
+
icon: icons.assistant,
|
|
530
|
+
accentColor: theme.assistant ?? theme.primary,
|
|
531
|
+
borderColor: theme.ui.border,
|
|
532
|
+
});
|
|
404
533
|
const telemetry = this.formatTelemetryLine(metadata);
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
lines.push(telemetry);
|
|
534
|
+
if (!telemetry) {
|
|
535
|
+
return panel;
|
|
408
536
|
}
|
|
409
|
-
return
|
|
537
|
+
return `${panel}\n${telemetry}`;
|
|
410
538
|
}
|
|
411
539
|
resolveMessageWidth() {
|
|
412
540
|
const columns = getTerminalColumns();
|
|
413
|
-
return Math.max(
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
buildThoughtStatus(content) {
|
|
423
|
-
const blocks = content
|
|
424
|
-
.split(/\n{2,}/)
|
|
425
|
-
.map((block) => block.trimEnd())
|
|
426
|
-
.filter((block) => block.trim().length > 0);
|
|
427
|
-
if (!blocks.length) {
|
|
428
|
-
return '';
|
|
429
|
-
}
|
|
430
|
-
const format = this.getThoughtFormat();
|
|
431
|
-
const lines = [];
|
|
432
|
-
blocks.forEach((block, index) => {
|
|
433
|
-
this.appendThoughtBlock(block, format, lines);
|
|
434
|
-
if (index < blocks.length - 1) {
|
|
435
|
-
lines.push('');
|
|
436
|
-
}
|
|
437
|
-
});
|
|
438
|
-
return lines.join('\n');
|
|
439
|
-
}
|
|
440
|
-
appendThoughtBlock(block, format, output) {
|
|
541
|
+
return Math.max(DISPLAY_CONSTANTS.MIN_MESSAGE_WIDTH, Math.min(columns - DISPLAY_CONSTANTS.MESSAGE_PADDING, DISPLAY_CONSTANTS.MAX_MESSAGE_WIDTH));
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Legacy method for appending thought blocks with tree-like formatting.
|
|
545
|
+
* Kept for backwards compatibility but not actively used.
|
|
546
|
+
* @deprecated Use buildClaudeStyleThought instead
|
|
547
|
+
*/
|
|
548
|
+
// @ts-expect-error - Legacy method kept for backwards compatibility
|
|
549
|
+
_appendThoughtBlock(block, format, output) {
|
|
441
550
|
const rawLines = block.split('\n');
|
|
442
551
|
const indices = rawLines
|
|
443
552
|
.map((line, index) => (line.trim().length ? index : -1))
|
|
@@ -448,7 +557,7 @@ export class Display {
|
|
|
448
557
|
const lastIndex = indices[indices.length - 1];
|
|
449
558
|
let usedFirst = false;
|
|
450
559
|
for (let index = 0; index < rawLines.length; index += 1) {
|
|
451
|
-
const rawLine = rawLines[index];
|
|
560
|
+
const rawLine = rawLines[index] ?? '';
|
|
452
561
|
if (!rawLine.trim()) {
|
|
453
562
|
continue;
|
|
454
563
|
}
|
|
@@ -478,10 +587,16 @@ export class Display {
|
|
|
478
587
|
}
|
|
479
588
|
return options.format.spacer;
|
|
480
589
|
}
|
|
481
|
-
|
|
482
|
-
|
|
590
|
+
/**
|
|
591
|
+
* Legacy method for generating thought formatting configuration.
|
|
592
|
+
* Kept for backwards compatibility but not actively used.
|
|
593
|
+
* @deprecated Use buildClaudeStyleThought instead
|
|
594
|
+
*/
|
|
595
|
+
// @ts-expect-error - Legacy method kept for backwards compatibility
|
|
596
|
+
_getThoughtFormat() {
|
|
597
|
+
const totalWidth = Math.max(DISPLAY_CONSTANTS.MIN_THOUGHT_WIDTH, Math.min(getTerminalColumns(), DISPLAY_CONSTANTS.MAX_THOUGHT_WIDTH));
|
|
483
598
|
const prefixWidth = Math.max(3, this.visibleLength(`${icons.bullet} `));
|
|
484
|
-
const available = Math.max(
|
|
599
|
+
const available = Math.max(DISPLAY_CONSTANTS.MIN_WRAP_WIDTH, totalWidth - prefixWidth);
|
|
485
600
|
return {
|
|
486
601
|
totalWidth,
|
|
487
602
|
prefixWidth,
|
|
@@ -510,11 +625,9 @@ export class Display {
|
|
|
510
625
|
const parts = [];
|
|
511
626
|
const elapsed = this.formatElapsed(metadata.elapsedMs);
|
|
512
627
|
if (elapsed) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
if (context) {
|
|
517
|
-
parts.push(theme.primary(context));
|
|
628
|
+
const elapsedLabel = theme.metrics?.elapsedLabel ?? theme.accent;
|
|
629
|
+
const elapsedValue = theme.metrics?.elapsedValue ?? theme.secondary;
|
|
630
|
+
parts.push(`${elapsedLabel('elapsed')} ${elapsedValue(elapsed)}`);
|
|
518
631
|
}
|
|
519
632
|
if (!parts.length) {
|
|
520
633
|
return '';
|
|
@@ -534,32 +647,63 @@ export class Display {
|
|
|
534
647
|
}
|
|
535
648
|
return `${seconds}s`;
|
|
536
649
|
}
|
|
537
|
-
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
650
|
+
buildClaudeStyleBanner(profileLabel, model, _provider, workingDir, width) {
|
|
651
|
+
const gradient = theme.gradient.cool;
|
|
652
|
+
const dim = theme.ui.muted;
|
|
653
|
+
// Build centered content
|
|
654
|
+
const lines = [];
|
|
655
|
+
// Top border
|
|
656
|
+
lines.push(gradient(`╭${'─'.repeat(width)}╮`));
|
|
657
|
+
// Empty line
|
|
658
|
+
lines.push(gradient('│') + ' '.repeat(width) + gradient('│'));
|
|
659
|
+
// Welcome message - centered
|
|
660
|
+
const userName = process.env['USER'] || 'User';
|
|
661
|
+
const welcome = `Welcome back ${userName}!`;
|
|
662
|
+
lines.push(this.centerLine(welcome, width, gradient));
|
|
663
|
+
// Empty line
|
|
664
|
+
lines.push(gradient('│') + ' '.repeat(width) + gradient('│'));
|
|
665
|
+
// Empty line
|
|
666
|
+
lines.push(gradient('│') + ' '.repeat(width) + gradient('│'));
|
|
667
|
+
// Epsilon logo - centered (Claude Code style)
|
|
668
|
+
const logo = [
|
|
669
|
+
'∴ ε ∴',
|
|
670
|
+
'✻ ε ε ε ✻',
|
|
671
|
+
'∴ ε ∴',
|
|
672
|
+
];
|
|
673
|
+
for (const logoLine of logo) {
|
|
674
|
+
lines.push(this.centerLine(logoLine, width, gradient));
|
|
675
|
+
}
|
|
676
|
+
// Empty line
|
|
677
|
+
lines.push(gradient('│') + ' '.repeat(width) + gradient('│'));
|
|
678
|
+
// Empty line
|
|
679
|
+
lines.push(gradient('│') + ' '.repeat(width) + gradient('│'));
|
|
680
|
+
// Model name - centered
|
|
681
|
+
lines.push(this.centerLine(model, width, gradient));
|
|
682
|
+
// Profile label - centered
|
|
683
|
+
lines.push(this.centerLine(profileLabel, width, gradient, dim));
|
|
684
|
+
// Workspace - centered
|
|
685
|
+
const shortPath = this.abbreviatePath(workingDir, width - 8);
|
|
686
|
+
lines.push(this.centerLine(shortPath, width, gradient, dim));
|
|
687
|
+
// Empty line
|
|
688
|
+
lines.push(gradient('│') + ' '.repeat(width) + gradient('│'));
|
|
689
|
+
// Bottom border
|
|
690
|
+
lines.push(gradient(`╰${'─'.repeat(width)}╯`));
|
|
691
|
+
return lines.join('\n');
|
|
551
692
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
693
|
+
centerLine(text, width, borderColor, textColor) {
|
|
694
|
+
const visibleLen = this.visibleLength(text);
|
|
695
|
+
const padding = Math.max(0, Math.floor((width - visibleLen) / 2));
|
|
696
|
+
const rightPad = width - visibleLen - padding;
|
|
697
|
+
const colored = textColor ? textColor(text) : text;
|
|
698
|
+
return borderColor('│') + ' '.repeat(padding) + colored + ' '.repeat(rightPad) + borderColor('│');
|
|
699
|
+
}
|
|
700
|
+
abbreviatePath(path, maxLen) {
|
|
701
|
+
if (path.length <= maxLen)
|
|
702
|
+
return path;
|
|
703
|
+
const parts = path.split('/');
|
|
704
|
+
if (parts.length <= 2)
|
|
705
|
+
return path;
|
|
706
|
+
return parts[0] + '/.../' + parts[parts.length - 1];
|
|
563
707
|
}
|
|
564
708
|
buildBanner(title, width, lines, options) {
|
|
565
709
|
const badge = options?.badge ? ` ${options.badge}` : '';
|
|
@@ -571,6 +715,12 @@ export class Display {
|
|
|
571
715
|
const bottom = gradient(`╰${'─'.repeat(width)}╯`);
|
|
572
716
|
return `${top}\n${body}\n${bottom}`;
|
|
573
717
|
}
|
|
718
|
+
buildBannerOptions(version) {
|
|
719
|
+
if (!version?.trim()) {
|
|
720
|
+
return undefined;
|
|
721
|
+
}
|
|
722
|
+
return { badge: `${version.trim()} • support@ero.solar` };
|
|
723
|
+
}
|
|
574
724
|
buildBannerLine(text, width) {
|
|
575
725
|
const padded = this.padLine(text, width);
|
|
576
726
|
const tinted = theme.ui.background(theme.ui.text(padded));
|
|
@@ -578,23 +728,72 @@ export class Display {
|
|
|
578
728
|
return `${edge}${tinted}${edge}`;
|
|
579
729
|
}
|
|
580
730
|
padLine(text, width) {
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
731
|
+
const visible = this.visibleLength(text);
|
|
732
|
+
if (visible >= width) {
|
|
733
|
+
return this.truncateVisible(text, width);
|
|
734
|
+
}
|
|
735
|
+
const padding = Math.max(0, width - visible);
|
|
736
|
+
return `${text}${' '.repeat(padding)}`;
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Formats an info block with label and value, wrapping if needed.
|
|
740
|
+
* First line gets the label prefix, subsequent lines are indented.
|
|
741
|
+
*/
|
|
742
|
+
formatInfoBlock(label, value, width, options) {
|
|
743
|
+
// Validate inputs
|
|
744
|
+
if (!label?.trim() || !value?.trim()) {
|
|
745
|
+
return [];
|
|
746
|
+
}
|
|
747
|
+
if (width <= 0) {
|
|
748
|
+
return [value];
|
|
749
|
+
}
|
|
586
750
|
const prefix = `${label.toUpperCase()}: `;
|
|
587
|
-
const
|
|
751
|
+
const prefixLength = prefix.length;
|
|
752
|
+
const available = Math.max(DISPLAY_CONSTANTS.MIN_CONTENT_WIDTH, width - prefixLength);
|
|
588
753
|
const wrapped = this.wrapLine(value, available);
|
|
589
754
|
return wrapped.map((line, index) => {
|
|
590
|
-
const indent = index === 0 ? prefix : ' '.repeat(
|
|
591
|
-
|
|
755
|
+
const indent = index === 0 ? prefix : ' '.repeat(prefixLength);
|
|
756
|
+
const raw = `${indent}${line}`;
|
|
757
|
+
const padded = this.padLine(raw, width);
|
|
758
|
+
if (!options) {
|
|
759
|
+
return padded;
|
|
760
|
+
}
|
|
761
|
+
const labelColor = index === 0 ? options.labelColor : undefined;
|
|
762
|
+
return this.applyInfoLineStyles(padded, prefixLength, line.length, labelColor, options.valueColor);
|
|
592
763
|
});
|
|
593
764
|
}
|
|
765
|
+
applyInfoLineStyles(line, prefixLength, valueLength, labelColor, valueColor) {
|
|
766
|
+
const prefix = line.slice(0, prefixLength);
|
|
767
|
+
const remainder = line.slice(prefixLength);
|
|
768
|
+
const tintedPrefix = labelColor ? labelColor(prefix) : prefix;
|
|
769
|
+
const safeValueLength = Math.max(0, Math.min(valueLength, remainder.length));
|
|
770
|
+
if (!valueColor || safeValueLength <= 0) {
|
|
771
|
+
return `${tintedPrefix}${remainder}`;
|
|
772
|
+
}
|
|
773
|
+
const valueSegment = remainder.slice(0, safeValueLength);
|
|
774
|
+
const trailing = remainder.slice(safeValueLength);
|
|
775
|
+
const tintedValue = valueColor(valueSegment);
|
|
776
|
+
return `${tintedPrefix}${tintedValue}${trailing}`;
|
|
777
|
+
}
|
|
778
|
+
getInfoFieldStyle(field) {
|
|
779
|
+
const labelColor = theme.fields?.label ?? ((text) => text);
|
|
780
|
+
const valueColor = theme.fields?.[field] ?? ((text) => text);
|
|
781
|
+
return {
|
|
782
|
+
labelColor,
|
|
783
|
+
valueColor,
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Wraps text with a prefix on the first line and optional continuation prefix.
|
|
788
|
+
* Handles multi-line text and word wrapping intelligently.
|
|
789
|
+
*/
|
|
594
790
|
wrapWithPrefix(text, prefix, options) {
|
|
595
|
-
|
|
791
|
+
if (!text) {
|
|
792
|
+
return prefix.trimEnd();
|
|
793
|
+
}
|
|
794
|
+
const width = Math.max(DISPLAY_CONSTANTS.MIN_ACTION_WIDTH, Math.min(getTerminalColumns(), DISPLAY_CONSTANTS.MAX_ACTION_WIDTH));
|
|
596
795
|
const prefixWidth = this.visibleLength(prefix);
|
|
597
|
-
const available = Math.max(
|
|
796
|
+
const available = Math.max(DISPLAY_CONSTANTS.MIN_CONTENT_WIDTH, width - prefixWidth);
|
|
598
797
|
const indent = typeof options?.continuationPrefix === 'string'
|
|
599
798
|
? options.continuationPrefix
|
|
600
799
|
: ' '.repeat(Math.max(0, prefixWidth));
|
|
@@ -638,11 +837,19 @@ export class Display {
|
|
|
638
837
|
const colorize = this.resolveStatusColor(status);
|
|
639
838
|
return colorize(`${icons.action}`);
|
|
640
839
|
}
|
|
840
|
+
buildClaudeStyleThought(content) {
|
|
841
|
+
// Claude Code style: compact ⏺ prefix for thoughts
|
|
842
|
+
const prefix = theme.ui.muted('⏺') + ' ';
|
|
843
|
+
return this.wrapWithPrefix(content, prefix);
|
|
844
|
+
}
|
|
845
|
+
// @ts-ignore - Legacy method kept for compatibility
|
|
846
|
+
// Keep legacy method to avoid breaking changes
|
|
641
847
|
buildSubActionPrefixes(status, isLast) {
|
|
642
848
|
if (isLast) {
|
|
643
849
|
const colorize = this.resolveStatusColor(status);
|
|
850
|
+
// Claude Code style: use ⎿ for sub-action prefix
|
|
644
851
|
return {
|
|
645
|
-
prefix: ` ${colorize(
|
|
852
|
+
prefix: ` ${colorize(icons.subaction)} `,
|
|
646
853
|
continuation: ' ',
|
|
647
854
|
};
|
|
648
855
|
}
|
|
@@ -652,7 +859,12 @@ export class Display {
|
|
|
652
859
|
continuation: ` ${branch} `,
|
|
653
860
|
};
|
|
654
861
|
}
|
|
862
|
+
/**
|
|
863
|
+
* Wraps a single line of text to fit within the specified width.
|
|
864
|
+
* Intelligently handles word breaking and preserves spaces.
|
|
865
|
+
*/
|
|
655
866
|
wrapLine(text, width) {
|
|
867
|
+
// Handle edge cases
|
|
656
868
|
if (width <= 0) {
|
|
657
869
|
return [text];
|
|
658
870
|
}
|
|
@@ -662,70 +874,119 @@ export class Display {
|
|
|
662
874
|
if (text.length <= width) {
|
|
663
875
|
return [text];
|
|
664
876
|
}
|
|
877
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
878
|
+
// If no words, chunk the entire text
|
|
879
|
+
if (!words.length) {
|
|
880
|
+
return this.chunkWord(text, width);
|
|
881
|
+
}
|
|
665
882
|
const lines = [];
|
|
666
883
|
let current = '';
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
if (
|
|
670
|
-
|
|
671
|
-
}
|
|
672
|
-
if (!current.length) {
|
|
673
|
-
if (word.length <= width) {
|
|
674
|
-
current = word;
|
|
675
|
-
return;
|
|
676
|
-
}
|
|
677
|
-
const chunks = this.chunkWord(word, width);
|
|
678
|
-
lines.push(...chunks.slice(0, -1));
|
|
679
|
-
current = chunks[chunks.length - 1];
|
|
680
|
-
return;
|
|
681
|
-
}
|
|
682
|
-
if (current.length + 1 + word.length <= width) {
|
|
683
|
-
current += ` ${word}`;
|
|
684
|
-
return;
|
|
884
|
+
for (const word of words) {
|
|
885
|
+
const appendResult = this.tryAppendWord(current, word, width);
|
|
886
|
+
if (appendResult.shouldFlush) {
|
|
887
|
+
lines.push(current);
|
|
685
888
|
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
889
|
+
if (appendResult.chunks.length > 0) {
|
|
890
|
+
// Word was too long and was chunked
|
|
891
|
+
lines.push(...appendResult.chunks.slice(0, -1));
|
|
892
|
+
current = appendResult.chunks[appendResult.chunks.length - 1] ?? '';
|
|
689
893
|
}
|
|
690
894
|
else {
|
|
691
|
-
|
|
692
|
-
lines.push(...chunks.slice(0, -1));
|
|
693
|
-
current = chunks[chunks.length - 1];
|
|
895
|
+
current = appendResult.newCurrent;
|
|
694
896
|
}
|
|
695
|
-
};
|
|
696
|
-
if (!words.length) {
|
|
697
|
-
const chunks = this.chunkWord(text, width);
|
|
698
|
-
return chunks;
|
|
699
|
-
}
|
|
700
|
-
for (const word of words) {
|
|
701
|
-
appendWord(word);
|
|
702
897
|
}
|
|
703
898
|
if (current) {
|
|
704
899
|
lines.push(current);
|
|
705
900
|
}
|
|
706
901
|
return lines.length ? lines : [''];
|
|
707
902
|
}
|
|
903
|
+
/**
|
|
904
|
+
* Attempts to append a word to the current line.
|
|
905
|
+
* Returns instructions on how to handle the word.
|
|
906
|
+
*/
|
|
907
|
+
tryAppendWord(current, word, width) {
|
|
908
|
+
if (!word) {
|
|
909
|
+
return { shouldFlush: false, newCurrent: current, chunks: [] };
|
|
910
|
+
}
|
|
911
|
+
// Empty current line - start new line with word
|
|
912
|
+
if (!current) {
|
|
913
|
+
if (word.length <= width) {
|
|
914
|
+
return { shouldFlush: false, newCurrent: word, chunks: [] };
|
|
915
|
+
}
|
|
916
|
+
// Word too long, need to chunk it
|
|
917
|
+
return { shouldFlush: false, newCurrent: '', chunks: this.chunkWord(word, width) };
|
|
918
|
+
}
|
|
919
|
+
// Word fits on current line with space
|
|
920
|
+
if (current.length + 1 + word.length <= width) {
|
|
921
|
+
return { shouldFlush: false, newCurrent: `${current} ${word}`, chunks: [] };
|
|
922
|
+
}
|
|
923
|
+
// Word doesn't fit - flush current and start new line
|
|
924
|
+
if (word.length <= width) {
|
|
925
|
+
return { shouldFlush: true, newCurrent: word, chunks: [] };
|
|
926
|
+
}
|
|
927
|
+
// Word doesn't fit and is too long - flush current and chunk word
|
|
928
|
+
return { shouldFlush: true, newCurrent: '', chunks: this.chunkWord(word, width) };
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Splits a long word into chunks that fit within the specified width.
|
|
932
|
+
* Used when a single word is too long to fit on one line.
|
|
933
|
+
*/
|
|
708
934
|
chunkWord(word, width) {
|
|
709
|
-
if (width <= 0) {
|
|
710
|
-
return [word];
|
|
935
|
+
if (width <= 0 || !word) {
|
|
936
|
+
return word ? [word] : [''];
|
|
711
937
|
}
|
|
712
938
|
const chunks = [];
|
|
713
939
|
for (let i = 0; i < word.length; i += width) {
|
|
714
940
|
chunks.push(word.slice(i, i + width));
|
|
715
941
|
}
|
|
716
|
-
return chunks;
|
|
942
|
+
return chunks.length > 0 ? chunks : [''];
|
|
717
943
|
}
|
|
944
|
+
/**
|
|
945
|
+
* Pads a prefix string to the specified width with spaces.
|
|
946
|
+
*/
|
|
718
947
|
padPrefix(value, width) {
|
|
719
|
-
if (value.length >= width) {
|
|
948
|
+
if (!value || value.length >= width || width <= 0) {
|
|
720
949
|
return value;
|
|
721
950
|
}
|
|
722
951
|
return value.padEnd(width, ' ');
|
|
723
952
|
}
|
|
953
|
+
/**
|
|
954
|
+
* Truncates a string to fit within the specified width,
|
|
955
|
+
* accounting for ANSI color codes and adding ellipsis.
|
|
956
|
+
*/
|
|
957
|
+
truncateVisible(value, width) {
|
|
958
|
+
if (width <= 0) {
|
|
959
|
+
return '';
|
|
960
|
+
}
|
|
961
|
+
if (!value) {
|
|
962
|
+
return '';
|
|
963
|
+
}
|
|
964
|
+
const plain = this.stripAnsi(value);
|
|
965
|
+
if (plain.length <= width) {
|
|
966
|
+
return value;
|
|
967
|
+
}
|
|
968
|
+
const slice = plain.slice(0, Math.max(1, width - 1));
|
|
969
|
+
return `${slice}…`;
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Returns the visible length of a string, excluding ANSI escape codes.
|
|
973
|
+
*/
|
|
724
974
|
visibleLength(value) {
|
|
975
|
+
if (!value) {
|
|
976
|
+
return 0;
|
|
977
|
+
}
|
|
725
978
|
return this.stripAnsi(value).length;
|
|
726
979
|
}
|
|
980
|
+
/**
|
|
981
|
+
* Removes ANSI escape codes from a string to get the visible text.
|
|
982
|
+
* Uses the standard ANSI escape sequence pattern.
|
|
983
|
+
*/
|
|
727
984
|
stripAnsi(value) {
|
|
985
|
+
if (!value) {
|
|
986
|
+
return '';
|
|
987
|
+
}
|
|
728
988
|
return value.replace(/\u001B\[[0-?]*[ -/]*[@-~]/g, '');
|
|
729
989
|
}
|
|
730
990
|
}
|
|
731
991
|
export const display = new Display();
|
|
992
|
+
//# sourceMappingURL=display.js.map
|