@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
@@ -37,7 +37,7 @@ export interface AiClientConfigurationServiceOptions {
37
37
  now?: () => Date;
38
38
  verifyGateway?: (input: {
39
39
  endpoint: string;
40
- gatewayKey: string;
40
+ apiKey: string;
41
41
  model?: string;
42
42
  signal: AbortSignal;
43
43
  }) => Promise<unknown>;
@@ -53,7 +53,7 @@ export interface PlanInput {
53
53
  export interface ApplyInput {
54
54
  client: AiClientId;
55
55
  planId: string;
56
- gatewayKey: string;
56
+ apiKey: string;
57
57
  webId?: string;
58
58
  confirmation?: {
59
59
  token: string;
@@ -61,7 +61,7 @@ class AiClientConfigurationService {
61
61
  const client = requireSupportedClient(input.client);
62
62
  const profile = {
63
63
  endpoint: normalizeEndpoint(input.endpoint),
64
- gatewayKey: PLAN_SECRET_PLACEHOLDER,
64
+ apiKey: PLAN_SECRET_PLACEHOLDER,
65
65
  webId: input.webId ?? 'https://xpod.local/.well-known/ai-client-configuration#owner',
66
66
  model: input.model,
67
67
  };
@@ -88,8 +88,8 @@ class AiClientConfigurationService {
88
88
  }
89
89
  async apply(input) {
90
90
  const plan = this.requirePlan(input.client, input.planId);
91
- if (!input.gatewayKey?.startsWith('xpod_')) {
92
- throw new AiClientConfigurationError('invalid_gateway_key', 'Gateway key is required.', 400);
91
+ if (!input.apiKey?.startsWith('sk-')) {
92
+ throw new AiClientConfigurationError('invalid_api_key', 'CSS client credentials API key is required.', 400);
93
93
  }
94
94
  if (plan.confirmation) {
95
95
  if (!input.confirmation?.token) {
@@ -109,13 +109,13 @@ class AiClientConfigurationService {
109
109
  }
110
110
  const profile = {
111
111
  ...plan.profile,
112
- gatewayKey: input.gatewayKey,
112
+ apiKey: input.apiKey,
113
113
  webId: input.webId ?? plan.profile.webId,
114
114
  };
115
115
  const adapter = this.adapterFor(plan.client);
116
116
  const nativePlan = await mapAdapterError(() => adapter.plan(profile));
117
117
  await mapAdapterError(() => adapter.apply(nativePlan));
118
- plan.gatewayKey = input.gatewayKey;
118
+ plan.apiKey = input.apiKey;
119
119
  plan.profile = profile;
120
120
  plan.nativePlan = nativePlan;
121
121
  try {
@@ -134,11 +134,11 @@ class AiClientConfigurationService {
134
134
  if (status.status !== 'configured') {
135
135
  return status;
136
136
  }
137
- if (!plan?.gatewayKey) {
137
+ if (!plan?.apiKey) {
138
138
  return {
139
139
  ...status,
140
140
  status: 'unverifiable',
141
- message: 'Gateway key is not recoverable after restart; re-apply the client configuration to verify it.',
141
+ message: 'API key is not recoverable after restart; re-apply the client configuration to verify it.',
142
142
  };
143
143
  }
144
144
  const adapter = this.adapterFor(input.client);
@@ -149,7 +149,7 @@ class AiClientConfigurationService {
149
149
  const controller = new AbortController();
150
150
  await this.verifyGateway({
151
151
  endpoint: plan.profile.endpoint,
152
- gatewayKey: plan.gatewayKey,
152
+ apiKey: plan.apiKey,
153
153
  model: plan.profile.model,
154
154
  signal: controller.signal,
155
155
  });
@@ -293,13 +293,13 @@ async function readOptional(filePath) {
293
293
  }
294
294
  }
295
295
  function createDefaultGatewayVerifier(fetchImpl, timeoutMs) {
296
- return async ({ endpoint, gatewayKey, model, signal }) => {
296
+ return async ({ endpoint, apiKey, model, signal }) => {
297
297
  const timeout = AbortSignal.timeout(timeoutMs);
298
298
  const linked = mergeSignals(signal, timeout);
299
299
  const base = endpoint.replace(/\/+$/u, '');
300
300
  await checkedGatewayFetch(fetchImpl, `${base}/v1/models`, {
301
301
  method: 'GET',
302
- headers: { accept: 'application/json', authorization: `Bearer ${gatewayKey}` },
302
+ headers: { accept: 'application/json', authorization: `Bearer ${apiKey}` },
303
303
  signal: linked,
304
304
  });
305
305
  await checkedGatewayFetch(fetchImpl, `${base}/v1/responses`, {
@@ -307,7 +307,7 @@ function createDefaultGatewayVerifier(fetchImpl, timeoutMs) {
307
307
  headers: {
308
308
  accept: 'application/json',
309
309
  'content-type': 'application/json',
310
- authorization: `Bearer ${gatewayKey}`,
310
+ authorization: `Bearer ${apiKey}`,
311
311
  },
312
312
  body: JSON.stringify({
313
313
  model: model ?? 'xpod/default',
@@ -1 +1 @@
1
- {"version":3,"file":"AiClientConfigurationService.js","sourceRoot":"","sources":["../../../src/api/service/AiClientConfigurationService.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from 'node:crypto';\nimport path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport {\n CodexConfigAdapter,\n ClaudeCodeConfigAdapter,\n CodeBuddyConfigAdapter,\n PiConfigAdapter,\n type AiClientConfigAdapter,\n AiClientConfigPlan,\n AiConnectionClientProfile,\n ConfigWrite,\n} from '@undefineds.co/ai-connection/client-config';\n\nexport type AiClientId = 'codex' | 'claude-code' | 'pi' | 'codebuddy';\n\nexport interface AiClientConfigurationCapabilityDescriptor {\n available: boolean;\n authority?: 'local-filesystem';\n manualInstructions: string;\n}\n\nexport interface AiClientConfigurationStatus {\n status: 'notConfigured' | 'configured' | 'drifted' | 'unavailable' | 'unverifiable' | 'failedAndRestored';\n message?: string;\n installed?: boolean;\n configExists?: boolean;\n}\n\nexport interface AiClientConfigurationPlan {\n planId: string;\n client: AiClientId;\n changes: AiClientConfigurationChange[];\n conflicts: string[];\n backupLocation: string;\n replacementConfirmationRequired: boolean;\n confirmation?: {\n required: boolean;\n token: string;\n targetHash: string;\n message?: string;\n };\n}\n\nexport interface AiClientConfigurationChange {\n target: string;\n action: 'update' | 'createOrUpdate' | 'delete';\n backup: boolean;\n current?: string;\n replacement?: string;\n}\n\nexport interface AiClientConfigurationServiceOptions {\n homeDir?: string;\n backupRoot?: string;\n now?: () => Date;\n verifyGateway?: (input: {\n endpoint: string;\n gatewayKey: string;\n model?: string;\n signal: AbortSignal;\n }) => Promise<unknown>;\n fetch?: typeof fetch;\n verificationTimeoutMs?: number;\n}\n\nexport interface PlanInput {\n client: AiClientId;\n endpoint: string;\n model?: string;\n webId?: string;\n}\n\nexport interface ApplyInput {\n client: AiClientId;\n planId: string;\n gatewayKey: string;\n webId?: string;\n confirmation?: {\n token: string;\n targetHash: string;\n };\n}\n\nexport interface VerifyInput {\n client: AiClientId;\n planId?: string;\n}\n\ninterface StoredPlan {\n planId: string;\n client: AiClientId;\n profile: AiConnectionClientProfile;\n nativePlan: AiClientConfigPlan;\n targets: PlannedTarget[];\n backupDir: string;\n gatewayKey?: string;\n confirmation?: {\n token: string;\n targetHash: string;\n };\n}\n\ninterface PlannedTarget {\n filePath: string;\n displayPath: string;\n beforeHash: string;\n beforeExists: boolean;\n beforeContent: string;\n plannedContentWithoutSecret: string;\n action: 'update' | 'createOrUpdate' | 'delete';\n}\n\nconst PLAN_SECRET_PLACEHOLDER = '[redacted]';\nconst MANUAL_INSTRUCTIONS = 'Manual client setup is available when this host cannot safely write local coding-client files.';\n\nconst CLIENT_LABELS: Record<AiClientId, string> = {\n codex: 'Codex',\n 'claude-code': 'Claude Code',\n pi: 'Pi',\n codebuddy: 'CodeBuddy',\n};\n\nexport class AiClientConfigurationError extends Error {\n public readonly statusCode: number;\n public readonly code: string;\n public readonly details?: unknown;\n\n public constructor(code: string, message: string, statusCode: number, details?: unknown) {\n super(message);\n this.code = code;\n this.statusCode = statusCode;\n this.details = details;\n }\n}\n\nexport class AiClientConfigurationService {\n private readonly homeDir: string;\n private readonly backupRoot: string;\n private readonly now: () => Date;\n private readonly verifyGateway: NonNullable<AiClientConfigurationServiceOptions['verifyGateway']>;\n private readonly plans = new Map<string, StoredPlan>();\n private readonly locks = new Map<string, Promise<void>>();\n\n public constructor(options: AiClientConfigurationServiceOptions = {}) {\n this.homeDir = path.resolve(options.homeDir ?? process.env.HOME ?? process.cwd());\n this.backupRoot = path.resolve(options.backupRoot ?? path.join(this.homeDir, '.xpod/client-config-backups'));\n this.now = options.now ?? (() => new Date());\n this.verifyGateway = options.verifyGateway ?? createDefaultGatewayVerifier(\n options.fetch ?? fetch,\n options.verificationTimeoutMs ?? 8_000,\n );\n }\n\n public capability(): AiClientConfigurationCapabilityDescriptor {\n return {\n available: true,\n authority: 'local-filesystem',\n manualInstructions: MANUAL_INSTRUCTIONS,\n };\n }\n\n public async inspect(client: AiClientId): Promise<AiClientConfigurationStatus> {\n const adapter = this.adapterFor(client);\n const detection = await mapAdapterError(() => adapter.detect());\n const inspection = await mapAdapterError(() => adapter.inspect());\n const configured = inspection.ownership === 'owned';\n return {\n status: configured ? 'configured' : 'notConfigured',\n installed: detection.installed,\n configExists: detection.configExists,\n message: configured\n ? `${CLIENT_LABELS[client]} is configured for Xpod.`\n : `${CLIENT_LABELS[client]} is not configured for Xpod.`,\n };\n }\n\n public async plan(input: PlanInput): Promise<AiClientConfigurationPlan> {\n const client = requireSupportedClient(input.client);\n const profile = {\n endpoint: normalizeEndpoint(input.endpoint),\n gatewayKey: PLAN_SECRET_PLACEHOLDER,\n webId: input.webId ?? 'https://xpod.local/.well-known/ai-client-configuration#owner',\n model: input.model,\n };\n const adapter = this.adapterFor(client);\n const nativePlan = await mapAdapterError(() => adapter.plan(profile));\n const targets = await this.publicTargets(nativePlan.writes);\n const beforeHash = hash(targets.map((target) => `${target.filePath}:${target.beforeHash}`).join('\\n'));\n const plan: StoredPlan = {\n planId: `aicfg_${randomUUID().replace(/-/gu, '')}`,\n client,\n profile,\n nativePlan,\n targets,\n backupDir: path.join(this.backupRoot, client, timestampForPath(this.now())),\n ...(isReplacementSensitive(client) ? {\n confirmation: {\n token: `confirm-${client}-${beforeHash.slice(0, 12)}`,\n targetHash: beforeHash,\n },\n } : {}),\n };\n this.plans.set(plan.planId, plan);\n return publicPlan(plan, this.homeDir);\n }\n\n public async apply(input: ApplyInput): Promise<{ applied: true }> {\n const plan = this.requirePlan(input.client, input.planId);\n if (!input.gatewayKey?.startsWith('xpod_')) {\n throw new AiClientConfigurationError('invalid_gateway_key', 'Gateway key is required.', 400);\n }\n if (plan.confirmation) {\n if (!input.confirmation?.token) {\n throw new AiClientConfigurationError('confirmation_required', 'Replacement confirmation is required.', 409);\n }\n if (input.confirmation.token !== plan.confirmation.token ||\n input.confirmation.targetHash !== plan.confirmation.targetHash) {\n throw new AiClientConfigurationError('confirmation_stale', 'Replacement confirmation is stale.', 409);\n }\n }\n\n return this.withTargetLocks(plan.nativePlan.writes.map((write) => write.path), async () => {\n for (const target of plan.targets) {\n const current = await readOptional(target.filePath);\n if (hash(current ?? '') !== target.beforeHash) {\n throw new AiClientConfigurationError('configuration_conflict', 'Configuration changed after planning.', 409);\n }\n }\n\n const profile = {\n ...plan.profile,\n gatewayKey: input.gatewayKey,\n webId: input.webId ?? plan.profile.webId,\n };\n const adapter = this.adapterFor(plan.client);\n const nativePlan = await mapAdapterError(() => adapter.plan(profile));\n await mapAdapterError(() => adapter.apply(nativePlan));\n plan.gatewayKey = input.gatewayKey;\n plan.profile = profile;\n plan.nativePlan = nativePlan;\n\n try {\n await this.verify({ client: plan.client, planId: plan.planId });\n } catch {\n await mapAdapterError(() => adapter.restore(profile.webId));\n throw new AiClientConfigurationError(\n 'verification_failed_restored',\n 'Gateway verification failed.',\n 502,\n { restored: true },\n );\n }\n return { applied: true };\n });\n }\n\n public async verify(input: VerifyInput): Promise<AiClientConfigurationStatus> {\n const plan = input.planId ? this.requirePlan(input.client, input.planId) : undefined;\n const status = await this.inspect(input.client);\n if (status.status !== 'configured') {\n return status;\n }\n if (!plan?.gatewayKey) {\n return {\n ...status,\n status: 'unverifiable',\n message: 'Gateway key is not recoverable after restart; re-apply the client configuration to verify it.',\n };\n }\n const adapter = this.adapterFor(input.client);\n const projection = await mapAdapterError(() => adapter.verify(plan.profile));\n if (!projection.ok) {\n throw new AiClientConfigurationError('client_projection_drifted', projection.reason ?? 'Client configuration drifted.', 409);\n }\n const controller = new AbortController();\n await this.verifyGateway({\n endpoint: plan.profile.endpoint,\n gatewayKey: plan.gatewayKey,\n model: plan.profile.model,\n signal: controller.signal,\n });\n return { ...status, status: 'configured', message: `${CLIENT_LABELS[input.client]} verified against Xpod Gateway.` };\n }\n\n public async restore(client: AiClientId, webId?: string): Promise<AiClientConfigurationStatus> {\n const adapter = this.adapterFor(client);\n const owner = webId ?? this.latestPlanFor(client)?.profile.webId;\n if (owner) {\n await this.withTargetLocks(await this.detectLockTargets(adapter), () => mapAdapterError(() => adapter.restore(owner)));\n }\n return this.inspect(client);\n }\n\n private adapterFor(client: AiClientId): AiClientConfigAdapter {\n requireSupportedClient(client);\n if (client === 'codex') return new CodexConfigAdapter({ homeDir: this.homeDir });\n if (client === 'claude-code') return new ClaudeCodeConfigAdapter({ homeDir: this.homeDir });\n if (client === 'pi') return new PiConfigAdapter({ homeDir: this.homeDir });\n return new CodeBuddyConfigAdapter({ homeDir: this.homeDir });\n }\n\n private async publicTargets(writes: ConfigWrite[]): Promise<PlannedTarget[]> {\n const targets: PlannedTarget[] = [];\n for (const write of writes.filter((candidate) => !isStateWrite(candidate))) {\n if (!isPathInside(this.homeDir, path.resolve(write.path))) {\n throw new AiClientConfigurationError('unsafe_config_target', 'Configuration target is outside the owner home directory.', 400);\n }\n const before = await readOptional(write.path);\n targets.push({\n filePath: write.path,\n displayPath: displayPath(this.homeDir, write.path),\n beforeHash: hash(before ?? ''),\n beforeExists: before !== undefined,\n beforeContent: before ?? '',\n plannedContentWithoutSecret: write.content ?? '',\n action: write.content === null ? 'delete' : before === undefined ? 'createOrUpdate' : 'update',\n });\n }\n return targets;\n }\n\n private async detectLockTargets(adapter: AiClientConfigAdapter): Promise<string[]> {\n const detection = await mapAdapterError(() => adapter.detect());\n return detection.configPaths;\n }\n\n private requirePlan(client: AiClientId, planId: string): StoredPlan {\n const plan = this.plans.get(planId);\n if (!plan || plan.client !== client) {\n throw new AiClientConfigurationError('plan_not_found', 'Configuration plan was not found.', 404);\n }\n return plan;\n }\n\n private latestPlanFor(client: AiClientId): StoredPlan | undefined {\n return [...this.plans.values()].reverse().find((plan) => plan.client === client);\n }\n\n private async withTargetLocks<T>(targets: string[], action: () => Promise<T>): Promise<T> {\n const sorted = [...new Set(targets.map((target) => path.resolve(target)))].sort();\n const previous = Promise.all(sorted.map((target) => this.locks.get(target))).then(() => undefined);\n let release!: () => void;\n const current = previous.then(() => new Promise<void>((resolve) => { release = resolve; }));\n for (const target of sorted) {\n this.locks.set(target, current);\n }\n await previous;\n try {\n return await action();\n } finally {\n release();\n for (const target of sorted) {\n if (this.locks.get(target) === current) {\n this.locks.delete(target);\n }\n }\n }\n }\n}\n\nfunction publicPlan(plan: StoredPlan, homeDir: string): AiClientConfigurationPlan {\n return {\n planId: plan.planId,\n client: plan.client,\n changes: plan.targets.map((target) => ({\n target: target.displayPath,\n action: target.action,\n backup: target.beforeExists,\n current: redactSecretText(target.beforeContent),\n replacement: redactSecretText(target.plannedContentWithoutSecret),\n })),\n conflicts: [],\n backupLocation: displayPath(homeDir, plan.backupDir),\n replacementConfirmationRequired: isReplacementSensitive(plan.client),\n ...(plan.confirmation ? {\n confirmation: {\n required: true,\n token: plan.confirmation.token,\n targetHash: plan.confirmation.targetHash,\n message: 'This client may replace the active default model. Re-enter the confirmation token before applying.',\n },\n } : {}),\n };\n}\n\nasync function mapAdapterError<T>(action: () => Promise<T>): Promise<T> {\n try {\n return await action();\n } catch (error) {\n if (error instanceof AiClientConfigurationError) throw error;\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('symbolic link') || message.includes('outside the owner home') || message.includes('not a regular file')) {\n throw new AiClientConfigurationError('unsafe_config_target', 'Configuration target is unsafe.', 400);\n }\n if (message.includes('invalid JSON') || message.includes('root must be a JSON object')) {\n throw new AiClientConfigurationError('invalid_config', 'Configuration file must contain a JSON object.', 400);\n }\n throw error;\n }\n}\n\nfunction requireSupportedClient(client: AiClientId): AiClientId {\n if (client === 'codex' || client === 'claude-code' || client === 'pi' || client === 'codebuddy') {\n return client;\n }\n throw new AiClientConfigurationError('unsupported_client', 'Unsupported AI client.', 404);\n}\n\nfunction isReplacementSensitive(client: AiClientId): boolean {\n return client === 'pi';\n}\n\nfunction isStateWrite(write: ConfigWrite): boolean {\n return path.basename(write.path).startsWith('.xpod-ai-connection-');\n}\n\nasync function readOptional(filePath: string): Promise<string | undefined> {\n try {\n return await fs.readFile(filePath, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined;\n throw error;\n }\n}\n\nfunction createDefaultGatewayVerifier(fetchImpl: typeof fetch, timeoutMs: number): NonNullable<AiClientConfigurationServiceOptions['verifyGateway']> {\n return async ({ endpoint, gatewayKey, model, signal }) => {\n const timeout = AbortSignal.timeout(timeoutMs);\n const linked = mergeSignals(signal, timeout);\n const base = endpoint.replace(/\\/+$/u, '');\n await checkedGatewayFetch(fetchImpl, `${base}/v1/models`, {\n method: 'GET',\n headers: { accept: 'application/json', authorization: `Bearer ${gatewayKey}` },\n signal: linked,\n });\n await checkedGatewayFetch(fetchImpl, `${base}/v1/responses`, {\n method: 'POST',\n headers: {\n accept: 'application/json',\n 'content-type': 'application/json',\n authorization: `Bearer ${gatewayKey}`,\n },\n body: JSON.stringify({\n model: model ?? 'xpod/default',\n input: 'ping',\n max_output_tokens: 1,\n }),\n signal: linked,\n });\n };\n}\n\nasync function checkedGatewayFetch(fetchImpl: typeof fetch, url: string, init: RequestInit): Promise<void> {\n const response = await fetchImpl(url, init);\n if (!response.ok) {\n await response.arrayBuffer();\n throw new Error(`Gateway verification failed: ${response.status}`);\n }\n await response.arrayBuffer();\n}\n\nfunction mergeSignals(a: AbortSignal, b: AbortSignal): AbortSignal {\n if (a.aborted) return a;\n if (b.aborted) return b;\n const controller = new AbortController();\n const abort = () => controller.abort();\n a.addEventListener('abort', abort, { once: true });\n b.addEventListener('abort', abort, { once: true });\n return controller.signal;\n}\n\nfunction normalizeEndpoint(endpoint: string): string {\n try {\n const parsed = new URL(endpoint);\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new Error('bad protocol');\n }\n return parsed.toString().replace(/\\/+$/u, '');\n } catch {\n throw new AiClientConfigurationError('invalid_endpoint', 'Endpoint must be an HTTP(S) URL.', 400);\n }\n}\n\nfunction timestampForPath(date: Date): string {\n return date.toISOString().replace(/[:.]/gu, '-');\n}\n\nfunction displayPath(homeDir: string, filePath: string): string {\n const relative = path.relative(homeDir, filePath);\n return relative.startsWith('..') ? filePath : `~/${relative}`;\n}\n\nfunction isPathInside(root: string, target: string): boolean {\n const relative = path.relative(root, target);\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\nfunction hash(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nexport function redactSecretText(input: string): string {\n return input\n .replace(/\\/(?:Users|var|tmp|private|home)\\/[^\\s\"',)]+/gu, '[path]')\n .replace(/xpod_[A-Za-z0-9._-]+/gu, '[redacted]')\n .replace(/sk-[A-Za-z0-9._-]+/gu, '[redacted]')\n .replace(/Bearer\\s+[A-Za-z0-9._-]+/giu, 'Bearer [redacted]');\n}\n\nexport function unavailableAiClientConfigurationCapability(): AiClientConfigurationCapabilityDescriptor {\n return {\n available: false,\n manualInstructions: MANUAL_INSTRUCTIONS,\n };\n}\n"]}
1
+ {"version":3,"file":"AiClientConfigurationService.js","sourceRoot":"","sources":["../../../src/api/service/AiClientConfigurationService.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from 'node:crypto';\nimport path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport {\n CodexConfigAdapter,\n ClaudeCodeConfigAdapter,\n CodeBuddyConfigAdapter,\n PiConfigAdapter,\n type AiClientConfigAdapter,\n AiClientConfigPlan,\n AiConnectionClientProfile,\n ConfigWrite,\n} from '@undefineds.co/ai-connection/client-config';\n\nexport type AiClientId = 'codex' | 'claude-code' | 'pi' | 'codebuddy';\n\nexport interface AiClientConfigurationCapabilityDescriptor {\n available: boolean;\n authority?: 'local-filesystem';\n manualInstructions: string;\n}\n\nexport interface AiClientConfigurationStatus {\n status: 'notConfigured' | 'configured' | 'drifted' | 'unavailable' | 'unverifiable' | 'failedAndRestored';\n message?: string;\n installed?: boolean;\n configExists?: boolean;\n}\n\nexport interface AiClientConfigurationPlan {\n planId: string;\n client: AiClientId;\n changes: AiClientConfigurationChange[];\n conflicts: string[];\n backupLocation: string;\n replacementConfirmationRequired: boolean;\n confirmation?: {\n required: boolean;\n token: string;\n targetHash: string;\n message?: string;\n };\n}\n\nexport interface AiClientConfigurationChange {\n target: string;\n action: 'update' | 'createOrUpdate' | 'delete';\n backup: boolean;\n current?: string;\n replacement?: string;\n}\n\nexport interface AiClientConfigurationServiceOptions {\n homeDir?: string;\n backupRoot?: string;\n now?: () => Date;\n verifyGateway?: (input: {\n endpoint: string;\n apiKey: string;\n model?: string;\n signal: AbortSignal;\n }) => Promise<unknown>;\n fetch?: typeof fetch;\n verificationTimeoutMs?: number;\n}\n\nexport interface PlanInput {\n client: AiClientId;\n endpoint: string;\n model?: string;\n webId?: string;\n}\n\nexport interface ApplyInput {\n client: AiClientId;\n planId: string;\n apiKey: string;\n webId?: string;\n confirmation?: {\n token: string;\n targetHash: string;\n };\n}\n\nexport interface VerifyInput {\n client: AiClientId;\n planId?: string;\n}\n\ninterface StoredPlan {\n planId: string;\n client: AiClientId;\n profile: AiConnectionClientProfile;\n nativePlan: AiClientConfigPlan;\n targets: PlannedTarget[];\n backupDir: string;\n apiKey?: string;\n confirmation?: {\n token: string;\n targetHash: string;\n };\n}\n\ninterface PlannedTarget {\n filePath: string;\n displayPath: string;\n beforeHash: string;\n beforeExists: boolean;\n beforeContent: string;\n plannedContentWithoutSecret: string;\n action: 'update' | 'createOrUpdate' | 'delete';\n}\n\nconst PLAN_SECRET_PLACEHOLDER = '[redacted]';\nconst MANUAL_INSTRUCTIONS = 'Manual client setup is available when this host cannot safely write local coding-client files.';\n\nconst CLIENT_LABELS: Record<AiClientId, string> = {\n codex: 'Codex',\n 'claude-code': 'Claude Code',\n pi: 'Pi',\n codebuddy: 'CodeBuddy',\n};\n\nexport class AiClientConfigurationError extends Error {\n public readonly statusCode: number;\n public readonly code: string;\n public readonly details?: unknown;\n\n public constructor(code: string, message: string, statusCode: number, details?: unknown) {\n super(message);\n this.code = code;\n this.statusCode = statusCode;\n this.details = details;\n }\n}\n\nexport class AiClientConfigurationService {\n private readonly homeDir: string;\n private readonly backupRoot: string;\n private readonly now: () => Date;\n private readonly verifyGateway: NonNullable<AiClientConfigurationServiceOptions['verifyGateway']>;\n private readonly plans = new Map<string, StoredPlan>();\n private readonly locks = new Map<string, Promise<void>>();\n\n public constructor(options: AiClientConfigurationServiceOptions = {}) {\n this.homeDir = path.resolve(options.homeDir ?? process.env.HOME ?? process.cwd());\n this.backupRoot = path.resolve(options.backupRoot ?? path.join(this.homeDir, '.xpod/client-config-backups'));\n this.now = options.now ?? (() => new Date());\n this.verifyGateway = options.verifyGateway ?? createDefaultGatewayVerifier(\n options.fetch ?? fetch,\n options.verificationTimeoutMs ?? 8_000,\n );\n }\n\n public capability(): AiClientConfigurationCapabilityDescriptor {\n return {\n available: true,\n authority: 'local-filesystem',\n manualInstructions: MANUAL_INSTRUCTIONS,\n };\n }\n\n public async inspect(client: AiClientId): Promise<AiClientConfigurationStatus> {\n const adapter = this.adapterFor(client);\n const detection = await mapAdapterError(() => adapter.detect());\n const inspection = await mapAdapterError(() => adapter.inspect());\n const configured = inspection.ownership === 'owned';\n return {\n status: configured ? 'configured' : 'notConfigured',\n installed: detection.installed,\n configExists: detection.configExists,\n message: configured\n ? `${CLIENT_LABELS[client]} is configured for Xpod.`\n : `${CLIENT_LABELS[client]} is not configured for Xpod.`,\n };\n }\n\n public async plan(input: PlanInput): Promise<AiClientConfigurationPlan> {\n const client = requireSupportedClient(input.client);\n const profile = {\n endpoint: normalizeEndpoint(input.endpoint),\n apiKey: PLAN_SECRET_PLACEHOLDER,\n webId: input.webId ?? 'https://xpod.local/.well-known/ai-client-configuration#owner',\n model: input.model,\n };\n const adapter = this.adapterFor(client);\n const nativePlan = await mapAdapterError(() => adapter.plan(profile));\n const targets = await this.publicTargets(nativePlan.writes);\n const beforeHash = hash(targets.map((target) => `${target.filePath}:${target.beforeHash}`).join('\\n'));\n const plan: StoredPlan = {\n planId: `aicfg_${randomUUID().replace(/-/gu, '')}`,\n client,\n profile,\n nativePlan,\n targets,\n backupDir: path.join(this.backupRoot, client, timestampForPath(this.now())),\n ...(isReplacementSensitive(client) ? {\n confirmation: {\n token: `confirm-${client}-${beforeHash.slice(0, 12)}`,\n targetHash: beforeHash,\n },\n } : {}),\n };\n this.plans.set(plan.planId, plan);\n return publicPlan(plan, this.homeDir);\n }\n\n public async apply(input: ApplyInput): Promise<{ applied: true }> {\n const plan = this.requirePlan(input.client, input.planId);\n if (!input.apiKey?.startsWith('sk-')) {\n throw new AiClientConfigurationError('invalid_api_key', 'CSS client credentials API key is required.', 400);\n }\n if (plan.confirmation) {\n if (!input.confirmation?.token) {\n throw new AiClientConfigurationError('confirmation_required', 'Replacement confirmation is required.', 409);\n }\n if (input.confirmation.token !== plan.confirmation.token ||\n input.confirmation.targetHash !== plan.confirmation.targetHash) {\n throw new AiClientConfigurationError('confirmation_stale', 'Replacement confirmation is stale.', 409);\n }\n }\n\n return this.withTargetLocks(plan.nativePlan.writes.map((write) => write.path), async () => {\n for (const target of plan.targets) {\n const current = await readOptional(target.filePath);\n if (hash(current ?? '') !== target.beforeHash) {\n throw new AiClientConfigurationError('configuration_conflict', 'Configuration changed after planning.', 409);\n }\n }\n\n const profile = {\n ...plan.profile,\n apiKey: input.apiKey,\n webId: input.webId ?? plan.profile.webId,\n };\n const adapter = this.adapterFor(plan.client);\n const nativePlan = await mapAdapterError(() => adapter.plan(profile));\n await mapAdapterError(() => adapter.apply(nativePlan));\n plan.apiKey = input.apiKey;\n plan.profile = profile;\n plan.nativePlan = nativePlan;\n\n try {\n await this.verify({ client: plan.client, planId: plan.planId });\n } catch {\n await mapAdapterError(() => adapter.restore(profile.webId));\n throw new AiClientConfigurationError(\n 'verification_failed_restored',\n 'Gateway verification failed.',\n 502,\n { restored: true },\n );\n }\n return { applied: true };\n });\n }\n\n public async verify(input: VerifyInput): Promise<AiClientConfigurationStatus> {\n const plan = input.planId ? this.requirePlan(input.client, input.planId) : undefined;\n const status = await this.inspect(input.client);\n if (status.status !== 'configured') {\n return status;\n }\n if (!plan?.apiKey) {\n return {\n ...status,\n status: 'unverifiable',\n message: 'API key is not recoverable after restart; re-apply the client configuration to verify it.',\n };\n }\n const adapter = this.adapterFor(input.client);\n const projection = await mapAdapterError(() => adapter.verify(plan.profile));\n if (!projection.ok) {\n throw new AiClientConfigurationError('client_projection_drifted', projection.reason ?? 'Client configuration drifted.', 409);\n }\n const controller = new AbortController();\n await this.verifyGateway({\n endpoint: plan.profile.endpoint,\n apiKey: plan.apiKey,\n model: plan.profile.model,\n signal: controller.signal,\n });\n return { ...status, status: 'configured', message: `${CLIENT_LABELS[input.client]} verified against Xpod Gateway.` };\n }\n\n public async restore(client: AiClientId, webId?: string): Promise<AiClientConfigurationStatus> {\n const adapter = this.adapterFor(client);\n const owner = webId ?? this.latestPlanFor(client)?.profile.webId;\n if (owner) {\n await this.withTargetLocks(await this.detectLockTargets(adapter), () => mapAdapterError(() => adapter.restore(owner)));\n }\n return this.inspect(client);\n }\n\n private adapterFor(client: AiClientId): AiClientConfigAdapter {\n requireSupportedClient(client);\n if (client === 'codex') return new CodexConfigAdapter({ homeDir: this.homeDir });\n if (client === 'claude-code') return new ClaudeCodeConfigAdapter({ homeDir: this.homeDir });\n if (client === 'pi') return new PiConfigAdapter({ homeDir: this.homeDir });\n return new CodeBuddyConfigAdapter({ homeDir: this.homeDir });\n }\n\n private async publicTargets(writes: ConfigWrite[]): Promise<PlannedTarget[]> {\n const targets: PlannedTarget[] = [];\n for (const write of writes.filter((candidate) => !isStateWrite(candidate))) {\n if (!isPathInside(this.homeDir, path.resolve(write.path))) {\n throw new AiClientConfigurationError('unsafe_config_target', 'Configuration target is outside the owner home directory.', 400);\n }\n const before = await readOptional(write.path);\n targets.push({\n filePath: write.path,\n displayPath: displayPath(this.homeDir, write.path),\n beforeHash: hash(before ?? ''),\n beforeExists: before !== undefined,\n beforeContent: before ?? '',\n plannedContentWithoutSecret: write.content ?? '',\n action: write.content === null ? 'delete' : before === undefined ? 'createOrUpdate' : 'update',\n });\n }\n return targets;\n }\n\n private async detectLockTargets(adapter: AiClientConfigAdapter): Promise<string[]> {\n const detection = await mapAdapterError(() => adapter.detect());\n return detection.configPaths;\n }\n\n private requirePlan(client: AiClientId, planId: string): StoredPlan {\n const plan = this.plans.get(planId);\n if (!plan || plan.client !== client) {\n throw new AiClientConfigurationError('plan_not_found', 'Configuration plan was not found.', 404);\n }\n return plan;\n }\n\n private latestPlanFor(client: AiClientId): StoredPlan | undefined {\n return [...this.plans.values()].reverse().find((plan) => plan.client === client);\n }\n\n private async withTargetLocks<T>(targets: string[], action: () => Promise<T>): Promise<T> {\n const sorted = [...new Set(targets.map((target) => path.resolve(target)))].sort();\n const previous = Promise.all(sorted.map((target) => this.locks.get(target))).then(() => undefined);\n let release!: () => void;\n const current = previous.then(() => new Promise<void>((resolve) => { release = resolve; }));\n for (const target of sorted) {\n this.locks.set(target, current);\n }\n await previous;\n try {\n return await action();\n } finally {\n release();\n for (const target of sorted) {\n if (this.locks.get(target) === current) {\n this.locks.delete(target);\n }\n }\n }\n }\n}\n\nfunction publicPlan(plan: StoredPlan, homeDir: string): AiClientConfigurationPlan {\n return {\n planId: plan.planId,\n client: plan.client,\n changes: plan.targets.map((target) => ({\n target: target.displayPath,\n action: target.action,\n backup: target.beforeExists,\n current: redactSecretText(target.beforeContent),\n replacement: redactSecretText(target.plannedContentWithoutSecret),\n })),\n conflicts: [],\n backupLocation: displayPath(homeDir, plan.backupDir),\n replacementConfirmationRequired: isReplacementSensitive(plan.client),\n ...(plan.confirmation ? {\n confirmation: {\n required: true,\n token: plan.confirmation.token,\n targetHash: plan.confirmation.targetHash,\n message: 'This client may replace the active default model. Re-enter the confirmation token before applying.',\n },\n } : {}),\n };\n}\n\nasync function mapAdapterError<T>(action: () => Promise<T>): Promise<T> {\n try {\n return await action();\n } catch (error) {\n if (error instanceof AiClientConfigurationError) throw error;\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('symbolic link') || message.includes('outside the owner home') || message.includes('not a regular file')) {\n throw new AiClientConfigurationError('unsafe_config_target', 'Configuration target is unsafe.', 400);\n }\n if (message.includes('invalid JSON') || message.includes('root must be a JSON object')) {\n throw new AiClientConfigurationError('invalid_config', 'Configuration file must contain a JSON object.', 400);\n }\n throw error;\n }\n}\n\nfunction requireSupportedClient(client: AiClientId): AiClientId {\n if (client === 'codex' || client === 'claude-code' || client === 'pi' || client === 'codebuddy') {\n return client;\n }\n throw new AiClientConfigurationError('unsupported_client', 'Unsupported AI client.', 404);\n}\n\nfunction isReplacementSensitive(client: AiClientId): boolean {\n return client === 'pi';\n}\n\nfunction isStateWrite(write: ConfigWrite): boolean {\n return path.basename(write.path).startsWith('.xpod-ai-connection-');\n}\n\nasync function readOptional(filePath: string): Promise<string | undefined> {\n try {\n return await fs.readFile(filePath, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined;\n throw error;\n }\n}\n\nfunction createDefaultGatewayVerifier(fetchImpl: typeof fetch, timeoutMs: number): NonNullable<AiClientConfigurationServiceOptions['verifyGateway']> {\n return async ({ endpoint, apiKey, model, signal }) => {\n const timeout = AbortSignal.timeout(timeoutMs);\n const linked = mergeSignals(signal, timeout);\n const base = endpoint.replace(/\\/+$/u, '');\n await checkedGatewayFetch(fetchImpl, `${base}/v1/models`, {\n method: 'GET',\n headers: { accept: 'application/json', authorization: `Bearer ${apiKey}` },\n signal: linked,\n });\n await checkedGatewayFetch(fetchImpl, `${base}/v1/responses`, {\n method: 'POST',\n headers: {\n accept: 'application/json',\n 'content-type': 'application/json',\n authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: model ?? 'xpod/default',\n input: 'ping',\n max_output_tokens: 1,\n }),\n signal: linked,\n });\n };\n}\n\nasync function checkedGatewayFetch(fetchImpl: typeof fetch, url: string, init: RequestInit): Promise<void> {\n const response = await fetchImpl(url, init);\n if (!response.ok) {\n await response.arrayBuffer();\n throw new Error(`Gateway verification failed: ${response.status}`);\n }\n await response.arrayBuffer();\n}\n\nfunction mergeSignals(a: AbortSignal, b: AbortSignal): AbortSignal {\n if (a.aborted) return a;\n if (b.aborted) return b;\n const controller = new AbortController();\n const abort = () => controller.abort();\n a.addEventListener('abort', abort, { once: true });\n b.addEventListener('abort', abort, { once: true });\n return controller.signal;\n}\n\nfunction normalizeEndpoint(endpoint: string): string {\n try {\n const parsed = new URL(endpoint);\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new Error('bad protocol');\n }\n return parsed.toString().replace(/\\/+$/u, '');\n } catch {\n throw new AiClientConfigurationError('invalid_endpoint', 'Endpoint must be an HTTP(S) URL.', 400);\n }\n}\n\nfunction timestampForPath(date: Date): string {\n return date.toISOString().replace(/[:.]/gu, '-');\n}\n\nfunction displayPath(homeDir: string, filePath: string): string {\n const relative = path.relative(homeDir, filePath);\n return relative.startsWith('..') ? filePath : `~/${relative}`;\n}\n\nfunction isPathInside(root: string, target: string): boolean {\n const relative = path.relative(root, target);\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\nfunction hash(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nexport function redactSecretText(input: string): string {\n return input\n .replace(/\\/(?:Users|var|tmp|private|home)\\/[^\\s\"',)]+/gu, '[path]')\n .replace(/xpod_[A-Za-z0-9._-]+/gu, '[redacted]')\n .replace(/sk-[A-Za-z0-9._-]+/gu, '[redacted]')\n .replace(/Bearer\\s+[A-Za-z0-9._-]+/giu, 'Bearer [redacted]');\n}\n\nexport function unavailableAiClientConfigurationCapability(): AiClientConfigurationCapabilityDescriptor {\n return {\n available: false,\n manualInstructions: MANUAL_INSTRUCTIONS,\n };\n}\n"]}
@@ -8,6 +8,7 @@ export declare const XPOD_TASK_EVENT = "xpod/task.event";
8
8
  export declare const XPOD_TASK_MATERIALIZE_DUE_FUNCTION_ID = "xpod-task-materialize-due-runs";
9
9
  export declare const XPOD_TASK_EVENT_FUNCTION_ID = "xpod-task-event";
10
10
  export interface XpodTaskMaterializeDueEventData {
11
+ source: string;
11
12
  requestId?: string;
12
13
  now?: number;
13
14
  limit?: number;
@@ -15,9 +16,10 @@ export interface XpodTaskMaterializeDueEventData {
15
16
  webId?: string;
16
17
  }
17
18
  export type XpodTaskMaterializeDueEvent = EventPayload<XpodTaskMaterializeDueEventData> & {
18
- name: typeof XPOD_TASK_MATERIALIZE_DUE_EVENT;
19
+ name: string;
19
20
  };
20
21
  export interface XpodTaskEventData {
22
+ source: string;
21
23
  requestId?: string;
22
24
  authBindingId?: string;
23
25
  webId?: string;
@@ -25,7 +27,7 @@ export interface XpodTaskEventData {
25
27
  payload?: Record<string, unknown>;
26
28
  }
27
29
  export type XpodTaskEvent = EventPayload<XpodTaskEventData> & {
28
- name: typeof XPOD_TASK_EVENT;
30
+ name: string;
29
31
  };
30
32
  export interface InngestTaskSchedulerOptions<TContext = StoreContext> {
31
33
  backend: InngestRunExecutionBackend;
@@ -41,7 +43,7 @@ export declare class InngestTaskScheduler<TContext = StoreContext> {
41
43
  readonly materializeDueRunsFunction: import("inngest").InngestFunction<import("inngest").InngestFunction.Options<[{
42
44
  readonly cron: "*/1 * * * *";
43
45
  }, {
44
- readonly event: "xpod/task.materialize_due";
46
+ readonly event: string;
45
47
  }], import("inngest").HandlerWithTriggers<{
46
48
  sendEvent: (idOrOptions: import("inngest/types").StepOptionsOrId, payload: import("inngest").SendEventPayload) => Promise<import("inngest/types").SendEventOutput<import("inngest").ClientOptionsFromInngest<import("inngest").Inngest<import("inngest/types").ClientOptions>>>>;
47
49
  waitForSignal: <TData>(idOrOptions: import("inngest/types").StepOptionsOrId, opts: {
@@ -130,7 +132,7 @@ export declare class InngestTaskScheduler<TContext = StoreContext> {
130
132
  }, [{
131
133
  readonly cron: "*/1 * * * *";
132
134
  }, {
133
- readonly event: "xpod/task.materialize_due";
135
+ readonly event: string;
134
136
  }], Omit<Omit<import("inngest/types").BaseContext<import("inngest").Inngest.Any>, never> & Record<never, never> & {
135
137
  logger: import("inngest").Logger;
136
138
  }, "group" | "requestId" | "event" | "attempt" | "events" | "runId" | "step" | "defer" | "jobId" | "maxAttempts"> & import("inngest/types").FailureEventArgs<EventPayload<any>> & {
@@ -308,7 +310,7 @@ export declare class InngestTaskScheduler<TContext = StoreContext> {
308
310
  }, [{
309
311
  readonly cron: "*/1 * * * *";
310
312
  }, {
311
- readonly event: "xpod/task.materialize_due";
313
+ readonly event: string;
312
314
  }], Omit<Omit<import("inngest/types").BaseContext<import("inngest").Inngest.Any>, never> & Record<never, never> & {
313
315
  logger: import("inngest").Logger;
314
316
  }, "group" | "requestId" | "event" | "attempt" | "events" | "runId" | "step" | "defer" | "jobId" | "maxAttempts"> & import("inngest/types").FailureEventArgs<EventPayload<any>> & {
@@ -401,10 +403,10 @@ export declare class InngestTaskScheduler<TContext = StoreContext> {
401
403
  }>, import("inngest").Inngest<import("inngest/types").ClientOptions>, [{
402
404
  readonly cron: "*/1 * * * *";
403
405
  }, {
404
- readonly event: "xpod/task.materialize_due";
406
+ readonly event: string;
405
407
  }]>;
406
408
  readonly eventTaskFunction: import("inngest").InngestFunction<import("inngest").InngestFunction.Options<[{
407
- readonly event: "xpod/task.event";
409
+ readonly event: string;
408
410
  }], import("inngest").HandlerWithTriggers<{
409
411
  sendEvent: (idOrOptions: import("inngest/types").StepOptionsOrId, payload: import("inngest").SendEventPayload) => Promise<import("inngest/types").SendEventOutput<import("inngest").ClientOptionsFromInngest<import("inngest").Inngest<import("inngest/types").ClientOptions>>>>;
410
412
  waitForSignal: <TData>(idOrOptions: import("inngest/types").StepOptionsOrId, opts: {
@@ -491,7 +493,7 @@ export declare class InngestTaskScheduler<TContext = StoreContext> {
491
493
  }) => import("inngest/types").InvocationResult<import("inngest/types").Jsonify<import("inngest").GetFunctionOutputRaw<TFunction>>>;
492
494
  fetch: import("inngest").StepFetch;
493
495
  }, [{
494
- readonly event: "xpod/task.event";
496
+ readonly event: string;
495
497
  }], Omit<Omit<import("inngest/types").BaseContext<import("inngest").Inngest.Any>, never> & Record<never, never> & {
496
498
  logger: import("inngest").Logger;
497
499
  }, "group" | "requestId" | "event" | "attempt" | "events" | "runId" | "step" | "defer" | "jobId" | "maxAttempts"> & import("inngest/types").FailureEventArgs<EventPayload<any>> & {
@@ -667,7 +669,7 @@ export declare class InngestTaskScheduler<TContext = StoreContext> {
667
669
  }) => import("inngest/types").InvocationResult<import("inngest/types").Jsonify<import("inngest").GetFunctionOutputRaw<TFunction>>>;
668
670
  fetch: import("inngest").StepFetch;
669
671
  }, [{
670
- readonly event: "xpod/task.event";
672
+ readonly event: string;
671
673
  }], Omit<Omit<import("inngest/types").BaseContext<import("inngest").Inngest.Any>, never> & Record<never, never> & {
672
674
  logger: import("inngest").Logger;
673
675
  }, "group" | "requestId" | "event" | "attempt" | "events" | "runId" | "step" | "defer" | "jobId" | "maxAttempts"> & import("inngest/types").FailureEventArgs<EventPayload<any>> & {
@@ -758,7 +760,7 @@ export declare class InngestTaskScheduler<TContext = StoreContext> {
758
760
  fetch: import("inngest").StepFetch;
759
761
  };
760
762
  }>, import("inngest").Inngest<import("inngest/types").ClientOptions>, [{
761
- readonly event: "xpod/task.event";
763
+ readonly event: string;
762
764
  }]>;
763
765
  private readonly taskService;
764
766
  private readonly getContext;
@@ -770,6 +772,9 @@ export declare class InngestTaskScheduler<TContext = StoreContext> {
770
772
  private readonly pendingDueTasks;
771
773
  private readonly pendingTaskEvents;
772
774
  private readonly client;
775
+ private readonly source;
776
+ private readonly materializeDueEventName;
777
+ private readonly taskEventName;
773
778
  constructor(options: InngestTaskSchedulerOptions<TContext>);
774
779
  getFunctions(): unknown[];
775
780
  materializeDueTasks(context: TContext, options?: {
@@ -786,6 +791,7 @@ export declare class InngestTaskScheduler<TContext = StoreContext> {
786
791
  private createInlineDueContext;
787
792
  private createInlineEventContext;
788
793
  private resolveDueContexts;
794
+ private sourceRequestId;
789
795
  private resolveSingleContext;
790
796
  private contextEventData;
791
797
  }
@@ -18,33 +18,39 @@ class InngestTaskScheduler {
18
18
  this.durableDelivery = options.durableDelivery ?? true;
19
19
  this.executeInline = options.executeInline ?? true;
20
20
  this.client = options.backend.getClient();
21
+ this.source = options.backend.getSource();
22
+ const identitySuffix = this.source === 'production' ? '' : `-${this.source}`;
23
+ const eventPath = this.source === 'production' ? 'xpod' : `xpod/${this.source}`;
24
+ this.materializeDueEventName = `${eventPath}/task.materialize_due`;
25
+ this.taskEventName = `${eventPath}/task.event`;
21
26
  this.materializeDueRunsFunction = this.client.createFunction({
22
- id: exports.XPOD_TASK_MATERIALIZE_DUE_FUNCTION_ID,
23
- name: 'Xpod Task Materialize Due Runs',
27
+ id: `${exports.XPOD_TASK_MATERIALIZE_DUE_FUNCTION_ID}${identitySuffix}`,
28
+ name: this.source === 'production' ? 'Xpod Task Materialize Due Runs' : `Xpod Task Materialize Due Runs (${this.source})`,
24
29
  triggers: [
25
30
  { cron: '*/1 * * * *' },
26
- { event: exports.XPOD_TASK_MATERIALIZE_DUE_EVENT },
31
+ { event: this.materializeDueEventName },
27
32
  ],
28
33
  }, (ctx) => this.handleDueTasks(ctx));
29
34
  this.eventTaskFunction = this.client.createFunction({
30
- id: exports.XPOD_TASK_EVENT_FUNCTION_ID,
31
- name: 'Xpod Task Event',
32
- triggers: [{ event: exports.XPOD_TASK_EVENT }],
35
+ id: `${exports.XPOD_TASK_EVENT_FUNCTION_ID}${identitySuffix}`,
36
+ name: this.source === 'production' ? 'Xpod Task Event' : `Xpod Task Event (${this.source})`,
37
+ triggers: [{ event: this.taskEventName }],
33
38
  }, (ctx) => this.handleTaskEvent(ctx));
34
39
  }
35
40
  getFunctions() {
36
41
  return [this.materializeDueRunsFunction, this.eventTaskFunction];
37
42
  }
38
43
  async materializeDueTasks(context, options = {}) {
39
- const requestId = (0, types_1.generateId)('task-due');
44
+ const requestId = this.sourceRequestId((0, types_1.generateId)('task-due'));
40
45
  this.recordContext?.(context);
41
46
  this.pendingDueTasks.set(requestId, { context, ...options });
42
47
  try {
43
48
  if (this.durableDelivery) {
44
49
  await this.client.send({
45
50
  id: requestId,
46
- name: exports.XPOD_TASK_MATERIALIZE_DUE_EVENT,
51
+ name: this.materializeDueEventName,
47
52
  data: {
53
+ source: this.source,
48
54
  requestId,
49
55
  now: options.now,
50
56
  limit: options.limit,
@@ -63,15 +69,16 @@ class InngestTaskScheduler {
63
69
  }
64
70
  }
65
71
  async materializeEventTasks(input) {
66
- const requestId = (0, types_1.generateId)('task-event');
72
+ const requestId = this.sourceRequestId((0, types_1.generateId)('task-event'));
67
73
  this.recordContext?.(input.context);
68
74
  this.pendingTaskEvents.set(requestId, input);
69
75
  try {
70
76
  if (this.durableDelivery) {
71
77
  await this.client.send({
72
78
  id: requestId,
73
- name: exports.XPOD_TASK_EVENT,
79
+ name: this.taskEventName,
74
80
  data: {
81
+ source: this.source,
75
82
  requestId,
76
83
  ...this.contextEventData(input.context),
77
84
  eventName: input.eventName,
@@ -143,8 +150,9 @@ class InngestTaskScheduler {
143
150
  return {
144
151
  event: {
145
152
  id: requestId,
146
- name: exports.XPOD_TASK_MATERIALIZE_DUE_EVENT,
153
+ name: this.materializeDueEventName,
147
154
  data: {
155
+ source: this.source,
148
156
  requestId,
149
157
  now: options.now,
150
158
  limit: options.limit,
@@ -161,8 +169,9 @@ class InngestTaskScheduler {
161
169
  return {
162
170
  event: {
163
171
  id: requestId,
164
- name: exports.XPOD_TASK_EVENT,
172
+ name: this.taskEventName,
165
173
  data: {
174
+ source: this.source,
166
175
  requestId,
167
176
  ...(pending ? this.contextEventData(pending.context) : {}),
168
177
  eventName: input.eventName,
@@ -188,6 +197,9 @@ class InngestTaskScheduler {
188
197
  const fallback = this.getContext();
189
198
  return fallback ? [fallback] : [];
190
199
  }
200
+ sourceRequestId(requestId) {
201
+ return this.source === 'production' ? requestId : `${this.source}:${requestId}`;
202
+ }
191
203
  async resolveSingleContext(eventData) {
192
204
  const resolved = eventData ? await this.resolveContext?.(eventData) : undefined;
193
205
  return resolved ?? this.getContext();
@@ -1 +1 @@
1
- {"version":3,"file":"InngestTaskScheduler.js","sourceRoot":"","sources":["../../../src/api/tasks/InngestTaskScheduler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { EventPayload } from 'inngest/types';\nimport type { InngestRunExecutionBackend } from '../runs/InngestRunExecutionBackend';\nimport type { StoreContext } from '../chatkit/store';\nimport { generateId } from '../chatkit/types';\nimport type { TaskService } from './TaskService';\nimport type { MaterializedTaskRun } from './TaskMaterializer';\n\nexport const XPOD_TASK_MATERIALIZE_DUE_EVENT = 'xpod/task.materialize_due';\nexport const XPOD_TASK_EVENT = 'xpod/task.event';\nexport const XPOD_TASK_MATERIALIZE_DUE_FUNCTION_ID = 'xpod-task-materialize-due-runs';\nexport const XPOD_TASK_EVENT_FUNCTION_ID = 'xpod-task-event';\n\nexport interface XpodTaskMaterializeDueEventData {\n requestId?: string;\n now?: number;\n limit?: number;\n authBindingId?: string;\n webId?: string;\n}\n\nexport type XpodTaskMaterializeDueEvent = EventPayload<XpodTaskMaterializeDueEventData> & {\n name: typeof XPOD_TASK_MATERIALIZE_DUE_EVENT;\n};\n\nexport interface XpodTaskEventData {\n requestId?: string;\n authBindingId?: string;\n webId?: string;\n eventName: string;\n payload?: Record<string, unknown>;\n}\n\nexport type XpodTaskEvent = EventPayload<XpodTaskEventData> & {\n name: typeof XPOD_TASK_EVENT;\n};\n\nexport interface InngestTaskSchedulerOptions<TContext = StoreContext> {\n backend: InngestRunExecutionBackend;\n taskService: TaskService<TContext>;\n getContext?: () => TContext | undefined;\n getContexts?: () => Iterable<TContext> | Promise<Iterable<TContext>>;\n resolveContext?: (\n data: Partial<XpodTaskMaterializeDueEventData & XpodTaskEventData>,\n ) => TContext | Promise<TContext | undefined> | undefined;\n recordContext?: (context: TContext | undefined) => void;\n durableDelivery?: boolean;\n executeInline?: boolean;\n}\n\ntype InngestTaskEventContext = {\n event: XpodTaskEvent;\n step: {\n run<T>(id: string, fn: () => Promise<T> | T): Promise<T>;\n };\n};\n\ntype InngestCronContext = {\n event?: XpodTaskMaterializeDueEvent;\n step: {\n run<T>(id: string, fn: () => Promise<T> | T): Promise<T>;\n };\n};\n\nexport class InngestTaskScheduler<TContext = StoreContext> {\n public readonly materializeDueRunsFunction;\n public readonly eventTaskFunction;\n\n private readonly taskService: TaskService<TContext>;\n private readonly getContext: () => TContext | undefined;\n private readonly getContexts?: () => Iterable<TContext> | Promise<Iterable<TContext>>;\n private readonly resolveContext?: InngestTaskSchedulerOptions<TContext>['resolveContext'];\n private readonly recordContext?: InngestTaskSchedulerOptions<TContext>['recordContext'];\n private readonly durableDelivery: boolean;\n private readonly executeInline: boolean;\n private readonly pendingDueTasks = new Map<string, { context: TContext; now?: number; limit?: number }>();\n private readonly pendingTaskEvents = new Map<string, { context: TContext; eventName: string; payload?: Record<string, unknown> }>();\n private readonly client: ReturnType<InngestRunExecutionBackend['getClient']>;\n\n public constructor(options: InngestTaskSchedulerOptions<TContext>) {\n this.taskService = options.taskService;\n this.getContext = options.getContext ?? (() => undefined);\n this.getContexts = options.getContexts;\n this.resolveContext = options.resolveContext;\n this.recordContext = options.recordContext;\n this.durableDelivery = options.durableDelivery ?? true;\n this.executeInline = options.executeInline ?? true;\n this.client = options.backend.getClient();\n\n this.materializeDueRunsFunction = this.client.createFunction(\n {\n id: XPOD_TASK_MATERIALIZE_DUE_FUNCTION_ID,\n name: 'Xpod Task Materialize Due Runs',\n triggers: [\n { cron: '*/1 * * * *' },\n { event: XPOD_TASK_MATERIALIZE_DUE_EVENT },\n ],\n },\n (ctx: any) => this.handleDueTasks(ctx as InngestCronContext),\n );\n\n this.eventTaskFunction = this.client.createFunction(\n {\n id: XPOD_TASK_EVENT_FUNCTION_ID,\n name: 'Xpod Task Event',\n triggers: [{ event: XPOD_TASK_EVENT }],\n },\n (ctx: any) => this.handleTaskEvent(ctx as InngestTaskEventContext),\n );\n }\n\n public getFunctions(): unknown[] {\n return [this.materializeDueRunsFunction, this.eventTaskFunction];\n }\n\n public async materializeDueTasks(\n context: TContext,\n options: { now?: number; limit?: number } = {},\n ): Promise<MaterializedTaskRun[]> {\n const requestId = generateId('task-due');\n this.recordContext?.(context);\n this.pendingDueTasks.set(requestId, { context, ...options });\n try {\n if (this.durableDelivery) {\n await this.client.send({\n id: requestId,\n name: XPOD_TASK_MATERIALIZE_DUE_EVENT,\n data: {\n requestId,\n now: options.now,\n limit: options.limit,\n ...this.contextEventData(context),\n },\n });\n }\n if (!this.executeInline) {\n return [];\n }\n return this.handleDueTasks(this.createInlineDueContext(requestId, options));\n } catch (error) {\n this.pendingDueTasks.delete(requestId);\n throw error;\n }\n }\n\n public async materializeEventTasks(input: {\n eventName: string;\n payload?: Record<string, unknown>;\n context: TContext;\n }): Promise<MaterializedTaskRun[]> {\n const requestId = generateId('task-event');\n this.recordContext?.(input.context);\n this.pendingTaskEvents.set(requestId, input);\n try {\n if (this.durableDelivery) {\n await this.client.send({\n id: requestId,\n name: XPOD_TASK_EVENT,\n data: {\n requestId,\n ...this.contextEventData(input.context),\n eventName: input.eventName,\n payload: input.payload,\n },\n });\n }\n if (!this.executeInline) {\n return [];\n }\n return this.handleTaskEvent(this.createInlineEventContext(requestId, input));\n } catch (error) {\n this.pendingTaskEvents.delete(requestId);\n throw error;\n }\n }\n\n private async handleDueTasks(ctx: InngestCronContext): Promise<MaterializedTaskRun[]> {\n const requestId = ctx.event?.data?.requestId;\n const pending = requestId ? this.pendingDueTasks.get(requestId) : undefined;\n const contexts = await this.resolveDueContexts(pending?.context, ctx.event?.data);\n if (contexts.length === 0) {\n return [];\n }\n try {\n return await ctx.step.run('materialize-due-tasks', async () => {\n const runs: MaterializedTaskRun[] = [];\n for (const context of contexts) {\n runs.push(...await this.taskService.materializeDueTasks(context, {\n now: pending?.now ?? ctx.event?.data?.now,\n limit: pending?.limit ?? ctx.event?.data?.limit,\n }));\n }\n return runs;\n });\n } finally {\n if (requestId) {\n this.pendingDueTasks.delete(requestId);\n }\n }\n }\n\n private async handleTaskEvent(ctx: InngestTaskEventContext): Promise<MaterializedTaskRun[]> {\n const requestId = ctx.event.data?.requestId;\n const pending = requestId ? this.pendingTaskEvents.get(requestId) : undefined;\n const eventName = pending?.eventName ?? ctx.event.data?.eventName;\n if (!eventName) {\n return [];\n }\n const context = pending?.context ?? await this.resolveSingleContext(ctx.event.data);\n if (!context) {\n return [];\n }\n try {\n return await ctx.step.run('materialize-event-tasks', async () => this.taskService.materializeEventTasks({\n eventName,\n payload: pending?.payload ?? ctx.event.data?.payload,\n context,\n }));\n } finally {\n if (requestId) {\n this.pendingTaskEvents.delete(requestId);\n }\n }\n }\n\n private createInlineDueContext(requestId: string, options: { now?: number; limit?: number }): InngestCronContext {\n const pending = this.pendingDueTasks.get(requestId);\n return {\n event: {\n id: requestId,\n name: XPOD_TASK_MATERIALIZE_DUE_EVENT,\n data: {\n requestId,\n now: options.now,\n limit: options.limit,\n ...(pending ? this.contextEventData(pending.context) : {}),\n },\n },\n step: {\n run: async <T>(_id: string, fn: () => Promise<T> | T): Promise<T> => fn(),\n },\n };\n }\n\n private createInlineEventContext(\n requestId: string,\n input: {\n eventName: string;\n payload?: Record<string, unknown>;\n },\n ): InngestTaskEventContext {\n const pending = this.pendingTaskEvents.get(requestId);\n return {\n event: {\n id: requestId,\n name: XPOD_TASK_EVENT,\n data: {\n requestId,\n ...(pending ? this.contextEventData(pending.context) : {}),\n eventName: input.eventName,\n payload: input.payload,\n },\n },\n step: {\n run: async <T>(_id: string, fn: () => Promise<T> | T): Promise<T> => fn(),\n },\n };\n }\n\n private async resolveDueContexts(\n pendingContext: TContext | undefined,\n eventData: XpodTaskMaterializeDueEventData | undefined,\n ): Promise<TContext[]> {\n if (pendingContext) {\n return [pendingContext];\n }\n const eventContext = await this.resolveSingleContext(eventData);\n if (eventContext) {\n return [eventContext];\n }\n if (this.getContexts) {\n return Array.from(await this.getContexts());\n }\n const fallback = this.getContext();\n return fallback ? [fallback] : [];\n }\n\n private async resolveSingleContext(\n eventData: Partial<XpodTaskMaterializeDueEventData & XpodTaskEventData> | undefined,\n ): Promise<TContext | undefined> {\n const resolved = eventData ? await this.resolveContext?.(eventData) : undefined;\n return resolved ?? this.getContext();\n }\n\n private contextEventData(context: TContext): Partial<XpodTaskMaterializeDueEventData & XpodTaskEventData> {\n const auth = (context as Record<string, unknown>).auth as { type?: unknown; webId?: unknown } | undefined;\n const data: Partial<XpodTaskMaterializeDueEventData & XpodTaskEventData> = {};\n const authBindingId = (context as Record<string, unknown>).authBindingId;\n if (typeof authBindingId === 'string' && authBindingId.length > 0) {\n data.authBindingId = authBindingId;\n }\n if (auth?.type === 'solid' && typeof auth.webId === 'string') {\n data.webId = auth.webId;\n }\n return data;\n }\n}\n"]}
1
+ {"version":3,"file":"InngestTaskScheduler.js","sourceRoot":"","sources":["../../../src/api/tasks/InngestTaskScheduler.ts"],"names":[],"mappings":";;;AAGA,4CAA8C;AAIjC,QAAA,+BAA+B,GAAG,2BAA2B,CAAC;AAC9D,QAAA,eAAe,GAAG,iBAAiB,CAAC;AACpC,QAAA,qCAAqC,GAAG,gCAAgC,CAAC;AACzE,QAAA,2BAA2B,GAAG,iBAAiB,CAAC;AAuD7D,MAAa,oBAAoB;IAkB/B,YAAmB,OAA8C;QAPhD,oBAAe,GAAG,IAAI,GAAG,EAA+D,CAAC;QACzF,sBAAiB,GAAG,IAAI,GAAG,EAAuF,CAAC;QAOlI,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,IAAI,CAAC;QACvD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC;QACnD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7E,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QAChF,IAAI,CAAC,uBAAuB,GAAG,GAAG,SAAS,uBAAuB,CAAC;QACnE,IAAI,CAAC,aAAa,GAAG,GAAG,SAAS,aAAa,CAAC;QAE/C,IAAI,CAAC,0BAA0B,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAC1D;YACE,EAAE,EAAE,GAAG,6CAAqC,GAAG,cAAc,EAAE;YAC/D,IAAI,EAAE,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,mCAAmC,IAAI,CAAC,MAAM,GAAG;YACzH,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,aAAa,EAAE;gBACvB,EAAE,KAAK,EAAE,IAAI,CAAC,uBAAuB,EAAE;aACxC;SACF,EACD,CAAC,GAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,GAAyB,CAAC,CAC7D,CAAC;QAEF,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CACjD;YACE,EAAE,EAAE,GAAG,mCAA2B,GAAG,cAAc,EAAE;YACrD,IAAI,EAAE,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,oBAAoB,IAAI,CAAC,MAAM,GAAG;YAC3F,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC;SAC1C,EACD,CAAC,GAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,GAA8B,CAAC,CACnE,CAAC;IACJ,CAAC;IAEM,YAAY;QACjB,OAAO,CAAC,IAAI,CAAC,0BAA0B,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACnE,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAC9B,OAAiB,EACjB,UAA4C,EAAE;QAE9C,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,IAAA,kBAAU,EAAC,UAAU,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,CAAC;QAC9B,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzB,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;oBACrB,EAAE,EAAE,SAAS;oBACb,IAAI,EAAE,IAAI,CAAC,uBAAuB;oBAClC,IAAI,EAAE;wBACJ,MAAM,EAAE,IAAI,CAAC,MAAM;wBACnB,SAAS;wBACT,GAAG,EAAE,OAAO,CAAC,GAAG;wBAChB,KAAK,EAAE,OAAO,CAAC,KAAK;wBACpB,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;qBAClC;iBACF,CAAC,CAAC;YACL,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACxB,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,sBAAsB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACvC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,qBAAqB,CAAC,KAIlC;QACC,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,IAAA,kBAAU,EAAC,YAAY,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7C,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzB,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;oBACrB,EAAE,EAAE,SAAS;oBACb,IAAI,EAAE,IAAI,CAAC,aAAa;oBACxB,IAAI,EAAE;wBACJ,MAAM,EAAE,IAAI,CAAC,MAAM;wBACnB,SAAS;wBACT,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC;wBACvC,SAAS,EAAE,KAAK,CAAC,SAAS;wBAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;qBACvB;iBACF,CAAC,CAAC;YACL,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACxB,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,wBAAwB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;QAC/E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACzC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,GAAuB;QAClD,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC;QAC7C,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAClF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,CAAC;YACH,OAAO,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;gBAC5D,MAAM,IAAI,GAA0B,EAAE,CAAC;gBACvC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,OAAO,EAAE;wBAC/D,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG;wBACzC,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK;qBAChD,CAAC,CAAC,CAAC;gBACN,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,IAAI,SAAS,EAAE,CAAC;gBACd,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,GAA4B;QACxD,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;QAC5C,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9E,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;QAClE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,MAAM,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,CAAC;YACH,OAAO,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,qBAAqB,CAAC;gBACtG,SAAS;gBACT,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO;gBACpD,OAAO;aACR,CAAC,CAAC,CAAC;QACN,CAAC;gBAAS,CAAC;YACT,IAAI,SAAS,EAAE,CAAC;gBACd,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;IAEO,sBAAsB,CAAC,SAAiB,EAAE,OAAyC;QACzF,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACpD,OAAO;YACL,KAAK,EAAE;gBACL,EAAE,EAAE,SAAS;gBACb,IAAI,EAAE,IAAI,CAAC,uBAAuB;gBAClC,IAAI,EAAE;oBACJ,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,SAAS;oBACT,GAAG,EAAE,OAAO,CAAC,GAAG;oBAChB,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC3D;aACF;YACD,IAAI,EAAE;gBACJ,GAAG,EAAE,KAAK,EAAK,GAAW,EAAE,EAAwB,EAAc,EAAE,CAAC,EAAE,EAAE;aAC1E;SACF,CAAC;IACJ,CAAC;IAEO,wBAAwB,CAC9B,SAAiB,EACjB,KAGC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACtD,OAAO;YACL,KAAK,EAAE;gBACL,EAAE,EAAE,SAAS;gBACb,IAAI,EAAE,IAAI,CAAC,aAAa;gBACxB,IAAI,EAAE;oBACJ,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,SAAS;oBACT,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC1D,SAAS,EAAE,KAAK,CAAC,SAAS;oBAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;iBACvB;aACF;YACD,IAAI,EAAE;gBACJ,GAAG,EAAE,KAAK,EAAK,GAAW,EAAE,EAAwB,EAAc,EAAE,CAAC,EAAE,EAAE;aAC1E;SACF,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAC9B,cAAoC,EACpC,SAAsD;QAEtD,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,CAAC,cAAc,CAAC,CAAC;QAC1B,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QAChE,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,YAAY,CAAC,CAAC;QACxB,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QACnC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpC,CAAC;IAEO,eAAe,CAAC,SAAiB;QACvC,OAAO,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;IAClF,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAChC,SAAmF;QAEnF,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChF,OAAO,QAAQ,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;IACvC,CAAC;IAEO,gBAAgB,CAAC,OAAiB;QACxC,MAAM,IAAI,GAAI,OAAmC,CAAC,IAAuD,CAAC;QAC1G,MAAM,IAAI,GAAiE,EAAE,CAAC;QAC9E,MAAM,aAAa,GAAI,OAAmC,CAAC,aAAa,CAAC;QACzE,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClE,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACrC,CAAC;QACD,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC7D,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAlQD,oDAkQC","sourcesContent":["import type { EventPayload } from 'inngest/types';\nimport type { InngestRunExecutionBackend } from '../runs/InngestRunExecutionBackend';\nimport type { StoreContext } from '../chatkit/store';\nimport { generateId } from '../chatkit/types';\nimport type { TaskService } from './TaskService';\nimport type { MaterializedTaskRun } from './TaskMaterializer';\n\nexport const XPOD_TASK_MATERIALIZE_DUE_EVENT = 'xpod/task.materialize_due';\nexport const XPOD_TASK_EVENT = 'xpod/task.event';\nexport const XPOD_TASK_MATERIALIZE_DUE_FUNCTION_ID = 'xpod-task-materialize-due-runs';\nexport const XPOD_TASK_EVENT_FUNCTION_ID = 'xpod-task-event';\n\nexport interface XpodTaskMaterializeDueEventData {\n source: string;\n requestId?: string;\n now?: number;\n limit?: number;\n authBindingId?: string;\n webId?: string;\n}\n\nexport type XpodTaskMaterializeDueEvent = EventPayload<XpodTaskMaterializeDueEventData> & {\n name: string;\n};\n\nexport interface XpodTaskEventData {\n source: string;\n requestId?: string;\n authBindingId?: string;\n webId?: string;\n eventName: string;\n payload?: Record<string, unknown>;\n}\n\nexport type XpodTaskEvent = EventPayload<XpodTaskEventData> & {\n name: string;\n};\n\nexport interface InngestTaskSchedulerOptions<TContext = StoreContext> {\n backend: InngestRunExecutionBackend;\n taskService: TaskService<TContext>;\n getContext?: () => TContext | undefined;\n getContexts?: () => Iterable<TContext> | Promise<Iterable<TContext>>;\n resolveContext?: (\n data: Partial<XpodTaskMaterializeDueEventData & XpodTaskEventData>,\n ) => TContext | Promise<TContext | undefined> | undefined;\n recordContext?: (context: TContext | undefined) => void;\n durableDelivery?: boolean;\n executeInline?: boolean;\n}\n\ntype InngestTaskEventContext = {\n event: XpodTaskEvent;\n step: {\n run<T>(id: string, fn: () => Promise<T> | T): Promise<T>;\n };\n};\n\ntype InngestCronContext = {\n event?: XpodTaskMaterializeDueEvent;\n step: {\n run<T>(id: string, fn: () => Promise<T> | T): Promise<T>;\n };\n};\n\nexport class InngestTaskScheduler<TContext = StoreContext> {\n public readonly materializeDueRunsFunction;\n public readonly eventTaskFunction;\n\n private readonly taskService: TaskService<TContext>;\n private readonly getContext: () => TContext | undefined;\n private readonly getContexts?: () => Iterable<TContext> | Promise<Iterable<TContext>>;\n private readonly resolveContext?: InngestTaskSchedulerOptions<TContext>['resolveContext'];\n private readonly recordContext?: InngestTaskSchedulerOptions<TContext>['recordContext'];\n private readonly durableDelivery: boolean;\n private readonly executeInline: boolean;\n private readonly pendingDueTasks = new Map<string, { context: TContext; now?: number; limit?: number }>();\n private readonly pendingTaskEvents = new Map<string, { context: TContext; eventName: string; payload?: Record<string, unknown> }>();\n private readonly client: ReturnType<InngestRunExecutionBackend['getClient']>;\n private readonly source: string;\n private readonly materializeDueEventName: string;\n private readonly taskEventName: string;\n\n public constructor(options: InngestTaskSchedulerOptions<TContext>) {\n this.taskService = options.taskService;\n this.getContext = options.getContext ?? (() => undefined);\n this.getContexts = options.getContexts;\n this.resolveContext = options.resolveContext;\n this.recordContext = options.recordContext;\n this.durableDelivery = options.durableDelivery ?? true;\n this.executeInline = options.executeInline ?? true;\n this.client = options.backend.getClient();\n this.source = options.backend.getSource();\n const identitySuffix = this.source === 'production' ? '' : `-${this.source}`;\n const eventPath = this.source === 'production' ? 'xpod' : `xpod/${this.source}`;\n this.materializeDueEventName = `${eventPath}/task.materialize_due`;\n this.taskEventName = `${eventPath}/task.event`;\n\n this.materializeDueRunsFunction = this.client.createFunction(\n {\n id: `${XPOD_TASK_MATERIALIZE_DUE_FUNCTION_ID}${identitySuffix}`,\n name: this.source === 'production' ? 'Xpod Task Materialize Due Runs' : `Xpod Task Materialize Due Runs (${this.source})`,\n triggers: [\n { cron: '*/1 * * * *' },\n { event: this.materializeDueEventName },\n ],\n },\n (ctx: any) => this.handleDueTasks(ctx as InngestCronContext),\n );\n\n this.eventTaskFunction = this.client.createFunction(\n {\n id: `${XPOD_TASK_EVENT_FUNCTION_ID}${identitySuffix}`,\n name: this.source === 'production' ? 'Xpod Task Event' : `Xpod Task Event (${this.source})`,\n triggers: [{ event: this.taskEventName }],\n },\n (ctx: any) => this.handleTaskEvent(ctx as InngestTaskEventContext),\n );\n }\n\n public getFunctions(): unknown[] {\n return [this.materializeDueRunsFunction, this.eventTaskFunction];\n }\n\n public async materializeDueTasks(\n context: TContext,\n options: { now?: number; limit?: number } = {},\n ): Promise<MaterializedTaskRun[]> {\n const requestId = this.sourceRequestId(generateId('task-due'));\n this.recordContext?.(context);\n this.pendingDueTasks.set(requestId, { context, ...options });\n try {\n if (this.durableDelivery) {\n await this.client.send({\n id: requestId,\n name: this.materializeDueEventName,\n data: {\n source: this.source,\n requestId,\n now: options.now,\n limit: options.limit,\n ...this.contextEventData(context),\n },\n });\n }\n if (!this.executeInline) {\n return [];\n }\n return this.handleDueTasks(this.createInlineDueContext(requestId, options));\n } catch (error) {\n this.pendingDueTasks.delete(requestId);\n throw error;\n }\n }\n\n public async materializeEventTasks(input: {\n eventName: string;\n payload?: Record<string, unknown>;\n context: TContext;\n }): Promise<MaterializedTaskRun[]> {\n const requestId = this.sourceRequestId(generateId('task-event'));\n this.recordContext?.(input.context);\n this.pendingTaskEvents.set(requestId, input);\n try {\n if (this.durableDelivery) {\n await this.client.send({\n id: requestId,\n name: this.taskEventName,\n data: {\n source: this.source,\n requestId,\n ...this.contextEventData(input.context),\n eventName: input.eventName,\n payload: input.payload,\n },\n });\n }\n if (!this.executeInline) {\n return [];\n }\n return this.handleTaskEvent(this.createInlineEventContext(requestId, input));\n } catch (error) {\n this.pendingTaskEvents.delete(requestId);\n throw error;\n }\n }\n\n private async handleDueTasks(ctx: InngestCronContext): Promise<MaterializedTaskRun[]> {\n const requestId = ctx.event?.data?.requestId;\n const pending = requestId ? this.pendingDueTasks.get(requestId) : undefined;\n const contexts = await this.resolveDueContexts(pending?.context, ctx.event?.data);\n if (contexts.length === 0) {\n return [];\n }\n try {\n return await ctx.step.run('materialize-due-tasks', async () => {\n const runs: MaterializedTaskRun[] = [];\n for (const context of contexts) {\n runs.push(...await this.taskService.materializeDueTasks(context, {\n now: pending?.now ?? ctx.event?.data?.now,\n limit: pending?.limit ?? ctx.event?.data?.limit,\n }));\n }\n return runs;\n });\n } finally {\n if (requestId) {\n this.pendingDueTasks.delete(requestId);\n }\n }\n }\n\n private async handleTaskEvent(ctx: InngestTaskEventContext): Promise<MaterializedTaskRun[]> {\n const requestId = ctx.event.data?.requestId;\n const pending = requestId ? this.pendingTaskEvents.get(requestId) : undefined;\n const eventName = pending?.eventName ?? ctx.event.data?.eventName;\n if (!eventName) {\n return [];\n }\n const context = pending?.context ?? await this.resolveSingleContext(ctx.event.data);\n if (!context) {\n return [];\n }\n try {\n return await ctx.step.run('materialize-event-tasks', async () => this.taskService.materializeEventTasks({\n eventName,\n payload: pending?.payload ?? ctx.event.data?.payload,\n context,\n }));\n } finally {\n if (requestId) {\n this.pendingTaskEvents.delete(requestId);\n }\n }\n }\n\n private createInlineDueContext(requestId: string, options: { now?: number; limit?: number }): InngestCronContext {\n const pending = this.pendingDueTasks.get(requestId);\n return {\n event: {\n id: requestId,\n name: this.materializeDueEventName,\n data: {\n source: this.source,\n requestId,\n now: options.now,\n limit: options.limit,\n ...(pending ? this.contextEventData(pending.context) : {}),\n },\n },\n step: {\n run: async <T>(_id: string, fn: () => Promise<T> | T): Promise<T> => fn(),\n },\n };\n }\n\n private createInlineEventContext(\n requestId: string,\n input: {\n eventName: string;\n payload?: Record<string, unknown>;\n },\n ): InngestTaskEventContext {\n const pending = this.pendingTaskEvents.get(requestId);\n return {\n event: {\n id: requestId,\n name: this.taskEventName,\n data: {\n source: this.source,\n requestId,\n ...(pending ? this.contextEventData(pending.context) : {}),\n eventName: input.eventName,\n payload: input.payload,\n },\n },\n step: {\n run: async <T>(_id: string, fn: () => Promise<T> | T): Promise<T> => fn(),\n },\n };\n }\n\n private async resolveDueContexts(\n pendingContext: TContext | undefined,\n eventData: XpodTaskMaterializeDueEventData | undefined,\n ): Promise<TContext[]> {\n if (pendingContext) {\n return [pendingContext];\n }\n const eventContext = await this.resolveSingleContext(eventData);\n if (eventContext) {\n return [eventContext];\n }\n if (this.getContexts) {\n return Array.from(await this.getContexts());\n }\n const fallback = this.getContext();\n return fallback ? [fallback] : [];\n }\n\n private sourceRequestId(requestId: string): string {\n return this.source === 'production' ? requestId : `${this.source}:${requestId}`;\n }\n\n private async resolveSingleContext(\n eventData: Partial<XpodTaskMaterializeDueEventData & XpodTaskEventData> | undefined,\n ): Promise<TContext | undefined> {\n const resolved = eventData ? await this.resolveContext?.(eventData) : undefined;\n return resolved ?? this.getContext();\n }\n\n private contextEventData(context: TContext): Partial<XpodTaskMaterializeDueEventData & XpodTaskEventData> {\n const auth = (context as Record<string, unknown>).auth as { type?: unknown; webId?: unknown } | undefined;\n const data: Partial<XpodTaskMaterializeDueEventData & XpodTaskEventData> = {};\n const authBindingId = (context as Record<string, unknown>).authBindingId;\n if (typeof authBindingId === 'string' && authBindingId.length > 0) {\n data.authBindingId = authBindingId;\n }\n if (auth?.type === 'solid' && typeof auth.webId === 'string') {\n data.webId = auth.webId;\n }\n return data;\n }\n}\n"]}
@@ -124,13 +124,6 @@ exports.startCommand = {
124
124
  baseUrl,
125
125
  externalOidcIssuer,
126
126
  });
127
- supervisor.register({
128
- name: 'css',
129
- command: childJsRuntime,
130
- args: cssArgs,
131
- cwd: cssRuntimeConfig.cwd,
132
- env: (0, css_process_1.buildCssChildEnv)(baseUrl, cssPort, externalOidcIssuer, authMode),
133
- });
134
127
  const isDevMode = __filename.endsWith('.ts');
135
128
  const apiArgs = isDevMode
136
129
  ? [
@@ -140,6 +133,13 @@ exports.startCommand = {
140
133
  ]
141
134
  : [path_1.default.resolve(__dirname, '..', '..', 'api', 'main.js')];
142
135
  const gatewayAdminProxyAuthSecret = (0, runtime_1.createGatewayAdminProxyAuthSecret)();
136
+ supervisor.register({
137
+ name: 'css',
138
+ command: childJsRuntime,
139
+ args: cssArgs,
140
+ cwd: cssRuntimeConfig.cwd,
141
+ env: (0, css_process_1.buildCssChildEnv)(baseUrl, cssPort, externalOidcIssuer, authMode, process.env, gatewayAdminProxyAuthSecret),
142
+ });
143
143
  supervisor.register({
144
144
  name: 'api',
145
145
  command: childJsRuntime,