byterover-cli 0.3.5 → 0.4.0
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 +119 -63
- package/bin/dev.js +8 -1
- package/bin/run.js +7 -0
- package/dist/commands/cipher-agent/run.d.ts +30 -0
- package/dist/commands/cipher-agent/run.js +123 -61
- package/dist/commands/cipher-agent/set-prompt.d.ts +2 -0
- package/dist/commands/cipher-agent/set-prompt.js +13 -8
- package/dist/commands/cipher-agent/show-prompt.d.ts +2 -0
- package/dist/commands/cipher-agent/show-prompt.js +17 -12
- package/dist/commands/curate.d.ts +3 -60
- package/dist/commands/curate.js +45 -341
- package/dist/commands/foo.d.ts +4 -2
- package/dist/commands/foo.js +21 -16
- package/dist/commands/main.d.ts +9 -0
- package/dist/commands/main.js +34 -0
- package/dist/commands/query.d.ts +2 -48
- package/dist/commands/query.js +19 -287
- package/dist/commands/status.d.ts +2 -13
- package/dist/commands/status.js +12 -91
- package/dist/commands/watch.d.ts +2 -0
- package/dist/commands/watch.js +23 -19
- package/dist/config/environment.d.ts +1 -1
- package/dist/config/environment.js +2 -2
- package/dist/constants.d.ts +4 -5
- package/dist/constants.js +5 -5
- package/dist/core/domain/cipher/errors/storage-error.d.ts +89 -0
- package/dist/core/domain/cipher/errors/storage-error.js +130 -0
- package/dist/core/domain/cipher/queue/types.d.ts +71 -0
- package/dist/core/domain/cipher/queue/types.js +9 -0
- package/dist/core/domain/cipher/storage/message-storage-types.d.ts +218 -0
- package/dist/core/domain/cipher/storage/message-storage-types.js +18 -0
- package/dist/core/domain/cipher/tools/constants.d.ts +1 -0
- package/dist/core/domain/cipher/tools/constants.js +1 -0
- package/dist/core/domain/entities/event.d.ts +1 -1
- package/dist/core/domain/entities/event.js +5 -0
- package/dist/core/domain/entities/global-config.d.ts +36 -0
- package/dist/core/domain/entities/global-config.js +66 -0
- package/dist/core/domain/knowledge/directory-manager.d.ts +10 -0
- package/dist/core/domain/knowledge/directory-manager.js +18 -0
- package/dist/core/domain/knowledge/markdown-writer.d.ts +9 -0
- package/dist/core/domain/knowledge/markdown-writer.js +51 -1
- package/dist/core/interfaces/cipher/i-agent-storage.d.ts +152 -0
- package/dist/core/interfaces/cipher/i-agent-storage.js +1 -0
- package/dist/core/interfaces/cipher/i-cipher-agent.d.ts +2 -0
- package/dist/core/interfaces/cipher/i-key-storage.d.ts +91 -0
- package/dist/core/interfaces/cipher/i-key-storage.js +1 -0
- package/dist/core/interfaces/i-global-config-store.d.ts +34 -0
- package/dist/core/interfaces/i-global-config-store.js +1 -0
- package/dist/core/interfaces/i-onboarding-preference-store.d.ts +20 -0
- package/dist/core/interfaces/i-onboarding-preference-store.js +1 -0
- package/dist/core/interfaces/i-terminal.d.ts +146 -0
- package/dist/core/interfaces/i-terminal.js +1 -0
- package/dist/core/interfaces/i-workspace-detector-service.d.ts +8 -0
- package/dist/core/interfaces/i-workspace-detector-service.js +1 -0
- package/dist/core/interfaces/usecase/i-clear-use-case.d.ts +6 -0
- package/dist/core/interfaces/usecase/i-clear-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-curate-use-case.d.ts +10 -0
- package/dist/core/interfaces/usecase/i-curate-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-generate-rules-use-case.d.ts +3 -0
- package/dist/core/interfaces/usecase/i-generate-rules-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-init-use-case.d.ts +5 -0
- package/dist/core/interfaces/usecase/i-init-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-login-use-case.d.ts +3 -0
- package/dist/core/interfaces/usecase/i-login-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-logout-use-case.d.ts +5 -0
- package/dist/core/interfaces/usecase/i-logout-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-pull-use-case.d.ts +5 -0
- package/dist/core/interfaces/usecase/i-pull-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-push-use-case.d.ts +6 -0
- package/dist/core/interfaces/usecase/i-push-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-query-use-case.d.ts +9 -0
- package/dist/core/interfaces/usecase/i-query-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-space-list-use-case.d.ts +3 -0
- package/dist/core/interfaces/usecase/i-space-list-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-space-switch-use-case.d.ts +3 -0
- package/dist/core/interfaces/usecase/i-space-switch-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-status-use-case.d.ts +5 -0
- package/dist/core/interfaces/usecase/i-status-use-case.js +1 -0
- package/dist/hooks/init/welcome.js +1 -2
- package/dist/infra/cipher/agent-service-factory.d.ts +13 -6
- package/dist/infra/cipher/agent-service-factory.js +40 -16
- package/dist/infra/cipher/cipher-agent.js +4 -4
- package/dist/infra/cipher/consumer/consumer-lock.d.ts +20 -0
- package/dist/infra/cipher/consumer/consumer-lock.js +40 -0
- package/dist/infra/cipher/consumer/consumer-service.d.ts +99 -0
- package/dist/infra/cipher/consumer/consumer-service.js +165 -0
- package/dist/infra/cipher/consumer/execution-consumer.d.ts +121 -0
- package/dist/infra/cipher/consumer/execution-consumer.js +523 -0
- package/dist/infra/cipher/consumer/index.d.ts +33 -0
- package/dist/infra/cipher/consumer/index.js +33 -0
- package/dist/infra/cipher/consumer/queue-polling-service.d.ts +120 -0
- package/dist/infra/cipher/consumer/queue-polling-service.js +248 -0
- package/dist/infra/cipher/http/internal-llm-http-service.d.ts +94 -0
- package/dist/infra/cipher/http/internal-llm-http-service.js +118 -0
- package/dist/infra/cipher/llm/context/compaction/compaction-service.d.ts +106 -0
- package/dist/infra/cipher/llm/context/compaction/compaction-service.js +132 -0
- package/dist/infra/cipher/llm/context/compaction/index.d.ts +9 -0
- package/dist/infra/cipher/llm/context/compaction/index.js +9 -0
- package/dist/infra/cipher/llm/context/context-manager.d.ts +46 -2
- package/dist/infra/cipher/llm/context/context-manager.js +68 -4
- package/dist/infra/cipher/llm/context/rw-lock.d.ts +72 -0
- package/dist/infra/cipher/llm/context/rw-lock.js +145 -0
- package/dist/infra/cipher/llm/generators/byterover-content-generator.d.ts +7 -7
- package/dist/infra/cipher/llm/generators/byterover-content-generator.js +8 -8
- package/dist/infra/cipher/llm/internal-llm-service.js +2 -0
- package/dist/infra/cipher/session/session-manager.d.ts +4 -4
- package/dist/infra/cipher/session/session-manager.js +5 -5
- package/dist/infra/cipher/storage/agent-storage.d.ts +246 -0
- package/dist/infra/cipher/storage/agent-storage.js +956 -0
- package/dist/infra/cipher/storage/dual-format-history-storage.d.ts +77 -0
- package/dist/infra/cipher/storage/dual-format-history-storage.js +149 -0
- package/dist/infra/cipher/storage/granular-history-storage.d.ts +65 -0
- package/dist/infra/cipher/storage/granular-history-storage.js +118 -0
- package/dist/infra/cipher/storage/message-storage-service.d.ts +108 -0
- package/dist/infra/cipher/storage/message-storage-service.js +529 -0
- package/dist/infra/cipher/storage/process-utils.d.ts +16 -0
- package/dist/infra/cipher/storage/process-utils.js +43 -0
- package/dist/infra/cipher/storage/sqlite-key-storage.d.ts +105 -0
- package/dist/infra/cipher/storage/sqlite-key-storage.js +404 -0
- package/dist/infra/cipher/system-prompt/simple-prompt-factory.d.ts +1 -0
- package/dist/infra/cipher/system-prompt/simple-prompt-factory.js +7 -0
- package/dist/infra/cipher/tools/default-policy-rules.js +1 -1
- package/dist/infra/cipher/tools/implementations/curate-tool.d.ts +10 -0
- package/dist/infra/cipher/tools/implementations/curate-tool.js +371 -0
- package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.js +11 -8
- package/dist/infra/cipher/tools/tool-manager.d.ts +8 -2
- package/dist/infra/cipher/tools/tool-manager.js +29 -2
- package/dist/infra/cipher/tools/tool-registry.js +7 -0
- package/dist/infra/http/authenticated-http-client.d.ts +21 -0
- package/dist/infra/http/authenticated-http-client.js +38 -0
- package/dist/infra/repl/commands/arg-parser.d.ts +97 -0
- package/dist/infra/repl/commands/arg-parser.js +129 -0
- package/dist/infra/repl/commands/clear-command.d.ts +5 -0
- package/dist/infra/repl/commands/clear-command.js +61 -0
- package/dist/infra/repl/commands/curate-command.d.ts +9 -0
- package/dist/infra/repl/commands/curate-command.js +88 -0
- package/dist/infra/repl/commands/gen-rules-command.d.ts +7 -0
- package/dist/infra/repl/commands/gen-rules-command.js +38 -0
- package/dist/infra/repl/commands/index.d.ts +8 -0
- package/dist/infra/repl/commands/index.js +36 -0
- package/dist/infra/repl/commands/init-command.d.ts +7 -0
- package/dist/infra/repl/commands/init-command.js +83 -0
- package/dist/infra/repl/commands/login-command.d.ts +7 -0
- package/dist/infra/repl/commands/login-command.js +50 -0
- package/dist/infra/repl/commands/logout-command.d.ts +5 -0
- package/dist/infra/repl/commands/logout-command.js +48 -0
- package/dist/infra/repl/commands/pull-command.d.ts +5 -0
- package/dist/infra/repl/commands/pull-command.js +61 -0
- package/dist/infra/repl/commands/push-command.d.ts +5 -0
- package/dist/infra/repl/commands/push-command.js +66 -0
- package/dist/infra/repl/commands/query-command.d.ts +5 -0
- package/dist/infra/repl/commands/query-command.js +66 -0
- package/dist/infra/repl/commands/space/index.d.ts +5 -0
- package/dist/infra/repl/commands/space/index.js +14 -0
- package/dist/infra/repl/commands/space/list-command.d.ts +5 -0
- package/dist/infra/repl/commands/space/list-command.js +70 -0
- package/dist/infra/repl/commands/space/switch-command.d.ts +5 -0
- package/dist/infra/repl/commands/space/switch-command.js +37 -0
- package/dist/infra/repl/commands/status-command.d.ts +5 -0
- package/dist/infra/repl/commands/status-command.js +39 -0
- package/dist/infra/repl/repl-startup.d.ts +18 -0
- package/dist/infra/repl/repl-startup.js +26 -0
- package/dist/infra/storage/file-global-config-store.d.ts +22 -0
- package/dist/infra/storage/file-global-config-store.js +65 -0
- package/dist/infra/storage/file-onboarding-preference-store.d.ts +10 -0
- package/dist/infra/storage/file-onboarding-preference-store.js +46 -0
- package/dist/infra/terminal/oclif-terminal.d.ts +19 -0
- package/dist/infra/terminal/oclif-terminal.js +60 -0
- package/dist/infra/terminal/repl-terminal.d.ts +31 -0
- package/dist/infra/terminal/repl-terminal.js +116 -0
- package/dist/infra/tracking/mixpanel-tracking-service.d.ts +11 -1
- package/dist/infra/tracking/mixpanel-tracking-service.js +18 -13
- package/dist/infra/usecase/clear-use-case.d.ts +20 -0
- package/dist/infra/usecase/clear-use-case.js +58 -0
- package/dist/infra/usecase/curate-use-case.d.ts +66 -0
- package/dist/infra/usecase/curate-use-case.js +283 -0
- package/dist/{commands/gen-rules.d.ts → infra/usecase/generate-rules-use-case.d.ts} +14 -20
- package/dist/{commands/gen-rules.js → infra/usecase/generate-rules-use-case.js} +59 -78
- package/dist/infra/usecase/init-use-case.d.ts +139 -0
- package/dist/{commands/init.js → infra/usecase/init-use-case.js} +184 -230
- package/dist/infra/usecase/login-use-case.d.ts +28 -0
- package/dist/infra/usecase/login-use-case.js +88 -0
- package/dist/infra/usecase/logout-use-case.d.ts +22 -0
- package/dist/infra/usecase/logout-use-case.js +51 -0
- package/dist/infra/usecase/pull-use-case.d.ts +35 -0
- package/dist/infra/usecase/pull-use-case.js +89 -0
- package/dist/infra/usecase/push-use-case.d.ts +37 -0
- package/dist/infra/usecase/push-use-case.js +124 -0
- package/dist/infra/usecase/query-use-case.d.ts +78 -0
- package/dist/infra/usecase/query-use-case.js +401 -0
- package/dist/infra/usecase/space-list-use-case.d.ts +27 -0
- package/dist/infra/usecase/space-list-use-case.js +64 -0
- package/dist/infra/usecase/space-switch-use-case.d.ts +36 -0
- package/dist/infra/usecase/space-switch-use-case.js +140 -0
- package/dist/infra/usecase/status-use-case.d.ts +27 -0
- package/dist/infra/usecase/status-use-case.js +97 -0
- package/dist/infra/workspace/workspace-detector-service.d.ts +3 -6
- package/dist/resources/prompts/curate-context-tree-curation.yml +23 -11
- package/dist/resources/prompts/query-context-tree-retrieval.yml +3 -4
- package/dist/resources/prompts/system-prompt.yml +1 -1
- package/dist/resources/prompts/tool-outputs.yml +4 -3
- package/dist/templates/sections/command-reference.md +12 -0
- package/dist/templates/sections/workflow.md +10 -1
- package/dist/tui/app.d.ts +9 -0
- package/dist/tui/app.js +26 -0
- package/dist/tui/components/enter-prompt.d.ts +13 -0
- package/dist/tui/components/enter-prompt.js +15 -0
- package/dist/tui/components/execution/execution-changes.d.ts +14 -0
- package/dist/tui/components/execution/execution-changes.js +15 -0
- package/dist/tui/components/execution/execution-content.d.ts +25 -0
- package/dist/tui/components/execution/execution-content.js +67 -0
- package/dist/tui/components/execution/execution-input.d.ts +12 -0
- package/dist/tui/components/execution/execution-input.js +16 -0
- package/dist/tui/components/execution/execution-progress.d.ts +21 -0
- package/dist/tui/components/execution/execution-progress.js +21 -0
- package/dist/tui/components/execution/execution-status.d.ts +13 -0
- package/dist/tui/components/execution/execution-status.js +19 -0
- package/dist/tui/components/execution/index.d.ts +11 -0
- package/dist/tui/components/execution/index.js +11 -0
- package/dist/tui/components/execution/log-item.d.ts +17 -0
- package/dist/tui/components/execution/log-item.js +25 -0
- package/dist/tui/components/footer.d.ts +5 -0
- package/dist/tui/components/footer.js +12 -0
- package/dist/tui/components/header.d.ts +18 -0
- package/dist/tui/components/header.js +18 -0
- package/dist/tui/components/index.d.ts +17 -0
- package/dist/tui/components/index.js +14 -0
- package/dist/tui/components/inline-prompts/index.d.ts +15 -0
- package/dist/tui/components/inline-prompts/index.js +10 -0
- package/dist/tui/components/inline-prompts/inline-confirm.d.ts +17 -0
- package/dist/tui/components/inline-prompts/inline-confirm.js +32 -0
- package/dist/tui/components/inline-prompts/inline-file-selector.d.ts +43 -0
- package/dist/tui/components/inline-prompts/inline-file-selector.js +185 -0
- package/dist/tui/components/inline-prompts/inline-input.d.ts +19 -0
- package/dist/tui/components/inline-prompts/inline-input.js +32 -0
- package/dist/tui/components/inline-prompts/inline-search.d.ts +20 -0
- package/dist/tui/components/inline-prompts/inline-search.js +50 -0
- package/dist/tui/components/inline-prompts/inline-select.d.ts +20 -0
- package/dist/tui/components/inline-prompts/inline-select.js +34 -0
- package/dist/tui/components/logo.d.ts +43 -0
- package/dist/tui/components/logo.js +103 -0
- package/dist/tui/components/message-item.d.ts +12 -0
- package/dist/tui/components/message-item.js +12 -0
- package/dist/tui/components/onboarding/copyable-prompt.d.ts +15 -0
- package/dist/tui/components/onboarding/copyable-prompt.js +65 -0
- package/dist/tui/components/onboarding/index.d.ts +7 -0
- package/dist/tui/components/onboarding/index.js +6 -0
- package/dist/tui/components/onboarding/onboarding-flow.d.ts +13 -0
- package/dist/tui/components/onboarding/onboarding-flow.js +304 -0
- package/dist/tui/components/onboarding/onboarding-step.d.ts +23 -0
- package/dist/tui/components/onboarding/onboarding-step.js +12 -0
- package/dist/tui/components/output-log.d.ts +14 -0
- package/dist/tui/components/output-log.js +13 -0
- package/dist/tui/components/scrollable-list.d.ts +30 -0
- package/dist/tui/components/scrollable-list.js +121 -0
- package/dist/tui/components/suggestions.d.ts +16 -0
- package/dist/tui/components/suggestions.js +162 -0
- package/dist/tui/components/tab-bar.d.ts +10 -0
- package/dist/tui/components/tab-bar.js +12 -0
- package/dist/tui/constants.d.ts +11 -0
- package/dist/tui/constants.js +13 -0
- package/dist/tui/contexts/auth-context.d.ts +30 -0
- package/dist/tui/contexts/auth-context.js +153 -0
- package/dist/tui/contexts/consumer.d.ts +31 -0
- package/dist/tui/contexts/consumer.js +56 -0
- package/dist/tui/contexts/index.d.ts +6 -0
- package/dist/tui/contexts/index.js +6 -0
- package/dist/tui/contexts/onboarding-context.d.ts +43 -0
- package/dist/tui/contexts/onboarding-context.js +181 -0
- package/dist/tui/contexts/services-context.d.ts +29 -0
- package/dist/tui/contexts/services-context.js +20 -0
- package/dist/tui/contexts/use-commands.d.ts +29 -0
- package/dist/tui/contexts/use-commands.js +53 -0
- package/dist/tui/contexts/use-mode.d.ts +43 -0
- package/dist/tui/contexts/use-mode.js +76 -0
- package/dist/tui/contexts/use-theme.d.ts +53 -0
- package/dist/tui/contexts/use-theme.js +60 -0
- package/dist/tui/hooks/index.d.ts +17 -0
- package/dist/tui/hooks/index.js +14 -0
- package/dist/tui/hooks/use-activity-logs.d.ts +26 -0
- package/dist/tui/hooks/use-activity-logs.js +90 -0
- package/dist/tui/hooks/use-consumer.d.ts +12 -0
- package/dist/tui/hooks/use-consumer.js +50 -0
- package/dist/tui/hooks/use-onboarding.d.ts +7 -0
- package/dist/tui/hooks/use-onboarding.js +6 -0
- package/dist/tui/hooks/use-queue-polling.d.ts +31 -0
- package/dist/tui/hooks/use-queue-polling.js +90 -0
- package/dist/tui/hooks/use-slash-command-processor.d.ts +16 -0
- package/dist/tui/hooks/use-slash-command-processor.js +132 -0
- package/dist/tui/hooks/use-slash-completion.d.ts +30 -0
- package/dist/tui/hooks/use-slash-completion.js +230 -0
- package/dist/tui/hooks/use-tab-navigation.d.ts +10 -0
- package/dist/tui/hooks/use-tab-navigation.js +35 -0
- package/dist/tui/hooks/use-visible-window.d.ts +22 -0
- package/dist/tui/hooks/use-visible-window.js +37 -0
- package/dist/tui/index.d.ts +1 -0
- package/dist/tui/index.js +1 -0
- package/dist/tui/providers/app-providers.d.ts +25 -0
- package/dist/tui/providers/app-providers.js +9 -0
- package/dist/tui/types/commands.d.ts +252 -0
- package/dist/tui/types/commands.js +16 -0
- package/dist/tui/types/dialogs.d.ts +37 -0
- package/dist/tui/types/dialogs.js +4 -0
- package/dist/tui/types/index.d.ts +11 -0
- package/dist/tui/types/index.js +7 -0
- package/dist/tui/types/messages.d.ts +55 -0
- package/dist/tui/types/messages.js +4 -0
- package/dist/tui/types/prompts.d.ts +100 -0
- package/dist/tui/types/prompts.js +4 -0
- package/dist/tui/types/ui.d.ts +14 -0
- package/dist/tui/types/ui.js +4 -0
- package/dist/tui/types.d.ts +1 -0
- package/dist/tui/types.js +1 -0
- package/dist/tui/views/command-view.d.ts +12 -0
- package/dist/tui/views/command-view.js +451 -0
- package/dist/tui/views/index.d.ts +6 -0
- package/dist/tui/views/index.js +6 -0
- package/dist/tui/views/login-view.d.ts +10 -0
- package/dist/tui/views/login-view.js +30 -0
- package/dist/tui/views/logs-view.d.ts +11 -0
- package/dist/tui/views/logs-view.js +73 -0
- package/dist/utils/file-validator.d.ts +16 -0
- package/dist/utils/file-validator.js +81 -0
- package/dist/utils/global-config-path.d.ts +15 -0
- package/dist/utils/global-config-path.js +38 -0
- package/oclif.manifest.json +29 -315
- package/package.json +11 -4
- package/dist/commands/clear.d.ts +0 -19
- package/dist/commands/clear.js +0 -78
- package/dist/commands/init.d.ts +0 -130
- package/dist/commands/login.d.ts +0 -22
- package/dist/commands/login.js +0 -108
- package/dist/commands/logout.d.ts +0 -16
- package/dist/commands/logout.js +0 -61
- package/dist/commands/pull.d.ts +0 -33
- package/dist/commands/pull.js +0 -115
- package/dist/commands/push.d.ts +0 -35
- package/dist/commands/push.js +0 -160
- package/dist/commands/space/list.d.ts +0 -25
- package/dist/commands/space/list.js +0 -114
- package/dist/commands/space/switch.d.ts +0 -36
- package/dist/commands/space/switch.js +0 -160
- package/dist/infra/cipher/grpc/internal-llm-grpc-service.d.ts +0 -149
- package/dist/infra/cipher/grpc/internal-llm-grpc-service.js +0 -364
- package/dist/infra/cipher/grpc/internal-llm-grpc.proto +0 -94
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Logo Component
|
|
3
|
+
*
|
|
4
|
+
* Renders ASCII logo or text logo based on terminal dimensions.
|
|
5
|
+
* - Large terminals (>= 60w, >= 20h): Full ASCII logo
|
|
6
|
+
* - Minimal terminals: Text-only logo
|
|
7
|
+
*/
|
|
8
|
+
import React from 'react';
|
|
9
|
+
interface PaddedLine {
|
|
10
|
+
content: string;
|
|
11
|
+
padEnd: string;
|
|
12
|
+
padStart: string;
|
|
13
|
+
}
|
|
14
|
+
type LogoVariant = 'full' | 'text';
|
|
15
|
+
/**
|
|
16
|
+
* Select the best logo variant based on terminal size
|
|
17
|
+
*/
|
|
18
|
+
declare function selectLogoVariant(width: number, height: number): LogoVariant;
|
|
19
|
+
/**
|
|
20
|
+
* Get logo lines for variant
|
|
21
|
+
*/
|
|
22
|
+
declare function getLogoLines(variant: LogoVariant, terminalWidth: number): PaddedLine[];
|
|
23
|
+
interface LogoProps {
|
|
24
|
+
/**
|
|
25
|
+
* Compact mode, only show text logo
|
|
26
|
+
*/
|
|
27
|
+
compact?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Optional version to display
|
|
30
|
+
*/
|
|
31
|
+
version?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Adaptive Logo Component
|
|
35
|
+
*
|
|
36
|
+
* Automatically selects the best logo variant based on terminal dimensions.
|
|
37
|
+
*/
|
|
38
|
+
export declare const Logo: React.FC<LogoProps>;
|
|
39
|
+
/**
|
|
40
|
+
* Export utilities for external use
|
|
41
|
+
*/
|
|
42
|
+
export { getLogoLines, selectLogoVariant };
|
|
43
|
+
export type { LogoVariant };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Adaptive Logo Component
|
|
4
|
+
*
|
|
5
|
+
* Renders ASCII logo or text logo based on terminal dimensions.
|
|
6
|
+
* - Large terminals (>= 60w, >= 20h): Full ASCII logo
|
|
7
|
+
* - Minimal terminals: Text-only logo
|
|
8
|
+
*/
|
|
9
|
+
import { Box, Text, useStdout } from 'ink';
|
|
10
|
+
import { useMemo } from 'react';
|
|
11
|
+
import { useTheme } from '../hooks/index.js';
|
|
12
|
+
/**
|
|
13
|
+
* Full ASCII logo "ByteRover" for large terminals
|
|
14
|
+
*/
|
|
15
|
+
const LOGO_FULL = [
|
|
16
|
+
'░█▀▄░█░█░▀█▀░█▀▀░█▀▄░█▀█░█░█░█▀▀░█▀▄',
|
|
17
|
+
'░█▀▄░░█░░░█░░█▀▀░█▀▄░█░█░▀▄▀░█▀▀░█▀▄',
|
|
18
|
+
'░▀▀░░░▀░░░▀░░▀▀▀░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀',
|
|
19
|
+
];
|
|
20
|
+
const MINI_LOGO = 'brv';
|
|
21
|
+
const PAD_START = '///// ';
|
|
22
|
+
/**
|
|
23
|
+
* Calculate padding end string to fill remaining width
|
|
24
|
+
*/
|
|
25
|
+
function calculatePadEnd(contentLength, terminalWidth) {
|
|
26
|
+
const availableWidth = terminalWidth;
|
|
27
|
+
const padEndLength = availableWidth - PAD_START.length - contentLength - 1;
|
|
28
|
+
return padEndLength > 0 ? ' ' + '/'.repeat(padEndLength) : '';
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get header line with BRV and version
|
|
32
|
+
*/
|
|
33
|
+
function getHeaderLine(logoLine, version, terminalWidth) {
|
|
34
|
+
const logoLength = [...logoLine].length;
|
|
35
|
+
const brv = '';
|
|
36
|
+
const versionText = version ? `v${version}` : '';
|
|
37
|
+
// Spaces between BRV and version to match logo width
|
|
38
|
+
const spacesLength = logoLength - brv.length - versionText.length;
|
|
39
|
+
const spaces = spacesLength > 0 ? ' '.repeat(spacesLength) : ' ';
|
|
40
|
+
const contentLength = brv.length + spaces.length + versionText.length;
|
|
41
|
+
const padEnd = calculatePadEnd(contentLength, terminalWidth);
|
|
42
|
+
return { brv, padEnd, padStart: PAD_START, spaces, version: versionText };
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get padded logo lines with '/' - 5 at start, fill rest to terminal width
|
|
46
|
+
*/
|
|
47
|
+
function getPaddedLogoLines(lines, terminalWidth) {
|
|
48
|
+
return lines.map((line) => {
|
|
49
|
+
const lineLength = [...line].length; // Handle unicode characters
|
|
50
|
+
const padEnd = calculatePadEnd(lineLength, terminalWidth);
|
|
51
|
+
return { content: line, padEnd, padStart: PAD_START };
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Select the best logo variant based on terminal size
|
|
56
|
+
*/
|
|
57
|
+
function selectLogoVariant(width, height) {
|
|
58
|
+
// Full logo needs >= 60 width, >= 20 height
|
|
59
|
+
if (width >= 60 && height >= 20) {
|
|
60
|
+
return 'full';
|
|
61
|
+
}
|
|
62
|
+
// Fall back to text-only
|
|
63
|
+
return 'text';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get logo lines for variant
|
|
67
|
+
*/
|
|
68
|
+
function getLogoLines(variant, terminalWidth) {
|
|
69
|
+
switch (variant) {
|
|
70
|
+
case 'full': {
|
|
71
|
+
return getPaddedLogoLines(LOGO_FULL, terminalWidth);
|
|
72
|
+
}
|
|
73
|
+
default: {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Adaptive Logo Component
|
|
80
|
+
*
|
|
81
|
+
* Automatically selects the best logo variant based on terminal dimensions.
|
|
82
|
+
*/
|
|
83
|
+
export const Logo = ({ compact, version }) => {
|
|
84
|
+
const { stdout } = useStdout();
|
|
85
|
+
const { theme: { colors }, } = useTheme();
|
|
86
|
+
const terminalWidth = stdout?.columns ?? 80;
|
|
87
|
+
const terminalHeight = stdout?.rows ?? 24;
|
|
88
|
+
const variant = useMemo(() => (compact ? 'text' : selectLogoVariant(terminalWidth, terminalHeight)), [compact, terminalWidth, terminalHeight]);
|
|
89
|
+
const logoLines = useMemo(() => getLogoLines(variant, terminalWidth), [variant, terminalWidth]);
|
|
90
|
+
const headerLine = useMemo(() => (variant === 'full' && LOGO_FULL[0] ? getHeaderLine(LOGO_FULL[0], version ?? '', terminalWidth) : null), [variant, version, terminalWidth]);
|
|
91
|
+
// Text-only logo for minimal terminals
|
|
92
|
+
if (variant === 'text') {
|
|
93
|
+
const textContent = MINI_LOGO + (version ? ` v${version}` : '');
|
|
94
|
+
const padEnd = calculatePadEnd(textContent.length, terminalWidth);
|
|
95
|
+
return (_jsxs(Box, { children: [_jsx(Text, { color: colors.logoDecor, children: PAD_START }), _jsxs(Text, { children: [_jsx(Text, { bold: true, color: colors.logoBold, children: MINI_LOGO }), version && _jsxs(Text, { color: colors.logoVersion, children: [" v", version] })] }), _jsx(Text, { color: colors.logoDecor, children: padEnd })] }));
|
|
96
|
+
}
|
|
97
|
+
// ASCII logo with header line and version
|
|
98
|
+
return (_jsxs(Box, { flexDirection: "column", children: [headerLine && (_jsxs(Box, { children: [_jsx(Text, { color: colors.logoDecor, children: headerLine.padStart }), _jsxs(Text, { children: [_jsx(Text, { children: headerLine.brv }), _jsx(Text, { children: headerLine.spaces }), _jsx(Text, { color: colors.logoVersion, children: headerLine.version })] }), _jsx(Text, { color: colors.logoDecor, children: headerLine.padEnd })] })), logoLines.map((line, index) => (_jsxs(Box, { children: [_jsx(Text, { color: colors.logoDecor, children: line.padStart }), _jsx(Text, { color: colors.logoBold, children: line.content }), _jsx(Text, { color: colors.logoDecor, children: line.padEnd })] }, index)))] }));
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Export utilities for external use
|
|
102
|
+
*/
|
|
103
|
+
export { getLogoLines, selectLogoVariant };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageItem Component
|
|
3
|
+
*
|
|
4
|
+
* Displays a single command message with the command name and result
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { CommandMessage } from '../types.js';
|
|
8
|
+
interface MessageItemProps {
|
|
9
|
+
message: CommandMessage;
|
|
10
|
+
}
|
|
11
|
+
export declare const MessageItem: React.FC<MessageItemProps>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* MessageItem Component
|
|
4
|
+
*
|
|
5
|
+
* Displays a single command message with the command name and result
|
|
6
|
+
*/
|
|
7
|
+
import { Box, Text } from 'ink';
|
|
8
|
+
import { useTheme } from '../hooks/index.js';
|
|
9
|
+
export const MessageItem = ({ message }) => {
|
|
10
|
+
const { theme: { colors } } = useTheme();
|
|
11
|
+
return (_jsxs(Box, { alignItems: "flex-start", flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { flexDirection: "row", gap: 1, children: [_jsx(Box, { borderBottom: false, borderLeftColor: colors.primary, borderRight: false, borderStyle: "bold", borderTop: false }), _jsx(Text, { children: message.fromCommand })] }), _jsx(Box, { borderColor: colors.border, borderStyle: "single", width: "100%", children: _jsx(Text, { children: message.content }) })] }));
|
|
12
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyable Prompt Component
|
|
3
|
+
*
|
|
4
|
+
* Displays a bordered prompt with keyboard shortcut to copy to clipboard.
|
|
5
|
+
* Shows visual feedback when copied.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
interface CopyablePromptProps {
|
|
9
|
+
/** Whether keyboard input is active for this component */
|
|
10
|
+
isActive?: boolean;
|
|
11
|
+
/** The prompt text to display and copy */
|
|
12
|
+
prompt: string;
|
|
13
|
+
}
|
|
14
|
+
export declare const CopyablePrompt: React.FC<CopyablePromptProps>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Copyable Prompt Component
|
|
4
|
+
*
|
|
5
|
+
* Displays a bordered prompt with keyboard shortcut to copy to clipboard.
|
|
6
|
+
* Shows visual feedback when copied.
|
|
7
|
+
*/
|
|
8
|
+
import { Box, Text, useInput } from 'ink';
|
|
9
|
+
import { execSync } from 'node:child_process';
|
|
10
|
+
import { platform } from 'node:os';
|
|
11
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
12
|
+
import { useTheme } from '../../hooks/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* Copy text to clipboard using platform-specific commands
|
|
15
|
+
*/
|
|
16
|
+
function copyToClipboard(text) {
|
|
17
|
+
try {
|
|
18
|
+
const os = platform();
|
|
19
|
+
if (os === 'darwin') {
|
|
20
|
+
execSync('pbcopy', { input: text });
|
|
21
|
+
}
|
|
22
|
+
else if (os === 'win32') {
|
|
23
|
+
execSync('clip', { input: text });
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
// Linux - try xclip first, then xsel
|
|
27
|
+
try {
|
|
28
|
+
execSync('xclip -selection clipboard', { input: text });
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
execSync('xsel --clipboard --input', { input: text });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export const CopyablePrompt = ({ isActive = true, prompt }) => {
|
|
41
|
+
const { theme: { colors }, } = useTheme();
|
|
42
|
+
const [copied, setCopied] = useState(false);
|
|
43
|
+
// Reset copied state after 2 seconds
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (copied) {
|
|
46
|
+
const timer = setTimeout(() => {
|
|
47
|
+
setCopied(false);
|
|
48
|
+
}, 2000);
|
|
49
|
+
return () => clearTimeout(timer);
|
|
50
|
+
}
|
|
51
|
+
}, [copied]);
|
|
52
|
+
const handleCopy = useCallback(() => {
|
|
53
|
+
const success = copyToClipboard(prompt);
|
|
54
|
+
if (success) {
|
|
55
|
+
setCopied(true);
|
|
56
|
+
}
|
|
57
|
+
}, [prompt]);
|
|
58
|
+
useInput((input, key) => {
|
|
59
|
+
// ctrl+y to copy
|
|
60
|
+
if (key.ctrl && input === 'y') {
|
|
61
|
+
handleCopy();
|
|
62
|
+
}
|
|
63
|
+
}, { isActive });
|
|
64
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { borderColor: colors.border, borderStyle: "round", paddingX: 1, children: _jsx(Text, { children: prompt }) }), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: colors.dimText, children: ["Press", ' ', _jsx(Text, { backgroundColor: colors.primary, color: "black", children: ' ctrl+y ' }), ' ', "to copy"] }), copied && _jsx(Text, { color: colors.secondary, children: " Copied!" })] })] }));
|
|
65
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Components
|
|
3
|
+
*/
|
|
4
|
+
export { CopyablePrompt } from './copyable-prompt.js';
|
|
5
|
+
export { OnboardingFlow } from './onboarding-flow.js';
|
|
6
|
+
export { OnboardingStep } from './onboarding-step.js';
|
|
7
|
+
export type { OnboardingStepType } from './onboarding-step.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Flow Component
|
|
3
|
+
*
|
|
4
|
+
* Main container for the onboarding flow.
|
|
5
|
+
* Handles step transitions and init command execution.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
interface OnboardingFlowProps {
|
|
9
|
+
/** Available height for the onboarding flow */
|
|
10
|
+
availableHeight: number;
|
|
11
|
+
}
|
|
12
|
+
export declare const OnboardingFlow: React.FC<OnboardingFlowProps>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Onboarding Flow Component
|
|
4
|
+
*
|
|
5
|
+
* Main container for the onboarding flow.
|
|
6
|
+
* Handles step transitions and init command execution.
|
|
7
|
+
*/
|
|
8
|
+
import { Box, Text, useInput } from 'ink';
|
|
9
|
+
import Spinner from 'ink-spinner';
|
|
10
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
11
|
+
import { useAuth } from '../../contexts/auth-context.js';
|
|
12
|
+
import { useConsumer } from '../../contexts/index.js';
|
|
13
|
+
import { useActivityLogs, useCommands, useMode, useTheme } from '../../hooks/index.js';
|
|
14
|
+
import { useOnboarding } from '../../hooks/use-onboarding.js';
|
|
15
|
+
import { EnterPrompt } from '../enter-prompt.js';
|
|
16
|
+
import { LogItem } from '../execution/index.js';
|
|
17
|
+
import { InlineConfirm, InlineInput, InlineSearch, InlineSelect } from '../inline-prompts/index.js';
|
|
18
|
+
import { CopyablePrompt } from './copyable-prompt.js';
|
|
19
|
+
import { OnboardingStep } from './onboarding-step.js';
|
|
20
|
+
/** Example prompts for curate and query steps */
|
|
21
|
+
const CURATE_PROMPT = 'brv curate "Auth uses JWT with 24h expiry. Tokens stored in httpOnly cookies"';
|
|
22
|
+
const QUERY_PROMPT = 'brv query "How is authentication implemented?"';
|
|
23
|
+
/** Minimum output lines to show before truncation */
|
|
24
|
+
const MIN_OUTPUT_LINES = 3;
|
|
25
|
+
/** Reserved lines for onboarding step (title + description + borders + margins + onboard title + onboard description + content margin top) */
|
|
26
|
+
const ONBOARDING_STEP_OVERHEAD = 8;
|
|
27
|
+
/** Reserved lines for onboarding curate/query (content margin bottom + 1 line + prompt 'enter' to continue) */
|
|
28
|
+
const ONBOARDING_CURATE_QUERY_OVER_BOTTOM = 3;
|
|
29
|
+
/** Reserved lines for inline search (message + input + margins) */
|
|
30
|
+
const INLINE_SEARCH_OVERHEAD = 3;
|
|
31
|
+
/** Minimum visible items for inline search */
|
|
32
|
+
const MIN_SEARCH_ITEMS = 3;
|
|
33
|
+
/**
|
|
34
|
+
* Count the total number of lines in streaming messages
|
|
35
|
+
*/
|
|
36
|
+
function countOutputLines(messages) {
|
|
37
|
+
let total = 0;
|
|
38
|
+
for (const msg of messages) {
|
|
39
|
+
total += msg.content.split('\n').length;
|
|
40
|
+
}
|
|
41
|
+
return total;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get messages from the end that fit within maxLines, truncating from the beginning
|
|
45
|
+
*/
|
|
46
|
+
function getMessagesFromEnd(messages, maxLines) {
|
|
47
|
+
const totalLines = countOutputLines(messages);
|
|
48
|
+
if (totalLines <= maxLines) {
|
|
49
|
+
return { displayMessages: messages, skippedLines: 0, totalLines };
|
|
50
|
+
}
|
|
51
|
+
const displayMessages = [];
|
|
52
|
+
let lineCount = 0;
|
|
53
|
+
// Iterate from the end (newest messages first)
|
|
54
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
55
|
+
const msg = messages[i];
|
|
56
|
+
const msgLineArray = msg.content.split('\n');
|
|
57
|
+
const msgLineCount = msgLineArray.length;
|
|
58
|
+
if (lineCount + msgLineCount <= maxLines) {
|
|
59
|
+
displayMessages.unshift(msg);
|
|
60
|
+
lineCount += msgLineCount;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const remainingSpace = maxLines - lineCount;
|
|
64
|
+
if (remainingSpace > 0) {
|
|
65
|
+
const truncatedContent = msgLineArray.slice(-remainingSpace).join('\n');
|
|
66
|
+
displayMessages.unshift({
|
|
67
|
+
...msg,
|
|
68
|
+
content: truncatedContent,
|
|
69
|
+
});
|
|
70
|
+
lineCount += remainingSpace;
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
displayMessages,
|
|
77
|
+
skippedLines: totalLines - lineCount,
|
|
78
|
+
totalLines,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Process streaming messages to handle action_start/action_stop pairs
|
|
83
|
+
*/
|
|
84
|
+
function processMessagesForActions(messages) {
|
|
85
|
+
const stopMessages = new Map();
|
|
86
|
+
for (const msg of messages) {
|
|
87
|
+
if (msg.type === 'action_stop' && msg.actionId) {
|
|
88
|
+
stopMessages.set(msg.actionId, msg.content);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const result = [];
|
|
92
|
+
for (const msg of messages) {
|
|
93
|
+
if (msg.type === 'action_stop') {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (msg.type === 'action_start' && msg.actionId) {
|
|
97
|
+
const stopMessage = stopMessages.get(msg.actionId);
|
|
98
|
+
result.push({
|
|
99
|
+
...msg,
|
|
100
|
+
isActionRunning: stopMessage === undefined,
|
|
101
|
+
stopMessage,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
result.push(msg);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
/** Get step number for display */
|
|
111
|
+
function getStepNumber(step) {
|
|
112
|
+
switch (step) {
|
|
113
|
+
case 'curate': {
|
|
114
|
+
return 2;
|
|
115
|
+
}
|
|
116
|
+
case 'init': {
|
|
117
|
+
return 1;
|
|
118
|
+
}
|
|
119
|
+
case 'query': {
|
|
120
|
+
return 3;
|
|
121
|
+
}
|
|
122
|
+
default: {
|
|
123
|
+
return 3;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export const OnboardingFlow = ({ availableHeight }) => {
|
|
128
|
+
const { theme: { colors }, } = useTheme();
|
|
129
|
+
const { mode } = useMode();
|
|
130
|
+
const { reloadAuth } = useAuth();
|
|
131
|
+
const { restart } = useConsumer();
|
|
132
|
+
const { handleSlashCommand } = useCommands();
|
|
133
|
+
const { completeOnboarding, curateAcknowledged, currentStep, hasCurated, hasQueried, queryAcknowledged, setCurateAcknowledged, setQueryAcknowledged, totalSteps, } = useOnboarding();
|
|
134
|
+
const { logs } = useActivityLogs();
|
|
135
|
+
// Calculate max output lines based on available height
|
|
136
|
+
// Reserve space for onboarding step title, description, borders, and margins
|
|
137
|
+
const maxOutputLines = Math.max(MIN_OUTPUT_LINES, availableHeight - ONBOARDING_STEP_OVERHEAD - ONBOARDING_CURATE_QUERY_OVER_BOTTOM);
|
|
138
|
+
// Calculate max visible items for inline search based on available height
|
|
139
|
+
const maxSearchItems = Math.max(MIN_SEARCH_ITEMS, maxOutputLines - INLINE_SEARCH_OVERHEAD);
|
|
140
|
+
// Find running or queued curate/query logs
|
|
141
|
+
const curateLog = useMemo(() => logs.find((log) => log.type === 'curate'), [logs]);
|
|
142
|
+
const queryLog = useMemo(() => logs.find((log) => log.type === 'query'), [logs]);
|
|
143
|
+
// Streaming state for init command
|
|
144
|
+
const [isRunningInit, setIsRunningInit] = useState(false);
|
|
145
|
+
const [streamingMessages, setStreamingMessages] = useState([]);
|
|
146
|
+
const [activePrompt, setActivePrompt] = useState(null);
|
|
147
|
+
const [initError, setInitError] = useState(null);
|
|
148
|
+
// Determine if we're in a skippable waiting state (curate/query without active log)
|
|
149
|
+
const isInWaitingState = mode === 'activity' && ((currentStep === 'curate' && !curateLog) || (currentStep === 'query' && !queryLog));
|
|
150
|
+
// Handle escape key to skip onboarding
|
|
151
|
+
useInput((_input, key) => {
|
|
152
|
+
if (key.escape) {
|
|
153
|
+
completeOnboarding(true); // Pass true to indicate skipped
|
|
154
|
+
}
|
|
155
|
+
}, { isActive: isInWaitingState });
|
|
156
|
+
// Handle init command execution
|
|
157
|
+
const runInit = useCallback(async () => {
|
|
158
|
+
if (isRunningInit)
|
|
159
|
+
return;
|
|
160
|
+
setIsRunningInit(true);
|
|
161
|
+
setStreamingMessages([]);
|
|
162
|
+
setInitError(null);
|
|
163
|
+
const result = await handleSlashCommand('/init');
|
|
164
|
+
if (result && result.type === 'streaming') {
|
|
165
|
+
const onMessage = (msg) => {
|
|
166
|
+
setStreamingMessages((prev) => [...prev, msg]);
|
|
167
|
+
setInitError(msg.type === 'error' ? msg.content : null);
|
|
168
|
+
};
|
|
169
|
+
const onPrompt = (prompt) => {
|
|
170
|
+
setActivePrompt(prompt);
|
|
171
|
+
};
|
|
172
|
+
try {
|
|
173
|
+
await result.execute(onMessage, onPrompt);
|
|
174
|
+
// Reload auth to detect config change
|
|
175
|
+
await reloadAuth();
|
|
176
|
+
// Restart consumer to pick up new project state
|
|
177
|
+
await restart();
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
181
|
+
setInitError(errorMessage);
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
setIsRunningInit(false);
|
|
185
|
+
setActivePrompt(null);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else if (result && result.type === 'message') {
|
|
189
|
+
setInitError(result.content);
|
|
190
|
+
setIsRunningInit(false);
|
|
191
|
+
}
|
|
192
|
+
}, [handleSlashCommand, isRunningInit, reloadAuth, restart]);
|
|
193
|
+
// Process streaming messages to handle action_start/action_stop pairs
|
|
194
|
+
const processedStreamingMessages = useMemo(() => processMessagesForActions(streamingMessages), [streamingMessages]);
|
|
195
|
+
// Render streaming message with proper styling
|
|
196
|
+
const renderStreamingMessage = useCallback((msg) => {
|
|
197
|
+
// Handle action messages with spinner
|
|
198
|
+
if (msg.type === 'action_start') {
|
|
199
|
+
if (msg.isActionRunning) {
|
|
200
|
+
return (_jsxs(Text, { color: colors.text, children: [_jsx(Spinner, { type: "dots" }), " ", msg.content] }, msg.id));
|
|
201
|
+
}
|
|
202
|
+
return (_jsxs(Text, { color: colors.text, children: [msg.content, msg.stopMessage ? `... ${msg.stopMessage}` : ''] }, msg.id));
|
|
203
|
+
}
|
|
204
|
+
// Regular messages
|
|
205
|
+
let color = colors.text;
|
|
206
|
+
if (msg.type === 'error')
|
|
207
|
+
color = colors.errorText;
|
|
208
|
+
if (msg.type === 'warning')
|
|
209
|
+
color = colors.warning;
|
|
210
|
+
return (_jsx(Text, { color: color, children: msg.content }, msg.id));
|
|
211
|
+
}, [colors]);
|
|
212
|
+
// Prompt response handlers
|
|
213
|
+
const handleSearchResponse = useCallback((value) => {
|
|
214
|
+
if (activePrompt?.type === 'search') {
|
|
215
|
+
activePrompt.onResponse(value);
|
|
216
|
+
setActivePrompt(null);
|
|
217
|
+
}
|
|
218
|
+
}, [activePrompt]);
|
|
219
|
+
const handleConfirmResponse = useCallback((value) => {
|
|
220
|
+
if (activePrompt?.type === 'confirm') {
|
|
221
|
+
activePrompt.onResponse(value);
|
|
222
|
+
setActivePrompt(null);
|
|
223
|
+
}
|
|
224
|
+
}, [activePrompt]);
|
|
225
|
+
const handleSelectResponse = useCallback((value) => {
|
|
226
|
+
if (activePrompt?.type === 'select') {
|
|
227
|
+
activePrompt.onResponse(value);
|
|
228
|
+
setActivePrompt(null);
|
|
229
|
+
}
|
|
230
|
+
}, [activePrompt]);
|
|
231
|
+
const handleInputResponse = useCallback((value) => {
|
|
232
|
+
if (activePrompt?.type === 'input') {
|
|
233
|
+
activePrompt.onResponse(value);
|
|
234
|
+
setActivePrompt(null);
|
|
235
|
+
}
|
|
236
|
+
}, [activePrompt]);
|
|
237
|
+
const handleFileSelectorResponse = useCallback((value) => {
|
|
238
|
+
if (activePrompt?.type === 'file_selector') {
|
|
239
|
+
activePrompt.onResponse(value);
|
|
240
|
+
setActivePrompt(null);
|
|
241
|
+
}
|
|
242
|
+
}, [activePrompt]);
|
|
243
|
+
// Render active prompt
|
|
244
|
+
const renderActivePrompt = useCallback(() => {
|
|
245
|
+
if (!activePrompt)
|
|
246
|
+
return null;
|
|
247
|
+
switch (activePrompt.type) {
|
|
248
|
+
case 'confirm': {
|
|
249
|
+
return (_jsx(InlineConfirm, { default: activePrompt.default, message: activePrompt.message, onConfirm: handleConfirmResponse }));
|
|
250
|
+
}
|
|
251
|
+
case 'input': {
|
|
252
|
+
return (_jsx(InlineInput, { message: activePrompt.message, onSubmit: handleInputResponse, placeholder: activePrompt.placeholder, validate: activePrompt.validate }));
|
|
253
|
+
}
|
|
254
|
+
case 'search': {
|
|
255
|
+
return (_jsx(InlineSearch, { maxVisibleItems: maxSearchItems, message: activePrompt.message, onSelect: handleSearchResponse, source: activePrompt.source }));
|
|
256
|
+
}
|
|
257
|
+
case 'select': {
|
|
258
|
+
return (_jsx(InlineSelect, { choices: activePrompt.choices, message: activePrompt.message, onSelect: handleSelectResponse }));
|
|
259
|
+
}
|
|
260
|
+
default: {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}, [
|
|
265
|
+
activePrompt,
|
|
266
|
+
handleConfirmResponse,
|
|
267
|
+
handleFileSelectorResponse,
|
|
268
|
+
handleInputResponse,
|
|
269
|
+
handleSearchResponse,
|
|
270
|
+
handleSelectResponse,
|
|
271
|
+
]);
|
|
272
|
+
// Render init step content
|
|
273
|
+
const renderInitContent = () => {
|
|
274
|
+
if (isRunningInit) {
|
|
275
|
+
const { displayMessages: liveMessages, skippedLines } = getMessagesFromEnd(processedStreamingMessages, maxOutputLines);
|
|
276
|
+
return (_jsx(Box, { flexDirection: "column", width: "100%", children: _jsxs(Box, { borderColor: colors.border, borderStyle: "round", flexDirection: "column", paddingX: 1, paddingY: 0, width: "100%", children: [skippedLines > 0 && (_jsxs(Text, { color: colors.secondary, dimColor: true, children: ["\u2191 ", skippedLines, " more lines above"] })), liveMessages.map((streamMsg) => renderStreamingMessage(streamMsg)), renderActivePrompt()] }) }));
|
|
277
|
+
}
|
|
278
|
+
if (initError) {
|
|
279
|
+
return (_jsxs(Box, { flexDirection: "column", rowGap: 1, children: [_jsxs(Text, { color: colors.errorText, children: ["Error: ", initError] }), _jsx(EnterPrompt, { action: "try again", active: mode === 'activity' && currentStep === 'init' && !isRunningInit && !activePrompt, onEnter: runInit })] }));
|
|
280
|
+
}
|
|
281
|
+
return (_jsx(EnterPrompt, { action: "initialize your project", active: mode === 'activity' && currentStep === 'init' && !isRunningInit && !activePrompt, onEnter: runInit }));
|
|
282
|
+
};
|
|
283
|
+
// Render curate step content
|
|
284
|
+
const renderCurateContent = () => {
|
|
285
|
+
// Show execution progress if curate is running
|
|
286
|
+
if (curateLog) {
|
|
287
|
+
return (_jsxs(Box, { flexDirection: "column", width: "100%", children: [_jsx(LogItem, { log: curateLog, maxContentLines: maxOutputLines }), hasCurated && !curateAcknowledged && (_jsx(EnterPrompt, { action: "continue", active: mode === 'activity' && currentStep === 'curate', onEnter: () => setCurateAcknowledged(true) }))] }));
|
|
288
|
+
}
|
|
289
|
+
// Show copyable prompt when waiting
|
|
290
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.dimText, wrap: "wrap", children: "Copy this command and paste it to your AI agent:" }), _jsx(CopyablePrompt, { isActive: mode === 'activity' && currentStep === 'curate', prompt: CURATE_PROMPT }), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: colors.dimText, children: [_jsx(Spinner, { type: "dots" }), " Waiting for curate..."] }), _jsx(Text, { color: colors.dimText, children: " (Press Esc to skip)" })] })] }));
|
|
291
|
+
};
|
|
292
|
+
// Render query step content
|
|
293
|
+
const renderQueryContent = () => {
|
|
294
|
+
// Show execution progress if query is running
|
|
295
|
+
if (queryLog) {
|
|
296
|
+
return (_jsxs(Box, { flexDirection: "column", width: "100%", children: [_jsx(LogItem, { log: queryLog, maxContentLines: maxOutputLines }), hasQueried && !queryAcknowledged && (_jsx(EnterPrompt, { action: "continue", active: mode === 'activity' && currentStep === 'query', onEnter: () => setQueryAcknowledged(true) }))] }));
|
|
297
|
+
}
|
|
298
|
+
// Show copyable prompt when waiting
|
|
299
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.dimText, wrap: "wrap", children: "Copy this command and paste it to your AI agent:" }), _jsx(CopyablePrompt, { isActive: mode === 'activity' && currentStep === 'query', prompt: QUERY_PROMPT }), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: colors.dimText, children: [_jsx(Spinner, { type: "dots" }), " Waiting for query..."] }), _jsx(Text, { color: colors.dimText, children: " (Press Esc to skip)" })] })] }));
|
|
300
|
+
};
|
|
301
|
+
// Render complete step content
|
|
302
|
+
const renderCompleteContent = () => (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.dimText, wrap: "wrap", children: "Activity logs will appear here as you use brv curate and brv query." }), _jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { color: colors.dimText, children: "Tips:" }), _jsx(Text, { color: colors.dimText, children: "- Press [Tab] to switch to commands view" }), _jsx(Text, { color: colors.dimText, children: "- Use /push to sync your context to the cloud" }), _jsx(Text, { color: colors.dimText, children: "- Use /gen-rules to generate agent rules" }), _jsx(Text, { color: colors.dimText, children: "- Type / for available commands" })] }), _jsx(EnterPrompt, { action: "finish onboarding", active: mode === 'activity' && currentStep === 'complete', onEnter: () => completeOnboarding() })] }));
|
|
303
|
+
return (_jsx(Box, { borderColor: colors.border, borderLeft: false, borderRight: false, borderStyle: "single", borderTop: false, flexDirection: "column", height: availableHeight, width: "100%", children: _jsxs(Box, { flexDirection: "column", paddingX: 1, children: [currentStep === 'init' && (_jsx(OnboardingStep, { description: "Let's get your project set up with ByteRover.", stepNumber: getStepNumber('init'), title: "Welcome to ByteRover!", totalSteps: totalSteps, children: renderInitContent() })), currentStep === 'curate' && (_jsx(OnboardingStep, { description: "Great! Now let's add some context to your knowledge base.", stepNumber: getStepNumber('curate'), title: "Add Your First Context", totalSteps: totalSteps, children: renderCurateContent() })), currentStep === 'query' && (_jsx(OnboardingStep, { description: "Excellent! Your context is saved. Let's query it.", stepNumber: getStepNumber('query'), title: "Query Your Knowledge", totalSteps: totalSteps, children: renderQueryContent() })), currentStep === 'complete' && (_jsx(OnboardingStep, { description: "Your ByteRover workspace is ready!", showStepIndicator: false, stepNumber: totalSteps, title: "You're All Set!", totalSteps: totalSteps, children: renderCompleteContent() }))] }) }));
|
|
304
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Step Component
|
|
3
|
+
*
|
|
4
|
+
* Displays an individual onboarding step with title, description, and content.
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
export type OnboardingStepType = 'complete' | 'curate' | 'init' | 'query';
|
|
8
|
+
interface OnboardingStepProps {
|
|
9
|
+
/** Child content to render */
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
/** Step description */
|
|
12
|
+
description: string;
|
|
13
|
+
/** Whether to show step indicator (default: true) */
|
|
14
|
+
showStepIndicator?: boolean;
|
|
15
|
+
/** Current step number (1-indexed) */
|
|
16
|
+
stepNumber: number;
|
|
17
|
+
/** Step title */
|
|
18
|
+
title: string;
|
|
19
|
+
/** Total number of steps */
|
|
20
|
+
totalSteps: number;
|
|
21
|
+
}
|
|
22
|
+
export declare const OnboardingStep: React.FC<OnboardingStepProps>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Onboarding Step Component
|
|
4
|
+
*
|
|
5
|
+
* Displays an individual onboarding step with title, description, and content.
|
|
6
|
+
*/
|
|
7
|
+
import { Box, Text } from 'ink';
|
|
8
|
+
import { useTheme } from '../../hooks/index.js';
|
|
9
|
+
export const OnboardingStep = ({ children, description, showStepIndicator = true, stepNumber, title, totalSteps, }) => {
|
|
10
|
+
const { theme: { colors }, } = useTheme();
|
|
11
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsxs(Text, { bold: true, color: colors.primary, children: [title, ' ', showStepIndicator && (_jsxs(Text, { color: colors.dimText, children: ["(", stepNumber, "/", totalSteps, ")"] }))] }), _jsx(Text, { children: description }), children && _jsx(Box, { marginTop: 1, children: children })] }));
|
|
12
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output Log Component
|
|
3
|
+
*
|
|
4
|
+
* Displays command output lines without causing flickering.
|
|
5
|
+
* Uses a simple Box instead of Static to avoid re-render issues.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
interface OutputLogProps {
|
|
9
|
+
lines: string[];
|
|
10
|
+
logColor?: string;
|
|
11
|
+
maxLines?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare const OutputLog: React.FC<OutputLogProps>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Output Log Component
|
|
4
|
+
*
|
|
5
|
+
* Displays command output lines without causing flickering.
|
|
6
|
+
* Uses a simple Box instead of Static to avoid re-render issues.
|
|
7
|
+
*/
|
|
8
|
+
import { Box, Text } from 'ink';
|
|
9
|
+
export const OutputLog = ({ lines, logColor, maxLines = 10 }) => {
|
|
10
|
+
// Show only the last N lines to prevent overflow
|
|
11
|
+
const visibleLines = lines.slice(-maxLines);
|
|
12
|
+
return (_jsx(Box, { flexDirection: "column", children: visibleLines.map((line, index) => (_jsx(Text, { color: logColor, children: line }, `${lines.length - maxLines + index}-${line.slice(0, 20)}`))) }));
|
|
13
|
+
};
|