byterover-cli 0.3.5 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +8 -1
- 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 +10 -26
- 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 +28 -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 +288 -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} +197 -233
- package/dist/infra/usecase/login-use-case.d.ts +28 -0
- package/dist/infra/usecase/login-use-case.js +94 -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 +402 -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 +54 -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,402 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { getCurrentConfig } from '../../config/environment.js';
|
|
3
|
+
import { PROJECT } from '../../constants.js';
|
|
4
|
+
import { formatError } from '../../utils/error-handler.js';
|
|
5
|
+
import { formatToolCall, formatToolResult } from '../../utils/tool-display-formatter.js';
|
|
6
|
+
import { CipherAgent } from '../cipher/cipher-agent.js';
|
|
7
|
+
import { getAgentStorage, getAgentStorageSync } from '../cipher/storage/agent-storage.js';
|
|
8
|
+
import { WorkspaceNotInitializedError } from '../cipher/validation/workspace-validator.js';
|
|
9
|
+
export class QueryUseCase {
|
|
10
|
+
projectConfigStore;
|
|
11
|
+
terminal;
|
|
12
|
+
tokenStore;
|
|
13
|
+
trackingService;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.projectConfigStore = options.projectConfigStore;
|
|
16
|
+
this.terminal = options.terminal;
|
|
17
|
+
this.tokenStore = options.tokenStore;
|
|
18
|
+
this.trackingService = options.trackingService;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create CipherAgent instance. Protected to allow test overrides.
|
|
22
|
+
*/
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
+
createCipherAgent(llmConfig, brvConfig) {
|
|
25
|
+
return new CipherAgent(llmConfig, brvConfig);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Generate a unique session ID for the query agent.
|
|
29
|
+
* Uses crypto.randomUUID() for guaranteed uniqueness (122 bits of entropy).
|
|
30
|
+
*/
|
|
31
|
+
generateSessionId() {
|
|
32
|
+
return randomUUID();
|
|
33
|
+
}
|
|
34
|
+
async run(options) {
|
|
35
|
+
await this.trackingService.track('mem:query', { status: 'started' });
|
|
36
|
+
// Initialize storage for tool call tracking (auto-detects .brv/blobs)
|
|
37
|
+
const storage = await getAgentStorage();
|
|
38
|
+
let executionId = null;
|
|
39
|
+
try {
|
|
40
|
+
// Get authentication token
|
|
41
|
+
const token = await this.tokenStore.load();
|
|
42
|
+
if (!token) {
|
|
43
|
+
this.terminal.log('Authentication required. Please run "/login" first.');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// Load project config
|
|
47
|
+
const brvConfig = await this.projectConfigStore.read();
|
|
48
|
+
// Validate workspace is initialized
|
|
49
|
+
if (!brvConfig) {
|
|
50
|
+
throw new WorkspaceNotInitializedError('Project not initialized. Please run "/init" to select your team and workspace.', '.brv');
|
|
51
|
+
}
|
|
52
|
+
// Create execution with status='running' (query runs synchronously)
|
|
53
|
+
executionId = storage.createExecution('query', options.query);
|
|
54
|
+
// Create LLM config
|
|
55
|
+
const model = options.model ?? (options.apiKey ? 'google/gemini-2.5-pro' : 'gemini-2.5-pro');
|
|
56
|
+
const envConfig = getCurrentConfig();
|
|
57
|
+
const llmConfig = {
|
|
58
|
+
accessToken: token.accessToken,
|
|
59
|
+
apiBaseUrl: envConfig.llmApiBaseUrl,
|
|
60
|
+
fileSystemConfig: { workingDirectory: process.cwd() },
|
|
61
|
+
maxIterations: 5,
|
|
62
|
+
maxTokens: 2048,
|
|
63
|
+
model,
|
|
64
|
+
openRouterApiKey: options.apiKey,
|
|
65
|
+
projectId: PROJECT,
|
|
66
|
+
sessionKey: token.sessionKey,
|
|
67
|
+
temperature: 0.7,
|
|
68
|
+
topK: 10,
|
|
69
|
+
topP: 0.95,
|
|
70
|
+
verbose: options.verbose ?? false,
|
|
71
|
+
};
|
|
72
|
+
// Create and start CipherAgent
|
|
73
|
+
const agent = this.createCipherAgent(llmConfig, brvConfig);
|
|
74
|
+
this.terminal.log('Querying context tree...');
|
|
75
|
+
await agent.start();
|
|
76
|
+
try {
|
|
77
|
+
const sessionId = this.generateSessionId();
|
|
78
|
+
// Setup event listeners (display + tool call tracking)
|
|
79
|
+
this.setupEventListeners(agent, options.verbose ?? false);
|
|
80
|
+
this.setupToolCallTracking(agent, executionId);
|
|
81
|
+
// Execute with autonomous mode and query commandType
|
|
82
|
+
const prompt = `Search the context tree for: ${options.query}`;
|
|
83
|
+
const response = await agent.execute(prompt, sessionId, {
|
|
84
|
+
executionContext: { commandType: 'query' },
|
|
85
|
+
mode: 'autonomous',
|
|
86
|
+
});
|
|
87
|
+
// Mark execution as completed
|
|
88
|
+
storage.updateExecutionStatus(executionId, 'completed', response);
|
|
89
|
+
this.terminal.log('\nQuery Results:');
|
|
90
|
+
this.terminal.log(response);
|
|
91
|
+
await this.trackingService.track('mem:query', { status: 'finished' });
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
// Cleanup old executions
|
|
95
|
+
storage.cleanupOldExecutions(100);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
// Mark execution as failed
|
|
100
|
+
if (executionId) {
|
|
101
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
102
|
+
storage.updateExecutionStatus(executionId, 'failed', undefined, errorMessage);
|
|
103
|
+
}
|
|
104
|
+
if (error instanceof WorkspaceNotInitializedError) {
|
|
105
|
+
this.handleWorkspaceError(error);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// Display context on one line, error on separate line
|
|
109
|
+
process.stderr.write('Failed to query context tree:\n');
|
|
110
|
+
await this.trackingService.track('mem:query', { message: formatError(error), status: 'error' });
|
|
111
|
+
this.terminal.log(formatError(error));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create result summary for tool call
|
|
116
|
+
*/
|
|
117
|
+
createResultSummary(result) {
|
|
118
|
+
const lines = result.split('\n').length;
|
|
119
|
+
const chars = result.length;
|
|
120
|
+
return `${lines} lines, ${chars} chars`;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Extract summary from curate tool result
|
|
124
|
+
*/
|
|
125
|
+
extractCurateSummary(result) {
|
|
126
|
+
if (typeof result === 'string') {
|
|
127
|
+
try {
|
|
128
|
+
const parsed = JSON.parse(result);
|
|
129
|
+
return parsed.summary ?? null;
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (typeof result === 'object' && result !== null) {
|
|
136
|
+
const resultObj = result;
|
|
137
|
+
return resultObj.summary ?? null;
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Format curate tool operation summary
|
|
143
|
+
*/
|
|
144
|
+
formatCurateResult(result) {
|
|
145
|
+
const summary = this.extractCurateSummary(result);
|
|
146
|
+
if (!summary) {
|
|
147
|
+
return '';
|
|
148
|
+
}
|
|
149
|
+
const { added = 0, deleted = 0, failed = 0, merged = 0, updated = 0 } = summary;
|
|
150
|
+
const parts = [];
|
|
151
|
+
if (added > 0)
|
|
152
|
+
parts.push(`${added} added`);
|
|
153
|
+
if (updated > 0)
|
|
154
|
+
parts.push(`${updated} updated`);
|
|
155
|
+
if (merged > 0)
|
|
156
|
+
parts.push(`${merged} merged`);
|
|
157
|
+
if (deleted > 0)
|
|
158
|
+
parts.push(`${deleted} deleted`);
|
|
159
|
+
if (failed > 0)
|
|
160
|
+
parts.push(`${failed} failed`);
|
|
161
|
+
return parts.length > 0 ? parts.join(', ') : 'No operations';
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Format items count from list_directory result
|
|
165
|
+
*/
|
|
166
|
+
formatItemsCount(result) {
|
|
167
|
+
if (typeof result === 'string') {
|
|
168
|
+
const lines = result.split('\n').filter((line) => line.trim());
|
|
169
|
+
return `${lines.length} items`;
|
|
170
|
+
}
|
|
171
|
+
if (Array.isArray(result)) {
|
|
172
|
+
return `${result.length} items`;
|
|
173
|
+
}
|
|
174
|
+
return '';
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Format matches count from grep_content result
|
|
178
|
+
*/
|
|
179
|
+
formatMatchesCount(result) {
|
|
180
|
+
if (typeof result === 'string') {
|
|
181
|
+
const lines = result.split('\n').filter((line) => line.trim());
|
|
182
|
+
return `${lines.length} matches found`;
|
|
183
|
+
}
|
|
184
|
+
if (Array.isArray(result)) {
|
|
185
|
+
return `${result.length} matches found`;
|
|
186
|
+
}
|
|
187
|
+
return '';
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Format tool result summary for display
|
|
191
|
+
*/
|
|
192
|
+
formatToolResultSummary(toolName, result) {
|
|
193
|
+
try {
|
|
194
|
+
switch (toolName) {
|
|
195
|
+
case 'bash_exec':
|
|
196
|
+
case 'create_knowledge_topic':
|
|
197
|
+
case 'delete_knowledge_topic':
|
|
198
|
+
case 'detect_domains':
|
|
199
|
+
case 'read_file':
|
|
200
|
+
case 'write_file': {
|
|
201
|
+
return '';
|
|
202
|
+
}
|
|
203
|
+
case 'curate': {
|
|
204
|
+
return this.formatCurateResult(result);
|
|
205
|
+
}
|
|
206
|
+
case 'find_knowledge_topics': {
|
|
207
|
+
return this.formatTopicsCount(result);
|
|
208
|
+
}
|
|
209
|
+
case 'grep_content': {
|
|
210
|
+
return this.formatMatchesCount(result);
|
|
211
|
+
}
|
|
212
|
+
case 'list_directory': {
|
|
213
|
+
return this.formatItemsCount(result);
|
|
214
|
+
}
|
|
215
|
+
default: {
|
|
216
|
+
return '';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return '';
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Format topics count from find_knowledge_topics result
|
|
226
|
+
*/
|
|
227
|
+
formatTopicsCount(result) {
|
|
228
|
+
if (typeof result === 'string') {
|
|
229
|
+
try {
|
|
230
|
+
const parsed = JSON.parse(result);
|
|
231
|
+
const count = Array.isArray(parsed) ? parsed.length : Object.keys(parsed).length;
|
|
232
|
+
return `${count} topics retrieved`;
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
return '';
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (typeof result === 'object' && result !== null) {
|
|
239
|
+
const resultObj = result;
|
|
240
|
+
if (Array.isArray(resultObj.results)) {
|
|
241
|
+
return `${resultObj.results.length} topics retrieved`;
|
|
242
|
+
}
|
|
243
|
+
if (typeof resultObj.total === 'number') {
|
|
244
|
+
return `${resultObj.total} topics retrieved`;
|
|
245
|
+
}
|
|
246
|
+
if (Array.isArray(result)) {
|
|
247
|
+
return `${result.length} topics retrieved`;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return '';
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Get user-friendly description for a tool
|
|
254
|
+
*
|
|
255
|
+
* @param toolName - Name of the tool
|
|
256
|
+
* @param args - Tool arguments
|
|
257
|
+
* @returns User-friendly description
|
|
258
|
+
*/
|
|
259
|
+
getToolDescription(toolName, args) {
|
|
260
|
+
switch (toolName) {
|
|
261
|
+
case 'bash_exec': {
|
|
262
|
+
const cmd = String(args.command ?? '');
|
|
263
|
+
return cmd.length > 60 ? `Running command...` : `Running: ${cmd}`;
|
|
264
|
+
}
|
|
265
|
+
case 'create_knowledge_topic': {
|
|
266
|
+
return 'Creating knowledge topic...';
|
|
267
|
+
}
|
|
268
|
+
case 'curate': {
|
|
269
|
+
return 'Curating context tree...';
|
|
270
|
+
}
|
|
271
|
+
case 'find_knowledge_topics': {
|
|
272
|
+
return 'Querying context tree...';
|
|
273
|
+
}
|
|
274
|
+
case 'grep_content': {
|
|
275
|
+
return 'Searching context tree...';
|
|
276
|
+
}
|
|
277
|
+
case 'list_directory': {
|
|
278
|
+
return 'Listing directory...';
|
|
279
|
+
}
|
|
280
|
+
case 'read_file': {
|
|
281
|
+
return `Reading file...`;
|
|
282
|
+
}
|
|
283
|
+
case 'write_file': {
|
|
284
|
+
return 'Writing file...';
|
|
285
|
+
}
|
|
286
|
+
default: {
|
|
287
|
+
return 'Processing...';
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Handle workspace not initialized error
|
|
293
|
+
*/
|
|
294
|
+
handleWorkspaceError(_error) {
|
|
295
|
+
const message = 'Project not initialized. Please run "brv init" to select your team and workspace.';
|
|
296
|
+
this.terminal.log(message);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Setup event listeners for CipherAgent
|
|
300
|
+
*/
|
|
301
|
+
setupEventListeners(agent, verbose) {
|
|
302
|
+
if (!agent.agentEventBus) {
|
|
303
|
+
throw new Error('Agent event bus not initialized');
|
|
304
|
+
}
|
|
305
|
+
const eventBus = agent.agentEventBus;
|
|
306
|
+
if (verbose) {
|
|
307
|
+
// Verbose mode: show detailed events
|
|
308
|
+
eventBus.on('llmservice:thinking', () => {
|
|
309
|
+
this.terminal.log('🤔 [Event] LLM is thinking...');
|
|
310
|
+
});
|
|
311
|
+
eventBus.on('llmservice:response', (payload) => {
|
|
312
|
+
this.terminal.log(`✅ [Event] LLM Response (${payload.provider}/${payload.model})`);
|
|
313
|
+
});
|
|
314
|
+
eventBus.on('llmservice:toolCall', (payload) => {
|
|
315
|
+
// Clear any spinner on current line before printing (use spaces instead of ANSI codes)
|
|
316
|
+
const formattedCall = formatToolCall(payload.toolName, payload.args);
|
|
317
|
+
this.terminal.log(`🔧 [Event] Tool Call: ${formattedCall}`);
|
|
318
|
+
});
|
|
319
|
+
eventBus.on('llmservice:toolResult', (payload) => {
|
|
320
|
+
const resultSummary = formatToolResult(payload.toolName, payload.success, payload.result, payload.error);
|
|
321
|
+
if (payload.success) {
|
|
322
|
+
this.terminal.log(`✓ [Event] Tool Success: ${payload.toolName} → ${resultSummary}`);
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
this.terminal.log(`✗ [Event] Tool Error: ${payload.toolName} → ${resultSummary}`);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
// NOTE: llmservice:error is handled by catch block in the run method
|
|
329
|
+
// which displays error via this.error(). DO NOT display here to avoid duplicate.
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
// Non-verbose mode: show concise tool progress with descriptions
|
|
333
|
+
// eventBus.on('llmservice:toolCall', (payload) => {
|
|
334
|
+
// // Clear any spinner on current line before printing (use spaces instead of ANSI codes)
|
|
335
|
+
// const description = this.getToolDescription(payload.toolName, payload.args)
|
|
336
|
+
// this.terminal.log(`🔧 ${payload.toolName} → ${description}`)
|
|
337
|
+
// })
|
|
338
|
+
// eventBus.on('llmservice:toolResult', (payload) => {
|
|
339
|
+
// if (payload.success) {
|
|
340
|
+
// // Show brief success summary for tool completion
|
|
341
|
+
// const summary = this.formatToolResultSummary(payload.toolName, payload.result)
|
|
342
|
+
// const completionText = summary ? `Complete (${summary})` : 'Complete'
|
|
343
|
+
// this.terminal.log(`✅ ${payload.toolName} → ${completionText}`)
|
|
344
|
+
// } else {
|
|
345
|
+
// this.terminal.log(`✗ ${payload.toolName} → Failed: ${payload.error}`)
|
|
346
|
+
// }
|
|
347
|
+
// })
|
|
348
|
+
// NOTE: llmservice:error is handled by catch block in the run method
|
|
349
|
+
// which displays error via this.error(). DO NOT display here to avoid duplicate.
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Setup tool call tracking to persist in database
|
|
354
|
+
*/
|
|
355
|
+
setupToolCallTracking(agent, executionId) {
|
|
356
|
+
if (!agent.agentEventBus) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const storage = getAgentStorageSync();
|
|
360
|
+
const eventBus = agent.agentEventBus;
|
|
361
|
+
const toolCallMap = new Map(); // callId -> dbToolCallId
|
|
362
|
+
eventBus.on('llmservice:toolCall', (payload) => {
|
|
363
|
+
try {
|
|
364
|
+
if (!payload.callId)
|
|
365
|
+
return;
|
|
366
|
+
const toolCallId = storage.addToolCall(executionId, {
|
|
367
|
+
args: payload.args,
|
|
368
|
+
name: payload.toolName,
|
|
369
|
+
});
|
|
370
|
+
toolCallMap.set(payload.callId, toolCallId);
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
// Ignore errors - don't break query execution
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
eventBus.on('llmservice:toolResult', (payload) => {
|
|
377
|
+
try {
|
|
378
|
+
if (!payload.callId)
|
|
379
|
+
return;
|
|
380
|
+
const toolCallId = toolCallMap.get(payload.callId);
|
|
381
|
+
if (toolCallId) {
|
|
382
|
+
// Format result: if error, wrap in {error: "..."} object
|
|
383
|
+
let result;
|
|
384
|
+
if (payload.success) {
|
|
385
|
+
result = typeof payload.result === 'string' ? payload.result : JSON.stringify(payload.result);
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
const errorMsg = payload.error ?? (typeof payload.result === 'string' ? payload.result : 'Unknown error');
|
|
389
|
+
result = JSON.stringify({ error: errorMsg });
|
|
390
|
+
}
|
|
391
|
+
storage.updateToolCall(toolCallId, payload.success ? 'completed' : 'failed', {
|
|
392
|
+
result,
|
|
393
|
+
resultSummary: payload.success ? this.createResultSummary(result) : undefined,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
catch {
|
|
398
|
+
// Ignore errors - don't break query execution
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { IProjectConfigStore } from '../../core/interfaces/i-project-config-store.js';
|
|
2
|
+
import type { ISpaceService } from '../../core/interfaces/i-space-service.js';
|
|
3
|
+
import type { ITerminal } from '../../core/interfaces/i-terminal.js';
|
|
4
|
+
import type { ITokenStore } from '../../core/interfaces/i-token-store.js';
|
|
5
|
+
import type { ISpaceListUseCase } from '../../core/interfaces/usecase/i-space-list-use-case.js';
|
|
6
|
+
export interface SpaceListFlags {
|
|
7
|
+
all: boolean;
|
|
8
|
+
json: boolean;
|
|
9
|
+
limit: number;
|
|
10
|
+
offset: number;
|
|
11
|
+
}
|
|
12
|
+
export interface SpaceListUseCaseDependencies {
|
|
13
|
+
flags: SpaceListFlags;
|
|
14
|
+
projectConfigStore: IProjectConfigStore;
|
|
15
|
+
spaceService: ISpaceService;
|
|
16
|
+
terminal: ITerminal;
|
|
17
|
+
tokenStore: ITokenStore;
|
|
18
|
+
}
|
|
19
|
+
export declare class SpaceListUseCase implements ISpaceListUseCase {
|
|
20
|
+
private readonly flags;
|
|
21
|
+
private readonly projectConfigStore;
|
|
22
|
+
private readonly spaceService;
|
|
23
|
+
private readonly terminal;
|
|
24
|
+
private readonly tokenStore;
|
|
25
|
+
constructor(deps: SpaceListUseCaseDependencies);
|
|
26
|
+
run(): Promise<void>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export class SpaceListUseCase {
|
|
2
|
+
flags;
|
|
3
|
+
projectConfigStore;
|
|
4
|
+
spaceService;
|
|
5
|
+
terminal;
|
|
6
|
+
tokenStore;
|
|
7
|
+
constructor(deps) {
|
|
8
|
+
this.flags = deps.flags;
|
|
9
|
+
this.projectConfigStore = deps.projectConfigStore;
|
|
10
|
+
this.spaceService = deps.spaceService;
|
|
11
|
+
this.terminal = deps.terminal;
|
|
12
|
+
this.tokenStore = deps.tokenStore;
|
|
13
|
+
}
|
|
14
|
+
async run() {
|
|
15
|
+
// Check project initialization
|
|
16
|
+
const projectConfig = await this.projectConfigStore.read();
|
|
17
|
+
if (!projectConfig) {
|
|
18
|
+
this.terminal.error('Project not initialized. Please run "brv init" first.');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const token = await this.tokenStore.load();
|
|
22
|
+
if (!token) {
|
|
23
|
+
this.terminal.error('Not authenticated. Please run "brv login" first.');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!token.isValid()) {
|
|
27
|
+
this.terminal.error('Authentication token expired. Please run "brv login" again.');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// Fetch spaces for the team from project config
|
|
31
|
+
this.terminal.actionStart(`Fetching spaces for ${projectConfig.teamName}`);
|
|
32
|
+
const result = await this.spaceService.getSpaces(token.accessToken, token.sessionKey, projectConfig.teamId, this.flags.all ? { fetchAll: true } : { limit: this.flags.limit, offset: this.flags.offset });
|
|
33
|
+
this.terminal.actionStop();
|
|
34
|
+
// Handle empty results
|
|
35
|
+
if (result.spaces.length === 0) {
|
|
36
|
+
this.terminal.log(`No spaces found in team "${projectConfig.teamName}".`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Display results based on format
|
|
40
|
+
if (this.flags.json) {
|
|
41
|
+
this.terminal.log(JSON.stringify({
|
|
42
|
+
showing: result.spaces.length,
|
|
43
|
+
spaces: result.spaces.map((s) => s.toJson()),
|
|
44
|
+
team: { id: projectConfig.teamId, name: projectConfig.teamName },
|
|
45
|
+
total: result.total,
|
|
46
|
+
}, null, 2));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Human-readable format
|
|
50
|
+
this.terminal.log(`\nSpaces in team "${projectConfig.teamName}":\n`);
|
|
51
|
+
this.terminal.log(`Found ${result.spaces.length} space(s):\n`);
|
|
52
|
+
for (const [index, space] of result.spaces.entries()) {
|
|
53
|
+
this.terminal.log(` ${index + 1}. ${space.getDisplayName()}`);
|
|
54
|
+
}
|
|
55
|
+
// Pagination warning
|
|
56
|
+
if (!this.flags.all && result.spaces.length < result.total) {
|
|
57
|
+
const remaining = result.total - result.spaces.length - this.flags.offset;
|
|
58
|
+
this.terminal.log(`\nShowing ${result.spaces.length} of ${result.total} spaces.`);
|
|
59
|
+
if (remaining > 0) {
|
|
60
|
+
this.terminal.log('Use --all to fetch all spaces, or use --limit and --offset for pagination.');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Space } from '../../core/domain/entities/space.js';
|
|
2
|
+
import type { Team } from '../../core/domain/entities/team.js';
|
|
3
|
+
import type { IProjectConfigStore } from '../../core/interfaces/i-project-config-store.js';
|
|
4
|
+
import type { ISpaceService } from '../../core/interfaces/i-space-service.js';
|
|
5
|
+
import type { ITeamService } from '../../core/interfaces/i-team-service.js';
|
|
6
|
+
import type { ITerminal } from '../../core/interfaces/i-terminal.js';
|
|
7
|
+
import type { ITokenStore } from '../../core/interfaces/i-token-store.js';
|
|
8
|
+
import type { IWorkspaceDetectorService } from '../../core/interfaces/i-workspace-detector-service.js';
|
|
9
|
+
import type { ISpaceSwitchUseCase } from '../../core/interfaces/usecase/i-space-switch-use-case.js';
|
|
10
|
+
import { Agent } from '../../core/domain/entities/agent.js';
|
|
11
|
+
export interface SpaceSwitchUseCaseDependencies {
|
|
12
|
+
projectConfigStore: IProjectConfigStore;
|
|
13
|
+
spaceService: ISpaceService;
|
|
14
|
+
teamService: ITeamService;
|
|
15
|
+
terminal: ITerminal;
|
|
16
|
+
tokenStore: ITokenStore;
|
|
17
|
+
workspaceDetector: IWorkspaceDetectorService;
|
|
18
|
+
}
|
|
19
|
+
export declare class SpaceSwitchUseCase implements ISpaceSwitchUseCase {
|
|
20
|
+
private readonly projectConfigStore;
|
|
21
|
+
private readonly spaceService;
|
|
22
|
+
private readonly teamService;
|
|
23
|
+
private readonly terminal;
|
|
24
|
+
private readonly tokenStore;
|
|
25
|
+
private readonly workspaceDetector;
|
|
26
|
+
constructor(deps: SpaceSwitchUseCaseDependencies);
|
|
27
|
+
/**
|
|
28
|
+
* Prompts the user to select an agent.
|
|
29
|
+
* This method is protected to allow test overrides.
|
|
30
|
+
* @returns The selected agent
|
|
31
|
+
*/
|
|
32
|
+
protected promptForAgentSelection(): Promise<Agent>;
|
|
33
|
+
protected promptForSpaceSelection(spaces: Space[]): Promise<Space | undefined>;
|
|
34
|
+
protected promptForTeamSelection(teams: Team[]): Promise<Team | undefined>;
|
|
35
|
+
run(): Promise<void>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { BRV_DIR, PROJECT_CONFIG_FILE } from '../../constants.js';
|
|
2
|
+
import { AGENT_VALUES } from '../../core/domain/entities/agent.js';
|
|
3
|
+
import { BrvConfig } from '../../core/domain/entities/brv-config.js';
|
|
4
|
+
/**
|
|
5
|
+
* Array of all agents with name and value properties.
|
|
6
|
+
* Useful for UI components like select dropdowns.
|
|
7
|
+
*/
|
|
8
|
+
const AGENTS = AGENT_VALUES.map((agent) => ({
|
|
9
|
+
name: agent,
|
|
10
|
+
value: agent,
|
|
11
|
+
}));
|
|
12
|
+
export class SpaceSwitchUseCase {
|
|
13
|
+
projectConfigStore;
|
|
14
|
+
spaceService;
|
|
15
|
+
teamService;
|
|
16
|
+
terminal;
|
|
17
|
+
tokenStore;
|
|
18
|
+
workspaceDetector;
|
|
19
|
+
constructor(deps) {
|
|
20
|
+
this.projectConfigStore = deps.projectConfigStore;
|
|
21
|
+
this.spaceService = deps.spaceService;
|
|
22
|
+
this.teamService = deps.teamService;
|
|
23
|
+
this.terminal = deps.terminal;
|
|
24
|
+
this.tokenStore = deps.tokenStore;
|
|
25
|
+
this.workspaceDetector = deps.workspaceDetector;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Prompts the user to select an agent.
|
|
29
|
+
* This method is protected to allow test overrides.
|
|
30
|
+
* @returns The selected agent
|
|
31
|
+
*/
|
|
32
|
+
async promptForAgentSelection() {
|
|
33
|
+
return this.terminal.search({
|
|
34
|
+
message: 'Which agent you are using (type to search):',
|
|
35
|
+
source(input) {
|
|
36
|
+
if (!input)
|
|
37
|
+
return AGENTS;
|
|
38
|
+
return AGENTS.filter((agent) => agent.name.toLowerCase().includes(input.toLowerCase()) ||
|
|
39
|
+
agent.value.toLowerCase().includes(input.toLowerCase()));
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async promptForSpaceSelection(spaces) {
|
|
44
|
+
const selectedSpaceId = await this.terminal.select({
|
|
45
|
+
choices: spaces.map((space) => ({
|
|
46
|
+
name: space.getDisplayName(),
|
|
47
|
+
value: space.id,
|
|
48
|
+
})),
|
|
49
|
+
message: 'Select a space',
|
|
50
|
+
});
|
|
51
|
+
const selectedSpace = spaces.find((space) => space.id === selectedSpaceId);
|
|
52
|
+
if (!selectedSpace) {
|
|
53
|
+
this.terminal.log('Space selection failed');
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
return selectedSpace;
|
|
57
|
+
}
|
|
58
|
+
async promptForTeamSelection(teams) {
|
|
59
|
+
const selectedTeamId = await this.terminal.select({
|
|
60
|
+
choices: teams.map((team) => ({
|
|
61
|
+
name: team.name,
|
|
62
|
+
value: team.id,
|
|
63
|
+
})),
|
|
64
|
+
message: 'Select a team',
|
|
65
|
+
});
|
|
66
|
+
const selectedTeam = teams.find((team) => team.id === selectedTeamId);
|
|
67
|
+
if (!selectedTeam) {
|
|
68
|
+
this.terminal.log('Team selection failed');
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
return selectedTeam;
|
|
72
|
+
}
|
|
73
|
+
async run() {
|
|
74
|
+
// Check project initialization (MUST exist for switch)
|
|
75
|
+
const currentConfig = await this.projectConfigStore.read();
|
|
76
|
+
if (!currentConfig) {
|
|
77
|
+
this.terminal.log('Project not initialized. Please run "brv init" first.');
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Show current configuration
|
|
81
|
+
this.terminal.log('Current configuration:');
|
|
82
|
+
this.terminal.log(` Team: ${currentConfig.teamName}`);
|
|
83
|
+
this.terminal.log(` Space: ${currentConfig.spaceName}`);
|
|
84
|
+
this.terminal.log();
|
|
85
|
+
// Validate authentication
|
|
86
|
+
const token = await this.tokenStore.load();
|
|
87
|
+
if (!token) {
|
|
88
|
+
this.terminal.log('Not authenticated. Please run "brv login" first.');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (!token.isValid()) {
|
|
92
|
+
this.terminal.log('Authentication token expired. Please run "brv login" again.');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Fetch all teams
|
|
96
|
+
this.terminal.actionStart('Fetching all teams');
|
|
97
|
+
const teamResult = await this.teamService.getTeams(token.accessToken, token.sessionKey, { fetchAll: true });
|
|
98
|
+
this.terminal.actionStop();
|
|
99
|
+
if (teamResult.teams.length === 0) {
|
|
100
|
+
this.terminal.log('No teams found. Please create a team in the ByteRover dashboard first.');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// Prompt for team selection
|
|
104
|
+
this.terminal.log();
|
|
105
|
+
const selectedTeam = await this.promptForTeamSelection(teamResult.teams);
|
|
106
|
+
if (!selectedTeam)
|
|
107
|
+
return;
|
|
108
|
+
// Fetch spaces for selected team
|
|
109
|
+
this.terminal.actionStart('Fetching all spaces');
|
|
110
|
+
const spaceResult = await this.spaceService.getSpaces(token.accessToken, token.sessionKey, selectedTeam.id, {
|
|
111
|
+
fetchAll: true,
|
|
112
|
+
});
|
|
113
|
+
this.terminal.actionStop();
|
|
114
|
+
if (spaceResult.spaces.length === 0) {
|
|
115
|
+
this.terminal.log(`No spaces found in team "${selectedTeam.getDisplayName()}". Please create a space in the ByteRover dashboard first.`);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Prompt for space selection
|
|
119
|
+
this.terminal.log();
|
|
120
|
+
const selectedSpace = await this.promptForSpaceSelection(spaceResult.spaces);
|
|
121
|
+
if (!selectedSpace)
|
|
122
|
+
return;
|
|
123
|
+
// Prompt for agent selection
|
|
124
|
+
this.terminal.log();
|
|
125
|
+
const selectedAgent = await this.promptForAgentSelection();
|
|
126
|
+
this.terminal.log();
|
|
127
|
+
const { chatLogPath, cwd } = this.workspaceDetector.detectWorkspaces(selectedAgent);
|
|
128
|
+
// Update configuration
|
|
129
|
+
const newConfig = BrvConfig.fromSpace({
|
|
130
|
+
chatLogPath,
|
|
131
|
+
cwd,
|
|
132
|
+
ide: selectedAgent,
|
|
133
|
+
space: selectedSpace,
|
|
134
|
+
});
|
|
135
|
+
await this.projectConfigStore.write(newConfig);
|
|
136
|
+
// Display success
|
|
137
|
+
this.terminal.log(`\n✓ Successfully switched to space: ${selectedSpace.getDisplayName()}`);
|
|
138
|
+
this.terminal.log(`✓ Configuration updated in: ${BRV_DIR}/${PROJECT_CONFIG_FILE}`);
|
|
139
|
+
}
|
|
140
|
+
}
|