vibeoscore 1.0.2 → 1.0.9

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.
Files changed (45) hide show
  1. package/client.js +1 -0
  2. package/client.ts +2 -0
  3. package/lib/logger.js +27 -0
  4. package/mcp-server.js +5 -4
  5. package/mcp-server.ts +4 -3
  6. package/package.json +12 -10
  7. package/dashboard/dist/assets/index-BnPt1Fii.js +0 -1
  8. package/dashboard/dist/assets/index-CfH00tOL.css +0 -1
  9. package/dashboard/dist/index.html +0 -3
  10. package/lib/blackbox-rf.js +0 -1099
  11. package/lib/blackbox.js +0 -137
  12. package/lib/compression.js +0 -119
  13. package/lib/db.js +0 -106
  14. package/lib/db.ts +0 -113
  15. package/lib/delegation.js +0 -137
  16. package/lib/meta-controller.js +0 -418
  17. package/lib/meta-controller.mjs +0 -499
  18. package/lib/patterns.js +0 -150
  19. package/lib/resolution-tracker.js +0 -486
  20. package/lib/stress.js +0 -84
  21. package/lib/tdd.js +0 -218
  22. package/lib/tier-routing.js +0 -48
  23. package/middleware/auth.js +0 -75
  24. package/middleware/auth.ts +0 -87
  25. package/middleware/usage-logging.js +0 -29
  26. package/middleware/usage-logging.ts +0 -41
  27. package/nginx-vibetheog-api.conf +0 -64
  28. package/routes/admin.js +0 -93
  29. package/routes/admin.ts +0 -107
  30. package/routes/blackbox.js +0 -463
  31. package/routes/compression.js +0 -12
  32. package/routes/delegation.js +0 -30
  33. package/routes/patterns.js +0 -53
  34. package/routes/pricing.js +0 -62
  35. package/routes/stress.js +0 -30
  36. package/routes/tdd.js +0 -68
  37. package/routes/tier-routing.js +0 -31
  38. package/scripts/dashboard-server.mjs +0 -246
  39. package/scripts/deploy-zero-downtime.sh +0 -77
  40. package/scripts/deploy.sh +0 -68
  41. package/scripts/release.mjs +0 -30
  42. package/scripts/seed-master-token.js +0 -29
  43. package/scripts/start-all.mjs +0 -34
  44. package/server.js +0 -88
  45. package/vibeos-api.service +0 -19
package/routes/admin.ts DELETED
@@ -1,107 +0,0 @@
1
- import { getDb } from "../lib/db.js"
2
- import { randomBytes } from "node:crypto"
3
-
4
- function generateToken() {
5
- return "vos_" + randomBytes(32).toString("hex")
6
- }
7
-
8
- export async function adminRoutes(fastify: any) {
9
- fastify.post("/admin/seats", async (request: any, reply: any) => {
10
- const { name, email } = request.body || {}
11
- if (!name) {
12
- return reply.code(400).send({ error: "name is required" })
13
- }
14
- const db = getDb()
15
- const result = db.prepare("INSERT INTO seats (name, email) VALUES (?, ?)").run(name, email || null)
16
- const seat = db.prepare("SELECT * FROM seats WHERE id = ?").get(result.lastInsertRowid)
17
- return { ok: true, seat }
18
- })
19
-
20
- fastify.get("/admin/seats", async (request: any, reply: any) => {
21
- const db = getDb()
22
- const seats = db.prepare("SELECT * FROM seats ORDER BY created_at DESC").all()
23
- return { seats, count: seats.length }
24
- })
25
-
26
- fastify.patch("/admin/seats/:id", async (request: any, reply: any) => {
27
- const { id } = request.params
28
- const { status } = request.body || {}
29
- if (!status || !["active", "suspended", "cancelled"].includes(status)) {
30
- return reply.code(400).send({ error: "valid status is required (active, suspended, cancelled)" })
31
- }
32
- const db = getDb()
33
- const result = db.prepare("UPDATE seats SET status = ?, updated_at = datetime('now') WHERE id = ?").run(status, id)
34
- if (result.changes === 0) {
35
- return reply.code(404).send({ error: "seat not found" })
36
- }
37
-
38
- if (status !== "active") {
39
- db.prepare("UPDATE api_tokens SET status = 'revoked', revoked_at = datetime('now') WHERE seat_id = ? AND status = 'active'").run(id)
40
- }
41
-
42
- const seat = db.prepare("SELECT * FROM seats WHERE id = ?").get(id)
43
- return { ok: true, seat }
44
- })
45
-
46
- fastify.post("/admin/tokens", async (request: any, reply: any) => {
47
- const { seat_id, label, expires_at } = request.body || {}
48
- if (!seat_id) {
49
- return reply.code(400).send({ error: "seat_id is required" })
50
- }
51
- const db = getDb()
52
- const seat = db.prepare("SELECT * FROM seats WHERE id = ?").get(seat_id)
53
- if (!seat) {
54
- return reply.code(404).send({ error: "seat not found" })
55
- }
56
-
57
- const token = generateToken()
58
- const result = db.prepare(
59
- "INSERT INTO api_tokens (token, seat_id, label, expires_at) VALUES (?, ?, ?, ?)"
60
- ).run(token, seat_id, label || null, expires_at || null)
61
-
62
- const tokenRow = db.prepare("SELECT * FROM api_tokens WHERE id = ?").get(result.lastInsertRowid)
63
- return { ok: true, token: tokenRow }
64
- })
65
-
66
- fastify.get("/admin/tokens", async (request: any, reply: any) => {
67
- const db = getDb()
68
- const tokens = db.prepare(`
69
- SELECT t.*, s.name as seat_name, s.email as seat_email, s.status as seat_status
70
- FROM api_tokens t
71
- JOIN seats s ON t.seat_id = s.id
72
- ORDER BY t.created_at DESC
73
- `).all()
74
- return { tokens, count: tokens.length }
75
- })
76
-
77
- fastify.patch("/admin/tokens/:id", async (request: any, reply: any) => {
78
- const { id } = request.params
79
- const { status } = request.body || {}
80
- if (!status || !["active", "revoked", "expired"].includes(status)) {
81
- return reply.code(400).send({ error: "valid status is required (active, revoked, expired)" })
82
- }
83
- const db = getDb()
84
- const update = status === "revoked"
85
- ? "UPDATE api_tokens SET status = ?, revoked_at = datetime('now') WHERE id = ?"
86
- : "UPDATE api_tokens SET status = ? WHERE id = ?"
87
- const result = db.prepare(update).run(status, id)
88
- if (result.changes === 0) {
89
- return reply.code(404).send({ error: "token not found" })
90
- }
91
- const token = db.prepare("SELECT * FROM api_tokens WHERE id = ?").get(id)
92
- return { ok: true, token }
93
- })
94
-
95
- fastify.get("/admin/usage", async (request: any, reply: any) => {
96
- const { days: daysRaw } = request.query || {}
97
- const days = Number(daysRaw)
98
- if (daysRaw !== undefined && (isNaN(days) || !Number.isFinite(days) || !Number.isInteger(days) || days < 1 || days > 365)) {
99
- return reply.code(400).send({ error: "days must be a positive integer between 1 and 365" })
100
- }
101
- const effectiveDays = days || 30
102
- const db = getDb()
103
- const sql = "SELECT t.token, t.label, s.name as seat_name, COUNT(*) as request_count, AVG(l.latency_ms) as avg_latency_ms, MIN(l.created_at) as first_used, MAX(l.created_at) as last_used FROM usage_log l JOIN api_tokens t ON l.token_id = t.id JOIN seats s ON t.seat_id = s.id WHERE l.created_at >= datetime('now', ?) GROUP BY t.id ORDER BY request_count DESC"
104
- const usage = db.prepare(sql).all("-" + effectiveDays + " days")
105
- return { usage, count: usage.length, days: effectiveDays }
106
- })
107
- }
@@ -1,463 +0,0 @@
1
- import { appendFileSync, mkdirSync } from "node:fs"
2
- import { dirname, resolve } from "node:path"
3
- import { fileURLToPath } from "node:url"
4
- import { ResolutionTracker, SUB_REGIMES, extractFeatures } from "../lib/blackbox.js"
5
- import { computeControlVector } from "../lib/meta-controller.js"
6
- import { getDb } from "../lib/db.js"
7
- import {
8
- getBlackboxRoutingModelMeta,
9
- rebuildBlackboxRoutingModel,
10
- selectBlackboxMode,
11
- } from "../lib/blackbox-rf.js"
12
-
13
- const trackers = new Map()
14
- const __dirname = dirname(fileURLToPath(import.meta.url))
15
- const TELEMETRY_PATH = process.env.VIBEOS_BLACKBOX_TELEMETRY_PATH || resolve(__dirname, "..", "data", "blackbox-telemetry.jsonl")
16
-
17
- function readSessionStateRow(sessionId) {
18
- try {
19
- const db = getDb()
20
- return db.prepare("SELECT state_json FROM blackbox_sessions WHERE session_id = ? ORDER BY updated_at DESC LIMIT 1").get(sessionId) || null
21
- } catch (err) {
22
- console.error(`[blackbox] readSessionStateRow failed for ${sessionId}: ${err.message}`)
23
- return null
24
- }
25
- }
26
-
27
- function parseStateJson(row) {
28
- if (!row?.state_json) return null
29
- try {
30
- return JSON.parse(row.state_json)
31
- } catch (err) {
32
- return null
33
- }
34
- }
35
-
36
- function loadTrackerFromDb(sessionId) {
37
- try {
38
- const data = parseStateJson(readSessionStateRow(sessionId))
39
- if (data) {
40
- return ResolutionTracker.deserialize(data)
41
- }
42
- } catch (err) {
43
- console.error(`[blackbox] loadTrackerFromDb failed for ${sessionId}: ${err.message}`)
44
- }
45
- return null
46
- }
47
-
48
- function appendTelemetryLog(record) {
49
- try {
50
- mkdirSync(dirname(TELEMETRY_PATH), { recursive: true })
51
- appendFileSync(TELEMETRY_PATH, `${JSON.stringify(record)}\n`, "utf-8")
52
- } catch (err) {
53
- console.error(`[blackbox] appendTelemetryLog failed: ${err.message}`)
54
- }
55
- }
56
-
57
- function saveTrackerToDb(sessionId, projectId, tracker, telemetry = null) {
58
- try {
59
- const db = getDb()
60
- const existing = parseStateJson(readSessionStateRow(sessionId))
61
- const serialized = tracker.serialize()
62
- const mergedTelemetry = {
63
- ...(existing?.telemetry && typeof existing.telemetry === "object" ? existing.telemetry : {}),
64
- ...(telemetry && typeof telemetry === "object" ? telemetry : {}),
65
- }
66
- const payload = {
67
- ...(existing && typeof existing === "object" ? existing : {}),
68
- ...serialized,
69
- }
70
- if (Object.keys(mergedTelemetry).length > 0) {
71
- payload.telemetry = mergedTelemetry
72
- }
73
- const stateJson = JSON.stringify(payload)
74
- const outcome = tracker.getOutcomeHistory().slice(-1)[0]?.outcome || null
75
- const now = new Date().toISOString()
76
- db.prepare(`
77
- INSERT INTO blackbox_sessions (session_id, project_id, state_json, outcome, created_at, updated_at)
78
- VALUES (?, ?, ?, ?, ?, ?)
79
- ON CONFLICT(session_id) DO UPDATE SET
80
- state_json = excluded.state_json,
81
- project_id = COALESCE(excluded.project_id, blackbox_sessions.project_id),
82
- outcome = COALESCE(excluded.outcome, blackbox_sessions.outcome),
83
- updated_at = excluded.updated_at
84
- `).run(sessionId, projectId || null, stateJson, outcome, now, now)
85
- if (Object.keys(mergedTelemetry).length > 0) {
86
- appendTelemetryLog({
87
- session_id: sessionId,
88
- project_id: projectId || null,
89
- event: "session_save",
90
- created_at: now,
91
- telemetry: mergedTelemetry,
92
- })
93
- }
94
- } catch (err) {
95
- console.error(`[blackbox] saveTrackerToDb failed for ${sessionId}: ${err.message}`)
96
- }
97
- }
98
-
99
- function getOrCreateTracker(sessionId, projectId) {
100
- let tracker = trackers.get(sessionId)
101
- if (!tracker) {
102
- tracker = loadTrackerFromDb(sessionId) || new ResolutionTracker(sessionId, projectId)
103
- trackers.set(sessionId, tracker)
104
- }
105
- if (projectId && !tracker.projectId) {
106
- tracker.projectId = projectId
107
- }
108
- return tracker
109
- }
110
-
111
- export async function blackboxRoutes(fastify) {
112
- fastify.post("/api/v1/blackbox/analyze", async (request, reply) => {
113
- const {
114
- session_id,
115
- project_id,
116
- user_text,
117
- prompt,
118
- features,
119
- action,
120
- entropy,
121
- uncertainty,
122
- embedding,
123
- latest_stress_multiplier,
124
- stress_multiplier,
125
- outcome,
126
- } = request.body || {}
127
-
128
- if (!user_text && !features && !action) {
129
- return reply.code(400).send({ error: "user_text is required" })
130
- }
131
-
132
- const sid = session_id || "default"
133
- const tracker = getOrCreateTracker(sid, project_id)
134
-
135
- const derivedFeatures = typeof features === "object" && !Array.isArray(features) && Object.keys(features || {}).length > 0
136
- ? features
137
- : extractFeatures(user_text)
138
-
139
- const state = tracker.update({
140
- userText: user_text || "",
141
- features: derivedFeatures,
142
- actions: typeof action === "string" ? [action] : (Array.isArray(action) ? action : []),
143
- entropy: entropy ?? 1.0,
144
- uncertainty: uncertainty ?? 50,
145
- embedding: embedding || null,
146
- })
147
-
148
- const selectionInput = {
149
- session_id: sid,
150
- project_id: project_id || tracker.projectId || null,
151
- user_text: user_text || "",
152
- prompt: prompt || "",
153
- features: derivedFeatures,
154
- state,
155
- pivot_detected: state.pivot_detected,
156
- pivot_score: state.pivot_score,
157
- resolution: state.resolution,
158
- continuity_state: state.continuity_state,
159
- is_looping: state.is_looping,
160
- loop_count: state.loop_consecutive,
161
- loop_consecutive: state.loop_consecutive,
162
- loop_intervention_level: state.loop_intervention_level,
163
- outcome: outcome || state.outcome || null,
164
- signals: state.signals,
165
- stress_multiplier: latest_stress_multiplier ?? stress_multiplier ?? 0,
166
- latest_stress_multiplier: latest_stress_multiplier ?? stress_multiplier ?? 0,
167
- }
168
- const selected = selectBlackboxMode(selectionInput)
169
- const controlVector = computeControlVector({
170
- ...state,
171
- user_text: user_text || "",
172
- prompt: prompt || "",
173
- features: derivedFeatures,
174
- latest_stress_multiplier: latest_stress_multiplier ?? stress_multiplier ?? 0,
175
- }, action, selected.mode)
176
- const telemetry = {
177
- observed_at: new Date().toISOString(),
178
- input: {
179
- user_text: user_text || "",
180
- prompt: prompt || "",
181
- action: typeof action === "string" ? action : Array.isArray(action) ? action[0] || null : null,
182
- entropy: entropy ?? 1.0,
183
- uncertainty: uncertainty ?? 50,
184
- latest_stress_multiplier: latest_stress_multiplier ?? stress_multiplier ?? 0,
185
- },
186
- selection: {
187
- optimization_mode: selected.mode,
188
- source: selected.source,
189
- confidence: selected.confidence,
190
- probabilities: selected.probabilities || {},
191
- },
192
- context_packet: controlVector.context_packet,
193
- control_vector: controlVector,
194
- signals: {
195
- sub_regime: state.sub_regime,
196
- resolution: state.resolution,
197
- continuity_state: state.continuity_state,
198
- pivot_detected: state.pivot_detected,
199
- pivot_score: state.pivot_score,
200
- is_looping: state.is_looping,
201
- loop_intervention_level: state.loop_intervention_level,
202
- loop_consecutive: state.loop_consecutive,
203
- action_consistency: state.signals?.action_consistency,
204
- n_interactions: state.n_interactions,
205
- outcome: outcome || state.outcome || null,
206
- },
207
- features: derivedFeatures,
208
- feature_vector: selected.features || [],
209
- }
210
-
211
- tracker.annotateLastTurn(telemetry)
212
- saveTrackerToDb(sid, project_id, tracker, telemetry)
213
-
214
- return {
215
- ...state,
216
- session_id: sid,
217
- project_id: project_id || tracker.projectId || null,
218
- features: derivedFeatures,
219
- optimization_mode: selected.mode,
220
- optimization_source: selected.source,
221
- optimization_confidence: selected.confidence,
222
- context_packet: controlVector.context_packet,
223
- control_vector: controlVector,
224
- }
225
- })
226
-
227
- fastify.post("/api/v1/blackbox/state", async (request, reply) => {
228
- const { session_id, project_id } = request.body || {}
229
- const sid = session_id || "default"
230
- const tracker = getOrCreateTracker(sid, project_id)
231
-
232
- return {
233
- ...tracker.getState(),
234
- session_id: sid,
235
- project_id: project_id || tracker.projectId || null,
236
- }
237
- })
238
-
239
- fastify.post("/api/v1/blackbox/reset", async (request, reply) => {
240
- const { session_id } = request.body || {}
241
- const sid = session_id || "default"
242
- trackers.delete(sid)
243
- try {
244
- getDb().prepare("DELETE FROM blackbox_sessions WHERE session_id = ?").run(sid)
245
- } catch {}
246
- return { ok: true, message: "tracker reset" }
247
- })
248
-
249
- fastify.get("/api/v1/blackbox/regimes", async (request, reply) => {
250
- return { regimes: SUB_REGIMES }
251
- })
252
-
253
- fastify.get("/api/v1/blackbox/project-sessions", async (request, reply) => {
254
- const { project_id } = request.query || {}
255
- if (!project_id) {
256
- return reply.code(400).send({ error: "project_id query parameter is required" })
257
- }
258
- try {
259
- const db = getDb()
260
- const rows = db.prepare(
261
- "SELECT session_id, created_at, updated_at, outcome FROM blackbox_sessions WHERE project_id = ? ORDER BY updated_at DESC LIMIT 50"
262
- ).all(project_id)
263
- return { project_id, sessions: rows }
264
- } catch (err) {
265
- return reply.code(500).send({ error: "failed to query sessions" })
266
- }
267
- })
268
-
269
- fastify.post("/api/v1/blackbox/outcome", async (request, reply) => {
270
- const { session_id, outcome } = request.body || {}
271
- if (!session_id || !outcome) {
272
- return reply.code(400).send({ error: "session_id and outcome are required" })
273
- }
274
- const sid = session_id
275
- const tracker = trackers.get(sid) || loadTrackerFromDb(sid)
276
- if (tracker) {
277
- tracker.recordOutcome(outcome)
278
- tracker.annotateLastTurn({
279
- observed_at: new Date().toISOString(),
280
- outcome,
281
- })
282
- }
283
- try {
284
- const db = getDb()
285
- db.prepare("UPDATE blackbox_sessions SET outcome = ?, updated_at = ? WHERE session_id = ?")
286
- .run(outcome, new Date().toISOString(), sid)
287
- if (tracker) {
288
- saveTrackerToDb(sid, tracker.projectId || null, tracker, {
289
- observed_at: new Date().toISOString(),
290
- outcome,
291
- })
292
- }
293
- } catch {}
294
- return { ok: true, session_id: sid, outcome }
295
- })
296
-
297
- fastify.post("/api/v1/blackbox/calibrate", async (request, reply) => {
298
- const { project_id } = request.body || {}
299
- const pid = project_id || "global"
300
- try {
301
- const db = getDb()
302
- const sessions = db.prepare(
303
- "SELECT state_json, outcome FROM blackbox_sessions WHERE project_id = ? AND outcome IS NOT NULL"
304
- ).all(pid)
305
-
306
- if (sessions.length < 3) {
307
- return reply.code(400).send({
308
- error: "need at least 3 sessions with outcomes to calibrate",
309
- samples: sessions.length,
310
- })
311
- }
312
-
313
- const outcomes = sessions.map(s => JSON.parse(s.state_json))
314
- const loopSessions = outcomes.filter(o => {
315
- try {
316
- const state = typeof o === "string" ? JSON.parse(o) : o
317
- return state?.is_looping
318
- } catch { return false }
319
- })
320
- const positiveOutcomes = sessions.filter(s => s.outcome === "positive").length
321
- const total = sessions.length
322
-
323
- const weights = {
324
- momentum: [-0.3, 0.5, 0.2],
325
- subRegime: {
326
- CONVERGING: -0.10,
327
- CLOSED: -0.10,
328
- DIVERGENT: +0.15,
329
- REFINING: 0.00,
330
- EXPLORING: +0.10,
331
- LOOPING: +0.15,
332
- INIT: +0.05,
333
- },
334
- loopJaccard: loopSessions.length > 0 ? 0.6 - (loopSessions.length / total) * 0.1 : 0.6,
335
- closureConfidence: positiveOutcomes > 0 ? 0.7 - (positiveOutcomes / total) * 0.1 : 0.7,
336
- }
337
-
338
- db.prepare(`
339
- INSERT INTO blackbox_calibration (project_id, weights_json, samples_used, updated_at)
340
- VALUES (?, ?, ?, ?)
341
- ON CONFLICT(project_id) DO UPDATE SET
342
- weights_json = excluded.weights_json,
343
- samples_used = excluded.samples_used,
344
- updated_at = excluded.updated_at
345
- `).run(pid, JSON.stringify(weights), total, new Date().toISOString())
346
-
347
- const tracker = [...trackers.values()].find(t => t.projectId === pid)
348
- if (tracker) {
349
- tracker.setCalibratedWeights(weights)
350
- }
351
-
352
- return { ok: true, project_id: pid, samples: total, weights }
353
- } catch (err) {
354
- return reply.code(500).send({ error: `calibration failed: ${err.message}` })
355
- }
356
- })
357
-
358
- fastify.get("/api/v1/blackbox/calibration", async (request, reply) => {
359
- const { project_id } = request.query || {}
360
- const pid = project_id || "global"
361
- try {
362
- const db = getDb()
363
- const row = db.prepare(
364
- "SELECT weights_json, samples_used, updated_at FROM blackbox_calibration WHERE project_id = ?"
365
- ).get(pid)
366
- if (!row) {
367
- return { project_id: pid, calibrated: false, message: "no calibration data yet" }
368
- }
369
- return {
370
- project_id: pid,
371
- calibrated: true,
372
- weights: JSON.parse(row.weights_json),
373
- samples_used: row.samples_used,
374
- updated_at: row.updated_at,
375
- }
376
- } catch (err) {
377
- return reply.code(500).send({ error: `failed to read calibration: ${err.message}` })
378
- }
379
- })
380
-
381
- fastify.post("/api/v1/blackbox/control-vector", async (request, reply) => {
382
- const {
383
- sub_regime,
384
- is_looping,
385
- loop_intervention_level,
386
- momentum,
387
- n_interactions,
388
- latest_stress_multiplier,
389
- action,
390
- optimization_mode,
391
- user_text,
392
- prompt,
393
- features,
394
- pivot_detected,
395
- pivot_score,
396
- resolution,
397
- continuity_state,
398
- outcome,
399
- signals,
400
- } = request.body || {}
401
- const state = {
402
- sub_regime,
403
- is_looping,
404
- loop_intervention_level,
405
- momentum,
406
- n_interactions,
407
- latest_stress_multiplier,
408
- user_text,
409
- prompt,
410
- features,
411
- pivot_detected,
412
- pivot_score,
413
- resolution,
414
- continuity_state,
415
- outcome,
416
- signals,
417
- }
418
- const cv = computeControlVector(state, action, optimization_mode)
419
- return { ok: true, control_vector: cv }
420
- })
421
-
422
- fastify.post("/api/v1/blackbox/select-mode", async (request, reply) => {
423
- const result = selectBlackboxMode(request.body || {})
424
- return { ok: true, mode: result.mode, ...result }
425
- })
426
-
427
- fastify.get("/api/v1/blackbox/model", async () => {
428
- return { ok: true, ...getBlackboxRoutingModelMeta() }
429
- })
430
-
431
- fastify.post("/api/v1/blackbox/model/rebuild", async (request, reply) => {
432
- const {
433
- project_id,
434
- limit,
435
- include_bootstrap,
436
- seed,
437
- tree_count,
438
- max_depth,
439
- min_samples_split,
440
- min_samples_leaf,
441
- feature_subsample,
442
- confidence_threshold,
443
- } = request.body || {}
444
-
445
- const result = rebuildBlackboxRoutingModel({
446
- projectId: project_id || null,
447
- limit: Number.isFinite(Number(limit)) ? Number(limit) : 5000,
448
- includeBootstrap: include_bootstrap !== false,
449
- seed: Number.isFinite(Number(seed)) ? Number(seed) : 42,
450
- treeCount: Number.isFinite(Number(tree_count)) ? Number(tree_count) : undefined,
451
- maxDepth: Number.isFinite(Number(max_depth)) ? Number(max_depth) : undefined,
452
- minSamplesSplit: Number.isFinite(Number(min_samples_split)) ? Number(min_samples_split) : undefined,
453
- minSamplesLeaf: Number.isFinite(Number(min_samples_leaf)) ? Number(min_samples_leaf) : undefined,
454
- featureSubsample: Number.isFinite(Number(feature_subsample)) ? Number(feature_subsample) : undefined,
455
- confidenceThreshold: Number.isFinite(Number(confidence_threshold)) ? Number(confidence_threshold) : undefined,
456
- })
457
-
458
- if (!result.ok) {
459
- return reply.code(400).send(result)
460
- }
461
- return result
462
- })
463
- }
@@ -1,12 +0,0 @@
1
- import { compressToolOutput, COMPRESS_THRESHOLD } from "../lib/compression.js"
2
-
3
- export async function compressionRoutes(fastify) {
4
- fastify.post("/api/v1/compress/context", async (request, reply) => {
5
- const { text, threshold } = request.body || {}
6
- if (!text) {
7
- return reply.code(400).send({ error: "text is required" })
8
- }
9
- const result = compressToolOutput(text, threshold || COMPRESS_THRESHOLD)
10
- return result
11
- })
12
- }
@@ -1,30 +0,0 @@
1
- import { checkDelegation, checkSoftQuota, modelCostPerTurn, normalizeModelId } from "../lib/delegation.js"
2
-
3
- export async function delegationRoutes(fastify) {
4
- fastify.post("/api/v1/delegate/check", async (request, reply) => {
5
- const { tool, tier, model, prompt, dynamic_cache } = request.body || {}
6
- if (!tool || !tier) {
7
- return reply.code(400).send({ error: "tool and tier are required" })
8
- }
9
- const result = checkDelegation(tool, tier, model, prompt, dynamic_cache || {})
10
- return result
11
- })
12
-
13
- fastify.post("/api/v1/delegate/soft-quota", async (request, reply) => {
14
- const { tool, current_count, limit } = request.body || {}
15
- if (!tool) {
16
- return reply.code(400).send({ error: "tool is required" })
17
- }
18
- const result = checkSoftQuota(tool, current_count || 0, limit)
19
- return result
20
- })
21
-
22
- fastify.post("/api/v1/delegation/cost", async (request, reply) => {
23
- const { model, dynamic_cache } = request.body || {}
24
- if (!model) {
25
- return reply.code(400).send({ error: "model is required" })
26
- }
27
- const cost = modelCostPerTurn(model, dynamic_cache || {})
28
- return { model: normalizeModelId(model), cost_per_turn: cost }
29
- })
30
- }
@@ -1,53 +0,0 @@
1
- import { PatternStore } from "../lib/patterns.js"
2
-
3
- const stores = new Map()
4
-
5
- function getStore(sessionId = "default") {
6
- if (!stores.has(sessionId)) {
7
- stores.set(sessionId, new PatternStore())
8
- }
9
- return stores.get(sessionId)
10
- }
11
-
12
- export async function patternRoutes(fastify) {
13
- fastify.post("/api/v1/patterns/observe", async (request, reply) => {
14
- const { session_id, tool_name, input, output, directory } = request.body || {}
15
- if (!tool_name) {
16
- return reply.code(400).send({ error: "tool_name is required" })
17
- }
18
- const store = getStore(session_id)
19
- const patterns = store.observeToolEvent(tool_name, input, output, directory)
20
- return { patterns_detected: patterns.length, patterns }
21
- })
22
-
23
- fastify.post("/api/v1/patterns/record", async (request, reply) => {
24
- const { session_id, kind, key, summary, meta } = request.body || {}
25
- if (!kind || !key || !summary) {
26
- return reply.code(400).send({ error: "kind, key, and summary are required" })
27
- }
28
- const store = getStore(session_id)
29
- const pattern = store.recordPattern(kind, key, summary, meta || {})
30
- return pattern
31
- })
32
-
33
- fastify.get("/api/v1/patterns/query", async (request, reply) => {
34
- const { session_id, kind } = request.query || {}
35
- const store = getStore(session_id)
36
- const patterns = store.getPatterns(kind || null)
37
- return { patterns, count: patterns.length }
38
- })
39
-
40
- fastify.get("/api/v1/patterns/exploratory-words", async (request, reply) => {
41
- const { session_id } = request.query || {}
42
- const store = getStore(session_id)
43
- const words = store.getLearnedExploratoryWords()
44
- return { words }
45
- })
46
-
47
- fastify.post("/api/v1/patterns/clear", async (request, reply) => {
48
- const { session_id } = request.body || {}
49
- const store = getStore(session_id)
50
- store.clear()
51
- return { ok: true }
52
- })
53
- }