@platless/axom-cli 0.5.9 → 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.
Files changed (163) hide show
  1. package/README.md +18 -5
  2. package/dist/axom-patch/cli/README.md +100 -12
  3. package/dist/axom-patch/cli/account-limits/generate.py +15 -12
  4. package/dist/axom-patch/cli/account-limits/kimi-proxy.mjs +20 -3
  5. package/dist/axom-patch/cli/claude-account-limits.json +9 -9
  6. package/dist/axom-patch/cli/codex-account-limits.json +11 -11
  7. package/dist/axom-patch/cli/codex-terminal-output.json +16 -0
  8. package/dist/axom-patch/cli/commandcode-account-limits.json +9 -9
  9. package/dist/axom-patch/cli/kimi-quota.mjs +12 -0
  10. package/dist/axom-patch/cli/kimi-subagents.mjs +173 -0
  11. package/dist/axom-patch/cli/nightly-task.md +55 -13
  12. package/dist/axom-patch/cli/probes/codex-terminal-output.mjs +33 -0
  13. package/dist/axom-patch/cli/probes/kimi-subagent-subwork.mjs +82 -0
  14. package/dist/axom-patch/cli/qoder/dist/axom-acp-compat.mjs +1591 -0
  15. package/dist/axom-patch/cli/qoder/releases/1.1.75.json +360 -0
  16. package/dist/axom-patch/cli/qoder-background-terminal.md +13 -6
  17. package/dist/axom-patch/cli/qoder-foreground-output.md +14 -8
  18. package/dist/axom-patch/cli/qoder-native-acp.json +227 -0
  19. package/dist/axom-patch/cli/qoder-steering.md +20 -25
  20. package/dist/axom-patch/cli/qoder-subagent-subwork.md +17 -68
  21. package/dist/axom-patch/cli/runtime.json +16 -18
  22. package/dist/axom-patch/cli/zcode-account-limits.json +10 -11
  23. package/dist/axom-patch/cli/zcode-models.json +1 -2
  24. package/dist/axom-patch/cli/zcode-subagent-subwork.json +9 -10
  25. package/dist/cli.js +4 -36
  26. package/dist/commands/knowledge.js +47 -0
  27. package/dist/commands/update.js +65 -3
  28. package/dist/commands/workstation.js +73 -7
  29. package/dist/install/claude/commands.js +13 -13
  30. package/dist/mcp.js +1 -1
  31. package/dist/native/darwin-arm64/axom-quic +0 -0
  32. package/dist/workstation/acp/acpAgents.js +102 -98
  33. package/dist/workstation/acp/acpClient.js +26 -0
  34. package/dist/workstation/acp/builds/install/npm.js +99 -10
  35. package/dist/workstation/acp/initializeResponse.js +6 -1
  36. package/dist/workstation/acp/managedPatches.js +189 -25
  37. package/dist/workstation/acp/managedRuntime.js +314 -0
  38. package/dist/workstation/acp/patchAssets.js +40 -0
  39. package/dist/workstation/acp/processor/checkpoint.js +25 -34
  40. package/dist/workstation/acp/processor/control.js +5 -78
  41. package/dist/workstation/acp/processor/runtime.js +5 -81
  42. package/dist/workstation/acp/processor/session.js +51 -80
  43. package/dist/workstation/acp/processor/state.js +6 -13
  44. package/dist/workstation/acp/processor/step.js +3 -20
  45. package/dist/workstation/acp/processor/test/fixtureLog.js +9 -16
  46. package/dist/workstation/acp/processor/updates.js +131 -105
  47. package/dist/workstation/acp/processorSession.js +8 -172
  48. package/dist/workstation/acp/registry/catalog.js +65 -39
  49. package/dist/workstation/acp/registry/launch.js +16 -1
  50. package/dist/workstation/acp/switching.js +0 -3
  51. package/dist/workstation/acp/test/fakeAgent.js +13 -0
  52. package/dist/workstation/acp/test/keeperWorld.js +28 -0
  53. package/dist/workstation/acp/test/raw/sources.js +16 -130
  54. package/dist/workstation/acp/test/realAdapter.js +1 -47
  55. package/dist/workstation/acp/test/scriptAgent.js +11 -3
  56. package/dist/workstation/agentFlow.js +1 -1
  57. package/dist/workstation/agentSessions.js +38 -143
  58. package/dist/workstation/channels/management.js +95 -11
  59. package/dist/workstation/channels/url.js +1 -1
  60. package/dist/workstation/config.js +16 -4
  61. package/dist/workstation/connection/encryptedChannel.js +4 -1
  62. package/dist/workstation/control/bindingStore.js +200 -0
  63. package/dist/workstation/control/commands.js +124 -0
  64. package/dist/workstation/control/daemonIdentity.js +53 -0
  65. package/dist/workstation/control/enrollment.js +106 -0
  66. package/dist/workstation/control/inspect.js +71 -0
  67. package/dist/workstation/control/locks.js +63 -0
  68. package/dist/workstation/control/protocol.js +40 -0
  69. package/dist/workstation/control/restartGuard.js +46 -0
  70. package/dist/workstation/control/runtimeClient.js +97 -0
  71. package/dist/workstation/control/runtimeHost.js +148 -0
  72. package/dist/workstation/control/serverIdentity.js +35 -0
  73. package/dist/workstation/daemon.js +106 -6
  74. package/dist/workstation/daemonctl.js +77 -14
  75. package/dist/workstation/desktopControl/audio.js +99 -0
  76. package/dist/workstation/desktopControl/capabilities.js +92 -0
  77. package/dist/workstation/desktopControl/captureModes.js +9 -0
  78. package/dist/workstation/desktopControl/captureTargetLabel.js +9 -0
  79. package/dist/workstation/desktopControl/deviceSockets.js +246 -0
  80. package/dist/workstation/desktopControl/helperProcess.js +353 -0
  81. package/dist/workstation/desktopControl/lobby.js +129 -0
  82. package/dist/workstation/desktopControl/macProvider.js +155 -0
  83. package/dist/workstation/desktopControl/media.js +331 -0
  84. package/dist/workstation/desktopControl/nativeProvider.js +1018 -0
  85. package/dist/workstation/desktopControl/networkEvidence.js +43 -0
  86. package/dist/workstation/desktopControl/overview.js +58 -0
  87. package/dist/workstation/desktopControl/protocol.js +302 -0
  88. package/dist/workstation/desktopControl/quicMedia.js +240 -0
  89. package/dist/workstation/desktopControl/rateController.js +226 -0
  90. package/dist/workstation/desktopControl/supervisor.js +1681 -0
  91. package/dist/workstation/desktopControl/transport.js +27 -0
  92. package/dist/workstation/desktopControl/wallpaper.js +78 -0
  93. package/dist/workstation/files/credentials.js +142 -0
  94. package/dist/workstation/files/text.js +42 -8
  95. package/dist/workstation/keepers/kit/bundle.js +21 -17
  96. package/dist/workstation/keepers/kit/launcher.js +47 -7
  97. package/dist/workstation/keepers/kit/paths.js +2 -1
  98. package/dist/workstation/managedInstall.js +57 -0
  99. package/dist/workstation/protocol/agent.js +2 -15
  100. package/dist/workstation/protocol/management.js +93 -4
  101. package/dist/workstation/protocol/runtimeDiagnostics.js +15 -0
  102. package/dist/workstation/rd/artifact.js +119 -0
  103. package/dist/workstation/rd/control.js +119 -0
  104. package/dist/workstation/rd/display.js +29 -0
  105. package/dist/workstation/rd/provider.js +222 -0
  106. package/dist/workstation/rd/sessions.js +391 -0
  107. package/dist/workstation/rd/state.js +45 -0
  108. package/dist/workstation/rd/update.js +171 -0
  109. package/dist/workstation/rd/upkeep.js +38 -0
  110. package/dist/workstation/register.js +27 -37
  111. package/dist/workstation/service/installer.js +104 -13
  112. package/dist/workstation/service/launchd.js +1 -0
  113. package/dist/workstation/storageMetrics.js +118 -0
  114. package/dist/workstation/systemMetrics.js +44 -92
  115. package/dist/workstation/toolchain.js +94 -0
  116. package/dist/workstation/tools/browser.js +28 -4
  117. package/dist/workstation/update/artifact.js +2 -1
  118. package/dist/workstation/update/globalInstall.js +116 -0
  119. package/dist/workstation/update/npmInstaller.js +49 -23
  120. package/dist/workstation/update/rdRollback.js +145 -0
  121. package/dist/workstation/update/runUpdate.js +3 -2
  122. package/dist/workstation/update/watchdog.js +16790 -334
  123. package/package.json +5 -5
  124. package/skills/axom/SKILL.md +11 -11
  125. package/skills/axom-definition/SKILL.md +3 -3
  126. package/skills/axom-platform/SKILL.md +3 -3
  127. package/dist/axom-patch/cli/probes/qoder-steering.mjs +0 -89
  128. package/dist/axom-patch/cli/probes/qoder-subagent-origin.mjs +0 -61
  129. package/dist/axom-patch/cli/qoder-steering.json +0 -52
  130. package/dist/axom-patch/cli/qoder-subagent-origin.json +0 -73
  131. package/dist/commands/guide.js +0 -38
  132. package/dist/runtime-deps/qoder-sdk/package-lock.json +0 -1189
  133. package/dist/runtime-deps/qoder-sdk/package.json +0 -8
  134. package/dist/workstation/acp/delegationMcp.js +0 -24
  135. package/dist/workstation/acp/processor/sideChannel.js +0 -80
  136. package/dist/workstation/acp/qoderStartup.js +0 -45
  137. package/dist/workstation/acp/test/raw/qoderCaptures.js +0 -125
  138. package/dist/workstation/qoderAdapter/backgroundProcess.js +0 -118
  139. package/dist/workstation/qoderAdapter/backgroundTerminal.js +0 -193
  140. package/dist/workstation/qoderAdapter/backgroundTerminalFold.js +0 -372
  141. package/dist/workstation/qoderAdapter/callbackContext.js +0 -76
  142. package/dist/workstation/qoderAdapter/completedContinuation.js +0 -139
  143. package/dist/workstation/qoderAdapter/contract.js +0 -78
  144. package/dist/workstation/qoderAdapter/foregroundOutput.js +0 -36
  145. package/dist/workstation/qoderAdapter/history.js +0 -85
  146. package/dist/workstation/qoderAdapter/identityIndex.js +0 -191
  147. package/dist/workstation/qoderAdapter/inputQueue.js +0 -42
  148. package/dist/workstation/qoderAdapter/main.js +0 -95
  149. package/dist/workstation/qoderAdapter/mapper.js +0 -117
  150. package/dist/workstation/qoderAdapter/observerPlugin.js +0 -245
  151. package/dist/workstation/qoderAdapter/observerReceiver.js +0 -187
  152. package/dist/workstation/qoderAdapter/permissions.js +0 -61
  153. package/dist/workstation/qoderAdapter/profile.js +0 -93
  154. package/dist/workstation/qoderAdapter/sdkDriver.js +0 -48
  155. package/dist/workstation/qoderAdapter/sdkRuntime.js +0 -93
  156. package/dist/workstation/qoderAdapter/sdkRuntimeInstall.js +0 -145
  157. package/dist/workstation/qoderAdapter/session.js +0 -319
  158. package/dist/workstation/qoderAdapter/subagentMeta.js +0 -28
  159. package/dist/workstation/qoderAdapter/subwork.js +0 -85
  160. package/dist/workstation/qoderAdapter/taskControl.js +0 -38
  161. package/dist/workstation/qoderAdapter/taskLedger.js +0 -163
  162. package/dist/workstation/qoderAdapter/usage.js +0 -37
  163. /package/dist/workstation/{qoderAdapter/types.js → desktopControl/provider.js} +0 -0
@@ -2,8 +2,7 @@
2
2
  "id": "zcode-subagent-subwork",
3
3
  "package": "zcode-acp-server",
4
4
  "versions": [
5
- "0.69.3",
6
- "0.69.4"
5
+ "0.76.3"
7
6
  ],
8
7
  "edits": [
9
8
  {
@@ -29,15 +28,15 @@
29
28
  },
30
29
  {
31
30
  "file": "dist/server.js",
32
- "before_sha256": "547d640a68ad56a97bd587348ea38ee3eca57d1fad9ea1d14e04c486e1efc85a",
33
- "after_sha256": "df37fa0b7e5873d13a2cdd71a5fbc931a7ea9ffca521b0218d60a7a9b11e1d3c",
31
+ "before_sha256": "40a55e7b7fc6662a664f9d462dd4c8774e2e73d222669cb3902448c026b6b6a2",
32
+ "after_sha256": "95e940c79d16571c1c125d4536c88c94136ddc09713dee65e003cce3ac2a4a8e",
34
33
  "before": "export class ZcodeAcpServer {",
35
34
  "after": "/** Axom patch `zcode-subagent-subwork`: normalize ZCode sub-agents and background\n * tasks into the draft ACP subagent variants (RFD #1992) and the AIR async-task\n * extension — the same contracts claude-agent-acp ships. The backend already emits\n * first-class lifecycle events on `session.updated` (agentId/childSessionId for\n * sub-agents, taskId for background tasks); this listener forwards them so hosts\n * can project subworks, and dispatch.js re-scopes a foreground sub-agent's internal\n * `tool_subagent_*` tool calls onto its child session. */\nclass AxomZcodeSubagents {\n constructor(server, zcodeSid) {\n this.server = server;\n this.sid = zcodeSid;\n /** agentId → { agentId, child, background, terminal, pendingState, pendingP, resultSeen, preview } */\n this.agents = new Map();\n /** parentToolCallId → agent record (foreground result flush). */\n this.parents = new Map();\n /** taskId → { terminal } (bash/exec background tasks only). */\n this.tasks = new Map();\n }\n /** Draft RFD #1992 negotiated — the axom daemon always declares this. */\n nativeOk() {\n const caps = this.server.clientCapabilities;\n return !!(caps && caps.subagents);\n }\n /** AIR async-task capability declared (`_meta.jetbrains.air.capabilities`). */\n asyncOk() {\n const air = this.server.clientCapabilities?._meta?.jetbrains?.air;\n return !!(air && Array.isArray(air.capabilities) && air.capabilities.includes(\"asyncTasks\"));\n }\n handleEvent(ev) {\n try {\n void this.onEvent(ev);\n }\n catch {\n // Never crash the bridge from a normalization observer.\n }\n }\n async onEvent(ev) {\n if (!ev || ev.type !== \"session.updated\") {\n this.onToolEvent(ev);\n return;\n }\n const p = ev.payload ?? {};\n if (typeof p.agentId === \"string\" && p.agentId && typeof p.childSessionId === \"string\" && p.childSessionId) {\n this.onAgent(p);\n return;\n }\n // Sub-agent background tasks also carry taskId with taskKind \"subagent\" —\n // the agentId path above owns those. Workflow runs have their own poller.\n if (typeof p.taskId === \"string\" && p.taskId && p.taskKind !== \"subagent\" && p.taskKind !== \"workflow\") {\n this.onTask(p);\n }\n }\n onAgent(p) {\n if (!this.nativeOk())\n return;\n const agentId = p.agentId;\n const child = p.childSessionId;\n const status = typeof p.status === \"string\" ? p.status : \"running\";\n let rec = this.agents.get(agentId);\n if (!rec) {\n rec = { agentId, child, background: p.background === true, terminal: false, pendingState: null, pendingP: null, resultSeen: false, preview: null };\n this.agents.set(agentId, rec);\n if (typeof p.parentToolCallId === \"string\" && p.parentToolCallId)\n this.parents.set(p.parentToolCallId, rec);\n // First sighting already terminal (adapter restart): adopt — emit the\n // spawn so the host can still link the child, then the state below.\n if (status !== \"running\")\n rec.resultSeen = true;\n this.emit({\n sessionUpdate: \"subagent_spawned\",\n subagentSessionId: child,\n name: (typeof p.description === \"string\" && p.description) || (typeof p.agentType === \"string\" && p.agentType) || \"Subagent\",\n task: typeof p.prompt === \"string\" ? p.prompt : (p.description ?? \"\"),\n capabilities: {},\n _meta: { zcode: { agentId, parentToolCallId: p.parentToolCallId, background: rec.background, adopted: status !== \"running\" } },\n });\n }\n if (rec.child !== child)\n return;\n const mapped = status === \"completed\" ? \"completed\"\n : status === \"failed\" || status === \"error\" ? \"failed\"\n : status === \"cancelled\" || status === \"stopped\" ? \"cancelled\"\n : status === \"disconnected\" ? \"disconnected\" : null;\n if (!mapped || rec.terminal)\n return;\n if (rec.background || rec.resultSeen || mapped !== \"completed\") {\n this.finishAgent(rec, mapped, p);\n return;\n }\n // Foreground completion: hold the state until the parent Agent tool's own\n // result event arrives (one event later, measured) so the child-scoped\n // preview precedes the terminal state on the wire.\n rec.pendingState = mapped;\n rec.pendingP = p;\n }\n finishAgent(rec, state, p) {\n rec.terminal = true;\n if (rec.preview) {\n this.emitChild(rec.child, { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text: rec.preview } });\n rec.preview = null;\n }\n const meta = { zcode: { agentId: rec.agentId } };\n if (p) {\n for (const key of [\"parentToolCallId\", \"outputFile\"])\n if (typeof p[key] === \"string\")\n meta.zcode[key] = p[key];\n if (typeof p.totalTokens === \"number\")\n meta.zcode.totalTokens = p.totalTokens;\n if (typeof p.totalDurationMs === \"number\")\n meta.zcode.totalDurationMs = p.totalDurationMs;\n }\n this.emit({ sessionUpdate: \"subagent_state_update\", subagentSessionId: rec.child, state, _meta: meta });\n }\n onToolEvent(ev) {\n if (!ev || ev.type !== \"tool.updated\")\n return;\n const p = ev.payload ?? {};\n if (p.kind !== \"result\" || typeof p.toolCallId !== \"string\")\n return;\n const rec = this.parents.get(p.toolCallId);\n if (!rec || rec.terminal || rec.background)\n return;\n rec.resultSeen = true;\n const text = axomSubagentResultPreview(p.result);\n if (text)\n rec.preview = text;\n if (rec.pendingState)\n this.finishAgent(rec, rec.pendingState, rec.pendingP);\n }\n onTask(p) {\n if (!this.asyncOk())\n return;\n const taskId = p.taskId;\n let task = this.tasks.get(taskId);\n const status = typeof p.status === \"string\" ? p.status : \"running\";\n if (!task) {\n task = { terminal: false };\n this.tasks.set(taskId, task);\n this.emit({\n sessionUpdate: \"async_task_spawned\",\n asyncTaskId: taskId,\n name: (typeof p.description === \"string\" && p.description) || (typeof p.command === \"string\" && p.command) || \"background task\",\n taskType: typeof p.taskKind === \"string\" ? p.taskKind : \"shell\",\n description: typeof p.description === \"string\" ? p.description : \"\",\n showInTranscript: false,\n canStop: p.cancellable === true,\n ...(typeof p.outputPath === \"string\" ? { outputFilePath: p.outputPath } : {}),\n ...(typeof p.toolCallId === \"string\" ? { toolCallId: p.toolCallId } : {}),\n _meta: { zcode: { taskKind: p.taskKind, command: p.command } },\n });\n }\n const mapped = status === \"completed\" ? \"completed\"\n : status === \"failed\" || status === \"error\" ? \"failed\"\n : status === \"cancelled\" ? \"stopped\" : null;\n if (!mapped || task.terminal)\n return;\n task.terminal = true;\n this.emit({\n sessionUpdate: \"async_task_state_update\",\n asyncTaskId: taskId,\n state: mapped,\n ...(typeof p.toolCallId === \"string\" ? { toolCallId: p.toolCallId } : {}),\n });\n }\n emit(update) {\n void this.server.notifyByZcodeSid(this.sid, update);\n }\n emitChild(childId, update) {\n const server = this.server;\n if (!server.clients || server.clients.size === 0)\n return;\n void enqueueSessionSend(childId, () => server.clients.broadcast().notify(\"session/update\", { sessionId: childId, update }));\n }\n}\n/** The parent Agent tool's result carries the sub-agent's final message plus an\n * `agentId:` line and a `<usage>` block that belong to the envelope, not the\n * answer. The backend delivers the payload as a JSON string or as an already\n * parsed object (both measured) — accept either. */\nfunction axomSubagentResultPreview(result) {\n let content = null;\n if (typeof result === \"string\") {\n try {\n const parsed = JSON.parse(result);\n if (parsed && typeof parsed.content === \"string\")\n content = parsed.content;\n }\n catch {\n content = result;\n }\n }\n else if (result && typeof result === \"object\" && typeof result.content === \"string\") {\n content = result.content;\n }\n if (typeof content !== \"string\" || !content.trim())\n return null;\n const stripped = content\n .replace(/<usage>[\\s\\S]*?<\\/usage>/g, \"\")\n .split(\"\\n\")\n .filter((line) => !/^agentId:\\s*\\S+/.test(line))\n .join(\"\\n\")\n .trim();\n return stripped ? stripped.slice(0, 2000) : null;\n}\nexport { AxomZcodeSubagents };\nexport class ZcodeAcpServer {"
36
35
  },
37
36
  {
38
37
  "file": "dist/server.js",
39
- "before_sha256": "df37fa0b7e5873d13a2cdd71a5fbc931a7ea9ffca521b0218d60a7a9b11e1d3c",
40
- "after_sha256": "55d776521298e0a59d7512be34aeb2b86bc10a4cce9b038a9387ab860ab1aa2c",
38
+ "before_sha256": "95e940c79d16571c1c125d4536c88c94136ddc09713dee65e003cce3ac2a4a8e",
39
+ "after_sha256": "240a49618e47792dfbaa5f713dca8072bd1e0c56f726e177a1936e071c69df42",
41
40
  "before": " backend.registerEventListener(zcodeSid, new SessionTitleListener(this, zcodeSid));\n this.backgroundListenerBackend.set(zcodeSid, backend);",
42
41
  "after": " backend.registerEventListener(zcodeSid, new SessionTitleListener(this, zcodeSid));\n backend.registerEventListener(zcodeSid, new AxomZcodeSubagents(this, zcodeSid));\n this.backgroundListenerBackend.set(zcodeSid, backend);"
43
42
  },
@@ -57,15 +56,15 @@
57
56
  },
58
57
  {
59
58
  "file": "dist/handlers/session.js",
60
- "before_sha256": "e36756aa50f823d97df4861566fafc2ea6b36d7baf6d1f9aa9f918930e1c40a6",
61
- "after_sha256": "799343ea4036b518ad7d411d192c696ebe821a4eb2b32e87c0b8b5f288cf509f",
59
+ "before_sha256": "770b8094520487b3eefbea3b47edfad82895bb2658b38dd8c70b201f29ac07be",
60
+ "after_sha256": "86877e687c74d97e581a0991e549842130567e2041cf4caa10b8ae910a0f2a77",
62
61
  "before": "async function adoptStoredTitle(server, acpSid, zcodeSid) {\n if (server.sessionTitles.has(acpSid))\n return;",
63
62
  "after": "async function adoptStoredTitle(server, acpSid, zcodeSid) {\n // Axom patch `zcode-subagent-subwork`: the in-memory title is usually the first\n // prompt's echo; the backend's stored generated title is the real answer, and the\n // live titleUpdated push is routinely lost at a backend respawn boundary — this\n // load-time read is then the only surviving copy. A user-pinned rename still wins.\n if (server.sessionTitles.has(acpSid) && server.titleUserSetBy.has(acpSid))\n return;"
64
63
  },
65
64
  {
66
65
  "file": "dist/handlers/session.js",
67
- "before_sha256": "799343ea4036b518ad7d411d192c696ebe821a4eb2b32e87c0b8b5f288cf509f",
68
- "after_sha256": "e28f651c842a85e308e12f3e97d742bcb49a2f470530f7fe3babe4c04fdca4c9",
66
+ "before_sha256": "86877e687c74d97e581a0991e549842130567e2041cf4caa10b8ae910a0f2a77",
67
+ "after_sha256": "ba1d5ba52957793c9f392ee6ab425a13eb912e1a5544b485d548d11e25f95a95",
69
68
  "before": " if (hit?.title) {\n server.sessionTitles.set(acpSid, hit.title);\n server.touchSessionSummary(acpSid, hit.title);\n refreshTerminalTabTitle(server, acpSid);\n log(`adopted stored title for ${acpSid.slice(0, 8)}: ${hit.title}`);\n }",
70
69
  "after": " if (hit?.title && server.sessionTitles.get(acpSid) !== hit.title) {\n server.sessionTitles.set(acpSid, hit.title);\n server.touchSessionSummary(acpSid, hit.title);\n refreshTerminalTabTitle(server, acpSid);\n // Axom patch `zcode-subagent-subwork`: broadcast so hosts sync the stored\n // generated title on (re-)attach — the live push was lost at a respawn.\n void sendSessionUpdate(server.clients.broadcast(), acpSid, {\n sessionUpdate: \"session_info_update\",\n title: hit.title,\n updatedAt: new Date().toISOString(),\n }).catch(() => { });\n log(`adopted stored title for ${acpSid.slice(0, 8)}: ${hit.title}`);\n }"
71
70
  }
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import { realpathSync } from 'node:fs';
4
4
  import { fileURLToPath, pathToFileURL } from 'node:url';
5
5
  import { authAction, logoutAction } from './commands/auth.js';
6
6
  import { registerExecuteCommand } from './commands/execute.js';
7
- import { registerGuideCommands } from './commands/guide.js';
7
+ import { registerKnowledgeCommands } from './commands/knowledge.js';
8
8
  import { registerRecordCommands } from './commands/record.js';
9
9
  import { registerSkillsCommands } from './commands/skills.js';
10
10
  import { registerStructCommands } from './commands/struct.js';
@@ -39,50 +39,18 @@ export function buildProgram() {
39
39
  program
40
40
  .command('__credential-broker', { hidden: true })
41
41
  .action(() => runCredentialBroker());
42
- const qoderCommand = program.command('qoder-acp')
43
- .description('Prepare or run the Qoder SDK ACP adapter')
44
- .option('--qodercli <path>', 'Explicit Qoder CLI executable')
45
- .option('--prepare-sdk', 'Install the separate SDK runtime, then exit');
46
- qoderCommand.action(async (options) => {
47
- if (Boolean(options.qodercli) === Boolean(options.prepareSdk))
48
- qoderCommand.error('Choose exactly one of --prepare-sdk or --qodercli <path>');
49
- try {
50
- if (options.prepareSdk) {
51
- const { prepareSdkRuntime } = await import('./workstation/qoderAdapter/sdkRuntimeInstall.js');
52
- const controller = new AbortController();
53
- const cancel = () => controller.abort();
54
- process.once('SIGINT', cancel);
55
- process.once('SIGTERM', cancel);
56
- try {
57
- console.error('Preparing Qoder SDK…');
58
- const result = await prepareSdkRuntime({ signal: controller.signal });
59
- console.error(`Qoder SDK ready${result.alreadyInstalled ? ' (already prepared)' : ''}: ${result.instance}`);
60
- }
61
- finally {
62
- process.removeListener('SIGINT', cancel);
63
- process.removeListener('SIGTERM', cancel);
64
- }
65
- }
66
- else {
67
- const { runQoderAdapter } = await import('./workstation/qoderAdapter/main.js');
68
- await runQoderAdapter(options.qodercli);
69
- }
70
- }
71
- catch (error) {
72
- console.error(error instanceof Error ? error.message : String(error));
73
- process.exitCode = 1;
74
- }
75
- });
76
42
  registerStructCommands(program);
77
43
  registerRecordCommands(program);
78
44
  registerExecuteCommand(program);
79
- registerGuideCommands(program);
45
+ registerKnowledgeCommands(program);
80
46
  registerSkillsCommands(program);
81
47
  registerUpdateCommand(program);
82
48
  registerWorkstationCommands(program, {
83
49
  start, stop, restart, install, uninstall, runDaemon, registerWorkstation,
84
50
  status: async () => {
85
51
  const current = await status();
52
+ if (current.uncertain)
53
+ return 'workstation state is unknown; run `axom workstation inspect --json` to verify it';
86
54
  return current.running
87
55
  ? `running connected to ${current.server ?? 'unknown server'} as ${current.workstationId ?? 'unknown workstation'}`
88
56
  : 'stopped';
@@ -0,0 +1,47 @@
1
+ import { loadConfig, resolveServer, UsageError } from '../config.js';
2
+ import { callAxomTool } from '../mcp.js';
3
+ import { printOutcome, runCommand } from '../output.js';
4
+ export const GUIDE_RENAMED_MESSAGE = 'axom guide was renamed: use axom knowledge get|search';
5
+ export function registerKnowledgeCommands(program) {
6
+ const knowledge = program.command('knowledge').description('Read and search the Axomwork manual');
7
+ const serverOption = () => program.opts().server;
8
+ knowledge
9
+ .command('get')
10
+ .description('Get a manual page, or the table of contents when no path is given')
11
+ .argument('[path]', 'manual page path, e.g. script-language/sdk/records.md')
12
+ .option('--locale <locale>', 'manual locale (en|zh)')
13
+ .action((path, options) => runCommand(() => knowledgeGetAction({ path, locale: options.locale, server: serverOption() })));
14
+ knowledge
15
+ .command('search')
16
+ .description('Search the manual with keywords or a question')
17
+ .argument('<query>')
18
+ .option('--locale <locale>', 'manual locale (en|zh)')
19
+ .option('--limit <n>', 'maximum hits')
20
+ .action((query, options) => runCommand(() => knowledgeSearchAction({ query, locale: options.locale, limit: options.limit, server: serverOption() })));
21
+ // Deliberately not an alias: old scripts must fail loudly and learn the new name.
22
+ program
23
+ .command('guide', { hidden: true })
24
+ .allowUnknownOption()
25
+ .allowExcessArguments()
26
+ .argument('[args...]')
27
+ .helpOption(false)
28
+ .action(() => runCommand(async () => { throw new UsageError(GUIDE_RENAMED_MESSAGE); }));
29
+ }
30
+ export async function knowledgeGetAction(options) {
31
+ const server = resolveServer(await loadConfig(), options.server);
32
+ const args = {};
33
+ if (options.path !== undefined)
34
+ args.path = options.path;
35
+ if (options.locale !== undefined)
36
+ args.locale = options.locale;
37
+ printOutcome(await callAxomTool(server, 'axom__knowledge__get', args));
38
+ }
39
+ export async function knowledgeSearchAction(options) {
40
+ const server = resolveServer(await loadConfig(), options.server);
41
+ const args = { query: options.query };
42
+ if (options.locale !== undefined)
43
+ args.locale = options.locale;
44
+ if (options.limit !== undefined)
45
+ args.limit = Number(options.limit);
46
+ printOutcome(await callAxomTool(server, 'axom__knowledge__search', args));
47
+ }
@@ -1,3 +1,11 @@
1
+ import { z } from 'zod';
2
+ import { inspectWorkstation } from '../workstation/control/inspect.js';
3
+ import { requestRuntimeUpdate } from '../workstation/control/runtimeClient.js';
4
+ import { withWorkstationLock } from '../workstation/control/locks.js';
5
+ import { bindingGuardSchema, LocalControlError } from '../workstation/control/protocol.js';
6
+ import { enrollmentFailure } from '../workstation/control/enrollment.js';
7
+ import { readLocalRequest } from '../workstation/control/commands.js';
8
+ import { deploymentDownloadURL, normalizeWorkstationServer, workstationEndpoint } from '../workstation/control/serverIdentity.js';
1
9
  import { randomUUID } from 'node:crypto';
2
10
  import { UsageError, loadConfig, resolveServer } from '../config.js';
3
11
  import { runCommand } from '../output.js';
@@ -13,8 +21,8 @@ function isManifest(value) {
13
21
  }
14
22
  /** Fetches the release the server currently publishes for this exact deployment. */
15
23
  async function fetchManifest(server, fetchImpl) {
16
- const url = new URL('/download/client/manifest.json', server).toString();
17
- const response = await fetchImpl(url);
24
+ const url = workstationEndpoint(server, '/download/client/manifest.json').toString();
25
+ const response = await fetchImpl(url, { redirect: 'error', signal: AbortSignal.timeout(30_000) });
18
26
  if (!response.ok) {
19
27
  throw new Error(`Fetching the release manifest failed with HTTP ${response.status}`);
20
28
  }
@@ -55,6 +63,15 @@ export async function updateAction(options, deps = {}) {
55
63
  version: manifest.version, url: manifest.url, size: manifest.size, sha512: manifest.sha512,
56
64
  };
57
65
  const dir = deps.dir ?? clientDir();
66
+ if (!deps.createCoordinator) {
67
+ const current = await inspectWorkstation(dir);
68
+ const result = await updateLocalCli({ operationId: `manual-${randomUUID()}`, server, guard: { revision: current.revision, runtimeGeneration: current.runtime.generation }, expectedRelease: { version: release.version, sha512: release.sha512 } }, dir, fetchImpl);
69
+ if (result.status === 'succeeded' || result.status === 'pending') {
70
+ (deps.log ?? console.log)(result.status === 'pending' ? 'Update requested. Check workstation status for progress.' : `Installed ${release.version}.`);
71
+ return;
72
+ }
73
+ throw new Error(result.error?.message ?? 'The workstation is busy; try again when its work finishes.');
74
+ }
58
75
  const coordinator = deps.createCoordinator ? deps.createCoordinator({ dir, server }) : defaultCoordinator(dir, server);
59
76
  const command = { commandId: `manual-${randomUUID()}`, release, force: false };
60
77
  const status = await coordinator.handle(command);
@@ -78,11 +95,56 @@ export async function updateAction(options, deps = {}) {
78
95
  throw new Error(status.error ?? `Update did not complete (phase: ${status.phase}).`);
79
96
  }
80
97
  }
98
+ const updateRequestSchema = z.object({ operationId: z.string().min(1).max(128), server: z.string(), guard: bindingGuardSchema, expectedRelease: z.object({ version: z.string(), sha512: z.string().regex(/^[a-f0-9]{128}$/i) }).strict() }).strict();
99
+ export async function updateLocalCli(raw, directory, fetchImpl = globalThis.fetch) {
100
+ try {
101
+ const request = updateRequestSchema.parse(raw);
102
+ const server = normalizeWorkstationServer(request.server);
103
+ const manifest = await fetchManifest(server, fetchImpl);
104
+ if (manifest.version !== request.expectedRelease.version || manifest.sha512 !== request.expectedRelease.sha512)
105
+ throw new LocalControlError('BINDING_CONFLICT', 'The published release changed; review it again');
106
+ manifest.url = deploymentDownloadURL(server, manifest.url);
107
+ return await withWorkstationLock(directory, 'installation', () => withWorkstationLock(directory, 'operation', async () => {
108
+ const current = await inspectWorkstation(directory);
109
+ if (current.revision !== request.guard.revision || current.runtime.generation !== request.guard.runtimeGeneration)
110
+ throw new LocalControlError('BINDING_CONFLICT', 'Workstation changed; check it again');
111
+ if (current.runtime.state === 'unknown')
112
+ throw new LocalControlError('OUTCOME_UNKNOWN', 'Stop and verify the existing daemon before updating');
113
+ if (current.runtime.state === 'running' && current.runtime.binding?.server !== server)
114
+ throw new LocalControlError('INSTANCE_OCCUPIED', 'Another server owns the running daemon');
115
+ const status = current.runtime.state === 'running'
116
+ ? await requestRuntimeUpdate(directory, manifest, request.operationId)
117
+ : await createUpdateCoordinator({ dir: directory, server, cliPath: CLI_PATH, serviceLifecycle: 'none', installationLockHeld: true }).handle({ commandId: request.operationId, release: manifest, force: false });
118
+ return { status: ['BUSY', 'UPDATE_IN_PROGRESS'].includes(status.phase) ? 'busy' : status.phase === 'SUCCEEDED' ? 'succeeded' : status.phase === 'FAILED' || status.phase === 'ROLLED_BACK' ? 'failed' : 'pending', inspection: await inspectWorkstation(directory) };
119
+ }));
120
+ }
121
+ catch (error) {
122
+ return enrollmentFailure(error, directory);
123
+ }
124
+ }
81
125
  export function registerUpdateCommand(program) {
82
126
  const serverOption = () => program.opts().server;
83
127
  program
84
128
  .command('update')
85
129
  .description('Update axom-cli to the release the configured server currently publishes')
130
+ .option('--json', 'Emit local management protocol JSON')
131
+ .option('--input-stdin', 'Read the guarded update request from stdin')
86
132
  .option('--version <version>', 'Fail unless the server-published release matches this exact version')
87
- .action((options) => runCommand(() => updateAction({ server: serverOption(), version: options.version })));
133
+ .action((options) => runCommand(async () => {
134
+ if (!options.json)
135
+ return updateAction({ server: serverOption(), version: options.version });
136
+ if (!options.inputStdin)
137
+ throw new UsageError('--json requires --input-stdin');
138
+ let request;
139
+ let result;
140
+ try {
141
+ request = await readLocalRequest(process.stdin);
142
+ result = await updateLocalCli(request, clientDir());
143
+ }
144
+ catch (error) {
145
+ result = await enrollmentFailure(error, clientDir());
146
+ }
147
+ const id = updateRequestSchema.safeParse(request);
148
+ process.stdout.write(JSON.stringify({ schemaVersion: 1, kind: 'result', operationId: id.success ? id.data.operationId : randomUUID(), result }) + '\n');
149
+ }));
88
150
  }
@@ -1,3 +1,7 @@
1
+ import { assertIdentityCanStart, recoverStoppedIdentity } from '../workstation/control/daemonIdentity.js';
2
+ import { withWorkstationLock } from '../workstation/control/locks.js';
3
+ import { inspectWorkstation } from '../workstation/control/inspect.js';
4
+ import { runLocalJsonCommand } from '../workstation/control/commands.js';
1
5
  import { hostname } from 'node:os';
2
6
  import { basename } from 'node:path';
3
7
  import { loadConfig, resolveServer, UsageError } from '../config.js';
@@ -6,6 +10,8 @@ import { ensureFreshToken } from '../mcp.js';
6
10
  import { runCommand } from '../output.js';
7
11
  import { clientDir, loadClientConfig } from '../workstation/config.js';
8
12
  import { resolveWorkstationName, sanitizeName } from '../workstation/names.js';
13
+ import { configureRd, rdStatus } from '../workstation/rd/control.js';
14
+ import { runManagedDesktop } from '../workstation/rd/sessions.js';
9
15
  /**
10
16
  * Registers this workstation with the server if it has no credential yet, then leaves it alone.
11
17
  * Returns whether it just registered (`false` when an existing credential meant there was nothing
@@ -89,6 +95,7 @@ function dropAccessTokenFromEnvironment() {
89
95
  * top-level argument (see service/launchd.ts and service/systemd.ts).
90
96
  */
91
97
  export function registerWorkstationCommands(program, deps) {
98
+ const localJson = deps.localJson ?? runLocalJsonCommand;
92
99
  const workstation = program.command('workstation').description('Manage the local Axomwork workstation daemon');
93
100
  // Same idiom as `registerUpdateCommand`: the global `--server` is read at action time, not at
94
101
  // registration time, so `axom --server <url> workstation start` works. `axom auth` only writes
@@ -106,12 +113,29 @@ export function registerWorkstationCommands(program, deps) {
106
113
  // own `options.name` the dead one instead. `start`'s action below reads the whole fallback chain
107
114
  // so it doesn't matter which link is live for a given flag.
108
115
  const workstationOption = () => workstation.opts();
116
+ const applyRd = deps.configureRd ?? configureRd;
109
117
  workstation
110
118
  .command('start')
119
+ .option('--json', 'Emit local management protocol JSON')
120
+ .option('--input-stdin', 'Read the guarded request from stdin')
111
121
  .option('--server <url>', 'Axomwork server URL to register this workstation against')
112
122
  .option('--name <name>', 'Workstation name (default: AXOM_WORKSTATION_NAME, then the hostname)')
123
+ .option('--enable-rd', 'Install and enable Linux remote desktop')
124
+ .option('--disable-rd', 'Disable remote desktop without changing workstation registration')
125
+ .option('--rd-session <mode>', 'Desktop selection: auto, existing, or virtual')
126
+ .option('--rd-display <display>', 'Choose an existing local X11 display, such as :10')
113
127
  .description('Start the workstation user service')
114
128
  .action((options) => runCommand(async () => {
129
+ const rd = { ...workstationOption(), ...options, server: options.server ?? workstationOption().server ?? serverOption() };
130
+ if (options.json && (rd.enableRd || rd.disableRd || rd.rdSession || rd.rdDisplay))
131
+ throw new UsageError('RD flags cannot be combined with the JSON management protocol');
132
+ if (options.json) {
133
+ if (!options.inputStdin)
134
+ throw new UsageError('--json requires --input-stdin');
135
+ await localJson('start');
136
+ return;
137
+ }
138
+ await applyRd(clientDir(), rd);
115
139
  // `install()` runs only when this call just registered the workstation, not on every
116
140
  // `start` — it's not the free idempotent no-op it looks like. On macOS it's bootout, write
117
141
  // plist, bootstrap, and the `deps.start()` right after it is `kickstart -k`: on an
@@ -122,40 +146,82 @@ export function registerWorkstationCommands(program, deps) {
122
146
  // by a removed nvm version only if that's a *good* node; run from an ad-hoc one and it
123
147
  // manufactures the exact stranding it's meant to cure. That repair belongs to the explicit
124
148
  // verb that already exists for it, `axom workstation install`, not as a side effect here.
149
+ await withWorkstationLock(clientDir(), 'operation', async () => { await recoverStoppedIdentity(clientDir()); await assertIdentityCanStart(clientDir()); });
125
150
  const justRegistered = await ensureRegistered(deps, options.server ?? workstationOption().server ?? serverOption(), options.name ?? workstationOption().name);
126
- if (justRegistered)
127
- await deps.install();
128
- await deps.start();
151
+ await withWorkstationLock(clientDir(), 'operation', async () => { await assertIdentityCanStart(clientDir()); if (justRegistered)
152
+ await deps.install(); await deps.start(); });
129
153
  }));
130
154
  workstation
131
155
  .command('stop')
156
+ .option('--json', 'Emit local management protocol JSON')
157
+ .option('--input-stdin', 'Read the guarded request from stdin')
132
158
  .description('Stop the workstation user service')
133
- .action(() => runCommand(async () => { await deps.stop(); }));
159
+ .action((options) => runCommand(async () => { if (options.json) {
160
+ if (!options.inputStdin)
161
+ throw new UsageError('--json requires --input-stdin');
162
+ await localJson('stop');
163
+ }
164
+ else
165
+ await withWorkstationLock(clientDir(), 'operation', () => deps.stop()); }));
134
166
  workstation
135
167
  .command('restart')
168
+ .option('--json', 'Emit local management protocol JSON')
169
+ .option('--input-stdin', 'Read the guarded request from stdin')
136
170
  .description('Restart the workstation user service')
137
- .action(() => runCommand(async () => { await deps.restart(); }));
171
+ .action((options) => runCommand(async () => { if (options.json) {
172
+ if (!options.inputStdin)
173
+ throw new UsageError('--json requires --input-stdin');
174
+ await localJson('restart');
175
+ }
176
+ else
177
+ await withWorkstationLock(clientDir(), 'operation', async () => { await recoverStoppedIdentity(clientDir()); await assertIdentityCanStart(clientDir()); await deps.restart(); }); }));
138
178
  workstation
139
179
  .command('status')
140
180
  .description('Report whether the workstation daemon is running')
141
181
  .action(() => runCommand(async () => { deps.log(await deps.status()); }));
142
182
  workstation
143
183
  .command('install')
184
+ .option('--json', 'Emit local management protocol JSON')
185
+ .option('--input-stdin', 'Read the guarded request from stdin')
144
186
  .description('Install and enable the operating-system service')
145
- .action(() => runCommand(async () => { await deps.install(); }));
187
+ .action((options) => runCommand(async () => { if (options.json) {
188
+ if (!options.inputStdin)
189
+ throw new UsageError('--json requires --input-stdin');
190
+ await localJson('install');
191
+ }
192
+ else
193
+ await withWorkstationLock(clientDir(), 'operation', async () => { await recoverStoppedIdentity(clientDir()); await assertIdentityCanStart(clientDir()); await deps.install(); }); }));
146
194
  workstation
147
195
  .command('uninstall')
148
196
  .description('Disable and remove the operating-system service')
149
- .action(() => runCommand(async () => { await deps.uninstall(); }));
197
+ .action(() => runCommand(async () => { await withWorkstationLock(clientDir(), 'operation', () => deps.uninstall()); }));
198
+ workstation.command('inspect').requiredOption('--json', 'Emit local management protocol JSON')
199
+ .action(() => runCommand(async () => { process.stdout.write(JSON.stringify(await inspectWorkstation(clientDir())) + '\n'); }));
200
+ workstation.command('set-enabled').description('Persistently enable or disable this workstation service')
201
+ .requiredOption('--json').requiredOption('--input-stdin').action(() => localJson('set-enabled'));
202
+ for (const verb of ['register', 'forget', 'begin-remove', 'adopt-owner', 'recover']) {
203
+ workstation.command(verb, { hidden: verb === 'forget' }).requiredOption('--json', 'Emit local management protocol JSON')
204
+ .requiredOption('--input-stdin', 'Read the guarded request from stdin').action(() => localJson(verb));
205
+ }
206
+ const rd = workstation.command('rd').description('Manage Linux remote desktop independently of the workstation service');
207
+ rd.command('status').action(() => runCommand(async () => { deps.log(JSON.stringify(await rdStatus(clientDir()), null, 2)); }));
208
+ rd.command('disable').action(() => runCommand(async () => { await applyRd(clientDir(), { disableRd: true }); }));
150
209
  workstation
151
210
  .option('--server <url>', 'Axomwork server URL to register against (default: AXOM_SERVER, then the stored default)')
152
211
  .option('--name <name>', 'Workstation name (default: AXOM_WORKSTATION_NAME, then the hostname)')
212
+ .option('--enable-rd', 'Install and enable Linux remote desktop')
213
+ .option('--disable-rd', 'Disable remote desktop without changing workstation registration')
214
+ .option('--rd-session <mode>', 'Desktop selection: auto, existing, or virtual')
215
+ .option('--rd-display <display>', 'Choose an existing local X11 display, such as :10')
153
216
  .description('Run the workstation daemon in the foreground (Docker ENTRYPOINT / debugging); subcommands manage the OS service')
154
217
  .action((options) => runCommand(async () => {
218
+ await applyRd(clientDir(), { ...options, server: options.server ?? serverOption() });
155
219
  await ensureRegistered(deps, options.server ?? serverOption(), options.name);
156
220
  dropAccessTokenFromEnvironment();
157
221
  await deps.runDaemon({ supervision: deps.detectSupervision() });
158
222
  }));
223
+ program.command('__rd-desktop', { hidden: true }).requiredOption('--directory <path>')
224
+ .action((options) => runCommand(async () => { dropAccessTokenFromEnvironment(); await runManagedDesktop(options.directory); }));
159
225
  program.command('__daemon', { hidden: true }).action(() => runCommand(async () => {
160
226
  // The literal exec target launchd/systemd start: the one call site allowed to opt into
161
227
  // OS-service treatment. See RunDaemonOptions in daemon.ts for why this must be an explicit
@@ -12,7 +12,7 @@ Workflow:
12
12
  2. \`axom__app_struct__list_models\` / \`axom__app_struct__get_model\` for a model's attributes, operations, and display metadata.
13
13
  3. Prefer read-only struct tools here; do not mutate anything from this command.
14
14
 
15
- For the underlying concepts (applications, models, attributes, references), load guide \`concepts/data-model/index.md\` with \`axom__guide__load\`.
15
+ For the underlying concepts (applications, models, attributes, references), see knowledge page \`concepts/data-model/index.md\` (\`axom__knowledge__get\`).
16
16
  `,
17
17
  record: `---
18
18
  description: Query, create, update, upsert, or delete Axomwork records
@@ -24,11 +24,11 @@ $ARGUMENTS
24
24
 
25
25
  Workflow:
26
26
  1. Discover structure first when unsure: \`axom__app_struct__get_model\` for attribute names and types.
27
- 2. Query with \`axom__record_query__query_records\` (filters/sorts/page criteria — for criteria syntax, load guide \`agent-integration/mcp/record-query-criteria.md\`).
27
+ 2. Query with \`axom__record_query__query_records\` (filters/sorts/page criteria — for criteria syntax, see knowledge page \`agent-integration/mcp/record-query-criteria.md\`).
28
28
  3. Mutate with \`axom__record_write__create_record\` / \`axom__record_write__update_record\` / \`axom__record_write__upsert_record\` / \`axom__record_write__delete_record\`. Read the record first before updating; confirm with the user before deleting.
29
29
  4. \`axom__record_write__upsert_record\` needs \`identityField\` and the identity value inside \`record\`.
30
30
 
31
- For safe mutation patterns, load guide \`agent-integration/operating-patterns/safe-record-mutations.md\`.
31
+ For safe mutation patterns, see knowledge page \`agent-integration/operating-patterns/safe-record-mutations.md\`.
32
32
  `,
33
33
  execute: `---
34
34
  description: Execute Axomwork operations and services, following async runs to completion
@@ -44,7 +44,7 @@ Workflow:
44
44
  3. Interpret the ExecuteResult payload: \`status\` (success/failure/running), \`message\`, \`text\`, \`returnValue\`, \`runId\`/\`runType\`, \`errors[]\` ({target,code,message}).
45
45
  4. When \`status\` is \`running\`, follow \`runId\` (see \`runType\`) until a terminal state before reporting the outcome.
46
46
 
47
- For sync-vs-job semantics load guide \`concepts/execution/synchronous-and-task-execution.md\`; for run following load guide \`agent-integration/operating-patterns/following-runs.md\`.
47
+ For sync-vs-job semantics see knowledge page \`concepts/execution/synchronous-and-task-execution.md\`; for run following see knowledge page \`agent-integration/operating-patterns/following-runs.md\`.
48
48
  `,
49
49
  definition: `---
50
50
  description: Develop Axomwork definitions — apps, models, attributes, operations, workflows (requires app_studio scope and an admin account)
@@ -56,8 +56,8 @@ $ARGUMENTS
56
56
 
57
57
  Rules:
58
58
  1. ETag workflow: read the resource first, send its \`etag\` back as \`expectedEtag\` (bodies use \`expectedBodyEtag\`). On conflict, re-read and merge intentionally.
59
- 2. Before authoring \`.axom.kts\` script bodies, load guide \`script-language/sdk/index.md\`; workflow DSL: \`script-language/workflows/index.md\`; sync/job/streaming patterns: \`script-language/patterns/index.md\`.
60
- 3. For definition semantics (apps, models, attributes, operations, workflows), load guide \`application-development/index.md\`.
59
+ 2. Before authoring \`.axom.kts\` script bodies, see knowledge page \`script-language/sdk/index.md\`; workflow DSL: \`script-language/workflows/index.md\`; sync/job/streaming patterns: \`script-language/patterns/index.md\`.
60
+ 3. For definition semantics (apps, models, attributes, operations, workflows), see knowledge page \`application-development/index.md\`.
61
61
  4. Confirm destructive definition deletes with the user first.
62
62
  `,
63
63
  platform: `---
@@ -70,20 +70,20 @@ $ARGUMENTS
70
70
 
71
71
  Rules:
72
72
  1. Read current configuration before editing; respect ETag guards where tools expose them.
73
- 2. For configuration semantics (AI providers and profiles, cowork agents, datasources, platform skills and settings), load guide \`platform-operations/index.md\` first.
73
+ 2. For configuration semantics (AI providers and profiles, cowork agents, datasources, platform skills and settings), see knowledge page \`platform-operations/index.md\` first.
74
74
  3. Confirm with the user before changes that can interrupt running workflows or agent sessions.
75
75
  `,
76
- guide: `---
77
- description: Look something up in the Axomwork Guide (platform manual)
76
+ knowledge: `---
77
+ description: Look something up in the Axomwork manual
78
78
  ---
79
79
 
80
- Answer using the Axomwork Guide:
80
+ Answer using the Axomwork manual:
81
81
 
82
82
  $ARGUMENTS
83
83
 
84
84
  Workflow:
85
- 1. \`axom__guide__search\` with keywords or the question itself; read the ranked snippets.
86
- 2. \`axom__guide__load\` a hit's \`path\` for the full page (omit \`path\` for the table of contents).
87
- 3. Answer from guide content and cite the guide paths you used. If the guide has no answer, say so and fall back to tool discovery (\`tools/list\`).
85
+ 1. \`axom__knowledge__search\` with keywords or the question itself; read the ranked snippets.
86
+ 2. \`axom__knowledge__get\` a hit's \`path\` for the full page (omit \`path\` for the table of contents).
87
+ 3. Answer from the manual and cite the knowledge page paths you used. If the manual has no answer, say so and fall back to tool discovery (\`tools/list\`).
88
88
  `,
89
89
  };
package/dist/mcp.js CHANGED
@@ -98,7 +98,7 @@ export function isInsufficientScope(error) {
98
98
  return /\b403\b/.test(message);
99
99
  }
100
100
  /** Abilities every credential has (Ability registry: BASELINE with the MCP surface). */
101
- const BASELINE_TOOL_SCOPES = new Set(['system', 'guide', 'app_struct']);
101
+ const BASELINE_TOOL_SCOPES = new Set(['system', 'knowledge', 'app_struct']);
102
102
  const TOOL_SCOPE = /^axom__([a-z][a-z0-9]*(?:_[a-z0-9]+)*)__[a-z]/;
103
103
  const ADMIN_NOTE = ' Scopes marked "Requires an administrator account" on the consent page also need an administrator user.';
104
104
  /** An external tool's middle segment IS the OAuth scope that grants it (spec 2026-09-26 §3.5). */