@runuai/host 0.9.171 → 0.9.172
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/lib/agents/claude.ts +13 -0
- package/lib/agents/codex.ts +11 -5
- package/lib/agents/session-state.ts +77 -0
- package/lib/agents/transport.ts +2 -0
- package/lib/agents/types.ts +3 -0
- package/lib/agents/uai.ts +3 -25
- package/lib/assignment-evidence.ts +2 -1
- package/lib/capture-flow.ts +14 -1
- package/lib/cloud-credential-leases.ts +9 -3
- package/lib/cloud-credential-runtime.ts +8 -0
- package/lib/connection-secret-redaction.ts +25 -0
- package/lib/credential-cleanup-inventory.ts +2 -1
- package/lib/credential-consumers/engines.ts +29 -5
- package/lib/custom-connection-capture.ts +395 -0
- package/lib/custom-connection-launch.ts +299 -0
- package/lib/custom-connection-runtime.ts +70 -0
- package/lib/engine-accounts.ts +1 -1
- package/lib/engine-credential-env.ts +2 -0
- package/lib/internal-connections.ts +5 -0
- package/lib/obs.ts +2 -1
- package/lib/openrouter-budget.ts +247 -0
- package/lib/orchestrator.ts +308 -26
- package/lib/secrets-proxy/address.ts +23 -0
- package/lib/task-credential-cleanup.ts +13 -3
- package/package.json +1 -1
- package/runner/runner.mjs +231 -3
- package/src/capture-wire.ts +102 -0
- package/src/cloud-credentials.ts +36 -372
- package/src/credential-location.ts +248 -0
- package/src/credential-wire-validation.ts +25 -0
- package/src/custom-connections.ts +207 -0
- package/src/main.ts +104 -3
- package/src/protocol.ts +18 -0
package/src/main.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
+
import "./load-env";
|
|
3
|
+
import { discoverCustomConnection, saveCustomConnection, saveCustomConnectionManual } from "../lib/custom-connection-capture";
|
|
4
|
+
import { OpenRouterBudgetPoller } from "../lib/openrouter-budget";
|
|
5
|
+
import { onLeasedEnginesChanged, leasedEnginesFor, isLeasedEngineAccount } from "../lib/credential-consumers/engines";
|
|
6
|
+
import { isOwnedInternalConnectionRuntime } from "../lib/internal-connections";
|
|
7
|
+
import { CUSTOM_CONNECTIONS_FEATURE, ENGINE_CONNECT_CUSTOM_FEATURE, ENGINE_CONNECT_CUSTOM_MANUAL_FEATURE, INTERNAL_CONNECTIONS_FEATURE, connectionOpId, parseCustomConnectionMaterial, parseCustomConnectionEnabled, parseEngineConnectCustomDiscoverFrame, parseEngineConnectCustomSaveFrame, parseEngineConnectCustomManualSaveFrame } from "./custom-connections";
|
|
2
8
|
import type { AssignmentDelivery, DeliveryOrigin } from "./protocol";
|
|
9
|
+
import { parseCaptureFlowWire } from "./cloud-credentials";
|
|
3
10
|
|
|
4
|
-
import "./load-env";
|
|
5
11
|
import { sampleDiskPressure } from "../lib/disk-pressure";
|
|
6
12
|
import { TASK_SECRETS_FEATURE, isTaskSecretStagingPut } from "./task-secrets";
|
|
7
13
|
import { writeTaskSecretStaging } from "../lib/task-secret-staging";
|
|
@@ -181,7 +187,7 @@ import {
|
|
|
181
187
|
rejectContainerRuntimeSelection,
|
|
182
188
|
reprobeContainerRuntimeMachineIdentity,
|
|
183
189
|
} from "../lib/container-runtime";
|
|
184
|
-
import { persistedTaskEnvironmentsMatchMachine, reconstructPersistedTaskEnvironment } from "../lib/task-environment";
|
|
190
|
+
import { machineTasksEnabled, persistedTaskEnvironmentsMatchMachine, reconstructPersistedTaskEnvironment } from "../lib/task-environment";
|
|
185
191
|
import { reconcileRunningTaskPersonCredentials } from "../lib/task-person-credentials";
|
|
186
192
|
import { logVnodePressure } from "../lib/vnode-pressure";
|
|
187
193
|
import { resolveAppleTunnelRoute } from "./apple-tunnel-route";
|
|
@@ -509,6 +515,15 @@ const bridgeUrl =
|
|
|
509
515
|
|
|
510
516
|
let ws: WebSocket | null = null;
|
|
511
517
|
let stopping = false;
|
|
518
|
+
const openRouterBudgets = new OpenRouterBudgetPoller({ emit: frame => {
|
|
519
|
+
if (!stopping && credentialFramesReady && ws?.readyState === WebSocket.OPEN) send(ws, frame);
|
|
520
|
+
} });
|
|
521
|
+
onLeasedEnginesChanged(taskId => {
|
|
522
|
+
if (stopping) { openRouterBudgets.stop(taskId); return; }
|
|
523
|
+
const lease = leasedEnginesFor(taskId);
|
|
524
|
+
openRouterBudgets.sync(taskId, lease?.open ? lease.accounts.flatMap(account => isLeasedEngineAccount(account) && account.authKind === "custom-connection" && account.connectionMaterial?.providerType === "openrouter" ? [{ credentialId: account.credentialId, revision: account.revision, apiKey: account.connectionMaterial.apiKey }] : []) : []);
|
|
525
|
+
});
|
|
526
|
+
|
|
512
527
|
let fatal = false;
|
|
513
528
|
/** Auth-rejected (4001) retry cadence. A genuinely revoked credential costs
|
|
514
529
|
* one connection attempt per interval; a transient rejection (the bridge's
|
|
@@ -523,6 +538,17 @@ let shutdownRequested = false;
|
|
|
523
538
|
let shutdownExitCode = 0;
|
|
524
539
|
const managedMutationDrain = new ManagedOperationDrain(maybeExit);
|
|
525
540
|
const hostLogManager = createHostLogManager();
|
|
541
|
+
const customConnectionOperations = new Map<AbortController, Promise<void>>();
|
|
542
|
+
|
|
543
|
+
function runCustomConnectionOperation(operation: (signal: AbortSignal) => Promise<void>): void {
|
|
544
|
+
void managedMutationDrain.track(async () => {
|
|
545
|
+
const controller = new AbortController();
|
|
546
|
+
const work = Promise.resolve().then(() => operation(controller.signal));
|
|
547
|
+
customConnectionOperations.set(controller, work);
|
|
548
|
+
try { await work; } finally { customConnectionOperations.delete(controller); }
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
526
552
|
const pendingRemoteOperationCleanups = new Set<Promise<void>>();
|
|
527
553
|
let stopActiveRemoteOperations = (): Promise<void> => Promise.resolve();
|
|
528
554
|
|
|
@@ -545,8 +571,10 @@ function trackRemoteOperationCleanup(cleanup: Promise<void>): Promise<void> {
|
|
|
545
571
|
function stopRemoteOperationManagers(): Promise<void> {
|
|
546
572
|
hostLogManager.stopAll();
|
|
547
573
|
engineConnectManager.stopAll();
|
|
574
|
+
for (const controller of customConnectionOperations.keys()) controller.abort();
|
|
548
575
|
return trackRemoteOperationCleanup(
|
|
549
576
|
Promise.all([
|
|
577
|
+
...customConnectionOperations.values(),
|
|
550
578
|
engineLoginManager.stopAll(),
|
|
551
579
|
// Tunnel upstreams are generation-scoped resources just like login
|
|
552
580
|
// containers; a bridge replacement or shutdown must join their
|
|
@@ -1033,6 +1061,7 @@ const taskFiles = sidecarMode()
|
|
|
1033
1061
|
: null;
|
|
1034
1062
|
const cloudCredentials = new CloudCredentialRuntime({
|
|
1035
1063
|
runnerKind: sidecarMode() ? "task-machine" : "owned",
|
|
1064
|
+
internalRuntimeProvider: (assignment) => internalRuntimeProvider(assignment.taskId),
|
|
1036
1065
|
send: sendCredentialFrame,
|
|
1037
1066
|
quiesceProcesses: (request) => getOrchestrator().quiesceLeasedEngineAgents(request),
|
|
1038
1067
|
mcpServedChanged: (taskId) => getOrchestrator().mcpServedChanged(taskId),
|
|
@@ -1492,12 +1521,30 @@ void refreshDiskSnapshot();
|
|
|
1492
1521
|
const diskTimer = setInterval(() => void refreshDiskSnapshot(), 60_000);
|
|
1493
1522
|
diskTimer.unref?.();
|
|
1494
1523
|
|
|
1524
|
+
/** A persisted provider wins over this runner's default selection. Legacy
|
|
1525
|
+
* resources without a proven provider are unknown; only a new/empty task
|
|
1526
|
+
* may use the selected provisioning backend as its authoritative plan. */
|
|
1527
|
+
function internalRuntimeProvider(taskId?: string): string | null {
|
|
1528
|
+
if (sidecarMode() || signInBoxMode()) return null;
|
|
1529
|
+
const task = taskId ? getHostTask(taskId) : undefined;
|
|
1530
|
+
if (task?.environmentProvider !== null && task?.environmentProvider !== undefined) return task.environmentProvider;
|
|
1531
|
+
if (task && (task.composeProject !== null || task.worktreePath !== null)) return null;
|
|
1532
|
+
if (machineTasksEnabled()) return null;
|
|
1533
|
+
const runtime = containerRuntimeCapabilityState();
|
|
1534
|
+
if (runtime.status !== "ready") return null;
|
|
1535
|
+
return runtime.provider === "docker" ? "docker-compose" : runtime.provider === "apple-container" ? "apple-container" : null;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1495
1538
|
/** Build the current host capability advertisement (ADR-021). */
|
|
1496
1539
|
function buildCapabilities(): HostCapabilities {
|
|
1497
1540
|
const runtime = containerRuntimeCapabilityState();
|
|
1498
1541
|
const projectEnvBindings = projectEnvBindingCapability();
|
|
1499
1542
|
return {
|
|
1500
1543
|
version: packageVersion(),
|
|
1544
|
+
customConnections: credentialsMode() === "active",
|
|
1545
|
+
engineConnectCustom: signInBoxMode(),
|
|
1546
|
+
engineConnectCustomManual: signInBoxMode(),
|
|
1547
|
+
internalConnections: isOwnedInternalConnectionRuntime(internalRuntimeProvider()),
|
|
1501
1548
|
...(diskSnapshot ? { disk: diskSnapshot } : {}),
|
|
1502
1549
|
protocolFeatures: [
|
|
1503
1550
|
"host-workspace-file-read-v1",
|
|
@@ -1543,6 +1590,9 @@ function buildCapabilities(): HostCapabilities {
|
|
|
1543
1590
|
// ADR-161 §1.11: this image's `uai files` reads cloud links. The cloud
|
|
1544
1591
|
// captures the advertisement at container creation.
|
|
1545
1592
|
HOST_AGENT_FILES_FEATURE,
|
|
1593
|
+
...(credentialsMode() === "active" ? [CUSTOM_CONNECTIONS_FEATURE] : []),
|
|
1594
|
+
...(signInBoxMode() ? [ENGINE_CONNECT_CUSTOM_FEATURE, ENGINE_CONNECT_CUSTOM_MANUAL_FEATURE] : []),
|
|
1595
|
+
...(isOwnedInternalConnectionRuntime(internalRuntimeProvider()) ? [INTERNAL_CONNECTIONS_FEATURE] : []),
|
|
1546
1596
|
// ADR-154: only the sign-in box writes cloud credentials.
|
|
1547
1597
|
...(signInBoxMode()
|
|
1548
1598
|
? [
|
|
@@ -3058,7 +3108,7 @@ async function connect(): Promise<void> {
|
|
|
3058
3108
|
}
|
|
3059
3109
|
|
|
3060
3110
|
const frame = parseCloudFrame(data);
|
|
3061
|
-
if (!frame) return;
|
|
3111
|
+
if (!frame) { replyToInvalidCustomConnectionFrame(socket, data); return; }
|
|
3062
3112
|
if (stopping && rejectFrameDuringShutdown(socket, frame)) return;
|
|
3063
3113
|
if (signInBoxMode() && rejectFrameOnSignInBox(socket, frame)) return;
|
|
3064
3114
|
if (!onOwnCredentials() && rejectCredentialFrameOffOwnCredentials(socket, frame)) return;
|
|
@@ -3609,6 +3659,21 @@ async function connect(): Promise<void> {
|
|
|
3609
3659
|
);
|
|
3610
3660
|
break;
|
|
3611
3661
|
}
|
|
3662
|
+
case "engine.connect.custom.discover": {
|
|
3663
|
+
if (!signInBoxMode()) { send(socket, { kind: "engine.connect.custom.discovered", opId: frame.opId, result: { ok: false, reason: "unsupported" } }); break; }
|
|
3664
|
+
runCustomConnectionOperation(signal => discoverCustomConnection(frame, { signal }).catch(() => ({ ok: false as const, reason: "upstream-error" as const })).then(result => send(socket, { kind: "engine.connect.custom.discovered", opId: frame.opId, result })));
|
|
3665
|
+
break;
|
|
3666
|
+
}
|
|
3667
|
+
case "engine.connect.custom.manual-save": {
|
|
3668
|
+
if (!signInBoxMode()) { send(socket, { kind: "engine.connect.custom.saved", opId: frame.opId, result: { ok: false, reason: "unsupported" } }); break; }
|
|
3669
|
+
runCustomConnectionOperation(signal => saveCustomConnectionManual(frame, configuredCredentialStore(), { signal }).catch(() => ({ ok: false as const, reason: "upstream-error" as const })).then(result => send(socket, { kind: "engine.connect.custom.saved", opId: frame.opId, result })));
|
|
3670
|
+
break;
|
|
3671
|
+
}
|
|
3672
|
+
case "engine.connect.custom.save": {
|
|
3673
|
+
if (!signInBoxMode()) { send(socket, { kind: "engine.connect.custom.saved", opId: frame.opId, result: { ok: false, reason: "unsupported" } }); break; }
|
|
3674
|
+
runCustomConnectionOperation(signal => saveCustomConnection(frame, configuredCredentialStore(), { signal }).catch(() => ({ ok: false as const, reason: "upstream-error" as const })).then(result => send(socket, { kind: "engine.connect.custom.saved", opId: frame.opId, result })));
|
|
3675
|
+
break;
|
|
3676
|
+
}
|
|
3612
3677
|
case "mcp.capture.probe":
|
|
3613
3678
|
case "mcp.capture.complete": {
|
|
3614
3679
|
// ADR-154 §11: only the sign-in box runs an MCP handshake as a
|
|
@@ -4831,6 +4896,24 @@ const PICKER_FAILURE_TEXT: Record<GitHubRepositoryAccessErrorCode, string> = {
|
|
|
4831
4896
|
invalid_response: "GitHub answered with something unexpected",
|
|
4832
4897
|
};
|
|
4833
4898
|
|
|
4899
|
+
function replyToInvalidCustomConnectionFrame(socket: WebSocket, data: RawData): void {
|
|
4900
|
+
let value: unknown;
|
|
4901
|
+
try { value = JSON.parse(rawDataToBuffer(data).toString("utf8")); } catch { return; }
|
|
4902
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
4903
|
+
const frame = value as Record<string, unknown>;
|
|
4904
|
+
if (!connectionOpId(frame.opId)) return;
|
|
4905
|
+
if (frame.kind === "engine.connect.custom.discover") {
|
|
4906
|
+
send(socket, { kind: "engine.connect.custom.discovered", opId: frame.opId, result: { ok: false, reason: "unsupported" } });
|
|
4907
|
+
} else if (frame.kind === "engine.connect.custom.save" || frame.kind === "engine.connect.custom.manual-save") {
|
|
4908
|
+
const settings = parseCustomConnectionMaterial(frame.settings);
|
|
4909
|
+
const flow = parseCaptureFlowWire(frame.flow);
|
|
4910
|
+
const supported = settings && (frame.kind !== "engine.connect.custom.manual-save" || (settings.providerType === "custom" && settings.internal === true)) && parseCustomConnectionEnabled(frame.enabled) && flow &&
|
|
4911
|
+
flow.location.class === "engine" && flow.location.engineKind === settings.engine && flow.brokerParameter === null;
|
|
4912
|
+
send(socket, { kind: "engine.connect.custom.saved", opId: frame.opId,
|
|
4913
|
+
result: { ok: false, reason: supported ? "invalid-models" : "unsupported" } });
|
|
4914
|
+
}
|
|
4915
|
+
}
|
|
4916
|
+
|
|
4834
4917
|
function parseCloudFrame(data: RawData): CloudToHost | null {
|
|
4835
4918
|
let parsed: unknown;
|
|
4836
4919
|
try {
|
|
@@ -5092,6 +5175,9 @@ function parseCloudFrame(data: RawData): CloudToHost | null {
|
|
|
5092
5175
|
// ADR-154: the v1 lease, credential and task env replica frames, parsed
|
|
5093
5176
|
// to their exact shapes here; only a runner on cloud credentials acts on
|
|
5094
5177
|
// them.
|
|
5178
|
+
if (frame.kind === "engine.connect.custom.discover") return parseEngineConnectCustomDiscoverFrame(frame);
|
|
5179
|
+
if (frame.kind === "engine.connect.custom.manual-save") return parseEngineConnectCustomManualSaveFrame(frame);
|
|
5180
|
+
if (frame.kind === "engine.connect.custom.save") return parseEngineConnectCustomSaveFrame(frame);
|
|
5095
5181
|
if (frame.kind === "lease.grant.v1") return parseLeaseGrantV1Frame(frame);
|
|
5096
5182
|
if (frame.kind === "lease.unavailable") return parseLeaseUnavailableFrame(frame);
|
|
5097
5183
|
if (frame.kind === "lease.stale") return parseLeaseStaleFrame(frame);
|
|
@@ -5213,6 +5299,13 @@ function rejectFrameDuringShutdown(
|
|
|
5213
5299
|
): boolean {
|
|
5214
5300
|
const error = "managed host is restarting; retry the operation";
|
|
5215
5301
|
switch (frame.kind) {
|
|
5302
|
+
case "engine.connect.custom.discover":
|
|
5303
|
+
send(socket, { kind: "engine.connect.custom.discovered", opId: frame.opId, result: { ok: false, reason: "unreachable" } });
|
|
5304
|
+
return true;
|
|
5305
|
+
case "engine.connect.custom.manual-save":
|
|
5306
|
+
case "engine.connect.custom.save":
|
|
5307
|
+
send(socket, { kind: "engine.connect.custom.saved", opId: frame.opId, result: { ok: false, reason: "unreachable" } });
|
|
5308
|
+
return true;
|
|
5216
5309
|
case "command":
|
|
5217
5310
|
send(socket, {
|
|
5218
5311
|
kind: "result",
|
|
@@ -5626,6 +5719,12 @@ function expectTaskAgents(value: unknown): TaskAgent[] {
|
|
|
5626
5719
|
) {
|
|
5627
5720
|
out.accountId = row.accountId;
|
|
5628
5721
|
}
|
|
5722
|
+
if (row.accountBinding !== undefined) {
|
|
5723
|
+
if (row.accountBinding !== "required" && row.accountBinding !== "preferred") throw new Error("invalid command args: account binding");
|
|
5724
|
+
if (row.accountBinding === "required" && row.kind !== "claude" && row.kind !== "codex") throw new Error("invalid command args: unsupported required account engine");
|
|
5725
|
+
if (row.accountBinding === "required" && !out.accountId) throw new Error("invalid command args: required account missing");
|
|
5726
|
+
out.accountBinding = row.accountBinding;
|
|
5727
|
+
}
|
|
5629
5728
|
if (row.uaiProvider === "anthropic" || row.uaiProvider === "openai") {
|
|
5630
5729
|
out.uaiProvider = row.uaiProvider;
|
|
5631
5730
|
}
|
|
@@ -6107,6 +6206,7 @@ function reconnectDelay(): number {
|
|
|
6107
6206
|
function requestShutdown(signal: NodeJS.Signals): void {
|
|
6108
6207
|
console.log(`[host-agent] ${signal} received; shutting down`);
|
|
6109
6208
|
stopping = true;
|
|
6209
|
+
openRouterBudgets.stop();
|
|
6110
6210
|
// Cancel human-paced operations without invalidating this socket's exact
|
|
6111
6211
|
// generation: already-admitted one-shot config writes may still ack while
|
|
6112
6212
|
// the ordinary in-flight drain completes.
|
|
@@ -6119,6 +6219,7 @@ function requestShutdown(signal: NodeJS.Signals): void {
|
|
|
6119
6219
|
// it). Exit waits for it.
|
|
6120
6220
|
void cloudCredentials
|
|
6121
6221
|
.shutdown()
|
|
6222
|
+
.then(() => openRouterBudgets.drain())
|
|
6122
6223
|
.catch((error: unknown) =>
|
|
6123
6224
|
console.warn(`[credentials] shutdown failed: ${error instanceof Error ? error.message : String(error)}`),
|
|
6124
6225
|
)
|
package/src/protocol.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export * from "./custom-connections";
|
|
2
|
+
import type { AccountBinding, EngineConnectCustomDiscoverFrame, EngineConnectCustomDiscoveredFrame, EngineConnectCustomSaveFrame, EngineConnectCustomManualSaveFrame, EngineConnectCustomSavedFrame, OpenRouterBudgetFrame } from "./custom-connections";
|
|
1
3
|
import type { TaskSecretApplied, TaskSecretStagingPut, TaskSecretStagingAck } from "./task-secrets";
|
|
2
4
|
import {
|
|
3
5
|
parseCaptureFlowWire,
|
|
@@ -3154,6 +3156,7 @@ export interface TaskAgent {
|
|
|
3154
3156
|
effort?: string;
|
|
3155
3157
|
/** ADR-157 addendum §7: preferred cloud-leased AI account. */
|
|
3156
3158
|
accountId?: string;
|
|
3159
|
+
accountBinding?: AccountBinding;
|
|
3157
3160
|
defaultPrompt?: string;
|
|
3158
3161
|
initialPrompt?: string;
|
|
3159
3162
|
/** ADR-046 reference material resolved from the agent's persona + team.
|
|
@@ -4068,6 +4071,10 @@ export function isHostConfigAckFrame(
|
|
|
4068
4071
|
* changes. The cloud caches it per hostId to drive the task-creation pickers.
|
|
4069
4072
|
*/
|
|
4070
4073
|
export interface HostCapabilities {
|
|
4074
|
+
customConnections?: boolean;
|
|
4075
|
+
engineConnectCustom?: boolean;
|
|
4076
|
+
engineConnectCustomManual?: boolean;
|
|
4077
|
+
internalConnections?: boolean;
|
|
4071
4078
|
/** Filesystem capacity, refreshed each minute. Null means unmeasurable
|
|
4072
4079
|
* (for example Docker in a VM); available excludes root-reserved blocks. */
|
|
4073
4080
|
disk?: {
|
|
@@ -4904,6 +4911,9 @@ export interface TaskMachineRetireAckFrame {
|
|
|
4904
4911
|
}
|
|
4905
4912
|
|
|
4906
4913
|
export type CloudToHost =
|
|
4914
|
+
| EngineConnectCustomDiscoverFrame
|
|
4915
|
+
| EngineConnectCustomSaveFrame
|
|
4916
|
+
| EngineConnectCustomManualSaveFrame
|
|
4907
4917
|
| {
|
|
4908
4918
|
kind: "command";
|
|
4909
4919
|
commandId: string;
|
|
@@ -5083,6 +5093,9 @@ export interface AssignmentDelivery {
|
|
|
5083
5093
|
recipientGeneration: string | null;
|
|
5084
5094
|
}
|
|
5085
5095
|
export interface AssignmentTurnEvidence {
|
|
5096
|
+
credentialId?: string | null;
|
|
5097
|
+
credentialRevision?: string | null;
|
|
5098
|
+
connection?: boolean | null;
|
|
5086
5099
|
leadRunId?: string | null;
|
|
5087
5100
|
turnId: string;
|
|
5088
5101
|
assignmentId: string | null;
|
|
@@ -5156,6 +5169,9 @@ export type McpOp =
|
|
|
5156
5169
|
| { kind: "disconnect"; connectionId: string };
|
|
5157
5170
|
|
|
5158
5171
|
export type HostToCloud =
|
|
5172
|
+
| EngineConnectCustomDiscoveredFrame
|
|
5173
|
+
| EngineConnectCustomSavedFrame
|
|
5174
|
+
| OpenRouterBudgetFrame
|
|
5159
5175
|
// ADR-103: `bootId` scopes event seqs to one host process lifetime — the
|
|
5160
5176
|
// cloud's replay watermark only applies within a matching boot. Optional
|
|
5161
5177
|
// for pre-103 hosts (which also never send seq'd events).
|
|
@@ -5358,6 +5374,8 @@ export type HostEvent =
|
|
|
5358
5374
|
* `credentialId` is the leased AI account the turn ran on (host
|
|
5359
5375
|
* 0.9.167+); older runners omit it and the cloud stores null. */
|
|
5360
5376
|
usage?: {
|
|
5377
|
+
connection?: boolean;
|
|
5378
|
+
credentialRevision?: string;
|
|
5361
5379
|
model?: string;
|
|
5362
5380
|
inputTokens?: number;
|
|
5363
5381
|
outputTokens?: number;
|