@axiom-lattice/gateway 4.2.0 → 4.2.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 (103) hide show
  1. package/dist/{A2AAuthService-DK5X6VIL.mjs → A2AAuthService-7UGQ7GMW.mjs} +3 -2
  2. package/dist/{WechatChannelAdapter-WSDKR4OA.mjs → WechatChannelAdapter-7WHE5UGY.mjs} +2 -1
  3. package/dist/{WechatChannelAdapter-WSDKR4OA.mjs.map → WechatChannelAdapter-7WHE5UGY.mjs.map} +1 -1
  4. package/dist/{a2a-7N3WDAOP.mjs → a2a-FGYX2HH3.mjs} +71 -32
  5. package/dist/a2a-FGYX2HH3.mjs.map +1 -0
  6. package/dist/{a2a-standard-WC2BSOFV.mjs → a2a-standard-VEQBXBMM.mjs} +93 -115
  7. package/dist/a2a-standard-VEQBXBMM.mjs.map +1 -0
  8. package/dist/agentProvider-X4FVQPKW.mjs +88 -0
  9. package/dist/agentProvider-X4FVQPKW.mjs.map +1 -0
  10. package/dist/chunk-2POW27EI.mjs +27 -0
  11. package/dist/chunk-2POW27EI.mjs.map +1 -0
  12. package/dist/chunk-52SUWMOX.mjs +121 -0
  13. package/dist/chunk-52SUWMOX.mjs.map +1 -0
  14. package/dist/chunk-GF4GGTWJ.mjs +164 -0
  15. package/dist/chunk-GF4GGTWJ.mjs.map +1 -0
  16. package/dist/{chunk-2HOCF46L.mjs → chunk-GPHOYR3X.mjs} +33 -11
  17. package/dist/chunk-GPHOYR3X.mjs.map +1 -0
  18. package/dist/chunk-NFEGQTCC.mjs +27 -0
  19. package/dist/chunk-PWHUWFXL.mjs +173 -0
  20. package/dist/chunk-PWHUWFXL.mjs.map +1 -0
  21. package/dist/chunk-QUT2DS4R.mjs +50 -0
  22. package/dist/chunk-QUT2DS4R.mjs.map +1 -0
  23. package/dist/chunk-TJAUXMYJ.mjs +109 -0
  24. package/dist/chunk-TJAUXMYJ.mjs.map +1 -0
  25. package/dist/chunk-WKNZ7GBC.mjs +56 -0
  26. package/dist/chunk-WKNZ7GBC.mjs.map +1 -0
  27. package/dist/collection_service-RTRJEQFL.mjs +8 -0
  28. package/dist/embed/agent-chat-loader.js +1 -1
  29. package/dist/embed/{embed-page-AgentDetailSideApp-6CVXM3P3.js → embed-page-AgentDetailSideApp-KGYKTMZR.js} +1 -1
  30. package/dist/embed/{embed-page-AgentDetailSideApp-DRGKJ6C5.css → embed-page-AgentDetailSideApp-O6G4NJ7I.css} +1 -1
  31. package/dist/embed/{embed-page-AgentGovernanceWorkbench-4B3NJPCY.js → embed-page-AgentGovernanceWorkbench-F42AJH77.js} +1 -1
  32. package/dist/embed/embed-page-AgentGovernanceWorkbench-SFZNVMUH.css +1 -0
  33. package/dist/embed/embed-page-MessageGraph-ACHQORG7.js +6 -0
  34. package/dist/embed/{embed-page-ReactChart-OG5Z43H7.js → embed-page-ReactChart-FGUHXBED.js} +1 -1
  35. package/dist/embed/{embed-page-SkillFlow-GS4OUCJJ.js → embed-page-SkillFlow-SFZ5HLMK.js} +1 -1
  36. package/dist/embed/{embed-page-TasksSideApp-I6Z7BOT2.js → embed-page-TasksSideApp-4GY5YBTN.js} +1 -1
  37. package/dist/embed/{embed-page-TeamWorkspace-LSCUIJDA.js → embed-page-TeamWorkspace-YWE6ZTLB.js} +4 -4
  38. package/dist/embed/{embed-page-TopologyRuntimeView-RY7NOUB7.js → embed-page-TopologyRuntimeView-MKFPCHT3.js} +1 -1
  39. package/dist/embed/{embed-page-WorkflowAutomationView-RNKIKDUX.js → embed-page-WorkflowAutomationView-WT6VH5HD.js} +1 -1
  40. package/dist/embed/{embed-page-chunk-7CFGO35V.js → embed-page-chunk-3PY2YGBU.js} +1 -1
  41. package/dist/embed/embed-page-chunk-3WXEO6CG.js +245 -0
  42. package/dist/embed/embed-page-chunk-42S7N5Y5.js +4084 -0
  43. package/dist/embed/{embed-page-chunk-SU5GXLKX.js → embed-page-chunk-67U2KZFL.js} +4 -4
  44. package/dist/embed/{embed-page-chunk-4X5XHAMX.js → embed-page-chunk-74BPRLSV.js} +4 -4
  45. package/dist/embed/{embed-page-chunk-DVHOG6AY.js → embed-page-chunk-AC6X2XRH.js} +1 -1
  46. package/dist/embed/{embed-page-chunk-4BIOW547.js → embed-page-chunk-FDID7LZP.js} +1 -1
  47. package/dist/embed/{embed-page-chunk-JLWIJ4BP.js → embed-page-chunk-FU2KMTSK.js} +1 -1
  48. package/dist/embed/{embed-page-chunk-EPEKIAZP.js → embed-page-chunk-HS5VQFWH.js} +1 -1
  49. package/dist/embed/{embed-page-chunk-Q32Y7CP2.js → embed-page-chunk-IV5C4DYL.js} +1 -1
  50. package/dist/embed/{embed-page-chunk-KGX7G7XQ.js → embed-page-chunk-KEL6XU6R.js} +1 -1
  51. package/dist/embed/{embed-page-chunk-AYOVLRHX.js → embed-page-chunk-MGZK7ELC.js} +94 -69
  52. package/dist/embed/{embed-page-chunk-BZI3YCE7.js → embed-page-chunk-N46WJ2FS.js} +1 -1
  53. package/dist/embed/{embed-page-chunk-KG5A66WX.js → embed-page-chunk-O4QK5LWZ.js} +83 -83
  54. package/dist/embed/{embed-page-chunk-ESLOGPBN.js → embed-page-chunk-Z7USDLHI.js} +1 -1
  55. package/dist/embed/{embed-page-code-highlighter-TBT4ICNZ.js → embed-page-code-highlighter-Y6CQA4CN.js} +1 -1
  56. package/dist/embed/{embed-page-mermaid-TBO3M7GX.js → embed-page-mermaid-CW4QCAH3.js} +1 -1
  57. package/dist/embed/embed-page.css +1 -1
  58. package/dist/embed/embed-page.js +1 -1
  59. package/dist/index.js +2074 -619
  60. package/dist/index.js.map +1 -1
  61. package/dist/index.mjs +345 -346
  62. package/dist/index.mjs.map +1 -1
  63. package/dist/kbProvider-2D6DZ34N.mjs +50 -0
  64. package/dist/kbProvider-2D6DZ34N.mjs.map +1 -0
  65. package/dist/{mcp-configs-IIKQM5GM.mjs → mcp-configs-WCY5EXCW.mjs} +2 -1
  66. package/dist/mcp-configs-WCY5EXCW.mjs.map +1 -0
  67. package/dist/{mcpTransportRegistry-XMJ5Y2RG.mjs → mcpTransportRegistry-VXUVJKBC.mjs} +2 -1
  68. package/dist/mcpTransportRegistry-VXUVJKBC.mjs.map +1 -0
  69. package/dist/open-HH7RKGML.mjs +260 -0
  70. package/dist/open-HH7RKGML.mjs.map +1 -0
  71. package/dist/open-audit-UJ3NXCGW.mjs +32 -0
  72. package/dist/open-audit-UJ3NXCGW.mjs.map +1 -0
  73. package/dist/open-catalog-WYS2AENM.mjs +59 -0
  74. package/dist/open-catalog-WYS2AENM.mjs.map +1 -0
  75. package/dist/open-exposure-FK4G6O6L.mjs +67 -0
  76. package/dist/open-exposure-FK4G6O6L.mjs.map +1 -0
  77. package/dist/open-files-GVRMK5PL.mjs +146 -0
  78. package/dist/open-files-GVRMK5PL.mjs.map +1 -0
  79. package/dist/open-session-3VN65PRR.mjs +53 -0
  80. package/dist/open-session-3VN65PRR.mjs.map +1 -0
  81. package/dist/openLattice-GAAGQJST.mjs +16 -0
  82. package/dist/openLattice-GAAGQJST.mjs.map +1 -0
  83. package/dist/registerExposedPlugins-63EUF4VS.mjs +99 -0
  84. package/dist/registerExposedPlugins-63EUF4VS.mjs.map +1 -0
  85. package/dist/{resources-VA7LSDKN.mjs → resources-SRQRKW5G.mjs} +47 -4
  86. package/dist/resources-SRQRKW5G.mjs.map +1 -0
  87. package/dist/sandboxProvider-I3P66VXT.mjs +10 -0
  88. package/dist/sandboxProvider-I3P66VXT.mjs.map +1 -0
  89. package/dist/{sender-PX32VSHB.mjs → sender-PLDU5EZ3.mjs} +3 -1
  90. package/dist/{sender-PX32VSHB.mjs.map → sender-PLDU5EZ3.mjs.map} +1 -1
  91. package/package.json +7 -7
  92. package/dist/a2a-7N3WDAOP.mjs.map +0 -1
  93. package/dist/a2a-standard-WC2BSOFV.mjs.map +0 -1
  94. package/dist/chunk-2HOCF46L.mjs.map +0 -1
  95. package/dist/embed/embed-page-chunk-A2LQIHX4.js +0 -261
  96. package/dist/embed/embed-page-chunk-OWGBADV6.js +0 -3880
  97. package/dist/open-DCAOL5CG.mjs +0 -176
  98. package/dist/open-DCAOL5CG.mjs.map +0 -1
  99. package/dist/resources-VA7LSDKN.mjs.map +0 -1
  100. /package/dist/{A2AAuthService-DK5X6VIL.mjs.map → A2AAuthService-7UGQ7GMW.mjs.map} +0 -0
  101. /package/dist/{mcp-configs-IIKQM5GM.mjs.map → chunk-NFEGQTCC.mjs.map} +0 -0
  102. /package/dist/{mcpTransportRegistry-XMJ5Y2RG.mjs.map → collection_service-RTRJEQFL.mjs.map} +0 -0
  103. /package/dist/embed/{embed-page-AgentGovernanceWorkbench-SDS3GBCC.css → embed-page-MessageGraph-TYOOATYV.css} +0 -0
@@ -0,0 +1,164 @@
1
+ // src/services/open/openLattice.ts
2
+ import { z } from "zod";
3
+ var GrantDeniedError = class extends Error {
4
+ constructor(toolName) {
5
+ super(`GRANT_DENIED: no grant covers ${toolName}`);
6
+ this.code = "GRANT_DENIED";
7
+ this.name = "GrantDeniedError";
8
+ }
9
+ };
10
+ var ValidationError = class extends Error {
11
+ constructor(detail) {
12
+ super(`VALIDATION_FAILED: ${detail}`);
13
+ this.code = "VALIDATION_FAILED";
14
+ this.name = "ValidationError";
15
+ }
16
+ };
17
+ var ActionNotFoundError = class extends Error {
18
+ constructor(toolName) {
19
+ super(`ACTION_NOT_FOUND: ${toolName}`);
20
+ this.code = "ACTION_NOT_FOUND";
21
+ this.name = "ActionNotFoundError";
22
+ }
23
+ };
24
+ function effectiveToolName(domain, action) {
25
+ return action.toolName ?? `${domain}_${action.name}`;
26
+ }
27
+ function grantCoversAction(grants, domain, action) {
28
+ return grants.some(
29
+ (g) => g.domain === domain && (!g.items || g.items.length === 0 || g.items.includes(action))
30
+ );
31
+ }
32
+ var OpenLattice = class {
33
+ constructor() {
34
+ this.providers = /* @__PURE__ */ new Map();
35
+ }
36
+ /** Register a provider; domain+action collisions are rejected. */
37
+ register(declaration) {
38
+ const existing = this.providers.get(declaration.domain);
39
+ if (existing) {
40
+ throw new Error(
41
+ `Open provider domain already registered: ${declaration.domain}`
42
+ );
43
+ }
44
+ const actions = /* @__PURE__ */ new Map();
45
+ for (const action of declaration.actions) {
46
+ actions.set(action.name, action);
47
+ }
48
+ this.providers.set(declaration.domain, { declaration, actions });
49
+ }
50
+ /** Tool descriptors visible under the given grants (default-deny). */
51
+ async catalogFor(grants, ctx) {
52
+ const catalog = [];
53
+ for (const [domain, entry] of this.providers) {
54
+ for (const [actionName, action] of entry.actions) {
55
+ if (!grantCoversAction(grants, domain, actionName)) continue;
56
+ catalog.push({
57
+ toolName: effectiveToolName(domain, action),
58
+ domain,
59
+ action: actionName,
60
+ description: action.description,
61
+ schema: action.schema,
62
+ annotations: action.annotations
63
+ });
64
+ }
65
+ if (entry.declaration.instanceActions) {
66
+ const instances = await entry.declaration.instanceActions(grants, ctx);
67
+ for (const action of instances) {
68
+ catalog.push({
69
+ toolName: effectiveToolName(domain, action),
70
+ domain,
71
+ action: action.name,
72
+ description: action.description,
73
+ schema: action.schema,
74
+ annotations: action.annotations
75
+ });
76
+ }
77
+ }
78
+ }
79
+ return catalog;
80
+ }
81
+ /**
82
+ * Full grantable catalog (unfiltered by grants) for the management picker.
83
+ * Instance domains (agent) return an empty item list — the catalog service
84
+ * fills their per-tenant instances.
85
+ */
86
+ describeCatalog() {
87
+ const domains = [];
88
+ for (const [domain, entry] of this.providers) {
89
+ const declaration = entry.declaration;
90
+ const items = [];
91
+ if ((declaration.itemKind ?? "action") === "action") {
92
+ for (const [actionName, action] of entry.actions) {
93
+ items.push({
94
+ id: actionName,
95
+ toolName: `${domain}_${actionName}`,
96
+ label: action.label ?? actionName,
97
+ description: action.description,
98
+ annotations: action.annotations
99
+ });
100
+ }
101
+ }
102
+ domains.push({
103
+ domain,
104
+ label: declaration.label ?? domain,
105
+ source: declaration.source ?? "builtin",
106
+ scopeKind: declaration.scopeKind ?? "tenant",
107
+ itemKind: declaration.itemKind ?? "action",
108
+ items
109
+ });
110
+ }
111
+ return domains;
112
+ }
113
+ async resolveAction(grants, toolName, ctx) {
114
+ for (const [domain, entry] of this.providers) {
115
+ for (const [actionName, action] of entry.actions) {
116
+ if (effectiveToolName(domain, action) === toolName) {
117
+ return { domain, entry, action, actionName };
118
+ }
119
+ }
120
+ if (entry.declaration.instanceActions) {
121
+ const instances = await entry.declaration.instanceActions(grants, ctx);
122
+ for (const action of instances) {
123
+ if (effectiveToolName(domain, action) === toolName) {
124
+ return { domain, entry, action, actionName: action.name };
125
+ }
126
+ }
127
+ }
128
+ }
129
+ return null;
130
+ }
131
+ /** Whether the given grants cover a tool (`{domain}_{action}`). */
132
+ isAllowed(grants, toolName) {
133
+ const sep = toolName.indexOf("_");
134
+ const domain = sep > 0 ? toolName.slice(0, sep) : toolName;
135
+ const action = sep > 0 ? toolName.slice(sep + 1) : "";
136
+ return grantCoversAction(grants, domain, action);
137
+ }
138
+ /** The single credential-driven execution path. */
139
+ async invoke(grants, ctx, toolName, args) {
140
+ const resolved = await this.resolveAction(grants, toolName, { tenantId: ctx.tenantId });
141
+ if (!resolved) {
142
+ throw new ActionNotFoundError(toolName);
143
+ }
144
+ if (!grantCoversAction(grants, resolved.domain, resolved.actionName)) {
145
+ throw new GrantDeniedError(toolName);
146
+ }
147
+ const resolvedSchema = resolved.action.schema;
148
+ const parsed = "safeParse" in resolvedSchema ? resolvedSchema.safeParse(args) : z.object(resolvedSchema).safeParse(args);
149
+ if (!parsed.success) {
150
+ throw new ValidationError(parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; "));
151
+ }
152
+ return resolved.entry.declaration.execute(resolved.actionName, parsed.data, ctx);
153
+ }
154
+ };
155
+ var openLattice = new OpenLattice();
156
+
157
+ export {
158
+ GrantDeniedError,
159
+ ValidationError,
160
+ ActionNotFoundError,
161
+ OpenLattice,
162
+ openLattice
163
+ };
164
+ //# sourceMappingURL=chunk-GF4GGTWJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/open/openLattice.ts"],"sourcesContent":["/**\n * OpenLattice — the registry + invocation kernel for the Open API surface.\n *\n * Every credential-driven execution flows through exactly one path:\n * catalogFor(grants) → what the credential may see\n * invoke(grants, ...) → authorize → validate → execute → result\n *\n * Built-in providers (kb, sandbox, agent) and plugin-exposed tools all\n * register the same OpenProviderDeclaration contract.\n */\n\nimport { z } from \"zod\";\nimport type {\n OpenCapabilitySource,\n OpenCatalogDomain,\n OpenCatalogItem,\n OpenExecutionContext,\n OpenExecutionResult,\n OpenGrant,\n} from \"@axiom-lattice/protocols\";\n\nexport interface OpenActionDeclaration {\n name: string;\n /** Explicit MCP tool name override (defaults to `{domain}_{name}`). */\n toolName?: string;\n /** Friendly display label (falls back to the action name). */\n label?: string;\n description: string;\n schema: z.ZodRawShape | z.ZodTypeAny;\n annotations: { readOnlyHint: boolean; destructiveHint: boolean };\n}\n\n/** Request-scoped context available while deriving the catalog. */\nexport interface OpenCatalogContext {\n tenantId?: string;\n}\n\nexport interface OpenProviderDeclaration {\n domain: string;\n /** Human label for the management catalog (defaults to domain). */\n label?: string;\n /** Catalog provenance (defaults to \"builtin\"). */\n source?: OpenCapabilitySource;\n /** \"action\" (kb/plugins) or \"instance\" (agent); defaults to \"action\". */\n itemKind?: \"action\" | \"instance\";\n /** Display-only scope hint (defaults to \"tenant\"). */\n scopeKind?: \"tenant\" | \"workspace\" | \"project\";\n actions: OpenActionDeclaration[];\n /**\n * Dynamic actions derived from the credential's grants — used by instance\n * domains (e.g. agent: one tool per granted assistant).\n */\n instanceActions?: (grants: OpenGrant[], ctx?: OpenCatalogContext) => OpenActionDeclaration[] | Promise<OpenActionDeclaration[]>;\n execute: (\n action: string,\n args: unknown,\n ctx: OpenExecutionContext,\n ) => Promise<OpenExecutionResult>;\n}\n\nexport interface OpenToolDescriptor {\n /** MCP tool name, \"{domain}_{action}\". */\n toolName: string;\n domain: string;\n action: string;\n description: string;\n schema: z.ZodRawShape | z.ZodTypeAny;\n annotations: { readOnlyHint: boolean; destructiveHint: boolean };\n}\n\n/** Thrown when a credential has no grant covering the requested action. */\nexport class GrantDeniedError extends Error {\n readonly code = \"GRANT_DENIED\";\n constructor(toolName: string) {\n super(`GRANT_DENIED: no grant covers ${toolName}`);\n this.name = \"GrantDeniedError\";\n }\n}\n\n/** Thrown when args fail the action's zod schema. */\nexport class ValidationError extends Error {\n readonly code = \"VALIDATION_FAILED\";\n constructor(detail: string) {\n super(`VALIDATION_FAILED: ${detail}`);\n this.name = \"ValidationError\";\n }\n}\n\n/** Thrown for a toolName with no registered provider/action. */\nexport class ActionNotFoundError extends Error {\n readonly code = \"ACTION_NOT_FOUND\";\n constructor(toolName: string) {\n super(`ACTION_NOT_FOUND: ${toolName}`);\n this.name = \"ActionNotFoundError\";\n }\n}\n\ninterface RegisteredProvider {\n declaration: OpenProviderDeclaration;\n actions: Map<string, OpenActionDeclaration>;\n}\n\n/** Effective MCP tool name: explicit override, else `{domain}_{name}`. */\nfunction effectiveToolName(domain: string, action: OpenActionDeclaration): string {\n return action.toolName ?? `${domain}_${action.name}`;\n}\n\nfunction grantCoversAction(\n grants: OpenGrant[],\n domain: string,\n action: string,\n): boolean {\n return grants.some(\n (g) => g.domain === domain && (!g.items || g.items.length === 0 || g.items.includes(action)),\n );\n}\n\nexport class OpenLattice {\n private providers = new Map<string, RegisteredProvider>();\n\n /** Register a provider; domain+action collisions are rejected. */\n register(declaration: OpenProviderDeclaration): void {\n const existing = this.providers.get(declaration.domain);\n if (existing) {\n throw new Error(\n `Open provider domain already registered: ${declaration.domain}`,\n );\n }\n const actions = new Map<string, OpenActionDeclaration>();\n for (const action of declaration.actions) {\n actions.set(action.name, action);\n }\n this.providers.set(declaration.domain, { declaration, actions });\n }\n\n /** Tool descriptors visible under the given grants (default-deny). */\n async catalogFor(grants: OpenGrant[], ctx?: OpenCatalogContext): Promise<OpenToolDescriptor[]> {\n const catalog: OpenToolDescriptor[] = [];\n for (const [domain, entry] of this.providers) {\n // Static actions.\n for (const [actionName, action] of entry.actions) {\n if (!grantCoversAction(grants, domain, actionName)) continue;\n catalog.push({\n toolName: effectiveToolName(domain, action),\n domain,\n action: actionName,\n description: action.description,\n schema: action.schema,\n annotations: action.annotations,\n });\n }\n // Instance-derived actions (e.g. agent: one tool per granted assistant).\n if (entry.declaration.instanceActions) {\n const instances = await entry.declaration.instanceActions(grants, ctx);\n for (const action of instances) {\n catalog.push({\n toolName: effectiveToolName(domain, action),\n domain,\n action: action.name,\n description: action.description,\n schema: action.schema,\n annotations: action.annotations,\n });\n }\n }\n }\n return catalog;\n }\n\n /**\n * Full grantable catalog (unfiltered by grants) for the management picker.\n * Instance domains (agent) return an empty item list — the catalog service\n * fills their per-tenant instances.\n */\n describeCatalog(): OpenCatalogDomain[] {\n const domains: OpenCatalogDomain[] = [];\n for (const [domain, entry] of this.providers) {\n const declaration = entry.declaration;\n const items: OpenCatalogItem[] = [];\n if ((declaration.itemKind ?? \"action\") === \"action\") {\n for (const [actionName, action] of entry.actions) {\n items.push({\n id: actionName,\n toolName: `${domain}_${actionName}`,\n label: action.label ?? actionName,\n description: action.description,\n annotations: action.annotations,\n });\n }\n }\n domains.push({\n domain,\n label: declaration.label ?? domain,\n source: declaration.source ?? \"builtin\",\n scopeKind: declaration.scopeKind ?? \"tenant\",\n itemKind: declaration.itemKind ?? \"action\",\n items,\n });\n }\n return domains;\n }\n\n private async resolveAction(\n grants: OpenGrant[],\n toolName: string,\n ctx?: OpenCatalogContext,\n ): Promise<{\n domain: string;\n entry: RegisteredProvider;\n action: OpenActionDeclaration;\n /** Grant-matching id: the action name (assistant id for agent instances). */\n actionName: string;\n } | null> {\n for (const [domain, entry] of this.providers) {\n for (const [actionName, action] of entry.actions) {\n if (effectiveToolName(domain, action) === toolName) {\n return { domain, entry, action, actionName };\n }\n }\n if (entry.declaration.instanceActions) {\n const instances = await entry.declaration.instanceActions(grants, ctx);\n for (const action of instances) {\n if (effectiveToolName(domain, action) === toolName) {\n return { domain, entry, action, actionName: action.name };\n }\n }\n }\n }\n return null;\n }\n\n /** Whether the given grants cover a tool (`{domain}_{action}`). */\n isAllowed(grants: OpenGrant[], toolName: string): boolean {\n const sep = toolName.indexOf(\"_\");\n const domain = sep > 0 ? toolName.slice(0, sep) : toolName;\n const action = sep > 0 ? toolName.slice(sep + 1) : \"\";\n return grantCoversAction(grants, domain, action);\n }\n\n /** The single credential-driven execution path. */\n async invoke(\n grants: OpenGrant[],\n ctx: OpenExecutionContext,\n toolName: string,\n args: unknown,\n ): Promise<OpenExecutionResult> {\n const resolved = await this.resolveAction(grants, toolName, { tenantId: ctx.tenantId });\n if (!resolved) {\n throw new ActionNotFoundError(toolName);\n }\n if (!grantCoversAction(grants, resolved.domain, resolved.actionName)) {\n throw new GrantDeniedError(toolName);\n }\n const resolvedSchema = resolved.action.schema;\n const parsed = (\n \"safeParse\" in resolvedSchema\n ? (resolvedSchema as z.ZodTypeAny).safeParse(args)\n : z.object(resolvedSchema as z.ZodRawShape).safeParse(args)\n );\n if (!parsed.success) {\n throw new ValidationError(parsed.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \"));\n }\n return resolved.entry.declaration.execute(resolved.actionName, parsed.data, ctx);\n }\n}\n\n/** Process-wide singleton for the gateway's Open surface. */\nexport const openLattice = new OpenLattice();\n"],"mappings":"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","names":[]}
@@ -1,4 +1,5 @@
1
1
  // src/services/a2a/A2AAuthService.ts
2
+ import { effectiveGrants } from "@axiom-lattice/protocols";
2
3
  var A2AAuthError = class extends Error {
3
4
  constructor(message, statusCode) {
4
5
  super(message);
@@ -72,20 +73,26 @@ var A2AAuthService = class {
72
73
  const merged = new Map([...this.envKeyMap, ...storeMap]);
73
74
  const entry = merged.get(token);
74
75
  if (!entry) return { authenticated: false };
76
+ const hasExplicitGrants = Array.isArray(entry.grants) && entry.grants.length > 0;
77
+ const agentGrant = effectiveGrants(entry).find((g) => g.domain === "agent");
78
+ const assistantIds = hasExplicitGrants ? agentGrant?.items ?? [] : entry.assistantIds;
75
79
  return {
76
80
  authenticated: true,
77
81
  apiKey: token,
78
82
  tenantId: entry.tenantId,
79
83
  projectId: entry.projectId,
80
- assistantIds: entry.assistantIds,
84
+ assistantIds,
81
85
  source: header && BEARER_SCHEME_RE.test(header) ? "bearer" : "x-api-key"
82
86
  };
83
87
  }
84
88
  /**
85
- * Assert that the given assistant is reachable under the provided auth context:
86
- * authenticated, within the key's assistant whitelist, same tenant, and exposed.
89
+ * Assert that the given assistant is reachable under the provided auth
90
+ * context: authenticated, same tenant, and within the key's whitelist.
91
+ *
92
+ * Authorization is unified on the API key — the agent no longer carries an
93
+ * exposure flag; the key's assistant whitelist / grants is the single source.
87
94
  */
88
- async assertExposedAgent(auth, assistantId) {
95
+ async assertAgentAccess(auth, assistantId) {
89
96
  if (!auth.authenticated || !auth.tenantId) {
90
97
  throw new A2AAuthError("Unauthorized", 401);
91
98
  }
@@ -94,12 +101,9 @@ var A2AAuthService = class {
94
101
  throw new A2AAuthError("Agent not found", 404);
95
102
  }
96
103
  const whitelist = auth.assistantIds;
97
- if (whitelist && whitelist.length > 0 && !whitelist.includes(assistantId)) {
104
+ if (whitelist !== void 0 && !whitelist.includes(assistantId)) {
98
105
  throw new A2AAuthError("Agent not allowed for this key", 403);
99
106
  }
100
- if (assistant.graphDefinition?.a2aExposure?.enabled !== true) {
101
- throw new A2AAuthError("Agent not exposed", 404);
102
- }
103
107
  return assistant;
104
108
  }
105
109
  /**
@@ -107,7 +111,7 @@ var A2AAuthService = class {
107
111
  * in the tenant and every assistant belongs to the same tenant.
108
112
  */
109
113
  async createKeyScoped(input) {
110
- const { tenantId, projectId, assistantIds, label } = input;
114
+ const { tenantId, projectId, assistantIds, grants, label } = input;
111
115
  if (!projectId) {
112
116
  throw new A2AAuthError("projectId is required", 400);
113
117
  }
@@ -123,7 +127,25 @@ var A2AAuthService = class {
123
127
  }
124
128
  }
125
129
  }
126
- return this.keyStore.create({ tenantId, projectId, assistantIds, label });
130
+ return this.keyStore.create({ tenantId, projectId, assistantIds, grants, label });
131
+ }
132
+ async updateKeyScoped(id, tenantId, input) {
133
+ const { projectId, assistantIds, grants, label } = input;
134
+ if (projectId) {
135
+ const project = await this.projectStore.getProjectById(tenantId, projectId);
136
+ if (!project || project.tenantId !== tenantId) {
137
+ throw new A2AAuthError("Project not found", 400);
138
+ }
139
+ }
140
+ if (assistantIds && assistantIds.length > 0) {
141
+ for (const aId of assistantIds) {
142
+ const assistant = await this.assistantStore.getAssistantById(tenantId, aId);
143
+ if (!assistant || assistant.tenantId !== tenantId) {
144
+ throw new A2AAuthError("Assistant not found", 400);
145
+ }
146
+ }
147
+ }
148
+ return this.keyStore.update(id, { label, projectId, assistantIds, grants });
127
149
  }
128
150
  extractToken(header) {
129
151
  if (!header) return void 0;
@@ -140,4 +162,4 @@ export {
140
162
  parseEnvKeys,
141
163
  A2AAuthService
142
164
  };
143
- //# sourceMappingURL=chunk-2HOCF46L.mjs.map
165
+ //# sourceMappingURL=chunk-GPHOYR3X.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/a2a/A2AAuthService.ts"],"sourcesContent":["import { effectiveGrants } from \"@axiom-lattice/protocols\";\nimport type {\n A2AApiKeyEntry,\n A2AApiKeyRecord,\n A2AApiKeyStore,\n A2AAuthContext,\n Assistant,\n AssistantStore,\n ProjectStore,\n OpenGrant,\n} from \"@axiom-lattice/protocols\";\n\n/**\n * Error thrown by {@link A2AAuthService} for authz/authn failures.\n * Carries an HTTP status code for the route layer to surface.\n */\nexport class A2AAuthError extends Error {\n public readonly statusCode: number;\n\n constructor(message: string, statusCode: number) {\n super(message);\n this.name = \"A2AAuthError\";\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Dependencies injected into {@link A2AAuthService} so stores can be mocked in tests.\n */\nexport interface A2AAuthServiceDeps {\n keyStore: A2AApiKeyStore;\n assistantStore: AssistantStore;\n projectStore: ProjectStore;\n envKeyMap?: Map<string, A2AApiKeyEntry>;\n /**\n * When true, requests with no key are allowed through when no keys are\n * configured (dev mode). Defaults to false — JSON-RPC stays locked until a\n * key is configured or this opt-in is explicitly enabled.\n */\n allowUnauthenticated?: boolean;\n}\n\nexport interface UpdateKeyScopedInput {\n label?: string;\n projectId?: string;\n assistantIds?: string[];\n grants?: OpenGrant[];\n}\n\n/** Input for creating an API key scoped to a tenant + project. */\nexport interface CreateKeyScopedInput {\n tenantId: string;\n projectId?: string;\n assistantIds?: string[];\n /** Open-door grants (validated minimally; unknown domains simply never match). */\n grants?: OpenGrant[];\n label?: string;\n}\n\nconst DEFAULT_TENANT_ENV = \"A2A_DEFAULT_TENANT_ID\";\nconst DEFAULT_TENANT_ID = \"a2a-default-tenant\";\nconst DEFAULT_PROJECT_ENV = \"A2A_DEFAULT_PROJECT_ID\";\n\n/** Matches an HTTP `Authorization` Bearer scheme, case-insensitively (`bearer`/`Bearer`). */\nconst BEARER_SCHEME_RE = /^Bearer\\s+/i;\n\n/**\n * Parse an `A2A_API_KEYS=\"key:tenant:project,...\"` env string into a lookup map.\n * Entries missing a key, tenant, or project segment are skipped.\n */\nexport function parseEnvKeys(env: string): Map<string, A2AApiKeyEntry> {\n const map = new Map<string, A2AApiKeyEntry>();\n\n if (!env) return map;\n\n for (const entry of env.split(\",\")) {\n const trimmed = entry.trim();\n if (!trimmed) continue;\n\n const parts = trimmed.split(\":\");\n const key = parts[0]?.trim();\n const tenantId = parts[1]?.trim();\n const projectId = parts[2]?.trim();\n if (!key || !tenantId || !projectId) continue;\n\n map.set(key, { key, tenantId, projectId });\n }\n\n return map;\n}\n\n/**\n * Resolve the dev-mode default tenant/project when no keys are configured.\n */\nfunction devModeDefaults(): { tenantId: string; projectId?: string } {\n const tenantId = process.env[DEFAULT_TENANT_ENV] || DEFAULT_TENANT_ID;\n const projectId = process.env[DEFAULT_PROJECT_ENV] || undefined;\n return { tenantId, projectId };\n}\n\n/**\n * Authenticates A2A requests against the key store + env key map,\n * enforces assistant whitelist / exposure, and validates key scope on creation.\n */\nexport class A2AAuthService {\n private readonly keyStore: A2AApiKeyStore;\n private readonly assistantStore: AssistantStore;\n private readonly projectStore: ProjectStore;\n private readonly envKeyMap: Map<string, A2AApiKeyEntry>;\n /** Lazily-populated store key map; reloaded via {@link refresh} after keys CRUD. */\n private storeKeyMapCache: Map<string, A2AApiKeyEntry> | null = null;\n private readonly allowUnauthenticated: boolean;\n\n constructor(deps: A2AAuthServiceDeps) {\n this.keyStore = deps.keyStore;\n this.assistantStore = deps.assistantStore;\n this.projectStore = deps.projectStore;\n this.envKeyMap = deps.envKeyMap ?? new Map();\n this.allowUnauthenticated = deps.allowUnauthenticated ?? false;\n }\n\n /**\n * Reload the cached store key map. Call once at startup and after any keys\n * CRUD mutation so {@link authenticate} does not hit the store on every request.\n */\n async refresh(): Promise<void> {\n this.storeKeyMapCache = await this.keyStore.loadIntoMap();\n }\n\n /** Return the cached store key map, loading it on first use. */\n private async getStoreKeyMap(): Promise<Map<string, A2AApiKeyEntry>> {\n if (this.storeKeyMapCache === null) {\n await this.refresh();\n }\n return this.storeKeyMapCache ?? new Map<string, A2AApiKeyEntry>();\n }\n\n /**\n * Authenticate an incoming request header (authorization or x-api-key value).\n * Returns an auth context; `authenticated: false` means the caller must reject.\n */\n async authenticate(header: string | undefined): Promise<A2AAuthContext> {\n const storeMap = await this.getStoreKeyMap();\n const noAuthRequired = storeMap.size === 0 && this.envKeyMap.size === 0;\n\n const token = this.extractToken(header);\n\n if (!token) {\n if (noAuthRequired && this.allowUnauthenticated) {\n const { tenantId, projectId } = devModeDefaults();\n return { authenticated: true, tenantId, projectId };\n }\n return { authenticated: false };\n }\n\n // Store keys take priority; env keys serve as fallback.\n const merged = new Map<string, A2AApiKeyEntry>([...this.envKeyMap, ...storeMap]);\n const entry = merged.get(token);\n\n if (!entry) return { authenticated: false };\n\n // Unified key management: the agent whitelist comes from the key's grants\n // when present, else the legacy assistantIds.\n //\n // - explicit grants: agent access only if an agent-domain grant exists\n // (missing agent grant => empty whitelist => no agents);\n // - bare agent grant (no items) => undefined => legacy \"all agents\";\n // - no grants: fall back to legacy assistantIds (undefined => all agents).\n const hasExplicitGrants = Array.isArray(entry.grants) && entry.grants.length > 0;\n const agentGrant = effectiveGrants(entry).find((g) => g.domain === \"agent\");\n const assistantIds = hasExplicitGrants\n ? (agentGrant?.items ?? [])\n : entry.assistantIds;\n\n return {\n authenticated: true,\n apiKey: token,\n tenantId: entry.tenantId,\n projectId: entry.projectId,\n assistantIds,\n source: header && BEARER_SCHEME_RE.test(header) ? \"bearer\" : \"x-api-key\",\n };\n }\n\n /**\n * Assert that the given assistant is reachable under the provided auth\n * context: authenticated, same tenant, and within the key's whitelist.\n *\n * Authorization is unified on the API key — the agent no longer carries an\n * exposure flag; the key's assistant whitelist / grants is the single source.\n */\n async assertAgentAccess(auth: A2AAuthContext, assistantId: string): Promise<Assistant> {\n if (!auth.authenticated || !auth.tenantId) {\n throw new A2AAuthError(\"Unauthorized\", 401);\n }\n\n const assistant = await this.assistantStore.getAssistantById(auth.tenantId, assistantId);\n if (!assistant || assistant.tenantId !== auth.tenantId) {\n throw new A2AAuthError(\"Agent not found\", 404);\n }\n\n // undefined = legacy \"all agents\"; [] = explicitly none; list = whitelist.\n const whitelist = auth.assistantIds;\n if (whitelist !== undefined && !whitelist.includes(assistantId)) {\n throw new A2AAuthError(\"Agent not allowed for this key\", 403);\n }\n\n return assistant;\n }\n\n /**\n * Create an API key scoped to a tenant + project, validating the project exists\n * in the tenant and every assistant belongs to the same tenant.\n */\n async createKeyScoped(input: CreateKeyScopedInput): Promise<A2AApiKeyRecord> {\n const { tenantId, projectId, assistantIds, grants, label } = input;\n\n if (!projectId) {\n throw new A2AAuthError(\"projectId is required\", 400);\n }\n\n const project = await this.projectStore.getProjectById(tenantId, projectId);\n if (!project || project.tenantId !== tenantId) {\n throw new A2AAuthError(\"Project not found\", 400);\n }\n\n if (assistantIds && assistantIds.length > 0) {\n for (const id of assistantIds) {\n const assistant = await this.assistantStore.getAssistantById(tenantId, id);\n if (!assistant || assistant.tenantId !== tenantId) {\n throw new A2AAuthError(\"Assistant not found\", 400);\n }\n }\n }\n\n return this.keyStore.create({ tenantId, projectId, assistantIds, grants, label });\n }\n\n async updateKeyScoped(\n id: string,\n tenantId: string,\n input: UpdateKeyScopedInput,\n ): Promise<A2AApiKeyRecord> {\n const { projectId, assistantIds, grants, label } = input;\n if (projectId) {\n const project = await this.projectStore.getProjectById(tenantId, projectId);\n if (!project || project.tenantId !== tenantId) {\n throw new A2AAuthError(\"Project not found\", 400);\n }\n }\n if (assistantIds && assistantIds.length > 0) {\n for (const aId of assistantIds) {\n const assistant = await this.assistantStore.getAssistantById(tenantId, aId);\n if (!assistant || assistant.tenantId !== tenantId) {\n throw new A2AAuthError(\"Assistant not found\", 400);\n }\n }\n }\n return this.keyStore.update(id, { label, projectId, assistantIds, grants });\n }\n\n private extractToken(header: string | undefined): string | undefined {\n if (!header) return undefined;\n const match = BEARER_SCHEME_RE.exec(header);\n if (match) {\n return header.substring(match[0].length);\n }\n return header;\n }\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AAgBzB,IAAM,eAAN,cAA2B,MAAM;AAAA,EAGtC,YAAY,SAAiB,YAAoB;AAC/C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAmCA,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB;AAC1B,IAAM,sBAAsB;AAG5B,IAAM,mBAAmB;AAMlB,SAAS,aAAa,KAA0C;AACrE,QAAM,MAAM,oBAAI,IAA4B;AAE5C,MAAI,CAAC,IAAK,QAAO;AAEjB,aAAW,SAAS,IAAI,MAAM,GAAG,GAAG;AAClC,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,QAAS;AAEd,UAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,UAAM,MAAM,MAAM,CAAC,GAAG,KAAK;AAC3B,UAAM,WAAW,MAAM,CAAC,GAAG,KAAK;AAChC,UAAM,YAAY,MAAM,CAAC,GAAG,KAAK;AACjC,QAAI,CAAC,OAAO,CAAC,YAAY,CAAC,UAAW;AAErC,QAAI,IAAI,KAAK,EAAE,KAAK,UAAU,UAAU,CAAC;AAAA,EAC3C;AAEA,SAAO;AACT;AAKA,SAAS,kBAA4D;AACnE,QAAM,WAAW,QAAQ,IAAI,kBAAkB,KAAK;AACpD,QAAM,YAAY,QAAQ,IAAI,mBAAmB,KAAK;AACtD,SAAO,EAAE,UAAU,UAAU;AAC/B;AAMO,IAAM,iBAAN,MAAqB;AAAA,EAS1B,YAAY,MAA0B;AAHtC;AAAA,SAAQ,mBAAuD;AAI7D,SAAK,WAAW,KAAK;AACrB,SAAK,iBAAiB,KAAK;AAC3B,SAAK,eAAe,KAAK;AACzB,SAAK,YAAY,KAAK,aAAa,oBAAI,IAAI;AAC3C,SAAK,uBAAuB,KAAK,wBAAwB;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAyB;AAC7B,SAAK,mBAAmB,MAAM,KAAK,SAAS,YAAY;AAAA,EAC1D;AAAA;AAAA,EAGA,MAAc,iBAAuD;AACnE,QAAI,KAAK,qBAAqB,MAAM;AAClC,YAAM,KAAK,QAAQ;AAAA,IACrB;AACA,WAAO,KAAK,oBAAoB,oBAAI,IAA4B;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAAa,QAAqD;AACtE,UAAM,WAAW,MAAM,KAAK,eAAe;AAC3C,UAAM,iBAAiB,SAAS,SAAS,KAAK,KAAK,UAAU,SAAS;AAEtE,UAAM,QAAQ,KAAK,aAAa,MAAM;AAEtC,QAAI,CAAC,OAAO;AACV,UAAI,kBAAkB,KAAK,sBAAsB;AAC/C,cAAM,EAAE,UAAU,UAAU,IAAI,gBAAgB;AAChD,eAAO,EAAE,eAAe,MAAM,UAAU,UAAU;AAAA,MACpD;AACA,aAAO,EAAE,eAAe,MAAM;AAAA,IAChC;AAGA,UAAM,SAAS,IAAI,IAA4B,CAAC,GAAG,KAAK,WAAW,GAAG,QAAQ,CAAC;AAC/E,UAAM,QAAQ,OAAO,IAAI,KAAK;AAE9B,QAAI,CAAC,MAAO,QAAO,EAAE,eAAe,MAAM;AAS1C,UAAM,oBAAoB,MAAM,QAAQ,MAAM,MAAM,KAAK,MAAM,OAAO,SAAS;AAC/E,UAAM,aAAa,gBAAgB,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,OAAO;AAC1E,UAAM,eAAe,oBAChB,YAAY,SAAS,CAAC,IACvB,MAAM;AAEV,WAAO;AAAA,MACL,eAAe;AAAA,MACf,QAAQ;AAAA,MACR,UAAU,MAAM;AAAA,MAChB,WAAW,MAAM;AAAA,MACjB;AAAA,MACA,QAAQ,UAAU,iBAAiB,KAAK,MAAM,IAAI,WAAW;AAAA,IAC/D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,kBAAkB,MAAsB,aAAyC;AACrF,QAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,UAAU;AACzC,YAAM,IAAI,aAAa,gBAAgB,GAAG;AAAA,IAC5C;AAEA,UAAM,YAAY,MAAM,KAAK,eAAe,iBAAiB,KAAK,UAAU,WAAW;AACvF,QAAI,CAAC,aAAa,UAAU,aAAa,KAAK,UAAU;AACtD,YAAM,IAAI,aAAa,mBAAmB,GAAG;AAAA,IAC/C;AAGA,UAAM,YAAY,KAAK;AACvB,QAAI,cAAc,UAAa,CAAC,UAAU,SAAS,WAAW,GAAG;AAC/D,YAAM,IAAI,aAAa,kCAAkC,GAAG;AAAA,IAC9D;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBAAgB,OAAuD;AAC3E,UAAM,EAAE,UAAU,WAAW,cAAc,QAAQ,MAAM,IAAI;AAE7D,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,aAAa,yBAAyB,GAAG;AAAA,IACrD;AAEA,UAAM,UAAU,MAAM,KAAK,aAAa,eAAe,UAAU,SAAS;AAC1E,QAAI,CAAC,WAAW,QAAQ,aAAa,UAAU;AAC7C,YAAM,IAAI,aAAa,qBAAqB,GAAG;AAAA,IACjD;AAEA,QAAI,gBAAgB,aAAa,SAAS,GAAG;AAC3C,iBAAW,MAAM,cAAc;AAC7B,cAAM,YAAY,MAAM,KAAK,eAAe,iBAAiB,UAAU,EAAE;AACzE,YAAI,CAAC,aAAa,UAAU,aAAa,UAAU;AACjD,gBAAM,IAAI,aAAa,uBAAuB,GAAG;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAEA,WAAO,KAAK,SAAS,OAAO,EAAE,UAAU,WAAW,cAAc,QAAQ,MAAM,CAAC;AAAA,EAClF;AAAA,EAEA,MAAM,gBACJ,IACA,UACA,OAC0B;AAC1B,UAAM,EAAE,WAAW,cAAc,QAAQ,MAAM,IAAI;AACnD,QAAI,WAAW;AACb,YAAM,UAAU,MAAM,KAAK,aAAa,eAAe,UAAU,SAAS;AAC1E,UAAI,CAAC,WAAW,QAAQ,aAAa,UAAU;AAC7C,cAAM,IAAI,aAAa,qBAAqB,GAAG;AAAA,MACjD;AAAA,IACF;AACA,QAAI,gBAAgB,aAAa,SAAS,GAAG;AAC3C,iBAAW,OAAO,cAAc;AAC9B,cAAM,YAAY,MAAM,KAAK,eAAe,iBAAiB,UAAU,GAAG;AAC1E,YAAI,CAAC,aAAa,UAAU,aAAa,UAAU;AACjD,gBAAM,IAAI,aAAa,uBAAuB,GAAG;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK,SAAS,OAAO,IAAI,EAAE,OAAO,WAAW,cAAc,OAAO,CAAC;AAAA,EAC5E;AAAA,EAEQ,aAAa,QAAgD;AACnE,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,QAAQ,iBAAiB,KAAK,MAAM;AAC1C,QAAI,OAAO;AACT,aAAO,OAAO,UAAU,MAAM,CAAC,EAAE,MAAM;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -0,0 +1,27 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __esm = (fn, res) => function __init() {
6
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
7
+ };
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ export {
23
+ __esm,
24
+ __export,
25
+ __toCommonJS
26
+ };
27
+ //# sourceMappingURL=chunk-NFEGQTCC.mjs.map
@@ -0,0 +1,173 @@
1
+ // src/services/collection_service.ts
2
+ import { v4 as uuidv4 } from "uuid";
3
+ import { Document } from "@langchain/core/documents";
4
+ import {
5
+ collectionLatticeManager,
6
+ embeddingsLatticeManager,
7
+ getOrCreateCollectionVectorStore,
8
+ getCollectionEntryCount,
9
+ listCollectionEntries,
10
+ removeCollectionVectorStore
11
+ } from "@axiom-lattice/core";
12
+ function getTenantId(request) {
13
+ return request.user?.tenantId || request.headers["x-tenant-id"] || "default";
14
+ }
15
+ var CollectionService = class {
16
+ // ─── Collection CRUD ──────────────────────────────────────────
17
+ async getAllCollections(request) {
18
+ const tenantId = getTenantId(request);
19
+ const collections = await collectionLatticeManager.getAllCollections(tenantId);
20
+ for (const c of collections) {
21
+ try {
22
+ c._entryCount = await getCollectionEntryCount(c.name, c.embeddingKey, c.tenantId);
23
+ } catch {
24
+ c._entryCount = 0;
25
+ }
26
+ }
27
+ return collections;
28
+ }
29
+ async getCollectionByName(request, name) {
30
+ const tenantId = getTenantId(request);
31
+ return collectionLatticeManager.getCollection(tenantId, name);
32
+ }
33
+ async createCollection(request, data) {
34
+ const tenantId = getTenantId(request);
35
+ const collection = await collectionLatticeManager.registerCollection(tenantId, data);
36
+ try {
37
+ await getOrCreateCollectionVectorStore(data.name, data.embeddingKey, tenantId);
38
+ } catch (err) {
39
+ console.warn(`[CollectionService] Failed to init vector store for ${data.name}:`, err);
40
+ }
41
+ return collection;
42
+ }
43
+ async updateCollection(request, name, updates) {
44
+ const tenantId = getTenantId(request);
45
+ return collectionLatticeManager.updateCollection(tenantId, name, updates);
46
+ }
47
+ async deleteCollection(request, name) {
48
+ const tenantId = getTenantId(request);
49
+ await removeCollectionVectorStore(name, tenantId);
50
+ return collectionLatticeManager.removeCollection(tenantId, name);
51
+ }
52
+ // ─── Entry CRUD ───────────────────────────────────────────────
53
+ async getEntries(request, collectionName) {
54
+ const collection = await this.getCollectionByName(request, collectionName);
55
+ if (!collection) throw new Error(`Collection "${collectionName}" not found`);
56
+ const docs = await listCollectionEntries(collectionName, collection.embeddingKey, collection.tenantId);
57
+ return docs.map((doc) => ({
58
+ id: doc.metadata._id || "",
59
+ content: doc.pageContent,
60
+ metadata: Object.fromEntries(
61
+ Object.entries(doc.metadata).filter(([k]) => !k.startsWith("_"))
62
+ )
63
+ }));
64
+ }
65
+ async createEntry(request, collectionName, data) {
66
+ const collection = await this.getCollectionByName(request, collectionName);
67
+ if (!collection) throw new Error(`Collection "${collectionName}" not found`);
68
+ const vectorStore = await getOrCreateCollectionVectorStore(
69
+ collectionName,
70
+ collection.embeddingKey,
71
+ collection.tenantId
72
+ );
73
+ const entryId = uuidv4();
74
+ const now = (/* @__PURE__ */ new Date()).toISOString();
75
+ const doc = new Document({
76
+ pageContent: data.content,
77
+ metadata: {
78
+ _id: entryId,
79
+ _created_at: now,
80
+ _updated_at: now,
81
+ ...data.metadata || {}
82
+ }
83
+ });
84
+ await vectorStore.addDocuments([doc]);
85
+ return { id: entryId, content: data.content, metadata: data.metadata || {} };
86
+ }
87
+ async getEntry(request, collectionName, entryId) {
88
+ const collection = await this.getCollectionByName(request, collectionName);
89
+ if (!collection) throw new Error(`Collection "${collectionName}" not found`);
90
+ const docs = await listCollectionEntries(collectionName, collection.embeddingKey, collection.tenantId);
91
+ const doc = docs.find((d) => d.metadata._id === entryId);
92
+ if (!doc) return null;
93
+ return {
94
+ id: entryId,
95
+ content: doc.pageContent,
96
+ metadata: Object.fromEntries(
97
+ Object.entries(doc.metadata).filter(([k]) => !k.startsWith("_"))
98
+ )
99
+ };
100
+ }
101
+ async updateEntry(request, collectionName, entryId, data) {
102
+ const existing = await this.getEntry(request, collectionName, entryId);
103
+ if (!existing) return null;
104
+ const collection = await this.getCollectionByName(request, collectionName);
105
+ if (!collection) throw new Error(`Collection "${collectionName}" not found`);
106
+ const vectorStore = await getOrCreateCollectionVectorStore(
107
+ collectionName,
108
+ collection.embeddingKey,
109
+ collection.tenantId
110
+ );
111
+ try {
112
+ await vectorStore.delete({ filter: { _id: entryId } });
113
+ } catch {
114
+ }
115
+ const now = (/* @__PURE__ */ new Date()).toISOString();
116
+ const mergedMetadata = { ...existing.metadata, ...data.metadata || {} };
117
+ const doc = new Document({
118
+ pageContent: data.content ?? existing.content,
119
+ metadata: { _id: entryId, _created_at: now, _updated_at: now, ...mergedMetadata }
120
+ });
121
+ await vectorStore.addDocuments([doc]);
122
+ return { id: entryId, content: data.content ?? existing.content, metadata: mergedMetadata };
123
+ }
124
+ async deleteEntry(request, collectionName, entryId) {
125
+ const collection = await this.getCollectionByName(request, collectionName);
126
+ if (!collection) throw new Error(`Collection "${collectionName}" not found`);
127
+ const vectorStore = await getOrCreateCollectionVectorStore(
128
+ collectionName,
129
+ collection.embeddingKey,
130
+ collection.tenantId
131
+ );
132
+ try {
133
+ await vectorStore.delete({ filter: { _id: entryId } });
134
+ return true;
135
+ } catch {
136
+ return false;
137
+ }
138
+ }
139
+ async searchEntries(request, collectionName, params) {
140
+ const collection = await this.getCollectionByName(request, collectionName);
141
+ if (!collection) throw new Error(`Collection "${collectionName}" not found`);
142
+ const vectorStore = await getOrCreateCollectionVectorStore(
143
+ collectionName,
144
+ collection.embeddingKey,
145
+ collection.tenantId
146
+ );
147
+ let embeddings;
148
+ try {
149
+ embeddings = embeddingsLatticeManager.getEmbeddingsClient(collection.embeddingKey);
150
+ } catch {
151
+ embeddings = embeddingsLatticeManager.getEmbeddingsClient("default");
152
+ }
153
+ const queryVector = await embeddings.embedQuery(params.query);
154
+ const results = await vectorStore.similaritySearchVectorWithScore(
155
+ queryVector,
156
+ params.top_k || 5,
157
+ params.filter
158
+ );
159
+ return results.map(([doc, score]) => ({
160
+ id: doc.metadata._id || uuidv4(),
161
+ content: doc.pageContent,
162
+ metadata: Object.fromEntries(
163
+ Object.entries(doc.metadata).filter(([k]) => !k.startsWith("_"))
164
+ ),
165
+ score
166
+ }));
167
+ }
168
+ };
169
+
170
+ export {
171
+ CollectionService
172
+ };
173
+ //# sourceMappingURL=chunk-PWHUWFXL.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/collection_service.ts"],"sourcesContent":["/**\n * CollectionService\n *\n * Business logic layer for collection management and entry operations.\n * Uses CollectionLatticeManager for registration, VectorStoreLatticeManager for storage,\n * and EmbeddingsLatticeManager for vector embedding.\n * All vector store operations are tenant-isolated.\n */\n\nimport { v4 as uuidv4 } from \"uuid\";\nimport { Document } from \"@langchain/core/documents\";\nimport {\n collectionLatticeManager,\n embeddingsLatticeManager,\n getOrCreateCollectionVectorStore,\n getCollectionEntryCount,\n listCollectionEntries,\n removeCollectionVectorStore,\n} from \"@axiom-lattice/core\";\nimport type {\n Collection,\n CreateCollectionRequest,\n UpdateCollectionRequest,\n} from \"@axiom-lattice/protocols\";\nimport { FastifyRequest } from \"fastify\";\n\nfunction getTenantId(request: FastifyRequest): string {\n return (\n (request as any).user?.tenantId ||\n (request.headers[\"x-tenant-id\"] as string) ||\n \"default\"\n );\n}\n\nexport interface EntryResponse {\n id: string;\n content: string;\n metadata: Record<string, unknown>;\n score?: number;\n}\n\nexport class CollectionService {\n // ─── Collection CRUD ──────────────────────────────────────────\n\n async getAllCollections(request: FastifyRequest): Promise<Collection[]> {\n const tenantId = getTenantId(request);\n const collections = await collectionLatticeManager.getAllCollections(tenantId);\n\n for (const c of collections) {\n try {\n (c as any)._entryCount = await getCollectionEntryCount(c.name, c.embeddingKey, c.tenantId);\n } catch {\n (c as any)._entryCount = 0;\n }\n }\n\n return collections;\n }\n\n async getCollectionByName(\n request: FastifyRequest,\n name: string\n ): Promise<Collection | null> {\n const tenantId = getTenantId(request);\n return collectionLatticeManager.getCollection(tenantId, name);\n }\n\n async createCollection(\n request: FastifyRequest,\n data: CreateCollectionRequest\n ): Promise<Collection> {\n const tenantId = getTenantId(request);\n const collection = await collectionLatticeManager.registerCollection(tenantId, data);\n\n try {\n await getOrCreateCollectionVectorStore(data.name, data.embeddingKey, tenantId);\n } catch (err) {\n console.warn(`[CollectionService] Failed to init vector store for ${data.name}:`, err);\n }\n\n return collection;\n }\n\n async updateCollection(\n request: FastifyRequest,\n name: string,\n updates: UpdateCollectionRequest\n ): Promise<Collection | null> {\n const tenantId = getTenantId(request);\n return collectionLatticeManager.updateCollection(tenantId, name, updates);\n }\n\n async deleteCollection(\n request: FastifyRequest,\n name: string\n ): Promise<boolean> {\n const tenantId = getTenantId(request);\n await removeCollectionVectorStore(name, tenantId);\n return collectionLatticeManager.removeCollection(tenantId, name);\n }\n\n // ─── Entry CRUD ───────────────────────────────────────────────\n\n async getEntries(\n request: FastifyRequest,\n collectionName: string\n ): Promise<EntryResponse[]> {\n const collection = await this.getCollectionByName(request, collectionName);\n if (!collection) throw new Error(`Collection \"${collectionName}\" not found`);\n\n const docs = await listCollectionEntries(collectionName, collection.embeddingKey, collection.tenantId);\n\n return docs.map((doc: Document) => ({\n id: (doc.metadata._id as string) || \"\",\n content: doc.pageContent,\n metadata: Object.fromEntries(\n Object.entries(doc.metadata).filter(([k]) => !k.startsWith(\"_\"))\n ),\n }));\n }\n\n async createEntry(\n request: FastifyRequest,\n collectionName: string,\n data: { content: string; metadata?: Record<string, unknown> }\n ): Promise<EntryResponse> {\n const collection = await this.getCollectionByName(request, collectionName);\n if (!collection) throw new Error(`Collection \"${collectionName}\" not found`);\n\n const vectorStore = await getOrCreateCollectionVectorStore(\n collectionName, collection.embeddingKey, collection.tenantId\n );\n\n const entryId = uuidv4();\n const now = new Date().toISOString();\n const doc = new Document({\n pageContent: data.content,\n metadata: {\n _id: entryId,\n _created_at: now,\n _updated_at: now,\n ...(data.metadata || {}),\n },\n });\n\n await vectorStore.addDocuments([doc]);\n\n return { id: entryId, content: data.content, metadata: data.metadata || {} };\n }\n\n async getEntry(\n request: FastifyRequest,\n collectionName: string,\n entryId: string\n ): Promise<EntryResponse | null> {\n const collection = await this.getCollectionByName(request, collectionName);\n if (!collection) throw new Error(`Collection \"${collectionName}\" not found`);\n\n const docs = await listCollectionEntries(collectionName, collection.embeddingKey, collection.tenantId);\n const doc = docs.find((d: Document) => d.metadata._id === entryId);\n if (!doc) return null;\n return {\n id: entryId,\n content: doc.pageContent,\n metadata: Object.fromEntries(\n Object.entries(doc.metadata).filter(([k]) => !k.startsWith(\"_\"))\n ),\n };\n }\n\n async updateEntry(\n request: FastifyRequest,\n collectionName: string,\n entryId: string,\n data: { content?: string; metadata?: Record<string, unknown> }\n ): Promise<EntryResponse | null> {\n const existing = await this.getEntry(request, collectionName, entryId);\n if (!existing) return null;\n\n const collection = await this.getCollectionByName(request, collectionName);\n if (!collection) throw new Error(`Collection \"${collectionName}\" not found`);\n\n const vectorStore = await getOrCreateCollectionVectorStore(\n collectionName, collection.embeddingKey, collection.tenantId\n );\n\n try {\n await vectorStore.delete({ filter: { _id: entryId } } as any);\n } catch {\n // best effort\n }\n\n const now = new Date().toISOString();\n const mergedMetadata = { ...existing.metadata, ...(data.metadata || {}) };\n const doc = new Document({\n pageContent: data.content ?? existing.content,\n metadata: { _id: entryId, _created_at: now, _updated_at: now, ...mergedMetadata },\n });\n\n await vectorStore.addDocuments([doc]);\n\n return { id: entryId, content: data.content ?? existing.content, metadata: mergedMetadata };\n }\n\n async deleteEntry(\n request: FastifyRequest,\n collectionName: string,\n entryId: string\n ): Promise<boolean> {\n const collection = await this.getCollectionByName(request, collectionName);\n if (!collection) throw new Error(`Collection \"${collectionName}\" not found`);\n\n const vectorStore = await getOrCreateCollectionVectorStore(\n collectionName, collection.embeddingKey, collection.tenantId\n );\n\n try {\n await vectorStore.delete({ filter: { _id: entryId } } as any);\n return true;\n } catch {\n return false;\n }\n }\n\n async searchEntries(\n request: FastifyRequest,\n collectionName: string,\n params: { query: string; filter?: Record<string, unknown>; top_k?: number }\n ): Promise<EntryResponse[]> {\n const collection = await this.getCollectionByName(request, collectionName);\n if (!collection) throw new Error(`Collection \"${collectionName}\" not found`);\n\n const vectorStore = await getOrCreateCollectionVectorStore(\n collectionName, collection.embeddingKey, collection.tenantId\n );\n\n let embeddings;\n try {\n embeddings = embeddingsLatticeManager.getEmbeddingsClient(collection.embeddingKey);\n } catch {\n embeddings = embeddingsLatticeManager.getEmbeddingsClient(\"default\");\n }\n\n const queryVector = await embeddings.embedQuery(params.query);\n const results = await vectorStore.similaritySearchVectorWithScore(\n queryVector, params.top_k || 5, params.filter as any\n );\n\n return results.map(([doc, score]: [Document, number]) => ({\n id: (doc.metadata._id as string) || uuidv4(),\n content: doc.pageContent,\n metadata: Object.fromEntries(\n Object.entries(doc.metadata).filter(([k]) => !k.startsWith(\"_\"))\n ),\n score,\n }));\n }\n}\n"],"mappings":";AASA,SAAS,MAAM,cAAc;AAC7B,SAAS,gBAAgB;AACzB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAQP,SAAS,YAAY,SAAiC;AACpD,SACG,QAAgB,MAAM,YACtB,QAAQ,QAAQ,aAAa,KAC9B;AAEJ;AASO,IAAM,oBAAN,MAAwB;AAAA;AAAA,EAG7B,MAAM,kBAAkB,SAAgD;AACtE,UAAM,WAAW,YAAY,OAAO;AACpC,UAAM,cAAc,MAAM,yBAAyB,kBAAkB,QAAQ;AAE7E,eAAW,KAAK,aAAa;AAC3B,UAAI;AACF,QAAC,EAAU,cAAc,MAAM,wBAAwB,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ;AAAA,MAC3F,QAAQ;AACN,QAAC,EAAU,cAAc;AAAA,MAC3B;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,oBACJ,SACA,MAC4B;AAC5B,UAAM,WAAW,YAAY,OAAO;AACpC,WAAO,yBAAyB,cAAc,UAAU,IAAI;AAAA,EAC9D;AAAA,EAEA,MAAM,iBACJ,SACA,MACqB;AACrB,UAAM,WAAW,YAAY,OAAO;AACpC,UAAM,aAAa,MAAM,yBAAyB,mBAAmB,UAAU,IAAI;AAEnF,QAAI;AACF,YAAM,iCAAiC,KAAK,MAAM,KAAK,cAAc,QAAQ;AAAA,IAC/E,SAAS,KAAK;AACZ,cAAQ,KAAK,uDAAuD,KAAK,IAAI,KAAK,GAAG;AAAA,IACvF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,iBACJ,SACA,MACA,SAC4B;AAC5B,UAAM,WAAW,YAAY,OAAO;AACpC,WAAO,yBAAyB,iBAAiB,UAAU,MAAM,OAAO;AAAA,EAC1E;AAAA,EAEA,MAAM,iBACJ,SACA,MACkB;AAClB,UAAM,WAAW,YAAY,OAAO;AACpC,UAAM,4BAA4B,MAAM,QAAQ;AAChD,WAAO,yBAAyB,iBAAiB,UAAU,IAAI;AAAA,EACjE;AAAA;AAAA,EAIA,MAAM,WACJ,SACA,gBAC0B;AAC1B,UAAM,aAAa,MAAM,KAAK,oBAAoB,SAAS,cAAc;AACzE,QAAI,CAAC,WAAY,OAAM,IAAI,MAAM,eAAe,cAAc,aAAa;AAE3E,UAAM,OAAO,MAAM,sBAAsB,gBAAgB,WAAW,cAAc,WAAW,QAAQ;AAErG,WAAO,KAAK,IAAI,CAAC,SAAmB;AAAA,MAClC,IAAK,IAAI,SAAS,OAAkB;AAAA,MACpC,SAAS,IAAI;AAAA,MACb,UAAU,OAAO;AAAA,QACf,OAAO,QAAQ,IAAI,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC;AAAA,MACjE;AAAA,IACF,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,YACJ,SACA,gBACA,MACwB;AACxB,UAAM,aAAa,MAAM,KAAK,oBAAoB,SAAS,cAAc;AACzE,QAAI,CAAC,WAAY,OAAM,IAAI,MAAM,eAAe,cAAc,aAAa;AAE3E,UAAM,cAAc,MAAM;AAAA,MACxB;AAAA,MAAgB,WAAW;AAAA,MAAc,WAAW;AAAA,IACtD;AAEA,UAAM,UAAU,OAAO;AACvB,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,MAAM,IAAI,SAAS;AAAA,MACvB,aAAa,KAAK;AAAA,MAClB,UAAU;AAAA,QACR,KAAK;AAAA,QACL,aAAa;AAAA,QACb,aAAa;AAAA,QACb,GAAI,KAAK,YAAY,CAAC;AAAA,MACxB;AAAA,IACF,CAAC;AAED,UAAM,YAAY,aAAa,CAAC,GAAG,CAAC;AAEpC,WAAO,EAAE,IAAI,SAAS,SAAS,KAAK,SAAS,UAAU,KAAK,YAAY,CAAC,EAAE;AAAA,EAC7E;AAAA,EAEA,MAAM,SACJ,SACA,gBACA,SAC+B;AAC/B,UAAM,aAAa,MAAM,KAAK,oBAAoB,SAAS,cAAc;AACzE,QAAI,CAAC,WAAY,OAAM,IAAI,MAAM,eAAe,cAAc,aAAa;AAE3E,UAAM,OAAO,MAAM,sBAAsB,gBAAgB,WAAW,cAAc,WAAW,QAAQ;AACrG,UAAM,MAAM,KAAK,KAAK,CAAC,MAAgB,EAAE,SAAS,QAAQ,OAAO;AACjE,QAAI,CAAC,IAAK,QAAO;AACjB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS,IAAI;AAAA,MACb,UAAU,OAAO;AAAA,QACf,OAAO,QAAQ,IAAI,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,YACJ,SACA,gBACA,SACA,MAC+B;AAC/B,UAAM,WAAW,MAAM,KAAK,SAAS,SAAS,gBAAgB,OAAO;AACrE,QAAI,CAAC,SAAU,QAAO;AAEtB,UAAM,aAAa,MAAM,KAAK,oBAAoB,SAAS,cAAc;AACzE,QAAI,CAAC,WAAY,OAAM,IAAI,MAAM,eAAe,cAAc,aAAa;AAE3E,UAAM,cAAc,MAAM;AAAA,MACxB;AAAA,MAAgB,WAAW;AAAA,MAAc,WAAW;AAAA,IACtD;AAEA,QAAI;AACF,YAAM,YAAY,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,CAAQ;AAAA,IAC9D,QAAQ;AAAA,IAER;AAEA,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,iBAAiB,EAAE,GAAG,SAAS,UAAU,GAAI,KAAK,YAAY,CAAC,EAAG;AACxE,UAAM,MAAM,IAAI,SAAS;AAAA,MACvB,aAAa,KAAK,WAAW,SAAS;AAAA,MACtC,UAAU,EAAE,KAAK,SAAS,aAAa,KAAK,aAAa,KAAK,GAAG,eAAe;AAAA,IAClF,CAAC;AAED,UAAM,YAAY,aAAa,CAAC,GAAG,CAAC;AAEpC,WAAO,EAAE,IAAI,SAAS,SAAS,KAAK,WAAW,SAAS,SAAS,UAAU,eAAe;AAAA,EAC5F;AAAA,EAEA,MAAM,YACJ,SACA,gBACA,SACkB;AAClB,UAAM,aAAa,MAAM,KAAK,oBAAoB,SAAS,cAAc;AACzE,QAAI,CAAC,WAAY,OAAM,IAAI,MAAM,eAAe,cAAc,aAAa;AAE3E,UAAM,cAAc,MAAM;AAAA,MACxB;AAAA,MAAgB,WAAW;AAAA,MAAc,WAAW;AAAA,IACtD;AAEA,QAAI;AACF,YAAM,YAAY,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,CAAQ;AAC5D,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,cACJ,SACA,gBACA,QAC0B;AAC1B,UAAM,aAAa,MAAM,KAAK,oBAAoB,SAAS,cAAc;AACzE,QAAI,CAAC,WAAY,OAAM,IAAI,MAAM,eAAe,cAAc,aAAa;AAE3E,UAAM,cAAc,MAAM;AAAA,MACxB;AAAA,MAAgB,WAAW;AAAA,MAAc,WAAW;AAAA,IACtD;AAEA,QAAI;AACJ,QAAI;AACF,mBAAa,yBAAyB,oBAAoB,WAAW,YAAY;AAAA,IACnF,QAAQ;AACN,mBAAa,yBAAyB,oBAAoB,SAAS;AAAA,IACrE;AAEA,UAAM,cAAc,MAAM,WAAW,WAAW,OAAO,KAAK;AAC5D,UAAM,UAAU,MAAM,YAAY;AAAA,MAChC;AAAA,MAAa,OAAO,SAAS;AAAA,MAAG,OAAO;AAAA,IACzC;AAEA,WAAO,QAAQ,IAAI,CAAC,CAAC,KAAK,KAAK,OAA2B;AAAA,MACxD,IAAK,IAAI,SAAS,OAAkB,OAAO;AAAA,MAC3C,SAAS,IAAI;AAAA,MACb,UAAU,OAAO;AAAA,QACf,OAAO,QAAQ,IAAI,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC;AAAA,MACjE;AAAA,MACA;AAAA,IACF,EAAE;AAAA,EACJ;AACF;","names":[]}
@@ -0,0 +1,50 @@
1
+ // src/services/a2a/A2AAgentCardBuilder.ts
2
+ function deriveAgentSkills(assistant) {
3
+ const enabled = assistant.graphDefinition?.middleware?.filter((m) => m.enabled) ?? [];
4
+ return enabled.map((m) => ({
5
+ id: m.type || m.id,
6
+ name: m.name || m.type || m.id,
7
+ description: m.description || "",
8
+ tags: [],
9
+ examples: []
10
+ }));
11
+ }
12
+ function buildAgentCardForAssistant(params) {
13
+ const { assistant, baseUrl } = params;
14
+ const jsonRpcUrl = `${baseUrl}/api/a2a/agents/${assistant.id}/jsonrpc`;
15
+ return {
16
+ name: assistant.name,
17
+ description: assistant.description ?? "",
18
+ url: jsonRpcUrl,
19
+ protocolVersion: "0.3.0",
20
+ version: "1.0.0",
21
+ defaultInputModes: ["text"],
22
+ defaultOutputModes: ["text"],
23
+ capabilities: {
24
+ streaming: true,
25
+ pushNotifications: false,
26
+ stateTransitionHistory: true
27
+ },
28
+ skills: deriveAgentSkills(assistant),
29
+ additionalInterfaces: [{ transport: "JSONRPC", url: jsonRpcUrl }],
30
+ securitySchemes: {
31
+ bearer: {
32
+ type: "http",
33
+ scheme: "Bearer",
34
+ description: "API key sent as an Authorization Bearer token"
35
+ },
36
+ apiKeyHeader: {
37
+ type: "apiKey",
38
+ in: "header",
39
+ name: "x-api-key",
40
+ description: "API key sent via the x-api-key header"
41
+ }
42
+ },
43
+ security: [{ bearer: [] }, { apiKeyHeader: [] }]
44
+ };
45
+ }
46
+
47
+ export {
48
+ buildAgentCardForAssistant
49
+ };
50
+ //# sourceMappingURL=chunk-QUT2DS4R.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/a2a/A2AAgentCardBuilder.ts"],"sourcesContent":["import type { AgentCard, A2ASkill, AgentMiddlewareConfig } from \"@axiom-lattice/protocols\";\n\n/** Minimal assistant shape needed to derive a card from its own definition. */\nexport interface CardAssistant {\n id: string;\n name: string;\n description?: string;\n graphDefinition?: {\n middleware?: AgentMiddlewareConfig[];\n } | null;\n}\n\n/**\n * Parameters for building a per-assistant A2A AgentCard.\n */\nexport interface BuildAgentCardParams {\n assistant: CardAssistant;\n /** Gateway origin, e.g. \"https://gw.example.com\". */\n baseUrl: string;\n}\n\n/**\n * Derive the card's advertised skills from the agent's own definition: every\n * enabled middleware contributes a skill (id = middleware type, name/description\n * from its config). No manual `a2aExposure` declaration — the card reflects\n * what the agent is actually built from.\n */\nexport function deriveAgentSkills(assistant: CardAssistant): A2ASkill[] {\n const enabled = assistant.graphDefinition?.middleware?.filter((m) => m.enabled) ?? [];\n return enabled.map((m) => ({\n id: m.type || m.id,\n name: m.name || m.type || m.id,\n description: m.description || \"\",\n tags: [],\n examples: [],\n }));\n}\n\n/**\n * Build an A2A 0.3 AgentCard (discovery document) for a single assistant.\n *\n * `url` points at the assistant's JSON-RPC endpoint (also advertised via\n * `additionalInterfaces`). Skills are derived from the agent definition;\n * input/output modes default to text.\n */\nexport function buildAgentCardForAssistant(params: BuildAgentCardParams): AgentCard {\n const { assistant, baseUrl } = params;\n const jsonRpcUrl = `${baseUrl}/api/a2a/agents/${assistant.id}/jsonrpc`;\n\n return {\n name: assistant.name,\n description: assistant.description ?? \"\",\n url: jsonRpcUrl,\n protocolVersion: \"0.3.0\",\n version: \"1.0.0\",\n defaultInputModes: [\"text\"],\n defaultOutputModes: [\"text\"],\n capabilities: {\n streaming: true,\n pushNotifications: false,\n stateTransitionHistory: true,\n },\n skills: deriveAgentSkills(assistant),\n additionalInterfaces: [{ transport: \"JSONRPC\", url: jsonRpcUrl }],\n securitySchemes: {\n bearer: {\n type: \"http\",\n scheme: \"Bearer\",\n description: \"API key sent as an Authorization Bearer token\",\n },\n apiKeyHeader: {\n type: \"apiKey\",\n in: \"header\",\n name: \"x-api-key\",\n description: \"API key sent via the x-api-key header\",\n },\n },\n security: [{ bearer: [] }, { apiKeyHeader: [] }],\n };\n}\n"],"mappings":";AA2BO,SAAS,kBAAkB,WAAsC;AACtE,QAAM,UAAU,UAAU,iBAAiB,YAAY,OAAO,CAAC,MAAM,EAAE,OAAO,KAAK,CAAC;AACpF,SAAO,QAAQ,IAAI,CAAC,OAAO;AAAA,IACzB,IAAI,EAAE,QAAQ,EAAE;AAAA,IAChB,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE;AAAA,IAC5B,aAAa,EAAE,eAAe;AAAA,IAC9B,MAAM,CAAC;AAAA,IACP,UAAU,CAAC;AAAA,EACb,EAAE;AACJ;AASO,SAAS,2BAA2B,QAAyC;AAClF,QAAM,EAAE,WAAW,QAAQ,IAAI;AAC/B,QAAM,aAAa,GAAG,OAAO,mBAAmB,UAAU,EAAE;AAE5D,SAAO;AAAA,IACL,MAAM,UAAU;AAAA,IAChB,aAAa,UAAU,eAAe;AAAA,IACtC,KAAK;AAAA,IACL,iBAAiB;AAAA,IACjB,SAAS;AAAA,IACT,mBAAmB,CAAC,MAAM;AAAA,IAC1B,oBAAoB,CAAC,MAAM;AAAA,IAC3B,cAAc;AAAA,MACZ,WAAW;AAAA,MACX,mBAAmB;AAAA,MACnB,wBAAwB;AAAA,IAC1B;AAAA,IACA,QAAQ,kBAAkB,SAAS;AAAA,IACnC,sBAAsB,CAAC,EAAE,WAAW,WAAW,KAAK,WAAW,CAAC;AAAA,IAChE,iBAAiB;AAAA,MACf,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,MACf;AAAA,MACA,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,UAAU,CAAC,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,cAAc,CAAC,EAAE,CAAC;AAAA,EACjD;AACF;","names":[]}