@adonis-agora/agent 0.30.2 → 0.33.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 (240) hide show
  1. package/CHANGELOG.md +866 -0
  2. package/dist/assets/spa/assets/{index-Cfi3g3b2.js → index-3Q2m5_Ax.js} +1 -1
  3. package/dist/assets/spa/index.html +1 -1
  4. package/dist/providers/agent_provider.d.ts.map +1 -1
  5. package/dist/providers/agent_provider.js +157 -9
  6. package/dist/providers/agent_provider.js.map +1 -1
  7. package/dist/src/agent-deps-factory.d.ts +16 -2
  8. package/dist/src/agent-deps-factory.d.ts.map +1 -1
  9. package/dist/src/agent-deps-factory.js +8 -0
  10. package/dist/src/agent-deps-factory.js.map +1 -1
  11. package/dist/src/agent-deps.d.ts +21 -1
  12. package/dist/src/agent-deps.d.ts.map +1 -1
  13. package/dist/src/agent-deps.js.map +1 -1
  14. package/dist/src/agent-loop.d.ts +226 -9
  15. package/dist/src/agent-loop.d.ts.map +1 -1
  16. package/dist/src/agent-loop.js +1311 -208
  17. package/dist/src/agent-loop.js.map +1 -1
  18. package/dist/src/agent-service.d.ts +27 -0
  19. package/dist/src/agent-service.d.ts.map +1 -1
  20. package/dist/src/agent-service.js +29 -0
  21. package/dist/src/agent-service.js.map +1 -1
  22. package/dist/src/ai-sdk/ai-sdk-model.d.ts.map +1 -1
  23. package/dist/src/ai-sdk/ai-sdk-model.js +21 -1
  24. package/dist/src/ai-sdk/ai-sdk-model.js.map +1 -1
  25. package/dist/src/client/sse.d.ts +32 -2
  26. package/dist/src/client/sse.d.ts.map +1 -1
  27. package/dist/src/client/sse.js +45 -2
  28. package/dist/src/client/sse.js.map +1 -1
  29. package/dist/src/define_config.d.ts +41 -7
  30. package/dist/src/define_config.d.ts.map +1 -1
  31. package/dist/src/define_config.js.map +1 -1
  32. package/dist/src/durable/agent-run-workflow.d.ts +10 -11
  33. package/dist/src/durable/agent-run-workflow.d.ts.map +1 -1
  34. package/dist/src/durable/agent-run-workflow.js +49 -21
  35. package/dist/src/durable/agent-run-workflow.js.map +1 -1
  36. package/dist/src/durable/durable-agent-runner.d.ts +3 -2
  37. package/dist/src/durable/durable-agent-runner.d.ts.map +1 -1
  38. package/dist/src/durable/durable-agent-runner.js +2 -2
  39. package/dist/src/durable/durable-agent-runner.js.map +1 -1
  40. package/dist/src/elicitation.d.ts +207 -0
  41. package/dist/src/elicitation.d.ts.map +1 -0
  42. package/dist/src/elicitation.js +315 -0
  43. package/dist/src/elicitation.js.map +1 -0
  44. package/dist/src/evals/approval-prior.d.ts +58 -0
  45. package/dist/src/evals/approval-prior.d.ts.map +1 -0
  46. package/dist/src/evals/approval-prior.js +82 -0
  47. package/dist/src/evals/approval-prior.js.map +1 -0
  48. package/dist/src/evals/evaluate.d.ts +51 -0
  49. package/dist/src/evals/evaluate.d.ts.map +1 -0
  50. package/dist/src/evals/evaluate.js +76 -0
  51. package/dist/src/evals/evaluate.js.map +1 -0
  52. package/dist/src/evals/governance-sample-source.d.ts +23 -0
  53. package/dist/src/evals/governance-sample-source.d.ts.map +1 -0
  54. package/dist/src/evals/governance-sample-source.js +93 -0
  55. package/dist/src/evals/governance-sample-source.js.map +1 -0
  56. package/dist/src/evals/in-memory-score-store.d.ts +16 -0
  57. package/dist/src/evals/in-memory-score-store.d.ts.map +1 -0
  58. package/dist/src/evals/in-memory-score-store.js +57 -0
  59. package/dist/src/evals/in-memory-score-store.js.map +1 -0
  60. package/dist/src/evals/index.d.ts +15 -0
  61. package/dist/src/evals/index.d.ts.map +1 -0
  62. package/dist/src/evals/index.js +14 -0
  63. package/dist/src/evals/index.js.map +1 -0
  64. package/dist/src/evals/judge.d.ts +30 -0
  65. package/dist/src/evals/judge.d.ts.map +1 -0
  66. package/dist/src/evals/judge.js +53 -0
  67. package/dist/src/evals/judge.js.map +1 -0
  68. package/dist/src/evals/live-scoring.d.ts +42 -0
  69. package/dist/src/evals/live-scoring.d.ts.map +1 -0
  70. package/dist/src/evals/live-scoring.js +103 -0
  71. package/dist/src/evals/live-scoring.js.map +1 -0
  72. package/dist/src/evals/sample-source.d.ts +40 -0
  73. package/dist/src/evals/sample-source.d.ts.map +1 -0
  74. package/dist/src/evals/sample-source.js +33 -0
  75. package/dist/src/evals/sample-source.js.map +1 -0
  76. package/dist/src/evals/score-store.d.ts +54 -0
  77. package/dist/src/evals/score-store.d.ts.map +1 -0
  78. package/dist/src/evals/score-store.js +2 -0
  79. package/dist/src/evals/score-store.js.map +1 -0
  80. package/dist/src/evals/scorers/answer-relevancy.scorer.d.ts +28 -0
  81. package/dist/src/evals/scorers/answer-relevancy.scorer.d.ts.map +1 -0
  82. package/dist/src/evals/scorers/answer-relevancy.scorer.js +42 -0
  83. package/dist/src/evals/scorers/answer-relevancy.scorer.js.map +1 -0
  84. package/dist/src/evals/scorers/approval-outcome.scorer.d.ts +22 -0
  85. package/dist/src/evals/scorers/approval-outcome.scorer.d.ts.map +1 -0
  86. package/dist/src/evals/scorers/approval-outcome.scorer.js +60 -0
  87. package/dist/src/evals/scorers/approval-outcome.scorer.js.map +1 -0
  88. package/dist/src/evals/scorers/approval-risk.scorer.d.ts +28 -0
  89. package/dist/src/evals/scorers/approval-risk.scorer.d.ts.map +1 -0
  90. package/dist/src/evals/scorers/approval-risk.scorer.js +54 -0
  91. package/dist/src/evals/scorers/approval-risk.scorer.js.map +1 -0
  92. package/dist/src/evals/scorers/run-completion.scorer.d.ts +18 -0
  93. package/dist/src/evals/scorers/run-completion.scorer.d.ts.map +1 -0
  94. package/dist/src/evals/scorers/run-completion.scorer.js +55 -0
  95. package/dist/src/evals/scorers/run-completion.scorer.js.map +1 -0
  96. package/dist/src/evals/summarize.d.ts +44 -0
  97. package/dist/src/evals/summarize.d.ts.map +1 -0
  98. package/dist/src/evals/summarize.js +87 -0
  99. package/dist/src/evals/summarize.js.map +1 -0
  100. package/dist/src/evals/types.d.ts +81 -0
  101. package/dist/src/evals/types.d.ts.map +1 -0
  102. package/dist/src/evals/types.js +15 -0
  103. package/dist/src/evals/types.js.map +1 -0
  104. package/dist/src/history-window.d.ts +50 -11
  105. package/dist/src/history-window.d.ts.map +1 -1
  106. package/dist/src/history-window.js +84 -12
  107. package/dist/src/history-window.js.map +1 -1
  108. package/dist/src/index.d.ts +11 -3
  109. package/dist/src/index.d.ts.map +1 -1
  110. package/dist/src/index.js +10 -3
  111. package/dist/src/index.js.map +1 -1
  112. package/dist/src/mcp/server.d.ts +8 -0
  113. package/dist/src/mcp/server.d.ts.map +1 -1
  114. package/dist/src/mcp/server.js +27 -1
  115. package/dist/src/mcp/server.js.map +1 -1
  116. package/dist/src/mcp-client/importer.d.ts +75 -0
  117. package/dist/src/mcp-client/importer.d.ts.map +1 -0
  118. package/dist/src/mcp-client/importer.js +161 -0
  119. package/dist/src/mcp-client/importer.js.map +1 -0
  120. package/dist/src/mcp-client/index.d.ts +9 -0
  121. package/dist/src/mcp-client/index.d.ts.map +1 -0
  122. package/dist/src/mcp-client/index.js +8 -0
  123. package/dist/src/mcp-client/index.js.map +1 -0
  124. package/dist/src/mcp-client/options.d.ts +99 -0
  125. package/dist/src/mcp-client/options.d.ts.map +1 -0
  126. package/dist/src/mcp-client/options.js +2 -0
  127. package/dist/src/mcp-client/options.js.map +1 -0
  128. package/dist/src/mcp-client/tool-input.d.ts +39 -0
  129. package/dist/src/mcp-client/tool-input.d.ts.map +1 -0
  130. package/dist/src/mcp-client/tool-input.js +61 -0
  131. package/dist/src/mcp-client/tool-input.js.map +1 -0
  132. package/dist/src/mcp-client/tool-kind.d.ts +37 -0
  133. package/dist/src/mcp-client/tool-kind.d.ts.map +1 -0
  134. package/dist/src/mcp-client/tool-kind.js +20 -0
  135. package/dist/src/mcp-client/tool-kind.js.map +1 -0
  136. package/dist/src/mcp-client/tool-name.d.ts +22 -0
  137. package/dist/src/mcp-client/tool-name.d.ts.map +1 -0
  138. package/dist/src/mcp-client/tool-name.js +35 -0
  139. package/dist/src/mcp-client/tool-name.js.map +1 -0
  140. package/dist/src/mcp-client/tool-source.d.ts +75 -0
  141. package/dist/src/mcp-client/tool-source.d.ts.map +1 -0
  142. package/dist/src/mcp-client/tool-source.js +244 -0
  143. package/dist/src/mcp-client/tool-source.js.map +1 -0
  144. package/dist/src/mcp-client/transient.d.ts +28 -0
  145. package/dist/src/mcp-client/transient.d.ts.map +1 -0
  146. package/dist/src/mcp-client/transient.js +126 -0
  147. package/dist/src/mcp-client/transient.js.map +1 -0
  148. package/dist/src/mcp-client/unsafe-regex.d.ts +23 -0
  149. package/dist/src/mcp-client/unsafe-regex.d.ts.map +1 -0
  150. package/dist/src/mcp-client/unsafe-regex.js +194 -0
  151. package/dist/src/mcp-client/unsafe-regex.js.map +1 -0
  152. package/dist/src/memory.d.ts +448 -0
  153. package/dist/src/memory.d.ts.map +1 -0
  154. package/dist/src/memory.js +330 -0
  155. package/dist/src/memory.js.map +1 -0
  156. package/dist/src/pagination.d.ts +63 -0
  157. package/dist/src/pagination.d.ts.map +1 -0
  158. package/dist/src/pagination.js +16 -0
  159. package/dist/src/pagination.js.map +1 -0
  160. package/dist/src/processors.d.ts +134 -0
  161. package/dist/src/processors.d.ts.map +1 -0
  162. package/dist/src/processors.js +215 -0
  163. package/dist/src/processors.js.map +1 -0
  164. package/dist/src/rag/qdrant-store.d.ts +48 -6
  165. package/dist/src/rag/qdrant-store.d.ts.map +1 -1
  166. package/dist/src/rag/qdrant-store.js +77 -24
  167. package/dist/src/rag/qdrant-store.js.map +1 -1
  168. package/dist/src/replay-integrity.d.ts +17 -0
  169. package/dist/src/replay-integrity.d.ts.map +1 -0
  170. package/dist/src/replay-integrity.js +19 -0
  171. package/dist/src/replay-integrity.js.map +1 -0
  172. package/dist/src/runners/inline-agent-runner.d.ts +33 -7
  173. package/dist/src/runners/inline-agent-runner.d.ts.map +1 -1
  174. package/dist/src/runners/inline-agent-runner.js +113 -27
  175. package/dist/src/runners/inline-agent-runner.js.map +1 -1
  176. package/dist/src/skills.d.ts +291 -0
  177. package/dist/src/skills.d.ts.map +1 -0
  178. package/dist/src/skills.js +0 -0
  179. package/dist/src/skills.js.map +1 -0
  180. package/dist/src/spi/agent-runner.d.ts +20 -6
  181. package/dist/src/spi/agent-runner.d.ts.map +1 -1
  182. package/dist/src/spi/agent-store.d.ts +53 -0
  183. package/dist/src/spi/agent-store.d.ts.map +1 -1
  184. package/dist/src/spi/governance-queries.d.ts +33 -13
  185. package/dist/src/spi/governance-queries.d.ts.map +1 -1
  186. package/dist/src/spi/history-window.d.ts +64 -10
  187. package/dist/src/spi/history-window.d.ts.map +1 -1
  188. package/dist/src/spi/model-provider.d.ts +18 -0
  189. package/dist/src/spi/model-provider.d.ts.map +1 -1
  190. package/dist/src/spi/processors.d.ts +161 -0
  191. package/dist/src/spi/processors.d.ts.map +1 -0
  192. package/dist/src/spi/processors.js +57 -0
  193. package/dist/src/spi/processors.js.map +1 -0
  194. package/dist/src/spi/token-stream-sink.d.ts +43 -0
  195. package/dist/src/spi/token-stream-sink.d.ts.map +1 -1
  196. package/dist/src/spi/token-stream-sink.js +17 -1
  197. package/dist/src/spi/token-stream-sink.js.map +1 -1
  198. package/dist/src/sse.d.ts +5 -2
  199. package/dist/src/sse.d.ts.map +1 -1
  200. package/dist/src/sse.js +11 -2
  201. package/dist/src/sse.js.map +1 -1
  202. package/dist/src/stores/lucid-governance-queries.d.ts +5 -2
  203. package/dist/src/stores/lucid-governance-queries.d.ts.map +1 -1
  204. package/dist/src/stores/lucid-governance-queries.js +14 -5
  205. package/dist/src/stores/lucid-governance-queries.js.map +1 -1
  206. package/dist/src/stores/lucid-schema.d.ts.map +1 -1
  207. package/dist/src/stores/lucid-schema.js +15 -0
  208. package/dist/src/stores/lucid-schema.js.map +1 -1
  209. package/dist/src/stores/lucid.d.ts +11 -3
  210. package/dist/src/stores/lucid.d.ts.map +1 -1
  211. package/dist/src/stores/lucid.js +65 -0
  212. package/dist/src/stores/lucid.js.map +1 -1
  213. package/dist/src/structured-output.d.ts +57 -0
  214. package/dist/src/structured-output.d.ts.map +1 -0
  215. package/dist/src/structured-output.js +80 -0
  216. package/dist/src/structured-output.js.map +1 -0
  217. package/dist/src/telescope/agent-governance-providers.js +2 -2
  218. package/dist/src/telescope/agent-governance-providers.js.map +1 -1
  219. package/dist/src/testing/fake-model-provider.d.ts +8 -4
  220. package/dist/src/testing/fake-model-provider.d.ts.map +1 -1
  221. package/dist/src/testing/fake-model-provider.js +6 -9
  222. package/dist/src/testing/fake-model-provider.js.map +1 -1
  223. package/dist/src/testing/in-memory-governance-queries.d.ts.map +1 -1
  224. package/dist/src/testing/in-memory-governance-queries.js +8 -3
  225. package/dist/src/testing/in-memory-governance-queries.js.map +1 -1
  226. package/dist/src/testing/in-memory-store.d.ts +4 -3
  227. package/dist/src/testing/in-memory-store.d.ts.map +1 -1
  228. package/dist/src/testing/in-memory-store.js +13 -7
  229. package/dist/src/testing/in-memory-store.js.map +1 -1
  230. package/dist/src/testing/index.d.ts +1 -1
  231. package/dist/src/testing/index.d.ts.map +1 -1
  232. package/dist/src/testing/index.js.map +1 -1
  233. package/dist/src/tool-registry.d.ts +9 -0
  234. package/dist/src/tool-registry.d.ts.map +1 -1
  235. package/dist/src/tool-registry.js +11 -0
  236. package/dist/src/tool-registry.js.map +1 -1
  237. package/dist/src/types.d.ts +55 -2
  238. package/dist/src/types.d.ts.map +1 -1
  239. package/package.json +20 -10
  240. package/skills/agent-personas-agents/SKILL.md +16 -12
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Asking the USER a structured question, and waiting for the answer.
3
+ *
4
+ * `awaitApproval` collects a yes/no about work already proposed; this collects the scope BEFORE the
5
+ * work. Two surfaces produce it — a configured intake (`AgentLoopDeps.intake`) and the model-callable
6
+ * `ask` tool (`AgentLoopDeps.ask`) — and they deliberately produce the SAME {@link
7
+ * ElicitationRequest}, persist through the same tool-call row, and resume through the same
8
+ * `tool:<runId>:<callId>` signal. A consumer cannot tell which one asked, and should not have to.
9
+ */
10
+ /**
11
+ * Thrown when a reply is the wrong shape for the wait it was delivered to: answers to a question
12
+ * set, addressed to a tool call that is waiting on an approve/reject.
13
+ *
14
+ * Refused rather than reduced, because there is no honest reduction in that direction. A yes/no can
15
+ * be read as "confirmed the pre-picked answers" (see {@link normalizeElicitationReply}); a set of
16
+ * answers says nothing at all about whether the proposed work should go ahead, and reading its
17
+ * absent `approved` as `false` would record a rejection the person never made.
18
+ */
19
+ export class HumanReplyMismatchError extends Error {
20
+ runId;
21
+ toolCallId;
22
+ constructor(runId, toolCallId) {
23
+ super(`Tool call "${toolCallId}" on run "${runId}" is waiting for an approve/reject, not for answers`);
24
+ this.runId = runId;
25
+ this.toolCallId = toolCallId;
26
+ this.name = 'HumanReplyMismatchError';
27
+ }
28
+ }
29
+ /**
30
+ * Is this a human's yes/no {@link Decision}, rather than answers to a question set? Structural
31
+ * rather than by class: both shapes are plain JSON off an HTTP body by the time they arrive, and
32
+ * `approved` is the only field a `Decision` carries.
33
+ */
34
+ export function isHumanDecision(reply) {
35
+ return (typeof reply === 'object' &&
36
+ reply !== null &&
37
+ typeof reply.approved === 'boolean');
38
+ }
39
+ function optionValues(question) {
40
+ return new Set(question.options.map((option) => option.value));
41
+ }
42
+ /**
43
+ * Read whatever the human channel delivered as an {@link ElicitationReply}.
44
+ *
45
+ * A question set is persisted as an `action` tool call in `pending_approval` — that is what puts it
46
+ * in the approvals inbox a deployment already has, instead of needing one of its own. The cost of
47
+ * that choice is that the thing which comes back may be a {@link Decision} someone pressed
48
+ * Approve/Reject on rather than a set of answers, and a `Decision` carries no `answers` at all.
49
+ *
50
+ * Approve means every question keeps its own pre-picked `defaults`, which is exactly what "just
51
+ * submit" already means on this surface; Reject is the same declining-to-answer a skip is. Neither
52
+ * reading is a guess — a yes/no channel cannot say more than that, and saying it here is what lets
53
+ * one inbox settle both kinds of pending work.
54
+ *
55
+ * Returns the reply UNCHANGED when it already carries answers, so the common path allocates nothing
56
+ * and a caller can identity-compare.
57
+ */
58
+ export function normalizeElicitationReply(reply) {
59
+ if (typeof reply !== 'object' || reply === null) {
60
+ return { answers: {} };
61
+ }
62
+ const candidate = reply;
63
+ if (typeof candidate.answers === 'object' && candidate.answers !== null) {
64
+ return reply;
65
+ }
66
+ const answeredByRef = candidate.answeredByRef ?? candidate.executedByRef;
67
+ return {
68
+ answers: {},
69
+ ...(candidate.approved === false || candidate.skipped === true ? { skipped: true } : {}),
70
+ ...(answeredByRef !== undefined ? { answeredByRef } : {}),
71
+ };
72
+ }
73
+ /**
74
+ * Settle a reply against the request it answers: fill every unanswered question from its own
75
+ * `defaults`, drop submitted values that aren't on offer, and collapse a single-choice question to
76
+ * one value.
77
+ *
78
+ * PURE, and deliberately so. Both of its inputs are already journaled by the time the loop calls it
79
+ * — the request came from module config or from an `llm:<i>` checkpoint, the reply from the signal
80
+ * checkpoint — so every process replaying the turn reaches the same values without a checkpoint of
81
+ * its own. Resolving defaults in the HTTP layer instead would put them behind a store read that a
82
+ * replay would have to repeat.
83
+ */
84
+ export function resolveElicitation(args) {
85
+ const { request } = args;
86
+ const reply = normalizeElicitationReply(args.reply);
87
+ const answers = {};
88
+ const defaulted = [];
89
+ for (const question of request.questions) {
90
+ const submitted = reply.skipped === true ? undefined : reply.answers[question.id];
91
+ if (submitted === undefined) {
92
+ answers[question.id] = [...(question.defaults ?? [])];
93
+ defaulted.push(question.id);
94
+ continue;
95
+ }
96
+ const allowed = optionValues(question);
97
+ const valid = question.allowFreeText === true ? submitted : submitted.filter((value) => allowed.has(value));
98
+ answers[question.id] = question.multiple === true ? valid : valid.slice(0, 1);
99
+ }
100
+ return { answers, skipped: reply.skipped === true, defaulted };
101
+ }
102
+ /** {@link resolveElicitation} plus its human-readable rendering. Pure, for the same reason. */
103
+ export function settleElicitation(args) {
104
+ const outcome = resolveElicitation(args);
105
+ return { ...outcome, summary: renderElicitationAnswers({ request: args.request, outcome }) };
106
+ }
107
+ /**
108
+ * The answers as the model reads them: the question's own prompt against the chosen options' LABELS,
109
+ * not their opaque `value`s — a model shown `{"scope":["b"]}` has been told nothing.
110
+ */
111
+ export function renderElicitationAnswers(args) {
112
+ const { request, outcome } = args;
113
+ const lines = request.questions.map((question) => {
114
+ const chosen = outcome.answers[question.id] ?? [];
115
+ const labels = chosen.map((value) => question.options.find((option) => option.value === value)?.label ?? value);
116
+ return `${question.prompt} → ${labels.length > 0 ? labels.join(', ') : '(no answer)'}`;
117
+ });
118
+ const preface = outcome.skipped
119
+ ? 'The user declined to answer and asked you to proceed on these assumptions:'
120
+ : 'The user answered:';
121
+ return `${preface}\n${lines.join('\n')}`;
122
+ }
123
+ /** The reserved tool name the model calls to ask the user something. */
124
+ export const ASK_TOOL_NAME = 'ask';
125
+ /** How many questions one `ask` may carry. A form the user has to scroll is a form they skip. */
126
+ export const MAX_ASK_QUESTIONS = 5;
127
+ function issue(path, message) {
128
+ return { message, path };
129
+ }
130
+ function parseOption(raw, path, issues) {
131
+ if (typeof raw !== 'object' || raw === null) {
132
+ issues.push(issue(path, 'must be an object'));
133
+ return undefined;
134
+ }
135
+ const candidate = raw;
136
+ if (typeof candidate.value !== 'string' || candidate.value.length === 0) {
137
+ issues.push(issue([...path, 'value'], 'must be a non-empty string'));
138
+ return undefined;
139
+ }
140
+ if (typeof candidate.label !== 'string' || candidate.label.length === 0) {
141
+ issues.push(issue([...path, 'label'], 'must be a non-empty string'));
142
+ return undefined;
143
+ }
144
+ return {
145
+ value: candidate.value,
146
+ label: candidate.label,
147
+ ...(typeof candidate.hotkey === 'string' ? { hotkey: candidate.hotkey } : {}),
148
+ };
149
+ }
150
+ function parseQuestion(raw, path, issues) {
151
+ if (typeof raw !== 'object' || raw === null) {
152
+ issues.push(issue(path, 'must be an object'));
153
+ return undefined;
154
+ }
155
+ const candidate = raw;
156
+ if (typeof candidate.id !== 'string' || candidate.id.length === 0) {
157
+ issues.push(issue([...path, 'id'], 'must be a non-empty string'));
158
+ return undefined;
159
+ }
160
+ if (typeof candidate.prompt !== 'string' || candidate.prompt.length === 0) {
161
+ issues.push(issue([...path, 'prompt'], 'must be a non-empty string'));
162
+ return undefined;
163
+ }
164
+ if (!Array.isArray(candidate.options) || candidate.options.length === 0) {
165
+ issues.push(issue([...path, 'options'], 'must be a non-empty array'));
166
+ return undefined;
167
+ }
168
+ const options = [];
169
+ for (const [index, rawOption] of candidate.options.entries()) {
170
+ const option = parseOption(rawOption, [...path, 'options', index], issues);
171
+ if (option !== undefined) {
172
+ options.push(option);
173
+ }
174
+ }
175
+ // The one rule that carries the design: a question with no pre-picked answer is a question the
176
+ // user has to stop and think about, and this surface exists to avoid that.
177
+ if (!Array.isArray(candidate.defaults) || candidate.defaults.length === 0) {
178
+ issues.push(issue([...path, 'defaults'], 'must pre-pick at least one option — say what you would choose so the user can just confirm'));
179
+ return undefined;
180
+ }
181
+ const offered = new Set(options.map((option) => option.value));
182
+ const defaults = candidate.defaults.filter((value) => typeof value === 'string' && offered.has(value));
183
+ if (defaults.length === 0) {
184
+ issues.push(issue([...path, 'defaults'], "must name values that appear in this question's options"));
185
+ return undefined;
186
+ }
187
+ return {
188
+ id: candidate.id,
189
+ prompt: candidate.prompt,
190
+ options,
191
+ defaults,
192
+ ...(candidate.multiple === true ? { multiple: true } : {}),
193
+ ...(candidate.allowFreeText === true ? { allowFreeText: true } : {}),
194
+ };
195
+ }
196
+ const ASK_JSON_SCHEMA = {
197
+ type: 'object',
198
+ additionalProperties: false,
199
+ properties: {
200
+ preamble: {
201
+ type: 'string',
202
+ description: 'One sentence shown above the form, e.g. "Three questions before I start. I have pre-picked what I would choose, so confirming is enough."',
203
+ },
204
+ questions: {
205
+ type: 'array',
206
+ minItems: 1,
207
+ maxItems: MAX_ASK_QUESTIONS,
208
+ items: {
209
+ type: 'object',
210
+ additionalProperties: false,
211
+ required: ['id', 'prompt', 'options', 'defaults'],
212
+ properties: {
213
+ id: {
214
+ type: 'string',
215
+ description: 'Unique within this call; answers come back under it.',
216
+ },
217
+ prompt: { type: 'string' },
218
+ multiple: { type: 'boolean', description: 'Allow more than one option to be chosen.' },
219
+ allowFreeText: {
220
+ type: 'boolean',
221
+ description: 'Accept an answer that is not an option.',
222
+ },
223
+ defaults: {
224
+ type: 'array',
225
+ minItems: 1,
226
+ items: { type: 'string' },
227
+ description: 'REQUIRED. The option values you would pick yourself, so the user can confirm rather than decide.',
228
+ },
229
+ options: {
230
+ type: 'array',
231
+ minItems: 2,
232
+ items: {
233
+ type: 'object',
234
+ additionalProperties: false,
235
+ required: ['value', 'label'],
236
+ properties: {
237
+ value: { type: 'string' },
238
+ label: { type: 'string' },
239
+ hotkey: { type: 'string', maxLength: 1 },
240
+ },
241
+ },
242
+ },
243
+ },
244
+ },
245
+ },
246
+ },
247
+ required: ['questions'],
248
+ };
249
+ /**
250
+ * The `ask` tool's input schema, hand-written rather than borrowed from a validation library: core
251
+ * depends on no validator, and the schema has to carry a JSON Schema a provider can constrain
252
+ * generation against. It publishes one through the Standard JSON Schema extension
253
+ * (`~standard.jsonSchema.input`), which is the path the AI SDK adapter already recognises for
254
+ * Valibot / ArkType / Zod 4.
255
+ */
256
+ export const askInputSchema = {
257
+ '~standard': {
258
+ version: 1,
259
+ vendor: 'adonis-agora-agent',
260
+ validate: (value) => {
261
+ const issues = [];
262
+ if (typeof value !== 'object' || value === null) {
263
+ return { issues: [issue([], 'must be an object')] };
264
+ }
265
+ const candidate = value;
266
+ if (!Array.isArray(candidate.questions) || candidate.questions.length === 0) {
267
+ return { issues: [issue(['questions'], 'must be a non-empty array')] };
268
+ }
269
+ if (candidate.questions.length > MAX_ASK_QUESTIONS) {
270
+ return {
271
+ issues: [issue(['questions'], `must hold at most ${MAX_ASK_QUESTIONS} questions`)],
272
+ };
273
+ }
274
+ const questions = [];
275
+ for (const [index, raw] of candidate.questions.entries()) {
276
+ const question = parseQuestion(raw, ['questions', index], issues);
277
+ if (question !== undefined) {
278
+ questions.push(question);
279
+ }
280
+ }
281
+ if (issues.length > 0) {
282
+ return { issues };
283
+ }
284
+ return {
285
+ value: {
286
+ questions,
287
+ ...(typeof candidate.preamble === 'string' ? { preamble: candidate.preamble } : {}),
288
+ },
289
+ };
290
+ },
291
+ jsonSchema: { input: () => ASK_JSON_SCHEMA },
292
+ },
293
+ };
294
+ /**
295
+ * What the model is told the `ask` tool is for. Written to discourage the two failure modes that
296
+ * make a clarifying question worse than a guess: asking about something the conversation already
297
+ * settled, and asking without saying what you would have done.
298
+ */
299
+ export const ASK_TOOL_DESCRIPTION = 'Ask the user to settle the scope of the work before you do it. Use it when a reasonable person would produce a materially different result depending on the answer — not to confirm something the conversation already says. Every question must pre-pick the answer you would choose, so the user can confirm instead of deciding. The user may decline, in which case you proceed on those pre-picked answers.';
300
+ /**
301
+ * The `ask` tool as the model sees it. NOT a `ToolSpec` and never registered: `ask` has no handler,
302
+ * because the loop settles it against a human instead of invoking anything. Keeping it out of the
303
+ * `ToolRegistry` is also what keeps the kind decision off a process-local lookup — see
304
+ * `claimToolCall`.
305
+ */
306
+ export function askToolDefinition() {
307
+ return {
308
+ name: ASK_TOOL_NAME,
309
+ kind: 'ask',
310
+ description: ASK_TOOL_DESCRIPTION,
311
+ inputSchema: askInputSchema,
312
+ };
313
+ }
314
+ export const DEFAULT_INTAKE_PREAMBLE = 'A few questions before I start. I have pre-picked what I would choose, so confirming is enough.';
315
+ //# sourceMappingURL=elicitation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elicitation.js","sourceRoot":"","sources":["../../src/elicitation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type { AgentGovernanceQueries } from '../spi/governance-queries.js';
2
+ import type { ScorableRun } from './types.js';
3
+ /**
4
+ * The corpus behind {@link import('./scorers/approval-risk.scorer.js').ApprovalRiskScorer}: how
5
+ * often humans have approved each `action` tool, across the HITL decisions in view.
6
+ */
7
+ /** One recorded human decision on an `action` tool call. */
8
+ export interface ToolApprovalDecision {
9
+ toolName: string;
10
+ /** The tool call's final status, as the store recorded it. */
11
+ status: string;
12
+ }
13
+ /** How a single tool has fared with humans. */
14
+ export interface ToolApprovalCounts {
15
+ approved: number;
16
+ rejected: number;
17
+ }
18
+ /** Approval counts per tool name. */
19
+ export type ToolApprovalPrior = ReadonlyMap<string, ToolApprovalCounts>;
20
+ /** Fold recorded decisions into per-tool approval counts. Undecided statuses are ignored. */
21
+ export declare function buildApprovalPrior(decisions: Iterable<ToolApprovalDecision>): Map<string, ToolApprovalCounts>;
22
+ /**
23
+ * The prior over the runs a batch already loaded — the cheapest way to get one, and free of extra
24
+ * reads. {@link import('./governance-sample-source.js').GovernanceRunSampleSource} returns each run
25
+ * with its tool calls already attached, so the whole sample's HITL history is in hand before the
26
+ * first scorer runs. It is a prior over the corpus being scored, which is the honest reading of a
27
+ * batch that also IS the corpus; reach for {@link loadApprovalPrior} when the prior should come from
28
+ * a wider slice of history than the batch covers.
29
+ */
30
+ export declare function priorFromRuns(runs: Iterable<ScorableRun>): Map<string, ToolApprovalCounts>;
31
+ /** How much decision history {@link loadApprovalPrior} reads. */
32
+ export interface ApprovalPriorQuery {
33
+ /**
34
+ * How many of the most recent tool calls to read. The read-model's activity feed is not filtered
35
+ * by tool type, so this bounds calls of EVERY kind and a deployment whose traffic is mostly reads
36
+ * needs a generous number to see its actions. Hard cap on the work, by design: building a prior
37
+ * must never turn into an unbounded scan.
38
+ */
39
+ limit?: number;
40
+ /** Inclusive UTC day bounds on when the call was made, `YYYY-MM-DD`. */
41
+ fromDay?: string;
42
+ toDay?: string;
43
+ }
44
+ /**
45
+ * Build the prior from the store's own HITL history, off the governance activity feed. Offline by
46
+ * construction: it reads decisions humans already made, so a batch can score a whole backlog against
47
+ * the taste of the people who have been running the system.
48
+ */
49
+ export declare function loadApprovalPrior(args: {
50
+ queries: AgentGovernanceQueries;
51
+ query?: ApprovalPriorQuery;
52
+ }): Promise<Map<string, ToolApprovalCounts>>;
53
+ /**
54
+ * The smoothed probability that a human approves this tool the next time it is proposed. `0.5` for a
55
+ * tool nobody has ever decided on, which is what "we have no evidence" should look like.
56
+ */
57
+ export declare function approvalPosterior(counts: ToolApprovalCounts | undefined): number;
58
+ //# sourceMappingURL=approval-prior.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-prior.d.ts","sourceRoot":"","sources":["../../../src/evals/approval-prior.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;GAGG;AAEH,4DAA4D;AAC5D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qCAAqC;AACrC,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AAexE,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GACxC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAgBjC;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAU1F;AAED,iEAAiE;AACjE,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,OAAO,EAAE,sBAAsB,CAAC;IAChC,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC5B,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAc3C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,GAAG,MAAM,CAIhF"}
@@ -0,0 +1,82 @@
1
+ /** See the approval-outcome scorer — an approved action can still end `failed`. */
2
+ const APPROVED_STATUSES = new Set(['executed', 'failed']);
3
+ /**
4
+ * Pseudo-counts of a Beta(1,1) prior — one imagined approval and one imagined rejection per tool.
5
+ *
6
+ * Without it a tool rejected once out of one call scores 0.0 and a tool approved once out of one
7
+ * scores 1.0, and the whole ranking is decided by whichever tool happened to be used first. With it,
8
+ * an unseen tool sits at exactly 0.5 ("no evidence either way") and evidence moves it as it
9
+ * accumulates — 1-of-1 rejected reads 0.33, 1-of-6 reads 0.25, 0-of-50 reads 0.02.
10
+ */
11
+ const PRIOR_PSEUDO_COUNT = 1;
12
+ /** Fold recorded decisions into per-tool approval counts. Undecided statuses are ignored. */
13
+ export function buildApprovalPrior(decisions) {
14
+ const prior = new Map();
15
+ for (const decision of decisions) {
16
+ const approved = APPROVED_STATUSES.has(decision.status);
17
+ if (!approved && decision.status !== 'rejected') {
18
+ continue;
19
+ }
20
+ const counts = prior.get(decision.toolName) ?? { approved: 0, rejected: 0 };
21
+ if (approved) {
22
+ counts.approved += 1;
23
+ }
24
+ else {
25
+ counts.rejected += 1;
26
+ }
27
+ prior.set(decision.toolName, counts);
28
+ }
29
+ return prior;
30
+ }
31
+ /**
32
+ * The prior over the runs a batch already loaded — the cheapest way to get one, and free of extra
33
+ * reads. {@link import('./governance-sample-source.js').GovernanceRunSampleSource} returns each run
34
+ * with its tool calls already attached, so the whole sample's HITL history is in hand before the
35
+ * first scorer runs. It is a prior over the corpus being scored, which is the honest reading of a
36
+ * batch that also IS the corpus; reach for {@link loadApprovalPrior} when the prior should come from
37
+ * a wider slice of history than the batch covers.
38
+ */
39
+ export function priorFromRuns(runs) {
40
+ const decisions = [];
41
+ for (const run of runs) {
42
+ for (const call of run.toolCalls) {
43
+ if (call.toolType === 'action') {
44
+ decisions.push({ toolName: call.toolName, status: call.status });
45
+ }
46
+ }
47
+ }
48
+ return buildApprovalPrior(decisions);
49
+ }
50
+ const DEFAULT_LIMIT = 2_000;
51
+ /**
52
+ * Build the prior from the store's own HITL history, off the governance activity feed. Offline by
53
+ * construction: it reads decisions humans already made, so a batch can score a whole backlog against
54
+ * the taste of the people who have been running the system.
55
+ */
56
+ export async function loadApprovalPrior(args) {
57
+ const { queries, query = {} } = args;
58
+ const rows = await queries.recentToolCalls(query.limit ?? DEFAULT_LIMIT);
59
+ const decisions = [];
60
+ for (const row of rows) {
61
+ if (row.toolType !== 'action') {
62
+ continue;
63
+ }
64
+ const day = row.createdAt.slice(0, 10);
65
+ if (query.fromDay !== undefined && day < query.fromDay)
66
+ continue;
67
+ if (query.toDay !== undefined && day > query.toDay)
68
+ continue;
69
+ decisions.push({ toolName: row.toolName, status: row.status });
70
+ }
71
+ return buildApprovalPrior(decisions);
72
+ }
73
+ /**
74
+ * The smoothed probability that a human approves this tool the next time it is proposed. `0.5` for a
75
+ * tool nobody has ever decided on, which is what "we have no evidence" should look like.
76
+ */
77
+ export function approvalPosterior(counts) {
78
+ const approved = counts?.approved ?? 0;
79
+ const rejected = counts?.rejected ?? 0;
80
+ return (approved + PRIOR_PSEUDO_COUNT) / (approved + rejected + PRIOR_PSEUDO_COUNT * 2);
81
+ }
82
+ //# sourceMappingURL=approval-prior.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-prior.js","sourceRoot":"","sources":["../../../src/evals/approval-prior.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import type { RunSampleQuery, RunSampleSource } from './sample-source.js';
2
+ import type { RunScore, ScoreStore } from './score-store.js';
3
+ import type { ScorableRun, ScoreResult, Scorer } from './types.js';
4
+ /** One scorer blowing up on one run. Collected, never thrown — see {@link runEvaluation}. */
5
+ export interface ScorerFailure {
6
+ runId: string;
7
+ scorer: string;
8
+ message: string;
9
+ }
10
+ /** What a batch did. `runsRead - runsScored` is the runs no scorer had anything to say about. */
11
+ export interface EvaluationSummary {
12
+ /** Runs the source returned for the query. */
13
+ runsRead: number;
14
+ /** Distinct runs that produced at least one score. */
15
+ runsScored: number;
16
+ /** `(run, scorer)` pairs skipped because that scorer had already covered that run. */
17
+ pairsSkipped: number;
18
+ scoresRecorded: number;
19
+ failures: ScorerFailure[];
20
+ }
21
+ export interface EvaluationOptions {
22
+ source: RunSampleSource;
23
+ scorers: Scorer[];
24
+ store: ScoreStore;
25
+ query: RunSampleQuery;
26
+ /**
27
+ * Score runs a scorer has already covered. Default `false`, which makes a batch resumable: an
28
+ * interrupted backfill restarted with the same query costs nothing for the part it finished — and
29
+ * for a model-graded scorer, bills nothing.
30
+ */
31
+ rescore?: boolean;
32
+ /** Clock for {@link RunScore.scoredAt}; injectable so a test can pin it. */
33
+ now?: () => Date;
34
+ }
35
+ /**
36
+ * Score a batch of stored runs and persist the results — the offline path, and the one to reach for.
37
+ *
38
+ * A scorer that throws is recorded as a {@link ScorerFailure} and the batch carries on. One
39
+ * malformed run, one judge that returned prose instead of a verdict, one adapter row a scorer did
40
+ * not expect: none of those should cost you the other 499 runs of a backfill, and a failure that
41
+ * silently became a score of 0 would be worse still — it would read as the agent's fault.
42
+ */
43
+ export declare function runEvaluation(options: EvaluationOptions): Promise<EvaluationSummary>;
44
+ /** Assemble the persisted row: the scorer's verdict plus the provenance a summary groups by. */
45
+ export declare function toRunScore(args: {
46
+ run: ScorableRun;
47
+ scorer: Scorer;
48
+ result: ScoreResult;
49
+ scoredAt: Date;
50
+ }): RunScore;
51
+ //# sourceMappingURL=evaluate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../../src/evals/evaluate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEnE,6FAA6F;AAC7F,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,iGAAiG;AACjG,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAuD1F;AAED,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,IAAI,EAAE;IAC/B,GAAG,EAAE,WAAW,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,IAAI,CAAC;CAChB,GAAG,QAAQ,CAeX"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Score a batch of stored runs and persist the results — the offline path, and the one to reach for.
3
+ *
4
+ * A scorer that throws is recorded as a {@link ScorerFailure} and the batch carries on. One
5
+ * malformed run, one judge that returned prose instead of a verdict, one adapter row a scorer did
6
+ * not expect: none of those should cost you the other 499 runs of a backfill, and a failure that
7
+ * silently became a score of 0 would be worse still — it would read as the agent's fault.
8
+ */
9
+ export async function runEvaluation(options) {
10
+ const now = options.now ?? (() => new Date());
11
+ const runs = await options.source.listRuns(options.query);
12
+ const runIds = runs.map((run) => run.runId);
13
+ const alreadyScored = new Map();
14
+ if (options.rescore !== true) {
15
+ for (const scorer of options.scorers) {
16
+ alreadyScored.set(scorer.name, new Set(await options.store.scoredRunIds(scorer.name, runIds)));
17
+ }
18
+ }
19
+ const scores = [];
20
+ const failures = [];
21
+ const scoredRuns = new Set();
22
+ let pairsSkipped = 0;
23
+ for (const run of runs) {
24
+ for (const scorer of options.scorers) {
25
+ if (alreadyScored.get(scorer.name)?.has(run.runId) === true) {
26
+ pairsSkipped += 1;
27
+ continue;
28
+ }
29
+ let result;
30
+ try {
31
+ result = await scorer.score(run);
32
+ }
33
+ catch (error) {
34
+ failures.push({
35
+ runId: run.runId,
36
+ scorer: scorer.name,
37
+ message: error instanceof Error ? error.message : String(error),
38
+ });
39
+ continue;
40
+ }
41
+ if (result === null) {
42
+ continue;
43
+ }
44
+ scores.push(toRunScore({ run, scorer, result, scoredAt: now() }));
45
+ scoredRuns.add(run.runId);
46
+ }
47
+ }
48
+ if (scores.length > 0) {
49
+ await options.store.recordScores(scores);
50
+ }
51
+ return {
52
+ runsRead: runs.length,
53
+ runsScored: scoredRuns.size,
54
+ pairsSkipped,
55
+ scoresRecorded: scores.length,
56
+ failures,
57
+ };
58
+ }
59
+ /** Assemble the persisted row: the scorer's verdict plus the provenance a summary groups by. */
60
+ export function toRunScore(args) {
61
+ const { run, scorer, result, scoredAt } = args;
62
+ return {
63
+ runId: run.runId,
64
+ threadId: run.threadId,
65
+ agentName: run.agentName,
66
+ scorer: scorer.name,
67
+ kind: scorer.kind,
68
+ score: result.score,
69
+ reason: result.reason,
70
+ ...(result.metadata !== undefined ? { metadata: result.metadata } : {}),
71
+ // The RUN's day, not the batch's — see RunScore.day.
72
+ day: run.startedAt.slice(0, 10),
73
+ scoredAt: scoredAt.toISOString(),
74
+ };
75
+ }
76
+ //# sourceMappingURL=evaluate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../../src/evals/evaluate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { AgentGovernanceQueries } from '../spi/governance-queries.js';
2
+ import type { RunSampleQuery, RunSampleSource } from './sample-source.js';
3
+ import type { ScorableRun } from './types.js';
4
+ /**
5
+ * A {@link RunSampleSource} over what the agent already persisted, read through
6
+ * {@link AgentGovernanceQueries} alone. Works against any adapter that implements it (Lucid, the
7
+ * in-memory one) — this module adds no tables of its own on the read side.
8
+ *
9
+ * The prompt and the answer come off `runDetail`, whose messages are the ones stamped with this
10
+ * run's own `run_id`. There is no transcript join and no time-window heuristic: a run that wrote no
11
+ * message has empty text, and no other run's answer can ever be handed to it.
12
+ *
13
+ * One seam remains, and it is the read-model's rather than this class's: a run whose messages were
14
+ * written before message-level run stamping reads as empty text. A rule-based scorer over tool
15
+ * outcomes still works on it; a judge over the answer has nothing to read.
16
+ */
17
+ export declare class GovernanceRunSampleSource implements RunSampleSource {
18
+ private readonly queries;
19
+ constructor(queries: AgentGovernanceQueries);
20
+ listRuns(query: RunSampleQuery): Promise<ScorableRun[]>;
21
+ getRun(runId: string): Promise<ScorableRun | null>;
22
+ }
23
+ //# sourceMappingURL=governance-sample-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance-sample-source.d.ts","sourceRoot":"","sources":["../../../src/evals/governance-sample-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,YAAY,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,qBAAa,yBAA0B,YAAW,eAAe;IACnD,OAAO,CAAC,QAAQ,CAAC,OAAO;IAApC,YAA6B,OAAO,EAAE,sBAAsB,EAAI;IAE1D,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CA8B5D;IAEK,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAGvD;CACF"}