@platless/axom-cli 0.5.9 → 0.6.52
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/README.md +25 -6
- package/dist/axom-patch/cli/README.md +129 -12
- package/dist/axom-patch/cli/account-limits/generate.py +15 -12
- package/dist/axom-patch/cli/account-limits/kimi-proxy.mjs +20 -3
- package/dist/axom-patch/cli/claude-account-limits.json +9 -9
- package/dist/axom-patch/cli/claude-replay-lifecycle.json +16 -0
- package/dist/axom-patch/cli/codex-account-limits.json +11 -11
- package/dist/axom-patch/cli/codex-terminal-output.json +16 -0
- package/dist/axom-patch/cli/commandcode-account-limits.json +9 -9
- package/dist/axom-patch/cli/kimi-quota.mjs +12 -0
- package/dist/axom-patch/cli/kimi-subagents.mjs +173 -0
- package/dist/axom-patch/cli/nightly-task.md +55 -13
- package/dist/axom-patch/cli/probes/claude-replay-lifecycle.mjs +31 -0
- package/dist/axom-patch/cli/probes/codex-terminal-output.mjs +33 -0
- package/dist/axom-patch/cli/probes/kimi-subagent-subwork.mjs +82 -0
- package/dist/axom-patch/cli/probes/zcode-env-account.mjs +81 -0
- package/dist/axom-patch/cli/probes/zcode-subagent-subwork.mjs +7 -0
- package/dist/axom-patch/cli/qoder/dist/axom-acp-compat.mjs +1687 -0
- package/dist/axom-patch/cli/qoder/releases/1.1.75.json +277 -0
- package/dist/axom-patch/cli/qoder-background-terminal.md +13 -6
- package/dist/axom-patch/cli/qoder-foreground-output.md +14 -8
- package/dist/axom-patch/cli/qoder-native-acp.json +227 -0
- package/dist/axom-patch/cli/qoder-steering.md +20 -25
- package/dist/axom-patch/cli/qoder-subagent-subwork.md +17 -68
- package/dist/axom-patch/cli/runtime.json +19 -19
- package/dist/axom-patch/cli/zcode/env-account.mjs +13 -0
- package/dist/axom-patch/cli/zcode/generate-env-account.py +52 -0
- package/dist/axom-patch/cli/zcode-account-limits.json +10 -11
- package/dist/axom-patch/cli/zcode-env-account.json +58 -0
- package/dist/axom-patch/cli/zcode-models.json +9 -10
- package/dist/axom-patch/cli/zcode-subagent-subwork.json +10 -11
- package/dist/cli.js +11 -45
- package/dist/commands/auth.js +4 -1
- package/dist/commands/knowledge.js +47 -0
- package/dist/commands/update.js +126 -3
- package/dist/commands/workstation.js +101 -164
- package/dist/commands/workstationRegistrations.js +116 -0
- package/dist/credentialBroker.js +13 -2
- package/dist/credentials.js +16 -0
- package/dist/install/claude/commands.js +15 -15
- package/dist/keepers/terminal/keeper.mjs +1089 -673
- package/dist/keepers/terminal/manifest.json +4 -4
- package/dist/mcp.js +1 -1
- package/dist/native/darwin-x64/axom-quic +0 -0
- package/dist/workstation/acp/acpAgents.js +113 -102
- package/dist/workstation/acp/acpClient.js +26 -0
- package/dist/workstation/acp/builds/install/npm.js +99 -10
- package/dist/workstation/acp/initializeResponse.js +6 -1
- package/dist/workstation/acp/managedPatches.js +189 -25
- package/dist/workstation/acp/managedRuntime.js +314 -0
- package/dist/workstation/acp/outbox.js +12 -5
- package/dist/workstation/acp/patchAssets.js +40 -0
- package/dist/workstation/acp/permission.js +2 -2
- package/dist/workstation/acp/processor/checkpoint.js +26 -34
- package/dist/workstation/acp/processor/control.js +7 -80
- package/dist/workstation/acp/processor/jsonrpc.js +8 -0
- package/dist/workstation/acp/processor/runtime.js +5 -81
- package/dist/workstation/acp/processor/session.js +54 -82
- package/dist/workstation/acp/processor/state.js +7 -13
- package/dist/workstation/acp/processor/step.js +3 -20
- package/dist/workstation/acp/processor/test/fixtureLog.js +9 -16
- package/dist/workstation/acp/processor/transport/local.js +19 -3
- package/dist/workstation/acp/processor/updates.js +156 -105
- package/dist/workstation/acp/processorSession.js +20 -173
- package/dist/workstation/acp/registry/catalog.js +65 -39
- package/dist/workstation/acp/registry/launch.js +16 -1
- package/dist/workstation/acp/switching.js +0 -3
- package/dist/workstation/acp/test/fakeAgent.js +13 -0
- package/dist/workstation/acp/test/keeperWorld.js +32 -3
- package/dist/workstation/acp/test/raw/sources.js +16 -130
- package/dist/workstation/acp/test/realAdapter.js +1 -47
- package/dist/workstation/acp/test/scriptAgent.js +11 -3
- package/dist/workstation/agentFlow.js +1 -1
- package/dist/workstation/agentSessions.js +114 -166
- package/dist/workstation/channels/agent.js +9 -1
- package/dist/workstation/channels/computer.js +27 -4
- package/dist/workstation/channels/management.js +130 -15
- package/dist/workstation/channels/url.js +1 -1
- package/dist/workstation/config.js +33 -9
- package/dist/workstation/connection/encryptedChannel.js +4 -1
- package/dist/workstation/control/bindingStore.js +204 -0
- package/dist/workstation/control/commands.js +125 -0
- package/dist/workstation/control/daemonIdentity.js +143 -0
- package/dist/workstation/control/deviceCommands.js +191 -0
- package/dist/workstation/control/deviceProtocol.js +68 -0
- package/dist/workstation/control/enrollment.js +106 -0
- package/dist/workstation/control/inspect.js +71 -0
- package/dist/workstation/control/locks.js +110 -0
- package/dist/workstation/control/protocol.js +40 -0
- package/dist/workstation/control/restartGuard.js +46 -0
- package/dist/workstation/control/rootFormat.js +16 -0
- package/dist/workstation/control/runtimeClient.js +152 -0
- package/dist/workstation/control/runtimeHost.js +235 -0
- package/dist/workstation/control/serverIdentity.js +35 -0
- package/dist/workstation/control/updateTransition.js +91 -0
- package/dist/workstation/daemon.js +266 -264
- package/dist/workstation/daemonctl.js +226 -25
- package/dist/workstation/desktopControl/audio.js +99 -0
- package/dist/workstation/desktopControl/automationDevice.js +219 -0
- package/dist/workstation/desktopControl/automationJson.js +74 -0
- package/dist/workstation/desktopControl/automationLocalState.js +23 -0
- package/dist/workstation/desktopControl/automationProtocol.js +253 -0
- package/dist/workstation/desktopControl/automationSchema.generated.js +1 -0
- package/dist/workstation/desktopControl/automationSession.js +81 -0
- package/dist/workstation/desktopControl/automationTransport.js +138 -0
- package/dist/workstation/desktopControl/capabilities.js +93 -0
- package/dist/workstation/desktopControl/captureModes.js +9 -0
- package/dist/workstation/desktopControl/captureTargetLabel.js +9 -0
- package/dist/workstation/desktopControl/deviceAdmission.js +229 -0
- package/dist/workstation/desktopControl/deviceOwnership.js +130 -0
- package/dist/workstation/desktopControl/deviceSockets.js +246 -0
- package/dist/workstation/desktopControl/helperProcess.js +602 -0
- package/dist/workstation/desktopControl/hostGrant.js +65 -0
- package/dist/workstation/desktopControl/lobby.js +131 -0
- package/dist/workstation/desktopControl/macProvider.js +156 -0
- package/dist/workstation/desktopControl/media.js +331 -0
- package/dist/workstation/desktopControl/nativeDeviceAdmission.js +207 -0
- package/dist/workstation/desktopControl/nativeProvider.js +1044 -0
- package/dist/workstation/desktopControl/networkEvidence.js +43 -0
- package/dist/workstation/desktopControl/overview.js +58 -0
- package/dist/workstation/desktopControl/ownershipProtocol.js +31 -0
- package/dist/workstation/desktopControl/protocol.js +311 -0
- package/dist/workstation/desktopControl/provider.js +1 -0
- package/dist/workstation/desktopControl/quicMedia.js +240 -0
- package/dist/workstation/desktopControl/rateController.js +226 -0
- package/dist/workstation/desktopControl/supervisor.js +1774 -0
- package/dist/workstation/desktopControl/transport.js +27 -0
- package/dist/workstation/desktopControl/wallpaper.js +98 -0
- package/dist/workstation/exec/policy.js +5 -0
- package/dist/workstation/files/client.js +10 -1
- package/dist/workstation/files/credentials.js +142 -0
- package/dist/workstation/files/host.js +9 -2
- package/dist/workstation/files/text.js +42 -8
- package/dist/workstation/journal.js +5 -2
- package/dist/workstation/keepers/acp/client.js +38 -2
- package/dist/workstation/keepers/kit/buildVersion.js +35 -11
- package/dist/workstation/keepers/kit/bundle.js +21 -17
- package/dist/workstation/keepers/kit/client.js +2 -2
- package/dist/workstation/keepers/kit/launcher.js +123 -7
- package/dist/workstation/keepers/kit/paths.js +2 -1
- package/dist/workstation/keepers/legacy.js +16 -2
- package/dist/workstation/keepers/policy.js +5 -34
- package/dist/workstation/keepers/terminal/client.js +115 -23
- package/dist/workstation/keepers/terminal/exec.js +6 -3
- package/dist/workstation/keepers/terminal/frames.js +73 -0
- package/dist/workstation/keepers/terminal/generations.js +5 -8
- package/dist/workstation/keepers/terminal/gridProtocol.js +16 -0
- package/dist/workstation/keepers/terminal/input.js +146 -0
- package/dist/workstation/keepers/terminal/keeper.js +22 -8
- package/dist/workstation/keepers/terminal/main.js +1 -1
- package/dist/workstation/keepers/terminal/metadata.js +138 -0
- package/dist/workstation/keepers/terminal/protocol.js +4 -28
- package/dist/workstation/keepers/terminal/pty.js +1 -330
- package/dist/workstation/keepers/terminal/screen.js +246 -0
- package/dist/workstation/keepers/terminal/sessions.js +526 -0
- package/dist/workstation/managedInstall.js +57 -0
- package/dist/workstation/oauth/deviceAuthorization.js +31 -17
- package/dist/workstation/protocol/agent.js +2 -15
- package/dist/workstation/protocol/management.js +113 -5
- package/dist/workstation/protocol/runtimeDiagnostics.js +15 -0
- package/dist/workstation/rd/artifact.js +120 -0
- package/dist/workstation/rd/control.js +117 -0
- package/dist/workstation/rd/display.js +29 -0
- package/dist/workstation/rd/host.js +213 -0
- package/dist/workstation/rd/migrationReadiness.js +46 -0
- package/dist/workstation/rd/provider.js +256 -0
- package/dist/workstation/rd/sessions.js +391 -0
- package/dist/workstation/rd/state.js +57 -0
- package/dist/workstation/rd/update.js +168 -0
- package/dist/workstation/rd/upkeep.js +80 -0
- package/dist/workstation/register.js +27 -37
- package/dist/workstation/registrations/enrollment.js +250 -0
- package/dist/workstation/registrations/enrollmentPending.js +361 -0
- package/dist/workstation/registrations/migration.js +356 -0
- package/dist/workstation/registrations/model.js +34 -0
- package/dist/workstation/registrations/removal.js +222 -0
- package/dist/workstation/registrations/store.js +737 -0
- package/dist/workstation/runtime/desktopBinding.js +20 -0
- package/dist/workstation/runtime/deviceDesktop.js +193 -0
- package/dist/workstation/runtime/deviceRuntime.js +568 -0
- package/dist/workstation/runtime/deviceServices.js +117 -0
- package/dist/workstation/runtime/events.js +20 -0
- package/dist/workstation/runtime/ownership.js +100 -0
- package/dist/workstation/runtime/registrationRuntime.js +575 -0
- package/dist/workstation/runtime/remoteDesktopAdapter.js +186 -0
- package/dist/workstation/runtime/removalActivity.js +184 -0
- package/dist/workstation/service/installer.js +197 -14
- package/dist/workstation/service/launchd.js +2 -0
- package/dist/workstation/service/systemd.js +1 -0
- package/dist/workstation/storageMetrics.js +118 -0
- package/dist/workstation/systemMetrics.js +47 -92
- package/dist/workstation/toolchain.js +94 -0
- package/dist/workstation/tools/browser.js +28 -4
- package/dist/workstation/tools/client.js +8 -27
- package/dist/workstation/tools/info.js +6 -13
- package/dist/workstation/tools/terminalRouter.js +17 -172
- package/dist/workstation/tools/validation.js +55 -1
- package/dist/workstation/update/archiveEvidence.js +206 -0
- package/dist/workstation/update/artifact.js +2 -1
- package/dist/workstation/update/coordinator.js +34 -13
- package/dist/workstation/update/deviceCompatibility.js +119 -0
- package/dist/workstation/update/deviceCoordinator.js +369 -0
- package/dist/workstation/update/deviceHealth.js +104 -0
- package/dist/workstation/update/deviceHealthProtocol.js +26 -0
- package/dist/workstation/update/deviceRecoveryLifecycle.js +46 -0
- package/dist/workstation/update/deviceRollback.js +78 -0
- package/dist/workstation/update/globalInstall.js +186 -0
- package/dist/workstation/update/legacyBridge.js +414 -0
- package/dist/workstation/update/legacyOwner.js +39 -0
- package/dist/workstation/update/npmInstaller.js +51 -25
- package/dist/workstation/update/privateDurability.js +61 -0
- package/dist/workstation/update/rdRollback.js +145 -0
- package/dist/workstation/update/recoveryPlan.js +124 -0
- package/dist/workstation/update/runUpdate.js +10 -3
- package/dist/workstation/update/taskRegistry.js +161 -3
- package/dist/workstation/update/watchdog.js +29806 -333
- package/dist/workstation/update/watchdogProcess.js +72 -0
- package/package.json +11 -7
- package/skills/axom/SKILL.md +11 -11
- package/skills/axom-definition/SKILL.md +3 -3
- package/skills/axom-platform/SKILL.md +3 -3
- package/dist/axom-patch/cli/probes/qoder-steering.mjs +0 -89
- package/dist/axom-patch/cli/probes/qoder-subagent-origin.mjs +0 -61
- package/dist/axom-patch/cli/qoder-steering.json +0 -52
- package/dist/axom-patch/cli/qoder-subagent-origin.json +0 -73
- package/dist/commands/guide.js +0 -38
- package/dist/runtime-deps/qoder-sdk/package-lock.json +0 -1189
- package/dist/runtime-deps/qoder-sdk/package.json +0 -8
- package/dist/workstation/acp/delegationMcp.js +0 -24
- package/dist/workstation/acp/processor/sideChannel.js +0 -80
- package/dist/workstation/acp/qoderStartup.js +0 -45
- package/dist/workstation/acp/test/raw/qoderCaptures.js +0 -125
- package/dist/workstation/qoderAdapter/backgroundProcess.js +0 -118
- package/dist/workstation/qoderAdapter/backgroundTerminal.js +0 -193
- package/dist/workstation/qoderAdapter/backgroundTerminalFold.js +0 -372
- package/dist/workstation/qoderAdapter/callbackContext.js +0 -76
- package/dist/workstation/qoderAdapter/completedContinuation.js +0 -139
- package/dist/workstation/qoderAdapter/contract.js +0 -78
- package/dist/workstation/qoderAdapter/foregroundOutput.js +0 -36
- package/dist/workstation/qoderAdapter/history.js +0 -85
- package/dist/workstation/qoderAdapter/identityIndex.js +0 -191
- package/dist/workstation/qoderAdapter/inputQueue.js +0 -42
- package/dist/workstation/qoderAdapter/main.js +0 -95
- package/dist/workstation/qoderAdapter/mapper.js +0 -117
- package/dist/workstation/qoderAdapter/observerPlugin.js +0 -245
- package/dist/workstation/qoderAdapter/observerReceiver.js +0 -187
- package/dist/workstation/qoderAdapter/permissions.js +0 -61
- package/dist/workstation/qoderAdapter/profile.js +0 -93
- package/dist/workstation/qoderAdapter/sdkDriver.js +0 -48
- package/dist/workstation/qoderAdapter/sdkRuntime.js +0 -93
- package/dist/workstation/qoderAdapter/sdkRuntimeInstall.js +0 -145
- package/dist/workstation/qoderAdapter/session.js +0 -319
- package/dist/workstation/qoderAdapter/subagentMeta.js +0 -28
- package/dist/workstation/qoderAdapter/subwork.js +0 -85
- package/dist/workstation/qoderAdapter/taskControl.js +0 -38
- package/dist/workstation/qoderAdapter/taskLedger.js +0 -163
- package/dist/workstation/qoderAdapter/usage.js +0 -37
- /package/dist/workstation/{qoderAdapter/types.js → desktopControl/automationPreparation.js} +0 -0
|
@@ -1,34 +1,32 @@
|
|
|
1
|
+
import { claimDeviceDaemonIdentity } from './control/daemonIdentity.js';
|
|
2
|
+
import { openDeviceRuntimeHost } from './control/runtimeHost.js';
|
|
3
|
+
import { applyDeviceEnrollment, applyDeviceRemoval, inspectDeviceState } from './control/deviceCommands.js';
|
|
4
|
+
import { RegistrationRemovalController } from './registrations/removal.js';
|
|
5
|
+
import { LocalControlError } from './control/protocol.js';
|
|
6
|
+
import { DeviceRuntime } from './runtime/deviceRuntime.js';
|
|
7
|
+
import { createRegistrationRuntime } from './runtime/registrationRuntime.js';
|
|
8
|
+
import { createDeviceServices } from './runtime/deviceServices.js';
|
|
9
|
+
import { readLegacyRegistrationSources } from './registrations/migration.js';
|
|
1
10
|
import { promises as fs } from 'node:fs';
|
|
2
11
|
import os from 'node:os';
|
|
3
12
|
import path from 'node:path';
|
|
4
13
|
import { fileURLToPath } from 'node:url';
|
|
5
14
|
import { AGENT_WIRE_MIN_VERSION } from './protocol/agent.js';
|
|
6
|
-
import { clientDir,
|
|
7
|
-
import {
|
|
8
|
-
import { AcpAgents } from './acp/acpAgents.js';
|
|
9
|
-
import { ConnectionSupervisor } from './connection/supervisor.js';
|
|
10
|
-
import { ManagementChannel } from './channels/management.js';
|
|
11
|
-
import { ComputerChannel } from './channels/computer.js';
|
|
12
|
-
import { AgentChannel, dispatchAgentFrame as dispatchAgentChannelFrame } from './channels/agent.js';
|
|
13
|
-
import { TaskRegistry } from './update/taskRegistry.js';
|
|
15
|
+
import { clientDir, updateServiceContext } from './config.js';
|
|
16
|
+
import { dispatchAgentFrame as dispatchAgentChannelFrame } from './channels/agent.js';
|
|
14
17
|
import { createUpdateCoordinator } from './update/runUpdate.js';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import { KeeperTransport } from './acp/processor/transport/keeper.js';
|
|
28
|
-
import { keeperGenerations } from './acp/processor/transport/generations.js';
|
|
29
|
-
import { ExecPolicy } from './exec/policy.js';
|
|
30
|
-
import { LegacyToolsKeeper } from './keepers/legacy.js';
|
|
31
|
-
import { TerminalRouter, terminalEnv, terminalShell } from './tools/terminalRouter.js';
|
|
18
|
+
import { CLIENT_VERSION } from './version.js';
|
|
19
|
+
import { captureStartupPackageEvidence, deviceHealthExpectationSchema } from './update/deviceHealth.js';
|
|
20
|
+
import { readDeviceBootstrapRecovery } from './update/recoveryPlan.js';
|
|
21
|
+
import { readLegacyBridge, releaseLegacyBridge, prepareLegacyContainerBridge, recoverLegacyContainer, legacyBridgeUpdateSnapshot, resumeLegacyManagedBridge } from './update/legacyBridge.js';
|
|
22
|
+
import { prepareLegacyRdReadiness } from './rd/migrationReadiness.js';
|
|
23
|
+
import { createDeviceRecoveryTick } from './update/deviceRecoveryLifecycle.js';
|
|
24
|
+
import { UpdateStateStore } from './update/stateStore.js';
|
|
25
|
+
import { prepareDeviceRollbackHandoff } from './update/deviceRollback.js';
|
|
26
|
+
import { RdUpkeep } from './rd/upkeep.js';
|
|
27
|
+
import { adoptBundledRd, synchronizeRd } from './rd/update.js';
|
|
28
|
+
import { readRdState } from './rd/state.js';
|
|
29
|
+
import { resolveCliPath, serviceContext } from './daemonctl.js';
|
|
32
30
|
/**
|
|
33
31
|
* The path `runDaemon` hands `createUpdateCoordinator` as `cliPath`, used to re-provision the OS
|
|
34
32
|
* service after an update (see runUpdate.ts's `provisionService`).
|
|
@@ -234,8 +232,6 @@ export async function existingDirectories(roots) {
|
|
|
234
232
|
}
|
|
235
233
|
/** How often the daemon re-reads the workspaces config (and root existence) to restart the files host on a change. */
|
|
236
234
|
export const FILES_ROOTS_POLL_MS = 10_000;
|
|
237
|
-
/** How often the legacy tools keeper is re-probed and checked for retirement (keepers/legacy.ts). */
|
|
238
|
-
export const LEGACY_TICK_MS = 30_000;
|
|
239
235
|
/**
|
|
240
236
|
* Builds the object `ManagementChannelOptions.keepers` reports (Task 26): the policy's statuses, never a rejection (a failure is
|
|
241
237
|
* `null`, which the channel also guarantees). `countedExecs` (final review minor 7): keeper-terminal execs `activeShellTasks` also
|
|
@@ -250,7 +246,7 @@ export async function buildKeeperStatuses(policy, countedExecs = () => 0) {
|
|
|
250
246
|
catch {
|
|
251
247
|
return null;
|
|
252
248
|
}
|
|
253
|
-
const terminals = statuses.filter((status) => status.kind === 'terminal'
|
|
249
|
+
const terminals = statuses.filter((status) => status.kind === 'terminal');
|
|
254
250
|
const target = terminals.find((status) => status.replacement === 'none') ?? terminals[0];
|
|
255
251
|
if (!target)
|
|
256
252
|
return statuses;
|
|
@@ -281,248 +277,254 @@ export function startExclusivePoll(poll, intervalMs) {
|
|
|
281
277
|
return () => clearInterval(timer);
|
|
282
278
|
}
|
|
283
279
|
export async function runDaemon(options = {}) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
280
|
+
try {
|
|
281
|
+
await runDeviceDaemon(options);
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
const bridge = await readLegacyBridge(options.directory ?? clientDir());
|
|
285
|
+
if (bridge?.lifecycle !== 'container')
|
|
286
|
+
throw error;
|
|
287
|
+
console.error('[device] Container migration startup failed; restoring the verified predecessor', error instanceof Error ? error.message : String(error));
|
|
288
|
+
await recoverLegacyContainer(bridge);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
async function runDeviceDaemon(options) {
|
|
292
|
+
const directory = options.directory ?? clientDir();
|
|
293
|
+
const lifecycle = resolveServiceLifecycle(options);
|
|
294
|
+
if (lifecycle === 'container')
|
|
295
|
+
await prepareLegacyContainerBridge(directory, { ...serviceContext(), configDir: directory });
|
|
296
|
+
const packageRoot = updateServiceContext(directory).packageRoot;
|
|
297
|
+
const startupPackage = await captureStartupPackageEvidence(packageRoot, CLIENT_VERSION);
|
|
298
|
+
const legacyBridge = await readLegacyBridge(directory, startupPackage);
|
|
299
|
+
if (legacyBridge?.lifecycle === 'managed')
|
|
300
|
+
await resumeLegacyManagedBridge(directory, startupPackage);
|
|
301
|
+
let legacyStartupHeld = !!legacyBridge;
|
|
302
|
+
if (options.desktopProvider || options.onDesktopCommand)
|
|
303
|
+
throw new LocalControlError('UNSUPPORTED_PROTOCOL', 'Device remote desktop integration is unavailable until the physical isolation contract is integrated');
|
|
304
|
+
const shutdown = new AbortController();
|
|
305
|
+
const services = options.deviceServices ?? createDeviceServices({ root: directory });
|
|
306
|
+
const previousUpdateSnapshot = services.updates.snapshot.bind(services.updates);
|
|
307
|
+
services.updates.snapshot = async (registrationId) => await legacyBridgeUpdateSnapshot(directory) ?? previousUpdateSnapshot(registrationId);
|
|
308
|
+
let device;
|
|
309
|
+
let removal;
|
|
310
|
+
let generation = '';
|
|
311
|
+
let fullyInitialized = false;
|
|
312
|
+
let recoveryLease;
|
|
313
|
+
let rollbackLease;
|
|
314
|
+
let rollbackPreparation;
|
|
315
|
+
let rollbackBinding;
|
|
316
|
+
let rdUpkeep;
|
|
317
|
+
let stopRdPoll = () => { };
|
|
318
|
+
const mode = options.supervisedByServiceManager ? 'launchd' : 'foreground';
|
|
319
|
+
const snapshot = async () => ({ ...await inspectDeviceState({ store, device, generation, mode }), desktop: services.desktopFacts?.() });
|
|
320
|
+
let store;
|
|
321
|
+
let initialized;
|
|
322
|
+
let initializationFailed;
|
|
323
|
+
const initialization = new Promise((resolve, reject) => { initialized = resolve; initializationFailed = reject; });
|
|
324
|
+
void initialization.catch(() => { });
|
|
325
|
+
let preparing;
|
|
326
|
+
let preparedMode;
|
|
327
|
+
const prepareStop = (stopMode) => {
|
|
328
|
+
if (preparedMode)
|
|
329
|
+
return preparedMode === 'terminate' || preparedMode === stopMode ? Promise.resolve() : Promise.reject(new LocalControlError('OUTCOME_UNKNOWN', 'Detached work requires verified termination before the device can be stopped'));
|
|
330
|
+
if (preparing)
|
|
331
|
+
return preparing.then(() => prepareStop(stopMode));
|
|
332
|
+
const retiring = device?.stop(stopMode);
|
|
333
|
+
void retiring?.catch(() => { });
|
|
334
|
+
preparing = (async () => {
|
|
335
|
+
await initialization;
|
|
336
|
+
if (retiring)
|
|
337
|
+
await retiring;
|
|
338
|
+
else
|
|
339
|
+
await device?.stop(stopMode);
|
|
340
|
+
preparedMode = stopMode;
|
|
341
|
+
})().catch(error => { preparing = undefined; throw error; });
|
|
342
|
+
return preparing;
|
|
343
|
+
};
|
|
344
|
+
let stopping;
|
|
345
|
+
const stop = (stopMode) => {
|
|
346
|
+
fullyInitialized = false;
|
|
347
|
+
stopping ??= (async () => {
|
|
348
|
+
stopRdPoll();
|
|
349
|
+
await rdUpkeep?.stop();
|
|
350
|
+
await prepareStop(stopMode);
|
|
351
|
+
await services.stop();
|
|
352
|
+
shutdown.abort();
|
|
353
|
+
})().catch(error => { stopping = undefined; throw error; });
|
|
354
|
+
return stopping;
|
|
355
|
+
};
|
|
356
|
+
const host = await claimDeviceDaemonIdentity(directory, async (identity) => {
|
|
357
|
+
store = identity.store;
|
|
358
|
+
return openDeviceRuntimeHost({ directory, mode, snapshot,
|
|
359
|
+
shutdown: stop,
|
|
360
|
+
prepareShutdown: prepareStop,
|
|
361
|
+
addRegistration: async (request) => {
|
|
362
|
+
if (!fullyInitialized || !device || preparing || stopping)
|
|
363
|
+
throw new LocalControlError('BUSY', 'Device lifecycle transition is in progress');
|
|
364
|
+
const finishMutation = device.beginMembershipMutation();
|
|
365
|
+
let result;
|
|
366
|
+
try {
|
|
367
|
+
result = await applyDeviceEnrollment(request, directory, snapshot, () => device.assertMutationAllowed());
|
|
368
|
+
}
|
|
369
|
+
finally {
|
|
370
|
+
finishMutation();
|
|
371
|
+
}
|
|
372
|
+
await device.reconcile();
|
|
373
|
+
return result;
|
|
374
|
+
},
|
|
375
|
+
removeRegistration: async (request) => {
|
|
376
|
+
if (!fullyInitialized || !removal || preparing || stopping)
|
|
377
|
+
throw new LocalControlError('BUSY', 'Device lifecycle transition is in progress');
|
|
378
|
+
return applyDeviceRemoval(request, { controller: removal, snapshot });
|
|
379
|
+
},
|
|
380
|
+
reconcile: async () => { if (!fullyInitialized || !device)
|
|
381
|
+
throw new LocalControlError('BUSY', 'Device initialization is in progress'); await device.reconcile(); },
|
|
382
|
+
update: async (release, operationId, source) => { if (!fullyInitialized)
|
|
383
|
+
throw new LocalControlError('BUSY', 'Device initialization is in progress'); return services.updates.local(operationId, release, source); },
|
|
384
|
+
updateHealth: (request, currentGeneration) => services.updates.health(request, currentGeneration),
|
|
385
|
+
prepareUpdateRollback: async (request, currentGeneration) => {
|
|
386
|
+
if (!fullyInitialized || !device)
|
|
387
|
+
throw new LocalControlError('OUTCOME_UNKNOWN', 'Original target initialization is incomplete');
|
|
388
|
+
const binding = JSON.stringify(deviceHealthExpectationSchema.parse(request));
|
|
389
|
+
if (rollbackBinding && rollbackBinding !== binding)
|
|
390
|
+
throw new LocalControlError('BINDING_CONFLICT', 'Original rollback preparation request changed');
|
|
391
|
+
rollbackBinding = binding;
|
|
392
|
+
rollbackPreparation ??= prepareDeviceRollbackHandoff({ root: directory, generation: currentGeneration, startup: startupPackage,
|
|
393
|
+
lease: () => { rollbackLease ??= recoveryLease ?? device.acquireMaintenance({ transactionId: request.transactionId }); return rollbackLease; },
|
|
394
|
+
}, request).catch(error => { rollbackPreparation = undefined; throw error; });
|
|
395
|
+
return rollbackPreparation;
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
}, startupPackage);
|
|
399
|
+
generation = host.generation;
|
|
400
|
+
let stopPoll = () => { };
|
|
401
|
+
const signalStop = () => { void stop('detach').catch(error => console.error('[device] shutdown needs verification', error)); };
|
|
402
|
+
const rejection = (reason) => console.error('[device] unhandled rejection', reason instanceof Error ? reason.message : 'unknown');
|
|
403
|
+
process.on('unhandledRejection', rejection);
|
|
404
|
+
process.once('SIGINT', signalStop);
|
|
405
|
+
process.once('SIGTERM', signalStop);
|
|
406
|
+
try {
|
|
407
|
+
let bootstrap;
|
|
355
408
|
try {
|
|
356
|
-
|
|
357
|
-
const current = await existingDirectories(roots);
|
|
358
|
-
if (JSON.stringify(current) !== JSON.stringify(hostRoots))
|
|
359
|
-
filesHost.reconfigure();
|
|
409
|
+
bootstrap = await readDeviceBootstrapRecovery(directory, startupPackage);
|
|
360
410
|
}
|
|
361
|
-
catch {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
const drainKeeper = oneShotDrain((kind, gen) => (kind === 'acp' ? acpLauncher : terminalLauncher).pathsFor(kind, gen));
|
|
401
|
-
const keeperPolicy = new KeeperPolicy({
|
|
402
|
-
dir: path.join(dir, 'keepers'),
|
|
403
|
-
probe: oneShotProbe((kind, gen) => (kind === 'acp' ? acpLauncher : terminalLauncher).pathsFor(kind, gen)),
|
|
404
|
-
terminal: {
|
|
405
|
-
currentGen: () => terminalKeepers.currentGen(),
|
|
406
|
-
live: async () => (await terminalKeepers.running()).map((generation) => generation.gen),
|
|
407
|
-
manifest: () => terminalKeepers.manifest(),
|
|
408
|
-
stop: async (gen, mode) => {
|
|
409
|
-
const result = await terminalLauncher.stop('terminal', gen, mode);
|
|
410
|
-
if (result.stopped)
|
|
411
|
-
terminalKeepers.forget(gen);
|
|
412
|
-
return result;
|
|
411
|
+
catch (error) {
|
|
412
|
+
if (error.code !== 'ENOENT')
|
|
413
|
+
throw error;
|
|
414
|
+
}
|
|
415
|
+
if (legacyBridge && process.platform === 'linux') {
|
|
416
|
+
try {
|
|
417
|
+
const readiness = await prepareLegacyRdReadiness(directory);
|
|
418
|
+
if (readiness.kind === 'unavailable')
|
|
419
|
+
console.warn(`[rd] ${readiness.reason}`);
|
|
420
|
+
else if (readiness.kind === 'staged')
|
|
421
|
+
console.warn('[rd] Compatible desktop runtime staged; activation is deferred until the original desktop authority is retired and physically accepted.');
|
|
422
|
+
}
|
|
423
|
+
catch (error) {
|
|
424
|
+
console.warn('[rd] Legacy desktop configuration remains unavailable', error instanceof Error ? error.message : String(error));
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
await services.start();
|
|
428
|
+
device = new DeviceRuntime({ store, desktopActivity: () => services.desktopActivity?.() ?? { known: false, consumers: 1 }, factory: async (identity) => createRegistrationRuntime({ ...identity,
|
|
429
|
+
registrationRoot: store.root,
|
|
430
|
+
startupHeld: legacyStartupHeld || !!bootstrap && (bootstrap.transaction.phase === 'RESTARTING' || !!bootstrap.transaction.installedRollback && !!bootstrap.transaction.recoveryRequired),
|
|
431
|
+
paths: { legacySources: await readLegacyRegistrationSources(directory, identity.registration.id) }, deviceServices: services,
|
|
432
|
+
}) });
|
|
433
|
+
services.updates.configure({ directory, device, generation, lifecycle, startupPackage, packageRoot, initialized: () => fullyInitialized,
|
|
434
|
+
execute: (command, context) => createUpdateCoordinator({ dir: directory, server: context.source, cliPath: daemonCliPath(), serviceLifecycle: lifecycle, deviceUpdate: context, restart: async () => { await stop('detach'); } }).handle(command),
|
|
435
|
+
completeRecovery: async (persist) => {
|
|
436
|
+
if (!recoveryLease) {
|
|
437
|
+
await persist();
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const original = recoveryLease;
|
|
441
|
+
await original.release(async () => {
|
|
442
|
+
const recovery = await readDeviceBootstrapRecovery(directory, startupPackage);
|
|
443
|
+
if (!recovery)
|
|
444
|
+
throw new LocalControlError('OUTCOME_UNKNOWN', 'Original device restart recovery evidence is missing');
|
|
445
|
+
await new UpdateStateStore(directory).save({ phase: 'SUCCEEDED', commandId: recovery.transaction.transactionId, version: recovery.transaction.release.version, releaseSha512: recovery.transaction.release.sha512, remoteForcePolicy: 'drain-only' });
|
|
446
|
+
await persist();
|
|
447
|
+
});
|
|
448
|
+
if (recoveryLease === original)
|
|
449
|
+
recoveryLease = undefined;
|
|
413
450
|
},
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
});
|
|
449
|
-
const metrics = new SystemMetricsSampler(cfg.workspaces ?? []);
|
|
450
|
-
await metrics.start();
|
|
451
|
-
const management = new ManagementChannel({
|
|
452
|
-
server: cfg.server, workstationId: cfg.workstationId, workstation: cfg.workstationId, clientKey, serverPub,
|
|
453
|
-
bridges: () => bridges,
|
|
454
|
-
workspaces: cfg.workspaces,
|
|
455
|
-
playgroundCwd,
|
|
456
|
-
metrics: () => metrics.snapshot(),
|
|
457
|
-
allowInsecureWs,
|
|
458
|
-
onReady: (ready) => updates.managementReady(ready.release, ready.generation),
|
|
459
|
-
onUpdate: (command) => updates.handle(command),
|
|
460
|
-
onExternalAgentsScan: async () => {
|
|
461
|
-
bridges = await scanRoster();
|
|
462
|
-
return bridges;
|
|
463
|
-
},
|
|
464
|
-
snapshot: () => buildManagementSnapshot(supervisor, tasks, updates),
|
|
465
|
-
keepers: () => buildKeeperStatuses(keeperPolicy, () => tasks.countedKeeperExecs),
|
|
466
|
-
onKeeperControl: (frame) => keeperPolicy.control(frame),
|
|
467
|
-
});
|
|
468
|
-
const agent = new AgentChannel({ server: cfg.server, agents, bridges: () => bridges, allowInsecureWs });
|
|
469
|
-
// Spec §6.2: first take over what an older CLI left (`_npx` copies, pre-build binary dirs) so agents
|
|
470
|
-
// that worked keep working; then §6.1: a version this CLI certifies (runtime.json/catalog pin) or a
|
|
471
|
-
// changed patch set moves an installed agent's current build forward by itself ("Updated by Axom").
|
|
472
|
-
// In the background: either may copy or download, an open of an agent not done yet waits on that
|
|
473
|
-
// agent's lock, and running sessions keep the build they were spawned from either way. A changed
|
|
474
|
-
// roster reaches the server the way a scan's does; offline, the next hello carries it.
|
|
475
|
-
void maintainAdapterBuilds(acp, async () => {
|
|
476
|
-
bridges = await scanRoster();
|
|
477
|
-
management.pushRoster(bridges);
|
|
478
|
-
});
|
|
479
|
-
// A quota capability learned mid-flight (this process's first spawn of an agent) changes what the
|
|
480
|
-
// roster would say; push it the way a build change does. Coalesced: several agents flipping
|
|
481
|
-
// around one burst of opens share a single scan, and a flip during that scan queues one more.
|
|
482
|
-
let rosterPushQueued = false;
|
|
483
|
-
acp.onRosterChanged(() => {
|
|
484
|
-
if (rosterPushQueued)
|
|
451
|
+
});
|
|
452
|
+
removal = new RegistrationRemovalController({ store, device, generation });
|
|
453
|
+
const finishInitialization = device.beginMembershipMutation();
|
|
454
|
+
try {
|
|
455
|
+
await device.reconcile();
|
|
456
|
+
}
|
|
457
|
+
finally {
|
|
458
|
+
finishInitialization();
|
|
459
|
+
}
|
|
460
|
+
let legacyLease;
|
|
461
|
+
if (legacyBridge) {
|
|
462
|
+
legacyLease = device.acquireMaintenance({ transactionId: legacyBridge.commandId });
|
|
463
|
+
await legacyLease.ready;
|
|
464
|
+
}
|
|
465
|
+
if (bootstrap && (bootstrap.transaction.phase === 'RESTARTING' || bootstrap.transaction.installedRollback && bootstrap.transaction.recoveryRequired)) {
|
|
466
|
+
recoveryLease = device.acquireMaintenance({ transactionId: bootstrap.transaction.transactionId });
|
|
467
|
+
await recoveryLease.ready;
|
|
468
|
+
}
|
|
469
|
+
const rdSource = async () => (await readRdState(directory))?.artifactSource ?? services.rdSource?.();
|
|
470
|
+
let pinnedRdSource;
|
|
471
|
+
rdUpkeep = new RdUpkeep({ device,
|
|
472
|
+
adopt: async () => { pinnedRdSource = await rdSource(); if (pinnedRdSource)
|
|
473
|
+
await adoptBundledRd(directory, pinnedRdSource); },
|
|
474
|
+
synchronize: async () => pinnedRdSource ? synchronizeRd(directory, pinnedRdSource, { deferActivation: true }) : undefined,
|
|
475
|
+
whenIdle: async (operation) => { await operation(); return true; }, refresh: () => services.publishToolState?.(), log: message => console.warn(message),
|
|
476
|
+
});
|
|
477
|
+
const tickRd = async () => { if (process.platform === 'linux' && await rdSource())
|
|
478
|
+
await rdUpkeep.tick(); };
|
|
479
|
+
await tickRd();
|
|
480
|
+
fullyInitialized = true;
|
|
481
|
+
initialized();
|
|
482
|
+
if (stopping)
|
|
483
|
+
await stopping.catch(() => { });
|
|
484
|
+
if (shutdown.signal.aborted)
|
|
485
485
|
return;
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}).catch((error) => {
|
|
492
|
-
console.warn(`[acp-builds] roster push after capability change failed: ${String(error)}`);
|
|
486
|
+
stopRdPoll = startExclusivePoll(tickRd, 30_000);
|
|
487
|
+
const recoveryTick = createDeviceRecoveryTick({ root: directory, startup: startupPackage, generation, bootstrap, signal: shutdown.signal,
|
|
488
|
+
initialized: () => fullyInitialized, lease: () => recoveryLease,
|
|
489
|
+
released: original => { if (recoveryLease === original)
|
|
490
|
+
recoveryLease = undefined; }, reconcile: () => device.reconcile(),
|
|
493
491
|
});
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
try {
|
|
509
|
-
await supervisor.run(shutdown.signal);
|
|
492
|
+
stopPoll = startExclusivePoll(async () => {
|
|
493
|
+
if (legacyLease && await releaseLegacyBridge(directory, startupPackage, generation, complete => legacyLease.release(complete))) {
|
|
494
|
+
legacyLease = undefined;
|
|
495
|
+
legacyStartupHeld = false;
|
|
496
|
+
await device.reconcile();
|
|
497
|
+
}
|
|
498
|
+
await recoveryTick();
|
|
499
|
+
}, 2_000);
|
|
500
|
+
if (!shutdown.signal.aborted)
|
|
501
|
+
await new Promise(resolve => shutdown.signal.addEventListener('abort', () => resolve(), { once: true }));
|
|
502
|
+
}
|
|
503
|
+
catch (error) {
|
|
504
|
+
initializationFailed(error);
|
|
505
|
+
throw error;
|
|
510
506
|
}
|
|
511
507
|
finally {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
508
|
+
stopRdPoll();
|
|
509
|
+
stopPoll();
|
|
510
|
+
process.removeListener('SIGINT', signalStop);
|
|
511
|
+
process.removeListener('SIGTERM', signalStop);
|
|
512
|
+
process.removeListener('unhandledRejection', rejection);
|
|
513
|
+
try {
|
|
514
|
+
await rdUpkeep?.stop();
|
|
515
|
+
}
|
|
516
|
+
finally {
|
|
517
|
+
try {
|
|
518
|
+
await device?.stop('detach');
|
|
519
|
+
}
|
|
520
|
+
finally {
|
|
521
|
+
try {
|
|
522
|
+
await services.stop();
|
|
523
|
+
}
|
|
524
|
+
finally {
|
|
525
|
+
await host.close();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
527
529
|
}
|
|
528
530
|
}
|