byterover-cli 1.4.0 → 1.6.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.
Files changed (174) hide show
  1. package/README.md +193 -12
  2. package/dist/core/domain/cipher/process/types.d.ts +1 -1
  3. package/dist/core/domain/entities/provider-config.d.ts +92 -0
  4. package/dist/core/domain/entities/provider-config.js +181 -0
  5. package/dist/core/domain/entities/provider-registry.d.ts +55 -0
  6. package/dist/core/domain/entities/provider-registry.js +74 -0
  7. package/dist/core/domain/errors/headless-prompt-error.d.ts +11 -0
  8. package/dist/core/domain/errors/headless-prompt-error.js +18 -0
  9. package/dist/core/interfaces/cipher/i-content-generator.d.ts +30 -0
  10. package/dist/core/interfaces/cipher/i-content-generator.js +12 -1
  11. package/dist/core/interfaces/cipher/message-factory.d.ts +4 -1
  12. package/dist/core/interfaces/cipher/message-factory.js +5 -0
  13. package/dist/core/interfaces/cipher/message-types.d.ts +19 -1
  14. package/dist/core/interfaces/i-cogit-pull-service.d.ts +0 -1
  15. package/dist/core/interfaces/i-memory-retrieval-service.d.ts +0 -1
  16. package/dist/core/interfaces/i-memory-storage-service.d.ts +0 -2
  17. package/dist/core/interfaces/i-provider-config-store.d.ts +88 -0
  18. package/dist/core/interfaces/i-provider-config-store.js +1 -0
  19. package/dist/core/interfaces/i-provider-keychain-store.d.ts +33 -0
  20. package/dist/core/interfaces/i-provider-keychain-store.js +1 -0
  21. package/dist/core/interfaces/i-space-service.d.ts +1 -2
  22. package/dist/core/interfaces/i-team-service.d.ts +1 -2
  23. package/dist/core/interfaces/i-user-service.d.ts +1 -2
  24. package/dist/core/interfaces/usecase/i-curate-use-case.d.ts +2 -0
  25. package/dist/core/interfaces/usecase/i-init-use-case.d.ts +9 -3
  26. package/dist/core/interfaces/usecase/i-login-use-case.d.ts +4 -1
  27. package/dist/core/interfaces/usecase/i-pull-use-case.d.ts +5 -3
  28. package/dist/core/interfaces/usecase/i-push-use-case.d.ts +6 -4
  29. package/dist/core/interfaces/usecase/i-query-use-case.d.ts +2 -0
  30. package/dist/core/interfaces/usecase/i-status-use-case.d.ts +1 -0
  31. package/dist/infra/cipher/agent/service-initializer.d.ts +1 -1
  32. package/dist/infra/cipher/agent/service-initializer.js +0 -1
  33. package/dist/infra/cipher/file-system/file-system-service.js +5 -5
  34. package/dist/infra/cipher/http/internal-llm-http-service.d.ts +40 -1
  35. package/dist/infra/cipher/http/internal-llm-http-service.js +153 -4
  36. package/dist/infra/cipher/llm/formatters/gemini-formatter.js +8 -1
  37. package/dist/infra/cipher/llm/generators/byterover-content-generator.d.ts +2 -3
  38. package/dist/infra/cipher/llm/generators/byterover-content-generator.js +20 -11
  39. package/dist/infra/cipher/llm/generators/openrouter-content-generator.d.ts +1 -0
  40. package/dist/infra/cipher/llm/generators/openrouter-content-generator.js +26 -0
  41. package/dist/infra/cipher/llm/internal-llm-service.d.ts +13 -0
  42. package/dist/infra/cipher/llm/internal-llm-service.js +75 -4
  43. package/dist/infra/cipher/llm/model-capabilities.d.ts +74 -0
  44. package/dist/infra/cipher/llm/model-capabilities.js +157 -0
  45. package/dist/infra/cipher/llm/openrouter-llm-service.d.ts +35 -1
  46. package/dist/infra/cipher/llm/openrouter-llm-service.js +216 -28
  47. package/dist/infra/cipher/llm/stream-processor.d.ts +22 -2
  48. package/dist/infra/cipher/llm/stream-processor.js +78 -4
  49. package/dist/infra/cipher/llm/thought-parser.d.ts +1 -1
  50. package/dist/infra/cipher/llm/thought-parser.js +5 -5
  51. package/dist/infra/cipher/llm/transformers/openrouter-stream-transformer.d.ts +49 -0
  52. package/dist/infra/cipher/llm/transformers/openrouter-stream-transformer.js +272 -0
  53. package/dist/infra/cipher/llm/transformers/reasoning-extractor.d.ts +71 -0
  54. package/dist/infra/cipher/llm/transformers/reasoning-extractor.js +253 -0
  55. package/dist/infra/cipher/process/process-service.js +1 -1
  56. package/dist/infra/cipher/session/chat-session.d.ts +2 -0
  57. package/dist/infra/cipher/session/chat-session.js +13 -2
  58. package/dist/infra/cipher/storage/message-storage-service.js +4 -0
  59. package/dist/infra/cipher/tools/implementations/bash-exec-tool.js +3 -3
  60. package/dist/infra/cipher/tools/implementations/task-tool.js +1 -1
  61. package/dist/infra/cogit/http-cogit-pull-service.js +1 -1
  62. package/dist/infra/cogit/http-cogit-push-service.js +0 -1
  63. package/dist/infra/http/authenticated-http-client.d.ts +1 -3
  64. package/dist/infra/http/authenticated-http-client.js +1 -5
  65. package/dist/infra/http/openrouter-api-client.d.ts +148 -0
  66. package/dist/infra/http/openrouter-api-client.js +161 -0
  67. package/dist/infra/mcp/tools/task-result-waiter.js +9 -1
  68. package/dist/infra/memory/http-memory-retrieval-service.js +1 -1
  69. package/dist/infra/memory/http-memory-storage-service.js +2 -2
  70. package/dist/infra/process/agent-worker.js +178 -70
  71. package/dist/infra/process/inline-agent-executor.d.ts +32 -0
  72. package/dist/infra/process/inline-agent-executor.js +259 -0
  73. package/dist/infra/process/transport-handlers.d.ts +25 -4
  74. package/dist/infra/process/transport-handlers.js +57 -10
  75. package/dist/infra/repl/commands/connectors-command.js +2 -2
  76. package/dist/infra/repl/commands/index.js +5 -0
  77. package/dist/infra/repl/commands/model-command.d.ts +13 -0
  78. package/dist/infra/repl/commands/model-command.js +212 -0
  79. package/dist/infra/repl/commands/provider-command.d.ts +13 -0
  80. package/dist/infra/repl/commands/provider-command.js +181 -0
  81. package/dist/infra/repl/transport-client-helper.js +6 -2
  82. package/dist/infra/space/http-space-service.d.ts +1 -1
  83. package/dist/infra/space/http-space-service.js +2 -2
  84. package/dist/infra/storage/file-provider-config-store.d.ts +83 -0
  85. package/dist/infra/storage/file-provider-config-store.js +157 -0
  86. package/dist/infra/storage/provider-keychain-store.d.ts +37 -0
  87. package/dist/infra/storage/provider-keychain-store.js +75 -0
  88. package/dist/infra/storage/token-store.d.ts +4 -3
  89. package/dist/infra/storage/token-store.js +6 -5
  90. package/dist/infra/team/http-team-service.d.ts +1 -1
  91. package/dist/infra/team/http-team-service.js +2 -2
  92. package/dist/infra/terminal/headless-terminal.d.ts +91 -0
  93. package/dist/infra/terminal/headless-terminal.js +211 -0
  94. package/dist/infra/transport/socket-io-transport-client.d.ts +20 -0
  95. package/dist/infra/transport/socket-io-transport-client.js +88 -1
  96. package/dist/infra/usecase/curate-use-case.d.ts +40 -1
  97. package/dist/infra/usecase/curate-use-case.js +176 -15
  98. package/dist/infra/usecase/init-use-case.d.ts +27 -5
  99. package/dist/infra/usecase/init-use-case.js +200 -34
  100. package/dist/infra/usecase/login-use-case.d.ts +10 -8
  101. package/dist/infra/usecase/login-use-case.js +35 -2
  102. package/dist/infra/usecase/pull-use-case.d.ts +19 -5
  103. package/dist/infra/usecase/pull-use-case.js +71 -13
  104. package/dist/infra/usecase/push-use-case.d.ts +18 -5
  105. package/dist/infra/usecase/push-use-case.js +81 -14
  106. package/dist/infra/usecase/query-use-case.d.ts +21 -0
  107. package/dist/infra/usecase/query-use-case.js +114 -29
  108. package/dist/infra/usecase/space-list-use-case.js +1 -1
  109. package/dist/infra/usecase/space-switch-use-case.js +2 -2
  110. package/dist/infra/usecase/status-use-case.d.ts +36 -0
  111. package/dist/infra/usecase/status-use-case.js +185 -48
  112. package/dist/infra/user/http-user-service.d.ts +1 -1
  113. package/dist/infra/user/http-user-service.js +2 -2
  114. package/dist/oclif/commands/curate.d.ts +6 -1
  115. package/dist/oclif/commands/curate.js +24 -3
  116. package/dist/oclif/commands/init.d.ts +18 -0
  117. package/dist/oclif/commands/init.js +129 -0
  118. package/dist/oclif/commands/login.d.ts +9 -0
  119. package/dist/oclif/commands/login.js +45 -0
  120. package/dist/oclif/commands/pull.d.ts +16 -0
  121. package/dist/oclif/commands/pull.js +78 -0
  122. package/dist/oclif/commands/push.d.ts +17 -0
  123. package/dist/oclif/commands/push.js +87 -0
  124. package/dist/oclif/commands/query.d.ts +6 -1
  125. package/dist/oclif/commands/query.js +29 -4
  126. package/dist/oclif/commands/status.d.ts +5 -1
  127. package/dist/oclif/commands/status.js +17 -5
  128. package/dist/resources/tools/bash_exec.txt +1 -1
  129. package/dist/tui/components/api-key-dialog.d.ts +39 -0
  130. package/dist/tui/components/api-key-dialog.js +94 -0
  131. package/dist/tui/components/execution/execution-changes.d.ts +3 -1
  132. package/dist/tui/components/execution/execution-changes.js +4 -4
  133. package/dist/tui/components/execution/execution-content.d.ts +1 -1
  134. package/dist/tui/components/execution/execution-content.js +4 -12
  135. package/dist/tui/components/execution/execution-input.js +1 -1
  136. package/dist/tui/components/execution/execution-progress.d.ts +10 -13
  137. package/dist/tui/components/execution/execution-progress.js +70 -17
  138. package/dist/tui/components/execution/execution-reasoning.d.ts +16 -0
  139. package/dist/tui/components/execution/execution-reasoning.js +34 -0
  140. package/dist/tui/components/execution/execution-tool.d.ts +23 -0
  141. package/dist/tui/components/execution/execution-tool.js +125 -0
  142. package/dist/tui/components/execution/expanded-log-view.js +3 -3
  143. package/dist/tui/components/execution/log-item.d.ts +2 -0
  144. package/dist/tui/components/execution/log-item.js +6 -4
  145. package/dist/tui/components/index.d.ts +2 -0
  146. package/dist/tui/components/index.js +2 -0
  147. package/dist/tui/components/inline-prompts/inline-select.js +3 -2
  148. package/dist/tui/components/model-dialog.d.ts +63 -0
  149. package/dist/tui/components/model-dialog.js +89 -0
  150. package/dist/tui/components/onboarding/onboarding-flow.js +8 -2
  151. package/dist/tui/components/provider-dialog.d.ts +27 -0
  152. package/dist/tui/components/provider-dialog.js +31 -0
  153. package/dist/tui/components/reasoning-text.d.ts +26 -0
  154. package/dist/tui/components/reasoning-text.js +49 -0
  155. package/dist/tui/components/selectable-list.d.ts +54 -0
  156. package/dist/tui/components/selectable-list.js +180 -0
  157. package/dist/tui/components/streaming-text.d.ts +30 -0
  158. package/dist/tui/components/streaming-text.js +52 -0
  159. package/dist/tui/contexts/tasks-context.d.ts +15 -0
  160. package/dist/tui/contexts/tasks-context.js +224 -40
  161. package/dist/tui/contexts/theme-context.d.ts +1 -0
  162. package/dist/tui/contexts/theme-context.js +3 -2
  163. package/dist/tui/hooks/use-activity-logs.js +7 -1
  164. package/dist/tui/hooks/use-auth-polling.js +1 -1
  165. package/dist/tui/types/messages.d.ts +32 -5
  166. package/dist/tui/utils/index.d.ts +1 -1
  167. package/dist/tui/utils/index.js +1 -1
  168. package/dist/tui/utils/log.d.ts +0 -9
  169. package/dist/tui/utils/log.js +2 -53
  170. package/dist/tui/views/command-view.js +4 -1
  171. package/dist/utils/environment-detector.d.ts +15 -0
  172. package/dist/utils/environment-detector.js +62 -1
  173. package/oclif.manifest.json +287 -5
  174. package/package.json +1 -1
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Error thrown when headless mode encounters a prompt that cannot be handled.
3
+ * Provides detailed information about what prompt was required and available choices.
4
+ */
5
+ export declare class HeadlessPromptError extends Error {
6
+ readonly availableChoices?: string[];
7
+ readonly code = "HEADLESS_PROMPT_REQUIRED";
8
+ readonly promptMessage: string;
9
+ readonly promptType: string;
10
+ constructor(promptType: string, promptMessage: string, availableChoices?: string[]);
11
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Error thrown when headless mode encounters a prompt that cannot be handled.
3
+ * Provides detailed information about what prompt was required and available choices.
4
+ */
5
+ export class HeadlessPromptError extends Error {
6
+ availableChoices;
7
+ code = 'HEADLESS_PROMPT_REQUIRED';
8
+ promptMessage;
9
+ promptType;
10
+ constructor(promptType, promptMessage, availableChoices) {
11
+ const choicesInfo = availableChoices?.length ? ` Available choices: ${availableChoices.join(', ')}` : '';
12
+ super(`Headless mode cannot handle ${promptType} prompt: "${promptMessage}".${choicesInfo}`);
13
+ this.name = 'HeadlessPromptError';
14
+ this.promptType = promptType;
15
+ this.promptMessage = promptMessage;
16
+ this.availableChoices = availableChoices;
17
+ }
18
+ }
@@ -12,6 +12,17 @@
12
12
  import type { ToolSet } from '../../domain/cipher/tools/types.js';
13
13
  import type { ExecutionContext } from './i-cipher-agent.js';
14
14
  import type { InternalMessage, ToolCall } from './message-types.js';
15
+ /**
16
+ * Stream chunk type for distinguishing content types during streaming.
17
+ */
18
+ export declare enum StreamChunkType {
19
+ /** Regular text content */
20
+ CONTENT = "content",
21
+ /** Thinking/reasoning content from models like Gemini */
22
+ THINKING = "thinking",
23
+ /** Tool call request */
24
+ TOOL_CALL = "tool_call"
25
+ }
15
26
  /**
16
27
  * Configuration for content generation.
17
28
  */
@@ -76,8 +87,27 @@ export interface GenerateContentChunk {
76
87
  finishReason?: 'error' | 'max_tokens' | 'stop' | 'tool_calls';
77
88
  /** Whether this is the final chunk */
78
89
  isComplete: boolean;
90
+ /** Provider-specific metadata */
91
+ providerMetadata?: Record<string, unknown>;
92
+ /**
93
+ * Raw API chunk data for native reasoning extraction.
94
+ * Used by models that return reasoning in native fields (OpenAI, Grok, Gemini).
95
+ */
96
+ rawChunk?: unknown;
97
+ /**
98
+ * Incremental reasoning/thinking content.
99
+ * For models that provide native reasoning fields (OpenAI o1/o3, Grok, Gemini).
100
+ */
101
+ reasoning?: string;
102
+ /** Unique ID for the reasoning block (for tracking across deltas) */
103
+ reasoningId?: string;
79
104
  /** Tool calls (only on final chunk or when complete) */
80
105
  toolCalls?: ToolCall[];
106
+ /**
107
+ * Type of this chunk for distinguishing content from thinking.
108
+ * Defaults to CONTENT if not specified.
109
+ */
110
+ type?: StreamChunkType;
81
111
  }
82
112
  /**
83
113
  * Content Generator interface.
@@ -9,4 +9,15 @@
9
9
  *
10
10
  * Based on gemini-cli's ContentGenerator pattern.
11
11
  */
12
- export {};
12
+ /**
13
+ * Stream chunk type for distinguishing content types during streaming.
14
+ */
15
+ export var StreamChunkType;
16
+ (function (StreamChunkType) {
17
+ /** Regular text content */
18
+ StreamChunkType["CONTENT"] = "content";
19
+ /** Thinking/reasoning content from models like Gemini */
20
+ StreamChunkType["THINKING"] = "thinking";
21
+ /** Tool call request */
22
+ StreamChunkType["TOOL_CALL"] = "tool_call";
23
+ })(StreamChunkType || (StreamChunkType = {}));
@@ -40,7 +40,10 @@ export declare function createFilePart(data: FilePart['data'], mimeType: string,
40
40
  export declare function createReasoningPart(text: string, summary?: {
41
41
  description: string;
42
42
  subject: string;
43
- }, options?: PartOptions): ReasoningPart;
43
+ }, options?: PartOptions & {
44
+ id?: string;
45
+ providerMetadata?: Record<string, unknown>;
46
+ }): ReasoningPart;
44
47
  /**
45
48
  * Create a ToolPart in pending state.
46
49
  */
@@ -52,9 +52,14 @@ export function createFilePart(data, mimeType, filename, options) {
52
52
  */
53
53
  export function createReasoningPart(text, summary, options) {
54
54
  return {
55
+ id: options?.id ?? `reasoning-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
55
56
  text,
57
+ time: {
58
+ start: Date.now(),
59
+ },
56
60
  type: 'reasoning',
57
61
  ...(summary && { summary }),
62
+ ...(options?.providerMetadata && { providerMetadata: options.providerMetadata }),
58
63
  ...(options?.synthetic !== undefined && { synthetic: options.synthetic }),
59
64
  ...(options?.metadata && { metadata: options.metadata }),
60
65
  };
@@ -57,9 +57,17 @@ export interface FilePart extends BasePart {
57
57
  }
58
58
  /**
59
59
  * Reasoning/thinking content part.
60
- * Represents structured thinking traces from models like Gemini or Claude.
60
+ * Represents structured thinking traces from models like Gemini, Claude, Grok, or OpenAI.
61
+ * Follows OpenCode's pattern with id, timing, and provider metadata.
61
62
  */
62
63
  export interface ReasoningPart extends BasePart {
64
+ /** Unique identifier for this reasoning block */
65
+ id: string;
66
+ /**
67
+ * Provider-specific metadata (encrypted content, reasoning effort, etc.)
68
+ * Used to preserve original provider data for debugging and special handling.
69
+ */
70
+ providerMetadata?: Record<string, unknown>;
63
71
  /**
64
72
  * Parsed summary for display in UI.
65
73
  * Extracted from the raw text for easier rendering.
@@ -72,6 +80,16 @@ export interface ReasoningPart extends BasePart {
72
80
  };
73
81
  /** Raw reasoning/thinking text from the model */
74
82
  text: string;
83
+ /**
84
+ * Timing information for the reasoning block.
85
+ * Used for UX feedback and analytics.
86
+ */
87
+ time: {
88
+ /** Unix timestamp when reasoning ended (undefined if still streaming) */
89
+ end?: number;
90
+ /** Unix timestamp when reasoning started */
91
+ start: number;
92
+ };
75
93
  type: 'reasoning';
76
94
  }
77
95
  /**
@@ -3,7 +3,6 @@ import type { CogitSnapshot } from '../domain/entities/cogit-snapshot.js';
3
3
  * Parameters for pulling a snapshot from CoGit.
4
4
  */
5
5
  export type PullParams = {
6
- accessToken: string;
7
6
  branch: string;
8
7
  sessionKey: string;
9
8
  spaceId: string;
@@ -1,6 +1,5 @@
1
1
  import type { RetrieveResult } from '../domain/entities/retrieve-result.js';
2
2
  export type RetrieveParams = {
3
- accessToken: string;
4
3
  nodeKeys?: string[];
5
4
  query: string;
6
5
  sessionKey: string;
@@ -3,7 +3,6 @@ import type { PresignedUrlsResponse } from '../domain/entities/presigned-urls-re
3
3
  * Parameters for requesting presigned URLs.
4
4
  */
5
5
  export type GetPresignedUrlsParams = {
6
- accessToken: string;
7
6
  branch: string;
8
7
  fileNames: string[];
9
8
  sessionKey: string;
@@ -14,7 +13,6 @@ export type GetPresignedUrlsParams = {
14
13
  * Parameters for confirming upload completion.
15
14
  */
16
15
  export type ConfirmUploadParams = {
17
- accessToken: string;
18
16
  requestId: string;
19
17
  sessionKey: string;
20
18
  spaceId: string;
@@ -0,0 +1,88 @@
1
+ import type { ProviderConfig } from '../domain/entities/provider-config.js';
2
+ /**
3
+ * Interface for storing and retrieving provider configuration.
4
+ * Handles non-sensitive data (API keys stored separately in keychain).
5
+ */
6
+ export interface IProviderConfigStore {
7
+ /**
8
+ * Marks a provider as connected.
9
+ *
10
+ * @param providerId The provider ID to mark as connected
11
+ * @param options Optional settings like default model
12
+ */
13
+ connectProvider: (providerId: string, options?: {
14
+ activeModel?: string;
15
+ }) => Promise<void>;
16
+ /**
17
+ * Removes a provider connection.
18
+ *
19
+ * @param providerId The provider ID to disconnect
20
+ */
21
+ disconnectProvider: (providerId: string) => Promise<void>;
22
+ /**
23
+ * Gets the active model for a provider.
24
+ *
25
+ * @param providerId The provider ID
26
+ * @returns The active model ID or undefined
27
+ */
28
+ getActiveModel: (providerId: string) => Promise<string | undefined>;
29
+ /**
30
+ * Gets the active provider ID.
31
+ *
32
+ * @returns The active provider ID
33
+ */
34
+ getActiveProvider: () => Promise<string>;
35
+ /**
36
+ * Gets favorite models for a provider.
37
+ *
38
+ * @param providerId The provider ID
39
+ * @returns Array of favorite model IDs
40
+ */
41
+ getFavoriteModels: (providerId: string) => Promise<readonly string[]>;
42
+ /**
43
+ * Gets recent models for a provider.
44
+ *
45
+ * @param providerId The provider ID
46
+ * @returns Array of recent model IDs
47
+ */
48
+ getRecentModels: (providerId: string) => Promise<readonly string[]>;
49
+ /**
50
+ * Checks if a provider is connected.
51
+ *
52
+ * @param providerId The provider ID to check
53
+ * @returns True if the provider is connected
54
+ */
55
+ isProviderConnected: (providerId: string) => Promise<boolean>;
56
+ /**
57
+ * Reads the provider configuration.
58
+ *
59
+ * @returns The configuration if found, default config otherwise
60
+ */
61
+ read: () => Promise<ProviderConfig>;
62
+ /**
63
+ * Sets the active model for a provider.
64
+ *
65
+ * @param providerId The provider ID
66
+ * @param modelId The model ID to set as active
67
+ */
68
+ setActiveModel: (providerId: string, modelId: string) => Promise<void>;
69
+ /**
70
+ * Sets the active provider.
71
+ *
72
+ * @param providerId The provider ID to set as active
73
+ */
74
+ setActiveProvider: (providerId: string) => Promise<void>;
75
+ /**
76
+ * Toggles a model as favorite.
77
+ *
78
+ * @param providerId The provider ID
79
+ * @param modelId The model ID to toggle
80
+ */
81
+ toggleFavorite: (providerId: string, modelId: string) => Promise<void>;
82
+ /**
83
+ * Writes the provider configuration.
84
+ *
85
+ * @param config The configuration to write
86
+ */
87
+ write: (config: ProviderConfig) => Promise<void>;
88
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Interface for storing provider API keys securely.
3
+ * Uses system keychain (macOS Keychain, Linux Secret Service, Windows Credential Manager).
4
+ */
5
+ export interface IProviderKeychainStore {
6
+ /**
7
+ * Deletes the API key for a provider.
8
+ *
9
+ * @param providerId The provider ID
10
+ */
11
+ deleteApiKey: (providerId: string) => Promise<void>;
12
+ /**
13
+ * Gets the API key for a provider.
14
+ *
15
+ * @param providerId The provider ID
16
+ * @returns The API key if found, undefined otherwise
17
+ */
18
+ getApiKey: (providerId: string) => Promise<string | undefined>;
19
+ /**
20
+ * Checks if an API key exists for a provider.
21
+ *
22
+ * @param providerId The provider ID
23
+ * @returns True if an API key exists
24
+ */
25
+ hasApiKey: (providerId: string) => Promise<boolean>;
26
+ /**
27
+ * Sets the API key for a provider.
28
+ *
29
+ * @param providerId The provider ID
30
+ * @param apiKey The API key to store
31
+ */
32
+ setApiKey: (providerId: string, apiKey: string) => Promise<void>;
33
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -6,7 +6,6 @@ import type { Space } from '../domain/entities/space.js';
6
6
  export interface ISpaceService {
7
7
  /**
8
8
  * Fetches spaces accessible to the authenticated user within a specific team.
9
- * @param accessToken The OAuth access token for authentication
10
9
  * @param sessionKey The session key for tracking the user session
11
10
  * @param teamId The team ID to filter spaces by
12
11
  * @param option Optional pagination options
@@ -17,7 +16,7 @@ export interface ISpaceService {
17
16
  * - spaces: Array of Space entities
18
17
  * - total: Total number of spaces available (across all pages)
19
18
  */
20
- getSpaces: (accessToken: string, sessionKey: string, teamId: string, option?: {
19
+ getSpaces: (sessionKey: string, teamId: string, option?: {
21
20
  fetchAll?: boolean;
22
21
  limit?: number;
23
22
  offset?: number;
@@ -6,7 +6,6 @@ import type { Team } from '../domain/entities/team.js';
6
6
  export interface ITeamService {
7
7
  /**
8
8
  * Fetches teams where the authenticated user is a member.
9
- * @param accessToken The OAuth access token for authentication
10
9
  * @param sessionKey The session key for tracking the user session
11
10
  * @param option Optional filtering and pagination options
12
11
  * @param option.limit Maximum number of teams to fetch in a single request
@@ -17,7 +16,7 @@ export interface ITeamService {
17
16
  * - teams: Array of Team entities
18
17
  * - total: Total number of teams available (across all pages)
19
18
  */
20
- getTeams: (accessToken: string, sessionKey: string, option?: {
19
+ getTeams: (sessionKey: string, option?: {
21
20
  fetchAll?: boolean;
22
21
  isActive?: boolean;
23
22
  limit?: number;
@@ -6,9 +6,8 @@ import type { User } from '../domain/entities/user.js';
6
6
  export interface IUserService {
7
7
  /**
8
8
  * Fetches the current authenticated user's information.
9
- * @param accessToken The OAuth access token for authentication
10
9
  * @param sessionKey The session key for tracking the user session
11
10
  * @returns A promise that resolves to the User entity
12
11
  */
13
- getCurrentUser: (accessToken: string, sessionKey: string) => Promise<User>;
12
+ getCurrentUser: (sessionKey: string) => Promise<User>;
14
13
  }
@@ -2,6 +2,8 @@ export interface CurateUseCaseRunOptions {
2
2
  apiKey?: string;
3
3
  context?: string;
4
4
  files?: string[];
5
+ format?: 'json' | 'text';
6
+ headless?: boolean;
5
7
  model?: string;
6
8
  verbose?: boolean;
7
9
  }
@@ -1,5 +1,11 @@
1
+ export interface InitUseCaseRunOptions {
2
+ force: boolean;
3
+ format?: 'json' | 'text';
4
+ /** Space ID for headless mode (skips interactive selection) */
5
+ spaceId?: string;
6
+ /** Team ID for headless mode (skips interactive selection) */
7
+ teamId?: string;
8
+ }
1
9
  export interface IInitUseCase {
2
- run(options: {
3
- force: boolean;
4
- }): Promise<void>;
10
+ run(options: InitUseCaseRunOptions): Promise<void>;
5
11
  }
@@ -1,3 +1,6 @@
1
+ export interface LoginUseCaseRunOptions {
2
+ apiKey?: string;
3
+ }
1
4
  export interface ILoginUseCase {
2
- run(): Promise<void>;
5
+ run(options: LoginUseCaseRunOptions): Promise<void>;
3
6
  }
@@ -1,5 +1,7 @@
1
+ export interface PullUseCaseRunOptions {
2
+ branch: string;
3
+ format?: 'json' | 'text';
4
+ }
1
5
  export interface IPullUseCase {
2
- run: (options: {
3
- branch: string;
4
- }) => Promise<void>;
6
+ run: (options: PullUseCaseRunOptions) => Promise<void>;
5
7
  }
@@ -1,6 +1,8 @@
1
+ export interface PushUseCaseRunOptions {
2
+ branch: string;
3
+ format?: 'json' | 'text';
4
+ skipConfirmation: boolean;
5
+ }
1
6
  export interface IPushUseCase {
2
- run(options: {
3
- branch: string;
4
- skipConfirmation: boolean;
5
- }): Promise<void>;
7
+ run(options: PushUseCaseRunOptions): Promise<void>;
6
8
  }
@@ -1,5 +1,7 @@
1
1
  export interface QueryUseCaseRunOptions {
2
2
  apiKey?: string;
3
+ format?: 'json' | 'text';
4
+ headless?: boolean;
3
5
  model?: string;
4
6
  query: string;
5
7
  verbose?: boolean;
@@ -1,5 +1,6 @@
1
1
  export interface IStatusUseCase {
2
2
  run(options: {
3
3
  cliVersion: string;
4
+ format?: 'json' | 'text';
4
5
  }): Promise<void>;
5
6
  }
@@ -39,7 +39,7 @@ export interface SessionLLMConfig {
39
39
  temperature?: number;
40
40
  verbose?: boolean;
41
41
  }
42
- export type { CipherAgentServices, SessionManagerConfig, SessionServices } from '../../../core/interfaces/cipher/cipher-services.js';
42
+ export type { CipherAgentServices, SessionManagerConfig, SessionServices, } from '../../../core/interfaces/cipher/cipher-services.js';
43
43
  /**
44
44
  * Creates shared services for CipherAgent.
45
45
  * These services are singletons shared across all sessions.
@@ -232,7 +232,6 @@ export function createSessionServices(sessionId, sharedServices, httpConfig, llm
232
232
  // Use HTTP backend service (default) with generator pattern
233
233
  // Step 1: Create HTTP service
234
234
  const httpService = new ByteRoverLlmHttpService({
235
- accessToken: httpConfig.accessToken,
236
235
  apiBaseUrl: httpConfig.apiBaseUrl,
237
236
  projectId: httpConfig.projectId,
238
237
  region: httpConfig.region,
@@ -314,12 +314,12 @@ export class FileSystemService {
314
314
  */
315
315
  async listDirectory(dirPath, options = {}) {
316
316
  this.ensureInitialized();
317
- // Resolve path
318
- const resolvedPath = path.resolve(this.config.workingDirectory, dirPath || '.');
319
- // Validate path
320
- const validation = this.pathValidator.validate(resolvedPath, 'read');
317
+ // Validate path - let PathValidator handle resolution to prevent path duplication
318
+ // (e.g., when workingDirectory is .brv/context-tree and dirPath is also .brv/context-tree)
319
+ const pathToValidate = dirPath || '.';
320
+ const validation = this.pathValidator.validate(pathToValidate, 'read');
321
321
  if (!validation.valid) {
322
- this.throwValidationError(resolvedPath, validation.error);
322
+ this.throwValidationError(pathToValidate, validation.error);
323
323
  }
324
324
  const { normalizedPath } = validation;
325
325
  // Verify directory exists
@@ -1,11 +1,11 @@
1
1
  import type { RequestOptions } from '@anthropic-ai/sdk/internal/request-options';
2
2
  import type { MessageCreateParamsNonStreaming } from '@anthropic-ai/sdk/resources/messages.js';
3
3
  import type { Content, GenerateContentConfig, GenerateContentResponse } from '@google/genai';
4
+ import type { GenerateContentChunk } from '../../../core/interfaces/cipher/i-content-generator.js';
4
5
  /**
5
6
  * ByteRover HTTP LLM provider configuration.
6
7
  */
7
8
  export interface ByteRoverHttpConfig {
8
- accessToken: string;
9
9
  apiBaseUrl: string;
10
10
  projectId?: string;
11
11
  region?: string;
@@ -61,6 +61,22 @@ export declare class ByteRoverLlmHttpService {
61
61
  * @returns Response in GenerateContentResponse format
62
62
  */
63
63
  generateContent(contents: Content[] | MessageCreateParamsNonStreaming, config: GenerateContentConfig | RequestOptions, model: string, executionMetadata?: Record<string, unknown>): Promise<GenerateContentResponse>;
64
+ /**
65
+ * Call ByteRover REST LLM service to generate content with streaming.
66
+ *
67
+ * Currently falls back to non-streaming endpoint since /api/llm/generate/stream
68
+ * doesn't exist on the backend yet. Extracts thinking/reasoning from the complete
69
+ * response and yields them as separate chunks.
70
+ *
71
+ * When backend streaming is available, this will use SSE for true streaming.
72
+ *
73
+ * @param contents - For Gemini: Content[]. For Claude: MessageCreateParamsNonStreaming (complete body)
74
+ * @param config - For Gemini: GenerateContentConfig. For Claude: RequestOptions (optional HTTP options)
75
+ * @param model - Model to use (detects provider from model name)
76
+ * @param executionMetadata - Optional execution metadata (mode, executionContext)
77
+ * @yields GenerateContentChunk objects as they are generated
78
+ */
79
+ generateContentStream(contents: Content[] | MessageCreateParamsNonStreaming, config: GenerateContentConfig | RequestOptions, model: string, executionMetadata?: Record<string, unknown>): AsyncGenerator<GenerateContentChunk>;
64
80
  /**
65
81
  * Call the ByteRover REST Generate endpoint.
66
82
  *
@@ -91,4 +107,27 @@ export declare class ByteRoverLlmHttpService {
91
107
  * @returns GCP region identifier ('us-east5' or 'global')
92
108
  */
93
109
  private detectRegionFromModel;
110
+ /**
111
+ * Extract content chunks from a complete response.
112
+ *
113
+ * Looks for text parts (excluding thinking) and function calls,
114
+ * yields them as final chunks.
115
+ *
116
+ * @param response - Complete GenerateContentResponse
117
+ * @yields GenerateContentChunk for content and tool calls
118
+ */
119
+ private extractContentFromResponse;
120
+ /**
121
+ * Extract thinking/reasoning chunks from a complete response.
122
+ *
123
+ * Looks for parts with `thought: true` and yields them as THINKING chunks.
124
+ *
125
+ * @param response - Complete GenerateContentResponse
126
+ * @yields GenerateContentChunk for each thinking part
127
+ */
128
+ private extractThinkingFromResponse;
129
+ /**
130
+ * Map provider finish reason to standard format.
131
+ */
132
+ private mapFinishReason;
94
133
  }