@ddtcorex/dsh-maestro-supervisor 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/debug-agent.js +62 -21
- package/package.json +1 -1
package/lib/debug-agent.js
CHANGED
|
@@ -193,7 +193,8 @@ async function defaultDryBoot() {
|
|
|
193
193
|
const { execSync } = await import('node:child_process');
|
|
194
194
|
const tmp = execSync('mktemp -d', { encoding: 'utf-8' }).trim();
|
|
195
195
|
const port = Math.floor(19000 + Math.random() * 1000);
|
|
196
|
-
|
|
196
|
+
// Use spawn-based dry-boot to avoid nested quoting hell (prev \\$! / \\$(seq) caused syntax error)
|
|
197
|
+
const out = execSync(`timeout 8 bash -c 'DSH_HOME=${tmp} pnpm --dir /home/kai/Work/htdocs/maestro-harness/deepseek-harness dsh web --port ${port} --no-open >${tmp}/dsh.log 2>&1 & pid=$!; for i in $(seq 1 5); do sleep 1; if curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:${port}/ 2>&1 | grep -q 200; then kill $pid 2>/dev/null || true; wait $pid 2>/dev/null || true; echo ok; exit 0; fi; done; kill $pid 2>/dev/null || true; wait $pid 2>/dev/null || true; echo fail; exit 1'`, { encoding: 'utf-8', timeout: 12000 });
|
|
197
198
|
execSync(`rm -rf ${tmp}`);
|
|
198
199
|
return out.includes('ok');
|
|
199
200
|
}
|
|
@@ -202,17 +203,17 @@ async function defaultDryBoot() {
|
|
|
202
203
|
}
|
|
203
204
|
}
|
|
204
205
|
async function defaultFetchLLM(prompt) {
|
|
205
|
-
const
|
|
206
|
-
if (!key)
|
|
207
|
-
throw new Error('no api key — set DEEPSEEK_API_KEY or ~/.dsh/.credentials.yaml');
|
|
208
|
-
const res = await fetch(
|
|
206
|
+
const cfg = await resolveLLMConfig();
|
|
207
|
+
if (!cfg.key)
|
|
208
|
+
throw new Error('no api key — set DEEPSEEK_API_KEY / OMNI_ROUTE_API_KEY / OPENCODE_GO_API_KEY / OPENAI_API_KEY or ~/.dsh/.credentials.yaml or AI_API_KEY');
|
|
209
|
+
const res = await fetch(cfg.url, {
|
|
209
210
|
method: 'POST',
|
|
210
211
|
headers: {
|
|
211
212
|
'Content-Type': 'application/json',
|
|
212
|
-
'Authorization': `Bearer ${key}`,
|
|
213
|
+
'Authorization': `Bearer ${cfg.key}`,
|
|
213
214
|
},
|
|
214
215
|
body: JSON.stringify({
|
|
215
|
-
model:
|
|
216
|
+
model: cfg.model,
|
|
216
217
|
temperature: 0.2,
|
|
217
218
|
messages: [
|
|
218
219
|
{ role: 'system', content: 'You are a systematic-debugging agent for DSH Web resilience. Follow the 4 phases: root cause, pattern analysis, hypothesis, implementation. Always propose minimal single-file fix.' },
|
|
@@ -225,25 +226,65 @@ async function defaultFetchLLM(prompt) {
|
|
|
225
226
|
const j = await res.json();
|
|
226
227
|
return j.choices?.[0]?.message?.content ?? JSON.stringify(j);
|
|
227
228
|
}
|
|
228
|
-
async function
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
229
|
+
async function resolveLLMConfig() {
|
|
230
|
+
// Custom AI provider: env overrides, then credentials.yaml, then settings.json, then defaults
|
|
231
|
+
// Url: AI_API_URL / DEEPSEEK_API_URL / OPENAI_API_BASE / OMNI_ROUTE_API_URL -> default deepseek
|
|
232
|
+
const url = process.env.AI_API_URL ??
|
|
233
|
+
process.env.DEAPSEEK_API_URL ??
|
|
234
|
+
process.env.DEEPSEEK_API_URL ??
|
|
235
|
+
process.env.OPENAI_API_BASE ??
|
|
236
|
+
process.env.OMNI_ROUTE_API_URL ??
|
|
237
|
+
process.env.OPENCODE_API_URL ??
|
|
238
|
+
'https://api.deepseek.com/v1/chat/completions';
|
|
239
|
+
// Model: AI_MODEL / DEEPSEEK_MODEL / settings.json domains.review.model
|
|
240
|
+
let model = process.env.AI_MODEL ?? process.env.DEEPSEEK_MODEL ?? process.env.OPENAI_MODEL ?? 'deepseek-chat';
|
|
233
241
|
try {
|
|
234
242
|
const { readFileSync } = await import('node:fs');
|
|
235
243
|
const { homedir } = await import('node:os');
|
|
236
|
-
const
|
|
237
|
-
const
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
+
const settingsPath = `${homedir()}/.dsh/maestro/settings.json`;
|
|
245
|
+
const raw = readFileSync(settingsPath, 'utf-8');
|
|
246
|
+
const j = JSON.parse(raw);
|
|
247
|
+
const m = j?.domains?.review?.model?.model ?? j?.domains?.review?.model;
|
|
248
|
+
if (typeof m === 'string' && !process.env.AI_MODEL && !process.env.DEEPSEEK_MODEL)
|
|
249
|
+
model = m;
|
|
250
|
+
else if (m?.model && typeof m.model === 'string' && !process.env.AI_MODEL)
|
|
251
|
+
model = m.model;
|
|
244
252
|
}
|
|
245
253
|
catch { }
|
|
246
|
-
|
|
254
|
+
// Key: AI_API_KEY / DEEPSEEK_API_KEY / OMNI_ROUTE_API_KEY / OPENCODE_GO_API_KEY / OPENAI_API_KEY
|
|
255
|
+
let key = process.env.AI_API_KEY ??
|
|
256
|
+
process.env.DEEPSEEK_API_KEY ??
|
|
257
|
+
process.env.OMNI_ROUTE_API_KEY ??
|
|
258
|
+
process.env.OPENCODE_GO_API_KEY ??
|
|
259
|
+
process.env.OPENAI_API_KEY ??
|
|
260
|
+
null;
|
|
261
|
+
if (!key) {
|
|
262
|
+
try {
|
|
263
|
+
const { readFileSync } = await import('node:fs');
|
|
264
|
+
const { homedir } = await import('node:os');
|
|
265
|
+
const p = `${homedir()}/.dsh/.credentials.yaml`;
|
|
266
|
+
const content = readFileSync(p, 'utf-8');
|
|
267
|
+
const keys = ['AI_API_KEY', 'DEEPSEEK_API_KEY', 'OMNI_ROUTE_API_KEY', 'OPENCODE_GO_API_KEY', 'OPENAI_API_KEY'];
|
|
268
|
+
for (const k of keys) {
|
|
269
|
+
const m = content.match(new RegExp(`${k}:\\s*["']?([^"'\\n]+)["']?`));
|
|
270
|
+
if (m) {
|
|
271
|
+
key = m[1].trim();
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch { }
|
|
277
|
+
}
|
|
278
|
+
// If url is base without /v1/chat/completions, append
|
|
279
|
+
let finalUrl = url;
|
|
280
|
+
if (!url.includes('/v1/') && !url.includes('/chat/completions')) {
|
|
281
|
+
finalUrl = url.replace(/\/$/, '') + '/v1/chat/completions';
|
|
282
|
+
}
|
|
283
|
+
return { key, url: finalUrl, model };
|
|
284
|
+
}
|
|
285
|
+
async function resolveApiKey() {
|
|
286
|
+
const cfg = await resolveLLMConfig();
|
|
287
|
+
return cfg.key;
|
|
247
288
|
}
|
|
248
289
|
export function _resetDebugAgentForTest() {
|
|
249
290
|
lastRun = 0;
|