byterover-cli 3.3.0 → 3.5.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/dist/agent/core/domain/swarm/types.d.ts +132 -0
- package/dist/agent/core/domain/swarm/types.js +128 -0
- package/dist/agent/core/domain/tools/constants.d.ts +2 -0
- package/dist/agent/core/domain/tools/constants.js +2 -0
- package/dist/agent/core/interfaces/i-memory-provider.d.ts +45 -0
- package/dist/agent/core/interfaces/i-memory-provider.js +1 -0
- package/dist/agent/core/interfaces/i-sandbox-service.d.ts +8 -0
- package/dist/agent/core/interfaces/i-swarm-coordinator.d.ts +127 -0
- package/dist/agent/core/interfaces/i-swarm-coordinator.js +1 -0
- package/dist/agent/infra/agent/service-initializer.js +48 -0
- package/dist/agent/infra/map/map-shared.d.ts +2 -2
- package/dist/agent/infra/sandbox/sandbox-service.d.ts +10 -0
- package/dist/agent/infra/sandbox/sandbox-service.js +13 -0
- package/dist/agent/infra/sandbox/tools-sdk.d.ts +25 -0
- package/dist/agent/infra/sandbox/tools-sdk.js +24 -1
- package/dist/agent/infra/swarm/adapters/byterover-adapter.d.ts +39 -0
- package/dist/agent/infra/swarm/adapters/byterover-adapter.js +62 -0
- package/dist/agent/infra/swarm/adapters/gbrain-adapter.d.ts +63 -0
- package/dist/agent/infra/swarm/adapters/gbrain-adapter.js +209 -0
- package/dist/agent/infra/swarm/adapters/local-markdown-adapter.d.ts +41 -0
- package/dist/agent/infra/swarm/adapters/local-markdown-adapter.js +256 -0
- package/dist/agent/infra/swarm/adapters/memory-wiki-adapter.d.ts +29 -0
- package/dist/agent/infra/swarm/adapters/memory-wiki-adapter.js +244 -0
- package/dist/agent/infra/swarm/adapters/obsidian-adapter.d.ts +37 -0
- package/dist/agent/infra/swarm/adapters/obsidian-adapter.js +201 -0
- package/dist/agent/infra/swarm/cli/query-renderer.d.ts +15 -0
- package/dist/agent/infra/swarm/cli/query-renderer.js +126 -0
- package/dist/agent/infra/swarm/config/swarm-config-loader.d.ts +14 -0
- package/dist/agent/infra/swarm/config/swarm-config-loader.js +82 -0
- package/dist/agent/infra/swarm/config/swarm-config-schema.d.ts +667 -0
- package/dist/agent/infra/swarm/config/swarm-config-schema.js +305 -0
- package/dist/agent/infra/swarm/provider-factory.d.ts +21 -0
- package/dist/agent/infra/swarm/provider-factory.js +67 -0
- package/dist/agent/infra/swarm/search-precision.d.ts +95 -0
- package/dist/agent/infra/swarm/search-precision.js +141 -0
- package/dist/agent/infra/swarm/swarm-coordinator.d.ts +59 -0
- package/dist/agent/infra/swarm/swarm-coordinator.js +436 -0
- package/dist/agent/infra/swarm/swarm-graph.d.ts +63 -0
- package/dist/agent/infra/swarm/swarm-graph.js +167 -0
- package/dist/agent/infra/swarm/swarm-merger.d.ts +29 -0
- package/dist/agent/infra/swarm/swarm-merger.js +66 -0
- package/dist/agent/infra/swarm/swarm-router.d.ts +12 -0
- package/dist/agent/infra/swarm/swarm-router.js +40 -0
- package/dist/agent/infra/swarm/swarm-write-router.d.ts +23 -0
- package/dist/agent/infra/swarm/swarm-write-router.js +45 -0
- package/dist/agent/infra/swarm/validation/config-validator.d.ts +16 -0
- package/dist/agent/infra/swarm/validation/config-validator.js +402 -0
- package/dist/agent/infra/swarm/validation/memory-swarm-validation-error.d.ts +33 -0
- package/dist/agent/infra/swarm/validation/memory-swarm-validation-error.js +27 -0
- package/dist/agent/infra/swarm/wizard/config-scaffolder.d.ts +36 -0
- package/dist/agent/infra/swarm/wizard/config-scaffolder.js +96 -0
- package/dist/agent/infra/swarm/wizard/provider-detector.d.ts +54 -0
- package/dist/agent/infra/swarm/wizard/provider-detector.js +153 -0
- package/dist/agent/infra/swarm/wizard/swarm-wizard.d.ts +61 -0
- package/dist/agent/infra/swarm/wizard/swarm-wizard.js +187 -0
- package/dist/agent/infra/system-prompt/contributors/index.d.ts +1 -0
- package/dist/agent/infra/system-prompt/contributors/index.js +1 -0
- package/dist/agent/infra/system-prompt/contributors/swarm-state-contributor.d.ts +15 -0
- package/dist/agent/infra/system-prompt/contributors/swarm-state-contributor.js +65 -0
- package/dist/agent/infra/tools/implementations/curate-tool.d.ts +14 -14
- package/dist/agent/infra/tools/implementations/curate-tool.js +2 -0
- package/dist/agent/infra/tools/implementations/swarm-query-tool.d.ts +9 -0
- package/dist/agent/infra/tools/implementations/swarm-query-tool.js +44 -0
- package/dist/agent/infra/tools/implementations/swarm-store-tool.d.ts +9 -0
- package/dist/agent/infra/tools/implementations/swarm-store-tool.js +43 -0
- package/dist/agent/infra/tools/tool-provider.js +1 -0
- package/dist/agent/infra/tools/tool-registry.d.ts +3 -0
- package/dist/agent/infra/tools/tool-registry.js +25 -1
- package/dist/agent/resources/tools/code_exec.txt +2 -0
- package/dist/agent/resources/tools/swarm_query.txt +38 -0
- package/dist/agent/resources/tools/swarm_store.txt +35 -0
- package/dist/oclif/commands/connectors/install.d.ts +2 -2
- package/dist/oclif/commands/connectors/install.js +15 -7
- package/dist/oclif/commands/swarm/curate.d.ts +13 -0
- package/dist/oclif/commands/swarm/curate.js +81 -0
- package/dist/oclif/commands/swarm/onboard.d.ts +6 -0
- package/dist/oclif/commands/swarm/onboard.js +233 -0
- package/dist/oclif/commands/swarm/query.d.ts +14 -0
- package/dist/oclif/commands/swarm/query.js +84 -0
- package/dist/oclif/commands/swarm/status.d.ts +41 -0
- package/dist/oclif/commands/swarm/status.js +278 -0
- package/dist/server/constants.d.ts +3 -2
- package/dist/server/constants.js +10 -9
- package/dist/server/core/domain/entities/agent.js +4 -0
- package/dist/server/core/domain/source/source-schema.d.ts +6 -6
- package/dist/server/core/domain/transport/schemas.d.ts +4 -4
- package/dist/server/infra/connectors/mcp/claude-desktop-config-path.d.ts +20 -0
- package/dist/server/infra/connectors/mcp/claude-desktop-config-path.js +47 -0
- package/dist/server/infra/connectors/mcp/mcp-connector-config.d.ts +19 -0
- package/dist/server/infra/connectors/mcp/mcp-connector-config.js +9 -0
- package/dist/server/infra/connectors/mcp/mcp-connector.js +12 -3
- package/dist/server/infra/http/provider-model-fetchers.js +1 -0
- package/dist/server/infra/process/feature-handlers.js +13 -0
- package/dist/server/infra/project/project-registry.js +13 -1
- package/dist/server/infra/transport/handlers/locations-handler.d.ts +2 -0
- package/dist/server/infra/transport/handlers/locations-handler.js +16 -1
- package/dist/server/infra/transport/handlers/vc-handler.d.ts +0 -4
- package/dist/server/infra/transport/handlers/vc-handler.js +5 -16
- package/dist/server/templates/skill/SKILL.md +163 -0
- package/dist/server/utils/gitignore.d.ts +1 -0
- package/dist/server/utils/gitignore.js +36 -4
- package/dist/shared/types/agent.d.ts +2 -1
- package/dist/shared/types/agent.js +2 -0
- package/dist/tui/features/connectors/components/connectors-flow.js +7 -2
- package/oclif.manifest.json +503 -323
- package/package.json +2 -2
package/dist/server/constants.js
CHANGED
|
@@ -88,12 +88,13 @@ export const OVERVIEW_EXTENSION = '.overview.md';
|
|
|
88
88
|
export const MANIFEST_FILE = '_manifest.json';
|
|
89
89
|
export const ARCHIVE_IMPORTANCE_THRESHOLD = 35;
|
|
90
90
|
export const DEFAULT_GHOST_CUE_MAX_TOKENS = 220;
|
|
91
|
-
/**
|
|
92
|
-
export const
|
|
93
|
-
.gitignore
|
|
94
|
-
.snapshot.json
|
|
95
|
-
_manifest.json
|
|
96
|
-
_index.md
|
|
97
|
-
*.abstract.md
|
|
98
|
-
*.overview.md
|
|
99
|
-
|
|
91
|
+
/** Patterns the context-tree .gitignore must contain (derived artifacts only). */
|
|
92
|
+
export const CONTEXT_TREE_GITIGNORE_PATTERNS = [
|
|
93
|
+
'.gitignore',
|
|
94
|
+
'.snapshot.json',
|
|
95
|
+
'_manifest.json',
|
|
96
|
+
'_index.md',
|
|
97
|
+
'*.abstract.md',
|
|
98
|
+
'*.overview.md',
|
|
99
|
+
];
|
|
100
|
+
export const CONTEXT_TREE_GITIGNORE_HEADER = '# Derived artifacts — do not track';
|
|
@@ -5,15 +5,15 @@ export declare const SourceSchema: z.ZodObject<{
|
|
|
5
5
|
projectRoot: z.ZodString;
|
|
6
6
|
readOnly: z.ZodLiteral<true>;
|
|
7
7
|
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
readOnly: true;
|
|
8
9
|
addedAt: string;
|
|
9
10
|
alias: string;
|
|
10
11
|
projectRoot: string;
|
|
11
|
-
readOnly: true;
|
|
12
12
|
}, {
|
|
13
|
+
readOnly: true;
|
|
13
14
|
addedAt: string;
|
|
14
15
|
alias: string;
|
|
15
16
|
projectRoot: string;
|
|
16
|
-
readOnly: true;
|
|
17
17
|
}>;
|
|
18
18
|
export declare const SourcesFileSchema: z.ZodObject<{
|
|
19
19
|
sources: z.ZodArray<z.ZodObject<{
|
|
@@ -22,32 +22,32 @@ export declare const SourcesFileSchema: z.ZodObject<{
|
|
|
22
22
|
projectRoot: z.ZodString;
|
|
23
23
|
readOnly: z.ZodLiteral<true>;
|
|
24
24
|
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
readOnly: true;
|
|
25
26
|
addedAt: string;
|
|
26
27
|
alias: string;
|
|
27
28
|
projectRoot: string;
|
|
28
|
-
readOnly: true;
|
|
29
29
|
}, {
|
|
30
|
+
readOnly: true;
|
|
30
31
|
addedAt: string;
|
|
31
32
|
alias: string;
|
|
32
33
|
projectRoot: string;
|
|
33
|
-
readOnly: true;
|
|
34
34
|
}>, "many">;
|
|
35
35
|
version: z.ZodLiteral<1>;
|
|
36
36
|
}, "strip", z.ZodTypeAny, {
|
|
37
37
|
version: 1;
|
|
38
38
|
sources: {
|
|
39
|
+
readOnly: true;
|
|
39
40
|
addedAt: string;
|
|
40
41
|
alias: string;
|
|
41
42
|
projectRoot: string;
|
|
42
|
-
readOnly: true;
|
|
43
43
|
}[];
|
|
44
44
|
}, {
|
|
45
45
|
version: 1;
|
|
46
46
|
sources: {
|
|
47
|
+
readOnly: true;
|
|
47
48
|
addedAt: string;
|
|
48
49
|
alias: string;
|
|
49
50
|
projectRoot: string;
|
|
50
|
-
readOnly: true;
|
|
51
51
|
}[];
|
|
52
52
|
}>;
|
|
53
53
|
export type Source = z.infer<typeof SourceSchema>;
|
|
@@ -755,13 +755,13 @@ export declare const TaskCompletedEventSchema: z.ZodObject<{
|
|
|
755
755
|
}, "strip", z.ZodTypeAny, {
|
|
756
756
|
result: string;
|
|
757
757
|
taskId: string;
|
|
758
|
-
clientId?: string | undefined;
|
|
759
758
|
logId?: string | undefined;
|
|
759
|
+
clientId?: string | undefined;
|
|
760
760
|
}, {
|
|
761
761
|
result: string;
|
|
762
762
|
taskId: string;
|
|
763
|
-
clientId?: string | undefined;
|
|
764
763
|
logId?: string | undefined;
|
|
764
|
+
clientId?: string | undefined;
|
|
765
765
|
}>;
|
|
766
766
|
/**
|
|
767
767
|
* Structured error object
|
|
@@ -815,8 +815,8 @@ export declare const TaskErrorEventSchema: z.ZodObject<{
|
|
|
815
815
|
details?: Record<string, unknown> | undefined;
|
|
816
816
|
};
|
|
817
817
|
taskId: string;
|
|
818
|
-
clientId?: string | undefined;
|
|
819
818
|
logId?: string | undefined;
|
|
819
|
+
clientId?: string | undefined;
|
|
820
820
|
}, {
|
|
821
821
|
error: {
|
|
822
822
|
message: string;
|
|
@@ -825,8 +825,8 @@ export declare const TaskErrorEventSchema: z.ZodObject<{
|
|
|
825
825
|
details?: Record<string, unknown> | undefined;
|
|
826
826
|
};
|
|
827
827
|
taskId: string;
|
|
828
|
-
clientId?: string | undefined;
|
|
829
828
|
logId?: string | undefined;
|
|
829
|
+
clientId?: string | undefined;
|
|
830
830
|
}>;
|
|
831
831
|
/**
|
|
832
832
|
* llmservice:response - LLM text output
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependencies for platform detection, injectable for testing.
|
|
3
|
+
*/
|
|
4
|
+
type PlatformDeps = {
|
|
5
|
+
env: Record<string, string | undefined>;
|
|
6
|
+
existsSync?: (path: string) => boolean;
|
|
7
|
+
homedir: () => string;
|
|
8
|
+
platform: () => NodeJS.Platform;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Returns the absolute path to the Claude Desktop config file,
|
|
12
|
+
* following platform conventions:
|
|
13
|
+
* - macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
|
|
14
|
+
* - Windows: %APPDATA%\Claude\claude_desktop_config.json
|
|
15
|
+
* - Linux: ~/.config/Claude/claude_desktop_config.json
|
|
16
|
+
*
|
|
17
|
+
* @returns Absolute path to the Claude Desktop config file
|
|
18
|
+
*/
|
|
19
|
+
export declare const getClaudeDesktopConfigPath: (deps?: PlatformDeps) => string;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { homedir, platform } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
const CLAUDE_DESKTOP_CONFIG_FILE = 'claude_desktop_config.json';
|
|
5
|
+
const CLAUDE_DESKTOP_DIR = 'Claude';
|
|
6
|
+
// Publisher hash is derived from Anthropic's signing certificate — stable per publisher identity
|
|
7
|
+
const MSIX_PACKAGE_DIR = 'Claude_pzs8sxrjxfjjc';
|
|
8
|
+
const defaultDeps = {
|
|
9
|
+
env: process.env,
|
|
10
|
+
homedir,
|
|
11
|
+
platform,
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Returns the absolute path to the Claude Desktop config file,
|
|
15
|
+
* following platform conventions:
|
|
16
|
+
* - macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
|
|
17
|
+
* - Windows: %APPDATA%\Claude\claude_desktop_config.json
|
|
18
|
+
* - Linux: ~/.config/Claude/claude_desktop_config.json
|
|
19
|
+
*
|
|
20
|
+
* @returns Absolute path to the Claude Desktop config file
|
|
21
|
+
*/
|
|
22
|
+
export const getClaudeDesktopConfigPath = (deps = defaultDeps) => {
|
|
23
|
+
const currentPlatform = deps.platform();
|
|
24
|
+
if (currentPlatform === 'win32') {
|
|
25
|
+
const checkExists = deps.existsSync ?? existsSync;
|
|
26
|
+
const localAppData = deps.env.LOCALAPPDATA ?? join(deps.homedir(), 'AppData', 'Local');
|
|
27
|
+
const msixDir = join(localAppData, 'Packages', MSIX_PACKAGE_DIR, 'LocalCache', 'Roaming', CLAUDE_DESKTOP_DIR);
|
|
28
|
+
// Check directory, not the config file — file may not exist yet on first launch
|
|
29
|
+
if (checkExists(msixDir))
|
|
30
|
+
return join(msixDir, CLAUDE_DESKTOP_CONFIG_FILE);
|
|
31
|
+
const appData = deps.env.APPDATA;
|
|
32
|
+
if (appData !== undefined) {
|
|
33
|
+
return join(appData, CLAUDE_DESKTOP_DIR, CLAUDE_DESKTOP_CONFIG_FILE);
|
|
34
|
+
}
|
|
35
|
+
return join(deps.homedir(), 'AppData', 'Roaming', CLAUDE_DESKTOP_DIR, CLAUDE_DESKTOP_CONFIG_FILE);
|
|
36
|
+
}
|
|
37
|
+
if (currentPlatform === 'darwin') {
|
|
38
|
+
return join(deps.homedir(), 'Library', 'Application Support', CLAUDE_DESKTOP_DIR, CLAUDE_DESKTOP_CONFIG_FILE);
|
|
39
|
+
}
|
|
40
|
+
// Linux and other platforms: respect XDG_CONFIG_HOME if set
|
|
41
|
+
const xdgConfigHome = deps.env.XDG_CONFIG_HOME;
|
|
42
|
+
if (xdgConfigHome !== undefined) {
|
|
43
|
+
return join(xdgConfigHome, CLAUDE_DESKTOP_DIR, CLAUDE_DESKTOP_CONFIG_FILE);
|
|
44
|
+
}
|
|
45
|
+
// Default fallback (Linux and other platforms)
|
|
46
|
+
return join(deps.homedir(), '.config', CLAUDE_DESKTOP_DIR, CLAUDE_DESKTOP_CONFIG_FILE);
|
|
47
|
+
};
|
|
@@ -19,6 +19,12 @@ export type McpConfigMode = 'auto' | 'manual';
|
|
|
19
19
|
type McpConnectorConfigBase = {
|
|
20
20
|
/** Path to the MCP config file (relative to project root). Used when scope is 'project'. */
|
|
21
21
|
configPath?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Function that returns an absolute path to the config file.
|
|
24
|
+
* Takes precedence over configPath when present.
|
|
25
|
+
* Used when the path varies by platform (e.g., Claude Desktop).
|
|
26
|
+
*/
|
|
27
|
+
configPathResolver?: () => string;
|
|
22
28
|
/** Config file format */
|
|
23
29
|
format: McpConfigFormat;
|
|
24
30
|
/** Guide URL or instructions for manual setup. Required when mode is 'manual'. */
|
|
@@ -106,6 +112,19 @@ export declare const MCP_CONNECTOR_CONFIGS: {
|
|
|
106
112
|
};
|
|
107
113
|
readonly serverKeyPath: readonly ["mcpServers", "brv"];
|
|
108
114
|
};
|
|
115
|
+
readonly 'Claude Desktop': {
|
|
116
|
+
readonly configPathResolver: (deps?: {
|
|
117
|
+
env: Record<string, string | undefined>;
|
|
118
|
+
existsSync?: (path: string) => boolean;
|
|
119
|
+
homedir: () => string;
|
|
120
|
+
platform: () => NodeJS.Platform;
|
|
121
|
+
}) => string;
|
|
122
|
+
readonly format: "json";
|
|
123
|
+
readonly mode: "auto";
|
|
124
|
+
readonly scope: "global";
|
|
125
|
+
readonly serverConfig: McpServerConfig;
|
|
126
|
+
readonly serverKeyPath: readonly ["mcpServers", "brv"];
|
|
127
|
+
};
|
|
109
128
|
readonly Cline: {
|
|
110
129
|
readonly format: "json";
|
|
111
130
|
readonly manualGuide: "https://docs.cline.bot/mcp/configuring-mcp-servers#editing-mcp-settings-files";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getClaudeDesktopConfigPath } from './claude-desktop-config-path.js';
|
|
1
2
|
/* eslint-disable perfectionist/sort-objects */
|
|
2
3
|
/** Default MCP server configuration */
|
|
3
4
|
const DEFAULT_SERVER_CONFIG = {
|
|
@@ -60,6 +61,14 @@ export const MCP_CONNECTOR_CONFIGS = {
|
|
|
60
61
|
},
|
|
61
62
|
serverKeyPath: STANDARD_KEY_PATH,
|
|
62
63
|
},
|
|
64
|
+
'Claude Desktop': {
|
|
65
|
+
configPathResolver: getClaudeDesktopConfigPath,
|
|
66
|
+
format: 'json',
|
|
67
|
+
mode: 'auto',
|
|
68
|
+
scope: 'global',
|
|
69
|
+
serverConfig: DEFAULT_SERVER_CONFIG,
|
|
70
|
+
serverKeyPath: STANDARD_KEY_PATH,
|
|
71
|
+
},
|
|
63
72
|
Cline: {
|
|
64
73
|
format: 'json',
|
|
65
74
|
manualGuide: 'https://docs.cline.bot/mcp/configuring-mcp-servers#editing-mcp-settings-files',
|
|
@@ -198,6 +198,9 @@ export class McpConnector {
|
|
|
198
198
|
* - Global scope: relative to os.homedir()
|
|
199
199
|
*/
|
|
200
200
|
getFullConfigPath(config) {
|
|
201
|
+
if (config.configPathResolver) {
|
|
202
|
+
return config.configPathResolver();
|
|
203
|
+
}
|
|
201
204
|
if (!config.configPath) {
|
|
202
205
|
return '';
|
|
203
206
|
}
|
|
@@ -265,7 +268,9 @@ export class McpConnector {
|
|
|
265
268
|
* Install the rule file with MCP-specific content.
|
|
266
269
|
*/
|
|
267
270
|
async installRuleFile(agent) {
|
|
268
|
-
const rulesConfig = agent in RULES_CONNECTOR_CONFIGS
|
|
271
|
+
const rulesConfig = agent in RULES_CONNECTOR_CONFIGS
|
|
272
|
+
? RULES_CONNECTOR_CONFIGS[agent]
|
|
273
|
+
: undefined;
|
|
269
274
|
if (!rulesConfig) {
|
|
270
275
|
return;
|
|
271
276
|
}
|
|
@@ -300,7 +305,9 @@ export class McpConnector {
|
|
|
300
305
|
* Checks for markers AND MCP-specific tool references (brv-query, brv-curate).
|
|
301
306
|
*/
|
|
302
307
|
async statusManual(agent) {
|
|
303
|
-
const rulesConfig = agent in RULES_CONNECTOR_CONFIGS
|
|
308
|
+
const rulesConfig = agent in RULES_CONNECTOR_CONFIGS
|
|
309
|
+
? RULES_CONNECTOR_CONFIGS[agent]
|
|
310
|
+
: undefined;
|
|
304
311
|
if (!rulesConfig) {
|
|
305
312
|
return {
|
|
306
313
|
configExists: false,
|
|
@@ -330,7 +337,9 @@ export class McpConnector {
|
|
|
330
337
|
* Uninstall the rule file content.
|
|
331
338
|
*/
|
|
332
339
|
async uninstallRuleFile(agent) {
|
|
333
|
-
const rulesConfig = agent in RULES_CONNECTOR_CONFIGS
|
|
340
|
+
const rulesConfig = agent in RULES_CONNECTOR_CONFIGS
|
|
341
|
+
? RULES_CONNECTOR_CONFIGS[agent]
|
|
342
|
+
: undefined;
|
|
334
343
|
if (!rulesConfig) {
|
|
335
344
|
return;
|
|
336
345
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Registers all feature handlers (auth, init, status, etc.) on the transport server.
|
|
5
5
|
* These handlers implement the TUI ↔ Server event contract.
|
|
6
6
|
*/
|
|
7
|
+
import { access } from 'node:fs/promises';
|
|
7
8
|
import { join } from 'node:path';
|
|
8
9
|
import { ReviewEvents } from '../../../shared/transport/events/review-events.js';
|
|
9
10
|
import { getAuthConfig } from '../../config/auth.config.js';
|
|
@@ -106,6 +107,18 @@ export async function setupFeatureHandlers({ authStateStore, broadcastToProject,
|
|
|
106
107
|
new LocationsHandler({
|
|
107
108
|
contextTreeService,
|
|
108
109
|
getActiveProjectPaths,
|
|
110
|
+
async pathExists(path) {
|
|
111
|
+
try {
|
|
112
|
+
await access(path);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
},
|
|
109
122
|
projectRegistry,
|
|
110
123
|
resolveProjectPath,
|
|
111
124
|
transport,
|
|
@@ -82,7 +82,19 @@ export class ProjectRegistry {
|
|
|
82
82
|
return info;
|
|
83
83
|
}
|
|
84
84
|
unregister(projectPath) {
|
|
85
|
-
|
|
85
|
+
let resolved;
|
|
86
|
+
try {
|
|
87
|
+
resolved = resolvePath(projectPath);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
// ENOENT — path deleted from disk. Keys are already resolved, so try the raw input.
|
|
91
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
92
|
+
resolved = projectPath;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
86
98
|
if (!this.projects.has(resolved)) {
|
|
87
99
|
return false;
|
|
88
100
|
}
|
|
@@ -5,6 +5,7 @@ import { type ProjectPathResolver } from './handler-types.js';
|
|
|
5
5
|
export interface LocationsHandlerDeps {
|
|
6
6
|
contextTreeService: IContextTreeService;
|
|
7
7
|
getActiveProjectPaths: () => string[];
|
|
8
|
+
pathExists: (path: string) => Promise<boolean>;
|
|
8
9
|
projectRegistry: IProjectRegistry;
|
|
9
10
|
resolveProjectPath: ProjectPathResolver;
|
|
10
11
|
transport: ITransportServer;
|
|
@@ -16,6 +17,7 @@ export interface LocationsHandlerDeps {
|
|
|
16
17
|
export declare class LocationsHandler {
|
|
17
18
|
private readonly contextTreeService;
|
|
18
19
|
private readonly getActiveProjectPaths;
|
|
20
|
+
private readonly pathExists;
|
|
19
21
|
private readonly projectRegistry;
|
|
20
22
|
private readonly resolveProjectPath;
|
|
21
23
|
private readonly transport;
|
|
@@ -9,12 +9,14 @@ import { resolveRequiredProjectPath } from './handler-types.js';
|
|
|
9
9
|
export class LocationsHandler {
|
|
10
10
|
contextTreeService;
|
|
11
11
|
getActiveProjectPaths;
|
|
12
|
+
pathExists;
|
|
12
13
|
projectRegistry;
|
|
13
14
|
resolveProjectPath;
|
|
14
15
|
transport;
|
|
15
16
|
constructor(deps) {
|
|
16
17
|
this.contextTreeService = deps.contextTreeService;
|
|
17
18
|
this.getActiveProjectPaths = deps.getActiveProjectPaths;
|
|
19
|
+
this.pathExists = deps.pathExists;
|
|
18
20
|
this.projectRegistry = deps.projectRegistry;
|
|
19
21
|
this.resolveProjectPath = deps.resolveProjectPath;
|
|
20
22
|
this.transport = deps.transport;
|
|
@@ -35,6 +37,18 @@ export class LocationsHandler {
|
|
|
35
37
|
const all = this.projectRegistry.getAll();
|
|
36
38
|
const activeSet = new Set(this.getActiveProjectPaths());
|
|
37
39
|
const results = await Promise.all([...all.entries()].map(async ([path]) => {
|
|
40
|
+
try {
|
|
41
|
+
const exists = await this.pathExists(path);
|
|
42
|
+
if (!exists) {
|
|
43
|
+
this.projectRegistry.unregister(path);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// pathExists threw unexpectedly — skip this entry but do NOT unregister,
|
|
49
|
+
// since the path may still exist (e.g. a transient permission error).
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
38
52
|
let isInitialized = false;
|
|
39
53
|
try {
|
|
40
54
|
isInitialized = await this.contextTreeService.exists(path);
|
|
@@ -50,8 +64,9 @@ export class LocationsHandler {
|
|
|
50
64
|
projectPath: path,
|
|
51
65
|
};
|
|
52
66
|
}));
|
|
67
|
+
const filtered = results.filter((r) => r !== null);
|
|
53
68
|
// Sort: current first → active (has clients) → initialized → rest, all by registeredAt desc
|
|
54
|
-
return
|
|
69
|
+
return filtered.sort((a, b) => {
|
|
55
70
|
if (a.isCurrent !== b.isCurrent)
|
|
56
71
|
return a.isCurrent ? -1 : 1;
|
|
57
72
|
if (a.isActive !== b.isActive)
|
|
@@ -41,10 +41,6 @@ export declare class VcHandler {
|
|
|
41
41
|
setup(): void;
|
|
42
42
|
private buildAuthorHint;
|
|
43
43
|
private buildNoRemoteMessage;
|
|
44
|
-
/**
|
|
45
|
-
* Writes a .gitignore to the context-tree directory only if one does not already exist.
|
|
46
|
-
*/
|
|
47
|
-
private ensureGitignore;
|
|
48
44
|
/**
|
|
49
45
|
* When force is NOT set, checks for uncommitted changes and throws
|
|
50
46
|
* VcError(UNCOMMITTED_CHANGES) if the working tree is dirty.
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { VcErrorCode, VcEvents, } from '../../../../shared/transport/events/vc-events.js';
|
|
4
|
-
import { CONTEXT_TREE_GITIGNORE } from '../../../constants.js';
|
|
5
4
|
import { BrvConfig } from '../../../core/domain/entities/brv-config.js';
|
|
6
5
|
import { Space } from '../../../core/domain/entities/space.js';
|
|
7
6
|
import { GitAuthError, GitError } from '../../../core/domain/errors/git-error.js';
|
|
8
7
|
import { NotAuthenticatedError } from '../../../core/domain/errors/task-error.js';
|
|
9
8
|
import { VcError } from '../../../core/domain/errors/vc-error.js';
|
|
10
|
-
import { ensureGitignoreEntries } from '../../../utils/gitignore.js';
|
|
9
|
+
import { ensureContextTreeGitignore, ensureGitignoreEntries } from '../../../utils/gitignore.js';
|
|
11
10
|
import { buildCogitRemoteUrl, isValidBranchName, parseUserFacingUrl } from '../../git/cogit-url.js';
|
|
12
11
|
import { resolveRequiredProjectPath } from './handler-types.js';
|
|
13
12
|
/**
|
|
@@ -101,18 +100,6 @@ export class VcHandler {
|
|
|
101
100
|
` 3. Run: brv vc remote add origin <url>\n` +
|
|
102
101
|
` 4. Then: ${nextStep}`);
|
|
103
102
|
}
|
|
104
|
-
/**
|
|
105
|
-
* Writes a .gitignore to the context-tree directory only if one does not already exist.
|
|
106
|
-
*/
|
|
107
|
-
async ensureGitignore(contextTreeDir) {
|
|
108
|
-
const gitignorePath = join(contextTreeDir, '.gitignore');
|
|
109
|
-
try {
|
|
110
|
-
await fs.promises.access(gitignorePath);
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
await fs.promises.writeFile(gitignorePath, CONTEXT_TREE_GITIGNORE, 'utf8');
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
103
|
/**
|
|
117
104
|
* When force is NOT set, checks for uncommitted changes and throws
|
|
118
105
|
* VcError(UNCOMMITTED_CHANGES) if the working tree is dirty.
|
|
@@ -134,6 +121,7 @@ export class VcHandler {
|
|
|
134
121
|
if (!gitInitialized) {
|
|
135
122
|
throw new VcError('ByteRover version control not initialized.', VcErrorCode.GIT_NOT_INITIALIZED);
|
|
136
123
|
}
|
|
124
|
+
await ensureContextTreeGitignore(directory);
|
|
137
125
|
const statusBefore = await this.gitService.status({ directory });
|
|
138
126
|
const stagedBefore = new Set(statusBefore.files.filter((f) => f.staged).map((f) => f.path));
|
|
139
127
|
const hadUnstagedBefore = new Set(statusBefore.files.filter((f) => !f.staged).map((f) => f.path));
|
|
@@ -350,7 +338,7 @@ export class VcHandler {
|
|
|
350
338
|
await this.projectConfigStore.write(updated, projectPath);
|
|
351
339
|
}
|
|
352
340
|
// Ensure .gitignore exists (remote may not have one)
|
|
353
|
-
await
|
|
341
|
+
await ensureContextTreeGitignore(contextTreeDir);
|
|
354
342
|
// Add .brv entries to project .gitignore (prevents `git add .` fatal error from nested .git)
|
|
355
343
|
await ensureGitignoreEntries(projectPath);
|
|
356
344
|
}
|
|
@@ -456,7 +444,7 @@ export class VcHandler {
|
|
|
456
444
|
const reinitialized = await this.gitService.isInitialized({ directory: contextTreeDir });
|
|
457
445
|
await this.gitService.init({ defaultBranch: 'main', directory: contextTreeDir });
|
|
458
446
|
// 3. Ensure .gitignore exists with correct content (idempotent)
|
|
459
|
-
await
|
|
447
|
+
await ensureContextTreeGitignore(contextTreeDir);
|
|
460
448
|
// 4. Add .brv entries to project .gitignore (prevents `git add .` fatal error from nested .git)
|
|
461
449
|
await ensureGitignoreEntries(projectPath);
|
|
462
450
|
return {
|
|
@@ -818,6 +806,7 @@ export class VcHandler {
|
|
|
818
806
|
untracked: [],
|
|
819
807
|
};
|
|
820
808
|
}
|
|
809
|
+
await ensureContextTreeGitignore(contextTreeDir);
|
|
821
810
|
const branch = await this.gitService.getCurrentBranch({ directory: contextTreeDir });
|
|
822
811
|
const gitStatus = await this.gitService.status({ directory: contextTreeDir });
|
|
823
812
|
// Detect empty repo (no commits yet)
|
|
@@ -310,6 +310,169 @@ brv vc push -u origin main # push and set upstream tracking
|
|
|
310
310
|
brv vc clone https://byterover.dev/<team>/<space>.git
|
|
311
311
|
```
|
|
312
312
|
|
|
313
|
+
### 8. Swarm Query
|
|
314
|
+
**Overview:** Search across all active memory providers simultaneously — ByteRover context tree, Obsidian vault, Local Markdown folders, GBrain, and Memory Wiki. Results are fused via Reciprocal Rank Fusion (RRF) and ranked by provider weight and relevance. No LLM call — pure algorithmic search.
|
|
315
|
+
|
|
316
|
+
**Use this skill when:**
|
|
317
|
+
- You need to search across multiple knowledge sources at once
|
|
318
|
+
- The user has configured multiple memory providers (check with `brv swarm status`)
|
|
319
|
+
- You want results from Obsidian notes, GBrain entities, or wiki pages alongside ByteRover context
|
|
320
|
+
|
|
321
|
+
**Do NOT use this skill when:**
|
|
322
|
+
- The user only has ByteRover configured — use `brv query` instead (it synthesizes via LLM)
|
|
323
|
+
- You need an LLM-synthesized answer — `brv swarm query` returns raw search results, not synthesized text
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
brv swarm query "How does JWT refresh work?"
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Output:
|
|
330
|
+
```
|
|
331
|
+
Swarm Query: "How does JWT refresh work?"
|
|
332
|
+
Type: factual | Providers: 4 queried | Latency: 398ms
|
|
333
|
+
──────────────────────────────────────────────────
|
|
334
|
+
1. [memory-wiki] sources/jwt-token-lifecycle.md score: 0.0150 [keyword]
|
|
335
|
+
# JWT Token Lifecycle ...
|
|
336
|
+
2. [obsidian] SwarmTestData/Authentication System.md score: 0.0142 [keyword]
|
|
337
|
+
# Authentication System ...
|
|
338
|
+
3. [gbrain] alex-chen score: 0.0117 [semantic]
|
|
339
|
+
# Alex Chen — Senior Backend Engineer ...
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**With explain mode** (shows classification, provider selection, enrichment):
|
|
343
|
+
```bash
|
|
344
|
+
brv swarm query "authentication patterns" --explain
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Output:
|
|
348
|
+
```
|
|
349
|
+
Classification: factual
|
|
350
|
+
Provider selection: 4 of 4 available
|
|
351
|
+
✓ byterover (healthy, selected, 0 results, 14ms)
|
|
352
|
+
✓ obsidian (healthy, selected, 5 results, 91ms)
|
|
353
|
+
✓ memory-wiki (healthy, selected, 2 results, 15ms)
|
|
354
|
+
✓ gbrain (healthy, selected, 1 results, 260ms)
|
|
355
|
+
Enrichment:
|
|
356
|
+
byterover → obsidian
|
|
357
|
+
byterover → memory-wiki
|
|
358
|
+
Results: 8 raw → 7 after RRF fusion + precision filtering
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**JSON output:**
|
|
362
|
+
```bash
|
|
363
|
+
brv swarm query "rate limiting" --format json
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Output:
|
|
367
|
+
```json
|
|
368
|
+
{
|
|
369
|
+
"meta": {
|
|
370
|
+
"queryType": "factual",
|
|
371
|
+
"totalLatencyMs": 340,
|
|
372
|
+
"providers": {
|
|
373
|
+
"byterover": { "selected": true, "resultCount": 0 },
|
|
374
|
+
"obsidian": { "selected": true, "resultCount": 5 },
|
|
375
|
+
"gbrain": { "selected": true, "resultCount": 1 },
|
|
376
|
+
"memory-wiki": { "selected": true, "resultCount": 1 }
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
"results": [
|
|
380
|
+
{ "provider": "memory-wiki", "providerType": "memory-wiki", "score": 0.015, "content": "# Rate Limiting ..." }
|
|
381
|
+
]
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
**Limit results:**
|
|
386
|
+
```bash
|
|
387
|
+
brv swarm query "testing strategy" -n 5
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
**Flags:** `--explain` (show routing details), `--format json` (structured output), `-n <value>` (max results).
|
|
391
|
+
|
|
392
|
+
### 9. Swarm Curate
|
|
393
|
+
**Overview:** Store knowledge in the best available external memory provider. ByteRover automatically classifies the content type and routes accordingly: entities (people, orgs) go to GBrain, notes (meeting notes, TODOs) go to Local Markdown, general content goes to the first writable provider. Falls back to ByteRover context tree if no external providers are available.
|
|
394
|
+
|
|
395
|
+
**Use this skill when:**
|
|
396
|
+
- You want to store knowledge in an external provider (GBrain, Local Markdown, Memory Wiki)
|
|
397
|
+
- The user has configured writable swarm providers
|
|
398
|
+
|
|
399
|
+
**Do NOT use this skill when:**
|
|
400
|
+
- You want to store in ByteRover's context tree specifically — use `brv curate` instead
|
|
401
|
+
- No swarm providers are configured — use `brv curate` instead
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
brv swarm curate "Jane Smith is the CTO of TechCorp"
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Output:
|
|
408
|
+
```
|
|
409
|
+
Stored to gbrain as concept/jane-smith-cto
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**Target a specific provider:**
|
|
413
|
+
```bash
|
|
414
|
+
brv swarm curate "meeting notes: decided on JWT" --provider local-markdown:notes
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Output:
|
|
418
|
+
```
|
|
419
|
+
Stored to local-markdown:notes as note-1776052527043.md
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
brv swarm curate "Architecture uses event sourcing" --provider gbrain
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
Output:
|
|
427
|
+
```
|
|
428
|
+
Stored to gbrain as concept/event-sourcing-architecture
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
**JSON output:**
|
|
432
|
+
```bash
|
|
433
|
+
brv swarm curate "Test content" --format json
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Output:
|
|
437
|
+
```json
|
|
438
|
+
{
|
|
439
|
+
"id": "note-1776052594462.md",
|
|
440
|
+
"provider": "local-markdown:project-docs",
|
|
441
|
+
"success": true,
|
|
442
|
+
"latencyMs": 1
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**Flags:** `--provider <id>` (target specific provider), `--format json` (structured output).
|
|
447
|
+
|
|
448
|
+
### 10. Swarm Status
|
|
449
|
+
**Overview:** Check provider health and write targets before running swarm query or curate. Use this to verify which providers are available and operational.
|
|
450
|
+
|
|
451
|
+
**Use this skill when:**
|
|
452
|
+
- Before running `brv swarm query` or `brv swarm curate` to check available providers
|
|
453
|
+
- Diagnosing why swarm results are missing from a specific provider
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
brv swarm status
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
Output:
|
|
460
|
+
```
|
|
461
|
+
Memory Swarm Health Check
|
|
462
|
+
════════════════════════════════════════
|
|
463
|
+
✓ ByteRover context-tree (always on)
|
|
464
|
+
✓ Obsidian /Users/you/Documents/MyObsidian
|
|
465
|
+
✓ Local .md 1 folder(s)
|
|
466
|
+
✓ GBrain /Users/you/workspaces/gbrain
|
|
467
|
+
✓ Memory Wiki /Users/you/.openclaw/wiki/main
|
|
468
|
+
|
|
469
|
+
Write Targets:
|
|
470
|
+
gbrain (entity, general)
|
|
471
|
+
local-markdown:project-docs (note, general)
|
|
472
|
+
|
|
473
|
+
Swarm is operational (5/5 providers configured).
|
|
474
|
+
```
|
|
475
|
+
|
|
313
476
|
## Data Handling
|
|
314
477
|
|
|
315
478
|
**Storage**: All knowledge is stored as Markdown files in `.brv/context-tree/` within the project directory. Files are human-readable and version-controllable.
|