@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,96 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* One live agent session driven by the deterministic ACP processor over a transport (Task 19, spec 2026-10-11 §5.3/§5.4/§5.7):
|
|
3
|
-
* the daemon side of keeper-acp — or of the local fallback, which is the same session mechanism in this process.
|
|
4
|
-
*
|
|
5
|
-
* ## The record loop
|
|
6
|
-
*
|
|
7
|
-
* The transport's raw stream (`subscribeRaw`) is the only input. For each record, in order:
|
|
8
|
-
* `step(record)` → every command it produced is executed through the transport (`executeDownCommandsVia`: idempotent by cause,
|
|
9
|
-
* refused unless its spawn runs now, prompt blocks filled from this daemon's memory, `secretRef`s substituted from this daemon's
|
|
10
|
-
* memory) → a prompt whose blocks are gone is failed with an `agent_prompt_failed` note → the record's frames go out.
|
|
11
|
-
* Everything the server or this daemon decides reaches the processor as a note or a write first (`agent_prompt`, `agent_answer`,
|
|
12
|
-
* `agent_interrupt`, …); nothing here changes processor state directly, and nothing here numbers a frame — the processor does —
|
|
13
|
-
* with the one exception the poison contract names (below).
|
|
14
|
-
*
|
|
15
|
-
* ## What leaves
|
|
16
|
-
*
|
|
17
|
-
* Frames the manager sends (`onFrames`), unchanged, with `src`. The ones meant for the daemon itself stay here:
|
|
18
|
-
* `processor.open_result` settles {@link openSession}; `processor.history_event`/`history_end` become the load's backfill
|
|
19
|
-
* (never journaled: a daemon that dies inside the window loads again); an `agent_steered` / `agent_config_option_set` whose
|
|
20
|
-
* request this object made settles that call (one with nobody waiting goes out as a frame).
|
|
21
|
-
*
|
|
22
|
-
* ## Secrets and blocks
|
|
23
|
-
*
|
|
24
|
-
* Prompt and steer blocks are held in memory under a `blocksRef` until their `down` is written; secrets (a delegation bearer)
|
|
25
|
-
* under a `secretRef`, for the life of the session. Notes carry only the refs (spec §13).
|
|
26
|
-
*
|
|
27
|
-
* ## Poison (interface-contracts, "中毒恢复契约")
|
|
28
|
-
*
|
|
29
|
-
* A step that throws poisons the processor. The session is degraded: every turn still open ends with a failed `agent_turn_done`
|
|
30
|
-
* this object numbers itself, after the processor's last seq; the adapter is terminated; `onDegraded` tells the manager, which
|
|
31
|
-
* retires the session so the next `agent_open` starts a new spawn (`session/load`). Never retried from a checkpoint: replay is
|
|
32
|
-
* deterministic and would poison again on the same record. A transport that fails under the loop (keeper gone, raw truncated) is
|
|
33
|
-
* handled the same way: Task 19 has no re-attach (Task 21).
|
|
34
|
-
*
|
|
35
|
-
* ## Qoder side files (17c)
|
|
36
|
-
*
|
|
37
|
-
* When the repair is on, a 1 s timer asks the processor's **current** `sideDemand` — only once the processor has folded every
|
|
38
|
-
* record this object appended — runs `BackgroundSideNotes.poll(demand)` and appends the notes it returns, in order. The reader
|
|
39
|
-
* stops when the demand is `undefined` (no repair any more).
|
|
40
|
-
*
|
|
41
|
-
* ## Outbox, backpressure, checkpoints (Task 20, spec §5.5/§5.6)
|
|
42
|
-
*
|
|
43
|
-
* The manager records every journaled frame in {@link outbox} (the transport's outbox stream) before it sends it; the listener
|
|
44
|
-
* {@link onFrames} registers returns that append, and the loop awaits it before folding the next record — so the outbox holding a
|
|
45
|
-
* frame with `src.o = o` proves record `o`'s commands are in raw, and a checkpoint at `o` never precedes `o`'s frames. Before each
|
|
46
|
-
* record the loop waits for {@link SessionOutbox.room}: a server that does not acknowledge stops the processor, and the backlog
|
|
47
|
-
* stays in the raw log.
|
|
48
|
-
*
|
|
49
|
-
* Checkpoints (`acp.commit{checkpoint, rawThrough}`, raw truncated to the checkpoint): at the end of every turn; within a turn
|
|
50
|
-
* every {@link CHECKPOINT_RAW_BYTES} of folded raw or {@link CHECKPOINT_INTERVAL_MS}; and on a `close('keep')` (graceful exit,
|
|
51
|
-
* detach). Never while `boundaries.sideChunk` holds a half-read Qoder fact or a load's history window is open — deferred to the
|
|
52
|
-
* next record where both are clear. Each carries `processorVersion` (`checkpointOf`).
|
|
53
|
-
*
|
|
54
|
-
* ## A session left under the same key
|
|
55
|
-
*
|
|
56
|
-
* An earlier life of this ref (a swept or degraded session, a previous daemon's, a local outbox) is reused, not released: the new
|
|
57
|
-
* spawn continues the same raw log and outbox. Its unacknowledged frames are read back into {@link outbox} (resent when the server
|
|
58
|
-
* reopens the ref) and the processor numbers after the highest seq the outbox ever held — `max(outbox.maxSeq, committedTail.seq,
|
|
59
|
-
* resumeFromSeq)` (§5.5). An earlier life whose adapter still runs is never stopped here: the daemon adopts it at start
|
|
60
|
-
* ({@link ProcessorSession.adopt}), and keeper-acp refuses a second spawn into a running session.
|
|
61
|
-
*
|
|
62
|
-
* ## Adoption (Task 21, spec §5.5)
|
|
63
|
-
*
|
|
64
|
-
* A keeper-acp session whose adapter outlived the daemon (restart, upgrade, crash) is adopted, not stopped:
|
|
65
|
-
* `acp.attach` → the head checkpoint is restored → raw `(checkpoint.offset, replayEnd]` is replayed **updating state only** —
|
|
66
|
-
* `replayEnd = max(outbox last.src.o, committedTail.src.o)`, everything whose frames were recorded — and the frames the replay
|
|
67
|
-
* produces are compared byte for byte with the outbox entries that survive (daemon-numbered ones, `src.i ≥ DAEMON_FRAME_INDEX`,
|
|
68
|
-
* skipped; differences are only counted when the checkpoint came from this very processor version) → the seq continues after
|
|
69
|
-
* `max(replayed seq, outbox.maxSeq, committedTail.seq)` → the unacknowledged outbox entries are resent on the server's reopen →
|
|
70
|
-
* the records after `replayEnd` are folded live (their commands are idempotent by cause). A session whose open never completed, or
|
|
71
|
-
* that cannot be rebuilt (no readable checkpoint and no spawn record left), is refused ({@link AdoptionRefusedError}); the caller
|
|
72
|
-
* stops its adapter and keeps its outbox. A checkpoint is cut right after the spawn and when the open completes, so every session
|
|
73
|
-
* has one that says whether it is open.
|
|
74
|
-
*
|
|
75
|
-
* ## Detach (Task 21, spec §5.5.5)
|
|
76
|
-
*
|
|
77
|
-
* {@link detach} ends this daemon's hold on a keeper-hosted session without touching the adapter: the loop stops after the
|
|
78
|
-
* record in hand, a head checkpoint is cut when the state is safe (never mid Qoder chunk or load history — then the next daemon
|
|
79
|
-
* replays), the subscription is dropped. No `session/cancel`, no answer to a pending card, no `turn_done(failed)`: a detaching
|
|
80
|
-
* session never degrades. The next daemon adopts it.
|
|
81
|
-
*
|
|
82
|
-
* ## Keeper connection loss (Task 21)
|
|
83
|
-
*
|
|
84
|
-
* keeper-acp unreachable under the loop (a request lost on a dropped connection, a stream that ended) is not a degradation: the
|
|
85
|
-
* session re-attaches — `acp.attach` (which relaunches the current generation's keeper-acp if it died; an older generation is
|
|
86
|
-
* only reconnected) and the same rebuild as an adoption, in place — with bounded retries. A note whose append failed is looked
|
|
87
|
-
* for in raw before it is appended again. Only a keeper that is gone with the session (not found, or unreachable after the
|
|
88
|
-
* retries) degrades it. When keeper-acp itself restarted, the session it recovered ends with `proc exit{reason:'keeper_lost'}`:
|
|
89
|
-
* that tail is folded (a real `turn_done` in it is delivered) and the session reports its adapter dead.
|
|
90
|
-
*/
|
|
1
|
+
/** Daemon-side keeper session: records notes before commands, awaits outbox persistence before advancing, and checkpoints only complete history boundaries. A poisoned processor degrades the session and ends pending turns; it never retries half-updated state. */
|
|
91
2
|
import { PROTOCOL_VERSION, RequestError } from '@agentclientprotocol/sdk';
|
|
92
3
|
import { ACCOUNT_LIMITS_READ_TIMEOUT_MS } from '../protocol/accountLimits.js';
|
|
93
|
-
import { BackgroundSideNotes, nativeTerminalHistoryPath } from '../qoderAdapter/backgroundTerminal.js';
|
|
94
4
|
import { AgentInitializeTimeoutError, AgentSpawnError, UnsupportedProtocolVersionError } from './acpClient.js';
|
|
95
5
|
import { executeDownCommandsVia } from './processor/transport/types.js';
|
|
96
6
|
import { createProcessor, ProcessorPoisonedError, restoreProcessor } from './processor/step.js';
|
|
@@ -98,21 +8,18 @@ import { checkpointOf, decodeCheckpoint, encodeCheckpoint, PROCESSOR_VERSION } f
|
|
|
98
8
|
import { DAEMON_FRAME_INDEX, isOutboxTail, SessionOutbox, transportOutboxStore } from './outbox.js';
|
|
99
9
|
import { initialState } from './processor/state.js';
|
|
100
10
|
import { activityRaw, runtimeDiagnostics } from './processor/runtime.js';
|
|
101
|
-
import {
|
|
102
|
-
import { unfinishedAsyncTasks } from './processor/updates.js';
|
|
11
|
+
import { unfinishedAsyncTasks, unfinishedDraftSubagentCount } from './processor/updates.js';
|
|
103
12
|
import { pendingRequestIds } from './processor/session.js';
|
|
104
13
|
import { steeredIds } from './processor/control.js';
|
|
105
14
|
import { RawTruncatedError } from './processor/transport/types.js';
|
|
106
|
-
import { REPAIR_NOTE } from '../qoderAdapter/backgroundTerminalFold.js';
|
|
107
15
|
import { AcpKeeperUnavailableError } from '../keepers/acp/client.js';
|
|
16
|
+
import { RegistrationOwnershipError } from '../runtime/ownership.js';
|
|
108
17
|
import { AcpErrorCode } from '../keepers/acp/protocol.js';
|
|
109
18
|
import { KeeperClosedError, KeeperConnectionLostError, KeeperNotConnectedError, KeeperRequestError, KeeperRequestTimeoutError, } from '../keepers/kit/client.js';
|
|
110
19
|
/** What the executor reports when a prompt's blocks are no longer in this daemon's memory (interface-contracts). */
|
|
111
20
|
export const PROMPT_LOST = 'The prompt was lost before it reached the agent';
|
|
112
21
|
/** The error a turn ends with when the session degrades under it (poison, or a transport that failed under the loop). */
|
|
113
22
|
export const SESSION_DEGRADED = 'The agent session failed and was stopped; reopen it to continue';
|
|
114
|
-
/** How often the Qoder side-file reader polls (the live repair's timer). */
|
|
115
|
-
const SIDE_POLL_MS = 1_000;
|
|
116
23
|
/** stderr kept for a startup failure's message (the `err` records the processor ignores). */
|
|
117
24
|
const STDERR_TAIL_BYTES = 8_192;
|
|
118
25
|
/** Within a turn, a checkpoint every this many bytes of folded raw (spec §5.5, §14). */
|
|
@@ -210,7 +117,6 @@ export class ProcessorSession {
|
|
|
210
117
|
openResult;
|
|
211
118
|
historyEnd;
|
|
212
119
|
history = [];
|
|
213
|
-
side;
|
|
214
120
|
/** The record loop's tail: notes it appends are serialised behind it. */
|
|
215
121
|
chain = Promise.resolve();
|
|
216
122
|
/** The loop is held at a record boundary for a switch ({@link suspend}); `release` lets it go on. */
|
|
@@ -252,7 +158,7 @@ export class ProcessorSession {
|
|
|
252
158
|
}
|
|
253
159
|
catch (error) {
|
|
254
160
|
// keeper-acp unreachable is not a launch failure: the caller falls back to the local transport.
|
|
255
|
-
if (error instanceof AcpKeeperUnavailableError)
|
|
161
|
+
if (error instanceof AcpKeeperUnavailableError || error instanceof RegistrationOwnershipError)
|
|
256
162
|
throw error;
|
|
257
163
|
throw spawnFailure(options.spawn.command, error);
|
|
258
164
|
}
|
|
@@ -262,11 +168,12 @@ export class ProcessorSession {
|
|
|
262
168
|
// resent when the server reopens the ref, and numbering continues after the highest seq the outbox ever held.
|
|
263
169
|
const attached = await transport.attach(sessionKey);
|
|
264
170
|
let leftovers = await readOutboxTail(transport, sessionKey, attached.outbox);
|
|
265
|
-
|
|
171
|
+
const imports = (seed?.imports ?? options.imports ?? []).filter((entry) => entry.seq > (attached.outbox?.lastSeq ?? 0));
|
|
172
|
+
if (imports.length > 0) {
|
|
266
173
|
// A switch's successor (Task 24): the predecessor's unacknowledged frames land here before anything this session numbers —
|
|
267
174
|
// the predecessor is released only after this append returned (never the other way round: the frames would be nowhere).
|
|
268
175
|
const at = Math.max(spawned.o - 1, 0);
|
|
269
|
-
const entries =
|
|
176
|
+
const entries = imports.map((entry, index) => ({ seq: entry.seq, src: { o: at, i: DAEMON_FRAME_INDEX + index }, frame: { ...entry.frame } }));
|
|
270
177
|
const { first } = await transport.appendOutbox(sessionKey, entries);
|
|
271
178
|
leftovers = [...leftovers, ...entries.map((entry, k) => ({ o: first + k, t: Date.now(), ...entry }))];
|
|
272
179
|
}
|
|
@@ -552,14 +459,9 @@ export class ProcessorSession {
|
|
|
552
459
|
if (this.checkpointDue && this.checkpointSafe())
|
|
553
460
|
this.cutCheckpoint();
|
|
554
461
|
}
|
|
555
|
-
/**
|
|
556
|
-
* A checkpoint must let a replay continue from it alone: not while a chunked Qoder fact is half-read (`sideChunk`, its first
|
|
557
|
-
* chunks would be truncated away) nor inside a load's history window (history is never journaled: a daemon that dies in the
|
|
558
|
-
* window loads again — interface-contracts, T19).
|
|
559
|
-
*/
|
|
560
462
|
checkpointSafe() {
|
|
561
463
|
const state = this.processor.state;
|
|
562
|
-
return state.offset >= 0 && state.offset <= this.recordedThrough && state.
|
|
464
|
+
return state.offset >= 0 && state.offset <= this.recordedThrough && state.history === null &&
|
|
563
465
|
this.processor.poisoned === undefined;
|
|
564
466
|
}
|
|
565
467
|
/** Snapshot now (a record boundary: the loop is between records) and commit it with raw truncated through it (not a marker's). */
|
|
@@ -644,7 +546,7 @@ export class ProcessorSession {
|
|
|
644
546
|
/** Async tasks / background work the adapter still runs for this session (processor state): a switch would kill them. */
|
|
645
547
|
get liveBackgroundWork() {
|
|
646
548
|
const state = this.processor.state;
|
|
647
|
-
return unfinishedAsyncTasks(state).length + (
|
|
549
|
+
return unfinishedAsyncTasks(state).length + unfinishedDraftSubagentCount(state);
|
|
648
550
|
}
|
|
649
551
|
/** The adapter's exit, once it has one: the spawn it ended and why (keeper-acp's `reason`, absent for an exit of its own). */
|
|
650
552
|
get adapterExit() {
|
|
@@ -674,6 +576,9 @@ export class ProcessorSession {
|
|
|
674
576
|
this.history.push(event);
|
|
675
577
|
}
|
|
676
578
|
continue;
|
|
579
|
+
case 'processor.closed_replay_level':
|
|
580
|
+
this.log(`[acp] session ${this.key}: ignored ${String(frame.sessionUpdate)} for ended replay scope ${JSON.stringify(frame.sessionId)}`);
|
|
581
|
+
continue;
|
|
677
582
|
case 'processor.history_end': {
|
|
678
583
|
const droppedCount = typeof frame.droppedCount === 'number' ? frame.droppedCount : 0;
|
|
679
584
|
this.historyEnd = { ok: frame.ok === true, droppedCount };
|
|
@@ -945,7 +850,6 @@ export class ProcessorSession {
|
|
|
945
850
|
for (const [, reply] of this.pendingReplies)
|
|
946
851
|
reply({ ok: false, error: reason });
|
|
947
852
|
this.pendingReplies.clear();
|
|
948
|
-
this.stopSide();
|
|
949
853
|
void this.transport.terminate(this.key).catch(() => null);
|
|
950
854
|
try {
|
|
951
855
|
this.options.onDegrade?.(this.headSeq);
|
|
@@ -1010,20 +914,8 @@ export class ProcessorSession {
|
|
|
1010
914
|
...(request.sessionId !== undefined ? { sessionId: request.sessionId } : {}),
|
|
1011
915
|
mcpServers: request.mcpServers,
|
|
1012
916
|
...(request.redact && request.redact.length > 0 ? { redact: [...request.redact] } : {}),
|
|
1013
|
-
...(request.delegation ? { delegation: request.delegation } : {}),
|
|
1014
917
|
};
|
|
1015
|
-
|
|
1016
|
-
if (repair) {
|
|
1017
|
-
// The repair note must follow the open note before the loop folds the open note (and so writes the `session/load` line
|
|
1018
|
-
// the history answers): the loop is held while both are appended.
|
|
1019
|
-
await this.holdingLoop(async () => {
|
|
1020
|
-
await this.send(note);
|
|
1021
|
-
await this.enableRepair(request.sessionId, request.cwd, repair.historyHome);
|
|
1022
|
-
});
|
|
1023
|
-
}
|
|
1024
|
-
else {
|
|
1025
|
-
await this.send(note);
|
|
1026
|
-
}
|
|
918
|
+
await this.send(note);
|
|
1027
919
|
return this.waitFor(() => this.openResult);
|
|
1028
920
|
}
|
|
1029
921
|
/** Runs `work` (appends only — never a wait on the loop) with the record loop held, so no record is folded meanwhile. */
|
|
@@ -1044,55 +936,6 @@ export class ProcessorSession {
|
|
|
1044
936
|
await this.send({ type: 'historyEnd' });
|
|
1045
937
|
return this.waitFor(() => this.historyEnd);
|
|
1046
938
|
}
|
|
1047
|
-
/**
|
|
1048
|
-
* Turn the Qoder background terminal repair on (17c): the `qoder_terminal_repair` note, then the side-file reader. Nothing for a
|
|
1049
|
-
* runtime the repair does not certify (no history path).
|
|
1050
|
-
*/
|
|
1051
|
-
async enableRepair(nativeSessionId, cwd, historyHome, restoreCalls = false) {
|
|
1052
|
-
const path = nativeTerminalHistoryPath(this.agentInfo, nativeSessionId, cwd, historyHome);
|
|
1053
|
-
if (!path || this.side?.nativeSessionId === nativeSessionId)
|
|
1054
|
-
return;
|
|
1055
|
-
// A load that failed and fell back to `session/new`: the processor closed the load's repair (`settleOpen`); its reader goes
|
|
1056
|
-
// too, and the new session gets its own (the old path closed the attached session and opened a fresh one).
|
|
1057
|
-
this.stopSide();
|
|
1058
|
-
const from = await this.appendNote({ type: REPAIR_NOTE, nativeSessionId, ...(restoreCalls ? { restoreCalls: true } : {}) });
|
|
1059
|
-
const reader = new BackgroundSideNotes({ path, nativeSessionId, cwd, restoreCalls });
|
|
1060
|
-
const timer = setInterval(() => { void this.pollSide(); }, SIDE_POLL_MS);
|
|
1061
|
-
timer.unref();
|
|
1062
|
-
this.side = { reader, timer, from, polling: false, nativeSessionId };
|
|
1063
|
-
}
|
|
1064
|
-
async pollSide() {
|
|
1065
|
-
const side = this.side;
|
|
1066
|
-
if (!side || side.polling || this.degraded !== undefined || this.closing)
|
|
1067
|
-
return;
|
|
1068
|
-
// The demand is the processor's *current* state, so only once it has folded everything this object appended.
|
|
1069
|
-
if (this.processor.state.offset < Math.max(side.from, this.appended))
|
|
1070
|
-
return;
|
|
1071
|
-
const demand = sideDemand(this.processor.state);
|
|
1072
|
-
if (!demand) {
|
|
1073
|
-
this.stopSide();
|
|
1074
|
-
return;
|
|
1075
|
-
}
|
|
1076
|
-
side.polling = true;
|
|
1077
|
-
try {
|
|
1078
|
-
const notes = await side.reader.poll(demand);
|
|
1079
|
-
for (const note of notes)
|
|
1080
|
-
await this.appendNote(note);
|
|
1081
|
-
}
|
|
1082
|
-
catch (error) {
|
|
1083
|
-
this.log(`[acp] session ${this.key}: background terminal read failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1084
|
-
}
|
|
1085
|
-
finally {
|
|
1086
|
-
side.polling = false;
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
stopSide() {
|
|
1090
|
-
if (!this.side)
|
|
1091
|
-
return;
|
|
1092
|
-
clearInterval(this.side.timer);
|
|
1093
|
-
this.side.reader.close();
|
|
1094
|
-
this.side = undefined;
|
|
1095
|
-
}
|
|
1096
939
|
// ---- AcpAgentSession ----------------------------------------------------------------------------------------------------
|
|
1097
940
|
get facts() {
|
|
1098
941
|
const initialize = this.processor.state.initialize;
|
|
@@ -1108,7 +951,6 @@ export class ProcessorSession {
|
|
|
1108
951
|
get configOptions() { return this.processor.state.configOptions ?? []; }
|
|
1109
952
|
get runtimeDiagnostics() { return runtimeDiagnostics(this.processor.state); }
|
|
1110
953
|
get activityRaw() { return activityRaw(this.processor.state); }
|
|
1111
|
-
get delegation() { return this.processor.state.delegation ?? null; }
|
|
1112
954
|
get nativeSessionId() {
|
|
1113
955
|
const root = this.processor.state.rootSessionId;
|
|
1114
956
|
return root !== null && root.length > 0 ? root : null;
|
|
@@ -1177,6 +1019,13 @@ export class ProcessorSession {
|
|
|
1177
1019
|
async steer(blocks, priority, id) {
|
|
1178
1020
|
if (this.pendingReplies.has(`agent_steered:${id}`))
|
|
1179
1021
|
throw new Error(`A steer with id '${id}' is already in flight`);
|
|
1022
|
+
// A full producing window stops the raw loop, including control notes. Appending here
|
|
1023
|
+
// would leave a steer that can execute long after the server's RPC timed out. Refuse
|
|
1024
|
+
// before recording anything: promptRequired proves this attempt cannot inject later.
|
|
1025
|
+
if (!this.outbox.hasRoom()) {
|
|
1026
|
+
this.log(`[acp] session ${this.key}: steer ${id} not admitted while awaiting event acknowledgements`);
|
|
1027
|
+
return 'promptRequired';
|
|
1028
|
+
}
|
|
1180
1029
|
const answered = this.reply('agent_steered', id);
|
|
1181
1030
|
await this.send({ type: 'agent_steer', id, blocksRef: this.holdBlocks(blocks), ...(priority !== undefined ? { priority } : {}) })
|
|
1182
1031
|
.catch((error) => { this.pendingReplies.delete(`agent_steered:${id}`); throw error; });
|
|
@@ -1283,7 +1132,6 @@ export class ProcessorSession {
|
|
|
1283
1132
|
this.resume();
|
|
1284
1133
|
this.detached = true;
|
|
1285
1134
|
this.unlisten();
|
|
1286
|
-
this.stopSide();
|
|
1287
1135
|
for (const waiter of [...this.waiters])
|
|
1288
1136
|
waiter.reject(new Error('The agent session was handed to the next daemon'));
|
|
1289
1137
|
// A loop waiting for room stops (it sees `closing`); the head checkpoint is cut at the record boundary after it.
|
|
@@ -1307,7 +1155,6 @@ export class ProcessorSession {
|
|
|
1307
1155
|
this.closing ??= (async () => {
|
|
1308
1156
|
this.resume(); // a held loop drains (every fold sees `closing`)
|
|
1309
1157
|
this.unlisten();
|
|
1310
|
-
this.stopSide();
|
|
1311
1158
|
for (const waiter of [...this.waiters])
|
|
1312
1159
|
waiter.reject(new Error('The agent session is closed'));
|
|
1313
1160
|
for (const [, reply] of this.pendingReplies)
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
*
|
|
45
45
|
* 这里写下的来源**整个替换** registry 的 `version` 与 `distribution`,id 与展示名仍是 registry 的,
|
|
46
46
|
* 于是已有的配置条目、roster、安装、启动、更新都不用知道发生过替换(见 {@link withCatalogOverrides})。
|
|
47
|
-
* 本文件的 distribution
|
|
47
|
+
* 本文件的 distribution 用于长期策略;临时的版本覆盖才放在
|
|
48
48
|
* axom-patch/cli/runtime.json,按 registry 版本挑选(`when_registry_version` / `until_registry_version`,
|
|
49
49
|
* 见 `patchAssets.ts`),registry 一到就自己让位。两者与上面的 `install` 是同一条安全边界:只能是
|
|
50
|
-
* 随 CLI
|
|
50
|
+
* 随 CLI 发布、钉死版本、由补丁哈希和回归验证过的可信配置。
|
|
51
51
|
*
|
|
52
52
|
* ## `supplement` 与 `supersedes`:registry 缺的条目、registry 不肯撤的条目
|
|
53
53
|
*
|
|
@@ -86,13 +86,13 @@ export const AXOM_AGENT_CATALOG = [
|
|
|
86
86
|
defaultName: 'claude-agent',
|
|
87
87
|
defaultLabel: 'Claude Agent',
|
|
88
88
|
detect: { commands: ['claude'] },
|
|
89
|
-
//
|
|
89
|
+
// 钉版本的唯一理由是补丁:账号配额与 replay lifecycle 配方只核验过 0.97.0(runtime.json 的
|
|
90
90
|
// package_patches)。不钉的话 registry 一发新版,Install/Update 就装上一个配方不覆盖的包,
|
|
91
91
|
// 账号配额扩展静默消失——2026-10-14 的 antigravity(registry 已到 1.4.0、native extension
|
|
92
92
|
// 只认 1.3.0)就是这个缺口的实例。钉住后 scan 的 Update 比对(installedVersion vs 本清单的
|
|
93
93
|
// version)只在落后于钉住版本时才成立,上游新版要等 nightly 核验移植配方后再 bump。
|
|
94
|
-
// 周期核验步骤见 axom-patch/
|
|
95
|
-
distribution: { version: '0.
|
|
94
|
+
// 周期核验步骤见 axom-patch/DAILY_UPGRADE_CHECK.md。
|
|
95
|
+
distribution: { version: '0.97.0', npx: { package: '@agentclientprotocol/claude-agent-acp@0.97.0' } },
|
|
96
96
|
launchEnv: {
|
|
97
97
|
// Axom 拉起的 Claude Code——会话进程、配额读的 /usage、auth status 探针、terminalLogin 代跑的
|
|
98
98
|
// `--cli auth login`——一律使用独立的 OAuth 凭据槽,与用户终端 `claude login` 写进默认槽
|
|
@@ -116,16 +116,18 @@ export const AXOM_AGENT_CATALOG = [
|
|
|
116
116
|
defaultName: 'codex',
|
|
117
117
|
defaultLabel: 'Codex',
|
|
118
118
|
detect: { commands: ['codex'] },
|
|
119
|
-
// 与 claude-acp 同一条规则:codex-account-limits 只核验过 2.2.
|
|
120
|
-
|
|
119
|
+
// 与 claude-acp 同一条规则:codex-account-limits 只核验过 2.3.0(2026-10-27 nightly;2.3.0 的
|
|
120
|
+
// authStatus 锚点在两处 capabilities 里重复,已加长到 initialize 独有后缀消歧),钉住直到配方随新版本移植。
|
|
121
|
+
distribution: { version: '2.3.0', npx: { package: '@agentclientprotocol/codex-acp@2.3.0' } },
|
|
121
122
|
},
|
|
122
123
|
{
|
|
123
124
|
registryAgent: 'qoder',
|
|
124
125
|
defaultName: 'qoder',
|
|
125
126
|
defaultLabel: 'Qoder',
|
|
126
127
|
detect: { commands: ['qodercli'] },
|
|
127
|
-
//
|
|
128
|
-
//
|
|
128
|
+
// Native ACP is the sole Qoder entry. The exact --acp argv is pinned here; the package
|
|
129
|
+
// patch layer verifies the 1.1.75 package and its qoder-native-acp recipe hashes.
|
|
130
|
+
distribution: { version: '1.1.75', npx: { package: '@qoder-ai/qodercli@1.1.75', args: ['--acp'] } },
|
|
129
131
|
},
|
|
130
132
|
// `gemini` was here and is deliberately gone. `@google/gemini-cli --acp` now refuses `session/new`
|
|
131
133
|
// outright ("This client is no longer supported for Gemini Code Assist for individuals … migrate
|
|
@@ -144,7 +146,7 @@ export const AXOM_AGENT_CATALOG = [
|
|
|
144
146
|
// 其余字段照 registry#458 的条目写。
|
|
145
147
|
supplement: {
|
|
146
148
|
name: 'Kimi Code',
|
|
147
|
-
version: '2.
|
|
149
|
+
version: '2.3.3',
|
|
148
150
|
description: "Moonshot AI's next-gen coding agent",
|
|
149
151
|
repository: 'https://github.com/MoonshotAI/kimi-code',
|
|
150
152
|
website: 'https://moonshotai.github.io/kimi-code/',
|
|
@@ -152,13 +154,13 @@ export const AXOM_AGENT_CATALOG = [
|
|
|
152
154
|
license: 'MIT',
|
|
153
155
|
icon: 'https://cdn.agentclientprotocol.com/registry/v1/latest/kimi.svg',
|
|
154
156
|
distribution: {
|
|
155
|
-
binary: kimiCodeBinary('2.
|
|
156
|
-
'darwin-aarch64': ['darwin-arm64', '
|
|
157
|
-
'darwin-x86_64': ['darwin-x64', '
|
|
158
|
-
'linux-aarch64': ['linux-arm64', '
|
|
159
|
-
'linux-x86_64': ['linux-x64', '
|
|
160
|
-
'windows-aarch64': ['win32-arm64', '
|
|
161
|
-
'windows-x86_64': ['win32-x64', '
|
|
157
|
+
binary: kimiCodeBinary('2.3.3', {
|
|
158
|
+
'darwin-aarch64': ['darwin-arm64', 'd097b397db785e9bde07e9d169870e315dd9a0d9d6542727ea4a50e4a630a280'],
|
|
159
|
+
'darwin-x86_64': ['darwin-x64', '9c42127a60488add5cfb8ca60d35f4df9d881552eb3b05268c3a691f7b3c5406'],
|
|
160
|
+
'linux-aarch64': ['linux-arm64', '4b12a13d64dbf9cde631e4c74965ccd1b72bfd93892b30d8272b4bc6448fe45f'],
|
|
161
|
+
'linux-x86_64': ['linux-x64', '0e4a766d38e5202a2413b8517bd4b3a2c00486327a6e231c98f99a0bbf7422e1'],
|
|
162
|
+
'windows-aarch64': ['win32-arm64', '655a4b0e57090fa414aec6c69e4801c12a28e7ca75dd627bfc64340b600079fd'],
|
|
163
|
+
'windows-x86_64': ['win32-x64', '08bd5fcb7b0d6b3bcd70ef42e58b73c884149905b0044544a941ad795f587c4a'],
|
|
162
164
|
}),
|
|
163
165
|
},
|
|
164
166
|
},
|
|
@@ -173,21 +175,20 @@ export const AXOM_AGENT_CATALOG = [
|
|
|
173
175
|
registryAgent: 'command-code',
|
|
174
176
|
defaultName: 'command-code',
|
|
175
177
|
defaultLabel: 'Command Code',
|
|
176
|
-
// registry 没有它。1.66.0 还没有 `acp` 子命令,1.74.3 起有、真机试跑通过;2026-10-
|
|
177
|
-
//
|
|
178
|
-
// generate.py 移植(handler map 换了名字 u/dn→m/hn,锚点已跟)。包里有 `cmd`、`cmdc`、
|
|
178
|
+
// registry 没有它。1.66.0 还没有 `acp` 子命令,1.74.3 起有、真机试跑通过;2026-10-27 已到 1.88.0(10-25):`acp` 子命令仍在(四个 bin 不变),commandcode-account-limits 配方已随
|
|
179
|
+
// generate.py 移植(handler map 枚举每版改名 u/dn→m/hn→m/vn→m/bn,锚点已跟)。包里有 `cmd`、`cmdc`、
|
|
179
180
|
// `commandcode`、`command-code` 四个 bin,npx 挑与包名同名的那个。没有 ACP 登录方法,只有一句
|
|
180
181
|
// 说明(终端里跑 `cmd login`);凭据在 `~/.commandcode`,与用户自己装的那份共用。npm 上的许可证
|
|
181
182
|
// 写的是 UNLICENSED(专有)。
|
|
182
183
|
supplement: {
|
|
183
184
|
name: 'Command Code',
|
|
184
|
-
version: '1.
|
|
185
|
+
version: '1.88.0',
|
|
185
186
|
description: 'Command Code, coding agent that continuously learns your coding taste.',
|
|
186
187
|
website: 'https://commandcode.ai',
|
|
187
188
|
authors: ['Command Code'],
|
|
188
189
|
license: 'UNLICENSED',
|
|
189
190
|
icon: 'https://commandcode.ai/favicon.ico',
|
|
190
|
-
distribution: { npx: { package: 'command-code@1.
|
|
191
|
+
distribution: { npx: { package: 'command-code@1.88.0', args: ['acp'] } },
|
|
191
192
|
},
|
|
192
193
|
detect: { commands: ['command-code', 'commandcode'] },
|
|
193
194
|
},
|
|
@@ -203,19 +204,19 @@ export const AXOM_AGENT_CATALOG = [
|
|
|
203
204
|
// 2026-10-13 真机验证(ZCode 桌面 3.14.5 + 0.69.3):initialize → session/new → 首轮 prompt 通过,
|
|
204
205
|
// 日志 "serving the coding-plan API key (config.json or store)"。0.63/0.64 那轮不兼容(模型只剩
|
|
205
206
|
// 无授权的 builtin:bigmodel-coding-plan\GLM-5.3,首轮 CONFIGURATION_ERROR "Model creation failed",
|
|
206
|
-
// 2026-10-06 两台机器复现)自 0.68.1 起修复。2026-10-
|
|
207
|
-
//
|
|
208
|
-
//
|
|
207
|
+
// 2026-10-06 两台机器复现)自 0.68.1 起修复。2026-10-29 升到 0.80.0:迁移配额、模型兜底、
|
|
208
|
+
// subagent/async 补丁;env 账号包装复用上游 bridge-accounts(不写桌面配置)。
|
|
209
|
+
// ZCODE_PROVIDER + ZCODE_API_KEY 支持独立个人 Coding Plan,无需复用桌面 OAuth。
|
|
209
210
|
supplement: {
|
|
210
211
|
name: 'ZCode',
|
|
211
|
-
version: '0.
|
|
212
|
+
version: '0.80.0',
|
|
212
213
|
description: 'Community bridge that drives the real ZCode app-server (GLM) over ACP.',
|
|
213
214
|
repository: 'https://github.com/william0wang/zcode-acp',
|
|
214
215
|
website: 'https://github.com/william0wang/zcode-acp',
|
|
215
216
|
authors: ['William Wang'],
|
|
216
217
|
license: 'Apache-2.0',
|
|
217
218
|
icon: 'https://raw.githubusercontent.com/william0wang/zcode-acp/main/registry/zcode-acp/icon.svg',
|
|
218
|
-
distribution: { npx: { package: 'zcode-acp-server@0.
|
|
219
|
+
distribution: { npx: { package: 'zcode-acp-server@0.80.0' } },
|
|
219
220
|
},
|
|
220
221
|
prerequisite: {
|
|
221
222
|
label: 'ZCode',
|
|
@@ -238,7 +239,7 @@ export const AXOM_AGENT_CATALOG = [
|
|
|
238
239
|
recommended: true,
|
|
239
240
|
// pi-steering 与 pi-subagent-subwork 两份配方只核验过 0.0.34。registry 今天也在 0.0.34,
|
|
240
241
|
// 但那是巧合而不是保护:上游一发 0.0.35,未钉版本的 Install 就会装上一个 steering/子代理
|
|
241
|
-
// 归一都不生效的包。钉住后版本只随配方移植走(
|
|
242
|
+
// 归一都不生效的包。钉住后版本只随配方移植走(DAILY_UPGRADE_CHECK.md)。
|
|
242
243
|
distribution: { version: '0.0.34', npx: { package: 'pi-acp@0.0.34' } },
|
|
243
244
|
prerequisite: {
|
|
244
245
|
label: 'Pi',
|
|
@@ -287,27 +288,52 @@ export const AXOM_AGENT_CATALOG = [
|
|
|
287
288
|
// registry 自己的条目(binary .par),我们只补名字与本机检测;`agy` 是 Antigravity 装好后放进 PATH 的命令。
|
|
288
289
|
// distribution 钉住:antigravity 的账号配额靠 native extension(runtime.json
|
|
289
290
|
// native_extensions,account-limits/antigravity-proxy.mjs),proxy 是 stdio sidecar,只在核验过的
|
|
290
|
-
// 版本上声明能力。2026-10-
|
|
291
|
-
// `axom/accountRateLimits
|
|
292
|
-
// 归档 URL 抄自 registry 的 1.4.
|
|
293
|
-
// registry 直装一致(binaryInstall:无 sha256 即不校验)。上游发新版时按
|
|
291
|
+
// 版本上声明能力。2026-10-25 nightly 升到 1.4.3:真实 1.4.3 .par 经 proxy 拉起,initialize 透传无损、
|
|
292
|
+
// `axom/accountRateLimits`(v5)能力注入成功(本地实测;配额 READ 属于用户凭据路径,留给真机冒烟)。
|
|
293
|
+
// 归档 URL 抄自 registry 的 1.4.3 条目(六平台 HEAD 200);registry 本身不给这个条目发 sha256,这里同样不发,校验语义与
|
|
294
|
+
// registry 直装一致(binaryInstall:无 sha256 即不校验)。上游发新版时按 axom-patch/DAILY_UPGRADE_CHECK.md 核验后同升。
|
|
294
295
|
{
|
|
295
296
|
registryAgent: 'antigravity-acp',
|
|
296
297
|
defaultName: 'google-antigravity',
|
|
297
298
|
defaultLabel: 'Google Antigravity',
|
|
298
299
|
detect: { commands: ['agy'] },
|
|
299
300
|
distribution: {
|
|
300
|
-
version: '1.4.
|
|
301
|
+
version: '1.4.3',
|
|
301
302
|
binary: {
|
|
302
|
-
'darwin-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/macos/agy-acp-server-1.4.
|
|
303
|
-
'darwin-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/macos/agy-acp-server-1.4.
|
|
304
|
-
'linux-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/linux/agy-acp-server-1.4.
|
|
305
|
-
'linux-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/linux/agy-acp-server-1.4.
|
|
306
|
-
'windows-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/windows/agy-acp-server-1.4.
|
|
307
|
-
'windows-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/windows/agy-acp-server-1.4.
|
|
303
|
+
'darwin-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/macos/agy-acp-server-1.4.3-darwin-arm64.zip', cmd: './agy_acp_server.par' },
|
|
304
|
+
'darwin-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/macos/agy-acp-server-1.4.3-darwin-x86_64.zip', cmd: './agy_acp_server.par' },
|
|
305
|
+
'linux-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/linux/agy-acp-server-1.4.3-linux-x86_64.zip', cmd: './agy_acp_server.par', args: ['--uid='] },
|
|
306
|
+
'linux-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/linux/agy-acp-server-1.4.3-linux-arm64.zip', cmd: './agy_acp_server.par', args: ['--uid='] },
|
|
307
|
+
'windows-x86_64': { archive: 'https://dl.google.com/agy-extensions/releases/windows/agy-acp-server-1.4.3-windows-x86_64.zip', cmd: './agy_acp_server.exe' },
|
|
308
|
+
'windows-aarch64': { archive: 'https://dl.google.com/agy-extensions/releases/windows/agy-acp-server-1.4.3-windows-arm64.zip', cmd: './agy_acp_server.exe' },
|
|
308
309
|
},
|
|
309
310
|
},
|
|
310
311
|
},
|
|
312
|
+
// CodeBuddy(腾讯的编码 agent,npm 是它唯一的官方 CLI 分发)。registry 已收录 `codebuddy-code`
|
|
313
|
+
// (npx @tencent-ai/codebuddy-code --acp,包自带 @agentclientprotocol/sdk 依赖),于是这是最普通
|
|
314
|
+
// 的「registry 条目 + 本清单认证」形态:不 supplement(registry 有这个 id)、不 pathLaunch(有可装
|
|
315
|
+
// 产物,Axom 装自己托管的那份)、不钉版本(没有依赖版本的配方)、不配 launchEnv——本条就是
|
|
316
|
+
// CodeBuddy 本身,登录落在它的 copilot.tencent.com。
|
|
317
|
+
//
|
|
318
|
+
// 2026-10-19/21 真机实测(npm 2.169.0/2.171.0,ACP capture):`--acp` 起 initialize 通过,能力
|
|
319
|
+
// image/embeddedContext/mcp http+sse/loadSession/delegateTools/multitask;authMethods 声明
|
|
320
|
+
// iOA、external(Google/Github)、internal(WeChat)、selfhosted;登录链接经 `_codebuddy.ai/authUrl`
|
|
321
|
+
// 扩展通知推送(acpClient 的处理器)。凭据在 CODEBUDDY_CONFIG_DIR(默认 ~/.codebuddy)的
|
|
322
|
+
// credentials.json,登录走 ACP 认证流(一次性,与终端 CLI 共用)。
|
|
323
|
+
//
|
|
324
|
+
// 同一引擎另有 App 产品形态(App 内 product.json 声明 productName/endpoint/计费,经其自设的
|
|
325
|
+
// ACC_PRODUCT_CONFIG_PATH 环境变量切换)——那是**另一个产品、另一套账号**,npm 包名、registry
|
|
326
|
+
// id、CLI bin 都不带它的名字;Axom 只策展 npm 的 CodeBuddy,不策展那个 App 形态,也不替用户
|
|
327
|
+
// 预设产品开关(真需要的用户可经 agentEnv 自行覆盖)。
|
|
328
|
+
//
|
|
329
|
+
// detect 认 npm 包的两个主 bin(codebuddy 与 cbc;codebuddy-code/codebuddy-lowmem 是同名
|
|
330
|
+
// 变体,不另列)。
|
|
331
|
+
{
|
|
332
|
+
registryAgent: 'codebuddy-code',
|
|
333
|
+
defaultName: 'codebuddy',
|
|
334
|
+
defaultLabel: 'CodeBuddy',
|
|
335
|
+
detect: { commands: ['codebuddy', 'cbc'] },
|
|
336
|
+
},
|
|
311
337
|
];
|
|
312
338
|
/**
|
|
313
339
|
* Kimi Code 的六个平台归档:GitHub release `@moonshot-ai/kimi-code@<version>` 下的
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import semver from 'semver';
|
|
4
5
|
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { managedRuntimeFor, verifyManagedRuntime, verifyRecordedManagedRuntime } from '../managedRuntime.js';
|
|
5
7
|
import { nativeExtensionFor } from '../patchAssets.js';
|
|
6
8
|
import { verifyPatchedFiles } from '../managedPatches.js';
|
|
7
9
|
import { AdapterNotInstalledError, inside, labelFor } from '../builds/model.js';
|
|
@@ -45,10 +47,23 @@ function expandHomeInEnv(env) {
|
|
|
45
47
|
return Object.fromEntries(Object.entries(env).map(([key, value]) => [key, value === '~' ? home : value.startsWith('~/') ? path.join(home, value.slice(2)) : value]));
|
|
46
48
|
}
|
|
47
49
|
export async function launchForBuild(build, root, options) {
|
|
50
|
+
const policy = options.policy ?? managedRuntimeFor(build.agentId);
|
|
51
|
+
// Only a caller resolving an explicit recorded old binding/rollback may use legacy launch rules.
|
|
52
|
+
// Removing runtimeReleaseId from the strict target never changes its policy classification.
|
|
53
|
+
const legacy = options.allowLegacy && !build.runtimeReleaseId && policy && (build.package !== policy.package || (semver.valid(build.version) !== null && semver.lt(build.version, policy.version)));
|
|
54
|
+
if (policy && !legacy) {
|
|
55
|
+
const verify = options.allowLegacy && build.runtimeReleaseId ? verifyRecordedManagedRuntime : verifyManagedRuntime;
|
|
56
|
+
await verify({ ...options, policy, build, storeRoot: root, initialize: false });
|
|
57
|
+
}
|
|
58
|
+
// A build recorded under a strict policy this CLI no longer ships launches like any other build:
|
|
59
|
+
// its runtimeReleaseId is history, and the patched-file check below still applies.
|
|
48
60
|
const dir = inside(root, build.dir);
|
|
49
61
|
const entry = inside(dir, build.launch.entry);
|
|
50
62
|
if (build.kind === 'npm-patched' && build.package && build.patchedFiles) {
|
|
51
|
-
|
|
63
|
+
if (build.patchedFilesBase !== undefined && build.patchedFilesBase !== 'node_modules')
|
|
64
|
+
throw new Error('Invalid Axom patched file base');
|
|
65
|
+
const modules = path.join(dir, 'node_modules');
|
|
66
|
+
await verifyPatchedFiles(build.patchedFilesBase === 'node_modules' ? modules : inside(modules, build.package), build.patchedFiles);
|
|
52
67
|
}
|
|
53
68
|
if (!existsSync(entry))
|
|
54
69
|
throw new AdapterNotInstalledError(build.agentId, `build ${build.buildId} is missing its executable`);
|
|
@@ -62,7 +62,6 @@ const PLAIN_BLOCKERS = {
|
|
|
62
62
|
'a permission or elicitation is unanswered': 'it is waiting for an answer',
|
|
63
63
|
'the agent reports it is active': 'the agent says it is still working',
|
|
64
64
|
'an async task or background terminal is still running': 'it has a background task or terminal still running',
|
|
65
|
-
'a delegation refresh is pending': 'its delegated access is being renewed',
|
|
66
65
|
};
|
|
67
66
|
/** Why a session may not be switched now (spec §6.3 step 2); empty = strictly idle. */
|
|
68
67
|
export function switchBlockers(input) {
|
|
@@ -83,8 +82,6 @@ export function switchBlockers(input) {
|
|
|
83
82
|
blockers.push('the agent reports it is active');
|
|
84
83
|
if ((session.liveBackgroundWork ?? 0) > 0)
|
|
85
84
|
blockers.push('an async task or background terminal is still running');
|
|
86
|
-
if (session.delegation?.refreshPending)
|
|
87
|
-
blockers.push('a delegation refresh is pending');
|
|
88
85
|
const quiet = input.quietMs ?? SWITCH_QUIET_MS;
|
|
89
86
|
const last = Math.max(input.lastActivityAt, session.lastFoldAt ?? 0);
|
|
90
87
|
if (input.now - last < quiet)
|
|
@@ -113,6 +113,12 @@
|
|
|
113
113
|
// // with this message instead of succeeding — lets a
|
|
114
114
|
// // test prove a real agent-side rejection surfaces as
|
|
115
115
|
// // a rejected promise
|
|
116
|
+
// authenticateNotifications?: Array<{method: string, params: unknown}>,
|
|
117
|
+
// // sent as client notifications at the top of the
|
|
118
|
+
// // `authenticate` handler, before anything else —
|
|
119
|
+
// // models an agent that pushes a login URL as an
|
|
120
|
+
// // extension notification (`_codebuddy.ai/authUrl`)
|
|
121
|
+
// // rather than eliciting or printing it
|
|
116
122
|
// hangOnAuthenticate?: boolean, // if true, `authenticate` never resolves — the shape
|
|
117
123
|
// // measured on a real agent that opens a browser and
|
|
118
124
|
// // waits for its callback (spec §6.2: antigravity's
|
|
@@ -348,6 +354,13 @@ async function main() {
|
|
|
348
354
|
writeFileSync(config.authenticateSink, JSON.stringify(ctx.params));
|
|
349
355
|
if (config.authenticateRejectsWith)
|
|
350
356
|
throw new Error(config.authenticateRejectsWith);
|
|
357
|
+
// Extension notifications an agent pushes while answering `authenticate` (measured on the real
|
|
358
|
+
// CodeBuddy adapter: `_codebuddy.ai/authUrl` with `{authUrl, provider}` — a URL channel that
|
|
359
|
+
// is neither `elicitation/create` nor stderr). Sent before the reply, so a client that only
|
|
360
|
+
// listens from the reply onward still misses them, exactly like the real one.
|
|
361
|
+
for (const { method, params } of config.authenticateNotifications ?? []) {
|
|
362
|
+
await ctx.client.notify(method, params);
|
|
363
|
+
}
|
|
351
364
|
if (config.createElicitationDuringAuthenticate) {
|
|
352
365
|
// `requestId` is filled in here rather than in the config: a login elicitation is
|
|
353
366
|
// request-scoped (ACP's `ElicitationRequestScope` — "tied to a specific JSON-RPC request
|