@phuetz/code-buddy 0.1.25 → 0.1.26
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 +1049 -741
- package/dist/agent/codebuddy-agent.d.ts +5 -0
- package/dist/agent/codebuddy-agent.js +46 -1
- package/dist/agent/codebuddy-agent.js.map +1 -1
- package/dist/agent/execution/agent-executor.d.ts +12 -0
- package/dist/agent/execution/agent-executor.js +147 -6
- package/dist/agent/execution/agent-executor.js.map +1 -1
- package/dist/agent/lessons-tracker.d.ts +50 -0
- package/dist/agent/lessons-tracker.js +234 -0
- package/dist/agent/lessons-tracker.js.map +1 -0
- package/dist/agent/message-queue.d.ts +39 -2
- package/dist/agent/message-queue.js +67 -2
- package/dist/agent/message-queue.js.map +1 -1
- package/dist/agent/middleware/index.d.ts +1 -0
- package/dist/agent/middleware/index.js +1 -0
- package/dist/agent/middleware/index.js.map +1 -1
- package/dist/agent/middleware/workflow-guard.d.ts +21 -0
- package/dist/agent/middleware/workflow-guard.js +94 -0
- package/dist/agent/middleware/workflow-guard.js.map +1 -0
- package/dist/agent/repo-profiler.d.ts +61 -0
- package/dist/agent/repo-profiler.js +295 -0
- package/dist/agent/repo-profiler.js.map +1 -0
- package/dist/agent/response-constraint.d.ts +61 -0
- package/dist/agent/response-constraint.js +91 -0
- package/dist/agent/response-constraint.js.map +1 -0
- package/dist/agent/todo-tracker.d.ts +67 -0
- package/dist/agent/todo-tracker.js +245 -0
- package/dist/agent/todo-tracker.js.map +1 -0
- package/dist/agent/tool-handler.d.ts +11 -0
- package/dist/agent/tool-handler.js +79 -1
- package/dist/agent/tool-handler.js.map +1 -1
- package/dist/agent/types.d.ts +20 -2
- package/dist/agent/wide-research.d.ts +93 -0
- package/dist/agent/wide-research.js +232 -0
- package/dist/agent/wide-research.js.map +1 -0
- package/dist/channels/index.d.ts +2 -0
- package/dist/channels/index.js +2 -0
- package/dist/channels/index.js.map +1 -1
- package/dist/channels/pro/callback-router.d.ts +54 -0
- package/dist/channels/pro/callback-router.js +178 -0
- package/dist/channels/pro/callback-router.js.map +1 -0
- package/dist/channels/pro/ci-watcher.d.ts +86 -0
- package/dist/channels/pro/ci-watcher.js +343 -0
- package/dist/channels/pro/ci-watcher.js.map +1 -0
- package/dist/channels/pro/diff-first.d.ts +63 -0
- package/dist/channels/pro/diff-first.js +187 -0
- package/dist/channels/pro/diff-first.js.map +1 -0
- package/dist/channels/pro/enhanced-commands.d.ts +83 -0
- package/dist/channels/pro/enhanced-commands.js +218 -0
- package/dist/channels/pro/enhanced-commands.js.map +1 -0
- package/dist/channels/pro/index.d.ts +19 -0
- package/dist/channels/pro/index.js +21 -0
- package/dist/channels/pro/index.js.map +1 -0
- package/dist/channels/pro/pro-features.d.ts +79 -0
- package/dist/channels/pro/pro-features.js +203 -0
- package/dist/channels/pro/pro-features.js.map +1 -0
- package/dist/channels/pro/run-commands.d.ts +59 -0
- package/dist/channels/pro/run-commands.js +122 -0
- package/dist/channels/pro/run-commands.js.map +1 -0
- package/dist/channels/pro/run-tracker.d.ts +74 -0
- package/dist/channels/pro/run-tracker.js +252 -0
- package/dist/channels/pro/run-tracker.js.map +1 -0
- package/dist/channels/pro/scoped-auth.d.ts +97 -0
- package/dist/channels/pro/scoped-auth.js +340 -0
- package/dist/channels/pro/scoped-auth.js.map +1 -0
- package/dist/channels/pro/text-formatter.d.ts +27 -0
- package/dist/channels/pro/text-formatter.js +269 -0
- package/dist/channels/pro/text-formatter.js.map +1 -0
- package/dist/channels/pro/types.d.ts +242 -0
- package/dist/channels/pro/types.js +14 -0
- package/dist/channels/pro/types.js.map +1 -0
- package/dist/channels/streaming-policy.d.ts +66 -0
- package/dist/channels/streaming-policy.js +266 -0
- package/dist/channels/streaming-policy.js.map +1 -0
- package/dist/channels/telegram/ci-watcher.d.ts +5 -0
- package/dist/channels/telegram/ci-watcher.js +5 -0
- package/dist/channels/telegram/ci-watcher.js.map +1 -0
- package/dist/channels/telegram/client.d.ts +28 -0
- package/dist/channels/telegram/client.js +147 -1
- package/dist/channels/telegram/client.js.map +1 -1
- package/dist/channels/telegram/diff-first.d.ts +5 -0
- package/dist/channels/telegram/diff-first.js +5 -0
- package/dist/channels/telegram/diff-first.js.map +1 -0
- package/dist/channels/telegram/enhanced-commands.d.ts +6 -0
- package/dist/channels/telegram/enhanced-commands.js +6 -0
- package/dist/channels/telegram/enhanced-commands.js.map +1 -0
- package/dist/channels/telegram/index.d.ts +6 -0
- package/dist/channels/telegram/index.js +6 -0
- package/dist/channels/telegram/index.js.map +1 -1
- package/dist/channels/telegram/pro-formatter.d.ts +30 -0
- package/dist/channels/telegram/pro-formatter.js +276 -0
- package/dist/channels/telegram/pro-formatter.js.map +1 -0
- package/dist/channels/telegram/run-commands.d.ts +5 -0
- package/dist/channels/telegram/run-commands.js +6 -0
- package/dist/channels/telegram/run-commands.js.map +1 -0
- package/dist/channels/telegram/run-tracker.d.ts +5 -0
- package/dist/channels/telegram/run-tracker.js +5 -0
- package/dist/channels/telegram/run-tracker.js.map +1 -0
- package/dist/channels/telegram/scoped-auth.d.ts +6 -0
- package/dist/channels/telegram/scoped-auth.js +5 -0
- package/dist/channels/telegram/scoped-auth.js.map +1 -0
- package/dist/channels/telegram/types.d.ts +34 -0
- package/dist/codebuddy/client.js +14 -1
- package/dist/codebuddy/client.js.map +1 -1
- package/dist/commands/dev/index.d.ts +12 -0
- package/dist/commands/dev/index.js +231 -0
- package/dist/commands/dev/index.js.map +1 -0
- package/dist/commands/dev/workflows.d.ts +31 -0
- package/dist/commands/dev/workflows.js +214 -0
- package/dist/commands/dev/workflows.js.map +1 -0
- package/dist/commands/execpolicy.d.ts +17 -0
- package/dist/commands/execpolicy.js +155 -0
- package/dist/commands/execpolicy.js.map +1 -0
- package/dist/commands/knowledge.d.ts +13 -0
- package/dist/commands/knowledge.js +142 -0
- package/dist/commands/knowledge.js.map +1 -0
- package/dist/commands/lessons.d.ts +11 -0
- package/dist/commands/lessons.js +129 -0
- package/dist/commands/lessons.js.map +1 -0
- package/dist/commands/pairing.d.ts +14 -0
- package/dist/commands/pairing.js +132 -0
- package/dist/commands/pairing.js.map +1 -0
- package/dist/commands/research/index.d.ts +13 -0
- package/dist/commands/research/index.js +91 -0
- package/dist/commands/research/index.js.map +1 -0
- package/dist/commands/run-cli/index.d.ts +11 -0
- package/dist/commands/run-cli/index.js +49 -0
- package/dist/commands/run-cli/index.js.map +1 -0
- package/dist/commands/todos.d.ts +9 -0
- package/dist/commands/todos.js +119 -0
- package/dist/commands/todos.js.map +1 -0
- package/dist/config/toml-config.d.ts +21 -0
- package/dist/config/toml-config.js +15 -0
- package/dist/config/toml-config.js.map +1 -1
- package/dist/context/enhanced-compression.js +12 -1
- package/dist/context/enhanced-compression.js.map +1 -1
- package/dist/context/observation-variator.d.ts +44 -0
- package/dist/context/observation-variator.js +83 -0
- package/dist/context/observation-variator.js.map +1 -0
- package/dist/context/precompaction-flush.d.ts +40 -0
- package/dist/context/precompaction-flush.js +134 -0
- package/dist/context/precompaction-flush.js.map +1 -0
- package/dist/context/restorable-compression.d.ts +80 -0
- package/dist/context/restorable-compression.js +228 -0
- package/dist/context/restorable-compression.js.map +1 -0
- package/dist/daemon/daily-reset.d.ts +77 -0
- package/dist/daemon/daily-reset.js +175 -0
- package/dist/daemon/daily-reset.js.map +1 -0
- package/dist/daemon/index.d.ts +1 -0
- package/dist/daemon/index.js +1 -0
- package/dist/daemon/index.js.map +1 -1
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -1
- package/dist/knowledge/knowledge-manager.d.ts +77 -0
- package/dist/knowledge/knowledge-manager.js +244 -0
- package/dist/knowledge/knowledge-manager.js.map +1 -0
- package/dist/observability/run-store.d.ts +133 -0
- package/dist/observability/run-store.js +419 -0
- package/dist/observability/run-store.js.map +1 -0
- package/dist/observability/run-viewer.d.ts +33 -0
- package/dist/observability/run-viewer.js +254 -0
- package/dist/observability/run-viewer.js.map +1 -0
- package/dist/optimization/cache-breakpoints.d.ts +52 -0
- package/dist/optimization/cache-breakpoints.js +97 -0
- package/dist/optimization/cache-breakpoints.js.map +1 -0
- package/dist/persistence/session-store.d.ts +3 -1
- package/dist/persistence/session-store.js +1 -1
- package/dist/persistence/session-store.js.map +1 -1
- package/dist/prompts/system-base.js +51 -7
- package/dist/prompts/system-base.js.map +1 -1
- package/dist/prompts/variation-injector.d.ts +55 -0
- package/dist/prompts/variation-injector.js +171 -0
- package/dist/prompts/variation-injector.js.map +1 -0
- package/dist/prompts/workflow-rules.d.ts +10 -0
- package/dist/prompts/workflow-rules.js +79 -0
- package/dist/prompts/workflow-rules.js.map +1 -0
- package/dist/sandbox/execpolicy.d.ts +45 -0
- package/dist/sandbox/execpolicy.js +80 -0
- package/dist/sandbox/execpolicy.js.map +1 -1
- package/dist/sandbox/os-sandbox.d.ts +25 -0
- package/dist/sandbox/os-sandbox.js +73 -0
- package/dist/sandbox/os-sandbox.js.map +1 -1
- package/dist/security/security-audit.d.ts +10 -0
- package/dist/security/security-audit.js +116 -0
- package/dist/security/security-audit.js.map +1 -1
- package/dist/security/shell-env-policy.d.ts +45 -0
- package/dist/security/shell-env-policy.js +141 -0
- package/dist/security/shell-env-policy.js.map +1 -0
- package/dist/security/ssrf-guard.d.ts +61 -0
- package/dist/security/ssrf-guard.js +382 -0
- package/dist/security/ssrf-guard.js.map +1 -0
- package/dist/security/write-policy.d.ts +57 -0
- package/dist/security/write-policy.js +117 -0
- package/dist/security/write-policy.js.map +1 -0
- package/dist/services/prompt-builder.js +37 -0
- package/dist/services/prompt-builder.js.map +1 -1
- package/dist/themes/theme-schema.d.ts +10 -10
- package/dist/tools/ask-human-tool.d.ts +62 -0
- package/dist/tools/ask-human-tool.js +112 -0
- package/dist/tools/ask-human-tool.js.map +1 -0
- package/dist/tools/bash/bash-tool.d.ts +15 -0
- package/dist/tools/bash/bash-tool.js +62 -0
- package/dist/tools/bash/bash-tool.js.map +1 -1
- package/dist/tools/bash/command-validator.d.ts +1 -0
- package/dist/tools/bash/command-validator.js +5 -0
- package/dist/tools/bash/command-validator.js.map +1 -1
- package/dist/tools/create-skill-tool.d.ts +87 -0
- package/dist/tools/create-skill-tool.js +142 -0
- package/dist/tools/create-skill-tool.js.map +1 -0
- package/dist/tools/fetch-tool.js +5 -3
- package/dist/tools/fetch-tool.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +1 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/plan-tool.d.ts +22 -0
- package/dist/tools/plan-tool.js +128 -0
- package/dist/tools/plan-tool.js.map +1 -0
- package/dist/tools/registry/attention-tools.d.ts +32 -0
- package/dist/tools/registry/attention-tools.js +225 -0
- package/dist/tools/registry/attention-tools.js.map +1 -0
- package/dist/tools/registry/index.d.ts +9 -1
- package/dist/tools/registry/index.js +30 -2
- package/dist/tools/registry/index.js.map +1 -1
- package/dist/tools/registry/knowledge-tools.d.ts +46 -0
- package/dist/tools/registry/knowledge-tools.js +293 -0
- package/dist/tools/registry/knowledge-tools.js.map +1 -0
- package/dist/tools/registry/lessons-tools.d.ts +48 -0
- package/dist/tools/registry/lessons-tools.js +359 -0
- package/dist/tools/registry/lessons-tools.js.map +1 -0
- package/dist/tools/registry/plan-tools.d.ts +2 -0
- package/dist/tools/registry/plan-tools.js +7 -0
- package/dist/tools/registry/plan-tools.js.map +1 -0
- package/dist/tools/registry/script-tools.d.ts +2 -0
- package/dist/tools/registry/script-tools.js +7 -0
- package/dist/tools/registry/script-tools.js.map +1 -0
- package/dist/tools/registry/tool-aliases.d.ts +44 -0
- package/dist/tools/registry/tool-aliases.js +130 -0
- package/dist/tools/registry/tool-aliases.js.map +1 -0
- package/dist/tools/run-script-tool.d.ts +13 -0
- package/dist/tools/run-script-tool.js +146 -0
- package/dist/tools/run-script-tool.js.map +1 -0
- package/dist/tools/web-search.d.ts +25 -0
- package/dist/tools/web-search.js +68 -6
- package/dist/tools/web-search.js.map +1 -1
- package/dist/utils/config-validation/schema.d.ts +2 -2
- package/dist/utils/debug-logger.d.ts +1 -1
- package/dist/utils/stable-json.d.ts +27 -0
- package/dist/utils/stable-json.js +50 -0
- package/dist/utils/stable-json.js.map +1 -0
- package/dist/webhooks/webhook-manager.d.ts +7 -0
- package/dist/webhooks/webhook-manager.js +29 -0
- package/dist/webhooks/webhook-manager.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lessons Tracker — Self-improvement loop for recurring patterns
|
|
3
|
+
*
|
|
4
|
+
* Maintains a persistent `lessons.md` in `.codebuddy/lessons.md` (project)
|
|
5
|
+
* and `~/.codebuddy/lessons.md` (global). On every agent turn the active
|
|
6
|
+
* lessons are injected BEFORE the todo suffix (stable rules before recency
|
|
7
|
+
* bias), so the model internalises learned patterns across sessions.
|
|
8
|
+
*
|
|
9
|
+
* The agent calls `lessons_add` to capture a new lesson after a correction;
|
|
10
|
+
* `lessons_search` to find relevant lessons before similar tasks.
|
|
11
|
+
*
|
|
12
|
+
* Categories follow a structured taxonomy:
|
|
13
|
+
* PATTERN — "What went wrong → correct approach"
|
|
14
|
+
* RULE — Invariant to always follow (e.g. "run tests before marking done")
|
|
15
|
+
* CONTEXT — Project/domain-specific facts (e.g. "this repo uses ESM imports")
|
|
16
|
+
* INSIGHT — Non-obvious observation useful for future tasks
|
|
17
|
+
*/
|
|
18
|
+
import * as fs from 'fs';
|
|
19
|
+
import * as path from 'path';
|
|
20
|
+
import * as os from 'os';
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Singleton registry (one tracker per working directory)
|
|
23
|
+
// ============================================================================
|
|
24
|
+
const registry = new Map();
|
|
25
|
+
export function getLessonsTracker(workDir = process.cwd()) {
|
|
26
|
+
const key = path.resolve(workDir);
|
|
27
|
+
if (!registry.has(key)) {
|
|
28
|
+
registry.set(key, new LessonsTracker(key));
|
|
29
|
+
}
|
|
30
|
+
return registry.get(key);
|
|
31
|
+
}
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// LessonsTracker
|
|
34
|
+
// ============================================================================
|
|
35
|
+
export class LessonsTracker {
|
|
36
|
+
workDir;
|
|
37
|
+
projectPath;
|
|
38
|
+
globalPath;
|
|
39
|
+
items = [];
|
|
40
|
+
loaded = false;
|
|
41
|
+
constructor(workDir) {
|
|
42
|
+
this.workDir = workDir;
|
|
43
|
+
const projectDir = path.join(workDir, '.codebuddy');
|
|
44
|
+
this.projectPath = path.join(projectDir, 'lessons.md');
|
|
45
|
+
this.globalPath = path.join(os.homedir(), '.codebuddy', 'lessons.md');
|
|
46
|
+
}
|
|
47
|
+
// --------------------------------------------------------------------------
|
|
48
|
+
// Public API
|
|
49
|
+
// --------------------------------------------------------------------------
|
|
50
|
+
load() {
|
|
51
|
+
if (this.loaded)
|
|
52
|
+
return;
|
|
53
|
+
this.loaded = true;
|
|
54
|
+
const globalItems = this.loadFile(this.globalPath);
|
|
55
|
+
const projectItems = this.loadFile(this.projectPath);
|
|
56
|
+
// Merge: project overrides global for duplicate ids
|
|
57
|
+
const byId = new Map();
|
|
58
|
+
for (const item of [...globalItems, ...projectItems]) {
|
|
59
|
+
byId.set(item.id, item);
|
|
60
|
+
}
|
|
61
|
+
this.items = Array.from(byId.values());
|
|
62
|
+
}
|
|
63
|
+
save() {
|
|
64
|
+
this.load();
|
|
65
|
+
// Save to project path only (global is managed manually or by `lessons_add --global`)
|
|
66
|
+
try {
|
|
67
|
+
const dir = path.dirname(this.projectPath);
|
|
68
|
+
if (!fs.existsSync(dir)) {
|
|
69
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
fs.writeFileSync(this.projectPath, this.serialise(), 'utf-8');
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// non-fatal
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
add(category, content, source = 'manual', context) {
|
|
78
|
+
this.load();
|
|
79
|
+
const item = {
|
|
80
|
+
id: Date.now().toString(36) + Math.random().toString(36).slice(2, 5),
|
|
81
|
+
category,
|
|
82
|
+
content,
|
|
83
|
+
context,
|
|
84
|
+
createdAt: Date.now(),
|
|
85
|
+
source,
|
|
86
|
+
};
|
|
87
|
+
this.items.push(item);
|
|
88
|
+
this.save();
|
|
89
|
+
return item;
|
|
90
|
+
}
|
|
91
|
+
remove(id) {
|
|
92
|
+
this.load();
|
|
93
|
+
const idx = this.items.findIndex(i => i.id === id);
|
|
94
|
+
if (idx === -1)
|
|
95
|
+
return false;
|
|
96
|
+
this.items.splice(idx, 1);
|
|
97
|
+
this.save();
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
clearByCategory(category) {
|
|
101
|
+
this.load();
|
|
102
|
+
const before = this.items.length;
|
|
103
|
+
this.items = category
|
|
104
|
+
? this.items.filter(i => i.category !== category)
|
|
105
|
+
: [];
|
|
106
|
+
this.save();
|
|
107
|
+
return before - this.items.length;
|
|
108
|
+
}
|
|
109
|
+
list(category) {
|
|
110
|
+
this.load();
|
|
111
|
+
return category ? this.items.filter(i => i.category === category) : this.items;
|
|
112
|
+
}
|
|
113
|
+
search(query, category) {
|
|
114
|
+
this.load();
|
|
115
|
+
const q = query.toLowerCase();
|
|
116
|
+
return this.items.filter(item => {
|
|
117
|
+
if (category && item.category !== category)
|
|
118
|
+
return false;
|
|
119
|
+
return (item.content.toLowerCase().includes(q) ||
|
|
120
|
+
(item.context?.toLowerCase().includes(q) ?? false));
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Build the per-turn context block injected BEFORE the todo suffix.
|
|
125
|
+
* Returns null when there are no lessons (avoids noisy injections).
|
|
126
|
+
*/
|
|
127
|
+
buildContextBlock() {
|
|
128
|
+
this.load();
|
|
129
|
+
if (this.items.length === 0)
|
|
130
|
+
return null;
|
|
131
|
+
const lines = [
|
|
132
|
+
'<lessons_context>',
|
|
133
|
+
'## Active Lessons (apply to this turn)',
|
|
134
|
+
'',
|
|
135
|
+
];
|
|
136
|
+
const grouped = new Map();
|
|
137
|
+
for (const item of this.items) {
|
|
138
|
+
const arr = grouped.get(item.category) ?? [];
|
|
139
|
+
arr.push(item);
|
|
140
|
+
grouped.set(item.category, arr);
|
|
141
|
+
}
|
|
142
|
+
const order = ['RULE', 'PATTERN', 'CONTEXT', 'INSIGHT'];
|
|
143
|
+
for (const cat of order) {
|
|
144
|
+
const catItems = grouped.get(cat);
|
|
145
|
+
if (!catItems || catItems.length === 0)
|
|
146
|
+
continue;
|
|
147
|
+
for (const item of catItems) {
|
|
148
|
+
const ctx = item.context ? ` _(${item.context})_` : '';
|
|
149
|
+
lines.push(`**[${item.category}]**${ctx} ${item.content}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
lines.push('</lessons_context>');
|
|
153
|
+
return lines.join('\n');
|
|
154
|
+
}
|
|
155
|
+
// --------------------------------------------------------------------------
|
|
156
|
+
// Markdown serialisation / parsing
|
|
157
|
+
// --------------------------------------------------------------------------
|
|
158
|
+
serialise() {
|
|
159
|
+
const lines = [
|
|
160
|
+
'# Lessons Learned',
|
|
161
|
+
`<!-- auto-generated by Code Buddy — last updated ${new Date().toISOString()} -->`,
|
|
162
|
+
'',
|
|
163
|
+
];
|
|
164
|
+
const grouped = new Map();
|
|
165
|
+
for (const item of this.items) {
|
|
166
|
+
const arr = grouped.get(item.category) ?? [];
|
|
167
|
+
arr.push(item);
|
|
168
|
+
grouped.set(item.category, arr);
|
|
169
|
+
}
|
|
170
|
+
const order = ['PATTERN', 'RULE', 'CONTEXT', 'INSIGHT'];
|
|
171
|
+
for (const cat of order) {
|
|
172
|
+
const catItems = grouped.get(cat);
|
|
173
|
+
if (!catItems || catItems.length === 0)
|
|
174
|
+
continue;
|
|
175
|
+
lines.push(`## ${cat}`);
|
|
176
|
+
for (const item of catItems) {
|
|
177
|
+
const date = new Date(item.createdAt).toISOString().slice(0, 10);
|
|
178
|
+
const ctx = item.context ? `:${item.context}` : '';
|
|
179
|
+
lines.push(`- [${item.id}] ${item.content} <!-- ${date} ${item.source}${ctx} -->`);
|
|
180
|
+
}
|
|
181
|
+
lines.push('');
|
|
182
|
+
}
|
|
183
|
+
return lines.join('\n');
|
|
184
|
+
}
|
|
185
|
+
loadFile(filePath) {
|
|
186
|
+
if (!fs.existsSync(filePath))
|
|
187
|
+
return [];
|
|
188
|
+
try {
|
|
189
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
190
|
+
return this.parseMd(content);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
parseMd(content) {
|
|
197
|
+
const items = [];
|
|
198
|
+
let currentCategory = 'INSIGHT';
|
|
199
|
+
for (const rawLine of content.split('\n')) {
|
|
200
|
+
// Category header: ## PATTERN
|
|
201
|
+
const catMatch = rawLine.match(/^## (PATTERN|RULE|CONTEXT|INSIGHT)\s*$/);
|
|
202
|
+
if (catMatch) {
|
|
203
|
+
currentCategory = catMatch[1];
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
// Item: - [id] content <!-- date source:context -->
|
|
207
|
+
const itemMatch = rawLine.match(/^- \[([^\]]+)\] (.+?) <!-- ([^\s]+) ([^\s:]+)(?::([^-]+))? -->/);
|
|
208
|
+
if (itemMatch) {
|
|
209
|
+
items.push({
|
|
210
|
+
id: itemMatch[1],
|
|
211
|
+
content: itemMatch[2].trim(),
|
|
212
|
+
category: currentCategory,
|
|
213
|
+
createdAt: new Date(itemMatch[3]).getTime() || 0,
|
|
214
|
+
source: itemMatch[4] ?? 'manual',
|
|
215
|
+
context: itemMatch[5]?.trim() || undefined,
|
|
216
|
+
});
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
// Plain item fallback: - content
|
|
220
|
+
const plainMatch = rawLine.match(/^- (.+)/);
|
|
221
|
+
if (plainMatch) {
|
|
222
|
+
items.push({
|
|
223
|
+
id: Date.now().toString(36) + Math.random().toString(36).slice(2, 5),
|
|
224
|
+
content: plainMatch[1].trim(),
|
|
225
|
+
category: currentCategory,
|
|
226
|
+
createdAt: 0,
|
|
227
|
+
source: 'manual',
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return items;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=lessons-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lessons-tracker.js","sourceRoot":"","sources":["../../src/agent/lessons-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAiBzB,+EAA+E;AAC/E,yDAAyD;AACzD,+EAA+E;AAE/E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEnD,MAAM,UAAU,iBAAiB,CAAC,UAAkB,OAAO,CAAC,GAAG,EAAE;IAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;AAC5B,CAAC;AAED,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,MAAM,OAAO,cAAc;IAML;IALZ,WAAW,CAAS;IACpB,UAAU,CAAS;IACnB,KAAK,GAAiB,EAAE,CAAC;IACzB,MAAM,GAAG,KAAK,CAAC;IAEvB,YAAoB,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;QACjC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACpD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QACvD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;IACxE,CAAC;IAED,6EAA6E;IAC7E,aAAa;IACb,6EAA6E;IAE7E,IAAI;QACF,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrD,oDAAoD;QACpD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAC;QAC3C,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,WAAW,EAAE,GAAG,YAAY,CAAC,EAAE,CAAC;YACrD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,IAAI;QACF,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,sFAAsF;QACtF,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzC,CAAC;YACD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,EAAE,OAAO,CAAC,CAAC;QAChE,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;IACH,CAAC;IAED,GAAG,CACD,QAAwB,EACxB,OAAe,EACf,SAA+B,QAAQ,EACvC,OAAgB;QAEhB,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,MAAM,IAAI,GAAe;YACvB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACpE,QAAQ;YACR,OAAO;YACP,OAAO;YACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,MAAM;SACP,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,EAAU;QACf,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACnD,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAC7B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,eAAe,CAAC,QAAyB;QACvC,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,QAAQ;YACnB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC;YACjD,CAAC,CAAC,EAAE,CAAC;QACP,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IACpC,CAAC;IAED,IAAI,CAAC,QAAyB;QAC5B,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IACjF,CAAC;IAED,MAAM,CAAC,KAAa,EAAE,QAAyB;QAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YAC9B,IAAI,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YACzD,OAAO,CACL,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACtC,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CACnD,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,iBAAiB;QACf,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEzC,MAAM,KAAK,GAAG;YACZ,mBAAmB;YACnB,wCAAwC;YACxC,EAAE;SACH,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAgC,CAAC;QACxD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC7C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC;QAED,MAAM,KAAK,GAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAC1E,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YACjD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvD,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACjC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,6EAA6E;IAC7E,mCAAmC;IACnC,6EAA6E;IAErE,SAAS;QACf,MAAM,KAAK,GAAG;YACZ,mBAAmB;YACnB,oDAAoD,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM;YAClF,EAAE;SACH,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAgC,CAAC;QACxD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC7C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC;QAED,MAAM,KAAK,GAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAC1E,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YACjD,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;YACxB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACjE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnD,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,OAAO,SAAS,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC;YACrF,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAEO,QAAQ,CAAC,QAAgB;QAC/B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,OAAe;QAC7B,MAAM,KAAK,GAAiB,EAAE,CAAC;QAC/B,IAAI,eAAe,GAAmB,SAAS,CAAC;QAEhD,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,8BAA8B;YAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YACzE,IAAI,QAAQ,EAAE,CAAC;gBACb,eAAe,GAAG,QAAQ,CAAC,CAAC,CAAmB,CAAC;gBAChD,SAAS;YACX,CAAC;YAED,oDAAoD;YACpD,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;YAClG,IAAI,SAAS,EAAE,CAAC;gBACd,KAAK,CAAC,IAAI,CAAC;oBACT,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;oBAChB,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;oBAC5B,QAAQ,EAAE,eAAe;oBACzB,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC;oBAChD,MAAM,EAAG,SAAS,CAAC,CAAC,CAA0B,IAAI,QAAQ;oBAC1D,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,SAAS;iBAC3C,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YAED,iCAAiC;YACjC,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAC5C,IAAI,UAAU,EAAE,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC;oBACT,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;oBACpE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;oBAC7B,QAAQ,EAAE,eAAe;oBACzB,SAAS,EAAE,CAAC;oBACZ,MAAM,EAAE,QAAQ;iBACjB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - collect: Messages are batched into a single string for the next turn
|
|
10
10
|
*/
|
|
11
11
|
import { EventEmitter } from 'events';
|
|
12
|
-
export type MessageQueueMode = 'steer' | 'followup' | 'collect';
|
|
12
|
+
export type MessageQueueMode = 'steer' | 'followup' | 'collect' | 'steer-backlog';
|
|
13
13
|
export interface QueuedMessage {
|
|
14
14
|
/** Message content */
|
|
15
15
|
content: string;
|
|
@@ -18,10 +18,33 @@ export interface QueuedMessage {
|
|
|
18
18
|
/** When the message was enqueued */
|
|
19
19
|
timestamp: Date;
|
|
20
20
|
}
|
|
21
|
+
export interface MessageQueueOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Wait for this many ms of silence before starting a followup turn.
|
|
24
|
+
* Prevents rapid "continue continue" bursts from spamming turns.
|
|
25
|
+
* Default: 1000 ms.
|
|
26
|
+
*/
|
|
27
|
+
debounceMs?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Maximum queued messages before overflow handling kicks in.
|
|
30
|
+
* Default: 20.
|
|
31
|
+
*/
|
|
32
|
+
cap?: number;
|
|
33
|
+
/**
|
|
34
|
+
* How to handle overflow when `cap` is exceeded.
|
|
35
|
+
* 'drop' — silently drop the oldest message
|
|
36
|
+
* 'summarize' — replace the queue with a single synthetic bullet-list prompt
|
|
37
|
+
* Default: 'drop'.
|
|
38
|
+
*/
|
|
39
|
+
drop?: 'drop' | 'summarize';
|
|
40
|
+
}
|
|
21
41
|
export declare class MessageQueue extends EventEmitter {
|
|
22
42
|
private mode;
|
|
23
43
|
private queue;
|
|
24
44
|
private processing;
|
|
45
|
+
private opts;
|
|
46
|
+
private debounceTimer;
|
|
47
|
+
constructor(options?: MessageQueueOptions);
|
|
25
48
|
/**
|
|
26
49
|
* Set the queue mode
|
|
27
50
|
*/
|
|
@@ -31,9 +54,23 @@ export declare class MessageQueue extends EventEmitter {
|
|
|
31
54
|
*/
|
|
32
55
|
getMode(): MessageQueueMode;
|
|
33
56
|
/**
|
|
34
|
-
* Enqueue a message
|
|
57
|
+
* Enqueue a message.
|
|
58
|
+
* Handles debounce (followup mode), cap enforcement with overflow policy,
|
|
59
|
+
* and steer-backlog mode.
|
|
35
60
|
*/
|
|
36
61
|
enqueue(msg: QueuedMessage): void;
|
|
62
|
+
/**
|
|
63
|
+
* Collapse all queued messages + incoming overflow into a single synthetic prompt.
|
|
64
|
+
*/
|
|
65
|
+
private _summarizeOverflow;
|
|
66
|
+
/**
|
|
67
|
+
* Update queue options at runtime (e.g. from /queue steer debounce:2s cap:25)
|
|
68
|
+
*/
|
|
69
|
+
configure(options: Partial<MessageQueueOptions>): void;
|
|
70
|
+
/**
|
|
71
|
+
* Get current queue options
|
|
72
|
+
*/
|
|
73
|
+
getOptions(): Readonly<Required<MessageQueueOptions>>;
|
|
37
74
|
/**
|
|
38
75
|
* Check if a steering message is available (steer mode)
|
|
39
76
|
*/
|
|
@@ -16,6 +16,16 @@ export class MessageQueue extends EventEmitter {
|
|
|
16
16
|
mode = 'followup';
|
|
17
17
|
queue = [];
|
|
18
18
|
processing = false;
|
|
19
|
+
opts;
|
|
20
|
+
debounceTimer = null;
|
|
21
|
+
constructor(options = {}) {
|
|
22
|
+
super();
|
|
23
|
+
this.opts = {
|
|
24
|
+
debounceMs: options.debounceMs ?? 1000,
|
|
25
|
+
cap: options.cap ?? 20,
|
|
26
|
+
drop: options.drop ?? 'drop',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
19
29
|
/**
|
|
20
30
|
* Set the queue mode
|
|
21
31
|
*/
|
|
@@ -30,14 +40,69 @@ export class MessageQueue extends EventEmitter {
|
|
|
30
40
|
return this.mode;
|
|
31
41
|
}
|
|
32
42
|
/**
|
|
33
|
-
* Enqueue a message
|
|
43
|
+
* Enqueue a message.
|
|
44
|
+
* Handles debounce (followup mode), cap enforcement with overflow policy,
|
|
45
|
+
* and steer-backlog mode.
|
|
34
46
|
*/
|
|
35
47
|
enqueue(msg) {
|
|
48
|
+
// Enforce capacity cap
|
|
49
|
+
if (this.queue.length >= this.opts.cap) {
|
|
50
|
+
if (this.opts.drop === 'summarize') {
|
|
51
|
+
this._summarizeOverflow(msg);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Drop oldest
|
|
56
|
+
this.queue.shift();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
36
59
|
this.queue.push(msg);
|
|
37
60
|
this.emit('message-enqueued', msg);
|
|
38
|
-
if (this.mode === 'steer' && this.processing) {
|
|
61
|
+
if ((this.mode === 'steer' || this.mode === 'steer-backlog') && this.processing) {
|
|
39
62
|
this.emit('steering-available');
|
|
40
63
|
}
|
|
64
|
+
// Debounce: reset timer on each new message in followup/collect mode
|
|
65
|
+
if ((this.mode === 'followup' || this.mode === 'collect') && !this.processing) {
|
|
66
|
+
if (this.debounceTimer)
|
|
67
|
+
clearTimeout(this.debounceTimer);
|
|
68
|
+
this.debounceTimer = setTimeout(() => {
|
|
69
|
+
this.debounceTimer = null;
|
|
70
|
+
this.emit('debounce-ready');
|
|
71
|
+
}, this.opts.debounceMs);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Collapse all queued messages + incoming overflow into a single synthetic prompt.
|
|
76
|
+
*/
|
|
77
|
+
_summarizeOverflow(incoming) {
|
|
78
|
+
const all = [...this.queue, incoming];
|
|
79
|
+
this.queue = [];
|
|
80
|
+
const bullets = all.map(m => `- [${m.source}] ${m.content}`).join('\n');
|
|
81
|
+
const synthetic = {
|
|
82
|
+
content: `Multiple queued messages (summarized due to overflow):\n${bullets}`,
|
|
83
|
+
source: 'queue-summary',
|
|
84
|
+
timestamp: new Date(),
|
|
85
|
+
};
|
|
86
|
+
this.queue.push(synthetic);
|
|
87
|
+
this.emit('message-enqueued', synthetic);
|
|
88
|
+
this.emit('overflow-summarized', { count: all.length });
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Update queue options at runtime (e.g. from /queue steer debounce:2s cap:25)
|
|
92
|
+
*/
|
|
93
|
+
configure(options) {
|
|
94
|
+
if (options.debounceMs !== undefined)
|
|
95
|
+
this.opts.debounceMs = options.debounceMs;
|
|
96
|
+
if (options.cap !== undefined)
|
|
97
|
+
this.opts.cap = options.cap;
|
|
98
|
+
if (options.drop !== undefined)
|
|
99
|
+
this.opts.drop = options.drop;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get current queue options
|
|
103
|
+
*/
|
|
104
|
+
getOptions() {
|
|
105
|
+
return { ...this.opts };
|
|
41
106
|
}
|
|
42
107
|
/**
|
|
43
108
|
* Check if a steering message is available (steer mode)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-queue.js","sourceRoot":"","sources":["../../src/agent/message-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"message-queue.js","sourceRoot":"","sources":["../../src/agent/message-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,3 +12,4 @@ export { CostLimitMiddleware } from './cost-limit.js';
|
|
|
12
12
|
export { ContextWarningMiddleware } from './context-warning.js';
|
|
13
13
|
export { AutoObservationMiddleware } from './auto-observation.js';
|
|
14
14
|
export type { AutoObservationConfig } from './auto-observation.js';
|
|
15
|
+
export { WorkflowGuardMiddleware } from './workflow-guard.js';
|
|
@@ -10,4 +10,5 @@ export { TurnLimitMiddleware } from './turn-limit.js';
|
|
|
10
10
|
export { CostLimitMiddleware } from './cost-limit.js';
|
|
11
11
|
export { ContextWarningMiddleware } from './context-warning.js';
|
|
12
12
|
export { AutoObservationMiddleware } from './auto-observation.js';
|
|
13
|
+
export { WorkflowGuardMiddleware } from './workflow-guard.js';
|
|
13
14
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent/middleware/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent/middleware/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Guard Middleware
|
|
3
|
+
*
|
|
4
|
+
* Detects tasks that require planning before acting (priority 45).
|
|
5
|
+
* When the first user message contains 3+ distinct action verbs AND
|
|
6
|
+
* there is no existing PLAN.md, emits a `steer` hint suggesting
|
|
7
|
+
* the agent create a plan before diving into implementation.
|
|
8
|
+
*
|
|
9
|
+
* This resolves the plan-first vs bug-fix tension:
|
|
10
|
+
* - Single-file fixes with 1-2 verbs: proceed directly
|
|
11
|
+
* - Multi-verb, multi-file tasks: steer toward plan init
|
|
12
|
+
*
|
|
13
|
+
* Priority 45 — runs after cost-limit (10) and turn-limit (10),
|
|
14
|
+
* but before most business logic middlewares (100+).
|
|
15
|
+
*/
|
|
16
|
+
import type { ConversationMiddleware, MiddlewareContext, MiddlewareResult } from './types.js';
|
|
17
|
+
export declare class WorkflowGuardMiddleware implements ConversationMiddleware {
|
|
18
|
+
readonly name = "workflow-guard";
|
|
19
|
+
readonly priority = 45;
|
|
20
|
+
beforeTurn(context: MiddlewareContext): MiddlewareResult;
|
|
21
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Guard Middleware
|
|
3
|
+
*
|
|
4
|
+
* Detects tasks that require planning before acting (priority 45).
|
|
5
|
+
* When the first user message contains 3+ distinct action verbs AND
|
|
6
|
+
* there is no existing PLAN.md, emits a `steer` hint suggesting
|
|
7
|
+
* the agent create a plan before diving into implementation.
|
|
8
|
+
*
|
|
9
|
+
* This resolves the plan-first vs bug-fix tension:
|
|
10
|
+
* - Single-file fixes with 1-2 verbs: proceed directly
|
|
11
|
+
* - Multi-verb, multi-file tasks: steer toward plan init
|
|
12
|
+
*
|
|
13
|
+
* Priority 45 — runs after cost-limit (10) and turn-limit (10),
|
|
14
|
+
* but before most business logic middlewares (100+).
|
|
15
|
+
*/
|
|
16
|
+
import * as fs from 'fs';
|
|
17
|
+
import * as path from 'path';
|
|
18
|
+
// Action verbs that indicate non-trivial scope
|
|
19
|
+
const ACTION_VERBS = new Set([
|
|
20
|
+
'create', 'add', 'implement', 'build', 'write',
|
|
21
|
+
'fix', 'repair', 'resolve', 'debug', 'patch',
|
|
22
|
+
'update', 'change', 'modify', 'edit', 'refactor',
|
|
23
|
+
'test', 'verify', 'validate', 'check',
|
|
24
|
+
'deploy', 'release', 'publish', 'push',
|
|
25
|
+
'remove', 'delete', 'drop', 'clean',
|
|
26
|
+
'migrate', 'upgrade', 'downgrade',
|
|
27
|
+
'integrate', 'connect', 'setup', 'configure',
|
|
28
|
+
'optimise', 'optimize', 'improve', 'enhance',
|
|
29
|
+
'document', 'explain', 'analyse', 'analyze',
|
|
30
|
+
]);
|
|
31
|
+
function countDistinctActionVerbs(text) {
|
|
32
|
+
const words = text.toLowerCase().match(/\b\w+\b/g) ?? [];
|
|
33
|
+
const found = new Set();
|
|
34
|
+
for (const word of words) {
|
|
35
|
+
// Check base form and common conjugations
|
|
36
|
+
if (ACTION_VERBS.has(word))
|
|
37
|
+
found.add(word);
|
|
38
|
+
// Strip trailing 's' for 3rd person singular (creates → create)
|
|
39
|
+
else if (word.endsWith('s') && ACTION_VERBS.has(word.slice(0, -1)))
|
|
40
|
+
found.add(word.slice(0, -1));
|
|
41
|
+
// Strip 'ing' (creating → create)
|
|
42
|
+
else if (word.endsWith('ing') && ACTION_VERBS.has(word.slice(0, -3)))
|
|
43
|
+
found.add(word.slice(0, -3));
|
|
44
|
+
// Strip 'ed' (created → create)
|
|
45
|
+
else if (word.endsWith('ed') && ACTION_VERBS.has(word.slice(0, -2)))
|
|
46
|
+
found.add(word.slice(0, -2));
|
|
47
|
+
}
|
|
48
|
+
return found.size;
|
|
49
|
+
}
|
|
50
|
+
function hasPlanFile(cwd) {
|
|
51
|
+
return (fs.existsSync(path.join(cwd, 'PLAN.md')) ||
|
|
52
|
+
fs.existsSync(path.join(cwd, '.codebuddy', 'PLAN.md')));
|
|
53
|
+
}
|
|
54
|
+
export class WorkflowGuardMiddleware {
|
|
55
|
+
name = 'workflow-guard';
|
|
56
|
+
priority = 45;
|
|
57
|
+
beforeTurn(context) {
|
|
58
|
+
// Only trigger on the very first turn (round 0) of a session
|
|
59
|
+
if (context.toolRound !== 0) {
|
|
60
|
+
return { action: 'continue' };
|
|
61
|
+
}
|
|
62
|
+
// Extract last user message
|
|
63
|
+
const lastUser = [...context.messages]
|
|
64
|
+
.reverse()
|
|
65
|
+
.find(m => m.role === 'user');
|
|
66
|
+
if (!lastUser)
|
|
67
|
+
return { action: 'continue' };
|
|
68
|
+
const text = typeof lastUser.content === 'string'
|
|
69
|
+
? lastUser.content
|
|
70
|
+
: Array.isArray(lastUser.content)
|
|
71
|
+
? lastUser.content.map((c) => {
|
|
72
|
+
if (typeof c === 'object' && c !== null && 'text' in c) {
|
|
73
|
+
return c.text;
|
|
74
|
+
}
|
|
75
|
+
return '';
|
|
76
|
+
}).join(' ')
|
|
77
|
+
: '';
|
|
78
|
+
const verbCount = countDistinctActionVerbs(text);
|
|
79
|
+
// Trigger if 3+ distinct action verbs and no plan file exists
|
|
80
|
+
if (verbCount >= 3 && !hasPlanFile(process.cwd())) {
|
|
81
|
+
return {
|
|
82
|
+
action: 'warn',
|
|
83
|
+
message: [
|
|
84
|
+
`[workflow-guard] This task involves ${verbCount} distinct actions.`,
|
|
85
|
+
'Consider initialising a plan first: call the `plan` tool with action="init"',
|
|
86
|
+
'or create PLAN.md to break the work into verifiable steps before acting.',
|
|
87
|
+
'Proceeding without a plan — but be mindful of the Verification Contract.',
|
|
88
|
+
].join(' '),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return { action: 'continue' };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=workflow-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-guard.js","sourceRoot":"","sources":["../../../src/agent/middleware/workflow-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RepoProfiler
|
|
3
|
+
*
|
|
4
|
+
* Scans the current repository to detect language, framework, package manager,
|
|
5
|
+
* and build/test commands. Produces a compact contextPack string injected into
|
|
6
|
+
* the agent system prompt to give it awareness of project conventions.
|
|
7
|
+
*
|
|
8
|
+
* Result is cached in .codebuddy/repoProfile.json and invalidated when
|
|
9
|
+
* package.json (or equivalent) changes.
|
|
10
|
+
*/
|
|
11
|
+
export interface RepoProfile {
|
|
12
|
+
detectedAt: string;
|
|
13
|
+
languages: string[];
|
|
14
|
+
framework?: string;
|
|
15
|
+
packageManager?: 'npm' | 'pnpm' | 'yarn' | 'poetry' | 'pip' | 'cargo' | 'dotnet' | 'go';
|
|
16
|
+
commands: {
|
|
17
|
+
test?: string;
|
|
18
|
+
lint?: string;
|
|
19
|
+
format?: string;
|
|
20
|
+
build?: string;
|
|
21
|
+
};
|
|
22
|
+
directories: {
|
|
23
|
+
src?: string;
|
|
24
|
+
tests?: string;
|
|
25
|
+
docs?: string;
|
|
26
|
+
};
|
|
27
|
+
conventions: {
|
|
28
|
+
naming?: string;
|
|
29
|
+
lintRules?: string[];
|
|
30
|
+
};
|
|
31
|
+
/** Compact string injected into agent system prompt */
|
|
32
|
+
contextPack: string;
|
|
33
|
+
/** mtime of the primary config file used for cache invalidation */
|
|
34
|
+
_configMtime?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Profiles a repository to produce structured metadata.
|
|
38
|
+
*/
|
|
39
|
+
export declare class RepoProfiler {
|
|
40
|
+
private cwd;
|
|
41
|
+
private cachePath;
|
|
42
|
+
constructor(cwd?: string);
|
|
43
|
+
/**
|
|
44
|
+
* Get or compute the repo profile.
|
|
45
|
+
* Uses cached result if the primary config file hasn't changed.
|
|
46
|
+
*/
|
|
47
|
+
getProfile(): Promise<RepoProfile>;
|
|
48
|
+
/**
|
|
49
|
+
* Force recompute (ignores cache).
|
|
50
|
+
*/
|
|
51
|
+
refresh(): Promise<RepoProfile>;
|
|
52
|
+
private computeProfile;
|
|
53
|
+
private buildContextPack;
|
|
54
|
+
private loadCache;
|
|
55
|
+
private isCacheStale;
|
|
56
|
+
private saveCache;
|
|
57
|
+
private exists;
|
|
58
|
+
private mtime;
|
|
59
|
+
private glob;
|
|
60
|
+
}
|
|
61
|
+
export declare function getRepoProfiler(cwd?: string): RepoProfiler;
|