@phuetz/code-buddy 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -3
- package/dist/agent/autonomous/agentic-coding-contract.d.ts +6 -6
- package/dist/agent/base-agent.d.ts +4 -0
- package/dist/agent/base-agent.js +6 -0
- package/dist/agent/facades/infrastructure-facade.d.ts +9 -2
- package/dist/agent/facades/infrastructure-facade.js +15 -6
- package/dist/agent/self-improvement/authored-artifact-gate.d.ts +18 -0
- package/dist/agent/self-improvement/authored-artifact-gate.js +42 -0
- package/dist/agent/self-improvement/authored-tool-runtime.d.ts +27 -0
- package/dist/agent/self-improvement/authored-tool-runtime.js +57 -0
- package/dist/agent/self-improvement/authored-tool-store.d.ts +24 -0
- package/dist/agent/self-improvement/authored-tool-store.js +57 -0
- package/dist/agent/self-improvement/llm-tool-proposer.d.ts +41 -0
- package/dist/agent/self-improvement/llm-tool-proposer.js +136 -0
- package/dist/agent/self-improvement/sandbox-scorer.d.ts +17 -0
- package/dist/agent/self-improvement/sandbox-scorer.js +43 -0
- package/dist/agent/self-improvement/self-knowledge.d.ts +8 -0
- package/dist/agent/self-improvement/self-knowledge.js +24 -0
- package/dist/agent/self-improvement/skill-benchmark.d.ts +9 -0
- package/dist/agent/self-improvement/skill-benchmark.js +22 -0
- package/dist/agent/self-improvement/skill-consolidator.d.ts +71 -0
- package/dist/agent/self-improvement/skill-consolidator.js +137 -0
- package/dist/agent/self-improvement/skill-engine.d.ts +42 -0
- package/dist/agent/self-improvement/skill-engine.js +87 -0
- package/dist/agent/self-improvement/skill-gate.d.ts +19 -0
- package/dist/agent/self-improvement/skill-gate.js +62 -0
- package/dist/agent/self-improvement/skill-mutator.d.ts +74 -0
- package/dist/agent/self-improvement/skill-mutator.js +223 -0
- package/dist/agent/self-improvement/skill-proposer.d.ts +40 -0
- package/dist/agent/self-improvement/skill-proposer.js +82 -0
- package/dist/agent/self-improvement/skill-types.d.ts +41 -0
- package/dist/agent/self-improvement/skill-types.js +13 -0
- package/dist/agent/self-improvement/tool-benchmark.d.ts +10 -0
- package/dist/agent/self-improvement/tool-benchmark.js +37 -0
- package/dist/agent/self-improvement/tool-engine.d.ts +54 -0
- package/dist/agent/self-improvement/tool-engine.js +101 -0
- package/dist/agent/self-improvement/tool-gate.d.ts +20 -0
- package/dist/agent/self-improvement/tool-gate.js +78 -0
- package/dist/agent/self-improvement/tool-proposer.d.ts +31 -0
- package/dist/agent/self-improvement/tool-proposer.js +34 -0
- package/dist/agent/self-improvement/tool-skill-mutator.d.ts +40 -0
- package/dist/agent/self-improvement/tool-skill-mutator.js +79 -0
- package/dist/agent/self-improvement/tool-types.d.ts +48 -0
- package/dist/agent/self-improvement/tool-types.js +9 -0
- package/dist/agent/self-improvement/types.d.ts +3 -1
- package/dist/agent/tool-handler.js +3 -0
- package/dist/codebuddy/providers/provider-chatgpt-responses.js +6 -1
- package/dist/codebuddy/tools.d.ts +7 -0
- package/dist/codebuddy/tools.js +40 -0
- package/dist/commands/cli/improve-command.js +123 -0
- package/dist/commands/enhanced-command-handler.js +1 -1
- package/dist/commands/handlers/missing-handlers.d.ts +1 -1
- package/dist/commands/handlers/missing-handlers.js +26 -3
- package/dist/commands/skills-cli/index.js +123 -0
- package/dist/commands/slash/builtin-commands.js +1 -1
- package/dist/companion/percepts.js +11 -1
- package/dist/context/bootstrap-loader.js +6 -23
- package/dist/context/import-directive-parser.d.ts +4 -0
- package/dist/context/import-directive-parser.js +51 -6
- package/dist/context/instruction-excludes.d.ts +30 -1
- package/dist/context/instruction-excludes.js +71 -1
- package/dist/context/jit-context.d.ts +8 -10
- package/dist/context/jit-context.js +28 -106
- package/dist/context/project-context.d.ts +90 -0
- package/dist/context/project-context.js +295 -0
- package/dist/daemon/autonomous-loop.d.ts +31 -1
- package/dist/daemon/autonomous-loop.js +80 -2
- package/dist/harness/contract.d.ts +28 -28
- package/dist/identity/identity-manager.js +3 -2
- package/dist/index.js +17 -1
- package/dist/mcp/mcp-resources.js +2 -3
- package/dist/sensory/dreaming.d.ts +45 -0
- package/dist/sensory/dreaming.js +114 -0
- package/dist/sensory/heartbeat-scheduler.d.ts +38 -0
- package/dist/sensory/heartbeat-scheduler.js +72 -0
- package/dist/sensory/reactions.d.ts +24 -0
- package/dist/sensory/reactions.js +31 -0
- package/dist/sensory/screen-reaction.d.ts +23 -0
- package/dist/sensory/screen-reaction.js +59 -0
- package/dist/sensory/sensory-bridge.d.ts +23 -0
- package/dist/sensory/sensory-bridge.js +85 -0
- package/dist/sensory/sensory-memory.d.ts +20 -0
- package/dist/sensory/sensory-memory.js +39 -0
- package/dist/sensory/speech-reaction.d.ts +21 -0
- package/dist/sensory/speech-reaction.js +83 -0
- package/dist/sensory/vision-reaction.d.ts +31 -0
- package/dist/sensory/vision-reaction.js +74 -0
- package/dist/server/index.js +89 -0
- package/dist/services/prompt-builder.d.ts +10 -0
- package/dist/services/prompt-builder.js +75 -9
- package/dist/skills/parser.js +3 -0
- package/dist/skills/skill-importer.d.ts +58 -0
- package/dist/skills/skill-importer.js +261 -0
- package/dist/skills/skill-sources.d.ts +20 -0
- package/dist/skills/skill-sources.js +102 -0
- package/dist/skills/types.d.ts +6 -0
- package/dist/tools/register-tool-handler.d.ts +25 -0
- package/dist/tools/register-tool-handler.js +100 -0
- package/dist/tools/registry.d.ts +6 -0
- package/dist/tools/registry.js +8 -0
- package/dist/utils/init-project.d.ts +7 -0
- package/dist/utils/init-project.js +37 -0
- package/dist/utils/settings-manager.d.ts +12 -0
- package/package.json +1 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill sources — a small "referential" of named places skills can be imported
|
|
3
|
+
* from. A source is a local directory or a git repo. Persisted to
|
|
4
|
+
* `~/.codebuddy/skill-sources.json`. The importer resolves a source to a local
|
|
5
|
+
* directory (cloning/pulling a git source into a cache) and then runs the same
|
|
6
|
+
* firewall-gated import path.
|
|
7
|
+
*
|
|
8
|
+
* @module skills/skill-sources
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import os from 'os';
|
|
13
|
+
import { execFileSync } from 'child_process';
|
|
14
|
+
import { logger } from '../utils/logger.js';
|
|
15
|
+
function configPath() {
|
|
16
|
+
return path.join(os.homedir(), '.codebuddy', 'skill-sources.json');
|
|
17
|
+
}
|
|
18
|
+
function cacheRoot() {
|
|
19
|
+
return path.join(os.homedir(), '.codebuddy', 'skills', '.sources-cache');
|
|
20
|
+
}
|
|
21
|
+
/** Best-effort: locate the OpenClaw skills dir (it lives inside the npm global package). */
|
|
22
|
+
function findOpenclawSkillsDir() {
|
|
23
|
+
const candidates = [path.join(os.homedir(), '.openclaw', 'skills')];
|
|
24
|
+
const nvmRoot = path.join(os.homedir(), '.nvm', 'versions', 'node');
|
|
25
|
+
try {
|
|
26
|
+
for (const v of fs.readdirSync(nvmRoot)) {
|
|
27
|
+
candidates.push(path.join(nvmRoot, v, 'lib', 'node_modules', 'openclaw', 'skills'));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
/* no nvm */
|
|
32
|
+
}
|
|
33
|
+
candidates.push('/usr/local/lib/node_modules/openclaw/skills', '/usr/lib/node_modules/openclaw/skills');
|
|
34
|
+
return candidates.find((c) => fs.existsSync(c));
|
|
35
|
+
}
|
|
36
|
+
function read() {
|
|
37
|
+
try {
|
|
38
|
+
const parsed = JSON.parse(fs.readFileSync(configPath(), 'utf-8'));
|
|
39
|
+
if (Array.isArray(parsed.sources))
|
|
40
|
+
return { schemaVersion: 1, sources: parsed.sources };
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
/* no config yet */
|
|
44
|
+
}
|
|
45
|
+
// Seed known local skill repos as default `dir` sources when present.
|
|
46
|
+
const seed = [];
|
|
47
|
+
const hermes = path.join(os.homedir(), '.hermes', 'skills');
|
|
48
|
+
if (fs.existsSync(hermes))
|
|
49
|
+
seed.push({ name: 'hermes', type: 'dir', location: hermes });
|
|
50
|
+
const openclaw = findOpenclawSkillsDir();
|
|
51
|
+
if (openclaw)
|
|
52
|
+
seed.push({ name: 'openclaw', type: 'dir', location: openclaw });
|
|
53
|
+
return { schemaVersion: 1, sources: seed };
|
|
54
|
+
}
|
|
55
|
+
function write(file) {
|
|
56
|
+
fs.mkdirSync(path.dirname(configPath()), { recursive: true });
|
|
57
|
+
fs.writeFileSync(configPath(), JSON.stringify(file, null, 2), 'utf-8');
|
|
58
|
+
}
|
|
59
|
+
export function listSources() {
|
|
60
|
+
return read().sources;
|
|
61
|
+
}
|
|
62
|
+
export function getSource(name) {
|
|
63
|
+
return read().sources.find((s) => s.name === name);
|
|
64
|
+
}
|
|
65
|
+
export function addSource(name, location, type = location.endsWith('.git') || location.includes('://') ? 'git' : 'dir') {
|
|
66
|
+
const file = read();
|
|
67
|
+
const source = { name, type, location };
|
|
68
|
+
file.sources = file.sources.filter((s) => s.name !== name);
|
|
69
|
+
file.sources.push(source);
|
|
70
|
+
write(file);
|
|
71
|
+
return source;
|
|
72
|
+
}
|
|
73
|
+
export function removeSource(name) {
|
|
74
|
+
const file = read();
|
|
75
|
+
const before = file.sources.length;
|
|
76
|
+
file.sources = file.sources.filter((s) => s.name !== name);
|
|
77
|
+
if (file.sources.length === before)
|
|
78
|
+
return false;
|
|
79
|
+
write(file);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
/** Resolve a source to a local directory (clone/pull a git source into the cache). */
|
|
83
|
+
export function resolveSourceDir(source) {
|
|
84
|
+
if (source.type === 'dir')
|
|
85
|
+
return source.location;
|
|
86
|
+
// git: shallow clone or pull into the cache.
|
|
87
|
+
const dir = path.join(cacheRoot(), source.name);
|
|
88
|
+
fs.mkdirSync(cacheRoot(), { recursive: true });
|
|
89
|
+
try {
|
|
90
|
+
if (fs.existsSync(path.join(dir, '.git'))) {
|
|
91
|
+
execFileSync('git', ['-C', dir, 'pull', '--ff-only', '--depth', '1'], { stdio: 'ignore' });
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
execFileSync('git', ['clone', '--depth', '1', source.location, dir], { stdio: 'ignore' });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
logger.warn(`skill source "${source.name}": git fetch failed — ${err instanceof Error ? err.message : String(err)}`);
|
|
99
|
+
}
|
|
100
|
+
return dir;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=skill-sources.js.map
|
package/dist/skills/types.d.ts
CHANGED
|
@@ -28,6 +28,12 @@ export interface SkillMetadata {
|
|
|
28
28
|
contextFork?: boolean;
|
|
29
29
|
/** CC11: If true, skill content is returned directly without LLM invocation */
|
|
30
30
|
disableModelInvocation?: boolean;
|
|
31
|
+
/** Self-improvement: if true, curation won't overwrite/remove/consolidate this skill */
|
|
32
|
+
pinned?: boolean;
|
|
33
|
+
/** Provenance: this skill was imported from an external source. */
|
|
34
|
+
imported?: boolean;
|
|
35
|
+
/** Provenance: label of the source it was imported from (e.g. "hermes"). */
|
|
36
|
+
source?: string;
|
|
31
37
|
}
|
|
32
38
|
export interface SkillRequirements {
|
|
33
39
|
/** Required tools */
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* register_tool — lets Code Buddy author a NEW tool for itself at runtime.
|
|
3
|
+
*
|
|
4
|
+
* This is the "the code it builds can call its own tools" capability. On a
|
|
5
|
+
* passing static safety scan it writes BOTH tool registries (via LiveToolMutator):
|
|
6
|
+
* - FormalToolRegistry → the authored tool is immediately CALLABLE (dispatch),
|
|
7
|
+
* - legacy ToolRegistry → its schema becomes VISIBLE to the model next turn.
|
|
8
|
+
*
|
|
9
|
+
* Authored tools are namespaced `authored__<name>` and run SANDBOXED. Gated
|
|
10
|
+
* overall by `CODEBUDDY_SELF_IMPROVE=true` at the registration site (tools.ts).
|
|
11
|
+
*
|
|
12
|
+
* The static scan here is the same G1 used by the self-improvement engine
|
|
13
|
+
* (authored-artifact-gate). The fuller behavioural held-out gate (which proves a
|
|
14
|
+
* tool actually works on fresh inputs) is applied by the engine's tool-gate when
|
|
15
|
+
* a tool is proposed as a self-improvement against a benchmark scenario.
|
|
16
|
+
*/
|
|
17
|
+
import type { ITool, ToolSchema } from './registry/types.js';
|
|
18
|
+
import type { ToolResult } from '../types/index.js';
|
|
19
|
+
export declare class RegisterToolTool implements ITool {
|
|
20
|
+
readonly name = "register_tool";
|
|
21
|
+
readonly description: string;
|
|
22
|
+
execute(input: Record<string, unknown>): Promise<ToolResult>;
|
|
23
|
+
getSchema(): ToolSchema;
|
|
24
|
+
}
|
|
25
|
+
export declare function createRegisterToolTool(): RegisterToolTool;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* register_tool — lets Code Buddy author a NEW tool for itself at runtime.
|
|
3
|
+
*
|
|
4
|
+
* This is the "the code it builds can call its own tools" capability. On a
|
|
5
|
+
* passing static safety scan it writes BOTH tool registries (via LiveToolMutator):
|
|
6
|
+
* - FormalToolRegistry → the authored tool is immediately CALLABLE (dispatch),
|
|
7
|
+
* - legacy ToolRegistry → its schema becomes VISIBLE to the model next turn.
|
|
8
|
+
*
|
|
9
|
+
* Authored tools are namespaced `authored__<name>` and run SANDBOXED. Gated
|
|
10
|
+
* overall by `CODEBUDDY_SELF_IMPROVE=true` at the registration site (tools.ts).
|
|
11
|
+
*
|
|
12
|
+
* The static scan here is the same G1 used by the self-improvement engine
|
|
13
|
+
* (authored-artifact-gate). The fuller behavioural held-out gate (which proves a
|
|
14
|
+
* tool actually works on fresh inputs) is applied by the engine's tool-gate when
|
|
15
|
+
* a tool is proposed as a self-improvement against a benchmark scenario.
|
|
16
|
+
*/
|
|
17
|
+
import { AUTHORED_LANGUAGES, toAuthoredName, } from '../agent/self-improvement/authored-tool-runtime.js';
|
|
18
|
+
import { inspectAuthoredCode } from '../agent/self-improvement/authored-artifact-gate.js';
|
|
19
|
+
import { LiveToolMutator } from '../agent/self-improvement/tool-skill-mutator.js';
|
|
20
|
+
import { logger } from '../utils/logger.js';
|
|
21
|
+
export class RegisterToolTool {
|
|
22
|
+
name = 'register_tool';
|
|
23
|
+
description = 'Author a NEW tool for yourself at runtime. Provide a name, description, JSON-schema params, ' +
|
|
24
|
+
'a language (javascript|typescript|python) and the code. The code reads its call arguments as ' +
|
|
25
|
+
'JSON from the CODEBUDDY_TOOL_INPUT env var and prints its result to stdout. On a passing safety ' +
|
|
26
|
+
'check the tool is registered as `authored__<name>` and becomes callable by you on your next turn.';
|
|
27
|
+
async execute(input) {
|
|
28
|
+
const rawName = String(input.name ?? '').trim();
|
|
29
|
+
const description = String(input.description ?? '').trim();
|
|
30
|
+
const language = String(input.language ?? 'javascript').toLowerCase();
|
|
31
|
+
const code = typeof input.code === 'string' ? input.code : '';
|
|
32
|
+
const parameters = input.params && typeof input.params === 'object'
|
|
33
|
+
? input.params
|
|
34
|
+
: { type: 'object', properties: {} };
|
|
35
|
+
if (!rawName)
|
|
36
|
+
return { success: false, error: 'register_tool: `name` is required.' };
|
|
37
|
+
if (!description)
|
|
38
|
+
return { success: false, error: 'register_tool: `description` is required.' };
|
|
39
|
+
if (!code.trim())
|
|
40
|
+
return { success: false, error: 'register_tool: `code` is required.' };
|
|
41
|
+
if (!AUTHORED_LANGUAGES.includes(language)) {
|
|
42
|
+
return { success: false, error: `register_tool: language must be one of ${AUTHORED_LANGUAGES.join(', ')}.` };
|
|
43
|
+
}
|
|
44
|
+
// Static safety scan (engine G1): dangerous patterns, secrets, no-src/-write, omissions.
|
|
45
|
+
const scan = inspectAuthoredCode(code, 'code');
|
|
46
|
+
if (!scan.ok) {
|
|
47
|
+
return { success: false, error: `register_tool: refused — ${scan.reasons.join('; ')}.` };
|
|
48
|
+
}
|
|
49
|
+
const spec = {
|
|
50
|
+
name: toAuthoredName(rawName),
|
|
51
|
+
description,
|
|
52
|
+
parameters,
|
|
53
|
+
language,
|
|
54
|
+
code,
|
|
55
|
+
};
|
|
56
|
+
try {
|
|
57
|
+
new LiveToolMutator().register(spec);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
return {
|
|
61
|
+
success: false,
|
|
62
|
+
error: `register_tool: registration failed — ${err instanceof Error ? err.message : String(err)}`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
logger.info(`[self-improve] authored tool registered: ${spec.name}`);
|
|
66
|
+
return {
|
|
67
|
+
success: true,
|
|
68
|
+
output: `Registered tool \`${spec.name}\`. It is now callable by you on your next turn — ` +
|
|
69
|
+
`call it with arguments matching its params.`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
getSchema() {
|
|
73
|
+
return {
|
|
74
|
+
name: this.name,
|
|
75
|
+
description: this.description,
|
|
76
|
+
parameters: {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {
|
|
79
|
+
name: { type: 'string', description: 'Tool name (namespaced to authored__<name>)' },
|
|
80
|
+
description: { type: 'string', description: 'What the tool does and when to use it' },
|
|
81
|
+
params: { type: 'object', description: 'JSON Schema for the tool arguments' },
|
|
82
|
+
language: {
|
|
83
|
+
type: 'string',
|
|
84
|
+
enum: ['javascript', 'typescript', 'python'],
|
|
85
|
+
description: 'Implementation language (default javascript)',
|
|
86
|
+
},
|
|
87
|
+
code: {
|
|
88
|
+
type: 'string',
|
|
89
|
+
description: 'Code that reads its args as JSON from env CODEBUDDY_TOOL_INPUT and prints its result to stdout',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
required: ['name', 'description', 'code'],
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export function createRegisterToolTool() {
|
|
98
|
+
return new RegisterToolTool();
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=register-tool-handler.js.map
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -67,6 +67,12 @@ export declare class ToolRegistry {
|
|
|
67
67
|
* @returns The registered tool object or undefined if not found
|
|
68
68
|
*/
|
|
69
69
|
getTool(name: string): RegisteredTool | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Remove a registered tool by name (used to revert self-authored tools).
|
|
72
|
+
*
|
|
73
|
+
* @returns true if a tool was removed, false if it was not registered
|
|
74
|
+
*/
|
|
75
|
+
removeTool(name: string): boolean;
|
|
70
76
|
/**
|
|
71
77
|
* Check if a tool is registered and currently enabled.
|
|
72
78
|
*
|
package/dist/tools/registry.js
CHANGED
|
@@ -87,6 +87,14 @@ export class ToolRegistry {
|
|
|
87
87
|
getTool(name) {
|
|
88
88
|
return this.tools.get(name);
|
|
89
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Remove a registered tool by name (used to revert self-authored tools).
|
|
92
|
+
*
|
|
93
|
+
* @returns true if a tool was removed, false if it was not registered
|
|
94
|
+
*/
|
|
95
|
+
removeTool(name) {
|
|
96
|
+
return this.tools.delete(name);
|
|
97
|
+
}
|
|
90
98
|
/**
|
|
91
99
|
* Check if a tool is registered and currently enabled.
|
|
92
100
|
*
|
|
@@ -81,4 +81,11 @@ export declare function initCodeBuddyProject(workingDirectory?: string, options?
|
|
|
81
81
|
* Format init result for display (ASCII markers, no emojis)
|
|
82
82
|
*/
|
|
83
83
|
export declare function formatInitResult(result: InitResult): string;
|
|
84
|
+
/**
|
|
85
|
+
* Build the prompt for the agent-driven `/init`. Instructs the model to analyze
|
|
86
|
+
* the repository and write/improve a tailored root `AGENTS.md`, grounded on the
|
|
87
|
+
* RepoProfiler's verified facts so it cannot hallucinate build/test commands.
|
|
88
|
+
* Modeled on Codex's `prompt_for_init_command.md`.
|
|
89
|
+
*/
|
|
90
|
+
export declare function buildInitPrompt(contextPack: string): string;
|
|
84
91
|
export {};
|
|
@@ -495,6 +495,13 @@ ${archLines.join('\n')}
|
|
|
495
495
|
## More Context
|
|
496
496
|
${moreLines.join('\n')}
|
|
497
497
|
|
|
498
|
+
<sub>**How instruction files load:** Code Buddy reads from \`~/.codebuddy/\` (global), the
|
|
499
|
+
project root, and subdirectories — the file closest to what you're editing wins.
|
|
500
|
+
Accepted names compose in order: **AGENTS.md** (this file, primary), then \`CODEBUDDY.md\`,
|
|
501
|
+
\`CLAUDE.md\`, \`GEMINI.md\`, \`CONTEXT.md\`, \`INSTRUCTIONS.md\`. Drop \`@./path.md\` to import
|
|
502
|
+
another file. Override a file in the same directory with \`AGENTS.override.md\` (committed)
|
|
503
|
+
or \`AGENTS.local.md\` (gitignored).</sub>
|
|
504
|
+
|
|
498
505
|
---
|
|
499
506
|
*Auto-generated by \`buddy init\`. Re-run with \`--force\` to refresh, or edit by hand — \`buddy init\` won't overwrite without explicit force.*
|
|
500
507
|
`;
|
|
@@ -772,6 +779,8 @@ Safety checks:
|
|
|
772
779
|
.codebuddy/tool-results/
|
|
773
780
|
.codebuddy/cache/
|
|
774
781
|
.codebuddy/user-settings.json
|
|
782
|
+
# Personal, uncommitted instruction overrides (AGENTS.local.md, CODEBUDDY.local.md, …)
|
|
783
|
+
*.local.md
|
|
775
784
|
`;
|
|
776
785
|
if (fs.existsSync(gitignorePath)) {
|
|
777
786
|
const currentContent = fs.readFileSync(gitignorePath, 'utf-8');
|
|
@@ -897,6 +906,34 @@ export function formatInitResult(result) {
|
|
|
897
906
|
output += ' 5. Use /starter to browse framework starter packs for new projects\n';
|
|
898
907
|
return output;
|
|
899
908
|
}
|
|
909
|
+
/**
|
|
910
|
+
* Build the prompt for the agent-driven `/init`. Instructs the model to analyze
|
|
911
|
+
* the repository and write/improve a tailored root `AGENTS.md`, grounded on the
|
|
912
|
+
* RepoProfiler's verified facts so it cannot hallucinate build/test commands.
|
|
913
|
+
* Modeled on Codex's `prompt_for_init_command.md`.
|
|
914
|
+
*/
|
|
915
|
+
export function buildInitPrompt(contextPack) {
|
|
916
|
+
const facts = contextPack && contextPack.trim()
|
|
917
|
+
? `\nVERIFIED FACTS about this repository (auto-detected — use these, do not invent commands):\n${contextPack.trim()}\n`
|
|
918
|
+
: '';
|
|
919
|
+
return `Analyze THIS repository and write a tailored \`AGENTS.md\` at the project root — a concise contributor/agent guide (the cross-CLI standard read by Claude Code, Cursor, Codex, Gemini CLI and Code Buddy).
|
|
920
|
+
${facts}
|
|
921
|
+
How to do it:
|
|
922
|
+
1. Explore the real code first — use \`list_directory\`, \`view_file\`, \`search\` (and \`code_graph\` if available) to understand the actual structure, entry points, scripts and conventions. Read \`package.json\` / \`pyproject.toml\` / \`Cargo.toml\`, the README, and a few representative source files.
|
|
923
|
+
2. Trust any auto-detected facts shown above for build/test/lint commands, languages and directories — do NOT invent commands. Confirm anything else by reading the config files.
|
|
924
|
+
3. Write a clear, concise document (aim for 200–400 words, Markdown headings), adapting or omitting sections as appropriate:
|
|
925
|
+
- **Project Structure & Module Organization** — where source, tests and assets live.
|
|
926
|
+
- **Build, Test & Dev Commands** — the real commands, each briefly explained.
|
|
927
|
+
- **Coding Style & Naming Conventions** — indentation, language style, naming, lint/format tools.
|
|
928
|
+
- **Testing Guidelines** — framework, how to run, naming.
|
|
929
|
+
- **Commit & Pull Request Guidelines** — infer conventions from the git history.
|
|
930
|
+
- *(optional)* **Architecture Overview** — for non-obvious design.
|
|
931
|
+
|
|
932
|
+
Important:
|
|
933
|
+
- Write ONLY \`AGENTS.md\` at the project root. Do NOT modify anything under \`.codebuddy/\` — that config was just scaffolded deterministically.
|
|
934
|
+
- If \`AGENTS.md\` already has meaningful content, IMPROVE it in place: preserve the user's good wording, refine and fill gaps; never blank-overwrite.
|
|
935
|
+
- Keep it specific to THIS repository and actionable. No filler.`;
|
|
936
|
+
}
|
|
900
937
|
// ============================================================================
|
|
901
938
|
// Data flow renderer — shows how key components connect
|
|
902
939
|
// ============================================================================
|
|
@@ -27,6 +27,18 @@ export interface ProjectSettings {
|
|
|
27
27
|
judgeMaxTokens?: number;
|
|
28
28
|
judgeTimeoutMs?: number;
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Project-instruction context-file loading (the AGENTS.md/CLAUDE.md/GEMINI.md
|
|
32
|
+
* hierarchy). All fields optional; omitted keys fall back to defaults in
|
|
33
|
+
* `src/context/instruction-excludes.ts` (`loadContextConfig`).
|
|
34
|
+
*/
|
|
35
|
+
context?: {
|
|
36
|
+
fileNames?: string[];
|
|
37
|
+
maxBytes?: number;
|
|
38
|
+
jitMaxBytes?: number;
|
|
39
|
+
importMaxBytes?: number;
|
|
40
|
+
importMaxDepth?: number;
|
|
41
|
+
};
|
|
30
42
|
}
|
|
31
43
|
/**
|
|
32
44
|
* Unified settings manager that handles both user-level and project-level settings
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phuetz/code-buddy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Open-source multi-provider AI coding agent for the terminal. Supports Grok, Claude, ChatGPT, Gemini, Ollama and LM Studio with 52+ tools, multi-channel messaging, skills system, and Enterprise-grade architecture.",
|
|
5
5
|
"author": "Patrice Huetz <patrice.huetz@gmail.com>",
|
|
6
6
|
"repository": {
|