byterover-cli 1.0.3 → 1.0.4

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 (127) hide show
  1. package/README.md +62 -10
  2. package/dist/commands/curate.js +2 -2
  3. package/dist/commands/main.js +2 -2
  4. package/dist/commands/query.js +2 -2
  5. package/dist/commands/status.js +2 -2
  6. package/dist/config/context-tree-domains.d.ts +14 -2
  7. package/dist/config/context-tree-domains.js +22 -27
  8. package/dist/constants.d.ts +1 -0
  9. package/dist/constants.js +3 -0
  10. package/dist/core/domain/cipher/file-system/types.d.ts +2 -0
  11. package/dist/core/domain/entities/auth-token.js +6 -3
  12. package/dist/core/domain/entities/event.d.ts +1 -1
  13. package/dist/core/domain/entities/event.js +2 -1
  14. package/dist/core/domain/knowledge/relation-parser.d.ts +16 -1
  15. package/dist/core/domain/knowledge/relation-parser.js +19 -2
  16. package/dist/core/domain/transport/schemas.d.ts +17 -1
  17. package/dist/core/domain/transport/schemas.js +9 -1
  18. package/dist/core/interfaces/cipher/i-blob-storage.d.ts +6 -0
  19. package/dist/core/interfaces/cipher/index.d.ts +0 -1
  20. package/dist/core/interfaces/executor/i-curate-executor.d.ts +2 -0
  21. package/dist/infra/cipher/agent/cipher-agent.js +4 -0
  22. package/dist/infra/cipher/file-system/file-system-service.d.ts +4 -0
  23. package/dist/infra/cipher/file-system/file-system-service.js +5 -0
  24. package/dist/infra/cipher/system-prompt/contributors/context-tree-structure-contributor.js +4 -2
  25. package/dist/infra/cipher/tools/implementations/create-knowledge-topic-tool.js +24 -17
  26. package/dist/infra/cipher/tools/implementations/curate-tool.js +28 -33
  27. package/dist/infra/cipher/tools/implementations/read-file-tool.js +3 -12
  28. package/dist/infra/cipher/tools/implementations/spec-analyze-tool.js +18 -15
  29. package/dist/infra/cipher/tools/implementations/task-tool.js +53 -7
  30. package/dist/infra/context-tree/file-context-tree-service.js +4 -15
  31. package/dist/infra/core/executors/curate-executor.d.ts +2 -7
  32. package/dist/infra/core/executors/curate-executor.js +18 -53
  33. package/dist/infra/core/executors/query-executor.d.ts +1 -7
  34. package/dist/infra/core/executors/query-executor.js +10 -35
  35. package/dist/infra/core/task-processor.d.ts +2 -0
  36. package/dist/infra/core/task-processor.js +1 -0
  37. package/dist/infra/http/authenticated-http-client.js +5 -0
  38. package/dist/infra/process/agent-worker.js +113 -6
  39. package/dist/infra/process/constants.d.ts +1 -0
  40. package/dist/infra/process/constants.js +1 -0
  41. package/dist/infra/process/task-queue-manager.js +2 -1
  42. package/dist/infra/process/transport-handlers.js +4 -0
  43. package/dist/infra/process/transport-worker.js +89 -1
  44. package/dist/infra/repl/commands/curate-command.js +2 -2
  45. package/dist/infra/repl/commands/gen-rules-command.js +2 -2
  46. package/dist/infra/repl/commands/init-command.js +2 -2
  47. package/dist/infra/repl/commands/login-command.js +2 -2
  48. package/dist/infra/repl/commands/logout-command.js +2 -2
  49. package/dist/infra/repl/commands/pull-command.js +2 -2
  50. package/dist/infra/repl/commands/push-command.js +2 -2
  51. package/dist/infra/repl/commands/query-command.js +2 -2
  52. package/dist/infra/repl/commands/space/list-command.js +2 -2
  53. package/dist/infra/repl/commands/space/switch-command.js +2 -2
  54. package/dist/infra/repl/commands/status-command.js +2 -2
  55. package/dist/infra/repl/repl-startup.js +0 -2
  56. package/dist/infra/storage/file-token-store.d.ts +31 -0
  57. package/dist/infra/storage/file-token-store.js +98 -0
  58. package/dist/infra/storage/keychain-token-store.d.ts +4 -1
  59. package/dist/infra/storage/keychain-token-store.js +6 -4
  60. package/dist/infra/storage/token-store.d.ts +10 -0
  61. package/dist/infra/storage/token-store.js +14 -0
  62. package/dist/infra/usecase/curate-use-case.js +1 -1
  63. package/dist/infra/user/http-user-service.js +6 -11
  64. package/dist/resources/prompts/curate.yml +14 -5
  65. package/dist/resources/prompts/plan.yml +6 -0
  66. package/dist/tui/app.js +1 -1
  67. package/dist/tui/components/execution/log-item.js +2 -5
  68. package/dist/tui/components/header.d.ts +1 -1
  69. package/dist/tui/components/header.js +25 -4
  70. package/dist/tui/components/index.d.ts +5 -1
  71. package/dist/tui/components/index.js +3 -1
  72. package/dist/tui/components/init.d.ts +33 -0
  73. package/dist/tui/components/init.js +253 -0
  74. package/dist/tui/components/onboarding/index.d.ts +1 -0
  75. package/dist/tui/components/onboarding/index.js +1 -0
  76. package/dist/tui/components/onboarding/onboarding-flow.d.ts +2 -0
  77. package/dist/tui/components/onboarding/onboarding-flow.js +8 -229
  78. package/dist/tui/components/onboarding/onboarding-step.js +1 -1
  79. package/dist/tui/components/onboarding/welcome-box.d.ts +14 -0
  80. package/dist/tui/components/onboarding/welcome-box.js +23 -0
  81. package/dist/tui/components/status-badge.d.ts +22 -0
  82. package/dist/tui/components/status-badge.js +32 -0
  83. package/dist/tui/contexts/auth-context.js +2 -1
  84. package/dist/tui/contexts/index.d.ts +1 -0
  85. package/dist/tui/contexts/index.js +1 -0
  86. package/dist/tui/contexts/onboarding-context.d.ts +14 -0
  87. package/dist/tui/contexts/onboarding-context.js +17 -22
  88. package/dist/tui/contexts/status-context.d.ts +33 -0
  89. package/dist/tui/contexts/status-context.js +159 -0
  90. package/dist/tui/hooks/use-auth-polling.d.ts +4 -1
  91. package/dist/tui/hooks/use-auth-polling.js +21 -7
  92. package/dist/tui/hooks/use-tab-navigation.js +0 -2
  93. package/dist/tui/providers/app-providers.js +2 -2
  94. package/dist/tui/types/index.d.ts +2 -0
  95. package/dist/tui/types/index.js +2 -0
  96. package/dist/tui/types/status.d.ts +46 -0
  97. package/dist/tui/types/status.js +13 -0
  98. package/dist/tui/utils/index.d.ts +6 -0
  99. package/dist/tui/utils/index.js +6 -0
  100. package/dist/tui/utils/time.d.ts +10 -0
  101. package/dist/tui/utils/time.js +15 -0
  102. package/dist/tui/views/command-view.js +0 -2
  103. package/dist/tui/views/index.d.ts +1 -0
  104. package/dist/tui/views/index.js +1 -0
  105. package/dist/tui/views/init-view.d.ts +15 -0
  106. package/dist/tui/views/init-view.js +29 -0
  107. package/dist/tui/views/logs-view.js +22 -8
  108. package/dist/utils/environment-detector.d.ts +5 -0
  109. package/dist/utils/environment-detector.js +31 -0
  110. package/dist/utils/global-data-path.d.ts +11 -0
  111. package/dist/utils/global-data-path.js +32 -0
  112. package/oclif.manifest.json +1 -1
  113. package/package.json +1 -1
  114. package/dist/core/interfaces/cipher/i-agent-storage.d.ts +0 -152
  115. package/dist/core/interfaces/cipher/i-agent-storage.js +0 -1
  116. package/dist/infra/cipher/consumer/consumer-lock.d.ts +0 -20
  117. package/dist/infra/cipher/consumer/consumer-lock.js +0 -41
  118. package/dist/infra/cipher/consumer/consumer-service.d.ts +0 -99
  119. package/dist/infra/cipher/consumer/consumer-service.js +0 -166
  120. package/dist/infra/cipher/consumer/execution-consumer.d.ts +0 -126
  121. package/dist/infra/cipher/consumer/execution-consumer.js +0 -561
  122. package/dist/infra/cipher/consumer/index.d.ts +0 -33
  123. package/dist/infra/cipher/consumer/index.js +0 -34
  124. package/dist/infra/cipher/consumer/queue-polling-service.d.ts +0 -120
  125. package/dist/infra/cipher/consumer/queue-polling-service.js +0 -249
  126. package/dist/infra/cipher/storage/agent-storage.d.ts +0 -246
  127. package/dist/infra/cipher/storage/agent-storage.js +0 -956
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ByteRover CLI
2
2
 
3
- Command-line interface for ByteRover, featuring an interactive REPL with a modern terminal UI for managing your project's context tree and memory storage.
3
+ Command-line interface for ByteRover, featuring an interactive REPL with a modern React/Ink terminal UI for managing your project's context tree and knowledge storage. Seamlessly integrate with AI coding agents like Claude Code, Cursor, Windsurf, and GitHub Copilot.
4
4
 
5
5
  [![Version](https://img.shields.io/npm/v/byterover-cli.svg)](https://npmjs.org/package/byterover-cli)
6
6
  [![Downloads/week](https://img.shields.io/npm/dw/byterover-cli.svg)](https://npmjs.org/package/byterover-cli)
@@ -15,6 +15,7 @@ Command-line interface for ByteRover, featuring an interactive REPL with a moder
15
15
  * [Slash Commands Reference](#slash-commands-reference)
16
16
  * [Authentication](#authentication)
17
17
  * [Configuration](#configuration)
18
+ * [Troubleshooting](#troubleshooting)
18
19
  * [Getting Help](#getting-help)
19
20
 
20
21
  ## Installation
@@ -90,6 +91,16 @@ brv
90
91
 
91
92
  Running `brv` without arguments starts the interactive REPL. The REPL requires an interactive terminal (TTY).
92
93
 
94
+ ### TUI Features
95
+
96
+ The terminal UI includes:
97
+
98
+ - **Tab Navigation**: Switch between Chat and Activity views using `Tab`
99
+ - **Command Completion**: Type `/` to see available commands with auto-completion
100
+ - **Activity Log**: Real-time task status and execution progress
101
+ - **Streaming Output**: Live responses from AI-powered operations
102
+ - **File References**: Type `@` in curate mode to browse and attach files
103
+
93
104
  ### Using Commands
94
105
 
95
106
  In the REPL, use slash commands (commands prefixed with `/`) to interact with ByteRover:
@@ -104,24 +115,33 @@ Commands support tab completion for quick navigation.
104
115
 
105
116
  ## What is Context Tree?
106
117
 
107
- The **Context Tree** is ByteRover's structured memory system that helps you and your coding agents organize, store, and retrieve project knowledge efficiently.
118
+ The **Context Tree** is ByteRover's structured knowledge system that helps you and your AI coding agents organize, store, and retrieve project context efficiently.
108
119
 
109
120
  ### Why Use Context Tree?
110
121
 
111
122
  - **Organized Knowledge**: Structure your project knowledge by domain and topic
112
123
  - **Easy Retrieval**: Find relevant context quickly when you need it
113
124
  - **Persistent Memory**: Maintain project-specific knowledge across sessions
114
- - **Agent-Friendly**: Works seamlessly with coding agents like Claude Code, Cursor, and others
115
- - **Version Control**: Push and sync your context to ByteRover's cloud storage
125
+ - **Agent-Friendly**: Works seamlessly with AI coding agents like Claude Code, Cursor, Windsurf, and GitHub Copilot
126
+ - **Cloud Sync**: Push and sync your context tree to ByteRover's cloud storage for backup and team collaboration
127
+ - **Dynamic Domains**: Automatically creates new domains as your knowledge grows
116
128
 
117
129
  ### How It Works
118
130
 
119
131
  The context tree organizes knowledge into:
120
- - **Domains**: High-level categories (e.g., Architecture, API, Frontend)
132
+ - **Domains**: High-level categories (e.g., Architecture, API, Frontend) — created automatically or manually
121
133
  - **Topics**: Specific subjects within domains (e.g., Authentication, Components)
122
134
  - **Context Files**: Markdown files containing your actual knowledge
123
135
 
124
- For comprehensive instructions for coding agents, use `/gen-rules` to generate rule files.
136
+ ### Integrating with Coding Agents
137
+
138
+ Use `/gen-rules` to generate rule instruction files that help your AI coding agents understand and work with ByteRover:
139
+
140
+ ```
141
+ /gen-rules
142
+ ```
143
+
144
+ This creates agent-specific rule files (e.g., `CLAUDE.md`, `.cursorrules`) that instruct the agent how to read from and contribute to your context tree.
125
145
 
126
146
  ## Slash Commands Reference
127
147
 
@@ -150,8 +170,8 @@ For comprehensive instructions for coding agents, use `/gen-rules` to generate r
150
170
 
151
171
  | Command | Description |
152
172
  |---------|-------------|
153
- | `/push [-b branch] [-y]` | Push context tree to ByteRover memory storage |
154
- | `/pull [-b branch]` | Pull context tree from ByteRover memory storage |
173
+ | `/push [-b branch] [-y]` | Push context tree to ByteRover cloud storage |
174
+ | `/pull [-b branch]` | Pull context tree from ByteRover cloud storage |
155
175
 
156
176
  **Options:**
157
177
  - `-b, --branch <name>`: ByteRover branch name (default: `main`)
@@ -182,7 +202,7 @@ For comprehensive instructions for coding agents, use `/gen-rules` to generate r
182
202
 
183
203
  | Command | Description |
184
204
  |---------|-------------|
185
- | `/gen-rules` | Generate rule instructions for coding agents |
205
+ | `/gen-rules` | Generate rule files for AI coding agents (Claude Code, Cursor, etc.) |
186
206
  | `/clear [-y] [directory]` | Reset context tree to default domains |
187
207
 
188
208
  **Clear options:**
@@ -232,6 +252,16 @@ When you run `/init`, a configuration file is created at `.brv/config.json` in y
232
252
  - **User information**: Your user ID and email
233
253
  - **Project settings**: Project-specific configuration
234
254
 
255
+ ### Global Configuration
256
+
257
+ User-level configuration is stored at `~/.config/brv/`:
258
+
259
+ ```
260
+ ~/.config/brv/
261
+ ├── config.json # Global settings and device ID
262
+ └── logs/ # Session logs for debugging
263
+ ```
264
+
235
265
  ### Context Tree Structure
236
266
 
237
267
  The context tree is stored in `.brv/context-tree/`:
@@ -255,7 +285,29 @@ The context tree is stored in `.brv/context-tree/`:
255
285
  └── context.md
256
286
  ```
257
287
 
258
- **Note**: When you run `/push`, your context tree is uploaded to ByteRover's memory storage for version control and team collaboration.
288
+ **Note**: When you run `/push`, your context tree is uploaded to ByteRover's cloud storage for version control and team collaboration.
289
+
290
+ ## Troubleshooting
291
+
292
+ ### Session Logs
293
+
294
+ If you encounter issues, session logs are stored at `~/.config/brv/logs/`. Each session creates a timestamped log file (e.g., `brv-2024-01-15T10-30-00.log`) that can help diagnose problems.
295
+
296
+ ### Instance Lock
297
+
298
+ ByteRover CLI ensures only one instance runs per project folder. If you see an "instance already running" message:
299
+
300
+ 1. Check for another terminal with `brv` running in the same directory
301
+ 2. If no other instance is visible, the lock file may be stale — it will auto-release on the next start
302
+
303
+ ### Common Issues
304
+
305
+ | Issue | Solution |
306
+ |-------|----------|
307
+ | "REPL requires an interactive terminal" | Run `brv` directly in a terminal, not through piped commands |
308
+ | Authentication expires frequently | Run `/login` to refresh your session |
309
+ | Context tree not syncing | Check `/status` for sync status, then try `/push` or `/pull` |
310
+ | Rule files not generated | Ensure you're in a project directory with `.brv/` initialized |
259
311
 
260
312
  ## Getting Help
261
313
 
@@ -1,7 +1,7 @@
1
1
  import { Args, Command, Flags } from '@oclif/core';
2
2
  import { isDevelopment } from '../config/environment.js';
3
3
  import { FileGlobalConfigStore } from '../infra/storage/file-global-config-store.js';
4
- import { KeychainTokenStore } from '../infra/storage/keychain-token-store.js';
4
+ import { createTokenStore } from '../infra/storage/token-store.js';
5
5
  import { OclifTerminal } from '../infra/terminal/oclif-terminal.js';
6
6
  import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
7
7
  import { CurateUseCase } from '../infra/usecase/curate-use-case.js';
@@ -49,7 +49,7 @@ Bad examples:
49
49
  : {}),
50
50
  };
51
51
  createUseCase() {
52
- const tokenStore = new KeychainTokenStore();
52
+ const tokenStore = createTokenStore();
53
53
  const globalConfigStore = new FileGlobalConfigStore();
54
54
  const terminal = new OclifTerminal(this);
55
55
  const trackingService = new MixpanelTrackingService({ globalConfigStore, tokenStore });
@@ -4,7 +4,7 @@ import { getProcessManager } from '../infra/process/index.js';
4
4
  import { startRepl } from '../infra/repl/repl-startup.js';
5
5
  import { FileGlobalConfigStore } from '../infra/storage/file-global-config-store.js';
6
6
  import { FileOnboardingPreferenceStore } from '../infra/storage/file-onboarding-preference-store.js';
7
- import { KeychainTokenStore } from '../infra/storage/keychain-token-store.js';
7
+ import { createTokenStore } from '../infra/storage/token-store.js';
8
8
  import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
9
9
  import { initSessionLog } from '../utils/process-logger.js';
10
10
  /**
@@ -33,7 +33,7 @@ export default class Main extends Command {
33
33
  // Start Transport and Agent processes (v0.5.0 architecture)
34
34
  const processManager = getProcessManager();
35
35
  await processManager.start();
36
- const tokenStore = new KeychainTokenStore();
36
+ const tokenStore = createTokenStore();
37
37
  const globalConfigStore = new FileGlobalConfigStore();
38
38
  const trackingService = new MixpanelTrackingService({ globalConfigStore, tokenStore });
39
39
  const onboardingPreferenceStore = new FileOnboardingPreferenceStore();
@@ -1,7 +1,7 @@
1
1
  import { Args, Command, Flags } from '@oclif/core';
2
2
  import { isDevelopment } from '../config/environment.js';
3
3
  import { FileGlobalConfigStore } from '../infra/storage/file-global-config-store.js';
4
- import { KeychainTokenStore } from '../infra/storage/keychain-token-store.js';
4
+ import { createTokenStore } from '../infra/storage/token-store.js';
5
5
  import { OclifTerminal } from '../infra/terminal/oclif-terminal.js';
6
6
  import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
7
7
  import { QueryUseCase } from '../infra/usecase/query-use-case.js';
@@ -40,7 +40,7 @@ Bad:
40
40
  };
41
41
  static strict = false;
42
42
  createUseCase() {
43
- const tokenStore = new KeychainTokenStore();
43
+ const tokenStore = createTokenStore();
44
44
  const globalConfigStore = new FileGlobalConfigStore();
45
45
  const trackingService = new MixpanelTrackingService({ globalConfigStore, tokenStore });
46
46
  return new QueryUseCase({
@@ -3,7 +3,7 @@ import { ProjectConfigStore } from '../infra/config/file-config-store.js';
3
3
  import { FileContextTreeService } from '../infra/context-tree/file-context-tree-service.js';
4
4
  import { FileContextTreeSnapshotService } from '../infra/context-tree/file-context-tree-snapshot-service.js';
5
5
  import { FileGlobalConfigStore } from '../infra/storage/file-global-config-store.js';
6
- import { KeychainTokenStore } from '../infra/storage/keychain-token-store.js';
6
+ import { createTokenStore } from '../infra/storage/token-store.js';
7
7
  import { OclifTerminal } from '../infra/terminal/oclif-terminal.js';
8
8
  import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
9
9
  import { StatusUseCase } from '../infra/usecase/status-use-case.js';
@@ -29,7 +29,7 @@ export default class Status extends Command {
29
29
  }),
30
30
  };
31
31
  createUseCase() {
32
- const tokenStore = new KeychainTokenStore();
32
+ const tokenStore = createTokenStore();
33
33
  const globalConfigStore = new FileGlobalConfigStore();
34
34
  const trackingService = new MixpanelTrackingService({ globalConfigStore, tokenStore });
35
35
  const contextTreeSnapshotService = new FileContextTreeSnapshotService();
@@ -1,17 +1,29 @@
1
1
  /**
2
2
  * Domain configurations for the context tree structure.
3
3
  * Each domain represents a specific area of knowledge in the project.
4
+ *
5
+ * @deprecated Domains are now created dynamically based on content semantics.
6
+ * This file is kept for backward compatibility only.
4
7
  */
5
8
  export interface DomainConfig {
6
9
  description: string;
7
10
  name: string;
8
11
  }
9
12
  /**
10
- * Predefined domains that will be scaffolded during project initialization.
13
+ * Example domain names for reference only.
14
+ * Domains are now created dynamically by the agent based on content.
15
+ *
16
+ * @deprecated Domains are created dynamically. These are kept as examples only.
17
+ */
18
+ export declare const EXAMPLE_DOMAIN_NAMES: readonly ["authentication", "api_design", "data_models", "error_handling", "ui_components", "testing_patterns", "configuration", "logging", "security", "performance"];
19
+ /**
20
+ * @deprecated Domains are now created dynamically based on content semantics.
21
+ * The agent will create domain names that are semantically meaningful for the curated content.
22
+ * This constant is kept for backward compatibility but is no longer used.
11
23
  */
12
24
  export declare const DEFAULT_CONTEXT_TREE_DOMAINS: DomainConfig[];
13
25
  /**
14
26
  * Alias for backward compatibility.
15
- * @deprecated Use DEFAULT_CONTEXT_TREE_DOMAINS instead
27
+ * @deprecated Domains are created dynamically. This constant is no longer used.
16
28
  */
17
29
  export declare const CONTEXT_TREE_DOMAINS: DomainConfig[];
@@ -1,34 +1,29 @@
1
1
  /**
2
- * Predefined domains that will be scaffolded during project initialization.
2
+ * Example domain names for reference only.
3
+ * Domains are now created dynamically by the agent based on content.
4
+ *
5
+ * @deprecated Domains are created dynamically. These are kept as examples only.
3
6
  */
4
- export const DEFAULT_CONTEXT_TREE_DOMAINS = [
5
- {
6
- description: 'Ensure all code follows style guidelines and quality standards',
7
- name: 'code_style',
8
- },
9
- {
10
- description: 'UI libraries, themes, and design guidelines',
11
- name: 'design',
12
- },
13
- {
14
- description: 'Project structure, components, and related context',
15
- name: 'structure',
16
- },
17
- {
18
- description: 'Security and compliance information',
19
- name: 'compliance',
20
- },
21
- {
22
- description: 'Testing implementation context',
23
- name: 'testing',
24
- },
25
- {
26
- description: 'Bug fixing logic and procedures',
27
- name: 'bug_fixes',
28
- },
7
+ export const EXAMPLE_DOMAIN_NAMES = [
8
+ 'authentication',
9
+ 'api_design',
10
+ 'data_models',
11
+ 'error_handling',
12
+ 'ui_components',
13
+ 'testing_patterns',
14
+ 'configuration',
15
+ 'logging',
16
+ 'security',
17
+ 'performance',
29
18
  ];
19
+ /**
20
+ * @deprecated Domains are now created dynamically based on content semantics.
21
+ * The agent will create domain names that are semantically meaningful for the curated content.
22
+ * This constant is kept for backward compatibility but is no longer used.
23
+ */
24
+ export const DEFAULT_CONTEXT_TREE_DOMAINS = [];
30
25
  /**
31
26
  * Alias for backward compatibility.
32
- * @deprecated Use DEFAULT_CONTEXT_TREE_DOMAINS instead
27
+ * @deprecated Domains are created dynamically. This constant is no longer used.
33
28
  */
34
29
  export const CONTEXT_TREE_DOMAINS = DEFAULT_CONTEXT_TREE_DOMAINS;
@@ -6,6 +6,7 @@ export declare const BRV_CONFIG_VERSION = "0.0.1";
6
6
  export declare const GLOBAL_CONFIG_DIR = "brv";
7
7
  export declare const GLOBAL_CONFIG_FILE = "config.json";
8
8
  export declare const GLOBAL_CONFIG_VERSION = "0.0.1";
9
+ export declare const GLOBAL_DATA_DIR = "brv";
9
10
  export declare const ACE_DIR = "ace";
10
11
  export declare const PROJECT = "byterover";
11
12
  export declare const CONTEXT_TREE_DIR = "context-tree";
package/dist/constants.js CHANGED
@@ -7,6 +7,9 @@ export const BRV_CONFIG_VERSION = '0.0.1';
7
7
  export const GLOBAL_CONFIG_DIR = 'brv';
8
8
  export const GLOBAL_CONFIG_FILE = 'config.json';
9
9
  export const GLOBAL_CONFIG_VERSION = '0.0.1';
10
+ // Global data directory name (for XDG_DATA_HOME - secrets, credentials, cache)
11
+ // Same value as GLOBAL_CONFIG_DIR but different semantic purpose
12
+ export const GLOBAL_DATA_DIR = 'brv';
10
13
  // ACE directory structure constants
11
14
  export const ACE_DIR = 'ace';
12
15
  export const PROJECT = 'byterover';
@@ -146,6 +146,8 @@ export interface FileContent {
146
146
  totalLines: number;
147
147
  /** Whether content was truncated due to size/line limits */
148
148
  truncated: boolean;
149
+ /** Number of lines that were truncated due to excessive length */
150
+ truncatedLineCount?: number;
149
151
  }
150
152
  /**
151
153
  * Result of a file write operation.
@@ -24,9 +24,12 @@ export class AuthToken {
24
24
  * @returns An instance of AuthToken, or undefined if required fields are missing
25
25
  */
26
26
  static fromJson(json) {
27
- // Validate that new required fields exist (for backward compatibility with old tokens)
28
- if (!json.userId || !json.userEmail) {
29
- return undefined;
27
+ // Validate ALL required fields exist (prevents corrupted/incomplete tokens from being loaded)
28
+ const requiredFields = ['accessToken', 'expiresAt', 'refreshToken', 'sessionKey', 'userEmail', 'userId'];
29
+ for (const field of requiredFields) {
30
+ if (!json[field]) {
31
+ return undefined;
32
+ }
30
33
  }
31
34
  return new AuthToken({
32
35
  accessToken: json.accessToken,
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Array of all supported Events.
3
3
  */
4
- export declare const EVENT_VALUES: readonly ["repl", "auth:sign_in", "auth:signed_out", "space:init", "space:changed", "rule:generate", "mem:status", "mem:curate", "mem:pull", "mem:push", "mem:query", "onboarding:init_completed", "onboarding:curate_completed", "onboarding:query_completed", "onboarding:skipped", "onboarding:completed", "init"];
4
+ export declare const EVENT_VALUES: readonly ["repl", "auth:sign_in", "auth:signed_out", "auth:token_invalid", "space:init", "space:changed", "rule:generate", "mem:status", "mem:curate", "mem:pull", "mem:push", "mem:query", "onboarding:init_completed", "onboarding:curate_completed", "onboarding:query_completed", "onboarding:skipped", "onboarding:completed", "init"];
5
5
  export type EventName = (typeof EVENT_VALUES)[number];
6
6
  export interface PropertyDict {
7
7
  [key: string]: any;
@@ -5,6 +5,7 @@ export const EVENT_VALUES = [
5
5
  'repl',
6
6
  'auth:sign_in',
7
7
  'auth:signed_out',
8
+ 'auth:token_invalid',
8
9
  'space:init',
9
10
  'space:changed',
10
11
  'rule:generate',
@@ -18,5 +19,5 @@ export const EVENT_VALUES = [
18
19
  'onboarding:query_completed',
19
20
  'onboarding:skipped',
20
21
  'onboarding:completed',
21
- 'init'
22
+ 'init',
22
23
  ];
@@ -71,11 +71,26 @@ export declare function resolveRelationPath(basePath: string, relation: string):
71
71
  * ```
72
72
  */
73
73
  export declare function formatRelation(domain: string, topic: string, subtopic?: string): string;
74
+ /**
75
+ * Normalize a relation path by removing the @ prefix.
76
+ *
77
+ * @param relation - Relation path to normalize
78
+ * @returns Normalized relation path
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * normalizeRelation('code_style/error-handling') // 'code_style/error-handling'
83
+ * normalizeRelation('@code_style/error-handling') // 'code_style/error-handling'
84
+ * normalizeRelation('code_style/error-handling/title.md') // 'code_style/error-handling/title.md'
85
+ * normalizeRelation('@@@code_style/error-handling/title.md') // 'code_style/error-handling/title.md'
86
+ * ```
87
+ */
88
+ export declare function normalizeRelation(relation: string): string;
74
89
  /**
75
90
  * Generate the Relations section for context.md.
76
91
  * Returns empty string if no relations provided.
77
92
  *
78
- * @param relations - Array of relation paths (without @ prefix)
93
+ * @param relations - Array of relation paths (with or without @ prefix)
79
94
  * @returns Markdown formatted Relations section or empty string
80
95
  *
81
96
  * @example
@@ -104,11 +104,28 @@ export function formatRelation(domain, topic, subtopic) {
104
104
  ? `@${domain}/${topic}/${subtopic}`
105
105
  : `@${domain}/${topic}`;
106
106
  }
107
+ /**
108
+ * Normalize a relation path by removing the @ prefix.
109
+ *
110
+ * @param relation - Relation path to normalize
111
+ * @returns Normalized relation path
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * normalizeRelation('code_style/error-handling') // 'code_style/error-handling'
116
+ * normalizeRelation('@code_style/error-handling') // 'code_style/error-handling'
117
+ * normalizeRelation('code_style/error-handling/title.md') // 'code_style/error-handling/title.md'
118
+ * normalizeRelation('@@@code_style/error-handling/title.md') // 'code_style/error-handling/title.md'
119
+ * ```
120
+ */
121
+ export function normalizeRelation(relation) {
122
+ return relation.replace(/^@+/, '');
123
+ }
107
124
  /**
108
125
  * Generate the Relations section for context.md.
109
126
  * Returns empty string if no relations provided.
110
127
  *
111
- * @param relations - Array of relation paths (without @ prefix)
128
+ * @param relations - Array of relation paths (with or without @ prefix)
112
129
  * @returns Markdown formatted Relations section or empty string
113
130
  *
114
131
  * @example
@@ -125,7 +142,7 @@ export function generateRelationsSection(relations) {
125
142
  return '';
126
143
  }
127
144
  const formattedRelations = relations
128
- .map(rel => `@${rel}`)
145
+ .map(rel => `@${normalizeRelation(rel)}`)
129
146
  .join('\n');
130
147
  return `\n## Relations\n${formattedRelations}\n`;
131
148
  }
@@ -451,6 +451,8 @@ export declare const TransportSessionEventNames: {
451
451
  export declare const TaskExecuteSchema: z.ZodObject<{
452
452
  /** Client ID that created the task (for response routing) */
453
453
  clientId: z.ZodString;
454
+ /** Client's working directory for file validation */
455
+ clientCwd: z.ZodOptional<z.ZodString>;
454
456
  /** Task content/prompt */
455
457
  content: z.ZodString;
456
458
  /** Optional file paths for curate --files */
@@ -464,12 +466,14 @@ export declare const TaskExecuteSchema: z.ZodObject<{
464
466
  content: string;
465
467
  clientId: string;
466
468
  taskId: string;
469
+ clientCwd?: string | undefined;
467
470
  files?: string[] | undefined;
468
471
  }, {
469
472
  type: "curate" | "query";
470
473
  content: string;
471
474
  clientId: string;
472
475
  taskId: string;
476
+ clientCwd?: string | undefined;
473
477
  files?: string[] | undefined;
474
478
  }>;
475
479
  /**
@@ -606,6 +610,8 @@ export declare const TaskAckSchema: z.ZodObject<{
606
610
  * Sent to broadcast-room for TUI monitoring
607
611
  */
608
612
  export declare const TaskCreatedSchema: z.ZodObject<{
613
+ /** Client's working directory for file validation */
614
+ clientCwd: z.ZodOptional<z.ZodString>;
609
615
  /** Task content/prompt */
610
616
  content: z.ZodString;
611
617
  /** Optional file paths for curate --files */
@@ -618,19 +624,23 @@ export declare const TaskCreatedSchema: z.ZodObject<{
618
624
  type: "curate" | "query";
619
625
  content: string;
620
626
  taskId: string;
627
+ clientCwd?: string | undefined;
621
628
  files?: string[] | undefined;
622
629
  }, {
623
630
  type: "curate" | "query";
624
631
  content: string;
625
632
  taskId: string;
633
+ clientCwd?: string | undefined;
626
634
  files?: string[] | undefined;
627
635
  }>;
628
636
  /**
629
637
  * task:started - Agent begins processing the task
630
638
  * Direct send: {taskId} only
631
- * Broadcast: {taskId, content, type, files?}
639
+ * Broadcast: {taskId, content, type, files?, clientCwd?}
632
640
  */
633
641
  export declare const TaskStartedEventSchema: z.ZodObject<{
642
+ /** Client's working directory for file validation */
643
+ clientCwd: z.ZodOptional<z.ZodString>;
634
644
  /** Task content/prompt */
635
645
  content: z.ZodOptional<z.ZodString>;
636
646
  /** Optional file paths for curate --files */
@@ -643,11 +653,13 @@ export declare const TaskStartedEventSchema: z.ZodObject<{
643
653
  taskId: string;
644
654
  type?: string | undefined;
645
655
  content?: string | undefined;
656
+ clientCwd?: string | undefined;
646
657
  files?: string[] | undefined;
647
658
  }, {
648
659
  taskId: string;
649
660
  type?: string | undefined;
650
661
  content?: string | undefined;
662
+ clientCwd?: string | undefined;
651
663
  files?: string[] | undefined;
652
664
  }>;
653
665
  /**
@@ -854,6 +866,8 @@ export declare const TaskTypeSchema: z.ZodEnum<["curate", "query"]>;
854
866
  * Request to create a new task
855
867
  */
856
868
  export declare const TaskCreateRequestSchema: z.ZodObject<{
869
+ /** Client's working directory for file validation */
870
+ clientCwd: z.ZodOptional<z.ZodString>;
857
871
  /** Task content/prompt */
858
872
  content: z.ZodString;
859
873
  /** Optional file paths for curate --files (max 5) */
@@ -866,11 +880,13 @@ export declare const TaskCreateRequestSchema: z.ZodObject<{
866
880
  type: "curate" | "query";
867
881
  content: string;
868
882
  taskId: string;
883
+ clientCwd?: string | undefined;
869
884
  files?: string[] | undefined;
870
885
  }, {
871
886
  type: "curate" | "query";
872
887
  content: string;
873
888
  taskId: string;
889
+ clientCwd?: string | undefined;
874
890
  files?: string[] | undefined;
875
891
  }>;
876
892
  /**
@@ -274,6 +274,8 @@ export const TransportSessionEventNames = {
274
274
  export const TaskExecuteSchema = z.object({
275
275
  /** Client ID that created the task (for response routing) */
276
276
  clientId: z.string(),
277
+ /** Client's working directory for file validation */
278
+ clientCwd: z.string().optional(),
277
279
  /** Task content/prompt */
278
280
  content: z.string(),
279
281
  /** Optional file paths for curate --files */
@@ -326,6 +328,8 @@ export const TaskAckSchema = z.object({
326
328
  * Sent to broadcast-room for TUI monitoring
327
329
  */
328
330
  export const TaskCreatedSchema = z.object({
331
+ /** Client's working directory for file validation */
332
+ clientCwd: z.string().optional(),
329
333
  /** Task content/prompt */
330
334
  content: z.string(),
331
335
  /** Optional file paths for curate --files */
@@ -338,9 +342,11 @@ export const TaskCreatedSchema = z.object({
338
342
  /**
339
343
  * task:started - Agent begins processing the task
340
344
  * Direct send: {taskId} only
341
- * Broadcast: {taskId, content, type, files?}
345
+ * Broadcast: {taskId, content, type, files?, clientCwd?}
342
346
  */
343
347
  export const TaskStartedEventSchema = z.object({
348
+ /** Client's working directory for file validation */
349
+ clientCwd: z.string().optional(),
344
350
  /** Task content/prompt */
345
351
  content: z.string().optional(),
346
352
  /** Optional file paths for curate --files */
@@ -431,6 +437,8 @@ export const TaskTypeSchema = z.enum(['curate', 'query']);
431
437
  * Request to create a new task
432
438
  */
433
439
  export const TaskCreateRequestSchema = z.object({
440
+ /** Client's working directory for file validation */
441
+ clientCwd: z.string().optional(),
434
442
  /** Task content/prompt */
435
443
  content: z.string().min(1),
436
444
  /** Optional file paths for curate --files (max 5) */
@@ -11,6 +11,12 @@ export interface IBlobStorage {
11
11
  * @throws If clearing fails
12
12
  */
13
13
  clear(): Promise<void>;
14
+ /**
15
+ * Close the storage connection and release resources.
16
+ * Should be called when storage is no longer needed.
17
+ * Safe to call multiple times (idempotent).
18
+ */
19
+ close(): void;
14
20
  /**
15
21
  * Delete a blob by its key
16
22
  *
@@ -5,7 +5,6 @@
5
5
  */
6
6
  export type { BlobMetadata, StoredBlob } from '../../domain/cipher/blob/types.js';
7
7
  export * from './cipher-services.js';
8
- export type { IAgentStorage } from './i-agent-storage.js';
9
8
  export type { IBlobStorage } from './i-blob-storage.js';
10
9
  export type { IChatSession } from './i-chat-session.js';
11
10
  export type { ICipherAgent } from './i-cipher-agent.js';
@@ -6,6 +6,8 @@ import type { ICipherAgent } from '../cipher/i-cipher-agent.js';
6
6
  export interface CurateExecuteOptions {
7
7
  /** Context content to curate */
8
8
  content: string;
9
+ /** Client's working directory for file validation (defaults to process.cwd() if not provided) */
10
+ clientCwd?: string;
9
11
  /** Optional file paths for --files flag */
10
12
  files?: string[];
11
13
  /** Task ID for event routing (required for concurrent task isolation) */
@@ -122,6 +122,10 @@ export class CipherAgent extends BaseAgent {
122
122
  if (this.stateManager) {
123
123
  this.stateManager.reset();
124
124
  }
125
+ // Close SQLite databases to release file handles and ensure clean shutdown
126
+ if (this.services?.blobStorage) {
127
+ this.services.blobStorage.close();
128
+ }
125
129
  }
126
130
  /**
127
131
  * Create a new session.
@@ -6,6 +6,10 @@ import type { IFileSystem } from '../../../core/interfaces/cipher/i-file-system.
6
6
  * path validation, size limits, and allow/block list enforcement.
7
7
  */
8
8
  export declare class FileSystemService implements IFileSystem {
9
+ /**
10
+ * Maximum line length before truncation (2000 characters).
11
+ */
12
+ private static readonly MAX_LINE_LENGTH;
9
13
  private readonly config;
10
14
  private initialized;
11
15
  private readonly pathValidator;
@@ -118,6 +118,10 @@ const LIST_DIRECTORY_LIMIT = 100;
118
118
  * path validation, size limits, and allow/block list enforcement.
119
119
  */
120
120
  export class FileSystemService {
121
+ /**
122
+ * Maximum line length before truncation (2000 characters).
123
+ */
124
+ static MAX_LINE_LENGTH = 2000;
121
125
  config;
122
126
  initialized = false;
123
127
  pathValidator;
@@ -505,6 +509,7 @@ export class FileSystemService {
505
509
  size: stats.size,
506
510
  totalLines,
507
511
  truncated,
512
+ truncatedLineCount: truncatedLines.length,
508
513
  };
509
514
  }
510
515
  catch (error) {