@platless/axom-cli 0.3.13 → 0.6.36
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 +18 -5
- package/dist/axom-patch/cli/README.md +119 -9
- package/dist/axom-patch/cli/account-limits/README.md +27 -0
- package/dist/axom-patch/cli/account-limits/antigravity-proxy.mjs +47 -0
- package/dist/axom-patch/cli/account-limits/antigravity-read.mjs +90 -0
- package/dist/axom-patch/cli/account-limits/antigravity.mjs +46 -0
- package/dist/axom-patch/cli/account-limits/generate.py +123 -0
- package/dist/axom-patch/cli/account-limits/kimi-proxy.mjs +81 -0
- package/dist/axom-patch/cli/account-limits/normalize.mjs +151 -0
- package/dist/axom-patch/cli/claude-account-limits.json +37 -0
- package/dist/axom-patch/cli/codex-account-limits.json +37 -0
- package/dist/axom-patch/cli/codex-terminal-output.json +16 -0
- package/dist/axom-patch/cli/commandcode-account-limits.json +30 -0
- 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 +194 -0
- package/dist/axom-patch/cli/pi-subagent-subwork.json +23 -0
- package/dist/axom-patch/cli/probes/claude-late-async-terminal.mjs +5 -1
- 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/pi-subagent-subwork.mjs +211 -0
- package/dist/axom-patch/cli/probes/zcode-subagent-subwork.mjs +257 -0
- package/dist/axom-patch/cli/qoder/dist/axom-acp-compat.mjs +1591 -0
- package/dist/axom-patch/cli/qoder/releases/1.1.75.json +360 -0
- package/dist/axom-patch/cli/qoder-background-terminal.md +13 -5
- package/dist/axom-patch/cli/qoder-foreground-output.md +14 -7
- 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 +39 -15
- package/dist/axom-patch/cli/zcode-account-limits.json +30 -0
- package/dist/axom-patch/cli/zcode-models.json +37 -0
- package/dist/axom-patch/cli/zcode-subagent-subwork.json +72 -0
- package/dist/cli.js +4 -9
- package/dist/commands/knowledge.js +47 -0
- package/dist/commands/update.js +65 -3
- package/dist/commands/workstation.js +73 -7
- package/dist/install/claude/commands.js +13 -13
- package/dist/keepers/acp/keeper.mjs +3083 -0
- package/dist/keepers/acp/manifest.json +9 -0
- package/dist/keepers/terminal/keeper.mjs +8469 -0
- package/dist/keepers/terminal/manifest.json +9 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/conpty_console_list_agent.js +25 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/eventEmitter2.js +47 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/index.js +52 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/interfaces.js +7 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/shared/conout.js +10 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/terminal.js +190 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/types.js +7 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/unixTerminal.js +351 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/utils.js +38 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/windowsConoutConnection.js +131 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/windowsPtyAgent.js +344 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/windowsTerminal.js +209 -0
- package/dist/keepers/terminal/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
- package/dist/keepers/terminal/node_modules/node-pty/package.json +66 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-x64/pty.node +0 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/linux-arm64/pty.node +0 -0
- package/dist/keepers/terminal/node_modules/node-pty/prebuilds/linux-x64/pty.node +0 -0
- package/dist/mcp.js +1 -1
- package/dist/native/darwin-arm64/axom-quic +0 -0
- package/dist/test/keeperKit.js +67 -0
- package/dist/workstation/acp/acpAgents.js +2192 -636
- package/dist/workstation/acp/acpClient.js +84 -495
- package/dist/workstation/acp/adoption.js +10 -396
- package/dist/workstation/acp/binaryInstall.js +100 -27
- package/dist/workstation/acp/builds/gc.js +245 -0
- package/dist/workstation/acp/builds/install/binary.js +28 -0
- package/dist/workstation/acp/builds/install/npm.js +324 -0
- package/dist/workstation/acp/builds/install/uv.js +254 -0
- package/dist/workstation/acp/builds/migrate.js +195 -0
- package/dist/workstation/acp/builds/model.js +128 -0
- package/dist/workstation/acp/builds/nodeGate.js +100 -0
- package/dist/workstation/acp/builds/store.js +352 -0
- package/dist/workstation/acp/commandTableProbe.js +68 -0
- package/dist/workstation/acp/configOptions.js +103 -1
- package/dist/workstation/acp/envSecrets.js +27 -0
- package/dist/workstation/acp/initializeResponse.js +290 -0
- package/dist/workstation/acp/installErrors.js +12 -2
- package/dist/workstation/acp/installProbe.js +1 -1
- package/dist/workstation/acp/managedPatches.js +239 -159
- package/dist/workstation/acp/managedRuntime.js +314 -0
- package/dist/workstation/acp/outbox.js +330 -0
- package/dist/workstation/acp/patchAssets.js +60 -3
- package/dist/workstation/acp/permission.js +42 -10
- package/dist/workstation/acp/processor/checkpoint.js +78 -0
- package/dist/workstation/acp/processor/commands.js +35 -0
- package/dist/workstation/acp/processor/control.js +282 -0
- package/dist/workstation/acp/processor/emit.js +26 -0
- package/dist/workstation/acp/processor/jsonrpc.js +172 -0
- package/dist/workstation/acp/processor/memoryLog.js +49 -0
- package/dist/workstation/acp/processor/origins.js +48 -0
- package/dist/workstation/acp/processor/output.js +67 -0
- package/dist/workstation/acp/processor/projection.js +42 -0
- package/dist/workstation/acp/processor/record.js +128 -0
- package/dist/workstation/acp/processor/runtime.js +105 -0
- package/dist/workstation/acp/processor/sdkSchemas.js +61 -0
- package/dist/workstation/acp/processor/session.js +496 -0
- package/dist/workstation/acp/processor/state.js +67 -0
- package/dist/workstation/acp/processor/step.js +442 -0
- package/dist/workstation/acp/processor/test/fixtureLog.js +58 -0
- package/dist/workstation/acp/processor/test/harness.js +120 -0
- package/dist/workstation/acp/processor/test/largeIdEcho.js +50 -0
- package/dist/workstation/acp/processor/test/rawAgent.js +70 -0
- package/dist/workstation/acp/processor/transport/generations.js +76 -0
- package/dist/workstation/acp/processor/transport/keeper.js +130 -0
- package/dist/workstation/acp/processor/transport/local.js +269 -0
- package/dist/workstation/acp/processor/transport/types.js +78 -0
- package/dist/workstation/acp/processor/updates.js +390 -0
- package/dist/workstation/acp/processorSession.js +1348 -0
- package/dist/workstation/acp/registry/catalog.js +189 -41
- package/dist/workstation/acp/registry/launch.js +76 -119
- package/dist/workstation/acp/sessionUpdateMapper.js +18 -7
- package/dist/workstation/acp/steering.js +58 -0
- package/dist/workstation/acp/switching.js +111 -0
- package/dist/workstation/acp/terminalLogin.js +16 -42
- package/dist/workstation/acp/terminalLoginSpec.js +41 -0
- package/dist/workstation/acp/test/adapterFixtures.js +256 -0
- package/dist/workstation/acp/test/daemonLife.js +106 -0
- package/dist/workstation/acp/test/fakeAgent.js +13 -0
- package/dist/workstation/acp/test/keeperWorld.js +295 -0
- package/dist/workstation/acp/test/memoryOutbox.js +55 -0
- package/dist/workstation/acp/test/raw/fixtures.js +196 -0
- package/dist/workstation/acp/test/raw/sanitize.js +344 -0
- package/dist/workstation/acp/test/raw/sources.js +135 -0
- package/dist/workstation/acp/test/realAdapter.js +331 -0
- package/dist/workstation/acp/test/scriptAgent.js +214 -0
- package/dist/workstation/acp/test/sessionFrames.js +42 -0
- package/dist/workstation/acp/timedCommand.js +4 -2
- package/dist/workstation/acp/uvxInstall.js +72 -122
- package/dist/workstation/agentFlow.js +103 -0
- package/dist/workstation/agentSessions.js +1289 -544
- package/dist/workstation/channels/agent.js +7 -5
- package/dist/workstation/channels/computer.js +69 -21
- package/dist/workstation/channels/computerExecs.js +200 -0
- package/dist/workstation/channels/management.js +172 -8
- package/dist/workstation/channels/url.js +1 -1
- package/dist/workstation/config.js +16 -4
- package/dist/workstation/connection/encryptedChannel.js +4 -1
- package/dist/workstation/control/bindingStore.js +200 -0
- package/dist/workstation/control/commands.js +124 -0
- package/dist/workstation/control/daemonIdentity.js +53 -0
- package/dist/workstation/control/enrollment.js +106 -0
- package/dist/workstation/control/inspect.js +71 -0
- package/dist/workstation/control/locks.js +63 -0
- package/dist/workstation/control/protocol.js +40 -0
- package/dist/workstation/control/restartGuard.js +46 -0
- package/dist/workstation/control/runtimeClient.js +97 -0
- package/dist/workstation/control/runtimeHost.js +148 -0
- package/dist/workstation/control/serverIdentity.js +35 -0
- package/dist/workstation/daemon.js +393 -12
- package/dist/workstation/daemonctl.js +103 -14
- package/dist/workstation/desktopControl/audio.js +99 -0
- package/dist/workstation/desktopControl/capabilities.js +92 -0
- package/dist/workstation/desktopControl/captureModes.js +9 -0
- package/dist/workstation/desktopControl/captureTargetLabel.js +9 -0
- package/dist/workstation/desktopControl/deviceSockets.js +246 -0
- package/dist/workstation/desktopControl/helperProcess.js +353 -0
- package/dist/workstation/desktopControl/lobby.js +129 -0
- package/dist/workstation/desktopControl/macProvider.js +155 -0
- package/dist/workstation/desktopControl/media.js +331 -0
- package/dist/workstation/desktopControl/nativeProvider.js +1018 -0
- package/dist/workstation/desktopControl/networkEvidence.js +43 -0
- package/dist/workstation/desktopControl/overview.js +58 -0
- package/dist/workstation/desktopControl/protocol.js +302 -0
- package/dist/workstation/desktopControl/quicMedia.js +240 -0
- package/dist/workstation/desktopControl/rateController.js +226 -0
- package/dist/workstation/desktopControl/supervisor.js +1681 -0
- package/dist/workstation/desktopControl/transport.js +27 -0
- package/dist/workstation/desktopControl/wallpaper.js +78 -0
- package/dist/workstation/exec/attach.js +126 -0
- package/dist/workstation/exec/command.js +40 -0
- package/dist/workstation/exec/durable.js +517 -0
- package/dist/workstation/exec/fallback.js +106 -0
- package/dist/workstation/exec/policy.js +837 -0
- package/dist/workstation/exec/shaping.js +211 -0
- package/dist/workstation/exec.js +3 -112
- package/dist/workstation/files/adapters/computerFileFrames.js +51 -0
- package/dist/workstation/files/adapters/toolRequests.js +121 -0
- package/dist/workstation/files/client.js +455 -0
- package/dist/workstation/files/credentials.js +142 -0
- package/dist/workstation/files/errors.js +28 -0
- package/dist/workstation/files/fence.js +350 -0
- package/dist/workstation/files/find/fileIndex.js +153 -0
- package/dist/workstation/files/find/fuzzy.js +155 -0
- package/dist/workstation/files/host.js +122 -0
- package/dist/workstation/files/hostProtocol.js +2 -0
- package/dist/workstation/files/media/cache.js +620 -0
- package/dist/workstation/files/media/encoding.js +308 -0
- package/dist/workstation/files/media/estimator.js +100 -0
- package/dist/workstation/files/media/media.js +325 -0
- package/dist/workstation/files/media/packedAudio.js +23 -0
- package/dist/workstation/files/media/scheduler.js +551 -0
- package/dist/workstation/files/media/types.js +5 -0
- package/dist/workstation/files/scope.js +45 -0
- package/dist/workstation/files/structured.js +284 -0
- package/dist/workstation/{fileOps.js → files/text.js} +152 -39
- package/dist/workstation/files/uploads.js +351 -0
- package/dist/workstation/journal.js +65 -236
- package/dist/workstation/keepers/acp/client.js +101 -0
- package/dist/workstation/keepers/acp/envelope.js +62 -0
- package/dist/workstation/keepers/acp/host.js +419 -0
- package/dist/workstation/keepers/acp/main.js +18 -0
- package/dist/workstation/keepers/acp/memoryStream.js +121 -0
- package/dist/workstation/keepers/acp/params.js +137 -0
- package/dist/workstation/keepers/acp/protocol.js +66 -0
- package/dist/workstation/keepers/acp/recover.js +120 -0
- package/dist/workstation/keepers/acp/session.js +584 -0
- package/dist/workstation/keepers/acp/stderr.js +154 -0
- package/dist/workstation/keepers/kit/activity.js +103 -0
- package/dist/workstation/keepers/kit/bootstrap.js +164 -0
- package/dist/workstation/keepers/kit/buildVersion.js +51 -0
- package/dist/workstation/keepers/kit/bundle.js +124 -0
- package/dist/workstation/keepers/kit/client.js +432 -0
- package/dist/workstation/keepers/kit/identity.js +21 -0
- package/dist/workstation/keepers/kit/ipc.js +112 -0
- package/dist/workstation/keepers/kit/launchConfig.js +8 -0
- package/dist/workstation/keepers/kit/launcher.js +289 -0
- package/dist/workstation/keepers/kit/lock.js +123 -0
- package/dist/workstation/keepers/kit/orphanSweep.js +86 -0
- package/dist/workstation/keepers/kit/paths.js +76 -0
- package/dist/workstation/keepers/kit/protocol.js +43 -0
- package/dist/workstation/keepers/kit/server.js +518 -0
- package/dist/workstation/keepers/kit/streamLog.js +697 -0
- package/dist/workstation/keepers/legacy.js +296 -0
- package/dist/workstation/keepers/policy.js +576 -0
- package/dist/workstation/keepers/stop.js +34 -0
- package/dist/workstation/keepers/terminal/client.js +213 -0
- package/dist/workstation/keepers/terminal/exec.js +981 -0
- package/dist/workstation/keepers/terminal/generations.js +129 -0
- package/dist/workstation/keepers/terminal/keeper.js +62 -0
- package/dist/workstation/keepers/terminal/main.js +43 -0
- package/dist/workstation/keepers/terminal/orphanSweep.js +3 -0
- package/dist/workstation/keepers/terminal/params.js +27 -0
- package/dist/workstation/keepers/terminal/protocol.js +56 -0
- package/dist/workstation/keepers/terminal/pty.js +330 -0
- package/dist/workstation/managedInstall.js +57 -0
- package/dist/workstation/protocol/accountLimits.js +47 -0
- package/dist/workstation/protocol/agent.js +50 -19
- package/dist/workstation/protocol/common.js +30 -0
- package/dist/workstation/protocol/computer.js +15 -4
- package/dist/workstation/protocol/management.js +141 -4
- package/dist/workstation/protocol/runtimeDiagnostics.js +15 -0
- package/dist/workstation/rd/artifact.js +119 -0
- package/dist/workstation/rd/control.js +119 -0
- package/dist/workstation/rd/display.js +29 -0
- package/dist/workstation/rd/provider.js +222 -0
- package/dist/workstation/rd/sessions.js +391 -0
- package/dist/workstation/rd/state.js +45 -0
- package/dist/workstation/rd/update.js +171 -0
- package/dist/workstation/rd/upkeep.js +38 -0
- package/dist/workstation/register.js +27 -37
- package/dist/workstation/service/installer.js +104 -13
- package/dist/workstation/service/launchd.js +1 -0
- package/dist/workstation/storageMetrics.js +118 -0
- package/dist/workstation/systemMetrics.js +154 -93
- package/dist/workstation/toolchain.js +94 -0
- package/dist/workstation/tools/browser.js +28 -4
- package/dist/workstation/tools/client.js +9 -1
- package/dist/workstation/tools/info.js +50 -0
- package/dist/workstation/tools/keeperProcess.js +15 -5
- package/dist/workstation/tools/router.js +55 -0
- package/dist/workstation/tools/terminalRouter.js +222 -0
- package/dist/workstation/tools/validation.js +37 -1
- package/dist/workstation/update/artifact.js +2 -1
- package/dist/workstation/update/coordinator.js +3 -0
- package/dist/workstation/update/globalInstall.js +116 -0
- package/dist/workstation/update/npmInstaller.js +49 -23
- package/dist/workstation/update/ptyPreflight.js +21 -0
- package/dist/workstation/update/rdRollback.js +145 -0
- package/dist/workstation/update/runUpdate.js +3 -2
- package/dist/workstation/update/taskRegistry.js +105 -11
- package/dist/workstation/update/watchdog.js +16790 -334
- package/package.json +11 -8
- 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 -49
- 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/workstation/acp/acpSession.js +0 -1475
- package/dist/workstation/acp/contract.js +0 -499
- package/dist/workstation/acp/delegationMcp.js +0 -24
- package/dist/workstation/acp/draftInterceptor.js +0 -163
- package/dist/workstation/acp/qoderStartup.js +0 -45
- package/dist/workstation/acp/sessionScope.js +0 -19
- package/dist/workstation/filePaths.js +0 -174
- package/dist/workstation/fileWorker.js +0 -81
- package/dist/workstation/fileWorkerClient.js +0 -121
- package/dist/workstation/qoderAdapter/backgroundProcess.js +0 -106
- package/dist/workstation/qoderAdapter/backgroundTerminal.js +0 -262
- package/dist/workstation/qoderAdapter/completedContinuation.js +0 -139
- package/dist/workstation/qoderAdapter/contract.js +0 -78
- package/dist/workstation/qoderAdapter/foregroundOutput.js +0 -30
- package/dist/workstation/qoderAdapter/history.js +0 -87
- package/dist/workstation/qoderAdapter/identityIndex.js +0 -191
- package/dist/workstation/qoderAdapter/inputQueue.js +0 -42
- package/dist/workstation/qoderAdapter/main.js +0 -93
- 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 -49
- package/dist/workstation/qoderAdapter/session.js +0 -319
- package/dist/workstation/qoderAdapter/subagentMeta.js +0 -28
- package/dist/workstation/qoderAdapter/subwork.js +0 -77
- package/dist/workstation/qoderAdapter/taskControl.js +0 -38
- package/dist/workstation/qoderAdapter/taskEvent.js +0 -26
- package/dist/workstation/qoderAdapter/taskLedger.js +0 -163
- package/dist/workstation/qoderAdapter/usage.js +0 -37
- package/dist/workstation/tools/core.js +0 -50
- package/dist/workstation/tools/files.js +0 -525
- package/dist/workstation/tools/terminal.js +0 -214
- /package/dist/workstation/{qoderAdapter/types.js → desktopControl/provider.js} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @platless/axom-cli
|
|
2
2
|
|
|
3
|
-
One npm package, one bin: `axom`. An authenticated MCP client for Axomwork (`struct`/`record`/`execute`/`
|
|
3
|
+
One npm package, one bin: `axom`. An authenticated MCP client for Axomwork (`struct`/`record`/`execute`/`knowledge`), plus the personal Workstation daemon — registration, encrypted tunnels, self-update, and OS service lifecycle — merged into the same package.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -18,8 +18,9 @@ curl -s http://<your-axom-server>/download/client/manifest.json
|
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
A plain `-g` install on purpose: it puts `axom` on your `PATH` the way npm puts every other global
|
|
21
|
-
binary there.
|
|
22
|
-
|
|
21
|
+
binary there. For a manual installation, keep the existing global prefix. Desktop-managed macOS
|
|
22
|
+
installations use `~/.axom/cli` with an explicit Node runtime, installation receipt, terminal wrapper,
|
|
23
|
+
service environment and update/rollback context; do not imitate that by adding a standalone `--prefix` flag.
|
|
23
24
|
|
|
24
25
|
Verify before going further — this is the step that catches a broken install:
|
|
25
26
|
|
|
@@ -51,9 +52,19 @@ axom execute healthCheck '{}'
|
|
|
51
52
|
|
|
52
53
|
`axom workstation start` registers this machine (reusing the `axom auth` login) and installs/starts the daemon as an OS service; `stop`/`restart`/`status` control or query it; `install`/`uninstall` manage just the service definition (launchd/systemd) for manual repair.
|
|
53
54
|
|
|
55
|
+
On Debian 13 amd64, `axom workstation start --enable-rd` installs native remote desktop support and reuses the user's X11 desktop, or starts a managed Xfce desktop when none exists. `workstation rd status` reports its state; `workstation rd disable` revokes it without removing registration. See [Linux workstation RD](../docs/handbook/linux-workstation-rd.md) for session selection and package delivery.
|
|
56
|
+
|
|
57
|
+
Disk heartbeats discover mounted local data storage independently of configured workspaces.
|
|
58
|
+
Linux partitions and bind mounts are deduplicated by filesystem identity; macOS APFS volumes
|
|
59
|
+
share one entry per physical capacity container. Boot/recovery partitions, memory filesystems,
|
|
60
|
+
network shares and macOS disk images are excluded. Container overlay storage is shown only
|
|
61
|
+
when no persistent local data mount is available. Discovery refreshes every ten minutes;
|
|
62
|
+
capacity is sampled on each heartbeat. Space usage is `1 - available / total`, including
|
|
63
|
+
filesystem reserved space. Other platforms retain workspace-based discovery.
|
|
64
|
+
|
|
54
65
|
## Updating
|
|
55
66
|
|
|
56
|
-
`axom update [--version x.y.z]` upgrades `axom` itself to the release the connected server currently publishes.
|
|
67
|
+
`axom update [--version x.y.z]` upgrades `axom` itself to the release the connected server currently publishes. When a verified daemon is running, the command requests its existing update coordinator, which drains work and preserves keepers during service handoff. When stopped, it only installs the package. A busy or unverifiable daemon is not bypassed by a fresh empty task registry.
|
|
57
68
|
|
|
58
69
|
## Config
|
|
59
70
|
|
|
@@ -61,4 +72,6 @@ Non-secret CLI auth state is stored in `~/.axom/config.json` with mode `0600`. T
|
|
|
61
72
|
|
|
62
73
|
## Learn more
|
|
63
74
|
|
|
64
|
-
This README is a front page, not the manual. For the full command reference (arguments, exit codes, examples) and architecture notes, see `docs/guide/modules/cli.md` and `
|
|
75
|
+
This README is a front page, not the manual. For the full command reference (arguments, exit codes, examples) and architecture notes, see `docs/guide/modules/cli.md` and `knowledge/manual/en/agent-integration/axom-cli/` in the Axomwork monorepo this package is built from.
|
|
76
|
+
|
|
77
|
+
Desktop on macOS can install and manage this same CLI from personal Workstations. See [Desktop local workstation management](../docs/handbook/desktop-local-workstation.md). The local-management JSON protocol uses stdin for temporary authorization and never persists Desktop refresh tokens.
|
|
@@ -16,11 +16,20 @@ Workstation Docker 同样携带这份策略;普通 CLI 安装/Server 下发更
|
|
|
16
16
|
| 都不写 | 一直生效,直到删除 | 不允许 |
|
|
17
17
|
|
|
18
18
|
when 用于「这个版本有问题、已有修复版」,registry 一换版本就不再生效;until 用于「等上游发某个版本」,
|
|
19
|
-
|
|
19
|
+
钉住的版本不得高于界限:低于界限可用于等待正式修复版,等于界限可用于等待 registry 收录已发布版本。
|
|
20
|
+
两种都不需要为让位再发 CLI。
|
|
20
21
|
|
|
21
22
|
用户按正常界面安装/更新适配器即可:补充条目(Kimi Code、Command Code、ZCode)、分发源覆盖和启动环境变量通过 catalog 应用,
|
|
22
23
|
roster、Install、Update、启动统一读取同一来源。
|
|
23
|
-
|
|
24
|
+
|
|
25
|
+
**有补丁的条目必须钉版本**(2026-10-14 起的硬规则,`catalog.test.ts` 的 `patched agents stay pinned`
|
|
26
|
+
机械守卫):配方只核验过列出的版本,不钉的话 registry/npm 一发新版,Install/Update 就装上一个配方
|
|
27
|
+
不生效的包——账号配额、steering、子代理归一静默消失。钉住后 roster 上报的 `version`/`registryVersion`
|
|
28
|
+
就是生效(钉住)版本,设置页的 Update 比对(`installedVersion != registryVersion`)因此永远对着
|
|
29
|
+
catalog 的钉版本,**不对着官方 registry 比**;上游新版本要等
|
|
30
|
+
[`../DAILY_UPGRADE_CHECK.md`](../DAILY_UPGRADE_CHECK.md) 的周期任务核验移植配方后再 bump,届时
|
|
31
|
+
`reconcileCertifiedBuilds` 把已安装的工作站自动前移。
|
|
32
|
+
发布包补丁由 `managedPatches.ts` 在 Install/Update 和首次真实启动时应用。
|
|
24
33
|
历史安装也会补齐,配置显式 command 的用户自有启动程序按其配置执行。
|
|
25
34
|
|
|
26
35
|
发布包补丁步骤:
|
|
@@ -53,17 +62,27 @@ catalog 是 Axom 对官方 ACP registry 的本地扩展层,随 CLI 发布:
|
|
|
53
62
|
|
|
54
63
|
| 台账 ID | 状态/应用入口 | AI 核验与下线重点 |
|
|
55
64
|
|---|---|---|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
65
|
+
| qoder-native-acp | active;Catalog 固定官方 `@qoder-ai/qodercli@1.1.75 --acp`,由 `qoder-native-acp.json` 提供精确版本、资产和原/补丁哈希 | 与其他发布包补丁相同,Install/Update 只按 Catalog 钉版本和配方哈希应用;不读取认证表,也不要求用户提供 Qoder 登录态 |
|
|
66
|
+
| kimi-code-distribution | active;catalog.ts 补充条目 `kimi-code`(Kimi Code 2.3.3 官方二进制,六平台 tar.gz + sha256,2026-10-27 nightly),隐藏已归档的 `kimi` | registry#458 合入后补充条目自动让位、版本由 registry 跟进;验证 Install/Update、复用登录后删除 supplement |
|
|
67
|
+
| command-code-distribution | active;catalog.ts 补充条目 `command-code`(npx `command-code@1.88.0 acp`) | registry 收录后自动让位;确认 registry 版本带 `acp` 子命令后删除 supplement |
|
|
68
|
+
| zcode-acp-distribution | active;catalog.ts 补充条目 `zcode-acp`(npx `zcode-acp-server@0.76.3`),前置依赖 ZCode 本体 | registry#566/#650 合入后自动让位;删除 supplement 时保留 prerequisite |
|
|
69
|
+
| zcode-models | active;fresh-install 模型兑底并入账号目录(`loadAllModels` 兜底读 entitled builtin 表,GLM-5.3-Flash 等不再丢) | 上游 `loadAllModels` 并入账号快照目录后删除 |
|
|
70
|
+
| zcode-subagent-subwork | active;zcode-acp-server 0.76.3 四文件九编辑:`AxomZcodeSubagents` 监听器把后端 `session.updated`(agentId/childSessionId/taskId)转发为 `subagent_spawned`/`subagent_state_update`(RFD #1992)与 `async_task_*`;dispatch 把 `tool_subagent_*` 内部调用重定址到 `sess_subagent_*` 子会话,协商到原生能力时抑制 `_meta.subagent` 标记(防双投影),声明 AIR asyncTasks 时抑制上游 `[后台]` 合成卡(防与 async_task 双重呈现,workflow 折叠不受影响);`adoptStoredTitle` 在 (重)挂载时补发 `session_info_update` 同步后端已生成的标题(titleUpdated 推送会丢在 backend 重启断点上) | 上游 zcode-acp 原生发出 T2/T3 变体并路由子会话、且 load 时同步存量标题后删除配方;验收含并发、失败/取消、后台迟到、重启重放 |
|
|
59
71
|
| claude-plan-tools | active;启动任务清单工具变量 | 无变量真实 ACP 会话能发布 plan 后下线 |
|
|
60
72
|
| codex-plan-tools | active;CODEX_CONFIG 的 update_plan 开关 | 无覆盖真实 ACP 会话能发布 plan;保留显式用户配置优先级 |
|
|
61
|
-
| claude-
|
|
73
|
+
| claude-account-limits | active;配方 0.97.0,catalog 钉 0.97.0 | 上游 adapter 暴露标准化账号配额能力且不自动查询后删除;版本升级走 ../DAILY_UPGRADE_CHECK.md |
|
|
74
|
+
| codex-account-limits | active;配方 2.3.0,catalog 钉 2.3.0 | 同上 |
|
|
75
|
+
| codex-terminal-output | active;2.3.0,链在 codex-account-limits 后;终态保留完整 stdout 与退出码,避免流式输出遗漏首段 | 上游 AIR 命令终态无补丁即可保留完整输出后删除;探针 `probes/codex-terminal-output.mjs` 覆盖流式/非流式与成功/失败 |
|
|
76
|
+
| commandcode-account-limits | active;配方 1.88.0(supplement 同钉) | 同上 |
|
|
77
|
+
| antigravity-account-limits | active;native extension 1.3.0…1.4.3,catalog 钉 1.4.3(真实 .par 经 proxy 实测:透传无损、能力注入成功,最近 2026-10-25) | 官方 adapter 暴露配额读取与通知;上游发新版按 ../DAILY_UPGRADE_CHECK.md 核验后同升 |
|
|
78
|
+
| claude-async-task-preview | retired;0.86.0 钉 0.86.1-preview.2 的 override 已删除 | 修复 #1249 自 0.87.0 起入正式版;2026-10-13 无补丁原版 0.90.0 探针 6/6 通过(探针构造器参数改 `"air"`,0.90.0 将 enabled 改名为 form) |
|
|
62
79
|
| claude-late-async-terminal | retired;0.84.0/0.85.0 配方已删除 | 修复由上游 #1249 带入预览版并被采用;探针在无补丁预览版 6/6 通过 |
|
|
63
|
-
| acp-sdk-draft-variants | active;draftInterceptor
|
|
64
|
-
| acp-sdk-foreign-session | active;draftInterceptor | SDK
|
|
80
|
+
| acp-sdk-draft-variants | active;processor/updates(取代已删除的 draftInterceptor)/ draftSubagents | 发布 SDK 接收 subagent/async 变体后,验证真实通知流,再替换对应边界 |
|
|
81
|
+
| acp-sdk-foreign-session | active;processor/updates(取代已删除的 draftInterceptor) | processor 对子会话 session/update 原样直通(不经 SDK schema);正式 SDK schema 能校验子会话更新且改为先校验不丢通知后才下线;仅支持 draft 类型不足以下线 |
|
|
65
82
|
| acp-sdk-capability-fields | active;acpClient / draftSubagents | 无兼容桥 initialize 能保留 subagents,且 AIR vendor 能力协商仍有效 |
|
|
66
|
-
|
|
|
83
|
+
| pi-subagent-subwork | active;pi-acp 0.0.34 包补丁(链在 pi-steering 之后,catalog 钉 0.0.34)把 pi-subagents 派发/完成归一为 `subagent_spawned`/`subagent_state_update` | 无补丁 pi-acp 能发 T2 变体并透传 custom message 后移除;axom-cli/服务端零改动,processor 原生消费 |
|
|
84
|
+
| kimi-subagent-subwork | active;Kimi native shim 将 Agent / AgentSwarm 转为同一套 T2 子会话事件,子结果进入只读子会话;后台启动回执不算完成,读取该 ACP 会话的原生 task 状态及 output.log 补发迟到终态;load 重放使用确定性 ID,resume 复用已知子会话。不产生原始 Agent 工具卡,不伪造上游没有发送的中间推理/工具流 | 上游原生协商 subagents 时自动让位;无补丁前台/后台/失败/取消/load/resume 实测通过后删除 shim 模块 |
|
|
85
|
+
| qoder-native-acp | active;官方 Qoder 1.1.75 `--acp` 在同一进程内加载兼容 asset,沿用普通 package patch 安装路径 | 上游版本升级时重新核对原文件锚点和行为回归;通过后更新 recipe 的 `versions` 与 Catalog 钉版本 |
|
|
67
86
|
| acp-registry-etarget | active;版本不存在时单次回退 | 上游版本可安装时自然不触发;删除整个策略要检查 registry 契约 |
|
|
68
87
|
| claude-steering | draft;steering/ 的两份旧版 diff | 0.76/0.77 草案未经完整运行时验证,不自动应用;重新测 E1–E3 |
|
|
69
88
|
| codex-steering | draft;steering/ 的旧版 diff | 1.10/1.11 草案不适用于当前新版,不自动应用;重新测 E1–E3 |
|
|
@@ -71,6 +90,9 @@ catalog 是 Axom 对官方 ACP registry 的本地扩展层,随 CLI 发布:
|
|
|
71
90
|
每条完整路径、版本哈希、上游链接、删除条件与验证项见 [台账](../manifest.json)。
|
|
72
91
|
steering diff 原样来自历史 notes;维护本目录文件及台账哈希,历史归档保留实验上下文。
|
|
73
92
|
|
|
93
|
+
catalog 各 agent 的上游版本核查、补丁必要性判定与钉版本升级,按
|
|
94
|
+
[`../DAILY_UPGRADE_CHECK.md`](../DAILY_UPGRADE_CHECK.md) 的周期任务执行(AI 可直接照步骤运行).
|
|
95
|
+
|
|
74
96
|
## 验证
|
|
75
97
|
|
|
76
98
|
```bash
|
|
@@ -94,6 +116,9 @@ Pi 的发布包运行时探针(使用真实 adapter 类,不启动模型、
|
|
|
94
116
|
```bash
|
|
95
117
|
node axom-patch/cli/probes/pi-steering.mjs /path/to/pristine/pi-acp --expect-unsupported
|
|
96
118
|
node axom-patch/cli/probes/pi-steering.mjs /path/to/patched/pi-acp
|
|
119
|
+
node axom-patch/cli/probes/pi-subagent-subwork.mjs /path/to/pristine/pi-acp --expect-no-subagents
|
|
120
|
+
node axom-patch/cli/probes/pi-subagent-subwork.mjs /path/to/patched/pi-acp
|
|
121
|
+
node axom-patch/cli/probes/kimi-subagent-subwork.mjs /path/to/managed/kimi
|
|
97
122
|
```
|
|
98
123
|
|
|
99
124
|
仅已核验的原生 Pi 0.87.1 声明 `supported: true, timings: ["next"]`。其他原生版本不声明能力。
|
|
@@ -108,3 +133,88 @@ node axom-patch/cli/probes/pi-steering.mjs /path/to/patched/pi-acp
|
|
|
108
133
|
- 新增来源/环境覆盖:修改 runtime.overrides、台账和 catalog 回归,保留 registry/用户显式 env 优先级。
|
|
109
134
|
- 下线:先按统一证据门槛核验,从 runtime 移除策略或替换 SDK 边界,保留回归;台账标 retired 并记录证据。
|
|
110
135
|
- CLI 补丁变化必须 bump CLI npm version。相同版本不会触发 Server 自动升级,不能只改 Server 镜像 tag。
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
## Qoder native candidate certification (optional authoring evidence)
|
|
139
|
+
|
|
140
|
+
这套认证脚本只服务于维护者做版本升级和补丁退休判断,不参与 CLI 的安装、启动或版本选择。
|
|
141
|
+
Qoder 的当前运行路径和其他普通发布包补丁一致:Catalog 固定 `1.1.75`,`qoder-native-acp.json`
|
|
142
|
+
按包版本和文件哈希应用。用户不需要认证表,也不需要先把 Qoder 登录态复制给 Axom;Qoder 自己在真正调用模型时的登录仍由 Qoder 管理。
|
|
143
|
+
因此缺少某个平台的认证记录不会阻止普通补丁在该平台安装。
|
|
144
|
+
`runtime.json` 的 `install_policies` 为 `@qoder-ai/qodercli` 声明 `ignore_scripts: true`:它的 postinstall 会执行
|
|
145
|
+
`configure-path` 改写用户的 `~/.qoder/entry` 与 PATH,托管安装不能有这种副作用。这条策略与认证无关,只控制 npm lifecycle scripts。
|
|
146
|
+
|
|
147
|
+
`qoder/scripts/certify.mjs --candidate <dir> --evidence <dir> --platform <platform> --arch <arch>`
|
|
148
|
+
consumes the exact generated package plus sibling `.release.json` and `.recipe.json`.
|
|
149
|
+
The command runs a bounded real initialize in a new isolated HOME/cwd. Explicit
|
|
150
|
+
`--auth-home <source>` copies only the auth allowlist and enables the native model/tool
|
|
151
|
+
cases in `src/test/certificationCases.ts`; credentials and isolated HOME contents are
|
|
152
|
+
excluded from evidence artifact manifests. No SDK, relay or extra runtime
|
|
153
|
+
agent is introduced. stderr (including upstream DEP0169) is retained separately from
|
|
154
|
+
unmodified JSON-RPC traffic. Request IDs, native root/child IDs and tool IDs are retained.
|
|
155
|
+
`--collect-only` verifies records in `<evidence>/records/*.json` without model execution.
|
|
156
|
+
The command is directly executable with supported Node 24 from this authoring checkout.
|
|
157
|
+
|
|
158
|
+
Required checks are `initialize`, `ordinary-input`, `permissions`, `images-settings`,
|
|
159
|
+
`parallel-subagents`, `background-reconnect`, `next-append`, `next-button`, `stop`,
|
|
160
|
+
`cached-resume`, `legacy-migration`, `explicit-load`, `replay`, `install-gates`, `platform`.
|
|
161
|
+
Missing, duplicate, unknown, failed, mismatched or synthetic records produce NOT_PASS
|
|
162
|
+
and a nonzero exit. Native tests cannot replace real UI insert-button evidence. The
|
|
163
|
+
background case currently covers completion after the root response followed by process
|
|
164
|
+
reconnect; it does not establish arbitrary mid-flight crash recovery. Migration, replay,
|
|
165
|
+
installer and actual platform/UI evidence remain separate required producers.
|
|
166
|
+
|
|
167
|
+
Digest schema v1 uses canonical JSON: recursively lexicographically sorted plain-object
|
|
168
|
+
keys, array order preserved, JSON scalar encoding, finite numbers only; non-JSON values
|
|
169
|
+
are rejected. `candidateDigest` is SHA256 of canonical
|
|
170
|
+
`{domain:"axom-qoder-candidate-v1",release:<all release fields except certification>,
|
|
171
|
+
suite:{id:<certification.suite>,files:<trusted source manifest>},actualFiles:<map>}`.
|
|
172
|
+
The source manifest is the fixed `suiteFiles` list in `scripts/release.mjs`, read from
|
|
173
|
+
this checkout; `suiteDigest` is SHA256 of canonical suite. `actualFiles` is the complete
|
|
174
|
+
regular main-package map, excluding external `node_modules`, and must exactly equal
|
|
175
|
+
`release.files`. Symlinks and unsafe paths refuse. New runtime fields are automatically
|
|
176
|
+
bound; this includes `historyVersions`, `bin.args`, `runtimeTools`, and `patchDigest`.
|
|
177
|
+
The latter is exactly SHA256(JSON.stringify(orderedRecipeObjects)), matching
|
|
178
|
+
`managedPatches.patchDigest`, including asset records. No alternate recipe hash is used.
|
|
179
|
+
|
|
180
|
+
Each evidence record is `{schema:1,name,status,kind,releaseId,candidateDigest,suiteDigest,
|
|
181
|
+
platform,arch,node:{version,sha256},runtime:{dependencies,tools},artifacts:[{path,sha256}],
|
|
182
|
+
detail?:<JSON>}`. `kind` is `real` or `test`. Artifact paths are relative to the evidence
|
|
183
|
+
root. Node identity is the actual executing binary, not a supplied label. Dependencies
|
|
184
|
+
record resolved direct/optional package versions and package.json hashes; tools record
|
|
185
|
+
exact package/name/version, path, platform/arch, SHA256 and executability. Required
|
|
186
|
+
native tool declarations must be authored before certification. This does not claim a
|
|
187
|
+
complete third-party byte closure: npm integrity installation remains the dependency
|
|
188
|
+
trust boundary. The verifier recomputes candidate, suite, Node, platform, dependencies,
|
|
189
|
+
tools and artifact bytes before and after native work. A changed source manifest or any
|
|
190
|
+
runtime-relevant release field invalidates old evidence. The synthetic reducer fixtures
|
|
191
|
+
may report `schemaValid:true`, but always remain NOT_PASS for release authorization.
|
|
192
|
+
|
|
193
|
+
Every invocation creates a fresh directory and writes result files exclusively.
|
|
194
|
+
`result.sha256` hashes the exact UTF-8 `result.json` bytes (canonical JSON plus newline).
|
|
195
|
+
The result contains records and bindings but no digest of itself. Final release
|
|
196
|
+
`certification.checks/platforms` may therefore be assembled after verified real PASS
|
|
197
|
+
without self-reference: only certification is excluded from the candidate projection,
|
|
198
|
+
and its suite identity remains separately bound. Promotion must rerun `--collect-only`
|
|
199
|
+
on the final bytes, use the verified result digest for its platform and exact record
|
|
200
|
+
bytes/digests for checks, and preserve each platform/Node evidence relationship. Never
|
|
201
|
+
reuse another platform's PASS by editing a label or copy PASS across regenerated bytes.
|
|
202
|
+
|
|
203
|
+
Next evidence observes the original tool's real start artifact and in-progress stream,
|
|
204
|
+
then appends next input and checks original completion plus appended-input files on the
|
|
205
|
+
same root and single ACP prompt. A test-only native root engine wrapper counts actual
|
|
206
|
+
`submitMessage`/`abort` calls; its transformed entry hash and original hash are recorded.
|
|
207
|
+
An uninstrumented final-byte rerun is mandatory. Stop is tested separately, including
|
|
208
|
+
queued-next removal and cancellation while a permission request is pending. Runtime
|
|
209
|
+
instrumentation is never added to the generated release package.
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
Ordinary-tool acceptance requires distinct original Bash, Read and Grep tool IDs, an
|
|
213
|
+
exact-ID successful terminal update for each, and the unique artifact marker in actual
|
|
214
|
+
Read/Grep result text. A successful Bash file alone cannot hide a missing/failed helper.
|
|
215
|
+
Stop uses a unique queued nonce and a neutral followup. After native writer/process
|
|
216
|
+
closure, the harness copies the full root transcript bytes, verifies root/cwd/version,
|
|
217
|
+
requires the followup's original userMessageId, and rejects any consumed queued nonce.
|
|
218
|
+
Both next runs provide a positive native `queued_command`/`source_uuid` history control.
|
|
219
|
+
These transcript snapshots are hashed artifacts; failed/partial/forced-kill snapshots
|
|
220
|
+
cannot establish removal. Known upstream DEP0169 remains visible in stderr.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Account quota extension
|
|
2
|
+
|
|
3
|
+
Axom extension, not an upstream ACP standard. ACP extension methods use `_axom/account/rateLimits/read` and `_axom/account/rateLimits/updated`. Capability: `agentCapabilities._meta["axom/accountRateLimits"] = {version: 2, read: true, updated: true}`. A read's result and an update's params have the same snapshot schema.
|
|
4
|
+
|
|
5
|
+
Only the popover footer sends a read. Initialization, authentication, reconnects, session changes, turns, opening UI and reset deadlines do not query quota. Native Codex and Claude quota events are normalized without fetching. Command, Kimi and Antigravity publish updates from explicit reads; they do not synthesize a polling loop. UI SSE streams only database state.
|
|
6
|
+
|
|
7
|
+
Initialization publishes an identity-only unknown observation of adapter support. It does not establish quota display eligibility. Reconnects replay each live session's cached observation with its original timestamp; they never fetch usage. A pre-upgrade hello roster cannot hide a stored capability observation. Version-gated installed native extensions also advertise support in the roster without spawning or querying the provider.
|
|
8
|
+
|
|
9
|
+
Snapshots contain `schemaVersion`, `provider`, `billingMode`, `availability`, `observedAt`, nullable `plan`, independent `limits`, `balances` and bounded `_meta`. Optional `accountKey` must be opaque, never a credential. Modes are `subscription`, `non_subscription`, `unknown`; missing authentication or temporarily unavailable quota is unknown, not proof of API billing. `ExternalAgentAccountDto.supportsQuotaDisplay` is the shared eligibility rule for UI and server refresh: adapter support plus confirmed subscription billing, or an independent quota checker with unknown billing. The server identifies the existing Command Code, ZCode, Kimi and Antigravity readers through `quotaCheckerAvailable`, preserving their first manual discovery action. Non-subscription accounts expose no quota entry, and rejected refreshes do not claim a cooldown or contact the adapter. Codex/Claude authentication notifications establish billing without fetching quota; their unknown accounts remain hidden. Switching authentication publishes a complete identity snapshot to clear previous windows. Their processor also refuses quota reads until subscription authentication is confirmed. Future server-configured quota checkers should use this shared capability rather than add provider-specific UI branches.
|
|
10
|
+
|
|
11
|
+
Windows use integer seconds (monthly calendar periods use `period: "month"`), percentage consumed in 0..100, ISO UTC timestamps and nullable unknown values. Absolute credits or monetary values are decimal strings; money uses currency and exponent. Scoped model quotas remain detailed rows, not duplicated general rings. When only model quotas exist, one ring represents the most used model, with an explicit popover explanation. Vendor fields remain under `_meta._codex`, `_claude`, `_kimi`, `_commandcode`, `_antigravity`. Latest snapshots persist per workstation/configured entry; delayed older updates are ignored. A server transaction admits one refresh per 60 seconds, including failures. Errors preserve the prior snapshot.
|
|
12
|
+
|
|
13
|
+
Verified managed versions: Codex ACP 2.2.2; Claude ACP 0.89.1 (SDK experimental usage control); Command Code 1.74.3; native Kimi Code 2.1.1; ZCode ACP 0.69.3. New versions do not inherit unverified patches. Regenerate the npm recipes with `generate.py --codex <pristine-package-dir> --claude <pristine-package-dir> --commandcode <pristine-package-dir> [--zcode <pristine-package-dir>]`; update inventory artifact hashes after changes. Never patch a user's global installation.
|
|
14
|
+
|
|
15
|
+
Kimi's native shim starts a temporary loopback web process only during an explicit read and calls the SDK-backed local usage route; process cleanup is bounded. Its native provider catalog identifies actual API credentials before querying managed quota. The common launcher selects this shim from `runtime.json.native_extensions`. Claude uses an existing session's query when possible, otherwise a nonpersistent SDK control session. Neither submits a model inference request for quota. Native payload availability can vary with login/provider/version; failed reads are surfaced without overwriting previous observations.
|
|
16
|
+
|
|
17
|
+
`updateMode: "snapshot"` means a complete read or observation; `"delta"` updates only its supplied windows/balances. The server merges deltas transactionally by id (or equivalent window/scope for legacy Claude ids). Null partial measurements retain known values in the same reset period, with one-second timestamp rounding tolerance; a changed period becomes unknown rather than borrowing old utilization. Complete reads remove windows that are absent. Legacy update notifications without an explicit mode are treated as deltas by the CLI. Capability v2 lets explicit reads avoid old v1 session processes. No automatic query was added.
|
|
18
|
+
|
|
19
|
+
Command's month window uses its native `getPlanInfo` allowance and remaining monthly credits; billing `currentPeriodEnd` supplies reset time. Unknown plans have unknown percentage rather than an inferred cap. Purchased/free credits stay separate balances. Claude emits only the affected event window; the weekly snapshot is first acquired through the footer's manual refresh and survives subsequent 5-hour events.
|
|
20
|
+
|
|
21
|
+
ZCode's read resolves the individual coding-plan key through the adapter's own credential chain (`codingPlanRequestAuthFor`: legacy config.json first, then the encrypted `~/.zcode/v2/credentials.json` store #320 — the adapter's own `/quota` and `account/usage_stats` still read config.json only and stay broken on fresh 3.14.x installs; fixed upstream when they adopt the store path). The GLM quota endpoint returns plan `level` plus `limits[]` rows: `TOKENS_LIMIT number=5` is the 5h prompt window (percentage-only, no counters), `number=7` a weekly window when a plan has one, `TIME_LIMIT`/`MCP_LIMIT` the built-in tool allowance with absolute call counts and per-model detail (kept in `_meta._zcode`). The endpoint offers no monthly window on any measured plan; nothing is inferred. The read throws when no entitled individual plan is servable (team keys are deliberately not served by the adapter), which surfaces as a standard refresh failure.
|
|
22
|
+
|
|
23
|
+
Antigravity's native extension is limited to official ACP **1.3.0**. Its bundled discovery document defines `ModelDetails.quotaInfo.remainingFraction` (remaining, not consumed), `resetTime`, and `UserTier.availableCredits`. The sidecar reproduces the native consumer `loadCodeAssist` endpoint selection and reads `fetchAvailableModels` only on an explicit read. It does not perform onboarding, inference, alter settings, or write refreshed OAuth credentials. It uses the same `GEMINI_HOME/antigravity-acp` settings and consumer token store (`gemini` / `antigravity-acp` Keychain on macOS, secure-file fallback; `AGY_ACP_FORCE_FILE_STORAGE` respected). Explicit successful ACP authentication overrides the file's auth type. API key, Agent Platform, enterprise OAuth and gateway are outside this consumer subscription integration.
|
|
24
|
+
|
|
25
|
+
The quota schema supplies no window duration or monthly allowance: keep `windowSeconds: null`, list each model and its reset, and keep AI credits as a balance. Do not infer shared buckets from identical percentages/reset times. Extensions allowlist quota/tier fields and exclude project, tokens and account identity. Official ACP `usage_update` is context-token usage, not an account quota notification; it is never converted into subscription usage. No spontaneous account quota notification is exposed in 1.3.0. Protocol/normalization tests pass against the bundled native schema; a live read on the development machine could not be measured because its Keychain credential read timed out. A locked/inaccessible store surfaces the standard refresh failure and preserves the last snapshot.
|
|
26
|
+
|
|
27
|
+
Antigravity quota capability v3 fixes interactive Keychain authorization: the first explicit read permits up to 120 seconds for the OS dialog, within longer quota-specific CLI/server/client deadlines. A successful credential read and refreshed access token stay only in the reader process's memory; subsequent manual reads do not re-open Keychain. Explicit authentication/logout invalidates that cache, and failed credential loads are retryable. This matters because the native ACP credential writer deletes and recreates the Keychain item, potentially invalidating previous per-item “Always Allow” grants. No ACL, partition list or native credential file is modified by Axom. Older v2 model sessions are bypassed for quota reads without interruption. When necessary, a separate control connection is retained across manual reads, closed on authentication changes and CLI shutdown; it performs no background quota queries. Tests simulate delayed authorization and repeated reads without invoking the real password dialog; live OS authorization remains a user-side verification step.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Version-gated native ACP sidecar. Never queries on initialize, auth, turns or timers. */
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { createInterface } from 'node:readline';
|
|
4
|
+
import { READ, UPDATED, CAPABILITY } from './normalize.mjs';
|
|
5
|
+
import { readAntigravity, clearAntigravityCredentials } from './antigravity-read.mjs';
|
|
6
|
+
const [binary, ...args] = process.argv.slice(2);
|
|
7
|
+
const child = spawn(binary, args, { stdio: ['pipe', 'pipe', 'inherit'], env: process.env });
|
|
8
|
+
const write = value => process.stdout.write(JSON.stringify(value) + '\n');
|
|
9
|
+
let initializeId, authType, reading = false;
|
|
10
|
+
const authRequests = new Map();
|
|
11
|
+
createInterface({ input: child.stdout }).on('line', line => {
|
|
12
|
+
let message; try { message = JSON.parse(line); } catch { process.stdout.write(line + '\n'); return; }
|
|
13
|
+
if (message.id === initializeId && message.result) {
|
|
14
|
+
message.result.agentCapabilities ??= {};
|
|
15
|
+
message.result.agentCapabilities._meta ??= {};
|
|
16
|
+
message.result.agentCapabilities._meta['axom/accountRateLimits'] = { ...CAPABILITY, version: 5, provider: 'antigravity' };
|
|
17
|
+
}
|
|
18
|
+
if (authRequests.has(message.id)) {
|
|
19
|
+
if (message.result && !message.error) { authType = authRequests.get(message.id); clearAntigravityCredentials(); }
|
|
20
|
+
authRequests.delete(message.id);
|
|
21
|
+
}
|
|
22
|
+
write(message);
|
|
23
|
+
});
|
|
24
|
+
createInterface({ input: process.stdin }).on('line', line => {
|
|
25
|
+
let message; try { message = JSON.parse(line); } catch { child.stdin.write(line + '\n'); return; }
|
|
26
|
+
if (message.method === 'initialize') initializeId = message.id;
|
|
27
|
+
if (message.method === 'authenticate' && message.id !== undefined) authRequests.set(message.id, message.params?.methodId);
|
|
28
|
+
if (message.method === 'logout') { authType = undefined; clearAntigravityCredentials(); }
|
|
29
|
+
if (message.method === READ && message.id !== undefined) {
|
|
30
|
+
if (reading) { write({ jsonrpc: '2.0', id: message.id, error: { code: -32603, message: 'A usage refresh is already in progress' } }); return; }
|
|
31
|
+
reading = true;
|
|
32
|
+
void readAntigravity({ authType }).then(result => {
|
|
33
|
+
write({ jsonrpc: '2.0', id: message.id, result });
|
|
34
|
+
write({ jsonrpc: '2.0', method: UPDATED, params: result });
|
|
35
|
+
}, error => {
|
|
36
|
+
if (/^Antigravity (oauth|account|quota) request failed \(HTTP \d{3}\)$/.test(error?.message ?? '')) process.stderr.write(`${error.message}\n`);
|
|
37
|
+
write({ jsonrpc: '2.0', id: message.id, error: { code: -32603, message: 'Failed to fetch usage' } });
|
|
38
|
+
})
|
|
39
|
+
.finally(() => { reading = false; });
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
child.stdin.write(line + '\n');
|
|
43
|
+
});
|
|
44
|
+
process.stdin.on('end', () => child.stdin.end());
|
|
45
|
+
for (const signal of ['SIGTERM', 'SIGINT']) process.on(signal, () => child.kill(signal));
|
|
46
|
+
child.on('error', () => { process.exitCode = 1; });
|
|
47
|
+
child.on('exit', code => process.exit(code ?? 1));
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/** All credential access and network I/O occur only inside an explicit quota read. */
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { execFile } from 'node:child_process';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { homedir, type, machine } from 'node:os';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { antigravity } from './antigravity.mjs';
|
|
8
|
+
const execute = promisify(execFile);
|
|
9
|
+
const PROD = 'https://cloudcode-pa.googleapis.com';
|
|
10
|
+
const DAILY = 'https://daily-cloudcode-pa.googleapis.com';
|
|
11
|
+
// Official ACP 1.3.0 useragent.py: CCPA uses the antigravity token to resolve
|
|
12
|
+
// client-specific entitlements. A generic fetch User-Agent resolves the wrong tier.
|
|
13
|
+
const USER_AGENT = `antigravity/acp/1.3.0 (aidev_client; os_type=${process.platform === 'win32' ? 'windows' : type().toLowerCase()}; arch=${machine().toLowerCase()}; host_path=axom/unknown; proxy_client=antigravity/sdk)`;
|
|
14
|
+
async function jsonFile(path) {
|
|
15
|
+
try { return JSON.parse(await readFile(path, 'utf8')); }
|
|
16
|
+
catch (error) { if (error.code === 'ENOENT') return null; throw new Error('Failed to read Antigravity settings'); }
|
|
17
|
+
}
|
|
18
|
+
export async function loadAntigravityCredentials(root, env, { platform = process.platform, executeKeychain = execute } = {}) {
|
|
19
|
+
if (platform === 'darwin' && !['1', 'true'].includes(env.AGY_ACP_FORCE_FILE_STORAGE)) {
|
|
20
|
+
try {
|
|
21
|
+
// This is an interactive authorization, not a three-second background probe.
|
|
22
|
+
const { stdout } = await executeKeychain('/usr/bin/security', ['find-generic-password', '-s', 'gemini', '-a', 'antigravity-acp', '-w'], { timeout: 120000, maxBuffer: 65536 });
|
|
23
|
+
return JSON.parse(stdout);
|
|
24
|
+
} catch { /* Official store's secure-file fallback; never prompt for login here. */ }
|
|
25
|
+
}
|
|
26
|
+
return jsonFile(join(root, 'acp_token.json'));
|
|
27
|
+
}
|
|
28
|
+
/** Process-local only. A native token rewrite must not make every footer refresh reauthorize. */
|
|
29
|
+
export function createCredentialCache(read) {
|
|
30
|
+
const entries = new Map();
|
|
31
|
+
return {
|
|
32
|
+
clear: () => entries.clear(),
|
|
33
|
+
async load(root, env) {
|
|
34
|
+
const key = `${root}:${env.AGY_ACP_FORCE_FILE_STORAGE ?? ''}`;
|
|
35
|
+
if (!entries.has(key)) {
|
|
36
|
+
const pending = Promise.resolve().then(() => read(root, env));
|
|
37
|
+
entries.set(key, pending);
|
|
38
|
+
void pending.then(value => { if (!value && entries.get(key) === pending) entries.delete(key); }, () => { if (entries.get(key) === pending) entries.delete(key); });
|
|
39
|
+
}
|
|
40
|
+
return entries.get(key);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const credentialCache = createCredentialCache(loadAntigravityCredentials);
|
|
45
|
+
export const clearAntigravityCredentials = () => credentialCache.clear();
|
|
46
|
+
export async function readAntigravity({ authType, env = process.env, request = fetch, loadCredentials = credentialCache.load } = {}) {
|
|
47
|
+
const root = join(env.GEMINI_HOME?.trim() || join(homedir(), '.gemini'), 'antigravity-acp');
|
|
48
|
+
authType ??= (await jsonFile(join(root, 'settings.json')))?.auth?.type;
|
|
49
|
+
if (authType !== 'oauth-personal') return antigravity({}, authType);
|
|
50
|
+
const saved = await loadCredentials(root, env);
|
|
51
|
+
if (!saved) throw new Error('Antigravity credentials unavailable');
|
|
52
|
+
const signal = AbortSignal.timeout(20000);
|
|
53
|
+
const call = async (url, body, headers = {}) => {
|
|
54
|
+
const response = await request(url, { method: 'POST', headers, body, signal });
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
if (url === 'https://oauth2.googleapis.com/token' || response.status === 401) credentialCache.clear();
|
|
57
|
+
// No response bodies, project identifiers or credentials in diagnostics.
|
|
58
|
+
const stage = url.endsWith('/token') ? 'oauth' : url.endsWith(':loadCodeAssist') ? 'account' : 'quota';
|
|
59
|
+
throw new Error(`Antigravity ${stage} request failed (HTTP ${response.status})`);
|
|
60
|
+
}
|
|
61
|
+
return response.json();
|
|
62
|
+
};
|
|
63
|
+
let token = saved.token;
|
|
64
|
+
const expiry = Date.parse(saved.expiry ?? '');
|
|
65
|
+
if (!token || !Number.isFinite(expiry) || expiry <= Date.now() + 60000) {
|
|
66
|
+
if (!saved.refresh_token || !saved.client_id || !saved.client_secret) throw new Error('Antigravity credentials expired');
|
|
67
|
+
const refreshed = await call('https://oauth2.googleapis.com/token', new URLSearchParams({
|
|
68
|
+
grant_type: 'refresh_token', refresh_token: saved.refresh_token, client_id: saved.client_id, client_secret: saved.client_secret,
|
|
69
|
+
}), { 'Content-Type': 'application/x-www-form-urlencoded' });
|
|
70
|
+
token = refreshed.access_token;
|
|
71
|
+
if (typeof token === 'string' && token) {
|
|
72
|
+
saved.token = token;
|
|
73
|
+
saved.expiry = typeof refreshed.expires_in === 'number' && Number.isFinite(refreshed.expires_in) && refreshed.expires_in > 0 && refreshed.expires_in <= 86400
|
|
74
|
+
? new Date(Date.now() + refreshed.expires_in * 1000).toISOString() : undefined;
|
|
75
|
+
}
|
|
76
|
+
// Keep refresh in memory: a quota read must not race the native adapter's credential writes.
|
|
77
|
+
}
|
|
78
|
+
if (typeof token !== 'string' || !token) throw new Error('Antigravity credentials unavailable');
|
|
79
|
+
const headers = { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': USER_AGENT };
|
|
80
|
+
const load = await call(`${PROD}/v1internal:loadCodeAssist`, JSON.stringify({ metadata: { ideType: 'ANTIGRAVITY' } }), headers);
|
|
81
|
+
const project = load.cloudaicompanionProject ?? saved.project_id;
|
|
82
|
+
if (typeof project !== 'string' || !project) throw new Error('Antigravity account is not onboarded');
|
|
83
|
+
// Match the official consumer ACP endpoint selection; never perform onboarding or change settings.
|
|
84
|
+
const endpoint = load.paidTier?.usesGcpTos === true ? PROD : DAILY;
|
|
85
|
+
const summary = await call(`${endpoint}/v1internal:retrieveUserQuotaSummary`, JSON.stringify({ project }), headers);
|
|
86
|
+
if (!Array.isArray(summary.groups) && !Array.isArray(summary.buckets)) throw new Error('Invalid Antigravity quota response');
|
|
87
|
+
const result = antigravity({ quotaSummary: summary, currentTier: load.currentTier, paidTier: load.paidTier }, authType);
|
|
88
|
+
if (result.availability === 'unavailable') throw new Error('Antigravity quota unavailable');
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Antigravity ACP 1.3.0: schema from its bundled Cloud Code discovery document. */
|
|
2
|
+
import { windowKey } from './normalize.mjs';
|
|
3
|
+
export function antigravity(raw = {}, authType, observedAt = new Date().toISOString()) {
|
|
4
|
+
const billingMode = authType === 'oauth-personal' ? 'subscription'
|
|
5
|
+
: ['gemini-api-key', 'vertex-ai', 'agent-platform', 'oauth-business', 'gateway'].includes(authType) ? 'non_subscription' : 'unknown';
|
|
6
|
+
const tier = raw.paidTier ?? raw.currentTier;
|
|
7
|
+
// Deliberate allowlist: never persist tokens, account email, project or routing metadata.
|
|
8
|
+
const models = Object.fromEntries(Object.entries(raw.models ?? {}).map(([id, m]) => [id, {
|
|
9
|
+
displayName: m?.displayName, quotaInfo: m?.quotaInfo ? { remainingFraction: m.quotaInfo.remainingFraction, resetTime: m.quotaInfo.resetTime } : undefined,
|
|
10
|
+
}]));
|
|
11
|
+
const out = { schemaVersion: 1, updateMode: 'snapshot', provider: 'antigravity', billingMode,
|
|
12
|
+
availability: billingMode === 'subscription' ? 'available' : billingMode === 'unknown' ? 'unknown' : 'not_applicable',
|
|
13
|
+
observedAt, plan: tier?.id ? { id: tier.id, label: tier.name ?? tier.id } : null,
|
|
14
|
+
limits: [], balances: [], _meta: { _antigravity: { authType, models } } };
|
|
15
|
+
if (billingMode !== 'subscription') return out;
|
|
16
|
+
// Use Google's summary buckets, never infer shared pools or periods from model names.
|
|
17
|
+
const summary = raw.quotaSummary ?? {};
|
|
18
|
+
const groups = Array.isArray(summary.groups) ? summary.groups : [];
|
|
19
|
+
const rows = groups.length ? groups.flatMap(g => (g.buckets ?? []).map(bucket => ({ bucket, group: g.displayName })))
|
|
20
|
+
: (summary.buckets ?? []).map(bucket => ({ bucket, group: bucket.bucketId?.startsWith('gemini-') ? 'Gemini Models'
|
|
21
|
+
: bucket.bucketId?.startsWith('3p-') ? 'Claude and GPT models' : bucket.displayName }));
|
|
22
|
+
out._meta._antigravity.quotaSummary = { groups: [] };
|
|
23
|
+
const seen = new Set();
|
|
24
|
+
for (const { bucket: q, group } of rows) {
|
|
25
|
+
if (typeof q.bucketId !== 'string' || !q.bucketId || seen.has(q.bucketId)) continue;
|
|
26
|
+
seen.add(q.bucketId);
|
|
27
|
+
const fraction = q.remainingFraction;
|
|
28
|
+
const valid = typeof fraction === 'number' && Number.isFinite(fraction) && fraction >= 0 && fraction <= 1;
|
|
29
|
+
const usedPercent = valid ? Math.round((1 - fraction) * 10000) / 100 : null;
|
|
30
|
+
const date = typeof q.resetTime === 'string' ? new Date(q.resetTime) : null;
|
|
31
|
+
const windowSeconds = q.window === 'weekly' ? 604800 : q.window === '5h' ? 18000 : null;
|
|
32
|
+
out.limits.push({ id: `antigravity.${q.bucketId}`, label: q.displayName ?? q.bucketId, kind: 'subscription',
|
|
33
|
+
windowSeconds, key: windowKey(windowSeconds), usedPercent, resetsAt: date && Number.isFinite(date.getTime()) ? date.toISOString() : null,
|
|
34
|
+
active: q.disabled !== true,
|
|
35
|
+
status: !valid || q.disabled === true ? 'unknown' : fraction === 0 ? 'blocked' : usedPercent >= 80 ? 'warning' : 'allowed',
|
|
36
|
+
scope: { group: { id: q.bucketId.replace(/-(weekly|5h)$/, ''), display_name: group ?? 'Model quota' } } });
|
|
37
|
+
out._meta._antigravity.quotaSummary.groups.push({ displayName: group, bucketId: q.bucketId,
|
|
38
|
+
window: q.window, remainingFraction: valid ? fraction : null, resetTime: out.limits.at(-1).resetsAt, disabled: q.disabled === true });
|
|
39
|
+
}
|
|
40
|
+
for (const credit of tier?.availableCredits ?? []) {
|
|
41
|
+
const remaining = typeof credit.creditAmount === 'string' && /^\d+$/.test(credit.creditAmount) ? credit.creditAmount : null;
|
|
42
|
+
if (credit.creditType === 'GOOGLE_ONE_AI') out.balances.push({ id: 'antigravity.google-one-ai', label: 'AI credits', remaining, unit: 'credits', unlimited: false });
|
|
43
|
+
}
|
|
44
|
+
if (!out.limits.length && !out.balances.length) out.availability = 'unavailable';
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import json,hashlib
|
|
3
|
+
import argparse
|
|
4
|
+
parser=argparse.ArgumentParser(description='Regenerate exact-version quota recipes from pristine adapter package directories')
|
|
5
|
+
for name in ('codex','claude','commandcode'): parser.add_argument('--'+name,required=True,type=Path)
|
|
6
|
+
parser.add_argument('--zcode',required=False,type=Path,help='Also regenerate the zcode recipe (zcode-acp-server)')
|
|
7
|
+
options=parser.parse_args()
|
|
8
|
+
root=Path(__file__).resolve().parents[3]
|
|
9
|
+
module=(root/'axom-patch/cli/account-limits/normalize.mjs').read_text().replace('export ','')
|
|
10
|
+
helper='\nconst axomQuota = (() => {\n'+module+'\nreturn {READ,UPDATED,CAPABILITY,codex,codexEvent,claude,claudeEvent,kimi,commandcode,zcode};\n})();\nconst axomQuotaNotify = snapshot => process.stdout.write(JSON.stringify({jsonrpc:"2.0",method:axomQuota.UPDATED,params:snapshot})+"\\n");\n'
|
|
11
|
+
roots={name:getattr(options,name) for name in ('codex','claude','commandcode')}
|
|
12
|
+
if options.zcode: roots['zcode']=options.zcode
|
|
13
|
+
def patch(kind,file,version,pkg,changes,suffix='-account-limits',helper_text=helper,root_dir=None):
|
|
14
|
+
s=((root_dir or roots[kind])/file).read_text(); edits=[]
|
|
15
|
+
# The helper follows imports/shebang safely. Appending declarations executes before asynchronous requests.
|
|
16
|
+
if helper_text is not None:
|
|
17
|
+
changes.append((s[:100], (s.split('\n',1)[0]+'\n'+helper_text+s.split('\n',1)[1][:100-len(s.split('\n',1)[0])-1]) if s.startswith('#!') else helper_text+s[:100]))
|
|
18
|
+
for before,after in changes:
|
|
19
|
+
assert s.count(before)==1,(kind,before[:60],s.count(before))
|
|
20
|
+
n=s.replace(before,after)
|
|
21
|
+
edits.append(dict(file=file,before_sha256=hashlib.sha256(s.encode()).hexdigest(),after_sha256=hashlib.sha256(n.encode()).hexdigest(),before=before,after=after))
|
|
22
|
+
s=n
|
|
23
|
+
recipe=dict(id=kind+suffix,package=pkg,versions=[version],edits=edits)
|
|
24
|
+
(root/f'axom-patch/cli/{kind}{suffix}.json').write_text(json.dumps(recipe,ensure_ascii=False,indent=2)+'\n')
|
|
25
|
+
# No initialization queries: only declare the capability, and forward native events.
|
|
26
|
+
patch('codex','dist/index.js','2.3.0','@agentclientprotocol/codex-acp',[
|
|
27
|
+
# 2.3.0 repeats the authStatus line in a second capabilities block; extend through the
|
|
28
|
+
# initialize-only follower (authMethods:) to stay unique.
|
|
29
|
+
('[AUTH_STATUS_META_KEY]: authStatusCapability()\n }\n },\n authMethods:','[AUTH_STATUS_META_KEY]: authStatusCapability(), "axom/accountRateLimits": {...axomQuota.CAPABILITY,provider:"codex",authBillingModes:{account:"subscription",api_key:"non_subscription",external:"non_subscription",gateway:"non_subscription",none:"unknown"}}\n }\n },\n authMethods:'),
|
|
30
|
+
('this.handleRateLimitsUpdated(notification.params);\n return null;', 'this.handleRateLimitsUpdated(notification.params);\n axomQuotaNotify(axomQuota.codexEvent(notification.params, this.sessionState.account?.type ?? "unknown"));\n return null;'),
|
|
31
|
+
('.onRequest("authentication/status", emptyExtensionParamsParser,', '.onRequest(axomQuota.READ, emptyExtensionParamsParser, async () => { const agent=getAgent(); const account=(await agent.runWithProcessCheck(()=>agent.codexAcpClient.getAccount())).account; if (!account) throw new Error("Not authenticated"); if (account.type !== "chatgpt") return axomQuota.codex({},account.type); const raw=await agent.runWithProcessCheck(()=>agent.codexAcpClient.getRateLimits()); const snapshot=axomQuota.codex(raw,account.type); axomQuotaNotify(snapshot); return snapshot; }).onRequest("authentication/status", emptyExtensionParamsParser,')])
|
|
32
|
+
patch('claude','dist/acp-agent.js','0.97.0','@agentclientprotocol/claude-agent-acp',[
|
|
33
|
+
('authStatus: authStatusCapability(),','authStatus: authStatusCapability(), "axom/accountRateLimits": {...axomQuota.CAPABILITY,provider:"claude",authBillingModes:{account:"subscription",api_key:"non_subscription",external:"non_subscription",gateway:"non_subscription",none:"unknown"}},'),
|
|
34
|
+
('case "rate_limit_event": {','case "rate_limit_event": {\n this.axomAccountLimits = axomQuota.claudeEvent(message.rate_limit_info, this.axomAccountLimits);\n axomQuotaNotify(this.axomAccountLimits);'),
|
|
35
|
+
('.onRequest(methods.agent.session.new,', '.onRequest(axomQuota.READ, {parse: value => value ?? {}}, async ctx => { const session=agent.sessions[ctx.params.sessionId] ?? Object.values(agent.sessions)[0]; const owned=!session?.query; const q=session?.query ?? query({prompt:"/usage",options:{cwd:ctx.params.cwd??process.cwd(),persistSession:false}}); let raw;try{const auth=fromAccountInfo(await q.accountInfo()); if(["api_key","external","gateway"].includes(auth?.kind)){raw={billing_mode:"non_subscription",rate_limits_available:false};}else{raw=await q.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET({skipBehaviors:true});raw.subscription_type??=auth?.account?.plan;raw.billing_mode=auth?.kind==="account"?"subscription":"unknown";}}finally{if(owned)q.close();} agent.axomAccountLimits=axomQuota.claude({subscription_type:raw.subscription_type,rate_limits_available:raw.rate_limits_available,rate_limits:raw.rate_limits,billing_mode:raw.billing_mode}); if(agent.axomAccountLimits.billingMode==="unknown" || agent.axomAccountLimits.availability==="unavailable") throw new Error("Failed to fetch usage"); axomQuotaNotify(agent.axomAccountLimits); return agent.axomAccountLimits; })\n .onRequest(methods.agent.session.new,')])
|
|
36
|
+
patch('commandcode','dist/cli.mjs','1.88.0','command-code',[
|
|
37
|
+
# 1.82.1 renamed the handler map (u/dn -> m/hn) and gave INITIALIZE an explicit arrow body; 1.84.0
|
|
38
|
+
# the enum renames every release (hn->vn->bn). The read method still goes first in the same map.
|
|
39
|
+
('const m={[bn.INITIALIZE]:e=>handleInitialize(e),[bn.AUTHENTICATE]','const m={["_axom/account/rateLimits/read"]:async()=>{const raw=await fetchUsageData2(); if(raw.errors.length) throw new Error("Failed to fetch usage"); const snapshot=axomQuota.commandcode({credits:raw.credits,subscription:raw.subscription,orgLimits:raw.whoami?.orgLimits??[],monthly:{limit:raw.subscription?.data?.status==="active"?(getPlanInfo({planId:raw.subscription?.data?.planId??""})?.monthlyCredits??null):null}}); axomQuotaNotify(snapshot); return snapshot;},[bn.INITIALIZE]:e=>handleInitialize(e),[bn.AUTHENTICATE]'),
|
|
40
|
+
('agentCapabilities:{loadSession:!0,promptCapabilities:', 'agentCapabilities:{_meta:{"axom/accountRateLimits":{...axomQuota.CAPABILITY,provider:"commandcode"}},loadSession:!0,promptCapabilities:')])
|
|
41
|
+
if options.zcode: patch('zcode','dist/index.js','0.76.3','zcode-acp-server',[
|
|
42
|
+
# 0.72.0 moved the legacy usage_stats body to handlers/account.js as accountUsageStatsViaHub.
|
|
43
|
+
(' .onRequest("account/usage_stats", z.object({}).passthrough(), () => accountUsageStatsViaHub())',
|
|
44
|
+
' .onRequest(axomQuota.READ, z.object({}).passthrough(), async () => {\n'
|
|
45
|
+
' const { buildAccountProviderConfig, codingPlanRequestAuthFor } = await import("./config/account-provider.js");\n'
|
|
46
|
+
' const { resolveQuotaHost } = await import("./quota/client.js");\n'
|
|
47
|
+
' let apiKey = null, family = "";\n'
|
|
48
|
+
' for (const [providerId, provider] of Object.entries(buildAccountProviderConfig()?.providers ?? {})) {\n'
|
|
49
|
+
' if (!provider?.access?.entitled) continue;\n'
|
|
50
|
+
' const auth = codingPlanRequestAuthFor(providerId);\n'
|
|
51
|
+
' if (auth?.apiKey) { apiKey = auth.apiKey; family = providerId; break; }\n'
|
|
52
|
+
' }\n'
|
|
53
|
+
' if (!apiKey) throw new Error("No entitled GLM coding plan: sign in once in the ZCode desktop app");\n'
|
|
54
|
+
' const resp = await fetch(resolveQuotaHost(family.startsWith("account:zai") ? "https://api.z.ai" : "") + "/api/monitor/usage/quota/limit", { headers: { Accept: "application/json, text/plain, */*", Authorization: "Bearer " + apiKey }, signal: AbortSignal.timeout(8000) });\n'
|
|
55
|
+
' const text = await resp.text();\n'
|
|
56
|
+
' let json = null; try { json = text ? JSON.parse(text) : null; } catch {}\n'
|
|
57
|
+
' if (resp.status === 429 || !json || json.success !== true) throw new Error("GLM quota read failed" + (json?.msg ? ": " + json.msg : " (HTTP " + resp.status + ")"));\n'
|
|
58
|
+
' const snapshot = axomQuota.zcode({ provider: family, level: json.data?.level, limits: json.data?.limits });\n'
|
|
59
|
+
' axomQuotaNotify(snapshot);\n'
|
|
60
|
+
' return snapshot;\n'
|
|
61
|
+
' })\n'
|
|
62
|
+
' .onRequest("account/usage_stats", z.object({}).passthrough(), () => accountUsageStatsViaHub())'),
|
|
63
|
+
(' .onRequest("initialize", (ctx) => server.initialize(ctx.params, ctx.client))',
|
|
64
|
+
' .onRequest("initialize", async (ctx) => { const result = await server.initialize(ctx.params, ctx.client); const caps = result.agentCapabilities ?? {}; result.agentCapabilities = { ...caps, _meta: { ...caps._meta, "axom/accountRateLimits": { ...axomQuota.CAPABILITY, provider: "zcode" } } }; return result; })')])
|
|
65
|
+
models_fn='''function axomFreshInstallModels() {
|
|
66
|
+
const fallback = { providerId: DEFAULT_PROVIDER_ID, providerName: DEFAULT_PROVIDER_NAME, modelId: DEFAULT_MODEL_ID };
|
|
67
|
+
try {
|
|
68
|
+
const out = [];
|
|
69
|
+
for (const [pid, p] of Object.entries(axomAccountProviders()?.providers ?? {})) {
|
|
70
|
+
if (!p?.access?.entitled || !axomPlanAuth(pid)?.apiKey) continue;
|
|
71
|
+
const providerId = configProviderIdFor(pid);
|
|
72
|
+
for (const modelId of p.builtinModelIds ?? []) {
|
|
73
|
+
if (out.some((m) => m.providerId === providerId && m.modelId === modelId)) continue;
|
|
74
|
+
out.push({ providerId, providerName: providerId, modelId });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (out.length === 0) return [fallback];
|
|
78
|
+
return out.some((m) => m.providerId === fallback.providerId && m.modelId === fallback.modelId)
|
|
79
|
+
? [fallback, ...out.filter((m) => !(m.providerId === fallback.providerId && m.modelId === fallback.modelId))]
|
|
80
|
+
: [fallback, ...out];
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return [fallback];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
'''
|
|
87
|
+
if options.zcode: patch('zcode-models','dist/config/options.js','0.76.3','zcode-acp-server',[
|
|
88
|
+
('import { configProviderIdFor } from "./account-provider.js";',
|
|
89
|
+
'import { buildAccountProviderConfig as axomAccountProviders, codingPlanRequestAuthFor as axomPlanAuth, configProviderIdFor } from "./account-provider.js";'),
|
|
90
|
+
('/** Read the config.json contents (UTF-8). Throws on read/parse failure. */',
|
|
91
|
+
models_fn+'\n/** Read the config.json contents (UTF-8). Throws on read/parse failure. */'),
|
|
92
|
+
(''' if (out.length === 0 && Object.keys(cfg.provider ?? {}).length === 0) {
|
|
93
|
+
return [
|
|
94
|
+
{
|
|
95
|
+
providerId: DEFAULT_PROVIDER_ID,
|
|
96
|
+
providerName: DEFAULT_PROVIDER_NAME,
|
|
97
|
+
modelId: DEFAULT_MODEL_ID,
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
}''',
|
|
101
|
+
' if (out.length === 0 && Object.keys(cfg.provider ?? {}).length === 0) {\n return axomFreshInstallModels();\n }'),
|
|
102
|
+
(''' if (out.length > 0)
|
|
103
|
+
return out;
|
|
104
|
+
return [
|
|
105
|
+
{
|
|
106
|
+
providerId: DEFAULT_PROVIDER_ID,
|
|
107
|
+
providerName: DEFAULT_PROVIDER_NAME,
|
|
108
|
+
modelId: DEFAULT_MODEL_ID,
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
}''',
|
|
113
|
+
' if (out.length > 0)\n return out;\n return axomFreshInstallModels();\n }\n}'),
|
|
114
|
+
],suffix='',helper_text=None,root_dir=options.zcode)
|
|
115
|
+
runtime=root/'axom-patch/cli/runtime.json'; data=json.loads(runtime.read_text())
|
|
116
|
+
for kind in roots:
|
|
117
|
+
name=kind+'-account-limits.json'
|
|
118
|
+
if name not in data['package_patches']:data['package_patches'].append(name)
|
|
119
|
+
if options.zcode:
|
|
120
|
+
name='zcode-models.json'
|
|
121
|
+
if name not in data['package_patches']:data['package_patches'].append(name)
|
|
122
|
+
runtime.write_text(json.dumps(data,indent=2)+'\n')
|
|
123
|
+
print('Generated exact-version recipes'+(' including zcode' if options.zcode else ''))
|