ai-capability-framework 1.0.3 → 1.1.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 (246) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +38 -30
  3. package/ROADMAP.md +14 -0
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +32 -1
  6. package/dist/discovery/bindings.d.ts +7 -0
  7. package/dist/discovery/bindings.d.ts.map +1 -0
  8. package/dist/discovery/bindings.js +24 -0
  9. package/dist/discovery/budget.d.ts +17 -0
  10. package/dist/discovery/budget.d.ts.map +1 -0
  11. package/dist/discovery/budget.js +77 -0
  12. package/dist/discovery/configuration.d.ts +10 -0
  13. package/dist/discovery/configuration.d.ts.map +1 -0
  14. package/dist/discovery/configuration.js +63 -0
  15. package/dist/discovery/corpus.d.ts +8 -0
  16. package/dist/discovery/corpus.d.ts.map +1 -0
  17. package/dist/discovery/corpus.js +64 -0
  18. package/dist/discovery/diagnostics.d.ts +15 -0
  19. package/dist/discovery/diagnostics.d.ts.map +1 -0
  20. package/dist/discovery/diagnostics.js +11 -0
  21. package/dist/discovery/discoverer.d.ts +23 -0
  22. package/dist/discovery/discoverer.d.ts.map +1 -0
  23. package/dist/discovery/discoverer.js +261 -0
  24. package/dist/discovery/embedding-configuration.d.ts +12 -0
  25. package/dist/discovery/embedding-configuration.d.ts.map +1 -0
  26. package/dist/discovery/embedding-configuration.js +81 -0
  27. package/dist/discovery/embedding-types.d.ts +75 -0
  28. package/dist/discovery/embedding-types.d.ts.map +1 -0
  29. package/dist/discovery/embedding-types.js +1 -0
  30. package/dist/discovery/embeddings.d.ts +38 -0
  31. package/dist/discovery/embeddings.d.ts.map +1 -0
  32. package/dist/discovery/embeddings.js +71 -0
  33. package/dist/discovery/evaluation-validation.d.ts +8 -0
  34. package/dist/discovery/evaluation-validation.d.ts.map +1 -0
  35. package/dist/discovery/evaluation-validation.js +19 -0
  36. package/dist/discovery/evaluation.d.ts +84 -0
  37. package/dist/discovery/evaluation.d.ts.map +1 -0
  38. package/dist/discovery/evaluation.js +310 -0
  39. package/dist/discovery/export.d.ts +14 -0
  40. package/dist/discovery/export.d.ts.map +1 -0
  41. package/dist/discovery/export.js +81 -0
  42. package/dist/discovery/facade.d.ts +82 -0
  43. package/dist/discovery/facade.d.ts.map +1 -0
  44. package/dist/discovery/facade.js +266 -0
  45. package/dist/discovery/fingerprint.d.ts +71 -0
  46. package/dist/discovery/fingerprint.d.ts.map +1 -0
  47. package/dist/discovery/fingerprint.js +67 -0
  48. package/dist/discovery/index-builder.d.ts +3 -0
  49. package/dist/discovery/index-builder.d.ts.map +1 -0
  50. package/dist/discovery/index-builder.js +129 -0
  51. package/dist/discovery/index-validation.d.ts +12 -0
  52. package/dist/discovery/index-validation.d.ts.map +1 -0
  53. package/dist/discovery/index-validation.js +117 -0
  54. package/dist/discovery/index.d.ts +32 -0
  55. package/dist/discovery/index.d.ts.map +1 -0
  56. package/dist/discovery/index.js +18 -0
  57. package/dist/discovery/json-snapshot.d.ts +3 -0
  58. package/dist/discovery/json-snapshot.d.ts.map +1 -0
  59. package/dist/discovery/json-snapshot.js +11 -0
  60. package/dist/discovery/lexical.d.ts +12 -0
  61. package/dist/discovery/lexical.d.ts.map +1 -0
  62. package/dist/discovery/lexical.js +26 -0
  63. package/dist/discovery/metadata.d.ts +4 -0
  64. package/dist/discovery/metadata.d.ts.map +1 -0
  65. package/dist/discovery/metadata.js +33 -0
  66. package/dist/discovery/ranking.d.ts +7 -0
  67. package/dist/discovery/ranking.d.ts.map +1 -0
  68. package/dist/discovery/ranking.js +68 -0
  69. package/dist/discovery/replay.d.ts +50 -0
  70. package/dist/discovery/replay.d.ts.map +1 -0
  71. package/dist/discovery/replay.js +175 -0
  72. package/dist/discovery/retrieval-policy.d.ts +5 -0
  73. package/dist/discovery/retrieval-policy.d.ts.map +1 -0
  74. package/dist/discovery/retrieval-policy.js +10 -0
  75. package/dist/discovery/router.d.ts +39 -0
  76. package/dist/discovery/router.d.ts.map +1 -0
  77. package/dist/discovery/router.js +98 -0
  78. package/dist/discovery/selection-attempt.d.ts +20 -0
  79. package/dist/discovery/selection-attempt.d.ts.map +1 -0
  80. package/dist/discovery/selection-attempt.js +39 -0
  81. package/dist/discovery/selection-cards.d.ts +12 -0
  82. package/dist/discovery/selection-cards.d.ts.map +1 -0
  83. package/dist/discovery/selection-cards.js +79 -0
  84. package/dist/discovery/selection-configuration.d.ts +18 -0
  85. package/dist/discovery/selection-configuration.d.ts.map +1 -0
  86. package/dist/discovery/selection-configuration.js +71 -0
  87. package/dist/discovery/selection-response.d.ts +13 -0
  88. package/dist/discovery/selection-response.d.ts.map +1 -0
  89. package/dist/discovery/selection-response.js +47 -0
  90. package/dist/discovery/selection-types.d.ts +18 -0
  91. package/dist/discovery/selection-types.d.ts.map +1 -0
  92. package/dist/discovery/selection-types.js +1 -0
  93. package/dist/discovery/selection.d.ts +6 -0
  94. package/dist/discovery/selection.d.ts.map +1 -0
  95. package/dist/discovery/selection.js +145 -0
  96. package/dist/discovery/types.d.ts +291 -0
  97. package/dist/discovery/types.d.ts.map +1 -0
  98. package/dist/discovery/types.js +1 -0
  99. package/dist/discovery/usage.d.ts +2 -0
  100. package/dist/discovery/usage.d.ts.map +1 -0
  101. package/dist/discovery/usage.js +1 -0
  102. package/dist/discovery/vectors.d.ts +5 -0
  103. package/dist/discovery/vectors.d.ts.map +1 -0
  104. package/dist/discovery/vectors.js +43 -0
  105. package/dist/discovery/versions.d.ts +37 -0
  106. package/dist/discovery/versions.d.ts.map +1 -0
  107. package/dist/discovery/versions.js +36 -0
  108. package/dist/evals-live/live-eval-runner.d.ts +1 -0
  109. package/dist/evals-live/live-eval-runner.d.ts.map +1 -1
  110. package/dist/evals-live/live-eval-runner.js +12 -1
  111. package/dist/evals-live/types.d.ts +3 -0
  112. package/dist/evals-live/types.d.ts.map +1 -1
  113. package/dist/generated/manifest-types.d.ts +3655 -0
  114. package/dist/generated/manifest-types.d.ts.map +1 -1
  115. package/dist/loader.d.ts.map +1 -1
  116. package/dist/loader.js +8 -0
  117. package/dist/mcp-server/server.d.ts.map +1 -1
  118. package/dist/mcp-server/server.js +11 -2
  119. package/dist/mcp-server/types.d.ts +4 -0
  120. package/dist/mcp-server/types.d.ts.map +1 -1
  121. package/dist/observability/redaction.d.ts.map +1 -1
  122. package/dist/observability/redaction.js +6 -2
  123. package/dist/observability/types.d.ts +1 -1
  124. package/dist/observability/types.d.ts.map +1 -1
  125. package/dist/openai/index.d.ts +2 -0
  126. package/dist/openai/index.d.ts.map +1 -1
  127. package/dist/openai/index.js +1 -0
  128. package/dist/openai/responses-runner.d.ts +1 -1
  129. package/dist/openai/responses-runner.d.ts.map +1 -1
  130. package/dist/openai/responses-runner.js +134 -7
  131. package/dist/openai/selection-client.d.ts +28 -0
  132. package/dist/openai/selection-client.d.ts.map +1 -0
  133. package/dist/openai/selection-client.js +95 -0
  134. package/dist/openai/tool-loop.js +1 -1
  135. package/dist/openai/types.d.ts +19 -2
  136. package/dist/openai/types.d.ts.map +1 -1
  137. package/dist/replay/discovery-snapshot.d.ts +10 -0
  138. package/dist/replay/discovery-snapshot.d.ts.map +1 -0
  139. package/dist/replay/discovery-snapshot.js +17 -0
  140. package/dist/replay/recorder.d.ts.map +1 -1
  141. package/dist/replay/recorder.js +4 -0
  142. package/dist/replay/redaction.js +5 -1
  143. package/dist/replay/replayer.d.ts.map +1 -1
  144. package/dist/replay/replayer.js +14 -1
  145. package/dist/replay/types.d.ts +3 -0
  146. package/dist/replay/types.d.ts.map +1 -1
  147. package/dist/replay/validation.d.ts.map +1 -1
  148. package/dist/replay/validation.js +6 -0
  149. package/dist/runtime/bounded-json.d.ts +4 -0
  150. package/dist/runtime/bounded-json.d.ts.map +1 -0
  151. package/dist/runtime/bounded-json.js +74 -0
  152. package/dist/runtime/eligibility.d.ts +4 -0
  153. package/dist/runtime/eligibility.d.ts.map +1 -0
  154. package/dist/runtime/eligibility.js +128 -0
  155. package/dist/runtime/index.d.ts +5 -1
  156. package/dist/runtime/index.d.ts.map +1 -1
  157. package/dist/runtime/index.js +2 -0
  158. package/dist/runtime/provider-attempt.d.ts +11 -0
  159. package/dist/runtime/provider-attempt.d.ts.map +1 -0
  160. package/dist/runtime/provider-attempt.js +221 -0
  161. package/dist/runtime/provider-run.d.ts +10 -0
  162. package/dist/runtime/provider-run.d.ts.map +1 -0
  163. package/dist/runtime/provider-run.js +123 -0
  164. package/dist/runtime/provider-stop.d.ts +9 -0
  165. package/dist/runtime/provider-stop.d.ts.map +1 -0
  166. package/dist/runtime/provider-stop.js +28 -0
  167. package/dist/runtime/provider-types.d.ts +189 -0
  168. package/dist/runtime/provider-types.d.ts.map +1 -0
  169. package/dist/runtime/provider-types.js +1 -0
  170. package/dist/runtime/provider-usage.d.ts +9 -0
  171. package/dist/runtime/provider-usage.d.ts.map +1 -0
  172. package/dist/runtime/provider-usage.js +69 -0
  173. package/dist/runtime/router.d.ts.map +1 -1
  174. package/dist/runtime/router.js +3 -118
  175. package/dist/runtime/types.d.ts +9 -0
  176. package/dist/runtime/types.d.ts.map +1 -1
  177. package/dist/types.d.ts +1 -1
  178. package/dist/types.d.ts.map +1 -1
  179. package/dist/validator.d.ts +3 -0
  180. package/dist/validator.d.ts.map +1 -1
  181. package/dist/validator.js +32 -0
  182. package/docs/api/public-api-policy.md +10 -0
  183. package/docs/api/stable-workflow.md +58 -0
  184. package/docs/api.md +7 -0
  185. package/docs/capability-manifests.md +24 -0
  186. package/docs/development.md +22 -0
  187. package/docs/discovery.md +186 -0
  188. package/docs/evals/discovery-live.md +199 -0
  189. package/docs/evals/discovery-qualification.md +158 -0
  190. package/docs/evals/overview.md +9 -0
  191. package/docs/getting-started/installation.md +11 -12
  192. package/docs/getting-started/openai-quickstart.md +16 -5
  193. package/docs/getting-started/provider-neutral-quickstart.md +247 -88
  194. package/docs/getting-started/quickstart.md +8 -30
  195. package/docs/index.md +10 -0
  196. package/docs/release.md +29 -5
  197. package/docs/runtime.md +27 -0
  198. package/docs/start-here.md +23 -134
  199. package/examples/12-capability-discovery-selection/README.md +346 -0
  200. package/examples/12-capability-discovery-selection/customer-cases.mjs +52 -0
  201. package/examples/12-capability-discovery-selection/customer-harness.mjs +91 -0
  202. package/examples/12-capability-discovery-selection/customer-request-example.mjs +320 -0
  203. package/examples/12-capability-discovery-selection/discovery-example.mjs +175 -0
  204. package/examples/12-capability-discovery-selection/discovery-fixtures/three-domains.suite.json +7887 -0
  205. package/examples/12-capability-discovery-selection/discovery-fixtures/three-domains.v2.suite.json +8167 -0
  206. package/examples/12-capability-discovery-selection/discovery-fixtures/three-domains.v3.suite.json +8342 -0
  207. package/examples/12-capability-discovery-selection/evaluation/application.mjs +305 -0
  208. package/examples/12-capability-discovery-selection/evaluation/campaign.mjs +248 -0
  209. package/examples/12-capability-discovery-selection/evaluation/clients.mjs +433 -0
  210. package/examples/12-capability-discovery-selection/evaluation/continuation.mjs +208 -0
  211. package/examples/12-capability-discovery-selection/evaluation/durable-budget.mjs +420 -0
  212. package/examples/12-capability-discovery-selection/evaluation/freeze.mjs +9 -0
  213. package/examples/12-capability-discovery-selection/evaluation/harness.mjs +618 -0
  214. package/examples/12-capability-discovery-selection/evaluation/mock-host.mjs +260 -0
  215. package/examples/12-capability-discovery-selection/evaluation/preflight.mjs +115 -0
  216. package/examples/12-capability-discovery-selection/evaluation/qualification-workflows.mjs +87 -0
  217. package/examples/12-capability-discovery-selection/evaluation/regrade.mjs +281 -0
  218. package/examples/12-capability-discovery-selection/evaluation/report.mjs +517 -0
  219. package/examples/12-capability-discovery-selection/evaluation/runner.mjs +613 -0
  220. package/examples/12-capability-discovery-selection/evaluation/saved-campaign.mjs +385 -0
  221. package/examples/12-capability-discovery-selection/evaluation/wording.mjs +115 -0
  222. package/examples/12-capability-discovery-selection/evaluation/workflow-application.mjs +378 -0
  223. package/examples/12-capability-discovery-selection/evaluation/workflow-cases.mjs +90 -0
  224. package/examples/12-capability-discovery-selection/evaluation-example.mjs +154 -0
  225. package/examples/12-capability-discovery-selection/hybrid-example.mjs +174 -0
  226. package/examples/12-capability-discovery-selection/mock-embeddings.mjs +101 -0
  227. package/examples/12-capability-discovery-selection/mock-selection.mjs +78 -0
  228. package/examples/12-capability-discovery-selection/pipeline-example.mjs +496 -0
  229. package/examples/12-capability-discovery-selection/retrieval-cases.mjs +31 -0
  230. package/examples/12-capability-discovery-selection/run-campaign-mock.mjs +40 -0
  231. package/examples/12-capability-discovery-selection/run-customer-mock.mjs +15 -0
  232. package/examples/12-capability-discovery-selection/run-evaluation-live.mjs +10 -0
  233. package/examples/12-capability-discovery-selection/run-evaluation-mock.mjs +3 -0
  234. package/examples/12-capability-discovery-selection/run-evaluation-regrade.mjs +71 -0
  235. package/examples/12-capability-discovery-selection/run-hybrid-mock.mjs +3 -0
  236. package/examples/12-capability-discovery-selection/run-mock.mjs +3 -0
  237. package/examples/12-capability-discovery-selection/run-pipeline-mock.mjs +2 -0
  238. package/examples/12-capability-discovery-selection/run-selector-mock.mjs +3 -0
  239. package/examples/12-capability-discovery-selection/selection-example.mjs +88 -0
  240. package/package.json +17 -4
  241. package/schemas/discovery/embedding-index.schema.json +71 -0
  242. package/schemas/discovery/eval-observations.schema.json +409 -0
  243. package/schemas/discovery/eval-suite.schema.json +375 -0
  244. package/schemas/discovery/metadata.schema.json +30 -0
  245. package/schemas/discovery/selection-response.schema.json +47 -0
  246. package/schemas/replay/discovery-snapshot.schema.json +335 -0
@@ -0,0 +1,618 @@
1
+ import {
2
+ AicfActionLifecycleManager,
3
+ AicfHandlerRegistry,
4
+ AicfToolExecutor,
5
+ DefaultPolicyBroker,
6
+ DefaultContextBuilder,
7
+ InMemoryApprovalStore,
8
+ InMemoryAuditSink,
9
+ InMemoryIdempotencyStore,
10
+ InMemoryPreparedActionStore,
11
+ createAicfProviderRun
12
+ } from "ai-capability-framework/runtime";
13
+ import { runOpenAIResponses } from "ai-capability-framework/openai";
14
+ import {
15
+ buildCapabilitySearchCorpus,
16
+ createCapabilityDiscovery,
17
+ buildCapabilityEmbeddingIndex,
18
+ hashDiscoveryContent,
19
+ validateCapabilityEmbeddingIndex,
20
+ DISCOVERY_STANDARD_PROFILE
21
+ } from "ai-capability-framework/discovery";
22
+ import { EXECUTION, PROMPTS, projectTask } from "./campaign.mjs";
23
+
24
+ import Ajv2020 from "ajv/dist/2020.js";
25
+
26
+ const appAjv = new Ajv2020({ strict: true, allErrors: true });
27
+
28
+ const operation = (manifest) => (manifest.lifecycle.prepare ? "prepare" : "read");
29
+ const normalizeUsage = (raw) => {
30
+ const result = {};
31
+ for (const [key, value] of Object.entries({
32
+ inputTokens: raw?.input_tokens,
33
+ outputTokens: raw?.output_tokens,
34
+ totalTokens: raw?.total_tokens,
35
+ cachedInputTokens: raw?.input_tokens_details?.cached_tokens,
36
+ reasoningTokens: raw?.output_tokens_details?.reasoning_tokens
37
+ })) {
38
+ if (Number.isSafeInteger(value) && value >= 0) result[key] = value;
39
+ }
40
+ return result;
41
+ };
42
+
43
+ export function createSyntheticRuntime(registry) {
44
+ const handlers = new AicfHandlerRegistry({ registry }),
45
+ executed = [];
46
+ for (const { manifest } of registry.capabilities) {
47
+ if (manifest.lifecycle.commit) continue;
48
+ if (manifest.lifecycle.prepare)
49
+ handlers.register({
50
+ capabilityId: manifest.id,
51
+ prepare: ({ args }) => {
52
+ executed.push({
53
+ capabilityId: manifest.id,
54
+ operation: "prepare",
55
+ args: structuredClone(args)
56
+ });
57
+ return {
58
+ data: { ...args },
59
+ riskTier: "medium",
60
+ summary: "Synthetic proposal for review.",
61
+ userMessage: "The preview requires approval."
62
+ };
63
+ }
64
+ });
65
+ else
66
+ handlers.register({
67
+ capabilityId: manifest.id,
68
+ read: ({ args }) => {
69
+ executed.push({
70
+ capabilityId: manifest.id,
71
+ operation: "read",
72
+ args: structuredClone(args)
73
+ });
74
+ if (manifest.id === "support.ticket.activity")
75
+ return {
76
+ ticket_id: args.ticket_id,
77
+ events: [
78
+ {
79
+ event_id: "EVT-100",
80
+ kind: "reply",
81
+ message: "Replacement acknowledged.",
82
+ occurred_at: "2030-06-10T09:00:00Z"
83
+ }
84
+ ]
85
+ };
86
+ if (manifest.domain === "support")
87
+ return {
88
+ ticket: { ticket_id: args.ticket_id, order_id: "ORD-100", status: "open" }
89
+ };
90
+ if (manifest.id === "inventory.product.get")
91
+ return {
92
+ product: {
93
+ product_id: args.product_id,
94
+ description: "Synthetic packing item",
95
+ dimensions_cm: { width: 20, height: 10, depth: 5 }
96
+ }
97
+ };
98
+ if (manifest.domain === "inventory")
99
+ return {
100
+ stock: {
101
+ product_id: args.product_id,
102
+ warehouse_id: args.warehouse_id,
103
+ quantity: 12
104
+ }
105
+ };
106
+ if (manifest.id === "scheduling.calendar.events")
107
+ return {
108
+ events: [
109
+ {
110
+ event_id: "EVT-100",
111
+ participant_id: args.participant_id,
112
+ starts_at: "2030-06-10T09:00:00Z",
113
+ ends_at: "2030-06-10T09:30:00Z",
114
+ topic: "Existing appointment"
115
+ }
116
+ ]
117
+ };
118
+ return {
119
+ slots: [
120
+ { starts_at: "2030-06-10T10:00:00Z", ends_at: "2030-06-10T10:30:00Z" }
121
+ ]
122
+ };
123
+ }
124
+ });
125
+ }
126
+ let taskScope = null;
127
+ const blockedChoices = [];
128
+ const auditSink = new InMemoryAuditSink();
129
+ const policyBroker = new DefaultPolicyBroker({
130
+ hostPolicyHook: (input) => {
131
+ const requestedOperation =
132
+ input.operation === "select" ? "read" : input.operation;
133
+ if (taskScope && requestedOperation === "prepare") {
134
+ const field = { support: "ticket", inventory: "stock", scheduling: "slots" }[
135
+ input.capability.manifest.domain
136
+ ];
137
+ if (!taskScope.readiness?.some((receipt) => receipt.data?.[field]))
138
+ return {
139
+ status: "denied",
140
+ reasons: [
141
+ {
142
+ code: "application_readiness_missing",
143
+ message: "The application requires a verified prerequisite receipt.",
144
+ severity: "error",
145
+ source: "host"
146
+ }
147
+ ],
148
+ requiredApprovals: []
149
+ };
150
+ }
151
+ if (
152
+ taskScope &&
153
+ (requestedOperation !== taskScope.operation ||
154
+ !taskScope.authorization.permissions?.length)
155
+ ) {
156
+ blockedChoices.push({
157
+ capabilityId: input.capability.manifest.id,
158
+ operation: input.operation,
159
+ expectedOperation: taskScope.operation
160
+ });
161
+ return {
162
+ status: "denied",
163
+ reasons: [
164
+ {
165
+ code: "application_task_scope",
166
+ message: "The application task scope denied this operation.",
167
+ severity: "error",
168
+ source: "host"
169
+ }
170
+ ],
171
+ requiredApprovals: []
172
+ };
173
+ }
174
+ return input.operation === "prepare"
175
+ ? {
176
+ status: "approval_required",
177
+ reasons: [],
178
+ requiredApprovals: [
179
+ {
180
+ approvalType: "operator_review",
181
+ reason: "Synthetic preparation requires review."
182
+ }
183
+ ]
184
+ }
185
+ : null;
186
+ }
187
+ });
188
+ const actionLifecycle = new AicfActionLifecycleManager({
189
+ registry,
190
+ handlers,
191
+ auditSink,
192
+ policyBroker,
193
+ approvalStore: new InMemoryApprovalStore(),
194
+ idempotencyStore: new InMemoryIdempotencyStore(),
195
+ preparedActionStore: new InMemoryPreparedActionStore()
196
+ });
197
+ const executor = new AicfToolExecutor({
198
+ registry,
199
+ handlers,
200
+ auditSink,
201
+ policyBroker,
202
+ actionLifecycle
203
+ });
204
+ return {
205
+ executor,
206
+ executed,
207
+ blockedChoices,
208
+ setTaskScope(value) {
209
+ taskScope = value;
210
+ }
211
+ };
212
+ }
213
+
214
+ export async function buildEvaluationIndex({ registry, host, ledger, context }) {
215
+ const corpus = buildCapabilitySearchCorpus(registry),
216
+ runId = `index.${ledger.fingerprint.slice(7, 39)}`,
217
+ budget = ledger.scope(runId);
218
+ return buildCapabilityEmbeddingIndex({
219
+ corpus,
220
+ client: host.embeddingClient,
221
+ limits: DISCOVERY_STANDARD_PROFILE.indexLimits,
222
+ execution: {
223
+ budgetPolicy: budget.policy,
224
+ estimateCost: host.estimateCost,
225
+ limits: {
226
+ maxInputTokens: 4096,
227
+ maxCharactersPerText: 16_384,
228
+ maxCharactersPerCall: 65_536,
229
+ maxEstimatedCostPerCall: host.maxCost(4096, 0, true)
230
+ }
231
+ },
232
+ batchSize: 8,
233
+ maxProviderCalls: 3,
234
+ runId,
235
+ requestId: "index-build",
236
+ deadlineAt: Date.now() + 30_000,
237
+ budget: budget.ledger,
238
+ runtimeContext: context
239
+ });
240
+ }
241
+
242
+ export function discoveryOptions(registry, mode, k, host, index, contextBuilder) {
243
+ return {
244
+ registry,
245
+ limits: { maxCandidates: k },
246
+ contextBuilder,
247
+ ...(mode.startsWith("hybrid")
248
+ ? {
249
+ mode: "hybrid",
250
+ weights: { semantic: 0.75, lexical: 0.25 },
251
+ failurePolicy: "unavailable",
252
+ embedding: {
253
+ client: host.embeddingClient,
254
+ index,
255
+ maxInputTokens: 4096,
256
+ estimateCost: host.estimateCost,
257
+ maxEstimatedCostPerCall: host.maxCost(4096, 0, true)
258
+ }
259
+ }
260
+ : {})
261
+ };
262
+ }
263
+
264
+ export async function runReadyTask({
265
+ task,
266
+ registry,
267
+ mode,
268
+ k,
269
+ host,
270
+ index,
271
+ providerRun,
272
+ runtime,
273
+ deadlineAt,
274
+ contextBuilder,
275
+ controls,
276
+ afterSearch
277
+ }) {
278
+ const discovery = createCapabilityDiscovery(
279
+ discoveryOptions(registry, mode, k, host, index, contextBuilder)
280
+ );
281
+ const started = performance.now();
282
+ const [result] = await discovery.search({
283
+ tasks: [{ id: task.id, text: task.text }],
284
+ runtimeContext: task.runtimeContext,
285
+ eligibility: task.eligibility,
286
+ providerRun,
287
+ deadlineAt,
288
+ controls
289
+ });
290
+ await afterSearch?.({ result, task, discovery });
291
+ let batch, router;
292
+ if (result.status === "matched" && mode.endsWith("dedicated")) {
293
+ batch = await discovery.select({
294
+ results: [result],
295
+ client: host.selectionClient,
296
+ providerRun,
297
+ maxInputTokens: 8000,
298
+ maxOutputTokens: 1000,
299
+ limits: { maxAttempts: 1 },
300
+ deadlineAt,
301
+ contextByQueryId: {
302
+ [task.id]: {
303
+ ...(task.applicationInput ?? {}),
304
+ verifiedReadiness: task.runtimeContext.facts["example.readiness"] ?? null,
305
+ applicationFacts: task.runtimeContext.facts["example.request"] ?? {}
306
+ }
307
+ },
308
+ maxEstimatedCostPerCall: host.maxCost(),
309
+ estimateCost: host.estimateCost
310
+ });
311
+ router = discovery.routerFor(batch, task.id);
312
+ } else router = discovery.routerFor(result);
313
+ const missingAccess = !task.runtimeContext.subject.permissions?.length;
314
+ const actionable =
315
+ result.status === "matched" &&
316
+ !missingAccess &&
317
+ (!batch || batch.outcomes.some((x) => x.status === "selected"));
318
+ const loop = actionable
319
+ ? await runOpenAIResponses({
320
+ registry,
321
+ executor: runtime.executor,
322
+ runtimeContext: task.runtimeContext,
323
+ userInput: { text: task.text },
324
+ contextBuilder,
325
+ router,
326
+ providerRun,
327
+ deadlineAt,
328
+ controls,
329
+ model: EXECUTION.model,
330
+ client: host.client,
331
+ systemInstructions: PROMPTS.ordinary,
332
+ maxTurns: 3,
333
+ maxToolCalls: 1,
334
+ providerExecution: {
335
+ configuration: host.configuration,
336
+ mock: host.mock,
337
+ maxInputTokens: 8000,
338
+ maxOutputTokens: 1000,
339
+ inputTokenPreflight: host.inputTokenPreflight,
340
+ estimateCost: host.estimateCost,
341
+ maxEstimatedCostPerCall: host.maxCost()
342
+ }
343
+ })
344
+ : {
345
+ status: result.status === "cancelled" ? "cancelled" : "completed",
346
+ toolCalls: [],
347
+ toolResults: [],
348
+ selectedCapabilities: { items: [] },
349
+ errors: []
350
+ };
351
+ const selected = batch?.outcomes[0];
352
+ const call = loop.toolCalls[0];
353
+ const status =
354
+ result.status !== "matched"
355
+ ? "not_performed"
356
+ : (selected?.status ??
357
+ (call
358
+ ? "selected"
359
+ : loop.status === "completed"
360
+ ? "abstained"
361
+ : loop.status === "cancelled"
362
+ ? "cancelled"
363
+ : "unavailable"));
364
+ const selectedId =
365
+ status === "selected" ? (selected?.capabilityId ?? call?.capabilityId) : null;
366
+ const selectedManifest = selectedId
367
+ ? registry.capabilityById.get(selectedId)?.manifest
368
+ : null;
369
+ const observation = {
370
+ case_id: task.id,
371
+ status: result.status,
372
+ actual_mode: result.actualMode,
373
+ eligibility_fingerprint: result.eligibilityFingerprint,
374
+ ...(result.indexFingerprint ? { index_fingerprint: result.indexFingerprint } : {}),
375
+ candidates: result.candidates.map((candidate) => ({
376
+ capability_id: candidate.capabilityId,
377
+ capability_version: candidate.capabilityVersion,
378
+ score: candidate.scores.final
379
+ })),
380
+ latency_ms: performance.now() - started,
381
+ selection: {
382
+ mode: mode.endsWith("dedicated") ? "dedicated" : "native",
383
+ status,
384
+ capability_id: selectedId,
385
+ capability_version: selectedManifest?.version ?? null,
386
+ operation: selectedManifest ? operation(selectedManifest) : null
387
+ }
388
+ };
389
+ return {
390
+ observation,
391
+ missingAccess,
392
+ result,
393
+ selection: batch ?? null,
394
+ loop,
395
+ router,
396
+ toolOutcomes: loop.toolResults.map((outcome) => ({
397
+ capabilityId: outcome.capabilityId,
398
+ status: outcome.status,
399
+ operation: outcome.operation,
400
+ data: outcome.data ?? null,
401
+ approvalRequired: outcome.action?.approvalRequired ?? false,
402
+ reasonCodes: outcome.policy?.reasons?.map((reason) => reason.code) ?? []
403
+ })),
404
+ exported: loop.selectedCapabilities.items.map((item) => ({
405
+ capabilityId: item.capabilityId,
406
+ operations: item.exposedOperations
407
+ })),
408
+ deadlineExceeded:
409
+ observation.latency_ms > 30_000 ||
410
+ loop.errors.some((error) => error.code === "deadline_exceeded")
411
+ };
412
+ }
413
+
414
+ export async function runTaskTrial({
415
+ suite,
416
+ registry,
417
+ trial,
418
+ host,
419
+ ledger,
420
+ index,
421
+ afterSearch
422
+ }) {
423
+ const runId = `case.${hashDiscoveryContent([ledger.fingerprint, trial.key]).slice(7, 39)}`,
424
+ task = projectTask(
425
+ suite,
426
+ suite.cases.find((entry) => entry.id === trial.caseId),
427
+ runId
428
+ );
429
+ const deadlineAt = Date.now() + 30_000,
430
+ providerRun = createAicfProviderRun({
431
+ runId,
432
+ budget: ledger.scope(runId),
433
+ deadlineAt
434
+ });
435
+ const contextBuilder = new DefaultContextBuilder({
436
+ maxCharacters: 16_000,
437
+ hostItems: [
438
+ {
439
+ id: "application-facts",
440
+ kind: "entity",
441
+ title: "Explicit synthetic request facts",
442
+ data: {
443
+ "example.request": task.runtimeContext.facts["example.request"],
444
+ verifiedReadiness: task.runtimeContext.facts["example.readiness"],
445
+ originalCustomerRequest: task.text
446
+ },
447
+ trusted: true,
448
+ visibleToModel: true
449
+ }
450
+ ]
451
+ });
452
+ const original = hashDiscoveryContent(task.runtimeContext),
453
+ source = buildCapabilitySearchCorpus(registry).registrySourceFingerprint;
454
+ const scopedHost = host.forScope({
455
+ runtimeContext: task.runtimeContext,
456
+ registry,
457
+ deadlineAt,
458
+ guard: () =>
459
+ original !== hashDiscoveryContent(task.runtimeContext) ||
460
+ source !== buildCapabilitySearchCorpus(registry).registrySourceFingerprint
461
+ });
462
+ const runtime = createSyntheticRuntime(registry);
463
+ if (trial.stage === "train") {
464
+ const discovery = createCapabilityDiscovery(
465
+ discoveryOptions(registry, trial.mode, trial.k, scopedHost, index, contextBuilder)
466
+ );
467
+ const [result] = await discovery.search({
468
+ tasks: [{ id: task.id, text: task.text }],
469
+ runtimeContext: task.runtimeContext,
470
+ eligibility: task.eligibility,
471
+ providerRun,
472
+ deadlineAt
473
+ });
474
+ return {
475
+ trial,
476
+ result,
477
+ observation: {
478
+ case_id: task.id,
479
+ status: result.status,
480
+ actual_mode: result.actualMode,
481
+ eligibility_fingerprint: result.eligibilityFingerprint,
482
+ ...(result.indexFingerprint
483
+ ? { index_fingerprint: result.indexFingerprint }
484
+ : {}),
485
+ candidates: result.candidates.map((candidate) => ({
486
+ capability_id: candidate.capabilityId,
487
+ capability_version: candidate.capabilityVersion,
488
+ score: candidate.scores.final
489
+ })),
490
+ latency_ms: result.usage.totals.elapsedMs
491
+ },
492
+ run: providerRun.snapshot(),
493
+ executed: [],
494
+ exported: [],
495
+ toolOutcomes: [],
496
+ errors: result.diagnostics.map((item) => item.code)
497
+ };
498
+ }
499
+ const output = await runReadyTask({
500
+ task,
501
+ registry,
502
+ mode: trial.mode,
503
+ k: trial.k,
504
+ host: scopedHost,
505
+ index,
506
+ providerRun,
507
+ runtime,
508
+ deadlineAt,
509
+ contextBuilder,
510
+ afterSearch
511
+ });
512
+ return {
513
+ trial,
514
+ observation: output.observation,
515
+ result: output.result,
516
+ selection: output.selection,
517
+ loopStatus: output.loop.status,
518
+ errors: [
519
+ ...output.loop.errors.map((x) => x.code),
520
+ ...output.result.diagnostics.map((x) => x.code),
521
+ ...(output.selection?.diagnostics.map((x) => x.code) ?? [])
522
+ ],
523
+ exported: output.exported,
524
+ toolOutcomes: output.toolOutcomes,
525
+ executed: runtime.executed,
526
+ deadlineExceeded: output.deadlineExceeded,
527
+ run: providerRun.snapshot()
528
+ };
529
+ }
530
+
531
+ export async function modelJson({
532
+ providerRun,
533
+ host,
534
+ runtimeContext,
535
+ requestId,
536
+ stage,
537
+ instructions,
538
+ input,
539
+ schema,
540
+ outputLimit
541
+ }) {
542
+ const validate = appAjv.compile(schema);
543
+ const request = {
544
+ model: EXECUTION.model,
545
+ input,
546
+ instructions,
547
+ text: {
548
+ format: {
549
+ type: "json_schema",
550
+ name: stage === "planning" ? "application_plan_v2" : "application_response_v2",
551
+ strict: true,
552
+ schema
553
+ }
554
+ },
555
+ max_output_tokens: outputLimit,
556
+ truncation: "disabled"
557
+ };
558
+ const result = await providerRun.attempt({
559
+ stage,
560
+ requestId,
561
+ configuration: host.configuration,
562
+ mock: host.mock,
563
+ deadlineAt: Math.min(providerRun.deadlineAt, Date.now() + 30_000),
564
+ runtimeContext,
565
+ maxInputTokens: 8000,
566
+ maxOutputTokens: outputLimit,
567
+ estimateCost: host.estimateCost,
568
+ maxEstimatedCostPerCall: host.maxCost(8000, outputLimit),
569
+ invoke: async (context) => {
570
+ context.beforeProviderCall();
571
+ await host.inputTokenPreflight({
572
+ request,
573
+ history: [],
574
+ maxInputTokens: 8000,
575
+ configuration: host.configuration,
576
+ ...context
577
+ });
578
+ context.beforeProviderCall();
579
+ const value = await host.client.responses.create(request, {
580
+ signal: context.signal,
581
+ timeout: Math.max(1, context.deadlineAt - Date.now()),
582
+ maxRetries: 0
583
+ });
584
+ return { value, providerAttempts: 1, usage: normalizeUsage(value.usage) };
585
+ },
586
+ validate: (envelope) =>
587
+ envelope.value?.status === "completed" &&
588
+ typeof envelope.value.output_text === "string" &&
589
+ envelope.value.output_text.length <= 32_000
590
+ ? { value: envelope.value.output_text }
591
+ : { code: "invalid_output" }
592
+ });
593
+ if (result.code) throw new Error("Application model stage unavailable.");
594
+ let parsed;
595
+ try {
596
+ parsed = JSON.parse(result.value);
597
+ } catch {
598
+ throw Object.assign(new Error("Application model JSON is invalid."), {
599
+ applicationOutput: result.value.slice(0, 4000)
600
+ });
601
+ }
602
+ if (!validate(parsed))
603
+ throw Object.assign(new Error("Application model JSON is invalid."), {
604
+ applicationOutput: result.value.slice(0, 4000)
605
+ });
606
+ return parsed;
607
+ }
608
+
609
+ export { runWorkflowTrial } from "./workflow-application.mjs";
610
+
611
+ export function validateIndex(index, registry, host) {
612
+ return validateCapabilityEmbeddingIndex(index, {
613
+ corpus: buildCapabilitySearchCorpus(registry),
614
+ configuration: host.embeddingConfiguration,
615
+ mock: host.mock,
616
+ limits: DISCOVERY_STANDARD_PROFILE.indexLimits
617
+ });
618
+ }