@undefineds.co/xpod 0.4.25 → 0.4.27
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/dist/api/ApiServer.d.ts +1 -0
- package/dist/api/ApiServer.js +38 -0
- package/dist/api/ai-config/AiConfigStore.js +18 -6
- package/dist/api/ai-gateway/connect/index.d.ts +1 -0
- package/dist/api/ai-gateway/connect/index.js +39 -18
- package/dist/api/ai-gateway/models/ProviderModelsAdapter.js +5 -2
- package/dist/api/container/common.js +8 -2
- package/dist/api/container/index.js +2 -2
- package/dist/api/container/local.js +6 -3
- package/dist/api/handlers/AiGatewayHandler.d.ts +1 -0
- package/dist/api/handlers/AiGatewayHandler.js +53 -3
- package/dist/api/handlers/AiGatewayManagementHandler.js +9 -0
- package/dist/api/handlers/TaskHandler.js +15 -10
- package/dist/api/network/NetworkEnvironmentConfigurationStore.js +1 -1
- package/dist/api/runs/ManagedRunWorker.d.ts +0 -1
- package/dist/api/runs/ManagedRunWorker.js +2 -14
- package/dist/api/runs/PiAgentRuntimeDriver.d.ts +0 -8
- package/dist/api/runs/PiAgentRuntimeDriver.js +65 -21
- package/dist/api/runs/RunStateCenter.js +1 -0
- package/dist/api/runs/store.d.ts +1 -0
- package/dist/api/runs/store.js +13 -0
- package/dist/api/tasks/TaskMaterializer.js +13 -6
- package/dist/api/tasks/TaskResumeDiagnostics.d.ts +28 -0
- package/dist/api/tasks/TaskResumeDiagnostics.js +148 -0
- package/dist/api/tasks/TaskService.js +40 -23
- package/dist/storage/conditions/StorageETagHandler.d.ts +1 -1
- package/dist/storage/conditions/StorageETagHandler.js +13 -4
- package/dist/util/task-model-diagnostics.d.ts +67 -0
- package/dist/util/task-model-diagnostics.js +118 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiApiKeyPool.d.ts +1 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiApiKeyPool.js +2 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectDialog.d.ts +1 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.d.ts +1 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.js +10 -10
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeyRow.d.ts +3 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeyRow.js +2 -2
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.js +77 -23
- package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.d.ts +1 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiSortableCredentialList.js +59 -59
- package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.js +2 -0
- package/node_modules/@undefineds.co/ai-connections/dist/collections.js +14 -6
- package/node_modules/@undefineds.co/ai-connections/dist/contract/ai-connections-client.d.ts +2 -1
- package/node_modules/@undefineds.co/ai-connections/dist/contract/ai-connections-client.js +1 -0
- package/node_modules/@undefineds.co/ai-connections/dist/contract/client/gateway-model-roles.d.ts +11 -0
- package/node_modules/@undefineds.co/ai-connections/dist/contract/client/gateway-model-roles.js +11 -0
- package/node_modules/@undefineds.co/ai-connections/dist/contract/client/normalize.d.ts +2 -1
- package/node_modules/@undefineds.co/ai-connections/dist/contract/client/normalize.js +12 -5
- package/node_modules/@undefineds.co/ai-connections/dist/contract/client/request.js +10 -2
- package/node_modules/@undefineds.co/ai-connections/dist/contract/client/types.d.ts +10 -0
- package/node_modules/@undefineds.co/ai-connections/package.json +1 -1
- package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +1 -0
- package/node_modules/@undefineds.co/extension-sdk/package.json +1 -1
- package/node_modules/@undefineds.co/pod-collections/dist/index.cjs +60 -13
- package/node_modules/@undefineds.co/pod-collections/dist/mapping.d.ts +16 -1
- package/node_modules/@undefineds.co/pod-collections/dist/mapping.js +51 -0
- package/node_modules/@undefineds.co/pod-collections/dist/mutations.js +14 -18
- package/node_modules/@undefineds.co/pod-collections/package.json +1 -1
- package/node_modules/@undefineds.co/shared-ui/dist/list.d.ts +8 -1
- package/node_modules/@undefineds.co/shared-ui/dist/list.js +4 -1
- package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/IdpChrome.d.ts +1 -1
- package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/IdpChrome.js +2 -2
- package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/IdpViews.js +2 -2
- package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/PodSignInFrame.d.ts +3 -3
- package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/PodSignInFrame.js +5 -5
- package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/parts.d.ts +5 -5
- package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/parts.js +5 -5
- package/node_modules/@undefineds.co/shared-ui/dist/section-header.js +1 -1
- package/node_modules/@undefineds.co/shared-ui/dist/theme.css +5 -32
- package/node_modules/@undefineds.co/shared-ui/package.json +1 -1
- package/node_modules/@undefineds.co/solid-sdk/package.json +1 -1
- package/package.json +2 -2
- package/static/app/assets/main.css +1 -1
- package/static/app/assets/main.js +1 -1
- package/static/dashboard/assets/AccountAuthBoundary-Dv52SZc6.js +1 -0
- package/static/dashboard/assets/DesktopOidcCallback-DaT_Rumf.js +1 -0
- package/static/dashboard/assets/DevicePages-HjclpIVm.js +2 -0
- package/static/dashboard/assets/ModelsPage-Be2TPd-x.js +11 -0
- package/static/dashboard/assets/{PaneListHeader-Dn5O0mwy.js → PaneListHeader-DtvnRmFq.js} +1 -1
- package/static/dashboard/assets/{PodDeletionAuthorizationPanel-D3NOG6ZM.js → PodDeletionAuthorizationPanel-BJk_8rJq.js} +3 -3
- package/static/dashboard/assets/PodPage-C4gzEspV.js +1 -0
- package/static/dashboard/assets/{SystemSettingsPage-BNQP_Yuc.js → SystemSettingsPage-HaNrP1H1.js} +1 -1
- package/static/dashboard/assets/TasksPage-BdO5K2L7.js +1 -0
- package/static/dashboard/assets/{WebDesktopEntry-vnb4CZWp.js → WebDesktopEntry-Cj9_ZfJU.js} +1 -1
- package/static/dashboard/assets/XpodAiConnectionsPodStore-B7gmXBmC.js +3 -0
- package/static/dashboard/assets/XpodShellApp-D_KY4nCW.js +4 -0
- package/static/dashboard/assets/{account-session-DCUmCop1.js → account-session-DlcKNG7k.js} +1 -1
- package/static/dashboard/assets/{button-By5Bgvmb.js → button-wslF55uZ.js} +1 -1
- package/static/dashboard/assets/collection-runtime-uxxgEu13.js +1 -0
- package/static/dashboard/assets/{createLucideIcon-bunMzPms.js → createLucideIcon-BJQl82Qk.js} +1 -1
- package/static/dashboard/assets/dashboard-CbJ-JkrI.css +1 -0
- package/static/dashboard/assets/{dashboard-mlsg3yaw.js → dashboard-Or0gnkou.js} +2 -2
- package/static/dashboard/assets/index-BqFeOML9.js +1 -0
- package/static/dashboard/assets/{index-DvMG5pHk.js → index-DgKn1twH.js} +2 -2
- package/static/dashboard/assets/{label-Bj03L9xs.js → label-CS6Sx6Zb.js} +1 -1
- package/static/dashboard/assets/list-UyhlCFKk.js +1 -0
- package/static/dashboard/assets/{nav-item-style-BNqWQY6p.js → nav-item-style-CW1Nnorq.js} +1 -1
- package/static/dashboard/assets/{pod-collections-host-KnnGFZHL.js → pod-collections-host-DjK2xf-b.js} +6 -6
- package/static/dashboard/assets/{safe-continuation-D9AhcWiB.js → safe-continuation-ClWAhcma.js} +1 -1
- package/static/dashboard/assets/{section-header-CLCzbOp_.js → section-header-CEIEcco-.js} +1 -1
- package/static/dashboard/assets/{setting-row-DTCec8A2.js → setting-row-CaYv3dfF.js} +1 -1
- package/static/dashboard/assets/xpod-remembered-login-BUF9fin1.js +310 -0
- package/static/dashboard/dashboard.html +2 -2
- package/static/settings/assets/{AccountAuthBoundary-C0og_gIA.js → AccountAuthBoundary-Chqd38oU.js} +1 -1
- package/static/settings/assets/{DesktopOidcCallback-C5q4oFZ0.js → DesktopOidcCallback-VUrOSM_q.js} +1 -1
- package/static/settings/assets/DevicePages-C6qwvWwu.js +2 -0
- package/static/settings/assets/ModelsPage-Ry_dObRQ.js +11 -0
- package/static/settings/assets/{PaneListHeader-DqVlMe2D.js → PaneListHeader-B5RkRqr4.js} +1 -1
- package/static/settings/assets/{PodDeletionAuthorizationPanel-DgVvarVY.js → PodDeletionAuthorizationPanel-DPM-5Izt.js} +3 -3
- package/static/settings/assets/PodPage-CxND6wwc.js +1 -0
- package/static/settings/assets/{SystemSettingsPage-Crzm_DrI.js → SystemSettingsPage-C8EdMkW7.js} +1 -1
- package/static/settings/assets/TasksPage-DuqptEm8.js +1 -0
- package/static/settings/assets/{WebDesktopEntry-BGC5eRF2.js → WebDesktopEntry-BRcyktkv.js} +1 -1
- package/static/settings/assets/XpodAiConnectionsPodStore-CyA_BJVC.js +3 -0
- package/static/settings/assets/XpodShellApp-CsivHJl0.js +4 -0
- package/static/settings/assets/XpodThemeProvider-CbJ-JkrI.css +1 -0
- package/static/settings/assets/{XpodThemeProvider-CB6LepTA.js → XpodThemeProvider-DK3pIdRG.js} +2 -2
- package/static/settings/assets/{account-session-BcLjCj0x.js → account-session-DJOZ03xr.js} +1 -1
- package/static/settings/assets/auth-callback-GIBYEz_7.js +1 -0
- package/static/settings/assets/{button-BObT8pTE.js → button-D3yW-2o1.js} +1 -1
- package/static/settings/assets/collection-runtime-DfGo25mh.js +1 -0
- package/static/settings/assets/{createLucideIcon-BVsUxXpZ.js → createLucideIcon-CacwLsmB.js} +1 -1
- package/static/settings/assets/{index-ktjMkj7-.js → index-r5KRYsKC.js} +1 -1
- package/static/settings/assets/{label-BrqO8_m_.js → label-MJjUmvzG.js} +1 -1
- package/static/settings/assets/list-Ce-5k1MX.js +1 -0
- package/static/settings/assets/{nav-item-style-Di2CxkDU.js → nav-item-style-ZUbL8KOZ.js} +1 -1
- package/static/settings/assets/{pod-collections-host-KnnGFZHL.js → pod-collections-host-DjK2xf-b.js} +6 -6
- package/static/settings/assets/{safe-continuation-Dx6ceJpY.js → safe-continuation-vlBZFSlU.js} +1 -1
- package/static/settings/assets/{section-header-Dtl7yjVr.js → section-header-DGJdEvQw.js} +1 -1
- package/static/settings/assets/{setting-row-BL6Hhe8N.js → setting-row-C7tuFiho.js} +1 -1
- package/static/settings/assets/{settings-DaRBxoZk.js → settings-CyQPih1O.js} +1 -1
- package/static/settings/assets/xpod-remembered-login-D-TzzT5K.js +567 -0
- package/static/settings/auth-callback.html +3 -3
- package/static/settings/settings.html +3 -3
- package/static/dashboard/assets/AccountAuthBoundary-BvoDydRz.js +0 -1
- package/static/dashboard/assets/DesktopOidcCallback-BwIj874x.js +0 -1
- package/static/dashboard/assets/DevicePages-jOjMcvsr.js +0 -2
- package/static/dashboard/assets/ModelsPage-CMTdfqBR.js +0 -11
- package/static/dashboard/assets/PodPage-BueBdJ9_.js +0 -1
- package/static/dashboard/assets/TasksPage-CxtLJiSF.js +0 -1
- package/static/dashboard/assets/XpodAiConnectionsPodStore-wx3Ttupm.js +0 -18
- package/static/dashboard/assets/XpodShellApp-5FWY8-d5.js +0 -4
- package/static/dashboard/assets/collection-runtime-BnomuB0E.js +0 -1
- package/static/dashboard/assets/dashboard-C64R553B.css +0 -1
- package/static/dashboard/assets/xpod-remembered-login-Dr69A0Rv.js +0 -295
- package/static/settings/assets/DevicePages-fyHjjucT.js +0 -2
- package/static/settings/assets/ModelsPage-EyOByLyE.js +0 -11
- package/static/settings/assets/PodPage-DY4Oi9wg.js +0 -1
- package/static/settings/assets/TasksPage-CfXJbnlt.js +0 -1
- package/static/settings/assets/XpodAiConnectionsPodStore-CXcmgKmQ.js +0 -3
- package/static/settings/assets/XpodShellApp-D1PS3Iut.js +0 -4
- package/static/settings/assets/XpodThemeProvider-C64R553B.css +0 -1
- package/static/settings/assets/auth-callback-DSPQ28ar.js +0 -1
- package/static/settings/assets/collection-runtime-DzNbdZGe.js +0 -1
- package/static/settings/assets/index-browser-3WfrNbcG.js +0 -273
- package/static/settings/assets/xpod-remembered-login-Q66DH12t.js +0 -295
package/dist/api/ApiServer.d.ts
CHANGED
|
@@ -110,6 +110,7 @@ export declare class ApiServer {
|
|
|
110
110
|
getHttpServer(): Server | undefined;
|
|
111
111
|
address(): AddressInfo | string | null;
|
|
112
112
|
private handleRequest;
|
|
113
|
+
private observeTaskGatewayResponse;
|
|
113
114
|
private findRoute;
|
|
114
115
|
private pathToRegex;
|
|
115
116
|
private handleCors;
|
package/dist/api/ApiServer.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.ApiServer = void 0;
|
|
|
4
4
|
const node_http_1 = require("node:http");
|
|
5
5
|
const global_logger_factory_1 = require("global-logger-factory");
|
|
6
6
|
const NodeRuntimeHost_1 = require("../runtime/host/node/NodeRuntimeHost");
|
|
7
|
+
const task_model_diagnostics_1 = require("../util/task-model-diagnostics");
|
|
7
8
|
/**
|
|
8
9
|
* Standalone API Server
|
|
9
10
|
*/
|
|
@@ -183,6 +184,7 @@ class ApiServer {
|
|
|
183
184
|
const method = request.method?.toUpperCase() ?? 'GET';
|
|
184
185
|
const url = new URL(request.url ?? '/', `http://${request.headers.host ?? 'localhost'}`);
|
|
185
186
|
const path = url.pathname;
|
|
187
|
+
this.observeTaskGatewayResponse(request, response, method, path);
|
|
186
188
|
// Handle CORS preflight
|
|
187
189
|
if (method === 'OPTIONS') {
|
|
188
190
|
this.handleCors(request, response);
|
|
@@ -241,6 +243,42 @@ class ApiServer {
|
|
|
241
243
|
}
|
|
242
244
|
}
|
|
243
245
|
}
|
|
246
|
+
observeTaskGatewayResponse(request, response, method, path) {
|
|
247
|
+
if (method !== 'POST')
|
|
248
|
+
return;
|
|
249
|
+
const route = path === '/v1/chat/completions' ? 'chat_completions' :
|
|
250
|
+
path === '/v1/responses' ? 'responses' :
|
|
251
|
+
path === '/v1/messages' ? 'anthropic_messages' : undefined;
|
|
252
|
+
if (!route)
|
|
253
|
+
return;
|
|
254
|
+
const correlationHash = (0, task_model_diagnostics_1.hashTaskModelDiagnosticSession)(request.headers['x-opencode-session']);
|
|
255
|
+
if (!correlationHash)
|
|
256
|
+
return;
|
|
257
|
+
const startedAt = Date.now();
|
|
258
|
+
const observe = (statusSource) => {
|
|
259
|
+
response.off('finish', onFinish);
|
|
260
|
+
response.off('close', onClose);
|
|
261
|
+
// An unsent close has no actual caller HTTP status, regardless of statusCode.
|
|
262
|
+
if (statusSource === 'response_closed' && !response.headersSent)
|
|
263
|
+
return;
|
|
264
|
+
try {
|
|
265
|
+
const receipt = (0, task_model_diagnostics_1.selectTaskModelDiagnosticReceipt)({
|
|
266
|
+
event: 'xpod.task-gateway-http-diagnostic', schemaVersion: 1, scope: 'session',
|
|
267
|
+
correlationHash, route, callerHTTPstatus: response.statusCode, statusSource,
|
|
268
|
+
durationMs: Math.max(0, Math.min(2147483647, Date.now() - startedAt)),
|
|
269
|
+
});
|
|
270
|
+
if (receipt)
|
|
271
|
+
this.logger.error(JSON.stringify(receipt));
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
// Diagnostics are observational; a failing sink must not affect HTTP or cleanup.
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
const onFinish = () => observe('response_finished');
|
|
278
|
+
const onClose = () => observe('response_closed');
|
|
279
|
+
response.once('finish', onFinish);
|
|
280
|
+
response.once('close', onClose);
|
|
281
|
+
}
|
|
244
282
|
findRoute(method, path) {
|
|
245
283
|
for (const route of this.routes) {
|
|
246
284
|
if (!route.allMethods && route.method !== method) {
|
|
@@ -17,7 +17,7 @@ class DrizzlePodAiConfigStore {
|
|
|
17
17
|
db.findById(models_1.aiConfigResource, id),
|
|
18
18
|
db.findById(XpodAiConfigSchema_1.xpodAiConfigResource, id),
|
|
19
19
|
]);
|
|
20
|
-
return policyFromRows(sharedRow, productRow);
|
|
20
|
+
return policyFromRows(sharedRow, productRow, input.podUrl);
|
|
21
21
|
}
|
|
22
22
|
async update(input) {
|
|
23
23
|
const { db } = await this.open(input);
|
|
@@ -26,7 +26,7 @@ class DrizzlePodAiConfigStore {
|
|
|
26
26
|
db.findById(models_1.aiConfigResource, id),
|
|
27
27
|
db.findById(XpodAiConfigSchema_1.xpodAiConfigResource, id),
|
|
28
28
|
]);
|
|
29
|
-
const mergedPolicy = mergePolicy(policyFromRows(sharedCurrent, productCurrent), input.patch, this.now());
|
|
29
|
+
const mergedPolicy = mergePolicy(policyFromRows(sharedCurrent, productCurrent, input.podUrl), input.patch, this.now(), input.podUrl);
|
|
30
30
|
await Promise.all([
|
|
31
31
|
writeRow(db, models_1.aiConfigResource, id, sharedCurrent, sharedRowFromPolicy(mergedPolicy)),
|
|
32
32
|
writeRow(db, XpodAiConfigSchema_1.xpodAiConfigResource, id, productCurrent, productRowFromPolicy(mergedPolicy)),
|
|
@@ -49,7 +49,7 @@ exports.DrizzlePodAiConfigStore = DrizzlePodAiConfigStore;
|
|
|
49
49
|
function aiConfigResourceId() {
|
|
50
50
|
return models_1.aiConfigResource.buildId({ id: 'config' });
|
|
51
51
|
}
|
|
52
|
-
function policyFromRows(sharedRow, productRow) {
|
|
52
|
+
function policyFromRows(sharedRow, productRow, podUrl) {
|
|
53
53
|
const defaults = defaultPolicy();
|
|
54
54
|
if (!sharedRow && !productRow)
|
|
55
55
|
return defaults;
|
|
@@ -58,7 +58,7 @@ function policyFromRows(sharedRow, productRow) {
|
|
|
58
58
|
const models = {};
|
|
59
59
|
for (const key of modelKeys) {
|
|
60
60
|
if (typeof shared[key] === 'string' && shared[key])
|
|
61
|
-
models[key] = shared[key];
|
|
61
|
+
models[key] = canonicalModelReference(shared[key], podUrl);
|
|
62
62
|
}
|
|
63
63
|
return {
|
|
64
64
|
schemaVersion: '1.0',
|
|
@@ -92,14 +92,14 @@ function policyFromRows(sharedRow, productRow) {
|
|
|
92
92
|
updatedAt: isoDate(shared.updatedAt),
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
|
-
function mergePolicy(current, patch, now) {
|
|
95
|
+
function mergePolicy(current, patch, now, podUrl) {
|
|
96
96
|
const models = { ...current.models };
|
|
97
97
|
for (const key of modelKeys) {
|
|
98
98
|
const value = patch.models?.[key];
|
|
99
99
|
if (value === null)
|
|
100
100
|
delete models[key];
|
|
101
101
|
else if (value !== undefined)
|
|
102
|
-
models[key] = value;
|
|
102
|
+
models[key] = canonicalModelReference(value, podUrl);
|
|
103
103
|
}
|
|
104
104
|
return {
|
|
105
105
|
schemaVersion: '1.0',
|
|
@@ -110,6 +110,18 @@ function mergePolicy(current, patch, now) {
|
|
|
110
110
|
updatedAt: now.toISOString(),
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
|
+
/** API refs may be Pod-root-relative; linked ORM columns require target-relative ids or absolute IRIs. */
|
|
114
|
+
function canonicalModelReference(ref, podUrl) {
|
|
115
|
+
if (/^[a-z][a-z\d+.-]*:/i.test(ref)) {
|
|
116
|
+
// Validate without serializing: external IRI lexical identity must survive.
|
|
117
|
+
new URL(ref);
|
|
118
|
+
return ref;
|
|
119
|
+
}
|
|
120
|
+
const parsed = models_1.aiModelResource.parseRef(ref);
|
|
121
|
+
if (!parsed)
|
|
122
|
+
throw new Error('Invalid AI model resource reference');
|
|
123
|
+
return models_1.aiModelResource.buildIri(podUrl, { id: parsed.resourceId });
|
|
124
|
+
}
|
|
113
125
|
function sharedRowFromPolicy(policy) {
|
|
114
126
|
return {
|
|
115
127
|
...Object.fromEntries(modelKeys.map((key) => [key, policy.models[key] ?? null])),
|
|
@@ -1874,28 +1874,49 @@ class ProviderConnectService {
|
|
|
1874
1874
|
throw new Error('credential_pool_not_configured');
|
|
1875
1875
|
}
|
|
1876
1876
|
const existing = await this.credentialRepository.getCredentialById(input);
|
|
1877
|
-
|
|
1877
|
+
if (!existing)
|
|
1878
|
+
return undefined;
|
|
1879
|
+
if (input.expectedVersion !== (existing.version ?? 0))
|
|
1880
|
+
throw new Error('credential_version_conflict');
|
|
1881
|
+
const replacingKey = Object.prototype.hasOwnProperty.call(input.patch, 'apiKey');
|
|
1882
|
+
let replacement = {};
|
|
1883
|
+
if (replacingKey) {
|
|
1884
|
+
if (typeof input.patch.apiKey !== 'string' || !input.patch.apiKey.trim())
|
|
1885
|
+
throw new Error('invalid_api_key');
|
|
1886
|
+
if (existing.authMode !== 'apiKey')
|
|
1887
|
+
throw new Error('credential_auth_mode_mismatch');
|
|
1888
|
+
if (!this.vault)
|
|
1889
|
+
throw new Error('credential_pool_not_configured');
|
|
1890
|
+
replacement = {
|
|
1891
|
+
encryptedSecret: await this.vault.seal({ webId: input.webId }, existing.credentialIri, existing.provider, { type: 'apiKey', apiKey: input.patch.apiKey.trim() }),
|
|
1892
|
+
reauthRequired: false, failCount: 0, lastFailureCode: undefined,
|
|
1893
|
+
lastFailureAt: undefined, rateLimitResetAt: undefined,
|
|
1894
|
+
health: (input.patch.enabled ?? existing.enabled) === false ? 'disabled' : 'unknown',
|
|
1895
|
+
};
|
|
1896
|
+
}
|
|
1897
|
+
const metadata = metadataFromRowValue(existing.metadata) ?? {};
|
|
1878
1898
|
const updated = await this.credentialRepository.updateCredential({
|
|
1879
1899
|
...input,
|
|
1880
|
-
patch: metadataWithoutUndefined({
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
proxyUrl: input.patch.proxyUrl === undefined
|
|
1885
|
-
? undefined
|
|
1886
|
-
: (0, provider_http_transport_1.normalizeProviderProxyUrl)(input.patch.proxyUrl),
|
|
1887
|
-
health: input.patch.enabled === false ? 'disabled' : undefined,
|
|
1888
|
-
metadata: metadataWithoutUndefined({
|
|
1889
|
-
...metadata,
|
|
1890
|
-
baseUrl: input.patch.baseUrl ?? metadata.baseUrl,
|
|
1900
|
+
patch: { ...metadataWithoutUndefined({
|
|
1901
|
+
accountLabel: input.patch.label,
|
|
1902
|
+
enabled: input.patch.enabled,
|
|
1903
|
+
priority: input.patch.priority,
|
|
1891
1904
|
proxyUrl: input.patch.proxyUrl === undefined
|
|
1892
|
-
?
|
|
1905
|
+
? undefined
|
|
1893
1906
|
: (0, provider_http_transport_1.normalizeProviderProxyUrl)(input.patch.proxyUrl),
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1907
|
+
health: input.patch.enabled === false ? 'disabled' : undefined,
|
|
1908
|
+
metadata: metadataWithoutUndefined({
|
|
1909
|
+
...metadata,
|
|
1910
|
+
baseUrl: input.patch.baseUrl ?? metadata.baseUrl,
|
|
1911
|
+
proxyUrl: input.patch.proxyUrl === undefined
|
|
1912
|
+
? metadata.proxyUrl
|
|
1913
|
+
: (0, provider_http_transport_1.normalizeProviderProxyUrl)(input.patch.proxyUrl),
|
|
1914
|
+
priority: input.patch.priority ?? metadata.priority,
|
|
1915
|
+
enabled: input.patch.enabled ?? metadata.enabled,
|
|
1916
|
+
health: replacingKey ? replacement.health : input.patch.enabled === false ? 'disabled' : metadata.health,
|
|
1917
|
+
...(replacingKey ? { maskedHint: maskApiKey(input.patch.apiKey.trim()) } : {}),
|
|
1918
|
+
}),
|
|
1919
|
+
}), ...replacement },
|
|
1899
1920
|
});
|
|
1900
1921
|
return updated ? publicPoolCredentialSummary(updated) : undefined;
|
|
1901
1922
|
}
|
|
@@ -29,12 +29,15 @@ class ProviderModelsResponseError extends Error {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
exports.ProviderModelsResponseError = ProviderModelsResponseError;
|
|
32
|
+
// Codex protocol compatibility baseline, independent of Xpod and ACP wrapper versions.
|
|
33
|
+
// Verified release: https://github.com/openai/codex/releases/tag/rust-v0.160.0
|
|
34
|
+
const CODEX_MODELS_CLIENT_VERSION = '0.160.0';
|
|
32
35
|
/** Discovers the models currently enabled for a ChatGPT Codex subscription. */
|
|
33
36
|
class CodexSubscriptionModelsAdapter {
|
|
34
37
|
constructor(options = {}) {
|
|
35
38
|
this.protocol = 'codex-models';
|
|
36
39
|
this.transport = options.transport ?? new provider_http_transport_1.ProviderHttpTransport();
|
|
37
|
-
this.clientVersion = options.clientVersion ??
|
|
40
|
+
this.clientVersion = options.clientVersion ?? CODEX_MODELS_CLIENT_VERSION;
|
|
38
41
|
}
|
|
39
42
|
async fetch(input) {
|
|
40
43
|
const accessToken = stringSecret(input.secret, 'accessToken', 'access_token');
|
|
@@ -57,7 +60,7 @@ class CodexSubscriptionModelsAdapter {
|
|
|
57
60
|
const models = Array.isArray(body?.models) ? body.models : [];
|
|
58
61
|
return models
|
|
59
62
|
.filter((model) => Boolean(model) && typeof model === 'object')
|
|
60
|
-
.filter((model) => model.visibility
|
|
63
|
+
.filter((model) => model.visibility === 'list')
|
|
61
64
|
.map((model) => ({
|
|
62
65
|
id: String(model.slug ?? model.id ?? '').trim(),
|
|
63
66
|
...(typeof model.display_name === 'string' && model.display_name.trim()
|
|
@@ -88,13 +88,19 @@ function resolveHostedPodCssBaseUrl(config) {
|
|
|
88
88
|
// instead of a foreign loopback port.
|
|
89
89
|
return config.solidBaseUrl;
|
|
90
90
|
}
|
|
91
|
-
function
|
|
92
|
-
|
|
91
|
+
function resolveAiConnectionsCanonicalOrigin(config) {
|
|
92
|
+
return config.publicUrl
|
|
93
93
|
?? process.env.XPOD_PUBLIC_URL
|
|
94
94
|
?? process.env.CSS_BASE_URL
|
|
95
95
|
?? `http://${config.host === '0.0.0.0' ? '127.0.0.1' : config.host}:${config.port}`;
|
|
96
|
+
}
|
|
97
|
+
function aiConnectionsV1Url(origin) {
|
|
96
98
|
return new URL('/v1', origin.endsWith('/') ? origin : `${origin}/`).toString().replace(/\/$/u, '');
|
|
97
99
|
}
|
|
100
|
+
/** The canonical identity realm: token audience/issuer and the two authenticators use this. */
|
|
101
|
+
function resolveAiConnectionsBaseUrl(config) {
|
|
102
|
+
return aiConnectionsV1Url(resolveAiConnectionsCanonicalOrigin(config));
|
|
103
|
+
}
|
|
98
104
|
function credentialVaultForConfig(config) {
|
|
99
105
|
return new PlaintextCredentialVault_1.PlaintextCredentialVault({
|
|
100
106
|
legacyVault: config.secretCellCredentialVaultFactory?.(),
|
|
@@ -220,8 +220,8 @@ function loadConfigFromEnv() {
|
|
|
220
220
|
baseStorageDomain: process.env.CSS_BASE_STORAGE_DOMAIN,
|
|
221
221
|
cloudflareAccountId: process.env.CLOUDFLARE_ACCOUNT_ID,
|
|
222
222
|
cloudflareApiToken: process.env.CLOUDFLARE_API_TOKEN,
|
|
223
|
-
tencentDnsSecretId: process.env.
|
|
224
|
-
tencentDnsSecretKey: process.env.
|
|
223
|
+
tencentDnsSecretId: process.env.TENCENT_DNSPOD_ID,
|
|
224
|
+
tencentDnsSecretKey: process.env.TENCENT_DNSPOD_TOKEN,
|
|
225
225
|
},
|
|
226
226
|
// Local 托管式:连接 Cloud
|
|
227
227
|
cloudApiEndpoint,
|
|
@@ -137,9 +137,12 @@ function registerLocalServices(container) {
|
|
|
137
137
|
// The settings page lets an operator pick the DNS provider, so the runtime honours that
|
|
138
138
|
// choice instead of always wiring Cloudflare and ignoring a saved "tencent".
|
|
139
139
|
const dnsProviderId = process.env.XPOD_DNS_PROVIDER?.trim().toLowerCase() || 'cloudflare';
|
|
140
|
-
const tencentDnsToken = process.env.
|
|
141
|
-
const tencentDnsTokenId = process.env.
|
|
142
|
-
|
|
140
|
+
const tencentDnsToken = process.env.TENCENT_DNSPOD_TOKEN?.trim();
|
|
141
|
+
const tencentDnsTokenId = process.env.TENCENT_DNSPOD_ID?.trim();
|
|
142
|
+
// DNSPod 需要 ID 与 Token 同时具备;只看 token 会注册一个实际禁用的 provider(静默失效)。
|
|
143
|
+
const dnsCredentialReady = dnsProviderId === 'tencent'
|
|
144
|
+
? Boolean(tencentDnsToken && tencentDnsTokenId)
|
|
145
|
+
: Boolean(apiToken);
|
|
143
146
|
if (dnsCredentialReady && baseDomain) {
|
|
144
147
|
console.log(`[Local] Self-hosted DNS mode detected (provider: ${dnsProviderId})`);
|
|
145
148
|
container.register({
|
|
@@ -18,6 +18,7 @@ export declare class AiGatewayHandler {
|
|
|
18
18
|
handleModels(request: AuthenticatedRequest, response: ServerResponse): Promise<void>;
|
|
19
19
|
handleAcceptanceProvenance(request: AuthenticatedRequest, response: ServerResponse): Promise<void>;
|
|
20
20
|
private sendEventStream;
|
|
21
|
+
private logTaskGatewayFailure;
|
|
21
22
|
private logInference;
|
|
22
23
|
private writeTerminalStreamError;
|
|
23
24
|
private sendGatewayError;
|
|
@@ -6,7 +6,9 @@ const global_logger_factory_1 = require("global-logger-factory");
|
|
|
6
6
|
const readBoundedJsonBody_1 = require("../http/readBoundedJsonBody");
|
|
7
7
|
const errors_1 = require("../ai-gateway/errors");
|
|
8
8
|
const InvocationMetadata_1 = require("../ai-gateway/InvocationMetadata");
|
|
9
|
+
const task_model_diagnostics_1 = require("../../util/task-model-diagnostics");
|
|
9
10
|
const DEFAULT_JSON_BODY_LIMIT_BYTES = 2 * 1024 * 1024;
|
|
11
|
+
const TASK_GATEWAY_CODES = new Set(task_model_diagnostics_1.TASK_GATEWAY_DIAGNOSTIC_CODES);
|
|
10
12
|
function registerAiGatewayRoutes(server, options) {
|
|
11
13
|
const handler = new AiGatewayHandler(options);
|
|
12
14
|
server.post('/v1/responses', (request, response) => handler.handleInference(request, response, 'responses'));
|
|
@@ -25,12 +27,20 @@ class AiGatewayHandler {
|
|
|
25
27
|
}
|
|
26
28
|
async handleInference(request, response, protocol) {
|
|
27
29
|
const startedAt = Date.now();
|
|
30
|
+
// Observation only: preserve the existing body/header validation ordering.
|
|
31
|
+
let correlationHash;
|
|
32
|
+
try {
|
|
33
|
+
correlationHash = (0, task_model_diagnostics_1.hashTaskModelDiagnosticSession)((0, InvocationMetadata_1.readGatewayInvocationMetadata)(request.headers, request.rawHeaders).sessionId);
|
|
34
|
+
}
|
|
35
|
+
catch { /* Invalid invocation metadata is rejected by the existing path. */ }
|
|
28
36
|
const bodyResult = await (0, readBoundedJsonBody_1.readBoundedJsonBody)(request, { limitBytes: this.jsonBodyLimitBytes });
|
|
29
37
|
if (!bodyResult.ok) {
|
|
30
|
-
|
|
38
|
+
const error = new errors_1.GatewayProtocolError(bodyResult.error, {
|
|
31
39
|
code: 'invalid_request',
|
|
32
40
|
status: bodyResult.status,
|
|
33
|
-
})
|
|
41
|
+
});
|
|
42
|
+
this.sendGatewayError(response, error);
|
|
43
|
+
this.logTaskGatewayFailure(correlationHash, response, protocol, startedAt, false, taskGatewayFailure(error));
|
|
34
44
|
return;
|
|
35
45
|
}
|
|
36
46
|
const model = readRequestedModel(bodyResult.value);
|
|
@@ -69,16 +79,25 @@ class AiGatewayHandler {
|
|
|
69
79
|
});
|
|
70
80
|
const outcome = await this.sendEventStream(response, execution.frontend, execution.events);
|
|
71
81
|
this.logInference({ protocol, model, stream: true, startedAt, ...outcome });
|
|
82
|
+
if (outcome.failure) {
|
|
83
|
+
this.logTaskGatewayFailure(correlationHash, response, protocol, startedAt, true, outcome.failure);
|
|
84
|
+
}
|
|
72
85
|
}
|
|
73
86
|
catch (error) {
|
|
74
87
|
if (controller.signal.aborted || response.destroyed) {
|
|
75
88
|
return;
|
|
76
89
|
}
|
|
77
90
|
if (response.headersSent) {
|
|
78
|
-
|
|
91
|
+
try {
|
|
92
|
+
await this.writeTerminalStreamError(response, error);
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
this.logTaskGatewayFailure(correlationHash, response, protocol, startedAt, isStreamRequest(bodyResult.value), taskGatewayFailure(error));
|
|
96
|
+
}
|
|
79
97
|
return;
|
|
80
98
|
}
|
|
81
99
|
this.sendGatewayError(response, error);
|
|
100
|
+
this.logTaskGatewayFailure(correlationHash, response, protocol, startedAt, false, taskGatewayFailure(error));
|
|
82
101
|
}
|
|
83
102
|
finally {
|
|
84
103
|
response.off('close', abort);
|
|
@@ -175,6 +194,7 @@ class AiGatewayHandler {
|
|
|
175
194
|
}
|
|
176
195
|
catch (error) {
|
|
177
196
|
outcome.outcome = disconnected ? 'disconnected' : 'failed';
|
|
197
|
+
outcome.failure = taskGatewayFailure(error);
|
|
178
198
|
await returnIterator();
|
|
179
199
|
if (!disconnected) {
|
|
180
200
|
await this.writeTerminalStreamError(response, error);
|
|
@@ -188,9 +208,26 @@ class AiGatewayHandler {
|
|
|
188
208
|
}
|
|
189
209
|
if (disconnected) {
|
|
190
210
|
outcome.outcome = 'disconnected';
|
|
211
|
+
outcome.failure ??= taskGatewayFailure(undefined);
|
|
191
212
|
}
|
|
192
213
|
return outcome;
|
|
193
214
|
}
|
|
215
|
+
logTaskGatewayFailure(correlationHash, response, protocol, startedAt, streamOpen, failure) {
|
|
216
|
+
if (!correlationHash || !diagnosticHTTPStatus(response.statusCode))
|
|
217
|
+
return;
|
|
218
|
+
const route = protocol === 'chatCompletions' ? 'chat_completions'
|
|
219
|
+
: protocol === 'responses' ? 'responses' : 'anthropic_messages';
|
|
220
|
+
try {
|
|
221
|
+
const receipt = (0, task_model_diagnostics_1.selectTaskModelDiagnosticReceipt)({
|
|
222
|
+
event: 'xpod.task-gateway-diagnostic', schemaVersion: 1, scope: 'session', correlationHash, route,
|
|
223
|
+
callerHTTPstatus: response.statusCode, ...failure, streamOpen,
|
|
224
|
+
durationMs: Math.min(2_147_483_647, Math.max(0, Math.floor(Date.now() - startedAt))),
|
|
225
|
+
});
|
|
226
|
+
if (receipt)
|
|
227
|
+
this.logger.error(JSON.stringify(receipt));
|
|
228
|
+
}
|
|
229
|
+
catch { /* An observational receipt must not alter the response or cleanup. */ }
|
|
230
|
+
}
|
|
194
231
|
logInference(summary) {
|
|
195
232
|
const fields = [
|
|
196
233
|
`protocol=${summary.protocol}`,
|
|
@@ -232,6 +269,19 @@ class AiGatewayHandler {
|
|
|
232
269
|
}
|
|
233
270
|
}
|
|
234
271
|
exports.AiGatewayHandler = AiGatewayHandler;
|
|
272
|
+
function diagnosticHTTPStatus(value) {
|
|
273
|
+
return typeof value === 'number' && Number.isInteger(value) && value >= 100 && value <= 599 ? value : undefined;
|
|
274
|
+
}
|
|
275
|
+
function taskGatewayFailure(error) {
|
|
276
|
+
const code = (0, errors_1.normalizeGatewayError)(error).error.code;
|
|
277
|
+
const source = error && typeof error === 'object' ? error : undefined;
|
|
278
|
+
const cause = source?.cause && typeof source.cause === 'object' ? source.cause : undefined;
|
|
279
|
+
const underlyingErrorStatus = diagnosticHTTPStatus(cause?.status) ?? diagnosticHTTPStatus(source?.status);
|
|
280
|
+
return {
|
|
281
|
+
code: TASK_GATEWAY_CODES.has(code) ? code : 'internal_error',
|
|
282
|
+
...(underlyingErrorStatus !== undefined ? { underlyingErrorStatus } : {}),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
235
285
|
async function writeSerializedEvents(response, serialized) {
|
|
236
286
|
for (const event of Array.isArray(serialized) ? serialized : [serialized]) {
|
|
237
287
|
await writeWithBackpressure(response, `data: ${JSON.stringify(event)}\n\n`);
|
|
@@ -1200,6 +1200,11 @@ function publicGatewayAccessKeyRecord(record, plaintextAvailable, plaintext) {
|
|
|
1200
1200
|
}
|
|
1201
1201
|
function normalizeCredentialPatch(body) {
|
|
1202
1202
|
const patch = {};
|
|
1203
|
+
if (Object.prototype.hasOwnProperty.call(body, 'apiKey')) {
|
|
1204
|
+
if (typeof body.apiKey !== 'string' || !body.apiKey.trim())
|
|
1205
|
+
return undefined;
|
|
1206
|
+
patch.apiKey = body.apiKey.trim();
|
|
1207
|
+
}
|
|
1203
1208
|
if (body.label !== undefined) {
|
|
1204
1209
|
const label = normalizeOptionalString(body.label);
|
|
1205
1210
|
if (!label) {
|
|
@@ -1330,6 +1335,10 @@ function sendCredentialPoolError(response, error) {
|
|
|
1330
1335
|
sendJson(response, message === 'local_session_refresh_failed' ? 502 : 409, { error: message });
|
|
1331
1336
|
return;
|
|
1332
1337
|
}
|
|
1338
|
+
if (message === 'invalid_api_key' || message === 'credential_auth_mode_mismatch') {
|
|
1339
|
+
sendJson(response, 400, { error: message });
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1333
1342
|
if (message === 'credential_version_conflict') {
|
|
1334
1343
|
sendJson(response, 409, { error: 'credential_version_conflict' });
|
|
1335
1344
|
return;
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registerTaskRoutes = registerTaskRoutes;
|
|
4
4
|
exports.projectTask = projectTask;
|
|
5
|
+
const TaskResumeDiagnostics_1 = require("../tasks/TaskResumeDiagnostics");
|
|
5
6
|
const RunCancellation_1 = require("../runs/RunCancellation");
|
|
6
7
|
const PodAccessFailureResponse_1 = require("./PodAccessFailureResponse");
|
|
7
8
|
/** UI reads durable Pod projections; the scheduler is never a query backend. */
|
|
8
9
|
function registerTaskRoutes(server, options) {
|
|
9
|
-
const guarded = (handler) => async (request, response) => {
|
|
10
|
+
const guarded = (handler, resume = false) => async (request, response) => {
|
|
10
11
|
if (request.auth?.type !== 'solid') {
|
|
11
12
|
send(response, 401, { error: 'Authentication required' });
|
|
12
13
|
return;
|
|
@@ -17,7 +18,7 @@ function registerTaskRoutes(server, options) {
|
|
|
17
18
|
catch (error) {
|
|
18
19
|
if ((0, PodAccessFailureResponse_1.sendPodAccessFailure)(response, error))
|
|
19
20
|
return;
|
|
20
|
-
send(response, 400, { error: error instanceof Error ? error.message : 'Task request failed' });
|
|
21
|
+
send(response, 400, { error: error instanceof Error ? error.message : 'Task request failed', ...(resume ? { taskResumeStage: (0, TaskResumeDiagnostics_1.getTaskResumeStage)(error) ?? 'route_request', taskResumeErrorType: (0, TaskResumeDiagnostics_1.getTaskResumeErrorType)(error), taskResumeFailure: (0, TaskResumeDiagnostics_1.getTaskResumeFailure)(error) } : {}) });
|
|
21
22
|
}
|
|
22
23
|
};
|
|
23
24
|
const idOf = (request) => {
|
|
@@ -96,16 +97,20 @@ function registerTaskRoutes(server, options) {
|
|
|
96
97
|
return { runs: (await options.runStore.listRuns({ task: task.id }, context)).map(projectRun) };
|
|
97
98
|
}));
|
|
98
99
|
server.post('/api/tasks/resume', guarded(async (request, context, owner) => {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
100
|
+
const { approval, target } = await (0, TaskResumeDiagnostics_1.withTaskResumeStage)('route_validation', async () => {
|
|
101
|
+
const input = await body(request);
|
|
102
|
+
return { approval: requiredString(input.approval, 'Approval'), target: idOf(request) };
|
|
103
|
+
});
|
|
104
|
+
const run = await (0, TaskResumeDiagnostics_1.withTaskResumeStage)('route_run_read', async () => {
|
|
105
|
+
const run = (await options.runStore.listRuns({}, context)).find(item => item.id === target)
|
|
106
|
+
?? (target.startsWith('https://') || target.startsWith('http://') ? undefined : await options.runStore.loadRun(target, context));
|
|
107
|
+
if (!run)
|
|
108
|
+
throw new Error('Run not found');
|
|
109
|
+
return run;
|
|
110
|
+
});
|
|
106
111
|
const result = await options.taskService.resumeApprovedRun({ runId: run.id, approval, owner }, context, options.resolveExecutionContext);
|
|
107
112
|
return { ...result, run: projectRun(result.run) };
|
|
108
|
-
}));
|
|
113
|
+
}, true));
|
|
109
114
|
server.get('/api/tasks/selection', guarded(async (request, context, owner) => {
|
|
110
115
|
const target = idOf(request);
|
|
111
116
|
const runs = await options.runStore.listRuns({}, context);
|
|
@@ -159,7 +159,7 @@ function firstString(...values) {
|
|
|
159
159
|
function splitList(value) { return value?.split(',').map((item) => item.trim()).filter(Boolean) ?? []; }
|
|
160
160
|
function positiveInteger(value, fallback) { const parsed = Number(value); return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback; }
|
|
161
161
|
function dnsCredential(env, provider) { return env[dnsCredentialKey(provider)]; }
|
|
162
|
-
function dnsCredentialKey(provider) { return provider === 'tencent' ? '
|
|
162
|
+
function dnsCredentialKey(provider) { return provider === 'tencent' ? 'TENCENT_DNSPOD_TOKEN' : provider === 'cloudflare' ? 'CLOUDFLARE_API_TOKEN' : 'XPOD_DNS_PROVIDER_TOKEN'; }
|
|
163
163
|
function p2pFallback(value) { return value === 'never' || value === 'prefer-p2p' ? value : 'when-direct-unavailable'; }
|
|
164
164
|
function plainStringRecord(value) { return Boolean(value) && typeof value === 'object' && !Array.isArray(value) && Object.values(value).every((item) => typeof item === 'string'); }
|
|
165
165
|
function boolString(value) { return value === undefined ? undefined : String(value); }
|
|
@@ -37,7 +37,6 @@ export declare class ManagedRunWorker<TContext = StoreContext> {
|
|
|
37
37
|
private loadRunInput;
|
|
38
38
|
private resolveUserMessage;
|
|
39
39
|
private resolveRuntimeConfig;
|
|
40
|
-
private authBindingIdFromRun;
|
|
41
40
|
private asRuntimeConfig;
|
|
42
41
|
private parseRunner;
|
|
43
42
|
private isRunnerType;
|
|
@@ -76,7 +76,7 @@ class ManagedRunWorker {
|
|
|
76
76
|
conversation,
|
|
77
77
|
retrievedContext,
|
|
78
78
|
config: runtimeConfig,
|
|
79
|
-
authBindingId:
|
|
79
|
+
authBindingId: (0, store_1.resolveRunAuthBindingId)(run),
|
|
80
80
|
context: context,
|
|
81
81
|
})) {
|
|
82
82
|
const cancelled = await finishCancellation();
|
|
@@ -209,7 +209,7 @@ class ManagedRunWorker {
|
|
|
209
209
|
conversation,
|
|
210
210
|
retrievedContext,
|
|
211
211
|
config: loaded.runtimeConfig,
|
|
212
|
-
authBindingId:
|
|
212
|
+
authBindingId: (0, store_1.resolveRunAuthBindingId)(loaded.run),
|
|
213
213
|
context: context,
|
|
214
214
|
};
|
|
215
215
|
}
|
|
@@ -266,18 +266,6 @@ class ManagedRunWorker {
|
|
|
266
266
|
runner: this.parseRunner(run.runner),
|
|
267
267
|
};
|
|
268
268
|
}
|
|
269
|
-
authBindingIdFromRun(run) {
|
|
270
|
-
const authBindingId = run.metadata?.authBindingId;
|
|
271
|
-
if (typeof authBindingId === 'string' && authBindingId.length > 0) {
|
|
272
|
-
return authBindingId;
|
|
273
|
-
}
|
|
274
|
-
const authBinding = run.metadata?.authBinding;
|
|
275
|
-
if (authBinding && typeof authBinding === 'object') {
|
|
276
|
-
const id = authBinding.id;
|
|
277
|
-
return typeof id === 'string' && id.length > 0 ? id : undefined;
|
|
278
|
-
}
|
|
279
|
-
return undefined;
|
|
280
|
-
}
|
|
281
269
|
asRuntimeConfig(value) {
|
|
282
270
|
if (!value || typeof value !== 'object') {
|
|
283
271
|
return undefined;
|
|
@@ -97,14 +97,6 @@ export declare class PiAgentRuntimeDriver implements RunExecutionBackend {
|
|
|
97
97
|
private workerEnv;
|
|
98
98
|
private extractText;
|
|
99
99
|
private formatError;
|
|
100
|
-
/**
|
|
101
|
-
* Record a failed assistant turn with allowlisted wire facts only.
|
|
102
|
-
*
|
|
103
|
-
* The provider `errorMessage` can contain credentials, prompts, or response bodies, so it never
|
|
104
|
-
* leaves this method. What is kept is enough to place the failure: the protocol/provider/model
|
|
105
|
-
* and a stable coarse classification derived from the shape of the message (never its text).
|
|
106
|
-
*/
|
|
107
|
-
private logAssistantFailure;
|
|
108
100
|
private startupErrorToEvent;
|
|
109
101
|
private logWorkspaceRollbackError;
|
|
110
102
|
private loadPiSdk;
|