@dainprotocol/service-sdk 2.0.94 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +29 -0
  2. package/dist/client/api-sdk.d.ts +7 -1
  3. package/dist/client/api-sdk.js +2 -2
  4. package/dist/client/api-sdk.js.map +1 -1
  5. package/dist/client/client-auth.d.ts +38 -0
  6. package/dist/client/client-auth.js +131 -2
  7. package/dist/client/client-auth.js.map +1 -1
  8. package/dist/client/client.d.ts +1 -0
  9. package/dist/client/client.js +92 -25
  10. package/dist/client/client.js.map +1 -1
  11. package/dist/client/index.d.ts +1 -0
  12. package/dist/client/index.js +1 -0
  13. package/dist/client/index.js.map +1 -1
  14. package/dist/client/types.d.ts +252 -0
  15. package/dist/client/types.js +159 -31
  16. package/dist/client/types.js.map +1 -1
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.js +3 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/plugins/crypto-plugin.d.ts +26 -0
  21. package/dist/plugins/crypto-plugin.js +44 -4
  22. package/dist/plugins/crypto-plugin.js.map +1 -1
  23. package/dist/plugins/index.d.ts +1 -0
  24. package/dist/plugins/index.js +1 -0
  25. package/dist/plugins/index.js.map +1 -1
  26. package/dist/protocol/account.d.ts +91 -0
  27. package/dist/protocol/account.js +3 -0
  28. package/dist/protocol/account.js.map +1 -0
  29. package/dist/protocol/grants.d.ts +34 -0
  30. package/dist/protocol/grants.js +3 -0
  31. package/dist/protocol/grants.js.map +1 -0
  32. package/dist/protocol/index.d.ts +8 -0
  33. package/dist/protocol/index.js +12 -0
  34. package/dist/protocol/index.js.map +1 -0
  35. package/dist/protocol/payments.d.ts +53 -0
  36. package/dist/protocol/payments.js +3 -0
  37. package/dist/protocol/payments.js.map +1 -0
  38. package/dist/protocol/permissions.d.ts +21 -0
  39. package/dist/protocol/permissions.js +3 -0
  40. package/dist/protocol/permissions.js.map +1 -0
  41. package/dist/protocol/programs.d.ts +44 -0
  42. package/dist/protocol/programs.js +46 -0
  43. package/dist/protocol/programs.js.map +1 -0
  44. package/dist/protocol/registry.d.ts +43 -0
  45. package/dist/protocol/registry.js +3 -0
  46. package/dist/protocol/registry.js.map +1 -0
  47. package/dist/protocol/runtime.d.ts +15 -0
  48. package/dist/protocol/runtime.js +3 -0
  49. package/dist/protocol/runtime.js.map +1 -0
  50. package/dist/protocol/transactions.d.ts +63 -0
  51. package/dist/protocol/transactions.js +3 -0
  52. package/dist/protocol/transactions.js.map +1 -0
  53. package/dist/service/auth.d.ts +15 -1
  54. package/dist/service/auth.js +156 -35
  55. package/dist/service/auth.js.map +1 -1
  56. package/dist/service/core.js +9 -0
  57. package/dist/service/core.js.map +1 -1
  58. package/dist/service/index.d.ts +1 -0
  59. package/dist/service/index.js +1 -0
  60. package/dist/service/index.js.map +1 -1
  61. package/dist/service/nodeService.js +30 -2
  62. package/dist/service/nodeService.js.map +1 -1
  63. package/dist/service/server.js +733 -242
  64. package/dist/service/server.js.map +1 -1
  65. package/dist/service/service.js +6 -8
  66. package/dist/service/service.js.map +1 -1
  67. package/dist/service/types.d.ts +48 -34
  68. package/package.json +20 -7
@@ -98,18 +98,151 @@ async function safeParseBody(c) {
98
98
  return {};
99
99
  }
100
100
  }
101
+ function isRecord(value) {
102
+ return !!value && typeof value === "object" && !Array.isArray(value);
103
+ }
104
+ const DAIN_RUNTIME_CONTEXT_KEYS = new Set([
105
+ "dainAccountId",
106
+ "dainGroupId",
107
+ "smartAccountPDA",
108
+ "account",
109
+ "group",
110
+ "auth",
111
+ "grants",
112
+ "dataPermissions",
113
+ "registryPolicy",
114
+ ]);
115
+ function stripRuntimeContextFields(value) {
116
+ return Object.fromEntries(Object.entries(value).filter(([key]) => !DAIN_RUNTIME_CONTEXT_KEYS.has(key)));
117
+ }
118
+ function getStringClaim(payload, ...keys) {
119
+ if (!payload)
120
+ return undefined;
121
+ for (const key of keys) {
122
+ const value = payload[key];
123
+ if (typeof value === "string" && value.length > 0) {
124
+ return value;
125
+ }
126
+ }
127
+ return undefined;
128
+ }
129
+ function getObjectClaim(payload, key) {
130
+ if (!payload)
131
+ return undefined;
132
+ const value = payload[key];
133
+ return isRecord(value) ? value : undefined;
134
+ }
135
+ function getArrayClaim(payload, key) {
136
+ if (!payload)
137
+ return undefined;
138
+ const value = payload[key];
139
+ return Array.isArray(value) ? value : undefined;
140
+ }
141
+ function getRuntimeContextFromJwtPayload(payload, options = {}) {
142
+ const account = getObjectClaim(payload, "account_context");
143
+ const group = getObjectClaim(payload, "group_context");
144
+ const auth = getObjectClaim(payload, "auth_context");
145
+ const dainAccountId = getStringClaim(payload, "dain_account_id", "account_id") ?? account?.id;
146
+ const dainGroupId = getStringClaim(payload, "dain_group_id", "group_id") ?? group?.id;
147
+ const smartAccountPDA = getStringClaim(payload, "smart_account_pda") ??
148
+ options.fallbackSmartAccountPDA;
149
+ if (account?.id && dainAccountId && account.id !== dainAccountId) {
150
+ throw new http_exception_1.HTTPException(401, {
151
+ message: "JWT DAIN context mismatch: dain_account_id does not match account_context.id",
152
+ });
153
+ }
154
+ if (group?.id && dainGroupId && group.id !== dainGroupId) {
155
+ throw new http_exception_1.HTTPException(401, {
156
+ message: "JWT DAIN context mismatch: dain_group_id does not match group_context.id",
157
+ });
158
+ }
159
+ if (account?.smartAccount?.pda &&
160
+ smartAccountPDA &&
161
+ account.smartAccount.pda !== smartAccountPDA) {
162
+ throw new http_exception_1.HTTPException(401, {
163
+ message: "JWT DAIN context mismatch: smart_account_pda does not match account_context.smartAccount.pda",
164
+ });
165
+ }
166
+ const grants = getArrayClaim(payload, "action_grants");
167
+ const dataPermissions = getArrayClaim(payload, "data_permissions");
168
+ const registryPolicy = getObjectClaim(payload, "registry_policy");
169
+ const subject = getStringClaim(payload, "sub") ??
170
+ options.smartAccountId ??
171
+ dainAccountId ??
172
+ dainGroupId ??
173
+ smartAccountPDA;
174
+ return {
175
+ ...(dainAccountId ? { dainAccountId } : {}),
176
+ ...(dainGroupId ? { dainGroupId } : {}),
177
+ ...(smartAccountPDA ? { smartAccountPDA } : {}),
178
+ ...(account ? { account } : {}),
179
+ ...(group ? { group } : {}),
180
+ auth: auth ?? {
181
+ subject: subject ?? "unknown",
182
+ issuer: getStringClaim(payload, "iss"),
183
+ scopes: options.scopes,
184
+ source: "dain_id",
185
+ },
186
+ ...(grants ? { grants } : {}),
187
+ ...(dataPermissions ? { dataPermissions } : {}),
188
+ ...(registryPolicy ? { registryPolicy } : {}),
189
+ };
190
+ }
191
+ function getRuntimeContextFromAgentInfo(agentInfo) {
192
+ return {
193
+ ...(agentInfo.dainAccountId
194
+ ? { dainAccountId: agentInfo.dainAccountId }
195
+ : {}),
196
+ ...(agentInfo.dainGroupId ? { dainGroupId: agentInfo.dainGroupId } : {}),
197
+ ...(agentInfo.smartAccountPDA
198
+ ? { smartAccountPDA: agentInfo.smartAccountPDA }
199
+ : {}),
200
+ ...(agentInfo.account ? { account: agentInfo.account } : {}),
201
+ ...(agentInfo.group ? { group: agentInfo.group } : {}),
202
+ ...(agentInfo.auth ? { auth: agentInfo.auth } : {}),
203
+ ...(agentInfo.grants ? { grants: agentInfo.grants } : {}),
204
+ ...(agentInfo.dataPermissions
205
+ ? { dataPermissions: agentInfo.dataPermissions }
206
+ : {}),
207
+ ...(agentInfo.registryPolicy
208
+ ? { registryPolicy: agentInfo.registryPolicy }
209
+ : {}),
210
+ };
211
+ }
212
+ function getRequestExtraData(request) {
213
+ if (!isRecord(request))
214
+ return {};
215
+ return isRecord(request.DAIN_EXTRA_DATA)
216
+ ? stripRuntimeContextFields(request.DAIN_EXTRA_DATA)
217
+ : {};
218
+ }
219
+ function buildServiceExtraData(agentInfo, options = {}) {
220
+ const requestExtra = getRequestExtraData(options.request);
221
+ const runtimeContext = getRuntimeContextFromAgentInfo(agentInfo);
222
+ return {
223
+ ...requestExtra,
224
+ ...(options.extra ?? {}),
225
+ ...runtimeContext,
226
+ ...(options.plugins ? { plugins: options.plugins } : {}),
227
+ ...(Object.prototype.hasOwnProperty.call(options, "oauth2Client")
228
+ ? { oauth2Client: options.oauth2Client }
229
+ : {}),
230
+ };
231
+ }
101
232
  /**
102
233
  * Middleware factory to require specific OAuth scopes.
103
234
  * Defense-in-depth: Validates scopes even though JWT middleware already checked them.
104
235
  */
105
236
  function requireScope(requiredScope) {
106
237
  return async (c, next) => {
107
- const scopes = c.get('scope') || [];
108
- const requiredScopes = Array.isArray(requiredScope) ? requiredScope : [requiredScope];
109
- const hasRequiredScope = requiredScopes.some(scope => (0, auth_2.hasScope)(scopes, scope));
238
+ const scopes = c.get("scope") || [];
239
+ const requiredScopes = Array.isArray(requiredScope)
240
+ ? requiredScope
241
+ : [requiredScope];
242
+ const hasRequiredScope = requiredScopes.some((scope) => (0, auth_2.hasScope)(scopes, scope));
110
243
  if (!hasRequiredScope) {
111
244
  throw new http_exception_1.HTTPException(403, {
112
- message: `Insufficient scope. Required: ${requiredScopes.join(' OR ')}, Have: ${scopes.join(', ')}`
245
+ message: `Insufficient scope. Required: ${requiredScopes.join(" OR ")}, Have: ${scopes.join(", ")}`,
113
246
  });
114
247
  }
115
248
  await next();
@@ -120,6 +253,17 @@ function signedStreamSSE(c, privateKey, config, handler) {
120
253
  return (0, streaming_1.streamSSE)(c, async (stream) => {
121
254
  const requestSignal = c.req.raw?.signal;
122
255
  const isAborted = () => stream.aborted || stream.closed || requestSignal?.aborted === true;
256
+ const abortStream = () => {
257
+ if (!stream.closed) {
258
+ stream.abort();
259
+ }
260
+ };
261
+ if (requestSignal?.aborted) {
262
+ abortStream();
263
+ }
264
+ else {
265
+ requestSignal?.addEventListener("abort", abortStream, { once: true });
266
+ }
123
267
  const signedStream = {
124
268
  writeSSE: async (event) => {
125
269
  if (isAborted())
@@ -128,29 +272,46 @@ function signedStreamSSE(c, privateKey, config, handler) {
128
272
  const messageHash = (0, sseSignature_1.hashEventMessage)(event.data, timestamp);
129
273
  const signature = (0, utils_js_1.bytesToHex)(sseSignature_1.ed25519.sign(messageHash, privateKey));
130
274
  // Fast path for non-critical events (progress/UI updates)
131
- const isCriticalEvent = event.event === 'result' ||
132
- event.event === 'process-created' ||
133
- event.event === 'datasource-update';
275
+ const isCriticalEvent = event.event === "result" ||
276
+ event.event === "process-created" ||
277
+ event.event === "datasource-update";
134
278
  const dataWithSignature = isCriticalEvent
135
279
  ? JSON.stringify({
136
280
  data: JSON.parse(event.data),
137
- _signature: { signature, timestamp, agentId: config.identity.agentId, orgId: config.identity.orgId, address: config.identity.publicKey }
281
+ _signature: {
282
+ signature,
283
+ timestamp,
284
+ agentId: config.identity.agentId,
285
+ orgId: config.identity.orgId,
286
+ address: config.identity.publicKey,
287
+ },
138
288
  })
139
289
  : `{"data":${event.data},"_signature":{"signature":"${signature}","timestamp":"${timestamp}","agentId":"${config.identity.agentId}","orgId":"${config.identity.orgId}","address":"${config.identity.publicKey}"}}`;
140
- await stream.writeSSE({ event: event.event, data: dataWithSignature, id: event.id });
290
+ await stream.writeSSE({
291
+ event: event.event,
292
+ data: dataWithSignature,
293
+ id: event.id,
294
+ });
141
295
  },
142
296
  isAborted,
297
+ onAbort: (listener) => stream.onAbort(listener),
143
298
  };
144
- await handler(signedStream);
299
+ try {
300
+ await handler(signedStream);
301
+ }
302
+ finally {
303
+ requestSignal?.removeEventListener("abort", abortStream);
304
+ }
145
305
  });
146
306
  }
147
307
  function setupHttpServer(config, tools, services, toolboxes, metadata, privateKey, contexts, widgets, datasources = [], agents = []) {
148
308
  const app = new hono_1.Hono();
309
+ const datasourceStreamAbortControllers = new Map();
149
310
  const processHandler = new processes_1.ProcessHandler({
150
311
  serviceId: "service_" + config.identity.orgId + "_" + config.identity.agentId,
151
312
  privateKey,
152
313
  store: config.processStore,
153
- onHumanActionResponse: config.onHumanActionResponse
314
+ onHumanActionResponse: config.onHumanActionResponse,
154
315
  });
155
316
  app.processes = processHandler;
156
317
  // CORS middleware - apply to all routes
@@ -160,6 +321,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
160
321
  allowHeaders: [
161
322
  "X-DAIN-SIGNATURE",
162
323
  "X-DAIN-SMART-ACCOUNT-PDA",
324
+ "X-DAIN-ACCOUNT-ID",
325
+ "X-DAIN-GROUP-ID",
163
326
  "X-DAIN-AGENT-ID",
164
327
  "X-DAIN-ORG-ID",
165
328
  "X-DAIN-ADDRESS",
@@ -177,7 +340,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
177
340
  return c.text("Enabling CORS Pre-Flight", 200, {
178
341
  "Access-Control-Allow-Origin": "*",
179
342
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
180
- "Access-Control-Allow-Headers": "X-DAIN-SIGNATURE, X-DAIN-SMART-ACCOUNT-PDA, X-DAIN-AGENT-ID, X-DAIN-ORG-ID, X-DAIN-ADDRESS, X-DAIN-TIMESTAMP, Content-Type, Authorization, Accept, Origin, X-Requested-With",
343
+ "Access-Control-Allow-Headers": "X-DAIN-SIGNATURE, X-DAIN-SMART-ACCOUNT-PDA, X-DAIN-ACCOUNT-ID, X-DAIN-GROUP-ID, X-DAIN-AGENT-ID, X-DAIN-ORG-ID, X-DAIN-ADDRESS, X-DAIN-TIMESTAMP, Content-Type, Authorization, Accept, Origin, X-Requested-With",
181
344
  "Access-Control-Max-Age": "86400",
182
345
  });
183
346
  });
@@ -197,7 +360,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
197
360
  const isStreaming = acceptHeader.includes("text/event-stream");
198
361
  await next();
199
362
  // Skip signature for streaming responses
200
- if (isStreaming || c.res.headers.get("content-type")?.includes("text/event-stream")) {
363
+ if (isStreaming ||
364
+ c.res.headers.get("content-type")?.includes("text/event-stream")) {
201
365
  return;
202
366
  }
203
367
  const body = await c.res.clone().text();
@@ -210,12 +374,14 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
210
374
  });
211
375
  // Get all webhook paths for auth bypass
212
376
  const webhookPaths = config.webhookTriggers?.getWebhookPaths() || [];
213
- const hitlPath = config.hitl?.enabled ? (config.hitl.webhookPath || '/actions') : null;
377
+ const hitlPath = config.hitl?.enabled
378
+ ? config.hitl.webhookPath || "/actions"
379
+ : null;
214
380
  // Dual Authentication: JWT (users) or API Key (services)
215
381
  app.use("*", async (c, next) => {
216
382
  debugLog(`[Auth Middleware] Path: ${c.req.path}, Method: ${c.req.method}`);
217
383
  // Check if path is a webhook path (auth bypass)
218
- const isWebhookPath = webhookPaths.some(path => c.req.path === path);
384
+ const isWebhookPath = webhookPaths.some((path) => c.req.path === path);
219
385
  const isHITLPath = hitlPath && c.req.path === hitlPath;
220
386
  if (c.req.path.startsWith("/oauth2/callback/") ||
221
387
  c.req.path.startsWith("/addons") ||
@@ -237,16 +403,20 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
237
403
  const host = getFirstForwardedValue(c.req.header("x-forwarded-host")) ||
238
404
  getFirstForwardedValue(c.req.header("host"));
239
405
  if (!host) {
240
- throw new http_exception_1.HTTPException(400, { message: "Unable to determine service URL. Host header is required." });
406
+ throw new http_exception_1.HTTPException(400, {
407
+ message: "Unable to determine service URL. Host header is required.",
408
+ });
241
409
  }
242
410
  // Validate host format to prevent obvious attacks
243
- if (host.includes(' ') || host.includes('\n') || host.includes('\r')) {
411
+ if (host.includes(" ") || host.includes("\n") || host.includes("\r")) {
244
412
  throw new http_exception_1.HTTPException(400, { message: "Invalid Host header format" });
245
413
  }
246
414
  const xForwardedProto = getFirstForwardedValue(c.req.header("x-forwarded-proto"));
247
415
  const protocol = xForwardedProto === "http" || xForwardedProto === "https"
248
416
  ? xForwardedProto
249
- : (host.includes("localhost") || host.startsWith("127.") ? "http" : "https");
417
+ : host.includes("localhost") || host.startsWith("127.")
418
+ ? "http"
419
+ : "https";
250
420
  const forwardedPrefix = normalizeForwardedPrefix(getFirstForwardedValue(c.req.header("x-forwarded-prefix")));
251
421
  const jwtAudiences = [`${protocol}://${host}`];
252
422
  if (forwardedPrefix) {
@@ -259,7 +429,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
259
429
  audience: jwtAudiences,
260
430
  });
261
431
  if (!result.valid) {
262
- throw new http_exception_1.HTTPException(401, { message: `JWT verification failed: ${result.error}` });
432
+ throw new http_exception_1.HTTPException(401, {
433
+ message: `JWT verification failed: ${result.error}`,
434
+ });
263
435
  }
264
436
  // Defense in depth: double-check audience claim
265
437
  const tokenAudiences = Array.isArray(result.payload?.aud)
@@ -269,15 +441,21 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
269
441
  const audienceMatched = tokenAudiences.some((aud) => aud && expectedAudienceSet.has(aud));
270
442
  if (!audienceMatched) {
271
443
  throw new http_exception_1.HTTPException(403, {
272
- message: `JWT audience mismatch. Expected one of: ${jwtAudiences.join(", ")}, Got: ${tokenAudiences.filter(Boolean).join(", ")}`
444
+ message: `JWT audience mismatch. Expected one of: ${jwtAudiences.join(", ")}, Got: ${tokenAudiences.filter(Boolean).join(", ")}`,
273
445
  });
274
446
  }
275
- c.set('authMethod', 'jwt');
276
- c.set('smartAccountId', result.smartAccountId);
277
- c.set('address', result.smartAccountId); // Use smartAccountId as address for JWT auth
278
- c.set('scope', result.scope);
279
- c.set('jwtPayload', result.payload);
280
- c.set('smartAccountPDA', c.req.header("X-DAIN-SMART-ACCOUNT-PDA"));
447
+ c.set("authMethod", "jwt");
448
+ c.set("smartAccountId", result.smartAccountId);
449
+ c.set("address", result.smartAccountId); // Use smartAccountId as address for JWT auth
450
+ c.set("scope", result.scope);
451
+ c.set("jwtPayload", result.payload);
452
+ const jwtRuntimeContext = getRuntimeContextFromJwtPayload(result.payload, {
453
+ scopes: result.scope,
454
+ smartAccountId: result.smartAccountId,
455
+ fallbackSmartAccountPDA: c.req.header("X-DAIN-SMART-ACCOUNT-PDA"),
456
+ });
457
+ c.set("dainRuntimeContext", jwtRuntimeContext);
458
+ c.set("smartAccountPDA", jwtRuntimeContext.smartAccountPDA);
281
459
  debugLog(`[Auth Middleware] JWT auth SUCCESS - smartAccountId: ${result.smartAccountId}`);
282
460
  }
283
461
  else if (apiKey) {
@@ -295,11 +473,22 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
295
473
  throw new http_exception_1.HTTPException(401, { message: "Invalid API key" });
296
474
  }
297
475
  }
298
- c.set('authMethod', 'apiKey');
299
- c.set('agentId', parsed.agentId);
300
- c.set('orgId', parsed.orgId);
301
- c.set('address', parsed.agentId); // Use agentId as address for API key auth
302
- c.set('smartAccountPDA', c.req.header("X-DAIN-SMART-ACCOUNT-PDA"));
476
+ c.set("authMethod", "apiKey");
477
+ c.set("agentId", parsed.agentId);
478
+ c.set("orgId", parsed.orgId);
479
+ c.set("address", parsed.agentId); // Use agentId as address for API key auth
480
+ c.set("smartAccountPDA", c.req.header("X-DAIN-SMART-ACCOUNT-PDA"));
481
+ c.set("dainRuntimeContext", {
482
+ ...(c.req.header("X-DAIN-ACCOUNT-ID")
483
+ ? { dainAccountId: c.req.header("X-DAIN-ACCOUNT-ID") }
484
+ : {}),
485
+ ...(c.req.header("X-DAIN-GROUP-ID")
486
+ ? { dainGroupId: c.req.header("X-DAIN-GROUP-ID") }
487
+ : {}),
488
+ ...(c.req.header("X-DAIN-SMART-ACCOUNT-PDA")
489
+ ? { smartAccountPDA: c.req.header("X-DAIN-SMART-ACCOUNT-PDA") }
490
+ : {}),
491
+ });
303
492
  debugLog(`[Auth Middleware] API Key auth SUCCESS - agentId: ${parsed.agentId}, orgId: ${parsed.orgId}`);
304
493
  }
305
494
  else {
@@ -310,32 +499,58 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
310
499
  });
311
500
  async function getAgentInfo(c) {
312
501
  debugLog("[getAgentInfo] START");
313
- debugLog("[getAgentInfo] Auth method:", c.get('authMethod'));
314
- const smartAccountPDA = c.get('smartAccountPDA') || c.req.header("X-DAIN-SMART-ACCOUNT-PDA");
502
+ debugLog("[getAgentInfo] Auth method:", c.get("authMethod"));
503
+ const runtimeContext = (c.get("dainRuntimeContext") ||
504
+ {});
505
+ const smartAccountPDA = runtimeContext.smartAccountPDA ||
506
+ c.get("smartAccountPDA") ||
507
+ c.req.header("X-DAIN-SMART-ACCOUNT-PDA");
315
508
  const webhookUrl = c.req.header("X-DAIN-WEBHOOK-URL");
316
509
  debugLog("[getAgentInfo] smartAccountPDA:", smartAccountPDA);
317
510
  debugLog("[getAgentInfo] webhookUrl:", webhookUrl);
318
- if (c.get('authMethod') === 'jwt') {
319
- const smartAccountId = c.get('smartAccountId');
511
+ if (c.get("authMethod") === "jwt") {
512
+ const smartAccountId = c.get("smartAccountId");
320
513
  debugLog("[getAgentInfo] JWT auth - smartAccountId:", smartAccountId);
321
514
  const agentInfo = {
322
515
  agentId: smartAccountId,
323
516
  address: smartAccountId,
324
517
  smartAccountPDA,
325
- id: smartAccountPDA ? `dain_id_${smartAccountPDA}` : `smart_account_${smartAccountId}`,
518
+ dainAccountId: runtimeContext.dainAccountId,
519
+ dainGroupId: runtimeContext.dainGroupId,
520
+ account: runtimeContext.account,
521
+ group: runtimeContext.group,
522
+ auth: runtimeContext.auth,
523
+ grants: runtimeContext.grants,
524
+ dataPermissions: runtimeContext.dataPermissions,
525
+ registryPolicy: runtimeContext.registryPolicy,
526
+ id: runtimeContext.dainAccountId ??
527
+ runtimeContext.dainGroupId ??
528
+ (smartAccountPDA
529
+ ? `dain_id_${smartAccountPDA}`
530
+ : `smart_account_${smartAccountId}`),
326
531
  webhookUrl,
327
532
  };
328
533
  debugLog("[getAgentInfo] JWT - Returning agent info:", agentInfo);
329
534
  return agentInfo;
330
535
  }
331
- const agentId = c.get('agentId');
332
- const address = c.get('address');
536
+ const agentId = c.get("agentId");
537
+ const address = c.get("address");
333
538
  debugLog("[getAgentInfo] API Key auth - agentId:", agentId, "address:", address);
334
539
  const agentInfo = {
335
540
  agentId,
336
541
  address,
337
542
  smartAccountPDA,
338
- id: smartAccountPDA ? `dain_id_${smartAccountPDA}` : `address_${address}`,
543
+ dainAccountId: runtimeContext.dainAccountId,
544
+ dainGroupId: runtimeContext.dainGroupId,
545
+ account: runtimeContext.account,
546
+ group: runtimeContext.group,
547
+ auth: runtimeContext.auth,
548
+ grants: runtimeContext.grants,
549
+ dataPermissions: runtimeContext.dataPermissions,
550
+ registryPolicy: runtimeContext.registryPolicy,
551
+ id: runtimeContext.dainAccountId ??
552
+ runtimeContext.dainGroupId ??
553
+ (smartAccountPDA ? `dain_id_${smartAccountPDA}` : `address_${address}`),
339
554
  webhookUrl,
340
555
  };
341
556
  debugLog("[getAgentInfo] API Key - Returning agent info:", agentInfo);
@@ -365,7 +580,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
365
580
  app.get("/metadata", (c) => {
366
581
  // Compute service-level capability: does ANY tool support user actions (HITL)?
367
582
  const supportsUserActions = tools.some((tool) => tool.supportsUserActions === true);
368
- const requestedContract = c.req.header("x-butterfly-contract") || c.req.header("X-Butterfly-Contract");
583
+ const requestedContract = c.req.header("x-butterfly-contract") ||
584
+ c.req.header("X-Butterfly-Contract");
369
585
  const sdkMajor = Number.parseInt(String(package_json_1.default.version).split(".")[0] || "0", 10);
370
586
  const contractVersion = Number.isFinite(sdkMajor) && sdkMajor > 0 ? `${sdkMajor}.0.0` : "0.0.0";
371
587
  const capabilities = {
@@ -378,6 +594,14 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
378
594
  datasourcePolicy: true,
379
595
  widgetPolicy: true,
380
596
  toolSafety: true,
597
+ dainAccount: true,
598
+ registryDiscovery: true,
599
+ dataPermissions: true,
600
+ actionGrants: true,
601
+ smartAccountTransactions: true,
602
+ payments: true,
603
+ registryPolicy: true,
604
+ grantPolicies: true,
381
605
  };
382
606
  const compatibility = (() => {
383
607
  if (!requestedContract)
@@ -444,38 +668,53 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
444
668
  const autoContexts = app.oauth2?.getDirectProviderContexts?.() || [];
445
669
  const serviceSlug = (0, core_1.toSlug)(metadata.title);
446
670
  const skillsContext = config.skills?.getSkillsContext?.(serviceSlug);
447
- const allContexts = [...contexts, ...autoContexts, ...(skillsContext ? [skillsContext] : [])];
671
+ const allContexts = [
672
+ ...contexts,
673
+ ...autoContexts,
674
+ ...(skillsContext ? [skillsContext] : []),
675
+ ];
448
676
  const contextInfo = allContexts.map((context) => ({
449
677
  id: context.id,
450
678
  name: context.name,
451
679
  description: context.description,
452
680
  }));
453
681
  // Process plugins for the response
454
- const processedResponse = await processPluginsForResponse(contextInfo, body, { extraData: { plugins: processedPluginData.plugins } });
682
+ const processedResponse = await processPluginsForResponse(contextInfo, body, {
683
+ extraData: buildServiceExtraData(agentInfo, {
684
+ request: processedPluginData,
685
+ plugins: processedPluginData.plugins,
686
+ }),
687
+ });
455
688
  return c.json(processedResponse);
456
689
  });
457
690
  app.post("/contexts/:contextId", async (c) => {
458
691
  const autoContexts = app.oauth2?.getDirectProviderContexts?.() || [];
459
692
  const serviceSlug = (0, core_1.toSlug)(metadata.title);
460
693
  const skillsContext = config.skills?.getSkillsContext?.(serviceSlug);
461
- const allContexts = [...contexts, ...autoContexts, ...(skillsContext ? [skillsContext] : [])];
694
+ const allContexts = [
695
+ ...contexts,
696
+ ...autoContexts,
697
+ ...(skillsContext ? [skillsContext] : []),
698
+ ];
462
699
  const context = allContexts.find((ctx) => ctx.id === c.req.param("contextId"));
463
700
  if (context) {
464
701
  const agentInfo = await getAgentInfo(c);
465
702
  const body = await safeParseBody(c);
466
703
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
467
704
  const oauth2Client = app.oauth2?.getClient();
468
- const contextData = await context.getContextData(agentInfo, {
705
+ const extraData = buildServiceExtraData(agentInfo, {
706
+ request: processedPluginData,
469
707
  plugins: processedPluginData.plugins,
470
- oauth2Client
708
+ oauth2Client,
471
709
  });
710
+ const contextData = await context.getContextData(agentInfo, extraData);
472
711
  const response = {
473
712
  id: context.id,
474
713
  name: context.name,
475
714
  description: context.description,
476
- data: contextData
715
+ data: contextData,
477
716
  };
478
- const processedResponse = await processPluginsForResponse(response, body, { extraData: { plugins: processedPluginData.plugins } });
717
+ const processedResponse = await processPluginsForResponse(response, body, { extraData });
479
718
  return c.json(processedResponse);
480
719
  }
481
720
  else {
@@ -487,30 +726,42 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
487
726
  const body = await safeParseBody(c);
488
727
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
489
728
  const oauth2Client = app.oauth2?.getClient();
729
+ const extraData = buildServiceExtraData(agentInfo, {
730
+ request: processedPluginData,
731
+ plugins: processedPluginData.plugins,
732
+ oauth2Client,
733
+ });
490
734
  const autoContexts = app.oauth2?.getDirectProviderContexts?.() || [];
491
735
  const serviceSlug = (0, core_1.toSlug)(metadata.title);
492
736
  const skillsContext = config.skills?.getSkillsContext?.(serviceSlug);
493
- const allContexts = [...contexts, ...autoContexts, ...(skillsContext ? [skillsContext] : [])];
737
+ const allContexts = [
738
+ ...contexts,
739
+ ...autoContexts,
740
+ ...(skillsContext ? [skillsContext] : []),
741
+ ];
494
742
  const contextsFull = await Promise.all(allContexts.map(async (ctx) => ({
495
743
  id: ctx.id,
496
744
  name: ctx.name,
497
745
  description: ctx.description,
498
- data: await ctx.getContextData(agentInfo, {
499
- plugins: processedPluginData.plugins,
500
- oauth2Client
501
- }),
746
+ data: await ctx.getContextData(agentInfo, extraData),
502
747
  })));
503
- const processedResponse = await processPluginsForResponse(contextsFull, body, { extraData: { plugins: processedPluginData.plugins } });
748
+ const processedResponse = await processPluginsForResponse(contextsFull, body, { extraData });
504
749
  return c.json(processedResponse);
505
750
  });
506
751
  app.post("/widgets", async (c) => {
507
752
  const agentInfo = await getAgentInfo(c);
508
753
  const body = await safeParseBody(c);
509
754
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
755
+ const extraData = buildServiceExtraData(agentInfo, {
756
+ request: processedPluginData,
757
+ plugins: processedPluginData.plugins,
758
+ });
510
759
  const widgetIds = config.getUserWidgets
511
- ? await config.getUserWidgets(agentInfo, { plugins: processedPluginData.plugins })
512
- : widgets.map(widget => widget.id);
513
- const processedResponse = await processPluginsForResponse(widgetIds, body, { extraData: { plugins: processedPluginData.plugins } });
760
+ ? await config.getUserWidgets(agentInfo, extraData)
761
+ : widgets.map((widget) => widget.id);
762
+ const processedResponse = await processPluginsForResponse(widgetIds, body, {
763
+ extraData,
764
+ });
514
765
  return c.json(processedResponse);
515
766
  });
516
767
  app.post("/widgets/all", async (c) => {
@@ -518,18 +769,23 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
518
769
  const body = await safeParseBody(c);
519
770
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
520
771
  const widgetIds = config.getUserWidgets
521
- ? await config.getUserWidgets(agentInfo, { plugins: processedPluginData.plugins })
522
- : widgets.map(widget => widget.id);
772
+ ? await config.getUserWidgets(agentInfo, buildServiceExtraData(agentInfo, {
773
+ request: processedPluginData,
774
+ plugins: processedPluginData.plugins,
775
+ }))
776
+ : widgets.map((widget) => widget.id);
523
777
  const oauth2Client = app.oauth2?.getClient();
778
+ const extraData = buildServiceExtraData(agentInfo, {
779
+ request: processedPluginData,
780
+ plugins: processedPluginData.plugins,
781
+ oauth2Client,
782
+ app,
783
+ });
524
784
  const widgetsFull = await Promise.all(widgetIds.map(async (widgetId) => {
525
- const widget = widgets.find(w => w.id === widgetId);
785
+ const widget = widgets.find((w) => w.id === widgetId);
526
786
  if (!widget)
527
787
  return null;
528
- const widgetData = await widget.getWidget(agentInfo, {
529
- plugins: processedPluginData.plugins,
530
- oauth2Client,
531
- app
532
- });
788
+ const widgetData = await widget.getWidget(agentInfo, extraData);
533
789
  const response = {
534
790
  id: widget.id,
535
791
  name: widget.name,
@@ -537,7 +793,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
537
793
  icon: widget.icon,
538
794
  size: widget.size || "sm",
539
795
  refreshIntervalMs: widget.refreshIntervalMs,
540
- ...widgetData
796
+ ...widgetData,
541
797
  };
542
798
  if (!("freshness" in response)) {
543
799
  response.freshness = {
@@ -551,13 +807,13 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
551
807
  }
552
808
  return response;
553
809
  }));
554
- const validWidgets = widgetsFull.filter(w => w !== null);
555
- const processedResponse = await processPluginsForResponse(validWidgets, body, { extraData: { plugins: processedPluginData.plugins } });
810
+ const validWidgets = widgetsFull.filter((w) => w !== null);
811
+ const processedResponse = await processPluginsForResponse(validWidgets, body, { extraData });
556
812
  return c.json(processedResponse);
557
813
  });
558
814
  app.post("/widgets/:widgetId", async (c) => {
559
815
  const widgetId = c.req.param("widgetId");
560
- const widget = widgets.find(w => w.id === widgetId);
816
+ const widget = widgets.find((w) => w.id === widgetId);
561
817
  if (!widget) {
562
818
  throw new http_exception_1.HTTPException(404, { message: "Widget not found" });
563
819
  }
@@ -565,25 +821,34 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
565
821
  const body = await safeParseBody(c);
566
822
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
567
823
  if (config.getUserWidgets) {
824
+ const accessExtraData = buildServiceExtraData(agentInfo, {
825
+ request: processedPluginData,
826
+ plugins: processedPluginData.plugins,
827
+ });
568
828
  const userWidgetIds = await config.getUserWidgets(agentInfo, {
569
- plugins: processedPluginData.plugins
829
+ ...accessExtraData,
570
830
  });
571
831
  let homeUIWidgetId = null;
572
832
  if (config.homeUI) {
573
- homeUIWidgetId = typeof config.homeUI === 'string'
574
- ? config.homeUI
575
- : await config.homeUI(agentInfo, { plugins: processedPluginData.plugins });
833
+ homeUIWidgetId =
834
+ typeof config.homeUI === "string"
835
+ ? config.homeUI
836
+ : await config.homeUI(agentInfo, accessExtraData);
576
837
  }
577
838
  if (!userWidgetIds.includes(widgetId) && widgetId !== homeUIWidgetId) {
578
- throw new http_exception_1.HTTPException(403, { message: "Access denied to this widget" });
839
+ throw new http_exception_1.HTTPException(403, {
840
+ message: "Access denied to this widget",
841
+ });
579
842
  }
580
843
  }
581
844
  const oauth2Client = app.oauth2?.getClient();
582
- const widgetData = await widget.getWidget(agentInfo, {
845
+ const extraData = buildServiceExtraData(agentInfo, {
846
+ request: processedPluginData,
583
847
  plugins: processedPluginData.plugins,
584
848
  oauth2Client,
585
- app
849
+ app,
586
850
  });
851
+ const widgetData = await widget.getWidget(agentInfo, extraData);
587
852
  const response = {
588
853
  id: widget.id,
589
854
  name: widget.name,
@@ -591,7 +856,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
591
856
  icon: widget.icon,
592
857
  size: widget.size || "sm",
593
858
  refreshIntervalMs: widget.refreshIntervalMs,
594
- ...widgetData
859
+ ...widgetData,
595
860
  };
596
861
  if (!("freshness" in response)) {
597
862
  response.freshness = {
@@ -603,7 +868,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
603
868
  scope: "account",
604
869
  };
605
870
  }
606
- const processedResponse = await processPluginsForResponse(response, body, { extraData: { plugins: processedPluginData.plugins } });
871
+ const processedResponse = await processPluginsForResponse(response, body, {
872
+ extraData,
873
+ });
607
874
  return c.json(processedResponse);
608
875
  });
609
876
  app.post("/homeUI", async (c) => {
@@ -613,17 +880,21 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
613
880
  const agentInfo = await getAgentInfo(c);
614
881
  const body = await safeParseBody(c);
615
882
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
616
- const homeUIWidgetId = typeof config.homeUI === 'string'
883
+ const extraData = buildServiceExtraData(agentInfo, {
884
+ request: processedPluginData,
885
+ plugins: processedPluginData.plugins,
886
+ });
887
+ const homeUIWidgetId = typeof config.homeUI === "string"
617
888
  ? config.homeUI
618
- : await config.homeUI(agentInfo, { plugins: processedPluginData.plugins });
889
+ : await config.homeUI(agentInfo, extraData);
619
890
  if (!homeUIWidgetId) {
620
891
  return c.json({ widgetId: null });
621
892
  }
622
- const widget = widgets.find(w => w.id === homeUIWidgetId);
893
+ const widget = widgets.find((w) => w.id === homeUIWidgetId);
623
894
  if (!widget) {
624
895
  return c.json({ widgetId: null });
625
896
  }
626
- const processedResponse = await processPluginsForResponse({ widgetId: homeUIWidgetId }, body, { extraData: { plugins: processedPluginData.plugins } });
897
+ const processedResponse = await processPluginsForResponse({ widgetId: homeUIWidgetId }, body, { extraData });
627
898
  return c.json(processedResponse);
628
899
  });
629
900
  function mapDatasourceInfo(datasource) {
@@ -648,14 +919,24 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
648
919
  const agentInfo = await getAgentInfo(c);
649
920
  const body = await safeParseBody(c);
650
921
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
651
- const processedResponse = await processPluginsForResponse(datasources.map(mapDatasourceInfo), body, { extraData: { plugins: processedPluginData.plugins } });
922
+ const processedResponse = await processPluginsForResponse(datasources.map(mapDatasourceInfo), body, {
923
+ extraData: buildServiceExtraData(agentInfo, {
924
+ request: processedPluginData,
925
+ plugins: processedPluginData.plugins,
926
+ }),
927
+ });
652
928
  return c.json(processedResponse);
653
929
  });
654
930
  app.post("/datasources/all", async (c) => {
655
931
  const agentInfo = await getAgentInfo(c);
656
932
  const body = await safeParseBody(c);
657
933
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
658
- const processedResponse = await processPluginsForResponse(datasources.map(mapDatasourceInfo), body, { extraData: { plugins: processedPluginData.plugins } });
934
+ const processedResponse = await processPluginsForResponse(datasources.map(mapDatasourceInfo), body, {
935
+ extraData: buildServiceExtraData(agentInfo, {
936
+ request: processedPluginData,
937
+ plugins: processedPluginData.plugins,
938
+ }),
939
+ });
659
940
  return c.json(processedResponse);
660
941
  });
661
942
  app.post("/datasources/:datasourceId", async (c) => {
@@ -671,10 +952,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
671
952
  try {
672
953
  const parsedParams = datasource.input.parse(params);
673
954
  const oauth2Client = app.oauth2?.getClient();
674
- const data = await datasource.getDatasource(agentInfo, parsedParams, {
955
+ const extraData = buildServiceExtraData(agentInfo, {
956
+ request: params,
675
957
  plugins: pluginsData,
676
- oauth2Client
958
+ oauth2Client,
677
959
  });
960
+ const data = await datasource.getDatasource(agentInfo, parsedParams, extraData);
678
961
  const requestedPolicy = {
679
962
  refreshIntervalMs: datasource.refreshIntervalMs,
680
963
  maxStalenessMs: datasource.maxStalenessMs,
@@ -702,7 +985,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
702
985
  scope: datasource.scope,
703
986
  },
704
987
  };
705
- const processedResponse = await processPluginsForResponse(response, { plugins: pluginsData }, { extraData: { plugins: pluginsData } });
988
+ const processedResponse = await processPluginsForResponse(response, { plugins: pluginsData }, { extraData });
706
989
  return c.json(processedResponse);
707
990
  }
708
991
  catch (error) {
@@ -712,12 +995,23 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
712
995
  .join(", ");
713
996
  return c.json({
714
997
  error: `Missing or invalid parameters: ${missingParams}`,
715
- code: "INVALID_PARAMS"
998
+ code: "INVALID_PARAMS",
716
999
  }, 400);
717
1000
  }
718
1001
  throw error;
719
1002
  }
720
1003
  });
1004
+ app.delete("/datasources/:datasourceId/stream/:streamId", async (c) => {
1005
+ const datasourceId = c.req.param("datasourceId");
1006
+ const streamId = c.req.param("streamId");
1007
+ const streamKey = `${datasourceId}:${streamId}`;
1008
+ const abortController = datasourceStreamAbortControllers.get(streamKey);
1009
+ if (abortController) {
1010
+ abortController.abort();
1011
+ datasourceStreamAbortControllers.delete(streamKey);
1012
+ }
1013
+ return c.json({ success: true });
1014
+ });
721
1015
  // Stream datasource updates over SSE. This is primarily used for "fresh" UIs
722
1016
  // (positions/orders) where clients want stream-first updates with a poll fallback.
723
1017
  //
@@ -734,12 +1028,23 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
734
1028
  typeof rawBody === "object" &&
735
1029
  !Array.isArray(rawBody) &&
736
1030
  "params" in rawBody;
737
- const requestedIntervalMsRaw = hasWrappedParams ? rawBody.intervalMs : undefined;
738
- const requestParamsRaw = hasWrappedParams ? rawBody.params : rawBody;
739
- let params = await processPluginsForRequest(requestParamsRaw && typeof requestParamsRaw === "object" ? requestParamsRaw : {}, agentInfo);
740
- const pluginsData = (params.plugins && typeof params.plugins === "object"
741
- ? params.plugins
742
- : {});
1031
+ const requestedIntervalMsRaw = hasWrappedParams
1032
+ ? rawBody.intervalMs
1033
+ : undefined;
1034
+ const requestedStreamIdRaw = hasWrappedParams
1035
+ ? rawBody.streamId
1036
+ : undefined;
1037
+ const streamId = typeof requestedStreamIdRaw === "string" &&
1038
+ /^[A-Za-z0-9._:-]{1,128}$/.test(requestedStreamIdRaw)
1039
+ ? requestedStreamIdRaw
1040
+ : null;
1041
+ const requestParamsRaw = hasWrappedParams
1042
+ ? rawBody.params
1043
+ : rawBody;
1044
+ let params = await processPluginsForRequest(requestParamsRaw && typeof requestParamsRaw === "object"
1045
+ ? requestParamsRaw
1046
+ : {}, agentInfo);
1047
+ const pluginsData = (params.plugins && typeof params.plugins === "object" ? params.plugins : {});
743
1048
  delete params.plugins;
744
1049
  let parsedParams;
745
1050
  try {
@@ -752,24 +1057,31 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
752
1057
  .join(", ");
753
1058
  return c.json({
754
1059
  error: `Missing or invalid parameters: ${missingParams}`,
755
- code: "INVALID_PARAMS"
1060
+ code: "INVALID_PARAMS",
756
1061
  }, 400);
757
1062
  }
758
1063
  throw error;
759
1064
  }
1065
+ const oauth2Client = app.oauth2?.getClient();
1066
+ const extraData = buildServiceExtraData(agentInfo, {
1067
+ request: params,
1068
+ plugins: pluginsData,
1069
+ oauth2Client,
1070
+ });
760
1071
  const pluginRequestContext = hasWrappedParams
761
1072
  ? {
762
1073
  params: parsedParams,
763
1074
  intervalMs: requestedIntervalMsRaw,
764
1075
  plugins: pluginsData,
1076
+ DAIN_EXTRA_DATA: extraData,
765
1077
  }
766
1078
  : {
767
1079
  ...(typeof parsedParams === "object" && parsedParams !== null
768
1080
  ? parsedParams
769
1081
  : {}),
770
1082
  plugins: pluginsData,
1083
+ DAIN_EXTRA_DATA: extraData,
771
1084
  };
772
- const oauth2Client = app.oauth2?.getClient();
773
1085
  const requestedPolicy = {
774
1086
  refreshIntervalMs: datasource.refreshIntervalMs,
775
1087
  maxStalenessMs: datasource.maxStalenessMs,
@@ -778,23 +1090,35 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
778
1090
  scope: datasource.scope,
779
1091
  dataClass: datasource.dataClass,
780
1092
  };
781
- const requestedIntervalMs = typeof requestedIntervalMsRaw === "number" && Number.isFinite(requestedIntervalMsRaw) && requestedIntervalMsRaw > 0
1093
+ const requestedIntervalMs = typeof requestedIntervalMsRaw === "number" &&
1094
+ Number.isFinite(requestedIntervalMsRaw) &&
1095
+ requestedIntervalMsRaw > 0
782
1096
  ? requestedIntervalMsRaw
783
1097
  : null;
784
1098
  const baseIntervalMs = requestedIntervalMs ??
785
- (typeof datasource.refreshIntervalMs === "number" && datasource.refreshIntervalMs > 0
1099
+ (typeof datasource.refreshIntervalMs === "number" &&
1100
+ datasource.refreshIntervalMs > 0
786
1101
  ? datasource.refreshIntervalMs
787
1102
  : 15_000);
788
1103
  const intervalMs = Math.max(1_000, Math.floor(baseIntervalMs));
789
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
790
1104
  debugLog(`[SSE] Datasource ${datasource.id} stream start (${intervalMs}ms interval)`);
791
1105
  return signedStreamSSE(c, privateKey, config, async (stream) => {
792
1106
  let eventId = 0;
1107
+ const signal = c.req.raw?.signal;
1108
+ const streamAbortController = new AbortController();
1109
+ const streamKey = streamId ? `${datasource.id}:${streamId}` : null;
1110
+ if (streamKey) {
1111
+ datasourceStreamAbortControllers.set(streamKey, streamAbortController);
1112
+ }
1113
+ const isCancelled = () => stream.isAborted() ||
1114
+ signal?.aborted === true ||
1115
+ streamAbortController.signal.aborted;
793
1116
  const emitUpdate = async () => {
794
- const data = await datasource.getDatasource(agentInfo, parsedParams, {
795
- plugins: pluginsData,
796
- oauth2Client,
797
- });
1117
+ if (isCancelled())
1118
+ return false;
1119
+ const data = await datasource.getDatasource(agentInfo, parsedParams, extraData);
1120
+ if (isCancelled())
1121
+ return false;
798
1122
  const response = {
799
1123
  id: datasource.id,
800
1124
  name: datasource.name,
@@ -814,51 +1138,81 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
814
1138
  scope: datasource.scope,
815
1139
  },
816
1140
  };
817
- const processedResponse = await processPluginsForResponse(response, pluginRequestContext, { extraData: { plugins: pluginsData } });
1141
+ const processedResponse = await processPluginsForResponse(response, pluginRequestContext, { extraData });
1142
+ if (isCancelled())
1143
+ return false;
818
1144
  await stream.writeSSE({
819
1145
  event: "datasource-update",
820
1146
  data: JSON.stringify(processedResponse),
821
1147
  id: String(eventId++),
822
1148
  });
1149
+ return true;
823
1150
  };
824
- // Send initial snapshot immediately.
825
1151
  try {
826
- await emitUpdate();
827
- }
828
- catch (error) {
829
- console.error(`[SSE] Datasource ${datasource.id} initial update failed:`, error);
830
- if (!stream.isAborted()) {
831
- await stream.writeSSE({
832
- event: "error",
833
- data: JSON.stringify({ message: error?.message || "Datasource stream error" }),
834
- });
835
- }
836
- return;
837
- }
838
- // Continue sending updates until client disconnects.
839
- // Hono exposes the underlying Request via c.req.raw, which includes an AbortSignal.
840
- const signal = c.req.raw?.signal;
841
- while (!stream.isAborted() && !signal?.aborted) {
842
- await sleep(intervalMs);
843
- if (stream.isAborted() || signal?.aborted)
844
- break;
1152
+ // Send initial snapshot immediately.
845
1153
  try {
846
- await emitUpdate();
1154
+ const didEmitInitialUpdate = await emitUpdate();
1155
+ if (!didEmitInitialUpdate)
1156
+ return;
847
1157
  }
848
1158
  catch (error) {
849
- if (stream.isAborted() || signal?.aborted)
850
- break;
851
- console.error(`[SSE] Datasource ${datasource.id} update failed:`, error);
852
- // Keep the stream alive; clients should rely on poll fallback if needed.
853
- if (!stream.isAborted()) {
1159
+ console.error(`[SSE] Datasource ${datasource.id} initial update failed:`, error);
1160
+ if (!isCancelled()) {
854
1161
  await stream.writeSSE({
855
1162
  event: "error",
856
- data: JSON.stringify({ message: error?.message || "Datasource stream error" }),
1163
+ data: JSON.stringify({
1164
+ message: error?.message || "Datasource stream error",
1165
+ }),
857
1166
  });
858
1167
  }
1168
+ return;
1169
+ }
1170
+ // Continue sending updates until client disconnects.
1171
+ // Hono exposes the underlying Request via c.req.raw, which includes an AbortSignal.
1172
+ const abortPromise = new Promise((resolve) => {
1173
+ if (isCancelled()) {
1174
+ resolve();
1175
+ return;
1176
+ }
1177
+ stream.onAbort(() => resolve());
1178
+ signal?.addEventListener("abort", () => resolve(), { once: true });
1179
+ streamAbortController.signal.addEventListener("abort", () => resolve(), { once: true });
1180
+ });
1181
+ const sleepUntilNextUpdate = (ms) => Promise.race([
1182
+ new Promise((resolve) => setTimeout(resolve, ms)),
1183
+ abortPromise,
1184
+ ]);
1185
+ while (!isCancelled()) {
1186
+ await sleepUntilNextUpdate(intervalMs);
1187
+ if (isCancelled())
1188
+ break;
1189
+ try {
1190
+ const didEmitUpdate = await emitUpdate();
1191
+ if (!didEmitUpdate)
1192
+ break;
1193
+ }
1194
+ catch (error) {
1195
+ if (isCancelled())
1196
+ break;
1197
+ console.error(`[SSE] Datasource ${datasource.id} update failed:`, error);
1198
+ // Keep the stream alive; clients should rely on poll fallback if needed.
1199
+ if (!isCancelled()) {
1200
+ await stream.writeSSE({
1201
+ event: "error",
1202
+ data: JSON.stringify({
1203
+ message: error?.message || "Datasource stream error",
1204
+ }),
1205
+ });
1206
+ }
1207
+ }
859
1208
  }
860
1209
  }
861
- debugLog(`[SSE] Datasource ${datasource.id} stream end`);
1210
+ finally {
1211
+ if (streamKey) {
1212
+ datasourceStreamAbortControllers.delete(streamKey);
1213
+ }
1214
+ debugLog(`[SSE] Datasource ${datasource.id} stream end`);
1215
+ }
862
1216
  });
863
1217
  });
864
1218
  function mapAgentInfo(agent) {
@@ -868,7 +1222,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
868
1222
  context: agent.context,
869
1223
  prompt: agent.prompt,
870
1224
  resolveCondition: agent.resolveCondition,
871
- serviceConnections: agent.serviceConnections || [process.env.BASE_URL || 'http://localhost:3000'],
1225
+ serviceConnections: agent.serviceConnections || [
1226
+ process.env.BASE_URL || "http://localhost:3000",
1227
+ ],
872
1228
  inputSchema: (0, schemaStructure_1.zodToJsonSchema)(agent.input),
873
1229
  outputSchema: (0, schemaStructure_1.zodToJsonSchema)(agent.output),
874
1230
  };
@@ -880,7 +1236,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
880
1236
  const agentInfo = await getAgentInfo(c);
881
1237
  const body = await safeParseBody(c);
882
1238
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
883
- const processedResponse = await processPluginsForResponse(agents.map(mapAgentInfo), body, { extraData: { plugins: processedPluginData.plugins } });
1239
+ const processedResponse = await processPluginsForResponse(agents.map(mapAgentInfo), body, {
1240
+ extraData: buildServiceExtraData(agentInfo, {
1241
+ request: processedPluginData,
1242
+ plugins: processedPluginData.plugins,
1243
+ }),
1244
+ });
884
1245
  return c.json(processedResponse);
885
1246
  });
886
1247
  app.get("/agents/:agentId", (c) => {
@@ -898,18 +1259,25 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
898
1259
  const agentInfo = await getAgentInfo(c);
899
1260
  const body = await safeParseBody(c);
900
1261
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
901
- const processedResponse = await processPluginsForResponse(mapAgentInfo(agent), body, { extraData: { plugins: processedPluginData.plugins } });
1262
+ const processedResponse = await processPluginsForResponse(mapAgentInfo(agent), body, {
1263
+ extraData: buildServiceExtraData(agentInfo, {
1264
+ request: processedPluginData,
1265
+ plugins: processedPluginData.plugins,
1266
+ }),
1267
+ });
902
1268
  return c.json(processedResponse);
903
1269
  });
904
1270
  function fixEmptySchemas(schema) {
905
- if (!schema || typeof schema !== 'object')
1271
+ if (!schema || typeof schema !== "object")
906
1272
  return;
907
- if (schema.properties && typeof schema.properties === 'object') {
1273
+ if (schema.properties && typeof schema.properties === "object") {
908
1274
  const props = schema.properties;
909
1275
  for (const key of Object.keys(props)) {
910
1276
  const prop = props[key];
911
- if (prop && typeof prop === 'object' && Object.keys(prop).length === 0) {
912
- props[key] = { type: 'object' };
1277
+ if (prop &&
1278
+ typeof prop === "object" &&
1279
+ Object.keys(prop).length === 0) {
1280
+ props[key] = { type: "object" };
913
1281
  }
914
1282
  fixEmptySchemas(prop);
915
1283
  }
@@ -922,10 +1290,10 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
922
1290
  let inputSchema = (0, schemaStructure_1.zodToJsonSchema)(tool.input);
923
1291
  let outputSchema = (0, schemaStructure_1.zodToJsonSchema)(tool.output);
924
1292
  if (!inputSchema.type) {
925
- inputSchema = { ...inputSchema, type: 'object' };
1293
+ inputSchema = { ...inputSchema, type: "object" };
926
1294
  }
927
1295
  if (!outputSchema.type) {
928
- outputSchema = { ...outputSchema, type: 'object' };
1296
+ outputSchema = { ...outputSchema, type: "object" };
929
1297
  }
930
1298
  fixEmptySchemas(inputSchema);
931
1299
  fixEmptySchemas(outputSchema);
@@ -971,7 +1339,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
971
1339
  reccomendedPrompts,
972
1340
  }),
973
1341
  };
974
- const processedResponse = await processPluginsForResponse(response, body, { extraData: { plugins: processedPluginData.plugins } });
1342
+ const processedResponse = await processPluginsForResponse(response, body, {
1343
+ extraData: buildServiceExtraData(agentInfo, {
1344
+ request: processedPluginData,
1345
+ plugins: processedPluginData.plugins,
1346
+ }),
1347
+ });
975
1348
  return c.json(processedResponse);
976
1349
  });
977
1350
  // Webhook triggers endpoint
@@ -987,11 +1360,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
987
1360
  // Configure trigger forwarding (uses HITL config for automation API)
988
1361
  if (config.webhookTriggers) {
989
1362
  // Resolve automation API URL (priority: hitl config > env)
990
- const automationApiUrl = config.hitl?.automationApiUrl ||
991
- process.env.AUTOMATION_API_URL;
1363
+ const automationApiUrl = config.hitl?.automationApiUrl || process.env.AUTOMATION_API_URL;
992
1364
  // Resolve API key
993
- const automationApiKey = config.hitl?.automationApiKey ||
994
- process.env.AUTOMATION_API_KEY;
1365
+ const automationApiKey = config.hitl?.automationApiKey || process.env.AUTOMATION_API_KEY;
995
1366
  // Resolve service URL (priority: oauth2.baseUrl > env)
996
1367
  const serviceUrl = config.oauth2?.baseUrl ||
997
1368
  process.env.SERVICE_BASE_URL ||
@@ -1014,10 +1385,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1014
1385
  try {
1015
1386
  const registerUrl = `${automationApiUrl}/webhooks/register-triggers`;
1016
1387
  const response = await fetch(registerUrl, {
1017
- method: 'POST',
1388
+ method: "POST",
1018
1389
  headers: {
1019
- 'Content-Type': 'application/json',
1020
- ...(automationApiKey ? { 'Authorization': `Bearer ${automationApiKey}` } : {}),
1390
+ "Content-Type": "application/json",
1391
+ ...(automationApiKey
1392
+ ? { Authorization: `Bearer ${automationApiKey}` }
1393
+ : {}),
1021
1394
  },
1022
1395
  body: JSON.stringify({
1023
1396
  serviceUrl,
@@ -1042,10 +1415,10 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1042
1415
  }
1043
1416
  else {
1044
1417
  if (!automationApiUrl) {
1045
- console.warn('[Webhook] Trigger forwarding disabled: missing automationApiUrl (set hitl.automationApiUrl or AUTOMATION_API_URL)');
1418
+ console.warn("[Webhook] Trigger forwarding disabled: missing automationApiUrl (set hitl.automationApiUrl or AUTOMATION_API_URL)");
1046
1419
  }
1047
1420
  if (!serviceUrl) {
1048
- console.warn('[Webhook] Trigger forwarding disabled: missing serviceUrl (set oauth2.baseUrl or SERVICE_BASE_URL)');
1421
+ console.warn("[Webhook] Trigger forwarding disabled: missing serviceUrl (set oauth2.baseUrl or SERVICE_BASE_URL)");
1049
1422
  }
1050
1423
  }
1051
1424
  }
@@ -1070,7 +1443,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1070
1443
  success: true,
1071
1444
  triggerId: result.triggerId,
1072
1445
  triggerName: result.triggerName,
1073
- data: result.data
1446
+ data: result.data,
1074
1447
  });
1075
1448
  }
1076
1449
  else {
@@ -1078,7 +1451,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1078
1451
  // No trigger matched - return 200 OK but with success: false
1079
1452
  return c.json({
1080
1453
  success: false,
1081
- message: 'No trigger matched'
1454
+ message: "No trigger matched",
1082
1455
  }, 200);
1083
1456
  }
1084
1457
  }
@@ -1086,22 +1459,22 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1086
1459
  console.error(`[Webhook] Error processing webhook at ${path}:`, error);
1087
1460
  // Return error response
1088
1461
  throw new http_exception_1.HTTPException(500, {
1089
- message: `Webhook processing failed: ${error.message}`
1462
+ message: `Webhook processing failed: ${error.message}`,
1090
1463
  });
1091
1464
  }
1092
1465
  });
1093
1466
  }
1094
- console.log(`[Webhook] Registered ${webhookPaths.length} webhook endpoint(s): ${webhookPaths.join(', ')}`);
1467
+ console.log(`[Webhook] Registered ${webhookPaths.length} webhook endpoint(s): ${webhookPaths.join(", ")}`);
1095
1468
  }
1096
1469
  // Auto-register HITL action webhook
1097
1470
  if (config.hitl?.enabled) {
1098
- const hitlPath = config.hitl.webhookPath || '/actions';
1471
+ const hitlPath = config.hitl.webhookPath || "/actions";
1099
1472
  const automationApiUrl = config.hitl.automationApiUrl ||
1100
1473
  process.env.AUTOMATION_API_URL ||
1101
- 'http://localhost:3000';
1474
+ "http://localhost:3000";
1102
1475
  const automationApiKey = config.hitl.automationApiKey || process.env.AUTOMATION_API_KEY;
1103
1476
  if (!automationApiUrl) {
1104
- console.warn('[HITL] Enabled but missing automationApiUrl - HITL webhook will not work correctly');
1477
+ console.warn("[HITL] Enabled but missing automationApiUrl - HITL webhook will not work correctly");
1105
1478
  }
1106
1479
  const hitlHandler = new hitl_1.HITLHandler({
1107
1480
  automationApiUrl,
@@ -1112,19 +1485,19 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1112
1485
  try {
1113
1486
  const body = await c.req.json();
1114
1487
  const { action, context } = body;
1115
- if (!action || typeof action !== 'string') {
1488
+ if (!action || typeof action !== "string") {
1116
1489
  throw new http_exception_1.HTTPException(400, {
1117
1490
  message: 'Missing or invalid "action" field in request body',
1118
1491
  });
1119
1492
  }
1120
- if (!context || typeof context !== 'object') {
1493
+ if (!context || typeof context !== "object") {
1121
1494
  throw new http_exception_1.HTTPException(400, {
1122
1495
  message: 'Missing or invalid "context" field in request body',
1123
1496
  });
1124
1497
  }
1125
1498
  if (!hitlHandler.isValidAction(action)) {
1126
1499
  throw new http_exception_1.HTTPException(400, {
1127
- message: 'Invalid action format. Expected: scope:id:action[:payload]',
1500
+ message: "Invalid action format. Expected: scope:id:action[:payload]",
1128
1501
  });
1129
1502
  }
1130
1503
  const result = await hitlHandler.handleAction(action, context);
@@ -1134,7 +1507,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1134
1507
  if (error instanceof http_exception_1.HTTPException) {
1135
1508
  throw error;
1136
1509
  }
1137
- console.error('[HITL] Error processing action:', error);
1510
+ console.error("[HITL] Error processing action:", error);
1138
1511
  throw new http_exception_1.HTTPException(500, {
1139
1512
  message: `Action processing failed: ${error.message}`,
1140
1513
  });
@@ -1246,7 +1619,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1246
1619
  const oauthTool = (0, core_1.createOAuth2Tool)(providerName, serviceSlug, {
1247
1620
  logoUrl: providerConfig.logoUrl,
1248
1621
  reason: providerConfig.reason,
1249
- requiredTools: providerConfig.requiredTools
1622
+ requiredTools: providerConfig.requiredTools,
1250
1623
  });
1251
1624
  autoOAuth2Tools.push(oauthTool);
1252
1625
  });
@@ -1276,11 +1649,17 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1276
1649
  }
1277
1650
  try {
1278
1651
  await app.oauth2.handleCallback(code, state);
1279
- return c.html("<html><body><script>window.opener.postMessage({ type: 'oauth2-success', provider: '" + provider + "' }, '*');window.close();</script><h1>Authentication successful! You can close this window.</h1></body></html>");
1652
+ return c.html("<html><body><script>window.opener.postMessage({ type: 'oauth2-success', provider: '" +
1653
+ provider +
1654
+ "' }, '*');window.close();</script><h1>Authentication successful! You can close this window.</h1></body></html>");
1280
1655
  }
1281
1656
  catch (error) {
1282
1657
  console.error("OAuth callback error:", error);
1283
- return c.html("<html><body><script>window.opener.postMessage({ type: 'oauth2-error', provider: '" + provider + "', error: '" + error.message + "' }, '*');window.close();</script><h1>Authentication failed! You can close this window.</h1></body></html>");
1658
+ return c.html("<html><body><script>window.opener.postMessage({ type: 'oauth2-error', provider: '" +
1659
+ provider +
1660
+ "', error: '" +
1661
+ error.message +
1662
+ "' }, '*');window.close();</script><h1>Authentication failed! You can close this window.</h1></body></html>");
1284
1663
  }
1285
1664
  });
1286
1665
  // Make oauth2Handler available to tools
@@ -1299,7 +1678,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1299
1678
  }
1300
1679
  catch (error) {
1301
1680
  if (error.message === "Unauthorized access to process") {
1302
- throw new http_exception_1.HTTPException(403, { message: "Unauthorized access to process" });
1681
+ throw new http_exception_1.HTTPException(403, {
1682
+ message: "Unauthorized access to process",
1683
+ });
1303
1684
  }
1304
1685
  throw error;
1305
1686
  }
@@ -1315,7 +1696,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1315
1696
  const providersWithStatus = await Promise.all(providers.map(async ({ name, config }) => ({
1316
1697
  name,
1317
1698
  config,
1318
- connected: await app.oauth2.hasValidTokens(name, agentInfo.id)
1699
+ connected: await app.oauth2.hasValidTokens(name, agentInfo.id),
1319
1700
  })));
1320
1701
  return c.json(providersWithStatus);
1321
1702
  });
@@ -1332,7 +1713,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1332
1713
  app.get("/oauth2/connect/:provider", async (c) => {
1333
1714
  debugLog("[OAuth2 Connect] Route hit - START");
1334
1715
  debugLog("[OAuth2 Connect] Provider param:", c.req.param("provider"));
1335
- debugLog("[OAuth2 Connect] Auth method:", c.get('authMethod'));
1716
+ debugLog("[OAuth2 Connect] Auth method:", c.get("authMethod"));
1336
1717
  debugLog("[OAuth2 Connect] Headers:", {
1337
1718
  authorization: c.req.header("Authorization"),
1338
1719
  apiKey: c.req.header("X-DAIN-API-KEY"),
@@ -1363,7 +1744,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1363
1744
  catch (error) {
1364
1745
  debugLog("[OAuth2 Connect] ERROR generating auth URL:", error);
1365
1746
  throw new http_exception_1.HTTPException(400, {
1366
- message: `Invalid provider: ${provider}`
1747
+ message: `Invalid provider: ${provider}`,
1367
1748
  });
1368
1749
  }
1369
1750
  });
@@ -1381,8 +1762,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1381
1762
  if (isComplete) {
1382
1763
  const config = await setupManager.getProviderConfig(agentInfo.id, provider);
1383
1764
  return c.json({
1384
- status: 'complete',
1385
- config: config ? { configuredAt: config.configuredAt } : undefined
1765
+ status: "complete",
1766
+ config: config ? { configuredAt: config.configuredAt } : undefined,
1386
1767
  });
1387
1768
  }
1388
1769
  // Check if there's a pending setup
@@ -1390,15 +1771,15 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1390
1771
  if (pendingSetup) {
1391
1772
  const expiresIn = Math.max(0, Math.floor((pendingSetup.expiresAt - Date.now()) / 1000));
1392
1773
  return c.json({
1393
- status: 'authorization_pending',
1774
+ status: "authorization_pending",
1394
1775
  expires_in: expiresIn,
1395
- interval: 5 // Poll every 5 seconds
1776
+ interval: 5, // Poll every 5 seconds
1396
1777
  });
1397
1778
  }
1398
1779
  // No setup in progress
1399
1780
  return c.json({
1400
- status: 'not_found',
1401
- error: 'No setup in progress for this provider'
1781
+ status: "not_found",
1782
+ error: "No setup in progress for this provider",
1402
1783
  });
1403
1784
  });
1404
1785
  // Get all human actions for a process
@@ -1411,13 +1792,15 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1411
1792
  }
1412
1793
  if (process.agentId !== agentInfo.id) {
1413
1794
  debugLog("Unauthorized access to process", process.agentId, agentInfo.id);
1414
- throw new http_exception_1.HTTPException(403, { message: "Unauthorized access to process" });
1795
+ throw new http_exception_1.HTTPException(403, {
1796
+ message: "Unauthorized access to process",
1797
+ });
1415
1798
  }
1416
1799
  return c.json(process.humanActions);
1417
1800
  });
1418
1801
  // Get specific human action
1419
1802
  app.get("/processes/:processId/human-actions/:stepId", async (c) => {
1420
- debugLog('GET human action request:', c.req.path);
1803
+ debugLog("GET human action request:", c.req.path);
1421
1804
  const processId = c.req.param("processId");
1422
1805
  const stepId = c.req.param("stepId");
1423
1806
  const agentInfo = await getAgentInfo(c);
@@ -1427,7 +1810,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1427
1810
  }
1428
1811
  if (process.agentId !== agentInfo.id) {
1429
1812
  debugLog("Unauthorized access to process", process.agentId, agentInfo.id);
1430
- throw new http_exception_1.HTTPException(403, { message: "Unauthorized access to process" });
1813
+ throw new http_exception_1.HTTPException(403, {
1814
+ message: "Unauthorized access to process",
1815
+ });
1431
1816
  }
1432
1817
  const step = await app.processes.checkHumanAction(processId, stepId);
1433
1818
  if (!step) {
@@ -1446,7 +1831,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1446
1831
  }
1447
1832
  if (process.agentId !== agentInfo.id) {
1448
1833
  debugLog("Unauthorized access to process", process.agentId, agentInfo.id);
1449
- throw new http_exception_1.HTTPException(403, { message: "Unauthorized access to process" });
1834
+ throw new http_exception_1.HTTPException(403, {
1835
+ message: "Unauthorized access to process",
1836
+ });
1450
1837
  }
1451
1838
  const body = await c.req.json();
1452
1839
  const { actionId, responseText, data } = body;
@@ -1477,7 +1864,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1477
1864
  }
1478
1865
  catch (error) {
1479
1866
  console.error(`Error generating confirmation UI for tool ${tool.id}:`, error);
1480
- throw new http_exception_1.HTTPException(500, { message: "Error generating confirmation UI" });
1867
+ throw new http_exception_1.HTTPException(500, {
1868
+ message: "Error generating confirmation UI",
1869
+ });
1481
1870
  }
1482
1871
  });
1483
1872
  app.get("/exampleQueries", (c) => {
@@ -1487,7 +1876,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1487
1876
  const agentInfo = await getAgentInfo(c);
1488
1877
  const body = await safeParseBody(c);
1489
1878
  const processedPluginData = await processPluginsForRequest(body, agentInfo);
1490
- const processedResponse = await processPluginsForResponse(config.exampleQueries || [], body, { extraData: { plugins: processedPluginData.plugins } });
1879
+ const processedResponse = await processPluginsForResponse(config.exampleQueries || [], body, {
1880
+ extraData: buildServiceExtraData(agentInfo, {
1881
+ request: processedPluginData,
1882
+ plugins: processedPluginData.plugins,
1883
+ }),
1884
+ });
1491
1885
  return c.json(processedResponse);
1492
1886
  });
1493
1887
  // Services list endpoint
@@ -1508,7 +1902,10 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1508
1902
  // Toolboxes list endpoint
1509
1903
  app.get("/toolboxes", (c) => c.json(toolboxes));
1510
1904
  function normalizeRecommendationText(value) {
1511
- return value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
1905
+ return value
1906
+ .toLowerCase()
1907
+ .replace(/[^a-z0-9]+/g, " ")
1908
+ .trim();
1512
1909
  }
1513
1910
  function tokenizeRecommendationQuery(query) {
1514
1911
  const normalized = normalizeRecommendationText(query);
@@ -1527,7 +1924,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1527
1924
  throw new Error(`Duplicate recommendation card ID "${scopedCardId}". Card IDs must be unique per tool.`);
1528
1925
  }
1529
1926
  const isDynamic = !!card.inputSchema;
1530
- const inputSchema = isDynamic ? (0, schemaStructure_1.zodToJsonSchema)(card.inputSchema) : undefined;
1927
+ const inputSchema = isDynamic
1928
+ ? (0, schemaStructure_1.zodToJsonSchema)(card.inputSchema)
1929
+ : undefined;
1531
1930
  const searchText = normalizeRecommendationText([tool.id, tool.name, card.id, ...card.tags].join(" "));
1532
1931
  index.set(scopedCardId, {
1533
1932
  cardId: scopedCardId,
@@ -1589,7 +1988,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1589
1988
  details: parsed.error.format(),
1590
1989
  }, 400);
1591
1990
  }
1592
- const { query, limit, toolIds, includeStaticUI, } = parsed.data;
1991
+ const { query, limit, toolIds, includeStaticUI } = parsed.data;
1593
1992
  const toolIdSet = toolIds?.length ? new Set(toolIds) : null;
1594
1993
  const filteredCards = Array.from(recommendationCardsById.values()).filter((card) => !toolIdSet || toolIdSet.has(card.toolId));
1595
1994
  const tokens = tokenizeRecommendationQuery(query ?? "");
@@ -1625,7 +2024,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1625
2024
  count: cards.length,
1626
2025
  query,
1627
2026
  };
1628
- const processedResponse = await processPluginsForResponse(response, body, { extraData: { plugins: processedPluginData.plugins } });
2027
+ const processedResponse = await processPluginsForResponse(response, body, {
2028
+ extraData: buildServiceExtraData(agentInfo, {
2029
+ request: processedPluginData,
2030
+ plugins: processedPluginData.plugins,
2031
+ }),
2032
+ });
1629
2033
  return c.json(processedResponse);
1630
2034
  });
1631
2035
  const recommendationRenderSchema = zod_1.z.object({
@@ -1717,7 +2121,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1717
2121
  renderErrors.push({
1718
2122
  cardId: card.cardId,
1719
2123
  code: "render_failed",
1720
- message: error instanceof Error ? error.message : "Failed to render recommendation card",
2124
+ message: error instanceof Error
2125
+ ? error.message
2126
+ : "Failed to render recommendation card",
1721
2127
  });
1722
2128
  if (!continueOnError)
1723
2129
  break;
@@ -1729,7 +2135,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1729
2135
  renderedCount: renderedCards.length,
1730
2136
  requestedCount: requestedCards.length,
1731
2137
  };
1732
- const processedResponse = await processPluginsForResponse(response, body, { extraData: { plugins: processedPluginData.plugins } });
2138
+ const processedResponse = await processPluginsForResponse(response, body, {
2139
+ extraData: buildServiceExtraData(agentInfo, {
2140
+ request: processedPluginData,
2141
+ plugins: processedPluginData.plugins,
2142
+ }),
2143
+ });
1733
2144
  const statusCode = !continueOnError && renderErrors.length > 0 ? 400 : 200;
1734
2145
  return c.json(processedResponse, statusCode);
1735
2146
  });
@@ -1740,17 +2151,57 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1740
2151
  if (!processedRequest.plugins) {
1741
2152
  processedRequest.plugins = {};
1742
2153
  }
2154
+ processedRequest.DAIN_EXTRA_DATA = buildServiceExtraData(agentInfo, {
2155
+ request: processedRequest,
2156
+ plugins: processedRequest.plugins,
2157
+ });
1743
2158
  // Auto-inject smartAccountPDA into CryptoPlugin wallet context for automations
1744
2159
  // This allows automation wallets to work seamlessly without manual configuration
1745
2160
  if (agentInfo.smartAccountPDA) {
1746
- // Only inject if wallets aren't already provided (client can override)
1747
- if (!processedRequest.plugins['crypto-plugin']?.wallets) {
1748
- processedRequest.plugins['crypto-plugin'] = processedRequest.plugins['crypto-plugin'] || {};
1749
- processedRequest.plugins['crypto-plugin'].wallets = [
1750
- { chain: 'sol', address: agentInfo.smartAccountPDA }
2161
+ processedRequest.plugins["crypto-plugin"] =
2162
+ processedRequest.plugins["crypto-plugin"] || {};
2163
+ const cryptoData = isRecord(processedRequest.plugins["crypto-plugin"])
2164
+ ? stripRuntimeContextFields(processedRequest.plugins["crypto-plugin"])
2165
+ : {};
2166
+ processedRequest.plugins["crypto-plugin"] = cryptoData;
2167
+ const smartAccountWallet = {
2168
+ chain: "sol",
2169
+ address: agentInfo.smartAccountPDA,
2170
+ accountId: agentInfo.dainAccountId ?? agentInfo.dainGroupId,
2171
+ kind: "smart_account_vault",
2172
+ capabilities: ["solana-smart-account"],
2173
+ };
2174
+ if (Array.isArray(cryptoData.wallets)) {
2175
+ const hasSmartAccountWallet = cryptoData.wallets.some((wallet) => isRecord(wallet) &&
2176
+ wallet.chain === "sol" &&
2177
+ wallet.address === agentInfo.smartAccountPDA);
2178
+ if (!hasSmartAccountWallet) {
2179
+ cryptoData.wallets = [smartAccountWallet, ...cryptoData.wallets];
2180
+ }
2181
+ }
2182
+ else if (isRecord(cryptoData.wallets)) {
2183
+ cryptoData.wallets = [
2184
+ smartAccountWallet,
2185
+ ...Object.entries(cryptoData.wallets).map(([chain, address]) => ({
2186
+ chain,
2187
+ address: String(address),
2188
+ })),
1751
2189
  ];
1752
2190
  }
2191
+ else {
2192
+ cryptoData.wallets = [smartAccountWallet];
2193
+ }
1753
2194
  }
2195
+ if (processedRequest.plugins["crypto-plugin"]) {
2196
+ processedRequest.plugins["crypto-plugin"] = {
2197
+ ...stripRuntimeContextFields(processedRequest.plugins["crypto-plugin"]),
2198
+ ...getRuntimeContextFromAgentInfo(agentInfo),
2199
+ };
2200
+ }
2201
+ processedRequest.DAIN_EXTRA_DATA = buildServiceExtraData(agentInfo, {
2202
+ request: processedRequest,
2203
+ plugins: processedRequest.plugins,
2204
+ });
1754
2205
  // Process plugins if configured
1755
2206
  if (!config.plugins || config.plugins.length === 0) {
1756
2207
  return processedRequest;
@@ -1760,6 +2211,10 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1760
2211
  processedRequest = await plugin.processInputService(processedRequest);
1761
2212
  }
1762
2213
  }
2214
+ processedRequest.DAIN_EXTRA_DATA = buildServiceExtraData(agentInfo, {
2215
+ request: processedRequest,
2216
+ plugins: processedRequest.plugins,
2217
+ });
1763
2218
  return processedRequest;
1764
2219
  }
1765
2220
  // Process response with plugins
@@ -1769,6 +2224,11 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1769
2224
  }
1770
2225
  let processedResponse = { ...response };
1771
2226
  processedResponse.plugins = processedResponse.plugins || {};
2227
+ const extraData = isRecord(context?.extraData)
2228
+ ? context.extraData
2229
+ : isRecord(context)
2230
+ ? context
2231
+ : {};
1772
2232
  for (const plugin of config.plugins) {
1773
2233
  if (plugin.processOutputService) {
1774
2234
  // Provide context to the plugin
@@ -1776,8 +2236,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1776
2236
  ...processedResponse,
1777
2237
  context: {
1778
2238
  request,
1779
- extraData: context
1780
- }
2239
+ extraData,
2240
+ },
1781
2241
  });
1782
2242
  if (pluginOutput) {
1783
2243
  processedResponse.plugins[plugin.id] = pluginOutput;
@@ -1787,6 +2247,31 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1787
2247
  return processedResponse;
1788
2248
  }
1789
2249
  // Automatically create routes for each tool
2250
+ function buildToolContext(agentInfo, request, pluginsData, hooks = {}) {
2251
+ const oauth2Client = app.oauth2 ? app.oauth2.getClient() : undefined;
2252
+ const extraData = buildServiceExtraData(agentInfo, {
2253
+ request,
2254
+ plugins: pluginsData,
2255
+ oauth2Client,
2256
+ app,
2257
+ });
2258
+ const runtimeContext = getRuntimeContextFromAgentInfo(agentInfo);
2259
+ return {
2260
+ app,
2261
+ oauth2Client,
2262
+ extraData,
2263
+ dainAccountId: runtimeContext.dainAccountId ?? extraData.dainAccountId,
2264
+ dainGroupId: runtimeContext.dainGroupId ?? extraData.dainGroupId,
2265
+ smartAccountPDA: runtimeContext.smartAccountPDA ?? extraData.smartAccountPDA,
2266
+ account: runtimeContext.account ?? extraData.account,
2267
+ group: runtimeContext.group ?? extraData.group,
2268
+ auth: runtimeContext.auth ?? extraData.auth,
2269
+ grants: runtimeContext.grants ?? extraData.grants,
2270
+ dataPermissions: runtimeContext.dataPermissions ?? extraData.dataPermissions,
2271
+ registryPolicy: runtimeContext.registryPolicy ?? extraData.registryPolicy,
2272
+ ...hooks,
2273
+ };
2274
+ }
1790
2275
  tools.forEach((tool) => {
1791
2276
  /**
1792
2277
  * Shared handler for tool execution with streaming support
@@ -1800,27 +2285,25 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1800
2285
  return signedStreamSSE(c, privateKey, config, async (stream) => {
1801
2286
  try {
1802
2287
  // Execute the tool first
1803
- debugLog(`[SSE] Executing tool ${tool.id} in streaming mode${withContext ? ' with context' : ''}`);
1804
- const result = await tool.handler({ ...body, DAIN_EXTRA_DATA: undefined }, agentInfo, {
1805
- app,
1806
- oauth2Client: app.oauth2 ? app.oauth2.getClient() : undefined,
1807
- extraData: {
1808
- ...body.DAIN_EXTRA_DATA,
1809
- plugins: pluginsData
1810
- },
2288
+ debugLog(`[SSE] Executing tool ${tool.id} in streaming mode${withContext ? " with context" : ""}`);
2289
+ const { DAIN_EXTRA_DATA: _dainExtraData, ...toolInput } = body;
2290
+ const result = await tool.handler(toolInput, agentInfo, buildToolContext(agentInfo, body, pluginsData, {
1811
2291
  updateUI: async (update) => {
1812
2292
  try {
1813
2293
  // Check if this is a progress update
1814
- if (update.type === 'progress') {
2294
+ if (update.type === "progress") {
1815
2295
  await stream.writeSSE({
1816
- event: 'progress',
1817
- data: JSON.stringify({ text: update.text, data: update.data }),
2296
+ event: "progress",
2297
+ data: JSON.stringify({
2298
+ text: update.text,
2299
+ data: update.data,
2300
+ }),
1818
2301
  });
1819
2302
  }
1820
2303
  else {
1821
2304
  // Legacy UI page updates for Canvas rendering
1822
2305
  await stream.writeSSE({
1823
- event: 'uipage-update',
2306
+ event: "uipage-update",
1824
2307
  data: JSON.stringify(update),
1825
2308
  });
1826
2309
  }
@@ -1832,7 +2315,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1832
2315
  addProcess: async (processId) => {
1833
2316
  try {
1834
2317
  await stream.writeSSE({
1835
- event: 'process-created',
2318
+ event: "process-created",
1836
2319
  data: JSON.stringify({ processId }),
1837
2320
  id: Date.now().toString(),
1838
2321
  });
@@ -1840,8 +2323,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1840
2323
  catch (error) {
1841
2324
  console.error(`Error sending process update in ${tool.id}:`, error);
1842
2325
  }
1843
- }
1844
- });
2326
+ },
2327
+ }));
1845
2328
  // If we need to include context data
1846
2329
  let response = result;
1847
2330
  if (withContext) {
@@ -1856,8 +2339,13 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1856
2339
  name: context.name,
1857
2340
  description: context.description,
1858
2341
  data: await context.getContextData(agentInfo, {
1859
- plugins: pluginsData,
1860
- oauth2Client: app.oauth2 ? app.oauth2.getClient() : undefined
2342
+ ...buildServiceExtraData(agentInfo, {
2343
+ request: body,
2344
+ plugins: pluginsData,
2345
+ oauth2Client: app.oauth2
2346
+ ? app.oauth2.getClient()
2347
+ : undefined,
2348
+ }),
1861
2349
  }),
1862
2350
  };
1863
2351
  }
@@ -1875,11 +2363,11 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1875
2363
  // Use Promise.allSettled to continue even if some contexts fail
1876
2364
  const settledContexts = await Promise.allSettled(contextPromises);
1877
2365
  contextsNow = settledContexts
1878
- .filter(result => result.status === 'fulfilled')
1879
- .map(result => result.value);
1880
- // Log any rejected promises
2366
+ .filter((result) => result.status === "fulfilled")
2367
+ .map((result) => result.value);
2368
+ // Log any rejected promises
1881
2369
  settledContexts
1882
- .filter(result => result.status === 'rejected')
2370
+ .filter((result) => result.status === "rejected")
1883
2371
  .forEach((result, index) => {
1884
2372
  console.error(`Context at index ${index} failed:`, result.reason);
1885
2373
  });
@@ -1900,12 +2388,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1900
2388
  const processedResult = await processPluginsForResponse(response, body, {
1901
2389
  extraData: {
1902
2390
  ...body.DAIN_EXTRA_DATA,
1903
- plugins: pluginsData
1904
- }
2391
+ plugins: pluginsData,
2392
+ },
1905
2393
  });
1906
2394
  // Send the final result
1907
2395
  await stream.writeSSE({
1908
- event: 'result',
2396
+ event: "result",
1909
2397
  data: JSON.stringify(processedResult),
1910
2398
  id: Date.now().toString(),
1911
2399
  });
@@ -1917,13 +2405,13 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1917
2405
  try {
1918
2406
  if (withContext) {
1919
2407
  await stream.writeSSE({
1920
- event: 'result',
2408
+ event: "result",
1921
2409
  data: JSON.stringify({
1922
2410
  toolResult: {
1923
2411
  error: safeMsg,
1924
2412
  text: `Error: ${safeMsg}`,
1925
2413
  data: null,
1926
- ui: null
2414
+ ui: null,
1927
2415
  },
1928
2416
  context: [],
1929
2417
  }),
@@ -1932,12 +2420,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1932
2420
  }
1933
2421
  else {
1934
2422
  await stream.writeSSE({
1935
- event: 'result',
2423
+ event: "result",
1936
2424
  data: JSON.stringify({
1937
2425
  error: safeMsg,
1938
2426
  text: `Error: ${safeMsg}`,
1939
2427
  data: null,
1940
- ui: null
2428
+ ui: null,
1941
2429
  }),
1942
2430
  id: Date.now().toString(),
1943
2431
  });
@@ -1957,17 +2445,15 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1957
2445
  const uiUpdates = [];
1958
2446
  const progressUpdates = [];
1959
2447
  const processes = [];
1960
- const result = await tool.handler({ ...body, DAIN_EXTRA_DATA: undefined }, agentInfo, {
1961
- app,
1962
- oauth2Client: app.oauth2 ? app.oauth2.getClient() : undefined,
1963
- extraData: {
1964
- ...body.DAIN_EXTRA_DATA,
1965
- plugins: pluginsData
1966
- },
2448
+ const { DAIN_EXTRA_DATA: _dainExtraData, ...toolInput } = body;
2449
+ const result = await tool.handler(toolInput, agentInfo, buildToolContext(agentInfo, body, pluginsData, {
1967
2450
  updateUI: (update) => {
1968
2451
  // Collect UI updates instead of streaming them (synchronous for performance)
1969
- if (update.type === 'progress') {
1970
- progressUpdates.push({ text: update.text, data: update.data });
2452
+ if (update.type === "progress") {
2453
+ progressUpdates.push({
2454
+ text: update.text,
2455
+ data: update.data,
2456
+ });
1971
2457
  }
1972
2458
  else {
1973
2459
  uiUpdates.push(update);
@@ -1978,8 +2464,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1978
2464
  // Collect process IDs (synchronous for performance)
1979
2465
  processes.push(processId);
1980
2466
  return Promise.resolve();
1981
- }
1982
- });
2467
+ },
2468
+ }));
1983
2469
  // If we need to include context data
1984
2470
  let response = result;
1985
2471
  if (withContext) {
@@ -1990,8 +2476,13 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1990
2476
  name: context.name,
1991
2477
  description: context.description,
1992
2478
  data: await context.getContextData(agentInfo, {
1993
- plugins: pluginsData,
1994
- oauth2Client: app.oauth2 ? app.oauth2.getClient() : undefined
2479
+ ...buildServiceExtraData(agentInfo, {
2480
+ request: body,
2481
+ plugins: pluginsData,
2482
+ oauth2Client: app.oauth2
2483
+ ? app.oauth2.getClient()
2484
+ : undefined,
2485
+ }),
1995
2486
  }),
1996
2487
  })));
1997
2488
  // Create the complete response with context
@@ -2013,15 +2504,15 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2013
2504
  const processedResult = await processPluginsForResponse(response, body, {
2014
2505
  extraData: {
2015
2506
  ...body.DAIN_EXTRA_DATA,
2016
- plugins: pluginsData
2017
- }
2507
+ plugins: pluginsData,
2508
+ },
2018
2509
  });
2019
2510
  // Add collected updates to response for non-streaming clients
2020
2511
  const finalResponse = {
2021
2512
  ...processedResult,
2022
2513
  _updates: uiUpdates.length > 0 ? uiUpdates : undefined,
2023
2514
  _progress: progressUpdates.length > 0 ? progressUpdates : undefined,
2024
- _processes: processes.length > 0 ? processes : undefined
2515
+ _processes: processes.length > 0 ? processes : undefined,
2025
2516
  };
2026
2517
  return c.json(finalResponse);
2027
2518
  }
@@ -2036,7 +2527,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2036
2527
  error: safeMsg,
2037
2528
  text: `Error: ${safeMsg}`,
2038
2529
  data: null,
2039
- ui: null
2530
+ ui: null,
2040
2531
  },
2041
2532
  context: [],
2042
2533
  };
@@ -2046,7 +2537,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2046
2537
  error: safeMsg,
2047
2538
  text: `Error: ${safeMsg}`,
2048
2539
  data: null,
2049
- ui: null
2540
+ ui: null,
2050
2541
  };
2051
2542
  }
2052
2543
  // We return status 200 with error details in the body
@@ -2060,7 +2551,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2060
2551
  debugLog(`[Tool ${tool.id}] ========== TOOL EXECUTION START ==========`);
2061
2552
  debugLog(`[Tool ${tool.id}] Path: ${c.req.path}`);
2062
2553
  debugLog(`[Tool ${tool.id}] Method: ${c.req.method}`);
2063
- debugLog(`[Tool ${tool.id}] Auth Method: ${c.get('authMethod')}`);
2554
+ debugLog(`[Tool ${tool.id}] Auth Method: ${c.get("authMethod")}`);
2064
2555
  debugLog(`[Tool ${tool.id}] Headers:`, {
2065
2556
  authorization: c.req.header("Authorization") ? "Bearer ***" : undefined,
2066
2557
  apiKey: c.req.header("X-DAIN-API-KEY") ? "***" : undefined,
@@ -2097,7 +2588,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2097
2588
  debugLog(`[Tool ${tool.id} +Context] ========== TOOL EXECUTION START (WITH CONTEXT) ==========`);
2098
2589
  debugLog(`[Tool ${tool.id} +Context] Path: ${c.req.path}`);
2099
2590
  debugLog(`[Tool ${tool.id} +Context] Method: ${c.req.method}`);
2100
- debugLog(`[Tool ${tool.id} +Context] Auth Method: ${c.get('authMethod')}`);
2591
+ debugLog(`[Tool ${tool.id} +Context] Auth Method: ${c.get("authMethod")}`);
2101
2592
  debugLog(`[Tool ${tool.id} +Context] Headers:`, {
2102
2593
  authorization: c.req.header("Authorization") ? "Bearer ***" : undefined,
2103
2594
  apiKey: c.req.header("X-DAIN-API-KEY") ? "***" : undefined,
@@ -2130,7 +2621,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2130
2621
  console.error(`[Tool ${tool.id} +Context] Stack:`, error?.stack);
2131
2622
  throw new http_exception_1.HTTPException(500, {
2132
2623
  message: error?.message || "Internal server error",
2133
- cause: error
2624
+ cause: error,
2134
2625
  });
2135
2626
  }
2136
2627
  });