@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
|
@@ -23,6 +23,45 @@
|
|
|
23
23
|
import { chooseAutonomousModel, } from '../agent/model-tier.js';
|
|
24
24
|
import { beginFleetWork, isFleetSaturated } from '../fleet/fleet-load.js';
|
|
25
25
|
import { DEFAULT_COLAB_GOAL_MAX_TURNS } from './colab-goal.js';
|
|
26
|
+
/**
|
|
27
|
+
* Default idle self-improvement: author tools for any seed scenario NOT yet in the
|
|
28
|
+
* evolutionary archive (so it stops once the seed benchmark is covered, and the
|
|
29
|
+
* bound persists across restarts). Auto-apply; gated by the caller on idle +
|
|
30
|
+
* CODEBUDDY_SELF_IMPROVE + cooldown.
|
|
31
|
+
*/
|
|
32
|
+
async function defaultSelfImproveHook() {
|
|
33
|
+
const { EvolutionaryArchive } = await import('../agent/self-improvement/evolutionary-archive.js');
|
|
34
|
+
const archived = new Set(new EvolutionaryArchive().list().map((e) => e.targetScenarioId));
|
|
35
|
+
// Tools first.
|
|
36
|
+
const { ToolImprovementEngine } = await import('../agent/self-improvement/tool-engine.js');
|
|
37
|
+
const { LlmToolProposer } = await import('../agent/self-improvement/llm-tool-proposer.js');
|
|
38
|
+
const { SEED_TOOL_SCENARIOS } = await import('../agent/self-improvement/tool-benchmark.js');
|
|
39
|
+
const uncoveredTools = SEED_TOOL_SCENARIOS.filter((s) => !archived.has(s.id));
|
|
40
|
+
if (uncoveredTools.length > 0) {
|
|
41
|
+
const r = await new ToolImprovementEngine({
|
|
42
|
+
scenarios: uncoveredTools,
|
|
43
|
+
proposer: new LlmToolProposer(),
|
|
44
|
+
autonomy: 'auto-apply',
|
|
45
|
+
}).runCycle();
|
|
46
|
+
if (r.applied)
|
|
47
|
+
return { applied: true, detail: `authored tool ${r.gate?.appliedRef}` };
|
|
48
|
+
}
|
|
49
|
+
// Then skills.
|
|
50
|
+
const { SkillImprovementEngine } = await import('../agent/self-improvement/skill-engine.js');
|
|
51
|
+
const { LlmSkillProposer } = await import('../agent/self-improvement/skill-proposer.js');
|
|
52
|
+
const { SEED_SKILL_SCENARIOS } = await import('../agent/self-improvement/skill-benchmark.js');
|
|
53
|
+
const uncoveredSkills = SEED_SKILL_SCENARIOS.filter((s) => !archived.has(s.id));
|
|
54
|
+
if (uncoveredSkills.length > 0) {
|
|
55
|
+
const r = await new SkillImprovementEngine({
|
|
56
|
+
scenarios: uncoveredSkills,
|
|
57
|
+
proposer: new LlmSkillProposer(),
|
|
58
|
+
autonomy: 'auto-apply',
|
|
59
|
+
}).runCycle();
|
|
60
|
+
if (r.applied)
|
|
61
|
+
return { applied: true, detail: `authored skill ${r.gate?.appliedRef}` };
|
|
62
|
+
}
|
|
63
|
+
return { applied: false, detail: 'all seed tool + skill scenarios already covered (or no proposal)' };
|
|
64
|
+
}
|
|
26
65
|
function resolveGoalMaxTurns(raw) {
|
|
27
66
|
return typeof raw === 'number' && Number.isSafeInteger(raw) && raw > 0
|
|
28
67
|
? raw
|
|
@@ -45,6 +84,10 @@ export class FleetAutonomousLoop {
|
|
|
45
84
|
*/
|
|
46
85
|
failures = new Map();
|
|
47
86
|
goalJudge;
|
|
87
|
+
selfImprove;
|
|
88
|
+
selfImproveCooldownMs;
|
|
89
|
+
now;
|
|
90
|
+
lastSelfImproveAt = Number.NEGATIVE_INFINITY;
|
|
48
91
|
constructor(config) {
|
|
49
92
|
this.store = config.store;
|
|
50
93
|
this.tierConfig = config.tierConfig;
|
|
@@ -52,6 +95,40 @@ export class FleetAutonomousLoop {
|
|
|
52
95
|
this.policy = config.policy ?? {};
|
|
53
96
|
this.enabled = config.enabled ?? (() => true);
|
|
54
97
|
this.goalJudge = config.goalJudge;
|
|
98
|
+
this.selfImprove = config.selfImprove ?? defaultSelfImproveHook;
|
|
99
|
+
this.selfImproveCooldownMs = config.selfImproveCooldownMs ?? 15 * 60 * 1000;
|
|
100
|
+
this.now = config.now ?? (() => Date.now());
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Idle hook: when the queue is empty and self-improvement is opted in, run one
|
|
104
|
+
* bounded, cooldown-gated improvement cycle instead of sitting fully idle.
|
|
105
|
+
* Double-gated (idle + CODEBUDDY_SELF_IMPROVE) and bounded (cooldown + the
|
|
106
|
+
* engine no-ops once seed scenarios are covered). Never throws.
|
|
107
|
+
*/
|
|
108
|
+
async maybeSelfImprove() {
|
|
109
|
+
if (process.env.CODEBUDDY_SELF_IMPROVE !== 'true') {
|
|
110
|
+
this.store.updatePresence({ status: 'idle', currentTask: null });
|
|
111
|
+
return { outcome: 'idle' };
|
|
112
|
+
}
|
|
113
|
+
const now = this.now();
|
|
114
|
+
if (now - this.lastSelfImproveAt < this.selfImproveCooldownMs) {
|
|
115
|
+
this.store.updatePresence({ status: 'idle', currentTask: null });
|
|
116
|
+
return { outcome: 'idle', detail: 'self-improve on cooldown' };
|
|
117
|
+
}
|
|
118
|
+
this.lastSelfImproveAt = now;
|
|
119
|
+
this.store.updatePresence({ status: 'active', currentTask: 'self-improvement' });
|
|
120
|
+
const doneLoad = beginFleetWork('autonomy.task');
|
|
121
|
+
try {
|
|
122
|
+
const r = await this.selfImprove();
|
|
123
|
+
return { outcome: r.applied ? 'self_improved' : 'idle', detail: r.detail };
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
return { outcome: 'idle', detail: `self-improve error: ${err instanceof Error ? err.message : String(err)}` };
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
doneLoad();
|
|
130
|
+
this.store.updatePresence({ status: 'idle', currentTask: null });
|
|
131
|
+
}
|
|
55
132
|
}
|
|
56
133
|
/** Run a single autonomous tick. Never throws — failures are logged + reported. */
|
|
57
134
|
async tick() {
|
|
@@ -71,8 +148,9 @@ export class FleetAutonomousLoop {
|
|
|
71
148
|
this.store.updatePresence({ status: 'active' });
|
|
72
149
|
const next = this.store.nextClaimable();
|
|
73
150
|
if (!next) {
|
|
74
|
-
|
|
75
|
-
|
|
151
|
+
// No real work — use the idle moment for one bounded self-improvement
|
|
152
|
+
// cycle (opt-in + cooldown), otherwise sit idle.
|
|
153
|
+
return this.maybeSelfImprove();
|
|
76
154
|
}
|
|
77
155
|
// Claim. If another agent won the race between read and claim, treat it as
|
|
78
156
|
// idle for this tick rather than crashing.
|
|
@@ -139,6 +139,7 @@ export declare const runSchema: z.ZodObject<{
|
|
|
139
139
|
}, "strict", z.ZodTypeAny, {
|
|
140
140
|
status: "cancelled" | "running" | "completed" | "failed" | "queued" | "waiting_approval";
|
|
141
141
|
id: string;
|
|
142
|
+
schemaVersion: 1;
|
|
142
143
|
objective: string;
|
|
143
144
|
kind: "run";
|
|
144
145
|
actor: {
|
|
@@ -146,7 +147,6 @@ export declare const runSchema: z.ZodObject<{
|
|
|
146
147
|
id: string;
|
|
147
148
|
provider?: string | undefined;
|
|
148
149
|
};
|
|
149
|
-
schemaVersion: 1;
|
|
150
150
|
startedAt: number;
|
|
151
151
|
metadata?: {
|
|
152
152
|
tags: string[];
|
|
@@ -169,6 +169,7 @@ export declare const runSchema: z.ZodObject<{
|
|
|
169
169
|
}, {
|
|
170
170
|
status: "cancelled" | "running" | "completed" | "failed" | "queued" | "waiting_approval";
|
|
171
171
|
id: string;
|
|
172
|
+
schemaVersion: 1;
|
|
172
173
|
objective: string;
|
|
173
174
|
kind: "run";
|
|
174
175
|
actor: {
|
|
@@ -176,7 +177,6 @@ export declare const runSchema: z.ZodObject<{
|
|
|
176
177
|
id: string;
|
|
177
178
|
provider?: string | undefined;
|
|
178
179
|
};
|
|
179
|
-
schemaVersion: 1;
|
|
180
180
|
startedAt: number;
|
|
181
181
|
metadata?: {
|
|
182
182
|
sessionId?: string | undefined;
|
|
@@ -245,8 +245,8 @@ export declare const proofSchema: z.ZodObject<{
|
|
|
245
245
|
id: string;
|
|
246
246
|
summary: string;
|
|
247
247
|
createdAt: number;
|
|
248
|
-
kind: "proof";
|
|
249
248
|
schemaVersion: 1;
|
|
249
|
+
kind: "proof";
|
|
250
250
|
runId: string;
|
|
251
251
|
producedBy: {
|
|
252
252
|
type: "agent" | "human";
|
|
@@ -259,8 +259,8 @@ export declare const proofSchema: z.ZodObject<{
|
|
|
259
259
|
id: string;
|
|
260
260
|
summary: string;
|
|
261
261
|
createdAt: number;
|
|
262
|
-
kind: "proof";
|
|
263
262
|
schemaVersion: 1;
|
|
263
|
+
kind: "proof";
|
|
264
264
|
runId: string;
|
|
265
265
|
producedBy: {
|
|
266
266
|
type: "agent" | "human";
|
|
@@ -283,17 +283,17 @@ export declare const sensitiveActionSchema: z.ZodObject<{
|
|
|
283
283
|
name: string;
|
|
284
284
|
id: string;
|
|
285
285
|
scope: string[];
|
|
286
|
+
schemaVersion: 1;
|
|
286
287
|
kind: "sensitive-action";
|
|
287
288
|
requires: "autonomous" | "dry-run-required" | "approval-required";
|
|
288
|
-
schemaVersion: 1;
|
|
289
289
|
riskLevel: "low" | "medium" | "high";
|
|
290
290
|
defaultDryRun: boolean;
|
|
291
291
|
}, {
|
|
292
292
|
name: string;
|
|
293
293
|
id: string;
|
|
294
|
+
schemaVersion: 1;
|
|
294
295
|
kind: "sensitive-action";
|
|
295
296
|
requires: "autonomous" | "dry-run-required" | "approval-required";
|
|
296
|
-
schemaVersion: 1;
|
|
297
297
|
riskLevel: "low" | "medium" | "high";
|
|
298
298
|
scope?: string[] | undefined;
|
|
299
299
|
defaultDryRun?: boolean | undefined;
|
|
@@ -364,6 +364,7 @@ export declare const workflowSchema: z.ZodObject<{
|
|
|
364
364
|
id: string;
|
|
365
365
|
version: number;
|
|
366
366
|
summary: string;
|
|
367
|
+
schemaVersion: 1;
|
|
367
368
|
kind: "workflow";
|
|
368
369
|
nodes: {
|
|
369
370
|
id: string;
|
|
@@ -371,7 +372,6 @@ export declare const workflowSchema: z.ZodObject<{
|
|
|
371
372
|
canvasKind: "action" | "trigger" | "logic";
|
|
372
373
|
role?: "edit" | "analysis" | "handoff" | "approval" | "verification" | "gate" | undefined;
|
|
373
374
|
}[];
|
|
374
|
-
schemaVersion: 1;
|
|
375
375
|
edges: {
|
|
376
376
|
source: string;
|
|
377
377
|
target: string;
|
|
@@ -381,6 +381,7 @@ export declare const workflowSchema: z.ZodObject<{
|
|
|
381
381
|
id: string;
|
|
382
382
|
version: number;
|
|
383
383
|
summary: string;
|
|
384
|
+
schemaVersion: 1;
|
|
384
385
|
kind: "workflow";
|
|
385
386
|
nodes: {
|
|
386
387
|
id: string;
|
|
@@ -388,7 +389,6 @@ export declare const workflowSchema: z.ZodObject<{
|
|
|
388
389
|
canvasKind: "action" | "trigger" | "logic";
|
|
389
390
|
role?: "edit" | "analysis" | "handoff" | "approval" | "verification" | "gate" | undefined;
|
|
390
391
|
}[];
|
|
391
|
-
schemaVersion: 1;
|
|
392
392
|
edges?: {
|
|
393
393
|
source: string;
|
|
394
394
|
target: string;
|
|
@@ -413,8 +413,8 @@ export declare const approvalSchema: z.ZodObject<{
|
|
|
413
413
|
id: string;
|
|
414
414
|
target: string;
|
|
415
415
|
decision: "rejected" | "approved";
|
|
416
|
-
kind: "approval";
|
|
417
416
|
schemaVersion: 1;
|
|
417
|
+
kind: "approval";
|
|
418
418
|
reviewer: string;
|
|
419
419
|
decidedAt: number;
|
|
420
420
|
scope?: string | undefined;
|
|
@@ -425,8 +425,8 @@ export declare const approvalSchema: z.ZodObject<{
|
|
|
425
425
|
id: string;
|
|
426
426
|
target: string;
|
|
427
427
|
decision: "rejected" | "approved";
|
|
428
|
-
kind: "approval";
|
|
429
428
|
schemaVersion: 1;
|
|
429
|
+
kind: "approval";
|
|
430
430
|
reviewer: string;
|
|
431
431
|
decidedAt: number;
|
|
432
432
|
scope?: string | undefined;
|
|
@@ -453,17 +453,17 @@ export declare const lessonSchema: z.ZodObject<{
|
|
|
453
453
|
tags: string[];
|
|
454
454
|
createdAt: number;
|
|
455
455
|
policy: "none" | "lessons" | "handoff";
|
|
456
|
+
schemaVersion: 1;
|
|
456
457
|
kind: "lesson";
|
|
457
458
|
tier: "technical" | "experience";
|
|
458
|
-
schemaVersion: 1;
|
|
459
459
|
sourceRunId: string;
|
|
460
460
|
}, {
|
|
461
461
|
content: string;
|
|
462
462
|
id: string;
|
|
463
463
|
createdAt: number;
|
|
464
|
+
schemaVersion: 1;
|
|
464
465
|
kind: "lesson";
|
|
465
466
|
tier: "technical" | "experience";
|
|
466
|
-
schemaVersion: 1;
|
|
467
467
|
sourceRunId: string;
|
|
468
468
|
tags?: string[] | undefined;
|
|
469
469
|
policy?: "none" | "lessons" | "handoff" | undefined;
|
|
@@ -483,8 +483,8 @@ export declare const capabilitySchema: z.ZodObject<{
|
|
|
483
483
|
level: "read" | "sensitive" | "reversible-write";
|
|
484
484
|
id: string;
|
|
485
485
|
policy: "autonomous" | "dry-run-required" | "approval-required";
|
|
486
|
-
kind: "capability";
|
|
487
486
|
schemaVersion: 1;
|
|
487
|
+
kind: "capability";
|
|
488
488
|
fleetPolicy: "none" | "read-only-help" | "delegated-slices";
|
|
489
489
|
description?: string | undefined;
|
|
490
490
|
}, {
|
|
@@ -492,8 +492,8 @@ export declare const capabilitySchema: z.ZodObject<{
|
|
|
492
492
|
level: "read" | "sensitive" | "reversible-write";
|
|
493
493
|
id: string;
|
|
494
494
|
policy: "autonomous" | "dry-run-required" | "approval-required";
|
|
495
|
-
kind: "capability";
|
|
496
495
|
schemaVersion: 1;
|
|
496
|
+
kind: "capability";
|
|
497
497
|
description?: string | undefined;
|
|
498
498
|
fleetPolicy?: "none" | "read-only-help" | "delegated-slices" | undefined;
|
|
499
499
|
}>;
|
|
@@ -567,6 +567,7 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
567
567
|
}, "strict", z.ZodTypeAny, {
|
|
568
568
|
status: "cancelled" | "running" | "completed" | "failed" | "queued" | "waiting_approval";
|
|
569
569
|
id: string;
|
|
570
|
+
schemaVersion: 1;
|
|
570
571
|
objective: string;
|
|
571
572
|
kind: "run";
|
|
572
573
|
actor: {
|
|
@@ -574,7 +575,6 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
574
575
|
id: string;
|
|
575
576
|
provider?: string | undefined;
|
|
576
577
|
};
|
|
577
|
-
schemaVersion: 1;
|
|
578
578
|
startedAt: number;
|
|
579
579
|
metadata?: {
|
|
580
580
|
tags: string[];
|
|
@@ -597,6 +597,7 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
597
597
|
}, {
|
|
598
598
|
status: "cancelled" | "running" | "completed" | "failed" | "queued" | "waiting_approval";
|
|
599
599
|
id: string;
|
|
600
|
+
schemaVersion: 1;
|
|
600
601
|
objective: string;
|
|
601
602
|
kind: "run";
|
|
602
603
|
actor: {
|
|
@@ -604,7 +605,6 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
604
605
|
id: string;
|
|
605
606
|
provider?: string | undefined;
|
|
606
607
|
};
|
|
607
|
-
schemaVersion: 1;
|
|
608
608
|
startedAt: number;
|
|
609
609
|
metadata?: {
|
|
610
610
|
sessionId?: string | undefined;
|
|
@@ -651,8 +651,8 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
651
651
|
id: string;
|
|
652
652
|
summary: string;
|
|
653
653
|
createdAt: number;
|
|
654
|
-
kind: "proof";
|
|
655
654
|
schemaVersion: 1;
|
|
655
|
+
kind: "proof";
|
|
656
656
|
runId: string;
|
|
657
657
|
producedBy: {
|
|
658
658
|
type: "agent" | "human";
|
|
@@ -665,8 +665,8 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
665
665
|
id: string;
|
|
666
666
|
summary: string;
|
|
667
667
|
createdAt: number;
|
|
668
|
-
kind: "proof";
|
|
669
668
|
schemaVersion: 1;
|
|
669
|
+
kind: "proof";
|
|
670
670
|
runId: string;
|
|
671
671
|
producedBy: {
|
|
672
672
|
type: "agent" | "human";
|
|
@@ -687,17 +687,17 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
687
687
|
name: string;
|
|
688
688
|
id: string;
|
|
689
689
|
scope: string[];
|
|
690
|
+
schemaVersion: 1;
|
|
690
691
|
kind: "sensitive-action";
|
|
691
692
|
requires: "autonomous" | "dry-run-required" | "approval-required";
|
|
692
|
-
schemaVersion: 1;
|
|
693
693
|
riskLevel: "low" | "medium" | "high";
|
|
694
694
|
defaultDryRun: boolean;
|
|
695
695
|
}, {
|
|
696
696
|
name: string;
|
|
697
697
|
id: string;
|
|
698
|
+
schemaVersion: 1;
|
|
698
699
|
kind: "sensitive-action";
|
|
699
700
|
requires: "autonomous" | "dry-run-required" | "approval-required";
|
|
700
|
-
schemaVersion: 1;
|
|
701
701
|
riskLevel: "low" | "medium" | "high";
|
|
702
702
|
scope?: string[] | undefined;
|
|
703
703
|
defaultDryRun?: boolean | undefined;
|
|
@@ -738,6 +738,7 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
738
738
|
id: string;
|
|
739
739
|
version: number;
|
|
740
740
|
summary: string;
|
|
741
|
+
schemaVersion: 1;
|
|
741
742
|
kind: "workflow";
|
|
742
743
|
nodes: {
|
|
743
744
|
id: string;
|
|
@@ -745,7 +746,6 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
745
746
|
canvasKind: "action" | "trigger" | "logic";
|
|
746
747
|
role?: "edit" | "analysis" | "handoff" | "approval" | "verification" | "gate" | undefined;
|
|
747
748
|
}[];
|
|
748
|
-
schemaVersion: 1;
|
|
749
749
|
edges: {
|
|
750
750
|
source: string;
|
|
751
751
|
target: string;
|
|
@@ -755,6 +755,7 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
755
755
|
id: string;
|
|
756
756
|
version: number;
|
|
757
757
|
summary: string;
|
|
758
|
+
schemaVersion: 1;
|
|
758
759
|
kind: "workflow";
|
|
759
760
|
nodes: {
|
|
760
761
|
id: string;
|
|
@@ -762,7 +763,6 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
762
763
|
canvasKind: "action" | "trigger" | "logic";
|
|
763
764
|
role?: "edit" | "analysis" | "handoff" | "approval" | "verification" | "gate" | undefined;
|
|
764
765
|
}[];
|
|
765
|
-
schemaVersion: 1;
|
|
766
766
|
edges?: {
|
|
767
767
|
source: string;
|
|
768
768
|
target: string;
|
|
@@ -785,8 +785,8 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
785
785
|
id: string;
|
|
786
786
|
target: string;
|
|
787
787
|
decision: "rejected" | "approved";
|
|
788
|
-
kind: "approval";
|
|
789
788
|
schemaVersion: 1;
|
|
789
|
+
kind: "approval";
|
|
790
790
|
reviewer: string;
|
|
791
791
|
decidedAt: number;
|
|
792
792
|
scope?: string | undefined;
|
|
@@ -797,8 +797,8 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
797
797
|
id: string;
|
|
798
798
|
target: string;
|
|
799
799
|
decision: "rejected" | "approved";
|
|
800
|
-
kind: "approval";
|
|
801
800
|
schemaVersion: 1;
|
|
801
|
+
kind: "approval";
|
|
802
802
|
reviewer: string;
|
|
803
803
|
decidedAt: number;
|
|
804
804
|
scope?: string | undefined;
|
|
@@ -820,17 +820,17 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
820
820
|
tags: string[];
|
|
821
821
|
createdAt: number;
|
|
822
822
|
policy: "none" | "lessons" | "handoff";
|
|
823
|
+
schemaVersion: 1;
|
|
823
824
|
kind: "lesson";
|
|
824
825
|
tier: "technical" | "experience";
|
|
825
|
-
schemaVersion: 1;
|
|
826
826
|
sourceRunId: string;
|
|
827
827
|
}, {
|
|
828
828
|
content: string;
|
|
829
829
|
id: string;
|
|
830
830
|
createdAt: number;
|
|
831
|
+
schemaVersion: 1;
|
|
831
832
|
kind: "lesson";
|
|
832
833
|
tier: "technical" | "experience";
|
|
833
|
-
schemaVersion: 1;
|
|
834
834
|
sourceRunId: string;
|
|
835
835
|
tags?: string[] | undefined;
|
|
836
836
|
policy?: "none" | "lessons" | "handoff" | undefined;
|
|
@@ -848,8 +848,8 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
848
848
|
level: "read" | "sensitive" | "reversible-write";
|
|
849
849
|
id: string;
|
|
850
850
|
policy: "autonomous" | "dry-run-required" | "approval-required";
|
|
851
|
-
kind: "capability";
|
|
852
851
|
schemaVersion: 1;
|
|
852
|
+
kind: "capability";
|
|
853
853
|
fleetPolicy: "none" | "read-only-help" | "delegated-slices";
|
|
854
854
|
description?: string | undefined;
|
|
855
855
|
}, {
|
|
@@ -857,8 +857,8 @@ export declare const harnessArtifactSchema: z.ZodDiscriminatedUnion<"kind", [z.Z
|
|
|
857
857
|
level: "read" | "sensitive" | "reversible-write";
|
|
858
858
|
id: string;
|
|
859
859
|
policy: "autonomous" | "dry-run-required" | "approval-required";
|
|
860
|
-
kind: "capability";
|
|
861
860
|
schemaVersion: 1;
|
|
861
|
+
kind: "capability";
|
|
862
862
|
description?: string | undefined;
|
|
863
863
|
fleetPolicy?: "none" | "read-only-help" | "delegated-slices" | undefined;
|
|
864
864
|
}>]>;
|
|
@@ -16,13 +16,14 @@ import { logger } from '../utils/logger.js';
|
|
|
16
16
|
// ============================================================================
|
|
17
17
|
// Defaults
|
|
18
18
|
// ============================================================================
|
|
19
|
+
// AGENTS.md and INSTRUCTIONS.md are intentionally NOT here — they are owned by
|
|
20
|
+
// the unified project-context loader (src/context/project-context.ts). Identity
|
|
21
|
+
// covers only the soul/identity tier.
|
|
19
22
|
const DEFAULT_IDENTITY_FILES = [
|
|
20
23
|
'SOUL.md',
|
|
21
24
|
'USER.md',
|
|
22
|
-
'AGENTS.md',
|
|
23
25
|
'TOOLS.md',
|
|
24
26
|
'IDENTITY.md',
|
|
25
|
-
'INSTRUCTIONS.md',
|
|
26
27
|
'BOOT.md',
|
|
27
28
|
'BOOTSTRAP.md',
|
|
28
29
|
'HEARTBEAT.md',
|
package/dist/index.js
CHANGED
|
@@ -825,7 +825,11 @@ async function applyCustomAgentToolFilter(agentConfig) {
|
|
|
825
825
|
async function processPromptHeadless(prompt, apiKey, baseURL, model, maxToolRounds, selfHealEnabled = true, outputFormat = 'json', outputSchemaPath, agentName) {
|
|
826
826
|
const previousDisableMCP = process.env.CODEBUDDY_DISABLE_MCP;
|
|
827
827
|
const previousHeadless = process.env.CODEBUDDY_HEADLESS;
|
|
828
|
-
|
|
828
|
+
// Headless defaults MCP OFF (startup cost / determinism), but respect an
|
|
829
|
+
// explicit opt-in so `CODEBUDDY_DISABLE_MCP=false buddy -p …` can use MCP
|
|
830
|
+
// servers (e.g. the Code Explorer / gitnexus bridge, or the benchmark's
|
|
831
|
+
// "with graph" condition). Mirrors the opt-in pattern in goal-cli.ts.
|
|
832
|
+
process.env.CODEBUDDY_DISABLE_MCP = process.env.CODEBUDDY_DISABLE_MCP ?? 'true';
|
|
829
833
|
process.env.CODEBUDDY_HEADLESS = 'true';
|
|
830
834
|
try {
|
|
831
835
|
const customAgentConfig = await loadCustomAgentForCli(agentName, false);
|
|
@@ -834,6 +838,18 @@ async function processPromptHeadless(prompt, apiKey, baseURL, model, maxToolRoun
|
|
|
834
838
|
const agent = new CodeBuddyAgent(apiKey, baseURL, modelToUse, maxToolRounds);
|
|
835
839
|
await applyActiveLlmFailover(agent);
|
|
836
840
|
await agent.systemPromptReady;
|
|
841
|
+
// When MCP is opted in for this headless run, wait for the servers to finish
|
|
842
|
+
// connecting so their tools (e.g. the Code Explorer / gitnexus bridge) are
|
|
843
|
+
// registered before the first turn — otherwise the one-shot turn races init
|
|
844
|
+
// and the agent never sees the MCP tools.
|
|
845
|
+
if (process.env.CODEBUDDY_DISABLE_MCP !== 'true') {
|
|
846
|
+
try {
|
|
847
|
+
await agent.getMCPReady();
|
|
848
|
+
}
|
|
849
|
+
catch (e) {
|
|
850
|
+
logger.debug('MCP readiness wait failed (continuing without MCP tools)', { error: String(e) });
|
|
851
|
+
}
|
|
852
|
+
}
|
|
837
853
|
if (customAgentConfig?.systemPrompt) {
|
|
838
854
|
agent.setSystemPrompt(customAgentConfig.systemPrompt);
|
|
839
855
|
}
|
|
@@ -17,9 +17,8 @@ export function registerResources(server) {
|
|
|
17
17
|
mimeType: 'text/markdown',
|
|
18
18
|
}, async () => {
|
|
19
19
|
try {
|
|
20
|
-
const {
|
|
21
|
-
|
|
22
|
-
let text = formatContextForPrompt(context);
|
|
20
|
+
const { resolveProjectContext } = await import('../context/project-context.js');
|
|
21
|
+
let text = resolveProjectContext({ cwd: process.cwd() }).text;
|
|
23
22
|
// Append git status
|
|
24
23
|
try {
|
|
25
24
|
const { execSync } = await import('child_process');
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dreaming — heartbeat-paced memory consolidation. Every N beats, the short-term
|
|
3
|
+
* sensory buffer is drained and consolidated into a compact "dream" summary
|
|
4
|
+
* (counts by kind, salient events, time window, average load) appended to a
|
|
5
|
+
* long-term dream journal. The heartbeat-paced analogue of OpenClaw's dreaming
|
|
6
|
+
* (short-term recall → consolidated long-term memory).
|
|
7
|
+
*
|
|
8
|
+
* @module sensory/dreaming
|
|
9
|
+
*/
|
|
10
|
+
import type { Perception } from './reactions.js';
|
|
11
|
+
export interface DreamSummary {
|
|
12
|
+
dreamedAt: number;
|
|
13
|
+
windowStartMs: number | null;
|
|
14
|
+
windowEndMs: number | null;
|
|
15
|
+
total: number;
|
|
16
|
+
/** "audio/speech_start" → count, "vital/heartbeat" → count, … */
|
|
17
|
+
byKind: Record<string, number>;
|
|
18
|
+
salient: Array<{
|
|
19
|
+
modality?: string;
|
|
20
|
+
kind?: string;
|
|
21
|
+
salience?: number;
|
|
22
|
+
tsMs?: number;
|
|
23
|
+
}>;
|
|
24
|
+
avgLoad: number | null;
|
|
25
|
+
}
|
|
26
|
+
/** Pure consolidation: summarize a window of perceptions into a dream. */
|
|
27
|
+
export declare function consolidate(perceptions: Perception[], now: number): DreamSummary;
|
|
28
|
+
export interface DreamingOptions {
|
|
29
|
+
cwd?: string;
|
|
30
|
+
now?: number;
|
|
31
|
+
/** Injectable promotion (tests); defaults to promoteSalientDream. */
|
|
32
|
+
promote?: (summary: DreamSummary) => Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* One dreaming pass: drain the short-term buffer, consolidate, append to the
|
|
36
|
+
* dream journal, and promote a SALIENT dream into long-term persistent memory.
|
|
37
|
+
* Returns the summary, or null if there was nothing to consolidate.
|
|
38
|
+
*/
|
|
39
|
+
export declare function runDreamingPass(options?: DreamingOptions): Promise<DreamSummary | null>;
|
|
40
|
+
/**
|
|
41
|
+
* Promote a salient dream into Code Buddy's persistent memory under a STABLE key
|
|
42
|
+
* (`dream:recent`) so repeated promotions UPDATE rather than accumulate (stays
|
|
43
|
+
* within the memory char budget). Never throws.
|
|
44
|
+
*/
|
|
45
|
+
export declare function promoteSalientDream(summary: DreamSummary): Promise<void>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dreaming — heartbeat-paced memory consolidation. Every N beats, the short-term
|
|
3
|
+
* sensory buffer is drained and consolidated into a compact "dream" summary
|
|
4
|
+
* (counts by kind, salient events, time window, average load) appended to a
|
|
5
|
+
* long-term dream journal. The heartbeat-paced analogue of OpenClaw's dreaming
|
|
6
|
+
* (short-term recall → consolidated long-term memory).
|
|
7
|
+
*
|
|
8
|
+
* @module sensory/dreaming
|
|
9
|
+
*/
|
|
10
|
+
import { appendFile, mkdir, stat, rename } from 'fs/promises';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { getSensoryMemory } from './sensory-memory.js';
|
|
13
|
+
import { logger } from '../utils/logger.js';
|
|
14
|
+
const SALIENT_THRESHOLD = 128;
|
|
15
|
+
/** Pure consolidation: summarize a window of perceptions into a dream. */
|
|
16
|
+
export function consolidate(perceptions, now) {
|
|
17
|
+
const byKind = {};
|
|
18
|
+
const salient = [];
|
|
19
|
+
let loadSum = 0;
|
|
20
|
+
let loadN = 0;
|
|
21
|
+
let minTs = null;
|
|
22
|
+
let maxTs = null;
|
|
23
|
+
for (const p of perceptions) {
|
|
24
|
+
const key = `${p.modality}/${p.kind}`;
|
|
25
|
+
byKind[key] = (byKind[key] ?? 0) + 1;
|
|
26
|
+
if ((p.salience ?? 0) >= SALIENT_THRESHOLD) {
|
|
27
|
+
salient.push({ modality: p.modality, kind: p.kind, salience: p.salience, tsMs: p.tsMs });
|
|
28
|
+
}
|
|
29
|
+
const load = p.payload?.load1;
|
|
30
|
+
if (typeof load === 'number') {
|
|
31
|
+
loadSum += load;
|
|
32
|
+
loadN += 1;
|
|
33
|
+
}
|
|
34
|
+
// Window on the ingest wall-clock (consistent across senses), not the
|
|
35
|
+
// sense-relative tsMs (frame-relative for audio vs unix for vital).
|
|
36
|
+
if (typeof p.receivedAt === 'number') {
|
|
37
|
+
minTs = minTs === null ? p.receivedAt : Math.min(minTs, p.receivedAt);
|
|
38
|
+
maxTs = maxTs === null ? p.receivedAt : Math.max(maxTs, p.receivedAt);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
dreamedAt: now,
|
|
43
|
+
windowStartMs: minTs,
|
|
44
|
+
windowEndMs: maxTs,
|
|
45
|
+
total: perceptions.length,
|
|
46
|
+
byKind,
|
|
47
|
+
salient: salient.slice(0, 20),
|
|
48
|
+
avgLoad: loadN > 0 ? loadSum / loadN : null,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* One dreaming pass: drain the short-term buffer, consolidate, append to the
|
|
53
|
+
* dream journal, and promote a SALIENT dream into long-term persistent memory.
|
|
54
|
+
* Returns the summary, or null if there was nothing to consolidate.
|
|
55
|
+
*/
|
|
56
|
+
export async function runDreamingPass(options = {}) {
|
|
57
|
+
const perceptions = getSensoryMemory().drain();
|
|
58
|
+
if (perceptions.length === 0)
|
|
59
|
+
return null;
|
|
60
|
+
const summary = consolidate(perceptions, options.now ?? Date.now());
|
|
61
|
+
try {
|
|
62
|
+
const dir = path.join(options.cwd ?? process.cwd(), '.codebuddy', 'companion');
|
|
63
|
+
await mkdir(dir, { recursive: true });
|
|
64
|
+
const file = path.join(dir, 'dreams.jsonl');
|
|
65
|
+
// Rotate when large (the disk-guard lesson): keep one .1 backup, never grow unbounded.
|
|
66
|
+
try {
|
|
67
|
+
const info = await stat(file);
|
|
68
|
+
if (info.size > 512 * 1024)
|
|
69
|
+
await rename(file, `${file}.1`);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
/* no file yet */
|
|
73
|
+
}
|
|
74
|
+
await appendFile(file, `${JSON.stringify(summary)}\n`, 'utf8');
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
logger.warn(`[dreaming] could not persist dream: ${err instanceof Error ? err.message : String(err)}`);
|
|
78
|
+
}
|
|
79
|
+
// Deep consolidation — salient dreams become long-term memory the agent reads.
|
|
80
|
+
if (summary.salient.length > 0) {
|
|
81
|
+
await (options.promote ?? promoteSalientDream)(summary);
|
|
82
|
+
}
|
|
83
|
+
logger.info(`[dreaming] consolidated ${summary.total} perception(s) → ${Object.keys(summary.byKind).length} kind(s), ${summary.salient.length} salient, avg load ${summary.avgLoad ?? '?'}`);
|
|
84
|
+
return summary;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Promote a salient dream into Code Buddy's persistent memory under a STABLE key
|
|
88
|
+
* (`dream:recent`) so repeated promotions UPDATE rather than accumulate (stays
|
|
89
|
+
* within the memory char budget). Never throws.
|
|
90
|
+
*/
|
|
91
|
+
export async function promoteSalientDream(summary) {
|
|
92
|
+
try {
|
|
93
|
+
const { getMemoryManager } = await import('../memory/persistent-memory.js');
|
|
94
|
+
const manager = getMemoryManager();
|
|
95
|
+
await manager.initialize();
|
|
96
|
+
// Cap the kinds string (a daemon could emit many distinct kinds → an
|
|
97
|
+
// oversized write that the memory char-limit would reject).
|
|
98
|
+
const kindEntries = Object.entries(summary.byKind).sort((a, b) => b[1] - a[1]);
|
|
99
|
+
const kinds = kindEntries
|
|
100
|
+
.slice(0, 12)
|
|
101
|
+
.map(([k, n]) => `${k}×${n}`)
|
|
102
|
+
.join(', ') + (kindEntries.length > 12 ? `, +${kindEntries.length - 12} more` : '');
|
|
103
|
+
const top = summary.salient
|
|
104
|
+
.slice(0, 5)
|
|
105
|
+
.map((s) => `${s.modality}/${s.kind}`)
|
|
106
|
+
.join(', ');
|
|
107
|
+
const value = `Recent salient perception: ${summary.total} events (${kinds}); salient: ${top}; avg load ${summary.avgLoad ?? '?'}.`;
|
|
108
|
+
await manager.remember('dream:recent', value, { scope: 'project', category: 'context', tags: ['dream', 'sensory'] });
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
logger.warn(`[dreaming] could not promote dream to memory: ${err instanceof Error ? err.message : String(err)}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=dreaming.js.map
|