@goodandready/dsh-moa 0.2.59 → 0.2.61

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/index.js CHANGED
@@ -324,6 +324,7 @@ export function apply(ctx, config) {
324
324
  }, 'dsh-moa: llm stream interceptor')
325
325
  }
326
326
 
327
+ export { runMoAPipeline } from './moa-runner.js'
327
328
  export { executeTestGateForCandidates, runCandidateTestGate } from './moa-test-gate.js'
328
329
  export {
329
330
  COMPANION_PLUGINS,
@@ -0,0 +1,81 @@
1
+ import { getMoaHistory, getMoaLeaderboard, exportMoaHistory } from '../history.js'
2
+ import { writeJson, assertAuthorizedRequest } from '../access.js'
3
+
4
+ export function registerHistoryRoutes(ctx, { live }) {
5
+ ctx.effect(() => {
6
+ return ctx.webServer.register({
7
+ kind: 'exact',
8
+ path: '/dsh-moa/history',
9
+ handler: async (req, res) => {
10
+ if (!assertAuthorizedRequest(req, res, ctx)) return
11
+ if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
12
+ try {
13
+ const u = new URL(req.url, 'http://localhost')
14
+ const limit = Math.max(1, Math.min(100, parseInt(u.searchParams.get('limit') || '20', 10) || 20))
15
+ const offset = Math.max(0, parseInt(u.searchParams.get('offset') || '0', 10) || 0)
16
+ const data = getMoaHistory(limit, offset)
17
+ writeJson(res, 200, { ok: true, ...data })
18
+ } catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
19
+ },
20
+ })
21
+ }, 'dsh-moa: history route')
22
+
23
+ // Route: /dsh-moa/leaderboard
24
+
25
+ ctx.effect(() => {
26
+ return ctx.webServer.register({
27
+ kind: 'exact',
28
+ path: '/dsh-moa/leaderboard',
29
+ handler: async (req, res) => {
30
+ if (!assertAuthorizedRequest(req, res, ctx)) return
31
+ if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
32
+ try {
33
+ const url = new URL(req.url || '', 'http://127.0.0.1')
34
+ const preset = url.searchParams.get('preset') || null
35
+ const format = url.searchParams.get('format') || 'json'
36
+
37
+ if (format === 'csv') {
38
+ const csv = exportMoaHistory(undefined, { format: 'csv', preset })
39
+ res.writeHead(200, {
40
+ 'Content-Type': 'text/csv; charset=utf-8',
41
+ 'Content-Disposition': 'attachment; filename="moa-leaderboard.csv"',
42
+ })
43
+ res.end(csv)
44
+ return
45
+ }
46
+
47
+ const data = getMoaLeaderboard(undefined, { preset })
48
+ writeJson(res, 200, { ok: true, ...data })
49
+ } catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
50
+ },
51
+ })
52
+ }, 'dsh-moa: leaderboard route')
53
+
54
+ // Route: /dsh-moa/promote (Candidate Override Action)
55
+
56
+ ctx.effect(() => {
57
+ return ctx.webServer.register({
58
+ kind: 'exact',
59
+ path: '/dsh-moa/history/export',
60
+ handler: async (req, res) => {
61
+ if (!assertAuthorizedRequest(req, res, ctx)) return
62
+ if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
63
+ try {
64
+ const url = new URL(req.url || '', 'http://127.0.0.1')
65
+ const preset = url.searchParams.get('preset') || null
66
+ const format = url.searchParams.get('format') || 'json'
67
+ const data = exportMoaHistory(undefined, { format, preset })
68
+
69
+ const isCsv = format === 'csv'
70
+ res.writeHead(200, {
71
+ 'Content-Type': isCsv ? 'text/csv; charset=utf-8' : 'application/json; charset=utf-8',
72
+ 'Content-Disposition': `attachment; filename="moa-history.${isCsv ? 'csv' : 'json'}"`,
73
+ })
74
+ res.end(data)
75
+ } catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
76
+ },
77
+ })
78
+ }, 'dsh-moa: history export route')
79
+
80
+ // Route: /dsh-moa/runs/<id> (run replay by id and interactive workbench)
81
+ }
@@ -0,0 +1,91 @@
1
+ import path from 'node:path'
2
+ import os from 'node:os'
3
+ import { isTestEnvironment } from '../history.js'
4
+ import { isLoopbackUrl } from '../file-workspace.js'
5
+ import { runMoAPipeline } from '../moa-runner.js'
6
+ import { writeJson, readBody, isAllowedWorkspace, assertAuthorizedRequest } from '../access.js'
7
+ import { isSafeWriteRequest } from '../updater.js'
8
+
9
+
10
+ export function registerPipelineRoutes(ctx, { live, callLlm, liveCanvas, webServerPort, timeMachineEngine, workspaceRoot }) {
11
+ let _lastRunTimestamp = 0
12
+ const RUN_MIN_INTERVAL_MS = 1000
13
+
14
+ ctx.effect(() => {
15
+ return ctx.webServer.register({
16
+ kind: 'exact',
17
+ path: '/dsh-moa/run',
18
+ handler: async (req, res) => {
19
+ if (!assertAuthorizedRequest(req, res, ctx)) return
20
+ if (req.method !== 'POST') return writeJson(res, 405, { ok: false, error: 'POST required' })
21
+ if (!isSafeWriteRequest(req)) {
22
+ writeJson(res, 403, { ok: false, error: 'Forbidden: cross-site request rejected' })
23
+ return
24
+ }
25
+ const now = Date.now()
26
+ if (now - _lastRunTimestamp < RUN_MIN_INTERVAL_MS) {
27
+ writeJson(res, 429, { ok: false, error: 'Rate limit exceeded: please wait before starting another run' })
28
+ return
29
+ }
30
+
31
+ try {
32
+ const raw = await readBody(req)
33
+ const payload = JSON.parse(raw)
34
+ const prompt = payload.prompt || ''
35
+ if (!prompt.trim()) {
36
+ writeJson(res, 400, { ok: false, error: 'Empty prompt' })
37
+ return
38
+ }
39
+ _lastRunTimestamp = now
40
+
41
+ const cfg = live()
42
+ if (cfg.enabled === false) {
43
+ writeJson(res, 400, { ok: false, error: 'MoA is disabled in settings' })
44
+ return
45
+ }
46
+ if (payload.timeMachineUrl && !isLoopbackUrl(payload.timeMachineUrl)) {
47
+ writeJson(res, 400, { ok: false, error: 'Invalid timeMachineUrl: loopback host required' })
48
+ return
49
+ }
50
+ const presetName = payload.preset || cfg.default_preset || 'default'
51
+ const preset = (cfg.presets || []).find((p) => p.name === presetName) || cfg.presets?.[0]
52
+
53
+ const baseWorkspaceRoot = workspaceRoot || ctx?.reflect?.get?.('baseDir', false) || ctx?.reflect?.get?.('workspaceDir', false) || process.cwd()
54
+ const allowedRoots = [
55
+ baseWorkspaceRoot,
56
+ process.cwd(),
57
+ cfg.workspace_root,
58
+ ...(Array.isArray(cfg.allowed_workspaces) ? cfg.allowed_workspaces : (cfg.allowed_workspaces ? [cfg.allowed_workspaces] : [])),
59
+ ...(isTestEnvironment() ? [os.tmpdir()] : []),
60
+ ].filter(Boolean)
61
+
62
+ const targetCwd = payload.cwd ? path.resolve(payload.cwd) : baseWorkspaceRoot
63
+ if (payload.cwd && !isAllowedWorkspace(targetCwd, allowedRoots)) {
64
+ writeJson(res, 403, { ok: false, error: 'Forbidden: cwd escapes allowed workspace boundary' })
65
+ return
66
+ }
67
+
68
+ const result = await runMoAPipeline({
69
+ userPrompt: prompt, messages: payload.messages || [], preset, callLlm,
70
+ cwd: targetCwd, prices: cfg.prices || {}, liveCanvas,
71
+ webServerPort: webServerPort || ctx.webServer?.port,
72
+ timeMachineEngine: timeMachineEngine || ctx.reflect?.get?.('timeMachineEngine', false),
73
+ timeMachineUrl: payload.timeMachineUrl, force: false,
74
+ checkpoint: true,
75
+ runId: payload.runId,
76
+ })
77
+
78
+ if (result?.skippedFiles > 0) {
79
+ ctx.logger?.warn?.(`[dsh-moa] Workspace scan skipped ${result.skippedFiles} file(s): ${result.skippedList.join(', ')}`)
80
+ }
81
+ if (result?.error) {
82
+ writeJson(res, 500, { ok: false, error: result.error?.message || String(result.error) })
83
+ return
84
+ }
85
+
86
+ writeJson(res, 200, { ok: true, ...result })
87
+ } catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
88
+ },
89
+ })
90
+ }, 'dsh-moa: run pipeline route')
91
+ }
@@ -0,0 +1,241 @@
1
+ import { writeJson, readBody, assertAuthorizedRequest } from '../access.js'
2
+ import { isSafeWriteRequest } from '../updater.js'
3
+ import { resolvePresetForPrompt } from '../moa-router.js'
4
+
5
+ let _modelsCache = { timestamp: 0, models: [] }
6
+ const MODELS_CACHE_TTL = 60 * 1000
7
+
8
+ export function registerPresetRoutes(ctx, { live, callLlm, saveConfig, Config, plainConfig }) {
9
+ ctx.effect(() => {
10
+ return ctx.webServer.register({
11
+ kind: 'exact',
12
+ path: '/dsh-moa/status',
13
+ handler: (req, res) => {
14
+ if (!assertAuthorizedRequest(req, res, ctx)) return
15
+ if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
16
+ try {
17
+ const cfg = live()
18
+ writeJson(res, 200, {
19
+ ok: true,
20
+ enabled: cfg.enabled !== false,
21
+ defaultPreset: cfg.default_preset || 'default',
22
+ presetsCount: (cfg.presets || []).length,
23
+ })
24
+ } catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
25
+ },
26
+ })
27
+ }, 'dsh-moa: status route')
28
+
29
+ // Route: /dsh-moa/models
30
+
31
+ ctx.effect(() => {
32
+ return ctx.webServer.register({
33
+ kind: 'exact',
34
+ path: '/dsh-moa/models',
35
+ handler: async (req, res) => {
36
+ if (!assertAuthorizedRequest(req, res, ctx)) return
37
+ if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
38
+ if (_modelsCache.models.length > 0 && Date.now() - _modelsCache.timestamp < MODELS_CACHE_TTL) {
39
+ writeJson(res, 200, { ok: true, models: _modelsCache.models, cached: true })
40
+ return
41
+ }
42
+
43
+ const result = []
44
+ const seen = new Set()
45
+
46
+ const add = (p, m) => {
47
+ if (!p || !m) return
48
+ const key = `${p}:${m}`
49
+ if (!seen.has(key)) {
50
+ seen.add(key)
51
+ result.push({ provider: p, model: m, label: key })
52
+ }
53
+ }
54
+
55
+ if (ctx.llm) {
56
+ try {
57
+ if (typeof ctx.llm.listAvailableModels === 'function') {
58
+ const list = await ctx.llm.listAvailableModels()
59
+ for (const item of (list || [])) {
60
+ if (item?.provider && item?.id) add(item.provider, item.id)
61
+ }
62
+ }
63
+ } catch (e) {
64
+ ctx.logger?.warn?.('[dsh-moa] ctx.llm.listAvailableModels error:', e)
65
+ }
66
+
67
+ try {
68
+ if (typeof ctx.llm.listConfigurableProviders === 'function') {
69
+ const cProvs = ctx.llm.listConfigurableProviders() || []
70
+ const queries = cProvs.map(async (cp) => {
71
+ const cpId = cp.provider || cp.id
72
+ if (!cpId || typeof ctx.llm.listModels !== 'function') return
73
+ try {
74
+ const mList = await Promise.race([
75
+ ctx.llm.listModels(cpId),
76
+ new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 2000)),
77
+ ])
78
+ for (const m of (mList || [])) {
79
+ const mId = typeof m === 'string' ? m : (m?.id || m?.model || m?.name)
80
+ if (mId) add(cpId, mId)
81
+ }
82
+ } catch {
83
+ /* provider query timeout or error handled best-effort */
84
+ }
85
+ })
86
+ await Promise.allSettled(queries)
87
+ }
88
+ } catch (e) {
89
+ ctx.logger?.warn?.('[dsh-moa] ctx.llm.listConfigurableProviders error:', e)
90
+ }
91
+ }
92
+
93
+ // Query settings for configured providers
94
+ try {
95
+ let s = null
96
+ try { s = ctx.get ? ctx.get('settings') : null } catch { s = null }
97
+ const getSetting = (k) => { try { return s?.get?.(k) } catch { return undefined } }
98
+
99
+ const def = getSetting('agent-default-model')
100
+ if (def?.provider && def?.model) add(def.provider, def.model)
101
+
102
+ const piAi = getSetting('llm-pi-ai')
103
+ for (const [pName, pData] of Object.entries(piAi?.providers || {})) {
104
+ for (const m of (pData?.models || [])) {
105
+ const mId = typeof m === 'string' ? m : (m?.id || m?.model)
106
+ if (mId) add(pName, mId)
107
+ }
108
+ }
109
+
110
+ const sync = getSetting('dsh-model-sync')
111
+ for (const [syncProv, syncModels] of Object.entries(sync?.modelCatalogs || {})) {
112
+ for (const m of (syncModels || [])) {
113
+ const mId = typeof m === 'string' ? m : (m?.id || m?.model)
114
+ if (mId) add(syncProv, mId)
115
+ }
116
+ }
117
+ } catch (e) {
118
+ ctx.logger?.warn?.('[dsh-moa] Error reading settings:', e)
119
+ }
120
+
121
+ _modelsCache = { timestamp: Date.now(), models: result }
122
+ writeJson(res, 200, { ok: true, models: result })
123
+ },
124
+ })
125
+ }, 'dsh-moa: models route')
126
+
127
+ // Route: /dsh-moa/presets
128
+
129
+ ctx.effect(() => {
130
+ return ctx.webServer.register({
131
+ kind: 'exact',
132
+ path: '/dsh-moa/presets',
133
+ handler: async (req, res) => {
134
+ if (!assertAuthorizedRequest(req, res, ctx)) return
135
+ const cfg = live()
136
+ if (req.method === 'GET') {
137
+ writeJson(res, 200, {
138
+ ok: true,
139
+ defaultPreset: cfg.default_preset || 'default',
140
+ presets: cfg.presets || [],
141
+ })
142
+ return
143
+ }
144
+
145
+ if (req.method === 'POST' || req.method === 'PUT') {
146
+ if (!isSafeWriteRequest(req)) {
147
+ writeJson(res, 403, { ok: false, error: 'Forbidden: cross-site request rejected' })
148
+ return
149
+ }
150
+ try {
151
+ const raw = await readBody(req)
152
+ const payload = JSON.parse(raw)
153
+ const newConfig = {
154
+ ...cfg,
155
+ enabled: typeof payload.enabled === 'boolean' ? payload.enabled : cfg.enabled !== false,
156
+ default_preset: payload.default_preset || cfg.default_preset || 'default',
157
+ presets: Array.isArray(payload.presets) ? payload.presets : (cfg.presets || []),
158
+ ...(payload.prices !== undefined ? { prices: payload.prices } : {}),
159
+ ...(payload.smart_routing_enabled !== undefined ? { smart_routing_enabled: payload.smart_routing_enabled } : {}),
160
+ ...(payload.smart_routing_model !== undefined ? { smart_routing_model: payload.smart_routing_model } : {}),
161
+ }
162
+
163
+ // Validate the merged payload through the plugin schema before it
164
+ // reaches the settings storage: malformed payloads must be
165
+ // rejected with 400 instead of being persisted.
166
+ let validated
167
+ try {
168
+ validated = Config(structuredClone(newConfig))
169
+ } catch (verr) {
170
+ writeJson(res, 400, { ok: false, error: 'Invalid presets payload: ' + (verr?.message || String(verr)) })
171
+ return
172
+ }
173
+
174
+ // Persist via saveConfig (in-memory and DSH profile settings)
175
+ let persistResult
176
+ if (typeof saveConfig === 'function') {
177
+ try { persistResult = await saveConfig(validated) }
178
+ catch (perr) { return writeJson(res, 500, { ok: false, error: 'Settings persistence failed: ' + (perr?.message || String(perr)) }) }
179
+ }
180
+
181
+ const unwrapped = typeof plainConfig === 'function' ? plainConfig(validated) : validated
182
+ writeJson(res, 200, {
183
+ ok: true,
184
+ persisted: persistResult?.persisted ?? false,
185
+ enabled: unwrapped.enabled !== false,
186
+ defaultPreset: unwrapped.default_preset,
187
+ presets: unwrapped.presets,
188
+ })
189
+ } catch (err) { writeJson(res, 400, { ok: false, error: err?.message || String(err) }) }
190
+ return
191
+ }
192
+
193
+ writeJson(res, 405, { ok: false, error: 'Method Not Allowed' })
194
+ },
195
+ })
196
+ }, 'dsh-moa: presets route')
197
+
198
+ // Route: /dsh-moa/history (#9)
199
+
200
+ ctx.effect(() => {
201
+ return ctx.webServer.register({
202
+ kind: 'exact',
203
+ path: '/dsh-moa/route-preset',
204
+ handler: async (req, res) => {
205
+ if (!assertAuthorizedRequest(req, res, ctx)) return
206
+ if (req.method !== 'POST') return writeJson(res, 405, { ok: false, error: 'POST required' })
207
+ if (!isSafeWriteRequest(req)) {
208
+ writeJson(res, 403, { ok: false, error: 'Forbidden: cross-site request rejected' })
209
+ return
210
+ }
211
+ try {
212
+ const cfg = live()
213
+ if (cfg.enabled === false) {
214
+ writeJson(res, 400, { ok: false, error: 'MoA is disabled in settings' })
215
+ return
216
+ }
217
+ const raw = await readBody(req)
218
+ const body = JSON.parse(raw || '{}')
219
+ const prompt = body?.prompt || ''
220
+ const activePreset = (cfg.presets || []).find((p) => p.name === (cfg.default_preset || 'default')) || cfg.presets?.[0]
221
+ const routingModel = (activePreset?.smart_routing_model?.model && activePreset.smart_routing_model)
222
+ || (cfg.smart_routing_model?.model && cfg.smart_routing_model) || activePreset?.smart_routing_model || cfg.smart_routing_model
223
+ const result = await resolvePresetForPrompt({
224
+ prompt,
225
+ presets: cfg.presets || [],
226
+ defaultPreset: cfg.default_preset || 'default',
227
+ routingModel,
228
+ callLlm,
229
+ enabled: cfg.enabled !== false,
230
+ })
231
+ writeJson(res, 200, { ok: true, ...result })
232
+ } catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
233
+ },
234
+ })
235
+ }, 'dsh-moa: route preset endpoint')
236
+
237
+ let _lastRunTimestamp = 0
238
+ const RUN_MIN_INTERVAL_MS = 1000
239
+
240
+ // Route: /dsh-moa/run
241
+ }
@@ -0,0 +1,197 @@
1
+ import path from 'node:path'
2
+ import { getMoaHistory, getMoaRunById, isTestEnvironment } from '../history.js'
3
+ import { promoteCandidateWorkspace, readCandidateFiles, computeLineDiff, isSafeRelativePath, isLoopbackUrl } from '../file-workspace.js'
4
+ import { writeJson, readBody, isAllowedWorkspace, assertAuthorizedRequest } from '../access.js'
5
+ import { isSafeWriteRequest } from '../updater.js'
6
+ import { generateMoABenchmarkReport } from '../moa-report.js'
7
+ import { handleWorkbenchGet, handleWorkbenchAssemble } from '../moa-workbench.js'
8
+
9
+ export function registerWorkbenchRoutes(ctx, { live, callLlm, webServerPort, timeMachineEngine, workspaceRoot }) {
10
+ ctx.effect(() => {
11
+ return ctx.webServer.register({
12
+ kind: 'exact',
13
+ path: '/dsh-moa/promote',
14
+ handler: async (req, res) => {
15
+ if (!assertAuthorizedRequest(req, res, ctx)) return
16
+ if (req.method !== 'POST') return writeJson(res, 405, { ok: false, error: 'POST required' })
17
+ if (!isSafeWriteRequest(req)) {
18
+ writeJson(res, 403, { ok: false, error: 'Forbidden: cross-site request rejected' })
19
+ return
20
+ }
21
+ try {
22
+ const raw = await readBody(req)
23
+ const body = JSON.parse(raw || '{}')
24
+ const candidateIndex = parseInt(body?.candidateIndex, 10)
25
+ if (isNaN(candidateIndex) || candidateIndex < 1) {
26
+ writeJson(res, 400, { ok: false, error: 'Valid candidateIndex required (>= 1)' })
27
+ return
28
+ }
29
+ const runId = body?.runId
30
+ let recordedRun = null
31
+ if (runId) {
32
+ recordedRun = getMoaRunById(runId)
33
+ if (!recordedRun) {
34
+ writeJson(res, 404, { ok: false, error: `Run '${runId}' not found` })
35
+ return
36
+ }
37
+ } else {
38
+ recordedRun = getMoaHistory(1, 0)?.runs?.[0] || null
39
+ if (!recordedRun) {
40
+ writeJson(res, 400, { ok: false, error: 'No recorded MoA run found' })
41
+ return
42
+ }
43
+ }
44
+ if (body?.cwd && path.resolve(body.cwd) !== path.resolve(recordedRun.cwd)) {
45
+ writeJson(res, 403, { ok: false, error: 'Forbidden: cwd does not match recorded run cwd' })
46
+ return
47
+ }
48
+ const effectiveCwd = recordedRun.cwd
49
+ const promotedFiles = await promoteCandidateWorkspace(effectiveCwd, candidateIndex, {
50
+ runId: recordedRun.id,
51
+ keepMoa: true,
52
+ port: ctx.webServer?.port,
53
+ timeMachineEngine: timeMachineEngine || ctx.reflect?.get?.('timeMachineEngine', false),
54
+ force: Boolean(body?.force),
55
+ })
56
+ writeJson(res, 200, { ok: true, candidateIndex, promotedFiles, checkpoint: promotedFiles?.checkpoint || null })
57
+ } catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
58
+ },
59
+ })
60
+ }, 'dsh-moa: promote candidate route')
61
+
62
+ // Route: /dsh-moa/diff (Candidate Diff Viewer)
63
+
64
+ ctx.effect(() => {
65
+ return ctx.webServer.register({
66
+ kind: 'exact',
67
+ path: '/dsh-moa/diff',
68
+ handler: async (req, res) => {
69
+ if (!assertAuthorizedRequest(req, res, ctx)) return
70
+ if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
71
+ try {
72
+ const u = new URL(req.url, 'http://localhost')
73
+ const rawRunId = u.searchParams.get('runId')
74
+ const queryCwd = u.searchParams.get('cwd')
75
+ let run = null
76
+ if (rawRunId && rawRunId !== 'latest' && rawRunId !== 'active') {
77
+ run = getMoaRunById(rawRunId)
78
+ if (!run) {
79
+ writeJson(res, 404, { ok: false, error: `Run '${rawRunId}' not found` })
80
+ return
81
+ }
82
+ } else {
83
+ run = getMoaHistory(1, 0)?.runs?.[0] || null
84
+ if (!run) {
85
+ writeJson(res, 404, { ok: false, error: 'No recorded MoA run found' })
86
+ return
87
+ }
88
+ }
89
+ if (queryCwd && path.resolve(queryCwd) !== path.resolve(run.cwd)) {
90
+ writeJson(res, 403, { ok: false, error: 'Forbidden: cwd does not match recorded run cwd' })
91
+ return
92
+ }
93
+ const runId = run.id
94
+ const cwd = run.cwd
95
+ const sanitizeTarget = (val, def) => {
96
+ const clean = String(val || '').trim().replace(/[^a-zA-Z0-9_-]/g, '')
97
+ return clean || def
98
+ }
99
+ const from = sanitizeTarget(u.searchParams.get('from'), '1')
100
+ const to = sanitizeTarget(u.searchParams.get('to'), 'curator-synthesis')
101
+ const rawFile = u.searchParams.get('file') || ''
102
+ const file = (rawFile && isSafeRelativePath(rawFile)) ? rawFile : ''
103
+
104
+ const fromFiles = await readCandidateFiles(cwd, from, { runId })
105
+ const toFiles = await readCandidateFiles(cwd, to, { runId })
106
+
107
+ // Collect all unique file paths
108
+ const allPaths = Array.from(new Set([
109
+ ...fromFiles.map((f) => f.relativePath),
110
+ ...toFiles.map((f) => f.relativePath),
111
+ ])).sort()
112
+
113
+ const targetPath = file || allPaths[0] || ''
114
+ const fromItem = fromFiles.find((f) => f.relativePath === targetPath)
115
+ const toItem = toFiles.find((f) => f.relativePath === targetPath)
116
+
117
+ const diff = targetPath
118
+ ? computeLineDiff(fromItem?.content || '', toItem?.content || '')
119
+ : []
120
+
121
+ writeJson(res, 200, {
122
+ ok: true,
123
+ from,
124
+ to,
125
+ files: allPaths,
126
+ selectedFile: targetPath,
127
+ fromSize: fromItem?.size || 0,
128
+ toSize: toItem?.size || 0,
129
+ diff,
130
+ })
131
+ } catch (err) { writeJson(res, 500, { ok: false, error: err?.message || String(err) }) }
132
+ },
133
+ })
134
+ }, 'dsh-moa: candidate diff route')
135
+
136
+ // Route: /dsh-moa/history/export
137
+
138
+ ctx.effect(() => {
139
+ return ctx.webServer.register({
140
+ kind: 'prefix',
141
+ path: '/dsh-moa/runs',
142
+ handler: (req, res) => {
143
+ if (!assertAuthorizedRequest(req, res, ctx)) return
144
+ const urlPath = req.url.split('?')[0]
145
+ const parts = urlPath.split('/').filter(Boolean)
146
+ const runId = parts[2] || ''
147
+ if (parts[3] === 'workbench') {
148
+ const targetCwd = workspaceRoot || ctx?.reflect?.get?.('baseDir', false) || ctx?.reflect?.get?.('workspaceDir', false) || process.cwd()
149
+ if (req.method === 'GET') {
150
+ return handleWorkbenchGet(req, res, { runId, cwd: targetCwd })
151
+ }
152
+ if (req.method === 'POST') {
153
+ if (!isSafeWriteRequest(req)) {
154
+ return writeJson(res, 403, { ok: false, error: 'Forbidden: cross-site request rejected' })
155
+ }
156
+ return handleWorkbenchAssemble(req, res, { runId, cwd: targetCwd, live, callLlm, webServerPort, timeMachineEngine })
157
+ }
158
+ return writeJson(res, 405, { ok: false, error: 'Method not allowed' })
159
+ }
160
+ if (req.method !== 'GET') return writeJson(res, 405, { ok: false, error: 'GET required' })
161
+ const isReport = parts[3] === 'report'
162
+ const run = runId ? getMoaRunById(runId) : null
163
+ if (!run) {
164
+ writeJson(res, 404, { ok: false, error: 'Run not found' })
165
+ return
166
+ }
167
+ if (isReport) {
168
+ const u = new URL(req.url, 'http://127.0.0.1')
169
+ const format = u.searchParams.get('format') || 'md'
170
+ const report = run.benchmarkReport || generateMoABenchmarkReport({
171
+ runId: run.id,
172
+ timestamp: run.timestamp,
173
+ preset: run.preset,
174
+ prompt: run.prompt,
175
+ durationMs: run.durationMs,
176
+ usage: { totalTokens: run.totalTokens },
177
+ costUsd: run.totalCostUsd,
178
+ candidates: run.candidates,
179
+ winningIndex: run.winnerIndex,
180
+ winningLabel: run.winnerModel,
181
+ })
182
+ if (format === 'json') {
183
+ writeJson(res, 200, { ok: true, report: typeof report === 'object' ? (report.json || report) : report })
184
+ return
185
+ }
186
+ const mdText = typeof report === 'string' ? report : (report.markdown || JSON.stringify(report, null, 2))
187
+ res.writeHead(200, { 'Content-Type': 'text/markdown; charset=utf-8' })
188
+ res.end(mdText)
189
+ return
190
+ }
191
+ writeJson(res, 200, { ok: true, run })
192
+ },
193
+ })
194
+ }, 'dsh-moa: run by id route')
195
+
196
+ // Route: /dsh-moa/route-preset
197
+ }