@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
|
@@ -2,7 +2,8 @@ import { getLoggerFor } from 'global-logger-factory';
|
|
|
2
2
|
import type { ApiServer } from '../ApiServer';
|
|
3
3
|
import type { PodLookupRepository } from '../../identity/drizzle/PodLookupRepository';
|
|
4
4
|
import type { UsageRepository } from '../../storage/quota/UsageRepository';
|
|
5
|
-
import type {
|
|
5
|
+
import type { AuthContext } from '../auth/AuthContext';
|
|
6
|
+
import type { InternalPodAccessTokenProvider } from '../ai-gateway/pod/HostedPodDataAccess';
|
|
6
7
|
export interface PodSettingsStatus {
|
|
7
8
|
identity: {
|
|
8
9
|
webId: string;
|
|
@@ -42,6 +43,7 @@ export interface PodAiConnectionStatusReader {
|
|
|
42
43
|
read(input: {
|
|
43
44
|
webId: string;
|
|
44
45
|
podUrl?: string;
|
|
46
|
+
auth?: AuthContext;
|
|
45
47
|
}): Promise<PodAiConnectionStatus>;
|
|
46
48
|
}
|
|
47
49
|
export interface PodSettingsHandlerOptions {
|
|
@@ -60,9 +62,10 @@ export declare class DrizzlePodAiConnectionStatusReader implements PodAiConnecti
|
|
|
60
62
|
podUrl: string;
|
|
61
63
|
fetch: typeof fetch;
|
|
62
64
|
}) => Promise<AiConnectionStatusDb>);
|
|
63
|
-
read({ webId, podUrl }: {
|
|
65
|
+
read({ webId, podUrl, auth }: {
|
|
64
66
|
webId: string;
|
|
65
67
|
podUrl?: string;
|
|
68
|
+
auth?: AuthContext;
|
|
66
69
|
}): Promise<PodAiConnectionStatus>;
|
|
67
70
|
}
|
|
68
71
|
type AiConnectionStatusDb = {
|
|
@@ -22,7 +22,7 @@ function registerPodSettingsRoutes(server, options) {
|
|
|
22
22
|
const podUrl = pod?.storageUrl ?? pod?.baseUrl;
|
|
23
23
|
const [storage, aiConnection] = await Promise.all([
|
|
24
24
|
readStorageStatus(options.usageRepo, pod),
|
|
25
|
-
aiConnectionStatusReader.read({ webId, podUrl }).catch((error) => {
|
|
25
|
+
aiConnectionStatusReader.read({ webId, podUrl, auth: request.auth }).catch((error) => {
|
|
26
26
|
const reason = safeAiConnectionFailureReason(error);
|
|
27
27
|
logger.warn(`Failed to read Pod AI Connection status: ${reason}`);
|
|
28
28
|
return { status: 'error', reason };
|
|
@@ -77,8 +77,8 @@ class DrizzlePodAiConnectionStatusReader {
|
|
|
77
77
|
this.internalPodAccess = internalPodAccess;
|
|
78
78
|
this.dbFactory = dbFactory;
|
|
79
79
|
}
|
|
80
|
-
async read({ webId, podUrl }) {
|
|
81
|
-
const trustedFetch = await this.internalPodAccess?.getTrustedFetch(webId);
|
|
80
|
+
async read({ webId, podUrl, auth }) {
|
|
81
|
+
const trustedFetch = await this.internalPodAccess?.getTrustedFetch(webId, auth);
|
|
82
82
|
if (!trustedFetch) {
|
|
83
83
|
return { status: 'unsupported', reason: 'not_configured' };
|
|
84
84
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PodSettingsHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/PodSettingsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ServerResponse } from 'node:http';\nimport { drizzle, eq } from '@undefineds.co/drizzle-solid';\nimport {\n credentialResource,\n indexedFileResource,\n type CredentialRow,\n type IndexedFileRow,\n} from '@undefineds.co/models';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { ApiServer } from '../ApiServer';\nimport type { AuthenticatedRequest } from '../middleware/AuthMiddleware';\nimport type { PodLookupRepository, PodLookupResult } from '../../identity/drizzle/PodLookupRepository';\nimport type { UsageRepository, PodUsageRecord } from '../../storage/quota/UsageRepository';\nimport type { InternalPodAccessTokenProvider } from '../ai-gateway/auth/PodGatewayAccessKeyRepository';\n\nexport interface PodSettingsStatus {\n identity: {\n webId: string;\n podUrl?: string;\n };\n storage: PodStorageStatus;\n aiConnection: PodAiConnectionStatus;\n generatedAt: string;\n}\n\nexport type PodStorageStatus =\n | {\n status: 'available';\n usage: {\n storageBytes: number;\n ingressBytes: number;\n egressBytes: number;\n };\n limits: {\n storageLimitBytes: number | null;\n bandwidthLimitBps: number | null;\n };\n source: 'identity_usage';\n }\n | {\n status: 'unsupported' | 'error';\n reason: string;\n };\n\nexport type PodAiConnectionStatus =\n | {\n status: 'available';\n containerUrl?: string;\n configuredProviders: number;\n lastSyncAt?: string;\n source: 'drizzle-solid';\n }\n | {\n status: 'unsupported' | 'error';\n reason: string;\n };\n\nexport interface PodAiConnectionStatusReader {\n read(input: { webId: string; podUrl?: string }): Promise<PodAiConnectionStatus>;\n}\n\nexport interface PodSettingsHandlerOptions {\n podLookupRepository: Pick<PodLookupRepository, 'findByWebId'>;\n usageRepo: Pick<UsageRepository, 'getPodUsage'>;\n aiConnectionStatusReader?: PodAiConnectionStatusReader;\n now?: () => Date;\n logger?: Pick<ReturnType<typeof getLoggerFor>, 'warn' | 'error'>;\n}\n\nexport function registerPodSettingsRoutes(server: ApiServer, options: PodSettingsHandlerOptions): void {\n const logger = options.logger ?? getLoggerFor('PodSettingsHandler');\n const now = options.now ?? (() => new Date());\n const aiConnectionStatusReader = options.aiConnectionStatusReader ?? {\n read: async () => ({ status: 'unsupported', reason: 'not_configured' }) as const,\n };\n\n server.get('/api/pod/settings/status', async (request, response) => {\n if (!request.auth || request.auth.type !== 'solid') {\n sendJson(response, 401, { error: 'Authentication required' });\n return;\n }\n\n const webId = request.auth.webId;\n try {\n const pod = await options.podLookupRepository.findByWebId(webId);\n const podUrl = pod?.storageUrl ?? pod?.baseUrl;\n const [storage, aiConnection] = await Promise.all([\n readStorageStatus(options.usageRepo, pod),\n aiConnectionStatusReader.read({ webId, podUrl }).catch((error: unknown) => {\n const reason = safeAiConnectionFailureReason(error);\n logger.warn(`Failed to read Pod AI Connection status: ${reason}`);\n return { status: 'error', reason } as const;\n }),\n ]);\n\n sendJson(response, 200, {\n identity: {\n webId,\n podUrl,\n },\n storage,\n aiConnection,\n generatedAt: now().toISOString(),\n } satisfies PodSettingsStatus);\n } catch (error) {\n logger.error(`Failed to read Pod settings status: ${safeLogError(error)}`);\n sendJson(response, 500, { error: 'Failed to read Pod settings status' });\n }\n });\n}\n\nasync function readStorageStatus(\n usageRepo: Pick<UsageRepository, 'getPodUsage'>,\n pod: PodLookupResult | undefined,\n): Promise<PodStorageStatus> {\n if (!pod) {\n return { status: 'unsupported', reason: 'pod_not_found' };\n }\n\n let usage: PodUsageRecord | undefined;\n try {\n usage = await usageRepo.getPodUsage(pod.podId);\n } catch {\n return { status: 'error', reason: 'usage_unavailable' };\n }\n\n if (!usage) {\n return { status: 'unsupported', reason: 'usage_not_available' };\n }\n\n return {\n status: 'available',\n usage: {\n storageBytes: usage.storageBytes,\n ingressBytes: usage.ingressBytes,\n egressBytes: usage.egressBytes,\n },\n limits: {\n storageLimitBytes: usage.storageLimitBytes ?? null,\n bandwidthLimitBps: usage.bandwidthLimitBps ?? null,\n },\n source: 'identity_usage',\n };\n}\n\nexport class DrizzlePodAiConnectionStatusReader implements PodAiConnectionStatusReader {\n public constructor(\n private readonly internalPodAccess?: InternalPodAccessTokenProvider,\n private readonly dbFactory: (input: {\n webId: string;\n podUrl: string;\n fetch: typeof fetch;\n }) => Promise<AiConnectionStatusDb> = createAiConnectionStatusDb,\n ) {}\n\n public async read({ webId, podUrl }: { webId: string; podUrl?: string }): Promise<PodAiConnectionStatus> {\n const trustedFetch = await this.internalPodAccess?.getTrustedFetch(webId);\n if (!trustedFetch) {\n return { status: 'unsupported', reason: 'not_configured' };\n }\n if (!podUrl) {\n return { status: 'unsupported', reason: 'pod_not_found' };\n }\n\n try {\n const db = await this.dbFactory({ webId, podUrl, fetch: trustedFetch });\n await db.init?.(credentialResource, indexedFileResource);\n\n const credentialRows = await db.select().from(credentialResource).where(eq(credentialResource.status, 'active')).execute() as CredentialRow[];\n const indexedRows = await db.select().from(indexedFileResource).execute() as IndexedFileRow[];\n const lastSyncAt = latestIso([\n ...credentialRows.map((row) => row.lastUsedAt ?? row.lastRefreshAt),\n ...indexedRows.map((row) => row.indexedAt),\n ]);\n\n return {\n status: 'available',\n containerUrl: new URL('settings/credentials.ttl', podUrl).toString(),\n configuredProviders: credentialRows.length,\n lastSyncAt,\n source: 'drizzle-solid',\n };\n } catch {\n return { status: 'error', reason: 'ai_connection_unavailable' };\n }\n }\n}\n\ntype AiConnectionStatusDb = {\n init?: (...resources: unknown[]) => Promise<void>;\n select(): {\n from(resource: unknown): {\n where(condition: unknown): { execute(): Promise<unknown[]> };\n execute(): Promise<unknown[]>;\n };\n };\n};\n\nfunction createAiConnectionStatusDb(input: {\n webId: string;\n podUrl: string;\n fetch: typeof fetch;\n}): Promise<AiConnectionStatusDb> {\n return Promise.resolve(drizzle({\n fetch: input.fetch,\n info: { webId: input.webId, isLoggedIn: true },\n } as any, {\n podUrl: input.podUrl,\n schema: {\n credential: credentialResource,\n indexedFile: indexedFileResource,\n },\n }) as unknown as AiConnectionStatusDb);\n}\n\nfunction latestIso(values: unknown[]): string | undefined {\n const timestamps = values\n .map((value) => {\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'string' || typeof value === 'number') {\n const parsed = Date.parse(String(value));\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n })\n .filter((value): value is number => value !== undefined);\n if (timestamps.length === 0) {\n return undefined;\n }\n return new Date(Math.max(...timestamps)).toISOString();\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n\nfunction safeLogError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction safeAiConnectionFailureReason(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n for (const reason of [\n 'service_access_missing',\n 'not_configured',\n 'pod_not_found',\n 'ai_connection_unavailable',\n ]) {\n if (message.includes(reason)) {\n return reason;\n }\n }\n return 'ai_connection_unavailable';\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PodSettingsHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/PodSettingsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ServerResponse } from 'node:http';\nimport { drizzle, eq } from '@undefineds.co/drizzle-solid';\nimport {\n credentialResource,\n indexedFileResource,\n type CredentialRow,\n type IndexedFileRow,\n} from '@undefineds.co/models';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { ApiServer } from '../ApiServer';\nimport type { AuthenticatedRequest } from '../middleware/AuthMiddleware';\nimport type { PodLookupRepository, PodLookupResult } from '../../identity/drizzle/PodLookupRepository';\nimport type { UsageRepository, PodUsageRecord } from '../../storage/quota/UsageRepository';\nimport type { AuthContext } from '../auth/AuthContext';\nimport type { InternalPodAccessTokenProvider } from '../ai-gateway/pod/HostedPodDataAccess';\n\nexport interface PodSettingsStatus {\n identity: {\n webId: string;\n podUrl?: string;\n };\n storage: PodStorageStatus;\n aiConnection: PodAiConnectionStatus;\n generatedAt: string;\n}\n\nexport type PodStorageStatus =\n | {\n status: 'available';\n usage: {\n storageBytes: number;\n ingressBytes: number;\n egressBytes: number;\n };\n limits: {\n storageLimitBytes: number | null;\n bandwidthLimitBps: number | null;\n };\n source: 'identity_usage';\n }\n | {\n status: 'unsupported' | 'error';\n reason: string;\n };\n\nexport type PodAiConnectionStatus =\n | {\n status: 'available';\n containerUrl?: string;\n configuredProviders: number;\n lastSyncAt?: string;\n source: 'drizzle-solid';\n }\n | {\n status: 'unsupported' | 'error';\n reason: string;\n };\n\nexport interface PodAiConnectionStatusReader {\n read(input: { webId: string; podUrl?: string; auth?: AuthContext }): Promise<PodAiConnectionStatus>;\n}\n\nexport interface PodSettingsHandlerOptions {\n podLookupRepository: Pick<PodLookupRepository, 'findByWebId'>;\n usageRepo: Pick<UsageRepository, 'getPodUsage'>;\n aiConnectionStatusReader?: PodAiConnectionStatusReader;\n now?: () => Date;\n logger?: Pick<ReturnType<typeof getLoggerFor>, 'warn' | 'error'>;\n}\n\nexport function registerPodSettingsRoutes(server: ApiServer, options: PodSettingsHandlerOptions): void {\n const logger = options.logger ?? getLoggerFor('PodSettingsHandler');\n const now = options.now ?? (() => new Date());\n const aiConnectionStatusReader = options.aiConnectionStatusReader ?? {\n read: async () => ({ status: 'unsupported', reason: 'not_configured' }) as const,\n };\n\n server.get('/api/pod/settings/status', async (request, response) => {\n if (!request.auth || request.auth.type !== 'solid') {\n sendJson(response, 401, { error: 'Authentication required' });\n return;\n }\n\n const webId = request.auth.webId;\n try {\n const pod = await options.podLookupRepository.findByWebId(webId);\n const podUrl = pod?.storageUrl ?? pod?.baseUrl;\n const [storage, aiConnection] = await Promise.all([\n readStorageStatus(options.usageRepo, pod),\n aiConnectionStatusReader.read({ webId, podUrl, auth: request.auth }).catch((error: unknown) => {\n const reason = safeAiConnectionFailureReason(error);\n logger.warn(`Failed to read Pod AI Connection status: ${reason}`);\n return { status: 'error', reason } as const;\n }),\n ]);\n\n sendJson(response, 200, {\n identity: {\n webId,\n podUrl,\n },\n storage,\n aiConnection,\n generatedAt: now().toISOString(),\n } satisfies PodSettingsStatus);\n } catch (error) {\n logger.error(`Failed to read Pod settings status: ${safeLogError(error)}`);\n sendJson(response, 500, { error: 'Failed to read Pod settings status' });\n }\n });\n}\n\nasync function readStorageStatus(\n usageRepo: Pick<UsageRepository, 'getPodUsage'>,\n pod: PodLookupResult | undefined,\n): Promise<PodStorageStatus> {\n if (!pod) {\n return { status: 'unsupported', reason: 'pod_not_found' };\n }\n\n let usage: PodUsageRecord | undefined;\n try {\n usage = await usageRepo.getPodUsage(pod.podId);\n } catch {\n return { status: 'error', reason: 'usage_unavailable' };\n }\n\n if (!usage) {\n return { status: 'unsupported', reason: 'usage_not_available' };\n }\n\n return {\n status: 'available',\n usage: {\n storageBytes: usage.storageBytes,\n ingressBytes: usage.ingressBytes,\n egressBytes: usage.egressBytes,\n },\n limits: {\n storageLimitBytes: usage.storageLimitBytes ?? null,\n bandwidthLimitBps: usage.bandwidthLimitBps ?? null,\n },\n source: 'identity_usage',\n };\n}\n\nexport class DrizzlePodAiConnectionStatusReader implements PodAiConnectionStatusReader {\n public constructor(\n private readonly internalPodAccess?: InternalPodAccessTokenProvider,\n private readonly dbFactory: (input: {\n webId: string;\n podUrl: string;\n fetch: typeof fetch;\n }) => Promise<AiConnectionStatusDb> = createAiConnectionStatusDb,\n ) {}\n\n public async read({ webId, podUrl, auth }: { webId: string; podUrl?: string; auth?: AuthContext }): Promise<PodAiConnectionStatus> {\n const trustedFetch = await this.internalPodAccess?.getTrustedFetch(webId, auth);\n if (!trustedFetch) {\n return { status: 'unsupported', reason: 'not_configured' };\n }\n if (!podUrl) {\n return { status: 'unsupported', reason: 'pod_not_found' };\n }\n\n try {\n const db = await this.dbFactory({ webId, podUrl, fetch: trustedFetch });\n await db.init?.(credentialResource, indexedFileResource);\n\n const credentialRows = await db.select().from(credentialResource).where(eq(credentialResource.status, 'active')).execute() as CredentialRow[];\n const indexedRows = await db.select().from(indexedFileResource).execute() as IndexedFileRow[];\n const lastSyncAt = latestIso([\n ...credentialRows.map((row) => row.lastUsedAt ?? row.lastRefreshAt),\n ...indexedRows.map((row) => row.indexedAt),\n ]);\n\n return {\n status: 'available',\n containerUrl: new URL('settings/credentials.ttl', podUrl).toString(),\n configuredProviders: credentialRows.length,\n lastSyncAt,\n source: 'drizzle-solid',\n };\n } catch {\n return { status: 'error', reason: 'ai_connection_unavailable' };\n }\n }\n}\n\ntype AiConnectionStatusDb = {\n init?: (...resources: unknown[]) => Promise<void>;\n select(): {\n from(resource: unknown): {\n where(condition: unknown): { execute(): Promise<unknown[]> };\n execute(): Promise<unknown[]>;\n };\n };\n};\n\nfunction createAiConnectionStatusDb(input: {\n webId: string;\n podUrl: string;\n fetch: typeof fetch;\n}): Promise<AiConnectionStatusDb> {\n return Promise.resolve(drizzle({\n fetch: input.fetch,\n info: { webId: input.webId, isLoggedIn: true },\n } as any, {\n podUrl: input.podUrl,\n schema: {\n credential: credentialResource,\n indexedFile: indexedFileResource,\n },\n }) as unknown as AiConnectionStatusDb);\n}\n\nfunction latestIso(values: unknown[]): string | undefined {\n const timestamps = values\n .map((value) => {\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'string' || typeof value === 'number') {\n const parsed = Date.parse(String(value));\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n })\n .filter((value): value is number => value !== undefined);\n if (timestamps.length === 0) {\n return undefined;\n }\n return new Date(Math.max(...timestamps)).toISOString();\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n\nfunction safeLogError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction safeAiConnectionFailureReason(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n for (const reason of [\n 'service_access_missing',\n 'not_configured',\n 'pod_not_found',\n 'ai_connection_unavailable',\n ]) {\n if (message.includes(reason)) {\n return reason;\n }\n }\n return 'ai_connection_unavailable';\n}\n"]}
|
|
@@ -59,16 +59,16 @@ export interface AgentRuntimeConfig {
|
|
|
59
59
|
aiConnection?: AIConnectionInvocationConfig;
|
|
60
60
|
}
|
|
61
61
|
export type PersistedAgentRuntimeConfig = Omit<AgentRuntimeConfig, 'aiConnection'> & {
|
|
62
|
-
aiConnection?: Omit<AIConnectionInvocationConfig, '
|
|
62
|
+
aiConnection?: Omit<AIConnectionInvocationConfig, 'apiKey'>;
|
|
63
63
|
};
|
|
64
64
|
/**
|
|
65
65
|
* Runtime config persisted with a Run is a non-secret binding description.
|
|
66
|
-
* The
|
|
66
|
+
* The API key is restored from the current execution context on each
|
|
67
67
|
* initial or continuation invocation.
|
|
68
68
|
*/
|
|
69
69
|
export declare function toPersistedAgentRuntimeConfig(config: AgentRuntimeConfig): PersistedAgentRuntimeConfig;
|
|
70
70
|
export declare function withInvocationAiConnection<TContext>(config: AgentRuntimeConfig | PersistedAgentRuntimeConfig, context: TContext | undefined): AgentRuntimeConfig;
|
|
71
|
-
export declare function
|
|
71
|
+
export declare function deepScrubApiKey<T>(value: T): T;
|
|
72
72
|
export type AgentRuntimeEvent = {
|
|
73
73
|
type: 'text';
|
|
74
74
|
text: string;
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.toPersistedAgentRuntimeConfig = toPersistedAgentRuntimeConfig;
|
|
4
4
|
exports.withInvocationAiConnection = withInvocationAiConnection;
|
|
5
|
-
exports.
|
|
5
|
+
exports.deepScrubApiKey = deepScrubApiKey;
|
|
6
6
|
/**
|
|
7
7
|
* Runtime config persisted with a Run is a non-secret binding description.
|
|
8
|
-
* The
|
|
8
|
+
* The API key is restored from the current execution context on each
|
|
9
9
|
* initial or continuation invocation.
|
|
10
10
|
*/
|
|
11
11
|
function toPersistedAgentRuntimeConfig(config) {
|
|
12
|
-
return
|
|
12
|
+
return deepScrubApiKey(config);
|
|
13
13
|
}
|
|
14
14
|
function withInvocationAiConnection(config, context) {
|
|
15
15
|
const persisted = toPersistedAgentRuntimeConfig(config);
|
|
@@ -24,19 +24,19 @@ function withInvocationAiConnection(config, context) {
|
|
|
24
24
|
} : {}),
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
-
function
|
|
27
|
+
function deepScrubApiKey(value) {
|
|
28
28
|
if (Array.isArray(value)) {
|
|
29
|
-
return value.map((item) =>
|
|
29
|
+
return value.map((item) => deepScrubApiKey(item));
|
|
30
30
|
}
|
|
31
31
|
if (!value || typeof value !== 'object' || value instanceof Date) {
|
|
32
32
|
return value;
|
|
33
33
|
}
|
|
34
34
|
const output = {};
|
|
35
35
|
for (const [key, item] of Object.entries(value)) {
|
|
36
|
-
if (key === '
|
|
36
|
+
if (key === 'apiKey') {
|
|
37
37
|
continue;
|
|
38
38
|
}
|
|
39
|
-
output[key] =
|
|
39
|
+
output[key] = deepScrubApiKey(item);
|
|
40
40
|
}
|
|
41
41
|
return output;
|
|
42
42
|
}
|
|
@@ -51,13 +51,13 @@ function readInvocationAiConnection(context) {
|
|
|
51
51
|
const value = candidate;
|
|
52
52
|
if (typeof value.baseUrl !== 'string'
|
|
53
53
|
|| value.baseUrl.trim().length === 0
|
|
54
|
-
|| typeof value.
|
|
55
|
-
|| value.
|
|
54
|
+
|| typeof value.apiKey !== 'string'
|
|
55
|
+
|| value.apiKey.trim().length === 0) {
|
|
56
56
|
return undefined;
|
|
57
57
|
}
|
|
58
58
|
return {
|
|
59
59
|
baseUrl: value.baseUrl,
|
|
60
|
-
|
|
60
|
+
apiKey: value.apiKey,
|
|
61
61
|
...(typeof value.model === 'string' && value.model.trim().length > 0 ? { model: value.model } : {}),
|
|
62
62
|
};
|
|
63
63
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentRuntimeTypes.js","sourceRoot":"","sources":["../../../src/api/runs/AgentRuntimeTypes.ts"],"names":[],"mappings":";;AAoEA,sEAEC;AAED,gEAeC;AAED,
|
|
1
|
+
{"version":3,"file":"AgentRuntimeTypes.js","sourceRoot":"","sources":["../../../src/api/runs/AgentRuntimeTypes.ts"],"names":[],"mappings":";;AAoEA,sEAEC;AAED,gEAeC;AAED,0CAeC;AAzCD;;;;GAIG;AACH,SAAgB,6BAA6B,CAAC,MAA0B;IACtE,OAAO,eAAe,CAAC,MAAM,CAAgC,CAAC;AAChE,CAAC;AAED,SAAgB,0BAA0B,CACxC,MAAwD,EACxD,OAA6B;IAE7B,MAAM,SAAS,GAAG,6BAA6B,CAAC,MAA4B,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAC;IACvD,OAAO;QACL,GAAG,SAAS;QACZ,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;YACf,YAAY,EAAE;gBACZ,GAAG,SAAS,CAAC,YAAY;gBACzB,GAAG,UAAU;aACd;SACF,CAAC,CAAC,CAAC,EAAE,CAAC;KACc,CAAC;AAC1B,CAAC;AAED,SAAgB,eAAe,CAAI,KAAQ;IACzC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAM,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QACjE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QAC3E,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,MAAW,CAAC;AACrB,CAAC;AAED,SAAS,0BAA0B,CAAW,OAA6B;IACzE,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,SAAS,GAAI,OAAmC,CAAC,YAAY,CAAC;IACpE,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,SAAoC,CAAC;IACnD,IACE,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;WAC9B,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;WACjC,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;WAChC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EACnC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpG,CAAC;AACJ,CAAC","sourcesContent":["import type { ResolvedAgentConfig } from '../../agents/config/types';\nimport type { AIConnectionInvocationConfig } from '../../agents/types';\nimport type { WorkspaceRef } from '../workspace/types';\n\nexport type RunnerProtocol = 'pi' | 'acp';\nexport type AcpRunnerType = 'codebuddy' | 'claude' | 'codex';\nexport type RunnerType = 'pi' | AcpRunnerType;\n\nexport type WorktreeSpec =\n | { mode: 'existing'; path: string }\n | { mode: 'create'; baseRef?: string; branch?: string };\n\n/**\n * Canonical workspace reference for a Run.\n *\n * This is a workspace Container reference, not an execution config object.\n * Stable workspace metadata belongs on the Container .meta resource. Runners\n * resolve this reference into their own local cwd before starting the Agent Loop.\n */\nexport interface AgentRuntimeConfig {\n workspace: WorkspaceRef;\n /**\n * Optional execution policy for git workspaces. The workspace field still\n * points at the repo/workspace resource; this only selects the cwd used by a run.\n */\n worktree?: WorktreeSpec;\n /**\n * Stream idle cutoff for agent output. If no output arrives within this window,\n * the current streaming response ends.\n *\n * Defaults to 500ms for tests; real agents may need a larger value.\n */\n idleMs?: number;\n /**\n * How long to keep the stream open after an auth_required event.\n * Defaults to 5 minutes.\n */\n authWaitMs?: number;\n runner: {\n type: RunnerType;\n /**\n * pi: request-scoped pi AgentSession restored from Xpod Run/Thread/Message state.\n * acp: protocol adapter over JSON-RPC (Agent Client Protocol) stdio runners.\n */\n protocol?: RunnerProtocol;\n argv?: string[];\n allowCustomArgv?: boolean;\n };\n /**\n * Resolved non-secret agent profile from /agents/{agentId}/AGENTS.md + .meta.\n */\n agentConfig?: ResolvedAgentConfig;\n /**\n * Invocation-scoped Xpod AI Connection. Model runners fail closed without it;\n * raw Pod provider credentials must never be placed in agentConfig.\n */\n aiConnection?: AIConnectionInvocationConfig;\n}\n\nexport type PersistedAgentRuntimeConfig = Omit<AgentRuntimeConfig, 'aiConnection'> & {\n aiConnection?: Omit<AIConnectionInvocationConfig, 'apiKey'>;\n};\n\n/**\n * Runtime config persisted with a Run is a non-secret binding description.\n * The API key is restored from the current execution context on each\n * initial or continuation invocation.\n */\nexport function toPersistedAgentRuntimeConfig(config: AgentRuntimeConfig): PersistedAgentRuntimeConfig {\n return deepScrubApiKey(config) as PersistedAgentRuntimeConfig;\n}\n\nexport function withInvocationAiConnection<TContext>(\n config: AgentRuntimeConfig | PersistedAgentRuntimeConfig,\n context: TContext | undefined,\n): AgentRuntimeConfig {\n const persisted = toPersistedAgentRuntimeConfig(config as AgentRuntimeConfig);\n const invocation = readInvocationAiConnection(context);\n return {\n ...persisted,\n ...(invocation ? {\n aiConnection: {\n ...persisted.aiConnection,\n ...invocation,\n },\n } : {}),\n } as AgentRuntimeConfig;\n}\n\nexport function deepScrubApiKey<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map((item) => deepScrubApiKey(item)) as T;\n }\n if (!value || typeof value !== 'object' || value instanceof Date) {\n return value;\n }\n const output: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n if (key === 'apiKey') {\n continue;\n }\n output[key] = deepScrubApiKey(item);\n }\n return output as T;\n}\n\nfunction readInvocationAiConnection<TContext>(context: TContext | undefined): AIConnectionInvocationConfig | undefined {\n if (!context || typeof context !== 'object') {\n return undefined;\n }\n const candidate = (context as Record<string, unknown>).aiConnection;\n if (!candidate || typeof candidate !== 'object') {\n return undefined;\n }\n const value = candidate as Record<string, unknown>;\n if (\n typeof value.baseUrl !== 'string'\n || value.baseUrl.trim().length === 0\n || typeof value.apiKey !== 'string'\n || value.apiKey.trim().length === 0\n ) {\n return undefined;\n }\n return {\n baseUrl: value.baseUrl,\n apiKey: value.apiKey,\n ...(typeof value.model === 'string' && value.model.trim().length > 0 ? { model: value.model } : {}),\n };\n}\n\nexport type AgentRuntimeEvent =\n | { type: 'text'; text: string }\n | { type: 'error'; message: string }\n | {\n type: 'waiting_runner';\n workspace: WorkspaceRef;\n message: string;\n }\n | {\n type: 'auth_required';\n method: string;\n url?: string;\n message?: string;\n options?: Array<{ label?: string; url?: string; method?: string }>;\n }\n | {\n type: 'tool_call';\n requestId: string;\n name: string;\n arguments: string;\n };\n"]}
|
|
@@ -9,6 +9,7 @@ export declare const XPOD_RUN_REQUESTED_EVENT = "xpod/run.requested";
|
|
|
9
9
|
export declare const XPOD_RUN_CONTINUE_REQUESTED_EVENT = "xpod/run.continue_requested";
|
|
10
10
|
export declare const XPOD_AGENT_RUN_FUNCTION_ID = "xpod-agent-run";
|
|
11
11
|
export interface XpodRunRequestedEventData {
|
|
12
|
+
source: string;
|
|
12
13
|
runId: string;
|
|
13
14
|
threadId: string;
|
|
14
15
|
executionKey?: string;
|
|
@@ -17,10 +18,11 @@ export interface XpodRunRequestedEventData {
|
|
|
17
18
|
continuation?: RunExecutionInput['continuation'];
|
|
18
19
|
}
|
|
19
20
|
export type XpodRunRequestedEvent = EventPayload<XpodRunRequestedEventData> & {
|
|
20
|
-
name:
|
|
21
|
+
name: string;
|
|
21
22
|
};
|
|
22
23
|
export interface InngestRunExecutionBackendOptions {
|
|
23
24
|
client?: Inngest;
|
|
25
|
+
source?: string;
|
|
24
26
|
baseUrl?: string;
|
|
25
27
|
eventKey?: string;
|
|
26
28
|
signingKey?: string;
|
|
@@ -53,6 +55,9 @@ export interface InngestRunExecutionBackendOptions {
|
|
|
53
55
|
*/
|
|
54
56
|
export declare class InngestRunExecutionBackend implements RunExecutionBackend {
|
|
55
57
|
private readonly client;
|
|
58
|
+
private readonly source;
|
|
59
|
+
private readonly requestedEventName;
|
|
60
|
+
private readonly continueRequestedEventName;
|
|
56
61
|
private readonly runtimeDriver;
|
|
57
62
|
private readonly managedRunWorker?;
|
|
58
63
|
private readonly contextResolver?;
|
|
@@ -62,9 +67,9 @@ export declare class InngestRunExecutionBackend implements RunExecutionBackend {
|
|
|
62
67
|
private readonly durableDelivery;
|
|
63
68
|
private readonly pendingRuns;
|
|
64
69
|
readonly agentRunFunction: import("inngest").InngestFunction<import("inngest").InngestFunction.Options<[{
|
|
65
|
-
readonly event:
|
|
70
|
+
readonly event: string;
|
|
66
71
|
}, {
|
|
67
|
-
readonly event:
|
|
72
|
+
readonly event: string;
|
|
68
73
|
}], import("inngest").HandlerWithTriggers<{
|
|
69
74
|
sendEvent: (idOrOptions: import("inngest").StepOptionsOrId, payload: import("inngest").SendEventPayload) => Promise<import("inngest/types").SendEventOutput<import("inngest").ClientOptionsFromInngest<Inngest<import("inngest").ClientOptions>>>>;
|
|
70
75
|
waitForSignal: <TData>(idOrOptions: import("inngest").StepOptionsOrId, opts: {
|
|
@@ -151,9 +156,9 @@ export declare class InngestRunExecutionBackend implements RunExecutionBackend {
|
|
|
151
156
|
}) => import("inngest/types").InvocationResult<import("inngest/types").Jsonify<import("inngest").GetFunctionOutputRaw<TFunction>>>;
|
|
152
157
|
fetch: import("inngest").StepFetch;
|
|
153
158
|
}, [{
|
|
154
|
-
readonly event:
|
|
159
|
+
readonly event: string;
|
|
155
160
|
}, {
|
|
156
|
-
readonly event:
|
|
161
|
+
readonly event: string;
|
|
157
162
|
}], Omit<Omit<import("inngest").BaseContext<Inngest.Any>, never> & Record<never, never> & {
|
|
158
163
|
logger: import("inngest").Logger;
|
|
159
164
|
}, "group" | "requestId" | "event" | "attempt" | "events" | "runId" | "step" | "defer" | "jobId" | "maxAttempts"> & import("inngest").FailureEventArgs<EventPayload<any>> & {
|
|
@@ -332,9 +337,9 @@ export declare class InngestRunExecutionBackend implements RunExecutionBackend {
|
|
|
332
337
|
}) => import("inngest/types").InvocationResult<import("inngest/types").Jsonify<import("inngest").GetFunctionOutputRaw<TFunction>>>;
|
|
333
338
|
fetch: import("inngest").StepFetch;
|
|
334
339
|
}, [{
|
|
335
|
-
readonly event:
|
|
340
|
+
readonly event: string;
|
|
336
341
|
}, {
|
|
337
|
-
readonly event:
|
|
342
|
+
readonly event: string;
|
|
338
343
|
}], Omit<Omit<import("inngest").BaseContext<Inngest.Any>, never> & Record<never, never> & {
|
|
339
344
|
logger: import("inngest").Logger;
|
|
340
345
|
}, "group" | "requestId" | "event" | "attempt" | "events" | "runId" | "step" | "defer" | "jobId" | "maxAttempts"> & import("inngest").FailureEventArgs<EventPayload<any>> & {
|
|
@@ -425,12 +430,13 @@ export declare class InngestRunExecutionBackend implements RunExecutionBackend {
|
|
|
425
430
|
fetch: import("inngest").StepFetch;
|
|
426
431
|
};
|
|
427
432
|
}>, Inngest<import("inngest").ClientOptions>, [{
|
|
428
|
-
readonly event:
|
|
433
|
+
readonly event: string;
|
|
429
434
|
}, {
|
|
430
|
-
readonly event:
|
|
435
|
+
readonly event: string;
|
|
431
436
|
}]>;
|
|
432
437
|
constructor(options?: InngestRunExecutionBackendOptions);
|
|
433
438
|
getClient(): Inngest;
|
|
439
|
+
getSource(): string;
|
|
434
440
|
start(input: RunExecutionInput): AsyncIterable<AgentRuntimeEvent>;
|
|
435
441
|
private handleAgentRun;
|
|
436
442
|
restoreExecutionInput(runId: string, context: StoreContext): Promise<RunExecutionInput>;
|
|
@@ -21,8 +21,13 @@ exports.XPOD_AGENT_RUN_FUNCTION_ID = 'xpod-agent-run';
|
|
|
21
21
|
class InngestRunExecutionBackend {
|
|
22
22
|
constructor(options = {}) {
|
|
23
23
|
this.pendingRuns = new Map();
|
|
24
|
+
this.source = normalizeInngestSource(options.source ?? process.env.XPOD_INNGEST_SOURCE);
|
|
25
|
+
const identitySuffix = this.source === 'production' ? '' : `-${this.source}`;
|
|
26
|
+
const eventPath = this.source === 'production' ? 'xpod' : `xpod/${this.source}`;
|
|
27
|
+
this.requestedEventName = `${eventPath}/run.requested`;
|
|
28
|
+
this.continueRequestedEventName = `${eventPath}/run.continue_requested`;
|
|
24
29
|
this.client = options.client ?? new inngest_1.Inngest({
|
|
25
|
-
id:
|
|
30
|
+
id: `xpod-managed-agents${identitySuffix}`,
|
|
26
31
|
baseUrl: options.baseUrl,
|
|
27
32
|
eventKey: options.eventKey,
|
|
28
33
|
signingKey: options.signingKey,
|
|
@@ -43,11 +48,11 @@ class InngestRunExecutionBackend {
|
|
|
43
48
|
this.durableDelivery = options.durableDelivery ?? true;
|
|
44
49
|
this.executeInline = options.executeInline ?? true;
|
|
45
50
|
this.agentRunFunction = this.client.createFunction({
|
|
46
|
-
id: exports.XPOD_AGENT_RUN_FUNCTION_ID
|
|
47
|
-
name: 'Xpod Agent Run'
|
|
51
|
+
id: `${exports.XPOD_AGENT_RUN_FUNCTION_ID}${identitySuffix}`,
|
|
52
|
+
name: this.source === 'production' ? 'Xpod Agent Run' : `Xpod Agent Run (${this.source})`,
|
|
48
53
|
triggers: [
|
|
49
|
-
{ event:
|
|
50
|
-
{ event:
|
|
54
|
+
{ event: this.requestedEventName },
|
|
55
|
+
{ event: this.continueRequestedEventName },
|
|
51
56
|
],
|
|
52
57
|
idempotency: 'event.data.executionKey',
|
|
53
58
|
}, (ctx) => this.handleAgentRun(ctx));
|
|
@@ -55,14 +60,17 @@ class InngestRunExecutionBackend {
|
|
|
55
60
|
getClient() {
|
|
56
61
|
return this.client;
|
|
57
62
|
}
|
|
63
|
+
getSource() {
|
|
64
|
+
return this.source;
|
|
65
|
+
}
|
|
58
66
|
async *start(input) {
|
|
59
67
|
const queue = new AsyncPushQueue();
|
|
60
68
|
this.pendingRuns.set(input.runId, { input, queue, started: false });
|
|
61
69
|
const context = input.context;
|
|
62
70
|
this.contextRecorder?.(context);
|
|
63
71
|
const eventName = input.continuation
|
|
64
|
-
?
|
|
65
|
-
:
|
|
72
|
+
? this.continueRequestedEventName
|
|
73
|
+
: this.requestedEventName;
|
|
66
74
|
const executionKey = this.executionKeyForInput(input);
|
|
67
75
|
try {
|
|
68
76
|
if (!this.durableDelivery && !this.executeInline) {
|
|
@@ -77,6 +85,7 @@ class InngestRunExecutionBackend {
|
|
|
77
85
|
id: executionKey,
|
|
78
86
|
name: eventName,
|
|
79
87
|
data: {
|
|
88
|
+
source: this.source,
|
|
80
89
|
runId: input.runId,
|
|
81
90
|
threadId: input.threadId,
|
|
82
91
|
executionKey,
|
|
@@ -169,8 +178,9 @@ class InngestRunExecutionBackend {
|
|
|
169
178
|
return {
|
|
170
179
|
event: {
|
|
171
180
|
id: executionKey,
|
|
172
|
-
name: input.continuation ?
|
|
181
|
+
name: input.continuation ? this.continueRequestedEventName : this.requestedEventName,
|
|
173
182
|
data: {
|
|
183
|
+
source: this.source,
|
|
174
184
|
runId: input.runId,
|
|
175
185
|
threadId: input.threadId,
|
|
176
186
|
executionKey,
|
|
@@ -188,10 +198,11 @@ class InngestRunExecutionBackend {
|
|
|
188
198
|
return error instanceof Error ? error.message : String(error);
|
|
189
199
|
}
|
|
190
200
|
executionKeyForInput(input) {
|
|
201
|
+
const sourcePrefix = this.source === 'production' ? '' : `${this.source}:`;
|
|
191
202
|
if (!input.continuation) {
|
|
192
|
-
return
|
|
203
|
+
return `${sourcePrefix}run:${input.runId}`;
|
|
193
204
|
}
|
|
194
|
-
return
|
|
205
|
+
return `${sourcePrefix}run:${input.runId}:continue:${input.continuation.kind}:${input.continuation.itemId ?? 'none'}`;
|
|
195
206
|
}
|
|
196
207
|
contextEventData(input, context) {
|
|
197
208
|
const auth = context?.auth;
|
|
@@ -208,6 +219,10 @@ class InngestRunExecutionBackend {
|
|
|
208
219
|
}
|
|
209
220
|
}
|
|
210
221
|
exports.InngestRunExecutionBackend = InngestRunExecutionBackend;
|
|
222
|
+
function normalizeInngestSource(source) {
|
|
223
|
+
const normalized = source?.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
224
|
+
return normalized || 'production';
|
|
225
|
+
}
|
|
211
226
|
class AsyncPushQueue {
|
|
212
227
|
constructor() {
|
|
213
228
|
this.items = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InngestRunExecutionBackend.js","sourceRoot":"","sources":["../../../src/api/runs/InngestRunExecutionBackend.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inngest } from 'inngest';\nimport type { EventPayload } from 'inngest/types';\nimport type { StoreContext } from '../chatkit/store';\nimport type { AgentRuntimeEvent } from './AgentRuntimeTypes';\nimport { ManagedRunWorker, type ManagedRunStore } from './ManagedRunWorker';\nimport { PiAgentRuntimeDriver } from './PiAgentRuntimeDriver';\nimport type { RunContextRetriever, RunExecutionBackend, RunExecutionInput } from './RunExecutionBackend';\nimport type { AiConnectionInvocationKeyIssuer } from '../ai-gateway/auth/AiConnectionInvocationKeyIssuer';\n\nexport const XPOD_RUN_REQUESTED_EVENT = 'xpod/run.requested';\nexport const XPOD_RUN_CONTINUE_REQUESTED_EVENT = 'xpod/run.continue_requested';\nexport const XPOD_AGENT_RUN_FUNCTION_ID = 'xpod-agent-run';\n\nexport interface XpodRunRequestedEventData {\n runId: string;\n threadId: string;\n executionKey?: string;\n authBindingId?: string;\n webId?: string;\n continuation?: RunExecutionInput['continuation'];\n}\n\nexport type XpodRunRequestedEvent = EventPayload<XpodRunRequestedEventData> & {\n name: typeof XPOD_RUN_REQUESTED_EVENT | typeof XPOD_RUN_CONTINUE_REQUESTED_EVENT;\n};\n\nexport interface InngestRunExecutionBackendOptions {\n client?: Inngest;\n baseUrl?: string;\n eventKey?: string;\n signingKey?: string;\n isDev?: boolean;\n runtimeDriver?: RunExecutionBackend;\n store?: ManagedRunStore<StoreContext>;\n managedRunWorker?: ManagedRunWorker<StoreContext>;\n contextRetriever?: RunContextRetriever<StoreContext>;\n contextResolver?: (data: XpodRunRequestedEventData) => StoreContext | Promise<StoreContext | undefined> | undefined;\n contextRecorder?: (context: StoreContext | undefined) => void;\n aiConnectionInvocationKeyIssuer?: Pick<AiConnectionInvocationKeyIssuer, 'issue'>;\n durableDelivery?: boolean;\n /**\n * When true, execute the registered Inngest handler in-process after sending\n * the event. This keeps Chat streaming low-latency while preserving the\n * Inngest event/function boundary for the managed-agents backend.\n */\n executeInline?: boolean;\n}\n\ntype PendingRun = {\n input: RunExecutionInput;\n queue: AsyncPushQueue<AgentRuntimeEvent>;\n started: boolean;\n};\n\ntype InngestHandlerContext = {\n event: XpodRunRequestedEvent;\n runId: string;\n step: {\n run<T>(id: string, fn: () => Promise<T> | T): Promise<T>;\n };\n};\n\n/**\n * Inngest-backed managed-agent execution backend.\n *\n * Xpod owns the Run facts; Inngest owns durable function delivery. In this\n * first API-facing implementation the function can execute inline so ChatKit\n * still receives a normal SSE stream without waiting for external polling.\n *\n * The in-memory pending map is only the streaming bridge for an active HTTP\n * request. When no pending stream exists, the registered Inngest function can\n * restore the Run from store through ManagedRunWorker.\n */\nexport class InngestRunExecutionBackend implements RunExecutionBackend {\n private readonly client: Inngest;\n private readonly runtimeDriver: RunExecutionBackend;\n private readonly managedRunWorker?: ManagedRunWorker<StoreContext>;\n private readonly contextResolver?: InngestRunExecutionBackendOptions['contextResolver'];\n private readonly contextRecorder?: InngestRunExecutionBackendOptions['contextRecorder'];\n private readonly aiConnectionInvocationKeyIssuer?: Pick<AiConnectionInvocationKeyIssuer, 'issue'>;\n private readonly executeInline: boolean;\n private readonly durableDelivery: boolean;\n private readonly pendingRuns = new Map<string, PendingRun>();\n\n public readonly agentRunFunction;\n\n public constructor(options: InngestRunExecutionBackendOptions = {}) {\n this.client = options.client ?? new Inngest({\n id: 'xpod-managed-agents',\n baseUrl: options.baseUrl,\n eventKey: options.eventKey,\n signingKey: options.signingKey,\n isDev: options.isDev ?? !options.durableDelivery,\n });\n this.runtimeDriver = options.runtimeDriver ?? new PiAgentRuntimeDriver();\n this.managedRunWorker = options.managedRunWorker\n ?? (options.store\n ? new ManagedRunWorker({\n store: options.store,\n runtimeDriver: this.runtimeDriver,\n contextRetriever: options.contextRetriever,\n })\n : undefined);\n this.contextResolver = options.contextResolver;\n this.contextRecorder = options.contextRecorder;\n this.aiConnectionInvocationKeyIssuer = options.aiConnectionInvocationKeyIssuer;\n this.durableDelivery = options.durableDelivery ?? true;\n this.executeInline = options.executeInline ?? true;\n this.agentRunFunction = this.client.createFunction(\n {\n id: XPOD_AGENT_RUN_FUNCTION_ID,\n name: 'Xpod Agent Run',\n triggers: [\n { event: XPOD_RUN_REQUESTED_EVENT },\n { event: XPOD_RUN_CONTINUE_REQUESTED_EVENT },\n ],\n idempotency: 'event.data.executionKey',\n },\n (ctx: any) => this.handleAgentRun(ctx as InngestHandlerContext),\n );\n }\n\n public getClient(): Inngest {\n return this.client;\n }\n\n public async *start(input: RunExecutionInput): AsyncIterable<AgentRuntimeEvent> {\n const queue = new AsyncPushQueue<AgentRuntimeEvent>();\n this.pendingRuns.set(input.runId, { input, queue, started: false });\n const context = (input as RunExecutionInput & { context?: StoreContext }).context;\n this.contextRecorder?.(context);\n const eventName = input.continuation\n ? XPOD_RUN_CONTINUE_REQUESTED_EVENT\n : XPOD_RUN_REQUESTED_EVENT;\n const executionKey = this.executionKeyForInput(input);\n\n try {\n if (!this.durableDelivery && !this.executeInline) {\n yield {\n type: 'error',\n message: 'Run execution backend has neither durable delivery nor inline execution enabled',\n };\n return;\n }\n\n if (this.durableDelivery) {\n await this.client.send({\n id: executionKey,\n name: eventName,\n data: {\n runId: input.runId,\n threadId: input.threadId,\n executionKey,\n continuation: input.continuation,\n ...this.contextEventData(input, context),\n },\n });\n }\n\n if (!this.executeInline) {\n queue.close();\n return;\n }\n\n if (this.executeInline) {\n void this.handleAgentRun(this.createInlineContext(input)).catch((error) => {\n queue.push({ type: 'error', message: this.formatError(error) });\n queue.close();\n });\n }\n\n for await (const event of queue.iterate()) {\n yield event;\n }\n } catch (error) {\n yield { type: 'error', message: this.formatError(error) };\n } finally {\n this.pendingRuns.delete(input.runId);\n queue.close();\n }\n }\n\n private async handleAgentRun(ctx: InngestHandlerContext): Promise<{ runId: string; status: string }> {\n const runId = ctx.event.data?.runId;\n if (!runId) {\n return { runId: 'unknown', status: 'missing_run_id' };\n }\n const pending = this.pendingRuns.get(runId);\n if (pending) {\n if (pending.started) {\n return { runId, status: 'skipped' };\n }\n pending.started = true;\n await ctx.step.run('run-agent', async () => {\n try {\n for await (const event of this.runtimeDriver.start(pending.input)) {\n pending.queue.push(event);\n }\n } catch (error) {\n pending.queue.push({ type: 'error', message: this.formatError(error) });\n } finally {\n pending.queue.close();\n }\n });\n\n return { runId, status: 'completed' };\n }\n\n if (!this.managedRunWorker || !this.contextResolver) {\n return { runId, status: 'not_found' };\n }\n\n const resolvedContext = await this.contextResolver(ctx.event.data!);\n if (!resolvedContext) {\n return { runId, status: 'not_found' };\n }\n const context = this.aiConnectionInvocationKeyIssuer\n ? {\n ...resolvedContext,\n aiConnection: await this.aiConnectionInvocationKeyIssuer.issue(resolvedContext),\n }\n : resolvedContext;\n\n const result = await ctx.step.run('run-agent-from-store', async () => {\n return this.managedRunWorker!.executeRun(runId, context);\n });\n\n return { runId, status: result.status };\n }\n\n public async restoreExecutionInput(runId: string, context: StoreContext): Promise<RunExecutionInput> {\n if (!this.managedRunWorker) {\n throw new Error('Managed Run worker is not configured');\n }\n return this.managedRunWorker.loadExecutionInput(runId, context);\n }\n\n public async close(): Promise<void> {\n for (const pending of this.pendingRuns.values()) {\n pending.queue.close();\n }\n this.pendingRuns.clear();\n await (this.runtimeDriver as { close?: () => void | Promise<void> }).close?.();\n }\n\n private createInlineContext(input: RunExecutionInput): InngestHandlerContext {\n const executionKey = this.executionKeyForInput(input);\n return {\n event: {\n id: executionKey,\n name: input.continuation ? XPOD_RUN_CONTINUE_REQUESTED_EVENT : XPOD_RUN_REQUESTED_EVENT,\n data: {\n runId: input.runId,\n threadId: input.threadId,\n executionKey,\n continuation: input.continuation,\n ...this.contextEventData(input, (input as RunExecutionInput & { context?: StoreContext }).context),\n },\n },\n runId: `inline:${executionKey}`,\n step: {\n run: async <T>(_id: string, fn: () => Promise<T> | T): Promise<T> => fn(),\n },\n };\n }\n\n private formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n }\n\n private executionKeyForInput(input: RunExecutionInput): string {\n if (!input.continuation) {\n return `run:${input.runId}`;\n }\n return `run:${input.runId}:continue:${input.continuation.kind}:${input.continuation.itemId ?? 'none'}`;\n }\n\n private contextEventData(input: RunExecutionInput, context: StoreContext | undefined): Partial<XpodRunRequestedEventData> {\n const auth = context?.auth as { type?: unknown; webId?: unknown } | undefined;\n if (input.authBindingId) {\n return {\n authBindingId: input.authBindingId,\n ...(auth?.type === 'solid' && typeof auth.webId === 'string' ? { webId: auth.webId } : {}),\n };\n }\n if (auth?.type !== 'solid' || typeof auth.webId !== 'string') {\n return {};\n }\n return { webId: auth.webId };\n }\n}\n\nclass AsyncPushQueue<T> {\n private readonly items: T[] = [];\n private resolvers: Array<() => void> = [];\n private closed = false;\n\n public push(item: T): void {\n if (this.closed) {\n return;\n }\n this.items.push(item);\n const resolver = this.resolvers.shift();\n resolver?.();\n }\n\n public close(): void {\n if (this.closed) {\n return;\n }\n this.closed = true;\n for (const resolver of this.resolvers) {\n resolver();\n }\n this.resolvers = [];\n }\n\n public async *iterate(): AsyncIterable<T> {\n while (true) {\n if (this.items.length > 0) {\n yield this.items.shift()!;\n continue;\n }\n if (this.closed) {\n return;\n }\n await new Promise<void>((resolve) => this.resolvers.push(resolve));\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"InngestRunExecutionBackend.js","sourceRoot":"","sources":["../../../src/api/runs/InngestRunExecutionBackend.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inngest } from 'inngest';\nimport type { EventPayload } from 'inngest/types';\nimport type { StoreContext } from '../chatkit/store';\nimport type { AgentRuntimeEvent } from './AgentRuntimeTypes';\nimport { ManagedRunWorker, type ManagedRunStore } from './ManagedRunWorker';\nimport { PiAgentRuntimeDriver } from './PiAgentRuntimeDriver';\nimport type { RunContextRetriever, RunExecutionBackend, RunExecutionInput } from './RunExecutionBackend';\nimport type { AiConnectionInvocationKeyIssuer } from '../ai-gateway/auth/AiConnectionInvocationKeyIssuer';\n\nexport const XPOD_RUN_REQUESTED_EVENT = 'xpod/run.requested';\nexport const XPOD_RUN_CONTINUE_REQUESTED_EVENT = 'xpod/run.continue_requested';\nexport const XPOD_AGENT_RUN_FUNCTION_ID = 'xpod-agent-run';\n\nexport interface XpodRunRequestedEventData {\n source: string;\n runId: string;\n threadId: string;\n executionKey?: string;\n authBindingId?: string;\n webId?: string;\n continuation?: RunExecutionInput['continuation'];\n}\n\nexport type XpodRunRequestedEvent = EventPayload<XpodRunRequestedEventData> & {\n name: string;\n};\n\nexport interface InngestRunExecutionBackendOptions {\n client?: Inngest;\n source?: string;\n baseUrl?: string;\n eventKey?: string;\n signingKey?: string;\n isDev?: boolean;\n runtimeDriver?: RunExecutionBackend;\n store?: ManagedRunStore<StoreContext>;\n managedRunWorker?: ManagedRunWorker<StoreContext>;\n contextRetriever?: RunContextRetriever<StoreContext>;\n contextResolver?: (data: XpodRunRequestedEventData) => StoreContext | Promise<StoreContext | undefined> | undefined;\n contextRecorder?: (context: StoreContext | undefined) => void;\n aiConnectionInvocationKeyIssuer?: Pick<AiConnectionInvocationKeyIssuer, 'issue'>;\n durableDelivery?: boolean;\n /**\n * When true, execute the registered Inngest handler in-process after sending\n * the event. This keeps Chat streaming low-latency while preserving the\n * Inngest event/function boundary for the managed-agents backend.\n */\n executeInline?: boolean;\n}\n\ntype PendingRun = {\n input: RunExecutionInput;\n queue: AsyncPushQueue<AgentRuntimeEvent>;\n started: boolean;\n};\n\ntype InngestHandlerContext = {\n event: XpodRunRequestedEvent;\n runId: string;\n step: {\n run<T>(id: string, fn: () => Promise<T> | T): Promise<T>;\n };\n};\n\n/**\n * Inngest-backed managed-agent execution backend.\n *\n * Xpod owns the Run facts; Inngest owns durable function delivery. In this\n * first API-facing implementation the function can execute inline so ChatKit\n * still receives a normal SSE stream without waiting for external polling.\n *\n * The in-memory pending map is only the streaming bridge for an active HTTP\n * request. When no pending stream exists, the registered Inngest function can\n * restore the Run from store through ManagedRunWorker.\n */\nexport class InngestRunExecutionBackend implements RunExecutionBackend {\n private readonly client: Inngest;\n private readonly source: string;\n private readonly requestedEventName: string;\n private readonly continueRequestedEventName: string;\n private readonly runtimeDriver: RunExecutionBackend;\n private readonly managedRunWorker?: ManagedRunWorker<StoreContext>;\n private readonly contextResolver?: InngestRunExecutionBackendOptions['contextResolver'];\n private readonly contextRecorder?: InngestRunExecutionBackendOptions['contextRecorder'];\n private readonly aiConnectionInvocationKeyIssuer?: Pick<AiConnectionInvocationKeyIssuer, 'issue'>;\n private readonly executeInline: boolean;\n private readonly durableDelivery: boolean;\n private readonly pendingRuns = new Map<string, PendingRun>();\n\n public readonly agentRunFunction;\n\n public constructor(options: InngestRunExecutionBackendOptions = {}) {\n this.source = normalizeInngestSource(options.source ?? process.env.XPOD_INNGEST_SOURCE);\n const identitySuffix = this.source === 'production' ? '' : `-${this.source}`;\n const eventPath = this.source === 'production' ? 'xpod' : `xpod/${this.source}`;\n this.requestedEventName = `${eventPath}/run.requested`;\n this.continueRequestedEventName = `${eventPath}/run.continue_requested`;\n this.client = options.client ?? new Inngest({\n id: `xpod-managed-agents${identitySuffix}`,\n baseUrl: options.baseUrl,\n eventKey: options.eventKey,\n signingKey: options.signingKey,\n isDev: options.isDev ?? !options.durableDelivery,\n });\n this.runtimeDriver = options.runtimeDriver ?? new PiAgentRuntimeDriver();\n this.managedRunWorker = options.managedRunWorker\n ?? (options.store\n ? new ManagedRunWorker({\n store: options.store,\n runtimeDriver: this.runtimeDriver,\n contextRetriever: options.contextRetriever,\n })\n : undefined);\n this.contextResolver = options.contextResolver;\n this.contextRecorder = options.contextRecorder;\n this.aiConnectionInvocationKeyIssuer = options.aiConnectionInvocationKeyIssuer;\n this.durableDelivery = options.durableDelivery ?? true;\n this.executeInline = options.executeInline ?? true;\n this.agentRunFunction = this.client.createFunction(\n {\n id: `${XPOD_AGENT_RUN_FUNCTION_ID}${identitySuffix}`,\n name: this.source === 'production' ? 'Xpod Agent Run' : `Xpod Agent Run (${this.source})`,\n triggers: [\n { event: this.requestedEventName },\n { event: this.continueRequestedEventName },\n ],\n idempotency: 'event.data.executionKey',\n },\n (ctx: any) => this.handleAgentRun(ctx as InngestHandlerContext),\n );\n }\n\n public getClient(): Inngest {\n return this.client;\n }\n\n public getSource(): string {\n return this.source;\n }\n\n public async *start(input: RunExecutionInput): AsyncIterable<AgentRuntimeEvent> {\n const queue = new AsyncPushQueue<AgentRuntimeEvent>();\n this.pendingRuns.set(input.runId, { input, queue, started: false });\n const context = (input as RunExecutionInput & { context?: StoreContext }).context;\n this.contextRecorder?.(context);\n const eventName = input.continuation\n ? this.continueRequestedEventName\n : this.requestedEventName;\n const executionKey = this.executionKeyForInput(input);\n\n try {\n if (!this.durableDelivery && !this.executeInline) {\n yield {\n type: 'error',\n message: 'Run execution backend has neither durable delivery nor inline execution enabled',\n };\n return;\n }\n\n if (this.durableDelivery) {\n await this.client.send({\n id: executionKey,\n name: eventName,\n data: {\n source: this.source,\n runId: input.runId,\n threadId: input.threadId,\n executionKey,\n continuation: input.continuation,\n ...this.contextEventData(input, context),\n },\n });\n }\n\n if (!this.executeInline) {\n queue.close();\n return;\n }\n\n if (this.executeInline) {\n void this.handleAgentRun(this.createInlineContext(input)).catch((error) => {\n queue.push({ type: 'error', message: this.formatError(error) });\n queue.close();\n });\n }\n\n for await (const event of queue.iterate()) {\n yield event;\n }\n } catch (error) {\n yield { type: 'error', message: this.formatError(error) };\n } finally {\n this.pendingRuns.delete(input.runId);\n queue.close();\n }\n }\n\n private async handleAgentRun(ctx: InngestHandlerContext): Promise<{ runId: string; status: string }> {\n const runId = ctx.event.data?.runId;\n if (!runId) {\n return { runId: 'unknown', status: 'missing_run_id' };\n }\n const pending = this.pendingRuns.get(runId);\n if (pending) {\n if (pending.started) {\n return { runId, status: 'skipped' };\n }\n pending.started = true;\n await ctx.step.run('run-agent', async () => {\n try {\n for await (const event of this.runtimeDriver.start(pending.input)) {\n pending.queue.push(event);\n }\n } catch (error) {\n pending.queue.push({ type: 'error', message: this.formatError(error) });\n } finally {\n pending.queue.close();\n }\n });\n\n return { runId, status: 'completed' };\n }\n\n if (!this.managedRunWorker || !this.contextResolver) {\n return { runId, status: 'not_found' };\n }\n\n const resolvedContext = await this.contextResolver(ctx.event.data!);\n if (!resolvedContext) {\n return { runId, status: 'not_found' };\n }\n const context = this.aiConnectionInvocationKeyIssuer\n ? {\n ...resolvedContext,\n aiConnection: await this.aiConnectionInvocationKeyIssuer.issue(resolvedContext),\n }\n : resolvedContext;\n\n const result = await ctx.step.run('run-agent-from-store', async () => {\n return this.managedRunWorker!.executeRun(runId, context);\n });\n\n return { runId, status: result.status };\n }\n\n public async restoreExecutionInput(runId: string, context: StoreContext): Promise<RunExecutionInput> {\n if (!this.managedRunWorker) {\n throw new Error('Managed Run worker is not configured');\n }\n return this.managedRunWorker.loadExecutionInput(runId, context);\n }\n\n public async close(): Promise<void> {\n for (const pending of this.pendingRuns.values()) {\n pending.queue.close();\n }\n this.pendingRuns.clear();\n await (this.runtimeDriver as { close?: () => void | Promise<void> }).close?.();\n }\n\n private createInlineContext(input: RunExecutionInput): InngestHandlerContext {\n const executionKey = this.executionKeyForInput(input);\n return {\n event: {\n id: executionKey,\n name: input.continuation ? this.continueRequestedEventName : this.requestedEventName,\n data: {\n source: this.source,\n runId: input.runId,\n threadId: input.threadId,\n executionKey,\n continuation: input.continuation,\n ...this.contextEventData(input, (input as RunExecutionInput & { context?: StoreContext }).context),\n },\n },\n runId: `inline:${executionKey}`,\n step: {\n run: async <T>(_id: string, fn: () => Promise<T> | T): Promise<T> => fn(),\n },\n };\n }\n\n private formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n }\n\n private executionKeyForInput(input: RunExecutionInput): string {\n const sourcePrefix = this.source === 'production' ? '' : `${this.source}:`;\n if (!input.continuation) {\n return `${sourcePrefix}run:${input.runId}`;\n }\n return `${sourcePrefix}run:${input.runId}:continue:${input.continuation.kind}:${input.continuation.itemId ?? 'none'}`;\n }\n\n private contextEventData(input: RunExecutionInput, context: StoreContext | undefined): Partial<XpodRunRequestedEventData> {\n const auth = context?.auth as { type?: unknown; webId?: unknown } | undefined;\n if (input.authBindingId) {\n return {\n authBindingId: input.authBindingId,\n ...(auth?.type === 'solid' && typeof auth.webId === 'string' ? { webId: auth.webId } : {}),\n };\n }\n if (auth?.type !== 'solid' || typeof auth.webId !== 'string') {\n return {};\n }\n return { webId: auth.webId };\n }\n}\n\nfunction normalizeInngestSource(source: string | undefined): string {\n const normalized = source?.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');\n return normalized || 'production';\n}\n\nclass AsyncPushQueue<T> {\n private readonly items: T[] = [];\n private resolvers: Array<() => void> = [];\n private closed = false;\n\n public push(item: T): void {\n if (this.closed) {\n return;\n }\n this.items.push(item);\n const resolver = this.resolvers.shift();\n resolver?.();\n }\n\n public close(): void {\n if (this.closed) {\n return;\n }\n this.closed = true;\n for (const resolver of this.resolvers) {\n resolver();\n }\n this.resolvers = [];\n }\n\n public async *iterate(): AsyncIterable<T> {\n while (true) {\n if (this.items.length > 0) {\n yield this.items.shift()!;\n continue;\n }\n if (this.closed) {\n return;\n }\n await new Promise<void>((resolve) => this.resolvers.push(resolve));\n }\n }\n}\n"]}
|
|
@@ -258,7 +258,7 @@ class PiAgentRuntimeDriver {
|
|
|
258
258
|
resolvePiConfig(config) {
|
|
259
259
|
const connection = (0, safe_env_1.requireAiConnectionRuntimeConfig)({
|
|
260
260
|
baseUrl: config.aiConnection?.baseUrl,
|
|
261
|
-
apiKey: config.aiConnection?.
|
|
261
|
+
apiKey: config.aiConnection?.apiKey,
|
|
262
262
|
model: config.aiConnection?.model ?? config.agentConfig?.model ?? 'linx',
|
|
263
263
|
}, 'pi Agent Runtime');
|
|
264
264
|
const provider = 'xpod';
|
|
@@ -489,7 +489,7 @@ class PiAgentRuntimeDriver {
|
|
|
489
489
|
workdir,
|
|
490
490
|
baseUrl: connection?.baseUrl ?? '',
|
|
491
491
|
model: connection?.model ?? agent?.model ?? 'linx',
|
|
492
|
-
|
|
492
|
+
apiKeyHash: this.hashSecret(connection?.apiKey),
|
|
493
493
|
systemPrompt: agent?.systemPrompt ?? '',
|
|
494
494
|
skillsContent: agent?.skillsContent ?? '',
|
|
495
495
|
permissionMode: agent?.permissionMode ?? '',
|