@xenosystem/agent-interface-electron-host 0.1.36 → 0.1.37
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/sdkAgent.d.ts +39 -0
- package/dist/sdkAgent.d.ts.map +1 -1
- package/dist/sdkAgent.js +179 -8
- package/dist/sdkAgent.js.map +1 -1
- package/dist/sdkNativeHeadlessRunner.d.ts +16 -0
- package/dist/sdkNativeHeadlessRunner.d.ts.map +1 -1
- package/dist/sdkNativeHeadlessRunner.js +1 -0
- package/dist/sdkNativeHeadlessRunner.js.map +1 -1
- package/dist/sdkNativeRunner.d.ts +16 -0
- package/dist/sdkNativeRunner.d.ts.map +1 -1
- package/dist/sdkNativeRunner.js +1 -0
- package/dist/sdkNativeRunner.js.map +1 -1
- package/package.json +3 -3
- package/dist/desktopDocumentConnections.d.ts +0 -30
- package/dist/desktopDocumentConnections.d.ts.map +0 -1
- package/dist/desktopDocumentConnections.js +0 -81
- package/dist/desktopDocumentConnections.js.map +0 -1
- package/dist/desktopSenderAuthority.d.ts +0 -45
- package/dist/desktopSenderAuthority.d.ts.map +0 -1
- package/dist/desktopSenderAuthority.js +0 -133
- package/dist/desktopSenderAuthority.js.map +0 -1
- package/dist/sdkExecutionSettlement.d.ts +0 -27
- package/dist/sdkExecutionSettlement.d.ts.map +0 -1
- package/dist/sdkExecutionSettlement.js +0 -53
- package/dist/sdkExecutionSettlement.js.map +0 -1
package/dist/sdkAgent.d.ts
CHANGED
|
@@ -104,6 +104,16 @@ export declare function registerSdkNativeGovernedAutomationTools(options: {
|
|
|
104
104
|
agentId?: string;
|
|
105
105
|
sessionId?: string;
|
|
106
106
|
workspaceId?: string;
|
|
107
|
+
/**
|
|
108
|
+
* Where XENO Use is, from the host's ONE resolver (`resolveMachineEndpoint`). Optional because
|
|
109
|
+
* a host without it is a host with no machine to drive — not an error.
|
|
110
|
+
*/
|
|
111
|
+
machineEndpoint?: {
|
|
112
|
+
baseUrl: string;
|
|
113
|
+
bearer: string;
|
|
114
|
+
deviceId?: string;
|
|
115
|
+
allowedApplications: string[];
|
|
116
|
+
};
|
|
107
117
|
}): number;
|
|
108
118
|
export type { AgentPermissionProfileName, AgentSandboxCapabilities, } from '@xenosystem/agent-interface-host/node';
|
|
109
119
|
export interface SdkAgentRunOptions {
|
|
@@ -140,6 +150,24 @@ export interface SdkAgentRunOptions {
|
|
|
140
150
|
enableThinking?: boolean;
|
|
141
151
|
reasoningEffort?: string;
|
|
142
152
|
getAuthToken: () => string | null;
|
|
153
|
+
/**
|
|
154
|
+
* Authorize one inference request as the SIGNED-IN ACCOUNT.
|
|
155
|
+
*
|
|
156
|
+
* 🔴 This is the DEFAULT credential, and `getAuthToken` is the bring-your-own override — not the
|
|
157
|
+
* other way round. A person signed into XENO should not also need an API key, and until this
|
|
158
|
+
* existed they did: the lane could only express a static bearer, so a signed-in account with no
|
|
159
|
+
* key was reported as "requires the host-managed direct credential" and refused.
|
|
160
|
+
*
|
|
161
|
+
* Per-request because a DPoP proof binds to one method and URL. The gateway requires that scheme
|
|
162
|
+
* for an OIDC token, so a single string handed over once could never have carried it.
|
|
163
|
+
*/
|
|
164
|
+
authorizeRequest?: (target: {
|
|
165
|
+
method: string;
|
|
166
|
+
url: string;
|
|
167
|
+
}) => Promise<{
|
|
168
|
+
authorization: string;
|
|
169
|
+
dpop?: string;
|
|
170
|
+
} | null>;
|
|
143
171
|
getPlatformAuthToken?: () => string | null;
|
|
144
172
|
mainWindow: SdkAgentSurface;
|
|
145
173
|
signal: AbortSignal;
|
|
@@ -195,6 +223,17 @@ export interface AgentCommandExecutionEnvironment {
|
|
|
195
223
|
};
|
|
196
224
|
};
|
|
197
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Exported for tests ONLY — it is not part of the host's public surface.
|
|
228
|
+
*
|
|
229
|
+
* This predicate decides whether a failed turn is RETRIED and whether it falls back, so its
|
|
230
|
+
* classification is behaviour, not wording, and it earned a gate the hard way (see the
|
|
231
|
+
* auth-dependency note below). Testing it through a whole turn would need a live provider
|
|
232
|
+
* failure, which is exactly the shape that goes untested and then ships.
|
|
233
|
+
*/
|
|
234
|
+
export declare function isCloudApiTransientErrorMessage(message: string): boolean;
|
|
235
|
+
/** Exported for tests ONLY — see {@link isCloudApiTransientErrorMessage}. Not a public API. */
|
|
236
|
+
export declare function sanitizeAgentRunErrorMessage(error: Error | string): string;
|
|
198
237
|
export declare function runSdkAgent(options: SdkAgentRunOptions): Promise<void>;
|
|
199
238
|
export declare function grantSdkAccess(params: unknown): {
|
|
200
239
|
success: boolean;
|
package/dist/sdkAgent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdkAgent.d.ts","sourceRoot":"","sources":["../src/sdkAgent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,kCAAkC,CAAA;AACzC,OAAO,EAKL,KAAK,oBAAoB,EAC1B,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EAA2B,KAAK,8BAA8B,EAAE,MAAM,uCAAuC,CAAA;
|
|
1
|
+
{"version":3,"file":"sdkAgent.d.ts","sourceRoot":"","sources":["../src/sdkAgent.ts"],"names":[],"mappings":"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"}
|
package/dist/sdkAgent.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { createPermissionWaitRegistry, } from '@xenosystem/agent-interface-host';
|
|
12
12
|
import { commandSucceeded, commandShellArgv, LocalCommandExecutor, } from '@xenosystem/agent-interface-host/node';
|
|
13
13
|
import { sdkExecutionSettlements } from '@xenosystem/agent-interface-host/node';
|
|
14
|
+
import { resolveMachineTarget } from '@xenosystem/agent-interface-host/node';
|
|
14
15
|
import { spawn } from 'child_process';
|
|
15
16
|
import { createHash } from 'node:crypto';
|
|
16
17
|
import { requireSdkReasoningEffort } from './sdkReasoning.js';
|
|
@@ -25,7 +26,19 @@ import { answerChooseDirectoryRequest, answerWorkspacePlacementRequest, buildRun
|
|
|
25
26
|
import { clickBrowserSurface, gotoBrowserSurface, keyBrowserSurface, listBrowserSurfacesForAgent, listPtySurfaceSessions, readPtySurfaceOutput, snapshotBrowserSurface, typeBrowserSurface, writePtySurfaceInput, } from './surfaceRuntimeBridge.js';
|
|
26
27
|
import { loadWorkspaceTreeFromDisk, saveWorkspaceTreeToDisk } from './workspaceStateBridge.js';
|
|
27
28
|
const DEFAULT_CLOUD_API_BASE = 'https://api.xenostudio.ai';
|
|
28
|
-
|
|
29
|
+
/**
|
|
30
|
+
* 🔴 `https`, and it was `http` — the one scheme this endpoint refuses.
|
|
31
|
+
*
|
|
32
|
+
* Measured against the live host: `http://direct-api.xenostudio.ai:8443/v1/models` answers
|
|
33
|
+
* **400 `HTTPS required. Use https://direct-api.xenostudio.ai:8443`**, while the same path over
|
|
34
|
+
* https answers 401, the correct "authenticate first". So every request built on this default was
|
|
35
|
+
* rejected before authentication was even considered, and the failure surfaced far away as a
|
|
36
|
+
* generic cloud-unavailable error rather than as a bad URL.
|
|
37
|
+
*
|
|
38
|
+
* ⚠️ It also sends a credential over plaintext to a host that will not serve it — the redirect
|
|
39
|
+
* never happens because the server answers 400 instead of 301.
|
|
40
|
+
*/
|
|
41
|
+
const DEFAULT_DIRECT_API_BASE = 'https://direct-api.xenostudio.ai:8443';
|
|
29
42
|
function normalizeApiBase(baseURL) {
|
|
30
43
|
return baseURL.trim().replace(/\/+$/, '');
|
|
31
44
|
}
|
|
@@ -2233,6 +2246,28 @@ export function registerSdkNativeGovernedAutomationTools(options) {
|
|
|
2233
2246
|
const environment = structuredClone(options.environment);
|
|
2234
2247
|
if (options.capabilities.browser === false)
|
|
2235
2248
|
delete environment.browser;
|
|
2249
|
+
/**
|
|
2250
|
+
* 🔴 The computer surface was registered and could never resolve an adapter.
|
|
2251
|
+
*
|
|
2252
|
+
* `readXenoHostAutomationEnvironment()` fills `environment.computer` from ambient `XENO_USE_*`
|
|
2253
|
+
* variables, and NOTHING in this repo ever set them — measured, zero configuration sites — so
|
|
2254
|
+
* every turn registered COMPUTER_OBSERVE and COMPUTER_ACT against an endpoint that did not
|
|
2255
|
+
* exist. The tools were present, the profile allowed them, and the adapter behind them was
|
|
2256
|
+
* undefined: the "built, wired, unreachable" shape this repo keeps finding, in its quietest
|
|
2257
|
+
* form, because a tool that cannot resolve its adapter fails at CALL time and reads to the
|
|
2258
|
+
* model as the machine being unavailable rather than as us never having connected it.
|
|
2259
|
+
*
|
|
2260
|
+
* The host's resolver now supplies it, so the machine the PERSON can grant in Machine mode and
|
|
2261
|
+
* the machine the MODEL can reach mid-turn are the same machine, configured once.
|
|
2262
|
+
*/
|
|
2263
|
+
if (options.machineEndpoint) {
|
|
2264
|
+
environment.computer = {
|
|
2265
|
+
baseUrl: options.machineEndpoint.baseUrl,
|
|
2266
|
+
token: options.machineEndpoint.bearer,
|
|
2267
|
+
...(options.machineEndpoint.deviceId ? { deviceId: options.machineEndpoint.deviceId } : {}),
|
|
2268
|
+
allowedApplications: [...options.machineEndpoint.allowedApplications],
|
|
2269
|
+
};
|
|
2270
|
+
}
|
|
2236
2271
|
if (options.capabilities.appLaunch === false)
|
|
2237
2272
|
delete environment.computer;
|
|
2238
2273
|
const profile = options.sdk.compileAgentProfile(profileDefinition);
|
|
@@ -2257,10 +2292,27 @@ function isCloudTunnelFailure(status, body) {
|
|
|
2257
2292
|
function isUsingConfiguredDirectCloudApi() {
|
|
2258
2293
|
return CLOUD_API_BASE === DIRECT_API_BASE || !!process.env.XENO_AGENT_API_BASE || !!process.env.XENO_DIRECT_API_BASE;
|
|
2259
2294
|
}
|
|
2260
|
-
|
|
2295
|
+
/**
|
|
2296
|
+
* Whether this turn must go through the hosted text-only relay instead of the SDK runtime.
|
|
2297
|
+
*
|
|
2298
|
+
* 🔴 `hasDirectCredential` is NOT "has an API key", and that difference is the whole fix. This
|
|
2299
|
+
* read `!hasDirectApiKey` and was called with `!!apiKey`, so a person signed into XENO with no key
|
|
2300
|
+
* was diverted into the relay before the SDK ever ran — and since an engineering turn refuses to
|
|
2301
|
+
* be downgraded, the turn died with "the tool-capable SDK runtime is unavailable". The account was
|
|
2302
|
+
* valid at the gateway the entire time.
|
|
2303
|
+
*
|
|
2304
|
+
* That is the third place this equivalence was written. The lane policy and the model catalogue
|
|
2305
|
+
* were fixed first; this one sits below both, so a turn could pass every credential check above it
|
|
2306
|
+
* and still be routed away from the runtime here. Measured against the live gateway: an account
|
|
2307
|
+
* with no API key produced `platform-chat-fallback-…` request ids until this changed.
|
|
2308
|
+
*
|
|
2309
|
+
* The relay exists for a real case — the direct cloud API being unreachable — so the probe below
|
|
2310
|
+
* still runs. What no longer happens is treating "no API key" as "no credential".
|
|
2311
|
+
*/
|
|
2312
|
+
async function shouldUsePlatformChatFallback(hasDirectCredential) {
|
|
2261
2313
|
if (isUsingConfiguredDirectCloudApi())
|
|
2262
2314
|
return false;
|
|
2263
|
-
if (!
|
|
2315
|
+
if (!hasDirectCredential)
|
|
2264
2316
|
return true;
|
|
2265
2317
|
const now = Date.now();
|
|
2266
2318
|
if (cloudChatFallbackCache && (now - cloudChatFallbackCache.checkedAt) < 30000) {
|
|
@@ -2353,8 +2405,27 @@ function extractRetryAfterMs(message) {
|
|
|
2353
2405
|
function extractCloudflareRay(message) {
|
|
2354
2406
|
return message.match(/\bcf-ray=([a-z0-9-]+)\b/i)?.[1] || message.match(/Cloudflare Ray ID:\s*([a-z0-9]+)/i)?.[1] || null;
|
|
2355
2407
|
}
|
|
2356
|
-
|
|
2408
|
+
/**
|
|
2409
|
+
* Exported for tests ONLY — it is not part of the host's public surface.
|
|
2410
|
+
*
|
|
2411
|
+
* This predicate decides whether a failed turn is RETRIED and whether it falls back, so its
|
|
2412
|
+
* classification is behaviour, not wording, and it earned a gate the hard way (see the
|
|
2413
|
+
* auth-dependency note below). Testing it through a whole turn would need a live provider
|
|
2414
|
+
* failure, which is exactly the shape that goes untested and then ships.
|
|
2415
|
+
*/
|
|
2416
|
+
export function isCloudApiTransientErrorMessage(message) {
|
|
2357
2417
|
const status = extractCloudApiStatus(message);
|
|
2418
|
+
/**
|
|
2419
|
+
* 🔴 An authentication-dependency failure arrives as 503 and is NOT transient.
|
|
2420
|
+
*
|
|
2421
|
+
* This predicate drives retries and the text-only fallback, not just wording. When the gateway
|
|
2422
|
+
* could not reach its auth dependency (measured 2026-09-14: a missing GRANT on
|
|
2423
|
+
* `oauth_session_state`), every turn burned its retries and a fallback against a fault that
|
|
2424
|
+
* could never clear — and then reported upstream capacity. Retrying a permanent authorization
|
|
2425
|
+
* fault is load against our own gateway with no possible success.
|
|
2426
|
+
*/
|
|
2427
|
+
if (/auth[_-]dependency[_-]unavailable/i.test(message))
|
|
2428
|
+
return false;
|
|
2358
2429
|
return status === 408
|
|
2359
2430
|
|| status === 429
|
|
2360
2431
|
|| status === 500
|
|
@@ -2384,7 +2455,8 @@ function stripHtmlForErrorPreview(message) {
|
|
|
2384
2455
|
.replace(/\s+/g, ' ')
|
|
2385
2456
|
.trim();
|
|
2386
2457
|
}
|
|
2387
|
-
|
|
2458
|
+
/** Exported for tests ONLY — see {@link isCloudApiTransientErrorMessage}. Not a public API. */
|
|
2459
|
+
export function sanitizeAgentRunErrorMessage(error) {
|
|
2388
2460
|
const rawMessage = typeof error === 'string' ? error : (error.message || String(error));
|
|
2389
2461
|
const status = extractCloudApiStatus(rawMessage);
|
|
2390
2462
|
const retryAfterMs = extractRetryAfterMs(rawMessage);
|
|
@@ -2424,6 +2496,27 @@ function sanitizeAgentRunErrorMessage(error) {
|
|
|
2424
2496
|
cfRay ? `Cloudflare Ray: ${cfRay}.` : null,
|
|
2425
2497
|
].filter(Boolean).join(' ');
|
|
2426
2498
|
}
|
|
2499
|
+
/**
|
|
2500
|
+
* 🔴 An AUTHENTICATION fault is not a transient one, even when it arrives as 503.
|
|
2501
|
+
*
|
|
2502
|
+
* The gateway answers `503 auth_dependency_unavailable` when its own auth dependency fails —
|
|
2503
|
+
* measured 2026-09-14, that was a missing database GRANT on `oauth_session_state`, which no
|
|
2504
|
+
* amount of retrying could ever clear. Reported as "temporarily unavailable, try again in a
|
|
2505
|
+
* moment" it read as upstream capacity for hours, and the gateway log was simultaneously full
|
|
2506
|
+
* of a DIFFERENT caller's genuine `gpt-*` capacity events, which made the wrong answer look
|
|
2507
|
+
* confirmed. Advice that cannot work is worse than no advice: it sends the reader away from
|
|
2508
|
+
* the cause.
|
|
2509
|
+
*
|
|
2510
|
+
* Checked BEFORE the transient branch because the status alone cannot separate them.
|
|
2511
|
+
*/
|
|
2512
|
+
if (/auth[_-]dependency[_-]unavailable/i.test(rawMessage)) {
|
|
2513
|
+
return [
|
|
2514
|
+
`Cloud API could not authenticate this request (HTTP ${status || 503}).`,
|
|
2515
|
+
'The XENO gateway reached its authentication dependency and it failed, so retrying will not help.',
|
|
2516
|
+
'Report this with the time of the request.',
|
|
2517
|
+
cfRay ? `Cloudflare Ray: ${cfRay}.` : null,
|
|
2518
|
+
].filter(Boolean).join(' ');
|
|
2519
|
+
}
|
|
2427
2520
|
if (status && isCloudApiTransientErrorMessage(rawMessage)) {
|
|
2428
2521
|
return [
|
|
2429
2522
|
`Cloud API is temporarily unavailable (HTTP ${status}).`,
|
|
@@ -3215,7 +3308,7 @@ export async function runSdkAgent(options) {
|
|
|
3215
3308
|
}
|
|
3216
3309
|
}
|
|
3217
3310
|
async function runSdkAgentOwned(options, ownerId) {
|
|
3218
|
-
const { requestId, conversationId, hostBinding, sdkSessionId, subagentRunId, workspaceId, teamId, agentId, model, messages, systemPrompt, maxIterations = 10, enableThinking = false, reasoningEffort, getAuthToken, getPlatformAuthToken, mainWindow, signal, capabilities, permissionProfile, allowedDirectories, approvalRules: rawApprovalRules, allowTextOnlyFallback = false, toolExecution, onPersistedRuntimeEvent, prepareRuntimeEventForPersistence, runtimeEventStore: injectedRuntimeEventStore, coordinationTools, isProduction, executionEnvironment, workspaceEnvironment, } = options;
|
|
3311
|
+
const { requestId, conversationId, hostBinding, sdkSessionId, subagentRunId, workspaceId, teamId, agentId, model, messages, systemPrompt, maxIterations = 10, enableThinking = false, reasoningEffort, getAuthToken, authorizeRequest, getPlatformAuthToken, mainWindow, signal, capabilities, permissionProfile, allowedDirectories, approvalRules: rawApprovalRules, allowTextOnlyFallback = false, toolExecution, onPersistedRuntimeEvent, prepareRuntimeEventForPersistence, runtimeEventStore: injectedRuntimeEventStore, coordinationTools, isProduction, executionEnvironment, workspaceEnvironment, } = options;
|
|
3219
3312
|
const approvalRules = normalizeApprovalRules(rawApprovalRules);
|
|
3220
3313
|
const resolvedPermissionProfile = resolveAgentPermissionProfile({
|
|
3221
3314
|
...(permissionProfile ? { requestedProfile: permissionProfile } : {}),
|
|
@@ -3586,6 +3679,11 @@ async function runSdkAgentOwned(options, ownerId) {
|
|
|
3586
3679
|
// selected XENO_BROWSER_DRIVER resolves either XENO Browser or the XENO
|
|
3587
3680
|
// Extension native bridge; configured XENO Use device automation joins the
|
|
3588
3681
|
// same lease, execution-contract, policy, and evidence runtime.
|
|
3682
|
+
//
|
|
3683
|
+
// The XENO Use half of that sentence was ASPIRATIONAL until the endpoint below was passed: the
|
|
3684
|
+
// environment reader fills `computer` only from ambient XENO_USE_* variables, which nothing in
|
|
3685
|
+
// this repo set. Resolving it here is what makes the claim true.
|
|
3686
|
+
const machineEndpointStatus = await resolveMachineTarget();
|
|
3589
3687
|
const governedAutomationToolCount = registerSdkNativeGovernedAutomationTools({
|
|
3590
3688
|
sdk,
|
|
3591
3689
|
toolRegistry,
|
|
@@ -3596,6 +3694,7 @@ async function runSdkAgentOwned(options, ownerId) {
|
|
|
3596
3694
|
agentId: agentId || '__main_assistant__',
|
|
3597
3695
|
...(sdkSessionId || conversationId ? { sessionId: sdkSessionId || conversationId } : {}),
|
|
3598
3696
|
...(workspaceId ? { workspaceId } : {}),
|
|
3697
|
+
...(machineEndpointStatus.endpoint ? { machineEndpoint: machineEndpointStatus.endpoint } : {}),
|
|
3599
3698
|
});
|
|
3600
3699
|
if (governedAutomationToolCount > 0) {
|
|
3601
3700
|
logAgentDebug('registered SDK-governed XENO automation tools', {
|
|
@@ -4279,6 +4378,31 @@ async function runSdkAgentOwned(options, ownerId) {
|
|
|
4279
4378
|
if (isLocalModel) {
|
|
4280
4379
|
baseURL = 'http://localhost:3338';
|
|
4281
4380
|
}
|
|
4381
|
+
else if (!process.env.XENO_AGENT_API_BASE && !process.env.XENO_DIRECT_API_BASE) {
|
|
4382
|
+
/**
|
|
4383
|
+
* 🔴 The DIRECT origin, not the Cloudflare-fronted host — which is what `DIRECT_API_BASE` has
|
|
4384
|
+
* existed for all along, reachable only if somebody set an environment variable by hand.
|
|
4385
|
+
*
|
|
4386
|
+
* Measured 2026-09-14, and it is why an agent turn kept failing: a turn selecting
|
|
4387
|
+
* `claude-sonnet-5` reported `HTTP 503` with a Cloudflare Ray id, while the gateway's own log
|
|
4388
|
+
* recorded **zero** `claude-sonnet-5` requests in the entire hour. The request never reached
|
|
4389
|
+
* the origin. Every 503 the gateway did log belonged to another caller's `gpt-*` traffic
|
|
4390
|
+
* running 40–110 requests a minute — which is exactly how this failure kept being
|
|
4391
|
+
* misdiagnosed as upstream capacity.
|
|
4392
|
+
*
|
|
4393
|
+
* The two hosts are distinguishable in one probe:
|
|
4394
|
+
* https://api.xenostudio.ai/v1/models -> Server: cloudflare, CF-RAY present
|
|
4395
|
+
* https://direct-api.xenostudio.ai:8443/v1/models -> Server: nginx, no CF-RAY, HTTP 401
|
|
4396
|
+
*
|
|
4397
|
+
* An agent turn is long, streaming and tool-driven — the shape a CDN is least suited to, and
|
|
4398
|
+
* Cloudflare's 100s ceiling cuts exactly that. `xeno-agent-cli` already defaults to this
|
|
4399
|
+
* origin for the same reason.
|
|
4400
|
+
*
|
|
4401
|
+
* ⚠️ Both environment variables still win when set, so an operator can pin either host, and
|
|
4402
|
+
* the local-model branch above is untouched.
|
|
4403
|
+
*/
|
|
4404
|
+
baseURL = DIRECT_API_BASE;
|
|
4405
|
+
}
|
|
4282
4406
|
// Build the system prompt
|
|
4283
4407
|
const workspaceToolInstructions = [
|
|
4284
4408
|
'Workspace tool order:',
|
|
@@ -4335,7 +4459,11 @@ async function runSdkAgentOwned(options, ownerId) {
|
|
|
4335
4459
|
});
|
|
4336
4460
|
const finalSystemPrompt = `${systemPrompt || 'You are a helpful AI assistant in the XENO Hub desktop application.'}\n\n${runtimeAuthorityInstructions}\n\n${toolHonestyInstructions}\n\n${workspaceToolInstructions}\n\n${taskTrackingInstructions}\n\n${liveSurfaceInstructions}`.trim();
|
|
4337
4461
|
const runtimeSystemPrompt = isLocalModel ? normalizeLocalRuntimeText(finalSystemPrompt) : finalSystemPrompt;
|
|
4338
|
-
|
|
4462
|
+
// An account authorizer is a direct credential exactly as an API key is: the gateway accepts a
|
|
4463
|
+
// DPoP-bound OIDC token, so a signed-in person needs no key. Passing only `!!apiKey` here is what
|
|
4464
|
+
// routed every keyless account into the relay and then refused the turn.
|
|
4465
|
+
const hasDirectCredential = Boolean(apiKey) || Boolean(authorizeRequest);
|
|
4466
|
+
if (!isLocalModel && await shouldUsePlatformChatFallback(hasDirectCredential)) {
|
|
4339
4467
|
if (!allowTextOnlyFallback) {
|
|
4340
4468
|
emitPlatformChatFallbackFailure(new Error('The tool-capable SDK runtime is unavailable. XENO Agent will not downgrade this engineering turn to a text-only relay.'));
|
|
4341
4469
|
clearVisibleProgressWatchdog();
|
|
@@ -4548,6 +4676,9 @@ async function runSdkAgentOwned(options, ownerId) {
|
|
|
4548
4676
|
const agent = new sdk.AgentLoop({
|
|
4549
4677
|
ownerSessionId: ownerId,
|
|
4550
4678
|
apiKey,
|
|
4679
|
+
// the account first; `apiKey` stays as the BYO override the SDK falls back to when absent.
|
|
4680
|
+
// A local model needs no XENO credential at all, so it is deliberately not authorized here.
|
|
4681
|
+
...(authorizeRequest && !isLocalModel ? { authorizeRequest } : {}),
|
|
4551
4682
|
baseURL,
|
|
4552
4683
|
model: isLocalModel ? model : modelId,
|
|
4553
4684
|
...(reasoningEffort ? { effort: requireSdkReasoningEffort(reasoningEffort, sdk.AGENT_EFFORT_LEVELS) } : {}),
|
|
@@ -4965,11 +5096,51 @@ async function runSdkAgentOwned(options, ownerId) {
|
|
|
4965
5096
|
message: 'Agent model run failed.',
|
|
4966
5097
|
error: sanitizeAgentRunErrorMessage(error),
|
|
4967
5098
|
});
|
|
5099
|
+
/**
|
|
5100
|
+
* 🔴 The RAW provider message, next to the sanitized one — and the distinction is the whole
|
|
5101
|
+
* reason this exists. `sanitizeAgentRunErrorMessage` PARSES the status, the retry hint and
|
|
5102
|
+
* the Cloudflare ray out of the provider's message and then returns a formatted sentence,
|
|
5103
|
+
* discarding everything it did not recognise. So the fact that would identify the failure is
|
|
5104
|
+
* present, read once, and thrown away.
|
|
5105
|
+
*
|
|
5106
|
+
* Measured 2026-09-14: a turn reported `Cloud API is temporarily unavailable (HTTP 503)`
|
|
5107
|
+
* while the gateway's own log showed `200 | 955ms` for the same model on the same path, and
|
|
5108
|
+
* no error entry existed on the origin for our request at all. Those cannot all describe the
|
|
5109
|
+
* same request — and the transcript could not settle it, because the only surviving evidence
|
|
5110
|
+
* was the sentence the sanitizer produced.
|
|
5111
|
+
*
|
|
5112
|
+
* ⚠️ Debug log only, never the runtime event: a provider body can carry request ids, header
|
|
5113
|
+
* echoes and account identifiers, and the runtime event is persisted and surfaced. The
|
|
5114
|
+
* sanitized message stays the thing a person is shown.
|
|
5115
|
+
*/
|
|
4968
5116
|
logAgentDebug('Agent run errored', {
|
|
4969
5117
|
requestId,
|
|
4970
5118
|
model,
|
|
4971
|
-
error: sanitizeAgentRunErrorMessage(error)
|
|
5119
|
+
error: sanitizeAgentRunErrorMessage(error),
|
|
5120
|
+
rawProviderMessage: (error?.message || String(error)).slice(0, 2000),
|
|
5121
|
+
rawProviderName: error?.name,
|
|
4972
5122
|
});
|
|
5123
|
+
/**
|
|
5124
|
+
* Opt-in raw capture, because a packaged app's main-process console reaches nobody.
|
|
5125
|
+
*
|
|
5126
|
+
* 🔴 `sanitizeAgentRunErrorMessage` REWRITES the provider's message into a sentence — it
|
|
5127
|
+
* matched a status and produced "Cloud API is temporarily unavailable (HTTP 503)" while
|
|
5128
|
+
* `waitMs: 5` showed no request had left the machine and the gateway logged zero requests
|
|
5129
|
+
* for that model. The rendered sentence is therefore not evidence of where a failure came
|
|
5130
|
+
* from, and for a day it was the only surviving trace.
|
|
5131
|
+
*
|
|
5132
|
+
* ⚠️ OFF by default and never a runtime event: a provider message can carry request ids and
|
|
5133
|
+
* header echoes, and runtime events are persisted and rendered. This writes to a file only
|
|
5134
|
+
* when an operator sets `XENO_AGENT_DEBUG_RAW_ERRORS=1`, for exactly this kind of session.
|
|
5135
|
+
*/
|
|
5136
|
+
if (process.env.XENO_AGENT_DEBUG_RAW_ERRORS === '1') {
|
|
5137
|
+
try {
|
|
5138
|
+
const target = join(homedir(), '.xeno', 'raw-provider-errors.log');
|
|
5139
|
+
const line = `${new Date().toISOString()} ${model} ${error?.name ?? 'Error'}: ${(error?.message || String(error)).slice(0, 4000)}\n`;
|
|
5140
|
+
writeFileSync(target, line, { encoding: 'utf-8', flag: 'a' });
|
|
5141
|
+
}
|
|
5142
|
+
catch { /* diagnostics must never break a turn */ }
|
|
5143
|
+
}
|
|
4973
5144
|
if (allowTextOnlyFallback && !isLocalModel && isCloudApiTransientErrorMessage(error.message || '')) {
|
|
4974
5145
|
try {
|
|
4975
5146
|
const fallback = await emitPlatformChatFallback({
|