@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiConnectionServiceAccess.js","sourceRoot":"","sources":["../../../../src/api/ai-gateway/service-access/AiConnectionServiceAccess.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"AiConnectionServiceAccess.js","sourceRoot":"","sources":["../../../../src/api/ai-gateway/service-access/AiConnectionServiceAccess.ts"],"names":[],"mappings":";;;AA4CA,0EAqBC;AAjED,gEAAiE;AACjE,kDAI+B;AAElB,QAAA,uBAAuB,GAAG,6BAA6B,CAAC;AA+BrE,MAAM,qBAAqB,GAAG,IAAI,OAAO,CAAiB;IACxD,CAAC,2BAAkB,EAAE,oBAAoB,CAAC,2BAAkB,CAAC,CAAC;IAC9D,CAAC,2BAAkB,EAAE,oBAAoB,CAAC,2BAAkB,CAAC,CAAC;IAC9D,CAAC,8BAAqB,EAAE,oBAAoB,CAAC,8BAAqB,CAAC,CAAC;CACrE,CAAC,CAAC;AAEH,SAAgB,+BAA+B,CAAC,KAG/C;IACC,OAAO;QACL,QAAQ,EAAE,+BAAuB;QACjC,OAAO,EAAE;YACP,KAAK,EAAE,KAAK,CAAC,YAAY;YACzB,KAAK,EAAE,oBAAoB;SAC5B;QACD,SAAS,EAAE;YACT,CAAC,qBAAqB,EAAE,WAAW,CAAC,KAAK,CAAC,UAAU,EAAE,2BAAkB,CAAC,CAAC;YAC1E,CAAC,qBAAqB,EAAE,WAAW,CAAC,KAAK,CAAC,UAAU,EAAE,2BAAkB,CAAC,CAAC;YAC1E,CAAC,gBAAgB,EAAE,WAAW,CAAC,KAAK,CAAC,UAAU,EAAE,8BAAqB,CAAC,CAAC;SACzE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE;YACF,GAAG;YACH,SAAS,EAAE,aAAa;YACxB,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;SAClD,CAAC,CAAwC;KAC3C,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,UAAkB,EAAE,QAA4B;IACnE,MAAM,OAAO,GAAG,GAAG,IAAA,iCAAiB,EAAC,UAAU,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC;IACxE,MAAM,YAAY,GAAG,qBAAqB,CAAC,GAAG,CAAC,QAAkB,CAAC,CAAC;IACnE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,oBAAoB,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAClF,OAAO,IAAI,GAAG,CAAC,GAAG,YAAY,IAAI,YAAY,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;AACvF,CAAC;AAED,SAAS,oBAAoB,CAAC,QAA4B;IACxD,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAC/D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import { resolvePodBaseUrl } from '@undefineds.co/drizzle-solid';\nimport {\n aiProviderResource,\n credentialResource,\n quotaSnapshotResource,\n} from '@undefineds.co/models';\n\nexport const AI_CONNECTION_APPLET_ID = 'co.undefineds.ai-connection';\n\nexport interface AiConnectionServiceAccessDescriptor {\n appletId: typeof AI_CONNECTION_APPLET_ID;\n service: {\n webId: string;\n label: 'Xpod AI Connection';\n };\n resources: AiConnectionServiceAccessResource[];\n}\n\nexport interface AiConnectionServiceAccessResource {\n id: 'providerCredentials' | 'providerDefinitions' | 'quotaSnapshots';\n url: string;\n mediaType: 'text/turtle';\n access: {\n read: true;\n append: true;\n write: true;\n controlRead?: never;\n controlWrite?: never;\n };\n}\n\ninterface PodResourceLocator {\n config?: {\n base?: string;\n };\n buildId(value: { id: string }): string;\n}\n\nconst declaredResourceBases = new WeakMap<object, string>([\n [credentialResource, declaredResourceBase(credentialResource)],\n [aiProviderResource, declaredResourceBase(aiProviderResource)],\n [quotaSnapshotResource, declaredResourceBase(quotaSnapshotResource)],\n]);\n\nexport function createAiConnectionServiceAccess(input: {\n ownerWebId: string;\n serviceWebId: string;\n}): AiConnectionServiceAccessDescriptor {\n return {\n appletId: AI_CONNECTION_APPLET_ID,\n service: {\n webId: input.serviceWebId,\n label: 'Xpod AI Connection',\n },\n resources: [\n ['providerCredentials', resourceUrl(input.ownerWebId, credentialResource)],\n ['providerDefinitions', resourceUrl(input.ownerWebId, aiProviderResource)],\n ['quotaSnapshots', resourceUrl(input.ownerWebId, quotaSnapshotResource)],\n ].map(([id, url]) => ({\n id,\n url,\n mediaType: 'text/turtle',\n access: { read: true, append: true, write: true },\n })) as AiConnectionServiceAccessResource[],\n };\n}\n\nfunction resourceUrl(ownerWebId: string, resource: PodResourceLocator): string {\n const podRoot = `${resolvePodBaseUrl(ownerWebId).replace(/\\/$/u, '')}/`;\n const resourcePath = declaredResourceBases.get(resource as object);\n if (!resourcePath) {\n throw new Error('AI Connection resource is missing an immutable declared base');\n }\n const documentPath = resource.buildId({ id: '__service_access__' }).split('#')[0];\n return new URL(`${resourcePath}/${documentPath}`.replace(/^\\/+/u, ''), podRoot).href;\n}\n\nfunction declaredResourceBase(resource: PodResourceLocator): string {\n const base = resource.config?.base?.replace(/^\\/+|\\/+$/gu, '');\n if (!base) {\n throw new Error('AI Connection resource is missing a declared base');\n }\n return base;\n}\n"]}
|
|
@@ -19,15 +19,9 @@ export interface SolidAuthContext {
|
|
|
19
19
|
dpopProof?: string;
|
|
20
20
|
/** Whether this was authenticated via the sk-* CSS client credentials wrapper */
|
|
21
21
|
viaApiKey?: boolean;
|
|
22
|
-
/** Whether this was authenticated via an Xpod Gateway API key. */
|
|
23
|
-
viaGatewayApiKey?: boolean;
|
|
24
22
|
/** Whether this principal came from a stateless internal runtime invocation token. */
|
|
25
23
|
internalInvocation?: boolean;
|
|
26
|
-
/**
|
|
27
|
-
gatewayKeyId?: string;
|
|
28
|
-
/** SHA-256 fingerprint of the authenticated Gateway bearer key, never the raw key. */
|
|
29
|
-
gatewayKeyFingerprint?: string;
|
|
30
|
-
/** Gateway/API scopes bound to the authenticated principal. */
|
|
24
|
+
/** Explicit API scopes bound to constrained principals such as invocation tokens. */
|
|
31
25
|
scopes?: string[];
|
|
32
26
|
}
|
|
33
27
|
export interface NodeAuthContext {
|
|
@@ -62,8 +56,3 @@ export declare function isServiceAuth(ctx: AuthContext): ctx is ServiceAuthConte
|
|
|
62
56
|
* Check if a service auth context has the required scope.
|
|
63
57
|
*/
|
|
64
58
|
export declare function hasScope(ctx: AuthContext, scope: string): boolean;
|
|
65
|
-
/**
|
|
66
|
-
* Gateway API keys carry explicit API scopes. Normal Solid callers remain
|
|
67
|
-
* authorized by the Solid layer and are not narrowed here.
|
|
68
|
-
*/
|
|
69
|
-
export declare function hasGatewayScope(ctx: AuthContext, scope: string): boolean;
|
|
@@ -17,7 +17,6 @@ exports.getAccountId = getAccountId;
|
|
|
17
17
|
exports.getNodeId = getNodeId;
|
|
18
18
|
exports.isServiceAuth = isServiceAuth;
|
|
19
19
|
exports.hasScope = hasScope;
|
|
20
|
-
exports.hasGatewayScope = hasGatewayScope;
|
|
21
20
|
function isSolidAuth(ctx) {
|
|
22
21
|
return ctx.type === 'solid';
|
|
23
22
|
}
|
|
@@ -60,14 +59,4 @@ function isServiceAuth(ctx) {
|
|
|
60
59
|
function hasScope(ctx, scope) {
|
|
61
60
|
return ctx.type === 'service' && ctx.scopes.includes(scope);
|
|
62
61
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Gateway API keys carry explicit API scopes. Normal Solid callers remain
|
|
65
|
-
* authorized by the Solid layer and are not narrowed here.
|
|
66
|
-
*/
|
|
67
|
-
function hasGatewayScope(ctx, scope) {
|
|
68
|
-
if (ctx.type !== 'solid' || ctx.viaGatewayApiKey !== true) {
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
return ctx.scopes?.includes(scope) === true;
|
|
72
|
-
}
|
|
73
62
|
//# sourceMappingURL=AuthContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthContext.js","sourceRoot":"","sources":["../../../src/api/auth/AuthContext.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;
|
|
1
|
+
{"version":3,"file":"AuthContext.js","sourceRoot":"","sources":["../../../src/api/auth/AuthContext.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAmCH,kCAEC;AAED,gCAEC;AAKD,4BAEC;AAKD,wCAEC;AAKD,oCAQC;AAED,8BAEC;AAED,sCAEC;AAKD,4BAEC;AAhDD,SAAgB,WAAW,CAAC,GAAgB;IAC1C,OAAO,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC;AAC9B,CAAC;AAED,SAAgB,UAAU,CAAC,GAAgB;IACzC,OAAO,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAC,GAAgB;IACvC,OAAO,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,GAAgB;IAC7C,OAAO,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,GAAgB;IAC3C,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC,SAAS,CAAC;IACvB,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC,SAAS,CAAC;IACvB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,SAAS,CAAC,GAAgB;IACxC,OAAO,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACtD,CAAC;AAED,SAAgB,aAAa,CAAC,GAAgB;IAC5C,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAC,GAAgB,EAAE,KAAa;IACtD,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC","sourcesContent":["/**\n * Authentication context representing the authenticated caller\n * \n * Authenticated caller context.\n * - Solid Token: user provides Bearer or DPoP token\n * - CSS client credentials wrapper: third-party provides client_id/client_secret,\n * API Server exchanges them for a Solid token\n * - Node Token: edge node provides node API key\n */\n\nexport interface SolidAuthContext {\n type: 'solid';\n webId: string;\n accountId?: string;\n clientId?: string;\n clientSecret?: string; // For client credentials auth\n displayName?: string;\n accessToken?: string;\n tokenType?: 'Bearer' | 'DPoP';\n dpopProof?: string;\n /** Whether this was authenticated via the sk-* CSS client credentials wrapper */\n viaApiKey?: boolean;\n /** Whether this principal came from a stateless internal runtime invocation token. */\n internalInvocation?: boolean;\n /** Explicit API scopes bound to constrained principals such as invocation tokens. */\n scopes?: string[];\n}\n\nexport interface NodeAuthContext {\n type: 'node';\n nodeId: string;\n accountId?: string;\n}\n\nexport interface ServiceAuthContext {\n type: 'service';\n serviceType: 'local' | 'business' | 'cloud' | 'compute';\n serviceId: string;\n scopes: string[];\n}\n\nexport type AuthContext = SolidAuthContext | NodeAuthContext | ServiceAuthContext;\n\nexport function isSolidAuth(ctx: AuthContext): ctx is SolidAuthContext {\n return ctx.type === 'solid';\n}\n\nexport function isNodeAuth(ctx: AuthContext): ctx is NodeAuthContext {\n return ctx.type === 'node';\n}\n\n/**\n * Get webId from auth context\n */\nexport function getWebId(ctx: AuthContext): string | undefined {\n return ctx.type === 'solid' ? ctx.webId : undefined;\n}\n\n/**\n * Get display name from auth context\n */\nexport function getDisplayName(ctx: AuthContext): string | undefined {\n return ctx.type === 'solid' ? ctx.displayName : undefined;\n}\n\n/**\n * Get accountId from auth context (if available)\n */\nexport function getAccountId(ctx: AuthContext): string | undefined {\n if (ctx.type === 'solid') {\n return ctx.accountId;\n }\n if (ctx.type === 'node') {\n return ctx.accountId;\n }\n return undefined;\n}\n\nexport function getNodeId(ctx: AuthContext): string | undefined {\n return ctx.type === 'node' ? ctx.nodeId : undefined;\n}\n\nexport function isServiceAuth(ctx: AuthContext): ctx is ServiceAuthContext {\n return ctx.type === 'service';\n}\n\n/**\n * Check if a service auth context has the required scope.\n */\nexport function hasScope(ctx: AuthContext, scope: string): boolean {\n return ctx.type === 'service' && ctx.scopes.includes(scope);\n}\n"]}
|
|
@@ -33,8 +33,10 @@ class ClientCredentialsAuthenticator {
|
|
|
33
33
|
if (!token) {
|
|
34
34
|
return false;
|
|
35
35
|
}
|
|
36
|
-
//
|
|
37
|
-
|
|
36
|
+
// Xpod coding-client API keys are CSS client credentials wrapped as
|
|
37
|
+
// sk-base64(client_id:client_secret). Other bearer formats must be left
|
|
38
|
+
// for their owning authenticators or rejected by the auth chain.
|
|
39
|
+
return token.startsWith('sk-');
|
|
38
40
|
}
|
|
39
41
|
async authenticate(request) {
|
|
40
42
|
const authorization = request.headers.authorization;
|
|
@@ -121,15 +123,6 @@ class ClientCredentialsAuthenticator {
|
|
|
121
123
|
}
|
|
122
124
|
}
|
|
123
125
|
async exchangeForToken(clientId, clientSecret) {
|
|
124
|
-
// 开发模式:跳过 CSS token exchange
|
|
125
|
-
if (process.env.NODE_ENV === 'development') {
|
|
126
|
-
this.logger.warn(`[DEV] Skipping token exchange for ${clientId.slice(0, 8)}...`);
|
|
127
|
-
return {
|
|
128
|
-
success: true,
|
|
129
|
-
token: `dev-token-${clientId}`,
|
|
130
|
-
expiresAt: new Date(Date.now() + 3600000),
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
126
|
try {
|
|
134
127
|
const response = await fetch(this.tokenEndpoint, {
|
|
135
128
|
method: 'POST',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientCredentialsAuthenticator.js","sourceRoot":"","sources":["../../../src/api/auth/ClientCredentialsAuthenticator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { Authenticator, AuthResult } from './Authenticator';\nimport type { SolidAuthContext } from './AuthContext';\nimport { extractAuthoritativeWebIdFromTokenResponse } from './TokenIdentity';\n\n/**\n * Interface for token cache\n */\nexport interface TokenCache {\n get(clientId: string): Promise<{\n token: string;\n tokenType?: 'Bearer' | 'DPoP';\n webId: string;\n expiresAt: Date;\n } | undefined>;\n set(\n clientId: string,\n token: string,\n webId: string,\n expiresAt: Date,\n tokenType?: 'Bearer' | 'DPoP',\n ): Promise<void>;\n}\n\nexport interface ClientCredentialsAuthenticatorOptions {\n tokenCache?: TokenCache;\n /**\n * CSS token endpoint URL\n */\n tokenEndpoint: string;\n}\n\n/**\n * Authenticator for CSS client credentials wrapped in sk-xxx transport format.\n * \n * Format: sk-base64(client_id:client_secret)\n * \n * This authenticator:\n * 1. Decodes the wrapper to get client_id and client_secret\n * 2. Exchanges them for a Solid Token via CSS token endpoint\n * 3. Extracts webId from the token response\n * 4. Returns a SolidAuthContext\n */\nexport class ClientCredentialsAuthenticator implements Authenticator {\n private readonly logger = getLoggerFor(this);\n private readonly tokenCache?: TokenCache;\n private readonly tokenEndpoint: string;\n\n public constructor(options: ClientCredentialsAuthenticatorOptions) {\n this.tokenCache = options.tokenCache;\n this.tokenEndpoint = options.tokenEndpoint;\n }\n\n public canAuthenticate(request: IncomingMessage): boolean {\n const auth = request.headers.authorization;\n if (!auth?.startsWith('Bearer ')) {\n return false;\n }\n // If there's a DPoP header, it's a Solid Token, not a client credentials wrapper.\n if (request.headers.dpop) {\n return false;\n }\n const token = auth.slice(7).trim();\n if (!token) {\n return false;\n }\n // Only handle sk-xxx format or non-JWT tokens\n return token.startsWith('sk-') || !this.isJwt(token);\n }\n\n public async authenticate(request: IncomingMessage): Promise<AuthResult> {\n const authorization = request.headers.authorization;\n if (!authorization?.startsWith('Bearer ')) {\n return { success: false, error: 'Missing Bearer token' };\n }\n\n const token = authorization.slice(7).trim();\n if (!token) {\n return { success: false, error: 'Empty client credentials wrapper' };\n }\n\n try {\n let clientId: string;\n let clientSecret: string;\n\n // Parse sk-xxx format (base64 encoded client_id:client_secret)\n if (token.startsWith('sk-')) {\n const base64 = token.slice(3);\n try {\n const decoded = Buffer.from(base64, 'base64').toString('utf-8');\n const colonIndex = decoded.indexOf(':');\n if (colonIndex === -1) {\n return { success: false, error: 'Invalid client credentials wrapper: missing colon separator' };\n }\n clientId = decoded.slice(0, colonIndex);\n clientSecret = decoded.slice(colonIndex + 1);\n \n if (!clientId || !clientSecret) {\n return { success: false, error: 'Invalid client credentials wrapper: empty client_id or client_secret' };\n }\n } catch {\n return { success: false, error: 'Invalid client credentials wrapper encoding' };\n }\n } else {\n // Non sk- format is intentionally unsupported; Xpod does not keep an API key mirror table.\n return { success: false, error: 'Invalid client credentials wrapper: must start with sk-' };\n }\n\n // Check cache first\n if (this.tokenCache) {\n const cached = await this.tokenCache.get(clientId);\n if (cached && cached.expiresAt > new Date()) {\n this.logger.debug(`Using cached token for ${clientId.slice(0, 8)}...`);\n return {\n success: true,\n context: {\n type: 'solid',\n webId: cached.webId,\n accountId: cached.webId,\n clientId,\n clientSecret,\n accessToken: cached.token,\n tokenType: cached.tokenType ?? 'Bearer',\n viaApiKey: true,\n },\n };\n }\n }\n\n // Exchange for token at CSS endpoint\n this.logger.debug(`Exchanging client credentials at ${this.tokenEndpoint}`);\n const tokenResult = await this.exchangeForToken(clientId, clientSecret);\n this.logger.debug(`Token exchange result: success=${tokenResult.success}, webId=${tokenResult.webId}, error=${tokenResult.error}`);\n \n if (!tokenResult.success || !tokenResult.webId || !tokenResult.token) {\n return { success: false, error: tokenResult.error || 'Token exchange failed' };\n }\n\n // Cache the token\n if (this.tokenCache && tokenResult.expiresAt) {\n await this.tokenCache.set(\n clientId,\n tokenResult.token!,\n tokenResult.webId,\n tokenResult.expiresAt,\n tokenResult.tokenType,\n );\n }\n\n const context: SolidAuthContext = {\n type: 'solid',\n webId: tokenResult.webId,\n accountId: tokenResult.webId,\n clientId,\n clientSecret,\n accessToken: tokenResult.token,\n tokenType: tokenResult.tokenType ?? 'Bearer',\n viaApiKey: true,\n };\n\n this.logger.debug(`Authenticated client credentials for webId: ${tokenResult.webId}`);\n return { success: true, context };\n } catch (error) {\n this.logger.error(`Client credentials authentication error: ${error}`);\n return { success: false, error: 'Authentication failed' };\n }\n }\n\n private async exchangeForToken(clientId: string, clientSecret: string): Promise<{\n success: boolean;\n token?: string;\n tokenType?: 'Bearer' | 'DPoP';\n webId?: string;\n expiresAt?: Date;\n error?: string;\n }> {\n // 开发模式:跳过 CSS token exchange\n if (process.env.NODE_ENV === 'development') {\n this.logger.warn(`[DEV] Skipping token exchange for ${clientId.slice(0, 8)}...`);\n return {\n success: true,\n token: `dev-token-${clientId}`,\n expiresAt: new Date(Date.now() + 3600000),\n };\n }\n\n try {\n const response = await fetch(this.tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: clientId,\n client_secret: clientSecret,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n this.logger.warn(`Token exchange failed: ${response.status} ${error}`);\n return { success: false, error: `Token exchange failed: ${response.status}` };\n }\n\n const data = await response.json() as {\n access_token: string;\n expires_in?: number;\n token_type: string;\n webid?: string; // CSS returns webid in response\n };\n\n // Extract webId from token response or decode from JWT\n const webId = extractAuthoritativeWebIdFromTokenResponse(data);\n\n if (!webId) {\n return { success: false, error: 'Could not determine webId from token response' };\n }\n\n const expiresAt = data.expires_in\n ? new Date(Date.now() + data.expires_in * 1000 - 60000) // 1 min buffer\n : new Date(Date.now() + 3600000); // Default 1 hour\n\n return {\n success: true,\n token: data.access_token,\n tokenType: data.token_type?.toUpperCase() === 'DPOP' ? 'DPoP' : 'Bearer',\n webId,\n expiresAt,\n };\n } catch (error) {\n this.logger.error(`Token exchange error: ${error}`);\n return { success: false, error: 'Token exchange failed' };\n }\n }\n\n private isJwt(token: string): boolean {\n return /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/.test(token);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ClientCredentialsAuthenticator.js","sourceRoot":"","sources":["../../../src/api/auth/ClientCredentialsAuthenticator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { Authenticator, AuthResult } from './Authenticator';\nimport type { SolidAuthContext } from './AuthContext';\nimport { extractAuthoritativeWebIdFromTokenResponse } from './TokenIdentity';\n\n/**\n * Interface for token cache\n */\nexport interface TokenCache {\n get(clientId: string): Promise<{\n token: string;\n tokenType?: 'Bearer' | 'DPoP';\n webId: string;\n expiresAt: Date;\n } | undefined>;\n set(\n clientId: string,\n token: string,\n webId: string,\n expiresAt: Date,\n tokenType?: 'Bearer' | 'DPoP',\n ): Promise<void>;\n}\n\nexport interface ClientCredentialsAuthenticatorOptions {\n tokenCache?: TokenCache;\n /**\n * CSS token endpoint URL\n */\n tokenEndpoint: string;\n}\n\n/**\n * Authenticator for CSS client credentials wrapped in sk-xxx transport format.\n * \n * Format: sk-base64(client_id:client_secret)\n * \n * This authenticator:\n * 1. Decodes the wrapper to get client_id and client_secret\n * 2. Exchanges them for a Solid Token via CSS token endpoint\n * 3. Extracts webId from the token response\n * 4. Returns a SolidAuthContext\n */\nexport class ClientCredentialsAuthenticator implements Authenticator {\n private readonly logger = getLoggerFor(this);\n private readonly tokenCache?: TokenCache;\n private readonly tokenEndpoint: string;\n\n public constructor(options: ClientCredentialsAuthenticatorOptions) {\n this.tokenCache = options.tokenCache;\n this.tokenEndpoint = options.tokenEndpoint;\n }\n\n public canAuthenticate(request: IncomingMessage): boolean {\n const auth = request.headers.authorization;\n if (!auth?.startsWith('Bearer ')) {\n return false;\n }\n // If there's a DPoP header, it's a Solid Token, not a client credentials wrapper.\n if (request.headers.dpop) {\n return false;\n }\n const token = auth.slice(7).trim();\n if (!token) {\n return false;\n }\n // Xpod coding-client API keys are CSS client credentials wrapped as\n // sk-base64(client_id:client_secret). Other bearer formats must be left\n // for their owning authenticators or rejected by the auth chain.\n return token.startsWith('sk-');\n }\n\n public async authenticate(request: IncomingMessage): Promise<AuthResult> {\n const authorization = request.headers.authorization;\n if (!authorization?.startsWith('Bearer ')) {\n return { success: false, error: 'Missing Bearer token' };\n }\n\n const token = authorization.slice(7).trim();\n if (!token) {\n return { success: false, error: 'Empty client credentials wrapper' };\n }\n\n try {\n let clientId: string;\n let clientSecret: string;\n\n // Parse sk-xxx format (base64 encoded client_id:client_secret)\n if (token.startsWith('sk-')) {\n const base64 = token.slice(3);\n try {\n const decoded = Buffer.from(base64, 'base64').toString('utf-8');\n const colonIndex = decoded.indexOf(':');\n if (colonIndex === -1) {\n return { success: false, error: 'Invalid client credentials wrapper: missing colon separator' };\n }\n clientId = decoded.slice(0, colonIndex);\n clientSecret = decoded.slice(colonIndex + 1);\n \n if (!clientId || !clientSecret) {\n return { success: false, error: 'Invalid client credentials wrapper: empty client_id or client_secret' };\n }\n } catch {\n return { success: false, error: 'Invalid client credentials wrapper encoding' };\n }\n } else {\n // Non sk- format is intentionally unsupported; Xpod does not keep an API key mirror table.\n return { success: false, error: 'Invalid client credentials wrapper: must start with sk-' };\n }\n\n // Check cache first\n if (this.tokenCache) {\n const cached = await this.tokenCache.get(clientId);\n if (cached && cached.expiresAt > new Date()) {\n this.logger.debug(`Using cached token for ${clientId.slice(0, 8)}...`);\n return {\n success: true,\n context: {\n type: 'solid',\n webId: cached.webId,\n accountId: cached.webId,\n clientId,\n clientSecret,\n accessToken: cached.token,\n tokenType: cached.tokenType ?? 'Bearer',\n viaApiKey: true,\n },\n };\n }\n }\n\n // Exchange for token at CSS endpoint\n this.logger.debug(`Exchanging client credentials at ${this.tokenEndpoint}`);\n const tokenResult = await this.exchangeForToken(clientId, clientSecret);\n this.logger.debug(`Token exchange result: success=${tokenResult.success}, webId=${tokenResult.webId}, error=${tokenResult.error}`);\n \n if (!tokenResult.success || !tokenResult.webId || !tokenResult.token) {\n return { success: false, error: tokenResult.error || 'Token exchange failed' };\n }\n\n // Cache the token\n if (this.tokenCache && tokenResult.expiresAt) {\n await this.tokenCache.set(\n clientId,\n tokenResult.token!,\n tokenResult.webId,\n tokenResult.expiresAt,\n tokenResult.tokenType,\n );\n }\n\n const context: SolidAuthContext = {\n type: 'solid',\n webId: tokenResult.webId,\n accountId: tokenResult.webId,\n clientId,\n clientSecret,\n accessToken: tokenResult.token,\n tokenType: tokenResult.tokenType ?? 'Bearer',\n viaApiKey: true,\n };\n\n this.logger.debug(`Authenticated client credentials for webId: ${tokenResult.webId}`);\n return { success: true, context };\n } catch (error) {\n this.logger.error(`Client credentials authentication error: ${error}`);\n return { success: false, error: 'Authentication failed' };\n }\n }\n\n private async exchangeForToken(clientId: string, clientSecret: string): Promise<{\n success: boolean;\n token?: string;\n tokenType?: 'Bearer' | 'DPoP';\n webId?: string;\n expiresAt?: Date;\n error?: string;\n }> {\n try {\n const response = await fetch(this.tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: clientId,\n client_secret: clientSecret,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n this.logger.warn(`Token exchange failed: ${response.status} ${error}`);\n return { success: false, error: `Token exchange failed: ${response.status}` };\n }\n\n const data = await response.json() as {\n access_token: string;\n expires_in?: number;\n token_type: string;\n webid?: string; // CSS returns webid in response\n };\n\n // Extract webId from token response or decode from JWT\n const webId = extractAuthoritativeWebIdFromTokenResponse(data);\n\n if (!webId) {\n return { success: false, error: 'Could not determine webId from token response' };\n }\n\n const expiresAt = data.expires_in\n ? new Date(Date.now() + data.expires_in * 1000 - 60000) // 1 min buffer\n : new Date(Date.now() + 3600000); // Default 1 hour\n\n return {\n success: true,\n token: data.access_token,\n tokenType: data.token_type?.toUpperCase() === 'DPOP' ? 'DPoP' : 'Bearer',\n webId,\n expiresAt,\n };\n } catch (error) {\n this.logger.error(`Token exchange error: ${error}`);\n return { success: false, error: 'Token exchange failed' };\n }\n }\n\n private isJwt(token: string): boolean {\n return /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/.test(token);\n }\n}\n"]}
|
|
@@ -20,8 +20,8 @@ export interface DefaultAgentConfig {
|
|
|
20
20
|
export interface DefaultAgentAiConnection {
|
|
21
21
|
/** Xpod AI Connection endpoint, usually the current /v1 gateway URL */
|
|
22
22
|
baseUrl: string;
|
|
23
|
-
/**
|
|
24
|
-
|
|
23
|
+
/** Solid client-credentials API key for this invocation */
|
|
24
|
+
apiKey: string;
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Default Agent 会话上下文
|
|
@@ -91,7 +91,7 @@ function getDefaultAgentConfig(input = {}) {
|
|
|
91
91
|
* 检查 Default Agent 是否可用
|
|
92
92
|
*/
|
|
93
93
|
function isDefaultAgentAvailable(input = {}) {
|
|
94
|
-
return Boolean(input.connection?.baseUrl?.trim() && input.connection?.
|
|
94
|
+
return Boolean(input.connection?.baseUrl?.trim() && input.connection?.apiKey?.trim());
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
97
|
* Default Agent System Prompt
|
|
@@ -174,7 +174,7 @@ curl -s -X PUT \\
|
|
|
174
174
|
function buildClaudeEnv(config, context) {
|
|
175
175
|
const connection = (0, safe_env_1.requireAiConnectionRuntimeConfig)({
|
|
176
176
|
baseUrl: config.connection?.baseUrl,
|
|
177
|
-
apiKey: config.connection?.
|
|
177
|
+
apiKey: config.connection?.apiKey,
|
|
178
178
|
model: config.model,
|
|
179
179
|
}, 'Default Agent');
|
|
180
180
|
return {
|
|
@@ -204,7 +204,7 @@ async function runDefaultAgent(message, context, options) {
|
|
|
204
204
|
return {
|
|
205
205
|
content: '',
|
|
206
206
|
success: false,
|
|
207
|
-
error: 'Default Agent not configured: AI Connection baseUrl and
|
|
207
|
+
error: 'Default Agent not configured: AI Connection baseUrl and API key are required',
|
|
208
208
|
};
|
|
209
209
|
}
|
|
210
210
|
const abortController = new AbortController();
|
|
@@ -270,7 +270,7 @@ async function runDefaultAgent(message, context, options) {
|
|
|
270
270
|
async function* streamDefaultAgent(message, context, options) {
|
|
271
271
|
const config = getDefaultAgentConfig(options);
|
|
272
272
|
if (!isDefaultAgentAvailable(config)) {
|
|
273
|
-
throw new Error('Default Agent not configured: AI Connection baseUrl and
|
|
273
|
+
throw new Error('Default Agent not configured: AI Connection baseUrl and API key are required');
|
|
274
274
|
}
|
|
275
275
|
const abortController = new AbortController();
|
|
276
276
|
const timeout = options?.timeout || 60000;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-agent.js","sourceRoot":"","sources":["../../../src/api/chatkit/default-agent.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Default Agent\n *\n * 基于 Claude Code SDK 的默认 AI Agent,用于:\n * 1. 用户未配置 AI 时的降级方案\n * 2. 帮助用户完成初始化配置\n * 3. 识别并收纳结构化数据到 Pod\n */\n\nimport { getLoggerFor } from 'global-logger-factory';\nimport {\n projectAnthropicCompatibleEnv,\n requireAiConnectionRuntimeConfig,\n sanitizeRuntimeEnv,\n} from '../../runtime/safe-env';\n\n/**\n * CC SDK 运行时消息结构(避免直接静态导入 ESM 包导致 CJS 启动崩溃)\n */\ntype ClaudeAssistantBlock = { type: 'text'; text: string } | { type: string; [key: string]: unknown };\ntype ClaudeAssistantMessage = { type: 'assistant'; message: { content: ClaudeAssistantBlock[] | unknown } };\ntype ClaudeResultMessage = { type: 'result'; subtype?: string; result?: string; total_cost_usd?: number };\ntype ClaudeQueryMessage = ClaudeAssistantMessage | ClaudeResultMessage | { type: string; [key: string]: unknown };\ntype ClaudeQuery = (args: unknown) => AsyncIterable<ClaudeQueryMessage>;\n\nlet cachedClaudeQuery: ClaudeQuery | undefined;\n\nasync function loadClaudeQuery(): Promise<ClaudeQuery> {\n if (cachedClaudeQuery) {\n return cachedClaudeQuery;\n }\n\n // Keep native dynamic import so CJS build can load ESM-only SDK lazily.\n const mod = await import('@anthropic-ai/claude-agent-sdk') as Record<string, unknown>;\n const maybeQuery = (mod as { query?: unknown }).query;\n\n if (typeof maybeQuery !== 'function') {\n throw new Error('Invalid Claude Agent SDK: query() not found');\n }\n\n cachedClaudeQuery = maybeQuery as ClaudeQuery;\n return cachedClaudeQuery;\n}\n\nconst logger = getLoggerFor('DefaultAgent');\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isAssistantMessage(value: ClaudeQueryMessage): value is ClaudeAssistantMessage {\n return value.type === 'assistant' && isObject((value as { message?: unknown }).message);\n}\n\nfunction isResultMessage(value: ClaudeQueryMessage): value is ClaudeResultMessage {\n return value.type === 'result';\n}\n\nfunction getAssistantText(value: ClaudeQueryMessage): string {\n if (!isAssistantMessage(value)) {\n return '';\n }\n\n const content = value.message.content;\n if (!Array.isArray(content)) {\n return '';\n }\n\n let text = '';\n for (const block of content) {\n if (isObject(block) && block.type === 'text' && typeof block.text === 'string') {\n text += block.text;\n }\n }\n\n return text;\n}\n\n/**\n * Default Agent 配置\n */\nexport interface DefaultAgentConfig {\n /** Claude Code 可执行文件路径 */\n claudeCodePath?: string;\n /** AI Connection invocation endpoint/key */\n connection?: DefaultAgentAiConnection;\n /** 模型 */\n model?: string;\n}\n\nexport interface DefaultAgentAiConnection {\n /** Xpod AI Connection endpoint, usually the current /v1 gateway URL */\n baseUrl: string;\n /** Xpod-issued gateway key for this invocation */\n gatewayKey: string;\n}\n\n/**\n * Default Agent 会话上下文\n */\nexport interface DefaultAgentContext {\n /** 用户的访问令牌 */\n solidToken: string;\n /** 用户的 Pod 基础 URL */\n podBaseUrl: string;\n /** 用户 WebID */\n webId?: string;\n}\n\n/**\n * Default Agent 响应\n */\nexport interface DefaultAgentResponse {\n /** 响应内容 */\n content: string;\n /** 是否成功 */\n success: boolean;\n /** 错误信息 */\n error?: string;\n /** 使用的模型 */\n model?: string;\n /** 花费(USD) */\n costUsd?: number;\n}\n\nexport interface DefaultAgentRunOptions {\n timeout?: number;\n maxTurns?: number;\n connection?: DefaultAgentAiConnection;\n model?: string;\n}\n\n/**\n * 获取 Default Agent 配置\n */\nexport function getDefaultAgentConfig(input: {\n connection?: DefaultAgentAiConnection;\n model?: string;\n} = {}): DefaultAgentConfig {\n return {\n claudeCodePath: process.env.CLAUDE_CODE_PATH || undefined,\n connection: input.connection,\n model: input.model,\n };\n}\n\n/**\n * 检查 Default Agent 是否可用\n */\nexport function isDefaultAgentAvailable(input: {\n connection?: DefaultAgentAiConnection;\n} = {}): boolean {\n return Boolean(input.connection?.baseUrl?.trim() && input.connection?.gatewayKey?.trim());\n}\n\n/**\n * Default Agent System Prompt\n */\nconst DEFAULT_AGENT_SYSTEM_PROMPT = `你是 Xpod Default Agent,运行在用户的 Solid Pod 上。\n\n## 你的职责\n1. 帮助用户完成初始化配置(特别是 AI 配置)\n2. 识别用户消息中的结构化数据并存储到 Pod\n3. 按语义网规范组织数据\n\n## 数据收纳能力\n当用户的消息中包含以下类型的信息时,识别并保存:\n\n### AI 配置(最重要)\n- Provider、Model、Base URL 与认证方式\n- 引导用户通过 AI Connection 的 Connect UI/API 完成授权或录入凭证\n- 密钥由 SecretCell 安全保存;不要要求用户在聊天中发送密钥,也不要把明文凭证写入 Pod 资源\n\n### 联系人\n- 姓名、邮箱、电话、WebID\n- 存储位置:/contacts/<name>.ttl\n- 词汇表:vCard (http://www.w3.org/2006/vcard/ns#)\n\n### 日程/事件\n- 时间、地点、标题\n- 存储位置:/calendar/events.ttl\n- 词汇表:schema:Event\n\n### 笔记\n- 标题、内容\n- 存储位置:/notes/<title>.ttl\n- 词汇表:schema:Note\n\n## Pod 访问方式\n使用 curl 访问用户 Pod,鉴权信息已在环境变量中:\n\n### 读取资源\n\\`\\`\\`bash\ncurl -s -H \"Authorization: Bearer $SOLID_TOKEN\" \"$POD_BASE_URL<path>\"\n\\`\\`\\`\n\n### 写入 Turtle 数据\n\\`\\`\\`bash\ncurl -s -X PUT \\\\\n -H \"Authorization: Bearer $SOLID_TOKEN\" \\\\\n -H \"Content-Type: text/turtle\" \\\\\n -d '<turtle-content>' \\\\\n \"$POD_BASE_URL<path>\"\n\\`\\`\\`\n\n### 创建容器(目录)\n\\`\\`\\`bash\ncurl -s -X PUT \\\\\n -H \"Authorization: Bearer $SOLID_TOKEN\" \\\\\n -H \"Content-Type: text/turtle\" \\\\\n -H \"Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel=\\\\\"type\\\\\"\" \\\\\n \"$POD_BASE_URL<path>/\"\n\\`\\`\\`\n\n## 语义网规范\n使用 Turtle 格式,优先使用标准词汇表。\n\n### 联系人示例\n\\`\\`\\`turtle\n@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .\n\n<#person> a vcard:Individual ;\n vcard:fn \"张三\" ;\n vcard:hasEmail <mailto:zhangsan@example.com> ;\n vcard:hasTelephone <tel:+8613800138000> .\n\\`\\`\\`\n\n## 交互原则\n1. 识别到结构化数据时,直接保存(不需要确认)\n2. 保存成功后简短告知用户\n3. 如果是 AI 配置,引导用户打开 AI Connection 的 Connect UI 或调用 Connect API;不要代为收集或写入明文密钥\n4. 其他情况正常对话即可\n5. 回复使用中文`;\n\n\nfunction buildClaudeEnv(config: DefaultAgentConfig, context: DefaultAgentContext): NodeJS.ProcessEnv {\n const connection = requireAiConnectionRuntimeConfig({\n baseUrl: config.connection?.baseUrl,\n apiKey: config.connection?.gatewayKey,\n model: config.model,\n }, 'Default Agent');\n\n return {\n ...sanitizeRuntimeEnv(process.env),\n ...projectAnthropicCompatibleEnv(connection),\n SOLID_TOKEN: context.solidToken,\n POD_BASE_URL: context.podBaseUrl,\n };\n}\n\nfunction resolveClaudeModel(config: DefaultAgentConfig): string {\n const model = (config.model || '').trim();\n if (!model) {\n return 'sonnet';\n }\n\n if (model.startsWith('claude') || model.includes('anthropic/')) {\n return model;\n }\n\n // Non-Anthropic models (OpenRouter route) are mapped via ANTHROPIC_DEFAULT_SONNET_MODEL.\n return 'sonnet';\n}\n\n/**\n * 运行 Default Agent\n */\nexport async function runDefaultAgent(\n message: string,\n context: DefaultAgentContext,\n options?: DefaultAgentRunOptions,\n): Promise<DefaultAgentResponse> {\n const config = getDefaultAgentConfig(options);\n\n if (!isDefaultAgentAvailable(config)) {\n return {\n content: '',\n success: false,\n error: 'Default Agent not configured: AI Connection baseUrl and gateway key are required',\n };\n }\n\n const abortController = new AbortController();\n const timeout = options?.timeout || 60000;\n\n const timeoutId = setTimeout(() => {\n logger.warn('Default Agent timeout, aborting...');\n abortController.abort();\n }, timeout);\n\n try {\n logger.info(`Running Default Agent for Pod: ${context.podBaseUrl}`);\n\n const queryFn = await loadClaudeQuery();\n const q = queryFn({\n prompt: message,\n options: {\n abortController,\n pathToClaudeCodeExecutable: config.claudeCodePath,\n env: buildClaudeEnv(config, context),\n systemPrompt: DEFAULT_AGENT_SYSTEM_PROMPT,\n model: resolveClaudeModel(config),\n permissionMode: 'acceptEdits',\n allowedTools: ['Bash', 'Read', 'Write'],\n maxTurns: options?.maxTurns || 10,\n },\n });\n\n let content = '';\n let costUsd: number | undefined;\n\n for await (const msg of q) {\n const assistantText = getAssistantText(msg);\n if (assistantText) {\n content += assistantText;\n }\n\n if (isResultMessage(msg)) {\n if (msg.subtype === 'success' && typeof msg.result === 'string' && msg.result.trim()) {\n content = msg.result;\n }\n if (typeof msg.total_cost_usd === 'number') {\n costUsd = msg.total_cost_usd;\n }\n }\n }\n\n clearTimeout(timeoutId);\n\n return {\n content,\n success: true,\n model: config.model || resolveClaudeModel(config),\n costUsd,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Default Agent error: ${errorMessage}`);\n\n return {\n content: '',\n success: false,\n error: errorMessage,\n };\n }\n}\n\n/**\n * 流式运行 Default Agent\n */\nexport async function* streamDefaultAgent(\n message: string,\n context: DefaultAgentContext,\n options?: DefaultAgentRunOptions,\n): AsyncGenerator<string, void, unknown> {\n const config = getDefaultAgentConfig(options);\n\n if (!isDefaultAgentAvailable(config)) {\n throw new Error('Default Agent not configured: AI Connection baseUrl and gateway key are required');\n }\n\n const abortController = new AbortController();\n const timeout = options?.timeout || 60000;\n\n const timeoutId = setTimeout(() => {\n logger.warn('Default Agent timeout, aborting...');\n abortController.abort();\n }, timeout);\n\n try {\n logger.info(`Streaming Default Agent for Pod: ${context.podBaseUrl}`);\n\n const queryFn = await loadClaudeQuery();\n const q = queryFn({\n prompt: message,\n options: {\n abortController,\n pathToClaudeCodeExecutable: config.claudeCodePath,\n env: buildClaudeEnv(config, context),\n systemPrompt: DEFAULT_AGENT_SYSTEM_PROMPT,\n model: resolveClaudeModel(config),\n permissionMode: 'acceptEdits',\n allowedTools: ['Bash', 'Read', 'Write'],\n maxTurns: options?.maxTurns || 10,\n includePartialMessages: true,\n },\n });\n\n for await (const msg of q) {\n const assistantText = getAssistantText(msg);\n if (assistantText) {\n yield assistantText;\n }\n }\n\n clearTimeout(timeoutId);\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"default-agent.js","sourceRoot":"","sources":["../../../src/api/chatkit/default-agent.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Default Agent\n *\n * 基于 Claude Code SDK 的默认 AI Agent,用于:\n * 1. 用户未配置 AI 时的降级方案\n * 2. 帮助用户完成初始化配置\n * 3. 识别并收纳结构化数据到 Pod\n */\n\nimport { getLoggerFor } from 'global-logger-factory';\nimport {\n projectAnthropicCompatibleEnv,\n requireAiConnectionRuntimeConfig,\n sanitizeRuntimeEnv,\n} from '../../runtime/safe-env';\n\n/**\n * CC SDK 运行时消息结构(避免直接静态导入 ESM 包导致 CJS 启动崩溃)\n */\ntype ClaudeAssistantBlock = { type: 'text'; text: string } | { type: string; [key: string]: unknown };\ntype ClaudeAssistantMessage = { type: 'assistant'; message: { content: ClaudeAssistantBlock[] | unknown } };\ntype ClaudeResultMessage = { type: 'result'; subtype?: string; result?: string; total_cost_usd?: number };\ntype ClaudeQueryMessage = ClaudeAssistantMessage | ClaudeResultMessage | { type: string; [key: string]: unknown };\ntype ClaudeQuery = (args: unknown) => AsyncIterable<ClaudeQueryMessage>;\n\nlet cachedClaudeQuery: ClaudeQuery | undefined;\n\nasync function loadClaudeQuery(): Promise<ClaudeQuery> {\n if (cachedClaudeQuery) {\n return cachedClaudeQuery;\n }\n\n // Keep native dynamic import so CJS build can load ESM-only SDK lazily.\n const mod = await import('@anthropic-ai/claude-agent-sdk') as Record<string, unknown>;\n const maybeQuery = (mod as { query?: unknown }).query;\n\n if (typeof maybeQuery !== 'function') {\n throw new Error('Invalid Claude Agent SDK: query() not found');\n }\n\n cachedClaudeQuery = maybeQuery as ClaudeQuery;\n return cachedClaudeQuery;\n}\n\nconst logger = getLoggerFor('DefaultAgent');\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isAssistantMessage(value: ClaudeQueryMessage): value is ClaudeAssistantMessage {\n return value.type === 'assistant' && isObject((value as { message?: unknown }).message);\n}\n\nfunction isResultMessage(value: ClaudeQueryMessage): value is ClaudeResultMessage {\n return value.type === 'result';\n}\n\nfunction getAssistantText(value: ClaudeQueryMessage): string {\n if (!isAssistantMessage(value)) {\n return '';\n }\n\n const content = value.message.content;\n if (!Array.isArray(content)) {\n return '';\n }\n\n let text = '';\n for (const block of content) {\n if (isObject(block) && block.type === 'text' && typeof block.text === 'string') {\n text += block.text;\n }\n }\n\n return text;\n}\n\n/**\n * Default Agent 配置\n */\nexport interface DefaultAgentConfig {\n /** Claude Code 可执行文件路径 */\n claudeCodePath?: string;\n /** AI Connection invocation endpoint/key */\n connection?: DefaultAgentAiConnection;\n /** 模型 */\n model?: string;\n}\n\nexport interface DefaultAgentAiConnection {\n /** Xpod AI Connection endpoint, usually the current /v1 gateway URL */\n baseUrl: string;\n /** Solid client-credentials API key for this invocation */\n apiKey: string;\n}\n\n/**\n * Default Agent 会话上下文\n */\nexport interface DefaultAgentContext {\n /** 用户的访问令牌 */\n solidToken: string;\n /** 用户的 Pod 基础 URL */\n podBaseUrl: string;\n /** 用户 WebID */\n webId?: string;\n}\n\n/**\n * Default Agent 响应\n */\nexport interface DefaultAgentResponse {\n /** 响应内容 */\n content: string;\n /** 是否成功 */\n success: boolean;\n /** 错误信息 */\n error?: string;\n /** 使用的模型 */\n model?: string;\n /** 花费(USD) */\n costUsd?: number;\n}\n\nexport interface DefaultAgentRunOptions {\n timeout?: number;\n maxTurns?: number;\n connection?: DefaultAgentAiConnection;\n model?: string;\n}\n\n/**\n * 获取 Default Agent 配置\n */\nexport function getDefaultAgentConfig(input: {\n connection?: DefaultAgentAiConnection;\n model?: string;\n} = {}): DefaultAgentConfig {\n return {\n claudeCodePath: process.env.CLAUDE_CODE_PATH || undefined,\n connection: input.connection,\n model: input.model,\n };\n}\n\n/**\n * 检查 Default Agent 是否可用\n */\nexport function isDefaultAgentAvailable(input: {\n connection?: DefaultAgentAiConnection;\n} = {}): boolean {\n return Boolean(input.connection?.baseUrl?.trim() && input.connection?.apiKey?.trim());\n}\n\n/**\n * Default Agent System Prompt\n */\nconst DEFAULT_AGENT_SYSTEM_PROMPT = `你是 Xpod Default Agent,运行在用户的 Solid Pod 上。\n\n## 你的职责\n1. 帮助用户完成初始化配置(特别是 AI 配置)\n2. 识别用户消息中的结构化数据并存储到 Pod\n3. 按语义网规范组织数据\n\n## 数据收纳能力\n当用户的消息中包含以下类型的信息时,识别并保存:\n\n### AI 配置(最重要)\n- Provider、Model、Base URL 与认证方式\n- 引导用户通过 AI Connection 的 Connect UI/API 完成授权或录入凭证\n- 密钥由 SecretCell 安全保存;不要要求用户在聊天中发送密钥,也不要把明文凭证写入 Pod 资源\n\n### 联系人\n- 姓名、邮箱、电话、WebID\n- 存储位置:/contacts/<name>.ttl\n- 词汇表:vCard (http://www.w3.org/2006/vcard/ns#)\n\n### 日程/事件\n- 时间、地点、标题\n- 存储位置:/calendar/events.ttl\n- 词汇表:schema:Event\n\n### 笔记\n- 标题、内容\n- 存储位置:/notes/<title>.ttl\n- 词汇表:schema:Note\n\n## Pod 访问方式\n使用 curl 访问用户 Pod,鉴权信息已在环境变量中:\n\n### 读取资源\n\\`\\`\\`bash\ncurl -s -H \"Authorization: Bearer $SOLID_TOKEN\" \"$POD_BASE_URL<path>\"\n\\`\\`\\`\n\n### 写入 Turtle 数据\n\\`\\`\\`bash\ncurl -s -X PUT \\\\\n -H \"Authorization: Bearer $SOLID_TOKEN\" \\\\\n -H \"Content-Type: text/turtle\" \\\\\n -d '<turtle-content>' \\\\\n \"$POD_BASE_URL<path>\"\n\\`\\`\\`\n\n### 创建容器(目录)\n\\`\\`\\`bash\ncurl -s -X PUT \\\\\n -H \"Authorization: Bearer $SOLID_TOKEN\" \\\\\n -H \"Content-Type: text/turtle\" \\\\\n -H \"Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel=\\\\\"type\\\\\"\" \\\\\n \"$POD_BASE_URL<path>/\"\n\\`\\`\\`\n\n## 语义网规范\n使用 Turtle 格式,优先使用标准词汇表。\n\n### 联系人示例\n\\`\\`\\`turtle\n@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .\n\n<#person> a vcard:Individual ;\n vcard:fn \"张三\" ;\n vcard:hasEmail <mailto:zhangsan@example.com> ;\n vcard:hasTelephone <tel:+8613800138000> .\n\\`\\`\\`\n\n## 交互原则\n1. 识别到结构化数据时,直接保存(不需要确认)\n2. 保存成功后简短告知用户\n3. 如果是 AI 配置,引导用户打开 AI Connection 的 Connect UI 或调用 Connect API;不要代为收集或写入明文密钥\n4. 其他情况正常对话即可\n5. 回复使用中文`;\n\n\nfunction buildClaudeEnv(config: DefaultAgentConfig, context: DefaultAgentContext): NodeJS.ProcessEnv {\n const connection = requireAiConnectionRuntimeConfig({\n baseUrl: config.connection?.baseUrl,\n apiKey: config.connection?.apiKey,\n model: config.model,\n }, 'Default Agent');\n\n return {\n ...sanitizeRuntimeEnv(process.env),\n ...projectAnthropicCompatibleEnv(connection),\n SOLID_TOKEN: context.solidToken,\n POD_BASE_URL: context.podBaseUrl,\n };\n}\n\nfunction resolveClaudeModel(config: DefaultAgentConfig): string {\n const model = (config.model || '').trim();\n if (!model) {\n return 'sonnet';\n }\n\n if (model.startsWith('claude') || model.includes('anthropic/')) {\n return model;\n }\n\n // Non-Anthropic models (OpenRouter route) are mapped via ANTHROPIC_DEFAULT_SONNET_MODEL.\n return 'sonnet';\n}\n\n/**\n * 运行 Default Agent\n */\nexport async function runDefaultAgent(\n message: string,\n context: DefaultAgentContext,\n options?: DefaultAgentRunOptions,\n): Promise<DefaultAgentResponse> {\n const config = getDefaultAgentConfig(options);\n\n if (!isDefaultAgentAvailable(config)) {\n return {\n content: '',\n success: false,\n error: 'Default Agent not configured: AI Connection baseUrl and API key are required',\n };\n }\n\n const abortController = new AbortController();\n const timeout = options?.timeout || 60000;\n\n const timeoutId = setTimeout(() => {\n logger.warn('Default Agent timeout, aborting...');\n abortController.abort();\n }, timeout);\n\n try {\n logger.info(`Running Default Agent for Pod: ${context.podBaseUrl}`);\n\n const queryFn = await loadClaudeQuery();\n const q = queryFn({\n prompt: message,\n options: {\n abortController,\n pathToClaudeCodeExecutable: config.claudeCodePath,\n env: buildClaudeEnv(config, context),\n systemPrompt: DEFAULT_AGENT_SYSTEM_PROMPT,\n model: resolveClaudeModel(config),\n permissionMode: 'acceptEdits',\n allowedTools: ['Bash', 'Read', 'Write'],\n maxTurns: options?.maxTurns || 10,\n },\n });\n\n let content = '';\n let costUsd: number | undefined;\n\n for await (const msg of q) {\n const assistantText = getAssistantText(msg);\n if (assistantText) {\n content += assistantText;\n }\n\n if (isResultMessage(msg)) {\n if (msg.subtype === 'success' && typeof msg.result === 'string' && msg.result.trim()) {\n content = msg.result;\n }\n if (typeof msg.total_cost_usd === 'number') {\n costUsd = msg.total_cost_usd;\n }\n }\n }\n\n clearTimeout(timeoutId);\n\n return {\n content,\n success: true,\n model: config.model || resolveClaudeModel(config),\n costUsd,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Default Agent error: ${errorMessage}`);\n\n return {\n content: '',\n success: false,\n error: errorMessage,\n };\n }\n}\n\n/**\n * 流式运行 Default Agent\n */\nexport async function* streamDefaultAgent(\n message: string,\n context: DefaultAgentContext,\n options?: DefaultAgentRunOptions,\n): AsyncGenerator<string, void, unknown> {\n const config = getDefaultAgentConfig(options);\n\n if (!isDefaultAgentAvailable(config)) {\n throw new Error('Default Agent not configured: AI Connection baseUrl and API key are required');\n }\n\n const abortController = new AbortController();\n const timeout = options?.timeout || 60000;\n\n const timeoutId = setTimeout(() => {\n logger.warn('Default Agent timeout, aborting...');\n abortController.abort();\n }, timeout);\n\n try {\n logger.info(`Streaming Default Agent for Pod: ${context.podBaseUrl}`);\n\n const queryFn = await loadClaudeQuery();\n const q = queryFn({\n prompt: message,\n options: {\n abortController,\n pathToClaudeCodeExecutable: config.claudeCodePath,\n env: buildClaudeEnv(config, context),\n systemPrompt: DEFAULT_AGENT_SYSTEM_PROMPT,\n model: resolveClaudeModel(config),\n permissionMode: 'acceptEdits',\n allowedTools: ['Bash', 'Read', 'Write'],\n maxTurns: options?.maxTurns || 10,\n includePartialMessages: true,\n },\n });\n\n for await (const msg of q) {\n const assistantText = getAssistantText(msg);\n if (assistantText) {\n yield assistantText;\n }\n }\n\n clearTimeout(timeoutId);\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n}\n"]}
|
|
@@ -304,7 +304,7 @@ class AcpAgentRuntime {
|
|
|
304
304
|
}
|
|
305
305
|
const connection = (0, safe_env_1.requireAiConnectionRuntimeConfig)({
|
|
306
306
|
baseUrl: aiConnection?.baseUrl,
|
|
307
|
-
apiKey: aiConnection?.
|
|
307
|
+
apiKey: aiConnection?.apiKey,
|
|
308
308
|
model: aiConnection?.model ?? agentConfig?.model,
|
|
309
309
|
}, `${type} ACP runtime`);
|
|
310
310
|
const home = this.getIsolatedHomeDir(type, threadId, workdir);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AcpAgentRuntime.js","sourceRoot":"","sources":["../../../../src/api/chatkit/runtime/AcpAgentRuntime.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'node:path';\nimport * as crypto from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { WorkspaceRef } from '../../workspace/types';\nimport { PACKAGE_ROOT } from '../../../runtime';\nimport {\n projectAnthropicCompatibleEnv,\n projectOpenAiCompatibleEnv,\n requireAiConnectionRuntimeConfig,\n} from '../../../runtime/safe-env';\nimport { GitWorktreeService } from './GitWorktreeService';\nimport { AcpRunner } from './AcpRunner';\nimport { CodexRuntimeProjector } from './CodexRuntimeProjector';\nimport type { ResolvedAgentConfig } from '../../../agents/config/types';\nimport type { AIConnectionInvocationConfig, McpServerConfig } from '../../../agents/types';\nimport { codexWireApi } from '../../service/provider-registry';\nimport type {\n AcpRunnerType,\n AgentRuntimeConfig,\n AgentRuntimeEvent,\n} from '../../runs/AgentRuntimeTypes';\n\ninterface AgentRuntimeRunInput {\n threadId: string;\n prompt: string;\n config: AgentRuntimeConfig;\n}\n\n/**\n * Request-scoped ACP Agent Runtime.\n *\n * This class intentionally keeps no per-thread runner/session map. Durable\n * conversation state belongs in the Pod; each invocation starts an ACP runner,\n * creates one ACP session, streams events, then stops the runner.\n */\nexport class AcpAgentRuntime {\n private readonly logger = getLoggerFor(this);\n private readonly git = new GitWorktreeService();\n private readonly codexProjector = new CodexRuntimeProjector();\n\n public constructor(\n private readonly options: {\n worktreeRootDirName?: string;\n } = {},\n ) {}\n\n public async *run(input: AgentRuntimeRunInput): AsyncIterable<AgentRuntimeEvent> {\n const { threadId, prompt, config } = input;\n const workdir = await this.resolveWorkdir(threadId, config.workspace, config);\n\n if (config.runner.protocol && config.runner.protocol !== 'acp') {\n throw new Error(`Unsupported runner protocol: ${config.runner.protocol}. Only 'acp' is supported.`);\n }\n\n const runnerType = this.resolveAcpRunnerType(config.runner.type);\n const argv = this.resolveRunnerArgv(runnerType, config.runner.argv);\n const command = argv[0];\n const args = argv.slice(1);\n const env = this.buildRunnerEnv(runnerType, threadId, workdir, config.agentConfig, config.aiConnection);\n const runner = new AcpRunner();\n const queue = new AsyncPushQueue<AgentRuntimeEvent>();\n\n try {\n runner.start({ command, args, cwd: workdir, env });\n\n const sessionId = await this.createSession(runner, workdir, config.agentConfig);\n const runPromise = this.runPrompt(runner, sessionId, prompt, {\n idleMs: config.idleMs ?? 500,\n authWaitMs: Math.max(config.authWaitMs ?? 300_000, config.idleMs ?? 500),\n queue,\n }).catch((error) => {\n queue.push({ type: 'error', message: this.formatError(error) });\n queue.close();\n });\n\n for await (const event of queue.iterate()) {\n yield event;\n }\n await runPromise;\n } catch (error: any) {\n const message = this.formatError(error);\n this.logger.warn(`ACP agent runtime failed: ${message}`);\n yield { type: 'error', message };\n } finally {\n runner.stop('SIGINT');\n }\n }\n\n private async createSession(\n runner: AcpRunner,\n workdir: string,\n agentConfig?: ResolvedAgentConfig,\n ): Promise<string> {\n await runner.request('initialize', {\n protocolVersion: 1,\n clientCapabilities: {},\n clientInfo: { name: 'xpod', version: 'dev' },\n });\n\n const sessionParams: Record<string, unknown> = { cwd: workdir };\n if (agentConfig) {\n sessionParams.mcpServers = Object.keys(agentConfig.mcpServers).length > 0\n ? this.convertMcpServersForAcp(agentConfig.mcpServers)\n : [];\n if (agentConfig.systemPrompt) sessionParams.systemPrompt = agentConfig.systemPrompt;\n if (agentConfig.skillsContent) sessionParams.appendSystemPrompt = agentConfig.skillsContent;\n if (agentConfig.maxTurns) sessionParams.maxTurns = agentConfig.maxTurns;\n if (agentConfig.allowedTools) sessionParams.allowedTools = agentConfig.allowedTools;\n if (agentConfig.disallowedTools) sessionParams.disallowedTools = agentConfig.disallowedTools;\n if (agentConfig.permissionMode) sessionParams.permissionMode = agentConfig.permissionMode;\n } else {\n sessionParams.mcpServers = [];\n }\n\n const newSession = await runner.request<{ sessionId: string }>('session/new', sessionParams);\n if (!newSession?.sessionId) {\n throw new Error('ACP session/new did not return sessionId');\n }\n return newSession.sessionId;\n }\n\n private async runPrompt(\n runner: AcpRunner,\n sessionId: string,\n prompt: string,\n options: {\n idleMs: number;\n authWaitMs: number;\n queue: AsyncPushQueue<AgentRuntimeEvent>;\n },\n ): Promise<void> {\n const { idleMs, authWaitMs, queue } = options;\n let idleTimer: NodeJS.Timeout | undefined;\n let done = false;\n\n const finish = (): void => {\n if (done) return;\n done = true;\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = undefined;\n }\n runner.off('notification', onNotification);\n runner.off('request', onRequest);\n queue.close();\n };\n\n const bumpIdle = (ms: number = idleMs): void => {\n if (done) return;\n if (idleTimer) clearTimeout(idleTimer);\n idleTimer = setTimeout(() => finish(), ms);\n };\n\n const onRequest = (req: any): void => {\n if (!req || typeof req.method !== 'string') return;\n\n if (this.isRuntimeHandledRequest(req.method)) {\n const hint = req.params?.message || req.params?.reason || req.method;\n const url = this.extractAuthUrl(req.params);\n const authOptions =\n this.extractAuthOptions(req.params) ??\n (url ? [{ label: 'Continue in browser', url, method: req.method }] : undefined);\n queue.push({\n type: 'auth_required',\n method: req.method,\n url,\n message: typeof hint === 'string' ? hint : undefined,\n options: authOptions,\n });\n bumpIdle(authWaitMs);\n if (req.method === 'session/request_permission') {\n req.respond({ granted: true });\n } else {\n req.respond({ handled: true });\n }\n return;\n }\n\n const requestId = `acp:${String(req.id)}`;\n queue.push({\n type: 'tool_call',\n requestId,\n name: req.method,\n arguments: JSON.stringify(req.params ?? {}),\n });\n req.fail(-32601, `Unsupported ACP client request in stateless runtime: ${req.method}`);\n finish();\n };\n\n const onNotification = (method: string, params: any): void => {\n if (method !== 'session/update') return;\n if (!params || params.sessionId !== sessionId) return;\n\n const update = params.update;\n if (!update || typeof update !== 'object') return;\n\n const text = this.extractTextDeltaFromSessionUpdate(update);\n if (typeof text === 'string' && text.length > 0) {\n queue.push({ type: 'text', text });\n bumpIdle();\n }\n };\n\n runner.on('request', onRequest);\n runner.on('notification', onNotification);\n\n try {\n void runner.request('session/prompt', {\n sessionId,\n prompt: [ { type: 'text', text: prompt } ],\n }).then((result) => {\n const text = this.extractTextFromPromptResult(result);\n if (typeof text === 'string' && text.length > 0) {\n queue.push({ type: 'text', text });\n bumpIdle();\n } else {\n bumpIdle();\n }\n }).catch((error) => {\n if (!done) {\n queue.push({ type: 'error', message: this.formatError(error) });\n finish();\n }\n });\n bumpIdle();\n await queue.waitClosed();\n } finally {\n finish();\n }\n }\n\n private isRuntimeHandledRequest(method: string): boolean {\n return method === 'session/request_permission' ||\n method === 'auth/request' ||\n method === 'auth/authorize';\n }\n\n private async resolveWorkdir(threadId: string, workspace: WorkspaceRef, config: AgentRuntimeConfig): Promise<string> {\n const url = new URL(workspace);\n if (url.protocol !== 'file:') {\n throw new Error('ACP runtime only supports file:// workspaces; use pi Agent Runtime for Pod-backed runs');\n }\n if (!this.canResolveFileWorkspace(url)) {\n throw new Error(`Workspace is not resolvable by this ACP runner: ${workspace}`);\n }\n\n const repoRoot = decodeURIComponent(url.pathname);\n if (!fs.existsSync(repoRoot)) {\n throw new Error(`workspace reference does not exist on this runner: ${workspace}`);\n }\n\n const worktree = config.worktree;\n if (!worktree) {\n return repoRoot;\n }\n\n if (worktree.mode === 'existing') {\n if (!fs.existsSync(worktree.path)) {\n throw new Error(`worktree.path not found: ${worktree.path}`);\n }\n return worktree.path;\n }\n\n await this.git.assertGitRepo(repoRoot);\n\n const rootDirName = this.options.worktreeRootDirName ?? '.xpod-worktrees';\n const root = path.join(repoRoot, rootDirName);\n const worktreePath = path.join(root, threadId);\n\n if (fs.existsSync(worktreePath)) {\n return worktreePath;\n }\n\n const baseRef = worktree.baseRef ?? 'main';\n await this.git.createWorktree({\n repoPath: repoRoot,\n worktreePath,\n baseRef,\n branch: worktree.branch,\n });\n\n return worktreePath;\n }\n\n private canResolveFileWorkspace(url: URL): boolean {\n const authority = url.hostname;\n if (!authority || authority === 'localhost') {\n return true;\n }\n const configured = process.env.XPOD_RUNNER_AUTHORITY?.trim();\n return authority === configured || authority === os.hostname();\n }\n\n private resolveAcpRunnerType(type: string): AcpRunnerType {\n if (type === 'codebuddy' || type === 'claude' || type === 'codex') {\n return type;\n }\n throw new Error(`Unsupported ACP runner type: ${type}`);\n }\n\n private resolveRunnerArgv(type: AcpRunnerType, argv?: string[]): string[] {\n if (argv && argv.length > 0) {\n return argv;\n }\n switch (type) {\n case 'codebuddy':\n return [ this.resolveLocalBin('codebuddy'), '--acp' ];\n case 'claude':\n return [ this.resolveLocalBin('claude-code-acp') ];\n case 'codex':\n return [ this.resolveLocalBin('codex-acp') ];\n default:\n return [ type ];\n }\n }\n\n private resolveLocalBin(binName: string): string {\n const localBin = path.join(PACKAGE_ROOT, 'node_modules', '.bin', binName);\n if (fs.existsSync(localBin)) {\n return localBin;\n }\n return binName;\n }\n\n private buildRunnerEnv(\n type: AcpRunnerType,\n threadId: string,\n workdir: string,\n agentConfig?: ResolvedAgentConfig,\n aiConnection?: AIConnectionInvocationConfig,\n ): Record<string, string | undefined> | undefined {\n if (type === 'codebuddy') {\n return undefined;\n }\n\n const connection = requireAiConnectionRuntimeConfig({\n baseUrl: aiConnection?.baseUrl,\n apiKey: aiConnection?.gatewayKey,\n model: aiConnection?.model ?? agentConfig?.model,\n }, `${type} ACP runtime`);\n const home = this.getIsolatedHomeDir(type, threadId, workdir);\n\n if (type === 'codex') {\n const codexHome = path.join(home, '.codex');\n this.codexProjector.project({\n codexHome,\n baseUrl: connection.baseUrl,\n apiKey: connection.apiKey,\n wireApi: codexWireApi(connection.baseUrl),\n model: connection.model,\n agentConfig,\n });\n const env: Record<string, string | undefined> = {\n HOME: home,\n XDG_CONFIG_HOME: path.join(home, '.config'),\n XDG_STATE_HOME: path.join(home, '.local', 'state'),\n XDG_DATA_HOME: path.join(home, '.local', 'share'),\n XDG_CACHE_HOME: path.join(home, '.cache'),\n CODEX_HOME: codexHome,\n ...projectOpenAiCompatibleEnv(connection),\n };\n return env;\n }\n\n const env: Record<string, string | undefined> = {\n HOME: home,\n XDG_CONFIG_HOME: path.join(home, '.config'),\n XDG_STATE_HOME: path.join(home, '.local', 'state'),\n XDG_DATA_HOME: path.join(home, '.local', 'share'),\n XDG_CACHE_HOME: path.join(home, '.cache'),\n ...projectAnthropicCompatibleEnv(connection),\n };\n return env;\n }\n\n private getIsolatedHomeDir(type: Exclude<AcpRunnerType, 'codebuddy'>, threadId: string, workdir: string): string {\n const hash = crypto.createHash('sha256').update(`${type}:${threadId}:${workdir}`).digest('hex').slice(0, 16);\n const root = path.join(os.tmpdir(), 'xpod-acp-home', type, hash);\n fs.mkdirSync(root, { recursive: true });\n return root;\n }\n\n private convertMcpServersForAcp(\n servers: Record<string, McpServerConfig>,\n ): Array<Record<string, unknown>> {\n return Object.entries(servers).map(([name, config]) => ({\n name,\n ...config,\n }));\n }\n\n private extractTextDeltaFromSessionUpdate(update: any): string | undefined {\n if (!update) return undefined;\n\n if (typeof update === 'string') return update;\n if (typeof update.delta === 'string') return update.delta;\n if (typeof update.text === 'string') return update.text;\n\n const content = update.content?.content ?? update.content;\n if (typeof content === 'string') return content;\n if (content && typeof content === 'object') {\n if (typeof content.text === 'string') return content.text;\n if (Array.isArray(content)) {\n const parts = content\n .map((part: any) => (part && typeof part === 'object' ? part.text : undefined))\n .filter((text: any) => typeof text === 'string');\n if (parts.length) return parts.join('');\n }\n }\n\n const message = update.message ?? update.item ?? update.assistant_message;\n if (message && typeof message === 'object') {\n const msgContent = message.content?.content ?? message.content;\n if (typeof msgContent === 'string') return msgContent;\n if (Array.isArray(msgContent)) {\n const parts = msgContent\n .map((part: any) => {\n if (!part || typeof part !== 'object') return undefined;\n if (typeof part.text === 'string') return part.text;\n if (typeof part.delta === 'string') return part.delta;\n return undefined;\n })\n .filter((text: any) => typeof text === 'string');\n if (parts.length) return parts.join('');\n }\n }\n\n return undefined;\n }\n\n private extractTextFromPromptResult(result: any): string | undefined {\n if (!result) return undefined;\n if (typeof result === 'string') return result;\n\n if (typeof result.text === 'string') return result.text;\n if (typeof result.output_text === 'string') return result.output_text;\n\n const message = result.message ?? result.item ?? result.assistant_message;\n if (message && typeof message === 'object') {\n const msgContent = message.content?.content ?? message.content;\n if (typeof msgContent === 'string') return msgContent;\n if (Array.isArray(msgContent)) {\n const parts = msgContent\n .map((part: any) => (part && typeof part === 'object' ? (typeof part.text === 'string' ? part.text : undefined) : undefined))\n .filter((text: any) => typeof text === 'string');\n if (parts.length) return parts.join('');\n }\n }\n\n const content = result.content?.content ?? result.content;\n if (typeof content === 'string') return content;\n if (Array.isArray(content)) {\n const parts = content\n .map((part: any) => (part && typeof part === 'object' ? (typeof part.text === 'string' ? part.text : undefined) : undefined))\n .filter((text: any) => typeof text === 'string');\n if (parts.length) return parts.join('');\n }\n\n return undefined;\n }\n\n private extractAuthUrl(params: any): string | undefined {\n if (!params || typeof params !== 'object') return undefined;\n const candidates = [\n params.url,\n params.authorizationUrl,\n params.authorization_url,\n params.authUrl,\n params.auth_url,\n params.browserUrl,\n params.browser_url,\n params.verification_uri,\n params.verificationUri,\n params.verificationUrl,\n ];\n return candidates.find((value) => typeof value === 'string' && value.startsWith('http'));\n }\n\n private extractAuthOptions(params: any): Array<{ label?: string; url?: string; method?: string }> | undefined {\n if (!params || typeof params !== 'object') return undefined;\n\n const raw =\n Array.isArray((params as any).methods) ? (params as any).methods\n : Array.isArray((params as any).options) ? (params as any).options\n : Array.isArray((params as any).authMethods) ? (params as any).authMethods\n : Array.isArray((params as any).auth_methods) ? (params as any).auth_methods\n : undefined;\n\n if (!raw) return undefined;\n\n const options = raw\n .map((method: any) => {\n if (!method || typeof method !== 'object') return undefined;\n const url = this.extractAuthUrl(method);\n const label =\n typeof method.label === 'string' ? method.label :\n typeof method.name === 'string' ? method.name :\n typeof method.type === 'string' ? method.type :\n undefined;\n const optionMethod =\n typeof method.method === 'string' ? method.method :\n typeof method.type === 'string' ? method.type :\n undefined;\n return { label, url, method: optionMethod };\n })\n .filter(Boolean) as Array<{ label?: string; url?: string; method?: string }>;\n\n return options.length > 0 ? options : undefined;\n }\n\n private formatError(error: unknown): string {\n const anyError = error as any;\n const dataMessage =\n anyError?.data && typeof anyError.data === 'object' && typeof anyError.data.message === 'string'\n ? anyError.data.message\n : undefined;\n const message = String(anyError?.message ?? error);\n return dataMessage ? `${message} | data.message=${dataMessage.slice(0, 800)}` : message;\n }\n}\n\nclass AsyncPushQueue<T> {\n private readonly items: T[] = [];\n private resolvers: Array<() => void> = [];\n private closed = false;\n private closeResolvers: Array<() => void> = [];\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 for (const resolver of this.closeResolvers) {\n resolver();\n }\n this.closeResolvers = [];\n }\n\n public async waitClosed(): Promise<void> {\n if (this.closed) {\n return;\n }\n await new Promise<void>((resolve) => this.closeResolvers.push(resolve));\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":"AcpAgentRuntime.js","sourceRoot":"","sources":["../../../../src/api/chatkit/runtime/AcpAgentRuntime.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'node:path';\nimport * as crypto from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { WorkspaceRef } from '../../workspace/types';\nimport { PACKAGE_ROOT } from '../../../runtime';\nimport {\n projectAnthropicCompatibleEnv,\n projectOpenAiCompatibleEnv,\n requireAiConnectionRuntimeConfig,\n} from '../../../runtime/safe-env';\nimport { GitWorktreeService } from './GitWorktreeService';\nimport { AcpRunner } from './AcpRunner';\nimport { CodexRuntimeProjector } from './CodexRuntimeProjector';\nimport type { ResolvedAgentConfig } from '../../../agents/config/types';\nimport type { AIConnectionInvocationConfig, McpServerConfig } from '../../../agents/types';\nimport { codexWireApi } from '../../service/provider-registry';\nimport type {\n AcpRunnerType,\n AgentRuntimeConfig,\n AgentRuntimeEvent,\n} from '../../runs/AgentRuntimeTypes';\n\ninterface AgentRuntimeRunInput {\n threadId: string;\n prompt: string;\n config: AgentRuntimeConfig;\n}\n\n/**\n * Request-scoped ACP Agent Runtime.\n *\n * This class intentionally keeps no per-thread runner/session map. Durable\n * conversation state belongs in the Pod; each invocation starts an ACP runner,\n * creates one ACP session, streams events, then stops the runner.\n */\nexport class AcpAgentRuntime {\n private readonly logger = getLoggerFor(this);\n private readonly git = new GitWorktreeService();\n private readonly codexProjector = new CodexRuntimeProjector();\n\n public constructor(\n private readonly options: {\n worktreeRootDirName?: string;\n } = {},\n ) {}\n\n public async *run(input: AgentRuntimeRunInput): AsyncIterable<AgentRuntimeEvent> {\n const { threadId, prompt, config } = input;\n const workdir = await this.resolveWorkdir(threadId, config.workspace, config);\n\n if (config.runner.protocol && config.runner.protocol !== 'acp') {\n throw new Error(`Unsupported runner protocol: ${config.runner.protocol}. Only 'acp' is supported.`);\n }\n\n const runnerType = this.resolveAcpRunnerType(config.runner.type);\n const argv = this.resolveRunnerArgv(runnerType, config.runner.argv);\n const command = argv[0];\n const args = argv.slice(1);\n const env = this.buildRunnerEnv(runnerType, threadId, workdir, config.agentConfig, config.aiConnection);\n const runner = new AcpRunner();\n const queue = new AsyncPushQueue<AgentRuntimeEvent>();\n\n try {\n runner.start({ command, args, cwd: workdir, env });\n\n const sessionId = await this.createSession(runner, workdir, config.agentConfig);\n const runPromise = this.runPrompt(runner, sessionId, prompt, {\n idleMs: config.idleMs ?? 500,\n authWaitMs: Math.max(config.authWaitMs ?? 300_000, config.idleMs ?? 500),\n queue,\n }).catch((error) => {\n queue.push({ type: 'error', message: this.formatError(error) });\n queue.close();\n });\n\n for await (const event of queue.iterate()) {\n yield event;\n }\n await runPromise;\n } catch (error: any) {\n const message = this.formatError(error);\n this.logger.warn(`ACP agent runtime failed: ${message}`);\n yield { type: 'error', message };\n } finally {\n runner.stop('SIGINT');\n }\n }\n\n private async createSession(\n runner: AcpRunner,\n workdir: string,\n agentConfig?: ResolvedAgentConfig,\n ): Promise<string> {\n await runner.request('initialize', {\n protocolVersion: 1,\n clientCapabilities: {},\n clientInfo: { name: 'xpod', version: 'dev' },\n });\n\n const sessionParams: Record<string, unknown> = { cwd: workdir };\n if (agentConfig) {\n sessionParams.mcpServers = Object.keys(agentConfig.mcpServers).length > 0\n ? this.convertMcpServersForAcp(agentConfig.mcpServers)\n : [];\n if (agentConfig.systemPrompt) sessionParams.systemPrompt = agentConfig.systemPrompt;\n if (agentConfig.skillsContent) sessionParams.appendSystemPrompt = agentConfig.skillsContent;\n if (agentConfig.maxTurns) sessionParams.maxTurns = agentConfig.maxTurns;\n if (agentConfig.allowedTools) sessionParams.allowedTools = agentConfig.allowedTools;\n if (agentConfig.disallowedTools) sessionParams.disallowedTools = agentConfig.disallowedTools;\n if (agentConfig.permissionMode) sessionParams.permissionMode = agentConfig.permissionMode;\n } else {\n sessionParams.mcpServers = [];\n }\n\n const newSession = await runner.request<{ sessionId: string }>('session/new', sessionParams);\n if (!newSession?.sessionId) {\n throw new Error('ACP session/new did not return sessionId');\n }\n return newSession.sessionId;\n }\n\n private async runPrompt(\n runner: AcpRunner,\n sessionId: string,\n prompt: string,\n options: {\n idleMs: number;\n authWaitMs: number;\n queue: AsyncPushQueue<AgentRuntimeEvent>;\n },\n ): Promise<void> {\n const { idleMs, authWaitMs, queue } = options;\n let idleTimer: NodeJS.Timeout | undefined;\n let done = false;\n\n const finish = (): void => {\n if (done) return;\n done = true;\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = undefined;\n }\n runner.off('notification', onNotification);\n runner.off('request', onRequest);\n queue.close();\n };\n\n const bumpIdle = (ms: number = idleMs): void => {\n if (done) return;\n if (idleTimer) clearTimeout(idleTimer);\n idleTimer = setTimeout(() => finish(), ms);\n };\n\n const onRequest = (req: any): void => {\n if (!req || typeof req.method !== 'string') return;\n\n if (this.isRuntimeHandledRequest(req.method)) {\n const hint = req.params?.message || req.params?.reason || req.method;\n const url = this.extractAuthUrl(req.params);\n const authOptions =\n this.extractAuthOptions(req.params) ??\n (url ? [{ label: 'Continue in browser', url, method: req.method }] : undefined);\n queue.push({\n type: 'auth_required',\n method: req.method,\n url,\n message: typeof hint === 'string' ? hint : undefined,\n options: authOptions,\n });\n bumpIdle(authWaitMs);\n if (req.method === 'session/request_permission') {\n req.respond({ granted: true });\n } else {\n req.respond({ handled: true });\n }\n return;\n }\n\n const requestId = `acp:${String(req.id)}`;\n queue.push({\n type: 'tool_call',\n requestId,\n name: req.method,\n arguments: JSON.stringify(req.params ?? {}),\n });\n req.fail(-32601, `Unsupported ACP client request in stateless runtime: ${req.method}`);\n finish();\n };\n\n const onNotification = (method: string, params: any): void => {\n if (method !== 'session/update') return;\n if (!params || params.sessionId !== sessionId) return;\n\n const update = params.update;\n if (!update || typeof update !== 'object') return;\n\n const text = this.extractTextDeltaFromSessionUpdate(update);\n if (typeof text === 'string' && text.length > 0) {\n queue.push({ type: 'text', text });\n bumpIdle();\n }\n };\n\n runner.on('request', onRequest);\n runner.on('notification', onNotification);\n\n try {\n void runner.request('session/prompt', {\n sessionId,\n prompt: [ { type: 'text', text: prompt } ],\n }).then((result) => {\n const text = this.extractTextFromPromptResult(result);\n if (typeof text === 'string' && text.length > 0) {\n queue.push({ type: 'text', text });\n bumpIdle();\n } else {\n bumpIdle();\n }\n }).catch((error) => {\n if (!done) {\n queue.push({ type: 'error', message: this.formatError(error) });\n finish();\n }\n });\n bumpIdle();\n await queue.waitClosed();\n } finally {\n finish();\n }\n }\n\n private isRuntimeHandledRequest(method: string): boolean {\n return method === 'session/request_permission' ||\n method === 'auth/request' ||\n method === 'auth/authorize';\n }\n\n private async resolveWorkdir(threadId: string, workspace: WorkspaceRef, config: AgentRuntimeConfig): Promise<string> {\n const url = new URL(workspace);\n if (url.protocol !== 'file:') {\n throw new Error('ACP runtime only supports file:// workspaces; use pi Agent Runtime for Pod-backed runs');\n }\n if (!this.canResolveFileWorkspace(url)) {\n throw new Error(`Workspace is not resolvable by this ACP runner: ${workspace}`);\n }\n\n const repoRoot = decodeURIComponent(url.pathname);\n if (!fs.existsSync(repoRoot)) {\n throw new Error(`workspace reference does not exist on this runner: ${workspace}`);\n }\n\n const worktree = config.worktree;\n if (!worktree) {\n return repoRoot;\n }\n\n if (worktree.mode === 'existing') {\n if (!fs.existsSync(worktree.path)) {\n throw new Error(`worktree.path not found: ${worktree.path}`);\n }\n return worktree.path;\n }\n\n await this.git.assertGitRepo(repoRoot);\n\n const rootDirName = this.options.worktreeRootDirName ?? '.xpod-worktrees';\n const root = path.join(repoRoot, rootDirName);\n const worktreePath = path.join(root, threadId);\n\n if (fs.existsSync(worktreePath)) {\n return worktreePath;\n }\n\n const baseRef = worktree.baseRef ?? 'main';\n await this.git.createWorktree({\n repoPath: repoRoot,\n worktreePath,\n baseRef,\n branch: worktree.branch,\n });\n\n return worktreePath;\n }\n\n private canResolveFileWorkspace(url: URL): boolean {\n const authority = url.hostname;\n if (!authority || authority === 'localhost') {\n return true;\n }\n const configured = process.env.XPOD_RUNNER_AUTHORITY?.trim();\n return authority === configured || authority === os.hostname();\n }\n\n private resolveAcpRunnerType(type: string): AcpRunnerType {\n if (type === 'codebuddy' || type === 'claude' || type === 'codex') {\n return type;\n }\n throw new Error(`Unsupported ACP runner type: ${type}`);\n }\n\n private resolveRunnerArgv(type: AcpRunnerType, argv?: string[]): string[] {\n if (argv && argv.length > 0) {\n return argv;\n }\n switch (type) {\n case 'codebuddy':\n return [ this.resolveLocalBin('codebuddy'), '--acp' ];\n case 'claude':\n return [ this.resolveLocalBin('claude-code-acp') ];\n case 'codex':\n return [ this.resolveLocalBin('codex-acp') ];\n default:\n return [ type ];\n }\n }\n\n private resolveLocalBin(binName: string): string {\n const localBin = path.join(PACKAGE_ROOT, 'node_modules', '.bin', binName);\n if (fs.existsSync(localBin)) {\n return localBin;\n }\n return binName;\n }\n\n private buildRunnerEnv(\n type: AcpRunnerType,\n threadId: string,\n workdir: string,\n agentConfig?: ResolvedAgentConfig,\n aiConnection?: AIConnectionInvocationConfig,\n ): Record<string, string | undefined> | undefined {\n if (type === 'codebuddy') {\n return undefined;\n }\n\n const connection = requireAiConnectionRuntimeConfig({\n baseUrl: aiConnection?.baseUrl,\n apiKey: aiConnection?.apiKey,\n model: aiConnection?.model ?? agentConfig?.model,\n }, `${type} ACP runtime`);\n const home = this.getIsolatedHomeDir(type, threadId, workdir);\n\n if (type === 'codex') {\n const codexHome = path.join(home, '.codex');\n this.codexProjector.project({\n codexHome,\n baseUrl: connection.baseUrl,\n apiKey: connection.apiKey,\n wireApi: codexWireApi(connection.baseUrl),\n model: connection.model,\n agentConfig,\n });\n const env: Record<string, string | undefined> = {\n HOME: home,\n XDG_CONFIG_HOME: path.join(home, '.config'),\n XDG_STATE_HOME: path.join(home, '.local', 'state'),\n XDG_DATA_HOME: path.join(home, '.local', 'share'),\n XDG_CACHE_HOME: path.join(home, '.cache'),\n CODEX_HOME: codexHome,\n ...projectOpenAiCompatibleEnv(connection),\n };\n return env;\n }\n\n const env: Record<string, string | undefined> = {\n HOME: home,\n XDG_CONFIG_HOME: path.join(home, '.config'),\n XDG_STATE_HOME: path.join(home, '.local', 'state'),\n XDG_DATA_HOME: path.join(home, '.local', 'share'),\n XDG_CACHE_HOME: path.join(home, '.cache'),\n ...projectAnthropicCompatibleEnv(connection),\n };\n return env;\n }\n\n private getIsolatedHomeDir(type: Exclude<AcpRunnerType, 'codebuddy'>, threadId: string, workdir: string): string {\n const hash = crypto.createHash('sha256').update(`${type}:${threadId}:${workdir}`).digest('hex').slice(0, 16);\n const root = path.join(os.tmpdir(), 'xpod-acp-home', type, hash);\n fs.mkdirSync(root, { recursive: true });\n return root;\n }\n\n private convertMcpServersForAcp(\n servers: Record<string, McpServerConfig>,\n ): Array<Record<string, unknown>> {\n return Object.entries(servers).map(([name, config]) => ({\n name,\n ...config,\n }));\n }\n\n private extractTextDeltaFromSessionUpdate(update: any): string | undefined {\n if (!update) return undefined;\n\n if (typeof update === 'string') return update;\n if (typeof update.delta === 'string') return update.delta;\n if (typeof update.text === 'string') return update.text;\n\n const content = update.content?.content ?? update.content;\n if (typeof content === 'string') return content;\n if (content && typeof content === 'object') {\n if (typeof content.text === 'string') return content.text;\n if (Array.isArray(content)) {\n const parts = content\n .map((part: any) => (part && typeof part === 'object' ? part.text : undefined))\n .filter((text: any) => typeof text === 'string');\n if (parts.length) return parts.join('');\n }\n }\n\n const message = update.message ?? update.item ?? update.assistant_message;\n if (message && typeof message === 'object') {\n const msgContent = message.content?.content ?? message.content;\n if (typeof msgContent === 'string') return msgContent;\n if (Array.isArray(msgContent)) {\n const parts = msgContent\n .map((part: any) => {\n if (!part || typeof part !== 'object') return undefined;\n if (typeof part.text === 'string') return part.text;\n if (typeof part.delta === 'string') return part.delta;\n return undefined;\n })\n .filter((text: any) => typeof text === 'string');\n if (parts.length) return parts.join('');\n }\n }\n\n return undefined;\n }\n\n private extractTextFromPromptResult(result: any): string | undefined {\n if (!result) return undefined;\n if (typeof result === 'string') return result;\n\n if (typeof result.text === 'string') return result.text;\n if (typeof result.output_text === 'string') return result.output_text;\n\n const message = result.message ?? result.item ?? result.assistant_message;\n if (message && typeof message === 'object') {\n const msgContent = message.content?.content ?? message.content;\n if (typeof msgContent === 'string') return msgContent;\n if (Array.isArray(msgContent)) {\n const parts = msgContent\n .map((part: any) => (part && typeof part === 'object' ? (typeof part.text === 'string' ? part.text : undefined) : undefined))\n .filter((text: any) => typeof text === 'string');\n if (parts.length) return parts.join('');\n }\n }\n\n const content = result.content?.content ?? result.content;\n if (typeof content === 'string') return content;\n if (Array.isArray(content)) {\n const parts = content\n .map((part: any) => (part && typeof part === 'object' ? (typeof part.text === 'string' ? part.text : undefined) : undefined))\n .filter((text: any) => typeof text === 'string');\n if (parts.length) return parts.join('');\n }\n\n return undefined;\n }\n\n private extractAuthUrl(params: any): string | undefined {\n if (!params || typeof params !== 'object') return undefined;\n const candidates = [\n params.url,\n params.authorizationUrl,\n params.authorization_url,\n params.authUrl,\n params.auth_url,\n params.browserUrl,\n params.browser_url,\n params.verification_uri,\n params.verificationUri,\n params.verificationUrl,\n ];\n return candidates.find((value) => typeof value === 'string' && value.startsWith('http'));\n }\n\n private extractAuthOptions(params: any): Array<{ label?: string; url?: string; method?: string }> | undefined {\n if (!params || typeof params !== 'object') return undefined;\n\n const raw =\n Array.isArray((params as any).methods) ? (params as any).methods\n : Array.isArray((params as any).options) ? (params as any).options\n : Array.isArray((params as any).authMethods) ? (params as any).authMethods\n : Array.isArray((params as any).auth_methods) ? (params as any).auth_methods\n : undefined;\n\n if (!raw) return undefined;\n\n const options = raw\n .map((method: any) => {\n if (!method || typeof method !== 'object') return undefined;\n const url = this.extractAuthUrl(method);\n const label =\n typeof method.label === 'string' ? method.label :\n typeof method.name === 'string' ? method.name :\n typeof method.type === 'string' ? method.type :\n undefined;\n const optionMethod =\n typeof method.method === 'string' ? method.method :\n typeof method.type === 'string' ? method.type :\n undefined;\n return { label, url, method: optionMethod };\n })\n .filter(Boolean) as Array<{ label?: string; url?: string; method?: string }>;\n\n return options.length > 0 ? options : undefined;\n }\n\n private formatError(error: unknown): string {\n const anyError = error as any;\n const dataMessage =\n anyError?.data && typeof anyError.data === 'object' && typeof anyError.data.message === 'string'\n ? anyError.data.message\n : undefined;\n const message = String(anyError?.message ?? error);\n return dataMessage ? `${message} | data.message=${dataMessage.slice(0, 800)}` : message;\n }\n}\n\nclass AsyncPushQueue<T> {\n private readonly items: T[] = [];\n private resolvers: Array<() => void> = [];\n private closed = false;\n private closeResolvers: Array<() => void> = [];\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 for (const resolver of this.closeResolvers) {\n resolver();\n }\n this.closeResolvers = [];\n }\n\n public async waitClosed(): Promise<void> {\n if (this.closed) {\n return;\n }\n await new Promise<void>((resolve) => this.closeResolvers.push(resolve));\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"]}
|