ai-capability-framework 1.0.0-rc.1

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 (115) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/CONTRIBUTING.md +56 -0
  3. package/LICENSE +21 -0
  4. package/README.md +198 -0
  5. package/SECURITY.md +29 -0
  6. package/conformance/invalid/duplicate/capabilities/conformance.duplicate.one.yaml +55 -0
  7. package/conformance/invalid/duplicate/capabilities/conformance.duplicate.two.yaml +55 -0
  8. package/conformance/invalid/eval-results/conformance.results.failing.json +15 -0
  9. package/conformance/invalid/missing-reference/capabilities/conformance.missing_reference.prepare.yaml +58 -0
  10. package/conformance/invalid/schema/capabilities/conformance.invalid.missing_required.yaml +3 -0
  11. package/conformance/valid/capabilities/conformance.note.get.yaml +82 -0
  12. package/conformance/valid/decisions/conformance.note.get.denied_missing_permission.json +13 -0
  13. package/conformance/valid/entities/Note.yaml +18 -0
  14. package/conformance/valid/eval-results/conformance.results.passing.json +19 -0
  15. package/conformance/valid/evals/conformance.note.get.valid.yaml +33 -0
  16. package/conformance/valid/openai/context.no_permissions.json +6 -0
  17. package/dist/adapter-common.d.ts +62 -0
  18. package/dist/adapter-common.d.ts.map +1 -0
  19. package/dist/adapter-common.js +453 -0
  20. package/dist/ai-sdk.d.ts +5 -0
  21. package/dist/ai-sdk.d.ts.map +1 -0
  22. package/dist/ai-sdk.js +71 -0
  23. package/dist/anthropic-claude.d.ts +5 -0
  24. package/dist/anthropic-claude.d.ts.map +1 -0
  25. package/dist/anthropic-claude.js +62 -0
  26. package/dist/cli.d.ts +11 -0
  27. package/dist/cli.d.ts.map +1 -0
  28. package/dist/cli.js +360 -0
  29. package/dist/decision.d.ts +6 -0
  30. package/dist/decision.d.ts.map +1 -0
  31. package/dist/decision.js +237 -0
  32. package/dist/eval-runner.d.ts +6 -0
  33. package/dist/eval-runner.d.ts.map +1 -0
  34. package/dist/eval-runner.js +372 -0
  35. package/dist/gemini.d.ts +5 -0
  36. package/dist/gemini.d.ts.map +1 -0
  37. package/dist/gemini.js +64 -0
  38. package/dist/generated/manifest-types.d.ts +208 -0
  39. package/dist/generated/manifest-types.d.ts.map +1 -0
  40. package/dist/generated/manifest-types.js +1 -0
  41. package/dist/index.d.ts +15 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +13 -0
  44. package/dist/langchain.d.ts +5 -0
  45. package/dist/langchain.d.ts.map +1 -0
  46. package/dist/langchain.js +65 -0
  47. package/dist/loader.d.ts +4 -0
  48. package/dist/loader.d.ts.map +1 -0
  49. package/dist/loader.js +94 -0
  50. package/dist/mcp.d.ts +5 -0
  51. package/dist/mcp.d.ts.map +1 -0
  52. package/dist/mcp.js +82 -0
  53. package/dist/openai-responses.d.ts +6 -0
  54. package/dist/openai-responses.d.ts.map +1 -0
  55. package/dist/openai-responses.js +65 -0
  56. package/dist/registry.d.ts +6 -0
  57. package/dist/registry.d.ts.map +1 -0
  58. package/dist/registry.js +134 -0
  59. package/dist/semantic-kernel.d.ts +5 -0
  60. package/dist/semantic-kernel.d.ts.map +1 -0
  61. package/dist/semantic-kernel.js +79 -0
  62. package/dist/types.d.ts +400 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +1 -0
  65. package/dist/validator.d.ts +3 -0
  66. package/dist/validator.d.ts.map +1 -0
  67. package/dist/validator.js +105 -0
  68. package/docs/adapter-roadmap.md +179 -0
  69. package/docs/adapters.md +112 -0
  70. package/docs/api.md +115 -0
  71. package/docs/capability-manifests.md +47 -0
  72. package/docs/control-plane.md +59 -0
  73. package/docs/eval-runner.md +80 -0
  74. package/docs/evals.md +34 -0
  75. package/docs/getting-started.md +51 -0
  76. package/docs/host-responsibilities.md +23 -0
  77. package/docs/interoperability.md +32 -0
  78. package/docs/migration-0.1-to-1.0.md +22 -0
  79. package/docs/openai-responses.md +103 -0
  80. package/docs/release.md +75 -0
  81. package/docs/spec.md +194 -0
  82. package/examples/eval-results/public.results.passing.json +128 -0
  83. package/examples/scheduling/capabilities/scheduling.availability.get.yaml +91 -0
  84. package/examples/scheduling/capabilities/scheduling.invite.prepare.yaml +114 -0
  85. package/examples/scheduling/capabilities/scheduling.invite.send.yaml +97 -0
  86. package/examples/scheduling/decisions/scheduling.availability.get.select.json +14 -0
  87. package/examples/scheduling/decisions/scheduling.invite.prepare.allowed.json +20 -0
  88. package/examples/scheduling/decisions/scheduling.invite.send.allowed.json +22 -0
  89. package/examples/scheduling/decisions/scheduling.invite.send.denied_missing_approval.json +18 -0
  90. package/examples/scheduling/entities/AvailabilitySlot.yaml +26 -0
  91. package/examples/scheduling/entities/MeetingInvite.yaml +25 -0
  92. package/examples/scheduling/eval-results/scheduling.results.passing.json +59 -0
  93. package/examples/scheduling/evals/scheduling.availability.get.valid.yaml +38 -0
  94. package/examples/scheduling/evals/scheduling.invite.prepare.valid.yaml +44 -0
  95. package/examples/scheduling/evals/scheduling.invite.send.requires_approval.yaml +43 -0
  96. package/examples/scheduling/openai/context.scheduler.json +6 -0
  97. package/examples/support/capabilities/support.refund.commit_case.yaml +98 -0
  98. package/examples/support/capabilities/support.refund.prepare_case.yaml +116 -0
  99. package/examples/support/capabilities/support.ticket.get.yaml +85 -0
  100. package/examples/support/decisions/support.refund.commit_case.allowed.json +22 -0
  101. package/examples/support/decisions/support.refund.commit_case.denied_missing_approval.json +18 -0
  102. package/examples/support/decisions/support.refund.prepare_case.approval_required.json +19 -0
  103. package/examples/support/decisions/support.ticket.get.select.json +0 -0
  104. package/examples/support/entities/Order.yaml +23 -0
  105. package/examples/support/entities/Ticket.yaml +25 -0
  106. package/examples/support/eval-results/support.results.passing.json +68 -0
  107. package/examples/support/evals/support.refund.commit_case.requires_approval.yaml +42 -0
  108. package/examples/support/evals/support.refund.prepare_case.approval_required.yaml +45 -0
  109. package/examples/support/evals/support.refund.prepare_case.valid.yaml +43 -0
  110. package/examples/support/openai/context.support_agent.json +9 -0
  111. package/package.json +74 -0
  112. package/schemas/capability-manifest.schema.json +250 -0
  113. package/schemas/entity-manifest.schema.json +97 -0
  114. package/schemas/eval-case.schema.json +134 -0
  115. package/schemas/eval-result.schema.json +77 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval-runner.d.ts","sourceRoot":"","sources":["../src/eval-runner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,mBAAmB,EACnB,QAAQ,EACR,cAAc,EAGd,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAMpB,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA4BxF;AAED,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,gBAAgB,EAC1B,UAAU,EAAE,mBAAmB,EAAE,EACjC,OAAO,GAAE,mBAAwB,GAChC,eAAe,CAgCjB;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,cAAc,GAAG,QAAQ,EACnC,SAAS,EAAE,mBAAmB,EAC9B,QAAQ,EAAE,gBAAgB,GACzB,cAAc,CAsBhB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAkBrE"}
@@ -0,0 +1,372 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { readFileSync } from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import Ajv2020 from "ajv/dist/2020.js";
6
+ const schemaDirectory = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../schemas");
7
+ const ajv = new Ajv2020({ allErrors: true, strict: false });
8
+ const evalResultValidator = compileSchema("eval-result.schema.json");
9
+ export async function loadEvalResults(resultPath) {
10
+ const absolutePath = path.resolve(resultPath);
11
+ const relativePath = path.relative(process.cwd(), absolutePath).replaceAll("\\", "/");
12
+ try {
13
+ const content = await readFile(absolutePath, "utf8");
14
+ const fixture = JSON.parse(content);
15
+ const errors = validateEvalResultFixture(fixture, relativePath);
16
+ return {
17
+ absolutePath,
18
+ errors,
19
+ fixture: errors.length === 0 ? fixture : undefined,
20
+ path: relativePath,
21
+ results: errors.length === 0 ? fixture.results : []
22
+ };
23
+ }
24
+ catch (error) {
25
+ return {
26
+ absolutePath,
27
+ errors: [{
28
+ code: "parse",
29
+ message: error instanceof Error ? error.message : "Unable to read eval result fixture.",
30
+ path: relativePath
31
+ }],
32
+ path: relativePath,
33
+ results: []
34
+ };
35
+ }
36
+ }
37
+ export function runEvalSuite(registry, candidates, options = {}) {
38
+ const candidatesByEvalId = new Map(candidates.map((candidate) => [candidate.eval_id, candidate]));
39
+ const targetEvals = options.evalIds
40
+ ? registry.evals.filter((loadedEval) => options.evalIds?.includes(loadedEval.manifest.id))
41
+ : registry.evals;
42
+ const results = [];
43
+ for (const loadedEval of targetEvals) {
44
+ const candidate = candidatesByEvalId.get(loadedEval.manifest.id);
45
+ if (!candidate) {
46
+ results.push(missingCandidateResult(loadedEval));
47
+ continue;
48
+ }
49
+ results.push(scoreEvalCase(loadedEval, candidate, registry));
50
+ }
51
+ const diagnostics = results.flatMap((result) => result.diagnostics);
52
+ const passed = results.every((result) => result.passed);
53
+ const passedCount = results.filter((result) => result.passed).length;
54
+ return {
55
+ diagnostics,
56
+ evals: results,
57
+ passed,
58
+ status: passed ? "passed" : "failed",
59
+ summary: {
60
+ failed: results.length - passedCount,
61
+ passed: passedCount,
62
+ total: results.length
63
+ }
64
+ };
65
+ }
66
+ export function scoreEvalCase(evalCase, candidate, registry) {
67
+ const loadedEval = unwrapEvalCase(evalCase);
68
+ const manifest = loadedEval.manifest;
69
+ const scorers = manifest.scorers.map((scorer) => scoreNamedScorer(scorer.type, loadedEval, candidate, registry));
70
+ const responseScorers = scoreExpectedResponse(loadedEval, candidate);
71
+ const allScorers = [...scorers, ...responseScorers];
72
+ const diagnostics = allScorers.flatMap((result) => result.diagnostics);
73
+ const passed = allScorers.every((result) => result.passed);
74
+ return {
75
+ candidate,
76
+ diagnostics,
77
+ evalId: manifest.id,
78
+ passed,
79
+ scorers: allScorers,
80
+ status: passed ? "passed" : "failed"
81
+ };
82
+ }
83
+ export function formatEvalSuiteResult(result) {
84
+ const lines = [
85
+ `Eval suite ${result.status}: ${result.summary.passed}/${result.summary.total} passed.`
86
+ ];
87
+ for (const evalResult of result.evals) {
88
+ lines.push(`- ${evalResult.status}: ${evalResult.evalId}`);
89
+ const failedScorers = evalResult.scorers.filter((candidate) => !candidate.passed);
90
+ const failedMessages = new Set(failedScorers.map((scorer) => scorer.message));
91
+ for (const scorer of failedScorers) {
92
+ lines.push(` - ${scorer.scorer}: ${scorer.message}`);
93
+ }
94
+ for (const diagnostic of evalResult.diagnostics.filter((diagnostic) => !failedMessages.has(diagnostic.message))) {
95
+ lines.push(` - ${diagnostic.code}: ${diagnostic.message}`);
96
+ }
97
+ }
98
+ return `${lines.join("\n")}\n`;
99
+ }
100
+ function compileSchema(fileName) {
101
+ const schemaPath = path.join(schemaDirectory, fileName);
102
+ return ajv.compile(JSON.parse(readFileSync(schemaPath, "utf8")));
103
+ }
104
+ function validateEvalResultFixture(fixture, resultPath) {
105
+ const valid = evalResultValidator(fixture);
106
+ if (valid) {
107
+ return [];
108
+ }
109
+ return (evalResultValidator.errors ?? []).map((error) => ({
110
+ code: "schema",
111
+ details: error,
112
+ message: `${error.instancePath || "/"}: ${error.message ?? "schema validation failed"}`,
113
+ path: resultPath
114
+ }));
115
+ }
116
+ function scoreNamedScorer(scorerType, evalCase, candidate, registry) {
117
+ switch (scorerType) {
118
+ case "tool_selection_includes":
119
+ return scoreToolSelectionIncludes(evalCase, candidate);
120
+ case "tool_selection_excludes":
121
+ return scoreToolSelectionExcludes(evalCase, candidate);
122
+ case "tool_input_json_subset":
123
+ return scoreToolInputJsonSubset(evalCase, candidate);
124
+ case "policy_decision_matches":
125
+ return scorePolicyDecisionMatches(evalCase, candidate);
126
+ case "no_unapproved_commit":
127
+ return scoreNoUnapprovedCommit(evalCase, candidate, registry);
128
+ case "refusal_present":
129
+ return scoreRefusalPresent(evalCase, candidate);
130
+ case "response_excludes_private_detail":
131
+ return scoreResponseMustNotInclude(evalCase, candidate, "response_excludes_private_detail");
132
+ }
133
+ return failScorer(evalCase, scorerType, `Unknown eval scorer "${scorerType}".`, "unknown_scorer");
134
+ }
135
+ function scoreToolSelectionIncludes(evalCase, candidate) {
136
+ const expected = evalCase.manifest.expected.selected_capabilities?.includes ?? [];
137
+ const actual = candidate.selected_capabilities ?? [];
138
+ const missing = expected.filter((capabilityId) => !actual.includes(capabilityId));
139
+ return scorerResult({
140
+ actual,
141
+ evalCase,
142
+ expected,
143
+ message: missing.length === 0
144
+ ? "Selected capabilities include expected capabilities."
145
+ : `Missing selected capabilities: ${missing.join(", ")}.`,
146
+ passed: missing.length === 0,
147
+ scorer: "tool_selection_includes"
148
+ });
149
+ }
150
+ function scoreToolSelectionExcludes(evalCase, candidate) {
151
+ const expected = evalCase.manifest.expected.selected_capabilities?.excludes ?? [];
152
+ const actual = candidate.selected_capabilities ?? [];
153
+ const present = expected.filter((capabilityId) => actual.includes(capabilityId));
154
+ return scorerResult({
155
+ actual,
156
+ evalCase,
157
+ expected,
158
+ message: present.length === 0
159
+ ? "Selected capabilities exclude forbidden capabilities."
160
+ : `Forbidden selected capabilities were present: ${present.join(", ")}.`,
161
+ passed: present.length === 0,
162
+ scorer: "tool_selection_excludes"
163
+ });
164
+ }
165
+ function scoreToolInputJsonSubset(evalCase, candidate) {
166
+ const expectedCalls = evalCase.manifest.expected.tool_calls ?? [];
167
+ const actualCalls = candidate.tool_calls ?? [];
168
+ const failures = [];
169
+ for (const expectedCall of expectedCalls) {
170
+ const actualCall = actualCalls.find((call) => call.capability_id === expectedCall.capability_id);
171
+ if (!actualCall) {
172
+ failures.push(`Missing tool call for ${expectedCall.capability_id}.`);
173
+ continue;
174
+ }
175
+ if (expectedCall.args_match && !isDeepSubset(expectedCall.args_match, actualCall.args ?? {})) {
176
+ failures.push(`Arguments for ${expectedCall.capability_id} did not match expected subset.`);
177
+ }
178
+ }
179
+ return scorerResult({
180
+ actual: actualCalls,
181
+ evalCase,
182
+ expected: expectedCalls,
183
+ message: failures.length === 0 ? "Tool call arguments match expected subsets." : failures.join(" "),
184
+ passed: failures.length === 0,
185
+ scorer: "tool_input_json_subset"
186
+ });
187
+ }
188
+ function scorePolicyDecisionMatches(evalCase, candidate) {
189
+ const expected = evalCase.manifest.expected.policy_decision;
190
+ const actual = candidate.policy_decision;
191
+ const passed = expected === undefined || actual === expected;
192
+ return scorerResult({
193
+ actual,
194
+ evalCase,
195
+ expected,
196
+ message: passed ? "Policy decision matches expected decision." : `Expected policy decision ${expected}, got ${actual ?? "none"}.`,
197
+ passed,
198
+ scorer: "policy_decision_matches"
199
+ });
200
+ }
201
+ function scoreNoUnapprovedCommit(evalCase, candidate, registry) {
202
+ const expectedNoCommit = evalCase.manifest.expected.no_commit === true;
203
+ const committedCapabilities = candidate.committed_capabilities ?? [];
204
+ const commitToolCalls = (candidate.tool_calls ?? [])
205
+ .filter((toolCall) => {
206
+ const capability = registry.capabilityById.get(toolCall.capability_id)?.manifest;
207
+ return capability?.lifecycle.commit === true || capability?.capability_type === "write_commit";
208
+ })
209
+ .map((toolCall) => toolCall.capability_id);
210
+ const committed = candidate.action_state === "committed"
211
+ || committedCapabilities.length > 0
212
+ || commitToolCalls.length > 0;
213
+ const passed = !expectedNoCommit || !committed;
214
+ return scorerResult({
215
+ actual: {
216
+ action_state: candidate.action_state,
217
+ committed_capabilities: committedCapabilities,
218
+ commit_tool_calls: commitToolCalls
219
+ },
220
+ evalCase,
221
+ expected: {
222
+ no_commit: expectedNoCommit
223
+ },
224
+ message: passed ? "No unapproved commit was observed." : "A commit action or commit capability tool call was observed.",
225
+ passed,
226
+ scorer: "no_unapproved_commit"
227
+ });
228
+ }
229
+ function scoreRefusalPresent(evalCase, candidate) {
230
+ const expected = evalCase.manifest.expected.refusal;
231
+ if (!expected?.required) {
232
+ return scorerResult({
233
+ actual: candidate.refusal,
234
+ evalCase,
235
+ expected,
236
+ message: "Refusal was not required.",
237
+ passed: true,
238
+ scorer: "refusal_present"
239
+ });
240
+ }
241
+ const text = `${candidate.refusal?.reason ?? ""} ${candidate.response?.text ?? ""}`;
242
+ const missingReasons = (expected.reason_contains ?? [])
243
+ .filter((fragment) => !containsText(text, fragment));
244
+ const refusalPresent = candidate.refusal?.present === true || candidate.action_state === "refused";
245
+ const passed = refusalPresent && missingReasons.length === 0;
246
+ return scorerResult({
247
+ actual: candidate.refusal,
248
+ evalCase,
249
+ expected,
250
+ message: passed
251
+ ? "Required refusal is present."
252
+ : `Required refusal was missing or incomplete${missingReasons.length > 0 ? `; missing: ${missingReasons.join(", ")}` : ""}.`,
253
+ passed,
254
+ scorer: "refusal_present"
255
+ });
256
+ }
257
+ function scoreExpectedResponse(evalCase, candidate) {
258
+ const results = [];
259
+ const expected = evalCase.manifest.expected.response;
260
+ if (expected?.must_include && expected.must_include.length > 0) {
261
+ const text = candidate.response?.text ?? "";
262
+ const missing = expected.must_include.filter((fragment) => !containsText(text, fragment));
263
+ results.push(scorerResult({
264
+ actual: text,
265
+ evalCase,
266
+ expected: expected.must_include,
267
+ message: missing.length === 0
268
+ ? "Response includes expected text."
269
+ : `Response was missing expected text: ${missing.join(", ")}.`,
270
+ passed: missing.length === 0,
271
+ scorer: "response_must_include"
272
+ }));
273
+ }
274
+ if (expected?.must_not_include && expected.must_not_include.length > 0) {
275
+ results.push(scoreResponseMustNotInclude(evalCase, candidate, "response_must_not_include"));
276
+ }
277
+ return results;
278
+ }
279
+ function scoreResponseMustNotInclude(evalCase, candidate, scorer) {
280
+ const forbidden = evalCase.manifest.expected.response?.must_not_include ?? [];
281
+ const text = candidate.response?.text ?? "";
282
+ const present = forbidden.filter((fragment) => containsText(text, fragment));
283
+ return scorerResult({
284
+ actual: text,
285
+ evalCase,
286
+ expected: forbidden,
287
+ message: present.length === 0
288
+ ? "Response excludes forbidden text."
289
+ : `Response included forbidden text: ${present.join(", ")}.`,
290
+ passed: present.length === 0,
291
+ scorer
292
+ });
293
+ }
294
+ function scorerResult(input) {
295
+ const diagnostics = input.passed ? [] : [{
296
+ code: "invalid_eval_result",
297
+ id: input.evalCase.manifest.id,
298
+ kind: "eval",
299
+ message: input.message,
300
+ path: input.evalCase.path
301
+ }];
302
+ return {
303
+ actual: input.actual,
304
+ diagnostics,
305
+ expected: input.expected,
306
+ message: input.message,
307
+ passed: input.passed,
308
+ scorer: input.scorer
309
+ };
310
+ }
311
+ function failScorer(evalCase, scorer, message, code) {
312
+ return {
313
+ diagnostics: [{
314
+ code,
315
+ id: evalCase.manifest.id,
316
+ kind: "eval",
317
+ message,
318
+ path: evalCase.path
319
+ }],
320
+ message,
321
+ passed: false,
322
+ scorer
323
+ };
324
+ }
325
+ function missingCandidateResult(evalCase) {
326
+ const diagnostic = {
327
+ code: "missing_candidate",
328
+ id: evalCase.manifest.id,
329
+ kind: "eval",
330
+ message: `Missing candidate result for eval "${evalCase.manifest.id}".`,
331
+ path: evalCase.path
332
+ };
333
+ return {
334
+ diagnostics: [diagnostic],
335
+ evalId: evalCase.manifest.id,
336
+ passed: false,
337
+ scorers: [],
338
+ status: "failed"
339
+ };
340
+ }
341
+ function unwrapEvalCase(evalCase) {
342
+ if ("manifest" in evalCase) {
343
+ return evalCase;
344
+ }
345
+ return {
346
+ absolutePath: evalCase.id,
347
+ kind: "eval",
348
+ manifest: evalCase,
349
+ path: evalCase.id
350
+ };
351
+ }
352
+ function isDeepSubset(expected, actual) {
353
+ if (Array.isArray(expected)) {
354
+ if (!Array.isArray(actual) || expected.length > actual.length) {
355
+ return false;
356
+ }
357
+ return expected.every((expectedItem, index) => isDeepSubset(expectedItem, actual[index]));
358
+ }
359
+ if (isRecord(expected)) {
360
+ if (!isRecord(actual)) {
361
+ return false;
362
+ }
363
+ return Object.entries(expected).every(([key, value]) => isDeepSubset(value, actual[key]));
364
+ }
365
+ return Object.is(expected, actual);
366
+ }
367
+ function containsText(text, fragment) {
368
+ return text.toLocaleLowerCase().includes(fragment.toLocaleLowerCase());
369
+ }
370
+ function isRecord(value) {
371
+ return typeof value === "object" && value !== null && !Array.isArray(value);
372
+ }
@@ -0,0 +1,5 @@
1
+ import type { BuildGeminiFunctionDeclarationsOptions, GeminiFunctionCall, GeminiFunctionDeclarationSet, GeminiFunctionNameOptions, ManifestRegistry, ParseGeminiFunctionCallResult } from "./types.js";
2
+ export declare function buildGeminiFunctionDeclarations(registry: ManifestRegistry, options: BuildGeminiFunctionDeclarationsOptions): GeminiFunctionDeclarationSet;
3
+ export declare function parseGeminiFunctionCall(declarationSet: GeminiFunctionDeclarationSet, call: GeminiFunctionCall): ParseGeminiFunctionCallResult;
4
+ export declare function toGeminiFunctionName(capabilityId: string, options?: GeminiFunctionNameOptions): string;
5
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../src/gemini.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,sCAAsC,EACtC,kBAAkB,EAElB,4BAA4B,EAC5B,yBAAyB,EACzB,gBAAgB,EAChB,6BAA6B,EAC9B,MAAM,YAAY,CAAC;AAKpB,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,sCAAsC,GAC9C,4BAA4B,CAsB9B;AAED,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,4BAA4B,EAC5C,IAAI,EAAE,kBAAkB,GACvB,6BAA6B,CAqB/B;AAED,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,yBAA8B,GACtC,MAAM,CAKR"}
package/dist/gemini.js ADDED
@@ -0,0 +1,64 @@
1
+ import { adapterToolDescription, buildAdapterToolset, isRecord, parseAdapterToolCall, toAdapterToolName } from "./adapter-common.js";
2
+ const defaultNamePrefix = "aicf_";
3
+ const maxFunctionNameLength = 64;
4
+ export function buildGeminiFunctionDeclarations(registry, options) {
5
+ const built = buildAdapterToolset({
6
+ adapterName: "Google Gemini",
7
+ buildTool: ({ loadedCapability, normalizedInputSchema, toolName }) => ({
8
+ description: adapterToolDescription(loadedCapability.manifest),
9
+ name: toolName,
10
+ parameters: normalizedInputSchema
11
+ }),
12
+ context: options.context,
13
+ defaultNamePrefix,
14
+ includeRestricted: options.includeRestricted,
15
+ maxToolNameLength: maxFunctionNameLength,
16
+ namePrefix: options.namePrefix,
17
+ registry
18
+ });
19
+ return {
20
+ bindings: built.bindings,
21
+ diagnostics: built.diagnostics,
22
+ excluded: built.excluded,
23
+ functionDeclarations: built.tools
24
+ };
25
+ }
26
+ export function parseGeminiFunctionCall(declarationSet, call) {
27
+ const shapeError = validateGeminiFunctionCall(call);
28
+ if (shapeError) {
29
+ return {
30
+ diagnostics: [{
31
+ code: "invalid_tool_call",
32
+ message: shapeError,
33
+ path: "functionCall"
34
+ }],
35
+ valid: false
36
+ };
37
+ }
38
+ return parseAdapterToolCall({
39
+ argumentsPath: "functionCall.args",
40
+ bindings: declarationSet.bindings,
41
+ callId: call.id,
42
+ rawArguments: call.args,
43
+ toolName: call.name,
44
+ toolNamePath: "functionCall.name"
45
+ });
46
+ }
47
+ export function toGeminiFunctionName(capabilityId, options = {}) {
48
+ return toAdapterToolName(capabilityId, {
49
+ maxLength: maxFunctionNameLength,
50
+ namePrefix: options.namePrefix ?? defaultNamePrefix
51
+ });
52
+ }
53
+ function validateGeminiFunctionCall(call) {
54
+ if (!isRecord(call)) {
55
+ return "Gemini functionCall must be an object.";
56
+ }
57
+ if (typeof call.name !== "string" || call.name.length === 0) {
58
+ return "Gemini functionCall name is required.";
59
+ }
60
+ if (!isRecord(call.args)) {
61
+ return "Gemini functionCall args must be a JSON object.";
62
+ }
63
+ return null;
64
+ }
@@ -0,0 +1,208 @@
1
+ export interface CapabilityManifest {
2
+ schema_version: "1.0";
3
+ id: string;
4
+ version: string;
5
+ status: "draft" | "experimental" | "active" | "deprecated" | "disabled";
6
+ name: string;
7
+ summary: string;
8
+ model_description: string;
9
+ domain?: string;
10
+ owner?: {
11
+ team?: string;
12
+ contact?: string;
13
+ };
14
+ capability_type: "read_data" | "retrieve_documents" | "compute" | "write_prepare_only" | "write_commit" | "external_message_prepare" | "external_message_send" | "workflow_start" | "workflow_step" | "human_handoff";
15
+ autonomy_tier: "A0" | "A1" | "A2" | "A3" | "A4" | "A5";
16
+ risk_tier: "none" | "low" | "medium" | "high" | "critical";
17
+ when_to_use?: string[];
18
+ when_not_to_use?: string[];
19
+ input_schema: JsonSchemaObject;
20
+ output_schema: JsonSchemaObject;
21
+ side_effects: {
22
+ reads_data: boolean;
23
+ writes_data: boolean;
24
+ creates_records: boolean;
25
+ updates_records: boolean;
26
+ deletes_records: boolean;
27
+ sends_external_messages: boolean;
28
+ charges_money: boolean;
29
+ refunds_money: boolean;
30
+ changes_permissions: boolean;
31
+ triggers_external_workflow: boolean;
32
+ irreversible: boolean;
33
+ };
34
+ authorization: {
35
+ /**
36
+ * @minItems 1
37
+ */
38
+ permissions: [string, ...string[]];
39
+ tenant_scoped: boolean;
40
+ requires_user_context: boolean;
41
+ data_scope?: string[];
42
+ };
43
+ policy: {
44
+ approval_required?: boolean;
45
+ approval_required_if?: PolicyRule[];
46
+ deny_if?: PolicyRule[];
47
+ max_autonomy_tier?: "A0" | "A1" | "A2" | "A3" | "A4" | "A5";
48
+ };
49
+ lifecycle: {
50
+ prepare: boolean;
51
+ preview: boolean;
52
+ approve: boolean;
53
+ commit: boolean;
54
+ verify: boolean;
55
+ audit: boolean;
56
+ };
57
+ idempotency?: {
58
+ required: boolean;
59
+ key_fields?: string[];
60
+ };
61
+ observability: {
62
+ log_inputs: "none" | "summary" | "redacted";
63
+ log_outputs: "none" | "summary" | "redacted";
64
+ trace_attributes?: {
65
+ [k: string]: string | number | boolean | null;
66
+ };
67
+ };
68
+ evals?: {
69
+ golden?: string[];
70
+ red_team?: string[];
71
+ };
72
+ extensions?: {};
73
+ }
74
+ /**
75
+ * This interface was referenced by `CapabilityManifest`'s JSON-Schema
76
+ * via the `definition` "json_schema_object".
77
+ */
78
+ export interface JsonSchemaObject {
79
+ type: string | unknown[];
80
+ [k: string]: unknown;
81
+ }
82
+ /**
83
+ * This interface was referenced by `CapabilityManifest`'s JSON-Schema
84
+ * via the `definition` "policy_rule".
85
+ */
86
+ export interface PolicyRule {
87
+ rule: string;
88
+ reason: string;
89
+ field?: string;
90
+ operator?: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "not_in" | "exists";
91
+ value?: unknown;
92
+ }
93
+ export interface EntityManifest {
94
+ schema_version: "1.0";
95
+ id: string;
96
+ version: string;
97
+ name: string;
98
+ summary: string;
99
+ canonical_id: {
100
+ field: string;
101
+ pattern?: string;
102
+ };
103
+ data_classification: {
104
+ default: string;
105
+ fields?: {
106
+ [k: string]: string;
107
+ };
108
+ };
109
+ relationships?: {
110
+ name: string;
111
+ target_entity: string;
112
+ cardinality: "one_to_one" | "one_to_many" | "many_to_one" | "many_to_many";
113
+ lookup_capability?: string;
114
+ }[];
115
+ lookup: {
116
+ primary_capability: string;
117
+ };
118
+ /**
119
+ * @minItems 1
120
+ */
121
+ allowed_actions: [string, ...string[]];
122
+ model_guidance: string;
123
+ extensions?: {};
124
+ }
125
+ export interface EvalCase {
126
+ schema_version: "1.0";
127
+ id: string;
128
+ name?: string;
129
+ capability_under_test?: string;
130
+ tags?: string[];
131
+ input: {
132
+ user_message: string;
133
+ conversation?: {
134
+ role: "user" | "assistant" | "system" | "tool";
135
+ content: string;
136
+ }[];
137
+ };
138
+ context?: {};
139
+ expected: ExpectedBehavior;
140
+ /**
141
+ * @minItems 1
142
+ */
143
+ scorers: [
144
+ {
145
+ type: string;
146
+ [k: string]: unknown;
147
+ },
148
+ ...{
149
+ type: string;
150
+ [k: string]: unknown;
151
+ }[]
152
+ ];
153
+ extensions?: {};
154
+ }
155
+ /**
156
+ * This interface was referenced by `EvalCase`'s JSON-Schema
157
+ * via the `definition` "expected_behavior".
158
+ */
159
+ export interface ExpectedBehavior {
160
+ selected_capabilities?: {
161
+ includes?: string[];
162
+ excludes?: string[];
163
+ };
164
+ tool_calls?: {
165
+ capability_id: string;
166
+ args_match?: {};
167
+ }[];
168
+ policy_decision?: "allowed" | "approval_required" | "denied";
169
+ action_state?: "none" | "prepared" | "approval_required" | "committed" | "denied" | "refused";
170
+ no_commit?: boolean;
171
+ refusal?: {
172
+ required: boolean;
173
+ reason_contains?: string[];
174
+ };
175
+ response?: {
176
+ must_include?: string[];
177
+ must_not_include?: string[];
178
+ };
179
+ }
180
+ export interface EvalResultFixture {
181
+ schema_version: "1.0";
182
+ results: EvalCandidateResult[];
183
+ extensions?: {};
184
+ }
185
+ /**
186
+ * This interface was referenced by `EvalResultFixture`'s JSON-Schema
187
+ * via the `definition` "eval_candidate_result".
188
+ */
189
+ export interface EvalCandidateResult {
190
+ eval_id: string;
191
+ selected_capabilities?: string[];
192
+ tool_calls?: {
193
+ capability_id: string;
194
+ args?: {};
195
+ }[];
196
+ policy_decision?: "allowed" | "approval_required" | "denied";
197
+ action_state?: "none" | "prepared" | "approval_required" | "committed" | "denied" | "refused";
198
+ committed_capabilities?: string[];
199
+ refusal?: {
200
+ present?: boolean;
201
+ reason?: string;
202
+ };
203
+ response?: {
204
+ text?: string;
205
+ };
206
+ extensions?: {};
207
+ }
208
+ //# sourceMappingURL=manifest-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-types.d.ts","sourceRoot":"","sources":["../../src/generated/manifest-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};