@undefineds.co/xpod 0.3.70 → 0.3.71-rc.13

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 (172) hide show
  1. package/config/cloud.json +3 -0
  2. package/config/local.json +3 -0
  3. package/config/resolver.json +7 -0
  4. package/config/xpod.base.json +20 -0
  5. package/dist/agents/ClaudeExecutor.js +1 -1
  6. package/dist/agents/ClaudeExecutor.js.map +1 -1
  7. package/dist/agents/types.d.ts +5 -5
  8. package/dist/agents/types.js.map +1 -1
  9. package/dist/api/ai-gateway/AiGatewayService.d.ts +5 -16
  10. package/dist/api/ai-gateway/AiGatewayService.js +13 -35
  11. package/dist/api/ai-gateway/AiGatewayService.js.map +1 -1
  12. package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.d.ts +3 -2
  13. package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.js +37 -12
  14. package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.js.map +1 -1
  15. package/dist/api/ai-gateway/auth/GatewayPrincipal.d.ts +2 -16
  16. package/dist/api/ai-gateway/auth/GatewayPrincipal.js +3 -33
  17. package/dist/api/ai-gateway/auth/GatewayPrincipal.js.map +1 -1
  18. package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.d.ts +23 -0
  19. package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.js +81 -0
  20. package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.js.map +1 -0
  21. package/dist/api/ai-gateway/auth/InvocationTokenCodec.d.ts +7 -4
  22. package/dist/api/ai-gateway/auth/InvocationTokenCodec.js.map +1 -1
  23. package/dist/api/ai-gateway/connect/index.d.ts +7 -26
  24. package/dist/api/ai-gateway/connect/index.js +40 -67
  25. package/dist/api/ai-gateway/connect/index.js.map +1 -1
  26. package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.d.ts +17 -0
  27. package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.js +65 -0
  28. package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.js.map +1 -0
  29. package/dist/api/ai-gateway/pod/HostedPodDataAccess.d.ts +24 -0
  30. package/dist/api/ai-gateway/pod/HostedPodDataAccess.js +149 -0
  31. package/dist/api/ai-gateway/pod/HostedPodDataAccess.js.map +1 -0
  32. package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.d.ts +13 -5
  33. package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js +16 -19
  34. package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js.map +1 -1
  35. package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.d.ts +1 -1
  36. package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.js +0 -2
  37. package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.js.map +1 -1
  38. package/dist/api/auth/AuthContext.d.ts +1 -12
  39. package/dist/api/auth/AuthContext.js +0 -11
  40. package/dist/api/auth/AuthContext.js.map +1 -1
  41. package/dist/api/auth/ClientCredentialsAuthenticator.js +4 -11
  42. package/dist/api/auth/ClientCredentialsAuthenticator.js.map +1 -1
  43. package/dist/api/chatkit/default-agent.d.ts +2 -2
  44. package/dist/api/chatkit/default-agent.js +4 -4
  45. package/dist/api/chatkit/default-agent.js.map +1 -1
  46. package/dist/api/chatkit/runtime/AcpAgentRuntime.js +1 -1
  47. package/dist/api/chatkit/runtime/AcpAgentRuntime.js.map +1 -1
  48. package/dist/api/container/common.js +28 -69
  49. package/dist/api/container/common.js.map +1 -1
  50. package/dist/api/container/index.js +5 -6
  51. package/dist/api/container/index.js.map +1 -1
  52. package/dist/api/container/routes.js +2 -5
  53. package/dist/api/container/routes.js.map +1 -1
  54. package/dist/api/container/types.d.ts +8 -10
  55. package/dist/api/container/types.js.map +1 -1
  56. package/dist/api/handlers/AiClientConfigurationHandler.js +3 -3
  57. package/dist/api/handlers/AiClientConfigurationHandler.js.map +1 -1
  58. package/dist/api/handlers/AiGatewayHandler.js +2 -2
  59. package/dist/api/handlers/AiGatewayHandler.js.map +1 -1
  60. package/dist/api/handlers/AiGatewayManagementHandler.d.ts +2 -10
  61. package/dist/api/handlers/AiGatewayManagementHandler.js +4 -154
  62. package/dist/api/handlers/AiGatewayManagementHandler.js.map +1 -1
  63. package/dist/api/handlers/NetworkSettingsHandler.js +0 -3
  64. package/dist/api/handlers/NetworkSettingsHandler.js.map +1 -1
  65. package/dist/api/handlers/PodSettingsHandler.d.ts +5 -2
  66. package/dist/api/handlers/PodSettingsHandler.js +3 -3
  67. package/dist/api/handlers/PodSettingsHandler.js.map +1 -1
  68. package/dist/api/runs/AgentRuntimeTypes.d.ts +3 -3
  69. package/dist/api/runs/AgentRuntimeTypes.js +10 -10
  70. package/dist/api/runs/AgentRuntimeTypes.js.map +1 -1
  71. package/dist/api/runs/InngestRunExecutionBackend.d.ts +15 -9
  72. package/dist/api/runs/InngestRunExecutionBackend.js +25 -10
  73. package/dist/api/runs/InngestRunExecutionBackend.js.map +1 -1
  74. package/dist/api/runs/PiAgentRuntimeDriver.js +2 -2
  75. package/dist/api/runs/PiAgentRuntimeDriver.js.map +1 -1
  76. package/dist/api/runs/RunStateCenter.js +1 -1
  77. package/dist/api/runs/RunStateCenter.js.map +1 -1
  78. package/dist/api/service/AiClientConfigurationService.d.ts +2 -2
  79. package/dist/api/service/AiClientConfigurationService.js +11 -11
  80. package/dist/api/service/AiClientConfigurationService.js.map +1 -1
  81. package/dist/api/tasks/InngestTaskScheduler.d.ts +16 -10
  82. package/dist/api/tasks/InngestTaskScheduler.js +24 -12
  83. package/dist/api/tasks/InngestTaskScheduler.js.map +1 -1
  84. package/dist/cli/commands/start.js +7 -7
  85. package/dist/cli/commands/start.js.map +1 -1
  86. package/dist/components/components.jsonld +1 -0
  87. package/dist/components/context.jsonld +36 -0
  88. package/dist/http/InternalPodDataHttpHandler.d.ts +32 -0
  89. package/dist/http/InternalPodDataHttpHandler.js +258 -0
  90. package/dist/http/InternalPodDataHttpHandler.js.map +1 -0
  91. package/dist/http/InternalPodDataHttpHandler.jsonld +201 -0
  92. package/dist/index.d.ts +2 -1
  93. package/dist/index.js +4 -2
  94. package/dist/index.js.map +1 -1
  95. package/dist/main.js +13 -13
  96. package/dist/main.js.map +1 -1
  97. package/dist/runtime/GatewayAdminProxyAuth.d.ts +15 -1
  98. package/dist/runtime/GatewayAdminProxyAuth.js +57 -2
  99. package/dist/runtime/GatewayAdminProxyAuth.js.map +1 -1
  100. package/dist/runtime/bootstrap.js +3 -0
  101. package/dist/runtime/bootstrap.js.map +1 -1
  102. package/dist/runtime/css-process.d.ts +1 -1
  103. package/dist/runtime/css-process.js +4 -1
  104. package/dist/runtime/css-process.js.map +1 -1
  105. package/dist/runtime/runner/node/CommunitySolidServerCssRunner.d.ts +2 -0
  106. package/dist/runtime/runner/node/CommunitySolidServerCssRunner.js +50 -0
  107. package/dist/runtime/runner/node/CommunitySolidServerCssRunner.js.map +1 -1
  108. package/node_modules/@undefineds.co/ai-connection/dist/AiClientConfigurationSection.d.ts +5 -5
  109. package/node_modules/@undefineds.co/ai-connection/dist/AiClientConfigurationSection.js +7 -7
  110. package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionMain.js +1 -1
  111. package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionPanel.d.ts +3 -1
  112. package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionPanel.js +74 -60
  113. package/node_modules/@undefineds.co/ai-connection/dist/ai-connection-client.d.ts +0 -21
  114. package/node_modules/@undefineds.co/ai-connection/dist/ai-connection-client.js +0 -41
  115. package/node_modules/@undefineds.co/ai-connection/dist/client-config/base-adapter.d.ts +1 -0
  116. package/node_modules/@undefineds.co/ai-connection/dist/client-config/base-adapter.js +7 -2
  117. package/node_modules/@undefineds.co/ai-connection/dist/client-config/codex.js +3 -3
  118. package/node_modules/@undefineds.co/ai-connection/dist/client-config/index.cjs +15 -9
  119. package/node_modules/@undefineds.co/ai-connection/dist/client-config/json-env-adapter.js +4 -4
  120. package/node_modules/@undefineds.co/ai-connection/dist/client-config/pi.js +3 -3
  121. package/node_modules/@undefineds.co/ai-connection/dist/client-config/types.d.ts +1 -1
  122. package/node_modules/@undefineds.co/ai-connection/dist/controller.d.ts +2 -1
  123. package/node_modules/@undefineds.co/ai-connection/dist/controller.js +1 -0
  124. package/node_modules/@undefineds.co/ai-connection/dist/service-access.js +0 -1
  125. package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +22 -1
  126. package/package.json +3 -3
  127. package/static/app/assets/main.js +7 -7
  128. package/static/dashboard/assets/NetworkPage-CXjiUMR1.js +2 -0
  129. package/static/dashboard/assets/{PaneListHeader-57nvMwH6.js → PaneListHeader-BSipfl0W.js} +1 -1
  130. package/static/dashboard/assets/PodPage-Bd3Xhmp-.js +2 -0
  131. package/static/dashboard/assets/ServicesPage-CI3jWZGe.js +1 -0
  132. package/static/dashboard/assets/{card-B9Zjf_2p.js → card-z5BV5hTo.js} +1 -1
  133. package/static/dashboard/assets/{dashboard-8C6o666W.js → dashboard-CSrqAv2L.js} +2 -2
  134. package/static/dashboard/assets/{database-DPh9wDY9.js → database-Ct5ZPe6L.js} +1 -1
  135. package/static/dashboard/assets/{external-link-VbMQvVMz.js → external-link-B7wD1hkm.js} +1 -1
  136. package/static/dashboard/assets/index-tOBaUnM1.js +44 -0
  137. package/static/dashboard/assets/{refresh-cw-BxVxNxNr.js → refresh-cw-CFDZPaE8.js} +1 -1
  138. package/static/dashboard/assets/{services-status-context-DKmJ7ISr.js → services-status-context-DN1Icg4A.js} +1 -1
  139. package/static/dashboard/dashboard.html +1 -1
  140. package/static/settings/assets/ModelsPage-03NPWzoX.js +1 -0
  141. package/static/settings/assets/{PaneListHeader-Bgaze006.js → PaneListHeader-DMD8OJef.js} +1 -1
  142. package/static/settings/assets/PodPage-DT4EMYhL.js +2 -0
  143. package/static/settings/assets/ServicesPage-CJ0ub6IH.js +1 -0
  144. package/static/settings/assets/SettingsPage-BkR7ZK18.js +41 -0
  145. package/static/settings/assets/{card-B_bXSIn-.js → card-Cjsia0_V.js} +1 -1
  146. package/static/settings/assets/{services-status-context-DiX-AbrP.js → services-status-context-CkuKmH5h.js} +1 -1
  147. package/static/settings/assets/{settings-B30oMfZq.js → settings-Cyyv6-SD.js} +2 -2
  148. package/static/settings/assets/{workspace-layout-Dv1Yn9Ci.js → workspace-layout-B47luv6r.js} +1 -1
  149. package/static/settings/settings.html +1 -1
  150. package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.d.ts +0 -25
  151. package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.js +0 -91
  152. package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.js.map +0 -1
  153. package/dist/api/ai-gateway/auth/GatewayApiKey.d.ts +0 -28
  154. package/dist/api/ai-gateway/auth/GatewayApiKey.js +0 -162
  155. package/dist/api/ai-gateway/auth/GatewayApiKey.js.map +0 -1
  156. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.d.ts +0 -56
  157. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js +0 -143
  158. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js.map +0 -1
  159. package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.d.ts +0 -26
  160. package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.js +0 -97
  161. package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.js.map +0 -1
  162. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.d.ts +0 -54
  163. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js +0 -152
  164. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js.map +0 -1
  165. package/static/dashboard/assets/NetworkPage-Brt79fuQ.js +0 -2
  166. package/static/dashboard/assets/PodPage-CM6do1vB.js +0 -2
  167. package/static/dashboard/assets/ServicesPage-BUNxGJRz.js +0 -1
  168. package/static/dashboard/assets/index-RfiFckzb.js +0 -51
  169. package/static/settings/assets/ModelsPage-D_IH7AH3.js +0 -1
  170. package/static/settings/assets/PodPage-Cy1VNObw.js +0 -2
  171. package/static/settings/assets/ServicesPage-BsFaxVWC.js +0 -1
  172. package/static/settings/assets/SettingsPage-UafNWE_p.js +0 -48
@@ -2,7 +2,8 @@ import { getLoggerFor } from 'global-logger-factory';
2
2
  import type { ApiServer } from '../ApiServer';
3
3
  import type { PodLookupRepository } from '../../identity/drizzle/PodLookupRepository';
4
4
  import type { UsageRepository } from '../../storage/quota/UsageRepository';
5
- import type { InternalPodAccessTokenProvider } from '../ai-gateway/auth/PodGatewayAccessKeyRepository';
5
+ import type { AuthContext } from '../auth/AuthContext';
6
+ import type { InternalPodAccessTokenProvider } from '../ai-gateway/pod/HostedPodDataAccess';
6
7
  export interface PodSettingsStatus {
7
8
  identity: {
8
9
  webId: string;
@@ -42,6 +43,7 @@ export interface PodAiConnectionStatusReader {
42
43
  read(input: {
43
44
  webId: string;
44
45
  podUrl?: string;
46
+ auth?: AuthContext;
45
47
  }): Promise<PodAiConnectionStatus>;
46
48
  }
47
49
  export interface PodSettingsHandlerOptions {
@@ -60,9 +62,10 @@ export declare class DrizzlePodAiConnectionStatusReader implements PodAiConnecti
60
62
  podUrl: string;
61
63
  fetch: typeof fetch;
62
64
  }) => Promise<AiConnectionStatusDb>);
63
- read({ webId, podUrl }: {
65
+ read({ webId, podUrl, auth }: {
64
66
  webId: string;
65
67
  podUrl?: string;
68
+ auth?: AuthContext;
66
69
  }): Promise<PodAiConnectionStatus>;
67
70
  }
68
71
  type AiConnectionStatusDb = {
@@ -22,7 +22,7 @@ function registerPodSettingsRoutes(server, options) {
22
22
  const podUrl = pod?.storageUrl ?? pod?.baseUrl;
23
23
  const [storage, aiConnection] = await Promise.all([
24
24
  readStorageStatus(options.usageRepo, pod),
25
- aiConnectionStatusReader.read({ webId, podUrl }).catch((error) => {
25
+ aiConnectionStatusReader.read({ webId, podUrl, auth: request.auth }).catch((error) => {
26
26
  const reason = safeAiConnectionFailureReason(error);
27
27
  logger.warn(`Failed to read Pod AI Connection status: ${reason}`);
28
28
  return { status: 'error', reason };
@@ -77,8 +77,8 @@ class DrizzlePodAiConnectionStatusReader {
77
77
  this.internalPodAccess = internalPodAccess;
78
78
  this.dbFactory = dbFactory;
79
79
  }
80
- async read({ webId, podUrl }) {
81
- const trustedFetch = await this.internalPodAccess?.getTrustedFetch(webId);
80
+ async read({ webId, podUrl, auth }) {
81
+ const trustedFetch = await this.internalPodAccess?.getTrustedFetch(webId, auth);
82
82
  if (!trustedFetch) {
83
83
  return { status: 'unsupported', reason: 'not_configured' };
84
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PodSettingsHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/PodSettingsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ServerResponse } from 'node:http';\nimport { drizzle, eq } from '@undefineds.co/drizzle-solid';\nimport {\n credentialResource,\n indexedFileResource,\n type CredentialRow,\n type IndexedFileRow,\n} from '@undefineds.co/models';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { ApiServer } from '../ApiServer';\nimport type { AuthenticatedRequest } from '../middleware/AuthMiddleware';\nimport type { PodLookupRepository, PodLookupResult } from '../../identity/drizzle/PodLookupRepository';\nimport type { UsageRepository, PodUsageRecord } from '../../storage/quota/UsageRepository';\nimport type { InternalPodAccessTokenProvider } from '../ai-gateway/auth/PodGatewayAccessKeyRepository';\n\nexport interface PodSettingsStatus {\n identity: {\n webId: string;\n podUrl?: string;\n };\n storage: PodStorageStatus;\n aiConnection: PodAiConnectionStatus;\n generatedAt: string;\n}\n\nexport type PodStorageStatus =\n | {\n status: 'available';\n usage: {\n storageBytes: number;\n ingressBytes: number;\n egressBytes: number;\n };\n limits: {\n storageLimitBytes: number | null;\n bandwidthLimitBps: number | null;\n };\n source: 'identity_usage';\n }\n | {\n status: 'unsupported' | 'error';\n reason: string;\n };\n\nexport type PodAiConnectionStatus =\n | {\n status: 'available';\n containerUrl?: string;\n configuredProviders: number;\n lastSyncAt?: string;\n source: 'drizzle-solid';\n }\n | {\n status: 'unsupported' | 'error';\n reason: string;\n };\n\nexport interface PodAiConnectionStatusReader {\n read(input: { webId: string; podUrl?: string }): Promise<PodAiConnectionStatus>;\n}\n\nexport interface PodSettingsHandlerOptions {\n podLookupRepository: Pick<PodLookupRepository, 'findByWebId'>;\n usageRepo: Pick<UsageRepository, 'getPodUsage'>;\n aiConnectionStatusReader?: PodAiConnectionStatusReader;\n now?: () => Date;\n logger?: Pick<ReturnType<typeof getLoggerFor>, 'warn' | 'error'>;\n}\n\nexport function registerPodSettingsRoutes(server: ApiServer, options: PodSettingsHandlerOptions): void {\n const logger = options.logger ?? getLoggerFor('PodSettingsHandler');\n const now = options.now ?? (() => new Date());\n const aiConnectionStatusReader = options.aiConnectionStatusReader ?? {\n read: async () => ({ status: 'unsupported', reason: 'not_configured' }) as const,\n };\n\n server.get('/api/pod/settings/status', async (request, response) => {\n if (!request.auth || request.auth.type !== 'solid') {\n sendJson(response, 401, { error: 'Authentication required' });\n return;\n }\n\n const webId = request.auth.webId;\n try {\n const pod = await options.podLookupRepository.findByWebId(webId);\n const podUrl = pod?.storageUrl ?? pod?.baseUrl;\n const [storage, aiConnection] = await Promise.all([\n readStorageStatus(options.usageRepo, pod),\n aiConnectionStatusReader.read({ webId, podUrl }).catch((error: unknown) => {\n const reason = safeAiConnectionFailureReason(error);\n logger.warn(`Failed to read Pod AI Connection status: ${reason}`);\n return { status: 'error', reason } as const;\n }),\n ]);\n\n sendJson(response, 200, {\n identity: {\n webId,\n podUrl,\n },\n storage,\n aiConnection,\n generatedAt: now().toISOString(),\n } satisfies PodSettingsStatus);\n } catch (error) {\n logger.error(`Failed to read Pod settings status: ${safeLogError(error)}`);\n sendJson(response, 500, { error: 'Failed to read Pod settings status' });\n }\n });\n}\n\nasync function readStorageStatus(\n usageRepo: Pick<UsageRepository, 'getPodUsage'>,\n pod: PodLookupResult | undefined,\n): Promise<PodStorageStatus> {\n if (!pod) {\n return { status: 'unsupported', reason: 'pod_not_found' };\n }\n\n let usage: PodUsageRecord | undefined;\n try {\n usage = await usageRepo.getPodUsage(pod.podId);\n } catch {\n return { status: 'error', reason: 'usage_unavailable' };\n }\n\n if (!usage) {\n return { status: 'unsupported', reason: 'usage_not_available' };\n }\n\n return {\n status: 'available',\n usage: {\n storageBytes: usage.storageBytes,\n ingressBytes: usage.ingressBytes,\n egressBytes: usage.egressBytes,\n },\n limits: {\n storageLimitBytes: usage.storageLimitBytes ?? null,\n bandwidthLimitBps: usage.bandwidthLimitBps ?? null,\n },\n source: 'identity_usage',\n };\n}\n\nexport class DrizzlePodAiConnectionStatusReader implements PodAiConnectionStatusReader {\n public constructor(\n private readonly internalPodAccess?: InternalPodAccessTokenProvider,\n private readonly dbFactory: (input: {\n webId: string;\n podUrl: string;\n fetch: typeof fetch;\n }) => Promise<AiConnectionStatusDb> = createAiConnectionStatusDb,\n ) {}\n\n public async read({ webId, podUrl }: { webId: string; podUrl?: string }): Promise<PodAiConnectionStatus> {\n const trustedFetch = await this.internalPodAccess?.getTrustedFetch(webId);\n if (!trustedFetch) {\n return { status: 'unsupported', reason: 'not_configured' };\n }\n if (!podUrl) {\n return { status: 'unsupported', reason: 'pod_not_found' };\n }\n\n try {\n const db = await this.dbFactory({ webId, podUrl, fetch: trustedFetch });\n await db.init?.(credentialResource, indexedFileResource);\n\n const credentialRows = await db.select().from(credentialResource).where(eq(credentialResource.status, 'active')).execute() as CredentialRow[];\n const indexedRows = await db.select().from(indexedFileResource).execute() as IndexedFileRow[];\n const lastSyncAt = latestIso([\n ...credentialRows.map((row) => row.lastUsedAt ?? row.lastRefreshAt),\n ...indexedRows.map((row) => row.indexedAt),\n ]);\n\n return {\n status: 'available',\n containerUrl: new URL('settings/credentials.ttl', podUrl).toString(),\n configuredProviders: credentialRows.length,\n lastSyncAt,\n source: 'drizzle-solid',\n };\n } catch {\n return { status: 'error', reason: 'ai_connection_unavailable' };\n }\n }\n}\n\ntype AiConnectionStatusDb = {\n init?: (...resources: unknown[]) => Promise<void>;\n select(): {\n from(resource: unknown): {\n where(condition: unknown): { execute(): Promise<unknown[]> };\n execute(): Promise<unknown[]>;\n };\n };\n};\n\nfunction createAiConnectionStatusDb(input: {\n webId: string;\n podUrl: string;\n fetch: typeof fetch;\n}): Promise<AiConnectionStatusDb> {\n return Promise.resolve(drizzle({\n fetch: input.fetch,\n info: { webId: input.webId, isLoggedIn: true },\n } as any, {\n podUrl: input.podUrl,\n schema: {\n credential: credentialResource,\n indexedFile: indexedFileResource,\n },\n }) as unknown as AiConnectionStatusDb);\n}\n\nfunction latestIso(values: unknown[]): string | undefined {\n const timestamps = values\n .map((value) => {\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'string' || typeof value === 'number') {\n const parsed = Date.parse(String(value));\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n })\n .filter((value): value is number => value !== undefined);\n if (timestamps.length === 0) {\n return undefined;\n }\n return new Date(Math.max(...timestamps)).toISOString();\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n\nfunction safeLogError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction safeAiConnectionFailureReason(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n for (const reason of [\n 'service_access_missing',\n 'not_configured',\n 'pod_not_found',\n 'ai_connection_unavailable',\n ]) {\n if (message.includes(reason)) {\n return reason;\n }\n }\n return 'ai_connection_unavailable';\n}\n"]}
1
+ {"version":3,"file":"PodSettingsHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/PodSettingsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ServerResponse } from 'node:http';\nimport { drizzle, eq } from '@undefineds.co/drizzle-solid';\nimport {\n credentialResource,\n indexedFileResource,\n type CredentialRow,\n type IndexedFileRow,\n} from '@undefineds.co/models';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { ApiServer } from '../ApiServer';\nimport type { AuthenticatedRequest } from '../middleware/AuthMiddleware';\nimport type { PodLookupRepository, PodLookupResult } from '../../identity/drizzle/PodLookupRepository';\nimport type { UsageRepository, PodUsageRecord } from '../../storage/quota/UsageRepository';\nimport type { AuthContext } from '../auth/AuthContext';\nimport type { InternalPodAccessTokenProvider } from '../ai-gateway/pod/HostedPodDataAccess';\n\nexport interface PodSettingsStatus {\n identity: {\n webId: string;\n podUrl?: string;\n };\n storage: PodStorageStatus;\n aiConnection: PodAiConnectionStatus;\n generatedAt: string;\n}\n\nexport type PodStorageStatus =\n | {\n status: 'available';\n usage: {\n storageBytes: number;\n ingressBytes: number;\n egressBytes: number;\n };\n limits: {\n storageLimitBytes: number | null;\n bandwidthLimitBps: number | null;\n };\n source: 'identity_usage';\n }\n | {\n status: 'unsupported' | 'error';\n reason: string;\n };\n\nexport type PodAiConnectionStatus =\n | {\n status: 'available';\n containerUrl?: string;\n configuredProviders: number;\n lastSyncAt?: string;\n source: 'drizzle-solid';\n }\n | {\n status: 'unsupported' | 'error';\n reason: string;\n };\n\nexport interface PodAiConnectionStatusReader {\n read(input: { webId: string; podUrl?: string; auth?: AuthContext }): Promise<PodAiConnectionStatus>;\n}\n\nexport interface PodSettingsHandlerOptions {\n podLookupRepository: Pick<PodLookupRepository, 'findByWebId'>;\n usageRepo: Pick<UsageRepository, 'getPodUsage'>;\n aiConnectionStatusReader?: PodAiConnectionStatusReader;\n now?: () => Date;\n logger?: Pick<ReturnType<typeof getLoggerFor>, 'warn' | 'error'>;\n}\n\nexport function registerPodSettingsRoutes(server: ApiServer, options: PodSettingsHandlerOptions): void {\n const logger = options.logger ?? getLoggerFor('PodSettingsHandler');\n const now = options.now ?? (() => new Date());\n const aiConnectionStatusReader = options.aiConnectionStatusReader ?? {\n read: async () => ({ status: 'unsupported', reason: 'not_configured' }) as const,\n };\n\n server.get('/api/pod/settings/status', async (request, response) => {\n if (!request.auth || request.auth.type !== 'solid') {\n sendJson(response, 401, { error: 'Authentication required' });\n return;\n }\n\n const webId = request.auth.webId;\n try {\n const pod = await options.podLookupRepository.findByWebId(webId);\n const podUrl = pod?.storageUrl ?? pod?.baseUrl;\n const [storage, aiConnection] = await Promise.all([\n readStorageStatus(options.usageRepo, pod),\n aiConnectionStatusReader.read({ webId, podUrl, auth: request.auth }).catch((error: unknown) => {\n const reason = safeAiConnectionFailureReason(error);\n logger.warn(`Failed to read Pod AI Connection status: ${reason}`);\n return { status: 'error', reason } as const;\n }),\n ]);\n\n sendJson(response, 200, {\n identity: {\n webId,\n podUrl,\n },\n storage,\n aiConnection,\n generatedAt: now().toISOString(),\n } satisfies PodSettingsStatus);\n } catch (error) {\n logger.error(`Failed to read Pod settings status: ${safeLogError(error)}`);\n sendJson(response, 500, { error: 'Failed to read Pod settings status' });\n }\n });\n}\n\nasync function readStorageStatus(\n usageRepo: Pick<UsageRepository, 'getPodUsage'>,\n pod: PodLookupResult | undefined,\n): Promise<PodStorageStatus> {\n if (!pod) {\n return { status: 'unsupported', reason: 'pod_not_found' };\n }\n\n let usage: PodUsageRecord | undefined;\n try {\n usage = await usageRepo.getPodUsage(pod.podId);\n } catch {\n return { status: 'error', reason: 'usage_unavailable' };\n }\n\n if (!usage) {\n return { status: 'unsupported', reason: 'usage_not_available' };\n }\n\n return {\n status: 'available',\n usage: {\n storageBytes: usage.storageBytes,\n ingressBytes: usage.ingressBytes,\n egressBytes: usage.egressBytes,\n },\n limits: {\n storageLimitBytes: usage.storageLimitBytes ?? null,\n bandwidthLimitBps: usage.bandwidthLimitBps ?? null,\n },\n source: 'identity_usage',\n };\n}\n\nexport class DrizzlePodAiConnectionStatusReader implements PodAiConnectionStatusReader {\n public constructor(\n private readonly internalPodAccess?: InternalPodAccessTokenProvider,\n private readonly dbFactory: (input: {\n webId: string;\n podUrl: string;\n fetch: typeof fetch;\n }) => Promise<AiConnectionStatusDb> = createAiConnectionStatusDb,\n ) {}\n\n public async read({ webId, podUrl, auth }: { webId: string; podUrl?: string; auth?: AuthContext }): Promise<PodAiConnectionStatus> {\n const trustedFetch = await this.internalPodAccess?.getTrustedFetch(webId, auth);\n if (!trustedFetch) {\n return { status: 'unsupported', reason: 'not_configured' };\n }\n if (!podUrl) {\n return { status: 'unsupported', reason: 'pod_not_found' };\n }\n\n try {\n const db = await this.dbFactory({ webId, podUrl, fetch: trustedFetch });\n await db.init?.(credentialResource, indexedFileResource);\n\n const credentialRows = await db.select().from(credentialResource).where(eq(credentialResource.status, 'active')).execute() as CredentialRow[];\n const indexedRows = await db.select().from(indexedFileResource).execute() as IndexedFileRow[];\n const lastSyncAt = latestIso([\n ...credentialRows.map((row) => row.lastUsedAt ?? row.lastRefreshAt),\n ...indexedRows.map((row) => row.indexedAt),\n ]);\n\n return {\n status: 'available',\n containerUrl: new URL('settings/credentials.ttl', podUrl).toString(),\n configuredProviders: credentialRows.length,\n lastSyncAt,\n source: 'drizzle-solid',\n };\n } catch {\n return { status: 'error', reason: 'ai_connection_unavailable' };\n }\n }\n}\n\ntype AiConnectionStatusDb = {\n init?: (...resources: unknown[]) => Promise<void>;\n select(): {\n from(resource: unknown): {\n where(condition: unknown): { execute(): Promise<unknown[]> };\n execute(): Promise<unknown[]>;\n };\n };\n};\n\nfunction createAiConnectionStatusDb(input: {\n webId: string;\n podUrl: string;\n fetch: typeof fetch;\n}): Promise<AiConnectionStatusDb> {\n return Promise.resolve(drizzle({\n fetch: input.fetch,\n info: { webId: input.webId, isLoggedIn: true },\n } as any, {\n podUrl: input.podUrl,\n schema: {\n credential: credentialResource,\n indexedFile: indexedFileResource,\n },\n }) as unknown as AiConnectionStatusDb);\n}\n\nfunction latestIso(values: unknown[]): string | undefined {\n const timestamps = values\n .map((value) => {\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'string' || typeof value === 'number') {\n const parsed = Date.parse(String(value));\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n })\n .filter((value): value is number => value !== undefined);\n if (timestamps.length === 0) {\n return undefined;\n }\n return new Date(Math.max(...timestamps)).toISOString();\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n\nfunction safeLogError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction safeAiConnectionFailureReason(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n for (const reason of [\n 'service_access_missing',\n 'not_configured',\n 'pod_not_found',\n 'ai_connection_unavailable',\n ]) {\n if (message.includes(reason)) {\n return reason;\n }\n }\n return 'ai_connection_unavailable';\n}\n"]}
@@ -59,16 +59,16 @@ export interface AgentRuntimeConfig {
59
59
  aiConnection?: AIConnectionInvocationConfig;
60
60
  }
61
61
  export type PersistedAgentRuntimeConfig = Omit<AgentRuntimeConfig, 'aiConnection'> & {
62
- aiConnection?: Omit<AIConnectionInvocationConfig, 'gatewayKey'>;
62
+ aiConnection?: Omit<AIConnectionInvocationConfig, 'apiKey'>;
63
63
  };
64
64
  /**
65
65
  * Runtime config persisted with a Run is a non-secret binding description.
66
- * The gateway key is restored from the current execution context on each
66
+ * The API key is restored from the current execution context on each
67
67
  * initial or continuation invocation.
68
68
  */
69
69
  export declare function toPersistedAgentRuntimeConfig(config: AgentRuntimeConfig): PersistedAgentRuntimeConfig;
70
70
  export declare function withInvocationAiConnection<TContext>(config: AgentRuntimeConfig | PersistedAgentRuntimeConfig, context: TContext | undefined): AgentRuntimeConfig;
71
- export declare function deepScrubGatewayKey<T>(value: T): T;
71
+ export declare function deepScrubApiKey<T>(value: T): T;
72
72
  export type AgentRuntimeEvent = {
73
73
  type: 'text';
74
74
  text: string;
@@ -2,14 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.toPersistedAgentRuntimeConfig = toPersistedAgentRuntimeConfig;
4
4
  exports.withInvocationAiConnection = withInvocationAiConnection;
5
- exports.deepScrubGatewayKey = deepScrubGatewayKey;
5
+ exports.deepScrubApiKey = deepScrubApiKey;
6
6
  /**
7
7
  * Runtime config persisted with a Run is a non-secret binding description.
8
- * The gateway key is restored from the current execution context on each
8
+ * The API key is restored from the current execution context on each
9
9
  * initial or continuation invocation.
10
10
  */
11
11
  function toPersistedAgentRuntimeConfig(config) {
12
- return deepScrubGatewayKey(config);
12
+ return deepScrubApiKey(config);
13
13
  }
14
14
  function withInvocationAiConnection(config, context) {
15
15
  const persisted = toPersistedAgentRuntimeConfig(config);
@@ -24,19 +24,19 @@ function withInvocationAiConnection(config, context) {
24
24
  } : {}),
25
25
  };
26
26
  }
27
- function deepScrubGatewayKey(value) {
27
+ function deepScrubApiKey(value) {
28
28
  if (Array.isArray(value)) {
29
- return value.map((item) => deepScrubGatewayKey(item));
29
+ return value.map((item) => deepScrubApiKey(item));
30
30
  }
31
31
  if (!value || typeof value !== 'object' || value instanceof Date) {
32
32
  return value;
33
33
  }
34
34
  const output = {};
35
35
  for (const [key, item] of Object.entries(value)) {
36
- if (key === 'gatewayKey') {
36
+ if (key === 'apiKey') {
37
37
  continue;
38
38
  }
39
- output[key] = deepScrubGatewayKey(item);
39
+ output[key] = deepScrubApiKey(item);
40
40
  }
41
41
  return output;
42
42
  }
@@ -51,13 +51,13 @@ function readInvocationAiConnection(context) {
51
51
  const value = candidate;
52
52
  if (typeof value.baseUrl !== 'string'
53
53
  || value.baseUrl.trim().length === 0
54
- || typeof value.gatewayKey !== 'string'
55
- || value.gatewayKey.trim().length === 0) {
54
+ || typeof value.apiKey !== 'string'
55
+ || value.apiKey.trim().length === 0) {
56
56
  return undefined;
57
57
  }
58
58
  return {
59
59
  baseUrl: value.baseUrl,
60
- gatewayKey: value.gatewayKey,
60
+ apiKey: value.apiKey,
61
61
  ...(typeof value.model === 'string' && value.model.trim().length > 0 ? { model: value.model } : {}),
62
62
  };
63
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AgentRuntimeTypes.js","sourceRoot":"","sources":["../../../src/api/runs/AgentRuntimeTypes.ts"],"names":[],"mappings":";;AAoEA,sEAEC;AAED,gEAeC;AAED,kDAeC;AAzCD;;;;GAIG;AACH,SAAgB,6BAA6B,CAAC,MAA0B;IACtE,OAAO,mBAAmB,CAAC,MAAM,CAAgC,CAAC;AACpE,CAAC;AAED,SAAgB,0BAA0B,CACxC,MAAwD,EACxD,OAA6B;IAE7B,MAAM,SAAS,GAAG,6BAA6B,CAAC,MAA4B,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAC;IACvD,OAAO;QACL,GAAG,SAAS;QACZ,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;YACf,YAAY,EAAE;gBACZ,GAAG,SAAS,CAAC,YAAY;gBACzB,GAAG,UAAU;aACd;SACF,CAAC,CAAC,CAAC,EAAE,CAAC;KACc,CAAC;AAC1B,CAAC;AAED,SAAgB,mBAAmB,CAAI,KAAQ;IAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAM,CAAC;IAC7D,CAAC;IACD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QACjE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QAC3E,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YACzB,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,MAAW,CAAC;AACrB,CAAC;AAED,SAAS,0BAA0B,CAAW,OAA6B;IACzE,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,SAAS,GAAI,OAAmC,CAAC,YAAY,CAAC;IACpE,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,SAAoC,CAAC;IACnD,IACE,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;WAC9B,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;WACjC,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;WACpC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EACvC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpG,CAAC;AACJ,CAAC","sourcesContent":["import type { ResolvedAgentConfig } from '../../agents/config/types';\nimport type { AIConnectionInvocationConfig } from '../../agents/types';\nimport type { WorkspaceRef } from '../workspace/types';\n\nexport type RunnerProtocol = 'pi' | 'acp';\nexport type AcpRunnerType = 'codebuddy' | 'claude' | 'codex';\nexport type RunnerType = 'pi' | AcpRunnerType;\n\nexport type WorktreeSpec =\n | { mode: 'existing'; path: string }\n | { mode: 'create'; baseRef?: string; branch?: string };\n\n/**\n * Canonical workspace reference for a Run.\n *\n * This is a workspace Container reference, not an execution config object.\n * Stable workspace metadata belongs on the Container .meta resource. Runners\n * resolve this reference into their own local cwd before starting the Agent Loop.\n */\nexport interface AgentRuntimeConfig {\n workspace: WorkspaceRef;\n /**\n * Optional execution policy for git workspaces. The workspace field still\n * points at the repo/workspace resource; this only selects the cwd used by a run.\n */\n worktree?: WorktreeSpec;\n /**\n * Stream idle cutoff for agent output. If no output arrives within this window,\n * the current streaming response ends.\n *\n * Defaults to 500ms for tests; real agents may need a larger value.\n */\n idleMs?: number;\n /**\n * How long to keep the stream open after an auth_required event.\n * Defaults to 5 minutes.\n */\n authWaitMs?: number;\n runner: {\n type: RunnerType;\n /**\n * pi: request-scoped pi AgentSession restored from Xpod Run/Thread/Message state.\n * acp: protocol adapter over JSON-RPC (Agent Client Protocol) stdio runners.\n */\n protocol?: RunnerProtocol;\n argv?: string[];\n allowCustomArgv?: boolean;\n };\n /**\n * Resolved non-secret agent profile from /agents/{agentId}/AGENTS.md + .meta.\n */\n agentConfig?: ResolvedAgentConfig;\n /**\n * Invocation-scoped Xpod AI Connection. Model runners fail closed without it;\n * raw Pod provider credentials must never be placed in agentConfig.\n */\n aiConnection?: AIConnectionInvocationConfig;\n}\n\nexport type PersistedAgentRuntimeConfig = Omit<AgentRuntimeConfig, 'aiConnection'> & {\n aiConnection?: Omit<AIConnectionInvocationConfig, 'gatewayKey'>;\n};\n\n/**\n * Runtime config persisted with a Run is a non-secret binding description.\n * The gateway key is restored from the current execution context on each\n * initial or continuation invocation.\n */\nexport function toPersistedAgentRuntimeConfig(config: AgentRuntimeConfig): PersistedAgentRuntimeConfig {\n return deepScrubGatewayKey(config) as PersistedAgentRuntimeConfig;\n}\n\nexport function withInvocationAiConnection<TContext>(\n config: AgentRuntimeConfig | PersistedAgentRuntimeConfig,\n context: TContext | undefined,\n): AgentRuntimeConfig {\n const persisted = toPersistedAgentRuntimeConfig(config as AgentRuntimeConfig);\n const invocation = readInvocationAiConnection(context);\n return {\n ...persisted,\n ...(invocation ? {\n aiConnection: {\n ...persisted.aiConnection,\n ...invocation,\n },\n } : {}),\n } as AgentRuntimeConfig;\n}\n\nexport function deepScrubGatewayKey<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map((item) => deepScrubGatewayKey(item)) as T;\n }\n if (!value || typeof value !== 'object' || value instanceof Date) {\n return value;\n }\n const output: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n if (key === 'gatewayKey') {\n continue;\n }\n output[key] = deepScrubGatewayKey(item);\n }\n return output as T;\n}\n\nfunction readInvocationAiConnection<TContext>(context: TContext | undefined): AIConnectionInvocationConfig | undefined {\n if (!context || typeof context !== 'object') {\n return undefined;\n }\n const candidate = (context as Record<string, unknown>).aiConnection;\n if (!candidate || typeof candidate !== 'object') {\n return undefined;\n }\n const value = candidate as Record<string, unknown>;\n if (\n typeof value.baseUrl !== 'string'\n || value.baseUrl.trim().length === 0\n || typeof value.gatewayKey !== 'string'\n || value.gatewayKey.trim().length === 0\n ) {\n return undefined;\n }\n return {\n baseUrl: value.baseUrl,\n gatewayKey: value.gatewayKey,\n ...(typeof value.model === 'string' && value.model.trim().length > 0 ? { model: value.model } : {}),\n };\n}\n\nexport type AgentRuntimeEvent =\n | { type: 'text'; text: string }\n | { type: 'error'; message: string }\n | {\n type: 'waiting_runner';\n workspace: WorkspaceRef;\n message: string;\n }\n | {\n type: 'auth_required';\n method: string;\n url?: string;\n message?: string;\n options?: Array<{ label?: string; url?: string; method?: string }>;\n }\n | {\n type: 'tool_call';\n requestId: string;\n name: string;\n arguments: string;\n };\n"]}
1
+ {"version":3,"file":"AgentRuntimeTypes.js","sourceRoot":"","sources":["../../../src/api/runs/AgentRuntimeTypes.ts"],"names":[],"mappings":";;AAoEA,sEAEC;AAED,gEAeC;AAED,0CAeC;AAzCD;;;;GAIG;AACH,SAAgB,6BAA6B,CAAC,MAA0B;IACtE,OAAO,eAAe,CAAC,MAAM,CAAgC,CAAC;AAChE,CAAC;AAED,SAAgB,0BAA0B,CACxC,MAAwD,EACxD,OAA6B;IAE7B,MAAM,SAAS,GAAG,6BAA6B,CAAC,MAA4B,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAC;IACvD,OAAO;QACL,GAAG,SAAS;QACZ,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;YACf,YAAY,EAAE;gBACZ,GAAG,SAAS,CAAC,YAAY;gBACzB,GAAG,UAAU;aACd;SACF,CAAC,CAAC,CAAC,EAAE,CAAC;KACc,CAAC;AAC1B,CAAC;AAED,SAAgB,eAAe,CAAI,KAAQ;IACzC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAM,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QACjE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QAC3E,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,MAAW,CAAC;AACrB,CAAC;AAED,SAAS,0BAA0B,CAAW,OAA6B;IACzE,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,SAAS,GAAI,OAAmC,CAAC,YAAY,CAAC;IACpE,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,SAAoC,CAAC;IACnD,IACE,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;WAC9B,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;WACjC,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;WAChC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EACnC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpG,CAAC;AACJ,CAAC","sourcesContent":["import type { ResolvedAgentConfig } from '../../agents/config/types';\nimport type { AIConnectionInvocationConfig } from '../../agents/types';\nimport type { WorkspaceRef } from '../workspace/types';\n\nexport type RunnerProtocol = 'pi' | 'acp';\nexport type AcpRunnerType = 'codebuddy' | 'claude' | 'codex';\nexport type RunnerType = 'pi' | AcpRunnerType;\n\nexport type WorktreeSpec =\n | { mode: 'existing'; path: string }\n | { mode: 'create'; baseRef?: string; branch?: string };\n\n/**\n * Canonical workspace reference for a Run.\n *\n * This is a workspace Container reference, not an execution config object.\n * Stable workspace metadata belongs on the Container .meta resource. Runners\n * resolve this reference into their own local cwd before starting the Agent Loop.\n */\nexport interface AgentRuntimeConfig {\n workspace: WorkspaceRef;\n /**\n * Optional execution policy for git workspaces. The workspace field still\n * points at the repo/workspace resource; this only selects the cwd used by a run.\n */\n worktree?: WorktreeSpec;\n /**\n * Stream idle cutoff for agent output. If no output arrives within this window,\n * the current streaming response ends.\n *\n * Defaults to 500ms for tests; real agents may need a larger value.\n */\n idleMs?: number;\n /**\n * How long to keep the stream open after an auth_required event.\n * Defaults to 5 minutes.\n */\n authWaitMs?: number;\n runner: {\n type: RunnerType;\n /**\n * pi: request-scoped pi AgentSession restored from Xpod Run/Thread/Message state.\n * acp: protocol adapter over JSON-RPC (Agent Client Protocol) stdio runners.\n */\n protocol?: RunnerProtocol;\n argv?: string[];\n allowCustomArgv?: boolean;\n };\n /**\n * Resolved non-secret agent profile from /agents/{agentId}/AGENTS.md + .meta.\n */\n agentConfig?: ResolvedAgentConfig;\n /**\n * Invocation-scoped Xpod AI Connection. Model runners fail closed without it;\n * raw Pod provider credentials must never be placed in agentConfig.\n */\n aiConnection?: AIConnectionInvocationConfig;\n}\n\nexport type PersistedAgentRuntimeConfig = Omit<AgentRuntimeConfig, 'aiConnection'> & {\n aiConnection?: Omit<AIConnectionInvocationConfig, 'apiKey'>;\n};\n\n/**\n * Runtime config persisted with a Run is a non-secret binding description.\n * The API key is restored from the current execution context on each\n * initial or continuation invocation.\n */\nexport function toPersistedAgentRuntimeConfig(config: AgentRuntimeConfig): PersistedAgentRuntimeConfig {\n return deepScrubApiKey(config) as PersistedAgentRuntimeConfig;\n}\n\nexport function withInvocationAiConnection<TContext>(\n config: AgentRuntimeConfig | PersistedAgentRuntimeConfig,\n context: TContext | undefined,\n): AgentRuntimeConfig {\n const persisted = toPersistedAgentRuntimeConfig(config as AgentRuntimeConfig);\n const invocation = readInvocationAiConnection(context);\n return {\n ...persisted,\n ...(invocation ? {\n aiConnection: {\n ...persisted.aiConnection,\n ...invocation,\n },\n } : {}),\n } as AgentRuntimeConfig;\n}\n\nexport function deepScrubApiKey<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map((item) => deepScrubApiKey(item)) as T;\n }\n if (!value || typeof value !== 'object' || value instanceof Date) {\n return value;\n }\n const output: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n if (key === 'apiKey') {\n continue;\n }\n output[key] = deepScrubApiKey(item);\n }\n return output as T;\n}\n\nfunction readInvocationAiConnection<TContext>(context: TContext | undefined): AIConnectionInvocationConfig | undefined {\n if (!context || typeof context !== 'object') {\n return undefined;\n }\n const candidate = (context as Record<string, unknown>).aiConnection;\n if (!candidate || typeof candidate !== 'object') {\n return undefined;\n }\n const value = candidate as Record<string, unknown>;\n if (\n typeof value.baseUrl !== 'string'\n || value.baseUrl.trim().length === 0\n || typeof value.apiKey !== 'string'\n || value.apiKey.trim().length === 0\n ) {\n return undefined;\n }\n return {\n baseUrl: value.baseUrl,\n apiKey: value.apiKey,\n ...(typeof value.model === 'string' && value.model.trim().length > 0 ? { model: value.model } : {}),\n };\n}\n\nexport type AgentRuntimeEvent =\n | { type: 'text'; text: string }\n | { type: 'error'; message: string }\n | {\n type: 'waiting_runner';\n workspace: WorkspaceRef;\n message: string;\n }\n | {\n type: 'auth_required';\n method: string;\n url?: string;\n message?: string;\n options?: Array<{ label?: string; url?: string; method?: string }>;\n }\n | {\n type: 'tool_call';\n requestId: string;\n name: string;\n arguments: string;\n };\n"]}
@@ -9,6 +9,7 @@ export declare const XPOD_RUN_REQUESTED_EVENT = "xpod/run.requested";
9
9
  export declare const XPOD_RUN_CONTINUE_REQUESTED_EVENT = "xpod/run.continue_requested";
10
10
  export declare const XPOD_AGENT_RUN_FUNCTION_ID = "xpod-agent-run";
11
11
  export interface XpodRunRequestedEventData {
12
+ source: string;
12
13
  runId: string;
13
14
  threadId: string;
14
15
  executionKey?: string;
@@ -17,10 +18,11 @@ export interface XpodRunRequestedEventData {
17
18
  continuation?: RunExecutionInput['continuation'];
18
19
  }
19
20
  export type XpodRunRequestedEvent = EventPayload<XpodRunRequestedEventData> & {
20
- name: typeof XPOD_RUN_REQUESTED_EVENT | typeof XPOD_RUN_CONTINUE_REQUESTED_EVENT;
21
+ name: string;
21
22
  };
22
23
  export interface InngestRunExecutionBackendOptions {
23
24
  client?: Inngest;
25
+ source?: string;
24
26
  baseUrl?: string;
25
27
  eventKey?: string;
26
28
  signingKey?: string;
@@ -53,6 +55,9 @@ export interface InngestRunExecutionBackendOptions {
53
55
  */
54
56
  export declare class InngestRunExecutionBackend implements RunExecutionBackend {
55
57
  private readonly client;
58
+ private readonly source;
59
+ private readonly requestedEventName;
60
+ private readonly continueRequestedEventName;
56
61
  private readonly runtimeDriver;
57
62
  private readonly managedRunWorker?;
58
63
  private readonly contextResolver?;
@@ -62,9 +67,9 @@ export declare class InngestRunExecutionBackend implements RunExecutionBackend {
62
67
  private readonly durableDelivery;
63
68
  private readonly pendingRuns;
64
69
  readonly agentRunFunction: import("inngest").InngestFunction<import("inngest").InngestFunction.Options<[{
65
- readonly event: "xpod/run.requested";
70
+ readonly event: string;
66
71
  }, {
67
- readonly event: "xpod/run.continue_requested";
72
+ readonly event: string;
68
73
  }], import("inngest").HandlerWithTriggers<{
69
74
  sendEvent: (idOrOptions: import("inngest").StepOptionsOrId, payload: import("inngest").SendEventPayload) => Promise<import("inngest/types").SendEventOutput<import("inngest").ClientOptionsFromInngest<Inngest<import("inngest").ClientOptions>>>>;
70
75
  waitForSignal: <TData>(idOrOptions: import("inngest").StepOptionsOrId, opts: {
@@ -151,9 +156,9 @@ export declare class InngestRunExecutionBackend implements RunExecutionBackend {
151
156
  }) => import("inngest/types").InvocationResult<import("inngest/types").Jsonify<import("inngest").GetFunctionOutputRaw<TFunction>>>;
152
157
  fetch: import("inngest").StepFetch;
153
158
  }, [{
154
- readonly event: "xpod/run.requested";
159
+ readonly event: string;
155
160
  }, {
156
- readonly event: "xpod/run.continue_requested";
161
+ readonly event: string;
157
162
  }], Omit<Omit<import("inngest").BaseContext<Inngest.Any>, never> & Record<never, never> & {
158
163
  logger: import("inngest").Logger;
159
164
  }, "group" | "requestId" | "event" | "attempt" | "events" | "runId" | "step" | "defer" | "jobId" | "maxAttempts"> & import("inngest").FailureEventArgs<EventPayload<any>> & {
@@ -332,9 +337,9 @@ export declare class InngestRunExecutionBackend implements RunExecutionBackend {
332
337
  }) => import("inngest/types").InvocationResult<import("inngest/types").Jsonify<import("inngest").GetFunctionOutputRaw<TFunction>>>;
333
338
  fetch: import("inngest").StepFetch;
334
339
  }, [{
335
- readonly event: "xpod/run.requested";
340
+ readonly event: string;
336
341
  }, {
337
- readonly event: "xpod/run.continue_requested";
342
+ readonly event: string;
338
343
  }], Omit<Omit<import("inngest").BaseContext<Inngest.Any>, never> & Record<never, never> & {
339
344
  logger: import("inngest").Logger;
340
345
  }, "group" | "requestId" | "event" | "attempt" | "events" | "runId" | "step" | "defer" | "jobId" | "maxAttempts"> & import("inngest").FailureEventArgs<EventPayload<any>> & {
@@ -425,12 +430,13 @@ export declare class InngestRunExecutionBackend implements RunExecutionBackend {
425
430
  fetch: import("inngest").StepFetch;
426
431
  };
427
432
  }>, Inngest<import("inngest").ClientOptions>, [{
428
- readonly event: "xpod/run.requested";
433
+ readonly event: string;
429
434
  }, {
430
- readonly event: "xpod/run.continue_requested";
435
+ readonly event: string;
431
436
  }]>;
432
437
  constructor(options?: InngestRunExecutionBackendOptions);
433
438
  getClient(): Inngest;
439
+ getSource(): string;
434
440
  start(input: RunExecutionInput): AsyncIterable<AgentRuntimeEvent>;
435
441
  private handleAgentRun;
436
442
  restoreExecutionInput(runId: string, context: StoreContext): Promise<RunExecutionInput>;
@@ -21,8 +21,13 @@ exports.XPOD_AGENT_RUN_FUNCTION_ID = 'xpod-agent-run';
21
21
  class InngestRunExecutionBackend {
22
22
  constructor(options = {}) {
23
23
  this.pendingRuns = new Map();
24
+ this.source = normalizeInngestSource(options.source ?? process.env.XPOD_INNGEST_SOURCE);
25
+ const identitySuffix = this.source === 'production' ? '' : `-${this.source}`;
26
+ const eventPath = this.source === 'production' ? 'xpod' : `xpod/${this.source}`;
27
+ this.requestedEventName = `${eventPath}/run.requested`;
28
+ this.continueRequestedEventName = `${eventPath}/run.continue_requested`;
24
29
  this.client = options.client ?? new inngest_1.Inngest({
25
- id: 'xpod-managed-agents',
30
+ id: `xpod-managed-agents${identitySuffix}`,
26
31
  baseUrl: options.baseUrl,
27
32
  eventKey: options.eventKey,
28
33
  signingKey: options.signingKey,
@@ -43,11 +48,11 @@ class InngestRunExecutionBackend {
43
48
  this.durableDelivery = options.durableDelivery ?? true;
44
49
  this.executeInline = options.executeInline ?? true;
45
50
  this.agentRunFunction = this.client.createFunction({
46
- id: exports.XPOD_AGENT_RUN_FUNCTION_ID,
47
- name: 'Xpod Agent Run',
51
+ id: `${exports.XPOD_AGENT_RUN_FUNCTION_ID}${identitySuffix}`,
52
+ name: this.source === 'production' ? 'Xpod Agent Run' : `Xpod Agent Run (${this.source})`,
48
53
  triggers: [
49
- { event: exports.XPOD_RUN_REQUESTED_EVENT },
50
- { event: exports.XPOD_RUN_CONTINUE_REQUESTED_EVENT },
54
+ { event: this.requestedEventName },
55
+ { event: this.continueRequestedEventName },
51
56
  ],
52
57
  idempotency: 'event.data.executionKey',
53
58
  }, (ctx) => this.handleAgentRun(ctx));
@@ -55,14 +60,17 @@ class InngestRunExecutionBackend {
55
60
  getClient() {
56
61
  return this.client;
57
62
  }
63
+ getSource() {
64
+ return this.source;
65
+ }
58
66
  async *start(input) {
59
67
  const queue = new AsyncPushQueue();
60
68
  this.pendingRuns.set(input.runId, { input, queue, started: false });
61
69
  const context = input.context;
62
70
  this.contextRecorder?.(context);
63
71
  const eventName = input.continuation
64
- ? exports.XPOD_RUN_CONTINUE_REQUESTED_EVENT
65
- : exports.XPOD_RUN_REQUESTED_EVENT;
72
+ ? this.continueRequestedEventName
73
+ : this.requestedEventName;
66
74
  const executionKey = this.executionKeyForInput(input);
67
75
  try {
68
76
  if (!this.durableDelivery && !this.executeInline) {
@@ -77,6 +85,7 @@ class InngestRunExecutionBackend {
77
85
  id: executionKey,
78
86
  name: eventName,
79
87
  data: {
88
+ source: this.source,
80
89
  runId: input.runId,
81
90
  threadId: input.threadId,
82
91
  executionKey,
@@ -169,8 +178,9 @@ class InngestRunExecutionBackend {
169
178
  return {
170
179
  event: {
171
180
  id: executionKey,
172
- name: input.continuation ? exports.XPOD_RUN_CONTINUE_REQUESTED_EVENT : exports.XPOD_RUN_REQUESTED_EVENT,
181
+ name: input.continuation ? this.continueRequestedEventName : this.requestedEventName,
173
182
  data: {
183
+ source: this.source,
174
184
  runId: input.runId,
175
185
  threadId: input.threadId,
176
186
  executionKey,
@@ -188,10 +198,11 @@ class InngestRunExecutionBackend {
188
198
  return error instanceof Error ? error.message : String(error);
189
199
  }
190
200
  executionKeyForInput(input) {
201
+ const sourcePrefix = this.source === 'production' ? '' : `${this.source}:`;
191
202
  if (!input.continuation) {
192
- return `run:${input.runId}`;
203
+ return `${sourcePrefix}run:${input.runId}`;
193
204
  }
194
- return `run:${input.runId}:continue:${input.continuation.kind}:${input.continuation.itemId ?? 'none'}`;
205
+ return `${sourcePrefix}run:${input.runId}:continue:${input.continuation.kind}:${input.continuation.itemId ?? 'none'}`;
195
206
  }
196
207
  contextEventData(input, context) {
197
208
  const auth = context?.auth;
@@ -208,6 +219,10 @@ class InngestRunExecutionBackend {
208
219
  }
209
220
  }
210
221
  exports.InngestRunExecutionBackend = InngestRunExecutionBackend;
222
+ function normalizeInngestSource(source) {
223
+ const normalized = source?.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');
224
+ return normalized || 'production';
225
+ }
211
226
  class AsyncPushQueue {
212
227
  constructor() {
213
228
  this.items = [];
@@ -1 +1 @@
1
- {"version":3,"file":"InngestRunExecutionBackend.js","sourceRoot":"","sources":["../../../src/api/runs/InngestRunExecutionBackend.ts"],"names":[],"mappings":";;;AAAA,qCAAkC;AAIlC,yDAA4E;AAC5E,iEAA8D;AAIjD,QAAA,wBAAwB,GAAG,oBAAoB,CAAC;AAChD,QAAA,iCAAiC,GAAG,6BAA6B,CAAC;AAClE,QAAA,0BAA0B,GAAG,gBAAgB,CAAC;AAmD3D;;;;;;;;;;GAUG;AACH,MAAa,0BAA0B;IAarC,YAAmB,UAA6C,EAAE;QAJjD,gBAAW,GAAG,IAAI,GAAG,EAAsB,CAAC;QAK3D,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,iBAAO,CAAC;YAC1C,EAAE,EAAE,qBAAqB;YACzB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,eAAe;SACjD,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,2CAAoB,EAAE,CAAC;QACzE,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB;eAC3C,CAAC,OAAO,CAAC,KAAK;gBACf,CAAC,CAAC,IAAI,mCAAgB,CAAC;oBACrB,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,aAAa,EAAE,IAAI,CAAC,aAAa;oBACjC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;iBAC3C,CAAC;gBACF,CAAC,CAAC,SAAS,CAAC,CAAC;QACjB,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;QAC/C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;QAC/C,IAAI,CAAC,+BAA+B,GAAG,OAAO,CAAC,+BAA+B,CAAC;QAC/E,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,IAAI,CAAC;QACvD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC;QACnD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAChD;YACE,EAAE,EAAE,kCAA0B;YAC9B,IAAI,EAAE,gBAAgB;YACtB,QAAQ,EAAE;gBACR,EAAE,KAAK,EAAE,gCAAwB,EAAE;gBACnC,EAAE,KAAK,EAAE,yCAAiC,EAAE;aAC7C;YACD,WAAW,EAAE,yBAAyB;SACvC,EACD,CAAC,GAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,GAA4B,CAAC,CAChE,CAAC;IACJ,CAAC;IAEM,SAAS;QACd,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEM,KAAK,CAAC,CAAC,KAAK,CAAC,KAAwB;QAC1C,MAAM,KAAK,GAAG,IAAI,cAAc,EAAqB,CAAC;QACtD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACpE,MAAM,OAAO,GAAI,KAAwD,CAAC,OAAO,CAAC;QAClF,IAAI,CAAC,eAAe,EAAE,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY;YAClC,CAAC,CAAC,yCAAiC;YACnC,CAAC,CAAC,gCAAwB,CAAC;QAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAEtD,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACjD,MAAM;oBACJ,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,iFAAiF;iBAC3F,CAAC;gBACF,OAAO;YACT,CAAC;YAED,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzB,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;oBACrB,EAAE,EAAE,YAAY;oBAChB,IAAI,EAAE,SAAS;oBACf,IAAI,EAAE;wBACJ,KAAK,EAAE,KAAK,CAAC,KAAK;wBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,YAAY;wBACZ,YAAY,EAAE,KAAK,CAAC,YAAY;wBAChC,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC;qBACzC;iBACF,CAAC,CAAC;YACL,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACxB,KAAK,CAAC,KAAK,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YAED,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvB,KAAK,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;oBACxE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBAChE,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,CAAC,CAAC,CAAC;YACL,CAAC;YAED,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC1C,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrC,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,GAA0B;QACrD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC;QACpC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACxD,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YACtC,CAAC;YACD,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;YACvB,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;gBACzC,IAAI,CAAC;oBACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;wBAClE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBAC5B,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC1E,CAAC;wBAAS,CAAC;oBACT,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACxB,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QACxC,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YACpD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QACxC,CAAC;QAED,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAK,CAAC,CAAC;QACpE,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QACxC,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,+BAA+B;YAClD,CAAC,CAAC;gBACA,GAAG,eAAe;gBAClB,YAAY,EAAE,MAAM,IAAI,CAAC,+BAA+B,CAAC,KAAK,CAAC,eAAe,CAAC;aAChF;YACD,CAAC,CAAC,eAAe,CAAC;QAEpB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YACnE,OAAO,IAAI,CAAC,gBAAiB,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IAC1C,CAAC;IAEM,KAAK,CAAC,qBAAqB,CAAC,KAAa,EAAE,OAAqB;QACrE,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClE,CAAC;IAEM,KAAK,CAAC,KAAK;QAChB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;YAChD,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QACzB,MAAO,IAAI,CAAC,aAAwD,CAAC,KAAK,EAAE,EAAE,CAAC;IACjF,CAAC;IAEO,mBAAmB,CAAC,KAAwB;QAClD,MAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACtD,OAAO;YACL,KAAK,EAAE;gBACL,EAAE,EAAE,YAAY;gBAChB,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,yCAAiC,CAAC,CAAC,CAAC,gCAAwB;gBACvF,IAAI,EAAE;oBACJ,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,YAAY;oBACZ,YAAY,EAAE,KAAK,CAAC,YAAY;oBAChC,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAG,KAAwD,CAAC,OAAO,CAAC;iBACnG;aACF;YACD,KAAK,EAAE,UAAU,YAAY,EAAE;YAC/B,IAAI,EAAE;gBACJ,GAAG,EAAE,KAAK,EAAK,GAAW,EAAE,EAAwB,EAAc,EAAE,CAAC,EAAE,EAAE;aAC1E;SACF,CAAC;IACJ,CAAC;IAEO,WAAW,CAAC,KAAc;QAChC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC;IAEO,oBAAoB,CAAC,KAAwB;QACnD,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YACxB,OAAO,OAAO,KAAK,CAAC,KAAK,EAAE,CAAC;QAC9B,CAAC;QACD,OAAO,OAAO,KAAK,CAAC,KAAK,aAAa,KAAK,CAAC,YAAY,CAAC,IAAI,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;IACzG,CAAC;IAEO,gBAAgB,CAAC,KAAwB,EAAE,OAAiC;QAClF,MAAM,IAAI,GAAG,OAAO,EAAE,IAAuD,CAAC;QAC9E,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YACxB,OAAO;gBACL,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3F,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC7D,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;CACF;AAzND,gEAyNC;AAED,MAAM,cAAc;IAApB;QACmB,UAAK,GAAQ,EAAE,CAAC;QACzB,cAAS,GAAsB,EAAE,CAAC;QAClC,WAAM,GAAG,KAAK,CAAC;IAkCzB,CAAC;IAhCQ,IAAI,CAAC,IAAO;QACjB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACxC,QAAQ,EAAE,EAAE,CAAC;IACf,CAAC;IAEM,KAAK;QACV,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,QAAQ,EAAE,CAAC;QACb,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;IACtB,CAAC;IAEM,KAAK,CAAC,CAAC,OAAO;QACnB,OAAO,IAAI,EAAE,CAAC;YACZ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;gBAC1B,SAAS;YACX,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,OAAO;YACT,CAAC;YACD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;CACF","sourcesContent":["import { Inngest } from 'inngest';\nimport type { EventPayload } from 'inngest/types';\nimport type { StoreContext } from '../chatkit/store';\nimport type { AgentRuntimeEvent } from './AgentRuntimeTypes';\nimport { ManagedRunWorker, type ManagedRunStore } from './ManagedRunWorker';\nimport { PiAgentRuntimeDriver } from './PiAgentRuntimeDriver';\nimport type { RunContextRetriever, RunExecutionBackend, RunExecutionInput } from './RunExecutionBackend';\nimport type { AiConnectionInvocationKeyIssuer } from '../ai-gateway/auth/AiConnectionInvocationKeyIssuer';\n\nexport const XPOD_RUN_REQUESTED_EVENT = 'xpod/run.requested';\nexport const XPOD_RUN_CONTINUE_REQUESTED_EVENT = 'xpod/run.continue_requested';\nexport const XPOD_AGENT_RUN_FUNCTION_ID = 'xpod-agent-run';\n\nexport interface XpodRunRequestedEventData {\n runId: string;\n threadId: string;\n executionKey?: string;\n authBindingId?: string;\n webId?: string;\n continuation?: RunExecutionInput['continuation'];\n}\n\nexport type XpodRunRequestedEvent = EventPayload<XpodRunRequestedEventData> & {\n name: typeof XPOD_RUN_REQUESTED_EVENT | typeof XPOD_RUN_CONTINUE_REQUESTED_EVENT;\n};\n\nexport interface InngestRunExecutionBackendOptions {\n client?: Inngest;\n baseUrl?: string;\n eventKey?: string;\n signingKey?: string;\n isDev?: boolean;\n runtimeDriver?: RunExecutionBackend;\n store?: ManagedRunStore<StoreContext>;\n managedRunWorker?: ManagedRunWorker<StoreContext>;\n contextRetriever?: RunContextRetriever<StoreContext>;\n contextResolver?: (data: XpodRunRequestedEventData) => StoreContext | Promise<StoreContext | undefined> | undefined;\n contextRecorder?: (context: StoreContext | undefined) => void;\n aiConnectionInvocationKeyIssuer?: Pick<AiConnectionInvocationKeyIssuer, 'issue'>;\n durableDelivery?: boolean;\n /**\n * When true, execute the registered Inngest handler in-process after sending\n * the event. This keeps Chat streaming low-latency while preserving the\n * Inngest event/function boundary for the managed-agents backend.\n */\n executeInline?: boolean;\n}\n\ntype PendingRun = {\n input: RunExecutionInput;\n queue: AsyncPushQueue<AgentRuntimeEvent>;\n started: boolean;\n};\n\ntype InngestHandlerContext = {\n event: XpodRunRequestedEvent;\n runId: string;\n step: {\n run<T>(id: string, fn: () => Promise<T> | T): Promise<T>;\n };\n};\n\n/**\n * Inngest-backed managed-agent execution backend.\n *\n * Xpod owns the Run facts; Inngest owns durable function delivery. In this\n * first API-facing implementation the function can execute inline so ChatKit\n * still receives a normal SSE stream without waiting for external polling.\n *\n * The in-memory pending map is only the streaming bridge for an active HTTP\n * request. When no pending stream exists, the registered Inngest function can\n * restore the Run from store through ManagedRunWorker.\n */\nexport class InngestRunExecutionBackend implements RunExecutionBackend {\n private readonly client: Inngest;\n private readonly runtimeDriver: RunExecutionBackend;\n private readonly managedRunWorker?: ManagedRunWorker<StoreContext>;\n private readonly contextResolver?: InngestRunExecutionBackendOptions['contextResolver'];\n private readonly contextRecorder?: InngestRunExecutionBackendOptions['contextRecorder'];\n private readonly aiConnectionInvocationKeyIssuer?: Pick<AiConnectionInvocationKeyIssuer, 'issue'>;\n private readonly executeInline: boolean;\n private readonly durableDelivery: boolean;\n private readonly pendingRuns = new Map<string, PendingRun>();\n\n public readonly agentRunFunction;\n\n public constructor(options: InngestRunExecutionBackendOptions = {}) {\n this.client = options.client ?? new Inngest({\n id: 'xpod-managed-agents',\n baseUrl: options.baseUrl,\n eventKey: options.eventKey,\n signingKey: options.signingKey,\n isDev: options.isDev ?? !options.durableDelivery,\n });\n this.runtimeDriver = options.runtimeDriver ?? new PiAgentRuntimeDriver();\n this.managedRunWorker = options.managedRunWorker\n ?? (options.store\n ? new ManagedRunWorker({\n store: options.store,\n runtimeDriver: this.runtimeDriver,\n contextRetriever: options.contextRetriever,\n })\n : undefined);\n this.contextResolver = options.contextResolver;\n this.contextRecorder = options.contextRecorder;\n this.aiConnectionInvocationKeyIssuer = options.aiConnectionInvocationKeyIssuer;\n this.durableDelivery = options.durableDelivery ?? true;\n this.executeInline = options.executeInline ?? true;\n this.agentRunFunction = this.client.createFunction(\n {\n id: XPOD_AGENT_RUN_FUNCTION_ID,\n name: 'Xpod Agent Run',\n triggers: [\n { event: XPOD_RUN_REQUESTED_EVENT },\n { event: XPOD_RUN_CONTINUE_REQUESTED_EVENT },\n ],\n idempotency: 'event.data.executionKey',\n },\n (ctx: any) => this.handleAgentRun(ctx as InngestHandlerContext),\n );\n }\n\n public getClient(): Inngest {\n return this.client;\n }\n\n public async *start(input: RunExecutionInput): AsyncIterable<AgentRuntimeEvent> {\n const queue = new AsyncPushQueue<AgentRuntimeEvent>();\n this.pendingRuns.set(input.runId, { input, queue, started: false });\n const context = (input as RunExecutionInput & { context?: StoreContext }).context;\n this.contextRecorder?.(context);\n const eventName = input.continuation\n ? XPOD_RUN_CONTINUE_REQUESTED_EVENT\n : XPOD_RUN_REQUESTED_EVENT;\n const executionKey = this.executionKeyForInput(input);\n\n try {\n if (!this.durableDelivery && !this.executeInline) {\n yield {\n type: 'error',\n message: 'Run execution backend has neither durable delivery nor inline execution enabled',\n };\n return;\n }\n\n if (this.durableDelivery) {\n await this.client.send({\n id: executionKey,\n name: eventName,\n data: {\n runId: input.runId,\n threadId: input.threadId,\n executionKey,\n continuation: input.continuation,\n ...this.contextEventData(input, context),\n },\n });\n }\n\n if (!this.executeInline) {\n queue.close();\n return;\n }\n\n if (this.executeInline) {\n void this.handleAgentRun(this.createInlineContext(input)).catch((error) => {\n queue.push({ type: 'error', message: this.formatError(error) });\n queue.close();\n });\n }\n\n for await (const event of queue.iterate()) {\n yield event;\n }\n } catch (error) {\n yield { type: 'error', message: this.formatError(error) };\n } finally {\n this.pendingRuns.delete(input.runId);\n queue.close();\n }\n }\n\n private async handleAgentRun(ctx: InngestHandlerContext): Promise<{ runId: string; status: string }> {\n const runId = ctx.event.data?.runId;\n if (!runId) {\n return { runId: 'unknown', status: 'missing_run_id' };\n }\n const pending = this.pendingRuns.get(runId);\n if (pending) {\n if (pending.started) {\n return { runId, status: 'skipped' };\n }\n pending.started = true;\n await ctx.step.run('run-agent', async () => {\n try {\n for await (const event of this.runtimeDriver.start(pending.input)) {\n pending.queue.push(event);\n }\n } catch (error) {\n pending.queue.push({ type: 'error', message: this.formatError(error) });\n } finally {\n pending.queue.close();\n }\n });\n\n return { runId, status: 'completed' };\n }\n\n if (!this.managedRunWorker || !this.contextResolver) {\n return { runId, status: 'not_found' };\n }\n\n const resolvedContext = await this.contextResolver(ctx.event.data!);\n if (!resolvedContext) {\n return { runId, status: 'not_found' };\n }\n const context = this.aiConnectionInvocationKeyIssuer\n ? {\n ...resolvedContext,\n aiConnection: await this.aiConnectionInvocationKeyIssuer.issue(resolvedContext),\n }\n : resolvedContext;\n\n const result = await ctx.step.run('run-agent-from-store', async () => {\n return this.managedRunWorker!.executeRun(runId, context);\n });\n\n return { runId, status: result.status };\n }\n\n public async restoreExecutionInput(runId: string, context: StoreContext): Promise<RunExecutionInput> {\n if (!this.managedRunWorker) {\n throw new Error('Managed Run worker is not configured');\n }\n return this.managedRunWorker.loadExecutionInput(runId, context);\n }\n\n public async close(): Promise<void> {\n for (const pending of this.pendingRuns.values()) {\n pending.queue.close();\n }\n this.pendingRuns.clear();\n await (this.runtimeDriver as { close?: () => void | Promise<void> }).close?.();\n }\n\n private createInlineContext(input: RunExecutionInput): InngestHandlerContext {\n const executionKey = this.executionKeyForInput(input);\n return {\n event: {\n id: executionKey,\n name: input.continuation ? XPOD_RUN_CONTINUE_REQUESTED_EVENT : XPOD_RUN_REQUESTED_EVENT,\n data: {\n runId: input.runId,\n threadId: input.threadId,\n executionKey,\n continuation: input.continuation,\n ...this.contextEventData(input, (input as RunExecutionInput & { context?: StoreContext }).context),\n },\n },\n runId: `inline:${executionKey}`,\n step: {\n run: async <T>(_id: string, fn: () => Promise<T> | T): Promise<T> => fn(),\n },\n };\n }\n\n private formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n }\n\n private executionKeyForInput(input: RunExecutionInput): string {\n if (!input.continuation) {\n return `run:${input.runId}`;\n }\n return `run:${input.runId}:continue:${input.continuation.kind}:${input.continuation.itemId ?? 'none'}`;\n }\n\n private contextEventData(input: RunExecutionInput, context: StoreContext | undefined): Partial<XpodRunRequestedEventData> {\n const auth = context?.auth as { type?: unknown; webId?: unknown } | undefined;\n if (input.authBindingId) {\n return {\n authBindingId: input.authBindingId,\n ...(auth?.type === 'solid' && typeof auth.webId === 'string' ? { webId: auth.webId } : {}),\n };\n }\n if (auth?.type !== 'solid' || typeof auth.webId !== 'string') {\n return {};\n }\n return { webId: auth.webId };\n }\n}\n\nclass AsyncPushQueue<T> {\n private readonly items: T[] = [];\n private resolvers: Array<() => void> = [];\n private closed = false;\n\n public push(item: T): void {\n if (this.closed) {\n return;\n }\n this.items.push(item);\n const resolver = this.resolvers.shift();\n resolver?.();\n }\n\n public close(): void {\n if (this.closed) {\n return;\n }\n this.closed = true;\n for (const resolver of this.resolvers) {\n resolver();\n }\n this.resolvers = [];\n }\n\n public async *iterate(): AsyncIterable<T> {\n while (true) {\n if (this.items.length > 0) {\n yield this.items.shift()!;\n continue;\n }\n if (this.closed) {\n return;\n }\n await new Promise<void>((resolve) => this.resolvers.push(resolve));\n }\n }\n}\n"]}
1
+ {"version":3,"file":"InngestRunExecutionBackend.js","sourceRoot":"","sources":["../../../src/api/runs/InngestRunExecutionBackend.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inngest } from 'inngest';\nimport type { EventPayload } from 'inngest/types';\nimport type { StoreContext } from '../chatkit/store';\nimport type { AgentRuntimeEvent } from './AgentRuntimeTypes';\nimport { ManagedRunWorker, type ManagedRunStore } from './ManagedRunWorker';\nimport { PiAgentRuntimeDriver } from './PiAgentRuntimeDriver';\nimport type { RunContextRetriever, RunExecutionBackend, RunExecutionInput } from './RunExecutionBackend';\nimport type { AiConnectionInvocationKeyIssuer } from '../ai-gateway/auth/AiConnectionInvocationKeyIssuer';\n\nexport const XPOD_RUN_REQUESTED_EVENT = 'xpod/run.requested';\nexport const XPOD_RUN_CONTINUE_REQUESTED_EVENT = 'xpod/run.continue_requested';\nexport const XPOD_AGENT_RUN_FUNCTION_ID = 'xpod-agent-run';\n\nexport interface XpodRunRequestedEventData {\n source: string;\n runId: string;\n threadId: string;\n executionKey?: string;\n authBindingId?: string;\n webId?: string;\n continuation?: RunExecutionInput['continuation'];\n}\n\nexport type XpodRunRequestedEvent = EventPayload<XpodRunRequestedEventData> & {\n name: string;\n};\n\nexport interface InngestRunExecutionBackendOptions {\n client?: Inngest;\n source?: string;\n baseUrl?: string;\n eventKey?: string;\n signingKey?: string;\n isDev?: boolean;\n runtimeDriver?: RunExecutionBackend;\n store?: ManagedRunStore<StoreContext>;\n managedRunWorker?: ManagedRunWorker<StoreContext>;\n contextRetriever?: RunContextRetriever<StoreContext>;\n contextResolver?: (data: XpodRunRequestedEventData) => StoreContext | Promise<StoreContext | undefined> | undefined;\n contextRecorder?: (context: StoreContext | undefined) => void;\n aiConnectionInvocationKeyIssuer?: Pick<AiConnectionInvocationKeyIssuer, 'issue'>;\n durableDelivery?: boolean;\n /**\n * When true, execute the registered Inngest handler in-process after sending\n * the event. This keeps Chat streaming low-latency while preserving the\n * Inngest event/function boundary for the managed-agents backend.\n */\n executeInline?: boolean;\n}\n\ntype PendingRun = {\n input: RunExecutionInput;\n queue: AsyncPushQueue<AgentRuntimeEvent>;\n started: boolean;\n};\n\ntype InngestHandlerContext = {\n event: XpodRunRequestedEvent;\n runId: string;\n step: {\n run<T>(id: string, fn: () => Promise<T> | T): Promise<T>;\n };\n};\n\n/**\n * Inngest-backed managed-agent execution backend.\n *\n * Xpod owns the Run facts; Inngest owns durable function delivery. In this\n * first API-facing implementation the function can execute inline so ChatKit\n * still receives a normal SSE stream without waiting for external polling.\n *\n * The in-memory pending map is only the streaming bridge for an active HTTP\n * request. When no pending stream exists, the registered Inngest function can\n * restore the Run from store through ManagedRunWorker.\n */\nexport class InngestRunExecutionBackend implements RunExecutionBackend {\n private readonly client: Inngest;\n private readonly source: string;\n private readonly requestedEventName: string;\n private readonly continueRequestedEventName: string;\n private readonly runtimeDriver: RunExecutionBackend;\n private readonly managedRunWorker?: ManagedRunWorker<StoreContext>;\n private readonly contextResolver?: InngestRunExecutionBackendOptions['contextResolver'];\n private readonly contextRecorder?: InngestRunExecutionBackendOptions['contextRecorder'];\n private readonly aiConnectionInvocationKeyIssuer?: Pick<AiConnectionInvocationKeyIssuer, 'issue'>;\n private readonly executeInline: boolean;\n private readonly durableDelivery: boolean;\n private readonly pendingRuns = new Map<string, PendingRun>();\n\n public readonly agentRunFunction;\n\n public constructor(options: InngestRunExecutionBackendOptions = {}) {\n this.source = normalizeInngestSource(options.source ?? process.env.XPOD_INNGEST_SOURCE);\n const identitySuffix = this.source === 'production' ? '' : `-${this.source}`;\n const eventPath = this.source === 'production' ? 'xpod' : `xpod/${this.source}`;\n this.requestedEventName = `${eventPath}/run.requested`;\n this.continueRequestedEventName = `${eventPath}/run.continue_requested`;\n this.client = options.client ?? new Inngest({\n id: `xpod-managed-agents${identitySuffix}`,\n baseUrl: options.baseUrl,\n eventKey: options.eventKey,\n signingKey: options.signingKey,\n isDev: options.isDev ?? !options.durableDelivery,\n });\n this.runtimeDriver = options.runtimeDriver ?? new PiAgentRuntimeDriver();\n this.managedRunWorker = options.managedRunWorker\n ?? (options.store\n ? new ManagedRunWorker({\n store: options.store,\n runtimeDriver: this.runtimeDriver,\n contextRetriever: options.contextRetriever,\n })\n : undefined);\n this.contextResolver = options.contextResolver;\n this.contextRecorder = options.contextRecorder;\n this.aiConnectionInvocationKeyIssuer = options.aiConnectionInvocationKeyIssuer;\n this.durableDelivery = options.durableDelivery ?? true;\n this.executeInline = options.executeInline ?? true;\n this.agentRunFunction = this.client.createFunction(\n {\n id: `${XPOD_AGENT_RUN_FUNCTION_ID}${identitySuffix}`,\n name: this.source === 'production' ? 'Xpod Agent Run' : `Xpod Agent Run (${this.source})`,\n triggers: [\n { event: this.requestedEventName },\n { event: this.continueRequestedEventName },\n ],\n idempotency: 'event.data.executionKey',\n },\n (ctx: any) => this.handleAgentRun(ctx as InngestHandlerContext),\n );\n }\n\n public getClient(): Inngest {\n return this.client;\n }\n\n public getSource(): string {\n return this.source;\n }\n\n public async *start(input: RunExecutionInput): AsyncIterable<AgentRuntimeEvent> {\n const queue = new AsyncPushQueue<AgentRuntimeEvent>();\n this.pendingRuns.set(input.runId, { input, queue, started: false });\n const context = (input as RunExecutionInput & { context?: StoreContext }).context;\n this.contextRecorder?.(context);\n const eventName = input.continuation\n ? this.continueRequestedEventName\n : this.requestedEventName;\n const executionKey = this.executionKeyForInput(input);\n\n try {\n if (!this.durableDelivery && !this.executeInline) {\n yield {\n type: 'error',\n message: 'Run execution backend has neither durable delivery nor inline execution enabled',\n };\n return;\n }\n\n if (this.durableDelivery) {\n await this.client.send({\n id: executionKey,\n name: eventName,\n data: {\n source: this.source,\n runId: input.runId,\n threadId: input.threadId,\n executionKey,\n continuation: input.continuation,\n ...this.contextEventData(input, context),\n },\n });\n }\n\n if (!this.executeInline) {\n queue.close();\n return;\n }\n\n if (this.executeInline) {\n void this.handleAgentRun(this.createInlineContext(input)).catch((error) => {\n queue.push({ type: 'error', message: this.formatError(error) });\n queue.close();\n });\n }\n\n for await (const event of queue.iterate()) {\n yield event;\n }\n } catch (error) {\n yield { type: 'error', message: this.formatError(error) };\n } finally {\n this.pendingRuns.delete(input.runId);\n queue.close();\n }\n }\n\n private async handleAgentRun(ctx: InngestHandlerContext): Promise<{ runId: string; status: string }> {\n const runId = ctx.event.data?.runId;\n if (!runId) {\n return { runId: 'unknown', status: 'missing_run_id' };\n }\n const pending = this.pendingRuns.get(runId);\n if (pending) {\n if (pending.started) {\n return { runId, status: 'skipped' };\n }\n pending.started = true;\n await ctx.step.run('run-agent', async () => {\n try {\n for await (const event of this.runtimeDriver.start(pending.input)) {\n pending.queue.push(event);\n }\n } catch (error) {\n pending.queue.push({ type: 'error', message: this.formatError(error) });\n } finally {\n pending.queue.close();\n }\n });\n\n return { runId, status: 'completed' };\n }\n\n if (!this.managedRunWorker || !this.contextResolver) {\n return { runId, status: 'not_found' };\n }\n\n const resolvedContext = await this.contextResolver(ctx.event.data!);\n if (!resolvedContext) {\n return { runId, status: 'not_found' };\n }\n const context = this.aiConnectionInvocationKeyIssuer\n ? {\n ...resolvedContext,\n aiConnection: await this.aiConnectionInvocationKeyIssuer.issue(resolvedContext),\n }\n : resolvedContext;\n\n const result = await ctx.step.run('run-agent-from-store', async () => {\n return this.managedRunWorker!.executeRun(runId, context);\n });\n\n return { runId, status: result.status };\n }\n\n public async restoreExecutionInput(runId: string, context: StoreContext): Promise<RunExecutionInput> {\n if (!this.managedRunWorker) {\n throw new Error('Managed Run worker is not configured');\n }\n return this.managedRunWorker.loadExecutionInput(runId, context);\n }\n\n public async close(): Promise<void> {\n for (const pending of this.pendingRuns.values()) {\n pending.queue.close();\n }\n this.pendingRuns.clear();\n await (this.runtimeDriver as { close?: () => void | Promise<void> }).close?.();\n }\n\n private createInlineContext(input: RunExecutionInput): InngestHandlerContext {\n const executionKey = this.executionKeyForInput(input);\n return {\n event: {\n id: executionKey,\n name: input.continuation ? this.continueRequestedEventName : this.requestedEventName,\n data: {\n source: this.source,\n runId: input.runId,\n threadId: input.threadId,\n executionKey,\n continuation: input.continuation,\n ...this.contextEventData(input, (input as RunExecutionInput & { context?: StoreContext }).context),\n },\n },\n runId: `inline:${executionKey}`,\n step: {\n run: async <T>(_id: string, fn: () => Promise<T> | T): Promise<T> => fn(),\n },\n };\n }\n\n private formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n }\n\n private executionKeyForInput(input: RunExecutionInput): string {\n const sourcePrefix = this.source === 'production' ? '' : `${this.source}:`;\n if (!input.continuation) {\n return `${sourcePrefix}run:${input.runId}`;\n }\n return `${sourcePrefix}run:${input.runId}:continue:${input.continuation.kind}:${input.continuation.itemId ?? 'none'}`;\n }\n\n private contextEventData(input: RunExecutionInput, context: StoreContext | undefined): Partial<XpodRunRequestedEventData> {\n const auth = context?.auth as { type?: unknown; webId?: unknown } | undefined;\n if (input.authBindingId) {\n return {\n authBindingId: input.authBindingId,\n ...(auth?.type === 'solid' && typeof auth.webId === 'string' ? { webId: auth.webId } : {}),\n };\n }\n if (auth?.type !== 'solid' || typeof auth.webId !== 'string') {\n return {};\n }\n return { webId: auth.webId };\n }\n}\n\nfunction normalizeInngestSource(source: string | undefined): string {\n const normalized = source?.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');\n return normalized || 'production';\n}\n\nclass AsyncPushQueue<T> {\n private readonly items: T[] = [];\n private resolvers: Array<() => void> = [];\n private closed = false;\n\n public push(item: T): void {\n if (this.closed) {\n return;\n }\n this.items.push(item);\n const resolver = this.resolvers.shift();\n resolver?.();\n }\n\n public close(): void {\n if (this.closed) {\n return;\n }\n this.closed = true;\n for (const resolver of this.resolvers) {\n resolver();\n }\n this.resolvers = [];\n }\n\n public async *iterate(): AsyncIterable<T> {\n while (true) {\n if (this.items.length > 0) {\n yield this.items.shift()!;\n continue;\n }\n if (this.closed) {\n return;\n }\n await new Promise<void>((resolve) => this.resolvers.push(resolve));\n }\n }\n}\n"]}
@@ -258,7 +258,7 @@ class PiAgentRuntimeDriver {
258
258
  resolvePiConfig(config) {
259
259
  const connection = (0, safe_env_1.requireAiConnectionRuntimeConfig)({
260
260
  baseUrl: config.aiConnection?.baseUrl,
261
- apiKey: config.aiConnection?.gatewayKey,
261
+ apiKey: config.aiConnection?.apiKey,
262
262
  model: config.aiConnection?.model ?? config.agentConfig?.model ?? 'linx',
263
263
  }, 'pi Agent Runtime');
264
264
  const provider = 'xpod';
@@ -489,7 +489,7 @@ class PiAgentRuntimeDriver {
489
489
  workdir,
490
490
  baseUrl: connection?.baseUrl ?? '',
491
491
  model: connection?.model ?? agent?.model ?? 'linx',
492
- gatewayKeyHash: this.hashSecret(connection?.gatewayKey),
492
+ apiKeyHash: this.hashSecret(connection?.apiKey),
493
493
  systemPrompt: agent?.systemPrompt ?? '',
494
494
  skillsContent: agent?.skillsContent ?? '',
495
495
  permissionMode: agent?.permissionMode ?? '',