@inneranimalmedia/agentsam-sdk 2.6.7 → 2.6.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 (371) hide show
  1. package/README.md +37 -0
  2. package/apps/README.md +25 -0
  3. package/apps/cad-creator/shared/cad/package.json +1 -1
  4. package/apps/client-cms-editor/backend/package.json +4 -6
  5. package/apps/client-cms-editor/frontend/package.json +6 -8
  6. package/apps/client-cms-editor/frontend/tsconfig.json +27 -8
  7. package/apps/client-cms-editor/package.json +1 -1
  8. package/apps/client-cms-editor/shared/cms/package.json +4 -6
  9. package/docs/LOCAL_ENGINE_COMPUTE_AUDIT_PLAN.md +299 -0
  10. package/docs/REPO_FILE_MAP.txt +132 -0
  11. package/migrations/d1/0018_goap_control_plane_remaster.sql +40 -0
  12. package/migrations/d1/0019_agentsam_agent_run_plan_todo.sql +14 -0
  13. package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +20 -9
  14. package/migrations/runtime/0002_goap_blackboard_v1.sql +15 -0
  15. package/migrations/runtime/0004_agent_run_plan_linkage.sql +8 -0
  16. package/native/agentsam-machine/cli/Cargo.toml +8 -1
  17. package/native/agentsam-machine/cli/README.md +21 -0
  18. package/native/agentsam-machine/core/Cargo.toml +7 -0
  19. package/native/agentsam-machine/core/README.md +14 -0
  20. package/native/agentsam-machine/core/build.rs +33 -0
  21. package/native/agentsam-machine/core/contracts/source-types.v1.json +353 -0
  22. package/native/agentsam-machine/core/src/lib.rs +6 -0
  23. package/native/agentsam-machine/core/src/source_types.rs +2 -2
  24. package/package.json +31 -10
  25. package/packages/agentsam-brand/package.json +1 -1
  26. package/packages/agentsam-contracts/package.json +71 -20
  27. package/packages/agentsam-contracts/scripts/build.mjs +18 -0
  28. package/packages/agentsam-contracts/test/contracts.test.mjs +4 -1
  29. package/packages/agentsam-contracts/test/repository.test.mjs +4 -1
  30. package/packages/agentsam-contracts/tsconfig.build.json +10 -0
  31. package/packages/agentsam-errors/package.json +3 -2
  32. package/packages/agentsam-errors/src/index.js +1 -0
  33. package/packages/agentsam-errors/src/tool.js +56 -0
  34. package/packages/agentsam-errors/test/tool.test.mjs +58 -0
  35. package/packages/agentsam-goap/README.md +52 -0
  36. package/packages/agentsam-goap/package.json +37 -0
  37. package/packages/agentsam-goap/src/adapters/d1-sqlite.js +570 -0
  38. package/packages/agentsam-goap/src/adapters/memory.js +199 -0
  39. package/packages/agentsam-goap/src/contracts.js +226 -0
  40. package/packages/agentsam-goap/src/control-plane.js +112 -0
  41. package/packages/agentsam-goap/src/errors.js +157 -0
  42. package/packages/agentsam-goap/src/index.js +5 -0
  43. package/packages/agentsam-goap/src/world.js +202 -0
  44. package/packages/agentsam-goap/test/goap-control-plane.test.mjs +245 -0
  45. package/packages/agentsam-goap/test/world.test.mjs +79 -0
  46. package/packages/agentsam-knowledge/package.json +3 -2
  47. package/packages/agentsam-nav/package.json +1 -1
  48. package/packages/agentsam-queue-control/package.json +1 -1
  49. package/packages/agentsam-rapid-rust/src/main.rs +1 -0
  50. package/packages/agentsam-repository/package.json +3 -2
  51. package/packages/agentsam-repository/src/goap.js +13 -14
  52. package/packages/agentsam-repository/src/tickets.js +15 -22
  53. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +19 -8
  54. package/packages/agentsam-vault/package.json +8 -5
  55. package/packages/agentsam-workbench/package.json +44 -17
  56. package/packages/connectors/cloudflare/package.json +4 -2
  57. package/packages/heuristic-theme/package.json +1 -1
  58. package/packages/identity/package.json +4 -3
  59. package/packages/identity/tests/lane1-packed-consumer.test.mjs +10 -2
  60. package/packages/providers/completeful/package.json +1 -1
  61. package/packages/theme-church-site/README.md +2 -2
  62. package/packages/theme-church-site/package.json +3 -4
  63. package/packages/theme-church-site/src/index.js +1 -1
  64. package/packages/theme-church-site/test/theme.test.mjs +1 -1
  65. package/packages/theme-companions-site/README.md +2 -2
  66. package/packages/theme-companions-site/package.json +3 -4
  67. package/packages/theme-companions-site/src/index.js +1 -1
  68. package/packages/theme-companions-site/test/theme.test.mjs +1 -1
  69. package/packages/theme-floors-site/README.md +2 -2
  70. package/packages/theme-floors-site/package.json +3 -4
  71. package/packages/theme-floors-site/src/index.js +1 -1
  72. package/packages/theme-floors-site/test/theme.test.mjs +1 -1
  73. package/packages/theme-fuelnfree-site/README.md +2 -2
  74. package/packages/theme-fuelnfree-site/package.json +3 -4
  75. package/packages/theme-fuelnfree-site/src/index.js +1 -1
  76. package/packages/theme-fuelnfree-site/test/theme.test.mjs +1 -1
  77. package/packages/theme-handyman-site/README.md +2 -2
  78. package/packages/theme-handyman-site/package.json +3 -4
  79. package/packages/theme-handyman-site/src/index.js +1 -1
  80. package/packages/theme-handyman-site/test/theme.test.mjs +1 -1
  81. package/packages/theme-insurance-site/README.md +2 -2
  82. package/packages/theme-insurance-site/package.json +3 -4
  83. package/packages/theme-insurance-site/src/index.js +1 -1
  84. package/packages/theme-insurance-site/test/theme.test.mjs +1 -1
  85. package/packages/theme-scenes/package.json +1 -1
  86. package/packages/theme-shinshu-site/README.md +2 -2
  87. package/packages/theme-shinshu-site/package.json +3 -4
  88. package/packages/theme-shinshu-site/src/index.js +1 -1
  89. package/packages/theme-shinshu-site/test/theme.test.mjs +1 -1
  90. package/packages/work-graph/package.json +3 -2
  91. package/protocol/local-engine/benchmark.v1.schema.json +14 -0
  92. package/protocol/local-engine/engine.v1.schema.json +17 -0
  93. package/python/agentsam_sdk/repository/intelligence/discovery.py +27 -2
  94. package/python/agentsam_sdk/repository/intelligence/git.py +4 -0
  95. package/python/tests/test_repository_intelligence.py +30 -0
  96. package/src/cli/command-catalog.js +3 -1
  97. package/src/cli.js +20 -1
  98. package/src/commands/app.js +10 -0
  99. package/src/commands/engine.js +10 -0
  100. package/src/commands/goap-world.js +134 -0
  101. package/src/commands/goap.js +11 -4
  102. package/src/commands/machine-binary.js +33 -27
  103. package/src/commands/machine-runtime.js +266 -0
  104. package/src/commands/machine.js +155 -51
  105. package/src/commands/package.js +537 -0
  106. package/src/commands/plan-ledger.js +370 -0
  107. package/src/commands/plan.js +183 -0
  108. package/src/commands/runtime.js +25 -10
  109. package/src/commands/setup.js +30 -6
  110. package/src/commands/skill.js +78 -17
  111. package/src/commands/terminal.js +20 -8
  112. package/src/errors/contract.js +4 -4
  113. package/src/errors/diagnostic.js +1 -1
  114. package/src/errors/index.js +1 -1
  115. package/src/index.js +20 -0
  116. package/src/indexing/ingest/materials.js +237 -30
  117. package/src/knowledge/source.js +1 -1
  118. package/src/lib/setup/runtime.js +4 -2
  119. package/src/lib/slash-commands.js +1 -1
  120. package/src/local/runtime-store.js +24 -2
  121. package/src/local/sqlite.js +17 -0
  122. package/src/local-engine/assets.js +37 -0
  123. package/src/local-engine/audit.js +133 -0
  124. package/src/local-engine/benchmark.js +26 -0
  125. package/src/local-engine/contracts.js +101 -0
  126. package/src/local-engine/engines.js +142 -0
  127. package/src/local-engine/index.js +18 -0
  128. package/src/local-engine/runtime.js +39 -0
  129. package/src/sam/operations/package-audit.js +41 -0
  130. package/src/sam/seed.js +2 -0
  131. package/skills/grok-auth/SKILL.md +0 -110
  132. package/skills/grok-auth/agentsam.skill.json +0 -25
  133. package/skills/grok-auth/references/grok-identity.md +0 -64
  134. package/skills/grok-auth/references/per-user-data.md +0 -49
  135. package/skills/grok-auth/references/prewired-and-env.md +0 -54
  136. package/skills/grok-auth/references/session-ui.md +0 -133
  137. package/skills/grok-auth/references/sign-in-methods.md +0 -55
  138. package/skills/grok-auth/references/wiring.md +0 -71
  139. package/skills/grok-building-games/SKILL.md +0 -213
  140. package/skills/grok-building-games/agentsam.skill.json +0 -25
  141. package/skills/grok-building-games/references/3d-libs.md +0 -64
  142. package/skills/grok-building-games/references/ai-pathfinding.md +0 -122
  143. package/skills/grok-building-games/references/audio.md +0 -129
  144. package/skills/grok-building-games/references/babylon.md +0 -202
  145. package/skills/grok-building-games/references/collision-physics.md +0 -122
  146. package/skills/grok-building-games/references/ecs-architecture.md +0 -111
  147. package/skills/grok-building-games/references/game-feel-juice.md +0 -110
  148. package/skills/grok-building-games/references/genres/board-card-chess.md +0 -89
  149. package/skills/grok-building-games/references/genres/endless-runner.md +0 -83
  150. package/skills/grok-building-games/references/genres/fps.md +0 -105
  151. package/skills/grok-building-games/references/genres/platformer-2d.md +0 -97
  152. package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +0 -131
  153. package/skills/grok-building-games/references/genres/racing-kart.md +0 -106
  154. package/skills/grok-building-games/references/genres/topdown-twin-stick.md +0 -97
  155. package/skills/grok-building-games/references/genres/tower-defense.md +0 -84
  156. package/skills/grok-building-games/references/genres/voxel-minecraft.md +0 -89
  157. package/skills/grok-building-games/references/input.md +0 -139
  158. package/skills/grok-building-games/references/phaser.md +0 -277
  159. package/skills/grok-building-games/references/procedural-generation.md +0 -141
  160. package/skills/grok-building-games/references/save-persistence.md +0 -108
  161. package/skills/grok-building-games/references/threejs-foundational.md +0 -148
  162. package/skills/grok-controls/SKILL.md +0 -274
  163. package/skills/grok-controls/agentsam.skill.json +0 -25
  164. package/skills/grok-design-ui/SKILL.md +0 -122
  165. package/skills/grok-design-ui/agentsam.skill.json +0 -25
  166. package/skills/grok-design-ui/references/animations.md +0 -379
  167. package/skills/grok-design-ui/references/performance.md +0 -88
  168. package/skills/grok-design-ui/references/refined-ui.md +0 -384
  169. package/skills/grok-design-ui/references/surfaces.md +0 -247
  170. package/skills/grok-design-ui/references/typography.md +0 -123
  171. package/skills/grok-game-animation-frames/SKILL.md +0 -84
  172. package/skills/grok-game-animation-frames/agentsam.skill.json +0 -25
  173. package/skills/grok-game-asset-core/SKILL.md +0 -69
  174. package/skills/grok-game-asset-core/agentsam.skill.json +0 -25
  175. package/skills/grok-game-character-consistency/SKILL.md +0 -69
  176. package/skills/grok-game-character-consistency/agentsam.skill.json +0 -25
  177. package/skills/grok-game-tilesets/SKILL.md +0 -65
  178. package/skills/grok-game-tilesets/agentsam.skill.json +0 -25
  179. package/skills/grok-game-ui-icons/SKILL.md +0 -56
  180. package/skills/grok-game-ui-icons/agentsam.skill.json +0 -25
  181. package/skills/grok-generate2dmap/LICENSE +0 -21
  182. package/skills/grok-generate2dmap/SKILL.md +0 -120
  183. package/skills/grok-generate2dmap/SOURCE.md +0 -6
  184. package/skills/grok-generate2dmap/agentsam.skill.json +0 -25
  185. package/skills/grok-generate2dmap/references/deliverables.md +0 -101
  186. package/skills/grok-generate2dmap/references/layered-map-contract.md +0 -209
  187. package/skills/grok-generate2dmap/references/map-strategies.md +0 -341
  188. package/skills/grok-generate2dmap/references/object-production-gate.md +0 -24
  189. package/skills/grok-generate2dmap/references/pipeline.md +0 -149
  190. package/skills/grok-generate2dmap/references/prop-pack-contract.md +0 -174
  191. package/skills/grok-generate2dmap/references/side-scroll-stages.md +0 -29
  192. package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +0 -157
  193. package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +0 -369
  194. package/skills/grok-generate2dsprite/LICENSE +0 -21
  195. package/skills/grok-generate2dsprite/SKILL.md +0 -313
  196. package/skills/grok-generate2dsprite/SOURCE.md +0 -6
  197. package/skills/grok-generate2dsprite/agentsam.skill.json +0 -25
  198. package/skills/grok-generate2dsprite/references/modes.md +0 -124
  199. package/skills/grok-generate2dsprite/references/prompt-rules.md +0 -315
  200. package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +0 -1031
  201. package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +0 -109
  202. package/skills/grok-imagine/SKILL.md +0 -201
  203. package/skills/grok-imagine/agentsam.skill.json +0 -25
  204. package/skills/grok-multiplayer-p2p/SKILL.md +0 -111
  205. package/skills/grok-multiplayer-p2p/agentsam.skill.json +0 -25
  206. package/skills/grok-multiplayer-p2p/references/react-binding.md +0 -144
  207. package/skills/grok-multiplayer-p2p/references/signaling-relay.md +0 -269
  208. package/skills/grok-neon/SKILL.md +0 -157
  209. package/skills/grok-neon/agentsam.skill.json +0 -25
  210. package/skills/grok-og/SKILL.md +0 -102
  211. package/skills/grok-og/agentsam.skill.json +0 -25
  212. package/skills/grok-og/references/brand-pass.md +0 -53
  213. package/skills/grok-og/references/custom-card.md +0 -107
  214. package/skills/grok-og/references/favicon-and-icons.md +0 -48
  215. package/skills/grok-og/references/og-type-contract.md +0 -18
  216. package/skills/grok-og/references/placeholder-card.md +0 -21
  217. package/skills/grok-og/references/x-banner.md +0 -41
  218. package/skills/grok-threejs/SKILL.md +0 -67
  219. package/skills/grok-threejs/agentsam.skill.json +0 -25
  220. package/skills/grok-threejs/references/llms-full.txt +0 -2780
  221. package/skills/grok-video2dsprite/LICENSE +0 -21
  222. package/skills/grok-video2dsprite/SKILL.md +0 -236
  223. package/skills/grok-video2dsprite/SOURCE.md +0 -6
  224. package/skills/grok-video2dsprite/agentsam.skill.json +0 -25
  225. package/skills/grok-video2dsprite/references/pipeline.md +0 -90
  226. package/skills/grok-video2dsprite/references/prompt-rules.md +0 -63
  227. package/skills/grok-video2dsprite/scripts/video2dsprite.py +0 -490
  228. package/skills/grok-xai-api/SKILL.md +0 -152
  229. package/skills/grok-xai-api/agentsam.skill.json +0 -25
  230. package/test/account-session.test.mjs +0 -101
  231. package/test/agent-capabilities.test.mjs +0 -67
  232. package/test/app-authority-context.test.mjs +0 -32
  233. package/test/app-building-skills.test.mjs +0 -61
  234. package/test/apps-scaffold-contract.test.mjs +0 -115
  235. package/test/blender-cad.test.mjs +0 -146
  236. package/test/cad-docker.test.mjs +0 -96
  237. package/test/capabilities.test.mjs +0 -133
  238. package/test/cli/api-key-env-whoami.test.mjs +0 -129
  239. package/test/cli/catalog-authority.test.mjs +0 -64
  240. package/test/cli/codebaseindex-plan-ux.test.mjs +0 -37
  241. package/test/cli/eval-live.test.mjs +0 -219
  242. package/test/cli/go.test.mjs +0 -128
  243. package/test/cli/local-vault-and-provider-setup.test.mjs +0 -268
  244. package/test/cli/machine-command.test.mjs +0 -34
  245. package/test/cli/mcp-client.test.mjs +0 -256
  246. package/test/cli/preferences-runtime.test.mjs +0 -11
  247. package/test/cli/runtime-persist.test.mjs +0 -56
  248. package/test/cli/runtime-ui.test.mjs +0 -141
  249. package/test/cli/rust-command.test.mjs +0 -21
  250. package/test/cli/skill-npm-and-env.test.mjs +0 -52
  251. package/test/cli/status-actions.test.mjs +0 -88
  252. package/test/cli/wireframes-go-registry.test.mjs +0 -139
  253. package/test/cli-preferences.test.mjs +0 -46
  254. package/test/cloudflare-connector.test.mjs +0 -93
  255. package/test/cloudflare-runtime.test.mjs +0 -82
  256. package/test/context.test.mjs +0 -159
  257. package/test/credentials-audit.test.mjs +0 -113
  258. package/test/deploy-health-scan.test.mjs +0 -95
  259. package/test/deploy-receipt.test.mjs +0 -91
  260. package/test/dockerize.test.mjs +0 -93
  261. package/test/error-diagnostics.test.mjs +0 -124
  262. package/test/eval-context.test.mjs +0 -37
  263. package/test/execution-approvals.test.mjs +0 -27
  264. package/test/fixtures/cad/courtyard-house.json +0 -208
  265. package/test/fixtures/knowledge-rpc-worker.mjs +0 -16
  266. package/test/fixtures/project-authority/customer-app/.agentsam/app.json +0 -5
  267. package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +0 -1
  268. package/test/fixtures/project-authority/customer-app/wrangler.toml +0 -17
  269. package/test/gcloud-auth.test.mjs +0 -111
  270. package/test/go/build-source-identity.test.mjs +0 -31
  271. package/test/go/cloudflare-probe.test.mjs +0 -317
  272. package/test/go/distribution.test.mjs +0 -28
  273. package/test/google-cloud-connection.test.mjs +0 -83
  274. package/test/google-cloud-inventory.test.mjs +0 -64
  275. package/test/indexing-provider.test.mjs +0 -29
  276. package/test/init-options.test.mjs +0 -35
  277. package/test/integration/ai-access-onboarding.test.mjs +0 -47
  278. package/test/integration/app-command.test.mjs +0 -85
  279. package/test/integration/autorag-project-authority.integration.test.mjs +0 -51
  280. package/test/integration/autorag-runtime-discovery.test.mjs +0 -107
  281. package/test/integration/cad-discovery.test.mjs +0 -158
  282. package/test/integration/cad-docker-executor.test.mjs +0 -249
  283. package/test/integration/cad-execution.test.mjs +0 -184
  284. package/test/integration/cad-project-app.test.mjs +0 -31
  285. package/test/integration/cad-project-d1.test.mjs +0 -25
  286. package/test/integration/cad-project-native.test.mjs +0 -24
  287. package/test/integration/cad-project-workflow.test.mjs +0 -9
  288. package/test/integration/cad-project.test.mjs +0 -85
  289. package/test/integration/cli-help.test.mjs +0 -41
  290. package/test/integration/cms-app-scaffold.test.mjs +0 -77
  291. package/test/integration/cms-site-tenancy-contract.test.mjs +0 -268
  292. package/test/integration/codebaseindex-ingest.test.mjs +0 -255
  293. package/test/integration/core-client.integration.test.mjs +0 -55
  294. package/test/integration/database-hosted-honesty.test.mjs +0 -49
  295. package/test/integration/desktop-keychain-boundary.test.mjs +0 -45
  296. package/test/integration/error-runtime-rpc.test.mjs +0 -71
  297. package/test/integration/features-resolve.test.mjs +0 -147
  298. package/test/integration/hosted-work-host-authority.test.mjs +0 -47
  299. package/test/integration/icon-registry.test.mjs +0 -67
  300. package/test/integration/ingest-discover-models.test.mjs +0 -30
  301. package/test/integration/inspect-path-cli.test.mjs +0 -46
  302. package/test/integration/install-script.test.mjs +0 -110
  303. package/test/integration/inventory-core.test.mjs +0 -53
  304. package/test/integration/inventory-eligibility.test.mjs +0 -59
  305. package/test/integration/inventory-evidence.test.mjs +0 -125
  306. package/test/integration/knowledge-rpc.test.mjs +0 -112
  307. package/test/integration/local-fs.test.mjs +0 -113
  308. package/test/integration/local-provider-bridge.test.mjs +0 -65
  309. package/test/integration/local-studio-settings-production.test.mjs +0 -40
  310. package/test/integration/lockfile-sync.test.mjs +0 -26
  311. package/test/integration/merkle-cli.test.mjs +0 -61
  312. package/test/integration/merkle-persistence-identity.test.mjs +0 -48
  313. package/test/integration/plugins-cloudflare.integration.test.mjs +0 -28
  314. package/test/integration/provider-env-cli.test.mjs +0 -60
  315. package/test/integration/provider-factory.test.mjs +0 -197
  316. package/test/integration/repository-company-graph.test.mjs +0 -90
  317. package/test/integration/runtime-migrations.test.mjs +0 -87
  318. package/test/integration/runtime-status.integration.test.mjs +0 -227
  319. package/test/integration/sam-activity-recovery.test.mjs +0 -147
  320. package/test/integration/sam-decision.test.mjs +0 -584
  321. package/test/integration/sam-kernel.test.mjs +0 -99
  322. package/test/integration/sam-planning-astar.test.mjs +0 -279
  323. package/test/integration/scaffold-cloudflare.test.mjs +0 -46
  324. package/test/integration/skill-runtime.test.mjs +0 -240
  325. package/test/integration/storage-architecture.test.mjs +0 -154
  326. package/test/integration/store-discovery.test.mjs +0 -44
  327. package/test/integration/studio-fs-pty-e2e.test.mjs +0 -294
  328. package/test/integration/terminal-exec.integration.test.mjs +0 -86
  329. package/test/integration/theme-package-registry.test.mjs +0 -31
  330. package/test/integration/tool-runtime.test.mjs +0 -124
  331. package/test/integration/tool-schema.test.mjs +0 -59
  332. package/test/jr-dev-skill.test.mjs +0 -26
  333. package/test/knowledge-context-pack.test.mjs +0 -19
  334. package/test/knowledge-postgres.test.mjs +0 -40
  335. package/test/knowledge-service.test.mjs +0 -110
  336. package/test/knowledge.test.mjs +0 -206
  337. package/test/live/terminal-transport.live.test.mjs +0 -24
  338. package/test/local-sessions.test.mjs +0 -57
  339. package/test/local-studio-deploy.test.mjs +0 -83
  340. package/test/loopback-oauth.test.mjs +0 -53
  341. package/test/merkle-render.test.mjs +0 -31
  342. package/test/mini.test.mjs +0 -140
  343. package/test/model-catalog.test.mjs +0 -70
  344. package/test/models.test.mjs +0 -309
  345. package/test/npm10-lock.test.mjs +0 -29
  346. package/test/ollama.test.mjs +0 -137
  347. package/test/open-url.test.mjs +0 -64
  348. package/test/openai-responses.test.mjs +0 -155
  349. package/test/portable-context.test.mjs +0 -94
  350. package/test/project-config.test.mjs +0 -81
  351. package/test/project-rules.test.mjs +0 -44
  352. package/test/provider-credentials.test.mjs +0 -106
  353. package/test/rehydrate.test.mjs +0 -25
  354. package/test/release-hygiene.test.mjs +0 -42
  355. package/test/repository-snapshot-view.test.mjs +0 -112
  356. package/test/responses-runner.test.mjs +0 -465
  357. package/test/runtime-activity.test.mjs +0 -98
  358. package/test/sdk-worker-contract.test.mjs +0 -72
  359. package/test/security.test.mjs +0 -266
  360. package/test/setup-planner.test.mjs +0 -74
  361. package/test/setup-runtime.test.mjs +0 -51
  362. package/test/shell.test.mjs +0 -281
  363. package/test/skills.test.mjs +0 -22
  364. package/test/smoke.mjs +0 -122
  365. package/test/telemetry.test.mjs +0 -79
  366. package/test/terminal/local-pty.mock.test.mjs +0 -153
  367. package/test/terminal-machine-identity.test.mjs +0 -88
  368. package/test/theme-portability.test.mjs +0 -14
  369. package/test/tools-search.test.mjs +0 -73
  370. package/test/unit/website-assets-bindings.test.mjs +0 -60
  371. package/test/whoami-resume.test.mjs +0 -157
@@ -1,16 +1,18 @@
1
1
  /**
2
2
  * Resolve the agentsam-machine native binary.
3
3
  * Preference order:
4
- * 1. AGENTSAM_MACHINE_BIN
5
- * 2. agentsam-machine on PATH
6
- * 3. Built binary under native/agentsam-machine/target/{release,debug}
7
- * 4. cargo run --manifest-path … (dev fallback inside the SDK repo)
4
+ * 1. AgentSam-managed user runtime under ~/.agentsam/runtimes/machine
5
+ * 2. AGENTSAM_MACHINE_BIN explicit override
6
+ * 3. agentsam-machine on PATH
7
+ * 4. Built binary under native/agentsam-machine/target/{release,debug}
8
+ * 5. cargo run --manifest-path (SDK contributor fallback)
8
9
  */
9
10
 
10
11
  import fs from 'node:fs';
11
12
  import path from 'node:path';
12
13
  import { fileURLToPath } from 'node:url';
13
14
  import { spawnSync } from 'node:child_process';
15
+ import { findExecutable, managedMachineResolution } from './machine-runtime.js';
14
16
 
15
17
  const here = path.dirname(fileURLToPath(import.meta.url));
16
18
  const sdkRoot = path.resolve(here, '../..');
@@ -18,7 +20,7 @@ const machineCrate = path.join(sdkRoot, 'native/agentsam-machine');
18
20
  const machineManifest = path.join(machineCrate, 'Cargo.toml');
19
21
 
20
22
  /**
21
- * @typedef {{ kind: 'binary', path: string, source: string } | { kind: 'cargo', manifest: string, source: string } | { kind: 'missing', tried: string[] }} MachineBinaryResolution
23
+ * @typedef {{ kind: 'binary', path: string, source: string, version?: string } | { kind: 'cargo', manifest: string, source: string } | { kind: 'missing', tried: string[] }} MachineBinaryResolution
22
24
  */
23
25
 
24
26
  /**
@@ -27,6 +29,17 @@ const machineManifest = path.join(machineCrate, 'Cargo.toml');
27
29
  export function resolveMachineBinary(env = process.env) {
28
30
  const tried = [];
29
31
 
32
+ const managed = managedMachineResolution(env);
33
+ tried.push(...managed.tried);
34
+ if (managed.available) {
35
+ return {
36
+ kind: 'binary',
37
+ path: managed.path,
38
+ source: 'managed-runtime',
39
+ version: managed.state.current_version,
40
+ };
41
+ }
42
+
30
43
  const explicit = String(env.AGENTSAM_MACHINE_BIN || '').trim();
31
44
  if (explicit) {
32
45
  tried.push(explicit);
@@ -35,25 +48,25 @@ export function resolveMachineBinary(env = process.env) {
35
48
  }
36
49
  }
37
50
 
38
- const pathHit = which('agentsam-machine');
39
- if (pathHit) {
40
- return { kind: 'binary', path: pathHit, source: 'PATH' };
41
- }
51
+ const pathHit = findExecutable('agentsam-machine', env);
52
+ if (pathHit) return { kind: 'binary', path: pathHit, source: 'PATH' };
42
53
  tried.push('PATH:agentsam-machine');
43
54
 
44
55
  for (const rel of ['target/release/agentsam-machine', 'target/debug/agentsam-machine']) {
45
56
  const candidate = path.join(machineCrate, rel);
46
57
  tried.push(candidate);
47
58
  if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
48
- return { kind: 'binary', path: candidate, source: rel.includes('release') ? 'crate-release' : 'crate-debug' };
59
+ return {
60
+ kind: 'binary',
61
+ path: candidate,
62
+ source: rel.includes('release') ? 'crate-release' : 'crate-debug',
63
+ };
49
64
  }
50
65
  }
51
66
 
52
67
  if (fs.existsSync(machineManifest)) {
53
- const cargo = which('cargo');
54
- if (cargo) {
55
- return { kind: 'cargo', manifest: machineManifest, source: 'cargo-run' };
56
- }
68
+ const cargo = findExecutable('cargo', env);
69
+ if (cargo) return { kind: 'cargo', manifest: machineManifest, source: 'cargo-run' };
57
70
  tried.push('cargo');
58
71
  }
59
72
 
@@ -62,7 +75,7 @@ export function resolveMachineBinary(env = process.env) {
62
75
 
63
76
  /**
64
77
  * @param {MachineBinaryResolution} resolution
65
- * @param {string[]} machineArgv args after `agentsam machine` (e.g. ['inspect', './site', '--json'])
78
+ * @param {string[]} machineArgv
66
79
  * @param {{ stdio?: import('node:child_process').StdioOptions, env?: NodeJS.ProcessEnv }} [options]
67
80
  */
68
81
  export function spawnMachine(resolution, machineArgv, options = {}) {
@@ -73,6 +86,7 @@ export function spawnMachine(resolution, machineArgv, options = {}) {
73
86
  if (resolution.kind === 'binary') {
74
87
  return spawnSync(resolution.path, machineArgv, { stdio, env, encoding: 'utf8', maxBuffer });
75
88
  }
89
+
76
90
  if (resolution.kind === 'cargo') {
77
91
  return spawnSync(
78
92
  'cargo',
@@ -80,24 +94,16 @@ export function spawnMachine(resolution, machineArgv, options = {}) {
80
94
  { stdio, env, encoding: 'utf8', maxBuffer },
81
95
  );
82
96
  }
97
+
83
98
  const err = new Error(
84
- `agentsam-machine binary not found. Tried: ${(resolution.tried || []).join(', ') || '(none)'}. Build with: cargo build --manifest-path native/agentsam-machine/Cargo.toml --release`,
99
+ 'agentsam-machine is not installed. Run: agentsam machine install. ' +
100
+ 'Standalone Cargo users can run: cargo install agentsam-machine-cli. ' +
101
+ 'Tried: ' + ((resolution.tried || []).join(', ') || '(none)'),
85
102
  );
86
103
  err.code = 'AGENTSAM_MACHINE_BINARY_MISSING';
87
104
  throw err;
88
105
  }
89
106
 
90
- function which(cmd) {
91
- const probe = process.platform === 'win32' ? ['where', [cmd]] : ['which', [cmd]];
92
- const result = spawnSync(probe[0], probe[1], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
93
- if (result.status !== 0) return null;
94
- const line = String(result.stdout || '')
95
- .split(/\r?\n/)
96
- .map((s) => s.trim())
97
- .find(Boolean);
98
- return line || null;
99
- }
100
-
101
107
  export function machineSdkRoot() {
102
108
  return sdkRoot;
103
109
  }
@@ -0,0 +1,266 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { spawnSync } from 'node:child_process';
5
+
6
+ export const MACHINE_RUNTIME_SCHEMA = 'agentsam.machine.runtime.v1';
7
+ export const MACHINE_PACKAGE = 'agentsam-machine-cli';
8
+
9
+ function expandHome(value, home) {
10
+ if (!value) return value;
11
+ if (value === '~') return home;
12
+ if (value.startsWith('~/')) return path.join(home, value.slice(2));
13
+ return value;
14
+ }
15
+
16
+ export function agentsamHome(env = process.env) {
17
+ const home = os.homedir();
18
+ const configured = String(env.AGENTSAM_HOME || '').trim();
19
+ return configured ? path.resolve(expandHome(configured, home)) : path.join(home, '.agentsam');
20
+ }
21
+
22
+ export function machineRuntimeRoot(env = process.env) {
23
+ return path.join(agentsamHome(env), 'runtimes', 'machine');
24
+ }
25
+
26
+ export function machineRuntimeStatePath(env = process.env) {
27
+ return path.join(machineRuntimeRoot(env), 'current.json');
28
+ }
29
+
30
+ export function machineBinaryName() {
31
+ return process.platform === 'win32' ? 'agentsam-machine.exe' : 'agentsam-machine';
32
+ }
33
+
34
+ export function machineManagedAliasPath(env = process.env) {
35
+ return path.join(agentsamHome(env), 'bin', machineBinaryName());
36
+ }
37
+
38
+ export function readMachineRuntimeState(env = process.env) {
39
+ const file = machineRuntimeStatePath(env);
40
+ if (!fs.existsSync(file)) return null;
41
+ try {
42
+ const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
43
+ if (parsed?.schema !== MACHINE_RUNTIME_SCHEMA) return null;
44
+ if (typeof parsed?.current_version !== 'string' || !parsed.current_version.trim()) return null;
45
+ return parsed;
46
+ } catch {
47
+ return null;
48
+ }
49
+ }
50
+
51
+ export function managedMachineResolution(env = process.env) {
52
+ const statePath = machineRuntimeStatePath(env);
53
+ const state = readMachineRuntimeState(env);
54
+ const tried = [statePath];
55
+ if (!state) return { available: false, state: null, path: null, tried };
56
+
57
+ const binary = path.join(
58
+ machineRuntimeRoot(env),
59
+ 'versions',
60
+ state.current_version,
61
+ 'bin',
62
+ machineBinaryName(),
63
+ );
64
+ tried.push(binary);
65
+
66
+ if (!fs.existsSync(binary) || !fs.statSync(binary).isFile()) {
67
+ return { available: false, state, path: binary, tried };
68
+ }
69
+ return { available: true, state, path: binary, tried };
70
+ }
71
+
72
+ export function findExecutable(command, env = process.env) {
73
+ const probe = process.platform === 'win32' ? ['where', [command]] : ['which', [command]];
74
+ const result = spawnSync(probe[0], probe[1], {
75
+ encoding: 'utf8',
76
+ stdio: ['ignore', 'pipe', 'ignore'],
77
+ env,
78
+ });
79
+ if (result.status !== 0) return null;
80
+ return String(result.stdout || '')
81
+ .split(/\r?\n/)
82
+ .map((line) => line.trim())
83
+ .find(Boolean) || null;
84
+ }
85
+
86
+ export function machineBinaryVersion(binary, env = process.env) {
87
+ const result = spawnSync(binary, ['--version'], {
88
+ encoding: 'utf8',
89
+ stdio: ['ignore', 'pipe', 'pipe'],
90
+ env,
91
+ });
92
+ if (result.status !== 0) return null;
93
+ const output = String(result.stdout || result.stderr || '').trim();
94
+ const match = output.match(/(?:^|\s)(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)(?:\s|$)/);
95
+ return match?.[1] || null;
96
+ }
97
+
98
+ export function machineRuntimeStatus(env = process.env) {
99
+ const managed = managedMachineResolution(env);
100
+ const cargo = findExecutable('cargo', env);
101
+ return {
102
+ schema: MACHINE_RUNTIME_SCHEMA,
103
+ manager: 'agentsam',
104
+ runtime_root: machineRuntimeRoot(env),
105
+ state_path: machineRuntimeStatePath(env),
106
+ installed: managed.available,
107
+ current_version: managed.state?.current_version || null,
108
+ binary: managed.path,
109
+ source: managed.state?.source || null,
110
+ installed_at_iso: managed.state?.installed_at_iso || null,
111
+ stable_alias: machineManagedAliasPath(env),
112
+ cargo: { available: Boolean(cargo), path: cargo },
113
+ };
114
+ }
115
+
116
+ export function discoverLatestMachineVersion(env = process.env) {
117
+ const cargo = findExecutable('cargo', env);
118
+ if (!cargo) {
119
+ const error = new Error('Cargo is required to install the current agentsam-machine crates.io distribution.');
120
+ error.code = 'AGENTSAM_MACHINE_CARGO_MISSING';
121
+ throw error;
122
+ }
123
+
124
+ const result = spawnSync(cargo, ['search', MACHINE_PACKAGE, '--limit', '1'], {
125
+ encoding: 'utf8',
126
+ stdio: ['ignore', 'pipe', 'pipe'],
127
+ env,
128
+ });
129
+ if (result.status !== 0) {
130
+ const error = new Error(
131
+ String(result.stderr || '').trim() ||
132
+ 'Unable to resolve latest ' + MACHINE_PACKAGE + ' version from crates.io.',
133
+ );
134
+ error.code = 'AGENTSAM_MACHINE_REGISTRY_LOOKUP_FAILED';
135
+ throw error;
136
+ }
137
+
138
+ const match = String(result.stdout || '').match(/^agentsam-machine-cli\s*=\s*"([^"]+)"/m);
139
+ if (!match) {
140
+ const error = new Error('Unable to parse crates.io version for ' + MACHINE_PACKAGE + '.');
141
+ error.code = 'AGENTSAM_MACHINE_REGISTRY_PARSE_FAILED';
142
+ throw error;
143
+ }
144
+ return match[1];
145
+ }
146
+
147
+ function writeCurrentState(version, env = process.env) {
148
+ const root = machineRuntimeRoot(env);
149
+ fs.mkdirSync(root, { recursive: true });
150
+ const state = {
151
+ schema: MACHINE_RUNTIME_SCHEMA,
152
+ manager: 'agentsam',
153
+ package: MACHINE_PACKAGE,
154
+ current_version: version,
155
+ source: 'crates.io',
156
+ installed_at_iso: new Date().toISOString(),
157
+ };
158
+ const target = machineRuntimeStatePath(env);
159
+ const temp = target + '.tmp-' + process.pid;
160
+ fs.writeFileSync(temp, JSON.stringify(state, null, 2) + '\n', { mode: 0o600 });
161
+ fs.renameSync(temp, target);
162
+ return state;
163
+ }
164
+
165
+ function syncManagedAlias(binary, env = process.env) {
166
+ const alias = machineManagedAliasPath(env);
167
+ fs.mkdirSync(path.dirname(alias), { recursive: true });
168
+ try { fs.rmSync(alias, { force: true }); } catch {}
169
+ if (process.platform === 'win32') fs.copyFileSync(binary, alias);
170
+ else fs.symlinkSync(binary, alias);
171
+ return alias;
172
+ }
173
+
174
+ export function installManagedMachine({
175
+ env = process.env,
176
+ version = null,
177
+ force = false,
178
+ write = () => {},
179
+ } = {}) {
180
+ const cargo = findExecutable('cargo', env);
181
+ if (!cargo) {
182
+ const error = new Error(
183
+ 'Cargo is required by the current Machine distribution. Install Rust/Cargo, then rerun agentsam machine install.',
184
+ );
185
+ error.code = 'AGENTSAM_MACHINE_CARGO_MISSING';
186
+ throw error;
187
+ }
188
+
189
+ const desired = version || discoverLatestMachineVersion(env);
190
+ const root = machineRuntimeRoot(env);
191
+ const versionsRoot = path.join(root, 'versions');
192
+ const finalRoot = path.join(versionsRoot, desired);
193
+ const finalBinary = path.join(finalRoot, 'bin', machineBinaryName());
194
+ fs.mkdirSync(versionsRoot, { recursive: true });
195
+
196
+ if (!force && fs.existsSync(finalBinary)) {
197
+ const actual = machineBinaryVersion(finalBinary, env);
198
+ if (actual === desired) {
199
+ const state = writeCurrentState(desired, env);
200
+ const alias = syncManagedAlias(finalBinary, env);
201
+ return { changed: false, version: desired, binary: finalBinary, alias, state, source: 'managed-cache' };
202
+ }
203
+ }
204
+
205
+ const stage = fs.mkdtempSync(path.join(root, '.install-'));
206
+ write('Installing ' + MACHINE_PACKAGE + '@' + desired + ' from crates.io…\n');
207
+
208
+ const result = spawnSync(
209
+ cargo,
210
+ ['install', MACHINE_PACKAGE, '--root', stage, '--version', desired, '--locked', '--force'],
211
+ { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], env },
212
+ );
213
+ if (result.status !== 0) {
214
+ fs.rmSync(stage, { recursive: true, force: true });
215
+ const error = new Error(
216
+ String(result.stderr || result.stdout || '').trim() ||
217
+ 'cargo install failed for ' + MACHINE_PACKAGE + '@' + desired,
218
+ );
219
+ error.code = 'AGENTSAM_MACHINE_INSTALL_FAILED';
220
+ throw error;
221
+ }
222
+
223
+ const stagedBinary = path.join(stage, 'bin', machineBinaryName());
224
+ if (!fs.existsSync(stagedBinary)) {
225
+ fs.rmSync(stage, { recursive: true, force: true });
226
+ const error = new Error('cargo install completed without ' + machineBinaryName());
227
+ error.code = 'AGENTSAM_MACHINE_INSTALL_BINARY_MISSING';
228
+ throw error;
229
+ }
230
+
231
+ const actual = machineBinaryVersion(stagedBinary, env);
232
+ if (actual !== desired) {
233
+ fs.rmSync(stage, { recursive: true, force: true });
234
+ const error = new Error(
235
+ 'installed Machine version mismatch: expected ' + desired + ', received ' + (actual || 'unknown'),
236
+ );
237
+ error.code = 'AGENTSAM_MACHINE_INSTALL_VERSION_MISMATCH';
238
+ throw error;
239
+ }
240
+
241
+ if (fs.existsSync(finalRoot)) fs.rmSync(finalRoot, { recursive: true, force: true });
242
+ fs.renameSync(stage, finalRoot);
243
+ const state = writeCurrentState(desired, env);
244
+ const alias = syncManagedAlias(finalBinary, env);
245
+ return { changed: true, version: desired, binary: finalBinary, alias, state, source: 'crates.io' };
246
+ }
247
+
248
+ export function updateManagedMachine({
249
+ env = process.env,
250
+ force = false,
251
+ write = () => {},
252
+ } = {}) {
253
+ const latest = discoverLatestMachineVersion(env);
254
+ const status = machineRuntimeStatus(env);
255
+ if (!force && status.installed && status.current_version === latest) {
256
+ return {
257
+ changed: false,
258
+ version: latest,
259
+ binary: status.binary,
260
+ alias: machineManagedAliasPath(env),
261
+ state: readMachineRuntimeState(env),
262
+ source: 'already-current',
263
+ };
264
+ }
265
+ return installManagedMachine({ env, version: latest, force, write });
266
+ }
@@ -1,81 +1,164 @@
1
1
  /**
2
- * agentsam machine — graduate the native Machine engine to the product CLI.
3
- *
4
- * Graduation rule: capability is complete when reachable through
5
- * `agentsam machine …`, emits bounded deterministic receipts, and preserves evidence.
6
- *
7
- * Asset perception rule: discovery is read-only and network-free by default.
2
+ * agentsam machine — deterministic native Machine lifecycle + perception.
8
3
  */
9
4
 
5
+ import os from 'node:os';
10
6
  import path from 'node:path';
7
+ import pc from 'picocolors';
11
8
  import { resolveMachineBinary, spawnMachine } from './machine-binary.js';
9
+ import {
10
+ installManagedMachine,
11
+ machineBinaryVersion,
12
+ machineRuntimeStatus,
13
+ updateManagedMachine,
14
+ } from './machine-runtime.js';
12
15
 
13
16
  function usage() {
14
- return `agentsam machine — deterministic local perception (native engine)
15
-
16
- Usage:
17
- agentsam machine inspect <path> [--json] [--run-id <id>] [--include-generated]
18
- agentsam machine doctor [--json]
19
- agentsam machine --help
20
-
21
- Notes:
22
- Default inspect is read-only and network-free.
23
- Large detail is externalized under <target>/.agentsam/machine/runs/<run_id>/.
24
- Generated/cache trees are summarized unless --include-generated is set.
25
- Remote fetch/probe, optimization, storage, and reference rewriting are separate explicit actions.
26
- Set AGENTSAM_MACHINE_BIN to force a specific agentsam-machine binary.`;
17
+ return [
18
+ `${pc.bold('agentsam machine')} — deterministic local perception (native engine)`,
19
+ '',
20
+ pc.bold('Usage'),
21
+ ` ${pc.cyan('agentsam machine status')} Show the active runtime`,
22
+ ` ${pc.cyan('agentsam machine doctor')} Diagnose runtime resolution`,
23
+ ` ${pc.cyan('agentsam machine install')} [--version <semver>] Install the managed runtime`,
24
+ ` ${pc.cyan('agentsam machine update')} Update the managed runtime`,
25
+ ` ${pc.cyan('agentsam machine inspect <path>')} Inspect a repository or directory`,
26
+ '',
27
+ pc.bold('Options'),
28
+ ` ${pc.dim('--json')} Machine-readable output`,
29
+ ` ${pc.dim('--force')} Replace an existing managed version`,
30
+ ` ${pc.dim('--run-id <id>')} Reuse an externalized inspection run`,
31
+ ` ${pc.dim('--include-generated')} Include generated and cache trees`,
32
+ ` ${pc.dim('--help')} Show this help`,
33
+ '',
34
+ pc.bold('Runtime authority'),
35
+ ' AgentSam manages one user-level Machine runtime under ~/.agentsam/runtimes/machine/.',
36
+ ' Resolution order: managed runtime → explicit override → PATH → SDK source.',
37
+ ' Install and update are explicit; entering a repository never changes the host.',
38
+ '',
39
+ pc.bold('Behavior'),
40
+ ' Inspect is read-only and network-free by default.',
41
+ ' Large detail is externalized under <target>/.agentsam/machine/runs/<run_id>/.',
42
+ ' Generated and cache trees are summarized unless --include-generated is set.',
43
+ ' Install/update use the crates.io distribution and require Cargo.',
44
+ '',
45
+ ].join('\n');
27
46
  }
28
47
 
29
48
  function parseArgs(argv = []) {
30
49
  const out = {
31
50
  help: false,
32
51
  json: false,
52
+ force: false,
33
53
  includeGenerated: false,
34
54
  runId: null,
55
+ version: null,
35
56
  subcommand: null,
36
57
  target: null,
37
58
  positionals: [],
38
59
  };
60
+
39
61
  for (let i = 0; i < argv.length; i += 1) {
40
62
  const arg = argv[i];
41
63
  if (arg === '--help' || arg === '-h') out.help = true;
42
64
  else if (arg === '--json') out.json = true;
65
+ else if (arg === '--force') out.force = true;
43
66
  else if (arg === '--include-generated') out.includeGenerated = true;
44
67
  else if (arg === '--run-id') {
45
68
  const value = argv[++i];
46
- if (value == null || value.startsWith('--')) {
47
- throw new Error('--run-id requires a value');
48
- }
69
+ if (value == null || value.startsWith('--')) throw new Error('--run-id requires a value');
49
70
  out.runId = value;
71
+ } else if (arg === '--version') {
72
+ const value = argv[++i];
73
+ if (value == null || value.startsWith('--')) throw new Error('--version requires a value');
74
+ out.version = value;
50
75
  } else if (arg.startsWith('-')) {
51
- throw new Error(`unknown machine option: ${arg}`);
76
+ throw new Error('unknown machine option: ' + arg);
52
77
  } else {
53
78
  out.positionals.push(arg);
54
79
  }
55
80
  }
81
+
56
82
  out.subcommand = out.positionals[0] || null;
57
83
  out.target = out.positionals[1] || null;
58
84
  return out;
59
85
  }
60
86
 
61
- function printTextDoctor(resolution) {
62
- if (resolution.kind === 'binary') {
63
- console.log(`agentsam-machine available (${resolution.source}): ${resolution.path}`);
64
- console.log('capability: machine.inspect');
65
- return;
87
+ function statusPayload() {
88
+ const managed = machineRuntimeStatus();
89
+ const resolution = resolveMachineBinary();
90
+ let effectiveVersion = null;
91
+ if (resolution.kind === 'binary') effectiveVersion = machineBinaryVersion(resolution.path);
92
+
93
+ return {
94
+ capability: 'machine.status',
95
+ managed,
96
+ effective: {
97
+ ...resolution,
98
+ version: resolution.version || effectiveVersion,
99
+ },
100
+ };
101
+ }
102
+
103
+ function compactPath(value) {
104
+ const raw = String(value || '—');
105
+ const home = os.homedir();
106
+ return home && (raw === home || raw.startsWith(home + path.sep))
107
+ ? '~' + raw.slice(home.length)
108
+ : raw;
109
+ }
110
+
111
+ function stateLabel(installed) {
112
+ return installed ? pc.green('installed') : pc.yellow('not installed');
113
+ }
114
+
115
+ function printTextStatus(payload) {
116
+ const managed = payload.managed;
117
+ const effective = payload.effective;
118
+ console.log(pc.bold('AgentSam Machine'));
119
+ console.log(pc.dim('Deterministic local perception · native runtime'));
120
+ console.log('');
121
+ console.log(pc.bold('Managed runtime'));
122
+ console.log(` status ${stateLabel(managed.installed)}`);
123
+ console.log(` version ${managed.current_version || pc.dim('—')}`);
124
+ console.log(` runtime ${compactPath(managed.runtime_root)}`);
125
+ console.log(` binary ${compactPath(managed.binary)}`);
126
+ console.log('');
127
+ console.log(pc.bold('Active resolution'));
128
+ console.log(` source ${effective.source || pc.dim('unavailable')}`);
129
+ console.log(` version ${effective.version || pc.dim('unknown')}`);
130
+ console.log(` cargo ${managed.cargo.available ? compactPath(managed.cargo.path) : pc.dim('not found')}`);
131
+ if (!managed.installed) {
132
+ console.log('');
133
+ console.log(` ${pc.yellow('Next step')} agentsam machine install`);
66
134
  }
67
- if (resolution.kind === 'cargo') {
68
- console.log(`agentsam-machine via cargo run (${resolution.source}): ${resolution.manifest}`);
69
- console.log('capability: machine.inspect (dev fallback)');
70
- return;
135
+ }
136
+
137
+ function printTextDoctor(payload) {
138
+ printTextStatus(payload);
139
+ console.log('');
140
+ console.log(pc.bold('Doctor'));
141
+ if (payload.effective.kind === 'missing') {
142
+ console.log(` ${pc.red('✕')} Machine unavailable`);
143
+ console.log(` tried ${(payload.effective.tried || []).map(compactPath).join(', ') || pc.dim('none')}`);
144
+ } else if (payload.managed.installed) {
145
+ console.log(` ${pc.green('✓')} Managed Machine runtime is available`);
146
+ } else {
147
+ console.log(` ${pc.yellow('○')} Fallback runtime is active: ${payload.effective.source}`);
148
+ console.log(' install the managed runtime for consistent resolution across repositories');
71
149
  }
72
- console.log('agentsam-machine unavailable');
73
- console.log(`tried: ${(resolution.tried || []).join(', ')}`);
74
150
  }
75
151
 
76
- /**
77
- * @param {string[]} argv
78
- */
152
+ function printInstallResult(action, result) {
153
+ console.log(pc.bold(`AgentSam Machine · ${action}`));
154
+ console.log('');
155
+ console.log(` ${pc.green('✓')} Runtime ${result.changed ? 'installed' : 'already current'}`);
156
+ console.log(` version ${result.version}`);
157
+ console.log(` source ${result.source}`);
158
+ console.log(` binary ${compactPath(result.binary)}`);
159
+ console.log(` alias ${compactPath(result.alias)}`);
160
+ }
161
+
79
162
  export async function runMachine(argv = []) {
80
163
  const args = parseArgs(argv);
81
164
  if (args.help || !args.subcommand) {
@@ -83,20 +166,43 @@ export async function runMachine(argv = []) {
83
166
  return 0;
84
167
  }
85
168
 
86
- const resolution = resolveMachineBinary();
169
+ if (args.subcommand === 'status') {
170
+ const payload = statusPayload();
171
+ if (args.json) console.log(JSON.stringify(payload));
172
+ else printTextStatus(payload);
173
+ return 0;
174
+ }
87
175
 
88
176
  if (args.subcommand === 'doctor') {
89
- const payload = {
90
- capability: 'machine.doctor',
91
- available: resolution.kind !== 'missing',
92
- resolution,
93
- };
94
- if (args.json) console.log(JSON.stringify(payload));
95
- else printTextDoctor(resolution);
96
- return resolution.kind === 'missing' ? 1 : 0;
177
+ const payload = statusPayload();
178
+ if (args.json) console.log(JSON.stringify({ ...payload, capability: 'machine.doctor' }));
179
+ else printTextDoctor(payload);
180
+ return payload.effective.kind === 'missing' ? 1 : 0;
181
+ }
182
+
183
+ if (args.subcommand === 'install') {
184
+ const result = installManagedMachine({
185
+ version: args.version,
186
+ force: args.force,
187
+ write: args.json ? () => {} : (value) => process.stdout.write(value),
188
+ });
189
+ if (args.json) console.log(JSON.stringify({ capability: 'machine.install', ...result }));
190
+ else printInstallResult('install', result);
191
+ return 0;
192
+ }
193
+
194
+ if (args.subcommand === 'update') {
195
+ const result = updateManagedMachine({
196
+ force: args.force,
197
+ write: args.json ? () => {} : (value) => process.stdout.write(value),
198
+ });
199
+ if (args.json) console.log(JSON.stringify({ capability: 'machine.update', ...result }));
200
+ else printInstallResult('update', result);
201
+ return 0;
97
202
  }
98
203
 
99
204
  if (args.subcommand === 'inspect') {
205
+ const resolution = resolveMachineBinary();
100
206
  const target = args.target || process.cwd();
101
207
  const abs = path.resolve(target);
102
208
  const machineArgv = ['inspect', abs];
@@ -106,7 +212,6 @@ export async function runMachine(argv = []) {
106
212
 
107
213
  const result = spawnMachine(resolution, machineArgv, {
108
214
  stdio: args.json ? ['ignore', 'pipe', 'pipe'] : 'inherit',
109
- // Large donors still emit bounded compact JSON; raise buffer for safety.
110
215
  maxBuffer: 32 * 1024 * 1024,
111
216
  });
112
217
 
@@ -115,13 +220,12 @@ export async function runMachine(argv = []) {
115
220
  const stdout = String(result.stdout || '');
116
221
  const stderr = String(result.stderr || '');
117
222
  if (result.status && result.status !== 0) {
118
- const err = new Error(stderr.trim() || `agentsam-machine exited with code ${result.status}`);
223
+ const err = new Error(stderr.trim() || 'agentsam-machine exited with code ' + result.status);
119
224
  err.exitCode = result.status;
120
225
  throw err;
121
226
  }
122
227
  try {
123
- const parsed = JSON.parse(stdout);
124
- console.log(JSON.stringify(parsed));
228
+ console.log(JSON.stringify(JSON.parse(stdout)));
125
229
  } catch {
126
230
  process.stdout.write(stdout);
127
231
  }
@@ -131,7 +235,7 @@ export async function runMachine(argv = []) {
131
235
  }
132
236
 
133
237
  console.log(usage());
134
- const err = new Error(`Unknown machine subcommand: ${args.subcommand}`);
238
+ const err = new Error('Unknown machine subcommand: ' + args.subcommand);
135
239
  err.exitCode = 1;
136
240
  throw err;
137
241
  }