@ddtcorex/dsh-maestro-supervisor 0.5.1 → 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 +60 -20
- package/package.json +1 -1
package/lib/debug-agent.js
CHANGED
|
@@ -203,17 +203,17 @@ async function defaultDryBoot() {
|
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
async function defaultFetchLLM(prompt) {
|
|
206
|
-
const
|
|
207
|
-
if (!key)
|
|
208
|
-
throw new Error('no api key — set DEEPSEEK_API_KEY or ~/.dsh/.credentials.yaml');
|
|
209
|
-
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, {
|
|
210
210
|
method: 'POST',
|
|
211
211
|
headers: {
|
|
212
212
|
'Content-Type': 'application/json',
|
|
213
|
-
'Authorization': `Bearer ${key}`,
|
|
213
|
+
'Authorization': `Bearer ${cfg.key}`,
|
|
214
214
|
},
|
|
215
215
|
body: JSON.stringify({
|
|
216
|
-
model:
|
|
216
|
+
model: cfg.model,
|
|
217
217
|
temperature: 0.2,
|
|
218
218
|
messages: [
|
|
219
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.' },
|
|
@@ -226,25 +226,65 @@ async function defaultFetchLLM(prompt) {
|
|
|
226
226
|
const j = await res.json();
|
|
227
227
|
return j.choices?.[0]?.message?.content ?? JSON.stringify(j);
|
|
228
228
|
}
|
|
229
|
-
async function
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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';
|
|
234
241
|
try {
|
|
235
242
|
const { readFileSync } = await import('node:fs');
|
|
236
243
|
const { homedir } = await import('node:os');
|
|
237
|
-
const
|
|
238
|
-
const
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (
|
|
244
|
-
|
|
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;
|
|
245
252
|
}
|
|
246
253
|
catch { }
|
|
247
|
-
|
|
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;
|
|
248
288
|
}
|
|
249
289
|
export function _resetDebugAgentForTest() {
|
|
250
290
|
lastRun = 0;
|