@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.
- package/config/cloud.json +3 -0
- package/config/local.json +3 -0
- package/config/resolver.json +7 -0
- package/config/xpod.base.json +20 -0
- package/dist/agents/ClaudeExecutor.js +1 -1
- package/dist/agents/ClaudeExecutor.js.map +1 -1
- package/dist/agents/types.d.ts +5 -5
- package/dist/agents/types.js.map +1 -1
- package/dist/api/ai-gateway/AiGatewayService.d.ts +5 -16
- package/dist/api/ai-gateway/AiGatewayService.js +13 -35
- package/dist/api/ai-gateway/AiGatewayService.js.map +1 -1
- package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.d.ts +3 -2
- package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.js +37 -12
- package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.js.map +1 -1
- package/dist/api/ai-gateway/auth/GatewayPrincipal.d.ts +2 -16
- package/dist/api/ai-gateway/auth/GatewayPrincipal.js +3 -33
- package/dist/api/ai-gateway/auth/GatewayPrincipal.js.map +1 -1
- package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.d.ts +23 -0
- package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.js +81 -0
- package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.js.map +1 -0
- package/dist/api/ai-gateway/auth/InvocationTokenCodec.d.ts +7 -4
- package/dist/api/ai-gateway/auth/InvocationTokenCodec.js.map +1 -1
- package/dist/api/ai-gateway/connect/index.d.ts +7 -26
- package/dist/api/ai-gateway/connect/index.js +40 -67
- package/dist/api/ai-gateway/connect/index.js.map +1 -1
- package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.d.ts +17 -0
- package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.js +65 -0
- package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.js.map +1 -0
- package/dist/api/ai-gateway/pod/HostedPodDataAccess.d.ts +24 -0
- package/dist/api/ai-gateway/pod/HostedPodDataAccess.js +149 -0
- package/dist/api/ai-gateway/pod/HostedPodDataAccess.js.map +1 -0
- package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.d.ts +13 -5
- package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js +16 -19
- package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js.map +1 -1
- package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.d.ts +1 -1
- package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.js +0 -2
- package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.js.map +1 -1
- package/dist/api/auth/AuthContext.d.ts +1 -12
- package/dist/api/auth/AuthContext.js +0 -11
- package/dist/api/auth/AuthContext.js.map +1 -1
- package/dist/api/auth/ClientCredentialsAuthenticator.js +4 -11
- package/dist/api/auth/ClientCredentialsAuthenticator.js.map +1 -1
- package/dist/api/chatkit/default-agent.d.ts +2 -2
- package/dist/api/chatkit/default-agent.js +4 -4
- package/dist/api/chatkit/default-agent.js.map +1 -1
- package/dist/api/chatkit/runtime/AcpAgentRuntime.js +1 -1
- package/dist/api/chatkit/runtime/AcpAgentRuntime.js.map +1 -1
- package/dist/api/container/common.js +28 -69
- package/dist/api/container/common.js.map +1 -1
- package/dist/api/container/index.js +5 -6
- package/dist/api/container/index.js.map +1 -1
- package/dist/api/container/routes.js +2 -5
- package/dist/api/container/routes.js.map +1 -1
- package/dist/api/container/types.d.ts +8 -10
- package/dist/api/container/types.js.map +1 -1
- package/dist/api/handlers/AiClientConfigurationHandler.js +3 -3
- package/dist/api/handlers/AiClientConfigurationHandler.js.map +1 -1
- package/dist/api/handlers/AiGatewayHandler.js +2 -2
- package/dist/api/handlers/AiGatewayHandler.js.map +1 -1
- package/dist/api/handlers/AiGatewayManagementHandler.d.ts +2 -10
- package/dist/api/handlers/AiGatewayManagementHandler.js +4 -154
- package/dist/api/handlers/AiGatewayManagementHandler.js.map +1 -1
- package/dist/api/handlers/NetworkSettingsHandler.js +0 -3
- package/dist/api/handlers/NetworkSettingsHandler.js.map +1 -1
- package/dist/api/handlers/PodSettingsHandler.d.ts +5 -2
- package/dist/api/handlers/PodSettingsHandler.js +3 -3
- package/dist/api/handlers/PodSettingsHandler.js.map +1 -1
- package/dist/api/runs/AgentRuntimeTypes.d.ts +3 -3
- package/dist/api/runs/AgentRuntimeTypes.js +10 -10
- package/dist/api/runs/AgentRuntimeTypes.js.map +1 -1
- package/dist/api/runs/InngestRunExecutionBackend.d.ts +15 -9
- package/dist/api/runs/InngestRunExecutionBackend.js +25 -10
- package/dist/api/runs/InngestRunExecutionBackend.js.map +1 -1
- package/dist/api/runs/PiAgentRuntimeDriver.js +2 -2
- package/dist/api/runs/PiAgentRuntimeDriver.js.map +1 -1
- package/dist/api/runs/RunStateCenter.js +1 -1
- package/dist/api/runs/RunStateCenter.js.map +1 -1
- package/dist/api/service/AiClientConfigurationService.d.ts +2 -2
- package/dist/api/service/AiClientConfigurationService.js +11 -11
- package/dist/api/service/AiClientConfigurationService.js.map +1 -1
- package/dist/api/tasks/InngestTaskScheduler.d.ts +16 -10
- package/dist/api/tasks/InngestTaskScheduler.js +24 -12
- package/dist/api/tasks/InngestTaskScheduler.js.map +1 -1
- package/dist/cli/commands/start.js +7 -7
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/components/components.jsonld +1 -0
- package/dist/components/context.jsonld +36 -0
- package/dist/http/InternalPodDataHttpHandler.d.ts +32 -0
- package/dist/http/InternalPodDataHttpHandler.js +258 -0
- package/dist/http/InternalPodDataHttpHandler.js.map +1 -0
- package/dist/http/InternalPodDataHttpHandler.jsonld +201 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/main.js +13 -13
- package/dist/main.js.map +1 -1
- package/dist/runtime/GatewayAdminProxyAuth.d.ts +15 -1
- package/dist/runtime/GatewayAdminProxyAuth.js +57 -2
- package/dist/runtime/GatewayAdminProxyAuth.js.map +1 -1
- package/dist/runtime/bootstrap.js +3 -0
- package/dist/runtime/bootstrap.js.map +1 -1
- package/dist/runtime/css-process.d.ts +1 -1
- package/dist/runtime/css-process.js +4 -1
- package/dist/runtime/css-process.js.map +1 -1
- package/dist/runtime/runner/node/CommunitySolidServerCssRunner.d.ts +2 -0
- package/dist/runtime/runner/node/CommunitySolidServerCssRunner.js +50 -0
- package/dist/runtime/runner/node/CommunitySolidServerCssRunner.js.map +1 -1
- package/node_modules/@undefineds.co/ai-connection/dist/AiClientConfigurationSection.d.ts +5 -5
- package/node_modules/@undefineds.co/ai-connection/dist/AiClientConfigurationSection.js +7 -7
- package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionMain.js +1 -1
- package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionPanel.d.ts +3 -1
- package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionPanel.js +74 -60
- package/node_modules/@undefineds.co/ai-connection/dist/ai-connection-client.d.ts +0 -21
- package/node_modules/@undefineds.co/ai-connection/dist/ai-connection-client.js +0 -41
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/base-adapter.d.ts +1 -0
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/base-adapter.js +7 -2
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/codex.js +3 -3
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/index.cjs +15 -9
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/json-env-adapter.js +4 -4
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/pi.js +3 -3
- package/node_modules/@undefineds.co/ai-connection/dist/client-config/types.d.ts +1 -1
- package/node_modules/@undefineds.co/ai-connection/dist/controller.d.ts +2 -1
- package/node_modules/@undefineds.co/ai-connection/dist/controller.js +1 -0
- package/node_modules/@undefineds.co/ai-connection/dist/service-access.js +0 -1
- package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +22 -1
- package/package.json +3 -3
- package/static/app/assets/main.js +7 -7
- package/static/dashboard/assets/NetworkPage-CXjiUMR1.js +2 -0
- package/static/dashboard/assets/{PaneListHeader-57nvMwH6.js → PaneListHeader-BSipfl0W.js} +1 -1
- package/static/dashboard/assets/PodPage-Bd3Xhmp-.js +2 -0
- package/static/dashboard/assets/ServicesPage-CI3jWZGe.js +1 -0
- package/static/dashboard/assets/{card-B9Zjf_2p.js → card-z5BV5hTo.js} +1 -1
- package/static/dashboard/assets/{dashboard-8C6o666W.js → dashboard-CSrqAv2L.js} +2 -2
- package/static/dashboard/assets/{database-DPh9wDY9.js → database-Ct5ZPe6L.js} +1 -1
- package/static/dashboard/assets/{external-link-VbMQvVMz.js → external-link-B7wD1hkm.js} +1 -1
- package/static/dashboard/assets/index-tOBaUnM1.js +44 -0
- package/static/dashboard/assets/{refresh-cw-BxVxNxNr.js → refresh-cw-CFDZPaE8.js} +1 -1
- package/static/dashboard/assets/{services-status-context-DKmJ7ISr.js → services-status-context-DN1Icg4A.js} +1 -1
- package/static/dashboard/dashboard.html +1 -1
- package/static/settings/assets/ModelsPage-03NPWzoX.js +1 -0
- package/static/settings/assets/{PaneListHeader-Bgaze006.js → PaneListHeader-DMD8OJef.js} +1 -1
- package/static/settings/assets/PodPage-DT4EMYhL.js +2 -0
- package/static/settings/assets/ServicesPage-CJ0ub6IH.js +1 -0
- package/static/settings/assets/SettingsPage-BkR7ZK18.js +41 -0
- package/static/settings/assets/{card-B_bXSIn-.js → card-Cjsia0_V.js} +1 -1
- package/static/settings/assets/{services-status-context-DiX-AbrP.js → services-status-context-CkuKmH5h.js} +1 -1
- package/static/settings/assets/{settings-B30oMfZq.js → settings-Cyyv6-SD.js} +2 -2
- package/static/settings/assets/{workspace-layout-Dv1Yn9Ci.js → workspace-layout-B47luv6r.js} +1 -1
- package/static/settings/settings.html +1 -1
- package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.d.ts +0 -25
- package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.js +0 -91
- package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.js.map +0 -1
- package/dist/api/ai-gateway/auth/GatewayApiKey.d.ts +0 -28
- package/dist/api/ai-gateway/auth/GatewayApiKey.js +0 -162
- package/dist/api/ai-gateway/auth/GatewayApiKey.js.map +0 -1
- package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.d.ts +0 -56
- package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js +0 -143
- package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js.map +0 -1
- package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.d.ts +0 -26
- package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.js +0 -97
- package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.js.map +0 -1
- package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.d.ts +0 -54
- package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js +0 -152
- package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js.map +0 -1
- package/static/dashboard/assets/NetworkPage-Brt79fuQ.js +0 -2
- package/static/dashboard/assets/PodPage-CM6do1vB.js +0 -2
- package/static/dashboard/assets/ServicesPage-BUNxGJRz.js +0 -1
- package/static/dashboard/assets/index-RfiFckzb.js +0 -51
- package/static/settings/assets/ModelsPage-D_IH7AH3.js +0 -1
- package/static/settings/assets/PodPage-Cy1VNObw.js +0 -2
- package/static/settings/assets/ServicesPage-BsFaxVWC.js +0 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
92
|
-
throw new AiClientConfigurationError('
|
|
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
|
-
|
|
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.
|
|
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?.
|
|
137
|
+
if (!plan?.apiKey) {
|
|
138
138
|
return {
|
|
139
139
|
...status,
|
|
140
140
|
status: 'unverifiable',
|
|
141
|
-
message: '
|
|
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
|
-
|
|
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,
|
|
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 ${
|
|
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 ${
|
|
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":";;;;;;AAsfA,4CAMC;AAED,gGAKC;AAngBD,6CAAqD;AACrD,0DAA6B;AAC7B,qCAAyC;AACzC,8EASoD;AAqGpD,MAAM,uBAAuB,GAAG,YAAY,CAAC;AAC7C,MAAM,mBAAmB,GAAG,gGAAgG,CAAC;AAE7H,MAAM,aAAa,GAA+B;IAChD,KAAK,EAAE,OAAO;IACd,aAAa,EAAE,aAAa;IAC5B,EAAE,EAAE,IAAI;IACR,SAAS,EAAE,WAAW;CACvB,CAAC;AAEF,MAAa,0BAA2B,SAAQ,KAAK;IAKnD,YAAmB,IAAY,EAAE,OAAe,EAAE,UAAkB,EAAE,OAAiB;QACrF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAXD,gEAWC;AAED,MAAa,4BAA4B;IAQvC,YAAmB,UAA+C,EAAE;QAHnD,UAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;QACtC,UAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;QAGxD,IAAI,CAAC,OAAO,GAAG,mBAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAClF,IAAI,CAAC,UAAU,GAAG,mBAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,IAAI,mBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC,CAAC;QAC7G,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,4BAA4B,CACxE,OAAO,CAAC,KAAK,IAAI,KAAK,EACtB,OAAO,CAAC,qBAAqB,IAAI,KAAK,CACvC,CAAC;IACJ,CAAC;IAEM,UAAU;QACf,OAAO;YACL,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,kBAAkB;YAC7B,kBAAkB,EAAE,mBAAmB;SACxC,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,MAAkB;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAChE,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAClE,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,KAAK,OAAO,CAAC;QACpD,OAAO;YACL,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe;YACnD,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,YAAY,EAAE,SAAS,CAAC,YAAY;YACpC,OAAO,EAAE,UAAU;gBACjB,CAAC,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,0BAA0B;gBACpD,CAAC,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,8BAA8B;SAC3D,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,KAAgB;QAChC,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC3C,MAAM,EAAE,uBAAuB;YAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,8DAA8D;YACpF,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACvG,MAAM,IAAI,GAAe;YACvB,MAAM,EAAE,SAAS,IAAA,wBAAU,GAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE;YAClD,MAAM;YACN,OAAO;YACP,UAAU;YACV,OAAO;YACP,SAAS,EAAE,mBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAC3E,GAAG,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBACnC,YAAY,EAAE;oBACZ,KAAK,EAAE,WAAW,MAAM,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;oBACrD,UAAU,EAAE,UAAU;iBACvB;aACF,CAAC,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAClC,OAAO,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,KAAiB;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC1D,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,0BAA0B,CAAC,iBAAiB,EAAE,6CAA6C,EAAE,GAAG,CAAC,CAAC;QAC9G,CAAC;QACD,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC;gBAC/B,MAAM,IAAI,0BAA0B,CAAC,uBAAuB,EAAE,uCAAuC,EAAE,GAAG,CAAC,CAAC;YAC9G,CAAC;YACD,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,KAAK,IAAI,CAAC,YAAY,CAAC,KAAK;gBACtD,KAAK,CAAC,YAAY,CAAC,UAAU,KAAK,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;gBACjE,MAAM,IAAI,0BAA0B,CAAC,oBAAoB,EAAE,oCAAoC,EAAE,GAAG,CAAC,CAAC;YACxG,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE;YACxF,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACpD,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC;oBAC9C,MAAM,IAAI,0BAA0B,CAAC,wBAAwB,EAAE,uCAAuC,EAAE,GAAG,CAAC,CAAC;gBAC/G,CAAC;YACH,CAAC;YAED,MAAM,OAAO,GAAG;gBACd,GAAG,IAAI,CAAC,OAAO;gBACf,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK;aACzC,CAAC;YACF,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7C,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YACtE,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YACvD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;YACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;YAE7B,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YAClE,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC5D,MAAM,IAAI,0BAA0B,CAClC,8BAA8B,EAC9B,8BAA8B,EAC9B,GAAG,EACH,EAAE,QAAQ,EAAE,IAAI,EAAE,CACnB,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,KAAkB;QACpC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACrF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAChD,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;YACnC,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;YAClB,OAAO;gBACL,GAAG,MAAM;gBACT,MAAM,EAAE,cAAc;gBACtB,OAAO,EAAE,2FAA2F;aACrG,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC;YACnB,MAAM,IAAI,0BAA0B,CAAC,2BAA2B,EAAE,UAAU,CAAC,MAAM,IAAI,+BAA+B,EAAE,GAAG,CAAC,CAAC;QAC/H,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,IAAI,CAAC,aAAa,CAAC;YACvB,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;YACzB,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,iCAAiC,EAAE,CAAC;IACvH,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,MAAkB,EAAE,KAAc;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC;QACjE,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzH,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAEO,UAAU,CAAC,MAAkB;QACnC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,MAAM,KAAK,OAAO;YAAE,OAAO,IAAI,kCAAkB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACjF,IAAI,MAAM,KAAK,aAAa;YAAE,OAAO,IAAI,uCAAuB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5F,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,+BAAe,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3E,OAAO,IAAI,sCAAsB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/D,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,MAAqB;QAC/C,MAAM,OAAO,GAAoB,EAAE,CAAC;QACpC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YAC3E,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAC1D,MAAM,IAAI,0BAA0B,CAAC,sBAAsB,EAAE,2DAA2D,EAAE,GAAG,CAAC,CAAC;YACjI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9C,OAAO,CAAC,IAAI,CAAC;gBACX,QAAQ,EAAE,KAAK,CAAC,IAAI;gBACpB,WAAW,EAAE,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC;gBAClD,UAAU,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;gBAC9B,YAAY,EAAE,MAAM,KAAK,SAAS;gBAClC,aAAa,EAAE,MAAM,IAAI,EAAE;gBAC3B,2BAA2B,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE;gBAChD,MAAM,EAAE,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ;aAC/F,CAAC,CAAC;QACL,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,OAA8B;QAC5D,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAChE,OAAO,SAAS,CAAC,WAAW,CAAC;IAC/B,CAAC;IAEO,WAAW,CAAC,MAAkB,EAAE,MAAc;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACpC,MAAM,IAAI,0BAA0B,CAAC,gBAAgB,EAAE,mCAAmC,EAAE,GAAG,CAAC,CAAC;QACnG,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,aAAa,CAAC,MAAkB;QACtC,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACnF,CAAC;IAEO,KAAK,CAAC,eAAe,CAAI,OAAiB,EAAE,MAAwB;QAC1E,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,mBAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAClF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACnG,IAAI,OAAoB,CAAC;QACzB,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5F,KAAK,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,CAAC;QACD,MAAM,QAAQ,CAAC;QACf,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,EAAE,CAAC;QACxB,CAAC;gBAAS,CAAC;YACT,OAAO,EAAE,CAAC;YACV,KAAK,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC;gBAC5B,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,OAAO,EAAE,CAAC;oBACvC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF;AA/ND,oEA+NC;AAED,SAAS,UAAU,CAAC,IAAgB,EAAE,OAAe;IACnD,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACrC,MAAM,EAAE,MAAM,CAAC,WAAW;YAC1B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,YAAY;YAC3B,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,aAAa,CAAC;YAC/C,WAAW,EAAE,gBAAgB,CAAC,MAAM,CAAC,2BAA2B,CAAC;SAClE,CAAC,CAAC;QACH,SAAS,EAAE,EAAE;QACb,cAAc,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;QACpD,+BAA+B,EAAE,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC;QACpE,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;YACtB,YAAY,EAAE;gBACZ,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK;gBAC9B,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,UAAU;gBACxC,OAAO,EAAE,oGAAoG;aAC9G;SACF,CAAC,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,eAAe,CAAI,MAAwB;IACxD,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,EAAE,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,0BAA0B;YAAE,MAAM,KAAK,CAAC;QAC7D,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,IAAI,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;YAC9H,MAAM,IAAI,0BAA0B,CAAC,sBAAsB,EAAE,iCAAiC,EAAE,GAAG,CAAC,CAAC;QACvG,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAC,EAAE,CAAC;YACvF,MAAM,IAAI,0BAA0B,CAAC,gBAAgB,EAAE,gDAAgD,EAAE,GAAG,CAAC,CAAC;QAChH,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,MAAkB;IAChD,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,aAAa,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;QAChG,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,IAAI,0BAA0B,CAAC,oBAAoB,EAAE,wBAAwB,EAAE,GAAG,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,sBAAsB,CAAC,MAAkB;IAChD,OAAO,MAAM,KAAK,IAAI,CAAC;AACzB,CAAC;AAED,SAAS,YAAY,CAAC,KAAkB;IACtC,OAAO,mBAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;AACtE,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC1C,IAAI,CAAC;QACH,OAAO,MAAM,kBAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACzE,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,4BAA4B,CAAC,SAAuB,EAAE,SAAiB;IAC9E,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE;QACnD,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC3C,MAAM,mBAAmB,CAAC,SAAS,EAAE,GAAG,IAAI,YAAY,EAAE;YACxD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE;YAC1E,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;QACH,MAAM,mBAAmB,CAAC,SAAS,EAAE,GAAG,IAAI,eAAe,EAAE;YAC3D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;gBAC1B,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,MAAM,EAAE;aAClC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,KAAK,IAAI,cAAc;gBAC9B,KAAK,EAAE,MAAM;gBACb,iBAAiB,EAAE,CAAC;aACrB,CAAC;YACF,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,SAAuB,EAAE,GAAW,EAAE,IAAiB;IACxF,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,YAAY,CAAC,CAAc,EAAE,CAAc;IAClD,IAAI,CAAC,CAAC,OAAO;QAAE,OAAO,CAAC,CAAC;IACxB,IAAI,CAAC,CAAC,OAAO;QAAE,OAAO,CAAC,CAAC;IACxB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACvC,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,OAAO,UAAU,CAAC,MAAM,CAAC;AAC3B,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,0BAA0B,CAAC,kBAAkB,EAAE,kCAAkC,EAAE,GAAG,CAAC,CAAC;IACpG,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAU;IAClC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,WAAW,CAAC,OAAe,EAAE,QAAgB;IACpD,MAAM,QAAQ,GAAG,mBAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClD,OAAO,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;AAChE,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,MAAc;IAChD,MAAM,QAAQ,GAAG,mBAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7C,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,SAAS,IAAI,CAAC,OAAe;IAC3B,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,SAAgB,gBAAgB,CAAC,KAAa;IAC5C,OAAO,KAAK;SACT,OAAO,CAAC,gDAAgD,EAAE,QAAQ,CAAC;SACnE,OAAO,CAAC,wBAAwB,EAAE,YAAY,CAAC;SAC/C,OAAO,CAAC,sBAAsB,EAAE,YAAY,CAAC;SAC7C,OAAO,CAAC,6BAA6B,EAAE,mBAAmB,CAAC,CAAC;AACjE,CAAC;AAED,SAAgB,0CAA0C;IACxD,OAAO;QACL,SAAS,EAAE,KAAK;QAChB,kBAAkB,EAAE,mBAAmB;KACxC,CAAC;AACJ,CAAC","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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
406
|
+
readonly event: string;
|
|
405
407
|
}]>;
|
|
406
408
|
readonly eventTaskFunction: import("inngest").InngestFunction<import("inngest").InngestFunction.Options<[{
|
|
407
|
-
readonly 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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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":";;;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;AAqD7D,MAAa,oBAAoB;IAe/B,YAAmB,OAA8C;QAJhD,oBAAe,GAAG,IAAI,GAAG,EAA+D,CAAC;QACzF,sBAAiB,GAAG,IAAI,GAAG,EAAuF,CAAC;QAIlI,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;QAE1C,IAAI,CAAC,0BAA0B,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAC1D;YACE,EAAE,EAAE,6CAAqC;YACzC,IAAI,EAAE,gCAAgC;YACtC,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,aAAa,EAAE;gBACvB,EAAE,KAAK,EAAE,uCAA+B,EAAE;aAC3C;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,mCAA2B;YAC/B,IAAI,EAAE,iBAAiB;YACvB,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,uBAAe,EAAE,CAAC;SACvC,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,IAAA,kBAAU,EAAC,UAAU,CAAC,CAAC;QACzC,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,uCAA+B;oBACrC,IAAI,EAAE;wBACJ,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,IAAA,kBAAU,EAAC,YAAY,CAAC,CAAC;QAC3C,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,uBAAe;oBACrB,IAAI,EAAE;wBACJ,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,uCAA+B;gBACrC,IAAI,EAAE;oBACJ,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,uBAAe;gBACrB,IAAI,EAAE;oBACJ,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,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;AAlPD,oDAkPC","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":"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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 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,
|