@runuai/host 0.9.153 → 0.9.155
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/agent-cli.ts +64 -1
- package/lib/agents/claude.ts +19 -2
- package/lib/agents/codex.ts +15 -1
- package/lib/agents/registry.ts +5 -4
- package/lib/agents/types.ts +4 -1
- package/lib/agents/uai.ts +15 -1
- package/lib/cloud-credential-leases.ts +9 -0
- package/lib/cloud-credential-runtime.ts +187 -21
- package/lib/credential-consumers/github.ts +140 -32
- package/lib/orchestrator.ts +90 -25
- package/lib/task-person-credentials.ts +76 -0
- package/lib/task-token.ts +3 -0
- package/package.json +1 -1
- package/src/cloud-credentials.ts +25 -0
- package/src/index.ts +3 -6
- package/src/main.ts +16 -10
- package/src/protocol.ts +42 -0
package/src/main.ts
CHANGED
|
@@ -92,8 +92,7 @@ import { cancelMcpCapture, completeMcpCapture, probeMcpCapture } from "../lib/mc
|
|
|
92
92
|
import { captureGithub, mintSsh, readGithubRevision, revokeGithub } from "../lib/person-capture";
|
|
93
93
|
import { handleMcpOp } from "../lib/mcp-connections";
|
|
94
94
|
import {
|
|
95
|
-
|
|
96
|
-
ENGINE_ENV_CREDENTIAL_KEYS,
|
|
95
|
+
CLOUD_CREDENTIAL_KINDS,
|
|
97
96
|
HOST_CLOUD_CREDENTIALS_FEATURE,
|
|
98
97
|
parseCredentialsActivateResultFrame,
|
|
99
98
|
runEpochFromWire,
|
|
@@ -178,6 +177,7 @@ import {
|
|
|
178
177
|
reprobeContainerRuntimeMachineIdentity,
|
|
179
178
|
} from "../lib/container-runtime";
|
|
180
179
|
import { persistedTaskEnvironmentsMatchMachine, reconstructPersistedTaskEnvironment } from "../lib/task-environment";
|
|
180
|
+
import { reconcileRunningTaskPersonCredentials } from "../lib/task-person-credentials";
|
|
181
181
|
import { logVnodePressure } from "../lib/vnode-pressure";
|
|
182
182
|
import { resolveAppleTunnelRoute } from "./apple-tunnel-route";
|
|
183
183
|
import {
|
|
@@ -300,6 +300,7 @@ import {
|
|
|
300
300
|
HOST_ENGINE_DISCONNECT_PROTOCOL_FEATURE,
|
|
301
301
|
HOST_ENGINE_LOGIN_PROTOCOL_FEATURE,
|
|
302
302
|
LIVE_ROSTER_EDIT_PROTOCOL_FEATURE,
|
|
303
|
+
AGENT_TOKEN_GENERATION_PROTOCOL_FEATURE,
|
|
303
304
|
isEngineAccountScope,
|
|
304
305
|
HOST_LOGS_PROTOCOL_FEATURE,
|
|
305
306
|
HOST_TASK_INVENTORY_PROTOCOL_FEATURE,
|
|
@@ -702,10 +703,6 @@ setCredentialsModeSource(() => credentialsActivation.mode());
|
|
|
702
703
|
* so the operator turning them on reaches it within minutes. */
|
|
703
704
|
const CREDENTIALS_ACTIVATION_RETRY_MS = 5 * 60_000;
|
|
704
705
|
const CREDENTIALS_ACTIVATION_ANSWER_MS = 60_000;
|
|
705
|
-
const LEASED_ENGINE_KINDS: ReadonlySet<string> = new Set([
|
|
706
|
-
...Object.keys(ENGINE_ENV_CREDENTIAL_KEYS),
|
|
707
|
-
...Object.keys(ENGINE_CREDENTIAL_FILES),
|
|
708
|
-
]);
|
|
709
706
|
// Started here, first fired long after the bridge's state exists.
|
|
710
707
|
const credentialsActivationTimer = setInterval(() => {
|
|
711
708
|
if (stopping || !credentialFramesReady) return;
|
|
@@ -939,6 +936,7 @@ const cloudCredentials = new CloudCredentialRuntime({
|
|
|
939
936
|
// delivery look again; /env reads it afresh on every command.
|
|
940
937
|
envReplica: new ProjectEnvTaskReplicaManager({ onChange: () => noteProjectEnvViewChange() }),
|
|
941
938
|
envServedChanged: () => noteProjectEnvViewChange(),
|
|
939
|
+
personCredentialsReady: reconcileRunningTaskPersonCredentials,
|
|
942
940
|
files: taskFiles,
|
|
943
941
|
});
|
|
944
942
|
// Leaving its own credentials ends every task's env from the runner's
|
|
@@ -1396,6 +1394,7 @@ function buildCapabilities(): HostCapabilities {
|
|
|
1396
1394
|
HOST_ENGINE_ACCOUNT_MANAGE_PROTOCOL_FEATURE,
|
|
1397
1395
|
HOST_ENGINE_DISCONNECT_PROTOCOL_FEATURE,
|
|
1398
1396
|
LIVE_ROSTER_EDIT_PROTOCOL_FEATURE,
|
|
1397
|
+
AGENT_TOKEN_GENERATION_PROTOCOL_FEATURE,
|
|
1399
1398
|
// The echo adapter cannot execute the in-task CLI. Advertising typed
|
|
1400
1399
|
// dispatch in mock mode would let the composer create a Secretary that
|
|
1401
1400
|
// has no way to wake crew.
|
|
@@ -1897,10 +1896,11 @@ function flushStoppedTaskStatuses(socket: WebSocket | null = ws): void {
|
|
|
1897
1896
|
// ADR-131 D3: a stored account (any scope) makes a kind advertisable even
|
|
1898
1897
|
// when the host's own credential is absent — see hasStoredEngineAccounts.
|
|
1899
1898
|
setAdvertisementFallback((kind) => hasStoredEngineAccounts(kind));
|
|
1900
|
-
// ADR-154: on cloud credentials the runner holds none of its own, so
|
|
1901
|
-
//
|
|
1902
|
-
//
|
|
1903
|
-
|
|
1899
|
+
// ADR-154 §10: on cloud credentials the runner holds none of its own, so it
|
|
1900
|
+
// advertises the kinds a leased task can run, whatever this process's env
|
|
1901
|
+
// says: the leased lanes and the Managed Engine, which leases nothing (Kimi,
|
|
1902
|
+
// with no lane yet, is left out).
|
|
1903
|
+
setLeasedAdvertisement(() => (credentialsMode() === "active" ? CLOUD_CREDENTIAL_KINDS : null));
|
|
1904
1904
|
onRegistryChange(() => sendCapabilities());
|
|
1905
1905
|
onContainerRuntimeChange((next, previous) => {
|
|
1906
1906
|
if (stopping) return;
|
|
@@ -5416,6 +5416,12 @@ function expectTaskAgents(value: unknown): TaskAgent[] {
|
|
|
5416
5416
|
const perms = row.permissions.filter((p): p is string => typeof p === "string");
|
|
5417
5417
|
if (perms.length > 0) out.permissions = perms;
|
|
5418
5418
|
}
|
|
5419
|
+
// ADR-157: the built-in Astronaut's marker, set only by the cloud.
|
|
5420
|
+
if (row.builtIn === "astronaut") out.builtIn = "astronaut";
|
|
5421
|
+
// ADR-157 §3: the generation its task token must carry.
|
|
5422
|
+
if (typeof row.tokenGeneration === "string" && row.tokenGeneration.length > 0) {
|
|
5423
|
+
out.tokenGeneration = row.tokenGeneration;
|
|
5424
|
+
}
|
|
5419
5425
|
return out;
|
|
5420
5426
|
});
|
|
5421
5427
|
}
|
package/src/protocol.ts
CHANGED
|
@@ -82,6 +82,14 @@ export type HostCommandResult<T> =
|
|
|
82
82
|
* An unknown FIELD is ignored by old readers; an unknown CODE is not.
|
|
83
83
|
*/
|
|
84
84
|
origin?: "cloud";
|
|
85
|
+
/**
|
|
86
|
+
* With `origin: "cloud"`: the protocol feature the command's payload
|
|
87
|
+
* needs and this runner does not advertise, so the bridge never sent it
|
|
88
|
+
* (ADR-157 §3: a roster with token generations needs
|
|
89
|
+
* `agent-token-generation-v1`). Additive for the same reason as
|
|
90
|
+
* `origin`; never set by a host.
|
|
91
|
+
*/
|
|
92
|
+
requiresFeature?: string;
|
|
85
93
|
};
|
|
86
94
|
|
|
87
95
|
/** Capability ids shared by host advertisement and fail-closed cloud gates. */
|
|
@@ -156,6 +164,12 @@ export const HOST_ENGINE_ACCOUNT_SCOPES_PROTOCOL_FEATURE =
|
|
|
156
164
|
* unrelated respawn and never stops a removed one, so the cloud refuses to
|
|
157
165
|
* edit or remove a running task's agents on it. */
|
|
158
166
|
export const LIVE_ROSTER_EDIT_PROTOCOL_FEATURE = "live-roster-edit-v1";
|
|
167
|
+
/** ADR-157 §3: the host signs an agent's `tokenGeneration` into its task token
|
|
168
|
+
* (claim `g`). The cloud stamps a fresh generation on an agent that joins a
|
|
169
|
+
* running task only on a host advertising this, and refuses a token whose
|
|
170
|
+
* generation is not its roster entry's, so a token minted for an earlier agent
|
|
171
|
+
* under the same handle stays dead. */
|
|
172
|
+
export const AGENT_TOKEN_GENERATION_PROTOCOL_FEATURE = "agent-token-generation-v1";
|
|
159
173
|
/** ADR-153 declarations + owner bindings. Advertising this means the host
|
|
160
174
|
* understands every additive env frame field, persists bindings separately
|
|
161
175
|
* from values, and reports immutable repository schema observations. Keep it
|
|
@@ -2956,6 +2970,29 @@ export const MAX_HOST_TASK_INVENTORY_TASK_ID_CHARS = 128;
|
|
|
2956
2970
|
export const ENROLLMENT_REPLAY_PROTOCOL_HEADER = "x-uai-enrollment-replay";
|
|
2957
2971
|
export const ENROLLMENT_REPLAY_PROTOCOL_VERSION = "same-host-v1";
|
|
2958
2972
|
export const COMMUNICATOR_EXECUTION_PROFILE = "communicator";
|
|
2973
|
+
/**
|
|
2974
|
+
* ADR-157: the built-in Astronaut. An Astronaut task has exactly one lead agent with
|
|
2975
|
+
* this id, marked `builtIn: "astronaut"` by the cloud when it builds the entry;
|
|
2976
|
+
* no client may send the marker. The lead runs under the `astronaut` execution
|
|
2977
|
+
* profile: normal tools, but no native subagents (Claude's Agent/Task, Codex's
|
|
2978
|
+
* multi-agent), so every helper it uses is an accounted crew agent.
|
|
2979
|
+
*/
|
|
2980
|
+
export const ASTRONAUT_AGENT_ID = "astronaut";
|
|
2981
|
+
export const ASTRONAUT_BUILT_IN = "astronaut";
|
|
2982
|
+
export const ASTRONAUT_EXECUTION_PROFILE = "astronaut";
|
|
2983
|
+
|
|
2984
|
+
/** Whether `agent` is this task's built-in Astronaut (ADR-157 §1). */
|
|
2985
|
+
export function isBuiltInAstronaut(
|
|
2986
|
+
task: { mode?: string | null; secretaryAgentId?: string | null },
|
|
2987
|
+
agent: { id: string; builtIn?: string | null } | null | undefined,
|
|
2988
|
+
): boolean {
|
|
2989
|
+
return (
|
|
2990
|
+
task.mode === "secretary" &&
|
|
2991
|
+
task.secretaryAgentId === ASTRONAUT_AGENT_ID &&
|
|
2992
|
+
agent?.id === ASTRONAUT_AGENT_ID &&
|
|
2993
|
+
agent.builtIn === ASTRONAUT_BUILT_IN
|
|
2994
|
+
);
|
|
2995
|
+
}
|
|
2959
2996
|
export const MAX_AGENT_ID_CHARS = 128;
|
|
2960
2997
|
export const MAX_SECRETARY_DISPATCH_RECIPIENTS = 16;
|
|
2961
2998
|
export const MAX_SECRETARY_DISPATCH_INSTRUCTION_CHARS = 8_000;
|
|
@@ -3023,6 +3060,11 @@ export interface TaskAgent {
|
|
|
3023
3060
|
}>;
|
|
3024
3061
|
/** ADR-048: the source persona's flat permission list for the `uai` CLI. */
|
|
3025
3062
|
permissions?: string[];
|
|
3063
|
+
/** ADR-157: set by the cloud on the built-in Astronaut only. */
|
|
3064
|
+
builtIn?: "astronaut";
|
|
3065
|
+
/** ADR-157 §3: this agent's token generation, stamped by the cloud when it
|
|
3066
|
+
* joined the running task; signed into its task token as `g`. */
|
|
3067
|
+
tokenGeneration?: string;
|
|
3026
3068
|
}
|
|
3027
3069
|
|
|
3028
3070
|
export type ContainerRuntimePreference = "auto" | "docker" | "apple-container";
|