@dainprotocol/service-sdk 2.0.95 → 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.
@@ -142,20 +142,26 @@ function getRuntimeContextFromJwtPayload(payload, options = {}) {
142
142
  const account = getObjectClaim(payload, "account_context");
143
143
  const group = getObjectClaim(payload, "group_context");
144
144
  const auth = getObjectClaim(payload, "auth_context");
145
- const dainAccountId = getStringClaim(payload, "dain_account_id", "account_id") ??
146
- account?.id;
147
- const dainGroupId = getStringClaim(payload, "dain_group_id", "group_id") ??
148
- group?.id;
145
+ const dainAccountId = getStringClaim(payload, "dain_account_id", "account_id") ?? account?.id;
146
+ const dainGroupId = getStringClaim(payload, "dain_group_id", "group_id") ?? group?.id;
149
147
  const smartAccountPDA = getStringClaim(payload, "smart_account_pda") ??
150
148
  options.fallbackSmartAccountPDA;
151
149
  if (account?.id && dainAccountId && account.id !== dainAccountId) {
152
- throw new http_exception_1.HTTPException(401, { message: "JWT DAIN context mismatch: dain_account_id does not match account_context.id" });
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
153
  }
154
154
  if (group?.id && dainGroupId && group.id !== dainGroupId) {
155
- throw new http_exception_1.HTTPException(401, { message: "JWT DAIN context mismatch: dain_group_id does not match group_context.id" });
155
+ throw new http_exception_1.HTTPException(401, {
156
+ message: "JWT DAIN context mismatch: dain_group_id does not match group_context.id",
157
+ });
156
158
  }
157
- if (account?.smartAccount?.pda && smartAccountPDA && account.smartAccount.pda !== smartAccountPDA) {
158
- throw new http_exception_1.HTTPException(401, { message: "JWT DAIN context mismatch: smart_account_pda does not match account_context.smartAccount.pda" });
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
+ });
159
165
  }
160
166
  const grants = getArrayClaim(payload, "action_grants");
161
167
  const dataPermissions = getArrayClaim(payload, "data_permissions");
@@ -184,15 +190,23 @@ function getRuntimeContextFromJwtPayload(payload, options = {}) {
184
190
  }
185
191
  function getRuntimeContextFromAgentInfo(agentInfo) {
186
192
  return {
187
- ...(agentInfo.dainAccountId ? { dainAccountId: agentInfo.dainAccountId } : {}),
193
+ ...(agentInfo.dainAccountId
194
+ ? { dainAccountId: agentInfo.dainAccountId }
195
+ : {}),
188
196
  ...(agentInfo.dainGroupId ? { dainGroupId: agentInfo.dainGroupId } : {}),
189
- ...(agentInfo.smartAccountPDA ? { smartAccountPDA: agentInfo.smartAccountPDA } : {}),
197
+ ...(agentInfo.smartAccountPDA
198
+ ? { smartAccountPDA: agentInfo.smartAccountPDA }
199
+ : {}),
190
200
  ...(agentInfo.account ? { account: agentInfo.account } : {}),
191
201
  ...(agentInfo.group ? { group: agentInfo.group } : {}),
192
202
  ...(agentInfo.auth ? { auth: agentInfo.auth } : {}),
193
203
  ...(agentInfo.grants ? { grants: agentInfo.grants } : {}),
194
- ...(agentInfo.dataPermissions ? { dataPermissions: agentInfo.dataPermissions } : {}),
195
- ...(agentInfo.registryPolicy ? { registryPolicy: agentInfo.registryPolicy } : {}),
204
+ ...(agentInfo.dataPermissions
205
+ ? { dataPermissions: agentInfo.dataPermissions }
206
+ : {}),
207
+ ...(agentInfo.registryPolicy
208
+ ? { registryPolicy: agentInfo.registryPolicy }
209
+ : {}),
196
210
  };
197
211
  }
198
212
  function getRequestExtraData(request) {
@@ -221,12 +235,14 @@ function buildServiceExtraData(agentInfo, options = {}) {
221
235
  */
222
236
  function requireScope(requiredScope) {
223
237
  return async (c, next) => {
224
- const scopes = c.get('scope') || [];
225
- const requiredScopes = Array.isArray(requiredScope) ? requiredScope : [requiredScope];
226
- 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));
227
243
  if (!hasRequiredScope) {
228
244
  throw new http_exception_1.HTTPException(403, {
229
- message: `Insufficient scope. Required: ${requiredScopes.join(' OR ')}, Have: ${scopes.join(', ')}`
245
+ message: `Insufficient scope. Required: ${requiredScopes.join(" OR ")}, Have: ${scopes.join(", ")}`,
230
246
  });
231
247
  }
232
248
  await next();
@@ -256,16 +272,26 @@ function signedStreamSSE(c, privateKey, config, handler) {
256
272
  const messageHash = (0, sseSignature_1.hashEventMessage)(event.data, timestamp);
257
273
  const signature = (0, utils_js_1.bytesToHex)(sseSignature_1.ed25519.sign(messageHash, privateKey));
258
274
  // Fast path for non-critical events (progress/UI updates)
259
- const isCriticalEvent = event.event === 'result' ||
260
- event.event === 'process-created' ||
261
- event.event === 'datasource-update';
275
+ const isCriticalEvent = event.event === "result" ||
276
+ event.event === "process-created" ||
277
+ event.event === "datasource-update";
262
278
  const dataWithSignature = isCriticalEvent
263
279
  ? JSON.stringify({
264
280
  data: JSON.parse(event.data),
265
- _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
+ },
266
288
  })
267
289
  : `{"data":${event.data},"_signature":{"signature":"${signature}","timestamp":"${timestamp}","agentId":"${config.identity.agentId}","orgId":"${config.identity.orgId}","address":"${config.identity.publicKey}"}}`;
268
- 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
+ });
269
295
  },
270
296
  isAborted,
271
297
  onAbort: (listener) => stream.onAbort(listener),
@@ -285,7 +311,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
285
311
  serviceId: "service_" + config.identity.orgId + "_" + config.identity.agentId,
286
312
  privateKey,
287
313
  store: config.processStore,
288
- onHumanActionResponse: config.onHumanActionResponse
314
+ onHumanActionResponse: config.onHumanActionResponse,
289
315
  });
290
316
  app.processes = processHandler;
291
317
  // CORS middleware - apply to all routes
@@ -334,7 +360,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
334
360
  const isStreaming = acceptHeader.includes("text/event-stream");
335
361
  await next();
336
362
  // Skip signature for streaming responses
337
- 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")) {
338
365
  return;
339
366
  }
340
367
  const body = await c.res.clone().text();
@@ -347,12 +374,14 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
347
374
  });
348
375
  // Get all webhook paths for auth bypass
349
376
  const webhookPaths = config.webhookTriggers?.getWebhookPaths() || [];
350
- const hitlPath = config.hitl?.enabled ? (config.hitl.webhookPath || '/actions') : null;
377
+ const hitlPath = config.hitl?.enabled
378
+ ? config.hitl.webhookPath || "/actions"
379
+ : null;
351
380
  // Dual Authentication: JWT (users) or API Key (services)
352
381
  app.use("*", async (c, next) => {
353
382
  debugLog(`[Auth Middleware] Path: ${c.req.path}, Method: ${c.req.method}`);
354
383
  // Check if path is a webhook path (auth bypass)
355
- const isWebhookPath = webhookPaths.some(path => c.req.path === path);
384
+ const isWebhookPath = webhookPaths.some((path) => c.req.path === path);
356
385
  const isHITLPath = hitlPath && c.req.path === hitlPath;
357
386
  if (c.req.path.startsWith("/oauth2/callback/") ||
358
387
  c.req.path.startsWith("/addons") ||
@@ -374,16 +403,20 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
374
403
  const host = getFirstForwardedValue(c.req.header("x-forwarded-host")) ||
375
404
  getFirstForwardedValue(c.req.header("host"));
376
405
  if (!host) {
377
- 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
+ });
378
409
  }
379
410
  // Validate host format to prevent obvious attacks
380
- if (host.includes(' ') || host.includes('\n') || host.includes('\r')) {
411
+ if (host.includes(" ") || host.includes("\n") || host.includes("\r")) {
381
412
  throw new http_exception_1.HTTPException(400, { message: "Invalid Host header format" });
382
413
  }
383
414
  const xForwardedProto = getFirstForwardedValue(c.req.header("x-forwarded-proto"));
384
415
  const protocol = xForwardedProto === "http" || xForwardedProto === "https"
385
416
  ? xForwardedProto
386
- : (host.includes("localhost") || host.startsWith("127.") ? "http" : "https");
417
+ : host.includes("localhost") || host.startsWith("127.")
418
+ ? "http"
419
+ : "https";
387
420
  const forwardedPrefix = normalizeForwardedPrefix(getFirstForwardedValue(c.req.header("x-forwarded-prefix")));
388
421
  const jwtAudiences = [`${protocol}://${host}`];
389
422
  if (forwardedPrefix) {
@@ -396,7 +429,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
396
429
  audience: jwtAudiences,
397
430
  });
398
431
  if (!result.valid) {
399
- 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
+ });
400
435
  }
401
436
  // Defense in depth: double-check audience claim
402
437
  const tokenAudiences = Array.isArray(result.payload?.aud)
@@ -406,21 +441,21 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
406
441
  const audienceMatched = tokenAudiences.some((aud) => aud && expectedAudienceSet.has(aud));
407
442
  if (!audienceMatched) {
408
443
  throw new http_exception_1.HTTPException(403, {
409
- 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(", ")}`,
410
445
  });
411
446
  }
412
- c.set('authMethod', 'jwt');
413
- c.set('smartAccountId', result.smartAccountId);
414
- c.set('address', result.smartAccountId); // Use smartAccountId as address for JWT auth
415
- c.set('scope', result.scope);
416
- c.set('jwtPayload', result.payload);
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);
417
452
  const jwtRuntimeContext = getRuntimeContextFromJwtPayload(result.payload, {
418
453
  scopes: result.scope,
419
454
  smartAccountId: result.smartAccountId,
420
455
  fallbackSmartAccountPDA: c.req.header("X-DAIN-SMART-ACCOUNT-PDA"),
421
456
  });
422
- c.set('dainRuntimeContext', jwtRuntimeContext);
423
- c.set('smartAccountPDA', jwtRuntimeContext.smartAccountPDA);
457
+ c.set("dainRuntimeContext", jwtRuntimeContext);
458
+ c.set("smartAccountPDA", jwtRuntimeContext.smartAccountPDA);
424
459
  debugLog(`[Auth Middleware] JWT auth SUCCESS - smartAccountId: ${result.smartAccountId}`);
425
460
  }
426
461
  else if (apiKey) {
@@ -438,15 +473,21 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
438
473
  throw new http_exception_1.HTTPException(401, { message: "Invalid API key" });
439
474
  }
440
475
  }
441
- c.set('authMethod', 'apiKey');
442
- c.set('agentId', parsed.agentId);
443
- c.set('orgId', parsed.orgId);
444
- c.set('address', parsed.agentId); // Use agentId as address for API key auth
445
- c.set('smartAccountPDA', c.req.header("X-DAIN-SMART-ACCOUNT-PDA"));
446
- c.set('dainRuntimeContext', {
447
- ...(c.req.header("X-DAIN-ACCOUNT-ID") ? { dainAccountId: c.req.header("X-DAIN-ACCOUNT-ID") } : {}),
448
- ...(c.req.header("X-DAIN-GROUP-ID") ? { dainGroupId: c.req.header("X-DAIN-GROUP-ID") } : {}),
449
- ...(c.req.header("X-DAIN-SMART-ACCOUNT-PDA") ? { 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
+ : {}),
450
491
  });
451
492
  debugLog(`[Auth Middleware] API Key auth SUCCESS - agentId: ${parsed.agentId}, orgId: ${parsed.orgId}`);
452
493
  }
@@ -458,14 +499,17 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
458
499
  });
459
500
  async function getAgentInfo(c) {
460
501
  debugLog("[getAgentInfo] START");
461
- debugLog("[getAgentInfo] Auth method:", c.get('authMethod'));
462
- const runtimeContext = (c.get('dainRuntimeContext') || {});
463
- const smartAccountPDA = runtimeContext.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");
464
508
  const webhookUrl = c.req.header("X-DAIN-WEBHOOK-URL");
465
509
  debugLog("[getAgentInfo] smartAccountPDA:", smartAccountPDA);
466
510
  debugLog("[getAgentInfo] webhookUrl:", webhookUrl);
467
- if (c.get('authMethod') === 'jwt') {
468
- const smartAccountId = c.get('smartAccountId');
511
+ if (c.get("authMethod") === "jwt") {
512
+ const smartAccountId = c.get("smartAccountId");
469
513
  debugLog("[getAgentInfo] JWT auth - smartAccountId:", smartAccountId);
470
514
  const agentInfo = {
471
515
  agentId: smartAccountId,
@@ -481,14 +525,16 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
481
525
  registryPolicy: runtimeContext.registryPolicy,
482
526
  id: runtimeContext.dainAccountId ??
483
527
  runtimeContext.dainGroupId ??
484
- (smartAccountPDA ? `dain_id_${smartAccountPDA}` : `smart_account_${smartAccountId}`),
528
+ (smartAccountPDA
529
+ ? `dain_id_${smartAccountPDA}`
530
+ : `smart_account_${smartAccountId}`),
485
531
  webhookUrl,
486
532
  };
487
533
  debugLog("[getAgentInfo] JWT - Returning agent info:", agentInfo);
488
534
  return agentInfo;
489
535
  }
490
- const agentId = c.get('agentId');
491
- const address = c.get('address');
536
+ const agentId = c.get("agentId");
537
+ const address = c.get("address");
492
538
  debugLog("[getAgentInfo] API Key auth - agentId:", agentId, "address:", address);
493
539
  const agentInfo = {
494
540
  agentId,
@@ -534,7 +580,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
534
580
  app.get("/metadata", (c) => {
535
581
  // Compute service-level capability: does ANY tool support user actions (HITL)?
536
582
  const supportsUserActions = tools.some((tool) => tool.supportsUserActions === true);
537
- 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");
538
585
  const sdkMajor = Number.parseInt(String(package_json_1.default.version).split(".")[0] || "0", 10);
539
586
  const contractVersion = Number.isFinite(sdkMajor) && sdkMajor > 0 ? `${sdkMajor}.0.0` : "0.0.0";
540
587
  const capabilities = {
@@ -553,6 +600,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
553
600
  actionGrants: true,
554
601
  smartAccountTransactions: true,
555
602
  payments: true,
603
+ registryPolicy: true,
604
+ grantPolicies: true,
556
605
  };
557
606
  const compatibility = (() => {
558
607
  if (!requestedContract)
@@ -619,7 +668,11 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
619
668
  const autoContexts = app.oauth2?.getDirectProviderContexts?.() || [];
620
669
  const serviceSlug = (0, core_1.toSlug)(metadata.title);
621
670
  const skillsContext = config.skills?.getSkillsContext?.(serviceSlug);
622
- const allContexts = [...contexts, ...autoContexts, ...(skillsContext ? [skillsContext] : [])];
671
+ const allContexts = [
672
+ ...contexts,
673
+ ...autoContexts,
674
+ ...(skillsContext ? [skillsContext] : []),
675
+ ];
623
676
  const contextInfo = allContexts.map((context) => ({
624
677
  id: context.id,
625
678
  name: context.name,
@@ -638,7 +691,11 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
638
691
  const autoContexts = app.oauth2?.getDirectProviderContexts?.() || [];
639
692
  const serviceSlug = (0, core_1.toSlug)(metadata.title);
640
693
  const skillsContext = config.skills?.getSkillsContext?.(serviceSlug);
641
- const allContexts = [...contexts, ...autoContexts, ...(skillsContext ? [skillsContext] : [])];
694
+ const allContexts = [
695
+ ...contexts,
696
+ ...autoContexts,
697
+ ...(skillsContext ? [skillsContext] : []),
698
+ ];
642
699
  const context = allContexts.find((ctx) => ctx.id === c.req.param("contextId"));
643
700
  if (context) {
644
701
  const agentInfo = await getAgentInfo(c);
@@ -655,7 +712,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
655
712
  id: context.id,
656
713
  name: context.name,
657
714
  description: context.description,
658
- data: contextData
715
+ data: contextData,
659
716
  };
660
717
  const processedResponse = await processPluginsForResponse(response, body, { extraData });
661
718
  return c.json(processedResponse);
@@ -677,7 +734,11 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
677
734
  const autoContexts = app.oauth2?.getDirectProviderContexts?.() || [];
678
735
  const serviceSlug = (0, core_1.toSlug)(metadata.title);
679
736
  const skillsContext = config.skills?.getSkillsContext?.(serviceSlug);
680
- const allContexts = [...contexts, ...autoContexts, ...(skillsContext ? [skillsContext] : [])];
737
+ const allContexts = [
738
+ ...contexts,
739
+ ...autoContexts,
740
+ ...(skillsContext ? [skillsContext] : []),
741
+ ];
681
742
  const contextsFull = await Promise.all(allContexts.map(async (ctx) => ({
682
743
  id: ctx.id,
683
744
  name: ctx.name,
@@ -697,8 +758,10 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
697
758
  });
698
759
  const widgetIds = config.getUserWidgets
699
760
  ? await config.getUserWidgets(agentInfo, extraData)
700
- : widgets.map(widget => widget.id);
701
- const processedResponse = await processPluginsForResponse(widgetIds, body, { extraData });
761
+ : widgets.map((widget) => widget.id);
762
+ const processedResponse = await processPluginsForResponse(widgetIds, body, {
763
+ extraData,
764
+ });
702
765
  return c.json(processedResponse);
703
766
  });
704
767
  app.post("/widgets/all", async (c) => {
@@ -710,7 +773,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
710
773
  request: processedPluginData,
711
774
  plugins: processedPluginData.plugins,
712
775
  }))
713
- : widgets.map(widget => widget.id);
776
+ : widgets.map((widget) => widget.id);
714
777
  const oauth2Client = app.oauth2?.getClient();
715
778
  const extraData = buildServiceExtraData(agentInfo, {
716
779
  request: processedPluginData,
@@ -719,7 +782,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
719
782
  app,
720
783
  });
721
784
  const widgetsFull = await Promise.all(widgetIds.map(async (widgetId) => {
722
- const widget = widgets.find(w => w.id === widgetId);
785
+ const widget = widgets.find((w) => w.id === widgetId);
723
786
  if (!widget)
724
787
  return null;
725
788
  const widgetData = await widget.getWidget(agentInfo, extraData);
@@ -730,7 +793,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
730
793
  icon: widget.icon,
731
794
  size: widget.size || "sm",
732
795
  refreshIntervalMs: widget.refreshIntervalMs,
733
- ...widgetData
796
+ ...widgetData,
734
797
  };
735
798
  if (!("freshness" in response)) {
736
799
  response.freshness = {
@@ -744,13 +807,13 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
744
807
  }
745
808
  return response;
746
809
  }));
747
- const validWidgets = widgetsFull.filter(w => w !== null);
810
+ const validWidgets = widgetsFull.filter((w) => w !== null);
748
811
  const processedResponse = await processPluginsForResponse(validWidgets, body, { extraData });
749
812
  return c.json(processedResponse);
750
813
  });
751
814
  app.post("/widgets/:widgetId", async (c) => {
752
815
  const widgetId = c.req.param("widgetId");
753
- const widget = widgets.find(w => w.id === widgetId);
816
+ const widget = widgets.find((w) => w.id === widgetId);
754
817
  if (!widget) {
755
818
  throw new http_exception_1.HTTPException(404, { message: "Widget not found" });
756
819
  }
@@ -763,16 +826,19 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
763
826
  plugins: processedPluginData.plugins,
764
827
  });
765
828
  const userWidgetIds = await config.getUserWidgets(agentInfo, {
766
- ...accessExtraData
829
+ ...accessExtraData,
767
830
  });
768
831
  let homeUIWidgetId = null;
769
832
  if (config.homeUI) {
770
- homeUIWidgetId = typeof config.homeUI === 'string'
771
- ? config.homeUI
772
- : await config.homeUI(agentInfo, accessExtraData);
833
+ homeUIWidgetId =
834
+ typeof config.homeUI === "string"
835
+ ? config.homeUI
836
+ : await config.homeUI(agentInfo, accessExtraData);
773
837
  }
774
838
  if (!userWidgetIds.includes(widgetId) && widgetId !== homeUIWidgetId) {
775
- 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
+ });
776
842
  }
777
843
  }
778
844
  const oauth2Client = app.oauth2?.getClient();
@@ -790,7 +856,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
790
856
  icon: widget.icon,
791
857
  size: widget.size || "sm",
792
858
  refreshIntervalMs: widget.refreshIntervalMs,
793
- ...widgetData
859
+ ...widgetData,
794
860
  };
795
861
  if (!("freshness" in response)) {
796
862
  response.freshness = {
@@ -802,7 +868,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
802
868
  scope: "account",
803
869
  };
804
870
  }
805
- const processedResponse = await processPluginsForResponse(response, body, { extraData });
871
+ const processedResponse = await processPluginsForResponse(response, body, {
872
+ extraData,
873
+ });
806
874
  return c.json(processedResponse);
807
875
  });
808
876
  app.post("/homeUI", async (c) => {
@@ -816,13 +884,13 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
816
884
  request: processedPluginData,
817
885
  plugins: processedPluginData.plugins,
818
886
  });
819
- const homeUIWidgetId = typeof config.homeUI === 'string'
887
+ const homeUIWidgetId = typeof config.homeUI === "string"
820
888
  ? config.homeUI
821
889
  : await config.homeUI(agentInfo, extraData);
822
890
  if (!homeUIWidgetId) {
823
891
  return c.json({ widgetId: null });
824
892
  }
825
- const widget = widgets.find(w => w.id === homeUIWidgetId);
893
+ const widget = widgets.find((w) => w.id === homeUIWidgetId);
826
894
  if (!widget) {
827
895
  return c.json({ widgetId: null });
828
896
  }
@@ -927,7 +995,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
927
995
  .join(", ");
928
996
  return c.json({
929
997
  error: `Missing or invalid parameters: ${missingParams}`,
930
- code: "INVALID_PARAMS"
998
+ code: "INVALID_PARAMS",
931
999
  }, 400);
932
1000
  }
933
1001
  throw error;
@@ -960,17 +1028,23 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
960
1028
  typeof rawBody === "object" &&
961
1029
  !Array.isArray(rawBody) &&
962
1030
  "params" in rawBody;
963
- const requestedIntervalMsRaw = hasWrappedParams ? rawBody.intervalMs : undefined;
964
- const requestedStreamIdRaw = hasWrappedParams ? rawBody.streamId : undefined;
1031
+ const requestedIntervalMsRaw = hasWrappedParams
1032
+ ? rawBody.intervalMs
1033
+ : undefined;
1034
+ const requestedStreamIdRaw = hasWrappedParams
1035
+ ? rawBody.streamId
1036
+ : undefined;
965
1037
  const streamId = typeof requestedStreamIdRaw === "string" &&
966
1038
  /^[A-Za-z0-9._:-]{1,128}$/.test(requestedStreamIdRaw)
967
1039
  ? requestedStreamIdRaw
968
1040
  : null;
969
- const requestParamsRaw = hasWrappedParams ? rawBody.params : rawBody;
970
- let params = await processPluginsForRequest(requestParamsRaw && typeof requestParamsRaw === "object" ? requestParamsRaw : {}, agentInfo);
971
- const pluginsData = (params.plugins && typeof params.plugins === "object"
972
- ? params.plugins
973
- : {});
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 : {});
974
1048
  delete params.plugins;
975
1049
  let parsedParams;
976
1050
  try {
@@ -983,7 +1057,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
983
1057
  .join(", ");
984
1058
  return c.json({
985
1059
  error: `Missing or invalid parameters: ${missingParams}`,
986
- code: "INVALID_PARAMS"
1060
+ code: "INVALID_PARAMS",
987
1061
  }, 400);
988
1062
  }
989
1063
  throw error;
@@ -1016,11 +1090,14 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1016
1090
  scope: datasource.scope,
1017
1091
  dataClass: datasource.dataClass,
1018
1092
  };
1019
- const requestedIntervalMs = typeof requestedIntervalMsRaw === "number" && Number.isFinite(requestedIntervalMsRaw) && requestedIntervalMsRaw > 0
1093
+ const requestedIntervalMs = typeof requestedIntervalMsRaw === "number" &&
1094
+ Number.isFinite(requestedIntervalMsRaw) &&
1095
+ requestedIntervalMsRaw > 0
1020
1096
  ? requestedIntervalMsRaw
1021
1097
  : null;
1022
1098
  const baseIntervalMs = requestedIntervalMs ??
1023
- (typeof datasource.refreshIntervalMs === "number" && datasource.refreshIntervalMs > 0
1099
+ (typeof datasource.refreshIntervalMs === "number" &&
1100
+ datasource.refreshIntervalMs > 0
1024
1101
  ? datasource.refreshIntervalMs
1025
1102
  : 15_000);
1026
1103
  const intervalMs = Math.max(1_000, Math.floor(baseIntervalMs));
@@ -1033,7 +1110,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1033
1110
  if (streamKey) {
1034
1111
  datasourceStreamAbortControllers.set(streamKey, streamAbortController);
1035
1112
  }
1036
- const isCancelled = () => stream.isAborted() || signal?.aborted === true || streamAbortController.signal.aborted;
1113
+ const isCancelled = () => stream.isAborted() ||
1114
+ signal?.aborted === true ||
1115
+ streamAbortController.signal.aborted;
1037
1116
  const emitUpdate = async () => {
1038
1117
  if (isCancelled())
1039
1118
  return false;
@@ -1081,7 +1160,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1081
1160
  if (!isCancelled()) {
1082
1161
  await stream.writeSSE({
1083
1162
  event: "error",
1084
- data: JSON.stringify({ message: error?.message || "Datasource stream error" }),
1163
+ data: JSON.stringify({
1164
+ message: error?.message || "Datasource stream error",
1165
+ }),
1085
1166
  });
1086
1167
  }
1087
1168
  return;
@@ -1118,7 +1199,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1118
1199
  if (!isCancelled()) {
1119
1200
  await stream.writeSSE({
1120
1201
  event: "error",
1121
- data: JSON.stringify({ message: error?.message || "Datasource stream error" }),
1202
+ data: JSON.stringify({
1203
+ message: error?.message || "Datasource stream error",
1204
+ }),
1122
1205
  });
1123
1206
  }
1124
1207
  }
@@ -1139,7 +1222,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1139
1222
  context: agent.context,
1140
1223
  prompt: agent.prompt,
1141
1224
  resolveCondition: agent.resolveCondition,
1142
- serviceConnections: agent.serviceConnections || [process.env.BASE_URL || 'http://localhost:3000'],
1225
+ serviceConnections: agent.serviceConnections || [
1226
+ process.env.BASE_URL || "http://localhost:3000",
1227
+ ],
1143
1228
  inputSchema: (0, schemaStructure_1.zodToJsonSchema)(agent.input),
1144
1229
  outputSchema: (0, schemaStructure_1.zodToJsonSchema)(agent.output),
1145
1230
  };
@@ -1183,14 +1268,16 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1183
1268
  return c.json(processedResponse);
1184
1269
  });
1185
1270
  function fixEmptySchemas(schema) {
1186
- if (!schema || typeof schema !== 'object')
1271
+ if (!schema || typeof schema !== "object")
1187
1272
  return;
1188
- if (schema.properties && typeof schema.properties === 'object') {
1273
+ if (schema.properties && typeof schema.properties === "object") {
1189
1274
  const props = schema.properties;
1190
1275
  for (const key of Object.keys(props)) {
1191
1276
  const prop = props[key];
1192
- if (prop && typeof prop === 'object' && Object.keys(prop).length === 0) {
1193
- props[key] = { type: 'object' };
1277
+ if (prop &&
1278
+ typeof prop === "object" &&
1279
+ Object.keys(prop).length === 0) {
1280
+ props[key] = { type: "object" };
1194
1281
  }
1195
1282
  fixEmptySchemas(prop);
1196
1283
  }
@@ -1203,10 +1290,10 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1203
1290
  let inputSchema = (0, schemaStructure_1.zodToJsonSchema)(tool.input);
1204
1291
  let outputSchema = (0, schemaStructure_1.zodToJsonSchema)(tool.output);
1205
1292
  if (!inputSchema.type) {
1206
- inputSchema = { ...inputSchema, type: 'object' };
1293
+ inputSchema = { ...inputSchema, type: "object" };
1207
1294
  }
1208
1295
  if (!outputSchema.type) {
1209
- outputSchema = { ...outputSchema, type: 'object' };
1296
+ outputSchema = { ...outputSchema, type: "object" };
1210
1297
  }
1211
1298
  fixEmptySchemas(inputSchema);
1212
1299
  fixEmptySchemas(outputSchema);
@@ -1273,11 +1360,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1273
1360
  // Configure trigger forwarding (uses HITL config for automation API)
1274
1361
  if (config.webhookTriggers) {
1275
1362
  // Resolve automation API URL (priority: hitl config > env)
1276
- const automationApiUrl = config.hitl?.automationApiUrl ||
1277
- process.env.AUTOMATION_API_URL;
1363
+ const automationApiUrl = config.hitl?.automationApiUrl || process.env.AUTOMATION_API_URL;
1278
1364
  // Resolve API key
1279
- const automationApiKey = config.hitl?.automationApiKey ||
1280
- process.env.AUTOMATION_API_KEY;
1365
+ const automationApiKey = config.hitl?.automationApiKey || process.env.AUTOMATION_API_KEY;
1281
1366
  // Resolve service URL (priority: oauth2.baseUrl > env)
1282
1367
  const serviceUrl = config.oauth2?.baseUrl ||
1283
1368
  process.env.SERVICE_BASE_URL ||
@@ -1300,10 +1385,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1300
1385
  try {
1301
1386
  const registerUrl = `${automationApiUrl}/webhooks/register-triggers`;
1302
1387
  const response = await fetch(registerUrl, {
1303
- method: 'POST',
1388
+ method: "POST",
1304
1389
  headers: {
1305
- 'Content-Type': 'application/json',
1306
- ...(automationApiKey ? { 'Authorization': `Bearer ${automationApiKey}` } : {}),
1390
+ "Content-Type": "application/json",
1391
+ ...(automationApiKey
1392
+ ? { Authorization: `Bearer ${automationApiKey}` }
1393
+ : {}),
1307
1394
  },
1308
1395
  body: JSON.stringify({
1309
1396
  serviceUrl,
@@ -1328,10 +1415,10 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1328
1415
  }
1329
1416
  else {
1330
1417
  if (!automationApiUrl) {
1331
- 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)");
1332
1419
  }
1333
1420
  if (!serviceUrl) {
1334
- 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)");
1335
1422
  }
1336
1423
  }
1337
1424
  }
@@ -1356,7 +1443,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1356
1443
  success: true,
1357
1444
  triggerId: result.triggerId,
1358
1445
  triggerName: result.triggerName,
1359
- data: result.data
1446
+ data: result.data,
1360
1447
  });
1361
1448
  }
1362
1449
  else {
@@ -1364,7 +1451,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1364
1451
  // No trigger matched - return 200 OK but with success: false
1365
1452
  return c.json({
1366
1453
  success: false,
1367
- message: 'No trigger matched'
1454
+ message: "No trigger matched",
1368
1455
  }, 200);
1369
1456
  }
1370
1457
  }
@@ -1372,22 +1459,22 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1372
1459
  console.error(`[Webhook] Error processing webhook at ${path}:`, error);
1373
1460
  // Return error response
1374
1461
  throw new http_exception_1.HTTPException(500, {
1375
- message: `Webhook processing failed: ${error.message}`
1462
+ message: `Webhook processing failed: ${error.message}`,
1376
1463
  });
1377
1464
  }
1378
1465
  });
1379
1466
  }
1380
- console.log(`[Webhook] Registered ${webhookPaths.length} webhook endpoint(s): ${webhookPaths.join(', ')}`);
1467
+ console.log(`[Webhook] Registered ${webhookPaths.length} webhook endpoint(s): ${webhookPaths.join(", ")}`);
1381
1468
  }
1382
1469
  // Auto-register HITL action webhook
1383
1470
  if (config.hitl?.enabled) {
1384
- const hitlPath = config.hitl.webhookPath || '/actions';
1471
+ const hitlPath = config.hitl.webhookPath || "/actions";
1385
1472
  const automationApiUrl = config.hitl.automationApiUrl ||
1386
1473
  process.env.AUTOMATION_API_URL ||
1387
- 'http://localhost:3000';
1474
+ "http://localhost:3000";
1388
1475
  const automationApiKey = config.hitl.automationApiKey || process.env.AUTOMATION_API_KEY;
1389
1476
  if (!automationApiUrl) {
1390
- 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");
1391
1478
  }
1392
1479
  const hitlHandler = new hitl_1.HITLHandler({
1393
1480
  automationApiUrl,
@@ -1398,19 +1485,19 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1398
1485
  try {
1399
1486
  const body = await c.req.json();
1400
1487
  const { action, context } = body;
1401
- if (!action || typeof action !== 'string') {
1488
+ if (!action || typeof action !== "string") {
1402
1489
  throw new http_exception_1.HTTPException(400, {
1403
1490
  message: 'Missing or invalid "action" field in request body',
1404
1491
  });
1405
1492
  }
1406
- if (!context || typeof context !== 'object') {
1493
+ if (!context || typeof context !== "object") {
1407
1494
  throw new http_exception_1.HTTPException(400, {
1408
1495
  message: 'Missing or invalid "context" field in request body',
1409
1496
  });
1410
1497
  }
1411
1498
  if (!hitlHandler.isValidAction(action)) {
1412
1499
  throw new http_exception_1.HTTPException(400, {
1413
- message: 'Invalid action format. Expected: scope:id:action[:payload]',
1500
+ message: "Invalid action format. Expected: scope:id:action[:payload]",
1414
1501
  });
1415
1502
  }
1416
1503
  const result = await hitlHandler.handleAction(action, context);
@@ -1420,7 +1507,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1420
1507
  if (error instanceof http_exception_1.HTTPException) {
1421
1508
  throw error;
1422
1509
  }
1423
- console.error('[HITL] Error processing action:', error);
1510
+ console.error("[HITL] Error processing action:", error);
1424
1511
  throw new http_exception_1.HTTPException(500, {
1425
1512
  message: `Action processing failed: ${error.message}`,
1426
1513
  });
@@ -1532,7 +1619,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1532
1619
  const oauthTool = (0, core_1.createOAuth2Tool)(providerName, serviceSlug, {
1533
1620
  logoUrl: providerConfig.logoUrl,
1534
1621
  reason: providerConfig.reason,
1535
- requiredTools: providerConfig.requiredTools
1622
+ requiredTools: providerConfig.requiredTools,
1536
1623
  });
1537
1624
  autoOAuth2Tools.push(oauthTool);
1538
1625
  });
@@ -1562,11 +1649,17 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1562
1649
  }
1563
1650
  try {
1564
1651
  await app.oauth2.handleCallback(code, state);
1565
- 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>");
1566
1655
  }
1567
1656
  catch (error) {
1568
1657
  console.error("OAuth callback error:", error);
1569
- 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>");
1570
1663
  }
1571
1664
  });
1572
1665
  // Make oauth2Handler available to tools
@@ -1585,7 +1678,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1585
1678
  }
1586
1679
  catch (error) {
1587
1680
  if (error.message === "Unauthorized access to process") {
1588
- 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
+ });
1589
1684
  }
1590
1685
  throw error;
1591
1686
  }
@@ -1601,7 +1696,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1601
1696
  const providersWithStatus = await Promise.all(providers.map(async ({ name, config }) => ({
1602
1697
  name,
1603
1698
  config,
1604
- connected: await app.oauth2.hasValidTokens(name, agentInfo.id)
1699
+ connected: await app.oauth2.hasValidTokens(name, agentInfo.id),
1605
1700
  })));
1606
1701
  return c.json(providersWithStatus);
1607
1702
  });
@@ -1618,7 +1713,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1618
1713
  app.get("/oauth2/connect/:provider", async (c) => {
1619
1714
  debugLog("[OAuth2 Connect] Route hit - START");
1620
1715
  debugLog("[OAuth2 Connect] Provider param:", c.req.param("provider"));
1621
- debugLog("[OAuth2 Connect] Auth method:", c.get('authMethod'));
1716
+ debugLog("[OAuth2 Connect] Auth method:", c.get("authMethod"));
1622
1717
  debugLog("[OAuth2 Connect] Headers:", {
1623
1718
  authorization: c.req.header("Authorization"),
1624
1719
  apiKey: c.req.header("X-DAIN-API-KEY"),
@@ -1649,7 +1744,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1649
1744
  catch (error) {
1650
1745
  debugLog("[OAuth2 Connect] ERROR generating auth URL:", error);
1651
1746
  throw new http_exception_1.HTTPException(400, {
1652
- message: `Invalid provider: ${provider}`
1747
+ message: `Invalid provider: ${provider}`,
1653
1748
  });
1654
1749
  }
1655
1750
  });
@@ -1667,8 +1762,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1667
1762
  if (isComplete) {
1668
1763
  const config = await setupManager.getProviderConfig(agentInfo.id, provider);
1669
1764
  return c.json({
1670
- status: 'complete',
1671
- config: config ? { configuredAt: config.configuredAt } : undefined
1765
+ status: "complete",
1766
+ config: config ? { configuredAt: config.configuredAt } : undefined,
1672
1767
  });
1673
1768
  }
1674
1769
  // Check if there's a pending setup
@@ -1676,15 +1771,15 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1676
1771
  if (pendingSetup) {
1677
1772
  const expiresIn = Math.max(0, Math.floor((pendingSetup.expiresAt - Date.now()) / 1000));
1678
1773
  return c.json({
1679
- status: 'authorization_pending',
1774
+ status: "authorization_pending",
1680
1775
  expires_in: expiresIn,
1681
- interval: 5 // Poll every 5 seconds
1776
+ interval: 5, // Poll every 5 seconds
1682
1777
  });
1683
1778
  }
1684
1779
  // No setup in progress
1685
1780
  return c.json({
1686
- status: 'not_found',
1687
- error: 'No setup in progress for this provider'
1781
+ status: "not_found",
1782
+ error: "No setup in progress for this provider",
1688
1783
  });
1689
1784
  });
1690
1785
  // Get all human actions for a process
@@ -1697,13 +1792,15 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1697
1792
  }
1698
1793
  if (process.agentId !== agentInfo.id) {
1699
1794
  debugLog("Unauthorized access to process", process.agentId, agentInfo.id);
1700
- 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
+ });
1701
1798
  }
1702
1799
  return c.json(process.humanActions);
1703
1800
  });
1704
1801
  // Get specific human action
1705
1802
  app.get("/processes/:processId/human-actions/:stepId", async (c) => {
1706
- debugLog('GET human action request:', c.req.path);
1803
+ debugLog("GET human action request:", c.req.path);
1707
1804
  const processId = c.req.param("processId");
1708
1805
  const stepId = c.req.param("stepId");
1709
1806
  const agentInfo = await getAgentInfo(c);
@@ -1713,7 +1810,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1713
1810
  }
1714
1811
  if (process.agentId !== agentInfo.id) {
1715
1812
  debugLog("Unauthorized access to process", process.agentId, agentInfo.id);
1716
- 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
+ });
1717
1816
  }
1718
1817
  const step = await app.processes.checkHumanAction(processId, stepId);
1719
1818
  if (!step) {
@@ -1732,7 +1831,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1732
1831
  }
1733
1832
  if (process.agentId !== agentInfo.id) {
1734
1833
  debugLog("Unauthorized access to process", process.agentId, agentInfo.id);
1735
- 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
+ });
1736
1837
  }
1737
1838
  const body = await c.req.json();
1738
1839
  const { actionId, responseText, data } = body;
@@ -1763,7 +1864,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1763
1864
  }
1764
1865
  catch (error) {
1765
1866
  console.error(`Error generating confirmation UI for tool ${tool.id}:`, error);
1766
- 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
+ });
1767
1870
  }
1768
1871
  });
1769
1872
  app.get("/exampleQueries", (c) => {
@@ -1799,7 +1902,10 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1799
1902
  // Toolboxes list endpoint
1800
1903
  app.get("/toolboxes", (c) => c.json(toolboxes));
1801
1904
  function normalizeRecommendationText(value) {
1802
- return value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
1905
+ return value
1906
+ .toLowerCase()
1907
+ .replace(/[^a-z0-9]+/g, " ")
1908
+ .trim();
1803
1909
  }
1804
1910
  function tokenizeRecommendationQuery(query) {
1805
1911
  const normalized = normalizeRecommendationText(query);
@@ -1818,7 +1924,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1818
1924
  throw new Error(`Duplicate recommendation card ID "${scopedCardId}". Card IDs must be unique per tool.`);
1819
1925
  }
1820
1926
  const isDynamic = !!card.inputSchema;
1821
- const inputSchema = isDynamic ? (0, schemaStructure_1.zodToJsonSchema)(card.inputSchema) : undefined;
1927
+ const inputSchema = isDynamic
1928
+ ? (0, schemaStructure_1.zodToJsonSchema)(card.inputSchema)
1929
+ : undefined;
1822
1930
  const searchText = normalizeRecommendationText([tool.id, tool.name, card.id, ...card.tags].join(" "));
1823
1931
  index.set(scopedCardId, {
1824
1932
  cardId: scopedCardId,
@@ -1880,7 +1988,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
1880
1988
  details: parsed.error.format(),
1881
1989
  }, 400);
1882
1990
  }
1883
- const { query, limit, toolIds, includeStaticUI, } = parsed.data;
1991
+ const { query, limit, toolIds, includeStaticUI } = parsed.data;
1884
1992
  const toolIdSet = toolIds?.length ? new Set(toolIds) : null;
1885
1993
  const filteredCards = Array.from(recommendationCardsById.values()).filter((card) => !toolIdSet || toolIdSet.has(card.toolId));
1886
1994
  const tokens = tokenizeRecommendationQuery(query ?? "");
@@ -2013,7 +2121,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2013
2121
  renderErrors.push({
2014
2122
  cardId: card.cardId,
2015
2123
  code: "render_failed",
2016
- 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",
2017
2127
  });
2018
2128
  if (!continueOnError)
2019
2129
  break;
@@ -2048,21 +2158,22 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2048
2158
  // Auto-inject smartAccountPDA into CryptoPlugin wallet context for automations
2049
2159
  // This allows automation wallets to work seamlessly without manual configuration
2050
2160
  if (agentInfo.smartAccountPDA) {
2051
- processedRequest.plugins['crypto-plugin'] = processedRequest.plugins['crypto-plugin'] || {};
2052
- const cryptoData = isRecord(processedRequest.plugins['crypto-plugin'])
2053
- ? stripRuntimeContextFields(processedRequest.plugins['crypto-plugin'])
2161
+ processedRequest.plugins["crypto-plugin"] =
2162
+ processedRequest.plugins["crypto-plugin"] || {};
2163
+ const cryptoData = isRecord(processedRequest.plugins["crypto-plugin"])
2164
+ ? stripRuntimeContextFields(processedRequest.plugins["crypto-plugin"])
2054
2165
  : {};
2055
- processedRequest.plugins['crypto-plugin'] = cryptoData;
2166
+ processedRequest.plugins["crypto-plugin"] = cryptoData;
2056
2167
  const smartAccountWallet = {
2057
- chain: 'sol',
2168
+ chain: "sol",
2058
2169
  address: agentInfo.smartAccountPDA,
2059
2170
  accountId: agentInfo.dainAccountId ?? agentInfo.dainGroupId,
2060
- kind: 'smart_account_vault',
2061
- capabilities: ['solana-smart-account'],
2171
+ kind: "smart_account_vault",
2172
+ capabilities: ["solana-smart-account"],
2062
2173
  };
2063
2174
  if (Array.isArray(cryptoData.wallets)) {
2064
2175
  const hasSmartAccountWallet = cryptoData.wallets.some((wallet) => isRecord(wallet) &&
2065
- wallet.chain === 'sol' &&
2176
+ wallet.chain === "sol" &&
2066
2177
  wallet.address === agentInfo.smartAccountPDA);
2067
2178
  if (!hasSmartAccountWallet) {
2068
2179
  cryptoData.wallets = [smartAccountWallet, ...cryptoData.wallets];
@@ -2081,9 +2192,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2081
2192
  cryptoData.wallets = [smartAccountWallet];
2082
2193
  }
2083
2194
  }
2084
- if (processedRequest.plugins['crypto-plugin']) {
2085
- processedRequest.plugins['crypto-plugin'] = {
2086
- ...stripRuntimeContextFields(processedRequest.plugins['crypto-plugin']),
2195
+ if (processedRequest.plugins["crypto-plugin"]) {
2196
+ processedRequest.plugins["crypto-plugin"] = {
2197
+ ...stripRuntimeContextFields(processedRequest.plugins["crypto-plugin"]),
2087
2198
  ...getRuntimeContextFromAgentInfo(agentInfo),
2088
2199
  };
2089
2200
  }
@@ -2115,7 +2226,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2115
2226
  processedResponse.plugins = processedResponse.plugins || {};
2116
2227
  const extraData = isRecord(context?.extraData)
2117
2228
  ? context.extraData
2118
- : (isRecord(context) ? context : {});
2229
+ : isRecord(context)
2230
+ ? context
2231
+ : {};
2119
2232
  for (const plugin of config.plugins) {
2120
2233
  if (plugin.processOutputService) {
2121
2234
  // Provide context to the plugin
@@ -2123,8 +2236,8 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2123
2236
  ...processedResponse,
2124
2237
  context: {
2125
2238
  request,
2126
- extraData
2127
- }
2239
+ extraData,
2240
+ },
2128
2241
  });
2129
2242
  if (pluginOutput) {
2130
2243
  processedResponse.plugins[plugin.id] = pluginOutput;
@@ -2172,22 +2285,25 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2172
2285
  return signedStreamSSE(c, privateKey, config, async (stream) => {
2173
2286
  try {
2174
2287
  // Execute the tool first
2175
- debugLog(`[SSE] Executing tool ${tool.id} in streaming mode${withContext ? ' with context' : ''}`);
2288
+ debugLog(`[SSE] Executing tool ${tool.id} in streaming mode${withContext ? " with context" : ""}`);
2176
2289
  const { DAIN_EXTRA_DATA: _dainExtraData, ...toolInput } = body;
2177
2290
  const result = await tool.handler(toolInput, agentInfo, buildToolContext(agentInfo, body, pluginsData, {
2178
2291
  updateUI: async (update) => {
2179
2292
  try {
2180
2293
  // Check if this is a progress update
2181
- if (update.type === 'progress') {
2294
+ if (update.type === "progress") {
2182
2295
  await stream.writeSSE({
2183
- event: 'progress',
2184
- 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
+ }),
2185
2301
  });
2186
2302
  }
2187
2303
  else {
2188
2304
  // Legacy UI page updates for Canvas rendering
2189
2305
  await stream.writeSSE({
2190
- event: 'uipage-update',
2306
+ event: "uipage-update",
2191
2307
  data: JSON.stringify(update),
2192
2308
  });
2193
2309
  }
@@ -2199,7 +2315,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2199
2315
  addProcess: async (processId) => {
2200
2316
  try {
2201
2317
  await stream.writeSSE({
2202
- event: 'process-created',
2318
+ event: "process-created",
2203
2319
  data: JSON.stringify({ processId }),
2204
2320
  id: Date.now().toString(),
2205
2321
  });
@@ -2207,7 +2323,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2207
2323
  catch (error) {
2208
2324
  console.error(`Error sending process update in ${tool.id}:`, error);
2209
2325
  }
2210
- }
2326
+ },
2211
2327
  }));
2212
2328
  // If we need to include context data
2213
2329
  let response = result;
@@ -2226,7 +2342,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2226
2342
  ...buildServiceExtraData(agentInfo, {
2227
2343
  request: body,
2228
2344
  plugins: pluginsData,
2229
- oauth2Client: app.oauth2 ? app.oauth2.getClient() : undefined,
2345
+ oauth2Client: app.oauth2
2346
+ ? app.oauth2.getClient()
2347
+ : undefined,
2230
2348
  }),
2231
2349
  }),
2232
2350
  };
@@ -2245,11 +2363,11 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2245
2363
  // Use Promise.allSettled to continue even if some contexts fail
2246
2364
  const settledContexts = await Promise.allSettled(contextPromises);
2247
2365
  contextsNow = settledContexts
2248
- .filter(result => result.status === 'fulfilled')
2249
- .map(result => result.value);
2250
- // Log any rejected promises
2366
+ .filter((result) => result.status === "fulfilled")
2367
+ .map((result) => result.value);
2368
+ // Log any rejected promises
2251
2369
  settledContexts
2252
- .filter(result => result.status === 'rejected')
2370
+ .filter((result) => result.status === "rejected")
2253
2371
  .forEach((result, index) => {
2254
2372
  console.error(`Context at index ${index} failed:`, result.reason);
2255
2373
  });
@@ -2270,12 +2388,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2270
2388
  const processedResult = await processPluginsForResponse(response, body, {
2271
2389
  extraData: {
2272
2390
  ...body.DAIN_EXTRA_DATA,
2273
- plugins: pluginsData
2274
- }
2391
+ plugins: pluginsData,
2392
+ },
2275
2393
  });
2276
2394
  // Send the final result
2277
2395
  await stream.writeSSE({
2278
- event: 'result',
2396
+ event: "result",
2279
2397
  data: JSON.stringify(processedResult),
2280
2398
  id: Date.now().toString(),
2281
2399
  });
@@ -2287,13 +2405,13 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2287
2405
  try {
2288
2406
  if (withContext) {
2289
2407
  await stream.writeSSE({
2290
- event: 'result',
2408
+ event: "result",
2291
2409
  data: JSON.stringify({
2292
2410
  toolResult: {
2293
2411
  error: safeMsg,
2294
2412
  text: `Error: ${safeMsg}`,
2295
2413
  data: null,
2296
- ui: null
2414
+ ui: null,
2297
2415
  },
2298
2416
  context: [],
2299
2417
  }),
@@ -2302,12 +2420,12 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2302
2420
  }
2303
2421
  else {
2304
2422
  await stream.writeSSE({
2305
- event: 'result',
2423
+ event: "result",
2306
2424
  data: JSON.stringify({
2307
2425
  error: safeMsg,
2308
2426
  text: `Error: ${safeMsg}`,
2309
2427
  data: null,
2310
- ui: null
2428
+ ui: null,
2311
2429
  }),
2312
2430
  id: Date.now().toString(),
2313
2431
  });
@@ -2331,8 +2449,11 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2331
2449
  const result = await tool.handler(toolInput, agentInfo, buildToolContext(agentInfo, body, pluginsData, {
2332
2450
  updateUI: (update) => {
2333
2451
  // Collect UI updates instead of streaming them (synchronous for performance)
2334
- if (update.type === 'progress') {
2335
- 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
+ });
2336
2457
  }
2337
2458
  else {
2338
2459
  uiUpdates.push(update);
@@ -2343,7 +2464,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2343
2464
  // Collect process IDs (synchronous for performance)
2344
2465
  processes.push(processId);
2345
2466
  return Promise.resolve();
2346
- }
2467
+ },
2347
2468
  }));
2348
2469
  // If we need to include context data
2349
2470
  let response = result;
@@ -2358,7 +2479,9 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2358
2479
  ...buildServiceExtraData(agentInfo, {
2359
2480
  request: body,
2360
2481
  plugins: pluginsData,
2361
- oauth2Client: app.oauth2 ? app.oauth2.getClient() : undefined,
2482
+ oauth2Client: app.oauth2
2483
+ ? app.oauth2.getClient()
2484
+ : undefined,
2362
2485
  }),
2363
2486
  }),
2364
2487
  })));
@@ -2381,15 +2504,15 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2381
2504
  const processedResult = await processPluginsForResponse(response, body, {
2382
2505
  extraData: {
2383
2506
  ...body.DAIN_EXTRA_DATA,
2384
- plugins: pluginsData
2385
- }
2507
+ plugins: pluginsData,
2508
+ },
2386
2509
  });
2387
2510
  // Add collected updates to response for non-streaming clients
2388
2511
  const finalResponse = {
2389
2512
  ...processedResult,
2390
2513
  _updates: uiUpdates.length > 0 ? uiUpdates : undefined,
2391
2514
  _progress: progressUpdates.length > 0 ? progressUpdates : undefined,
2392
- _processes: processes.length > 0 ? processes : undefined
2515
+ _processes: processes.length > 0 ? processes : undefined,
2393
2516
  };
2394
2517
  return c.json(finalResponse);
2395
2518
  }
@@ -2404,7 +2527,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2404
2527
  error: safeMsg,
2405
2528
  text: `Error: ${safeMsg}`,
2406
2529
  data: null,
2407
- ui: null
2530
+ ui: null,
2408
2531
  },
2409
2532
  context: [],
2410
2533
  };
@@ -2414,7 +2537,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2414
2537
  error: safeMsg,
2415
2538
  text: `Error: ${safeMsg}`,
2416
2539
  data: null,
2417
- ui: null
2540
+ ui: null,
2418
2541
  };
2419
2542
  }
2420
2543
  // We return status 200 with error details in the body
@@ -2428,7 +2551,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2428
2551
  debugLog(`[Tool ${tool.id}] ========== TOOL EXECUTION START ==========`);
2429
2552
  debugLog(`[Tool ${tool.id}] Path: ${c.req.path}`);
2430
2553
  debugLog(`[Tool ${tool.id}] Method: ${c.req.method}`);
2431
- debugLog(`[Tool ${tool.id}] Auth Method: ${c.get('authMethod')}`);
2554
+ debugLog(`[Tool ${tool.id}] Auth Method: ${c.get("authMethod")}`);
2432
2555
  debugLog(`[Tool ${tool.id}] Headers:`, {
2433
2556
  authorization: c.req.header("Authorization") ? "Bearer ***" : undefined,
2434
2557
  apiKey: c.req.header("X-DAIN-API-KEY") ? "***" : undefined,
@@ -2465,7 +2588,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2465
2588
  debugLog(`[Tool ${tool.id} +Context] ========== TOOL EXECUTION START (WITH CONTEXT) ==========`);
2466
2589
  debugLog(`[Tool ${tool.id} +Context] Path: ${c.req.path}`);
2467
2590
  debugLog(`[Tool ${tool.id} +Context] Method: ${c.req.method}`);
2468
- debugLog(`[Tool ${tool.id} +Context] Auth Method: ${c.get('authMethod')}`);
2591
+ debugLog(`[Tool ${tool.id} +Context] Auth Method: ${c.get("authMethod")}`);
2469
2592
  debugLog(`[Tool ${tool.id} +Context] Headers:`, {
2470
2593
  authorization: c.req.header("Authorization") ? "Bearer ***" : undefined,
2471
2594
  apiKey: c.req.header("X-DAIN-API-KEY") ? "***" : undefined,
@@ -2498,7 +2621,7 @@ function setupHttpServer(config, tools, services, toolboxes, metadata, privateKe
2498
2621
  console.error(`[Tool ${tool.id} +Context] Stack:`, error?.stack);
2499
2622
  throw new http_exception_1.HTTPException(500, {
2500
2623
  message: error?.message || "Internal server error",
2501
- cause: error
2624
+ cause: error,
2502
2625
  });
2503
2626
  }
2504
2627
  });