@phuetz/code-buddy 1.3.1 → 1.3.2
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 +2 -2
- package/dist/agent/autonomous/agentic-coding-runner.d.ts +2 -2
- package/dist/agent/autonomous/agentic-coding-runner.js +24 -24
- package/dist/agent/autonomous/checkpoint-manager.d.ts +2 -2
- package/dist/agent/base-agent.d.ts +1 -1
- package/dist/agent/base-agent.js +1 -1
- package/dist/agent/hermes-tool-parity-local.js +2 -2
- package/dist/agent/tool-handler.js +2 -2
- package/dist/codebuddy/providers/provider-chatgpt-responses.d.ts +4 -0
- package/dist/codebuddy/providers/provider-chatgpt-responses.js +34 -13
- package/dist/codebuddy/providers/provider-openai-compat.js +8 -0
- package/dist/codebuddy/tool-definitions/code-explorer-tools.d.ts +8 -0
- package/dist/codebuddy/tool-definitions/code-explorer-tools.js +24 -0
- package/dist/codebuddy/tool-definitions/graph-tools.d.ts +1 -1
- package/dist/codebuddy/tool-definitions/graph-tools.js +1 -1
- package/dist/codebuddy/tool-definitions/index.d.ts +1 -1
- package/dist/codebuddy/tool-definitions/index.js +2 -2
- package/dist/codebuddy/tools.d.ts +2 -2
- package/dist/codebuddy/tools.js +13 -13
- package/dist/collaboration/ai-colab-manager.js +9 -4
- package/dist/commands/cli/code-explorer-commands.d.ts +7 -0
- package/dist/commands/cli/code-explorer-commands.js +40 -0
- package/dist/commands/cli/native-engine-commands.js +64 -0
- package/dist/commands/handlers/graph-handlers.d.ts +1 -1
- package/dist/commands/handlers/graph-handlers.js +1 -1
- package/dist/config/model-tools.js +1 -1
- package/dist/daemon/autonomous-loop.d.ts +0 -7
- package/dist/daemon/autonomous-loop.js +24 -14
- package/dist/fleet/capability-registry.js +9 -1
- package/dist/fleet/colab-store.d.ts +109 -3
- package/dist/fleet/colab-store.js +181 -6
- package/dist/index.js +28 -11
- package/dist/kanban/colab-kanban-adapter.d.ts +31 -0
- package/dist/kanban/colab-kanban-adapter.js +232 -0
- package/dist/knowledge/community-detector.d.ts +1 -1
- package/dist/knowledge/community-detector.js +1 -1
- package/dist/knowledge/process-detector.d.ts +1 -1
- package/dist/knowledge/process-detector.js +1 -1
- package/dist/plugins/{gitnexus/GitNexusMCPClient.d.ts → code-explorer/CodeExplorerMCPClient.d.ts} +9 -9
- package/dist/plugins/{gitnexus/GitNexusMCPClient.js → code-explorer/CodeExplorerMCPClient.js} +17 -17
- package/dist/plugins/{gitnexus/GitNexusManager.d.ts → code-explorer/CodeExplorerManager.d.ts} +16 -16
- package/dist/plugins/{gitnexus/GitNexusManager.js → code-explorer/CodeExplorerManager.js} +35 -35
- package/dist/plugins/code-explorer/index.d.ts +9 -0
- package/dist/plugins/code-explorer/index.js +8 -0
- package/dist/providers/provider-catalog.js +23 -1
- package/dist/services/prompt-builder.js +9 -9
- package/dist/skills/parser.js +1 -1
- package/dist/tools/{gitnexus-tool.d.ts → code-explorer-tool.d.ts} +9 -9
- package/dist/tools/{gitnexus-tool.js → code-explorer-tool.js} +16 -16
- package/dist/tools/metadata.js +3 -3
- package/dist/tools/registry/code-explorer-tools.d.ts +18 -0
- package/dist/tools/registry/{gitnexus-tools.js → code-explorer-tools.js} +14 -14
- package/dist/tools/registry/graph-tools.d.ts +1 -1
- package/dist/tools/registry/graph-tools.js +1 -1
- package/dist/tools/registry/index.d.ts +1 -1
- package/dist/tools/registry/index.js +6 -6
- package/dist/tools/registry/kanban-tools.d.ts +1 -1
- package/dist/tools/registry/kanban-tools.js +2 -2
- package/package.json +1 -1
- package/dist/codebuddy/tool-definitions/gitnexus-tools.d.ts +0 -8
- package/dist/codebuddy/tool-definitions/gitnexus-tools.js +0 -24
- package/dist/commands/cli/gitnexus-commands.d.ts +0 -7
- package/dist/commands/cli/gitnexus-commands.js +0 -42
- package/dist/plugins/gitnexus/index.d.ts +0 -9
- package/dist/plugins/gitnexus/index.js +0 -8
- package/dist/tools/registry/gitnexus-tools.d.ts +0 -18
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* CodeExplorer Manager
|
|
3
3
|
*
|
|
4
|
-
* Handles
|
|
5
|
-
*
|
|
4
|
+
* Handles CodeExplorer indexing, stats retrieval, and MCP server lifecycle.
|
|
5
|
+
* CodeExplorer provides code graph analysis (symbols, relations, processes, clusters)
|
|
6
6
|
* and exposes them via an MCP server for agent consumption.
|
|
7
7
|
*
|
|
8
8
|
* Usage:
|
|
9
|
-
* const mgr =
|
|
9
|
+
* const mgr = getCodeExplorerManager('/path/to/repo');
|
|
10
10
|
* if (mgr.isInstalled() && !mgr.isRepoIndexed()) {
|
|
11
11
|
* await mgr.analyze();
|
|
12
12
|
* }
|
|
@@ -26,16 +26,16 @@ const DEFAULT_STATS = {
|
|
|
26
26
|
};
|
|
27
27
|
/** Singleton cache keyed by resolved repo path */
|
|
28
28
|
const instances = new Map();
|
|
29
|
-
export class
|
|
29
|
+
export class CodeExplorerManager {
|
|
30
30
|
repoPath;
|
|
31
31
|
mcpProcess = null;
|
|
32
32
|
constructor(repoPath = process.cwd()) {
|
|
33
33
|
this.repoPath = path.resolve(repoPath);
|
|
34
34
|
}
|
|
35
|
-
/** Check whether the `
|
|
35
|
+
/** Check whether the `code-explorer` CLI is available on PATH. */
|
|
36
36
|
isInstalled() {
|
|
37
37
|
try {
|
|
38
|
-
execSync('
|
|
38
|
+
execSync('code-explorer --version', {
|
|
39
39
|
stdio: 'pipe',
|
|
40
40
|
timeout: 10_000,
|
|
41
41
|
cwd: this.repoPath,
|
|
@@ -46,25 +46,25 @@ export class GitNexusManager {
|
|
|
46
46
|
return false;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
/** Check whether the repo has been indexed (`.
|
|
49
|
+
/** Check whether the repo has been indexed (`.codeexplorer/` directory exists). */
|
|
50
50
|
isRepoIndexed() {
|
|
51
|
-
return fs.existsSync(path.join(this.repoPath, '.
|
|
51
|
+
return fs.existsSync(path.join(this.repoPath, '.codeexplorer'));
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
|
-
* Run `
|
|
54
|
+
* Run `code-explorer analyze` to index the repository.
|
|
55
55
|
*
|
|
56
|
-
* @param options.force - Re-index even if `.
|
|
56
|
+
* @param options.force - Re-index even if `.codeexplorer/` already exists.
|
|
57
57
|
* @param options.withSkills - Also generate skill annotations.
|
|
58
58
|
*/
|
|
59
59
|
async analyze(options = {}) {
|
|
60
|
-
const args = ['
|
|
60
|
+
const args = ['analyze'];
|
|
61
61
|
if (options.force)
|
|
62
62
|
args.push('--force');
|
|
63
63
|
if (options.withSkills)
|
|
64
64
|
args.push('--with-skills');
|
|
65
|
-
logger.info(`
|
|
65
|
+
logger.info(`CodeExplorer: analyzing repo at ${this.repoPath}`, { args });
|
|
66
66
|
return new Promise((resolve, reject) => {
|
|
67
|
-
const child = spawn('
|
|
67
|
+
const child = spawn('code-explorer', args, {
|
|
68
68
|
cwd: this.repoPath,
|
|
69
69
|
stdio: 'pipe',
|
|
70
70
|
shell: true,
|
|
@@ -73,22 +73,22 @@ export class GitNexusManager {
|
|
|
73
73
|
child.stdout?.on('data', (chunk) => {
|
|
74
74
|
const line = chunk.toString().trim();
|
|
75
75
|
if (line)
|
|
76
|
-
logger.debug(`
|
|
76
|
+
logger.debug(`CodeExplorer analyze: ${line}`);
|
|
77
77
|
});
|
|
78
78
|
child.stderr?.on('data', (chunk) => {
|
|
79
79
|
stderr += chunk.toString();
|
|
80
80
|
});
|
|
81
81
|
child.on('error', (err) => {
|
|
82
|
-
logger.error('
|
|
83
|
-
reject(new Error(`
|
|
82
|
+
logger.error('CodeExplorer analyze failed to start', { error: err.message });
|
|
83
|
+
reject(new Error(`CodeExplorer analyze failed to start: ${err.message}`));
|
|
84
84
|
});
|
|
85
85
|
child.on('close', (code) => {
|
|
86
86
|
if (code === 0) {
|
|
87
|
-
logger.info('
|
|
87
|
+
logger.info('CodeExplorer: analysis complete');
|
|
88
88
|
resolve();
|
|
89
89
|
}
|
|
90
90
|
else {
|
|
91
|
-
const msg = `
|
|
91
|
+
const msg = `CodeExplorer analyze exited with code ${code}: ${stderr.trim()}`;
|
|
92
92
|
logger.error(msg);
|
|
93
93
|
reject(new Error(msg));
|
|
94
94
|
}
|
|
@@ -96,11 +96,11 @@ export class GitNexusManager {
|
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
|
-
* Read stats from `.
|
|
99
|
+
* Read stats from `.codeexplorer/meta.json`.
|
|
100
100
|
* Returns defaults if the index does not exist.
|
|
101
101
|
*/
|
|
102
102
|
getStats() {
|
|
103
|
-
const metaPath = path.join(this.repoPath, '.
|
|
103
|
+
const metaPath = path.join(this.repoPath, '.codeexplorer', 'meta.json');
|
|
104
104
|
if (!fs.existsSync(metaPath)) {
|
|
105
105
|
return { ...DEFAULT_STATS };
|
|
106
106
|
}
|
|
@@ -117,43 +117,43 @@ export class GitNexusManager {
|
|
|
117
117
|
};
|
|
118
118
|
}
|
|
119
119
|
catch (err) {
|
|
120
|
-
logger.warn('
|
|
120
|
+
logger.warn('CodeExplorer: failed to read meta.json', {
|
|
121
121
|
error: err instanceof Error ? err.message : String(err),
|
|
122
122
|
});
|
|
123
123
|
return { ...DEFAULT_STATS };
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
/**
|
|
127
|
-
* Start the
|
|
127
|
+
* Start the CodeExplorer MCP server as a child process (stdio transport).
|
|
128
128
|
* Only one server is kept alive per manager instance.
|
|
129
129
|
*/
|
|
130
130
|
async startMCPServer() {
|
|
131
131
|
if (this.mcpProcess) {
|
|
132
|
-
logger.debug('
|
|
132
|
+
logger.debug('CodeExplorer MCP server already running');
|
|
133
133
|
return;
|
|
134
134
|
}
|
|
135
|
-
logger.info('
|
|
136
|
-
this.mcpProcess = spawn('
|
|
135
|
+
logger.info('CodeExplorer: starting MCP server');
|
|
136
|
+
this.mcpProcess = spawn('code-explorer', ['mcp'], {
|
|
137
137
|
cwd: this.repoPath,
|
|
138
138
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
139
139
|
shell: true,
|
|
140
140
|
});
|
|
141
141
|
this.mcpProcess.on('error', (err) => {
|
|
142
|
-
logger.error('
|
|
142
|
+
logger.error('CodeExplorer MCP server error', { error: err.message });
|
|
143
143
|
this.mcpProcess = null;
|
|
144
144
|
});
|
|
145
145
|
this.mcpProcess.on('close', (code) => {
|
|
146
|
-
logger.debug(`
|
|
146
|
+
logger.debug(`CodeExplorer MCP server exited with code ${code}`);
|
|
147
147
|
this.mcpProcess = null;
|
|
148
148
|
});
|
|
149
149
|
// Give the server a moment to start
|
|
150
150
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
151
|
-
logger.info('
|
|
151
|
+
logger.info('CodeExplorer MCP server started');
|
|
152
152
|
}
|
|
153
153
|
/** Stop the MCP server if running. */
|
|
154
154
|
stopMCPServer() {
|
|
155
155
|
if (this.mcpProcess) {
|
|
156
|
-
logger.debug('
|
|
156
|
+
logger.debug('CodeExplorer: stopping MCP server');
|
|
157
157
|
this.mcpProcess.kill();
|
|
158
158
|
this.mcpProcess = null;
|
|
159
159
|
}
|
|
@@ -172,21 +172,21 @@ export class GitNexusManager {
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
175
|
-
* Get or create a singleton
|
|
175
|
+
* Get or create a singleton CodeExplorerManager for the given repo path.
|
|
176
176
|
* Defaults to `process.cwd()` if no path is provided.
|
|
177
177
|
*/
|
|
178
|
-
export function
|
|
178
|
+
export function getCodeExplorerManager(repoPath) {
|
|
179
179
|
const resolved = path.resolve(repoPath || process.cwd());
|
|
180
180
|
let manager = instances.get(resolved);
|
|
181
181
|
if (!manager) {
|
|
182
|
-
manager = new
|
|
182
|
+
manager = new CodeExplorerManager(resolved);
|
|
183
183
|
instances.set(resolved, manager);
|
|
184
184
|
}
|
|
185
185
|
return manager;
|
|
186
186
|
}
|
|
187
187
|
/** Clear the singleton cache (for testing). */
|
|
188
|
-
export function
|
|
188
|
+
export function clearCodeExplorerManagerCache() {
|
|
189
189
|
instances.forEach((mgr) => mgr.dispose());
|
|
190
190
|
instances.clear();
|
|
191
191
|
}
|
|
192
|
-
//# sourceMappingURL=
|
|
192
|
+
//# sourceMappingURL=CodeExplorerManager.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeExplorer Plugin — Barrel Export
|
|
3
|
+
*
|
|
4
|
+
* Code graph analysis via CodeExplorer MCP server integration.
|
|
5
|
+
*/
|
|
6
|
+
export { CodeExplorerManager, getCodeExplorerManager, clearCodeExplorerManagerCache, } from './CodeExplorerManager.js';
|
|
7
|
+
export { CodeExplorerMCPClient } from './CodeExplorerMCPClient.js';
|
|
8
|
+
export type { GNQueryResult, GNContextResult, GNImpactResult, GNCluster, GNProcess, } from './CodeExplorerMCPClient.js';
|
|
9
|
+
export type { CodeExplorerStats } from './CodeExplorerManager.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeExplorer Plugin — Barrel Export
|
|
3
|
+
*
|
|
4
|
+
* Code graph analysis via CodeExplorer MCP server integration.
|
|
5
|
+
*/
|
|
6
|
+
export { CodeExplorerManager, getCodeExplorerManager, clearCodeExplorerManagerCache, } from './CodeExplorerManager.js';
|
|
7
|
+
export { CodeExplorerMCPClient } from './CodeExplorerMCPClient.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -126,7 +126,29 @@ export const RUNTIME_PROVIDER_CATALOG = [
|
|
|
126
126
|
modelEnvKeys: ['MISTRAL_MODEL'],
|
|
127
127
|
defaultBaseURL: 'https://api.mistral.ai/v1',
|
|
128
128
|
defaultModel: 'mistral-large-latest',
|
|
129
|
-
models: [
|
|
129
|
+
models: [
|
|
130
|
+
'mistral-large-latest',
|
|
131
|
+
'mistral-medium-latest',
|
|
132
|
+
'mistral-small-latest',
|
|
133
|
+
'codestral-latest',
|
|
134
|
+
'devstral-latest',
|
|
135
|
+
'magistral-medium-latest',
|
|
136
|
+
'ministral-8b-latest',
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: 'deepseek',
|
|
141
|
+
label: 'DeepSeek',
|
|
142
|
+
authMode: 'api-key',
|
|
143
|
+
apiMode: 'openai-compatible',
|
|
144
|
+
runtimeSupport: 'direct',
|
|
145
|
+
priority: 72,
|
|
146
|
+
apiKeyEnvKeys: ['DEEPSEEK_API_KEY'],
|
|
147
|
+
baseUrlEnvKeys: ['DEEPSEEK_BASE_URL'],
|
|
148
|
+
modelEnvKeys: ['DEEPSEEK_MODEL'],
|
|
149
|
+
defaultBaseURL: 'https://api.deepseek.com/v1',
|
|
150
|
+
defaultModel: 'deepseek-chat',
|
|
151
|
+
models: ['deepseek-chat', 'deepseek-reasoner'],
|
|
130
152
|
},
|
|
131
153
|
{
|
|
132
154
|
id: 'groq',
|
|
@@ -355,7 +355,7 @@ export class PromptBuilder {
|
|
|
355
355
|
}
|
|
356
356
|
catch { /* rules module optional */ }
|
|
357
357
|
}
|
|
358
|
-
// Steer toward Code Explorer (
|
|
358
|
+
// Steer toward Code Explorer (code-explorer) when it is connected. Conditional:
|
|
359
359
|
// when Code Explorer is absent this injects nothing, so the built-in
|
|
360
360
|
// code_graph/codebase_map behaviour is unchanged. Presence is session-
|
|
361
361
|
// stable, so this stays in the cache-stable prefix.
|
|
@@ -364,17 +364,17 @@ export class PromptBuilder {
|
|
|
364
364
|
if (isCodeExplorerAvailable()) {
|
|
365
365
|
systemPrompt +=
|
|
366
366
|
`\n\n<code_explorer_priority>\n` +
|
|
367
|
-
`Code Explorer (
|
|
367
|
+
`Code Explorer (code-explorer) is connected. For ANY question about code relationships — ` +
|
|
368
368
|
`callers/callees, blast radius / impact ("what breaks if I change X"), dead code, cycles, ` +
|
|
369
|
-
`coupling, complexity — PREFER its MCP tools (\`
|
|
370
|
-
`\`
|
|
371
|
-
`over the built-in \`code_graph\` / \`codebase_map\`: the
|
|
369
|
+
`coupling, complexity — PREFER its MCP tools (\`mcp__code-explorer__impact\`, ` +
|
|
370
|
+
`\`mcp__code-explorer__context\`, \`mcp__code-explorer__query\`, \`mcp__code-explorer__find_cycles\`, …) ` +
|
|
371
|
+
`over the built-in \`code_graph\` / \`codebase_map\`: the code-explorer graph is broader and more ` +
|
|
372
372
|
`complete (whole-repo, 14 languages).\n` +
|
|
373
|
-
`Usage: first call \`
|
|
374
|
-
`\`
|
|
375
|
-
`optionally \`direction: "both"\`) and \`repo\` = that path; or \`
|
|
373
|
+
`Usage: first call \`mcp__code-explorer__list_repos\` once to get the repo \`path\`/\`id\`, then call ` +
|
|
374
|
+
`\`mcp__code-explorer__impact\` with the REQUIRED \`target\` = the symbol name (e.g. \`target: "executePlan"\`, ` +
|
|
375
|
+
`optionally \`direction: "both"\`) and \`repo\` = that path; or \`mcp__code-explorer__context\` with \`name\` = ` +
|
|
376
376
|
`the symbol. Always include \`target\`/\`name\` — never call these tools with empty arguments. ` +
|
|
377
|
-
`Use the built-in \`code_graph\`/\`codebase_map\` only as a fallback if a
|
|
377
|
+
`Use the built-in \`code_graph\`/\`codebase_map\` only as a fallback if a code-explorer tool errors.\n` +
|
|
378
378
|
`</code_explorer_priority>`;
|
|
379
379
|
logger.debug('Injected Code Explorer priority directive');
|
|
380
380
|
}
|
package/dist/skills/parser.js
CHANGED
|
@@ -57,7 +57,7 @@ function parseMetadata(yamlContent, sourcePath) {
|
|
|
57
57
|
// Parse allowed-tools (Standard compatibility)
|
|
58
58
|
let allowedTools = parsed['allowed-tools'];
|
|
59
59
|
if (typeof allowedTools === 'string') {
|
|
60
|
-
// Native Engine uses comma separated values like: Bash(
|
|
60
|
+
// Native Engine uses comma separated values like: Bash(code-explorer *), Read, Grep, Glob
|
|
61
61
|
const toolsList = allowedTools.split(',').map(t => t.trim());
|
|
62
62
|
const mappedTools = [];
|
|
63
63
|
for (const t of toolsList) {
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* CodeExplorer Tool Client
|
|
3
3
|
*
|
|
4
|
-
* Consultative, read-only interface to
|
|
4
|
+
* Consultative, read-only interface to CodeExplorer endpoints (/ask, /push-session, /world-model).
|
|
5
5
|
* Degrades gracefully by returning empty contexts/invariants and detailed notes on timeout/offline.
|
|
6
6
|
*/
|
|
7
|
-
export interface
|
|
7
|
+
export interface CodeExplorerConfig {
|
|
8
8
|
endpoint?: string;
|
|
9
9
|
apiKey?: string;
|
|
10
10
|
timeoutMs?: number;
|
|
11
11
|
}
|
|
12
|
-
export interface
|
|
12
|
+
export interface CodeExplorerContext {
|
|
13
13
|
likelyFiles: string[];
|
|
14
14
|
dependentSymbols: string[];
|
|
15
15
|
testsToWatch: string[];
|
|
@@ -19,21 +19,21 @@ export interface WorldModelInvariants {
|
|
|
19
19
|
architecture: string[];
|
|
20
20
|
invariants: string[];
|
|
21
21
|
}
|
|
22
|
-
export declare class
|
|
22
|
+
export declare class CodeExplorerTool {
|
|
23
23
|
private endpoint;
|
|
24
24
|
private apiKey;
|
|
25
25
|
private timeoutMs;
|
|
26
|
-
constructor(config?:
|
|
26
|
+
constructor(config?: CodeExplorerConfig);
|
|
27
27
|
/**
|
|
28
28
|
* Helper to perform HTTP request with timeout and headers.
|
|
29
29
|
*/
|
|
30
30
|
private request;
|
|
31
31
|
/**
|
|
32
|
-
* Lecture seule : interroge
|
|
32
|
+
* Lecture seule : interroge CodeExplorer pour une tâche/texte. Dégrade proprement si indisponible.
|
|
33
33
|
*/
|
|
34
|
-
ask(query: string): Promise<
|
|
34
|
+
ask(query: string): Promise<CodeExplorerContext>;
|
|
35
35
|
/**
|
|
36
|
-
* Pousse le résumé de session vers
|
|
36
|
+
* Pousse le résumé de session vers CodeExplorer (mémoire technique).
|
|
37
37
|
*/
|
|
38
38
|
pushSession(summary: string): Promise<{
|
|
39
39
|
ok: boolean;
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* CodeExplorer Tool Client
|
|
3
3
|
*
|
|
4
|
-
* Consultative, read-only interface to
|
|
4
|
+
* Consultative, read-only interface to CodeExplorer endpoints (/ask, /push-session, /world-model).
|
|
5
5
|
* Degrades gracefully by returning empty contexts/invariants and detailed notes on timeout/offline.
|
|
6
6
|
*/
|
|
7
7
|
import { logger } from '../utils/logger.js';
|
|
8
8
|
import { redactSecrets } from '../security/data-redaction.js';
|
|
9
|
-
export class
|
|
9
|
+
export class CodeExplorerTool {
|
|
10
10
|
endpoint;
|
|
11
11
|
apiKey;
|
|
12
12
|
timeoutMs;
|
|
13
13
|
constructor(config) {
|
|
14
|
-
this.endpoint = config?.endpoint || process.env.
|
|
15
|
-
this.apiKey = config?.apiKey || process.env.
|
|
16
|
-
this.timeoutMs = config?.timeoutMs ?? Number(process.env.
|
|
14
|
+
this.endpoint = config?.endpoint || process.env.CODE_EXPLORER_ENDPOINT || '';
|
|
15
|
+
this.apiKey = config?.apiKey || process.env.CODE_EXPLORER_API_KEY || '';
|
|
16
|
+
this.timeoutMs = config?.timeoutMs ?? Number(process.env.CODE_EXPLORER_TIMEOUT_MS || 5000);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Helper to perform HTTP request with timeout and headers.
|
|
20
20
|
*/
|
|
21
21
|
async request(path, options) {
|
|
22
22
|
if (!this.endpoint) {
|
|
23
|
-
logger.debug(`
|
|
23
|
+
logger.debug(`CodeExplorer: No endpoint configured, skipping request to ${path}`);
|
|
24
24
|
return null;
|
|
25
25
|
}
|
|
26
26
|
const url = `${this.endpoint.replace(/\/$/, '')}${path}`;
|
|
@@ -52,7 +52,7 @@ export class GitNexusTool {
|
|
|
52
52
|
catch (error) {
|
|
53
53
|
const rawMsg = error instanceof Error ? error.message : String(error);
|
|
54
54
|
const msg = redactSecrets(rawMsg);
|
|
55
|
-
logger.warn(`
|
|
55
|
+
logger.warn(`CodeExplorer request to ${path} failed: ${msg}`);
|
|
56
56
|
return null;
|
|
57
57
|
}
|
|
58
58
|
finally {
|
|
@@ -60,17 +60,17 @@ export class GitNexusTool {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
|
-
* Lecture seule : interroge
|
|
63
|
+
* Lecture seule : interroge CodeExplorer pour une tâche/texte. Dégrade proprement si indisponible.
|
|
64
64
|
*/
|
|
65
65
|
async ask(query) {
|
|
66
66
|
const redactedQuery = redactSecrets(query);
|
|
67
|
-
logger.debug(`
|
|
67
|
+
logger.debug(`CodeExplorer.ask called with query: ${redactedQuery}`);
|
|
68
68
|
if (!this.endpoint) {
|
|
69
69
|
return {
|
|
70
70
|
likelyFiles: [],
|
|
71
71
|
dependentSymbols: [],
|
|
72
72
|
testsToWatch: [],
|
|
73
|
-
notes: '
|
|
73
|
+
notes: 'CodeExplorer is not configured (missing endpoint).',
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
76
|
const response = await this.request('/ask', {
|
|
@@ -82,7 +82,7 @@ export class GitNexusTool {
|
|
|
82
82
|
likelyFiles: [],
|
|
83
83
|
dependentSymbols: [],
|
|
84
84
|
testsToWatch: [],
|
|
85
|
-
notes: '
|
|
85
|
+
notes: 'CodeExplorer is offline or returned an error.',
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
return {
|
|
@@ -93,11 +93,11 @@ export class GitNexusTool {
|
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
95
|
/**
|
|
96
|
-
* Pousse le résumé de session vers
|
|
96
|
+
* Pousse le résumé de session vers CodeExplorer (mémoire technique).
|
|
97
97
|
*/
|
|
98
98
|
async pushSession(summary) {
|
|
99
99
|
const redactedSummary = redactSecrets(summary);
|
|
100
|
-
logger.debug(`
|
|
100
|
+
logger.debug(`CodeExplorer.pushSession called: ${redactedSummary}`);
|
|
101
101
|
if (!this.endpoint) {
|
|
102
102
|
return { ok: false };
|
|
103
103
|
}
|
|
@@ -111,7 +111,7 @@ export class GitNexusTool {
|
|
|
111
111
|
* Lecture des invariants du world model.
|
|
112
112
|
*/
|
|
113
113
|
async readWorldModel() {
|
|
114
|
-
logger.debug('
|
|
114
|
+
logger.debug('CodeExplorer.readWorldModel called');
|
|
115
115
|
if (!this.endpoint) {
|
|
116
116
|
return null;
|
|
117
117
|
}
|
|
@@ -121,4 +121,4 @@ export class GitNexusTool {
|
|
|
121
121
|
return response;
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
|
-
//# sourceMappingURL=
|
|
124
|
+
//# sourceMappingURL=code-explorer-tool.js.map
|
package/dist/tools/metadata.js
CHANGED
|
@@ -1232,11 +1232,11 @@ export const TOOL_METADATA = [
|
|
|
1232
1232
|
description: 'Spawn an isolated sandboxed sub-agent session for a delegated task (depth-3 + 10/workflow caps)',
|
|
1233
1233
|
},
|
|
1234
1234
|
{
|
|
1235
|
-
name: '
|
|
1235
|
+
name: 'code_explorer_ask',
|
|
1236
1236
|
category: 'utility',
|
|
1237
|
-
keywords: ['
|
|
1237
|
+
keywords: ['code-explorer', 'ask', 'query', 'understand', 'explain', 'search', 'related files', 'dependents', 'tests'],
|
|
1238
1238
|
priority: 6,
|
|
1239
|
-
description: 'Consult
|
|
1239
|
+
description: 'Consult CodeExplorer for a query or code understanding request (read-only)',
|
|
1240
1240
|
fleetSafe: true,
|
|
1241
1241
|
},
|
|
1242
1242
|
{
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeExplorer Tool Adapter
|
|
3
|
+
*
|
|
4
|
+
* ITool-compliant adapter for the CodeExplorer tool.
|
|
5
|
+
*/
|
|
6
|
+
import type { ToolResult } from '../../types/index.js';
|
|
7
|
+
import type { ITool, ToolSchema, IToolMetadata, IValidationResult } from './types.js';
|
|
8
|
+
export declare class CodeExplorerAskTool implements ITool {
|
|
9
|
+
readonly name = "code_explorer_ask";
|
|
10
|
+
readonly description = "Consult CodeExplorer for a query or code understanding request. Returns related files, dependent symbols, tests to watch, and technical recommendations. This is a read-only tool.";
|
|
11
|
+
execute(input: Record<string, unknown>): Promise<ToolResult>;
|
|
12
|
+
getSchema(): ToolSchema;
|
|
13
|
+
validate(input: unknown): IValidationResult;
|
|
14
|
+
getMetadata(): IToolMetadata;
|
|
15
|
+
isAvailable(): boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function createCodeExplorerTools(): ITool[];
|
|
18
|
+
export declare function resetCodeExplorerInstances(): void;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* CodeExplorer Tool Adapter
|
|
3
3
|
*
|
|
4
|
-
* ITool-compliant adapter for the
|
|
4
|
+
* ITool-compliant adapter for the CodeExplorer tool.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
export class
|
|
8
|
-
name = '
|
|
9
|
-
description = 'Consult
|
|
6
|
+
import { CodeExplorerTool } from '../code-explorer-tool.js';
|
|
7
|
+
export class CodeExplorerAskTool {
|
|
8
|
+
name = 'code_explorer_ask';
|
|
9
|
+
description = 'Consult CodeExplorer for a query or code understanding request. Returns related files, dependent symbols, tests to watch, and technical recommendations. This is a read-only tool.';
|
|
10
10
|
async execute(input) {
|
|
11
11
|
const query = typeof input.query === 'string' ? input.query : '';
|
|
12
12
|
if (!query) {
|
|
@@ -16,8 +16,8 @@ export class GitNexusAskTool {
|
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
try {
|
|
19
|
-
const
|
|
20
|
-
const result = await
|
|
19
|
+
const codeExplorer = new CodeExplorerTool();
|
|
20
|
+
const result = await codeExplorer.ask(query);
|
|
21
21
|
return {
|
|
22
22
|
success: true,
|
|
23
23
|
output: JSON.stringify(result, null, 2),
|
|
@@ -39,7 +39,7 @@ export class GitNexusAskTool {
|
|
|
39
39
|
properties: {
|
|
40
40
|
query: {
|
|
41
41
|
type: 'string',
|
|
42
|
-
description: 'The query or task description to ask
|
|
42
|
+
description: 'The query or task description to ask CodeExplorer about.',
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
45
|
required: ['query'],
|
|
@@ -61,7 +61,7 @@ export class GitNexusAskTool {
|
|
|
61
61
|
name: this.name,
|
|
62
62
|
description: this.description,
|
|
63
63
|
category: 'utility',
|
|
64
|
-
keywords: ['
|
|
64
|
+
keywords: ['code-explorer', 'ask', 'query', 'understand', 'explain', 'search', 'related files', 'dependents', 'tests'],
|
|
65
65
|
priority: 6,
|
|
66
66
|
modifiesFiles: false,
|
|
67
67
|
makesNetworkRequests: true,
|
|
@@ -71,10 +71,10 @@ export class GitNexusAskTool {
|
|
|
71
71
|
return true;
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
export function
|
|
75
|
-
return [new
|
|
74
|
+
export function createCodeExplorerTools() {
|
|
75
|
+
return [new CodeExplorerAskTool()];
|
|
76
76
|
}
|
|
77
|
-
export function
|
|
77
|
+
export function resetCodeExplorerInstances() {
|
|
78
78
|
// Stateless tool — nothing to reset
|
|
79
79
|
}
|
|
80
|
-
//# sourceMappingURL=
|
|
80
|
+
//# sourceMappingURL=code-explorer-tools.js.map
|
|
@@ -57,7 +57,7 @@ export { ResolveConflictsExecuteTool, createMergeConflictTools, resetMergeConfli
|
|
|
57
57
|
export { VulnScannerExecuteTool, createVulnScannerTools, resetVulnScannerInstances, } from './vuln-scanner-tools.js';
|
|
58
58
|
export { AdvisorExecuteTool, createAdvisorTools, resetAdvisorInstances, setAdvisorConfigProvider, resetAdvisorConfigProvider, } from './advisor-tools.js';
|
|
59
59
|
export { PeerDelegateTool, PeerChainTool, ListPeersTool, RoutePeerTool, createFleetTools, resetFleetToolInstances, } from './fleet-tools.js';
|
|
60
|
-
export {
|
|
60
|
+
export { CodeExplorerAskTool, createCodeExplorerTools, resetCodeExplorerInstances, } from './code-explorer-tools.js';
|
|
61
61
|
export { ScreenMemoryTool, createScreenpipeTools, resetScreenpipeInstances, } from './screenpipe-tools.js';
|
|
62
62
|
export { AskUserQuestionExecuteTool, createAskUserQuestionTools, resetAskUserQuestionInstances, } from './ask-user-question-tools.js';
|
|
63
63
|
export { ExitPlanModeExecuteTool, createExitPlanModeTools, resetExitPlanModeInstances, } from './exit-plan-mode-tools.js';
|
|
@@ -99,8 +99,8 @@ export { VulnScannerExecuteTool, createVulnScannerTools, resetVulnScannerInstanc
|
|
|
99
99
|
export { AdvisorExecuteTool, createAdvisorTools, resetAdvisorInstances, setAdvisorConfigProvider, resetAdvisorConfigProvider, } from './advisor-tools.js';
|
|
100
100
|
// Tool Adapters - Fleet (peer_delegate, list_peers, route_peer)
|
|
101
101
|
export { PeerDelegateTool, PeerChainTool, ListPeersTool, RoutePeerTool, createFleetTools, resetFleetToolInstances, } from './fleet-tools.js';
|
|
102
|
-
// Tool Adapters -
|
|
103
|
-
export {
|
|
102
|
+
// Tool Adapters - CodeExplorer
|
|
103
|
+
export { CodeExplorerAskTool, createCodeExplorerTools, resetCodeExplorerInstances, } from './code-explorer-tools.js';
|
|
104
104
|
// Tool Adapters - Screenpipe (screen_memory)
|
|
105
105
|
export { ScreenMemoryTool, createScreenpipeTools, resetScreenpipeInstances, } from './screenpipe-tools.js';
|
|
106
106
|
// Tool Adapters - AskUserQuestion (ask_user_question)
|
|
@@ -172,7 +172,7 @@ export async function createAllToolsAsync() {
|
|
|
172
172
|
const { createFleetTools } = await import('./fleet-tools.js');
|
|
173
173
|
const { createAskUserQuestionTools } = await import('./ask-user-question-tools.js');
|
|
174
174
|
const { createExitPlanModeTools } = await import('./exit-plan-mode-tools.js');
|
|
175
|
-
const {
|
|
175
|
+
const { createCodeExplorerTools } = await import('./code-explorer-tools.js');
|
|
176
176
|
// Await MCP Manager initialization before registering its tools
|
|
177
177
|
const { getMcpManager } = await import('../mcp/mcp-manager.js');
|
|
178
178
|
await getMcpManager().initialize();
|
|
@@ -226,7 +226,7 @@ export async function createAllToolsAsync() {
|
|
|
226
226
|
...createFleetTools(),
|
|
227
227
|
...createAskUserQuestionTools(),
|
|
228
228
|
...createExitPlanModeTools(),
|
|
229
|
-
...
|
|
229
|
+
...createCodeExplorerTools(),
|
|
230
230
|
...createMcpTools(),
|
|
231
231
|
];
|
|
232
232
|
// Register backward-compat canonical-prefix aliases (shell_exec, file_read, etc.)
|
|
@@ -302,7 +302,7 @@ export function registerBuiltinTools(registry) {
|
|
|
302
302
|
...createExitPlanModeTools(),
|
|
303
303
|
...createGuiTools(),
|
|
304
304
|
...createSessionTools(),
|
|
305
|
-
...
|
|
305
|
+
...createCodeExplorerTools(),
|
|
306
306
|
];
|
|
307
307
|
// Append canonical-prefix aliases (shell_exec → bash_run, etc.).
|
|
308
308
|
allTools.push(...createAliasTools(allTools));
|
|
@@ -368,6 +368,6 @@ import { createExitPlanModeTools } from './exit-plan-mode-tools.js';
|
|
|
368
368
|
import { createGuiTools } from './gui-tools.js';
|
|
369
369
|
import { createSessionTools } from './session-tools.js';
|
|
370
370
|
import { createAliasTools } from './tool-aliases.js';
|
|
371
|
-
import {
|
|
371
|
+
import { createCodeExplorerTools } from './code-explorer-tools.js';
|
|
372
372
|
export * from "./windows-tools.js";
|
|
373
373
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { KanbanStoreOptions } from '../../kanban/kanban-store.js';
|
|
2
2
|
import type { ITool } from './types.js';
|
|
3
3
|
export type KanbanToolOptions = KanbanStoreOptions;
|
|
4
4
|
export declare function createKanbanTools(options?: KanbanToolOptions): ITool[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KANBAN_BLOCK_TOOL, KANBAN_COMMENT_TOOL, KANBAN_COMPLETE_TOOL, KANBAN_CREATE_TOOL, KANBAN_HEARTBEAT_TOOL, KANBAN_LINK_TOOL, KANBAN_LIST_TOOL, KANBAN_SHOW_TOOL, KANBAN_UNBLOCK_TOOL, } from '../../codebuddy/tool-definitions/kanban-tools.js';
|
|
2
|
-
import {
|
|
2
|
+
import { ColabKanbanAdapter } from '../../kanban/colab-kanban-adapter.js';
|
|
3
3
|
class KanbanTool {
|
|
4
4
|
definition;
|
|
5
5
|
executor;
|
|
@@ -54,7 +54,7 @@ class KanbanTool {
|
|
|
54
54
|
return true;
|
|
55
55
|
}
|
|
56
56
|
createStore(context) {
|
|
57
|
-
return new
|
|
57
|
+
return new ColabKanbanAdapter({
|
|
58
58
|
...this.options,
|
|
59
59
|
rootDir: this.options.rootDir ?? context?.cwd,
|
|
60
60
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phuetz/code-buddy",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Open-source multi-provider AI coding agent for the terminal, desktop, and HTTP. 15 LLM providers (Grok, Claude, ChatGPT, Gemini, Ollama, LM Studio, …) with ~110 tools, a peer-to-peer fleet, opt-in self-improvement, multi-channel messaging, and a skills system.",
|
|
5
5
|
"author": "Patrice Huetz <patrice.huetz@gmail.com>",
|
|
6
6
|
"repository": {
|