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,84 @@
1
+ import type { DiscoveryEvaluationSuite } from "../generated/manifest-types.js";
2
+ import type { ProviderUsage } from "../runtime/provider-types.js";
3
+ import type { ManifestRegistry } from "../types.js";
4
+ import type { DiscoveryEvaluationDiagnostic } from "./evaluation-validation.js";
5
+ export type { DiscoveryEvaluationSuite, DiscoveryEvaluationObservations } from "../generated/manifest-types.js";
6
+ export type { DiscoveryEvaluationDiagnostic } from "./evaluation-validation.js";
7
+ export interface DiscoveryEvaluationRate {
8
+ numerator: number;
9
+ denominator: number;
10
+ value: number | null;
11
+ }
12
+ export interface DiscoveryEvaluationDistribution {
13
+ count: number;
14
+ minimum: number | null;
15
+ mean: number | null;
16
+ p95: number | null;
17
+ maximum: number | null;
18
+ }
19
+ export interface DiscoveryEvaluationReport {
20
+ suiteFingerprint: string;
21
+ scopeFingerprint: string;
22
+ complete: boolean;
23
+ semanticQualityQualified: false;
24
+ counts: {
25
+ expected: number;
26
+ observed: number;
27
+ missing: number;
28
+ byPartition: Record<string, number>;
29
+ byDomain: Record<string, number>;
30
+ byCohort: Record<string, number>;
31
+ };
32
+ retrieval: {
33
+ k: number;
34
+ compatibleRecallAtK: DiscoveryEvaluationRate;
35
+ topOnePrecision: DiscoveryEvaluationRate;
36
+ noMatchFalsePositiveRate: DiscoveryEvaluationRate;
37
+ shortlistSize: DiscoveryEvaluationDistribution;
38
+ outcomes: Record<string, number>;
39
+ forbiddenCandidateCases: number;
40
+ policyViolationCases: number;
41
+ readToMutationCases: number;
42
+ };
43
+ selection: {
44
+ outcomes: Record<string, number>;
45
+ compatibleAccuracy: DiscoveryEvaluationRate;
46
+ abstentionRate: DiscoveryEvaluationRate;
47
+ coverage: DiscoveryEvaluationRate;
48
+ noMatchFalseSelectionRate: DiscoveryEvaluationRate;
49
+ forbiddenChoices: number;
50
+ policyViolations: number;
51
+ readToMutationChoices: number;
52
+ };
53
+ latencyMs: DiscoveryEvaluationDistribution;
54
+ accountingComplete: boolean;
55
+ usageComplete: boolean;
56
+ usage: ProviderUsage;
57
+ provenance: {
58
+ mockAttempts: number;
59
+ liveAttempts: number;
60
+ pendingAttempts: number;
61
+ };
62
+ }
63
+ export type DiscoveryEvaluationResult = {
64
+ valid: true;
65
+ report: Readonly<DiscoveryEvaluationReport>;
66
+ diagnostics: readonly [];
67
+ } | {
68
+ valid: false;
69
+ diagnostics: readonly DiscoveryEvaluationDiagnostic[];
70
+ };
71
+ export interface EvaluateCapabilityDiscoveryRequest {
72
+ suite: unknown;
73
+ registry: ManifestRegistry;
74
+ observations: unknown;
75
+ /** Explicit expected cases; omitted means the entire frozen suite. Missing observations remain missing. */
76
+ caseIds?: readonly string[];
77
+ }
78
+ /** Includes authored cases, labels, partitions and capability content; excludes no suite fields. */
79
+ export declare function fingerprintDiscoveryEvaluationSuite(value: DiscoveryEvaluationSuite): string;
80
+ /** Semantic fixture checks used by the CLI without executing retrieval or providers. */
81
+ export declare function validateDiscoveryEvaluationSuite(value: unknown, registry?: ManifestRegistry): readonly DiscoveryEvaluationDiagnostic[];
82
+ /** Scores observations only. It never calls a ranker, model, embedding client, or executor. */
83
+ export declare function evaluateCapabilityDiscovery(request: EvaluateCapabilityDiscoveryRequest): DiscoveryEvaluationResult;
84
+ //# sourceMappingURL=evaluation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluation.d.ts","sourceRoot":"","sources":["../../src/discovery/evaluation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,310 @@
1
+ import { buildRegistry } from "../registry.js";
2
+ import { validateRuntimeContext } from "../runtime/context.js";
3
+ import { deepFreeze } from "../runtime/bounded-json.js";
4
+ import { aggregateProviderUsage, usageQuantities, USAGE_QUANTITIES } from "../runtime/provider-usage.js";
5
+ import { validateManifests } from "../validator.js";
6
+ import { captureEligibility } from "./bindings.js";
7
+ import { buildCapabilitySearchCorpus, registrySourceFingerprint } from "./corpus.js";
8
+ import { resolveDiscoveryConfiguration } from "./configuration.js";
9
+ import { DiscoveryError } from "./diagnostics.js";
10
+ import { hashDiscoveryContent } from "./fingerprint.js";
11
+ import { evaluationObservationsSnapshot, evaluationSuiteSnapshot } from "./evaluation-validation.js";
12
+ import { retrievalPolicyFingerprint } from "./retrieval-policy.js";
13
+ /** Includes authored cases, labels, partitions and capability content; excludes no suite fields. */
14
+ export function fingerprintDiscoveryEvaluationSuite(value) {
15
+ const suite = evaluationSuiteSnapshot(value);
16
+ if (!suite)
17
+ throw new DiscoveryError({ code: "invalid_input", message: "A valid discovery evaluation suite is required." });
18
+ return hashDiscoveryContent({ kind: "discovery_evaluation_suite", version: "1.0", suite });
19
+ }
20
+ function loadedSuite(suite) {
21
+ return suite.capabilities.map(manifest => ({ kind: "capability", path: `synthetic/${manifest.id}.yaml`,
22
+ absolutePath: `/synthetic/${manifest.id}.yaml`, manifest: manifest }));
23
+ }
24
+ function routeFor(suite, entry, registry) {
25
+ const context = suite.contexts[entry.context_id];
26
+ const runtimeContext = context.runtime_context;
27
+ validateRuntimeContext(runtimeContext);
28
+ if (!Array.isArray(runtimeContext.subject.permissions) || !runtimeContext.subject.permissions.every(x => typeof x === "string")
29
+ || !runtimeContext.autonomy || !["low", "medium", "high", "critical"].includes(runtimeContext.autonomy.maxRiskTier))
30
+ throw new Error("context");
31
+ return { ...context.eligibility, registry, userInput: { text: entry.fragments.map(fragment => fragment.text).join("\n") },
32
+ builtContext: { runtimeContext, items: [], modelContextText: "", redactions: [], warnings: [] } };
33
+ }
34
+ /** Semantic fixture checks used by the CLI without executing retrieval or providers. */
35
+ export function validateDiscoveryEvaluationSuite(value, registry) {
36
+ const suite = evaluationSuiteSnapshot(value);
37
+ if (!suite)
38
+ return [{ code: "invalid_suite_schema" }];
39
+ const errors = [];
40
+ const add = (code, caseId) => { if (errors.length < 64)
41
+ errors.push({ code, ...(caseId ? { caseId } : {}) }); };
42
+ try {
43
+ const definitions = loadedSuite(suite);
44
+ if (!validateManifests(definitions).valid)
45
+ return [{ code: "invalid_suite_capabilities" }];
46
+ const authoredRegistry = buildRegistry(definitions);
47
+ if (registry && registrySourceFingerprint(registry) !== registrySourceFingerprint(authoredRegistry))
48
+ return [{ code: "suite_registry_mismatch" }];
49
+ registry ??= authoredRegistry;
50
+ for (const context of Object.values(suite.contexts)) {
51
+ try {
52
+ validateRuntimeContext(context.runtime_context);
53
+ }
54
+ catch {
55
+ add("invalid_context");
56
+ }
57
+ for (const id of [...context.eligibility?.includeCapabilityIds ?? [], ...context.eligibility?.excludeCapabilityIds ?? []]) {
58
+ if (!registry.capabilityById.has(id))
59
+ add("unknown_eligibility_capability");
60
+ }
61
+ }
62
+ const ids = new Set(), families = new Map();
63
+ for (const entry of suite.cases) {
64
+ if (ids.has(entry.id))
65
+ add("duplicate_case", entry.id);
66
+ ids.add(entry.id);
67
+ if (families.has(entry.family_id) && families.get(entry.family_id) !== entry.partition)
68
+ add("family_partition_leak", entry.id);
69
+ families.set(entry.family_id, entry.partition);
70
+ if (!Object.hasOwn(suite.contexts, entry.context_id)) {
71
+ add("unknown_context", entry.id);
72
+ continue;
73
+ }
74
+ if (entry.compatible_ids.some(id => entry.forbidden_ids.includes(id))
75
+ || entry.compatible_ids.length && entry.forbidden_operations.includes(entry.expected_operation)
76
+ || entry.cohorts.includes("true_no_match") && entry.compatible_ids.length)
77
+ add("contradictory_labels", entry.id);
78
+ let eligible;
79
+ try {
80
+ eligible = new Set(captureEligibility(routeFor(suite, entry, registry)).eligible.map(x => x.manifest.id));
81
+ }
82
+ catch {
83
+ add("invalid_context", entry.id);
84
+ continue;
85
+ }
86
+ for (const id of [...entry.compatible_ids, ...entry.forbidden_ids]) {
87
+ const capability = registry.capabilityById.get(id)?.manifest;
88
+ if (!capability) {
89
+ add("unknown_capability", entry.id);
90
+ continue;
91
+ }
92
+ if (entry.compatible_ids.includes(id) && (!eligible.has(id) || operationFor(capability) !== entry.expected_operation
93
+ || capability.lifecycle.commit || capability.capability_type === "write_commit"))
94
+ add("invalid_compatible_capability", entry.id);
95
+ }
96
+ }
97
+ }
98
+ catch {
99
+ add("invalid_suite_bindings");
100
+ }
101
+ return errors;
102
+ }
103
+ const operationFor = (capability) => capability.lifecycle.commit
104
+ || capability.capability_type === "write_commit" ? "commit" : capability.lifecycle.prepare ? "prepare" : "read";
105
+ const rate = (numerator, denominator) => ({ numerator, denominator, value: denominator ? numerator / denominator : null });
106
+ function distribution(values) {
107
+ const sorted = [...values].sort((a, b) => a - b);
108
+ let mean = 0;
109
+ values.forEach((value, index) => { mean += (value - mean) / (index + 1); });
110
+ return { count: values.length, minimum: sorted[0] ?? null, maximum: sorted.at(-1) ?? null,
111
+ mean: values.length ? mean : null,
112
+ p95: sorted[Math.ceil(sorted.length * 0.95) - 1] ?? null };
113
+ }
114
+ /** Scores observations only. It never calls a ranker, model, embedding client, or executor. */
115
+ export function evaluateCapabilityDiscovery(request) {
116
+ const errors = [...validateDiscoveryEvaluationSuite(request.suite, request.registry)];
117
+ const suite = evaluationSuiteSnapshot(request.suite);
118
+ const observations = evaluationObservationsSnapshot(request.observations);
119
+ if (!observations)
120
+ errors.push({ code: "invalid_observations_schema" });
121
+ const caseIds = request.caseIds;
122
+ if (caseIds !== undefined && (!Array.isArray(caseIds) || caseIds.length > (suite?.cases.length ?? 0) || !Array.from(caseIds).every(id => typeof id === "string")
123
+ || new Set(caseIds).size !== caseIds.length || caseIds.some(id => !suite?.cases.some(entry => entry.id === id)))) {
124
+ errors.push({ code: "invalid_evaluation_scope" });
125
+ }
126
+ if (errors.length || !suite || !observations)
127
+ return { valid: false, diagnostics: deepFreeze(errors) };
128
+ try {
129
+ return evaluate(suite, observations, request.registry, caseIds);
130
+ }
131
+ catch {
132
+ return { valid: false, diagnostics: [{ code: "invalid_evaluation_bindings" }] };
133
+ }
134
+ }
135
+ function evaluate(suite, observations, registry, caseIds) {
136
+ const errors = [];
137
+ const add = (code, caseId) => { if (errors.length < 64)
138
+ errors.push({ code, ...(caseId ? { caseId } : {}) }); };
139
+ const configuration = resolveDiscoveryConfiguration(observations.configuration);
140
+ if (hashDiscoveryContent(configuration) !== hashDiscoveryContent(observations.configuration))
141
+ add("unresolved_configuration");
142
+ const corpus = buildCapabilitySearchCorpus(registry);
143
+ const suiteFingerprint = fingerprintDiscoveryEvaluationSuite(suite);
144
+ if (observations.suite_id !== suite.id || observations.suite_fingerprint !== suiteFingerprint
145
+ || observations.registry_source_fingerprint !== corpus.registrySourceFingerprint || observations.corpus_fingerprint !== corpus.corpusFingerprint
146
+ || observations.retrieval_policy_fingerprint !== retrievalPolicyFingerprint(configuration, observations.custom_ranker_version))
147
+ add("observation_binding_mismatch");
148
+ const definitions = new Map(suite.cases.map(entry => [entry.id, entry]));
149
+ const scope = new Set(caseIds ?? suite.cases.map(entry => entry.id));
150
+ const expectedCases = suite.cases.filter(entry => scope.has(entry.id));
151
+ const scopeFingerprint = hashDiscoveryContent({ kind: "discovery_evaluation_scope", version: "1.0", suiteFingerprint,
152
+ caseIds: [...scope].sort() });
153
+ const seen = new Set();
154
+ const retrievalOutcomes = { matched: 0, no_match: 0, unavailable: 0, cancelled: 0 };
155
+ const selectionOutcomes = { selected: 0, abstained: 0, unavailable: 0, invalid_output: 0, cancelled: 0, not_performed: 0 };
156
+ const byPartition = Object.create(null), byDomain = Object.create(null), byCohort = Object.create(null);
157
+ let hits = 0, topHits = 0, nonempty = 0, noMatchFalsePositives = 0;
158
+ let forbiddenCandidates = 0, policyCandidateCases = 0, readMutationCases = 0;
159
+ let selectedMatched = 0, correctSelected = 0, covered = 0, answerableMatched = 0, submitted = 0;
160
+ let forbiddenChoices = 0, policyChoices = 0, readMutationChoices = 0;
161
+ let noMatchSelections = 0;
162
+ const sizes = [], latencies = [];
163
+ for (const observed of observations.cases) {
164
+ const entry = definitions.get(observed.case_id);
165
+ if (!entry) {
166
+ add("foreign_observation", observed.case_id);
167
+ continue;
168
+ }
169
+ if (!scope.has(entry.id)) {
170
+ add("observation_outside_scope", entry.id);
171
+ continue;
172
+ }
173
+ if (seen.has(entry.id)) {
174
+ add("duplicate_observation", entry.id);
175
+ continue;
176
+ }
177
+ seen.add(entry.id);
178
+ const eligibility = captureEligibility(routeFor(suite, entry, registry));
179
+ const eligible = new Set(eligibility.eligible.map(x => x.manifest.id));
180
+ if (observed.eligibility_fingerprint !== eligibility.fingerprint)
181
+ add("eligibility_binding_mismatch", entry.id);
182
+ if ((observed.status === "matched") !== !!observed.candidates.length || observed.candidates.length > configuration.limits.maxCandidates
183
+ || (observed.status === "unavailable" || observed.status === "cancelled") !== (observed.actual_mode === null)
184
+ || configuration.mode === "lexical" && observed.actual_mode === "hybrid"
185
+ || configuration.mode === "hybrid" && observed.actual_mode === "lexical" && configuration.failurePolicy !== "lexical_fallback"
186
+ || observed.actual_mode === "hybrid" && observed.status === "matched" && !observed.index_fingerprint)
187
+ add("invalid_retrieval_observation", entry.id);
188
+ const candidateIds = new Set();
189
+ let forbidden = false, policy = false, readMutation = false;
190
+ for (const candidate of observed.candidates) {
191
+ const manifest = registry.capabilityById.get(candidate.capability_id)?.manifest;
192
+ if (!manifest || manifest.version !== candidate.capability_version || candidateIds.has(candidate.capability_id)) {
193
+ add("invalid_candidate_binding", entry.id);
194
+ continue;
195
+ }
196
+ candidateIds.add(candidate.capability_id);
197
+ const operation = operationFor(manifest);
198
+ forbidden ||= entry.forbidden_ids.includes(manifest.id) || entry.forbidden_operations.includes(operation);
199
+ policy ||= !eligible.has(manifest.id) || operation === "commit";
200
+ readMutation ||= entry.expected_operation === "read" && operation !== "read";
201
+ }
202
+ if (forbidden)
203
+ forbiddenCandidates++;
204
+ if (policy)
205
+ policyCandidateCases++;
206
+ if (readMutation)
207
+ readMutationCases++;
208
+ retrievalOutcomes[observed.status]++;
209
+ if (observed.candidates.length)
210
+ nonempty++;
211
+ if (entry.compatible_ids.some(id => candidateIds.has(id)))
212
+ hits++;
213
+ if (observed.candidates[0] && entry.compatible_ids.includes(observed.candidates[0].capability_id))
214
+ topHits++;
215
+ if (entry.cohorts.includes("true_no_match") && candidateIds.size)
216
+ noMatchFalsePositives++;
217
+ sizes.push(observed.candidates.length);
218
+ latencies.push(observed.latency_ms);
219
+ byPartition[entry.partition] = (byPartition[entry.partition] ?? 0) + 1;
220
+ byDomain[entry.domain] = (byDomain[entry.domain] ?? 0) + 1;
221
+ for (const cohort of entry.cohorts)
222
+ byCohort[cohort] = (byCohort[cohort] ?? 0) + 1;
223
+ const selection = observed.selection;
224
+ const answerable = entry.compatible_ids.length > 0;
225
+ if (answerable && observed.status === "matched")
226
+ answerableMatched++;
227
+ const status = selection?.status ?? "not_performed";
228
+ selectionOutcomes[status]++;
229
+ if (status !== "not_performed") {
230
+ submitted++;
231
+ if (observed.status !== "matched")
232
+ add("selection_without_shortlist", entry.id);
233
+ }
234
+ if (selection?.status === "selected") {
235
+ const manifest = registry.capabilityById.get(selection.capability_id)?.manifest;
236
+ if (!manifest || !candidateIds.has(manifest.id) || manifest.version !== selection.capability_version
237
+ || operationFor(manifest) !== selection.operation) {
238
+ add("invalid_selection_binding", entry.id);
239
+ continue;
240
+ }
241
+ if (answerable) {
242
+ selectedMatched++;
243
+ covered++;
244
+ if (entry.compatible_ids.includes(manifest.id))
245
+ correctSelected++;
246
+ }
247
+ if (entry.cohorts.includes("true_no_match"))
248
+ noMatchSelections++;
249
+ if (entry.forbidden_ids.includes(manifest.id) || entry.forbidden_operations.includes(selection.operation))
250
+ forbiddenChoices++;
251
+ if (!eligible.has(manifest.id) || selection.operation === "commit")
252
+ policyChoices++;
253
+ if (entry.expected_operation === "read" && selection.operation !== "read")
254
+ readMutationChoices++;
255
+ }
256
+ }
257
+ const attempts = new Map();
258
+ for (const attempt of observations.attempts) {
259
+ const key = JSON.stringify([attempt.run_id, attempt.attempt_id]);
260
+ const previous = attempts.get(key);
261
+ if (previous && hashDiscoveryContent(previous) !== hashDiscoveryContent(attempt))
262
+ add("conflicting_attempt_receipt");
263
+ attempts.set(key, attempt);
264
+ if (attempt.completed_responses > attempt.provider_attempts || attempt.retry_attempts > attempt.provider_attempts
265
+ || attempt.repair_attempts > attempt.provider_attempts)
266
+ add("invalid_attempt_counts");
267
+ }
268
+ if (errors.length)
269
+ return { valid: false, diagnostics: deepFreeze(errors) };
270
+ const stages = [...attempts.values()].map(attempt => ({
271
+ attemptId: JSON.stringify([attempt.run_id, attempt.attempt_id]), stage: attempt.stage, configuration: attempt.configuration,
272
+ mock: attempt.mock, pending: attempt.pending, outcome: attempt.outcome, cacheHits: 0,
273
+ providerAttempts: attempt.provider_attempts, completedResponses: attempt.completed_responses,
274
+ retryAttempts: attempt.retry_attempts, repairAttempts: attempt.repair_attempts, elapsedMs: attempt.elapsed_ms,
275
+ ...usageQuantities(attempt.usage, attempt.provider_attempts === 0)
276
+ }));
277
+ const elapsed = stages.reduce((sum, stage) => sum + stage.elapsedMs, 0);
278
+ if (!Number.isFinite(elapsed)
279
+ || ["providerAttempts", "completedResponses", "retryAttempts", "repairAttempts"].some(key => !Number.isSafeInteger(stages.reduce((sum, stage) => sum + stage[key], 0)))
280
+ || USAGE_QUANTITIES.some(key => {
281
+ const total = stages.reduce((sum, stage) => sum + stage[key].knownSubtotal, 0);
282
+ return !Number.isFinite(total) || key !== "estimatedCost" && !Number.isSafeInteger(total);
283
+ }))
284
+ return { valid: false, diagnostics: [{ code: "invalid_accounting_totals" }] };
285
+ let usage = aggregateProviderUsage(stages, elapsed);
286
+ if (!observations.usage_complete) {
287
+ const totals = { ...usage.totals };
288
+ for (const key of USAGE_QUANTITIES)
289
+ totals[key] = { total: null, complete: false, knownSubtotal: totals[key].knownSubtotal };
290
+ usage = deepFreeze({ stages: usage.stages, totals });
291
+ }
292
+ // Missing cases stay in recall/no-match denominators; partial runs cannot inflate them.
293
+ const answerable = expectedCases.filter(entry => entry.compatible_ids.length).length;
294
+ const trueNoMatch = expectedCases.filter(entry => entry.cohorts.includes("true_no_match")).length;
295
+ return { valid: true, diagnostics: [], report: deepFreeze({
296
+ suiteFingerprint, scopeFingerprint, complete: seen.size === expectedCases.length, semanticQualityQualified: false,
297
+ counts: { expected: expectedCases.length, observed: seen.size, missing: expectedCases.length - seen.size, byPartition, byDomain, byCohort },
298
+ retrieval: { k: configuration.limits.maxCandidates, compatibleRecallAtK: rate(hits, answerable), topOnePrecision: rate(topHits, nonempty),
299
+ noMatchFalsePositiveRate: rate(noMatchFalsePositives, trueNoMatch), shortlistSize: distribution(sizes), outcomes: retrievalOutcomes,
300
+ forbiddenCandidateCases: forbiddenCandidates, policyViolationCases: policyCandidateCases, readToMutationCases: readMutationCases },
301
+ selection: { outcomes: selectionOutcomes, compatibleAccuracy: rate(correctSelected, selectedMatched),
302
+ abstentionRate: rate(selectionOutcomes.abstained, submitted), coverage: rate(covered, answerableMatched),
303
+ noMatchFalseSelectionRate: rate(noMatchSelections, trueNoMatch),
304
+ forbiddenChoices, policyViolations: policyChoices, readToMutationChoices: readMutationChoices },
305
+ latencyMs: distribution(latencies), accountingComplete: observations.usage_complete,
306
+ usageComplete: observations.usage_complete && stages.every(stage => !stage.pending) && USAGE_QUANTITIES.every(key => usage.totals[key].complete), usage,
307
+ provenance: { mockAttempts: stages.filter(stage => stage.mock).reduce((sum, x) => sum + x.providerAttempts, 0),
308
+ liveAttempts: stages.filter(stage => !stage.mock).reduce((sum, x) => sum + x.providerAttempts, 0), pendingAttempts: stages.filter(stage => stage.pending).length }
309
+ }) };
310
+ }
@@ -0,0 +1,14 @@
1
+ import type { CapabilityRouteRequest } from "../runtime/types.js";
2
+ import type { CapabilityDiscoveryResult, CapabilitySelectionBatchResult, DiscoveryRouteResult } from "./types.js";
3
+ export declare function validateRouterLimit(limit: number | undefined): void;
4
+ /** A task-local selector decision narrows an already validated shortlist. */
5
+ export declare function exportSelectedResult(request: CapabilityRouteRequest & {
6
+ signal?: AbortSignal;
7
+ deadlineAt?: number;
8
+ }, original: CapabilityDiscoveryResult, batch: CapabilitySelectionBatchResult, source: string, current?: boolean): DiscoveryRouteResult;
9
+ /** Shared final gate for fresh retrieval and request-bound shortlist reuse. */
10
+ export declare function exportDiscoveryResult(request: CapabilityRouteRequest & {
11
+ signal?: AbortSignal;
12
+ deadlineAt?: number;
13
+ }, original: CapabilityDiscoveryResult, sourceFingerprint: string, bindingCurrent?: boolean): DiscoveryRouteResult;
14
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/discovery/export.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAKlE,OAAO,KAAK,EAAE,yBAAyB,EAAE,8BAA8B,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAInE;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,sBAAsB,GAAG;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/E,QAAQ,EAAE,yBAAyB,EAAE,KAAK,EAAE,8BAA8B,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,UAAO,GACzG,oBAAoB,CAetB;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,sBAAsB,GAAG;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/E,QAAQ,EAAE,yBAAyB,EACnC,iBAAiB,EAAE,MAAM,EACzB,cAAc,UAAO,GACpB,oBAAoB,CAkDtB"}
@@ -0,0 +1,81 @@
1
+ import { captureEligibility } from "./bindings.js";
2
+ import { registrySourceFingerprint } from "./corpus.js";
3
+ import { discoveryStopReason } from "./discoverer.js";
4
+ import { DiscoveryError } from "./diagnostics.js";
5
+ export function validateRouterLimit(limit) {
6
+ if (limit !== undefined && (!Number.isInteger(limit) || limit < 1 || limit > 20)) {
7
+ throw new DiscoveryError({ code: "invalid_input", message: "maxCapabilities must be an integer from 1 through 20." });
8
+ }
9
+ }
10
+ /** A task-local selector decision narrows an already validated shortlist. */
11
+ export function exportSelectedResult(request, original, batch, source, current = true) {
12
+ const exported = exportDiscoveryResult(request, original, source, current);
13
+ const outcome = batch.outcomes.find(item => item.queryId === original.queryId);
14
+ const selected = outcome?.status === "selected" && exported.discovery[0]?.status === "matched"
15
+ && request.registry.capabilityById.get(outcome.capabilityId)?.manifest.version === outcome.capabilityVersion
16
+ ? outcome.capabilityId : undefined;
17
+ const items = exported.slice.items.filter(item => item.capabilityId === selected).map(item => ({ ...item,
18
+ reasons: ["Selected for this task by the explicitly configured selector; execution authorization remains required."] }));
19
+ return { ...exported, selection: batch.outcomes, selectionBatch: batch, slice: {
20
+ items, excluded: [...exported.slice.excluded, ...exported.slice.items.filter(item => item.capabilityId !== selected)
21
+ .map(item => ({ capabilityId: item.capabilityId, reason: "Capability was not selected for this task." }))],
22
+ warnings: items.length ? exported.slice.warnings : [...exported.slice.warnings, {
23
+ code: "selection_" + (outcome?.status ?? "not_submitted"), message: "Selection did not provide a current actionable capability for this task."
24
+ }]
25
+ } };
26
+ }
27
+ /** Shared final gate for fresh retrieval and request-bound shortlist reuse. */
28
+ export function exportDiscoveryResult(request, original, sourceFingerprint, bindingCurrent = true) {
29
+ let result = original;
30
+ let eligibility;
31
+ let current = false;
32
+ try {
33
+ eligibility = captureEligibility(request);
34
+ current = bindingCurrent && eligibility.fingerprint === result.eligibilityFingerprint
35
+ && registrySourceFingerprint(request.registry) === sourceFingerprint;
36
+ }
37
+ catch { /* Invalidated live registries cannot yield a tool slice. */ }
38
+ const stop = discoveryStopReason(request);
39
+ if (stop || (!current && result.status === "matched")) {
40
+ const code = stop ?? "stale_binding";
41
+ result = {
42
+ ...result, status: stop ? "cancelled" : "unavailable", actualMode: null, candidates: [],
43
+ diagnostics: [{ code, queryId: result.queryId, message: stop
44
+ ? "Discovery was cancelled or its deadline elapsed." : "Discovery bindings changed before tool export." }]
45
+ };
46
+ delete result.indexFingerprint;
47
+ }
48
+ const candidates = result.status === "matched" ? result.candidates.slice(0, request.maxCapabilities ?? result.candidates.length) : [];
49
+ const selected = new Set(candidates.map(candidate => candidate.capabilityId));
50
+ const excluded = [...(eligibility?.excluded ?? [])];
51
+ for (const entry of eligibility?.eligible ?? []) {
52
+ if (!selected.has(entry.manifest.id))
53
+ excluded.push({
54
+ capabilityId: entry.manifest.id, reason: "Capability was not included in the retrieval shortlist."
55
+ });
56
+ }
57
+ const warnings = result.status === "matched" ? [] : [{
58
+ code: "discovery_" + result.status,
59
+ message: result.status === "no_match" ? "Discovery found no eligible candidates meeting the retrieval policy."
60
+ : result.status === "cancelled" ? "Discovery was cancelled or its deadline elapsed."
61
+ : "Discovery is unavailable; no tools were shortlisted."
62
+ }];
63
+ if (result.actualMode === "lexical" && result.degradedReason)
64
+ warnings.push({
65
+ code: "discovery_lexical_fallback", message: "Discovery used the configured whole-query lexical fallback policy."
66
+ });
67
+ return {
68
+ discovery: [result],
69
+ slice: {
70
+ items: candidates.map(candidate => {
71
+ const manifest = request.registry.capabilityById.get(candidate.capabilityId).manifest;
72
+ return {
73
+ capabilityId: candidate.capabilityId, score: candidate.scores.final,
74
+ exposedOperations: manifest.lifecycle.prepare ? ["select", "prepare"] : ["select"],
75
+ reasons: ["Included by the retrieval policy; ordinary tool selection is required."]
76
+ };
77
+ }),
78
+ excluded, warnings
79
+ }
80
+ };
81
+ }
@@ -0,0 +1,82 @@
1
+ import type { AicfProviderRun } from "../runtime/provider-types.js";
2
+ import type { AicfCapabilityRouter, AicfContextBuilder, AicfRuntimeContext, CapabilityRouteRequest } from "../runtime/types.js";
3
+ import type { ManifestRegistry } from "../types.js";
4
+ import type { DiscoveryBudgetScope } from "./budget.js";
5
+ import type { EmbeddingExecutionOptions, EmbeddingIndexLimits } from "./embedding-types.js";
6
+ import type { CapabilitySelectRequest } from "./selection-types.js";
7
+ import type { CapabilityDiscoveryResult, CapabilityLexicalRanker, CapabilitySelectionBatchResult, DiscoveryLimits, DiscoveryRouteResult, EmbeddingClient, HybridDiscoveryConfiguration } from "./types.js";
8
+ export declare const DISCOVERY_STANDARD_PROFILE: {
9
+ policyVersion: string;
10
+ timeoutMs: number;
11
+ weights: {
12
+ semantic: number;
13
+ lexical: number;
14
+ };
15
+ failurePolicy: "unavailable";
16
+ indexLimits: {
17
+ maxArtifactBytes: number;
18
+ maxEntries: number;
19
+ maxVectorDimension: number;
20
+ };
21
+ maxCharactersPerText: number;
22
+ maxCharactersPerCall: number;
23
+ };
24
+ /** @inline */
25
+ interface CapabilityDiscoveryOptionsBase {
26
+ registry: ManifestRegistry;
27
+ contextBuilder?: AicfContextBuilder;
28
+ ranker?: CapabilityLexicalRanker;
29
+ policyVersion?: string;
30
+ timeoutMs?: number;
31
+ limits?: Partial<DiscoveryLimits>;
32
+ aliasWeight?: number;
33
+ minRetrievalScore?: number;
34
+ }
35
+ export interface CapabilityDiscoveryEmbeddingOptions {
36
+ client: EmbeddingClient;
37
+ index: unknown;
38
+ maxInputTokens: number;
39
+ indexLimits?: Partial<EmbeddingIndexLimits>;
40
+ maxCharactersPerText?: number;
41
+ maxCharactersPerCall?: number;
42
+ maxEstimatedCostPerCall?: number;
43
+ estimateCost?: EmbeddingExecutionOptions["estimateCost"];
44
+ }
45
+ export type CapabilityDiscoveryOptions = CapabilityDiscoveryOptionsBase & ({
46
+ mode?: "lexical";
47
+ embedding?: never;
48
+ weights?: never;
49
+ failurePolicy?: never;
50
+ } | {
51
+ mode: "hybrid";
52
+ embedding: CapabilityDiscoveryEmbeddingOptions;
53
+ weights?: HybridDiscoveryConfiguration["weights"];
54
+ failurePolicy?: HybridDiscoveryConfiguration["failurePolicy"];
55
+ });
56
+ export type CapabilityDiscoveryEligibility = Omit<CapabilityRouteRequest, "registry" | "builtContext" | "userInput" | "controls">;
57
+ export interface CapabilitySearchRequest {
58
+ providerRun?: AicfProviderRun;
59
+ tasks: readonly {
60
+ id: string;
61
+ text: string;
62
+ }[];
63
+ runtimeContext: AicfRuntimeContext;
64
+ controls?: CapabilityRouteRequest["controls"];
65
+ eligibility?: CapabilityDiscoveryEligibility;
66
+ signal?: AbortSignal;
67
+ deadlineAt?: number;
68
+ budget?: DiscoveryBudgetScope;
69
+ }
70
+ export interface CapabilityResultRouter extends AicfCapabilityRouter {
71
+ routeWithDiagnostics(request: CapabilityRouteRequest): DiscoveryRouteResult;
72
+ }
73
+ export interface CapabilityDiscovery {
74
+ search(request: CapabilitySearchRequest): Promise<readonly CapabilityDiscoveryResult[]>;
75
+ select(request: CapabilitySelectRequest): Promise<CapabilitySelectionBatchResult>;
76
+ routerFor(result: CapabilityDiscoveryResult): CapabilityResultRouter;
77
+ routerFor(batch: CapabilitySelectionBatchResult, queryId: string): CapabilityResultRouter;
78
+ }
79
+ /** Simple application-driven search. Model choice and execution stay in the ordinary runtime. */
80
+ export declare function createCapabilityDiscovery(options: CapabilityDiscoveryOptions): CapabilityDiscovery;
81
+ export {};
82
+ //# sourceMappingURL=facade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facade.d.ts","sourceRoot":"","sources":["../../src/discovery/facade.ts"],"names":[],"mappings":"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"}