@goodandready/dsh-moa 0.2.44 → 0.2.46
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/file-workspace.js +35 -27
- package/lib/history.js +1 -0
- package/lib/index.js +12 -1
- package/lib/moa-budget.js +134 -30
- package/lib/moa-runner.js +99 -106
- package/lib/moa-test-gate.js +210 -33
- package/lib/routes.js +80 -110
- package/package.json +1 -1
package/lib/routes.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* DeepSeek Harness Mixture of Agents (MoA) — HTTP Route Handlers
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import path from 'node:path'
|
|
5
6
|
import { getMoaHistory, getMoaLeaderboard, getMoaRunById, exportMoaHistory } from './history.js'
|
|
6
|
-
import { promoteCandidateWorkspace, readCandidateFiles, computeLineDiff, isSafeRelativePath } from './file-workspace.js'
|
|
7
|
+
import { promoteCandidateWorkspace, readCandidateFiles, computeLineDiff, isSafeRelativePath, isLoopbackUrl } from './file-workspace.js'
|
|
7
8
|
import { isSafeWriteRequest } from './updater.js'
|
|
8
9
|
import { runMoAPipeline } from './moa-runner.js'
|
|
9
10
|
import { generateMoABenchmarkReport } from './moa-report.js'
|
|
@@ -36,10 +37,7 @@ ctx.effect(() => {
|
|
|
36
37
|
kind: 'exact',
|
|
37
38
|
path: '/dsh-moa/status',
|
|
38
39
|
handler: (req, res) => {
|
|
39
|
-
if (req.method !== 'GET') {
|
|
40
|
-
writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
41
|
-
return
|
|
42
|
-
}
|
|
40
|
+
if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
43
41
|
try {
|
|
44
42
|
const cfg = live()
|
|
45
43
|
writeJson(res, 200, {
|
|
@@ -48,9 +46,7 @@ ctx.effect(() => {
|
|
|
48
46
|
defaultPreset: cfg.default_preset || 'default',
|
|
49
47
|
presetsCount: (cfg.presets || []).length,
|
|
50
48
|
})
|
|
51
|
-
} catch (err) {
|
|
52
|
-
writeJson(res, 500, { ok: false, error: err?.message || String(err) })
|
|
53
|
-
}
|
|
49
|
+
} catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
|
|
54
50
|
},
|
|
55
51
|
})
|
|
56
52
|
}, 'dsh-moa: status route')
|
|
@@ -61,10 +57,7 @@ ctx.effect(() => {
|
|
|
61
57
|
kind: 'exact',
|
|
62
58
|
path: '/dsh-moa/models',
|
|
63
59
|
handler: async (req, res) => {
|
|
64
|
-
if (req.method !== 'GET') {
|
|
65
|
-
writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
66
|
-
return
|
|
67
|
-
}
|
|
60
|
+
if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
68
61
|
if (_modelsCache.models.length > 0 && Date.now() - _modelsCache.timestamp < MODELS_CACHE_TTL) {
|
|
69
62
|
writeJson(res, 200, { ok: true, models: _modelsCache.models, cached: true })
|
|
70
63
|
return
|
|
@@ -123,19 +116,11 @@ ctx.effect(() => {
|
|
|
123
116
|
// Query settings for configured providers
|
|
124
117
|
try {
|
|
125
118
|
let s = null
|
|
126
|
-
try {
|
|
127
|
-
|
|
128
|
-
} catch {
|
|
129
|
-
s = null
|
|
130
|
-
}
|
|
131
|
-
const getSetting = (k) => {
|
|
132
|
-
try { return s?.get?.(k) } catch { return undefined }
|
|
133
|
-
}
|
|
119
|
+
try { s = ctx.get ? ctx.get('settings') : null } catch { s = null }
|
|
120
|
+
const getSetting = (k) => { try { return s?.get?.(k) } catch { return undefined } }
|
|
134
121
|
|
|
135
122
|
const def = getSetting('agent-default-model')
|
|
136
|
-
if (def?.provider && def?.model)
|
|
137
|
-
add(def.provider, def.model)
|
|
138
|
-
}
|
|
123
|
+
if (def?.provider && def?.model) add(def.provider, def.model)
|
|
139
124
|
|
|
140
125
|
const piAi = getSetting('llm-pi-ai')
|
|
141
126
|
for (const [pName, pData] of Object.entries(piAi?.providers || {})) {
|
|
@@ -208,25 +193,21 @@ ctx.effect(() => {
|
|
|
208
193
|
}
|
|
209
194
|
|
|
210
195
|
// Persist via saveConfig (in-memory and DSH profile settings)
|
|
196
|
+
let persistResult
|
|
211
197
|
if (typeof saveConfig === 'function') {
|
|
212
|
-
try {
|
|
213
|
-
|
|
214
|
-
} catch (perr) {
|
|
215
|
-
writeJson(res, 500, { ok: false, error: 'Settings persistence failed: ' + (perr?.message || String(perr)) })
|
|
216
|
-
return
|
|
217
|
-
}
|
|
198
|
+
try { persistResult = await saveConfig(validated) }
|
|
199
|
+
catch (perr) { return writeJson(res, 500, { ok: false, error: 'Settings persistence failed: ' + (perr?.message || String(perr)) }) }
|
|
218
200
|
}
|
|
219
201
|
|
|
220
202
|
const unwrapped = typeof plainConfig === 'function' ? plainConfig(validated) : validated
|
|
221
203
|
writeJson(res, 200, {
|
|
222
204
|
ok: true,
|
|
205
|
+
persisted: persistResult?.persisted ?? false,
|
|
223
206
|
enabled: unwrapped.enabled !== false,
|
|
224
207
|
defaultPreset: unwrapped.default_preset,
|
|
225
208
|
presets: unwrapped.presets,
|
|
226
209
|
})
|
|
227
|
-
} catch (err) {
|
|
228
|
-
writeJson(res, 400, { ok: false, error: err?.message || String(err) })
|
|
229
|
-
}
|
|
210
|
+
} catch (err) { writeJson(res, 400, { ok: false, error: err?.message || String(err) }) }
|
|
230
211
|
return
|
|
231
212
|
}
|
|
232
213
|
|
|
@@ -241,21 +222,14 @@ ctx.effect(() => {
|
|
|
241
222
|
kind: 'exact',
|
|
242
223
|
path: '/dsh-moa/history',
|
|
243
224
|
handler: async (req, res) => {
|
|
244
|
-
if (req.method !== 'GET') {
|
|
245
|
-
writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
246
|
-
return
|
|
247
|
-
}
|
|
225
|
+
if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
248
226
|
try {
|
|
249
227
|
const u = new URL(req.url, 'http://localhost')
|
|
250
|
-
const
|
|
251
|
-
const
|
|
252
|
-
const limit = Math.max(1, Math.min(100, Number.isFinite(rawLimit) ? rawLimit : 20))
|
|
253
|
-
const offset = Math.max(0, Number.isFinite(rawOffset) ? rawOffset : 0)
|
|
228
|
+
const limit = Math.max(1, Math.min(100, parseInt(u.searchParams.get('limit') || '20', 10) || 20))
|
|
229
|
+
const offset = Math.max(0, parseInt(u.searchParams.get('offset') || '0', 10) || 0)
|
|
254
230
|
const data = getMoaHistory(limit, offset)
|
|
255
231
|
writeJson(res, 200, { ok: true, ...data })
|
|
256
|
-
} catch (err) {
|
|
257
|
-
writeJson(res, 500, { ok: false, error: err?.message || String(err) })
|
|
258
|
-
}
|
|
232
|
+
} catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
|
|
259
233
|
},
|
|
260
234
|
})
|
|
261
235
|
}, 'dsh-moa: history route')
|
|
@@ -266,10 +240,7 @@ ctx.effect(() => {
|
|
|
266
240
|
kind: 'exact',
|
|
267
241
|
path: '/dsh-moa/leaderboard',
|
|
268
242
|
handler: async (req, res) => {
|
|
269
|
-
if (req.method !== 'GET') {
|
|
270
|
-
writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
271
|
-
return
|
|
272
|
-
}
|
|
243
|
+
if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
273
244
|
try {
|
|
274
245
|
const url = new URL(req.url || '', 'http://127.0.0.1')
|
|
275
246
|
const preset = url.searchParams.get('preset') || null
|
|
@@ -287,9 +258,7 @@ ctx.effect(() => {
|
|
|
287
258
|
|
|
288
259
|
const data = getMoaLeaderboard(undefined, { preset })
|
|
289
260
|
writeJson(res, 200, { ok: true, ...data })
|
|
290
|
-
} catch (err) {
|
|
291
|
-
writeJson(res, 500, { ok: false, error: err?.message || String(err) })
|
|
292
|
-
}
|
|
261
|
+
} catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
|
|
293
262
|
},
|
|
294
263
|
})
|
|
295
264
|
}, 'dsh-moa: leaderboard route')
|
|
@@ -300,10 +269,7 @@ ctx.effect(() => {
|
|
|
300
269
|
kind: 'exact',
|
|
301
270
|
path: '/dsh-moa/promote',
|
|
302
271
|
handler: async (req, res) => {
|
|
303
|
-
if (req.method !== 'POST') {
|
|
304
|
-
writeJson(res, 405, { ok: false, error: 'POST required' })
|
|
305
|
-
return
|
|
306
|
-
}
|
|
272
|
+
if (req.method !== 'POST') return writeJson(res, 405, { ok: false, error: 'POST required' })
|
|
307
273
|
if (!isSafeWriteRequest(req)) {
|
|
308
274
|
writeJson(res, 403, { ok: false, error: 'Forbidden: cross-site request rejected' })
|
|
309
275
|
return
|
|
@@ -316,19 +282,35 @@ ctx.effect(() => {
|
|
|
316
282
|
writeJson(res, 400, { ok: false, error: 'Valid candidateIndex required (>= 1)' })
|
|
317
283
|
return
|
|
318
284
|
}
|
|
319
|
-
const cwd = body?.cwd || process.cwd()
|
|
320
285
|
const runId = body?.runId
|
|
321
|
-
|
|
322
|
-
|
|
286
|
+
let recordedRun = null
|
|
287
|
+
if (runId) {
|
|
288
|
+
recordedRun = getMoaRunById(runId)
|
|
289
|
+
if (!recordedRun) {
|
|
290
|
+
writeJson(res, 404, { ok: false, error: `Run '${runId}' not found` })
|
|
291
|
+
return
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
recordedRun = getMoaHistory(1, 0)?.runs?.[0] || null
|
|
295
|
+
if (!recordedRun) {
|
|
296
|
+
writeJson(res, 400, { ok: false, error: 'No recorded MoA run found' })
|
|
297
|
+
return
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (body?.cwd && path.resolve(body.cwd) !== path.resolve(recordedRun.cwd)) {
|
|
301
|
+
writeJson(res, 403, { ok: false, error: 'Forbidden: cwd does not match recorded run cwd' })
|
|
302
|
+
return
|
|
303
|
+
}
|
|
304
|
+
const effectiveCwd = recordedRun.cwd
|
|
305
|
+
const promotedFiles = await promoteCandidateWorkspace(effectiveCwd, candidateIndex, {
|
|
306
|
+
runId: runId ? recordedRun.id : undefined,
|
|
323
307
|
keepMoa: true,
|
|
324
308
|
port: ctx.webServer?.port,
|
|
325
309
|
timeMachineEngine: timeMachineEngine || ctx.reflect?.get?.('timeMachineEngine', false),
|
|
326
310
|
force: Boolean(body?.force),
|
|
327
311
|
})
|
|
328
312
|
writeJson(res, 200, { ok: true, candidateIndex, promotedFiles, checkpoint: promotedFiles?.checkpoint || null })
|
|
329
|
-
} catch (err) {
|
|
330
|
-
writeJson(res, 500, { ok: false, error: err?.message || String(err) })
|
|
331
|
-
}
|
|
313
|
+
} catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
|
|
332
314
|
},
|
|
333
315
|
})
|
|
334
316
|
}, 'dsh-moa: promote candidate route')
|
|
@@ -339,17 +321,31 @@ ctx.effect(() => {
|
|
|
339
321
|
kind: 'exact',
|
|
340
322
|
path: '/dsh-moa/diff',
|
|
341
323
|
handler: async (req, res) => {
|
|
342
|
-
if (req.method !== 'GET') {
|
|
343
|
-
writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
344
|
-
return
|
|
345
|
-
}
|
|
324
|
+
if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
346
325
|
try {
|
|
347
326
|
const u = new URL(req.url, 'http://localhost')
|
|
348
327
|
const rawRunId = u.searchParams.get('runId')
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
328
|
+
const queryCwd = u.searchParams.get('cwd')
|
|
329
|
+
let run = null
|
|
330
|
+
if (rawRunId && rawRunId !== 'latest' && rawRunId !== 'active') {
|
|
331
|
+
run = getMoaRunById(rawRunId)
|
|
332
|
+
if (!run) {
|
|
333
|
+
writeJson(res, 404, { ok: false, error: `Run '${rawRunId}' not found` })
|
|
334
|
+
return
|
|
335
|
+
}
|
|
336
|
+
} else {
|
|
337
|
+
run = getMoaHistory(1, 0)?.runs?.[0] || null
|
|
338
|
+
if (!run) {
|
|
339
|
+
writeJson(res, 404, { ok: false, error: 'No recorded MoA run found' })
|
|
340
|
+
return
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (queryCwd && path.resolve(queryCwd) !== path.resolve(run.cwd)) {
|
|
344
|
+
writeJson(res, 403, { ok: false, error: 'Forbidden: cwd does not match recorded run cwd' })
|
|
345
|
+
return
|
|
346
|
+
}
|
|
347
|
+
const runId = run.id
|
|
348
|
+
const cwd = run.cwd
|
|
353
349
|
const sanitizeTarget = (val, def) => {
|
|
354
350
|
const clean = String(val || '').trim().replace(/[^a-zA-Z0-9_-]/g, '')
|
|
355
351
|
return clean || def
|
|
@@ -386,47 +382,31 @@ ctx.effect(() => {
|
|
|
386
382
|
toSize: toItem?.size || 0,
|
|
387
383
|
diff,
|
|
388
384
|
})
|
|
389
|
-
} catch (err) {
|
|
390
|
-
writeJson(res, 500, { ok: false, error: err?.message || String(err) })
|
|
391
|
-
}
|
|
385
|
+
} catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
|
|
392
386
|
},
|
|
393
387
|
})
|
|
394
388
|
}, 'dsh-moa: candidate diff route')
|
|
395
389
|
|
|
396
|
-
|
|
397
390
|
// Route: /dsh-moa/history/export
|
|
398
391
|
ctx.effect(() => {
|
|
399
392
|
return ctx.webServer.register({
|
|
400
393
|
kind: 'exact',
|
|
401
394
|
path: '/dsh-moa/history/export',
|
|
402
395
|
handler: async (req, res) => {
|
|
403
|
-
if (req.method !== 'GET') {
|
|
404
|
-
writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
405
|
-
return
|
|
406
|
-
}
|
|
396
|
+
if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
407
397
|
try {
|
|
408
398
|
const url = new URL(req.url || '', 'http://127.0.0.1')
|
|
409
399
|
const preset = url.searchParams.get('preset') || null
|
|
410
400
|
const format = url.searchParams.get('format') || 'json'
|
|
411
401
|
const data = exportMoaHistory(undefined, { format, preset })
|
|
412
402
|
|
|
413
|
-
|
|
414
|
-
res.writeHead(200, {
|
|
415
|
-
'Content-Type': 'text/csv; charset=utf-8',
|
|
416
|
-
'Content-Disposition': 'attachment; filename="moa-history.csv"',
|
|
417
|
-
})
|
|
418
|
-
res.end(data)
|
|
419
|
-
return
|
|
420
|
-
}
|
|
421
|
-
|
|
403
|
+
const isCsv = format === 'csv'
|
|
422
404
|
res.writeHead(200, {
|
|
423
|
-
'Content-Type': 'application/json; charset=utf-8',
|
|
424
|
-
'Content-Disposition':
|
|
405
|
+
'Content-Type': isCsv ? 'text/csv; charset=utf-8' : 'application/json; charset=utf-8',
|
|
406
|
+
'Content-Disposition': `attachment; filename="moa-history.${isCsv ? 'csv' : 'json'}"`,
|
|
425
407
|
})
|
|
426
408
|
res.end(data)
|
|
427
|
-
} catch (err) {
|
|
428
|
-
writeJson(res, 500, { ok: false, error: err?.message || String(err) })
|
|
429
|
-
}
|
|
409
|
+
} catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
|
|
430
410
|
},
|
|
431
411
|
})
|
|
432
412
|
}, 'dsh-moa: history export route')
|
|
@@ -437,10 +417,7 @@ ctx.effect(() => {
|
|
|
437
417
|
kind: 'prefix',
|
|
438
418
|
path: '/dsh-moa/runs/',
|
|
439
419
|
handler: (req, res) => {
|
|
440
|
-
if (req.method !== 'GET') {
|
|
441
|
-
writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
442
|
-
return
|
|
443
|
-
}
|
|
420
|
+
if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
|
|
444
421
|
const urlPath = req.url.split('?')[0]
|
|
445
422
|
const parts = urlPath.split('/').filter(Boolean)
|
|
446
423
|
const runId = parts[2] || ''
|
|
@@ -485,10 +462,7 @@ ctx.effect(() => {
|
|
|
485
462
|
kind: 'exact',
|
|
486
463
|
path: '/dsh-moa/route-preset',
|
|
487
464
|
handler: async (req, res) => {
|
|
488
|
-
if (req.method !== 'POST') {
|
|
489
|
-
writeJson(res, 405, { ok: false, error: 'POST required' })
|
|
490
|
-
return
|
|
491
|
-
}
|
|
465
|
+
if (req.method !== 'POST') return writeJson(res, 405, { ok: false, error: 'POST required' })
|
|
492
466
|
if (!isSafeWriteRequest(req)) {
|
|
493
467
|
writeJson(res, 403, { ok: false, error: 'Forbidden: cross-site request rejected' })
|
|
494
468
|
return
|
|
@@ -514,9 +488,7 @@ ctx.effect(() => {
|
|
|
514
488
|
enabled: cfg.enabled !== false,
|
|
515
489
|
})
|
|
516
490
|
writeJson(res, 200, { ok: true, ...result })
|
|
517
|
-
} catch (err) {
|
|
518
|
-
writeJson(res, 500, { ok: false, error: err?.message || String(err) })
|
|
519
|
-
}
|
|
491
|
+
} catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
|
|
520
492
|
},
|
|
521
493
|
})
|
|
522
494
|
}, 'dsh-moa: route preset endpoint')
|
|
@@ -530,10 +502,7 @@ ctx.effect(() => {
|
|
|
530
502
|
kind: 'exact',
|
|
531
503
|
path: '/dsh-moa/run',
|
|
532
504
|
handler: async (req, res) => {
|
|
533
|
-
if (req.method !== 'POST') {
|
|
534
|
-
writeJson(res, 405, { ok: false, error: 'POST required' })
|
|
535
|
-
return
|
|
536
|
-
}
|
|
505
|
+
if (req.method !== 'POST') return writeJson(res, 405, { ok: false, error: 'POST required' })
|
|
537
506
|
if (!isSafeWriteRequest(req)) {
|
|
538
507
|
writeJson(res, 403, { ok: false, error: 'Forbidden: cross-site request rejected' })
|
|
539
508
|
return
|
|
@@ -559,6 +528,10 @@ ctx.effect(() => {
|
|
|
559
528
|
writeJson(res, 400, { ok: false, error: 'MoA is disabled in settings' })
|
|
560
529
|
return
|
|
561
530
|
}
|
|
531
|
+
if (payload.timeMachineUrl && !isLoopbackUrl(payload.timeMachineUrl)) {
|
|
532
|
+
writeJson(res, 400, { ok: false, error: 'Invalid timeMachineUrl: loopback host required' })
|
|
533
|
+
return
|
|
534
|
+
}
|
|
562
535
|
const presetName = payload.preset || cfg.default_preset || 'default'
|
|
563
536
|
const preset = (cfg.presets || []).find((p) => p.name === presetName) || cfg.presets?.[0]
|
|
564
537
|
|
|
@@ -568,23 +541,20 @@ ctx.effect(() => {
|
|
|
568
541
|
webServerPort: webServerPort || ctx.webServer?.port,
|
|
569
542
|
timeMachineEngine: timeMachineEngine || ctx.reflect?.get?.('timeMachineEngine', false),
|
|
570
543
|
timeMachineUrl: payload.timeMachineUrl, force: payload.force,
|
|
571
|
-
checkpoint: payload.checkpoint,
|
|
544
|
+
checkpoint: payload.checkpoint,
|
|
572
545
|
runId: payload.runId,
|
|
573
546
|
})
|
|
574
547
|
|
|
575
548
|
if (result?.skippedFiles > 0) {
|
|
576
549
|
ctx.logger?.warn?.(`[dsh-moa] Workspace scan skipped ${result.skippedFiles} file(s): ${result.skippedList.join(', ')}`)
|
|
577
550
|
}
|
|
578
|
-
|
|
579
551
|
if (result?.error) {
|
|
580
552
|
writeJson(res, 500, { ok: false, error: result.error?.message || String(result.error) })
|
|
581
553
|
return
|
|
582
554
|
}
|
|
583
555
|
|
|
584
556
|
writeJson(res, 200, { ok: true, ...result })
|
|
585
|
-
} catch (err) {
|
|
586
|
-
writeJson(res, 500, { ok: false, error: err?.message || String(err) })
|
|
587
|
-
}
|
|
557
|
+
} catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
|
|
588
558
|
},
|
|
589
559
|
})
|
|
590
560
|
}, 'dsh-moa: run pipeline route')
|