byterover-cli 2.5.2 → 3.0.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/.env.production +8 -0
- package/LICENSE +44 -0
- package/README.md +240 -14
- package/bin/dev.js +8 -1
- package/bin/run.js +8 -1
- package/dist/agent/core/domain/knowledge/conflict-detector.d.ts +38 -0
- package/dist/agent/core/domain/knowledge/conflict-detector.js +71 -0
- package/dist/agent/core/domain/knowledge/conflict-resolver.d.ts +17 -0
- package/dist/agent/core/domain/knowledge/conflict-resolver.js +118 -0
- package/dist/agent/core/domain/knowledge/utils.d.ts +4 -0
- package/dist/agent/core/domain/knowledge/utils.js +6 -0
- package/dist/agent/core/interfaces/i-curate-service.d.ts +6 -0
- package/dist/agent/infra/tools/implementations/curate-tool.d.ts +67 -34
- package/dist/agent/infra/tools/implementations/curate-tool.js +294 -47
- package/dist/agent/resources/prompts/system-prompt.yml +15 -8
- package/dist/agent/resources/tools/code_exec.txt +3 -0
- package/dist/agent/resources/tools/curate.txt +12 -3
- package/dist/oclif/commands/connectors/install.d.ts +2 -1
- package/dist/oclif/commands/connectors/install.js +38 -3
- package/dist/oclif/commands/curate/index.d.ts +18 -0
- package/dist/oclif/commands/curate/index.js +78 -1
- package/dist/oclif/commands/init.d.ts +12 -0
- package/dist/oclif/commands/init.js +75 -0
- package/dist/oclif/commands/locations.js +1 -1
- package/dist/oclif/commands/providers/connect.d.ts +31 -1
- package/dist/oclif/commands/providers/connect.js +307 -27
- package/dist/oclif/commands/pull.d.ts +1 -0
- package/dist/oclif/commands/pull.js +7 -0
- package/dist/oclif/commands/push.d.ts +1 -0
- package/dist/oclif/commands/push.js +8 -0
- package/dist/oclif/commands/review/approve.d.ts +17 -0
- package/dist/oclif/commands/review/approve.js +37 -0
- package/dist/oclif/commands/review/base-review-decision.d.ts +18 -0
- package/dist/oclif/commands/review/base-review-decision.js +71 -0
- package/dist/oclif/commands/review/pending.d.ts +13 -0
- package/dist/oclif/commands/review/pending.js +94 -0
- package/dist/oclif/commands/review/reject.d.ts +17 -0
- package/dist/oclif/commands/review/reject.js +38 -0
- package/dist/oclif/commands/space/list.d.ts +2 -2
- package/dist/oclif/commands/space/list.js +13 -35
- package/dist/oclif/commands/space/switch.d.ts +2 -7
- package/dist/oclif/commands/space/switch.js +13 -56
- package/dist/oclif/commands/status.d.ts +1 -0
- package/dist/oclif/commands/status.js +11 -1
- package/dist/oclif/commands/vc/add.d.ts +7 -0
- package/dist/oclif/commands/vc/add.js +29 -0
- package/dist/oclif/commands/vc/branch.d.ts +15 -0
- package/dist/oclif/commands/vc/branch.js +70 -0
- package/dist/oclif/commands/vc/checkout.d.ts +14 -0
- package/dist/oclif/commands/vc/checkout.js +47 -0
- package/dist/oclif/commands/vc/clone.d.ts +9 -0
- package/dist/oclif/commands/vc/clone.js +61 -0
- package/dist/oclif/commands/vc/commit.d.ts +10 -0
- package/dist/oclif/commands/vc/commit.js +32 -0
- package/dist/oclif/commands/vc/config.d.ts +10 -0
- package/dist/oclif/commands/vc/config.js +30 -0
- package/dist/oclif/commands/vc/fetch.d.ts +10 -0
- package/dist/oclif/commands/vc/fetch.js +42 -0
- package/dist/oclif/commands/vc/index.d.ts +6 -0
- package/dist/oclif/commands/vc/index.js +8 -0
- package/dist/oclif/commands/vc/init.d.ts +6 -0
- package/dist/oclif/commands/vc/init.js +25 -0
- package/dist/oclif/commands/vc/log.d.ts +13 -0
- package/dist/oclif/commands/vc/log.js +48 -0
- package/dist/oclif/commands/vc/merge.d.ts +19 -0
- package/dist/oclif/commands/vc/merge.js +130 -0
- package/dist/oclif/commands/vc/pull.d.ts +13 -0
- package/dist/oclif/commands/vc/pull.js +60 -0
- package/dist/oclif/commands/vc/push.d.ts +13 -0
- package/dist/oclif/commands/vc/push.js +60 -0
- package/dist/oclif/commands/vc/remote/add.d.ts +10 -0
- package/dist/oclif/commands/vc/remote/add.js +30 -0
- package/dist/oclif/commands/vc/remote/index.d.ts +6 -0
- package/dist/oclif/commands/vc/remote/index.js +16 -0
- package/dist/oclif/commands/vc/remote/set-url.d.ts +10 -0
- package/dist/oclif/commands/vc/remote/set-url.js +30 -0
- package/dist/oclif/commands/vc/reset.d.ts +13 -0
- package/dist/oclif/commands/vc/reset.js +62 -0
- package/dist/oclif/commands/vc/status.d.ts +8 -0
- package/dist/oclif/commands/vc/status.js +106 -0
- package/dist/oclif/hooks/init/validate-brv-config.d.ts +26 -0
- package/dist/oclif/hooks/init/validate-brv-config.js +62 -0
- package/dist/oclif/lib/daemon-client.d.ts +2 -0
- package/dist/oclif/lib/daemon-client.js +36 -10
- package/dist/oclif/lib/prompt-utils.d.ts +43 -0
- package/dist/oclif/lib/prompt-utils.js +84 -0
- package/dist/oclif/lib/spinner.d.ts +8 -0
- package/dist/oclif/lib/spinner.js +23 -0
- package/dist/oclif/lib/task-client.d.ts +5 -0
- package/dist/oclif/lib/task-client.js +15 -2
- package/dist/server/config/environment.d.ts +2 -19
- package/dist/server/config/environment.js +31 -38
- package/dist/server/constants.d.ts +3 -9
- package/dist/server/constants.js +9 -12
- package/dist/server/core/domain/entities/auth-token.d.ts +2 -0
- package/dist/server/core/domain/entities/auth-token.js +7 -1
- package/dist/server/core/domain/entities/curate-log-entry.d.ts +11 -0
- package/dist/server/core/domain/entities/space.d.ts +4 -0
- package/dist/server/core/domain/entities/space.js +8 -0
- package/dist/server/core/domain/entities/team.d.ts +2 -0
- package/dist/server/core/domain/entities/team.js +4 -0
- package/dist/server/core/domain/errors/auth-error.d.ts +0 -6
- package/dist/server/core/domain/errors/auth-error.js +0 -12
- package/dist/server/core/domain/errors/git-error.d.ts +6 -0
- package/dist/server/core/domain/errors/git-error.js +12 -0
- package/dist/server/core/domain/errors/task-error.d.ts +4 -3
- package/dist/server/core/domain/errors/task-error.js +8 -8
- package/dist/server/core/domain/errors/transport-error.d.ts +0 -31
- package/dist/server/core/domain/errors/transport-error.js +0 -50
- package/dist/server/core/domain/errors/vc-error.d.ts +5 -0
- package/dist/server/core/domain/errors/vc-error.js +8 -0
- package/dist/server/core/domain/knowledge/markdown-writer.d.ts +4 -1
- package/dist/server/core/domain/knowledge/markdown-writer.js +37 -7
- package/dist/server/core/domain/transport/schemas.d.ts +6 -6
- package/dist/server/core/interfaces/context-tree/i-context-tree-service.d.ts +11 -0
- package/dist/server/core/interfaces/process/i-task-lifecycle-hook.d.ts +6 -0
- package/dist/server/core/interfaces/services/i-git-service.d.ts +234 -0
- package/dist/server/core/interfaces/storage/i-curate-log-store.d.ts +5 -0
- package/dist/server/core/interfaces/storage/i-review-backup-store.d.ts +19 -0
- package/dist/server/core/interfaces/vc/i-vc-git-config-store.d.ts +8 -0
- package/dist/server/infra/config/auto-init.d.ts +0 -2
- package/dist/server/infra/config/auto-init.js +0 -1
- package/dist/server/infra/connectors/rules/rules-connector-config.d.ts +0 -4
- package/dist/server/infra/context-tree/file-context-tree-service.d.ts +2 -0
- package/dist/server/infra/context-tree/file-context-tree-service.js +13 -0
- package/dist/server/infra/daemon/brv-server.js +23 -3
- package/dist/server/infra/git/cogit-url.d.ts +17 -0
- package/dist/server/infra/git/cogit-url.js +39 -0
- package/dist/server/infra/git/git-http-wrapper.d.ts +20 -0
- package/dist/server/infra/git/git-http-wrapper.js +334 -0
- package/dist/server/infra/git/isomorphic-git-service.d.ts +78 -0
- package/dist/server/infra/git/isomorphic-git-service.js +983 -0
- package/dist/server/infra/http/models-dev-client.d.ts +0 -4
- package/dist/server/infra/http/models-dev-client.js +0 -6
- package/dist/server/infra/http/openrouter-api-client.d.ts +0 -8
- package/dist/server/infra/http/openrouter-api-client.js +0 -13
- package/dist/server/infra/http/provider-model-fetcher-registry.d.ts +0 -5
- package/dist/server/infra/http/provider-model-fetcher-registry.js +0 -7
- package/dist/server/infra/http/review-api-handler.d.ts +13 -0
- package/dist/server/infra/http/review-api-handler.js +286 -0
- package/dist/server/infra/http/review-ui.d.ts +7 -0
- package/dist/server/infra/http/review-ui.js +606 -0
- package/dist/server/infra/mcp/tools/brv-curate-tool.d.ts +2 -2
- package/dist/server/infra/process/curate-log-handler.d.ts +18 -2
- package/dist/server/infra/process/curate-log-handler.js +50 -13
- package/dist/server/infra/process/feature-handlers.js +41 -1
- package/dist/server/infra/process/task-router.js +16 -0
- package/dist/server/infra/provider/env-provider-detector.d.ts +0 -20
- package/dist/server/infra/provider/env-provider-detector.js +0 -27
- package/dist/server/infra/space/http-space-service.js +2 -0
- package/dist/server/infra/storage/file-curate-log-store.d.ts +10 -0
- package/dist/server/infra/storage/file-curate-log-store.js +35 -0
- package/dist/server/infra/storage/file-provider-config-store.d.ts +0 -4
- package/dist/server/infra/storage/file-provider-config-store.js +0 -6
- package/dist/server/infra/storage/file-review-backup-store.d.ts +29 -0
- package/dist/server/infra/storage/file-review-backup-store.js +121 -0
- package/dist/server/infra/transport/handlers/auth-handler.js +9 -5
- package/dist/server/infra/transport/handlers/handler-types.d.ts +9 -0
- package/dist/server/infra/transport/handlers/handler-types.js +11 -0
- package/dist/server/infra/transport/handlers/index.d.ts +4 -0
- package/dist/server/infra/transport/handlers/index.js +2 -0
- package/dist/server/infra/transport/handlers/init-handler.d.ts +1 -0
- package/dist/server/infra/transport/handlers/init-handler.js +13 -1
- package/dist/server/infra/transport/handlers/pull-handler.d.ts +3 -0
- package/dist/server/infra/transport/handlers/pull-handler.js +5 -1
- package/dist/server/infra/transport/handlers/push-handler.d.ts +20 -0
- package/dist/server/infra/transport/handlers/push-handler.js +116 -14
- package/dist/server/infra/transport/handlers/reset-handler.d.ts +11 -0
- package/dist/server/infra/transport/handlers/reset-handler.js +37 -1
- package/dist/server/infra/transport/handlers/review-handler.d.ts +35 -0
- package/dist/server/infra/transport/handlers/review-handler.js +162 -0
- package/dist/server/infra/transport/handlers/space-handler.d.ts +3 -0
- package/dist/server/infra/transport/handlers/space-handler.js +4 -1
- package/dist/server/infra/transport/handlers/status-handler.d.ts +5 -0
- package/dist/server/infra/transport/handlers/status-handler.js +51 -16
- package/dist/server/infra/transport/handlers/vc-handler.d.ts +100 -0
- package/dist/server/infra/transport/handlers/vc-handler.js +1050 -0
- package/dist/server/infra/transport/socket-io-transport-server.d.ts +7 -0
- package/dist/server/infra/transport/socket-io-transport-server.js +12 -1
- package/dist/server/infra/transport/transport-connector.d.ts +1 -1
- package/dist/server/infra/transport/transport-connector.js +2 -1
- package/dist/server/infra/vc/file-vc-git-config-store.d.ts +11 -0
- package/dist/server/infra/vc/file-vc-git-config-store.js +43 -0
- package/dist/server/templates/skill/SKILL.md +167 -33
- package/dist/server/utils/curate-result-parser.d.ts +64 -0
- package/dist/server/utils/curate-result-parser.js +8 -0
- package/dist/server/utils/file-content-reader.d.ts +2 -1
- package/dist/server/utils/file-helpers.d.ts +0 -24
- package/dist/server/utils/file-helpers.js +0 -81
- package/dist/server/utils/gitignore.d.ts +9 -0
- package/dist/server/utils/gitignore.js +47 -0
- package/dist/server/utils/process-logger.d.ts +0 -13
- package/dist/server/utils/process-logger.js +1 -78
- package/dist/shared/transport/events/index.d.ts +6 -0
- package/dist/shared/transport/events/index.js +3 -0
- package/dist/shared/transport/events/init-events.d.ts +8 -0
- package/dist/shared/transport/events/init-events.js +1 -0
- package/dist/shared/transport/events/push-events.d.ts +6 -0
- package/dist/shared/transport/events/review-events.d.ts +41 -0
- package/dist/shared/transport/events/review-events.js +5 -0
- package/dist/shared/transport/events/vc-events.d.ts +257 -0
- package/dist/shared/transport/events/vc-events.js +67 -0
- package/dist/shared/transport/types/dto.d.ts +6 -1
- package/dist/tui/app/pages/init-project-page.d.ts +9 -0
- package/dist/tui/app/pages/init-project-page.js +54 -0
- package/dist/tui/app/pages/protected-routes.js +14 -6
- package/dist/tui/components/index.d.ts +0 -2
- package/dist/tui/components/index.js +0 -1
- package/dist/tui/features/activity/hooks/use-activity-logs.js +7 -1
- package/dist/tui/features/commands/definitions/index.js +3 -0
- package/dist/tui/features/commands/definitions/space-list.js +9 -18
- package/dist/tui/features/commands/definitions/space-switch.js +10 -6
- package/dist/tui/features/commands/definitions/vc-add.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-add.js +15 -0
- package/dist/tui/features/commands/definitions/vc-branch.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-branch.js +33 -0
- package/dist/tui/features/commands/definitions/vc-checkout.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-checkout.js +32 -0
- package/dist/tui/features/commands/definitions/vc-clone.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-clone.js +18 -0
- package/dist/tui/features/commands/definitions/vc-commit.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-commit.js +32 -0
- package/dist/tui/features/commands/definitions/vc-config.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-config.js +40 -0
- package/dist/tui/features/commands/definitions/vc-fetch.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-fetch.js +37 -0
- package/dist/tui/features/commands/definitions/vc-init.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-init.js +11 -0
- package/dist/tui/features/commands/definitions/vc-log.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-log.js +25 -0
- package/dist/tui/features/commands/definitions/vc-merge.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-merge.js +48 -0
- package/dist/tui/features/commands/definitions/vc-pull.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-pull.js +42 -0
- package/dist/tui/features/commands/definitions/vc-push.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-push.js +38 -0
- package/dist/tui/features/commands/definitions/vc-remote.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-remote.js +57 -0
- package/dist/tui/features/commands/definitions/vc-reset.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-reset.js +35 -0
- package/dist/tui/features/commands/definitions/vc-status.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc-status.js +11 -0
- package/dist/tui/features/commands/definitions/vc.d.ts +2 -0
- package/dist/tui/features/commands/definitions/vc.js +36 -0
- package/dist/tui/features/commands/hooks/use-slash-command-processor.js +5 -5
- package/dist/tui/features/log/api/execute-log.d.ts +8 -0
- package/dist/tui/features/log/api/execute-log.js +13 -0
- package/dist/tui/features/log/components/log-flow.d.ts +14 -0
- package/dist/tui/features/log/components/log-flow.js +29 -0
- package/dist/tui/features/log/utils/format-log.d.ts +3 -0
- package/dist/tui/features/log/utils/format-log.js +42 -0
- package/dist/tui/features/onboarding/hooks/use-app-view-mode.d.ts +9 -5
- package/dist/tui/features/onboarding/hooks/use-app-view-mode.js +12 -5
- package/dist/tui/features/push/components/push-flow.js +9 -2
- package/dist/tui/features/reset/components/reset-flow.js +2 -1
- package/dist/tui/features/status/components/status-view.js +2 -1
- package/dist/tui/features/status/utils/format-status.js +9 -0
- package/dist/tui/features/tasks/hooks/use-task-subscriptions.js +11 -0
- package/dist/tui/features/tasks/stores/tasks-store.d.ts +10 -0
- package/dist/tui/features/tasks/stores/tasks-store.js +16 -0
- package/dist/tui/features/vc/add/api/execute-vc-add.d.ts +8 -0
- package/dist/tui/features/vc/add/api/execute-vc-add.js +13 -0
- package/dist/tui/features/vc/add/components/vc-add-flow.d.ts +7 -0
- package/dist/tui/features/vc/add/components/vc-add-flow.js +35 -0
- package/dist/tui/features/vc/branch/api/execute-vc-branch.d.ts +8 -0
- package/dist/tui/features/vc/branch/api/execute-vc-branch.js +13 -0
- package/dist/tui/features/vc/branch/components/vc-branch-flow.d.ts +8 -0
- package/dist/tui/features/vc/branch/components/vc-branch-flow.js +53 -0
- package/dist/tui/features/vc/branch/utils/format-branch.d.ts +4 -0
- package/dist/tui/features/vc/branch/utils/format-branch.js +12 -0
- package/dist/tui/features/vc/checkout/api/execute-vc-checkout.d.ts +8 -0
- package/dist/tui/features/vc/checkout/api/execute-vc-checkout.js +13 -0
- package/dist/tui/features/vc/checkout/components/vc-checkout-flow.d.ts +8 -0
- package/dist/tui/features/vc/checkout/components/vc-checkout-flow.js +33 -0
- package/dist/tui/features/vc/clone/api/execute-vc-clone.d.ts +8 -0
- package/dist/tui/features/vc/clone/api/execute-vc-clone.js +13 -0
- package/dist/tui/features/vc/clone/components/vc-clone-flow.d.ts +7 -0
- package/dist/tui/features/vc/clone/components/vc-clone-flow.js +79 -0
- package/dist/tui/features/vc/commit/api/execute-vc-commit.d.ts +8 -0
- package/dist/tui/features/vc/commit/api/execute-vc-commit.js +13 -0
- package/dist/tui/features/vc/commit/components/vc-commit-flow.d.ts +7 -0
- package/dist/tui/features/vc/commit/components/vc-commit-flow.js +29 -0
- package/dist/tui/features/vc/config/api/execute-vc-config.d.ts +8 -0
- package/dist/tui/features/vc/config/api/execute-vc-config.js +13 -0
- package/dist/tui/features/vc/config/components/vc-config-flow.d.ts +9 -0
- package/dist/tui/features/vc/config/components/vc-config-flow.js +30 -0
- package/dist/tui/features/vc/fetch/api/execute-vc-fetch.d.ts +8 -0
- package/dist/tui/features/vc/fetch/api/execute-vc-fetch.js +13 -0
- package/dist/tui/features/vc/fetch/components/vc-fetch-flow.d.ts +8 -0
- package/dist/tui/features/vc/fetch/components/vc-fetch-flow.js +75 -0
- package/dist/tui/features/vc/init/api/execute-vc-init.d.ts +8 -0
- package/dist/tui/features/vc/init/api/execute-vc-init.js +13 -0
- package/dist/tui/features/vc/init/components/vc-init-flow.d.ts +10 -0
- package/dist/tui/features/vc/init/components/vc-init-flow.js +37 -0
- package/dist/tui/features/vc/merge/api/execute-vc-merge.d.ts +8 -0
- package/dist/tui/features/vc/merge/api/execute-vc-merge.js +13 -0
- package/dist/tui/features/vc/merge/components/vc-merge-flow.d.ts +11 -0
- package/dist/tui/features/vc/merge/components/vc-merge-flow.js +72 -0
- package/dist/tui/features/vc/pull/api/execute-vc-pull.d.ts +8 -0
- package/dist/tui/features/vc/pull/api/execute-vc-pull.js +13 -0
- package/dist/tui/features/vc/pull/components/vc-pull-flow.d.ts +9 -0
- package/dist/tui/features/vc/pull/components/vc-pull-flow.js +83 -0
- package/dist/tui/features/vc/push/api/execute-vc-push.d.ts +8 -0
- package/dist/tui/features/vc/push/api/execute-vc-push.js +13 -0
- package/dist/tui/features/vc/push/components/vc-push-flow.d.ts +8 -0
- package/dist/tui/features/vc/push/components/vc-push-flow.js +83 -0
- package/dist/tui/features/vc/remote/api/execute-vc-remote.d.ts +8 -0
- package/dist/tui/features/vc/remote/api/execute-vc-remote.js +13 -0
- package/dist/tui/features/vc/remote/components/vc-remote-flow.d.ts +9 -0
- package/dist/tui/features/vc/remote/components/vc-remote-flow.js +42 -0
- package/dist/tui/features/vc/reset/api/execute-vc-reset.d.ts +8 -0
- package/dist/tui/features/vc/reset/api/execute-vc-reset.js +13 -0
- package/dist/tui/features/vc/reset/components/vc-reset-flow.d.ts +10 -0
- package/dist/tui/features/vc/reset/components/vc-reset-flow.js +63 -0
- package/dist/tui/features/vc/status/api/execute-vc-status.d.ts +8 -0
- package/dist/tui/features/vc/status/api/execute-vc-status.js +13 -0
- package/dist/tui/features/vc/status/components/vc-status-flow.d.ts +10 -0
- package/dist/tui/features/vc/status/components/vc-status-flow.js +133 -0
- package/dist/tui/lib/environment.d.ts +8 -0
- package/dist/tui/lib/environment.js +8 -0
- package/dist/tui/utils/error-messages.d.ts +5 -1
- package/dist/tui/utils/error-messages.js +32 -3
- package/node_modules/@campfirein/brv-transport-client/LICENSE +95 -0
- package/node_modules/@campfirein/brv-transport-client/README.md +3 -4
- package/node_modules/@campfirein/brv-transport-client/package.json +2 -2
- package/oclif.manifest.json +985 -65
- package/package.json +13 -5
- package/dist/oclif/hooks/prerun/validate-brv-config-version.d.ts +0 -33
- package/dist/oclif/hooks/prerun/validate-brv-config-version.js +0 -86
- package/dist/server/core/domain/entities/bullet.d.ts +0 -51
- package/dist/server/core/domain/entities/bullet.js +0 -94
- package/dist/server/core/domain/entities/memory.d.ts +0 -55
- package/dist/server/core/domain/entities/memory.js +0 -90
- package/dist/server/core/domain/entities/playbook.d.ts +0 -80
- package/dist/server/core/domain/entities/playbook.js +0 -214
- package/dist/server/core/domain/entities/presigned-url.d.ts +0 -9
- package/dist/server/core/domain/entities/presigned-url.js +0 -18
- package/dist/server/core/domain/entities/presigned-urls-response.d.ts +0 -10
- package/dist/server/core/domain/entities/presigned-urls-response.js +0 -18
- package/dist/server/core/domain/entities/retrieve-result.d.ts +0 -35
- package/dist/server/core/domain/entities/retrieve-result.js +0 -35
- package/dist/server/core/domain/errors/headless-prompt-error.d.ts +0 -11
- package/dist/server/core/domain/errors/headless-prompt-error.js +0 -18
- package/dist/server/core/interfaces/services/i-legacy-rule-detector.d.ts +0 -56
- package/dist/server/core/interfaces/services/i-memory-retrieval-service.d.ts +0 -39
- package/dist/server/core/interfaces/services/i-memory-storage-service.d.ts +0 -53
- package/dist/server/core/interfaces/services/i-terminal.d.ts +0 -146
- package/dist/server/core/interfaces/services/i-terminal.js +0 -1
- package/dist/server/core/interfaces/services/i-workspace-detector-service.d.ts +0 -8
- package/dist/server/core/interfaces/services/i-workspace-detector-service.js +0 -1
- package/dist/server/core/interfaces/storage/i-onboarding-preference-store.d.ts +0 -20
- package/dist/server/core/interfaces/storage/i-onboarding-preference-store.js +0 -1
- package/dist/server/infra/connectors/rules/legacy-rule-detector.d.ts +0 -21
- package/dist/server/infra/connectors/rules/legacy-rule-detector.js +0 -106
- package/dist/server/infra/memory/http-memory-retrieval-service.d.ts +0 -18
- package/dist/server/infra/memory/http-memory-retrieval-service.js +0 -64
- package/dist/server/infra/memory/http-memory-storage-service.d.ts +0 -18
- package/dist/server/infra/memory/http-memory-storage-service.js +0 -72
- package/dist/server/infra/memory/memory-to-playbook-mapper.d.ts +0 -33
- package/dist/server/infra/memory/memory-to-playbook-mapper.js +0 -51
- package/dist/server/infra/storage/file-onboarding-preference-store.d.ts +0 -10
- package/dist/server/infra/storage/file-onboarding-preference-store.js +0 -45
- package/dist/server/infra/terminal/headless-terminal.d.ts +0 -91
- package/dist/server/infra/terminal/headless-terminal.js +0 -211
- package/dist/server/infra/workspace/workspace-detector-service.d.ts +0 -57
- package/dist/server/infra/workspace/workspace-detector-service.js +0 -165
- package/dist/server/utils/crash-log.d.ts +0 -14
- package/dist/server/utils/crash-log.js +0 -19
- package/dist/server/utils/emoji-helpers.d.ts +0 -38
- package/dist/server/utils/emoji-helpers.js +0 -42
- package/dist/server/utils/error-handler.d.ts +0 -51
- package/dist/server/utils/error-handler.js +0 -169
- package/dist/server/utils/oclif-error-helpers.d.ts +0 -40
- package/dist/server/utils/oclif-error-helpers.js +0 -46
- package/dist/server/utils/tool-display-formatter.d.ts +0 -53
- package/dist/server/utils/tool-display-formatter.js +0 -257
- package/dist/tui/components/init.d.ts +0 -33
- package/dist/tui/components/init.js +0 -234
- package/dist/tui/features/space/api/get-spaces.d.ts +0 -16
- package/dist/tui/features/space/api/get-spaces.js +0 -17
- package/dist/tui/features/space/api/switch-space.d.ts +0 -11
- package/dist/tui/features/space/api/switch-space.js +0 -24
- package/dist/tui/features/space/components/space-list-view.d.ts +0 -12
- package/dist/tui/features/space/components/space-list-view.js +0 -56
- package/dist/tui/features/space/components/space-switch-flow.d.ts +0 -13
- package/dist/tui/features/space/components/space-switch-flow.js +0 -97
- /package/dist/server/core/interfaces/services/{i-legacy-rule-detector.js → i-git-service.js} +0 -0
- /package/dist/server/core/interfaces/{services/i-memory-retrieval-service.js → storage/i-review-backup-store.js} +0 -0
- /package/dist/server/core/interfaces/{services/i-memory-storage-service.js → vc/i-vc-git-config-store.js} +0 -0
|
@@ -1,24 +1,27 @@
|
|
|
1
|
+
import { input, password, select, Separator } from '@inquirer/prompts';
|
|
1
2
|
import { Args, Command, Flags } from '@oclif/core';
|
|
3
|
+
import chalk from 'chalk';
|
|
2
4
|
import { OAUTH_CALLBACK_TIMEOUT_MS } from '../../../shared/constants/oauth.js';
|
|
3
|
-
import { ModelEvents } from '../../../shared/transport/events/model-events.js';
|
|
5
|
+
import { ModelEvents, } from '../../../shared/transport/events/model-events.js';
|
|
4
6
|
import { ProviderEvents, } from '../../../shared/transport/events/provider-events.js';
|
|
5
7
|
import { withDaemonRetry } from '../../lib/daemon-client.js';
|
|
6
8
|
import { writeJsonResponse } from '../../lib/json-response.js';
|
|
9
|
+
import { createEscapeSignal, isEscBack, isPromptCancelled, validateUrl, wizardSelectTheme, } from '../../lib/prompt-utils.js';
|
|
10
|
+
import { createSpinner } from '../../lib/spinner.js';
|
|
7
11
|
export default class ProviderConnect extends Command {
|
|
8
12
|
static args = {
|
|
9
13
|
provider: Args.string({
|
|
10
|
-
description: 'Provider ID to connect (e.g., anthropic, openai, openrouter)',
|
|
11
|
-
required:
|
|
14
|
+
description: 'Provider ID to connect (e.g., anthropic, openai, openrouter). Omit for interactive selection.',
|
|
15
|
+
required: false,
|
|
12
16
|
}),
|
|
13
17
|
};
|
|
14
18
|
static description = 'Connect or switch to an LLM provider';
|
|
15
19
|
static examples = [
|
|
20
|
+
'<%= config.bin %> providers connect',
|
|
16
21
|
'<%= config.bin %> providers connect anthropic --api-key sk-xxx',
|
|
17
|
-
'<%= config.bin %> providers connect openai --api-key sk-xxx --model gpt-4.1',
|
|
18
22
|
'<%= config.bin %> providers connect openai --oauth',
|
|
19
23
|
'<%= config.bin %> providers connect byterover',
|
|
20
|
-
'<%= config.bin %> providers connect openai-compatible --base-url http://localhost:11434/v1',
|
|
21
|
-
'<%= config.bin %> providers connect openai-compatible --base-url http://localhost:11434/v1 --api-key sk-xxx --model llama3',
|
|
24
|
+
'<%= config.bin %> providers connect openai-compatible --base-url http://localhost:11434/v1 --api-key sk-xxx',
|
|
22
25
|
];
|
|
23
26
|
static flags = {
|
|
24
27
|
'api-key': Flags.string({
|
|
@@ -64,15 +67,9 @@ export default class ProviderConnect extends Command {
|
|
|
64
67
|
'\nExample: brv providers connect openai-compatible --base-url http://localhost:11434/v1');
|
|
65
68
|
}
|
|
66
69
|
if (baseUrl) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
catch {
|
|
72
|
-
throw new Error(`Invalid base URL format: "${baseUrl}". Must be a valid http:// or https:// URL.`);
|
|
73
|
-
}
|
|
74
|
-
if (!['http:', 'https:'].includes(parsed.protocol)) {
|
|
75
|
-
throw new Error('URL must start with http:// or https://');
|
|
70
|
+
const validationResult = validateUrl(baseUrl);
|
|
71
|
+
if (typeof validationResult === 'string') {
|
|
72
|
+
throw new TypeError(validationResult);
|
|
76
73
|
}
|
|
77
74
|
}
|
|
78
75
|
}
|
|
@@ -104,7 +101,6 @@ export default class ProviderConnect extends Command {
|
|
|
104
101
|
}
|
|
105
102
|
async connectProviderOAuth({ code, providerId }, options, onProgress) {
|
|
106
103
|
return withDaemonRetry(async (client) => {
|
|
107
|
-
// 1. Verify provider exists and supports OAuth
|
|
108
104
|
const { providers } = await client.requestWithAck(ProviderEvents.LIST);
|
|
109
105
|
const provider = providers.find((p) => p.id === providerId);
|
|
110
106
|
if (!provider) {
|
|
@@ -113,13 +109,10 @@ export default class ProviderConnect extends Command {
|
|
|
113
109
|
if (!provider.supportsOAuth) {
|
|
114
110
|
throw new Error(`Provider "${providerId}" does not support OAuth. Use --api-key instead.`);
|
|
115
111
|
}
|
|
116
|
-
// --code is only valid for code-paste providers (e.g., Anthropic).
|
|
117
|
-
// Browser-callback providers like OpenAI handle the code exchange automatically.
|
|
118
112
|
if (code && provider.oauthCallbackMode !== 'code-paste') {
|
|
119
113
|
throw new Error(`Provider "${providerId}" uses browser-based OAuth and does not accept --code.\n` +
|
|
120
114
|
`Run: brv providers connect ${providerId} --oauth`);
|
|
121
115
|
}
|
|
122
|
-
// If --code is provided, submit it directly (code-paste providers)
|
|
123
116
|
if (code) {
|
|
124
117
|
const response = await client.requestWithAck(ProviderEvents.SUBMIT_OAUTH_CODE, { code, providerId });
|
|
125
118
|
if (!response.success) {
|
|
@@ -127,16 +120,13 @@ export default class ProviderConnect extends Command {
|
|
|
127
120
|
}
|
|
128
121
|
return { providerName: provider.name, showInstructions: false };
|
|
129
122
|
}
|
|
130
|
-
// 2. Start OAuth flow — returns immediately with auth URL
|
|
131
123
|
const startResponse = await client.requestWithAck(ProviderEvents.START_OAUTH, {
|
|
132
124
|
providerId,
|
|
133
125
|
});
|
|
134
126
|
if (!startResponse.success) {
|
|
135
127
|
throw new Error(startResponse.error ?? 'Failed to start OAuth flow');
|
|
136
128
|
}
|
|
137
|
-
// Always print auth URL (user's machine may not support browser launch)
|
|
138
129
|
onProgress?.(`\nOpen this URL to authenticate:\n ${startResponse.authUrl}\n`);
|
|
139
|
-
// 3. Handle based on callback mode
|
|
140
130
|
if (startResponse.callbackMode === 'auto') {
|
|
141
131
|
onProgress?.('Waiting for authentication in browser...');
|
|
142
132
|
const awaitResponse = await client.requestWithAck(ProviderEvents.AWAIT_OAUTH_CALLBACK, { providerId }, { timeout: OAUTH_CALLBACK_TIMEOUT_MS });
|
|
@@ -145,20 +135,230 @@ export default class ProviderConnect extends Command {
|
|
|
145
135
|
}
|
|
146
136
|
return { providerName: provider.name, showInstructions: false };
|
|
147
137
|
}
|
|
148
|
-
// code-paste mode: print instructions and exit
|
|
149
138
|
onProgress?.('Copy the authorization code from the browser and run:');
|
|
150
139
|
onProgress?.(` brv providers connect ${providerId} --oauth --code <code>`);
|
|
151
140
|
return { providerName: provider.name, showInstructions: true };
|
|
152
141
|
}, options);
|
|
153
142
|
}
|
|
143
|
+
async disconnectProvider(providerId, options) {
|
|
144
|
+
await withDaemonRetry(async (client) => {
|
|
145
|
+
await client.requestWithAck(ProviderEvents.DISCONNECT, { providerId });
|
|
146
|
+
}, options);
|
|
147
|
+
}
|
|
148
|
+
async fetchModels(providerId, options) {
|
|
149
|
+
return withDaemonRetry(async (client) => client.requestWithAck(ModelEvents.LIST, { providerId }), options);
|
|
150
|
+
}
|
|
151
|
+
async fetchProviders(options) {
|
|
152
|
+
const { providers } = await withDaemonRetry(async (client) => client.requestWithAck(ProviderEvents.LIST), options);
|
|
153
|
+
return providers;
|
|
154
|
+
}
|
|
155
|
+
// All prompt methods emit a blank line before rendering for visual spacing between wizard steps.
|
|
156
|
+
async promptForApiKey(providerName, apiKeyUrl, signal) {
|
|
157
|
+
this.log();
|
|
158
|
+
const hint = apiKeyUrl ? ` (get one at ${apiKeyUrl}):` : ':';
|
|
159
|
+
return password({
|
|
160
|
+
mask: true,
|
|
161
|
+
message: `Enter API key for ${providerName}${chalk.dim(hint)}`,
|
|
162
|
+
}, { signal });
|
|
163
|
+
}
|
|
164
|
+
async promptForAuthMethod(provider, signal) {
|
|
165
|
+
this.log();
|
|
166
|
+
const oauthLabel = provider.oauthLabel ?? 'OAuth (browser-based)';
|
|
167
|
+
return select({
|
|
168
|
+
choices: [
|
|
169
|
+
{
|
|
170
|
+
name: `API Key${provider.apiKeyUrl ? ` — get one at ${provider.apiKeyUrl}` : ''}`,
|
|
171
|
+
value: 'api-key',
|
|
172
|
+
},
|
|
173
|
+
{ name: oauthLabel, value: 'oauth' },
|
|
174
|
+
],
|
|
175
|
+
message: `How do you want to authenticate with ${provider.name}?`,
|
|
176
|
+
theme: wizardSelectTheme,
|
|
177
|
+
}, { signal });
|
|
178
|
+
}
|
|
179
|
+
async promptForBaseUrl(signal) {
|
|
180
|
+
this.log();
|
|
181
|
+
return input({
|
|
182
|
+
message: `Enter base URL ${chalk.dim('(e.g. http://localhost:11434/v1):')}`,
|
|
183
|
+
required: true,
|
|
184
|
+
validate: validateUrl,
|
|
185
|
+
}, { signal });
|
|
186
|
+
}
|
|
187
|
+
async promptForConnectedAction(provider, signal) {
|
|
188
|
+
this.log();
|
|
189
|
+
const choices = [];
|
|
190
|
+
if (!provider.isCurrent) {
|
|
191
|
+
choices.push({ name: 'Set as active', value: 'activate' });
|
|
192
|
+
}
|
|
193
|
+
if (provider.isConnected) {
|
|
194
|
+
choices.push({ name: 'Disconnect', value: 'disconnect' });
|
|
195
|
+
}
|
|
196
|
+
if (provider.requiresApiKey || provider.supportsOAuth) {
|
|
197
|
+
choices.push({ name: `Reconfigure ${provider.authMethod === 'oauth' ? 'OAuth' : 'API key'}`, value: 'reconfigure' });
|
|
198
|
+
}
|
|
199
|
+
return select({
|
|
200
|
+
choices,
|
|
201
|
+
message: `${provider.name} is already connected. What would you like to do?`,
|
|
202
|
+
theme: wizardSelectTheme,
|
|
203
|
+
}, { signal });
|
|
204
|
+
}
|
|
205
|
+
async promptForModel(models, signal) {
|
|
206
|
+
this.log();
|
|
207
|
+
if (models.length === 0) {
|
|
208
|
+
this.log(chalk.dim('No models available. Check your API key or provider configuration.'));
|
|
209
|
+
// Trigger back-navigation to auth step by throwing cancel
|
|
210
|
+
const error = new Error('No models available');
|
|
211
|
+
error.name = 'AbortPromptError';
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
return select({
|
|
215
|
+
choices: [{ name: 'Skip (use default)', value: '' }, ...models.map((m) => ({ name: m.name, value: m.id }))],
|
|
216
|
+
loop: false,
|
|
217
|
+
message: 'Select a model',
|
|
218
|
+
theme: wizardSelectTheme,
|
|
219
|
+
}, { signal }).then((v) => v || undefined);
|
|
220
|
+
}
|
|
221
|
+
async promptForOptionalApiKey(providerName, signal) {
|
|
222
|
+
this.log();
|
|
223
|
+
const value = await input({ message: `Enter API key for ${providerName} ${chalk.dim('(optional, press Enter to skip):')}` }, { signal });
|
|
224
|
+
return value.trim() || undefined;
|
|
225
|
+
}
|
|
226
|
+
async promptForProvider(providers, signal) {
|
|
227
|
+
this.log();
|
|
228
|
+
const nameMaxChars = Math.max(...providers.map((p) => p.name.length));
|
|
229
|
+
const popular = providers.filter((p) => p.category === 'popular');
|
|
230
|
+
const other = providers.filter((p) => p.category === 'other');
|
|
231
|
+
const formatChoice = (p) => ({
|
|
232
|
+
name: `${p.name.padEnd(nameMaxChars + 3)} ${p.description}`,
|
|
233
|
+
value: p.id,
|
|
234
|
+
});
|
|
235
|
+
return select({
|
|
236
|
+
choices: [
|
|
237
|
+
new Separator('---------- Popular ----------'),
|
|
238
|
+
...popular.map((p) => formatChoice(p)),
|
|
239
|
+
new Separator('\n---------- Others ----------'),
|
|
240
|
+
...other.map((p) => formatChoice(p)),
|
|
241
|
+
],
|
|
242
|
+
loop: false,
|
|
243
|
+
message: 'Select a provider',
|
|
244
|
+
theme: wizardSelectTheme,
|
|
245
|
+
}, { signal });
|
|
246
|
+
}
|
|
154
247
|
async run() {
|
|
155
248
|
const { args, flags } = await this.parse(ProviderConnect);
|
|
156
249
|
const providerId = args.provider;
|
|
157
|
-
const apiKey = flags['api-key'];
|
|
158
|
-
const baseUrl = flags['base-url'];
|
|
159
|
-
const { code, model, oauth } = flags;
|
|
160
250
|
const format = flags.format === 'json' ? 'json' : 'text';
|
|
161
|
-
//
|
|
251
|
+
// Interactive mode: no provider arg
|
|
252
|
+
if (!providerId) {
|
|
253
|
+
if (format === 'json') {
|
|
254
|
+
writeJsonResponse({
|
|
255
|
+
command: 'providers connect',
|
|
256
|
+
data: { error: 'Provider argument is required for JSON output' },
|
|
257
|
+
success: false,
|
|
258
|
+
});
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
try {
|
|
262
|
+
await this.runInteractive();
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
this.log(error instanceof Error
|
|
266
|
+
? error.message
|
|
267
|
+
: 'An unexpected error occurred while connecting the provider. Please try again.');
|
|
268
|
+
}
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
// Non-interactive mode: provider arg provided
|
|
272
|
+
await this.runNonInteractive(providerId, {
|
|
273
|
+
apiKey: flags['api-key'],
|
|
274
|
+
baseUrl: flags['base-url'],
|
|
275
|
+
code: flags.code,
|
|
276
|
+
model: flags.model,
|
|
277
|
+
oauth: flags.oauth,
|
|
278
|
+
}, format);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Interactive flow with cancel-to-go-back navigation.
|
|
282
|
+
* Step 1 (provider) ← Step 2 (auth) ← Step 3 (model)
|
|
283
|
+
*/
|
|
284
|
+
async runInteractive() {
|
|
285
|
+
const esc = createEscapeSignal();
|
|
286
|
+
const STEPS = ['provider', 'auth', 'model'];
|
|
287
|
+
let stepIndex = 0;
|
|
288
|
+
let providers = await this.fetchProviders();
|
|
289
|
+
let providerId;
|
|
290
|
+
let provider;
|
|
291
|
+
try {
|
|
292
|
+
/* eslint-disable no-await-in-loop -- intentional sequential interactive wizard */
|
|
293
|
+
while (stepIndex < STEPS.length) {
|
|
294
|
+
const currentStep = STEPS[stepIndex];
|
|
295
|
+
try {
|
|
296
|
+
switch (currentStep) {
|
|
297
|
+
case 'auth': {
|
|
298
|
+
// If providerId or provider is not set, go back to provider step
|
|
299
|
+
// eslint-disable-next-line max-depth
|
|
300
|
+
if (!providerId || !provider) {
|
|
301
|
+
stepIndex--;
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
const done = await this.runAuthStep(providerId, provider, esc.signal);
|
|
305
|
+
// eslint-disable-next-line max-depth
|
|
306
|
+
if (done) {
|
|
307
|
+
stepIndex = STEPS.length; // skip remaining steps
|
|
308
|
+
}
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
case 'model': {
|
|
312
|
+
// If providerId is not set, go back to provider step
|
|
313
|
+
// eslint-disable-next-line max-depth
|
|
314
|
+
if (!providerId) {
|
|
315
|
+
stepIndex = 0;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
// ByteRover does not need model selection
|
|
319
|
+
// eslint-disable-next-line max-depth
|
|
320
|
+
if (providerId === 'byterover')
|
|
321
|
+
break;
|
|
322
|
+
await this.runModelStep(providerId, esc.signal);
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
case 'provider': {
|
|
326
|
+
providerId = await this.promptForProvider(providers, esc.signal);
|
|
327
|
+
provider = providers.find((p) => p.id === providerId);
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
stepIndex++;
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
if (isEscBack(error)) {
|
|
335
|
+
// Esc → go back one step
|
|
336
|
+
if (stepIndex === 0)
|
|
337
|
+
return;
|
|
338
|
+
esc.reset();
|
|
339
|
+
stepIndex--;
|
|
340
|
+
// Re-fetch providers on back-navigation so isConnected states are fresh
|
|
341
|
+
if (STEPS[stepIndex] === 'provider') {
|
|
342
|
+
providers = await this.fetchProviders();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
else if (isPromptCancelled(error)) {
|
|
346
|
+
// Ctrl+C → exit wizard
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/* eslint-enable no-await-in-loop */
|
|
355
|
+
}
|
|
356
|
+
finally {
|
|
357
|
+
esc.cleanup();
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
async runNonInteractive(providerId, flags, format) {
|
|
361
|
+
const { apiKey, baseUrl, code, model, oauth } = flags;
|
|
162
362
|
if (oauth && apiKey) {
|
|
163
363
|
const msg = 'Cannot use --oauth and --api-key together';
|
|
164
364
|
if (format === 'json') {
|
|
@@ -215,4 +415,84 @@ export default class ProviderConnect extends Command {
|
|
|
215
415
|
}
|
|
216
416
|
}
|
|
217
417
|
}
|
|
418
|
+
/* eslint-disable no-await-in-loop -- intentional retry loop for interactive auth */
|
|
419
|
+
/** Returns true when wizard should end (skip model step), false to continue to model step. */
|
|
420
|
+
async runAuthStep(providerId, provider, signal) {
|
|
421
|
+
// Provider already connected — ask what to do
|
|
422
|
+
if (provider.isConnected) {
|
|
423
|
+
const action = await this.promptForConnectedAction(provider, signal);
|
|
424
|
+
if (action === 'activate') {
|
|
425
|
+
const spinner = createSpinner('Connecting...');
|
|
426
|
+
const result = await this.connectProvider({ providerId });
|
|
427
|
+
spinner.clear();
|
|
428
|
+
this.log(`Connected to ${result.providerName} (${result.providerId})`);
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
if (action === 'disconnect') {
|
|
432
|
+
const spinner = createSpinner('Disconnecting...');
|
|
433
|
+
await this.disconnectProvider(providerId);
|
|
434
|
+
spinner.clear();
|
|
435
|
+
this.log(`Disconnected from ${provider.name}`);
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
// reconfigure → fall through to auth flow below
|
|
439
|
+
}
|
|
440
|
+
// No API key required (e.g., ByteRover free) but not openai-compatible — connect directly
|
|
441
|
+
if (!provider.requiresApiKey && !provider.supportsOAuth && providerId !== 'openai-compatible') {
|
|
442
|
+
const spinner = createSpinner('Connecting...');
|
|
443
|
+
const result = await this.connectProvider({ providerId });
|
|
444
|
+
spinner.clear();
|
|
445
|
+
this.log(`Connected to ${result.providerName} (${result.providerId})`);
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
// Retry loop — on connection failure, show error and re-prompt credentials
|
|
449
|
+
while (true) {
|
|
450
|
+
// Choose auth method if provider supports both
|
|
451
|
+
let authMethod = 'api-key';
|
|
452
|
+
if (provider.supportsOAuth && provider.requiresApiKey) {
|
|
453
|
+
authMethod = await this.promptForAuthMethod(provider, signal);
|
|
454
|
+
}
|
|
455
|
+
else if (provider.supportsOAuth) {
|
|
456
|
+
authMethod = 'oauth';
|
|
457
|
+
}
|
|
458
|
+
try {
|
|
459
|
+
if (authMethod === 'oauth') {
|
|
460
|
+
const result = await this.connectProviderOAuth({ providerId }, undefined, (msg) => this.log(msg));
|
|
461
|
+
if (!result.showInstructions) {
|
|
462
|
+
this.log(`Connected to ${result.providerName} via OAuth`);
|
|
463
|
+
}
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
// API key flow
|
|
467
|
+
const isOpenAiCompatible = providerId === 'openai-compatible';
|
|
468
|
+
const baseUrl = isOpenAiCompatible ? await this.promptForBaseUrl(signal) : undefined;
|
|
469
|
+
const apiKey = isOpenAiCompatible
|
|
470
|
+
? await this.promptForOptionalApiKey(provider.name, signal)
|
|
471
|
+
: await this.promptForApiKey(provider.name, provider.apiKeyUrl, signal);
|
|
472
|
+
const spinner = createSpinner('Connecting...');
|
|
473
|
+
const result = await this.connectProvider({ apiKey, baseUrl, providerId });
|
|
474
|
+
spinner.clear();
|
|
475
|
+
this.log(`Connected to ${result.providerName} (${result.providerId})`);
|
|
476
|
+
return false;
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
479
|
+
// Prompt cancellation → propagate to state machine (go back to provider)
|
|
480
|
+
if (isPromptCancelled(error))
|
|
481
|
+
throw error;
|
|
482
|
+
// Connection error → show message and retry auth
|
|
483
|
+
this.log(error instanceof Error ? error.message : 'Connection failed. Please try again.');
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
/* eslint-enable no-await-in-loop */
|
|
488
|
+
async runModelStep(providerId, signal) {
|
|
489
|
+
const spinner = createSpinner('Fetching models...');
|
|
490
|
+
const modelList = await this.fetchModels(providerId);
|
|
491
|
+
spinner.clear();
|
|
492
|
+
const modelId = await this.promptForModel(modelList.models, signal);
|
|
493
|
+
if (!modelId)
|
|
494
|
+
return;
|
|
495
|
+
await withDaemonRetry(async (client) => client.requestWithAck(ModelEvents.SET_ACTIVE, { modelId, providerId }));
|
|
496
|
+
this.log(`Model set to: ${modelId}`);
|
|
497
|
+
}
|
|
218
498
|
}
|
|
@@ -38,6 +38,7 @@ Downloads the context tree from the ByteRover cloud to your local project.`;
|
|
|
38
38
|
}
|
|
39
39
|
else {
|
|
40
40
|
this.log(pullResult.summary);
|
|
41
|
+
this.logVcHint();
|
|
41
42
|
}
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
@@ -50,6 +51,7 @@ Downloads the context tree from the ByteRover cloud to your local project.`;
|
|
|
50
51
|
this.log(` Branch: ${branch}`);
|
|
51
52
|
this.log(` Commit: ${result.commitSha.slice(0, 7)}`);
|
|
52
53
|
this.log(` Added: ${result.added}, Edited: ${result.edited}, Deleted: ${result.deleted}`);
|
|
54
|
+
this.logVcHint();
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
catch (error) {
|
|
@@ -59,6 +61,7 @@ Downloads the context tree from the ByteRover cloud to your local project.`;
|
|
|
59
61
|
}
|
|
60
62
|
else {
|
|
61
63
|
this.log(formatConnectionError(error));
|
|
64
|
+
this.logVcHint();
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
67
|
}
|
|
@@ -72,4 +75,8 @@ Downloads the context tree from the ByteRover cloud to your local project.`;
|
|
|
72
75
|
return { hasChanges: false, result };
|
|
73
76
|
});
|
|
74
77
|
}
|
|
78
|
+
logVcHint() {
|
|
79
|
+
this.log('\nTip: Version control is now available for your context tree.');
|
|
80
|
+
this.log('Learn more: https://docs.byterover.dev/git-semantic/overview');
|
|
81
|
+
}
|
|
75
82
|
}
|
|
@@ -37,6 +37,7 @@ Uploads your local context tree changes to the ByteRover cloud.`;
|
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
39
|
this.log('Push cancelled.');
|
|
40
|
+
this.logVcHint();
|
|
40
41
|
}
|
|
41
42
|
return;
|
|
42
43
|
}
|
|
@@ -46,6 +47,7 @@ Uploads your local context tree changes to the ByteRover cloud.`;
|
|
|
46
47
|
}
|
|
47
48
|
else {
|
|
48
49
|
this.log('No context changes to push.');
|
|
50
|
+
this.logVcHint();
|
|
49
51
|
}
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
@@ -69,6 +71,7 @@ Uploads your local context tree changes to the ByteRover cloud.`;
|
|
|
69
71
|
this.log(` Branch: ${branch}`);
|
|
70
72
|
this.log(` Added: ${result.added}, Edited: ${result.edited}, Deleted: ${result.deleted}`);
|
|
71
73
|
this.log(` View: ${result.url}`);
|
|
74
|
+
this.logVcHint();
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
77
|
catch (error) {
|
|
@@ -78,6 +81,7 @@ Uploads your local context tree changes to the ByteRover cloud.`;
|
|
|
78
81
|
}
|
|
79
82
|
else {
|
|
80
83
|
this.log(formatConnectionError(error));
|
|
84
|
+
this.logVcHint();
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
}
|
|
@@ -91,4 +95,8 @@ Uploads your local context tree changes to the ByteRover cloud.`;
|
|
|
91
95
|
return { noChanges: false, result };
|
|
92
96
|
});
|
|
93
97
|
}
|
|
98
|
+
logVcHint() {
|
|
99
|
+
this.log('\nTip: Version control is now available for your context tree.');
|
|
100
|
+
this.log('Learn more: https://docs.byterover.dev/git-semantic/overview');
|
|
101
|
+
}
|
|
94
102
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ReviewDecideTaskResponse } from '../../../shared/transport/events/review-events.js';
|
|
2
|
+
import { ReviewDecisionCommand } from './base-review-decision.js';
|
|
3
|
+
type ReviewFile = ReviewDecideTaskResponse['files'][number];
|
|
4
|
+
export default class ReviewApprove extends ReviewDecisionCommand {
|
|
5
|
+
static args: {
|
|
6
|
+
taskId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static description: string;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
static flags: {
|
|
11
|
+
file: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
protected readonly decision: "approved";
|
|
15
|
+
protected formatFileLine(file: ReviewFile): string;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { ReviewDecisionCommand } from './base-review-decision.js';
|
|
3
|
+
export default class ReviewApprove extends ReviewDecisionCommand {
|
|
4
|
+
static args = {
|
|
5
|
+
taskId: Args.string({
|
|
6
|
+
description: 'Task ID shown in the curate output (e.g. "brv review approve abc-123")',
|
|
7
|
+
required: true,
|
|
8
|
+
}),
|
|
9
|
+
};
|
|
10
|
+
static description = 'Approve pending review operations for a curate task';
|
|
11
|
+
static examples = [
|
|
12
|
+
'# Approve all pending changes from a curate task',
|
|
13
|
+
'<%= config.bin %> review approve abc-123',
|
|
14
|
+
'',
|
|
15
|
+
'# Approve specific files',
|
|
16
|
+
'<%= config.bin %> review approve abc-123 --file architecture/security/audit.md',
|
|
17
|
+
'<%= config.bin %> review approve abc-123 --file auth/jwt.md --file auth/oauth.md',
|
|
18
|
+
'',
|
|
19
|
+
'# Approve and get structured output (useful for coding agents)',
|
|
20
|
+
'<%= config.bin %> review approve abc-123 --format json',
|
|
21
|
+
];
|
|
22
|
+
static flags = {
|
|
23
|
+
file: Flags.string({
|
|
24
|
+
description: 'Approve only the specified file path(s) (relative to context tree)',
|
|
25
|
+
multiple: true,
|
|
26
|
+
}),
|
|
27
|
+
format: Flags.string({
|
|
28
|
+
default: 'text',
|
|
29
|
+
description: 'Output format (text or json)',
|
|
30
|
+
options: ['text', 'json'],
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
decision = 'approved';
|
|
34
|
+
formatFileLine(file) {
|
|
35
|
+
return `✓ Approved ${file.path}`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { type ReviewDecideTaskResponse } from '../../../shared/transport/events/review-events.js';
|
|
3
|
+
import { type DaemonClientOptions } from '../../lib/daemon-client.js';
|
|
4
|
+
type ReviewFile = ReviewDecideTaskResponse['files'][number];
|
|
5
|
+
export declare abstract class ReviewDecisionCommand extends Command {
|
|
6
|
+
static args: {
|
|
7
|
+
taskId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
file: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
protected abstract readonly decision: 'approved' | 'rejected';
|
|
14
|
+
protected abstract formatFileLine(file: ReviewFile): string;
|
|
15
|
+
protected getDaemonClientOptions(): DaemonClientOptions;
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import { ReviewEvents } from '../../../shared/transport/events/review-events.js';
|
|
3
|
+
import { formatConnectionError, withDaemonRetry } from '../../lib/daemon-client.js';
|
|
4
|
+
import { writeJsonResponse } from '../../lib/json-response.js';
|
|
5
|
+
export class ReviewDecisionCommand extends Command {
|
|
6
|
+
static args = {
|
|
7
|
+
taskId: Args.string({
|
|
8
|
+
required: true,
|
|
9
|
+
}),
|
|
10
|
+
};
|
|
11
|
+
static flags = {
|
|
12
|
+
file: Flags.string({
|
|
13
|
+
multiple: true,
|
|
14
|
+
}),
|
|
15
|
+
format: Flags.string({
|
|
16
|
+
default: 'text',
|
|
17
|
+
description: 'Output format (text or json)',
|
|
18
|
+
options: ['text', 'json'],
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
getDaemonClientOptions() {
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
24
|
+
async run() {
|
|
25
|
+
const ctor = this.constructor;
|
|
26
|
+
const { args, flags } = await this.parse({ args: ctor.args, flags: ctor.flags });
|
|
27
|
+
const format = flags.format === 'json' ? 'json' : 'text';
|
|
28
|
+
try {
|
|
29
|
+
const response = await withDaemonRetry((client) => client.requestWithAck(ReviewEvents.DECIDE_TASK, {
|
|
30
|
+
decision: this.decision,
|
|
31
|
+
...(flags.file?.length ? { filePaths: flags.file } : {}),
|
|
32
|
+
taskId: args.taskId,
|
|
33
|
+
}), this.getDaemonClientOptions());
|
|
34
|
+
if (format === 'json') {
|
|
35
|
+
writeJsonResponse({
|
|
36
|
+
command: 'review',
|
|
37
|
+
data: {
|
|
38
|
+
decision: this.decision,
|
|
39
|
+
files: response.files,
|
|
40
|
+
status: 'success',
|
|
41
|
+
taskId: args.taskId,
|
|
42
|
+
totalCount: response.totalCount,
|
|
43
|
+
},
|
|
44
|
+
success: true,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
if (response.totalCount === 0) {
|
|
49
|
+
this.log(`No pending operations found for task ${args.taskId}.`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
for (const file of response.files) {
|
|
53
|
+
this.log(this.formatFileLine(file));
|
|
54
|
+
}
|
|
55
|
+
this.log(`\n${response.totalCount} operation${response.totalCount === 1 ? '' : 's'} ${this.decision}.`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (format === 'json') {
|
|
60
|
+
writeJsonResponse({
|
|
61
|
+
command: 'review',
|
|
62
|
+
data: { error: error instanceof Error ? error.message : 'Review failed', status: 'error' },
|
|
63
|
+
success: false,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
this.log(formatConnectionError(error));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { type DaemonClientOptions } from '../../lib/daemon-client.js';
|
|
3
|
+
export default class ReviewPending extends Command {
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
};
|
|
9
|
+
protected getDaemonClientOptions(): DaemonClientOptions;
|
|
10
|
+
run(): Promise<void>;
|
|
11
|
+
private printTask;
|
|
12
|
+
private printText;
|
|
13
|
+
}
|