@goodandready/dsh-moa 0.2.26 → 0.2.29

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/routes.js CHANGED
@@ -11,6 +11,8 @@ import {
11
11
  import { promoteCandidateWorkspace, readCandidateFiles, computeLineDiff, isSafeRelativePath } from './file-workspace.js'
12
12
  import { isSafeWriteRequest } from './updater.js'
13
13
  import { runMoAPipeline } from './moa-runner.js'
14
+ import { generateMoABenchmarkReport } from './moa-report.js'
15
+ import { resolvePresetForPrompt } from './moa-router.js'
14
16
 
15
17
  let _modelsCache = { timestamp: 0, models: [] }
16
18
  const MODELS_CACHE_TTL = 60 * 1000
@@ -44,7 +46,11 @@ ctx.effect(() => {
44
46
  return ctx.webServer.register({
45
47
  kind: 'exact',
46
48
  path: '/dsh-moa/status',
47
- handler: (_req, res) => {
49
+ handler: (req, res) => {
50
+ if (req.method !== 'GET') {
51
+ writeJson(res, 405, { ok: false, error: 'GET required' })
52
+ return
53
+ }
48
54
  try {
49
55
  const cfg = live()
50
56
  writeJson(res, 200, {
@@ -65,7 +71,11 @@ ctx.effect(() => {
65
71
  return ctx.webServer.register({
66
72
  kind: 'exact',
67
73
  path: '/dsh-moa/models',
68
- handler: async (_req, res) => {
74
+ handler: async (req, res) => {
75
+ if (req.method !== 'GET') {
76
+ writeJson(res, 405, { ok: false, error: 'GET required' })
77
+ return
78
+ }
69
79
  if (_modelsCache.models.length > 0 && Date.now() - _modelsCache.timestamp < MODELS_CACHE_TTL) {
70
80
  writeJson(res, 200, { ok: true, models: _modelsCache.models, cached: true })
71
81
  return
@@ -92,7 +102,7 @@ ctx.effect(() => {
92
102
  }
93
103
  }
94
104
  } catch (e) {
95
- console.warn('[dsh-moa] ctx.llm.listAvailableModels error:', e)
105
+ ctx.logger?.warn?.('[dsh-moa] ctx.llm.listAvailableModels error:', e)
96
106
  }
97
107
 
98
108
  try {
@@ -117,7 +127,7 @@ ctx.effect(() => {
117
127
  await Promise.allSettled(queries)
118
128
  }
119
129
  } catch (e) {
120
- console.warn('[dsh-moa] ctx.llm.listConfigurableProviders error:', e)
130
+ ctx.logger?.warn?.('[dsh-moa] ctx.llm.listConfigurableProviders error:', e)
121
131
  }
122
132
  }
123
133
 
@@ -154,7 +164,7 @@ ctx.effect(() => {
154
164
  }
155
165
  }
156
166
  } catch (e) {
157
- console.warn('[dsh-moa] Error reading settings:', e)
167
+ ctx.logger?.warn?.('[dsh-moa] Error reading settings:', e)
158
168
  }
159
169
 
160
170
  _modelsCache = { timestamp: Date.now(), models: result }
@@ -239,8 +249,10 @@ ctx.effect(() => {
239
249
  }
240
250
  try {
241
251
  const u = new URL(req.url, 'http://localhost')
242
- const limit = parseInt(u.searchParams.get('limit') || '20', 10)
243
- const offset = parseInt(u.searchParams.get('offset') || '0', 10)
252
+ const rawLimit = parseInt(u.searchParams.get('limit') || '20', 10)
253
+ const rawOffset = parseInt(u.searchParams.get('offset') || '0', 10)
254
+ const limit = Math.max(1, Math.min(100, Number.isFinite(rawLimit) ? rawLimit : 20))
255
+ const offset = Math.max(0, Number.isFinite(rawOffset) ? rawOffset : 0)
244
256
  const data = getMoaHistory(limit, offset)
245
257
  writeJson(res, 200, { ok: true, ...data })
246
258
  } catch (err) {
@@ -423,16 +435,83 @@ ctx.effect(() => {
423
435
  const urlPath = req.url.split('?')[0]
424
436
  const parts = urlPath.split('/').filter(Boolean)
425
437
  const runId = parts[2] || ''
438
+ const isReport = parts[3] === 'report'
426
439
  const run = runId ? getMoaRunById(runId) : null
427
440
  if (!run) {
428
441
  writeJson(res, 404, { ok: false, error: 'Run not found' })
429
442
  return
430
443
  }
444
+ if (isReport) {
445
+ const u = new URL(req.url, 'http://127.0.0.1')
446
+ const format = u.searchParams.get('format') || 'md'
447
+ const report = run.benchmarkReport || generateMoABenchmarkReport({
448
+ runId: run.id,
449
+ timestamp: run.timestamp,
450
+ preset: run.preset,
451
+ prompt: run.prompt,
452
+ durationMs: run.durationMs,
453
+ usage: { totalTokens: run.totalTokens },
454
+ costUsd: run.totalCostUsd,
455
+ candidates: run.candidates,
456
+ winningIndex: run.winnerIndex,
457
+ winningLabel: run.winnerModel,
458
+ })
459
+ if (format === 'json') {
460
+ writeJson(res, 200, { ok: true, report: typeof report === 'object' ? (report.json || report) : report })
461
+ return
462
+ }
463
+ const mdText = typeof report === 'string' ? report : (report.markdown || JSON.stringify(report, null, 2))
464
+ res.writeHead(200, { 'Content-Type': 'text/markdown; charset=utf-8' })
465
+ res.end(mdText)
466
+ return
467
+ }
431
468
  writeJson(res, 200, { ok: true, run })
432
469
  },
433
470
  })
434
471
  }, 'dsh-moa: run by id route')
435
472
 
473
+ // Route: /dsh-moa/route-preset
474
+ ctx.effect(() => {
475
+ return ctx.webServer.register({
476
+ kind: 'exact',
477
+ path: '/dsh-moa/route-preset',
478
+ handler: async (req, res) => {
479
+ if (req.method !== 'POST') {
480
+ writeJson(res, 405, { ok: false, error: 'POST required' })
481
+ return
482
+ }
483
+ if (!isSafeWriteRequest(req)) {
484
+ writeJson(res, 403, { ok: false, error: 'Forbidden: cross-site request rejected' })
485
+ return
486
+ }
487
+ try {
488
+ const cfg = live()
489
+ if (cfg.enabled === false) {
490
+ writeJson(res, 400, { ok: false, error: 'MoA is disabled in settings' })
491
+ return
492
+ }
493
+ const raw = await readBody(req)
494
+ const body = JSON.parse(raw || '{}')
495
+ const prompt = body?.prompt || ''
496
+ const result = await resolvePresetForPrompt({
497
+ prompt,
498
+ presets: cfg.presets || [],
499
+ defaultPreset: cfg.default_preset || 'default',
500
+ routingModel: cfg.smart_routing_model,
501
+ callLlm,
502
+ enabled: cfg.enabled !== false,
503
+ })
504
+ writeJson(res, 200, { ok: true, ...result })
505
+ } catch (err) {
506
+ writeJson(res, 500, { ok: false, error: err?.message || String(err) })
507
+ }
508
+ },
509
+ })
510
+ }, 'dsh-moa: route preset endpoint')
511
+
512
+ let _lastRunTimestamp = 0
513
+ const RUN_MIN_INTERVAL_MS = 1000
514
+
436
515
  // Route: /dsh-moa/run
437
516
  ctx.effect(() => {
438
517
  return ctx.webServer.register({
@@ -447,6 +526,12 @@ ctx.effect(() => {
447
526
  writeJson(res, 403, { ok: false, error: 'Forbidden: cross-site request rejected' })
448
527
  return
449
528
  }
529
+ const now = Date.now()
530
+ if (now - _lastRunTimestamp < RUN_MIN_INTERVAL_MS) {
531
+ writeJson(res, 429, { ok: false, error: 'Rate limit exceeded: please wait before starting another run' })
532
+ return
533
+ }
534
+ _lastRunTimestamp = now
450
535
 
451
536
  try {
452
537
  const raw = await readBody(req)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-moa",
3
- "version": "0.2.26",
3
+ "version": "0.2.29",
4
4
  "description": "Mixture of Agents (MoA) plugin for DeepSeek Harness with /moa slash command",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",