byterover-cli 1.0.4 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -11
- package/dist/commands/curate.js +1 -1
- package/dist/commands/hook-prompt-submit.d.ts +27 -0
- package/dist/commands/hook-prompt-submit.js +39 -0
- package/dist/commands/main.d.ts +13 -0
- package/dist/commands/main.js +53 -2
- package/dist/commands/query.js +1 -1
- package/dist/commands/status.js +8 -3
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +2 -2
- package/dist/core/domain/cipher/llm/registry.js +53 -2
- package/dist/core/domain/cipher/llm/types.d.ts +2 -0
- package/dist/core/domain/cipher/process/types.d.ts +7 -0
- package/dist/core/domain/cipher/session/session-metadata.d.ts +178 -0
- package/dist/core/domain/cipher/session/session-metadata.js +147 -0
- package/dist/core/domain/cipher/tools/constants.d.ts +1 -0
- package/dist/core/domain/cipher/tools/constants.js +1 -0
- package/dist/core/domain/entities/agent.d.ts +16 -0
- package/dist/core/domain/entities/agent.js +24 -0
- package/dist/core/domain/entities/connector-type.d.ts +9 -0
- package/dist/core/domain/entities/connector-type.js +8 -0
- package/dist/core/domain/entities/event.d.ts +1 -1
- package/dist/core/domain/entities/event.js +2 -0
- package/dist/core/domain/errors/task-error.d.ts +4 -0
- package/dist/core/domain/errors/task-error.js +7 -0
- package/dist/core/domain/knowledge/markdown-writer.d.ts +15 -18
- package/dist/core/domain/knowledge/markdown-writer.js +232 -34
- package/dist/core/domain/knowledge/relation-parser.d.ts +25 -39
- package/dist/core/domain/knowledge/relation-parser.js +39 -61
- package/dist/core/domain/transport/schemas.d.ts +77 -2
- package/dist/core/domain/transport/schemas.js +51 -2
- package/dist/core/interfaces/cipher/i-session-persistence.d.ts +133 -0
- package/dist/core/interfaces/cipher/i-session-persistence.js +7 -0
- package/dist/core/interfaces/cipher/message-types.d.ts +6 -0
- package/dist/core/interfaces/connectors/connector-types.d.ts +57 -0
- package/dist/core/interfaces/connectors/i-connector-manager.d.ts +72 -0
- package/dist/core/interfaces/connectors/i-connector.d.ts +54 -0
- package/dist/core/interfaces/connectors/i-connector.js +1 -0
- package/dist/core/interfaces/executor/i-curate-executor.d.ts +2 -2
- package/dist/core/interfaces/i-context-file-reader.d.ts +3 -0
- package/dist/core/interfaces/i-file-service.d.ts +7 -0
- package/dist/core/interfaces/usecase/i-connectors-use-case.d.ts +3 -0
- package/dist/core/interfaces/usecase/i-connectors-use-case.js +1 -0
- package/dist/core/interfaces/usecase/{i-clear-use-case.d.ts → i-reset-use-case.d.ts} +1 -1
- package/dist/core/interfaces/usecase/i-reset-use-case.js +1 -0
- package/dist/hooks/init/update-notifier.d.ts +1 -0
- package/dist/hooks/init/update-notifier.js +10 -1
- package/dist/infra/cipher/agent/agent-schemas.d.ts +6 -6
- package/dist/infra/cipher/agent/service-initializer.js +4 -4
- package/dist/infra/cipher/file-system/binary-utils.d.ts +7 -12
- package/dist/infra/cipher/file-system/binary-utils.js +46 -31
- package/dist/infra/cipher/file-system/context-tree-file-system-factory.js +3 -2
- package/dist/infra/cipher/file-system/file-system-service.js +1 -0
- package/dist/infra/cipher/http/internal-llm-http-service.js +3 -5
- package/dist/infra/cipher/interactive-loop.js +3 -1
- package/dist/infra/cipher/llm/context/context-manager.d.ts +2 -2
- package/dist/infra/cipher/llm/context/context-manager.js +63 -18
- package/dist/infra/cipher/llm/formatters/gemini-formatter.d.ts +13 -0
- package/dist/infra/cipher/llm/formatters/gemini-formatter.js +146 -15
- package/dist/infra/cipher/llm/generators/byterover-content-generator.js +6 -2
- package/dist/infra/cipher/llm/internal-llm-service.js +2 -2
- package/dist/infra/cipher/llm/thought-parser.d.ts +21 -0
- package/dist/infra/cipher/llm/thought-parser.js +27 -0
- package/dist/infra/cipher/llm/tool-output-processor.d.ts +10 -0
- package/dist/infra/cipher/llm/tool-output-processor.js +80 -7
- package/dist/infra/cipher/process/process-service.js +11 -3
- package/dist/infra/cipher/session/chat-session.d.ts +7 -2
- package/dist/infra/cipher/session/chat-session.js +90 -52
- package/dist/infra/cipher/session/session-metadata-store.d.ts +52 -0
- package/dist/infra/cipher/session/session-metadata-store.js +406 -0
- package/dist/infra/cipher/system-prompt/contributors/context-tree-structure-contributor.d.ts +6 -7
- package/dist/infra/cipher/system-prompt/contributors/context-tree-structure-contributor.js +57 -18
- package/dist/infra/cipher/tools/implementations/curate-tool.js +132 -36
- package/dist/infra/cipher/tools/implementations/read-file-tool.js +38 -17
- package/dist/infra/cipher/tools/implementations/search-knowledge-tool.d.ts +7 -0
- package/dist/infra/cipher/tools/implementations/search-knowledge-tool.js +303 -0
- package/dist/infra/cipher/tools/implementations/task-tool.js +1 -0
- package/dist/infra/cipher/tools/index.d.ts +1 -0
- package/dist/infra/cipher/tools/index.js +1 -0
- package/dist/infra/cipher/tools/tool-manager.js +1 -0
- package/dist/infra/cipher/tools/tool-registry.js +7 -0
- package/dist/infra/connectors/connector-manager.d.ts +32 -0
- package/dist/infra/connectors/connector-manager.js +156 -0
- package/dist/infra/connectors/hook/hook-connector-config.d.ts +52 -0
- package/dist/infra/connectors/hook/hook-connector-config.js +41 -0
- package/dist/infra/connectors/hook/hook-connector.d.ts +46 -0
- package/dist/infra/connectors/hook/hook-connector.js +231 -0
- package/dist/infra/{rule → connectors/rules}/legacy-rule-detector.d.ts +2 -2
- package/dist/infra/{rule → connectors/rules}/legacy-rule-detector.js +1 -1
- package/dist/infra/connectors/rules/rules-connector-config.d.ts +95 -0
- package/dist/infra/{rule/agent-rule-config.js → connectors/rules/rules-connector-config.js} +10 -10
- package/dist/infra/connectors/rules/rules-connector.d.ts +41 -0
- package/dist/infra/connectors/rules/rules-connector.js +204 -0
- package/dist/infra/{rule/rule-template-service.d.ts → connectors/shared/template-service.d.ts} +3 -3
- package/dist/infra/{rule/rule-template-service.js → connectors/shared/template-service.js} +1 -1
- package/dist/infra/context-tree/file-context-file-reader.js +4 -0
- package/dist/infra/context-tree/file-context-tree-writer-service.d.ts +5 -2
- package/dist/infra/context-tree/file-context-tree-writer-service.js +20 -5
- package/dist/infra/core/executors/curate-executor.d.ts +2 -2
- package/dist/infra/core/executors/curate-executor.js +7 -7
- package/dist/infra/core/executors/query-executor.d.ts +12 -0
- package/dist/infra/core/executors/query-executor.js +62 -1
- package/dist/infra/core/task-processor.d.ts +2 -2
- package/dist/infra/file/fs-file-service.d.ts +7 -0
- package/dist/infra/file/fs-file-service.js +15 -1
- package/dist/infra/process/agent-worker.d.ts +2 -2
- package/dist/infra/process/agent-worker.js +626 -142
- package/dist/infra/process/constants.d.ts +1 -1
- package/dist/infra/process/constants.js +1 -1
- package/dist/infra/process/ipc-types.d.ts +17 -4
- package/dist/infra/process/ipc-types.js +3 -3
- package/dist/infra/process/parent-heartbeat.d.ts +47 -0
- package/dist/infra/process/parent-heartbeat.js +118 -0
- package/dist/infra/process/process-manager.d.ts +89 -1
- package/dist/infra/process/process-manager.js +293 -9
- package/dist/infra/process/task-queue-manager.d.ts +13 -0
- package/dist/infra/process/task-queue-manager.js +19 -0
- package/dist/infra/process/transport-handlers.d.ts +3 -0
- package/dist/infra/process/transport-handlers.js +82 -5
- package/dist/infra/process/transport-worker.js +9 -69
- package/dist/infra/repl/commands/connectors-command.d.ts +8 -0
- package/dist/infra/repl/commands/{gen-rules-command.js → connectors-command.js} +21 -10
- package/dist/infra/repl/commands/index.js +8 -4
- package/dist/infra/repl/commands/init-command.js +11 -7
- package/dist/infra/repl/commands/new-command.d.ts +14 -0
- package/dist/infra/repl/commands/new-command.js +61 -0
- package/dist/infra/repl/commands/query-command.js +22 -2
- package/dist/infra/repl/commands/{clear-command.d.ts → reset-command.d.ts} +2 -2
- package/dist/infra/repl/commands/{clear-command.js → reset-command.js} +11 -11
- package/dist/infra/transport/socket-io-transport-client.d.ts +68 -0
- package/dist/infra/transport/socket-io-transport-client.js +283 -7
- package/dist/infra/usecase/connectors-use-case.d.ts +59 -0
- package/dist/infra/usecase/connectors-use-case.js +203 -0
- package/dist/infra/usecase/init-use-case.d.ts +8 -43
- package/dist/infra/usecase/init-use-case.js +29 -253
- package/dist/infra/usecase/logout-use-case.js +2 -2
- package/dist/infra/usecase/pull-use-case.js +5 -5
- package/dist/infra/usecase/push-use-case.js +5 -5
- package/dist/infra/usecase/{clear-use-case.d.ts → reset-use-case.d.ts} +5 -5
- package/dist/infra/usecase/{clear-use-case.js → reset-use-case.js} +7 -8
- package/dist/infra/usecase/space-list-use-case.js +3 -3
- package/dist/infra/usecase/space-switch-use-case.js +3 -3
- package/dist/resources/prompts/curate.yml +75 -13
- package/dist/resources/prompts/explore.yml +34 -0
- package/dist/resources/prompts/query-orchestrator.yml +112 -0
- package/dist/resources/prompts/system-prompt.yml +12 -2
- package/dist/resources/tools/curate.txt +60 -15
- package/dist/resources/tools/search_knowledge.txt +32 -0
- package/dist/templates/sections/brv-instructions.md +98 -0
- package/dist/tui/components/inline-prompts/inline-confirm.js +2 -2
- package/dist/tui/components/onboarding/onboarding-flow.js +14 -10
- package/dist/tui/components/onboarding/welcome-box.js +1 -1
- package/dist/tui/contexts/onboarding-context.d.ts +4 -0
- package/dist/tui/contexts/onboarding-context.js +14 -2
- package/dist/tui/views/command-view.js +19 -0
- package/dist/utils/file-validator.d.ts +1 -1
- package/dist/utils/file-validator.js +34 -35
- package/dist/utils/type-guards.d.ts +5 -0
- package/dist/utils/type-guards.js +7 -0
- package/oclif.manifest.json +32 -6
- package/package.json +4 -1
- package/dist/config/context-tree-domains.d.ts +0 -29
- package/dist/config/context-tree-domains.js +0 -29
- package/dist/core/interfaces/usecase/i-generate-rules-use-case.d.ts +0 -3
- package/dist/infra/repl/commands/gen-rules-command.d.ts +0 -7
- package/dist/infra/rule/agent-rule-config.d.ts +0 -19
- package/dist/infra/usecase/generate-rules-use-case.d.ts +0 -61
- package/dist/infra/usecase/generate-rules-use-case.js +0 -285
- /package/dist/core/interfaces/{usecase/i-clear-use-case.js → connectors/connector-types.js} +0 -0
- /package/dist/core/interfaces/{usecase/i-generate-rules-use-case.js → connectors/i-connector-manager.js} +0 -0
- /package/dist/infra/{rule → connectors/shared}/constants.d.ts +0 -0
- /package/dist/infra/{rule → connectors/shared}/constants.js +0 -0
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 React/Ink terminal UI for managing your project's context tree and knowledge storage. Seamlessly integrate with AI coding agents
|
|
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 18+ AI coding agents including Claude Code, Cursor, Windsurf, GitHub Copilot, Cline, and more.
|
|
4
4
|
|
|
5
5
|
[](https://npmjs.org/package/byterover-cli)
|
|
6
6
|
[](https://npmjs.org/package/byterover-cli)
|
|
@@ -46,7 +46,7 @@ brv --version
|
|
|
46
46
|
|
|
47
47
|
## Quick Start
|
|
48
48
|
|
|
49
|
-
Visit [**ByteRover
|
|
49
|
+
Visit [**ByteRover Docs**](https://docs.byterover.dev) for more information.
|
|
50
50
|
|
|
51
51
|
Get started with ByteRover CLI in three simple steps:
|
|
52
52
|
|
|
@@ -122,7 +122,7 @@ The **Context Tree** is ByteRover's structured knowledge system that helps you a
|
|
|
122
122
|
- **Organized Knowledge**: Structure your project knowledge by domain and topic
|
|
123
123
|
- **Easy Retrieval**: Find relevant context quickly when you need it
|
|
124
124
|
- **Persistent Memory**: Maintain project-specific knowledge across sessions
|
|
125
|
-
- **Agent-Friendly**: Works seamlessly with AI coding agents
|
|
125
|
+
- **Agent-Friendly**: Works seamlessly with 18+ AI coding agents (Claude Code, Cursor, Windsurf, GitHub Copilot, Cline, and more) via rules-based or hook-based integration
|
|
126
126
|
- **Cloud Sync**: Push and sync your context tree to ByteRover's cloud storage for backup and team collaboration
|
|
127
127
|
- **Dynamic Domains**: Automatically creates new domains as your knowledge grows
|
|
128
128
|
|
|
@@ -135,13 +135,15 @@ The context tree organizes knowledge into:
|
|
|
135
135
|
|
|
136
136
|
### Integrating with Coding Agents
|
|
137
137
|
|
|
138
|
-
Use `/
|
|
138
|
+
Use `/connectors` to manage integrations with your AI coding agents:
|
|
139
139
|
|
|
140
140
|
```
|
|
141
|
-
/
|
|
141
|
+
/connectors
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
ByteRover supports two connector types:
|
|
145
|
+
- **Hook integration** (Claude Code): Direct injection via IDE settings for seamless integration
|
|
146
|
+
- **Rules-based** (all agents): Generates agent-specific rule files (e.g., `CLAUDE.md`, `.cursorrules`) that instruct the agent how to read from and contribute to your context tree
|
|
145
147
|
|
|
146
148
|
## Slash Commands Reference
|
|
147
149
|
|
|
@@ -198,16 +200,27 @@ This creates agent-specific rule files (e.g., `CLAUDE.md`, `.cursorrules`) that
|
|
|
198
200
|
- `-l, --limit <n>`: Maximum spaces to fetch (default: 50)
|
|
199
201
|
- `-o, --offset <n>`: Number of spaces to skip
|
|
200
202
|
|
|
201
|
-
### Context Tree Management
|
|
203
|
+
### Connectors & Context Tree Management
|
|
202
204
|
|
|
203
205
|
| Command | Description |
|
|
204
206
|
|---------|-------------|
|
|
205
|
-
| `/
|
|
206
|
-
| `/
|
|
207
|
+
| `/connectors` | Manage agent connectors (rules-based or hook integration) |
|
|
208
|
+
| `/reset [-y] [directory]` | Reset context tree to empty state |
|
|
207
209
|
|
|
208
|
-
**
|
|
210
|
+
**Reset options:**
|
|
209
211
|
- `-y, --yes`: Skip confirmation prompt
|
|
210
212
|
|
|
213
|
+
### Session Management
|
|
214
|
+
|
|
215
|
+
| Command | Description |
|
|
216
|
+
|---------|-------------|
|
|
217
|
+
| `/new [-y]` | Start a fresh session (ends current session, clears conversation) |
|
|
218
|
+
|
|
219
|
+
**Options:**
|
|
220
|
+
- `-y, --yes`: Skip confirmation prompt
|
|
221
|
+
|
|
222
|
+
**Note:** This command does NOT affect the context tree—it only clears the conversation history and starts a new session.
|
|
223
|
+
|
|
211
224
|
### Project Setup
|
|
212
225
|
|
|
213
226
|
| Command | Description |
|
|
@@ -328,7 +341,7 @@ If you encounter issues or have questions:
|
|
|
328
341
|
|
|
329
342
|
1. Check the command help in the REPL
|
|
330
343
|
2. Run `/status` to review your project state
|
|
331
|
-
3. Visit [ByteRover Docs](https://docs.byterover.dev)
|
|
344
|
+
3. Visit the [ByteRover Docs](https://docs.byterover.dev)
|
|
332
345
|
4. Contact ByteRover support
|
|
333
346
|
|
|
334
347
|
---
|
package/dist/commands/curate.js
CHANGED
|
@@ -14,7 +14,7 @@ export default class Curate extends Command {
|
|
|
14
14
|
};
|
|
15
15
|
static description = `Curate context to the context tree (connects to running brv instance)
|
|
16
16
|
|
|
17
|
-
Requires a running brv instance. Start one with: brv
|
|
17
|
+
Requires a running brv instance. Start one with: brv
|
|
18
18
|
|
|
19
19
|
Good examples:
|
|
20
20
|
- "Auth uses JWT with 24h expiry. Tokens stored in httpOnly cookies via authMiddleware.ts"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { ITemplateLoader } from '../core/interfaces/i-template-loader.js';
|
|
3
|
+
/**
|
|
4
|
+
* Dependencies required by HookPromptSubmit command.
|
|
5
|
+
* Exported for test mocking.
|
|
6
|
+
*/
|
|
7
|
+
export type HookPromptSubmitDependencies = {
|
|
8
|
+
templateLoader: ITemplateLoader;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Hidden command for coding agent pre-prompt hooks.
|
|
12
|
+
* Outputs ByteRover workflow instructions to stdout.
|
|
13
|
+
* The agent wraps the output in system context (e.g., <system-reminder> tags).
|
|
14
|
+
*
|
|
15
|
+
* Supported agents:
|
|
16
|
+
* - Claude Code: .claude/settings.local.json (UserPromptSubmit)
|
|
17
|
+
*/
|
|
18
|
+
export default class HookPromptSubmit extends Command {
|
|
19
|
+
static description: string;
|
|
20
|
+
static hidden: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Factory method for creating dependencies.
|
|
23
|
+
* Override in tests to inject mock dependencies.
|
|
24
|
+
*/
|
|
25
|
+
protected createDependencies(): HookPromptSubmitDependencies;
|
|
26
|
+
run(): Promise<void>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { isDevelopment } from '../config/environment.js';
|
|
3
|
+
import { FsFileService } from '../infra/file/fs-file-service.js';
|
|
4
|
+
import { FsTemplateLoader } from '../infra/template/fs-template-loader.js';
|
|
5
|
+
/**
|
|
6
|
+
* Hidden command for coding agent pre-prompt hooks.
|
|
7
|
+
* Outputs ByteRover workflow instructions to stdout.
|
|
8
|
+
* The agent wraps the output in system context (e.g., <system-reminder> tags).
|
|
9
|
+
*
|
|
10
|
+
* Supported agents:
|
|
11
|
+
* - Claude Code: .claude/settings.local.json (UserPromptSubmit)
|
|
12
|
+
*/
|
|
13
|
+
export default class HookPromptSubmit extends Command {
|
|
14
|
+
static description = 'Internal: Pre-prompt hook for coding agents';
|
|
15
|
+
static hidden = true;
|
|
16
|
+
/**
|
|
17
|
+
* Factory method for creating dependencies.
|
|
18
|
+
* Override in tests to inject mock dependencies.
|
|
19
|
+
*/
|
|
20
|
+
createDependencies() {
|
|
21
|
+
const fileService = new FsFileService();
|
|
22
|
+
const templateLoader = new FsTemplateLoader(fileService);
|
|
23
|
+
return { templateLoader };
|
|
24
|
+
}
|
|
25
|
+
async run() {
|
|
26
|
+
try {
|
|
27
|
+
const { templateLoader } = this.createDependencies();
|
|
28
|
+
const instructions = await templateLoader.loadSection('brv-instructions');
|
|
29
|
+
// Output to stdout (agent wraps in system context)
|
|
30
|
+
this.log(instructions);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
// Silently fail in production - don't interrupt agent workflow
|
|
34
|
+
if (isDevelopment()) {
|
|
35
|
+
console.error('[hook-prompt-submit] Template load failed:', error);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
package/dist/commands/main.d.ts
CHANGED
|
@@ -14,4 +14,17 @@ export default class Main extends Command {
|
|
|
14
14
|
*/
|
|
15
15
|
static hidden: boolean;
|
|
16
16
|
run(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Resolve session ID for the agent.
|
|
19
|
+
*
|
|
20
|
+
* Strategy:
|
|
21
|
+
* 1. Check for active session in .brv/sessions/active.json
|
|
22
|
+
* 2. If active session exists and is valid (not stale), resume it
|
|
23
|
+
* 3. If stale (process crashed), mark as interrupted and create new
|
|
24
|
+
* 4. If no active session, create new session
|
|
25
|
+
* 5. Run session cleanup on startup
|
|
26
|
+
*
|
|
27
|
+
* @returns Session ID to use
|
|
28
|
+
*/
|
|
29
|
+
private resolveSessionId;
|
|
17
30
|
}
|
package/dist/commands/main.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { DEFAULT_SESSION_RETENTION } from '../core/domain/cipher/session/session-metadata.js';
|
|
4
|
+
import { SessionMetadataStore } from '../infra/cipher/session/session-metadata-store.js';
|
|
2
5
|
import { ProjectConfigStore } from '../infra/config/file-config-store.js';
|
|
3
6
|
import { getProcessManager } from '../infra/process/index.js';
|
|
4
7
|
import { startRepl } from '../infra/repl/repl-startup.js';
|
|
@@ -6,7 +9,7 @@ import { FileGlobalConfigStore } from '../infra/storage/file-global-config-store
|
|
|
6
9
|
import { FileOnboardingPreferenceStore } from '../infra/storage/file-onboarding-preference-store.js';
|
|
7
10
|
import { createTokenStore } from '../infra/storage/token-store.js';
|
|
8
11
|
import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
|
|
9
|
-
import { initSessionLog } from '../utils/process-logger.js';
|
|
12
|
+
import { initSessionLog, processManagerLog } from '../utils/process-logger.js';
|
|
10
13
|
/**
|
|
11
14
|
* Main command - Entry point for ByteRover CLI.
|
|
12
15
|
*
|
|
@@ -30,9 +33,13 @@ export default class Main extends Command {
|
|
|
30
33
|
this.log("Run 'brv --help' for available commands.");
|
|
31
34
|
return;
|
|
32
35
|
}
|
|
36
|
+
// Resolve session ID (auto-resume or create new)
|
|
37
|
+
const sessionId = await this.resolveSessionId();
|
|
38
|
+
processManagerLog(`Session ID resolved: ${sessionId}`);
|
|
33
39
|
// Start Transport and Agent processes (v0.5.0 architecture)
|
|
40
|
+
// Pass session ID to Agent via environment variable
|
|
34
41
|
const processManager = getProcessManager();
|
|
35
|
-
await processManager.start();
|
|
42
|
+
await processManager.start({ sessionId });
|
|
36
43
|
const tokenStore = createTokenStore();
|
|
37
44
|
const globalConfigStore = new FileGlobalConfigStore();
|
|
38
45
|
const trackingService = new MixpanelTrackingService({ globalConfigStore, tokenStore });
|
|
@@ -52,4 +59,48 @@ export default class Main extends Command {
|
|
|
52
59
|
await processManager.stop();
|
|
53
60
|
}
|
|
54
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Resolve session ID for the agent.
|
|
64
|
+
*
|
|
65
|
+
* Strategy:
|
|
66
|
+
* 1. Check for active session in .brv/sessions/active.json
|
|
67
|
+
* 2. If active session exists and is valid (not stale), resume it
|
|
68
|
+
* 3. If stale (process crashed), mark as interrupted and create new
|
|
69
|
+
* 4. If no active session, create new session
|
|
70
|
+
* 5. Run session cleanup on startup
|
|
71
|
+
*
|
|
72
|
+
* @returns Session ID to use
|
|
73
|
+
*/
|
|
74
|
+
async resolveSessionId() {
|
|
75
|
+
const sessionStore = new SessionMetadataStore();
|
|
76
|
+
// Run cleanup on startup (async, don't wait)
|
|
77
|
+
sessionStore.cleanupSessions(DEFAULT_SESSION_RETENTION).catch((error) => {
|
|
78
|
+
processManagerLog(`Session cleanup failed: ${error}`);
|
|
79
|
+
});
|
|
80
|
+
// Check for active session
|
|
81
|
+
const activeSession = await sessionStore.getActiveSession();
|
|
82
|
+
if (activeSession) {
|
|
83
|
+
// Check if the active session is stale (process not running)
|
|
84
|
+
const isStale = await sessionStore.isActiveSessionStale();
|
|
85
|
+
if (isStale) {
|
|
86
|
+
// Mark the old session as interrupted
|
|
87
|
+
processManagerLog(`Active session ${activeSession.sessionId} is stale, marking as interrupted`);
|
|
88
|
+
await sessionStore.markSessionInterrupted(activeSession.sessionId);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Valid active session - resume it
|
|
92
|
+
processManagerLog(`Resuming active session: ${activeSession.sessionId}`);
|
|
93
|
+
return activeSession.sessionId;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Create new session
|
|
97
|
+
const newSessionId = `agent-session-${randomUUID()}`;
|
|
98
|
+
processManagerLog(`Creating new session: ${newSessionId}`);
|
|
99
|
+
// Save session metadata
|
|
100
|
+
const metadata = sessionStore.createSessionMetadata(newSessionId);
|
|
101
|
+
await sessionStore.saveSession(metadata);
|
|
102
|
+
// Set as active session
|
|
103
|
+
await sessionStore.setActiveSession(newSessionId);
|
|
104
|
+
return newSessionId;
|
|
105
|
+
}
|
|
55
106
|
}
|
package/dist/commands/query.js
CHANGED
|
@@ -14,7 +14,7 @@ export default class Query extends Command {
|
|
|
14
14
|
};
|
|
15
15
|
static description = `Query and retrieve information from the context tree (connects to running brv instance)
|
|
16
16
|
|
|
17
|
-
Requires a running brv instance. Start one with: brv
|
|
17
|
+
Requires a running brv instance. Start one with: brv
|
|
18
18
|
|
|
19
19
|
Good:
|
|
20
20
|
- "How is user authentication implemented?"
|
package/dist/commands/status.js
CHANGED
|
@@ -14,9 +14,14 @@ export default class Status extends Command {
|
|
|
14
14
|
static description = 'Show CLI status and project information. Display local context tree managed by ByteRover CLI';
|
|
15
15
|
static examples = [
|
|
16
16
|
'<%= config.bin %> <%= command.id %>',
|
|
17
|
-
'# Check status after login
|
|
18
|
-
'
|
|
19
|
-
'
|
|
17
|
+
'# Check status after login (in REPL):',
|
|
18
|
+
'/login',
|
|
19
|
+
'/status',
|
|
20
|
+
'',
|
|
21
|
+
'# Verify project initialization (in REPL):',
|
|
22
|
+
'/init',
|
|
23
|
+
'/status',
|
|
24
|
+
'',
|
|
20
25
|
'<%= config.bin %> <%= command.id %> /path/to/project',
|
|
21
26
|
'<%= config.bin %> <%= command.id %> --format json',
|
|
22
27
|
];
|
package/dist/constants.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export declare const DEFAULT_BRANCH = "main";
|
|
|
23
23
|
* ByteRover documentation URL.
|
|
24
24
|
* Used in CLI help output to direct users to online documentation.
|
|
25
25
|
*/
|
|
26
|
-
export declare const DOCS_URL = "https://docs.byterover.dev
|
|
26
|
+
export declare const DOCS_URL = "https://docs.byterover.dev";
|
|
27
27
|
export declare const TRANSPORT_HOST = "127.0.0.1";
|
|
28
28
|
export declare const TRANSPORT_REQUEST_TIMEOUT_MS = 10000;
|
|
29
29
|
export declare const TRANSPORT_ROOM_TIMEOUT_MS = 2000;
|
|
@@ -34,4 +34,4 @@ export declare const TRANSPORT_RECONNECTION_ATTEMPTS = 30;
|
|
|
34
34
|
export declare const TRANSPORT_PING_INTERVAL_MS = 5000;
|
|
35
35
|
export declare const TRANSPORT_PING_TIMEOUT_MS = 10000;
|
|
36
36
|
export declare const TRANSPORT_DEFAULT_TRANSPORTS: ('polling' | 'websocket')[];
|
|
37
|
-
export declare const DEFAULT_LLM_MODEL = "gemini-
|
|
37
|
+
export declare const DEFAULT_LLM_MODEL = "gemini-3-flash-preview";
|
package/dist/constants.js
CHANGED
|
@@ -28,7 +28,7 @@ export const DEFAULT_BRANCH = 'main';
|
|
|
28
28
|
* ByteRover documentation URL.
|
|
29
29
|
* Used in CLI help output to direct users to online documentation.
|
|
30
30
|
*/
|
|
31
|
-
export const DOCS_URL = 'https://docs.byterover.dev
|
|
31
|
+
export const DOCS_URL = 'https://docs.byterover.dev';
|
|
32
32
|
// Transport layer constants (optimized for localhost real-time)
|
|
33
33
|
export const TRANSPORT_HOST = '127.0.0.1'; // Use hostname for better sandbox compatibility
|
|
34
34
|
export const TRANSPORT_REQUEST_TIMEOUT_MS = 10_000; // 10s - most operations complete quickly
|
|
@@ -43,4 +43,4 @@ export const TRANSPORT_PING_TIMEOUT_MS = 10_000; // 10s timeout - avoid false di
|
|
|
43
43
|
// HTTP polling may be blocked by IDE sandboxes causing "xhr poll error"
|
|
44
44
|
export const TRANSPORT_DEFAULT_TRANSPORTS = ['websocket'];
|
|
45
45
|
// LLM Model defaults
|
|
46
|
-
export const DEFAULT_LLM_MODEL = 'gemini-
|
|
46
|
+
export const DEFAULT_LLM_MODEL = 'gemini-3-flash-preview';
|
|
@@ -27,19 +27,54 @@ export const LLM_REGISTRY = {
|
|
|
27
27
|
supportedFileTypes: [],
|
|
28
28
|
},
|
|
29
29
|
gemini: {
|
|
30
|
-
defaultModel: 'gemini-
|
|
30
|
+
defaultModel: 'gemini-3-flash-preview',
|
|
31
31
|
models: [
|
|
32
|
-
// Gemini
|
|
32
|
+
// Gemini 3 series (Preview)
|
|
33
33
|
{
|
|
34
34
|
capabilities: {
|
|
35
35
|
supportsAudio: true,
|
|
36
36
|
supportsImages: true,
|
|
37
|
+
supportsMultimodalFunctionResponse: true,
|
|
37
38
|
supportsPdf: true,
|
|
38
39
|
supportsStreaming: true,
|
|
39
40
|
supportsThinking: true,
|
|
40
41
|
},
|
|
41
42
|
charsPerToken: 4,
|
|
42
43
|
default: true,
|
|
44
|
+
displayName: 'Gemini 3 Flash (Preview)',
|
|
45
|
+
maxInputTokens: 1_000_000,
|
|
46
|
+
maxOutputTokens: 8192,
|
|
47
|
+
name: 'gemini-3-flash-preview',
|
|
48
|
+
pricing: { inputPerM: 0.075, outputPerM: 0.3 },
|
|
49
|
+
supportedFileTypes: ['image', 'pdf', 'audio'],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
capabilities: {
|
|
53
|
+
supportsAudio: true,
|
|
54
|
+
supportsImages: true,
|
|
55
|
+
supportsMultimodalFunctionResponse: true,
|
|
56
|
+
supportsPdf: true,
|
|
57
|
+
supportsStreaming: true,
|
|
58
|
+
supportsThinking: true,
|
|
59
|
+
},
|
|
60
|
+
charsPerToken: 4,
|
|
61
|
+
displayName: 'Gemini 3 Pro (Preview)',
|
|
62
|
+
maxInputTokens: 1_000_000,
|
|
63
|
+
maxOutputTokens: 8192,
|
|
64
|
+
name: 'gemini-3-pro-preview',
|
|
65
|
+
pricing: { inputPerM: 1.25, outputPerM: 5 },
|
|
66
|
+
supportedFileTypes: ['image', 'pdf', 'audio'],
|
|
67
|
+
},
|
|
68
|
+
// Gemini 2.5 series
|
|
69
|
+
{
|
|
70
|
+
capabilities: {
|
|
71
|
+
supportsAudio: true,
|
|
72
|
+
supportsImages: true,
|
|
73
|
+
supportsPdf: true,
|
|
74
|
+
supportsStreaming: true,
|
|
75
|
+
supportsThinking: true,
|
|
76
|
+
},
|
|
77
|
+
charsPerToken: 4,
|
|
43
78
|
displayName: 'Gemini 2.5 Flash',
|
|
44
79
|
maxInputTokens: 1_000_000,
|
|
45
80
|
maxOutputTokens: 8192,
|
|
@@ -47,6 +82,22 @@ export const LLM_REGISTRY = {
|
|
|
47
82
|
pricing: { inputPerM: 0.075, outputPerM: 0.3 },
|
|
48
83
|
supportedFileTypes: ['image', 'pdf', 'audio'],
|
|
49
84
|
},
|
|
85
|
+
{
|
|
86
|
+
capabilities: {
|
|
87
|
+
supportsAudio: true,
|
|
88
|
+
supportsImages: true,
|
|
89
|
+
supportsPdf: true,
|
|
90
|
+
supportsStreaming: true,
|
|
91
|
+
supportsThinking: true,
|
|
92
|
+
},
|
|
93
|
+
charsPerToken: 4,
|
|
94
|
+
displayName: 'Gemini 2.5 Pro',
|
|
95
|
+
maxInputTokens: 1_000_000,
|
|
96
|
+
maxOutputTokens: 8192,
|
|
97
|
+
name: 'gemini-2.5-pro',
|
|
98
|
+
pricing: { inputPerM: 1.25, outputPerM: 5 },
|
|
99
|
+
supportedFileTypes: ['image', 'pdf', 'audio'],
|
|
100
|
+
},
|
|
50
101
|
// Gemini 1.5 series
|
|
51
102
|
{
|
|
52
103
|
capabilities: {
|
|
@@ -28,6 +28,8 @@ export interface ModelCapabilities {
|
|
|
28
28
|
supportsAudio: boolean;
|
|
29
29
|
/** Whether the model supports image input */
|
|
30
30
|
supportsImages: boolean;
|
|
31
|
+
/** Whether the model supports multimodal data in function responses (Gemini 3+) */
|
|
32
|
+
supportsMultimodalFunctionResponse?: boolean;
|
|
31
33
|
/** Whether the model supports PDF input */
|
|
32
34
|
supportsPdf: boolean;
|
|
33
35
|
/** Whether the model supports streaming responses */
|
|
@@ -17,6 +17,13 @@ export interface ProcessConfig {
|
|
|
17
17
|
* Custom environment variables for all commands.
|
|
18
18
|
*/
|
|
19
19
|
environment: Record<string, string>;
|
|
20
|
+
/**
|
|
21
|
+
* Grace period in milliseconds to wait after SIGTERM before sending SIGKILL.
|
|
22
|
+
* Allows processes time to clean up gracefully.
|
|
23
|
+
*
|
|
24
|
+
* @default 5000 (5 seconds)
|
|
25
|
+
*/
|
|
26
|
+
killGracePeriod: number;
|
|
20
27
|
/**
|
|
21
28
|
* Maximum number of concurrent background processes.
|
|
22
29
|
* @default 5
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Metadata Types and Schemas
|
|
3
|
+
*
|
|
4
|
+
* Defines the data structures for persistent session management.
|
|
5
|
+
* Sessions are stored in .brv/sessions/ directory as JSON files.
|
|
6
|
+
*
|
|
7
|
+
* Design adapted from gemini-cli's ChatRecordingService pattern.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
/**
|
|
11
|
+
* Session status indicating lifecycle state.
|
|
12
|
+
*/
|
|
13
|
+
export type SessionStatus = 'active' | 'ended' | 'interrupted';
|
|
14
|
+
/**
|
|
15
|
+
* Active session pointer stored in .brv/sessions/active.json
|
|
16
|
+
* Points to the currently active session for auto-resume.
|
|
17
|
+
*/
|
|
18
|
+
export interface ActiveSessionPointer {
|
|
19
|
+
/** ISO timestamp when this session became active */
|
|
20
|
+
activatedAt: string;
|
|
21
|
+
/** PID of the process that activated this session (for stale detection) */
|
|
22
|
+
pid: number;
|
|
23
|
+
/**
|
|
24
|
+
* Unique token identifying this specific process instance.
|
|
25
|
+
* Used to detect PID reuse: if the PID exists but token differs,
|
|
26
|
+
* it's a different process that got the same PID after the original crashed.
|
|
27
|
+
* Optional for backward compatibility with existing session files.
|
|
28
|
+
*/
|
|
29
|
+
processToken?: string;
|
|
30
|
+
/** Session ID of the currently active session */
|
|
31
|
+
sessionId: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Session metadata stored in .brv/sessions/session-*.json
|
|
35
|
+
* Contains metadata about a session for listing and management.
|
|
36
|
+
*/
|
|
37
|
+
export interface SessionMetadata {
|
|
38
|
+
/** ISO timestamp when session was created */
|
|
39
|
+
createdAt: string;
|
|
40
|
+
/** ISO timestamp of last activity */
|
|
41
|
+
lastUpdated: string;
|
|
42
|
+
/** Number of messages in session (cached for quick display) */
|
|
43
|
+
messageCount: number;
|
|
44
|
+
/** Unique session identifier (UUID) */
|
|
45
|
+
sessionId: string;
|
|
46
|
+
/** Session lifecycle status */
|
|
47
|
+
status: SessionStatus;
|
|
48
|
+
/** Optional AI-generated summary */
|
|
49
|
+
summary?: string;
|
|
50
|
+
/** Session title (generated from first user message) */
|
|
51
|
+
title?: string;
|
|
52
|
+
/** Project working directory (for validation) */
|
|
53
|
+
workingDirectory: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Session info for display purposes (extends metadata with computed fields).
|
|
57
|
+
*/
|
|
58
|
+
export interface SessionInfo extends SessionMetadata {
|
|
59
|
+
/** Filename without extension */
|
|
60
|
+
file: string;
|
|
61
|
+
/** Full filename including .json extension */
|
|
62
|
+
fileName: string;
|
|
63
|
+
/** First user message content (cleaned) */
|
|
64
|
+
firstUserMessage?: string;
|
|
65
|
+
/** Display index in the list (1-based) */
|
|
66
|
+
index: number;
|
|
67
|
+
/** Whether this is the currently active session */
|
|
68
|
+
isCurrentSession: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Result of resolving a session selection.
|
|
72
|
+
*/
|
|
73
|
+
export interface SessionSelectionResult {
|
|
74
|
+
/** Display info string for user feedback */
|
|
75
|
+
displayInfo: string;
|
|
76
|
+
/** Loaded session metadata */
|
|
77
|
+
sessionData: SessionMetadata;
|
|
78
|
+
/** Full path to session metadata file */
|
|
79
|
+
sessionPath: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Schema for ActiveSessionPointer validation.
|
|
83
|
+
*/
|
|
84
|
+
export declare const ActiveSessionPointerSchema: z.ZodObject<{
|
|
85
|
+
activatedAt: z.ZodUnion<[z.ZodString, z.ZodString]>;
|
|
86
|
+
pid: z.ZodNumber;
|
|
87
|
+
processToken: z.ZodOptional<z.ZodString>;
|
|
88
|
+
sessionId: z.ZodString;
|
|
89
|
+
}, "strip", z.ZodTypeAny, {
|
|
90
|
+
sessionId: string;
|
|
91
|
+
pid: number;
|
|
92
|
+
activatedAt: string;
|
|
93
|
+
processToken?: string | undefined;
|
|
94
|
+
}, {
|
|
95
|
+
sessionId: string;
|
|
96
|
+
pid: number;
|
|
97
|
+
activatedAt: string;
|
|
98
|
+
processToken?: string | undefined;
|
|
99
|
+
}>;
|
|
100
|
+
/**
|
|
101
|
+
* Schema for SessionMetadata validation.
|
|
102
|
+
*/
|
|
103
|
+
export declare const SessionMetadataSchema: z.ZodObject<{
|
|
104
|
+
createdAt: z.ZodUnion<[z.ZodString, z.ZodString]>;
|
|
105
|
+
lastUpdated: z.ZodUnion<[z.ZodString, z.ZodString]>;
|
|
106
|
+
messageCount: z.ZodNumber;
|
|
107
|
+
sessionId: z.ZodString;
|
|
108
|
+
status: z.ZodEnum<["active", "ended", "interrupted"]>;
|
|
109
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
110
|
+
title: z.ZodOptional<z.ZodString>;
|
|
111
|
+
workingDirectory: z.ZodString;
|
|
112
|
+
}, "strip", z.ZodTypeAny, {
|
|
113
|
+
status: "active" | "ended" | "interrupted";
|
|
114
|
+
sessionId: string;
|
|
115
|
+
createdAt: string;
|
|
116
|
+
lastUpdated: string;
|
|
117
|
+
messageCount: number;
|
|
118
|
+
workingDirectory: string;
|
|
119
|
+
summary?: string | undefined;
|
|
120
|
+
title?: string | undefined;
|
|
121
|
+
}, {
|
|
122
|
+
status: "active" | "ended" | "interrupted";
|
|
123
|
+
sessionId: string;
|
|
124
|
+
createdAt: string;
|
|
125
|
+
lastUpdated: string;
|
|
126
|
+
messageCount: number;
|
|
127
|
+
workingDirectory: string;
|
|
128
|
+
summary?: string | undefined;
|
|
129
|
+
title?: string | undefined;
|
|
130
|
+
}>;
|
|
131
|
+
/** Prefix for session metadata files */
|
|
132
|
+
export declare const SESSION_FILE_PREFIX = "session-";
|
|
133
|
+
/** Directory name for session storage */
|
|
134
|
+
export declare const SESSIONS_DIR = "sessions";
|
|
135
|
+
/** Filename for active session pointer */
|
|
136
|
+
export declare const ACTIVE_SESSION_FILE = "active.json";
|
|
137
|
+
/** Default session retention config */
|
|
138
|
+
export declare const DEFAULT_SESSION_RETENTION: {
|
|
139
|
+
/** Maximum age in days before auto-cleanup */
|
|
140
|
+
maxAgeDays: number;
|
|
141
|
+
/** Maximum number of sessions to keep */
|
|
142
|
+
maxCount: number;
|
|
143
|
+
/** Run cleanup on startup */
|
|
144
|
+
runOnStartup: boolean;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Generate a session filename from timestamp and session ID.
|
|
148
|
+
*
|
|
149
|
+
* @param sessionId - The session UUID
|
|
150
|
+
* @returns Filename in format: session-YYYY-MM-DDTHH-MM-SS-<uuid-prefix>.json
|
|
151
|
+
*/
|
|
152
|
+
export declare function generateSessionFilename(sessionId: string): string;
|
|
153
|
+
/**
|
|
154
|
+
* Parse a session filename to extract timestamp and UUID prefix.
|
|
155
|
+
*
|
|
156
|
+
* @param filename - The session filename
|
|
157
|
+
* @returns Parsed components or null if invalid format
|
|
158
|
+
*/
|
|
159
|
+
export declare function parseSessionFilename(filename: string): null | {
|
|
160
|
+
timestamp: string;
|
|
161
|
+
uuidPrefix: string;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Format a timestamp as relative time.
|
|
165
|
+
*
|
|
166
|
+
* @param timestamp - ISO timestamp string
|
|
167
|
+
* @param style - 'long' (e.g., "2 hours ago") or 'short' (e.g., "2h")
|
|
168
|
+
* @returns Formatted relative time string
|
|
169
|
+
*/
|
|
170
|
+
export declare function formatRelativeTime(timestamp: string, style?: 'long' | 'short'): string;
|
|
171
|
+
/**
|
|
172
|
+
* Clean and sanitize message content for display.
|
|
173
|
+
* Converts newlines to spaces, collapses whitespace, removes non-printable chars.
|
|
174
|
+
*
|
|
175
|
+
* @param message - Raw message content
|
|
176
|
+
* @returns Cleaned message suitable for display
|
|
177
|
+
*/
|
|
178
|
+
export declare function cleanMessageForTitle(message: string): string;
|