@skrr-ai/cli 0.1.88 → 0.1.90
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/commands/machines/computer-adoption.d.ts +3 -2
- package/dist/commands/machines/computer-adoption.js +4 -3
- package/dist/commands/machines/dedicated/agent-browser.d.ts +25 -0
- package/dist/commands/machines/dedicated/agent-browser.js +65 -0
- package/dist/commands/machines/dedicated/exec.js +60 -14
- package/dist/commands/machines/dedicated/index.js +2 -0
- package/dist/commands/machines/dedicated/power/explain.d.ts +13 -0
- package/dist/commands/machines/dedicated/power/explain.js +36 -0
- package/dist/commands/machines/dedicated/power/index.d.ts +10 -0
- package/dist/commands/machines/dedicated/power/index.js +24 -0
- package/dist/commands/machines/dedicated/power/keep-awake.d.ts +20 -0
- package/dist/commands/machines/dedicated/power/keep-awake.js +69 -0
- package/dist/commands/machines/dedicated/power/set.d.ts +23 -0
- package/dist/commands/machines/dedicated/power/set.js +106 -0
- package/dist/commands/machines/dedicated/power/show.d.ts +13 -0
- package/dist/commands/machines/dedicated/power/show.js +36 -0
- package/dist/commands/machines/dedicated/show.js +17 -2
- package/dist/lib/commitments.d.ts +1 -1
- package/dist/lib/commitments.js +4 -2
- package/dist/lib/computer-adoption.d.ts +5 -0
- package/dist/lib/computer-adoption.js +6 -1
- package/dist/lib/computer-consent.d.ts +43 -1
- package/dist/lib/computer-consent.js +125 -4
- package/dist/lib/dedicated-keep-awake.d.ts +19 -0
- package/dist/lib/dedicated-keep-awake.js +64 -0
- package/dist/lib/dedicated-machines.d.ts +31 -0
- package/dist/lib/dedicated-machines.js +40 -0
- package/dist/lib/dedicated-power.d.ts +61 -0
- package/dist/lib/dedicated-power.js +243 -0
- package/dist/lib/exec-runtime-binary.d.ts +3 -1
- package/dist/lib/exec-runtime-binary.js +16 -2
- package/dist/lib/format.d.ts +13 -0
- package/dist/lib/format.js +51 -0
- package/dist/lib/keychain.js +3 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.d.ts +135 -8
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.js +166 -16
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/dedicatedRuntimeBusyWire.d.ts +107 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/dedicatedRuntimeBusyWire.js +151 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/dedicatedRuntimeWakeWire.d.ts +115 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/dedicatedRuntimeWakeWire.js +117 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +8 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.d.ts +31 -7
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +149 -9
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.d.ts +135 -8
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.js +161 -13
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/dedicatedRuntimeBusyWire.d.ts +107 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/dedicatedRuntimeBusyWire.js +147 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/dedicatedRuntimeWakeWire.d.ts +115 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/dedicatedRuntimeWakeWire.js +113 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.d.ts +31 -7
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +144 -8
- package/dist/node_modules/@skrr-ai/auth-core/package.json +21 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +6730 -6366
- package/dist/node_modules/@skrr-ai/data-provider/package.json +1 -1
- package/oclif.manifest.json +6303 -5852
- package/package.json +2 -2
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The Dedicated Runtime wake-progress wire contract (power-control task W5,
|
|
4
|
+
* `dedicated-runtime-power-and-demand-wake-2026-10-07.md` §5.3, §7.2, §9).
|
|
5
|
+
*
|
|
6
|
+
* Declared ONCE, here, for the same reason `computerWire.ts` is: the browser,
|
|
7
|
+
* the React Native app and the CLI import it, and none of them may spell the
|
|
8
|
+
* event, the capability or a code a second time. `dedicatedRuntimeWakeWire.test.ts`
|
|
9
|
+
* fails on a second spelling in the API.
|
|
10
|
+
*
|
|
11
|
+
* WHAT IT IS
|
|
12
|
+
* ---------------------------------------------------------------------------
|
|
13
|
+
* A person opens a terminal, an SSH channel, a service call or the Computer on a
|
|
14
|
+
* STOPPED Dedicated Runtime. That is wake progress, not an error: the relay asks
|
|
15
|
+
* `requestWake` (source `person`) to start the machine, then tells THAT request,
|
|
16
|
+
* in stages, how far the start has got, until the machine is assignable and the
|
|
17
|
+
* original request is served, or a bound runs out and it says why and what to do.
|
|
18
|
+
*
|
|
19
|
+
* THE CLIENT ANNOUNCES IT
|
|
20
|
+
* ---------------------------------------------------------------------------
|
|
21
|
+
* A client that has not announced `dedicated_wake_progress_v1` in the open
|
|
22
|
+
* request's `capabilities` array is NEVER sent `dedicated:wake:progress` and is
|
|
23
|
+
* never made to wait: it gets an immediate typed refusal instead. (A client
|
|
24
|
+
* socket has no registration step to announce on, so the announcement rides each
|
|
25
|
+
* request — stateless, nothing held in the relay.)
|
|
26
|
+
*
|
|
27
|
+
* THE VOCABULARY
|
|
28
|
+
* ---------------------------------------------------------------------------
|
|
29
|
+
* `phase` uses the cold-start measurement's phase names
|
|
30
|
+
* (`scripts/dedicated-runtime/measure-cold-start.js` `COLD_START_PHASES`), so
|
|
31
|
+
* what the person sees and what F4 measures are the same words. A spec holds the
|
|
32
|
+
* two lists equal.
|
|
33
|
+
*
|
|
34
|
+
* NOT A SPINNER WITHOUT A BOUND
|
|
35
|
+
* ---------------------------------------------------------------------------
|
|
36
|
+
* `boundMs` is carried on every event so a surface can show elapsed-of-bound.
|
|
37
|
+
* The bound sits ABOVE a slow-but-working start (design §9): running out says
|
|
38
|
+
* "this is taking longer than expected" and the machine is left starting; it is
|
|
39
|
+
* never an accusation that the machine is dead.
|
|
40
|
+
*/
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.DEDICATED_WAKE_POLL_MS = exports.DEDICATED_WAKE_BOUND_MS = exports.DEDICATED_WAKE_CODES = exports.DEDICATED_WAKE_SURFACES = exports.DEDICATED_WAKE_STATES = exports.DEDICATED_WAKE_PHASES = exports.DEDICATED_WAKE_CAPABILITIES = exports.DEDICATED_WAKE_EVENTS = void 0;
|
|
43
|
+
exports.clientAnnouncesWakeProgress = clientAnnouncesWakeProgress;
|
|
44
|
+
/** API -> client, on the same socket as the request it belongs to. */
|
|
45
|
+
exports.DEDICATED_WAKE_EVENTS = {
|
|
46
|
+
progress: 'dedicated:wake:progress',
|
|
47
|
+
};
|
|
48
|
+
/** Announced in the open request's `capabilities` array. */
|
|
49
|
+
exports.DEDICATED_WAKE_CAPABILITIES = {
|
|
50
|
+
progress: 'dedicated_wake_progress_v1',
|
|
51
|
+
};
|
|
52
|
+
/** Same names, same order as `WAKE_PHASES` in api/server/services/DedicatedRuntime/wakePhases.js (pinned by a test). */
|
|
53
|
+
exports.DEDICATED_WAKE_PHASES = [
|
|
54
|
+
'start_requested',
|
|
55
|
+
'provider_start_accepted',
|
|
56
|
+
'instance_running',
|
|
57
|
+
'daemon_connected',
|
|
58
|
+
'first_heartbeat',
|
|
59
|
+
'assignable',
|
|
60
|
+
];
|
|
61
|
+
/**
|
|
62
|
+
* - `waking` a start is in flight; `phase` says how far.
|
|
63
|
+
* - `ready` assignable; the original request is about to be served.
|
|
64
|
+
* - `deferred` the machine is stopping; nothing was started. Retry after `retryAfterSeconds`.
|
|
65
|
+
* - `refused` the start was refused, with `code`, `reason`, `detail`, `fix`.
|
|
66
|
+
* - `timed_out` the bound ran out while it was still starting. Not a failure of the machine.
|
|
67
|
+
*/
|
|
68
|
+
exports.DEDICATED_WAKE_STATES = [
|
|
69
|
+
'waking',
|
|
70
|
+
'ready',
|
|
71
|
+
'deferred',
|
|
72
|
+
'refused',
|
|
73
|
+
'timed_out',
|
|
74
|
+
];
|
|
75
|
+
/** The surfaces a wake can be asked from. */
|
|
76
|
+
exports.DEDICATED_WAKE_SURFACES = [
|
|
77
|
+
'terminal',
|
|
78
|
+
'ssh',
|
|
79
|
+
'services',
|
|
80
|
+
'templates',
|
|
81
|
+
'computer',
|
|
82
|
+
'http',
|
|
83
|
+
];
|
|
84
|
+
/**
|
|
85
|
+
* Typed refusals. Each is a different fact with a different next step; none of
|
|
86
|
+
* them is the generic "Dedicated Runtime dispatch was refused".
|
|
87
|
+
*/
|
|
88
|
+
exports.DEDICATED_WAKE_CODES = {
|
|
89
|
+
/** Stopped, and this request did not (or could not) wake it. */
|
|
90
|
+
stopped: 'DEDICATED_RUNTIME_STOPPED',
|
|
91
|
+
/** A stop is finishing; retry when it has. */
|
|
92
|
+
stopping: 'DEDICATED_RUNTIME_STOPPING',
|
|
93
|
+
/** A start is in flight (ours or someone's). */
|
|
94
|
+
starting: 'DEDICATED_RUNTIME_STARTING',
|
|
95
|
+
/** The bound ran out while it was still starting. */
|
|
96
|
+
timeout: 'DEDICATED_RUNTIME_WAKE_TIMEOUT',
|
|
97
|
+
/** The start was refused: the plan no longer includes the machine. */
|
|
98
|
+
entitlement: 'DEDICATED_RUNTIME_WAKE_REFUSED_ENTITLEMENT',
|
|
99
|
+
/** The start was refused: the spend cap was reached. */
|
|
100
|
+
spendCap: 'DEDICATED_RUNTIME_WAKE_REFUSED_SPEND_CAP',
|
|
101
|
+
/** Any other refusal; `reason` names it. */
|
|
102
|
+
refused: 'DEDICATED_RUNTIME_WAKE_REFUSED',
|
|
103
|
+
/** The start was requested and the machine fell back to stopped or failed. */
|
|
104
|
+
failed: 'DEDICATED_RUNTIME_WAKE_FAILED',
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* How long a surface waits for a start before saying it is taking longer than
|
|
108
|
+
* expected. Above the slow-but-working case: a cold start on a fresh guest
|
|
109
|
+
* takes 25-30 s for the browser alone, and the AMI boot is longer. It is a
|
|
110
|
+
* bound on what we show, never a verdict on the machine.
|
|
111
|
+
*/
|
|
112
|
+
exports.DEDICATED_WAKE_BOUND_MS = 180_000;
|
|
113
|
+
/** How often the relay re-reads the lease while waiting. */
|
|
114
|
+
exports.DEDICATED_WAKE_POLL_MS = 2_000;
|
|
115
|
+
function clientAnnouncesWakeProgress(capabilities) {
|
|
116
|
+
return Array.isArray(capabilities) && capabilities.includes(exports.DEDICATED_WAKE_CAPABILITIES.progress);
|
|
117
|
+
}
|
|
@@ -30,7 +30,7 @@ export { buildProof as buildDeviceProof, generateDeviceKeyPair, jwkThumbprint, n
|
|
|
30
30
|
export { DPOP_HEADER, DPOP_MAX_AGE_SECONDS, DPOP_PROOF_INVALID, DPOP_PROOF_REQUIRED, DPOP_PROOF_TYP, DPOP_PROOF_VERIFY_UNAVAILABLE, accessTokenHash, createDpopKey, isAth, isJwkThumbprint, normalizeDpopHtu, verifyDpopProof, type DpopKey, type DpopProofClaims, type DpopProofRequest, type DpopVerifyFailureReason, type DpopVerifyOptions, type DpopVerifyResult, } from './dpop.js';
|
|
31
31
|
export { initCredEnvelope, resetCredEnvelope, shutdownCredEnvelope, isCredEnvelopeActive, hasCredEnvelopePathConflict, describeCredEnvelopeState, splitKeyConvergencePolicy, maybeEncryptForWrite, maybeDecryptOnRead, DEFAULT_UNREADABLE_CREDENTIAL_HINT, type DecryptOnReadOptions, __wrappedDekFilePathForTest, __setStateForTest as __setCredEnvelopeStateForTest, __getStateForTest as __getCredEnvelopeStateForTest, __resetShutdownGuardForTest, type ReadTransformResult, } from './credentialEnvelopeBridge.js';
|
|
32
32
|
export { initDeviceIdentity, resetDeviceIdentity, signServerRequest, enrollWithServer, clearEnrollmentMarker, isDeviceIdentityActive, getDevicePublicKey, describeDeviceIdentityState, describeDeviceKeySplit, __publicKeyPathForTest, __privateKeyPathForTest, __enrollmentMarkerPathForTest, __enrollmentBackoffPathForTest, __setStateForTest as __setDeviceIdentityStateForTest, __getStateForTest as __getDeviceIdentityStateForTest, type EnrollmentResult, } from './deviceIdentityBridge.js';
|
|
33
|
-
export { getMachineUuid, hostedRuntimeIdOverride, HOSTED_RUNTIME_MACHINE_SOURCES, __resetMachineUuidCacheForTest, } from './machineUuid.js';
|
|
33
|
+
export { getMachineUuid, getHardwareMachineUuid, setMachineUuidProfile, getMachineUuidProfile, qualifyMachineUuid, MACHINE_IDENTITY_FILENAME, hostedRuntimeIdOverride, HOSTED_RUNTIME_MACHINE_SOURCES, __resetMachineUuidCacheForTest, } from './machineUuid.js';
|
|
34
34
|
export { ensureMachineDaemonId, legacyDaemonUuids, __resetCachedDaemonIdForTest, } from './machineId.js';
|
|
35
35
|
export { PAIR_AAD_PREFIX, PAIR_AAD_MAX_LEN, PAIR_BUNDLE_MAX_BASE64_LEN, PAIR_NONCE_LEN, PAIR_PUBKEY_LEN, PAIR_SECRET_LEN, PairBundleError, assemblePairBundleBase64, base64ToUint8Array as pairBase64ToUint8Array, base64UrlToUint8Array as pairBase64UrlToUint8Array, buildPairAad, buildPairUrl, generatePairKeyPair, openPairBundleBase64, parsePairBundle, parsePairPlaintext, parsePairUrl, uint8ArrayToBase64 as pairUint8ArrayToBase64, uint8ArrayToBase64Url as pairUint8ArrayToBase64Url, type AssembleBundleOptions as PairAssembleBundleOptions, type OpenBundleOptions as PairOpenBundleOptions, type PairBundle, type PairBundleErrorCode, type PairKeyPair, type PairPlaintextV1, type PairUrlFields, } from './daemonPair.js';
|
|
36
36
|
export { HARNESS_TIERS, getHarnessTier, credentialPolicyForTier, tierPermitsConfiguredAutoMode, type HarnessTrustTier, type CredentialDeliveryPolicy, type CredentialMode, } from './harnessTrust.js';
|
|
@@ -24,9 +24,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
25
|
exports.runHeadersHelper = exports.SENTINEL_TRIGGERING_FAILURES = exports.__resetAuthHelperFailureReasonForTest = exports.getLastAuthHelperFailureReason = exports.getDefaultHelperTtlMs = exports.invokeAuthHelper = exports.AuthHelperUnavailableError = exports.AuthHelperUntrustedError = exports.isStaticTokenKind = exports.PERSONAL_ACCESS_TOKEN_PREFIX = exports.CI_TOKEN_PREFIX = exports.classifyTokenKind = exports.invalidateAuthHelperCache = exports.__resetCredentialResolverForTest = exports.CREDENTIAL_PRECEDENCE = exports.CredentialResolver = exports.__setFdReaderForTest = exports.readAuthFromFd = exports.createRefreshScheduler = exports.UNKNOWN_401_BUDGET = exports.__resetUnknown401StreaksForTest = exports.__refreshDiagnostics = exports.installLockExitHandlers = exports.clearReauthState = exports.needsReauthState = exports.persistReauthState = exports.withAuthLock = exports.revokeDaemonRefreshSession = exports.refreshDaemonToken = exports.classifyRefreshResponse = exports.EXIT_NEEDS_REAUTH = exports.reauthCommand = exports.formatReauthMessage = exports.handleMidStreamAuthExpiry = exports.isAuthExpiredSseEvent = exports.decodeJwtPayload = exports.decodeJwtExpiry = exports.TransientAuthFailure = exports.PermanentAuthFailure = exports.emitAuthTelemetry = exports.getAuthBinaryName = exports.getAuthKillSwitches = exports.getAuthConfigDir = exports.getAuthLogger = exports.configureAuthCore = exports.OAUTH_CLI_SCOPE = exports.isDaemonScope = exports.VALID_DAEMON_SCOPE_SET = exports.ALL_DAEMON_SCOPES = exports.SCOPES = void 0;
|
|
26
26
|
exports.jwkThumbprint = exports.generateDeviceKeyPair = exports.buildDeviceProof = exports.zeroizeKekCaches = exports.WindowsKek = exports.registerZeroizeHook = exports.MacosKek = exports.LinuxKek = exports.KekUnavailableError = exports.UnavailableKek = exports.InMemoryKek = exports.getKekStrategy = exports.__setKekStrategyForTest = exports.credEnvelopeWrap = exports.credEnvelopeUnwrap = exports.credEnvelopeSerialize = exports.credSealBuffer = exports.credOpenBuffer = exports.CRED_KEY_LEN = exports.isCredEnvelopeString = exports.generateDek = exports.CRED_ENVELOPE_MAGIC = exports.credEnvelopeEncrypt = exports.credEnvelopeDeserialize = exports.credEnvelopeDecrypt = exports.buildCredentialAad = exports.isValidRecoveryCode = exports.normalizeRecoveryCode = exports.parseRecoveryCode = exports.formatRecoveryCode = exports.MAX_TTL_DAYS = exports.MIN_TTL_DAYS = exports.parseTtlDays = exports.LoginExchangeError = exports.LoginInitError = exports.loginWithLocalhost = exports.LocalCallbackMalformedError = exports.LocalCallbackDeniedError = exports.LocalCallbackStateMismatchError = exports.LocalCallbackTimeoutError = exports.LocalCallbackBindError = exports.LocalCallbackError = exports.DEFAULT_LOGIN_TIMEOUT_MS = exports.startLocalCallback = exports.verifyChallenge = exports.safeEqual = exports.generateState = exports.challenge = exports.generateVerifier = exports.invalidateHeadersHelperCache = void 0;
|
|
27
|
-
exports.
|
|
28
|
-
exports.
|
|
29
|
-
exports.consolidateProfileState = exports.profileStateFilePathsToClear = exports.profileStateFileLocations = exports.resolveProfileStateFile = exports.resolveProfileStateDir = exports.legacyProfileStateDir = exports.profileStateDir = exports.SUPERSEDED_COPY_SUFFIX = exports.SUPERSEDED_MARKER_SUFFIX = exports.PROFILES_SEGMENT = exports.isConfigRootOverridden = exports.configRootPath = exports.resolveConfigRoot = exports.verifyManifest = exports.verifyArtifact = exports.isTrustedArtifactOrigin = exports.getDeltaFor = exports.buildManifestMessage = exports.buildArtifactMessage = exports.TRUSTED_FEED_ORIGINS = exports.MAX_SIGS = exports.OVERSKY_RELEASE_PUBLIC_KEYS = exports.resolveFirstPartyHarnessChannel = exports.resolveChannelManifestUrl = exports.isFirstPartyHarnessChannel = exports.firstPartyHarnessFeedCandidates = exports.firstPartyHarnessFeedBase = exports.firstPartyHarnessChannelPrefix = exports.FIRST_PARTY_HARNESS_CHANNELS = exports.DEFAULT_FIRST_PARTY_HARNESS_CHANNEL = exports.migrateFirstPartyHarnessHome = exports.linkFirstPartyHarnessAliases = exports.firstPartyHarnessInstalledBinaryPath = exports.firstPartyHarnessHomeDir = exports.firstPartyHarnessBinDir = exports.FIRST_PARTY_HARNESS_PROVENANCE_SUFFIX = exports.FIRST_PARTY_HARNESS_PREVIOUS_SUFFIX = exports.describeLegacyState = exports.findLegacyLocalState = void 0;
|
|
27
|
+
exports.qualifyMachineUuid = exports.getMachineUuidProfile = exports.setMachineUuidProfile = exports.getHardwareMachineUuid = exports.getMachineUuid = exports.__getDeviceIdentityStateForTest = exports.__setDeviceIdentityStateForTest = exports.__enrollmentBackoffPathForTest = exports.__enrollmentMarkerPathForTest = exports.__privateKeyPathForTest = exports.__publicKeyPathForTest = exports.describeDeviceKeySplit = exports.describeDeviceIdentityState = exports.getDevicePublicKey = exports.isDeviceIdentityActive = exports.clearEnrollmentMarker = exports.enrollWithServer = exports.signServerRequest = exports.resetDeviceIdentity = exports.initDeviceIdentity = exports.__resetShutdownGuardForTest = exports.__getCredEnvelopeStateForTest = exports.__setCredEnvelopeStateForTest = exports.__wrappedDekFilePathForTest = exports.DEFAULT_UNREADABLE_CREDENTIAL_HINT = exports.maybeDecryptOnRead = exports.maybeEncryptForWrite = exports.splitKeyConvergencePolicy = exports.describeCredEnvelopeState = exports.hasCredEnvelopePathConflict = exports.isCredEnvelopeActive = exports.shutdownCredEnvelope = exports.resetCredEnvelope = exports.initCredEnvelope = exports.verifyDpopProof = exports.normalizeDpopHtu = exports.isJwkThumbprint = exports.isAth = exports.createDpopKey = exports.accessTokenHash = exports.DPOP_PROOF_VERIFY_UNAVAILABLE = exports.DPOP_PROOF_TYP = exports.DPOP_PROOF_REQUIRED = exports.DPOP_PROOF_INVALID = exports.DPOP_MAX_AGE_SECONDS = exports.DPOP_HEADER = exports.verifyDeviceProof = exports.tokenHash = exports.publicJwkFromX = exports.normalizeHtu = void 0;
|
|
28
|
+
exports.LOOPBACK_DEFAULT_MAX_BODY_BYTES = exports.LoopbackTargetRefusedError = exports.isLoopbackAddress = exports.isLoopbackHostname = exports.assertLoopbackHttpUrl = exports.loopbackFetch = exports.withLoopbackNoProxy = exports.envHasProxy = exports.LOOPBACK_NO_PROXY_HOSTS = exports.isDaemonChildEnv = exports.DAEMON_CHILD_ENV = exports.SENSITIVE_ENV_PREFIX_EXCEPTIONS = exports.SENSITIVE_ENV_NAME_TOKENS = exports.SENSITIVE_ENV_SUFFIXES = exports.SENSITIVE_ENV_PREFIXES = exports.SENSITIVE_ENV_VARS = exports.sanitizeSpawnEnv = exports.harnessLoadsClaudeSkillsLayout = exports.claudeSkillsLayoutEvidence = exports.HARNESSES_LOADING_CLAUDE_SKILLS_LAYOUT = exports.tierPermitsConfiguredAutoMode = exports.credentialPolicyForTier = exports.getHarnessTier = exports.HARNESS_TIERS = exports.pairUint8ArrayToBase64Url = exports.pairUint8ArrayToBase64 = exports.parsePairUrl = exports.parsePairPlaintext = exports.parsePairBundle = exports.openPairBundleBase64 = exports.generatePairKeyPair = exports.buildPairUrl = exports.buildPairAad = exports.pairBase64UrlToUint8Array = exports.pairBase64ToUint8Array = exports.assemblePairBundleBase64 = exports.PairBundleError = exports.PAIR_SECRET_LEN = exports.PAIR_PUBKEY_LEN = exports.PAIR_NONCE_LEN = exports.PAIR_BUNDLE_MAX_BASE64_LEN = exports.PAIR_AAD_MAX_LEN = exports.PAIR_AAD_PREFIX = exports.__resetCachedDaemonIdForTest = exports.legacyDaemonUuids = exports.ensureMachineDaemonId = exports.__resetMachineUuidCacheForTest = exports.HOSTED_RUNTIME_MACHINE_SOURCES = exports.hostedRuntimeIdOverride = exports.MACHINE_IDENTITY_FILENAME = void 0;
|
|
29
|
+
exports.consolidateProfileState = exports.profileStateFilePathsToClear = exports.profileStateFileLocations = exports.resolveProfileStateFile = exports.resolveProfileStateDir = exports.legacyProfileStateDir = exports.profileStateDir = exports.SUPERSEDED_COPY_SUFFIX = exports.SUPERSEDED_MARKER_SUFFIX = exports.PROFILES_SEGMENT = exports.isConfigRootOverridden = exports.configRootPath = exports.resolveConfigRoot = exports.verifyManifest = exports.verifyArtifact = exports.isTrustedArtifactOrigin = exports.getDeltaFor = exports.buildManifestMessage = exports.buildArtifactMessage = exports.TRUSTED_FEED_ORIGINS = exports.MAX_SIGS = exports.OVERSKY_RELEASE_PUBLIC_KEYS = exports.resolveFirstPartyHarnessChannel = exports.resolveChannelManifestUrl = exports.isFirstPartyHarnessChannel = exports.firstPartyHarnessFeedCandidates = exports.firstPartyHarnessFeedBase = exports.firstPartyHarnessChannelPrefix = exports.FIRST_PARTY_HARNESS_CHANNELS = exports.DEFAULT_FIRST_PARTY_HARNESS_CHANNEL = exports.migrateFirstPartyHarnessHome = exports.linkFirstPartyHarnessAliases = exports.firstPartyHarnessInstalledBinaryPath = exports.firstPartyHarnessHomeDir = exports.firstPartyHarnessBinDir = exports.FIRST_PARTY_HARNESS_PROVENANCE_SUFFIX = exports.FIRST_PARTY_HARNESS_PREVIOUS_SUFFIX = exports.describeLegacyState = exports.findLegacyLocalState = exports.DEFAULT_BINARY_NAME = exports.LEGACY_NATIVE_ID_PREFIXES = exports.NATIVE_ID_PREFIX = exports.LEGACY_CONFIG_DIR_NAMES = exports.CONFIG_DIR_NAME = void 0;
|
|
30
30
|
// Daemon scope vocabulary — single source of truth for non-Mongoose tiers
|
|
31
31
|
// (daemon, desktop, cli). Schema-bound canonical lives in
|
|
32
32
|
// `@skrr-ai/data-schemas/common/daemonScopes`; the two are kept byte-equal
|
|
@@ -284,6 +284,11 @@ Object.defineProperty(exports, "__getDeviceIdentityStateForTest", { enumerable:
|
|
|
284
284
|
// OSK-12063. Also exposed dependency-free as `@skrr-ai/auth-core/machine-uuid`.
|
|
285
285
|
var machineUuid_js_1 = require("./machineUuid.js");
|
|
286
286
|
Object.defineProperty(exports, "getMachineUuid", { enumerable: true, get: function () { return machineUuid_js_1.getMachineUuid; } });
|
|
287
|
+
Object.defineProperty(exports, "getHardwareMachineUuid", { enumerable: true, get: function () { return machineUuid_js_1.getHardwareMachineUuid; } });
|
|
288
|
+
Object.defineProperty(exports, "setMachineUuidProfile", { enumerable: true, get: function () { return machineUuid_js_1.setMachineUuidProfile; } });
|
|
289
|
+
Object.defineProperty(exports, "getMachineUuidProfile", { enumerable: true, get: function () { return machineUuid_js_1.getMachineUuidProfile; } });
|
|
290
|
+
Object.defineProperty(exports, "qualifyMachineUuid", { enumerable: true, get: function () { return machineUuid_js_1.qualifyMachineUuid; } });
|
|
291
|
+
Object.defineProperty(exports, "MACHINE_IDENTITY_FILENAME", { enumerable: true, get: function () { return machineUuid_js_1.MACHINE_IDENTITY_FILENAME; } });
|
|
287
292
|
Object.defineProperty(exports, "hostedRuntimeIdOverride", { enumerable: true, get: function () { return machineUuid_js_1.hostedRuntimeIdOverride; } });
|
|
288
293
|
Object.defineProperty(exports, "HOSTED_RUNTIME_MACHINE_SOURCES", { enumerable: true, get: function () { return machineUuid_js_1.HOSTED_RUNTIME_MACHINE_SOURCES; } });
|
|
289
294
|
Object.defineProperty(exports, "__resetMachineUuidCacheForTest", { enumerable: true, get: function () { return machineUuid_js_1.__resetMachineUuidCacheForTest; } });
|
|
@@ -18,19 +18,43 @@ export declare const HOSTED_RUNTIME_MACHINE_SOURCES: ReadonlySet<string>;
|
|
|
18
18
|
*/
|
|
19
19
|
export declare function hostedRuntimeIdOverride(name: string, env?: NodeJS.ProcessEnv): string | null;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* The HARDWARE identity of this machine (IOPlatformUUID / machine-id /
|
|
22
|
+
* MachineGuid, or a control-plane-issued value on a hosted runtime). Cached for
|
|
23
|
+
* the process lifetime. Same machine -> same value across reboots.
|
|
22
24
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* The guarantee is only: same machine -> same value across reboots, and the
|
|
26
|
-
* same value from every binary that calls this function.
|
|
27
|
-
*
|
|
28
|
-
* On a hosted runtime the control-plane-issued `OVERSKY_MACHINE_UUID` wins.
|
|
25
|
+
* Almost nothing should call this: `getMachineUuid()` is what goes on the wire,
|
|
26
|
+
* and it equals this for the default profile.
|
|
29
27
|
*
|
|
30
28
|
* Falls back to a deterministic hostname+username hash if the platform
|
|
31
29
|
* probe fails. This preserves server-side record continuity even on
|
|
32
30
|
* locked-down machines that refuse ioreg / registry access.
|
|
33
31
|
*/
|
|
32
|
+
export declare function getHardwareMachineUuid(): string;
|
|
33
|
+
/** The profile's persisted machine-identity choice, beside its other state. */
|
|
34
|
+
export declare const MACHINE_IDENTITY_FILENAME = "machine-identity.json";
|
|
35
|
+
/** The server caps `machineUuid` at 64 characters; 36 + 15 fits, and so does a 41-character fallback. */
|
|
36
|
+
export declare function qualifyMachineUuid(hardware: string, profile: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Tell this module which profile the process runs as. Called wherever a binary
|
|
39
|
+
* resolves its profile (`setActiveProfile` in the daemon and in the CLI), so the
|
|
40
|
+
* identity cannot depend on call order. `null`, '' and the default profile all
|
|
41
|
+
* mean "the hardware identity".
|
|
42
|
+
*/
|
|
43
|
+
export declare function setMachineUuidProfile(profile: string | null | undefined): void;
|
|
44
|
+
export declare function getMachineUuidProfile(): string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Return the `machineUuid` this process sends to the server.
|
|
47
|
+
*
|
|
48
|
+
* Callers should treat this as opaque: the format differs per platform
|
|
49
|
+
* (macOS IOPlatformUUID, Linux systemd machine-id, Windows MachineGuid), and a
|
|
50
|
+
* non-default profile that started new carries a `:p-<hash>` suffix. The
|
|
51
|
+
* guarantee is only: same machine + same profile -> same value across reboots,
|
|
52
|
+
* and the same value from every binary of that profile that calls this function.
|
|
53
|
+
*
|
|
54
|
+
* Equals the hardware identity for the default profile, for a hosted runtime
|
|
55
|
+
* (the control-plane-issued `OVERSKY_MACHINE_UUID` wins) and for a non-default
|
|
56
|
+
* profile that already held credentials; see the block above.
|
|
57
|
+
*/
|
|
34
58
|
export declare function getMachineUuid(): string;
|
|
35
59
|
/** @internal test seam — forget the cached value so the next call re-probes. */
|
|
36
60
|
export declare function __resetMachineUuidCacheForTest(): void;
|
|
@@ -3,8 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.HOSTED_RUNTIME_MACHINE_SOURCES = void 0;
|
|
6
|
+
exports.MACHINE_IDENTITY_FILENAME = exports.HOSTED_RUNTIME_MACHINE_SOURCES = void 0;
|
|
7
7
|
exports.hostedRuntimeIdOverride = hostedRuntimeIdOverride;
|
|
8
|
+
exports.getHardwareMachineUuid = getHardwareMachineUuid;
|
|
9
|
+
exports.qualifyMachineUuid = qualifyMachineUuid;
|
|
10
|
+
exports.setMachineUuidProfile = setMachineUuidProfile;
|
|
11
|
+
exports.getMachineUuidProfile = getMachineUuidProfile;
|
|
8
12
|
exports.getMachineUuid = getMachineUuid;
|
|
9
13
|
exports.__resetMachineUuidCacheForTest = __resetMachineUuidCacheForTest;
|
|
10
14
|
/**
|
|
@@ -34,7 +38,9 @@ exports.__resetMachineUuidCacheForTest = __resetMachineUuidCacheForTest;
|
|
|
34
38
|
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
35
39
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
36
40
|
const node_os_1 = __importDefault(require("node:os"));
|
|
41
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
37
42
|
const node_child_process_1 = require("node:child_process");
|
|
43
|
+
const configRoot_js_1 = require("./configRoot.js");
|
|
38
44
|
/**
|
|
39
45
|
* Daemon sources whose identity is ISSUED by the control plane rather than
|
|
40
46
|
* derived from the host: the provisioner mints the daemon id and machine uuid
|
|
@@ -106,20 +112,18 @@ function readMachineUuidWindows() {
|
|
|
106
112
|
}
|
|
107
113
|
}
|
|
108
114
|
/**
|
|
109
|
-
*
|
|
115
|
+
* The HARDWARE identity of this machine (IOPlatformUUID / machine-id /
|
|
116
|
+
* MachineGuid, or a control-plane-issued value on a hosted runtime). Cached for
|
|
117
|
+
* the process lifetime. Same machine -> same value across reboots.
|
|
110
118
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* The guarantee is only: same machine -> same value across reboots, and the
|
|
114
|
-
* same value from every binary that calls this function.
|
|
115
|
-
*
|
|
116
|
-
* On a hosted runtime the control-plane-issued `OVERSKY_MACHINE_UUID` wins.
|
|
119
|
+
* Almost nothing should call this: `getMachineUuid()` is what goes on the wire,
|
|
120
|
+
* and it equals this for the default profile.
|
|
117
121
|
*
|
|
118
122
|
* Falls back to a deterministic hostname+username hash if the platform
|
|
119
123
|
* probe fails. This preserves server-side record continuity even on
|
|
120
124
|
* locked-down machines that refuse ioreg / registry access.
|
|
121
125
|
*/
|
|
122
|
-
function
|
|
126
|
+
function getHardwareMachineUuid() {
|
|
123
127
|
const hostedMachineUuid = hostedRuntimeIdOverride('OVERSKY_MACHINE_UUID');
|
|
124
128
|
if (hostedMachineUuid)
|
|
125
129
|
return hostedMachineUuid;
|
|
@@ -150,7 +154,143 @@ function getMachineUuid() {
|
|
|
150
154
|
cachedMachineUuid = fallback;
|
|
151
155
|
return fallback;
|
|
152
156
|
}
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
// Profile-qualified machine identity (OSK-13845)
|
|
159
|
+
//
|
|
160
|
+
// The server keys a Daemon row on (user, machineUuid), pins ONE device key to
|
|
161
|
+
// that row, and groups Harness rows into one "machine" by it. A profile is the
|
|
162
|
+
// documented way to run a second, isolated daemon on the same computer, and
|
|
163
|
+
// while the machineUuid was hardware only a second profile landed on the FIRST
|
|
164
|
+
// profile's row: it replaced the machine page's Daemon and working directory,
|
|
165
|
+
// re-registered every harness under itself, and its interactive login re-pinned
|
|
166
|
+
// the row's device key (OSK-12063), so the default profile's next refresh was
|
|
167
|
+
// refused DEVICE_KEY_MISMATCH and every `skrr` call failed until a re-login.
|
|
168
|
+
//
|
|
169
|
+
// So a profile that STARTS NEW on a machine is qualified:
|
|
170
|
+
// `<hardware>:p-<12 hex of sha256(profile)>`. Two rules keep everything that
|
|
171
|
+
// exists where it is:
|
|
172
|
+
//
|
|
173
|
+
// - the default profile is NEVER qualified: its identity is the hardware value
|
|
174
|
+
// it has always had, so no existing machine row changes;
|
|
175
|
+
// - a non-default profile that already holds credentials (an
|
|
176
|
+
// `auth-binding.json` or a persisted daemon identity) keeps the hardware
|
|
177
|
+
// value. Its refresh tokens are bound to that row and the server refuses a
|
|
178
|
+
// refresh whose machineUuid differs from the stored one (H7), so qualifying
|
|
179
|
+
// it would sign it out. It stays a second daemon on the shared row.
|
|
180
|
+
//
|
|
181
|
+
// The choice is made ONCE, from that evidence, and written to the profile's
|
|
182
|
+
// `machine-identity.json`; afterwards it is read, never re-derived. Deriving it
|
|
183
|
+
// every time would flip a profile from qualified to shared the moment its own
|
|
184
|
+
// first login wrote `auth-binding.json`.
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
/** The profile's persisted machine-identity choice, beside its other state. */
|
|
187
|
+
exports.MACHINE_IDENTITY_FILENAME = 'machine-identity.json';
|
|
188
|
+
/** Files that prove a profile already holds credentials bound to the shared row. */
|
|
189
|
+
const PRE_EXISTING_PROFILE_EVIDENCE = ['auth-binding.json', 'daemon-identity.json'];
|
|
190
|
+
const DEFAULT_PROFILE_NAME = 'default';
|
|
191
|
+
/** The server caps `machineUuid` at 64 characters; 36 + 15 fits, and so does a 41-character fallback. */
|
|
192
|
+
function qualifyMachineUuid(hardware, profile) {
|
|
193
|
+
const digest = node_crypto_1.default
|
|
194
|
+
.createHash('sha256')
|
|
195
|
+
.update(`profile:${profile}`)
|
|
196
|
+
.digest('hex')
|
|
197
|
+
.slice(0, 12);
|
|
198
|
+
return `${hardware}:p-${digest}`;
|
|
199
|
+
}
|
|
200
|
+
let activeMachineProfile = null;
|
|
201
|
+
const profileChoiceCache = new Map();
|
|
202
|
+
/**
|
|
203
|
+
* Tell this module which profile the process runs as. Called wherever a binary
|
|
204
|
+
* resolves its profile (`setActiveProfile` in the daemon and in the CLI), so the
|
|
205
|
+
* identity cannot depend on call order. `null`, '' and the default profile all
|
|
206
|
+
* mean "the hardware identity".
|
|
207
|
+
*/
|
|
208
|
+
function setMachineUuidProfile(profile) {
|
|
209
|
+
activeMachineProfile = typeof profile === 'string' && profile.trim() ? profile.trim() : null;
|
|
210
|
+
}
|
|
211
|
+
function getMachineUuidProfile() {
|
|
212
|
+
return activeMachineProfile;
|
|
213
|
+
}
|
|
214
|
+
function readPersistedChoice(file, hardware, profile) {
|
|
215
|
+
try {
|
|
216
|
+
const parsed = JSON.parse(node_fs_1.default.readFileSync(file, 'utf-8'));
|
|
217
|
+
// A file from another machine (a restored backup, a synced home) is absent.
|
|
218
|
+
if (parsed?.version !== 1 || parsed.hardware !== hardware)
|
|
219
|
+
return null;
|
|
220
|
+
// Only the two values this module can produce are accepted: a hand-edited or
|
|
221
|
+
// foreign string must never become an identity.
|
|
222
|
+
if (parsed.machineUuid === hardware)
|
|
223
|
+
return hardware;
|
|
224
|
+
const qualified = qualifyMachineUuid(hardware, profile);
|
|
225
|
+
return parsed.machineUuid === qualified ? qualified : null;
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function persistChoice(dir, file, hardware, machineUuid, reason) {
|
|
232
|
+
try {
|
|
233
|
+
node_fs_1.default.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
234
|
+
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
235
|
+
const body = { version: 1, hardware, machineUuid, reason, decidedAt: new Date().toISOString() };
|
|
236
|
+
node_fs_1.default.writeFileSync(tmp, `${JSON.stringify(body)}\n`, { mode: 0o600 });
|
|
237
|
+
node_fs_1.default.renameSync(tmp, file);
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
// Not persisted: the in-process cache keeps this process consistent, and the
|
|
241
|
+
// next process decides again from the same evidence.
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/** The identity a NON-default profile registers under. Never throws. */
|
|
245
|
+
function resolveProfileMachineUuid(profile, hardware) {
|
|
246
|
+
const cacheKey = `${hardware}\u0000${profile}`;
|
|
247
|
+
const cached = profileChoiceCache.get(cacheKey);
|
|
248
|
+
if (cached)
|
|
249
|
+
return cached;
|
|
250
|
+
const dir = node_path_1.default.join((0, configRoot_js_1.resolveConfigRoot)(), 'profiles', profile);
|
|
251
|
+
const file = node_path_1.default.join(dir, exports.MACHINE_IDENTITY_FILENAME);
|
|
252
|
+
let chosen = readPersistedChoice(file, hardware, profile);
|
|
253
|
+
if (!chosen) {
|
|
254
|
+
const preExisting = PRE_EXISTING_PROFILE_EVIDENCE.some((name) => {
|
|
255
|
+
try {
|
|
256
|
+
return node_fs_1.default.existsSync(node_path_1.default.join(dir, name));
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
chosen = preExisting ? hardware : qualifyMachineUuid(hardware, profile);
|
|
263
|
+
persistChoice(dir, file, hardware, chosen, preExisting ? 'pre_existing_profile' : 'new_profile');
|
|
264
|
+
}
|
|
265
|
+
profileChoiceCache.set(cacheKey, chosen);
|
|
266
|
+
return chosen;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Return the `machineUuid` this process sends to the server.
|
|
270
|
+
*
|
|
271
|
+
* Callers should treat this as opaque: the format differs per platform
|
|
272
|
+
* (macOS IOPlatformUUID, Linux systemd machine-id, Windows MachineGuid), and a
|
|
273
|
+
* non-default profile that started new carries a `:p-<hash>` suffix. The
|
|
274
|
+
* guarantee is only: same machine + same profile -> same value across reboots,
|
|
275
|
+
* and the same value from every binary of that profile that calls this function.
|
|
276
|
+
*
|
|
277
|
+
* Equals the hardware identity for the default profile, for a hosted runtime
|
|
278
|
+
* (the control-plane-issued `OVERSKY_MACHINE_UUID` wins) and for a non-default
|
|
279
|
+
* profile that already held credentials; see the block above.
|
|
280
|
+
*/
|
|
281
|
+
function getMachineUuid() {
|
|
282
|
+
const hardware = getHardwareMachineUuid();
|
|
283
|
+
// A hosted runtime's identity is ISSUED and fenced by the control plane.
|
|
284
|
+
if (hostedRuntimeIdOverride('OVERSKY_MACHINE_UUID'))
|
|
285
|
+
return hardware;
|
|
286
|
+
const profile = activeMachineProfile;
|
|
287
|
+
if (!profile || profile === DEFAULT_PROFILE_NAME)
|
|
288
|
+
return hardware;
|
|
289
|
+
return resolveProfileMachineUuid(profile, hardware);
|
|
290
|
+
}
|
|
153
291
|
/** @internal test seam — forget the cached value so the next call re-probes. */
|
|
154
292
|
function __resetMachineUuidCacheForTest() {
|
|
155
293
|
cachedMachineUuid = null;
|
|
294
|
+
activeMachineProfile = null;
|
|
295
|
+
profileChoiceCache.clear();
|
|
156
296
|
}
|
|
@@ -33,6 +33,22 @@ export declare const COMPUTER_EVENTS: {
|
|
|
33
33
|
readonly attach: "computer:attach";
|
|
34
34
|
/** client → API: leave. */
|
|
35
35
|
readonly detach: "computer:detach";
|
|
36
|
+
/**
|
|
37
|
+
* client → API: read the whole manifest again ON THE SAME ATTACHMENT, after
|
|
38
|
+
* a missed delta or a `stale_epoch` (OSK-13815). The ack carries what an
|
|
39
|
+
* attach's does — the attachment id (unchanged), the manifest and the
|
|
40
|
+
* operations — or a typed refusal; `not_found` means the attachment is gone
|
|
41
|
+
* and only then does the client attach afresh. Re-reading state must never
|
|
42
|
+
* change who the reader is: a control lease is bound to the attachment
|
|
43
|
+
* (`holderAttachmentId`), and a resync that detached and attached again
|
|
44
|
+
* orphaned the hold the person had just taken. Answered by the API, which
|
|
45
|
+
* renews the binding with the daemon exactly as its periodic re-check does
|
|
46
|
+
* (a repeated `daemon:computer:attach` with the same id), so it has no
|
|
47
|
+
* daemon mirror and needs no daemon capability. An API that predates it
|
|
48
|
+
* never answers; the client bounds the wait and falls back to attaching
|
|
49
|
+
* afresh.
|
|
50
|
+
*/
|
|
51
|
+
readonly resync: "computer:resync";
|
|
36
52
|
/** API → client: this attachment was detached, with the reason (revoked, stale generation, …). */
|
|
37
53
|
readonly detached: "computer:detached";
|
|
38
54
|
/** API → client: a whole manifest, or a revisioned delta. */
|
|
@@ -162,6 +178,22 @@ export declare const DAEMON_COMPUTER_EVENT_NAMES: readonly DaemonComputerEventNa
|
|
|
162
178
|
export declare const DAEMON_COMPUTER_REPORT_EVENT_KEYS: readonly ["ack", "manifest", "data", "activity", "detached", "filesChanged", "diagnostics"];
|
|
163
179
|
/** The API → client events; every other `computer:*` event flows client → API. */
|
|
164
180
|
export declare const COMPUTER_SERVER_EVENT_KEYS: readonly ["detached", "manifest", "data", "activity", "filesChanged"];
|
|
181
|
+
/**
|
|
182
|
+
* Client → API requests the API answers itself, with no `daemon:computer:*`
|
|
183
|
+
* mirror: every other client request is relayed to the daemon under the same
|
|
184
|
+
* key. `resync` renews the binding through the daemon's existing attach
|
|
185
|
+
* (OSK-13815).
|
|
186
|
+
*/
|
|
187
|
+
export declare const COMPUTER_API_ANSWERED_EVENT_KEYS: readonly ["resync"];
|
|
188
|
+
/** How long the client waits for a `computer:resync` answer before attaching afresh (an API that predates it never answers). */
|
|
189
|
+
export declare const COMPUTER_RESYNC_TIMEOUT_MS = 12000;
|
|
190
|
+
/**
|
|
191
|
+
* How long a client holds a manifest delta that arrived AHEAD of its
|
|
192
|
+
* predecessor before reading the hole as a loss (OSK-13815). Deltas fan out
|
|
193
|
+
* through a relay of several replicas; a reorder is milliseconds, a loss is
|
|
194
|
+
* forever, and only a loss needs the whole manifest again.
|
|
195
|
+
*/
|
|
196
|
+
export declare const COMPUTER_MANIFEST_REORDER_WAIT_MS = 300;
|
|
165
197
|
/**
|
|
166
198
|
* One capability per wire addition, each withheld positively at dispatch: the
|
|
167
199
|
* API never sends a computer event to a daemon that did not announce the
|
|
@@ -263,6 +295,42 @@ export declare const COMPUTER_CAPABILITIES: {
|
|
|
263
295
|
* browser; nothing is proxied to it. Announced by the relay that serves it.
|
|
264
296
|
*/
|
|
265
297
|
readonly declaredServices: "computer_declared_services_v1";
|
|
298
|
+
/**
|
|
299
|
+
* The page follows the controlling window (§6.2 "a stable viewport", §7.1,
|
|
300
|
+
* OSK-13808): a browser `viewport` input, sent only by the attachment that
|
|
301
|
+
* holds the browser's lease at the current epoch, sizes the streamed page
|
|
302
|
+
* to that window's content box (`COMPUTER_BROWSER_VIEWPORT_LIMITS`). Only
|
|
303
|
+
* while a person holds control: handing back — or the hold lapsing, being
|
|
304
|
+
* revoked or moving to the agent any other way — restores the browser's own
|
|
305
|
+
* viewport before the agent can act, so an agent never inherits a person's
|
|
306
|
+
* size. Watchers keep seeing the page at whatever size it is, scaled to
|
|
307
|
+
* fit. Announced only where the browser driver can override and restore
|
|
308
|
+
* the page's metrics; without it the window scales the fixed page, as
|
|
309
|
+
* before, and never sends the input.
|
|
310
|
+
*/
|
|
311
|
+
readonly browserViewport: "computer_browser_viewport_v1";
|
|
312
|
+
/**
|
|
313
|
+
* A browser surface whose browser is still starting says so (OSK-13824): its
|
|
314
|
+
* descriptor carries `starting: { since }` from the moment its Chromium
|
|
315
|
+
* begins to launch until that launch ends (running, or failed), and the
|
|
316
|
+
* window shows "Starting the browser…" instead of subscribing into a
|
|
317
|
+
* refusal. A cold start on a fresh guest takes 25–30 s. A daemon announcing
|
|
318
|
+
* this states the ABSENCE of `starting` too: a browser surface without it
|
|
319
|
+
* is not starting. Without the announcement a client cannot tell, and falls
|
|
320
|
+
* back to reading a surface it saw open moments ago as starting.
|
|
321
|
+
*/
|
|
322
|
+
readonly browserStarting: "computer_browser_starting_v1";
|
|
323
|
+
/**
|
|
324
|
+
* An agent actor on the machine's activity and control leases (OSK-13827)
|
|
325
|
+
* names the REAL agent: `agentId` is the agent's own id for tool-call and
|
|
326
|
+
* browser sessions too (v1 daemons put the SESSION id there for tool calls,
|
|
327
|
+
* so no reader could ever name them), and may carry `engine`, the harness
|
|
328
|
+
* the session runs on, so one agent's sessions on different engines can be
|
|
329
|
+
* told apart. A daemon announcing this states what it sends; the server
|
|
330
|
+
* withholds `engine` from every other daemon's actors, and a reader treats
|
|
331
|
+
* an actor without it as it always did.
|
|
332
|
+
*/
|
|
333
|
+
readonly activityActorV2: "computer_activity_actor_v2";
|
|
266
334
|
};
|
|
267
335
|
export type ComputerCapabilityKey = keyof typeof COMPUTER_CAPABILITIES;
|
|
268
336
|
export type ComputerCapability = (typeof COMPUTER_CAPABILITIES)[ComputerCapabilityKey];
|
|
@@ -271,14 +339,13 @@ export declare const COMPUTER_CAPABILITY_VALUES: [ComputerCapability, ...Compute
|
|
|
271
339
|
* Every refusal and limit the computer protocol can answer with. Callers branch
|
|
272
340
|
* on the code; a message beside it is free text and may change.
|
|
273
341
|
*/
|
|
274
|
-
export declare const COMPUTER_REFUSAL_CODES: readonly ["human_control", "stale_epoch", "stale_generation", "file_changed", "capability_missing", "unauthorized", "control_denied", "not_holder", "attachment_limit", "observer_limit", "watch_limit", "grant_limit", "browser_limit", "rate_limited", "not_found", "surface_ended", "machine_unavailable", "daemon_unreachable", "timeout", "invalid_request", "consent_missing", "path_withheld", "too_large", "service_limit"];
|
|
342
|
+
export declare const COMPUTER_REFUSAL_CODES: readonly ["human_control", "stale_epoch", "stale_generation", "file_changed", "capability_missing", "unauthorized", "control_denied", "not_holder", "attachment_limit", "observer_limit", "watch_limit", "grant_limit", "browser_limit", "rate_limited", "not_found", "surface_ended", "machine_unavailable", "daemon_unreachable", "relay_error", "timeout", "invalid_request", "consent_missing", "path_withheld", "too_large", "service_limit"];
|
|
275
343
|
export type ComputerRefusalCode = (typeof COMPUTER_REFUSAL_CODES)[number];
|
|
276
344
|
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
345
|
+
* The code when it is a computer refusal, else `null`. There is one spelling
|
|
346
|
+
* per code: the browser's older spelling of `human_control` was accepted for
|
|
347
|
+
* one release and retired with the old browser events (§5.2, OSK-13509).
|
|
279
348
|
*/
|
|
280
|
-
export declare const COMPUTER_LEGACY_REFUSAL_SPELLINGS: Readonly<Record<string, ComputerRefusalCode>>;
|
|
281
|
-
/** The canonical code for a received spelling, or `null` when it is not a computer refusal. */
|
|
282
349
|
export declare function normalizeComputerRefusalCode(code: unknown): ComputerRefusalCode | null;
|
|
283
350
|
export declare const COMPUTER_ACTOR_KINDS: readonly ["agent", "human"];
|
|
284
351
|
export type ComputerActorKind = (typeof COMPUTER_ACTOR_KINDS)[number];
|
|
@@ -291,13 +358,36 @@ export type ComputerActorKind = (typeof COMPUTER_ACTOR_KINDS)[number];
|
|
|
291
358
|
*/
|
|
292
359
|
export declare const COMPUTER_ACTIVITY_ACTOR_KINDS: readonly ["agent", "human", "system"];
|
|
293
360
|
export type ComputerActivityActorKind = (typeof COMPUTER_ACTIVITY_ACTOR_KINDS)[number];
|
|
361
|
+
/**
|
|
362
|
+
* The session ids the PLATFORM's own routes run daemon tools under — the web
|
|
363
|
+
* Files surface (`computer-files:` on a personal machine, `dedicated-runtime:`
|
|
364
|
+
* on a Dedicated Runtime) and the owner's `skrr machines dedicated` commands.
|
|
365
|
+
* No agent and no model is behind such a session: the person who asked is
|
|
366
|
+
* known to the API (which audits it), not to the daemon. So an activity event
|
|
367
|
+
* produced under one names no agent (OSK-13790: a person's upload used to read
|
|
368
|
+
* "agent created …"). Built by `ComputerFileService.runPersonalMachineTool`
|
|
369
|
+
* and `DedicatedRuntimeMachineAccess.runDedicatedRuntimeTool`.
|
|
370
|
+
*/
|
|
371
|
+
export declare const COMPUTER_PLATFORM_ROUTE_SESSION_PREFIXES: readonly ["dedicated-runtime:", "computer-files:"];
|
|
372
|
+
/** Whether a tool call's session is one of the platform's own routes, not an agent's. */
|
|
373
|
+
export declare function isComputerPlatformRouteSession(sessionId: unknown): boolean;
|
|
294
374
|
/** An agent session, as the wire names it. Same session = same `agentId` AND `sessionId`. */
|
|
295
375
|
export interface ComputerWireAgentActor {
|
|
296
376
|
kind: 'agent';
|
|
297
377
|
agentId: string;
|
|
298
378
|
sessionId: string;
|
|
299
379
|
label: string;
|
|
380
|
+
/**
|
|
381
|
+
* The engine the session runs on (`claude-code`, `codex`, …), as the daemon
|
|
382
|
+
* names its backend. Present only from a daemon that announced
|
|
383
|
+
* `computer_activity_actor_v2` (`COMPUTER_CAPABILITIES.activityActorV2`).
|
|
384
|
+
* A display distinction between one agent's sessions, never an identity:
|
|
385
|
+
* `sameComputerActor` still compares the agent id and the session id.
|
|
386
|
+
*/
|
|
387
|
+
engine?: string;
|
|
300
388
|
}
|
|
389
|
+
/** The longest `engine` the wire carries; a longer one is not an engine name. */
|
|
390
|
+
export declare const COMPUTER_ACTOR_ENGINE_MAX_LENGTH = 64;
|
|
301
391
|
export interface ComputerWireHumanActor {
|
|
302
392
|
kind: 'human';
|
|
303
393
|
userId: string;
|
|
@@ -420,7 +510,11 @@ export type ComputerSurfaceState = (typeof COMPUTER_SURFACE_STATES)[number];
|
|
|
420
510
|
*/
|
|
421
511
|
export declare const COMPUTER_SURFACE_END_REASONS: readonly ["machine_stopped", "closed_by_owner", "closed", "process_exited", "daemon_restarted", "browser_crashed", "expired", "browser_reset"];
|
|
422
512
|
export type ComputerSurfaceEndReason = (typeof COMPUTER_SURFACE_END_REASONS)[number];
|
|
423
|
-
/**
|
|
513
|
+
/**
|
|
514
|
+
* The browser's logical viewport whoever is looking (§6.2): what the agent
|
|
515
|
+
* always works at. A person holding control may size the page to their window
|
|
516
|
+
* (`computer_browser_viewport_v1`); handing back restores this.
|
|
517
|
+
*/
|
|
424
518
|
export declare const COMPUTER_BROWSER_VIEWPORT: Readonly<{
|
|
425
519
|
width: 1280;
|
|
426
520
|
height: 800;
|
|
@@ -492,8 +586,41 @@ export interface ComputerTerminalInfo {
|
|
|
492
586
|
};
|
|
493
587
|
caveats?: ComputerTerminalCaveat[];
|
|
494
588
|
}
|
|
495
|
-
/**
|
|
496
|
-
|
|
589
|
+
/**
|
|
590
|
+
* Input a browser surface takes. `tab` needs `computer_browser_tabs_v1`;
|
|
591
|
+
* `viewport` needs `computer_browser_viewport_v1`.
|
|
592
|
+
*/
|
|
593
|
+
export declare const COMPUTER_BROWSER_INPUT_TYPES: readonly ["pointer", "key", "text", "navigate", "history", "tab", "viewport"];
|
|
594
|
+
/**
|
|
595
|
+
* What a `viewport` input may ask of the page (OSK-13808), in CSS pixels: the
|
|
596
|
+
* controlling window's content box, bounded so no window can make the page
|
|
597
|
+
* absurd for the agent that gets it back, and aspect-clamped (`minAspect` and
|
|
598
|
+
* `maxAspect` are width ÷ height) so a sliver of a window cannot either.
|
|
599
|
+
* Device pixel ratio is not part of it: the page keeps the browser's own, so a
|
|
600
|
+
* high-density screen changes no layout and no picture size.
|
|
601
|
+
*/
|
|
602
|
+
export declare const COMPUTER_BROWSER_VIEWPORT_LIMITS: Readonly<{
|
|
603
|
+
minWidth: 320;
|
|
604
|
+
maxWidth: 2560;
|
|
605
|
+
minHeight: 240;
|
|
606
|
+
maxHeight: 1600;
|
|
607
|
+
minAspect: 0.4;
|
|
608
|
+
maxAspect: 3.2;
|
|
609
|
+
}>;
|
|
610
|
+
/**
|
|
611
|
+
* The size a `viewport` input asks for, made legal: whole CSS pixels inside
|
|
612
|
+
* `COMPUTER_BROWSER_VIEWPORT_LIMITS`, its aspect inside the clamp. Total and
|
|
613
|
+
* idempotent: the window sends what this returns and the daemon applies what
|
|
614
|
+
* this returns, so both ends agree on the page a size produces. Null for a size
|
|
615
|
+
* with no area (a hidden or collapsed window asks for nothing).
|
|
616
|
+
*/
|
|
617
|
+
export declare function clampComputerBrowserViewport(size: {
|
|
618
|
+
width: number;
|
|
619
|
+
height: number;
|
|
620
|
+
}): {
|
|
621
|
+
width: number;
|
|
622
|
+
height: number;
|
|
623
|
+
} | null;
|
|
497
624
|
/**
|
|
498
625
|
* The client OS a browser `key` input comes from. A person's shortcuts are
|
|
499
626
|
* mapped onto the Linux page's by the daemon: on `mac`, Command is Control,
|