@slashfi/agents-sdk 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/agent-definitions/auth.d.ts.map +1 -1
  2. package/dist/agent-definitions/auth.js +44 -11
  3. package/dist/agent-definitions/auth.js.map +1 -1
  4. package/dist/agent-definitions/integrations.d.ts.map +1 -1
  5. package/dist/agent-definitions/integrations.js +106 -45
  6. package/dist/agent-definitions/integrations.js.map +1 -1
  7. package/dist/agent-definitions/remote-registry.d.ts.map +1 -1
  8. package/dist/agent-definitions/remote-registry.js +174 -45
  9. package/dist/agent-definitions/remote-registry.js.map +1 -1
  10. package/dist/agent-definitions/secrets.d.ts.map +1 -1
  11. package/dist/agent-definitions/secrets.js +1 -4
  12. package/dist/agent-definitions/secrets.js.map +1 -1
  13. package/dist/agent-definitions/users.d.ts.map +1 -1
  14. package/dist/agent-definitions/users.js +14 -3
  15. package/dist/agent-definitions/users.js.map +1 -1
  16. package/dist/define-config.d.ts +125 -0
  17. package/dist/define-config.d.ts.map +1 -0
  18. package/dist/define-config.js +75 -0
  19. package/dist/define-config.js.map +1 -0
  20. package/dist/define.d.ts +11 -2
  21. package/dist/define.d.ts.map +1 -1
  22. package/dist/define.js +57 -26
  23. package/dist/define.js.map +1 -1
  24. package/dist/events.d.ts +133 -0
  25. package/dist/events.d.ts.map +1 -0
  26. package/dist/events.js +57 -0
  27. package/dist/events.js.map +1 -0
  28. package/dist/index.d.ts +16 -8
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +21 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/integration-interface.d.ts +3 -3
  33. package/dist/integration-interface.d.ts.map +1 -1
  34. package/dist/integration-interface.js +29 -21
  35. package/dist/integration-interface.js.map +1 -1
  36. package/dist/integrations-store.d.ts +2 -2
  37. package/dist/integrations-store.d.ts.map +1 -1
  38. package/dist/integrations-store.js +3 -3
  39. package/dist/integrations-store.js.map +1 -1
  40. package/dist/jwt.d.ts.map +1 -1
  41. package/dist/jwt.js +7 -5
  42. package/dist/jwt.js.map +1 -1
  43. package/dist/key-manager.d.ts.map +1 -1
  44. package/dist/key-manager.js +5 -3
  45. package/dist/key-manager.js.map +1 -1
  46. package/dist/oidc-signin.d.ts +32 -0
  47. package/dist/oidc-signin.d.ts.map +1 -0
  48. package/dist/oidc-signin.js +138 -0
  49. package/dist/oidc-signin.js.map +1 -0
  50. package/dist/registry-consumer.d.ts +104 -0
  51. package/dist/registry-consumer.d.ts.map +1 -0
  52. package/dist/registry-consumer.js +230 -0
  53. package/dist/registry-consumer.js.map +1 -0
  54. package/dist/registry.d.ts +5 -0
  55. package/dist/registry.d.ts.map +1 -1
  56. package/dist/registry.js +76 -4
  57. package/dist/registry.js.map +1 -1
  58. package/dist/secret-collection.d.ts.map +1 -1
  59. package/dist/secret-collection.js.map +1 -1
  60. package/dist/server.d.ts +3 -0
  61. package/dist/server.d.ts.map +1 -1
  62. package/dist/server.js +222 -27
  63. package/dist/server.js.map +1 -1
  64. package/dist/test-utils/mock-oidc-server.d.ts +36 -0
  65. package/dist/test-utils/mock-oidc-server.d.ts.map +1 -0
  66. package/dist/test-utils/mock-oidc-server.js +96 -0
  67. package/dist/test-utils/mock-oidc-server.js.map +1 -0
  68. package/dist/types.d.ts +106 -0
  69. package/dist/types.d.ts.map +1 -1
  70. package/package.json +6 -1
  71. package/src/agent-definitions/auth.ts +106 -38
  72. package/src/agent-definitions/integrations.ts +201 -73
  73. package/src/agent-definitions/remote-registry.ts +262 -65
  74. package/src/agent-definitions/secrets.ts +22 -8
  75. package/src/agent-definitions/users.ts +16 -4
  76. package/src/cli.ts +293 -0
  77. package/src/codegen.test.ts +527 -0
  78. package/src/codegen.ts +1348 -0
  79. package/src/consumer.test.ts +536 -0
  80. package/src/define-config.ts +205 -0
  81. package/src/define.ts +134 -46
  82. package/src/events.ts +237 -0
  83. package/src/index.ts +107 -8
  84. package/src/integration-interface.ts +52 -28
  85. package/src/integrations-store.ts +9 -5
  86. package/src/jwt.ts +48 -19
  87. package/src/key-manager.test.ts +22 -13
  88. package/src/key-manager.ts +8 -10
  89. package/src/oidc-signin.ts +223 -0
  90. package/src/registry-consumer.ts +413 -0
  91. package/src/registry.ts +115 -9
  92. package/src/secret-collection.ts +2 -1
  93. package/src/server.test.ts +304 -238
  94. package/src/server.ts +371 -69
  95. package/src/test-utils/mock-oidc-server.ts +123 -0
  96. package/src/types.ts +172 -18
@@ -0,0 +1,138 @@
1
+ /**
2
+ * OIDC Sign-In Provider
3
+ *
4
+ * Implements the full OIDC authorization code flow for user sign-in.
5
+ * The server acts as an OIDC Relying Party — users authenticate with
6
+ * an external Identity Provider and receive a server-signed JWT.
7
+ *
8
+ * Flow:
9
+ * GET /signin/authorize → 302 redirect to IdP
10
+ * GET /signin/callback → exchange code → fetch userinfo → sign JWT → return
11
+ */
12
+ import { signJwtES256 } from "./jwt.js";
13
+ export function createOIDCSignIn(config) {
14
+ let discoveryCache = null;
15
+ const pendingFlows = new Map();
16
+ async function fetchDiscovery() {
17
+ if (discoveryCache)
18
+ return discoveryCache;
19
+ const url = `${config.issuer}/.well-known/openid-configuration`;
20
+ const res = await fetch(url);
21
+ if (!res.ok)
22
+ throw new Error(`OIDC discovery failed: ${res.status}`);
23
+ discoveryCache = (await res.json());
24
+ return discoveryCache;
25
+ }
26
+ function generateState() {
27
+ const bytes = crypto.getRandomValues(new Uint8Array(24));
28
+ return Buffer.from(bytes).toString("base64url");
29
+ }
30
+ return {
31
+ async handleRequest(req, { baseUrl, signingKey, issuerUrl }) {
32
+ const url = new URL(req.url);
33
+ // ── GET /signin/authorize → redirect to IdP ──
34
+ if (url.pathname === "/signin/authorize" && req.method === "GET") {
35
+ const redirectUri = url.searchParams.get("redirect_uri") ?? "";
36
+ if (!redirectUri) {
37
+ return Response.json({
38
+ error: "invalid_request",
39
+ error_description: "Missing redirect_uri",
40
+ }, { status: 400 });
41
+ }
42
+ const discovery = await fetchDiscovery();
43
+ const state = generateState();
44
+ const nonce = generateState();
45
+ pendingFlows.set(state, {
46
+ redirectUri,
47
+ nonce,
48
+ createdAt: Date.now(),
49
+ });
50
+ // Clean up stale flows (> 10 min)
51
+ const now = Date.now();
52
+ for (const [k, v] of pendingFlows) {
53
+ if (now - v.createdAt > 600_000)
54
+ pendingFlows.delete(k);
55
+ }
56
+ const scopes = config.scopes ?? ["openid", "email", "profile"];
57
+ const callbackUrl = `${baseUrl}/signin/callback`;
58
+ const authUrl = new URL(discovery.authorization_endpoint);
59
+ authUrl.searchParams.set("response_type", "code");
60
+ authUrl.searchParams.set("client_id", config.clientId);
61
+ authUrl.searchParams.set("redirect_uri", callbackUrl);
62
+ authUrl.searchParams.set("scope", scopes.join(" "));
63
+ authUrl.searchParams.set("state", state);
64
+ authUrl.searchParams.set("nonce", nonce);
65
+ return Response.redirect(authUrl.toString(), 302);
66
+ }
67
+ // ── GET /signin/callback → exchange code → userinfo → JWT ──
68
+ if (url.pathname === "/signin/callback" && req.method === "GET") {
69
+ const code = url.searchParams.get("code");
70
+ const state = url.searchParams.get("state");
71
+ const error = url.searchParams.get("error");
72
+ if (error) {
73
+ return Response.json({
74
+ error,
75
+ error_description: url.searchParams.get("error_description") ?? "",
76
+ }, { status: 400 });
77
+ }
78
+ if (!code || !state) {
79
+ return Response.json({
80
+ error: "invalid_request",
81
+ error_description: "Missing code or state",
82
+ }, { status: 400 });
83
+ }
84
+ const flow = pendingFlows.get(state);
85
+ if (!flow) {
86
+ return Response.json({
87
+ error: "invalid_state",
88
+ error_description: "Unknown or expired state",
89
+ }, { status: 400 });
90
+ }
91
+ pendingFlows.delete(state);
92
+ const discovery = await fetchDiscovery();
93
+ const callbackUrl = `${baseUrl}/signin/callback`;
94
+ // Exchange code for tokens
95
+ const tokenRes = await fetch(discovery.token_endpoint, {
96
+ method: "POST",
97
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
98
+ body: new URLSearchParams({
99
+ grant_type: "authorization_code",
100
+ code,
101
+ redirect_uri: callbackUrl,
102
+ client_id: config.clientId,
103
+ client_secret: config.clientSecret,
104
+ }),
105
+ });
106
+ if (!tokenRes.ok) {
107
+ const text = await tokenRes.text();
108
+ return Response.json({ error: "token_exchange_failed", error_description: text }, { status: 502 });
109
+ }
110
+ const tokens = (await tokenRes.json());
111
+ // Fetch userinfo
112
+ const userinfoRes = await fetch(discovery.userinfo_endpoint, {
113
+ headers: { Authorization: `Bearer ${tokens.access_token}` },
114
+ });
115
+ if (!userinfoRes.ok) {
116
+ return Response.json({
117
+ error: "userinfo_failed",
118
+ error_description: `Status ${userinfoRes.status}`,
119
+ }, { status: 502 });
120
+ }
121
+ const userinfo = (await userinfoRes.json());
122
+ // Sign server JWT with user's identity
123
+ const jwt = await signJwtES256({
124
+ sub: userinfo.sub ?? "unknown",
125
+ name: userinfo.name ?? "unknown",
126
+ scopes: ["*"],
127
+ iss: issuerUrl,
128
+ }, signingKey.privateKey, signingKey.kid, issuerUrl, "1h");
129
+ // Redirect back to the caller with the JWT
130
+ const sep = flow.redirectUri.includes("?") ? "&" : "?";
131
+ return Response.redirect(`${flow.redirectUri}${sep}token=${jwt}`, 302);
132
+ }
133
+ // Not a signin route
134
+ return null;
135
+ },
136
+ };
137
+ }
138
+ //# sourceMappingURL=oidc-signin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-signin.js","sourceRoot":"","sources":["../src/oidc-signin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAmB,YAAY,EAAE,MAAM,UAAU,CAAC;AAuCzD,MAAM,UAAU,gBAAgB,CAC9B,MAA0B;IAE1B,IAAI,cAAc,GAAyB,IAAI,CAAC;IAChD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAuB,CAAC;IAEpD,KAAK,UAAU,cAAc;QAC3B,IAAI,cAAc;YAAE,OAAO,cAAc,CAAC;QAC1C,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,MAAM,mCAAmC,CAAC;QAChE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACrE,cAAc,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAkB,CAAC;QACrD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,SAAS,aAAa;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;IAED,OAAO;QACL,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE;YACzD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAE7B,gDAAgD;YAChD,IAAI,GAAG,CAAC,QAAQ,KAAK,mBAAmB,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBACjE,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;gBAC/D,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,OAAO,QAAQ,CAAC,IAAI,CAClB;wBACE,KAAK,EAAE,iBAAiB;wBACxB,iBAAiB,EAAE,sBAAsB;qBAC1C,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;gBACJ,CAAC;gBAED,MAAM,SAAS,GAAG,MAAM,cAAc,EAAE,CAAC;gBACzC,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;gBAC9B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;gBAE9B,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE;oBACtB,WAAW;oBACX,KAAK;oBACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;iBACtB,CAAC,CAAC;gBAEH,kCAAkC;gBAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACvB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,YAAY,EAAE,CAAC;oBAClC,IAAI,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,OAAO;wBAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBAC1D,CAAC;gBAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;gBAC/D,MAAM,WAAW,GAAG,GAAG,OAAO,kBAAkB,CAAC;gBACjD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;gBAC1D,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;gBAClD,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACvD,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;gBACtD,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBACpD,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACzC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBAEzC,OAAO,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;YACpD,CAAC;YAED,8DAA8D;YAC9D,IAAI,GAAG,CAAC,QAAQ,KAAK,kBAAkB,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBAChE,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAE5C,IAAI,KAAK,EAAE,CAAC;oBACV,OAAO,QAAQ,CAAC,IAAI,CAClB;wBACE,KAAK;wBACL,iBAAiB,EACf,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE;qBAClD,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBACpB,OAAO,QAAQ,CAAC,IAAI,CAClB;wBACE,KAAK,EAAE,iBAAiB;wBACxB,iBAAiB,EAAE,uBAAuB;qBAC3C,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;gBACJ,CAAC;gBAED,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACrC,IAAI,CAAC,IAAI,EAAE,CAAC;oBACV,OAAO,QAAQ,CAAC,IAAI,CAClB;wBACE,KAAK,EAAE,eAAe;wBACtB,iBAAiB,EAAE,0BAA0B;qBAC9C,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;gBACJ,CAAC;gBACD,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAE3B,MAAM,SAAS,GAAG,MAAM,cAAc,EAAE,CAAC;gBACzC,MAAM,WAAW,GAAG,GAAG,OAAO,kBAAkB,CAAC;gBAEjD,2BAA2B;gBAC3B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,cAAc,EAAE;oBACrD,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;oBAChE,IAAI,EAAE,IAAI,eAAe,CAAC;wBACxB,UAAU,EAAE,oBAAoB;wBAChC,IAAI;wBACJ,YAAY,EAAE,WAAW;wBACzB,SAAS,EAAE,MAAM,CAAC,QAAQ;wBAC1B,aAAa,EAAE,MAAM,CAAC,YAAY;qBACnC,CAAC;iBACH,CAAC,CAAC;gBAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;oBACnC,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAC3D,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;gBACJ,CAAC;gBAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6B,CAAC;gBAEnE,iBAAiB;gBACjB,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,iBAAiB,EAAE;oBAC3D,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,CAAC,YAAY,EAAE,EAAE;iBAC5D,CAAC,CAAC;gBAEH,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;oBACpB,OAAO,QAAQ,CAAC,IAAI,CAClB;wBACE,KAAK,EAAE,iBAAiB;wBACxB,iBAAiB,EAAE,UAAU,WAAW,CAAC,MAAM,EAAE;qBAClD,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;gBACJ,CAAC;gBAED,MAAM,QAAQ,GAAG,CAAC,MAAM,WAAW,CAAC,IAAI,EAAE,CAA4B,CAAC;gBAEvE,uCAAuC;gBACvC,MAAM,GAAG,GAAG,MAAM,YAAY,CAC5B;oBACE,GAAG,EAAG,QAAQ,CAAC,GAAc,IAAI,SAAS;oBAC1C,IAAI,EAAG,QAAQ,CAAC,IAAe,IAAI,SAAS;oBAC5C,MAAM,EAAE,CAAC,GAAG,CAAC;oBACb,GAAG,EAAE,SAAS;iBACuB,EACvC,UAAU,CAAC,UAAU,EACrB,UAAU,CAAC,GAAG,EACd,SAAS,EACT,IAAI,CACL,CAAC;gBAEF,2CAA2C;gBAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;gBACvD,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,WAAW,GAAG,GAAG,SAAS,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;YACzE,CAAC;YAED,qBAAqB;YACrB,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Registry Consumer — Connects to registries and resolves refs.
3
+ *
4
+ * The consumer reads a `ConsumerConfig`, discovers registries via
5
+ * `/.well-known/configuration`, resolves refs to agent definitions,
6
+ * and provides a unified interface for calling tools across all connected agents.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { createRegistryConsumer, defineConfig } from '@slashfi/agents-sdk';
11
+ *
12
+ * const config = defineConfig({
13
+ * registries: ['https://registry.slash.com'],
14
+ * refs: ['notion', { ref: 'postgres', as: 'prod-db', config: { url: '...' } }],
15
+ * });
16
+ *
17
+ * const consumer = await createRegistryConsumer(config);
18
+ *
19
+ * // List all available agents across registries
20
+ * const available = await consumer.list();
21
+ *
22
+ * // List configured refs
23
+ * const refs = consumer.refs();
24
+ *
25
+ * // Call a tool on a ref
26
+ * const result = await consumer.call('notion', 'search', { query: 'meeting notes' });
27
+ *
28
+ * // Resolve secrets in config values
29
+ * const dbUrl = await consumer.resolveSecret('https://twin.slash.com/secrets/crdb-url');
30
+ * ```
31
+ */
32
+ import type { ConsumerConfig, RefConfig, ResolvedConfig, ResolvedRef, ResolvedRegistry } from "./define-config.js";
33
+ /** Registry well-known configuration (from /.well-known/configuration) */
34
+ export interface RegistryConfiguration {
35
+ issuer: string;
36
+ jwks_uri?: string;
37
+ token_endpoint?: string;
38
+ agents_endpoint?: string;
39
+ call_endpoint?: string;
40
+ supported_grant_types?: string[];
41
+ /** @deprecated Use agents_endpoint + GET /list instead */
42
+ agents?: string[];
43
+ }
44
+ /** An agent definition as listed by a registry */
45
+ export interface AgentListing {
46
+ /** Agent path (e.g., '@notion') */
47
+ path: string;
48
+ /** Description */
49
+ description?: string;
50
+ /** Publisher (registry name) */
51
+ publisher: string;
52
+ /** Tools available */
53
+ tools?: Array<{
54
+ name: string;
55
+ description?: string;
56
+ }>;
57
+ /** Whether it requires auth */
58
+ requiresAuth?: boolean;
59
+ /** Integration config if applicable */
60
+ integration?: {
61
+ provider: string;
62
+ displayName: string;
63
+ category?: string;
64
+ };
65
+ }
66
+ export type SecretResolver = (uri: string, auth?: {
67
+ token?: string;
68
+ }) => Promise<string>;
69
+ export interface RegistryConsumerOptions {
70
+ /** Override the secret resolver (default: HTTP GET + JWT) */
71
+ resolveSecret?: SecretResolver;
72
+ /** Bearer token for authenticated registries */
73
+ token?: string;
74
+ /** Custom fetch implementation */
75
+ fetch?: typeof globalThis.fetch;
76
+ }
77
+ export interface RegistryConsumer {
78
+ /** List all available agents across all connected registries */
79
+ list(): Promise<AgentListing[]>;
80
+ /** List configured refs (from the consumer's config) */
81
+ refs(): ResolvedRef[];
82
+ /** Get the resolved registries */
83
+ registries(): ResolvedRegistry[];
84
+ /** Call a tool on a configured ref */
85
+ call(refName: string, tool: string, params?: Record<string, unknown>): Promise<unknown>;
86
+ /** Discover a registry's configuration */
87
+ discover(registryUrl: string): Promise<RegistryConfiguration>;
88
+ /** Resolve a secret URL to its value */
89
+ resolveSecret(url: string): Promise<string>;
90
+ /** Resolve all secret URLs in a config object, returning resolved values */
91
+ resolveConfig(config: RefConfig): Promise<Record<string, string | number | boolean>>;
92
+ /** Produce the indexed/serialized config output */
93
+ index(): ResolvedConfig;
94
+ /** Diff: what's available vs what's configured */
95
+ available(): Promise<AgentListing[]>;
96
+ }
97
+ /**
98
+ * Create a registry consumer from a config.
99
+ *
100
+ * The consumer connects to registries, discovers available agents,
101
+ * and provides a unified interface for calling tools.
102
+ */
103
+ export declare function createRegistryConsumer(config: ConsumerConfig, options?: RegistryConsumerOptions): Promise<RegistryConsumer>;
104
+ //# sourceMappingURL=registry-consumer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-consumer.d.ts","sourceRoot":"","sources":["../src/registry-consumer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,cAAc,EACd,WAAW,EACX,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAW5B,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,+BAA+B;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uCAAuC;IACvC,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AASD,MAAM,MAAM,cAAc,GAAG,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,KACtB,OAAO,CAAC,MAAM,CAAC,CAAC;AAoDrB,MAAM,WAAW,uBAAuB;IACtC,6DAA6D;IAC7D,aAAa,CAAC,EAAE,cAAc,CAAC;IAE/B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,kCAAkC;IAClC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAMD,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAEhC,wDAAwD;IACxD,IAAI,IAAI,WAAW,EAAE,CAAC;IAEtB,kCAAkC;IAClC,UAAU,IAAI,gBAAgB,EAAE,CAAC;IAEjC,sCAAsC;IACtC,IAAI,CACF,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAE9D,wCAAwC;IACxC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE5C,4EAA4E;IAC5E,aAAa,CACX,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAEtD,mDAAmD;IACnD,KAAK,IAAI,cAAc,CAAC;IAExB,kDAAkD;IAClD,SAAS,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACtC;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,gBAAgB,CAAC,CAiM3B"}
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Registry Consumer — Connects to registries and resolves refs.
3
+ *
4
+ * The consumer reads a `ConsumerConfig`, discovers registries via
5
+ * `/.well-known/configuration`, resolves refs to agent definitions,
6
+ * and provides a unified interface for calling tools across all connected agents.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { createRegistryConsumer, defineConfig } from '@slashfi/agents-sdk';
11
+ *
12
+ * const config = defineConfig({
13
+ * registries: ['https://registry.slash.com'],
14
+ * refs: ['notion', { ref: 'postgres', as: 'prod-db', config: { url: '...' } }],
15
+ * });
16
+ *
17
+ * const consumer = await createRegistryConsumer(config);
18
+ *
19
+ * // List all available agents across registries
20
+ * const available = await consumer.list();
21
+ *
22
+ * // List configured refs
23
+ * const refs = consumer.refs();
24
+ *
25
+ * // Call a tool on a ref
26
+ * const result = await consumer.call('notion', 'search', { query: 'meeting notes' });
27
+ *
28
+ * // Resolve secrets in config values
29
+ * const dbUrl = await consumer.resolveSecret('https://twin.slash.com/secrets/crdb-url');
30
+ * ```
31
+ */
32
+ import { isSecretUrl, normalizeRef, normalizeRegistry, } from "./define-config.js";
33
+ // ============================================
34
+ // Secret Resolver
35
+ // ============================================
36
+ /** Resolves secret URLs to their values */
37
+ import { readFile } from "node:fs/promises";
38
+ /**
39
+ * Default secret resolver — dispatches on URI scheme:
40
+ * file:// → read from filesystem
41
+ * env:// → read from environment variable
42
+ * https:// → HTTP GET with optional bearer token
43
+ * http:// → HTTP GET (dev only)
44
+ */
45
+ async function defaultSecretResolver(uri, auth) {
46
+ const parsed = new URL(uri);
47
+ switch (parsed.protocol) {
48
+ case "file:": {
49
+ const filePath = parsed.pathname;
50
+ return (await readFile(filePath, "utf-8")).trim();
51
+ }
52
+ case "env:": {
53
+ // env://VAR_NAME or env:///VAR_NAME
54
+ const varName = parsed.hostname || parsed.pathname.replace(/^\//, "");
55
+ const value = process.env[varName];
56
+ if (!value) {
57
+ throw new Error(`Environment variable not set: ${varName}`);
58
+ }
59
+ return value;
60
+ }
61
+ case "https:":
62
+ case "http:": {
63
+ const headers = {};
64
+ if (auth?.token) {
65
+ headers.Authorization = `Bearer ${auth.token}`;
66
+ }
67
+ const res = await fetch(uri, { headers });
68
+ if (!res.ok) {
69
+ throw new Error(`Failed to resolve secret ${uri}: ${res.status} ${res.statusText}`);
70
+ }
71
+ return res.text();
72
+ }
73
+ default:
74
+ throw new Error(`Unsupported secret URI scheme: ${parsed.protocol}`);
75
+ }
76
+ }
77
+ /**
78
+ * Create a registry consumer from a config.
79
+ *
80
+ * The consumer connects to registries, discovers available agents,
81
+ * and provides a unified interface for calling tools.
82
+ */
83
+ export async function createRegistryConsumer(config, options = {}) {
84
+ const fetchFn = options.fetch ?? globalThis.fetch;
85
+ const resolveSecretFn = options.resolveSecret ?? defaultSecretResolver;
86
+ // Normalize registries
87
+ const resolvedRegistries = (config.registries ?? []).map(normalizeRegistry);
88
+ // Normalize refs
89
+ const resolvedRefs = (config.refs ?? []).map((entry) => {
90
+ const normalized = normalizeRef(entry);
91
+ return {
92
+ ref: normalized.ref,
93
+ name: normalized.name,
94
+ registry: normalized.registry ?? resolvedRegistries[0]?.url ?? "unknown",
95
+ config: normalized.config,
96
+ };
97
+ });
98
+ // Cache for registry configurations
99
+ const discoveryCache = new Map();
100
+ // Discover a registry
101
+ async function discover(registryUrl) {
102
+ const cached = discoveryCache.get(registryUrl);
103
+ if (cached)
104
+ return cached;
105
+ const url = `${registryUrl.replace(/\/$/, "")}/.well-known/configuration`;
106
+ const res = await fetchFn(url);
107
+ if (!res.ok) {
108
+ throw new Error(`Failed to discover registry ${registryUrl}: ${res.status}`);
109
+ }
110
+ const configuration = (await res.json());
111
+ discoveryCache.set(registryUrl, configuration);
112
+ return configuration;
113
+ }
114
+ // List agents from a single registry
115
+ async function listFromRegistry(registry) {
116
+ const configuration = await discover(registry.url);
117
+ const listUrl = configuration.agents_endpoint ??
118
+ `${registry.url.replace(/\/$/, "")}/list`;
119
+ const headers = {};
120
+ if (registry.auth.type === "bearer" && "token" in registry.auth) {
121
+ headers.Authorization = `Bearer ${registry.auth.token}`;
122
+ }
123
+ else if (options.token) {
124
+ headers.Authorization = `Bearer ${options.token}`;
125
+ }
126
+ const res = await fetchFn(listUrl, { headers });
127
+ if (!res.ok) {
128
+ throw new Error(`Failed to list agents from ${registry.url}: ${res.status}`);
129
+ }
130
+ const agents = (await res.json());
131
+ return agents.map((agent) => ({
132
+ ...agent,
133
+ publisher: registry.publisher,
134
+ }));
135
+ }
136
+ // Call a tool via a registry
137
+ async function callTool(registry, agentPath, tool, params) {
138
+ const configuration = await discover(registry.url);
139
+ const callUrl = configuration.call_endpoint ?? `${registry.url.replace(/\/$/, "")}/call`;
140
+ const headers = {
141
+ "Content-Type": "application/json",
142
+ };
143
+ if (registry.auth.type === "bearer" && "token" in registry.auth) {
144
+ headers.Authorization = `Bearer ${registry.auth.token}`;
145
+ }
146
+ else if (options.token) {
147
+ headers.Authorization = `Bearer ${options.token}`;
148
+ }
149
+ const res = await fetchFn(callUrl, {
150
+ method: "POST",
151
+ headers,
152
+ body: JSON.stringify({ path: agentPath, tool, params }),
153
+ });
154
+ if (!res.ok) {
155
+ const text = await res.text().catch(() => "unknown error");
156
+ throw new Error(`Tool call failed (${registry.url}/${agentPath}/${tool}): ${res.status} ${text}`);
157
+ }
158
+ return res.json();
159
+ }
160
+ // Build the consumer
161
+ const consumer = {
162
+ async list() {
163
+ const results = await Promise.allSettled(resolvedRegistries.map(listFromRegistry));
164
+ return results.flatMap((r) => (r.status === "fulfilled" ? r.value : []));
165
+ },
166
+ refs() {
167
+ return resolvedRefs;
168
+ },
169
+ registries() {
170
+ return resolvedRegistries;
171
+ },
172
+ async call(refName, tool, params = {}) {
173
+ const ref = resolvedRefs.find((r) => r.name === refName);
174
+ if (!ref) {
175
+ throw new Error(`Ref "${refName}" not found in config. Available: ${resolvedRefs.map((r) => r.name).join(", ")}`);
176
+ }
177
+ const registry = resolvedRegistries.find((r) => r.url === ref.registry);
178
+ if (!registry) {
179
+ throw new Error(`Registry "${ref.registry}" not found for ref "${refName}"`);
180
+ }
181
+ return callTool(registry, ref.ref, tool, params);
182
+ },
183
+ discover,
184
+ async resolveSecret(url) {
185
+ return resolveSecretFn(url, { token: options.token });
186
+ },
187
+ async resolveConfig(config) {
188
+ const resolved = {};
189
+ for (const [key, value] of Object.entries(config)) {
190
+ if (isSecretUrl(value)) {
191
+ resolved[key] = await resolveSecretFn(value, {
192
+ token: options.token,
193
+ });
194
+ }
195
+ else {
196
+ resolved[key] = value;
197
+ }
198
+ }
199
+ return resolved;
200
+ },
201
+ index() {
202
+ return {
203
+ resolvedAt: new Date().toISOString(),
204
+ sourceHash: simpleHash(JSON.stringify(config)),
205
+ registries: resolvedRegistries,
206
+ refs: resolvedRefs,
207
+ meta: config.meta,
208
+ };
209
+ },
210
+ async available() {
211
+ const all = await consumer.list();
212
+ const configuredRefs = new Set(resolvedRefs.map((r) => r.ref));
213
+ return all.filter((a) => !configuredRefs.has(a.path));
214
+ },
215
+ };
216
+ return consumer;
217
+ }
218
+ // ============================================
219
+ // Utilities
220
+ // ============================================
221
+ /** Simple hash for cache invalidation (not cryptographic) */
222
+ function simpleHash(str) {
223
+ let hash = 0;
224
+ for (let i = 0; i < str.length; i++) {
225
+ const char = str.charCodeAt(i);
226
+ hash = ((hash << 5) - hash + char) | 0;
227
+ }
228
+ return Math.abs(hash).toString(36);
229
+ }
230
+ //# sourceMappingURL=registry-consumer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-consumer.js","sourceRoot":"","sources":["../src/registry-consumer.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * Manages registered agents and handles callAgent requests.
5
5
  */
6
+ import type { AgentEvent, EventCallback, EventType } from "./events.js";
6
7
  import type { AgentDefinition, CallAgentLoadRequest, CallAgentLoadResponse, CallAgentRequest, CallAgentResponse, Visibility } from "./types.js";
7
8
  /**
8
9
  * Middleware hooks for registry lifecycle actions.
@@ -43,6 +44,10 @@ export interface AgentRegistry {
43
44
  listPaths(): string[];
44
45
  /** Call an agent (execute action) */
45
46
  call(request: CallAgentRequest): Promise<CallAgentResponse>;
47
+ /** Register an event listener (global scope — fires for all agents) */
48
+ on<T extends EventType>(eventType: T, callback: EventCallback<T>): void;
49
+ /** Emit an event to all listeners. Used by the runtime to push lifecycle events. */
50
+ emit(event: AgentEvent): Promise<void>;
46
51
  }
47
52
  /**
48
53
  * Create an agent registry.
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAEV,eAAe,EAMf,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EAIjB,UAAU,EACX,MAAM,YAAY,CAAC;AAapB;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,CACL,SAAS,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,qBAAqB,CAAC,EACpG,GAAG,EAAE;QAAE,KAAK,EAAE,eAAe,CAAC;QAAC,OAAO,EAAE,oBAAoB,CAAC;QAAC,QAAQ,EAAE,aAAa,CAAA;KAAE,KACpF,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,mEAAmE;IACnE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iCAAiC;IACjC,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,wBAAwB;IACxB,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAEvC,2BAA2B;IAC3B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IAE/C,+BAA+B;IAC/B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAE3B,iCAAiC;IACjC,IAAI,IAAI,eAAe,EAAE,CAAC;IAE1B,sCAAsC;IACtC,SAAS,IAAI,MAAM,EAAE,CAAC;IAEtB,qCAAqC;IACrC,IAAI,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC7D;AAMD;;;;;;;;;;;;;;;GAeG;AACH;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,YAAY,EAAE,WAAW,KAAK,OAAO,YAAY,EAAE,WAAW,CAAC;AAE7G,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,oBAAyB,GACjC,aAAa,CA8Zf"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACV,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAEV,eAAe,EAMf,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EAIjB,UAAU,EACX,MAAM,YAAY,CAAC;AAapB;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,CACL,SAAS,EAAE,CACT,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,oBAAoB,KAC1B,OAAO,CAAC,qBAAqB,CAAC,EACnC,GAAG,EAAE;QACH,KAAK,EAAE,eAAe,CAAC;QACvB,OAAO,EAAE,oBAAoB,CAAC;QAC9B,QAAQ,EAAE,aAAa,CAAC;KACzB,KACE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,mEAAmE;IACnE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iCAAiC;IACjC,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,wBAAwB;IACxB,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAEvC,2BAA2B;IAC3B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IAE/C,+BAA+B;IAC/B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAE3B,iCAAiC;IACjC,IAAI,IAAI,eAAe,EAAE,CAAC;IAE1B,sCAAsC;IACtC,SAAS,IAAI,MAAM,EAAE,CAAC;IAEtB,qCAAqC;IACrC,IAAI,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAE5D,uEAAuE;IACvE,EAAE,CAAC,CAAC,SAAS,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAExE,oFAAoF;IACpF,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAMD;;;;;;;;;;;;;;;GAeG;AACH;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,OAAO,EAAE,OAAO,YAAY,EAAE,WAAW,KACtC,OAAO,YAAY,EAAE,WAAW,CAAC;AAEtC,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAmff"}
package/dist/registry.js CHANGED
@@ -4,6 +4,7 @@
4
4
  * Manages registered agents and handles callAgent requests.
5
5
  */
6
6
  import { dirname, resolve } from "node:path";
7
+ import { createEventBus } from "./events.js";
7
8
  /** Default supported actions if not specified */
8
9
  const DEFAULT_SUPPORTED_ACTIONS = [
9
10
  "execute_tool",
@@ -13,6 +14,7 @@ const DEFAULT_SUPPORTED_ACTIONS = [
13
14
  export function createAgentRegistry(options = {}) {
14
15
  const { defaultVisibility = "internal" } = options;
15
16
  const agents = new Map();
17
+ const eventBus = createEventBus();
16
18
  /**
17
19
  * Check if agent supports the requested action.
18
20
  */
@@ -167,6 +169,26 @@ export function createAgentRegistry(options = {}) {
167
169
  const registry = {
168
170
  register(agent) {
169
171
  agents.set(agent.path, agent);
172
+ // Collect agent-level listeners into the bus
173
+ if (agent._listeners) {
174
+ for (const entry of agent._listeners) {
175
+ eventBus._onScoped(entry.eventType, entry.callback, {
176
+ agentPath: agent.path,
177
+ toolName: entry.toolScope,
178
+ });
179
+ }
180
+ }
181
+ // Collect tool-level listeners into the bus
182
+ for (const tool of agent.tools) {
183
+ if (tool._listeners) {
184
+ for (const entry of tool._listeners) {
185
+ eventBus._onScoped(entry.eventType, entry.callback, {
186
+ agentPath: agent.path,
187
+ toolName: tool.name,
188
+ });
189
+ }
190
+ }
191
+ }
170
192
  },
171
193
  get(path) {
172
194
  return agents.get(path);
@@ -180,6 +202,12 @@ export function createAgentRegistry(options = {}) {
180
202
  listPaths() {
181
203
  return Array.from(agents.keys());
182
204
  },
205
+ on(eventType, callback) {
206
+ eventBus.on(eventType, callback);
207
+ },
208
+ async emit(event) {
209
+ await eventBus.emit(event);
210
+ },
183
211
  async call(request) {
184
212
  const agent = agents.get(request.path);
185
213
  if (!agent) {
@@ -266,16 +294,56 @@ export function createAgentRegistry(options = {}) {
266
294
  error: `Tool ${request.tool} has no execute function`,
267
295
  };
268
296
  }
269
- const result = await tool.execute(request.params, ctx);
297
+ // Emit tool/call before execution
298
+ const startMs = Date.now();
299
+ await eventBus.emit({
300
+ type: "tool/call",
301
+ agentPath: agent.path,
302
+ tool: request.tool,
303
+ params: request.params,
304
+ timestamp: startMs,
305
+ });
306
+ let result;
307
+ try {
308
+ result = await tool.execute(request.params, ctx);
309
+ }
310
+ catch (err) {
311
+ // Emit tool/error on failure
312
+ await eventBus.emit({
313
+ type: "tool/error",
314
+ agentPath: agent.path,
315
+ tool: request.tool,
316
+ params: request.params,
317
+ error: err,
318
+ durationMs: Date.now() - startMs,
319
+ timestamp: Date.now(),
320
+ }).catch(() => { }); // don't let emit error mask tool error
321
+ return {
322
+ success: false,
323
+ error: err instanceof Error ? err.message : String(err),
324
+ code: "TOOL_EXECUTION_ERROR",
325
+ };
326
+ }
327
+ // Emit tool/result after success
328
+ await eventBus.emit({
329
+ type: "tool/result",
330
+ agentPath: agent.path,
331
+ tool: request.tool,
332
+ params: request.params,
333
+ result,
334
+ durationMs: Date.now() - startMs,
335
+ timestamp: Date.now(),
336
+ });
270
337
  return {
271
338
  success: true,
272
339
  result,
273
340
  };
274
341
  }
275
- catch (err) {
342
+ catch (outerErr) {
343
+ // Catch-all for unexpected errors (e.g., emit failures)
276
344
  return {
277
345
  success: false,
278
- error: err instanceof Error ? err.message : String(err),
346
+ error: outerErr instanceof Error ? outerErr.message : String(outerErr),
279
347
  code: "TOOL_EXECUTION_ERROR",
280
348
  };
281
349
  }
@@ -297,7 +365,11 @@ export function createAgentRegistry(options = {}) {
297
365
  }
298
366
  case "load": {
299
367
  if (options.middleware?.load) {
300
- return options.middleware.load(defaultLoad, { agent, request, registry });
368
+ return options.middleware.load(defaultLoad, {
369
+ agent,
370
+ request,
371
+ registry,
372
+ });
301
373
  }
302
374
  return defaultLoad(agent, request);
303
375
  }