byterover-cli 1.0.4 → 1.0.5
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 +13 -2
- package/dist/commands/curate.js +1 -1
- package/dist/commands/main.d.ts +13 -0
- package/dist/commands/main.js +53 -2
- package/dist/commands/query.js +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- 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/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 +37 -2
- package/dist/core/domain/transport/schemas.js +23 -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/executor/i-curate-executor.d.ts +2 -2
- package/dist/core/interfaces/i-context-file-reader.d.ts +3 -0
- package/dist/core/interfaces/usecase/{i-clear-use-case.d.ts → i-reset-use-case.d.ts} +1 -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/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.js +40 -16
- package/dist/infra/cipher/llm/formatters/gemini-formatter.d.ts +13 -0
- package/dist/infra/cipher/llm/formatters/gemini-formatter.js +98 -6
- package/dist/infra/cipher/llm/generators/byterover-content-generator.js +6 -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/tools/implementations/curate-tool.js +113 -35
- package/dist/infra/cipher/tools/implementations/task-tool.js +1 -0
- package/dist/infra/context-tree/file-context-file-reader.js +4 -0
- package/dist/infra/core/task-processor.d.ts +2 -2
- package/dist/infra/process/process-manager.d.ts +10 -1
- package/dist/infra/process/process-manager.js +16 -6
- package/dist/infra/process/transport-handlers.js +31 -0
- package/dist/infra/repl/commands/index.js +5 -2
- 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/{clear-command.d.ts → reset-command.d.ts} +2 -2
- package/dist/infra/repl/commands/{clear-command.js → reset-command.js} +10 -10
- package/dist/infra/usecase/generate-rules-use-case.js +2 -2
- package/dist/infra/usecase/init-use-case.js +4 -4
- package/dist/infra/usecase/logout-use-case.js +1 -1
- package/dist/infra/usecase/push-use-case.js +1 -1
- 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} +5 -5
- package/dist/resources/prompts/curate.yml +68 -13
- package/dist/resources/tools/curate.txt +60 -15
- package/dist/tui/components/inline-prompts/inline-confirm.js +2 -2
- package/dist/tui/components/onboarding/onboarding-flow.js +1 -0
- package/dist/tui/views/command-view.js +15 -0
- package/dist/utils/file-validator.js +9 -7
- package/oclif.manifest.json +3 -3
- package/package.json +1 -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-clear-use-case.js → i-reset-use-case.js} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { BRV_DIR, CONTEXT_TREE_DIR } from '../../constants.js';
|
|
4
|
+
import { MarkdownWriter } from '../../core/domain/knowledge/markdown-writer.js';
|
|
4
5
|
/**
|
|
5
6
|
* Extracts the title from the first markdown heading in the content.
|
|
6
7
|
* @param content - The file content
|
|
@@ -27,9 +28,12 @@ export class FileContextFileReader {
|
|
|
27
28
|
try {
|
|
28
29
|
const content = await readFile(fullPath, 'utf8');
|
|
29
30
|
const title = extractTitle(content, relativePath);
|
|
31
|
+
const parsedContent = MarkdownWriter.parseContent(content, title);
|
|
30
32
|
return {
|
|
31
33
|
content,
|
|
34
|
+
narrative: parsedContent.narrative,
|
|
32
35
|
path: relativePath,
|
|
36
|
+
rawConcept: parsedContent.rawConcept,
|
|
33
37
|
title,
|
|
34
38
|
};
|
|
35
39
|
}
|
|
@@ -7,10 +7,10 @@ import type { IQueryExecutor } from '../../core/interfaces/executor/i-query-exec
|
|
|
7
7
|
* Agent uses its default session (Single-Session pattern).
|
|
8
8
|
*/
|
|
9
9
|
export type TaskInput = {
|
|
10
|
-
/** Task content/prompt */
|
|
11
|
-
content: string;
|
|
12
10
|
/** Client's working directory for file validation */
|
|
13
11
|
clientCwd?: string;
|
|
12
|
+
/** Task content/prompt */
|
|
13
|
+
content: string;
|
|
14
14
|
/** Optional file paths for curate --files */
|
|
15
15
|
files?: string[];
|
|
16
16
|
/** Task ID */
|
|
@@ -47,6 +47,13 @@ export type ProcessManagerConfig = {
|
|
|
47
47
|
/** Timeout for process startup (ms) */
|
|
48
48
|
startupTimeoutMs?: number;
|
|
49
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* Options for starting the process manager.
|
|
52
|
+
*/
|
|
53
|
+
export type ProcessStartOptions = {
|
|
54
|
+
/** Session ID to pass to Agent process (for stateful sessions) */
|
|
55
|
+
sessionId?: string;
|
|
56
|
+
};
|
|
50
57
|
/**
|
|
51
58
|
* ProcessManager - Spawns and manages Transport and Agent processes.
|
|
52
59
|
*
|
|
@@ -57,6 +64,7 @@ export type ProcessManagerConfig = {
|
|
|
57
64
|
* - Crash recovery: respawn on exit
|
|
58
65
|
*/
|
|
59
66
|
export declare class ProcessManager {
|
|
67
|
+
private currentSessionId?;
|
|
60
68
|
private healthCheckInterval?;
|
|
61
69
|
private lastHealthCheckTime;
|
|
62
70
|
private readonly shutdownTimeoutMs;
|
|
@@ -84,9 +92,10 @@ export declare class ProcessManager {
|
|
|
84
92
|
* 3. Start Agent Process with TRANSPORT_PORT env
|
|
85
93
|
* 4. Wait for Agent 'ready'
|
|
86
94
|
*
|
|
95
|
+
* @param options - Start options including session ID for stateful sessions
|
|
87
96
|
* @throws Error if startup fails or times out
|
|
88
97
|
*/
|
|
89
|
-
start(): Promise<void>;
|
|
98
|
+
start(options?: ProcessStartOptions): Promise<void>;
|
|
90
99
|
/**
|
|
91
100
|
* Stop all processes gracefully.
|
|
92
101
|
*
|
|
@@ -46,6 +46,7 @@ function createSystemError(error, context) {
|
|
|
46
46
|
* - Crash recovery: respawn on exit
|
|
47
47
|
*/
|
|
48
48
|
export class ProcessManager {
|
|
49
|
+
currentSessionId;
|
|
49
50
|
healthCheckInterval;
|
|
50
51
|
lastHealthCheckTime = Date.now();
|
|
51
52
|
shutdownTimeoutMs;
|
|
@@ -86,12 +87,15 @@ export class ProcessManager {
|
|
|
86
87
|
* 3. Start Agent Process with TRANSPORT_PORT env
|
|
87
88
|
* 4. Wait for Agent 'ready'
|
|
88
89
|
*
|
|
90
|
+
* @param options - Start options including session ID for stateful sessions
|
|
89
91
|
* @throws Error if startup fails or times out
|
|
90
92
|
*/
|
|
91
|
-
async start() {
|
|
93
|
+
async start(options) {
|
|
92
94
|
if (this.state.running) {
|
|
93
95
|
return;
|
|
94
96
|
}
|
|
97
|
+
// Store session ID for use when spawning agent
|
|
98
|
+
this.currentSessionId = options?.sessionId;
|
|
95
99
|
// Step 1: Start Transport Process
|
|
96
100
|
const port = await this.startTransportProcess();
|
|
97
101
|
this.state.port = port;
|
|
@@ -235,12 +239,18 @@ export class ProcessManager {
|
|
|
235
239
|
async startAgentProcess(transportPort) {
|
|
236
240
|
return new Promise((resolve, reject) => {
|
|
237
241
|
const workerPath = path.resolve(this.getWorkerDir(), 'agent-worker.js');
|
|
242
|
+
// Build environment variables for agent
|
|
243
|
+
const agentEnv = {
|
|
244
|
+
...process.env,
|
|
245
|
+
BRV_SESSION_LOG: getSessionLogPath(),
|
|
246
|
+
TRANSPORT_PORT: String(transportPort),
|
|
247
|
+
};
|
|
248
|
+
// Pass session ID if provided (for stateful sessions)
|
|
249
|
+
if (this.currentSessionId) {
|
|
250
|
+
agentEnv.BYTEROVER_SESSION_ID = this.currentSessionId;
|
|
251
|
+
}
|
|
238
252
|
const child = fork(workerPath, [], {
|
|
239
|
-
env:
|
|
240
|
-
...process.env,
|
|
241
|
-
BRV_SESSION_LOG: getSessionLogPath(),
|
|
242
|
-
TRANSPORT_PORT: String(transportPort),
|
|
243
|
-
},
|
|
253
|
+
env: agentEnv,
|
|
244
254
|
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
|
|
245
255
|
});
|
|
246
256
|
this.state.agentProcess = child;
|
|
@@ -285,6 +285,37 @@ export class TransportHandlers {
|
|
|
285
285
|
this.transport.broadcast(TransportAgentEventNames.RESTARTED, { error: data.error, success: false });
|
|
286
286
|
}
|
|
287
287
|
});
|
|
288
|
+
// agent:newSession - Client requests a new session (ends current, starts fresh)
|
|
289
|
+
this.transport.onRequest(TransportAgentEventNames.NEW_SESSION, (data, clientId) => {
|
|
290
|
+
transportLog(`New session requested by ${clientId}: ${data.reason ?? 'no reason'}`);
|
|
291
|
+
if (!this.agentClientId) {
|
|
292
|
+
return { error: 'Agent not connected', success: false };
|
|
293
|
+
}
|
|
294
|
+
// Forward new session command to Agent
|
|
295
|
+
this.transport.sendTo(this.agentClientId, TransportAgentEventNames.NEW_SESSION, { reason: data.reason });
|
|
296
|
+
// The actual response will come via agent:newSessionCreated event
|
|
297
|
+
// For now, return success to indicate the request was forwarded
|
|
298
|
+
return { success: true };
|
|
299
|
+
});
|
|
300
|
+
// agent:newSessionCreated - Agent reports new session creation result
|
|
301
|
+
this.transport.onRequest(TransportAgentEventNames.NEW_SESSION_CREATED, (data) => {
|
|
302
|
+
if (data.success) {
|
|
303
|
+
transportLog(`New session created: ${data.sessionId}`);
|
|
304
|
+
eventLog('agent:newSessionCreated', { sessionId: data.sessionId, success: true });
|
|
305
|
+
this.transport.broadcast(TransportAgentEventNames.NEW_SESSION_CREATED, {
|
|
306
|
+
sessionId: data.sessionId,
|
|
307
|
+
success: true,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
transportLog(`New session creation failed: ${data.error}`);
|
|
312
|
+
eventLog('agent:newSessionCreated', { error: data.error, success: false });
|
|
313
|
+
this.transport.broadcast(TransportAgentEventNames.NEW_SESSION_CREATED, {
|
|
314
|
+
error: data.error,
|
|
315
|
+
success: false,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
});
|
|
288
319
|
}
|
|
289
320
|
/**
|
|
290
321
|
* Setup Agent-related handlers.
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { clearCommand } from './clear-command.js';
|
|
2
1
|
import { curateCommand } from './curate-command.js';
|
|
3
2
|
import { genRulesCommand } from './gen-rules-command.js';
|
|
4
3
|
import { initCommand } from './init-command.js';
|
|
5
4
|
import { loginCommand } from './login-command.js';
|
|
6
5
|
import { logoutCommand } from './logout-command.js';
|
|
6
|
+
import { newCommand } from './new-command.js';
|
|
7
7
|
import { pullCommand } from './pull-command.js';
|
|
8
8
|
import { pushCommand } from './push-command.js';
|
|
9
9
|
import { queryCommand } from './query-command.js';
|
|
10
|
+
import { resetCommand } from './reset-command.js';
|
|
10
11
|
import { spaceCommand } from './space/index.js';
|
|
11
12
|
import { statusCommand } from './status-command.js';
|
|
12
13
|
/**
|
|
@@ -27,7 +28,9 @@ export const load = () => [
|
|
|
27
28
|
spaceCommand, // Switch/list spaces
|
|
28
29
|
// Context tree management
|
|
29
30
|
genRulesCommand, // Generate rule files
|
|
30
|
-
|
|
31
|
+
resetCommand, // Reset context tree (destructive)
|
|
32
|
+
// Session management
|
|
33
|
+
newCommand, // Start fresh session (ends current, clears conversation)
|
|
31
34
|
// Setup
|
|
32
35
|
initCommand, // Project setup (once per project)
|
|
33
36
|
// Auth
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type SlashCommand } from '../../../tui/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* /new command - Start a fresh session.
|
|
4
|
+
*
|
|
5
|
+
* This command:
|
|
6
|
+
* 1. Marks the current session as 'ended'
|
|
7
|
+
* 2. Creates a new session ID
|
|
8
|
+
* 3. Updates the active session pointer
|
|
9
|
+
* 4. Clears conversation history from the TUI view
|
|
10
|
+
*
|
|
11
|
+
* Note: This command does NOT affect the context tree (use /clear for that).
|
|
12
|
+
* The actual session switching is handled by command-view.tsx after this command executes.
|
|
13
|
+
*/
|
|
14
|
+
export declare const newCommand: SlashCommand;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { CommandKind } from '../../../tui/types.js';
|
|
2
|
+
import { ReplTerminal } from '../../terminal/repl-terminal.js';
|
|
3
|
+
import { Flags, parseReplArgs, toCommandFlags } from './arg-parser.js';
|
|
4
|
+
// Flags - defined once, used for both parsing and help display
|
|
5
|
+
const newFlags = {
|
|
6
|
+
yes: Flags.boolean({
|
|
7
|
+
char: 'y',
|
|
8
|
+
default: false,
|
|
9
|
+
description: 'Skip confirmation prompt',
|
|
10
|
+
}),
|
|
11
|
+
};
|
|
12
|
+
// Args - no args needed
|
|
13
|
+
const newArgs = {};
|
|
14
|
+
/**
|
|
15
|
+
* /new command - Start a fresh session.
|
|
16
|
+
*
|
|
17
|
+
* This command:
|
|
18
|
+
* 1. Marks the current session as 'ended'
|
|
19
|
+
* 2. Creates a new session ID
|
|
20
|
+
* 3. Updates the active session pointer
|
|
21
|
+
* 4. Clears conversation history from the TUI view
|
|
22
|
+
*
|
|
23
|
+
* Note: This command does NOT affect the context tree (use /clear for that).
|
|
24
|
+
* The actual session switching is handled by command-view.tsx after this command executes.
|
|
25
|
+
*/
|
|
26
|
+
export const newCommand = {
|
|
27
|
+
action(_context, args) {
|
|
28
|
+
return {
|
|
29
|
+
async execute(onMessage, onPrompt) {
|
|
30
|
+
const terminal = new ReplTerminal({ onMessage, onPrompt });
|
|
31
|
+
const parsed = await parseReplArgs(args, {
|
|
32
|
+
args: newArgs,
|
|
33
|
+
flags: newFlags,
|
|
34
|
+
strict: false,
|
|
35
|
+
});
|
|
36
|
+
// Show confirmation unless -y flag is passed
|
|
37
|
+
if (!parsed.flags.yes) {
|
|
38
|
+
const confirmed = await terminal.confirm({
|
|
39
|
+
default: false,
|
|
40
|
+
message: 'Start a new session (ends current session and clears conversation history)',
|
|
41
|
+
});
|
|
42
|
+
if (!confirmed) {
|
|
43
|
+
terminal.log('Cancelled.');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
terminal.log('Starting new session...');
|
|
48
|
+
// The actual session creation is handled by command-view.tsx
|
|
49
|
+
// after this command completes. It sends agent:newSession event.
|
|
50
|
+
},
|
|
51
|
+
type: 'streaming',
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
aliases: [],
|
|
55
|
+
args: [],
|
|
56
|
+
autoExecute: true,
|
|
57
|
+
description: 'Start a fresh session (ends current session, clears conversation)',
|
|
58
|
+
flags: toCommandFlags(newFlags),
|
|
59
|
+
kind: CommandKind.BUILT_IN,
|
|
60
|
+
name: 'new',
|
|
61
|
+
};
|
|
@@ -2,10 +2,10 @@ import { CommandKind } from '../../../tui/types.js';
|
|
|
2
2
|
import { FileContextTreeService } from '../../context-tree/file-context-tree-service.js';
|
|
3
3
|
import { FileContextTreeSnapshotService } from '../../context-tree/file-context-tree-snapshot-service.js';
|
|
4
4
|
import { ReplTerminal } from '../../terminal/repl-terminal.js';
|
|
5
|
-
import {
|
|
5
|
+
import { ResetUseCase } from '../../usecase/reset-use-case.js';
|
|
6
6
|
import { Args, Flags, parseReplArgs, toCommandFlags } from './arg-parser.js';
|
|
7
7
|
// Flags - defined once, used for both parsing and help display
|
|
8
|
-
const
|
|
8
|
+
const resetFlags = {
|
|
9
9
|
yes: Flags.boolean({
|
|
10
10
|
char: 'y',
|
|
11
11
|
default: false,
|
|
@@ -13,26 +13,26 @@ const clearFlags = {
|
|
|
13
13
|
}),
|
|
14
14
|
};
|
|
15
15
|
// Args - defined once for parsing
|
|
16
|
-
const
|
|
16
|
+
const resetArgs = {
|
|
17
17
|
directory: Args.string({
|
|
18
18
|
description: 'Project directory (defaults to current directory)',
|
|
19
19
|
required: false,
|
|
20
20
|
}),
|
|
21
21
|
};
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* reset command
|
|
24
24
|
*/
|
|
25
|
-
export const
|
|
25
|
+
export const resetCommand = {
|
|
26
26
|
action(_context, args) {
|
|
27
27
|
return {
|
|
28
28
|
async execute(onMessage, onPrompt) {
|
|
29
29
|
const terminal = new ReplTerminal({ onMessage, onPrompt });
|
|
30
30
|
const parsed = await parseReplArgs(args, {
|
|
31
|
-
args:
|
|
32
|
-
flags:
|
|
31
|
+
args: resetArgs,
|
|
32
|
+
flags: resetFlags,
|
|
33
33
|
strict: false,
|
|
34
34
|
});
|
|
35
|
-
const useCase = new
|
|
35
|
+
const useCase = new ResetUseCase({
|
|
36
36
|
contextTreeService: new FileContextTreeService(),
|
|
37
37
|
contextTreeSnapshotService: new FileContextTreeSnapshotService(),
|
|
38
38
|
terminal,
|
|
@@ -55,7 +55,7 @@ export const clearCommand = {
|
|
|
55
55
|
],
|
|
56
56
|
autoExecute: true,
|
|
57
57
|
description: 'Reset the current context tree and start with 6 default domains',
|
|
58
|
-
flags: toCommandFlags(
|
|
58
|
+
flags: toCommandFlags(resetFlags),
|
|
59
59
|
kind: CommandKind.BUILT_IN,
|
|
60
|
-
name: '
|
|
60
|
+
name: 'reset',
|
|
61
61
|
};
|
|
@@ -69,7 +69,7 @@ export class GenerateRulesUseCase {
|
|
|
69
69
|
async promptForFileCreation(agent, filePath) {
|
|
70
70
|
return this.terminal.confirm({
|
|
71
71
|
default: true,
|
|
72
|
-
message: `Rule file '${filePath}' doesn't exist. Create it with ByteRover rules
|
|
72
|
+
message: `Rule file '${filePath}' doesn't exist. Create it with ByteRover rules`,
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
@@ -81,7 +81,7 @@ export class GenerateRulesUseCase {
|
|
|
81
81
|
async promptForOverwriteConfirmation(agent) {
|
|
82
82
|
return this.terminal.confirm({
|
|
83
83
|
default: true,
|
|
84
|
-
message: `Rule file already exists for ${agent}. Overwrite
|
|
84
|
+
message: `Rule file already exists for ${agent}. Overwrite`,
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
async run() {
|
|
@@ -81,7 +81,7 @@ export class InitUseCase {
|
|
|
81
81
|
this.terminal.log(' - Regenerate rule instructions\n');
|
|
82
82
|
return this.terminal.confirm({
|
|
83
83
|
default: false,
|
|
84
|
-
message: 'Continue with re-initialization
|
|
84
|
+
message: 'Continue with re-initialization',
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
detectWorkspacesForAgent(agent) {
|
|
@@ -259,7 +259,7 @@ export class InitUseCase {
|
|
|
259
259
|
this.terminal.log(' This folder and all its contents can be safely removed.\n');
|
|
260
260
|
return this.terminal.confirm({
|
|
261
261
|
default: true,
|
|
262
|
-
message: 'Remove the ACE folder and its contents
|
|
262
|
+
message: 'Remove the ACE folder and its contents',
|
|
263
263
|
});
|
|
264
264
|
}
|
|
265
265
|
/**
|
|
@@ -314,7 +314,7 @@ export class InitUseCase {
|
|
|
314
314
|
async promptForFileCreation(agent, filePath) {
|
|
315
315
|
return this.terminal.confirm({
|
|
316
316
|
default: true,
|
|
317
|
-
message: `Rule file '${filePath}' doesn't exist. Create it with ByteRover rules
|
|
317
|
+
message: `Rule file '${filePath}' doesn't exist. Create it with ByteRover rules`,
|
|
318
318
|
});
|
|
319
319
|
}
|
|
320
320
|
/**
|
|
@@ -324,7 +324,7 @@ export class InitUseCase {
|
|
|
324
324
|
async promptForOverwriteConfirmation(agent) {
|
|
325
325
|
return this.terminal.confirm({
|
|
326
326
|
default: true,
|
|
327
|
-
message: `Rule file already exists for ${agent}. Overwrite
|
|
327
|
+
message: `Rule file already exists for ${agent}. Overwrite`,
|
|
328
328
|
});
|
|
329
329
|
}
|
|
330
330
|
async promptForSpaceSelection(spaces) {
|
|
@@ -12,7 +12,7 @@ export class LogoutUseCase {
|
|
|
12
12
|
async confirmLogout(userEmail) {
|
|
13
13
|
return this.terminal.confirm({
|
|
14
14
|
default: true,
|
|
15
|
-
message: `Logging out ${userEmail}. Are you sure
|
|
15
|
+
message: `Logging out ${userEmail}. Are you sure`,
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
async run(options) {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type { IContextTreeService } from '../../core/interfaces/i-context-tree-service.js';
|
|
2
2
|
import type { IContextTreeSnapshotService } from '../../core/interfaces/i-context-tree-snapshot-service.js';
|
|
3
3
|
import type { ITerminal } from '../../core/interfaces/i-terminal.js';
|
|
4
|
-
import type {
|
|
5
|
-
export interface
|
|
4
|
+
import type { IResetUseCase } from '../../core/interfaces/usecase/i-reset-use-case.js';
|
|
5
|
+
export interface ResetUseCaseOptions {
|
|
6
6
|
contextTreeService: IContextTreeService;
|
|
7
7
|
contextTreeSnapshotService: IContextTreeSnapshotService;
|
|
8
8
|
terminal: ITerminal;
|
|
9
9
|
}
|
|
10
|
-
export declare class
|
|
10
|
+
export declare class ResetUseCase implements IResetUseCase {
|
|
11
11
|
private readonly contextTreeService;
|
|
12
12
|
private readonly contextTreeSnapshotService;
|
|
13
13
|
private readonly terminal;
|
|
14
|
-
constructor(options:
|
|
15
|
-
protected
|
|
14
|
+
constructor(options: ResetUseCaseOptions);
|
|
15
|
+
protected confirmReset(): Promise<boolean>;
|
|
16
16
|
run(options: {
|
|
17
17
|
directory?: string;
|
|
18
18
|
skipConfirmation: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { rm } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { BRV_DIR, CONTEXT_TREE_DIR } from '../../constants.js';
|
|
4
|
-
export class
|
|
4
|
+
export class ResetUseCase {
|
|
5
5
|
contextTreeService;
|
|
6
6
|
contextTreeSnapshotService;
|
|
7
7
|
terminal;
|
|
@@ -11,10 +11,10 @@ export class ClearUseCase {
|
|
|
11
11
|
this.terminal = options.terminal;
|
|
12
12
|
}
|
|
13
13
|
// Protected method for testability - can be overridden in tests
|
|
14
|
-
async
|
|
14
|
+
async confirmReset() {
|
|
15
15
|
return this.terminal.confirm({
|
|
16
16
|
default: false,
|
|
17
|
-
message: 'Are you sure you want to reset the context tree? This will remove all existing context and restore default domains
|
|
17
|
+
message: 'Are you sure you want to reset the context tree? This will remove all existing context and restore default domains',
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
20
|
async run(options) {
|
|
@@ -22,12 +22,12 @@ export class ClearUseCase {
|
|
|
22
22
|
// Check if context tree exists
|
|
23
23
|
const exists = await this.contextTreeService.exists(options.directory);
|
|
24
24
|
if (!exists) {
|
|
25
|
-
this.terminal.log('No context tree found. Nothing to
|
|
25
|
+
this.terminal.log('No context tree found. Nothing to reset.');
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
28
|
// Confirmation prompt (unless skipConfirmation is true)
|
|
29
29
|
if (!options.skipConfirmation) {
|
|
30
|
-
const confirmed = await this.
|
|
30
|
+
const confirmed = await this.confirmReset();
|
|
31
31
|
if (!confirmed) {
|
|
32
32
|
this.terminal.log('Cancelled. Context tree was not reset.');
|
|
33
33
|
return;
|
|
@@ -10,8 +10,8 @@ prompt: |
|
|
|
10
10
|
- the domains of the context (dynamically created based on content)
|
|
11
11
|
- the topics of the context
|
|
12
12
|
- the subtopics of the context (maximum one level under topics)
|
|
13
|
-
- the
|
|
14
|
-
- the
|
|
13
|
+
- the structured metadata (Raw Concept) and descriptive context (Narrative)
|
|
14
|
+
- the code snippets of the context (optional, for backward compatibility)
|
|
15
15
|
|
|
16
16
|
For doing that, you will need to acquire information from the chat history with the corresponding tools. Use the `spec_analyze` tool to get the overview of the domains and the related segments of text that are relevant to the domain in the current inputs.
|
|
17
17
|
|
|
@@ -31,6 +31,8 @@ prompt: |
|
|
|
31
31
|
Use the `curate` tool to create new knowledge topics or update existing ones. Ensure that:
|
|
32
32
|
- **Dynamic Domain Creation**: Create domains that are semantically meaningful for the content being curated
|
|
33
33
|
- The context is well-structured and MUST meet **Context quality requirements**
|
|
34
|
+
- **Domain selection**: Always prefer predefined domains (code_style, design, structure, compliance, testing, bug_fixes). Only create custom domains if content clearly doesn't fit any predefined domain. Maximum 3 custom domains allowed.
|
|
35
|
+
- The context is well-structured and MUST use the **Two-Part Context Model**
|
|
34
36
|
- There is no duplication with existing context
|
|
35
37
|
- The information is clear and easy to understand
|
|
36
38
|
|
|
@@ -43,22 +45,71 @@ prompt: |
|
|
|
43
45
|
- **Before creating a new domain**: Check if existing domains could accommodate the content
|
|
44
46
|
- **Consolidate related concepts**: Group similar topics under the same domain for better organization
|
|
45
47
|
|
|
46
|
-
5. **
|
|
47
|
-
|
|
48
|
-
-
|
|
48
|
+
5. **Two-Part Context Model (REQUIRED)**: When creating context using the `curate` tool, you MUST use the structured format with `rawConcept` and `narrative`:
|
|
49
|
+
|
|
50
|
+
**rawConcept** - Captures essential metadata and technical footprint:
|
|
51
|
+
- `task`: What is the task/feature being documented (required - always include this)
|
|
52
|
+
- `changes`: Array of changes induced in the codebase (e.g., ["Added Redis caching", "Created singleton client"])
|
|
53
|
+
- `files`: Array of related files (e.g., ["services/auth.ts", "utils/cache.ts"])
|
|
54
|
+
- `flow`: The execution flow (e.g., "request -> validate -> cache check -> process -> respond")
|
|
55
|
+
- `timestamp`: When created (ISO 8601 format, e.g., "2025-03-18")
|
|
56
|
+
|
|
57
|
+
**narrative** - Captures descriptive and structural context:
|
|
58
|
+
- `structure`: Code structure documentation (describe file organization, class hierarchy, etc.)
|
|
59
|
+
- `dependencies`: Dependency management information (external libs, internal dependencies, initialization order)
|
|
60
|
+
- `features`: Feature documentation (behavior, limitations, edge cases, caching TTLs, etc.)
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
62
|
+
**Example curate tool call:**
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"type": "ADD",
|
|
66
|
+
"path": "structure/authentication",
|
|
67
|
+
"title": "JWT Token Handling",
|
|
68
|
+
"content": {
|
|
69
|
+
"rawConcept": {
|
|
70
|
+
"task": "Implement JWT-based authentication with refresh tokens",
|
|
71
|
+
"changes": [
|
|
72
|
+
"Added JWT verification middleware",
|
|
73
|
+
"Implemented refresh token rotation",
|
|
74
|
+
"Added token blacklist using Redis"
|
|
75
|
+
],
|
|
76
|
+
"files": [
|
|
77
|
+
"src/middleware/auth.ts",
|
|
78
|
+
"src/services/token-service.ts",
|
|
79
|
+
"src/utils/jwt.ts"
|
|
80
|
+
],
|
|
81
|
+
"flow": "request -> extract token -> verify JWT -> check blacklist -> attach user -> proceed",
|
|
82
|
+
"timestamp": "2025-01-02"
|
|
83
|
+
},
|
|
84
|
+
"narrative": {
|
|
85
|
+
"structure": "Authentication is handled by middleware in src/middleware/auth.ts which delegates to TokenService for JWT operations",
|
|
86
|
+
"dependencies": "Uses jsonwebtoken library for JWT operations, Redis for token blacklist with 24h TTL",
|
|
87
|
+
"features": "Access tokens expire in 15 minutes, refresh tokens in 7 days. Refresh token rotation invalidates old tokens immediately"
|
|
88
|
+
},
|
|
89
|
+
"relations": ["@structure/redis", "@design/security"]
|
|
90
|
+
},
|
|
91
|
+
"reason": "Documenting new JWT authentication system"
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
6. **Context Quality Requirements**: Each context MUST:
|
|
96
|
+
- Include a clear `task` in rawConcept describing what the concept is about
|
|
97
|
+
- Provide at least one of: `changes`, `files`, or `flow` in rawConcept
|
|
98
|
+
- Include at least one narrative field (`structure`, `dependencies`, or `features`)
|
|
99
|
+
- Contain minimum 2-4 sentences per context - otherwise, DO NOT add that context
|
|
100
|
+
- Ensure a developer can understand the concept without reading source code
|
|
53
101
|
- Include names of functions, classes, patterns, or key concepts
|
|
54
102
|
|
|
55
|
-
|
|
103
|
+
**AVOID** vague contexts like:
|
|
56
104
|
- "Hook system"
|
|
57
105
|
- "Error handling"
|
|
106
|
+
- Only snippets without rawConcept/narrative
|
|
107
|
+
- Missing task description
|
|
108
|
+
- Vague single-word descriptions
|
|
58
109
|
|
|
59
|
-
|
|
110
|
+
**WRITE** detailed contexts like:
|
|
60
111
|
- "The hook system allows registering callbacks for lifecycle events. Register hooks using
|
|
61
|
-
`HookRegistry.register(hookName, callback)` and trigger them with `HookRegistry.trigger(hookName, context)`. Hooks
|
|
112
|
+
`HookRegistry.register(hookName, callback)` and trigger them with `HookRegistry.trigger(hookName, context)`. Hooks
|
|
62
113
|
support async callbacks and are commonly used for: pre/post tool execution, agent lifecycle events, and custom
|
|
63
114
|
integrations."
|
|
64
115
|
|
|
@@ -66,7 +117,11 @@ prompt: |
|
|
|
66
117
|
code, message, context object, and optional cause. Use `ErrorHandler.wrap(fn)` for consistent error boundaries across
|
|
67
118
|
async operations."
|
|
68
119
|
|
|
69
|
-
7. **
|
|
120
|
+
7. **Tool Execution Efficiency**:
|
|
121
|
+
- When multiple tools don't depend on each other's results, execute them in parallel with `batch`
|
|
122
|
+
- Example: `glob_files`, `list_directory`, `grep_content` and `read_file` operations for different files can run together
|
|
123
|
+
|
|
124
|
+
8. **Response Format**:
|
|
70
125
|
- Your final response must be a brief summary (1-2 sentences) describing what knowledge was curated
|
|
71
126
|
- Do NOT include any file paths, directory paths, or specific location details in your response
|
|
72
|
-
- The system will automatically display created/updated file paths in a separate section
|
|
127
|
+
- The system will automatically display created/updated file paths in a separate section
|