@ddtcorex/dsh-maestro-supervisor 0.6.2 → 0.6.4
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/cli.js +66 -6
- package/lib/debug-agent.js +15 -6
- package/package.json +1 -1
package/lib/cli.js
CHANGED
|
@@ -106,19 +106,79 @@ Commands:
|
|
|
106
106
|
return writeReport({ reportsRoot, ts, health, gitDiff: diff, logTail: tail, action });
|
|
107
107
|
},
|
|
108
108
|
rollback: async () => {
|
|
109
|
-
|
|
109
|
+
const { execSync } = await import('node:child_process');
|
|
110
110
|
const entries = fs.existsSync(lkgRoot) ? fs.readdirSync(lkgRoot).sort() : [];
|
|
111
111
|
if (!entries.length)
|
|
112
112
|
throw new Error('no LKG to rollback to');
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
// Try newest to oldest (up to 3) to find a clean LKG for plugin failures
|
|
114
|
+
// Extract failing plugin from current log tail if possible
|
|
115
|
+
let failingPlugin;
|
|
116
|
+
try {
|
|
117
|
+
const tail = fs.readFileSync(path.join(os.homedir(), '.dsh/dsh-web.log'), 'utf8').slice(-5000);
|
|
118
|
+
const m = tail.match(/@ddtcorex\/dsh-maestro-[a-z0-9_-]+/i) ?? tail.match(/dsh-maestro-[a-z0-9_-]+/i);
|
|
119
|
+
if (m)
|
|
120
|
+
failingPlugin = m[0].replace(/^@ddtcorex\//, '');
|
|
121
|
+
}
|
|
122
|
+
catch { }
|
|
123
|
+
const candidates = [...entries].reverse().slice(0, 3);
|
|
124
|
+
let chosen;
|
|
125
|
+
for (const cand of candidates) {
|
|
126
|
+
if (!failingPlugin) {
|
|
127
|
+
chosen = cand;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const pkgPath = path.join(lkgRoot, cand, 'profiles/web/package.json');
|
|
132
|
+
if (!fs.existsSync(pkgPath)) {
|
|
133
|
+
chosen = cand;
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
137
|
+
const bundles = pkg?.dsh?.profile?.bundles ?? [];
|
|
138
|
+
const deps = pkg?.dependencies ?? {};
|
|
139
|
+
const hasFailing = bundles.some((b) => b.includes(failingPlugin)) || Object.keys(deps).some(k => k.includes(failingPlugin));
|
|
140
|
+
if (!hasFailing) {
|
|
141
|
+
chosen = cand;
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
console.log(`[supervisor] skipping LKG ${cand} still contains failing plugin ${failingPlugin}`);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
chosen = cand;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const target = chosen ?? entries[entries.length - 1];
|
|
152
|
+
const src = path.join(lkgRoot, target);
|
|
116
153
|
for (const entry of fs.readdirSync(src)) {
|
|
117
154
|
if (entry === 'manifest.json')
|
|
118
155
|
continue;
|
|
119
|
-
|
|
156
|
+
const srcPath = path.join(src, entry);
|
|
157
|
+
const destPath = path.join(dshHome, entry);
|
|
158
|
+
try {
|
|
159
|
+
// Skip if src and dest are the same file (e.g. symlink to same target like ~/.dsh/AGENTS.md)
|
|
160
|
+
try {
|
|
161
|
+
if (fs.existsSync(srcPath) && fs.existsSync(destPath) && fs.realpathSync(srcPath) === fs.realpathSync(destPath))
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
catch { }
|
|
165
|
+
fs.cpSync(srcPath, destPath, { recursive: true, force: true });
|
|
166
|
+
}
|
|
167
|
+
catch (e) {
|
|
168
|
+
if (String(e?.message ?? '').includes('cannot be the same'))
|
|
169
|
+
continue;
|
|
170
|
+
throw e;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
console.log(`[supervisor] rolled back to ${target}${failingPlugin ? ` (avoiding ${failingPlugin})` : ''}`);
|
|
174
|
+
// Reconcile node_modules from restored package.json (critical for link: deps)
|
|
175
|
+
try {
|
|
176
|
+
execSync('pnpm --dir ~/.dsh/profiles/web install --silent', { timeout: 30000, stdio: 'pipe' });
|
|
177
|
+
console.log('[supervisor] pnpm install reconciled profiles/web');
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
console.log(`[supervisor] pnpm install failed: ${e?.message ?? String(e)}`);
|
|
120
181
|
}
|
|
121
|
-
console.log(`[supervisor] rolled back to ${latest}`);
|
|
122
182
|
},
|
|
123
183
|
restartWeb: async () => {
|
|
124
184
|
const { execSync } = await import('node:child_process');
|
package/lib/debug-agent.js
CHANGED
|
@@ -316,9 +316,9 @@ async function resolveLLMConfig() {
|
|
|
316
316
|
process.env.OMNI_ROUTE_API_URL ??
|
|
317
317
|
process.env.OPENCODE_API_URL ??
|
|
318
318
|
null;
|
|
319
|
-
// Model: AI_MODEL / DEEPSEEK_MODEL / settings.json domains.review.model / default
|
|
319
|
+
// Model: AI_MODEL / DEEPSEEK_MODEL / settings.json domains.supervisor.model -> domains.review.model / default
|
|
320
|
+
// Supervisor has its own picker; falls back to review model for backward compat, then DSH default.
|
|
320
321
|
let model = process.env.AI_MODEL ?? process.env.DEEPSEEK_MODEL ?? process.env.OPENAI_MODEL ?? null;
|
|
321
|
-
// Try settings.json first (review model is the user's current default model)
|
|
322
322
|
if (!model) {
|
|
323
323
|
try {
|
|
324
324
|
const { readFileSync } = await import('node:fs');
|
|
@@ -326,11 +326,20 @@ async function resolveLLMConfig() {
|
|
|
326
326
|
const settingsPath = `${homedir()}/.dsh/maestro/settings.json`;
|
|
327
327
|
const raw = readFileSync(settingsPath, 'utf-8');
|
|
328
328
|
const j = JSON.parse(raw);
|
|
329
|
-
|
|
330
|
-
|
|
329
|
+
// Prefer supervisor model, fall back to review model (so old installs keep working)
|
|
330
|
+
const sup = j?.domains?.supervisor?.model?.model ?? j?.domains?.supervisor?.model;
|
|
331
|
+
const rev = j?.domains?.review?.model?.model ?? j?.domains?.review?.model;
|
|
332
|
+
let m = null;
|
|
333
|
+
if (typeof sup === 'string')
|
|
334
|
+
m = sup;
|
|
335
|
+
else if (sup?.model && typeof sup.model === 'string')
|
|
336
|
+
m = sup.model;
|
|
337
|
+
else if (typeof rev === 'string')
|
|
338
|
+
m = rev;
|
|
339
|
+
else if (rev?.model && typeof rev.model === 'string')
|
|
340
|
+
m = rev.model;
|
|
341
|
+
if (typeof m === 'string' && m.trim() !== '')
|
|
331
342
|
model = m;
|
|
332
|
-
else if (m?.model && typeof m.model === 'string')
|
|
333
|
-
model = m.model;
|
|
334
343
|
}
|
|
335
344
|
catch { }
|
|
336
345
|
}
|
package/package.json
CHANGED