@platless/axom-cli 0.1.0 → 0.5.9

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.
Files changed (281) hide show
  1. package/README.md +1 -1
  2. package/dist/authScopes.js +19 -0
  3. package/dist/axom-patch/cli/README.md +132 -0
  4. package/dist/axom-patch/cli/account-limits/README.md +27 -0
  5. package/dist/axom-patch/cli/account-limits/antigravity-proxy.mjs +47 -0
  6. package/dist/axom-patch/cli/account-limits/antigravity-read.mjs +90 -0
  7. package/dist/axom-patch/cli/account-limits/antigravity.mjs +46 -0
  8. package/dist/axom-patch/cli/account-limits/generate.py +120 -0
  9. package/dist/axom-patch/cli/account-limits/kimi-proxy.mjs +64 -0
  10. package/dist/axom-patch/cli/account-limits/normalize.mjs +151 -0
  11. package/dist/axom-patch/cli/claude-account-limits.json +37 -0
  12. package/dist/axom-patch/cli/codex-account-limits.json +37 -0
  13. package/dist/axom-patch/cli/commandcode-account-limits.json +30 -0
  14. package/dist/axom-patch/cli/nightly-task.md +152 -0
  15. package/dist/axom-patch/cli/pi-steering.json +37 -0
  16. package/dist/axom-patch/cli/pi-subagent-subwork.json +23 -0
  17. package/dist/axom-patch/cli/probes/claude-late-async-terminal.mjs +38 -0
  18. package/dist/axom-patch/cli/probes/pi-steering.mjs +80 -0
  19. package/dist/axom-patch/cli/probes/pi-subagent-subwork.mjs +211 -0
  20. package/dist/axom-patch/cli/probes/qoder-steering.mjs +89 -0
  21. package/dist/axom-patch/cli/probes/qoder-subagent-origin.mjs +61 -0
  22. package/dist/axom-patch/cli/probes/zcode-subagent-subwork.mjs +257 -0
  23. package/dist/axom-patch/cli/qoder-background-terminal.md +82 -0
  24. package/dist/axom-patch/cli/qoder-foreground-output.md +42 -0
  25. package/dist/axom-patch/cli/qoder-steering.json +52 -0
  26. package/dist/axom-patch/cli/qoder-steering.md +30 -0
  27. package/dist/axom-patch/cli/qoder-subagent-origin.json +73 -0
  28. package/dist/axom-patch/cli/qoder-subagent-subwork.md +73 -0
  29. package/dist/axom-patch/cli/runtime.json +63 -0
  30. package/dist/axom-patch/cli/steering/claude-steering-js.patch +89 -0
  31. package/dist/axom-patch/cli/steering/claude-steering-types.patch +28 -0
  32. package/dist/axom-patch/cli/steering/codex-steering.patch +57 -0
  33. package/dist/axom-patch/cli/steering/pi-steering.js +79 -0
  34. package/dist/axom-patch/cli/zcode-account-limits.json +31 -0
  35. package/dist/axom-patch/cli/zcode-models.json +38 -0
  36. package/dist/axom-patch/cli/zcode-subagent-subwork.json +73 -0
  37. package/dist/cli.js +36 -1
  38. package/dist/commands/auth.js +4 -13
  39. package/dist/commands/execute.js +4 -4
  40. package/dist/commands/record.js +6 -6
  41. package/dist/commands/struct.js +4 -4
  42. package/dist/commands/workstation.js +2 -2
  43. package/dist/credentials.js +2 -2
  44. package/dist/install/claude/commands.js +13 -13
  45. package/dist/keepers/acp/keeper.mjs +3083 -0
  46. package/dist/keepers/acp/manifest.json +9 -0
  47. package/dist/keepers/terminal/keeper.mjs +8469 -0
  48. package/dist/keepers/terminal/manifest.json +9 -0
  49. package/dist/keepers/terminal/node_modules/node-pty/lib/conpty_console_list_agent.js +25 -0
  50. package/dist/keepers/terminal/node_modules/node-pty/lib/eventEmitter2.js +47 -0
  51. package/dist/keepers/terminal/node_modules/node-pty/lib/index.js +52 -0
  52. package/dist/keepers/terminal/node_modules/node-pty/lib/interfaces.js +7 -0
  53. package/dist/keepers/terminal/node_modules/node-pty/lib/shared/conout.js +10 -0
  54. package/dist/keepers/terminal/node_modules/node-pty/lib/terminal.js +190 -0
  55. package/dist/keepers/terminal/node_modules/node-pty/lib/types.js +7 -0
  56. package/dist/keepers/terminal/node_modules/node-pty/lib/unixTerminal.js +351 -0
  57. package/dist/keepers/terminal/node_modules/node-pty/lib/utils.js +38 -0
  58. package/dist/keepers/terminal/node_modules/node-pty/lib/windowsConoutConnection.js +131 -0
  59. package/dist/keepers/terminal/node_modules/node-pty/lib/windowsPtyAgent.js +344 -0
  60. package/dist/keepers/terminal/node_modules/node-pty/lib/windowsTerminal.js +209 -0
  61. package/dist/keepers/terminal/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
  62. package/dist/keepers/terminal/node_modules/node-pty/package.json +66 -0
  63. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
  64. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
  65. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-x64/pty.node +0 -0
  66. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
  67. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/linux-arm64/pty.node +0 -0
  68. package/dist/keepers/terminal/node_modules/node-pty/prebuilds/linux-x64/pty.node +0 -0
  69. package/dist/mcp.js +32 -14
  70. package/dist/runtime-deps/qoder-sdk/package-lock.json +1189 -0
  71. package/dist/runtime-deps/qoder-sdk/package.json +8 -0
  72. package/dist/test/keeperKit.js +67 -0
  73. package/dist/workstation/acp/acpAgents.js +2514 -681
  74. package/dist/workstation/acp/acpClient.js +95 -318
  75. package/dist/workstation/acp/activityBusy.js +43 -0
  76. package/dist/workstation/acp/activityReporting.js +54 -0
  77. package/dist/workstation/acp/adoption.js +28 -356
  78. package/dist/workstation/acp/authUrlSniffer.js +36 -0
  79. package/dist/workstation/acp/binaryInstall.js +100 -27
  80. package/dist/workstation/acp/builds/gc.js +245 -0
  81. package/dist/workstation/acp/builds/install/binary.js +28 -0
  82. package/dist/workstation/acp/builds/install/npm.js +235 -0
  83. package/dist/workstation/acp/builds/install/uv.js +254 -0
  84. package/dist/workstation/acp/builds/migrate.js +195 -0
  85. package/dist/workstation/acp/builds/model.js +128 -0
  86. package/dist/workstation/acp/builds/nodeGate.js +100 -0
  87. package/dist/workstation/acp/builds/store.js +352 -0
  88. package/dist/workstation/acp/commandTableProbe.js +68 -0
  89. package/dist/workstation/acp/configOptions.js +103 -1
  90. package/dist/workstation/acp/delegationMcp.js +24 -0
  91. package/dist/workstation/acp/envSecrets.js +27 -0
  92. package/dist/workstation/acp/initializeResponse.js +285 -0
  93. package/dist/workstation/acp/installErrors.js +12 -2
  94. package/dist/workstation/acp/installProbe.js +1 -1
  95. package/dist/workstation/acp/managedPatches.js +144 -0
  96. package/dist/workstation/acp/outbox.js +330 -0
  97. package/dist/workstation/acp/patchAssets.js +80 -0
  98. package/dist/workstation/acp/permission.js +335 -37
  99. package/dist/workstation/acp/processor/checkpoint.js +87 -0
  100. package/dist/workstation/acp/processor/commands.js +35 -0
  101. package/dist/workstation/acp/processor/control.js +355 -0
  102. package/dist/workstation/acp/processor/emit.js +26 -0
  103. package/dist/workstation/acp/processor/jsonrpc.js +172 -0
  104. package/dist/workstation/acp/processor/memoryLog.js +49 -0
  105. package/dist/workstation/acp/processor/origins.js +48 -0
  106. package/dist/workstation/acp/processor/output.js +67 -0
  107. package/dist/workstation/acp/processor/projection.js +42 -0
  108. package/dist/workstation/acp/processor/record.js +128 -0
  109. package/dist/workstation/acp/processor/runtime.js +181 -0
  110. package/dist/workstation/acp/processor/sdkSchemas.js +61 -0
  111. package/dist/workstation/acp/processor/session.js +525 -0
  112. package/dist/workstation/acp/processor/sideChannel.js +80 -0
  113. package/dist/workstation/acp/processor/state.js +74 -0
  114. package/dist/workstation/acp/processor/step.js +459 -0
  115. package/dist/workstation/acp/processor/test/fixtureLog.js +65 -0
  116. package/dist/workstation/acp/processor/test/harness.js +120 -0
  117. package/dist/workstation/acp/processor/test/largeIdEcho.js +50 -0
  118. package/dist/workstation/acp/processor/test/rawAgent.js +70 -0
  119. package/dist/workstation/acp/processor/transport/generations.js +76 -0
  120. package/dist/workstation/acp/processor/transport/keeper.js +130 -0
  121. package/dist/workstation/acp/processor/transport/local.js +269 -0
  122. package/dist/workstation/acp/processor/transport/types.js +78 -0
  123. package/dist/workstation/acp/processor/updates.js +364 -0
  124. package/dist/workstation/acp/processorSession.js +1512 -0
  125. package/dist/workstation/acp/qoderStartup.js +45 -0
  126. package/dist/workstation/acp/registry/catalog.js +385 -4
  127. package/dist/workstation/acp/registry/detect.js +55 -0
  128. package/dist/workstation/acp/registry/launch.js +61 -119
  129. package/dist/workstation/acp/sessionUpdateMapper.js +56 -27
  130. package/dist/workstation/acp/steering.js +58 -0
  131. package/dist/workstation/acp/switching.js +114 -0
  132. package/dist/workstation/acp/terminalLogin.js +171 -0
  133. package/dist/workstation/acp/terminalLoginSpec.js +41 -0
  134. package/dist/workstation/acp/test/adapterFixtures.js +256 -0
  135. package/dist/workstation/acp/test/daemonLife.js +106 -0
  136. package/dist/workstation/acp/test/fakeAgent.js +185 -9
  137. package/dist/workstation/acp/test/keeperWorld.js +267 -0
  138. package/dist/workstation/acp/test/memoryOutbox.js +55 -0
  139. package/dist/workstation/acp/test/raw/fixtures.js +196 -0
  140. package/dist/workstation/acp/test/raw/qoderCaptures.js +125 -0
  141. package/dist/workstation/acp/test/raw/sanitize.js +344 -0
  142. package/dist/workstation/acp/test/raw/sources.js +249 -0
  143. package/dist/workstation/acp/test/realAdapter.js +377 -0
  144. package/dist/workstation/acp/test/scriptAgent.js +206 -0
  145. package/dist/workstation/acp/test/sessionFrames.js +42 -0
  146. package/dist/workstation/acp/timedCommand.js +4 -2
  147. package/dist/workstation/acp/uvxInstall.js +72 -122
  148. package/dist/workstation/acp/validate.js +33 -5
  149. package/dist/workstation/agentFlow.js +103 -0
  150. package/dist/workstation/agentSessions.js +1686 -348
  151. package/dist/workstation/channels/agent.js +14 -6
  152. package/dist/workstation/channels/computer.js +203 -7
  153. package/dist/workstation/channels/computerExecs.js +200 -0
  154. package/dist/workstation/channels/management.js +86 -6
  155. package/dist/workstation/config.js +3 -1
  156. package/dist/workstation/connection/encryptedChannel.js +88 -21
  157. package/dist/workstation/daemon.js +309 -6
  158. package/dist/workstation/daemonctl.js +28 -2
  159. package/dist/workstation/desktop/binding.js +36 -0
  160. package/dist/workstation/desktop/bridge.js +212 -0
  161. package/dist/workstation/desktop/flow-control.js +52 -0
  162. package/dist/workstation/desktop/focused-text.js +130 -0
  163. package/dist/workstation/desktop/protocol.js +35 -0
  164. package/dist/workstation/exec/attach.js +126 -0
  165. package/dist/workstation/exec/command.js +40 -0
  166. package/dist/workstation/exec/durable.js +517 -0
  167. package/dist/workstation/exec/fallback.js +106 -0
  168. package/dist/workstation/exec/policy.js +837 -0
  169. package/dist/workstation/exec/shaping.js +211 -0
  170. package/dist/workstation/exec.js +3 -112
  171. package/dist/workstation/files/adapters/computerFileFrames.js +51 -0
  172. package/dist/workstation/files/adapters/toolRequests.js +121 -0
  173. package/dist/workstation/files/client.js +455 -0
  174. package/dist/workstation/files/errors.js +28 -0
  175. package/dist/workstation/files/fence.js +350 -0
  176. package/dist/workstation/files/find/fileIndex.js +153 -0
  177. package/dist/workstation/files/find/fuzzy.js +155 -0
  178. package/dist/workstation/files/host.js +122 -0
  179. package/dist/workstation/files/hostProtocol.js +2 -0
  180. package/dist/workstation/files/media/cache.js +620 -0
  181. package/dist/workstation/files/media/encoding.js +308 -0
  182. package/dist/workstation/files/media/estimator.js +100 -0
  183. package/dist/workstation/files/media/media.js +325 -0
  184. package/dist/workstation/files/media/packedAudio.js +23 -0
  185. package/dist/workstation/files/media/scheduler.js +551 -0
  186. package/dist/workstation/files/media/types.js +5 -0
  187. package/dist/workstation/files/scope.js +45 -0
  188. package/dist/workstation/files/structured.js +284 -0
  189. package/dist/workstation/files/text.js +356 -0
  190. package/dist/workstation/files/uploads.js +351 -0
  191. package/dist/workstation/journal.js +65 -236
  192. package/dist/workstation/keepers/acp/client.js +101 -0
  193. package/dist/workstation/keepers/acp/envelope.js +62 -0
  194. package/dist/workstation/keepers/acp/host.js +419 -0
  195. package/dist/workstation/keepers/acp/main.js +18 -0
  196. package/dist/workstation/keepers/acp/memoryStream.js +121 -0
  197. package/dist/workstation/keepers/acp/params.js +137 -0
  198. package/dist/workstation/keepers/acp/protocol.js +66 -0
  199. package/dist/workstation/keepers/acp/recover.js +120 -0
  200. package/dist/workstation/keepers/acp/session.js +584 -0
  201. package/dist/workstation/keepers/acp/stderr.js +154 -0
  202. package/dist/workstation/keepers/kit/activity.js +103 -0
  203. package/dist/workstation/keepers/kit/bootstrap.js +164 -0
  204. package/dist/workstation/keepers/kit/buildVersion.js +51 -0
  205. package/dist/workstation/keepers/kit/bundle.js +120 -0
  206. package/dist/workstation/keepers/kit/client.js +432 -0
  207. package/dist/workstation/keepers/kit/identity.js +21 -0
  208. package/dist/workstation/keepers/kit/ipc.js +112 -0
  209. package/dist/workstation/keepers/kit/launchConfig.js +8 -0
  210. package/dist/workstation/keepers/kit/launcher.js +249 -0
  211. package/dist/workstation/keepers/kit/lock.js +123 -0
  212. package/dist/workstation/keepers/kit/orphanSweep.js +86 -0
  213. package/dist/workstation/keepers/kit/paths.js +75 -0
  214. package/dist/workstation/keepers/kit/protocol.js +43 -0
  215. package/dist/workstation/keepers/kit/server.js +518 -0
  216. package/dist/workstation/keepers/kit/streamLog.js +697 -0
  217. package/dist/workstation/keepers/legacy.js +296 -0
  218. package/dist/workstation/keepers/policy.js +576 -0
  219. package/dist/workstation/keepers/stop.js +34 -0
  220. package/dist/workstation/keepers/terminal/client.js +213 -0
  221. package/dist/workstation/keepers/terminal/exec.js +981 -0
  222. package/dist/workstation/keepers/terminal/generations.js +129 -0
  223. package/dist/workstation/keepers/terminal/keeper.js +62 -0
  224. package/dist/workstation/keepers/terminal/main.js +43 -0
  225. package/dist/workstation/keepers/terminal/orphanSweep.js +3 -0
  226. package/dist/workstation/keepers/terminal/params.js +27 -0
  227. package/dist/workstation/keepers/terminal/protocol.js +56 -0
  228. package/dist/workstation/keepers/terminal/pty.js +330 -0
  229. package/dist/workstation/oauth/deviceAuthorization.js +21 -12
  230. package/dist/workstation/protocol/accountLimits.js +47 -0
  231. package/dist/workstation/protocol/agent.js +201 -8
  232. package/dist/workstation/protocol/common.js +36 -0
  233. package/dist/workstation/protocol/computer.js +107 -7
  234. package/dist/workstation/protocol/management.js +50 -2
  235. package/dist/workstation/qoderAdapter/backgroundProcess.js +118 -0
  236. package/dist/workstation/qoderAdapter/backgroundTerminal.js +193 -0
  237. package/dist/workstation/qoderAdapter/backgroundTerminalFold.js +372 -0
  238. package/dist/workstation/qoderAdapter/callbackContext.js +76 -0
  239. package/dist/workstation/qoderAdapter/completedContinuation.js +139 -0
  240. package/dist/workstation/qoderAdapter/contract.js +78 -0
  241. package/dist/workstation/qoderAdapter/foregroundOutput.js +36 -0
  242. package/dist/workstation/qoderAdapter/history.js +85 -0
  243. package/dist/workstation/qoderAdapter/identityIndex.js +191 -0
  244. package/dist/workstation/qoderAdapter/inputQueue.js +42 -0
  245. package/dist/workstation/qoderAdapter/main.js +95 -0
  246. package/dist/workstation/qoderAdapter/mapper.js +117 -0
  247. package/dist/workstation/qoderAdapter/observerPlugin.js +245 -0
  248. package/dist/workstation/qoderAdapter/observerReceiver.js +187 -0
  249. package/dist/workstation/qoderAdapter/permissions.js +61 -0
  250. package/dist/workstation/qoderAdapter/profile.js +93 -0
  251. package/dist/workstation/qoderAdapter/sdkDriver.js +48 -0
  252. package/dist/workstation/qoderAdapter/sdkRuntime.js +93 -0
  253. package/dist/workstation/qoderAdapter/sdkRuntimeInstall.js +145 -0
  254. package/dist/workstation/qoderAdapter/session.js +319 -0
  255. package/dist/workstation/qoderAdapter/subagentMeta.js +28 -0
  256. package/dist/workstation/qoderAdapter/subwork.js +85 -0
  257. package/dist/workstation/qoderAdapter/taskControl.js +38 -0
  258. package/dist/workstation/qoderAdapter/taskLedger.js +163 -0
  259. package/dist/workstation/qoderAdapter/types.js +1 -0
  260. package/dist/workstation/qoderAdapter/usage.js +37 -0
  261. package/dist/workstation/register.js +4 -0
  262. package/dist/workstation/systemMetrics.js +110 -1
  263. package/dist/workstation/tools/browser.js +394 -0
  264. package/dist/workstation/tools/client.js +277 -0
  265. package/dist/workstation/tools/info.js +50 -0
  266. package/dist/workstation/tools/keeperProcess.js +124 -0
  267. package/dist/workstation/tools/router.js +55 -0
  268. package/dist/workstation/tools/terminalRouter.js +222 -0
  269. package/dist/workstation/tools/validation.js +86 -0
  270. package/dist/workstation/update/coordinator.js +32 -0
  271. package/dist/workstation/update/npmInstaller.js +2 -0
  272. package/dist/workstation/update/ptyPreflight.js +45 -0
  273. package/dist/workstation/update/taskRegistry.js +141 -23
  274. package/dist/workstation/update/watchdog.js +66 -0
  275. package/package.json +20 -7
  276. package/skills/axom/SKILL.md +55 -17
  277. package/skills/axom-definition/SKILL.md +32 -32
  278. package/skills/axom-platform/SKILL.md +39 -39
  279. package/dist/workstation/acp/acpSession.js +0 -1047
  280. package/dist/workstation/acp/contract.js +0 -494
  281. package/dist/workstation/acp/draftInterceptor.js +0 -154
@@ -0,0 +1,85 @@
1
+ const object = (v) => v && typeof v === 'object' && !Array.isArray(v) ? v : {};
2
+ const id = (v) => typeof v === 'string' && v.length > 0 && v.length <= 256 && !/[\x00-\x1f\x7f]/.test(v);
3
+ export function newSubworkData() {
4
+ return { calls: {}, count: 0 };
5
+ }
6
+ export function supportsSubworkMeta(info) {
7
+ return (info?.name === 'qoder-cli' && info.version === '1.1.61') ||
8
+ (info?.name === 'axom-qoder-sdk' && info.version === '1.0.50');
9
+ }
10
+ function resultText(value) {
11
+ if (typeof value === 'string')
12
+ return value;
13
+ if (Array.isArray(value)) {
14
+ const texts = value.filter(v => object(v).type === 'text').map(v => object(v).text).filter(v => typeof v === 'string');
15
+ return texts.length ? texts.join('\n') : undefined;
16
+ }
17
+ const v = object(value);
18
+ if (v.kind === 'agent-result')
19
+ return resultText(v.content ?? v.result);
20
+ return undefined;
21
+ }
22
+ export class SubworkBoundary {
23
+ root;
24
+ data;
25
+ constructor(root, data = newSubworkData()) {
26
+ this.root = root;
27
+ this.data = data;
28
+ }
29
+ get(toolId) { return Object.hasOwn(this.data.calls, toolId) ? this.data.calls[toolId] : undefined; }
30
+ child(toolId) { return `qoder-agent:${this.root}:${toolId}`; }
31
+ map(event) {
32
+ if (event.acpSessionId && event.acpSessionId !== this.root)
33
+ return [event];
34
+ const p = event.payload, q = object(object(p._meta).qoder), input = object(p.rawInput);
35
+ const marked = q.version === 1 && ['native-acp-patch', 'sdk', 'correction'].includes(String(q.source));
36
+ const toolId = p.toolCallId;
37
+ let call = id(toolId) ? this.get(toolId) : undefined;
38
+ const parent = marked && q.route !== 'unknown' && id(q.parentToolUseId) ? q.parentToolUseId : undefined;
39
+ const events = [];
40
+ if (!call && marked && p.kind === 'think' && q.toolName === 'Agent' && id(toolId) &&
41
+ typeof input.prompt === 'string' && (input.subagent_type == null || typeof input.subagent_type === 'string') &&
42
+ (input.run_in_background === undefined || typeof input.run_in_background === 'boolean') &&
43
+ ['tool_call', 'tool_call_update'].includes(event.eventName) && this.data.count < 4096) {
44
+ call = { child: this.child(toolId), ...(parent ? { parent: this.child(parent) } : {}),
45
+ background: input.run_in_background === true, ended: false, streamedText: '' };
46
+ Object.defineProperty(this.data.calls, toolId, { value: call, enumerable: true, writable: true, configurable: true });
47
+ this.data.count += 1;
48
+ events.push({ eventName: 'subagent_spawned', payload: { subagentSessionId: call.child,
49
+ name: typeof input.description === 'string' && input.description.trim() ? input.description : input.subagent_type ?? 'Agent',
50
+ task: input.prompt, capabilities: {} }, ...(call.parent ? { acpSessionId: call.parent } : {}) });
51
+ events.push({ eventName: 'user_message_chunk', payload: { content: { type: 'text', text: input.prompt } }, acpSessionId: call.child });
52
+ }
53
+ if (call && ['tool_call', 'tool_call_update'].includes(event.eventName)) {
54
+ if (call.ended)
55
+ return events;
56
+ const output = object(p.rawOutput);
57
+ const state = output.kind === 'agent-result' ? output.state : undefined;
58
+ const terminal = state === 'completed' ? 'completed' : ['error', 'failed'].includes(String(state)) ? 'failed' :
59
+ state === 'cancelled' ? 'cancelled' : ['failed', 'cancelled'].includes(String(p.status)) ? p.status :
60
+ !call.background && p.status === 'completed' ? 'completed' : undefined;
61
+ if (terminal) {
62
+ const text = resultText(p.rawOutput);
63
+ if (text !== undefined && !call.streamedText.endsWith(text))
64
+ events.push({ eventName: 'agent_message_chunk',
65
+ payload: { content: { type: 'text', text } }, acpSessionId: call.child });
66
+ events.push({ eventName: 'subagent_state_update', payload: { subagentSessionId: call.child, state: terminal },
67
+ ...(call.parent ? { acpSessionId: call.parent } : {}) });
68
+ call.ended = true;
69
+ // Read only by the check above, once: an ended call keeps no stream (checkpointed state).
70
+ call.streamedText = '';
71
+ }
72
+ // The Agent invocation becomes a dispatch/result in subwork. Keeping the vendor tool here
73
+ // would also create the old delegation card for the very same task.
74
+ return events;
75
+ }
76
+ if (parent) {
77
+ const owner = this.get(parent), content = object(p.content);
78
+ if (owner && !owner.ended && event.eventName === 'agent_message_chunk' && content.type === 'text' && typeof content.text === 'string') {
79
+ owner.streamedText += content.text;
80
+ }
81
+ return [{ ...event, acpSessionId: this.child(parent) }];
82
+ }
83
+ return [event];
84
+ }
85
+ }
@@ -0,0 +1,38 @@
1
+ import { capabilitiesFor } from './profile.js';
2
+ const validId = (value) => value.length > 0 && Buffer.byteLength(value, 'utf8') <= 256 &&
3
+ !/[\x00-\x1f\x7f]/.test(value);
4
+ export class TaskControl {
5
+ ledger;
6
+ profile;
7
+ query;
8
+ certifications;
9
+ binding;
10
+ requests = new Map();
11
+ constructor(ledger, profile, query, certifications, binding) {
12
+ this.ledger = ledger;
13
+ this.profile = profile;
14
+ this.query = query;
15
+ this.certifications = certifications;
16
+ this.binding = binding;
17
+ }
18
+ async stop(request) {
19
+ if (![request.sessionId, request.taskId, request.requestId].every(validId))
20
+ throw new Error('Invalid task stop identity');
21
+ const previous = this.requests.get(request.requestId);
22
+ if (previous) {
23
+ if (previous.sessionId !== request.sessionId || previous.taskId !== request.taskId)
24
+ throw new Error('Task stop request identity conflict');
25
+ return previous.receipt;
26
+ }
27
+ const profile = this.profile(), task = this.ledger.get(request.taskId);
28
+ if (!profile || !task || request.sessionId !== profile.rootSessionId ||
29
+ !task.origin.agentId || !task.origin.launchingToolUseId || task.taskType !== 'local_agent' ||
30
+ task.background !== true || !capabilitiesFor(profile, task, this.certifications, this.binding).stopActiveRun)
31
+ throw new Error('Task stop unavailable');
32
+ if (this.requests.size >= 4096)
33
+ throw new Error('Task stop receipt capacity exceeded');
34
+ const receipt = this.query.stopTask(request.taskId).then(() => ({ requestId: request.requestId, state: 'accepted' }), () => ({ requestId: request.requestId, state: 'unknown' }));
35
+ this.requests.set(request.requestId, { sessionId: request.sessionId, taskId: request.taskId, receipt });
36
+ return receipt;
37
+ }
38
+ }
@@ -0,0 +1,163 @@
1
+ const identifier = (value) => typeof value === 'string' && value.length > 0 &&
2
+ Buffer.byteLength(value, 'utf8') <= 256 && !/[\x00-\x1f\x7f]/.test(value);
3
+ const terminal = (state) => state === 'completed' || state === 'failed' || state === 'stopped';
4
+ const defaultMaxTasks = 4096;
5
+ const sameTask = (a, b) => a.state === b.state && a.live === b.live && a.stale === b.stale && a.taskType === b.taskType &&
6
+ a.background === b.background && JSON.stringify(a.origin) === JSON.stringify(b.origin);
7
+ export class TaskLedger {
8
+ rootSessionId;
9
+ runtimeGeneration;
10
+ maxTasks;
11
+ tasks = new Map();
12
+ seen = new Set();
13
+ actors = new Map();
14
+ launchTasks = new Map();
15
+ conflicts = new Set();
16
+ notified = new Set();
17
+ failed = false;
18
+ constructor(rootSessionId, runtimeGeneration, maxTasks = defaultMaxTasks) {
19
+ this.rootSessionId = rootSessionId;
20
+ this.runtimeGeneration = runtimeGeneration;
21
+ this.maxTasks = maxTasks;
22
+ if (!identifier(rootSessionId) || !identifier(runtimeGeneration))
23
+ throw new Error('Invalid task ledger binding');
24
+ if (!Number.isInteger(maxTasks) || maxTasks < 1 || maxTasks > defaultMaxTasks)
25
+ throw new Error('Invalid task ledger capacity');
26
+ }
27
+ get(taskId) {
28
+ const task = this.tasks.get(taskId);
29
+ return task && { ...task, origin: { ...task.origin } };
30
+ }
31
+ all() { return [...this.tasks.keys()].map((id) => this.get(id)); }
32
+ get launchObservationCount() { return this.actors.size; }
33
+ get degraded() { return this.failed; }
34
+ markStale() {
35
+ for (const [id, task] of this.tasks)
36
+ this.tasks.set(id, { ...task, live: false, stale: true });
37
+ return this.all();
38
+ }
39
+ degrade() {
40
+ this.failed = true;
41
+ return this.markStale();
42
+ }
43
+ observeLaunch(toolUseId, agentId) {
44
+ if (this.failed || !identifier(toolUseId) || !identifier(agentId))
45
+ return [];
46
+ const prior = this.actors.get(toolUseId);
47
+ if (prior !== undefined && prior !== agentId)
48
+ this.actors.set(toolUseId, null);
49
+ else if (prior === undefined && this.actors.size < this.maxTasks)
50
+ this.actors.set(toolUseId, agentId);
51
+ const changed = [];
52
+ for (const [id, task] of this.tasks) {
53
+ if (task.origin.launchingToolUseId !== toolUseId)
54
+ continue;
55
+ const actor = this.actors.get(toolUseId);
56
+ const next = { ...task, origin: { ...task.origin,
57
+ agentId: this.conflicts.has(id) ? undefined : actor ?? undefined },
58
+ stale: actor === null || this.conflicts.has(id) || task.stale };
59
+ this.tasks.set(id, next);
60
+ changed.push(next);
61
+ }
62
+ return changed;
63
+ }
64
+ ensure(taskId) {
65
+ if (!identifier(taskId))
66
+ return undefined;
67
+ const existing = this.tasks.get(taskId);
68
+ if (existing)
69
+ return existing;
70
+ if (this.tasks.size >= this.maxTasks) {
71
+ this.degrade();
72
+ return undefined;
73
+ }
74
+ const task = { origin: { rootSessionId: this.rootSessionId, runtimeGeneration: this.runtimeGeneration,
75
+ taskId }, state: 'unknown', live: false, stale: false };
76
+ this.tasks.set(taskId, task);
77
+ return task;
78
+ }
79
+ apply(message) {
80
+ if (this.failed || message.type !== 'system' || message.session_id !== this.rootSessionId ||
81
+ !identifier(message.uuid) || this.seen.has(message.uuid))
82
+ return [];
83
+ if (this.seen.size >= this.maxTasks * 4)
84
+ return this.degrade();
85
+ if (message.subtype === 'background_tasks_changed' && message.tasks.length > this.maxTasks)
86
+ return this.degrade();
87
+ if (message.subtype === 'background_tasks_changed') {
88
+ const added = new Set();
89
+ for (const entry of message.tasks) {
90
+ if (identifier(entry.task_id) && !this.tasks.has(entry.task_id))
91
+ added.add(entry.task_id);
92
+ if (this.tasks.size + added.size > this.maxTasks)
93
+ return this.degrade();
94
+ }
95
+ }
96
+ const previous = new Map(this.tasks);
97
+ this.seen.add(message.uuid);
98
+ if (message.subtype === 'background_tasks_changed') {
99
+ const current = new Map(message.tasks.filter((entry) => identifier(entry.task_id))
100
+ .map((entry) => [entry.task_id, entry]));
101
+ for (const [id, task] of this.tasks) {
102
+ if (!terminal(task.state) && task.background) {
103
+ const next = { ...task, live: current.has(id),
104
+ stale: current.has(id) ? this.conflicts.has(id) : task.stale };
105
+ if (!sameTask(task, next))
106
+ this.tasks.set(id, next);
107
+ }
108
+ }
109
+ for (const [id, entry] of current) {
110
+ const task = this.ensure(id);
111
+ if (task && !terminal(task.state)) {
112
+ const next = { ...task, state: 'running', live: true,
113
+ stale: this.conflicts.has(id), taskType: entry.task_type, background: true };
114
+ if (!sameTask(task, next))
115
+ this.tasks.set(id, next);
116
+ }
117
+ }
118
+ }
119
+ else if (message.subtype === 'task_started' || message.subtype === 'task_progress') {
120
+ const task = this.ensure(message.task_id);
121
+ if (task && !terminal(task.state)) {
122
+ const toolId = identifier(message.tool_use_id) ? message.tool_use_id : task.origin.launchingToolUseId;
123
+ if (toolId && !this.launchTasks.has(toolId) && this.launchTasks.size < this.maxTasks)
124
+ this.launchTasks.set(toolId, message.task_id);
125
+ else if (toolId && this.launchTasks.get(toolId) !== message.task_id) {
126
+ this.conflicts.add(message.task_id);
127
+ const other = this.launchTasks.get(toolId);
128
+ if (other) {
129
+ this.conflicts.add(other);
130
+ const previous = this.tasks.get(other);
131
+ if (previous)
132
+ this.tasks.set(other, { ...previous, stale: true,
133
+ origin: { ...previous.origin, agentId: undefined } });
134
+ }
135
+ }
136
+ const actor = toolId && this.actors.get(toolId);
137
+ this.tasks.set(message.task_id, { ...task, state: 'running', stale: this.conflicts.has(message.task_id),
138
+ taskType: 'task_type' in message ? message.task_type : task.taskType,
139
+ origin: { ...task.origin, launchingToolUseId: toolId,
140
+ agentId: this.conflicts.has(message.task_id) ? undefined : actor ?? task.origin.agentId } });
141
+ }
142
+ }
143
+ else if (message.subtype === 'task_updated') {
144
+ const task = this.ensure(message.task_id);
145
+ if (task && !terminal(task.state)) {
146
+ const status = message.patch.status;
147
+ const state = status === 'killed' ? 'stopped' : status ?? task.state;
148
+ this.tasks.set(message.task_id, { ...task, state, live: terminal(state) ? false : task.live,
149
+ stale: this.conflicts.has(message.task_id), background: message.patch.is_backgrounded ?? task.background });
150
+ }
151
+ }
152
+ else if (message.subtype === 'task_notification') {
153
+ const task = this.ensure(message.task_id);
154
+ if (task && (!this.notified.has(message.task_id) ||
155
+ (task.state === 'stopped' && message.status === 'completed'))) {
156
+ this.notified.add(message.task_id);
157
+ this.tasks.set(message.task_id, { ...task, state: message.status,
158
+ live: false, stale: this.conflicts.has(message.task_id) });
159
+ }
160
+ }
161
+ return [...this.tasks].filter(([id, task]) => task !== previous.get(id)).map(([id]) => this.get(id));
162
+ }
163
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ export const QODER_CREDITS_LABEL = 'Qoder Credits(厂商报告)';
2
+ const validCredits = (value) => typeof value === 'number' &&
3
+ Number.isFinite(value) && value >= 0;
4
+ /** Qoder's report is cumulative. A missing/invalid report never erases a prior valid value. */
5
+ export function applyCredits(previous, reported) {
6
+ if (validCredits(reported))
7
+ return reported;
8
+ return validCredits(previous) ? previous : undefined;
9
+ }
10
+ function reportedCredits(value) {
11
+ if (!value || typeof value !== 'object' || Array.isArray(value))
12
+ return undefined;
13
+ const input = value;
14
+ for (const key of ['total_credits', 'totalCredits', 'credits'])
15
+ if (validCredits(input[key]))
16
+ return input[key];
17
+ return undefined;
18
+ }
19
+ /**
20
+ * Keeps vendor credits separate from ACP token/USD counters. Qoder's SDK does not
21
+ * provide equivalent token or USD values, so zero placeholders are intentionally omitted.
22
+ */
23
+ export function normalizeQoderUsage(value, previousCredits) {
24
+ const input = value && typeof value === 'object' && !Array.isArray(value)
25
+ ? value : {};
26
+ const scope = input.cumulativeScope === 'unknown' ? 'unknown' : 'session';
27
+ const reported = reportedCredits(value);
28
+ if (scope === 'unknown') {
29
+ return { credits: undefined, creditsLabel: QODER_CREDITS_LABEL, creditsScope: scope,
30
+ inputTokens: undefined, outputTokens: undefined, costUsd: undefined,
31
+ ...(validCredits(previousCredits) ? { previousCredits } : {}) };
32
+ }
33
+ const credits = applyCredits(previousCredits, reported);
34
+ return { credits, creditsLabel: QODER_CREDITS_LABEL, creditsScope: scope,
35
+ inputTokens: undefined, outputTokens: undefined, costUsd: undefined,
36
+ ...(validCredits(previousCredits) ? { previousCredits } : {}) };
37
+ }
@@ -32,6 +32,10 @@ export async function registerWorkstation(server, clientName, token, ws) {
32
32
  + `when the same machine re-registers after an axom-cli upgrade. Delete it under Settings → `
33
33
  + 'Workstations, then run `axom workstation start` again.');
34
34
  }
35
+ if (res.status === 403) {
36
+ throw new UsageError('This credential is not authorized to register a workstation. '
37
+ + 'Run `axom auth` and select workstation, then try again.');
38
+ }
35
39
  throw new Error(`Registration failed: ${res.status} ${await res.text()}`);
36
40
  }
37
41
  const data = (await res.json());
@@ -100,6 +100,97 @@ async function defaultDarwinMemoryPressure() {
100
100
  return null;
101
101
  }
102
102
  }
103
+ /**
104
+ * Parses `ioreg -r -d 1 -w 0 -c AGXAccelerator` output. Apple Silicon publishes live GPU
105
+ * utilization (`Device Utilization %`, a driver-side running average) and GPU-resident unified
106
+ * memory (`In use system memory`) in each accelerator's `PerformanceStatistics`, without any
107
+ * privileges. Intel Macs expose no `AGXAccelerator` class, so they parse to null.
108
+ */
109
+ export function parseAppleAgxStats(output) {
110
+ const gpus = output.split('+-o ').slice(1).map((block, index) => {
111
+ const stats = /"PerformanceStatistics"\s*=\s*\{([^}]*)\}/.exec(block)?.[1];
112
+ if (stats === undefined)
113
+ return null;
114
+ const utilizationPercent = Number(/"Device Utilization %"\s*=\s*(\d+(?:\.\d+)?)/.exec(stats)?.[1]);
115
+ const memoryUsedBytes = Number(/"In use system memory"\s*=\s*(\d+)/.exec(stats)?.[1]);
116
+ return {
117
+ id: `apple:agx-${index}`,
118
+ name: /"model"\s*=\s*"([^"]+)"/.exec(block)?.[1] ?? 'Apple GPU',
119
+ utilization: Number.isFinite(utilizationPercent)
120
+ ? Math.max(0, Math.min(1, utilizationPercent / 100))
121
+ : null,
122
+ memoryTotalBytes: null,
123
+ memoryUsedBytes: Number.isFinite(memoryUsedBytes) && memoryUsedBytes >= 0 ? memoryUsedBytes : null,
124
+ coreCount: (() => {
125
+ const cores = Number(/"gpu-core-count"\s*=\s*(\d+)/.exec(block)?.[1]);
126
+ return Number.isFinite(cores) && cores > 0 ? cores : null;
127
+ })(),
128
+ };
129
+ }).filter((gpu) => gpu !== null);
130
+ return gpus.length > 0 ? gpus : null;
131
+ }
132
+ async function appleAgxGpuProbe() {
133
+ try {
134
+ const { stdout } = await execFileAsync('/usr/sbin/ioreg', ['-r', '-d', '1', '-w', '0', '-c', 'AGXAccelerator'], {
135
+ timeout: 2_000,
136
+ maxBuffer: 4 * 1024 * 1024,
137
+ });
138
+ return parseAppleAgxStats(stdout);
139
+ }
140
+ catch {
141
+ return null;
142
+ }
143
+ }
144
+ /** Parses `nvidia-smi --query-gpu=... --format=csv,noheader,nounits` output; `[N/A]` reads as null. */
145
+ export function parseNvidiaSmiGpus(output) {
146
+ const mib = (field) => {
147
+ if (field === undefined)
148
+ return null;
149
+ const value = Number(field);
150
+ return Number.isFinite(value) && value >= 0 ? Math.round(value * 1024 * 1024) : null;
151
+ };
152
+ const gpus = output.split(/\r?\n/).map((line) => {
153
+ const fields = line.split(',').map((field) => field.trim());
154
+ if (fields.length < 6)
155
+ return null;
156
+ const [, uuid, name, utilizationField, totalField, usedField] = fields;
157
+ if (!/^GPU-/.test(uuid) || name.length === 0)
158
+ return null;
159
+ const utilizationPercent = Number(utilizationField);
160
+ return {
161
+ id: `nvidia:${uuid}`,
162
+ name,
163
+ utilization: Number.isFinite(utilizationPercent)
164
+ ? Math.max(0, Math.min(1, utilizationPercent / 100))
165
+ : null,
166
+ memoryTotalBytes: mib(totalField),
167
+ memoryUsedBytes: mib(usedField),
168
+ coreCount: null,
169
+ };
170
+ }).filter((gpu) => gpu !== null);
171
+ return gpus.length > 0 ? gpus : null;
172
+ }
173
+ async function nvidiaSmiGpuProbe() {
174
+ try {
175
+ const { stdout } = await execFileAsync('nvidia-smi', [
176
+ '--query-gpu=index,uuid,name,utilization.gpu,memory.total,memory.used',
177
+ '--format=csv,noheader,nounits',
178
+ ], { timeout: 3_000 });
179
+ return parseNvidiaSmiGpus(stdout);
180
+ }
181
+ catch {
182
+ // Absent binary, driver hiccup, or unsupported GPU -- all read as "no reading", never as failure.
183
+ return null;
184
+ }
185
+ }
186
+ async function defaultProbeGpus(platform) {
187
+ const [apple, nvidia] = await Promise.all([
188
+ platform === 'darwin' ? appleAgxGpuProbe() : Promise.resolve(null),
189
+ nvidiaSmiGpuProbe(),
190
+ ]);
191
+ const gpus = [...(apple ?? []), ...(nvidia ?? [])];
192
+ return gpus.length > 0 ? gpus : null;
193
+ }
103
194
  /**
104
195
  * Low-overhead host sampler. CPU and memory are read only while a heartbeat is being built; storage
105
196
  * topology is discovered out of band and capacity reads use the cached representative paths.
@@ -114,6 +205,8 @@ export class SystemMetricsSampler {
114
205
  darwinMemoryRefreshInFlight = null;
115
206
  darwinMemoryAvailable = null;
116
207
  darwinMemoryPressure = null;
208
+ gpuRefreshInFlight = null;
209
+ gpus = null;
117
210
  constructor(workspaces, deps = {
118
211
  platform: process.platform,
119
212
  cpus: os.cpus,
@@ -126,12 +219,13 @@ export class SystemMetricsSampler {
126
219
  identifyStorage: (cwd, device) => defaultIdentifyStorage(process.platform, cwd, device),
127
220
  darwinAvailableMemory: defaultDarwinAvailableMemory,
128
221
  darwinMemoryPressure: defaultDarwinMemoryPressure,
222
+ probeGpus: () => defaultProbeGpus(process.platform),
129
223
  }) {
130
224
  this.workspaces = workspaces;
131
225
  this.deps = deps;
132
226
  }
133
227
  async start() {
134
- await Promise.all([this.refreshTopology(), this.refreshDarwinMemory()]);
228
+ await Promise.all([this.refreshTopology(), this.refreshDarwinMemory(), this.refreshGpus()]);
135
229
  this.refreshTimer = setInterval(() => this.refreshTopologyInBackground(), STORAGE_TOPOLOGY_REFRESH_MS);
136
230
  this.refreshTimer.unref();
137
231
  }
@@ -143,6 +237,7 @@ export class SystemMetricsSampler {
143
237
  snapshot() {
144
238
  try {
145
239
  this.refreshDarwinMemoryInBackground();
240
+ this.refreshGpusInBackground();
146
241
  const cpus = this.deps.cpus();
147
242
  const currentCpu = cpuTotals(cpus);
148
243
  const previousCpu = this.previousCpu;
@@ -192,6 +287,7 @@ export class SystemMetricsSampler {
192
287
  memoryTotalBytes,
193
288
  memoryAvailableBytes,
194
289
  storagePools: [...pools.values()],
290
+ gpus: this.gpus,
195
291
  };
196
292
  }
197
293
  catch {
@@ -218,6 +314,19 @@ export class SystemMetricsSampler {
218
314
  this.darwinMemoryRefreshInFlight = null;
219
315
  });
220
316
  }
317
+ refreshGpusInBackground() {
318
+ if (this.gpuRefreshInFlight)
319
+ return;
320
+ const refresh = this.refreshGpus();
321
+ this.gpuRefreshInFlight = refresh;
322
+ void refresh.finally(() => {
323
+ if (this.gpuRefreshInFlight === refresh)
324
+ this.gpuRefreshInFlight = null;
325
+ });
326
+ }
327
+ async refreshGpus() {
328
+ this.gpus = await this.deps.probeGpus().catch(() => null);
329
+ }
221
330
  async refreshDarwinMemory() {
222
331
  if (this.deps.platform !== 'darwin')
223
332
  return;