@marinoscar/kvox-eval 0.0.0-bootstrap → 0.1.0-next.0

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 (245) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +166 -0
  4. package/dist/ask/index.d.ts +6 -0
  5. package/dist/ask/index.js +28 -0
  6. package/dist/ask/question-schema.d.ts +121 -0
  7. package/dist/ask/question-schema.js +167 -0
  8. package/dist/ask/report.d.ts +88 -0
  9. package/dist/ask/report.js +170 -0
  10. package/dist/ask/scorer.d.ts +104 -0
  11. package/dist/ask/scorer.js +164 -0
  12. package/dist/ask-run/ask-command.d.ts +62 -0
  13. package/dist/ask-run/ask-command.js +254 -0
  14. package/dist/ask-run/host/app.d.ts +65 -0
  15. package/dist/ask-run/host/app.js +146 -0
  16. package/dist/ask-run/host/db.d.ts +38 -0
  17. package/dist/ask-run/host/db.js +126 -0
  18. package/dist/ask-run/host/ports.d.ts +35 -0
  19. package/dist/ask-run/host/ports.js +113 -0
  20. package/dist/ask-run/index.d.ts +13 -0
  21. package/dist/ask-run/index.js +35 -0
  22. package/dist/ask-run/replay.d.ts +128 -0
  23. package/dist/ask-run/replay.js +212 -0
  24. package/dist/ask-run/run-ask-eval.d.ts +125 -0
  25. package/dist/ask-run/run-ask-eval.js +193 -0
  26. package/dist/ask-run/seed-golden-graph.d.ts +64 -0
  27. package/dist/ask-run/seed-golden-graph.js +495 -0
  28. package/dist/cli/index.d.ts +3 -0
  29. package/dist/cli/index.js +12 -0
  30. package/dist/cli/kg-command.d.ts +66 -0
  31. package/dist/cli/kg-command.js +238 -0
  32. package/dist/cli/main.d.ts +18 -0
  33. package/dist/cli/main.js +69 -0
  34. package/dist/fixtures/domains.d.ts +16 -0
  35. package/dist/fixtures/domains.js +33 -0
  36. package/dist/fixtures/fixture-schema.d.ts +323 -0
  37. package/dist/fixtures/fixture-schema.js +199 -0
  38. package/dist/fixtures/index.d.ts +16 -0
  39. package/dist/fixtures/index.js +40 -0
  40. package/dist/fixtures/load.d.ts +73 -0
  41. package/dist/fixtures/load.js +137 -0
  42. package/dist/fixtures/questions.d.ts +15 -0
  43. package/dist/fixtures/questions.js +26 -0
  44. package/dist/index.d.ts +20 -0
  45. package/dist/index.js +36 -0
  46. package/dist/kg/gold-runner.d.ts +13 -0
  47. package/dist/kg/gold-runner.js +57 -0
  48. package/dist/kg/index.d.ts +17 -0
  49. package/dist/kg/index.js +65 -0
  50. package/dist/kg/internals.d.ts +7 -0
  51. package/dist/kg/internals.js +17 -0
  52. package/dist/kg/prediction-schema.d.ts +245 -0
  53. package/dist/kg/prediction-schema.js +102 -0
  54. package/dist/kg/predictions.d.ts +11 -0
  55. package/dist/kg/predictions.js +49 -0
  56. package/dist/kg/report.d.ts +84 -0
  57. package/dist/kg/report.js +125 -0
  58. package/dist/kg/run-kg-eval.d.ts +77 -0
  59. package/dist/kg/run-kg-eval.js +137 -0
  60. package/dist/kg/runner.d.ts +72 -0
  61. package/dist/kg/runner.js +51 -0
  62. package/dist/kg/runners/extract-resolve-runner.d.ts +40 -0
  63. package/dist/kg/runners/extract-resolve-runner.js +199 -0
  64. package/dist/kg/runners/extract-runner.d.ts +65 -0
  65. package/dist/kg/runners/extract-runner.js +243 -0
  66. package/dist/kg/scorer.d.ts +226 -0
  67. package/dist/kg/scorer.js +463 -0
  68. package/dist/kg/targets.d.ts +17 -0
  69. package/dist/kg/targets.js +16 -0
  70. package/dist/kg/text.d.ts +45 -0
  71. package/dist/kg/text.js +100 -0
  72. package/dist/live/adapters.d.ts +16 -0
  73. package/dist/live/adapters.js +58 -0
  74. package/dist/live/env.d.ts +39 -0
  75. package/dist/live/env.js +56 -0
  76. package/dist/live/index.d.ts +6 -0
  77. package/dist/live/index.js +16 -0
  78. package/dist/live/live-ai.d.ts +104 -0
  79. package/dist/live/live-ai.js +157 -0
  80. package/dist/parity/constants.d.ts +79 -0
  81. package/dist/parity/constants.js +104 -0
  82. package/dist/parity/index.d.ts +20 -0
  83. package/dist/parity/index.js +38 -0
  84. package/dist/parity/internals.d.ts +8 -0
  85. package/dist/parity/internals.js +16 -0
  86. package/dist/parity/scenario.d.ts +45 -0
  87. package/dist/parity/scenario.js +245 -0
  88. package/dist/parity/script.d.ts +44 -0
  89. package/dist/parity/script.js +136 -0
  90. package/dist/parity/snapshot.d.ts +43 -0
  91. package/dist/parity/snapshot.js +71 -0
  92. package/dist/real-data/index.d.ts +2 -0
  93. package/dist/real-data/index.js +12 -0
  94. package/dist/real-data/real-data.d.ts +76 -0
  95. package/dist/real-data/real-data.js +156 -0
  96. package/fixtures/kg-golden/README.md +136 -0
  97. package/fixtures/kg-golden/ask-questions.json +458 -0
  98. package/fixtures/kg-golden/meetings/m01-northwind-pilot-kickoff.json +792 -0
  99. package/fixtures/kg-golden/meetings/m02-halden-migration-planning.json +814 -0
  100. package/fixtures/kg-golden/meetings/m03-larkspur-weekly-sync.json +601 -0
  101. package/fixtures/kg-golden/meetings/m04-corvid-intake-discovery.json +690 -0
  102. package/fixtures/kg-golden/meetings/m05-hosting-vendor-selection.json +631 -0
  103. package/fixtures/kg-golden/meetings/m06-northwind-floor-data-review.json +649 -0
  104. package/fixtures/kg-golden/meetings/m07-gullwing-intro-notes.json +428 -0
  105. package/fixtures/kg-golden/meetings/m08-halden-migration-checkpoint.json +672 -0
  106. package/fixtures/kg-golden/meetings/m09-northwind-platform-org-update.json +711 -0
  107. package/fixtures/kg-golden/meetings/m10-corvid-prototype-review.json +623 -0
  108. package/fixtures/kg-golden/meetings/m11-solvane-grid-dashboard-scoping.json +689 -0
  109. package/fixtures/kg-golden/meetings/m12-northwind-pilot-replan.json +681 -0
  110. package/fixtures/kg-golden/meetings/m13-halden-cutover-go-no-go.json +721 -0
  111. package/fixtures/kg-golden/meetings/m14-gullwing-discovery-readout.json +719 -0
  112. package/fixtures/kg-golden/meetings/m15-halden-handover-ravi-leaving.json +716 -0
  113. package/fixtures/kg-golden/meetings/m16-varden-claims-portal-intro.json +704 -0
  114. package/fixtures/kg-golden/meetings/m17-corvid-usability-debrief.json +572 -0
  115. package/fixtures/kg-golden/meetings/m18-hosting-decision-revisited.json +655 -0
  116. package/fixtures/kg-golden/meetings/m19-solvane-integration-kickoff.json +726 -0
  117. package/fixtures/kg-golden/meetings/m20-northwind-go-live-retro.json +673 -0
  118. package/fixtures/kg-golden/meetings/m21-quarterly-account-review.json +449 -0
  119. package/fixtures/kg-golden/meetings/m22-halden-intro-call-2020.json +558 -0
  120. package/fixtures/kg-golden/meetings/m23-gullwing-model-review.json +702 -0
  121. package/fixtures/kg-golden/meetings/m24-varden-discovery-midpoint.json +643 -0
  122. package/fixtures/kg-golden/meetings/m25-corvid-rollout-planning.json +642 -0
  123. package/fixtures/kg-golden/meetings/m26-larkspur-engineering-prep.json +695 -0
  124. package/fixtures/kg-golden/meetings/m27-solvane-phase-one-demo.json +649 -0
  125. package/fixtures/kg-golden/meetings/m28-northwind-building-5-scoping.json +715 -0
  126. package/fixtures/kg-golden/meetings/m29-halden-southern-cutover-review.json +752 -0
  127. package/fixtures/kg-golden/meetings/m30-varden-portal-build-kickoff.json +697 -0
  128. package/fixtures/kg-golden/meetings/m31-gullwing-rollout-renewal.json +681 -0
  129. package/fixtures/kg-golden/meetings/m32-brambleway-weekly-sync.json +472 -0
  130. package/fixtures/kg-golden/meetings/m33-nina-oliver-one-on-one.json +342 -0
  131. package/fixtures/kg-golden/meetings/m34-coffee-with-dana.json +249 -0
  132. package/fixtures/kg-golden/meetings/m35-brambleway-june-sync.json +553 -0
  133. package/fixtures/kg-golden/meetings/m36-copenhagen-conference-planning.json +296 -0
  134. package/host/generated/client.d.ts +1 -0
  135. package/host/generated/client.js +5 -0
  136. package/host/generated/default.d.ts +1 -0
  137. package/host/generated/default.js +5 -0
  138. package/host/generated/edge.d.ts +1 -0
  139. package/host/generated/edge.js +1658 -0
  140. package/host/generated/index-browser.js +1684 -0
  141. package/host/generated/index.d.ts +192335 -0
  142. package/host/generated/index.js +1658 -0
  143. package/host/generated/package.json +139 -0
  144. package/host/generated/query_compiler_fast_bg.js +2 -0
  145. package/host/generated/query_compiler_fast_bg.wasm +0 -0
  146. package/host/generated/query_compiler_fast_bg.wasm-base64.js +2 -0
  147. package/host/generated/runtime/client.d.ts +3433 -0
  148. package/host/generated/runtime/client.js +110 -0
  149. package/host/generated/runtime/index-browser.d.ts +90 -0
  150. package/host/generated/runtime/index-browser.js +6 -0
  151. package/host/generated/runtime/wasm-compiler-edge.js +100 -0
  152. package/host/generated/schema.prisma +6312 -0
  153. package/host/generated/wasm-edge-light-loader.mjs +5 -0
  154. package/host/generated/wasm-worker-loader.mjs +5 -0
  155. package/host/prisma/fragments/kvox.ask.prisma +126 -0
  156. package/host/prisma/fragments/kvox.graph.prisma +1073 -0
  157. package/host/prisma/fragments/kvox.notes.prisma +787 -0
  158. package/host/prisma/fragments/kvox.search.prisma +211 -0
  159. package/host/prisma/fragments/kvox.transcripts.prisma +790 -0
  160. package/host/prisma/kvox.lock +101 -0
  161. package/host/prisma/migrations/20240101000000_initial/migration.sql +297 -0
  162. package/host/prisma/migrations/20240101000001_add_personal_access_tokens/migration.sql +31 -0
  163. package/host/prisma/migrations/20240101000002_add_credentials/migration.sql +20 -0
  164. package/host/prisma/migrations/20240101000003_add_notification_deliveries/migration.sql +27 -0
  165. package/host/prisma/migrations/20240101000004_drop_stale_uuid_defaults/migration.sql +35 -0
  166. package/host/prisma/migrations/20240101000005_add_notifications/migration.sql +22 -0
  167. package/host/prisma/migrations/20240101000006_add_push_subscriptions/migration.sql +25 -0
  168. package/host/prisma/migrations/20240101000007_add_jobs/migration.sql +110 -0
  169. package/host/prisma/migrations/20240101000008_add_worker_nodes/migration.sql +90 -0
  170. package/host/prisma/migrations/20240101000009_add_database_backup_runs/migration.sql +104 -0
  171. package/host/prisma/migrations/20240101000010_add_notification_broadcasts/migration.sql +57 -0
  172. package/host/prisma/migrations/20240101000011_add_backup_run_job_link/migration.sql +87 -0
  173. package/host/prisma/migrations/20240101000012_add_job_node_secrets/migration.sql +61 -0
  174. package/host/prisma/migrations/20240101000013_add_backup_run_pg_dump_version/migration.sql +26 -0
  175. package/host/prisma/migrations/20240101000014_add_job_claim_token/migration.sql +92 -0
  176. package/host/prisma/migrations/20240101000015_add_ai_platform/migration.sql +108 -0
  177. package/host/prisma/migrations/20240101000016_revoke_viewer_ai_use/migration.sql +32 -0
  178. package/host/prisma/migrations/20240101000017_add_user_credentials/migration.sql +29 -0
  179. package/host/prisma/migrations/20240101000018_add_device_session_credential_link/migration.sql +52 -0
  180. package/host/prisma/migrations/20240101000019_add_worker_node_vitals/migration.sql +3 -0
  181. package/host/prisma/migrations/20240101000020_add_job_trace_context/migration.sql +6 -0
  182. package/host/prisma/migrations/20240101000021_add_retention_created_at_indexes/migration.sql +13 -0
  183. package/host/prisma/migrations/20240101000022_add_organizations/migration.sql +142 -0
  184. package/host/prisma/migrations/20240101000023_split_system_org_roles/migration.sql +131 -0
  185. package/host/prisma/migrations/20240101000024_org_scoped_rls/migration.sql +215 -0
  186. package/host/prisma/migrations/20240101000025_add_groups/migration.sql +165 -0
  187. package/host/prisma/migrations/20240101000026_add_grants/migration.sql +117 -0
  188. package/host/prisma/migrations/20240101000027_add_org_settings/migration.sql +49 -0
  189. package/host/prisma/migrations/20240101000028_add_org_credentials/migration.sql +54 -0
  190. package/host/prisma/migrations/20240101000029_add_jobs_org_id/migration.sql +18 -0
  191. package/host/prisma/migrations/20240101000030_add_jobs_org_id_status_index/migration.sql +6 -0
  192. package/host/prisma/migrations/20240101000031_add_broadcast_target_org/migration.sql +21 -0
  193. package/host/prisma/migrations/20240101000032_add_android_app/migration.sql +60 -0
  194. package/host/prisma/migrations/20240101000033_open_job_reason/migration.sql +16 -0
  195. package/host/prisma/migrations/20240101000034_ai_usage_feature/migration.sql +37 -0
  196. package/host/prisma/migrations/20240101000035_add_app_metadata/migration.sql +49 -0
  197. package/host/prisma/migrations/20240101000036_open_sharing_vocabularies/migration.sql +97 -0
  198. package/host/prisma/migrations/20260914130000_kvox_add_transcripts/migration.sql +322 -0
  199. package/host/prisma/migrations/20260914140000_kvox_add_notes/migration.sql +311 -0
  200. package/host/prisma/migrations/20260915120000_kvox_add_search_vectors/migration.sql +150 -0
  201. package/host/prisma/migrations/20260915130000_kvox_add_search_embeddings/migration.sql +362 -0
  202. package/host/prisma/migrations/20260915210000_kvox_add_note_title_source/migration.sql +30 -0
  203. package/host/prisma/migrations/20260923120000_kvox_add_note_generation_context_snapshot/migration.sql +24 -0
  204. package/host/prisma/migrations/20260923130000_kvox_add_user_hidden_note_templates/migration.sql +35 -0
  205. package/host/prisma/migrations/20260923140000_kvox_add_transcript_speaker_identities/migration.sql +6 -0
  206. package/host/prisma/migrations/20260923150000_kvox_transcript_name_checks/migration.sql +95 -0
  207. package/host/prisma/migrations/20260923160000_kvox_add_note_body_format/migration.sql +27 -0
  208. package/host/prisma/migrations/20260923170000_kvox_add_note_version_body_format/migration.sql +23 -0
  209. package/host/prisma/migrations/20260926012548_kvox_add_knowledge_graph/migration.sql +680 -0
  210. package/host/prisma/migrations/20260926030000_kvox_fix_kg_relations_valid_precision_chk/migration.sql +29 -0
  211. package/host/prisma/migrations/20260926030100_kvox_add_transcript_recorded_at/migration.sql +9 -0
  212. package/host/prisma/migrations/20260926030200_kvox_kg_evidence_invariant/migration.sql +60 -0
  213. package/host/prisma/migrations/20260926040000_kvox_add_kg_graph_layouts/migration.sql +30 -0
  214. package/host/prisma/migrations/20260926050000_kvox_add_ask_conversations/migration.sql +99 -0
  215. package/host/prisma/migrations/20260926231512_kvox_add_kg_exports/migration.sql +52 -0
  216. package/host/prisma/migrations/20261016120000_kvox_transcripts_org_id/migration.sql +49 -0
  217. package/host/prisma/platform.lock +319 -0
  218. package/host/prisma/schema/app.kvox.ask.prisma +110 -0
  219. package/host/prisma/schema/app.kvox.graph.prisma +1030 -0
  220. package/host/prisma/schema/app.kvox.notes.prisma +746 -0
  221. package/host/prisma/schema/app.kvox.search.prisma +208 -0
  222. package/host/prisma/schema/app.kvox.transcripts.prisma +726 -0
  223. package/host/prisma/schema/platform.ai.prisma +419 -0
  224. package/host/prisma/schema/platform.android-app.prisma +46 -0
  225. package/host/prisma/schema/platform.base.prisma +15 -0
  226. package/host/prisma/schema/platform.credentials.prisma +156 -0
  227. package/host/prisma/schema/platform.db-backup.prisma +359 -0
  228. package/host/prisma/schema/platform.identity.prisma +638 -0
  229. package/host/prisma/schema/platform.jobs.prisma +824 -0
  230. package/host/prisma/schema/platform.notifications.prisma +641 -0
  231. package/host/prisma/schema/platform.settings.prisma +53 -0
  232. package/host/prisma/schema/platform.sharing.prisma +208 -0
  233. package/host/prisma/schema/platform.storage.prisma +118 -0
  234. package/package.json +112 -1
  235. package/parity/requests.ask.json +2681 -0
  236. package/parity/requests.m01.json +1554 -0
  237. package/parity/requests.m02.json +1554 -0
  238. package/parity/requests.m03.json +1554 -0
  239. package/parity/requests.m04.json +1554 -0
  240. package/parity/requests.m05.json +1554 -0
  241. package/parity/requests.m06.json +1554 -0
  242. package/parity/requests.m07.json +1554 -0
  243. package/parity/requests.m08.json +1554 -0
  244. package/parity/requests.m09.json +1554 -0
  245. package/parity/requests.m10.json +1554 -0
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // runAskEval: the Ask evaluation, headless (issue #608; the web app's runner #382)
4
+ // =============================================================================
5
+ //
6
+ // Starts the in-memory host (`host/app.ts`), seeds the golden graph under the
7
+ // evaluation user (`seed-golden-graph.ts`), then for every selected question:
8
+ //
9
+ // create a conversation (`AskConversationsService`) → post the question
10
+ // through the REAL `AskMessagesService` (checks, transaction, the real
11
+ // `ask.respond` job row) → invoke `AskRespondHandler.process(job)` DIRECTLY
12
+ // (nothing else claims the job) → read the finished assistant message back.
13
+ //
14
+ // The turn runs on the model port the caller hands in, exactly as a production
15
+ // turn runs on the host's binding: live, `createLiveKvoxAi` (`createKvoxAi`
16
+ // over the direct runtime and the provider adapters); replay, `createKvoxAi`
17
+ // over a scripted runtime (`replay.ts`). Every request the port receives is
18
+ // captured through a thin wrapper around its own `chat()` (never a second
19
+ // implementation), so the scorer's leak check sees exactly what left the run.
20
+ //
21
+ // EVERYTHING DIES WITH THE RUN: the database is PGlite in memory and `close()`
22
+ // runs in a `finally`, so there is nothing to tear down and no deployment
23
+ // setting to restore (the web app's runner had both).
24
+ // =============================================================================
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.DEFAULT_ASK_EVAL_MODEL = void 0;
27
+ exports.startAskEvalSession = startAskEvalSession;
28
+ exports.runAskEval = runAskEval;
29
+ const ask_1 = require("@marinoscar/kvox-api/ask");
30
+ const testing_1 = require("@marinoscar/kvox-api/ask/testing");
31
+ const ports_1 = require("@marinoscar/kvox-api/ports");
32
+ const index_js_1 = require("../ask/index.js");
33
+ const index_js_2 = require("../fixtures/index.js");
34
+ const app_js_1 = require("./host/app.js");
35
+ const seed_golden_graph_js_1 = require("./seed-golden-graph.js");
36
+ /**
37
+ * The model a live run uses when none is named.
38
+ *
39
+ * @stability experimental
40
+ */
41
+ exports.DEFAULT_ASK_EVAL_MODEL = 'gpt-4o-mini';
42
+ /**
43
+ * Wraps the port's own `chat()` so every request is recorded. Mutates the port in
44
+ * place (the handler holds the same object); returns the restorer.
45
+ */
46
+ function wrapChatForCapture(port, onRequest) {
47
+ const original = port.chat;
48
+ const bound = original.bind(port);
49
+ port.chat = (ctx, request) => {
50
+ const { signal: _signal, ...rest } = ctx;
51
+ onRequest({ ctx: rest, request });
52
+ return bound(ctx, request);
53
+ };
54
+ return () => {
55
+ port.chat = original;
56
+ };
57
+ }
58
+ /**
59
+ * Starts the host on `ai`, seeds the golden graph and returns a session that asks
60
+ * questions through the real Ask services and handler.
61
+ *
62
+ * @param options - the port, the fixtures (default: the whole golden set) and a progress sink.
63
+ * @returns the session; call `close()` when done (in a `finally`).
64
+ * @stability experimental
65
+ */
66
+ async function startAskEvalSession(options) {
67
+ const log = options.log ?? (() => { });
68
+ const fixtures = options.fixtures ?? (0, index_js_2.loadGoldenSet)();
69
+ const host = await (0, app_js_1.startAskEvalHost)({ ai: options.ai, log });
70
+ let bucket = [];
71
+ let unwrap = null;
72
+ try {
73
+ const seeded = await (0, seed_golden_graph_js_1.seedGoldenGraph)(host, fixtures);
74
+ log(`seed: ${fixtures.length} meetings, ${seeded.counts.entities} entities, ${seeded.counts.relations} relations, ` +
75
+ `${seeded.counts.items} items, ${seeded.counts.evidence} citations` +
76
+ (seeded.refusals.length ? `, ${seeded.refusals.length} refused` : '') +
77
+ (seeded.warnings.length ? `, ${seeded.warnings.length} warning(s)` : ''));
78
+ for (const r of seeded.refusals)
79
+ log(`seed refused: ${r.fixtureId} ${r.row}: ${r.reason}`);
80
+ for (const w of seeded.warnings)
81
+ log(`seed warning: ${w}`);
82
+ const conversations = host.resolve(ask_1.AskConversationsService);
83
+ const messages = host.resolve(testing_1.internals.AskMessagesService);
84
+ const handler = host.resolve(testing_1.internals.AskRespondHandler);
85
+ unwrap = wrapChatForCapture(host.ai, (captured) => bucket.push(captured));
86
+ let closed = false;
87
+ return {
88
+ host,
89
+ seeded,
90
+ async ask(question, model) {
91
+ bucket = [];
92
+ const started = Date.now();
93
+ const conversation = await conversations.create(host.userId, {});
94
+ const posted = await messages.post(host.userId, conversation.id, { content: question, model });
95
+ const row = await host.prisma.askMessage.findUniqueOrThrow({ where: { id: posted.assistantMessage.id } });
96
+ const job = await host.prisma.job.findUniqueOrThrow({ where: { id: row.jobId } });
97
+ let modelError;
98
+ try {
99
+ await handler.process({
100
+ id: job.id,
101
+ type: job.type,
102
+ subjectType: job.subjectType,
103
+ subjectId: job.subjectId,
104
+ payload: job.payload,
105
+ attempts: job.attempts,
106
+ orgId: job.orgId,
107
+ });
108
+ }
109
+ catch (error) {
110
+ // A failed model call: the handler has marked the turn `failed` and
111
+ // rethrown for the queue (which would record the attempt). This run is
112
+ // the queue; it records the class and goes on. A rate limit before any
113
+ // text leaves the turn `pending` for a re-run, which a run cannot wait
114
+ // for, so it (and anything else) stops the run.
115
+ if (!(error instanceof ports_1.KvoxAiError))
116
+ throw error;
117
+ const settled = await host.prisma.askMessage.findUniqueOrThrow({ where: { id: posted.assistantMessage.id }, select: { status: true } });
118
+ if (settled.status !== 'failed')
119
+ throw error;
120
+ modelError = { errorClass: error.errorClass };
121
+ }
122
+ const finished = await host.prisma.askMessage.findUniqueOrThrow({ where: { id: posted.assistantMessage.id } });
123
+ return {
124
+ message: testing_1.internals.toAskMessage(finished),
125
+ capturedPrompts: bucket.map((r) => JSON.stringify(r)),
126
+ ms: Date.now() - started,
127
+ ...(modelError ? { modelError } : {}),
128
+ };
129
+ },
130
+ async close() {
131
+ if (closed)
132
+ return;
133
+ closed = true;
134
+ unwrap?.();
135
+ await host.close();
136
+ },
137
+ };
138
+ }
139
+ catch (error) {
140
+ unwrap?.();
141
+ await host.close();
142
+ throw error;
143
+ }
144
+ }
145
+ /** The committed questions, narrowed to `ids`. */
146
+ function resolveQuestions(questions) {
147
+ if (questions === undefined)
148
+ return (0, index_js_2.loadGoldenAskQuestions)();
149
+ if (questions.every((q) => typeof q === 'string')) {
150
+ return (0, index_js_1.selectAskEvalQuestions)((0, index_js_2.loadGoldenAskQuestions)(), [...questions], null);
151
+ }
152
+ return [...questions];
153
+ }
154
+ /**
155
+ * Runs the Ask evaluation headless: an in-memory PostgreSQL, the golden graph
156
+ * seeded through the graph write service, every question through the real
157
+ * `ask.respond` handler on `ai`, each answer scored.
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * const key = readEvalApiKey(process.env);
162
+ * const { ai } = createLiveKvoxAi({ provider: 'openai', model: 'gpt-4o-mini', apiKey: key?.apiKey ?? null });
163
+ * const run = await runAskEval({ ai, model: 'gpt-4o-mini', questions: ['q01', 'q07'] });
164
+ * console.log(formatAskEvalReport(run.report));
165
+ * ```
166
+ *
167
+ * @param options - the port, the model, the questions and the gate.
168
+ * @returns the answers, the id map, the scores and the report.
169
+ * @throws `AskEvalQuestionLoadError` for an unknown question id; `KgEvalLoadError` for a malformed fixture.
170
+ * @stability experimental
171
+ */
172
+ async function runAskEval(options) {
173
+ const log = options.log ?? (() => { });
174
+ const questions = resolveQuestions(options.questions);
175
+ const session = await startAskEvalSession({ ai: options.ai, ...(options.fixtures ? { fixtures: options.fixtures } : {}), log });
176
+ try {
177
+ const results = [];
178
+ for (const question of questions) {
179
+ const answered = await session.ask(question.question, options.model);
180
+ log(`ask: ${question.id} ${answered.message.status} in ${answered.ms} ms` +
181
+ (answered.modelError ? ` (model call failed: ${answered.modelError.errorClass})` : ''));
182
+ results.push({ question, ...answered });
183
+ }
184
+ const idMap = session.seeded.idMap;
185
+ const scores = results.map((r) => (0, index_js_1.scoreAnswer)(r.question, r.message, r.capturedPrompts, idMap.evidenceSource, { ms: r.ms }));
186
+ const report = (0, index_js_1.buildAskEvalReport)(scores, { model: options.model, minMatch: options.minMatch ?? 0.8 });
187
+ const { refusals, warnings, counts } = session.seeded;
188
+ return { results, idMap, seed: { refusals, warnings, counts }, scores, report };
189
+ }
190
+ finally {
191
+ await session.close();
192
+ }
193
+ }
@@ -0,0 +1,64 @@
1
+ import { type GoldenFixture } from '../fixtures/index.js';
2
+ import type { AskEvalHost } from './host/app.js';
3
+ /**
4
+ * Fixture ids and labels ↔ the database rows the seeder wrote for them.
5
+ *
6
+ * @stability experimental
7
+ */
8
+ export interface AskEvalIdMap {
9
+ /** `"m01-s009"` → the real `transcript_segments.id`. */
10
+ segments: Map<string, string>;
11
+ /** Fixture id → that meeting's `notes.id`. */
12
+ notes: Map<string, string>;
13
+ /** A global (`knownEntities`) id → `kg_entities.id`. Mostly for debugging. */
14
+ entities: Map<string, string>;
15
+ /** `kg_evidence.id` → `"m01-s009"` or `"m01#note"`: what the scorer's `citeFrom` checks resolve against. */
16
+ evidenceSource: Map<string, string>;
17
+ }
18
+ /**
19
+ * One row the write service refused: which fixture and row, and why (the
20
+ * service's message and issue paths; never a label, statement or quote).
21
+ *
22
+ * @stability experimental
23
+ */
24
+ export interface AskEvalSeedRefusal {
25
+ /** The fixture id (`"m07"`). */
26
+ fixtureId: string;
27
+ /** The row, by kind, position and type key (`"relation #2 (WORKS_AT)"`). */
28
+ row: string;
29
+ /** The service's reason. */
30
+ reason: string;
31
+ }
32
+ /**
33
+ * What {@link seedGoldenGraph} wrote.
34
+ *
35
+ * @stability experimental
36
+ */
37
+ export interface SeededGoldenGraph {
38
+ /** The owner of every row (the host's evaluation user). */
39
+ userId: string;
40
+ /** Fixture ids ↔ row ids. */
41
+ idMap: AskEvalIdMap;
42
+ /** Rows the write service refused (skipped, reported). */
43
+ refusals: AskEvalSeedRefusal[];
44
+ /** Fixture data that could not be resolved (an unknown segment or entity reference). */
45
+ warnings: string[];
46
+ /** Row counts, for the log. */
47
+ counts: {
48
+ entities: number;
49
+ relations: number;
50
+ items: number;
51
+ evidence: number;
52
+ };
53
+ }
54
+ /**
55
+ * Seeds the evaluation user's entire gold graph from EVERY fixture in
56
+ * `fixtures` (pass the full loaded set: `loadGoldenSet()`), one transaction per
57
+ * fixture, in fixture id order, through `GraphWriteService`.
58
+ *
59
+ * @param host - the running host (its client, user and organization, and the write service).
60
+ * @param fixtures - the golden meetings.
61
+ * @returns the id map the scorer needs, the refusals and the warnings.
62
+ * @stability experimental
63
+ */
64
+ export declare function seedGoldenGraph(host: AskEvalHost, fixtures: readonly GoldenFixture[]): Promise<SeededGoldenGraph>;