closed-loop-cli 1.0.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.
Potentially problematic release.
This version of closed-loop-cli might be problematic. Click here for more details.
- package/dist/dashboard/server.js +237 -0
- package/dist/index.js +272 -0
- package/dist/orchestrator/agent-prompts.js +42 -0
- package/dist/orchestrator/autogenesis.js +973 -0
- package/dist/orchestrator/dgm-archive.js +223 -0
- package/dist/orchestrator/event-stream.js +103 -0
- package/dist/orchestrator/fitness-evaluator.js +99 -0
- package/dist/orchestrator/meta-agent.js +421 -0
- package/dist/orchestrator/microagent-registry.js +134 -0
- package/dist/orchestrator/mutation-strategies.js +174 -0
- package/dist/orchestrator/prompt-benchmark.js +102 -0
- package/dist/orchestrator/prompt-optimizer.js +169 -0
- package/dist/orchestrator/refactor-scanner.js +222 -0
- package/dist/orchestrator/research-manager.js +104 -0
- package/dist/orchestrator/rulez.js +135 -0
- package/dist/orchestrator/sahoo-gateway.js +261 -0
- package/dist/orchestrator/state-manager.js +121 -0
- package/dist/orchestrator/task-agent.js +444 -0
- package/dist/orchestrator/telegram-bot.js +374 -0
- package/dist/orchestrator/types.js +2 -0
- package/dist/tests/dynamic/dependencies.test.js +37 -0
- package/dist/tests/dynamic/dummy.test.js +7 -0
- package/dist/tests/dynamic/fuzzy-patch.test.js +68 -0
- package/dist/tests/dynamic/indexer.test.js +60 -0
- package/dist/tests/dynamic/openhands.test.js +83 -0
- package/dist/tests/dynamic/skills.test.js +88 -0
- package/dist/tests/run-tests.js +294 -0
- package/dist/tools/diff-tools.js +24 -0
- package/dist/tools/file-tools.js +191 -0
- package/dist/tools/indexer.js +301 -0
- package/dist/tools/math-helper.js +6 -0
- package/dist/tools/repo-map.js +122 -0
- package/dist/tools/search-tools.js +271 -0
- package/dist/tools/shell-tools.js +75 -0
- package/dist/tools/skills.js +122 -0
- package/dist/tools/tui-tools.js +82 -0
- package/docs/AI_Arch_Opt_Anti_Gaming.md +227 -0
- package/docs/AI_Self_Improvement_Safety.md +457 -0
- package/docs/Anthropic AI Agents_ Capabilities and Concerns.md +134 -0
- package/docs/Auto_ClosedLoop_AI_Agent.md +415 -0
- package/docs/Autonomous AI Agents_ Closing the Loop.docx +0 -0
- package/docs/Secure_AI_Sandbox_Framework.md +358 -0
- package/docs/skills/add-file-existence-check-utility.json +9 -0
- package/docs/skills/add-utility-function-for-file-existence-check.json +9 -0
- package/docs/skills/add-utility-function-to-module.json +9 -0
- package/docs/skills/extract-command-runner-utility.json +9 -0
- package/docs/skills/file-existence-check-utility.json +9 -0
- package/package.json +36 -0
- package/src/dashboard/public/index.css +1334 -0
- package/src/dashboard/public/index.html +385 -0
- package/src/dashboard/public/index.js +1059 -0
- package/src/dashboard/server.ts +209 -0
- package/src/index.ts +256 -0
- package/src/orchestrator/agent-prompts.ts +43 -0
- package/src/orchestrator/autogenesis.ts +1078 -0
- package/src/orchestrator/dgm-archive.ts +257 -0
- package/src/orchestrator/event-stream.ts +90 -0
- package/src/orchestrator/fitness-evaluator.ts +154 -0
- package/src/orchestrator/meta-agent.ts +434 -0
- package/src/orchestrator/microagent-registry.ts +115 -0
- package/src/orchestrator/microagents/git-helper.md +11 -0
- package/src/orchestrator/microagents/test-fixer.md +10 -0
- package/src/orchestrator/microagents/typescript-expert.md +11 -0
- package/src/orchestrator/mutation-strategies.ts +214 -0
- package/src/orchestrator/research-manager.ts +88 -0
- package/src/orchestrator/rulez.ts +118 -0
- package/src/orchestrator/sahoo-gateway.ts +300 -0
- package/src/orchestrator/state-manager.ts +161 -0
- package/src/orchestrator/system-prompt.txt +1 -0
- package/src/orchestrator/task-agent.ts +461 -0
- package/src/orchestrator/telegram-bot.ts +358 -0
- package/src/tests/dynamic/dependencies.test.ts +48 -0
- package/src/tests/dynamic/dummy.test.ts +4 -0
- package/src/tests/dynamic/fuzzy-patch.test.ts +42 -0
- package/src/tests/dynamic/indexer.test.ts +31 -0
- package/src/tests/dynamic/openhands.test.ts +59 -0
- package/src/tests/dynamic/skills.test.ts +63 -0
- package/src/tests/run-tests.ts +296 -0
- package/src/tools/diff-tools.ts +27 -0
- package/src/tools/file-tools.ts +187 -0
- package/src/tools/indexer.ts +325 -0
- package/src/tools/repo-map.ts +96 -0
- package/src/tools/search-tools.ts +258 -0
- package/src/tools/shell-tools.ts +90 -0
- package/src/tools/skills.ts +101 -0
- package/src/tools/tui-tools.ts +87 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.searchWeb = searchWeb;
|
|
37
|
+
const https = __importStar(require("https"));
|
|
38
|
+
/**
|
|
39
|
+
* Strips HTML tags from a string.
|
|
40
|
+
*/
|
|
41
|
+
function stripHtml(text) {
|
|
42
|
+
return text.replace(/<[^>]*>/g, '').trim();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Decodes common HTML entities.
|
|
46
|
+
*/
|
|
47
|
+
function decodeEntities(text) {
|
|
48
|
+
return text
|
|
49
|
+
.replace(/&/g, '&')
|
|
50
|
+
.replace(/</g, '<')
|
|
51
|
+
.replace(/>/g, '>')
|
|
52
|
+
.replace(/"/g, '"')
|
|
53
|
+
.replace(/'/g, "'")
|
|
54
|
+
.replace(///g, '/')
|
|
55
|
+
.replace(/'/g, "'");
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Formats results list into a readable string.
|
|
59
|
+
*/
|
|
60
|
+
function formatResults(query, results, source) {
|
|
61
|
+
let formatted = `Web search results (via ${source}) for: "${query}"\n\n`;
|
|
62
|
+
results.forEach((res, index) => {
|
|
63
|
+
formatted += `${index + 1}. ${res.title}\n`;
|
|
64
|
+
formatted += ` URL: ${res.link}\n`;
|
|
65
|
+
formatted += ` Snippet: ${res.snippet}\n\n`;
|
|
66
|
+
});
|
|
67
|
+
return formatted.trim();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Searches the web using DuckDuckGo Lite POST interface, falling back to DDG JSON and Wikipedia APIs on failure.
|
|
71
|
+
*/
|
|
72
|
+
async function searchWeb(query) {
|
|
73
|
+
// 1. Try DuckDuckGo Lite POST
|
|
74
|
+
try {
|
|
75
|
+
const results = await fetchDuckDuckGoLite(query);
|
|
76
|
+
if (results.length > 0) {
|
|
77
|
+
return formatResults(query, results, 'DuckDuckGo Lite');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
// Ignore and try next fallback
|
|
82
|
+
}
|
|
83
|
+
// 2. Try DuckDuckGo Instant Answer JSON API
|
|
84
|
+
try {
|
|
85
|
+
const results = await fetchDuckDuckGoApi(query);
|
|
86
|
+
if (results.length > 0) {
|
|
87
|
+
return formatResults(query, results, 'DuckDuckGo API');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
// Ignore and try next fallback
|
|
92
|
+
}
|
|
93
|
+
// 3. Try Wikipedia Search API
|
|
94
|
+
try {
|
|
95
|
+
const results = await fetchWikipedia(query);
|
|
96
|
+
if (results.length > 0) {
|
|
97
|
+
return formatResults(query, results, 'Wikipedia');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
// Ignore
|
|
102
|
+
}
|
|
103
|
+
return `No search results found for: "${query}". (Web search services are currently rate-limited or unavailable).`;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* DuckDuckGo Lite Scraper
|
|
107
|
+
*/
|
|
108
|
+
function fetchDuckDuckGoLite(query) {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
const encodedQuery = encodeURIComponent(query);
|
|
111
|
+
const postData = `q=${encodedQuery}`;
|
|
112
|
+
const options = {
|
|
113
|
+
hostname: 'lite.duckduckgo.com',
|
|
114
|
+
port: 443,
|
|
115
|
+
path: '/lite/',
|
|
116
|
+
method: 'POST',
|
|
117
|
+
headers: {
|
|
118
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
119
|
+
'Content-Length': Buffer.byteLength(postData),
|
|
120
|
+
'User-Agent': 'ClosedLoopCodingAgent/1.0 (contact: akara@example.com)',
|
|
121
|
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
122
|
+
'Accept-Language': 'en-US,en;q=0.5'
|
|
123
|
+
},
|
|
124
|
+
timeout: 6000
|
|
125
|
+
};
|
|
126
|
+
const req = https.request(options, (res) => {
|
|
127
|
+
if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) {
|
|
128
|
+
return reject(new Error(`Status ${res.statusCode}`));
|
|
129
|
+
}
|
|
130
|
+
let data = '';
|
|
131
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
132
|
+
res.on('end', () => {
|
|
133
|
+
try {
|
|
134
|
+
const results = parseDuckDuckGoLiteHTML(data);
|
|
135
|
+
resolve(results);
|
|
136
|
+
}
|
|
137
|
+
catch (e) {
|
|
138
|
+
reject(e);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
req.on('error', (err) => reject(err));
|
|
143
|
+
req.on('timeout', () => {
|
|
144
|
+
req.destroy();
|
|
145
|
+
reject(new Error('Timeout'));
|
|
146
|
+
});
|
|
147
|
+
req.write(postData);
|
|
148
|
+
req.end();
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function parseDuckDuckGoLiteHTML(html) {
|
|
152
|
+
const results = [];
|
|
153
|
+
const resultRegex = /<a[^>]+href="([^"]+)"[^>]+class='result-link'[^>]*>([\s\S]*?)<\/a>[\s\S]*?class='result-snippet'[^>]*>([\s\S]*?)<\/td>/gi;
|
|
154
|
+
let match;
|
|
155
|
+
while ((match = resultRegex.exec(html)) !== null && results.length < 8) {
|
|
156
|
+
const rawLink = match[1];
|
|
157
|
+
const title = decodeEntities(stripHtml(match[2]));
|
|
158
|
+
const snippet = decodeEntities(stripHtml(match[3]));
|
|
159
|
+
if (!title || !snippet)
|
|
160
|
+
continue;
|
|
161
|
+
let link = rawLink;
|
|
162
|
+
if (link.startsWith('//')) {
|
|
163
|
+
link = 'https:' + link;
|
|
164
|
+
}
|
|
165
|
+
if (link.includes('uddg=')) {
|
|
166
|
+
const uddgMatch = link.match(/uddg=([^&]+)/);
|
|
167
|
+
if (uddgMatch) {
|
|
168
|
+
link = decodeURIComponent(uddgMatch[1]);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
results.push({ title, link, snippet });
|
|
172
|
+
}
|
|
173
|
+
return results;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* DuckDuckGo Instant Answer API
|
|
177
|
+
*/
|
|
178
|
+
function fetchDuckDuckGoApi(query) {
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
const encodedQuery = encodeURIComponent(query);
|
|
181
|
+
const url = `https://api.duckduckgo.com/?q=${encodedQuery}&format=json&no_html=1&skip_disambig=1`;
|
|
182
|
+
const options = {
|
|
183
|
+
headers: {
|
|
184
|
+
'User-Agent': 'ClosedLoopCodingAgent/1.0 (contact: akara@example.com)'
|
|
185
|
+
},
|
|
186
|
+
timeout: 5000
|
|
187
|
+
};
|
|
188
|
+
https.get(url, options, (res) => {
|
|
189
|
+
if (res.statusCode !== 200) {
|
|
190
|
+
return reject(new Error(`Status ${res.statusCode}`));
|
|
191
|
+
}
|
|
192
|
+
let data = '';
|
|
193
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
194
|
+
res.on('end', () => {
|
|
195
|
+
try {
|
|
196
|
+
const json = JSON.parse(data);
|
|
197
|
+
const results = [];
|
|
198
|
+
if (json.AbstractText && json.AbstractURL) {
|
|
199
|
+
results.push({
|
|
200
|
+
title: json.Heading || query,
|
|
201
|
+
link: json.AbstractURL,
|
|
202
|
+
snippet: json.AbstractText
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
if (json.RelatedTopics && Array.isArray(json.RelatedTopics)) {
|
|
206
|
+
for (const topic of json.RelatedTopics) {
|
|
207
|
+
if (results.length >= 5)
|
|
208
|
+
break;
|
|
209
|
+
if (topic.Text && topic.FirstURL) {
|
|
210
|
+
results.push({
|
|
211
|
+
title: topic.Text.split(' - ')[0] || 'Topic Details',
|
|
212
|
+
link: topic.FirstURL,
|
|
213
|
+
snippet: topic.Text
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
resolve(results);
|
|
219
|
+
}
|
|
220
|
+
catch (e) {
|
|
221
|
+
reject(e);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}).on('error', (err) => reject(err));
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Wikipedia Search API
|
|
229
|
+
*/
|
|
230
|
+
function fetchWikipedia(query) {
|
|
231
|
+
return new Promise((resolve, reject) => {
|
|
232
|
+
const encodedQuery = encodeURIComponent(query);
|
|
233
|
+
const url = `https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=${encodedQuery}&format=json&origin=*`;
|
|
234
|
+
const options = {
|
|
235
|
+
headers: {
|
|
236
|
+
'User-Agent': 'ClosedLoopCodingAgent/1.0 (contact: akara@example.com)'
|
|
237
|
+
},
|
|
238
|
+
timeout: 5000
|
|
239
|
+
};
|
|
240
|
+
https.get(url, options, (res) => {
|
|
241
|
+
if (res.statusCode !== 200) {
|
|
242
|
+
return reject(new Error(`Status ${res.statusCode}`));
|
|
243
|
+
}
|
|
244
|
+
let data = '';
|
|
245
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
246
|
+
res.on('end', () => {
|
|
247
|
+
try {
|
|
248
|
+
const json = JSON.parse(data);
|
|
249
|
+
const results = [];
|
|
250
|
+
if (json.query && Array.isArray(json.query.search)) {
|
|
251
|
+
for (const item of json.query.search) {
|
|
252
|
+
if (results.length >= 8)
|
|
253
|
+
break;
|
|
254
|
+
const link = `https://en.wikipedia.org/wiki/${encodeURIComponent(item.title.replace(/ /g, '_'))}`;
|
|
255
|
+
const snippet = stripHtml(item.snippet);
|
|
256
|
+
results.push({
|
|
257
|
+
title: item.title,
|
|
258
|
+
link,
|
|
259
|
+
snippet
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
resolve(results);
|
|
264
|
+
}
|
|
265
|
+
catch (e) {
|
|
266
|
+
reject(e);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}).on('error', (err) => reject(err));
|
|
270
|
+
});
|
|
271
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runCommand = runCommand;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
/**
|
|
6
|
+
* Executes a terminal command within a specified working directory.
|
|
7
|
+
* Supports interactive stdin input streams and streams output in real-time.
|
|
8
|
+
* Safely caps execution time using a timeout.
|
|
9
|
+
*/
|
|
10
|
+
function runCommand(command, cwd = process.cwd(), timeoutMs = 120000 // 2 minutes timeout
|
|
11
|
+
) {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
const isWindows = process.platform === 'win32';
|
|
14
|
+
const shell = isWindows ? 'cmd.exe' : '/bin/sh';
|
|
15
|
+
const args = isWindows ? ['/d', '/s', '/c', command] : ['-c', command];
|
|
16
|
+
let stdoutData = '';
|
|
17
|
+
let stderrData = '';
|
|
18
|
+
let isFinished = false;
|
|
19
|
+
// Spawn child with stdin inherited so standard keyboard input goes through
|
|
20
|
+
const child = (0, child_process_1.spawn)(shell, args, {
|
|
21
|
+
cwd,
|
|
22
|
+
windowsVerbatimArguments: isWindows,
|
|
23
|
+
stdio: ['inherit', 'pipe', 'pipe']
|
|
24
|
+
});
|
|
25
|
+
const timeout = setTimeout(() => {
|
|
26
|
+
if (!isFinished) {
|
|
27
|
+
isFinished = true;
|
|
28
|
+
try {
|
|
29
|
+
child.kill('SIGKILL');
|
|
30
|
+
}
|
|
31
|
+
catch (e) { }
|
|
32
|
+
resolve({
|
|
33
|
+
stdout: stdoutData,
|
|
34
|
+
stderr: stderrData,
|
|
35
|
+
exitCode: 1,
|
|
36
|
+
error: `Command timed out after ${timeoutMs}ms.`
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}, timeoutMs);
|
|
40
|
+
child.stdout.on('data', (data) => {
|
|
41
|
+
const chunk = data.toString();
|
|
42
|
+
stdoutData += chunk;
|
|
43
|
+
process.stdout.write(chunk);
|
|
44
|
+
});
|
|
45
|
+
child.stderr.on('data', (data) => {
|
|
46
|
+
const chunk = data.toString();
|
|
47
|
+
stderrData += chunk;
|
|
48
|
+
process.stderr.write(chunk);
|
|
49
|
+
});
|
|
50
|
+
child.on('error', (err) => {
|
|
51
|
+
if (!isFinished) {
|
|
52
|
+
isFinished = true;
|
|
53
|
+
clearTimeout(timeout);
|
|
54
|
+
resolve({
|
|
55
|
+
stdout: stdoutData,
|
|
56
|
+
stderr: stderrData,
|
|
57
|
+
exitCode: 1,
|
|
58
|
+
error: err.message
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
child.on('close', (code) => {
|
|
63
|
+
if (!isFinished) {
|
|
64
|
+
isFinished = true;
|
|
65
|
+
clearTimeout(timeout);
|
|
66
|
+
resolve({
|
|
67
|
+
stdout: stdoutData,
|
|
68
|
+
stderr: stderrData,
|
|
69
|
+
exitCode: code,
|
|
70
|
+
error: code !== 0 ? `Command exited with code ${code}` : undefined
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.extractAndSaveSkill = extractAndSaveSkill;
|
|
40
|
+
exports.getSkillsSummary = getSkillsSummary;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
44
|
+
const dotenv = __importStar(require("dotenv"));
|
|
45
|
+
dotenv.config();
|
|
46
|
+
const apiKey = process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN || '';
|
|
47
|
+
const baseURL = process.env.ANTHROPIC_BASE_URL || undefined;
|
|
48
|
+
const defaultModel = process.env.ANTHROPIC_MODEL || 'mimo-v2.5-pro[1m]';
|
|
49
|
+
/**
|
|
50
|
+
* Summarizes the recent successful evolution step and saves it to docs/skills/
|
|
51
|
+
*/
|
|
52
|
+
async function extractAndSaveSkill(task, diffText) {
|
|
53
|
+
const workspaceRoot = process.cwd();
|
|
54
|
+
const skillsDir = path.join(workspaceRoot, 'docs', 'skills');
|
|
55
|
+
if (!fs.existsSync(skillsDir)) {
|
|
56
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
const anthropic = new sdk_1.default({
|
|
59
|
+
apiKey: apiKey,
|
|
60
|
+
baseURL: baseURL,
|
|
61
|
+
});
|
|
62
|
+
const prompt = `You are a technical documenter. Your task is to analyze the user's refactoring/coding task and the successful git diff, then extract a general reusable development recipe/skill.
|
|
63
|
+
|
|
64
|
+
Task: "${task}"
|
|
65
|
+
|
|
66
|
+
Git Diff:
|
|
67
|
+
"""
|
|
68
|
+
${diffText}
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
Output your response strictly as a JSON object of a reusable playbook. Do not write any markdown wrappers (like \`\`\`json or \`\`\`), greetings, or conversational headers/footers. Output ONLY the raw JSON.
|
|
72
|
+
|
|
73
|
+
Format:
|
|
74
|
+
{
|
|
75
|
+
"id": "hyphenated-lowercase-slug-id",
|
|
76
|
+
"title": "Clear Action-Oriented Title",
|
|
77
|
+
"description": "Concise summary of what this recipe achieves",
|
|
78
|
+
"filesModified": ["src/relative/path/to/file.ts"],
|
|
79
|
+
"recipe": "Step-by-step general instructions of the technique used, focusing on design patterns, APIs, and syntax."
|
|
80
|
+
}`;
|
|
81
|
+
try {
|
|
82
|
+
const response = await anthropic.messages.create({
|
|
83
|
+
model: defaultModel,
|
|
84
|
+
max_tokens: 1500,
|
|
85
|
+
messages: [{ role: 'user', content: prompt }]
|
|
86
|
+
});
|
|
87
|
+
const block = response.content.find(b => b.type === 'text');
|
|
88
|
+
if (block && block.text) {
|
|
89
|
+
const text = block.text.trim().replace(/^```json/, '').replace(/```$/, '').trim();
|
|
90
|
+
const recipe = JSON.parse(text);
|
|
91
|
+
const fileName = `${recipe.id}.json`;
|
|
92
|
+
fs.writeFileSync(path.join(skillsDir, fileName), JSON.stringify(recipe, null, 2), 'utf-8');
|
|
93
|
+
console.log(`\n\x1b[32m[Skill Registry] Reusable skill saved successfully to docs/skills/${fileName}\x1b[0m`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
console.error(`\x1b[31m[Skill Registry] Failed to extract skill: ${err.message}\x1b[0m`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Returns a concatenated summary of all available skills for prompt context.
|
|
102
|
+
*/
|
|
103
|
+
function getSkillsSummary() {
|
|
104
|
+
const workspaceRoot = process.cwd();
|
|
105
|
+
const skillsDir = path.join(workspaceRoot, 'docs', 'skills');
|
|
106
|
+
if (!fs.existsSync(skillsDir)) {
|
|
107
|
+
return 'No custom development skills recorded yet.';
|
|
108
|
+
}
|
|
109
|
+
const files = fs.readdirSync(skillsDir).filter(f => f.endsWith('.json'));
|
|
110
|
+
if (files.length === 0) {
|
|
111
|
+
return 'No custom development skills recorded yet.';
|
|
112
|
+
}
|
|
113
|
+
const summaries = [];
|
|
114
|
+
for (const file of files) {
|
|
115
|
+
try {
|
|
116
|
+
const recipe = JSON.parse(fs.readFileSync(path.join(skillsDir, file), 'utf-8'));
|
|
117
|
+
summaries.push(`- **${recipe.title}** (${recipe.id}): ${recipe.description}\n Recipe: ${recipe.recipe}`);
|
|
118
|
+
}
|
|
119
|
+
catch (e) { }
|
|
120
|
+
}
|
|
121
|
+
return summaries.join('\n\n');
|
|
122
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Spinner = void 0;
|
|
4
|
+
exports.printAgentHeader = printAgentHeader;
|
|
5
|
+
exports.printCollapsibleBlock = printCollapsibleBlock;
|
|
6
|
+
class Spinner {
|
|
7
|
+
timer = null;
|
|
8
|
+
frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
9
|
+
currentFrame = 0;
|
|
10
|
+
message;
|
|
11
|
+
isStarted = false;
|
|
12
|
+
constructor(message) {
|
|
13
|
+
this.message = message;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Starts the spinner animation in the terminal.
|
|
17
|
+
* Hides the terminal cursor for a cleaner look.
|
|
18
|
+
*/
|
|
19
|
+
start() {
|
|
20
|
+
if (this.isStarted)
|
|
21
|
+
return;
|
|
22
|
+
this.isStarted = true;
|
|
23
|
+
// Hide cursor
|
|
24
|
+
process.stdout.write('\x1b[?25l');
|
|
25
|
+
this.timer = setInterval(() => {
|
|
26
|
+
const frame = this.frames[this.currentFrame];
|
|
27
|
+
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
|
|
28
|
+
// Clear line and write spinner frame with cyan color
|
|
29
|
+
process.stdout.write(`\r\x1b[36m${frame}\x1b[0m ${this.message}`);
|
|
30
|
+
}, 80);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Updates the message text displayed alongside the spinner.
|
|
34
|
+
*/
|
|
35
|
+
update(newMessage) {
|
|
36
|
+
this.message = newMessage;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Stops the spinner and shows the terminal cursor again.
|
|
40
|
+
* Prints the final status indicator (green checkmark or red X).
|
|
41
|
+
*/
|
|
42
|
+
stop(success = true, finalMessage) {
|
|
43
|
+
if (!this.isStarted)
|
|
44
|
+
return;
|
|
45
|
+
this.isStarted = false;
|
|
46
|
+
if (this.timer) {
|
|
47
|
+
clearInterval(this.timer);
|
|
48
|
+
this.timer = null;
|
|
49
|
+
}
|
|
50
|
+
const msg = finalMessage || this.message;
|
|
51
|
+
const symbol = success ? '\x1b[32m✔\x1b[0m' : '\x1b[31m✖\x1b[0m';
|
|
52
|
+
// Clear spinner line, write final result, and restore cursor
|
|
53
|
+
process.stdout.write(`\r${symbol} ${msg}\n\x1b[?25h`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.Spinner = Spinner;
|
|
57
|
+
/**
|
|
58
|
+
* Prints a beautiful styled header block for the currently active agent.
|
|
59
|
+
*/
|
|
60
|
+
function printAgentHeader(agentRole) {
|
|
61
|
+
const roles = {
|
|
62
|
+
architect: { title: 'ARCHITECT / PLANNER', color: '\x1b[35;1m', emoji: '📐' }, // bold magenta
|
|
63
|
+
coder: { title: 'CODER / IMPLEMENTOR', color: '\x1b[32;1m', emoji: '💻' }, // bold green
|
|
64
|
+
debugger: { title: 'DIAGNOSTICS & DEBUGGER', color: '\x1b[33;1m', emoji: '🔧' }, // bold yellow
|
|
65
|
+
gatekeeper: { title: 'GATEKEEPER & REVIEWER', color: '\x1b[36;1m', emoji: '🛡️' } // bold cyan
|
|
66
|
+
};
|
|
67
|
+
const details = roles[agentRole.toLowerCase()] || { title: agentRole.toUpperCase(), color: '\x1b[37;1m', emoji: '🤖' };
|
|
68
|
+
const border = '='.repeat(60);
|
|
69
|
+
console.log(`\n${details.color}${border}\x1b[0m`);
|
|
70
|
+
console.log(`${details.color} ${details.emoji} ${details.title}\x1b[0m`);
|
|
71
|
+
console.log(`${details.color}${border}\x1b[0m\n`);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Renders block contents inside a beautiful box layout with color accents.
|
|
75
|
+
*/
|
|
76
|
+
function printCollapsibleBlock(title, content, color = '\x1b[34m') {
|
|
77
|
+
console.log(`${color}┌── ${title} ───────────────────────────────────────────────────────────────┐\x1b[0m`);
|
|
78
|
+
content.split('\n').forEach(line => {
|
|
79
|
+
console.log(`${color}│\x1b[0m ${line}`);
|
|
80
|
+
});
|
|
81
|
+
console.log(`${color}└───────────────────────────────────────────────────────────────────────────────┘\x1b[0m\n`);
|
|
82
|
+
}
|