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,15 @@
1
+ export { decideCapability, evaluateLifecycle, evaluatePolicy } from "./decision.js";
2
+ export { formatEvalSuiteResult, loadEvalResults, runEvalSuite, scoreEvalCase } from "./eval-runner.js";
3
+ export { buildAiSdkTools, parseAiSdkToolCall, toAiSdkToolName } from "./ai-sdk.js";
4
+ export { buildAnthropicClaudeTools, parseAnthropicClaudeToolUse, toAnthropicClaudeToolName } from "./anthropic-claude.js";
5
+ export { buildGeminiFunctionDeclarations, parseGeminiFunctionCall, toGeminiFunctionName } from "./gemini.js";
6
+ export { buildLangChainToolDescriptors, parseLangChainToolCall, toLangChainToolName } from "./langchain.js";
7
+ export { loadManifests, kindFromPath } from "./loader.js";
8
+ export { buildMcpToolDescriptors, parseMcpToolCall, toMcpToolName } from "./mcp.js";
9
+ export { buildOpenAIResponsesTools, parseOpenAIResponsesToolCall, toOpenAIResponsesToolName } from "./openai-responses.js";
10
+ export { buildRegistry, formatInspection, inspectRegistry } from "./registry.js";
11
+ export { runCli } from "./cli.js";
12
+ export { buildSemanticKernelFunctions, parseSemanticKernelFunctionCall, toSemanticKernelFunctionName } from "./semantic-kernel.js";
13
+ export { validateManifests } from "./validator.js";
14
+ export type { AdapterExcludedCapability, AdapterToolBinding, AicfDiagnostic, AicfErrorCode, AicfSchemaDiagnostic, AicfWarningCode, AiSdkTool, AiSdkToolCall, AiSdkToolNameOptions, AiSdkToolset, AnthropicClaudeTool, AnthropicClaudeToolNameOptions, AnthropicClaudeToolset, AnthropicClaudeToolUse, BuildAdapterToolsOptions, BuildAiSdkToolsOptions, BuildAnthropicClaudeToolsOptions, BuildGeminiFunctionDeclarationsOptions, BuildLangChainToolDescriptorsOptions, BuildMcpToolDescriptorsOptions, CapabilityManifest, DecisionAuditPreview, DecisionFact, DecisionOperation, DecisionReason, DecisionReasonCode, DecisionRequest, DecisionResult, DecisionStatus, EvalCandidateResult, EntityManifest, EvalCase, EvalCaseResult, EvalResultFixture, EvalRunStatus, EvalScorerResult, EvalSuiteResult, GeminiFunctionCall, GeminiFunctionDeclaration, GeminiFunctionDeclarationSet, GeminiFunctionNameOptions, LangChainToolCall, LangChainToolDescriptor, LangChainToolDescriptorSet, LangChainToolNameOptions, LifecycleEvaluation, LoadEvalResultsResult, LoadedCapabilityManifest, LoadedEntityManifest, LoadedEvalCase, LoadedManifest, LoadManifestsOptions, LoadManifestsResult, ManifestKind, ManifestRegistry, McpToolCall, McpToolDescriptor, McpToolDescriptorSet, McpToolNameOptions, BuildOpenAIResponsesToolsOptions, BuildSemanticKernelFunctionsOptions, JsonObject, JsonValue, OpenAIResponsesExcludedCapability, OpenAIResponsesFunctionCall, OpenAIResponsesFunctionTool, OpenAIResponsesToolBinding, OpenAIResponsesToolNameOptions, OpenAIResponsesToolset, ParsedAdapterToolCall, ParsedAiSdkToolCall, ParsedAnthropicClaudeToolUse, ParsedGeminiFunctionCall, ParsedLangChainToolCall, ParsedMcpToolCall, ParsedOpenAIResponsesToolCall, ParsedSemanticKernelFunctionCall, ParseAdapterToolCallResult, ParseAiSdkToolCallResult, ParseAnthropicClaudeToolUseResult, ParseGeminiFunctionCallResult, ParseLangChainToolCallResult, ParseMcpToolCallResult, ParseOpenAIResponsesToolCallResult, ParseSemanticKernelFunctionCallResult, PolicyEvaluation, RegistryInspection, RunEvalSuiteOptions, SemanticKernelFunction, SemanticKernelFunctionCall, SemanticKernelFunctionNameOptions, SemanticKernelFunctionSet, ValidateManifestsOptions, ValidationResult } from "./types.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACvG,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAC1H,OAAO,EAAE,+BAA+B,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAE,6BAA6B,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5G,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACpF,OAAO,EAAE,yBAAyB,EAAE,4BAA4B,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAC3H,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,4BAA4B,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACnI,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EACV,yBAAyB,EACzB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,mBAAmB,EACnB,8BAA8B,EAC9B,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,gCAAgC,EAChC,sCAAsC,EACtC,oCAAoC,EACpC,8BAA8B,EAC9B,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,QAAQ,EACR,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,EACzB,iBAAiB,EACjB,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,gCAAgC,EAChC,mCAAmC,EACnC,UAAU,EACV,SAAS,EACT,iCAAiC,EACjC,2BAA2B,EAC3B,2BAA2B,EAC3B,0BAA0B,EAC1B,8BAA8B,EAC9B,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,4BAA4B,EAC5B,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,6BAA6B,EAC7B,gCAAgC,EAChC,0BAA0B,EAC1B,wBAAwB,EACxB,iCAAiC,EACjC,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,kCAAkC,EAClC,qCAAqC,EACrC,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC1B,iCAAiC,EACjC,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EACjB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ export { decideCapability, evaluateLifecycle, evaluatePolicy } from "./decision.js";
2
+ export { formatEvalSuiteResult, loadEvalResults, runEvalSuite, scoreEvalCase } from "./eval-runner.js";
3
+ export { buildAiSdkTools, parseAiSdkToolCall, toAiSdkToolName } from "./ai-sdk.js";
4
+ export { buildAnthropicClaudeTools, parseAnthropicClaudeToolUse, toAnthropicClaudeToolName } from "./anthropic-claude.js";
5
+ export { buildGeminiFunctionDeclarations, parseGeminiFunctionCall, toGeminiFunctionName } from "./gemini.js";
6
+ export { buildLangChainToolDescriptors, parseLangChainToolCall, toLangChainToolName } from "./langchain.js";
7
+ export { loadManifests, kindFromPath } from "./loader.js";
8
+ export { buildMcpToolDescriptors, parseMcpToolCall, toMcpToolName } from "./mcp.js";
9
+ export { buildOpenAIResponsesTools, parseOpenAIResponsesToolCall, toOpenAIResponsesToolName } from "./openai-responses.js";
10
+ export { buildRegistry, formatInspection, inspectRegistry } from "./registry.js";
11
+ export { runCli } from "./cli.js";
12
+ export { buildSemanticKernelFunctions, parseSemanticKernelFunctionCall, toSemanticKernelFunctionName } from "./semantic-kernel.js";
13
+ export { validateManifests } from "./validator.js";
@@ -0,0 +1,5 @@
1
+ import type { BuildLangChainToolDescriptorsOptions, LangChainToolCall, LangChainToolDescriptorSet, LangChainToolNameOptions, ManifestRegistry, ParseLangChainToolCallResult } from "./types.js";
2
+ export declare function buildLangChainToolDescriptors(registry: ManifestRegistry, options: BuildLangChainToolDescriptorsOptions): LangChainToolDescriptorSet;
3
+ export declare function parseLangChainToolCall(descriptorSet: LangChainToolDescriptorSet, call: LangChainToolCall): ParseLangChainToolCallResult;
4
+ export declare function toLangChainToolName(capabilityId: string, options?: LangChainToolNameOptions): string;
5
+ //# sourceMappingURL=langchain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"langchain.d.ts","sourceRoot":"","sources":["../src/langchain.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,oCAAoC,EACpC,iBAAiB,EAEjB,0BAA0B,EAC1B,wBAAwB,EACxB,gBAAgB,EAChB,4BAA4B,EAC7B,MAAM,YAAY,CAAC;AAKpB,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,oCAAoC,GAC5C,0BAA0B,CAsB5B;AAED,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,0BAA0B,EACzC,IAAI,EAAE,iBAAiB,GACtB,4BAA4B,CAqB9B;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,wBAA6B,GACrC,MAAM,CAKR"}
@@ -0,0 +1,65 @@
1
+ import { adapterToolDescription, buildAdapterToolset, isRecord, parseAdapterToolCall, toAdapterToolName } from "./adapter-common.js";
2
+ const defaultNamePrefix = "aicf_";
3
+ const maxToolNameLength = 64;
4
+ export function buildLangChainToolDescriptors(registry, options) {
5
+ return buildAdapterToolset({
6
+ adapterName: "LangChain",
7
+ buildTool: ({ loadedCapability, normalizedInputSchema, restricted, toolName }) => ({
8
+ description: adapterToolDescription(loadedCapability.manifest),
9
+ metadata: {
10
+ autonomyTier: loadedCapability.manifest.autonomy_tier,
11
+ capabilityId: loadedCapability.manifest.id,
12
+ capabilityType: loadedCapability.manifest.capability_type,
13
+ restricted,
14
+ riskTier: loadedCapability.manifest.risk_tier
15
+ },
16
+ name: toolName,
17
+ schema: normalizedInputSchema
18
+ }),
19
+ context: options.context,
20
+ defaultNamePrefix,
21
+ includeRestricted: options.includeRestricted,
22
+ maxToolNameLength,
23
+ namePrefix: options.namePrefix,
24
+ registry
25
+ });
26
+ }
27
+ export function parseLangChainToolCall(descriptorSet, call) {
28
+ const shapeError = validateLangChainToolCall(call);
29
+ if (shapeError) {
30
+ return {
31
+ diagnostics: [{
32
+ code: "invalid_tool_call",
33
+ message: shapeError,
34
+ path: "tool_call"
35
+ }],
36
+ valid: false
37
+ };
38
+ }
39
+ return parseAdapterToolCall({
40
+ argumentsPath: "tool_call.args",
41
+ bindings: descriptorSet.bindings,
42
+ callId: call.id,
43
+ rawArguments: call.args,
44
+ toolName: call.name,
45
+ toolNamePath: "tool_call.name"
46
+ });
47
+ }
48
+ export function toLangChainToolName(capabilityId, options = {}) {
49
+ return toAdapterToolName(capabilityId, {
50
+ maxLength: maxToolNameLength,
51
+ namePrefix: options.namePrefix ?? defaultNamePrefix
52
+ });
53
+ }
54
+ function validateLangChainToolCall(call) {
55
+ if (!isRecord(call)) {
56
+ return "LangChain tool call must be an object.";
57
+ }
58
+ if (typeof call.name !== "string" || call.name.length === 0) {
59
+ return "LangChain tool call name is required.";
60
+ }
61
+ if (!isRecord(call.args)) {
62
+ return "LangChain tool call args must be a JSON object.";
63
+ }
64
+ return null;
65
+ }
@@ -0,0 +1,4 @@
1
+ import type { LoadManifestsOptions, LoadManifestsResult, ManifestKind } from "./types.js";
2
+ export declare function loadManifests(options?: LoadManifestsOptions): Promise<LoadManifestsResult>;
3
+ export declare function kindFromPath(filePath: string): ManifestKind | null;
4
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACb,MAAM,YAAY,CAAC;AAKpB,wBAAsB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAqDpG;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAQlE"}
package/dist/loader.js ADDED
@@ -0,0 +1,94 @@
1
+ import { readFile, readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import YAML from "yaml";
4
+ const structuredExtensions = new Set([".json", ".yaml", ".yml"]);
5
+ const ignoredDirectories = new Set([".git", "_private", "node_modules"]);
6
+ export async function loadManifests(options = {}) {
7
+ const root = path.resolve(options.root ?? process.cwd());
8
+ const basePath = path.resolve(root, options.path ?? "examples");
9
+ const manifests = [];
10
+ const errors = [];
11
+ let files;
12
+ try {
13
+ files = await listStructuredFiles(basePath);
14
+ }
15
+ catch (error) {
16
+ return {
17
+ basePath,
18
+ errors: [{
19
+ code: "unsupported",
20
+ message: error instanceof Error ? error.message : "Unable to read manifest path.",
21
+ path: toRelativePath(root, basePath)
22
+ }],
23
+ manifests,
24
+ root
25
+ };
26
+ }
27
+ for (const absolutePath of files) {
28
+ const kind = kindFromPath(absolutePath);
29
+ if (!kind) {
30
+ continue;
31
+ }
32
+ const relativePath = toRelativePath(root, absolutePath);
33
+ try {
34
+ const manifest = await readStructuredFile(absolutePath);
35
+ manifests.push({
36
+ absolutePath,
37
+ kind,
38
+ manifest,
39
+ path: relativePath
40
+ });
41
+ }
42
+ catch (error) {
43
+ errors.push({
44
+ code: "parse",
45
+ kind,
46
+ message: error instanceof Error ? error.message : "Unable to parse manifest.",
47
+ path: relativePath
48
+ });
49
+ }
50
+ }
51
+ return {
52
+ basePath,
53
+ errors,
54
+ manifests,
55
+ root
56
+ };
57
+ }
58
+ export function kindFromPath(filePath) {
59
+ const parts = filePath.replaceAll("\\", "/").split("/");
60
+ if (parts.includes("capabilities"))
61
+ return "capability";
62
+ if (parts.includes("entities"))
63
+ return "entity";
64
+ if (parts.includes("evals"))
65
+ return "eval";
66
+ return null;
67
+ }
68
+ async function listStructuredFiles(directory) {
69
+ const entries = await readdir(directory, { withFileTypes: true });
70
+ const files = [];
71
+ for (const entry of entries) {
72
+ if (entry.isDirectory()) {
73
+ if (!ignoredDirectories.has(entry.name)) {
74
+ files.push(...await listStructuredFiles(path.join(directory, entry.name)));
75
+ }
76
+ continue;
77
+ }
78
+ if (entry.isFile() && structuredExtensions.has(path.extname(entry.name).toLowerCase())) {
79
+ files.push(path.join(directory, entry.name));
80
+ }
81
+ }
82
+ return files.sort((left, right) => left.localeCompare(right));
83
+ }
84
+ async function readStructuredFile(filePath) {
85
+ const content = await readFile(filePath, "utf8");
86
+ const extension = path.extname(filePath).toLowerCase();
87
+ if (extension === ".json") {
88
+ return JSON.parse(content);
89
+ }
90
+ return YAML.parse(content);
91
+ }
92
+ function toRelativePath(root, absolutePath) {
93
+ return path.relative(root, absolutePath).replaceAll("\\", "/");
94
+ }
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import type { BuildMcpToolDescriptorsOptions, ManifestRegistry, McpToolCall, McpToolDescriptorSet, McpToolNameOptions, ParseMcpToolCallResult } from "./types.js";
2
+ export declare function buildMcpToolDescriptors(registry: ManifestRegistry, options: BuildMcpToolDescriptorsOptions): McpToolDescriptorSet;
3
+ export declare function parseMcpToolCall(descriptorSet: McpToolDescriptorSet, call: McpToolCall): ParseMcpToolCallResult;
4
+ export declare function toMcpToolName(capabilityId: string, options?: McpToolNameOptions): string;
5
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,8BAA8B,EAE9B,gBAAgB,EAChB,WAAW,EAEX,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAKpB,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,8BAA8B,GACtC,oBAAoB,CAkBtB;AAED,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,oBAAoB,EACnC,IAAI,EAAE,WAAW,GAChB,sBAAsB,CAoBxB;AAED,wBAAgB,aAAa,CAC3B,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CAKR"}
package/dist/mcp.js ADDED
@@ -0,0 +1,82 @@
1
+ import { adapterToolDescription, buildAdapterToolset, isRecord, parseAdapterToolCall, toAdapterToolName, toJsonObject } from "./adapter-common.js";
2
+ const defaultNamePrefix = "aicf_";
3
+ const maxToolNameLength = 64;
4
+ export function buildMcpToolDescriptors(registry, options) {
5
+ return buildAdapterToolset({
6
+ adapterName: "Model Context Protocol",
7
+ buildTool: ({ loadedCapability, normalizedInputSchema, toolName }) => ({
8
+ annotations: mcpAnnotations(loadedCapability.manifest),
9
+ description: adapterToolDescription(loadedCapability.manifest),
10
+ inputSchema: normalizedInputSchema,
11
+ name: toolName,
12
+ outputSchema: toJsonObject(loadedCapability.manifest.output_schema),
13
+ title: loadedCapability.manifest.name
14
+ }),
15
+ context: options.context,
16
+ defaultNamePrefix,
17
+ includeRestricted: options.includeRestricted,
18
+ maxToolNameLength,
19
+ namePrefix: options.namePrefix,
20
+ registry
21
+ });
22
+ }
23
+ export function parseMcpToolCall(descriptorSet, call) {
24
+ const shapeError = validateMcpToolCall(call);
25
+ if (shapeError) {
26
+ return {
27
+ diagnostics: [{
28
+ code: "invalid_tool_call",
29
+ message: shapeError,
30
+ path: "tools/call"
31
+ }],
32
+ valid: false
33
+ };
34
+ }
35
+ return parseAdapterToolCall({
36
+ argumentsPath: "tools/call.params.arguments",
37
+ bindings: descriptorSet.bindings,
38
+ rawArguments: call.params.arguments,
39
+ toolName: call.params.name,
40
+ toolNamePath: "tools/call.params.name"
41
+ });
42
+ }
43
+ export function toMcpToolName(capabilityId, options = {}) {
44
+ return toAdapterToolName(capabilityId, {
45
+ maxLength: maxToolNameLength,
46
+ namePrefix: options.namePrefix ?? defaultNamePrefix
47
+ });
48
+ }
49
+ function validateMcpToolCall(call) {
50
+ if (!isRecord(call)) {
51
+ return "MCP tools/call request must be an object.";
52
+ }
53
+ if (!isRecord(call.params)) {
54
+ return "MCP tools/call params must be an object.";
55
+ }
56
+ if (typeof call.params.name !== "string" || call.params.name.length === 0) {
57
+ return "MCP tools/call params.name is required.";
58
+ }
59
+ if (!isRecord(call.params.arguments)) {
60
+ return "MCP tools/call params.arguments must be a JSON object.";
61
+ }
62
+ return null;
63
+ }
64
+ function mcpAnnotations(capability) {
65
+ const writes = capability.side_effects.writes_data
66
+ || capability.side_effects.creates_records
67
+ || capability.side_effects.updates_records
68
+ || capability.side_effects.deletes_records;
69
+ const openWorld = capability.side_effects.sends_external_messages
70
+ || capability.side_effects.triggers_external_workflow;
71
+ const destructive = capability.side_effects.deletes_records
72
+ || capability.side_effects.changes_permissions
73
+ || capability.side_effects.irreversible
74
+ || capability.side_effects.charges_money
75
+ || capability.side_effects.refunds_money;
76
+ return {
77
+ destructiveHint: destructive,
78
+ idempotentHint: !destructive && (!writes || capability.idempotency?.required === true),
79
+ openWorldHint: openWorld,
80
+ readOnlyHint: capability.side_effects.reads_data && !writes && !openWorld && !destructive
81
+ };
82
+ }
@@ -0,0 +1,6 @@
1
+ import type { BuildOpenAIResponsesToolsOptions, OpenAIResponsesFunctionCall, OpenAIResponsesToolNameOptions, OpenAIResponsesToolset, ParseOpenAIResponsesToolCallResult } from "./types.js";
2
+ import type { ManifestRegistry } from "./types.js";
3
+ export declare function buildOpenAIResponsesTools(registry: ManifestRegistry, options: BuildOpenAIResponsesToolsOptions): OpenAIResponsesToolset;
4
+ export declare function parseOpenAIResponsesToolCall(toolset: OpenAIResponsesToolset, call: OpenAIResponsesFunctionCall): ParseOpenAIResponsesToolCallResult;
5
+ export declare function toOpenAIResponsesToolName(capabilityId: string, options?: OpenAIResponsesToolNameOptions): string;
6
+ //# sourceMappingURL=openai-responses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../src/openai-responses.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,gCAAgC,EAChC,2BAA2B,EAE3B,8BAA8B,EAC9B,sBAAsB,EACtB,kCAAkC,EACnC,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAKnD,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,gCAAgC,GACxC,sBAAsB,CAiBxB;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,sBAAsB,EAC/B,IAAI,EAAE,2BAA2B,GAChC,kCAAkC,CAuBpC;AAED,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,8BAAmC,GAC3C,MAAM,CAKR"}
@@ -0,0 +1,65 @@
1
+ import { adapterToolDescription, buildAdapterToolset, isRecord, parseAdapterToolCall, toAdapterToolName } from "./adapter-common.js";
2
+ const defaultNamePrefix = "aicf_";
3
+ const maxOpenAIToolNameLength = 64;
4
+ export function buildOpenAIResponsesTools(registry, options) {
5
+ return buildAdapterToolset({
6
+ adapterName: "OpenAI",
7
+ buildTool: ({ loadedCapability, normalizedInputSchema, toolName }) => ({
8
+ description: adapterToolDescription(loadedCapability.manifest),
9
+ name: toolName,
10
+ parameters: normalizedInputSchema,
11
+ strict: true,
12
+ type: "function"
13
+ }),
14
+ context: options.context,
15
+ defaultNamePrefix,
16
+ includeRestricted: options.includeRestricted,
17
+ maxToolNameLength: maxOpenAIToolNameLength,
18
+ namePrefix: options.namePrefix,
19
+ registry
20
+ });
21
+ }
22
+ export function parseOpenAIResponsesToolCall(toolset, call) {
23
+ const callShapeError = validateToolCallShape(call);
24
+ if (callShapeError) {
25
+ return {
26
+ diagnostics: [{
27
+ code: "invalid_tool_call",
28
+ message: callShapeError,
29
+ path: "tool_call"
30
+ }],
31
+ valid: false
32
+ };
33
+ }
34
+ return parseAdapterToolCall({
35
+ argumentsPath: "tool_call.arguments",
36
+ bindings: toolset.bindings,
37
+ callId: call.call_id,
38
+ id: call.id,
39
+ rawArguments: call.arguments,
40
+ rawArgumentsAreJsonString: true,
41
+ toolName: call.name,
42
+ toolNamePath: "tool_call.name"
43
+ });
44
+ }
45
+ export function toOpenAIResponsesToolName(capabilityId, options = {}) {
46
+ return toAdapterToolName(capabilityId, {
47
+ maxLength: maxOpenAIToolNameLength,
48
+ namePrefix: options.namePrefix ?? defaultNamePrefix
49
+ });
50
+ }
51
+ function validateToolCallShape(call) {
52
+ if (!isRecord(call)) {
53
+ return "OpenAI tool call must be an object.";
54
+ }
55
+ if (call.type !== "function_call") {
56
+ return "OpenAI tool call type must be function_call.";
57
+ }
58
+ if (typeof call.name !== "string" || call.name.length === 0) {
59
+ return "OpenAI tool call name is required.";
60
+ }
61
+ if (typeof call.arguments !== "string") {
62
+ return "OpenAI tool call arguments must be a JSON string.";
63
+ }
64
+ return null;
65
+ }
@@ -0,0 +1,6 @@
1
+ import type { LoadedManifest, ManifestRegistry, RegistryInspection } from "./types.js";
2
+ export declare function buildRegistry(manifests: LoadedManifest[]): ManifestRegistry;
3
+ export declare function inspectRegistry(registry: ManifestRegistry): RegistryInspection;
4
+ export declare function formatInspection(inspection: RegistryInspection): string;
5
+ export declare function resolveManifestReference(basePath: string, reference: string): string;
6
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAKV,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,aAAa,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,gBAAgB,CAkB3E;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,gBAAgB,GAAG,kBAAkB,CAsB9E;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM,CAsBvE;AA8FD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpF"}
@@ -0,0 +1,134 @@
1
+ import path from "node:path";
2
+ export function buildRegistry(manifests) {
3
+ const capabilities = manifests.filter(isCapability);
4
+ const entities = manifests.filter(isEntity);
5
+ const evals = manifests.filter(isEval);
6
+ const capabilityById = new Map(capabilities.map((entry) => [entry.manifest.id, entry]));
7
+ const entityById = new Map(entities.map((entry) => [entry.manifest.id, entry]));
8
+ const evalById = new Map(evals.map((entry) => [entry.manifest.id, entry]));
9
+ const warnings = buildWarnings(entities, evals, capabilityById);
10
+ return {
11
+ capabilities,
12
+ capabilityById,
13
+ entities,
14
+ entityById,
15
+ evalById,
16
+ evals,
17
+ warnings
18
+ };
19
+ }
20
+ export function inspectRegistry(registry) {
21
+ const evalCoverage = registry.capabilities
22
+ .map((entry) => ({
23
+ capabilityId: entry.manifest.id,
24
+ golden: entry.manifest.evals?.golden?.length ?? 0,
25
+ redTeam: entry.manifest.evals?.red_team?.length ?? 0
26
+ }))
27
+ .sort((left, right) => left.capabilityId.localeCompare(right.capabilityId));
28
+ return {
29
+ capabilitiesByRisk: groupCapabilities(registry.capabilities, "risk_tier"),
30
+ capabilitiesByType: groupCapabilities(registry.capabilities, "capability_type"),
31
+ counts: {
32
+ capabilities: registry.capabilities.length,
33
+ entities: registry.entities.length,
34
+ evals: registry.evals.length,
35
+ manifests: registry.capabilities.length + registry.entities.length + registry.evals.length
36
+ },
37
+ entities: registry.entities.map((entry) => entry.manifest.id).sort(),
38
+ evalCoverage,
39
+ warnings: registry.warnings
40
+ };
41
+ }
42
+ export function formatInspection(inspection) {
43
+ const lines = [
44
+ "AICF Registry",
45
+ `Manifests: ${inspection.counts.manifests} (${inspection.counts.capabilities} capabilities, ${inspection.counts.entities} entities, ${inspection.counts.evals} evals)`,
46
+ "",
47
+ "Capabilities by type:",
48
+ ...formatGroups(inspection.capabilitiesByType),
49
+ "",
50
+ "Capabilities by risk:",
51
+ ...formatGroups(inspection.capabilitiesByRisk),
52
+ "",
53
+ "Entities:",
54
+ ...formatList(inspection.entities),
55
+ "",
56
+ "Eval coverage:",
57
+ ...inspection.evalCoverage.map((coverage) => `- ${coverage.capabilityId}: golden ${coverage.golden}, red_team ${coverage.redTeam}`),
58
+ "",
59
+ "Warnings:",
60
+ ...formatWarnings(inspection.warnings)
61
+ ];
62
+ return `${lines.join("\n")}\n`;
63
+ }
64
+ function buildWarnings(entities, evals, capabilityById) {
65
+ const warnings = [];
66
+ for (const entity of entities) {
67
+ for (const capabilityId of entity.manifest.allowed_actions) {
68
+ if (!capabilityById.has(capabilityId)) {
69
+ warnings.push({
70
+ code: "unknown_allowed_action",
71
+ id: entity.manifest.id,
72
+ kind: "entity",
73
+ message: `Allowed action "${capabilityId}" does not match a loaded capability.`,
74
+ path: entity.path
75
+ });
76
+ }
77
+ }
78
+ // Lookup capabilities can be owned by another manifest bundle. Phase 2 only
79
+ // warns on action/eval references that affect this loaded registry.
80
+ }
81
+ for (const evalCase of evals) {
82
+ const capabilityId = evalCase.manifest.capability_under_test;
83
+ if (capabilityId && !capabilityById.has(capabilityId)) {
84
+ warnings.push({
85
+ code: "unknown_capability_under_test",
86
+ id: evalCase.manifest.id,
87
+ kind: "eval",
88
+ message: `Capability under test "${capabilityId}" does not match a loaded capability.`,
89
+ path: evalCase.path
90
+ });
91
+ }
92
+ }
93
+ return warnings.sort((left, right) => left.path.localeCompare(right.path) || left.message.localeCompare(right.message));
94
+ }
95
+ function groupCapabilities(capabilities, key) {
96
+ const groups = {};
97
+ for (const capability of capabilities) {
98
+ const group = capability.manifest[key];
99
+ groups[group] ??= [];
100
+ groups[group].push(capability.manifest.id);
101
+ }
102
+ for (const ids of Object.values(groups)) {
103
+ ids.sort();
104
+ }
105
+ return Object.fromEntries(Object.entries(groups).sort(([left], [right]) => left.localeCompare(right)));
106
+ }
107
+ function formatGroups(groups) {
108
+ const entries = Object.entries(groups);
109
+ if (entries.length === 0) {
110
+ return ["- none"];
111
+ }
112
+ return entries.map(([group, ids]) => `- ${group}: ${ids.join(", ")}`);
113
+ }
114
+ function formatList(items) {
115
+ return items.length > 0 ? items.map((item) => `- ${item}`) : ["- none"];
116
+ }
117
+ function formatWarnings(warnings) {
118
+ if (warnings.length === 0) {
119
+ return ["- none"];
120
+ }
121
+ return warnings.map((warning) => `- ${warning.path}: ${warning.message}`);
122
+ }
123
+ function isCapability(manifest) {
124
+ return manifest.kind === "capability";
125
+ }
126
+ function isEntity(manifest) {
127
+ return manifest.kind === "entity";
128
+ }
129
+ function isEval(manifest) {
130
+ return manifest.kind === "eval";
131
+ }
132
+ export function resolveManifestReference(basePath, reference) {
133
+ return path.normalize(path.resolve(path.dirname(basePath), reference));
134
+ }
@@ -0,0 +1,5 @@
1
+ import type { BuildSemanticKernelFunctionsOptions, ManifestRegistry, ParseSemanticKernelFunctionCallResult, SemanticKernelFunctionCall, SemanticKernelFunctionNameOptions, SemanticKernelFunctionSet } from "./types.js";
2
+ export declare function buildSemanticKernelFunctions(registry: ManifestRegistry, options: BuildSemanticKernelFunctionsOptions): SemanticKernelFunctionSet;
3
+ export declare function parseSemanticKernelFunctionCall(functionSet: SemanticKernelFunctionSet, call: SemanticKernelFunctionCall): ParseSemanticKernelFunctionCallResult;
4
+ export declare function toSemanticKernelFunctionName(capabilityId: string, options?: SemanticKernelFunctionNameOptions): string;
5
+ //# sourceMappingURL=semantic-kernel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-kernel.d.ts","sourceRoot":"","sources":["../src/semantic-kernel.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,mCAAmC,EACnC,gBAAgB,EAChB,qCAAqC,EAErC,0BAA0B,EAC1B,iCAAiC,EACjC,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAMpB,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,mCAAmC,GAC3C,yBAAyB,CA8B3B;AAED,wBAAgB,+BAA+B,CAC7C,WAAW,EAAE,yBAAyB,EACtC,IAAI,EAAE,0BAA0B,GAC/B,qCAAqC,CAuBvC;AAED,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,iCAAsC,GAC9C,MAAM,CAKR"}
@@ -0,0 +1,79 @@
1
+ import { adapterToolDescription, buildAdapterToolset, isRecord, parseAdapterToolCall, toAdapterToolName } from "./adapter-common.js";
2
+ const defaultNamePrefix = "aicf_";
3
+ const maxFunctionNameLength = 64;
4
+ const pluginName = "aicf";
5
+ export function buildSemanticKernelFunctions(registry, options) {
6
+ const built = buildAdapterToolset({
7
+ adapterName: "Semantic Kernel",
8
+ buildTool: ({ loadedCapability, normalizedInputSchema, restricted, toolName }) => ({
9
+ description: adapterToolDescription(loadedCapability.manifest),
10
+ metadata: {
11
+ autonomyTier: loadedCapability.manifest.autonomy_tier,
12
+ capabilityId: loadedCapability.manifest.id,
13
+ capabilityType: loadedCapability.manifest.capability_type,
14
+ restricted,
15
+ riskTier: loadedCapability.manifest.risk_tier
16
+ },
17
+ name: toolName,
18
+ parameters: normalizedInputSchema,
19
+ pluginName
20
+ }),
21
+ context: options.context,
22
+ defaultNamePrefix,
23
+ includeRestricted: options.includeRestricted,
24
+ maxToolNameLength: maxFunctionNameLength,
25
+ namePrefix: options.namePrefix,
26
+ registry
27
+ });
28
+ return {
29
+ bindings: built.bindings,
30
+ diagnostics: built.diagnostics,
31
+ excluded: built.excluded,
32
+ functions: built.tools
33
+ };
34
+ }
35
+ export function parseSemanticKernelFunctionCall(functionSet, call) {
36
+ const shapeError = validateSemanticKernelFunctionCall(call);
37
+ if (shapeError) {
38
+ return {
39
+ diagnostics: [{
40
+ code: "invalid_tool_call",
41
+ message: shapeError,
42
+ path: "function_call"
43
+ }],
44
+ valid: false
45
+ };
46
+ }
47
+ const functionName = call.functionName ?? call.name ?? "";
48
+ return parseAdapterToolCall({
49
+ argumentsPath: "function_call.arguments",
50
+ bindings: functionSet.bindings,
51
+ callId: call.id,
52
+ rawArguments: call.arguments,
53
+ toolName: stripPluginPrefix(functionName),
54
+ toolNamePath: "function_call.functionName"
55
+ });
56
+ }
57
+ export function toSemanticKernelFunctionName(capabilityId, options = {}) {
58
+ return toAdapterToolName(capabilityId, {
59
+ maxLength: maxFunctionNameLength,
60
+ namePrefix: options.namePrefix ?? defaultNamePrefix
61
+ });
62
+ }
63
+ function validateSemanticKernelFunctionCall(call) {
64
+ if (!isRecord(call)) {
65
+ return "Semantic Kernel function call must be an object.";
66
+ }
67
+ const name = call.functionName ?? call.name;
68
+ if (typeof name !== "string" || name.length === 0) {
69
+ return "Semantic Kernel function call functionName or name is required.";
70
+ }
71
+ if (!isRecord(call.arguments)) {
72
+ return "Semantic Kernel function call arguments must be a JSON object.";
73
+ }
74
+ return null;
75
+ }
76
+ function stripPluginPrefix(functionName) {
77
+ const prefix = `${pluginName}.`;
78
+ return functionName.startsWith(prefix) ? functionName.slice(prefix.length) : functionName;
79
+ }