@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,82 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
- import test from 'node:test';
6
- import { buildWranglerInvocation, listWranglerNativeCommands, runWranglerNative, summarizeCloudflareCpuProfile, summarizeCloudflareCpuProfileFile } from '../src/cloudflare/index.js';
7
- import { createCapabilityAdapter } from '../src/agent/capability-adapter.js';
8
-
9
- function tempRoot() { return fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-cf-')); }
10
-
11
- test('Cloudflare native command catalog exposes bounded read operations and never an auth-token secret read', () => {
12
- const ids = listWranglerNativeCommands().map((row) => row.id);
13
- assert.deepEqual(ids, ['whoami', 'deployments.list', 'versions.list', 'versions.view', 'types.check', 'queues.list', 'tunnel.list', 'tunnel.info']);
14
- assert.ok(!ids.some((id) => id.includes('token') || id.includes('secret') || id === 'deploy'));
15
- });
16
-
17
- test('Wrangler version view requires an exact version and keeps secret values unavailable', () => {
18
- const root = tempRoot();
19
- const plan = buildWranglerInvocation('versions.view', { cwd: root, name: 'demo', version_id: 'ver_123' });
20
- assert.deepEqual(plan.args, ['versions', 'view', 'ver_123', '--json', '--name', 'demo']);
21
- assert.throws(() => buildWranglerInvocation('versions.view', { cwd: root, name: 'demo' }), /version_id_required/);
22
- });
23
-
24
- test('Wrangler native invocation is argv-based and cwd/config scoped', () => {
25
- const root = tempRoot();
26
- fs.writeFileSync(path.join(root, 'wrangler.jsonc'), '{}');
27
- const plan = buildWranglerInvocation('deployments.list', { cwd: root, name: 'demo' });
28
- assert.equal(plan.cwd, root);
29
- assert.deepEqual(plan.args.slice(0, 4), ['deployments', 'list', '--json', '--name']);
30
- assert.equal(plan.args[4], 'demo');
31
- assert.ok(plan.args.includes('--config'));
32
- assert.throws(() => buildWranglerInvocation('whoami', { cwd: root, config: '../outside.toml' }), /outside_cwd/);
33
- });
34
-
35
- test('Wrangler native result preserves JSON and real exit code on failure', async () => {
36
- const root = tempRoot();
37
- const success = await runWranglerNative('whoami', { cwd: root }, { run: async () => ({ code: 0, stdout: JSON.stringify({ email: 'dev@example.com' }), stderr: '' }) });
38
- assert.equal(success.data.email, 'dev@example.com');
39
- await assert.rejects(
40
- runWranglerNative('versions.list', { cwd: root }, { run: async () => ({ code: 7, stdout: '', stderr: 'upstream failed' }) }),
41
- (error) => error.diagnostic?.exit_code === 7 && error.diagnostic?.code === 'wrangler_exit_nonzero',
42
- );
43
- await assert.rejects(
44
- runWranglerNative('deployments.list', { cwd: root }, { run: async () => ({ code: 1, stdout: '', stderr: 'Authentication error [code: 10000]\nRequest ID: req_cf_1\nCF-Ray: ray-123' }) }),
45
- (error) => error.diagnostic?.code === '10000' && error.diagnostic?.request_id === 'req_cf_1' && error.diagnostic?.ray_id === 'ray-123',
46
- );
47
- });
48
-
49
- test('CPU profile summary ranks self-time hotspots and explicitly rejects production timer inference', () => {
50
- const profile = {
51
- nodes: [
52
- { id: 1, callFrame: { functionName: 'fetch', url: 'worker.js', lineNumber: 0, columnNumber: 0 } },
53
- { id: 2, callFrame: { functionName: 'heavyLoop', url: 'worker.js', lineNumber: 10, columnNumber: 2 } },
54
- { id: 3, callFrame: { functionName: '(garbage collector)', url: '', lineNumber: -1, columnNumber: -1 } },
55
- ],
56
- samples: [1, 2, 2, 3],
57
- timeDeltas: [100, 1200, 800, 400],
58
- };
59
- const summary = summarizeCloudflareCpuProfile(profile);
60
- assert.equal(summary.top_frames[0].function, 'heavyLoop');
61
- assert.equal(summary.top_frames[0].self_us, 2000);
62
- assert.equal(summary.garbage_collection_ms, 0.4);
63
- assert.match(summary.timer_semantics, /do not advance during CPU-only execution/);
64
- });
65
-
66
- test('CPU profile file cannot escape runtime cwd', () => {
67
- const root = tempRoot();
68
- fs.writeFileSync(path.join(root, 'profile.cpuprofile'), JSON.stringify({ nodes: [], samples: [], timeDeltas: [] }));
69
- assert.equal(summarizeCloudflareCpuProfileFile({ cwd: root, file: 'profile.cpuprofile' }).file, 'profile.cpuprofile');
70
- assert.throws(() => summarizeCloudflareCpuProfileFile({ cwd: root, file: '../profile.cpuprofile' }), /outside_cwd/);
71
- });
72
-
73
- test('explicitly executable experimental Cloudflare capabilities enter cards-first discovery without exposing unavailable commands', () => {
74
- const adapter = createCapabilityAdapter();
75
- const rows = adapter.toolDescriptors();
76
- const ids = rows.map((row) => row.name);
77
- assert.ok(ids.includes('cloudflare.wrangler.native'));
78
- assert.ok(ids.includes('cloudflare.cpu.profile'));
79
- assert.ok(!ids.includes('cloudflare.cpu.audit'));
80
- assert.ok(!ids.includes('blender.build'));
81
- assert.equal(rows.find((row) => row.name === 'cloudflare.wrangler.native').risk, 'read');
82
- });
@@ -1,159 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
- import test from 'node:test';
6
- import {
7
- DEFAULT_RESULT_POLICY,
8
- assessContextUsage,
9
- compileAgentInstructions,
10
- createContextBudget,
11
- normalizeResultPolicy,
12
- resolveContext,
13
- resolveProjectContext,
14
- } from '../src/context/index.js';
15
-
16
- test('default result policy is bounded and callers may request less', () => {
17
- assert.deepEqual(DEFAULT_RESULT_POLICY, { max_items: 8, max_chars: 24_000, detail: 'excerpt' });
18
- assert.deepEqual(normalizeResultPolicy({ max_items: 3, max_chars: 8_000, detail: 'card' }), { max_items: 3, max_chars: 8_000, detail: 'card' });
19
- assert.throws(() => normalizeResultPolicy({ max_items: 9 }), /higher_detail_required:max_items/);
20
- assert.throws(() => normalizeResultPolicy({ max_chars: 24_001 }), /higher_detail_required:max_chars/);
21
- assert.throws(() => normalizeResultPolicy({ detail: 'full' }), /higher_detail_required:detail/);
22
- assert.equal(normalizeResultPolicy({ detail: 'full', max_items: 20, max_chars: 100_000 }, { operation: 'higher-detail' }).detail, 'full');
23
- });
24
-
25
- test('legacy ratio context budget remains compatible for ordinary windows', () => {
26
- const budget = createContextBudget({ windowTokens: 250_000 });
27
- assert.equal(budget.targetInputTokens, 150_000);
28
- assert.equal(budget.hardInputTokens, 212_500);
29
- assert.equal(budget.windowChars, 1_000_000);
30
- assert.equal(budget.maxSystemChars, 50_000);
31
- assert.equal(budget.maxToolSchemaChars, 40_000);
32
- assert.equal(budget.maxEvidenceChars, 100_000);
33
- assert.equal(budget.maxFileCharsPerRead, 32_768);
34
- assert.equal(budget.maxFileCharsPerTurn, 131_072);
35
- assert.equal(budget.maxToolResultChars, 24_000);
36
- });
37
-
38
- test('large model capacity is independent from AgentSam working-set and pricing policy', () => {
39
- const budget = createContextBudget({
40
- windowTokens: 1_050_000,
41
- targetInputTokens: 120_000,
42
- compactAtTokens: 180_000,
43
- interveneAtTokens: 220_000,
44
- maxNormalInputTokens: 250_000,
45
- pricingThresholdTokens: 272_000,
46
- safetyMarginTokens: 22_000,
47
- });
48
- assert.equal(budget.windowTokens, 1_050_000);
49
- assert.equal(budget.targetInputTokens, 120_000);
50
- assert.equal(budget.compactAtTokens, 180_000);
51
- assert.equal(budget.interveneAtTokens, 220_000);
52
- assert.equal(budget.maxNormalInputTokens, 250_000);
53
- assert.equal(budget.pricingThresholdTokens, 272_000);
54
- assert.ok(budget.targetInputRatio < 0.12);
55
-
56
- assert.equal(assessContextUsage(179_999, budget).shouldCompact, false);
57
- assert.equal(assessContextUsage(180_000, budget).shouldCompact, true);
58
- assert.equal(assessContextUsage(272_000, budget).pricingThresholdCrossed, false);
59
- const crossed = assessContextUsage(272_001, budget);
60
- assert.equal(crossed.pricingThresholdCrossed, true);
61
- assert.equal(crossed.tokensUntilPricingThreshold, -1);
62
- });
63
-
64
- test('context.resolve separates composition classes and returns an economic receipt', () => {
65
- const budget = createContextBudget({
66
- windowTokens: 32_000,
67
- maxEvidenceChars: 90,
68
- maxFileCharsPerRead: 50,
69
- maxFileCharsPerTurn: 60,
70
- maxToolResultChars: 30,
71
- });
72
- const pack = resolveContext({
73
- objective: 'fix terminal cwd persistence',
74
- refs: ['repo:demo'],
75
- budget,
76
- instructionChars: 20,
77
- toolSchemaChars: 12,
78
- historyChars: 8,
79
- items: [
80
- { ref: 'file:low', kind: 'file', priority: 1, content: 'L'.repeat(50) },
81
- { ref: 'tool:high', kind: 'tool_result', priority: 10, content: 'T'.repeat(50) },
82
- { ref: 'file:high', kind: 'file', priority: 8, content: 'F'.repeat(80) },
83
- { ref: 'memory:later', kind: 'memory', priority: 0, content: 'M'.repeat(40) },
84
- ],
85
- });
86
-
87
- assert.deepEqual(pack.items.map((item) => item.ref), ['tool:high', 'file:high', 'file:low']);
88
- assert.equal(pack.items[0].chars, 30);
89
- assert.equal(pack.items[1].chars, 50);
90
- assert.equal(pack.items[2].chars, 10);
91
- assert.equal(pack.receipt.tool_result_chars, 30);
92
- assert.equal(pack.receipt.evidence_chars, 60);
93
- assert.equal(pack.receipt.instruction_chars, 20);
94
- assert.equal(pack.receipt.tool_schema_chars, 12);
95
- assert.equal(pack.receipt.history_chars, 8);
96
- assert.equal(pack.receipt.chars, 130);
97
- assert.equal(pack.receipt.estimate_kind, 'local');
98
- assert.equal(pack.receipt.window_tokens, 32_000);
99
- assert.equal(pack.receipt.sources_considered, 4);
100
- assert.equal(pack.receipt.sources_included, 3);
101
- assert.ok(pack.receipt.sources_deferred >= 3);
102
- assert.ok(pack.receipt.deferred_refs.includes('memory:later'));
103
- assert.deepEqual(pack.receipt.rehydratable_refs, ['tool:high', 'file:high', 'file:low']);
104
- });
105
-
106
- test('AgentSam instructions compile in stable then repository-specific precedence', t => {
107
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-instructions-'));
108
- t.after(() => fs.rmSync(root, { recursive: true, force: true }));
109
- fs.mkdirSync(path.join(root, '.git'));
110
- fs.writeFileSync(path.join(root, 'AGENTSAM.md'), '# Stable\nbase law\n');
111
- fs.writeFileSync(path.join(root, '.agentsamrules'), '# Repo\nlocal law\n');
112
- const compiled = compileAgentInstructions(root);
113
- assert.deepEqual(compiled.precedence, ['AGENTSAM.md', '.agentsamrules']);
114
- assert.equal(compiled.sources.length, 2);
115
- assert.ok(compiled.content.indexOf('base law') < compiled.content.indexOf('local law'));
116
- });
117
-
118
- test('compatibility shims are not compiled into AgentSam instruction authority', t => {
119
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-instruction-shims-'));
120
- t.after(() => fs.rmSync(root, { recursive: true, force: true }));
121
- fs.mkdirSync(path.join(root, '.git'));
122
- fs.writeFileSync(path.join(root, 'AGENTSAM.md'), '# Stable\ncanonical only\n');
123
- fs.writeFileSync(path.join(root, 'AGENTS.md'), 'shim should not become policy\n');
124
- fs.writeFileSync(path.join(root, 'CLAUDE.md'), 'claude shim should not become policy\n');
125
- const compiled = compileAgentInstructions(root);
126
- assert.equal(compiled.sources.length, 1);
127
- assert.equal(compiled.sources[0].filename, 'AGENTSAM.md');
128
- assert.match(compiled.content, /canonical only/);
129
- assert.doesNotMatch(compiled.content, /shim should not become policy/);
130
- assert.doesNotMatch(compiled.content, /claude shim should not become policy/);
131
- });
132
-
133
- test('project context loads bounded compiled AgentSam instructions', t => {
134
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-context-rules-'));
135
- t.after(() => fs.rmSync(root, { recursive: true, force: true }));
136
- fs.mkdirSync(path.join(root, '.git'));
137
- fs.writeFileSync(path.join(root, 'AGENTSAM.md'), '# stable\n' + 'a'.repeat(300));
138
- fs.writeFileSync(path.join(root, '.agentsamrules'), '# rules\n' + 'x'.repeat(5000) + '\n');
139
- const pack = resolveProjectContext({
140
- cwd: root,
141
- objective: 'inspect repository',
142
- budget: createContextBudget({ windowTokens: 8_000, maxSystemChars: 1_000, maxEvidenceChars: 1_000 }),
143
- items: [],
144
- });
145
- assert.equal(pack.rules.found, true);
146
- assert.equal(pack.rules.chars, 1_000);
147
- assert.equal(pack.rules.truncated, true);
148
- assert.equal(pack.receipt.system_chars, 1_000);
149
- });
150
-
151
- test('consumed tool results compact to 4k while preserving rehydration identity', async () => {
152
- const { compactConsumedToolResult } = await import('../src/context/index.js');
153
- const item = compactConsumedToolResult('x'.repeat(10_000), { ref: 'tool:call_123', hash: 'sha256:abc' });
154
- assert.equal(item.ref, 'tool:call_123');
155
- assert.equal(item.hash, 'sha256:abc');
156
- assert.equal(item.chars, 4_000);
157
- assert.equal(item.compacted, true);
158
- assert.equal(item.source_chars, 10_000);
159
- });
@@ -1,113 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import test from 'node:test';
3
- import {
4
- remediateGcloudEdgeServiceAccountKey,
5
- remediateGcloudPermissionDenied,
6
- remediateGithubTokenShadow,
7
- remediateProviderFailure,
8
- renderRemediationCard,
9
- recommendedCommand,
10
- } from '../src/lib/provider-command-remediation.js';
11
- import { runCredentials } from '../src/commands/credentials.js';
12
- import { listCheatSheetGroups, renderCheatSheet } from '../src/commands/cheat-sheet.js';
13
- import { collectCredentialsAudit } from '../src/lib/credentials-audit.js';
14
-
15
- test('edge-cloud service-account key create remediates to IAM / compute intents', () => {
16
- const card = remediateGcloudEdgeServiceAccountKey({
17
- argv: ['gcloud', 'edge-cloud', 'service-accounts', 'keys', 'create'],
18
- projectId: 'gen-lang-client-0684066529',
19
- instance: 'iam-tunnel',
20
- zone: 'us-central1-f',
21
- });
22
- assert.ok(card);
23
- assert.equal(card.provider, 'google_cloud');
24
- assert.equal(card.kind, 'command_incomplete_wrong_family');
25
- assert.match(card.summary, /Distributed Cloud Edge/i);
26
- assert.match(card.summary, /Compute Engine/i);
27
- const commands = card.actions.map((row) => row.command).join('\n');
28
- assert.match(commands, /gcloud compute instances describe iam-tunnel/);
29
- assert.match(commands, /gcloud iam service-accounts list/);
30
- assert.match(commands, /gcloud iam service-accounts keys create/);
31
- assert.match(commands, /agentsam connections/);
32
- const rendered = renderRemediationCard(card);
33
- assert.match(rendered, /Command incomplete/);
34
- assert.match(rendered, /\[enter\]/);
35
- assert.equal(recommendedCommand(card), card.actions[0].command);
36
- });
37
-
38
- test('remediateProviderFailure matches edge-cloud argv fixture', () => {
39
- const card = remediateProviderFailure({
40
- argv: ['gcloud', 'edge-cloud', 'service-accounts', 'keys', 'create'],
41
- stderr: 'ERROR: argument OUTPUT_FILE (--service-account : --location): Must be specified.',
42
- });
43
- assert.ok(card);
44
- assert.equal(card.kind, 'command_incomplete_wrong_family');
45
- });
46
-
47
- test('permission denied remediation exposes reauth + IAM console actions', () => {
48
- const card = remediateGcloudPermissionDenied({
49
- operation: 'compute.instances.list',
50
- projectId: 'gen-lang-client-0684066529',
51
- connection: 'Google Cloud · InnerAnimalMedia',
52
- });
53
- assert.equal(card.kind, 'permission_denied');
54
- assert.match(renderRemediationCard(card), /Permission missing/);
55
- assert.match(renderRemediationCard(card), /Re-authorize Google Cloud/);
56
- assert.ok(card.actions.some((row) => /console\.cloud\.google\.com\/iam-admin/i.test(row.docs_url || '')));
57
- });
58
-
59
- test('github token shadow remediation prefers unset + keyring status', () => {
60
- const card = remediateGithubTokenShadow({
61
- envTokenPresent: true,
62
- keyringHealthy: true,
63
- scopes: ['repo', 'read:org'],
64
- });
65
- assert.ok(card);
66
- assert.equal(card.kind, 'credential_shadow');
67
- assert.match(recommendedCommand(card), /unset GITHUB_TOKEN/);
68
- });
69
-
70
- test('credentials remediate CLI prints edge-cloud card without secrets', async () => {
71
- const chunks = [];
72
- const code = await runCredentials(
73
- ['remediate', '--', 'gcloud', 'edge-cloud', 'service-accounts', 'keys', 'create'],
74
- { write: (s) => chunks.push(s) },
75
- );
76
- assert.equal(code, 0);
77
- const out = chunks.join('');
78
- assert.match(out, /Google Cloud/);
79
- assert.match(out, /gcloud iam service-accounts list/);
80
- assert.doesNotMatch(out, /gho_/);
81
- assert.doesNotMatch(out, /AIza/);
82
- });
83
-
84
- test('credentials audit --names-only never includes secret-looking values', async () => {
85
- const report = await collectCredentialsAudit({
86
- env: {
87
- HOME: process.env.HOME,
88
- AGENTSAM_API_KEY: 'aak_test_should_never_appear_in_output_fields_as_value',
89
- GITHUB_TOKEN: 'ghp_should_never_be_echoed',
90
- OPENAI_API_KEY: 'sk-should-never-be-echoed',
91
- },
92
- verify: false,
93
- drift: true,
94
- namesOnly: true,
95
- noNetwork: true,
96
- });
97
- const blob = JSON.stringify(report);
98
- assert.doesNotMatch(blob, /aak_test_should_never/);
99
- assert.doesNotMatch(blob, /ghp_should_never/);
100
- assert.doesNotMatch(blob, /sk-should-never/);
101
- assert.equal(report.shell_presence.GITHUB_TOKEN, true);
102
- assert.equal(report.shell_presence.AGENTSAM_API_KEY, true);
103
- assert.ok(report.drift.some((row) => row.code === 'github_env_token_present'));
104
- });
105
-
106
- test('cheat-sheet exposes System + Providers groups', () => {
107
- const groups = listCheatSheetGroups();
108
- assert.ok(groups.some((g) => g.id === 'system'));
109
- assert.ok(groups.some((g) => g.id === 'providers'));
110
- const text = renderCheatSheet('2.6.4');
111
- assert.match(text, /credentials audit/);
112
- assert.match(text, /cheat-sheet/);
113
- });
@@ -1,95 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import { describe, it } from 'node:test';
3
- import { scanTextForSecrets } from '../src/lib/deploy/secret-scan.js';
4
- import { HEALTH_USER_AGENT, parseWranglerVersionId, probeDeployHealth, resolveHealthOrigin } from '../src/lib/deploy/health.js';
5
-
6
- describe('deploy secret scan', () => {
7
- it('allows fixture oauth values', () => {
8
- const findings = scanTextForSecrets(
9
- 'CLOUDFLARE_OAUTH_CLIENT_ID=sillynotreal\nCLOUDFLARE_OAUTH_CLIENT_SECRET=sillynotreal-secret\n',
10
- { filename: 'apps/local-studio/.env.cloudflare.example' },
11
- );
12
- assert.equal(findings.length, 0);
13
- });
14
-
15
- it('flags live openai-like keys', () => {
16
- const findings = scanTextForSecrets('OPENAI_API_KEY=sk-abcdefghijklmnopqrstuvwxyz012345');
17
- assert.equal(findings.some((f) => f.label === 'openai-like'), true);
18
- });
19
- });
20
-
21
- describe('deploy health', () => {
22
- it('parses wrangler version ids', () => {
23
- assert.equal(
24
- parseWranglerVersionId('Current Version ID: e9747d3a-4db6-4e02-b6fe-aa5a47f1588b'),
25
- 'e9747d3a-4db6-4e02-b6fe-aa5a47f1588b',
26
- );
27
- });
28
-
29
- it('reads hostname from wrangler.jsonc', () => {
30
- const origin = resolveHealthOrigin({
31
- wranglerConfigText: '{"routes":[{"pattern":"agentsam.inneranimalmedia.com","custom_domain":true}]}',
32
- });
33
- assert.equal(origin, 'https://agentsam.inneranimalmedia.com');
34
- });
35
-
36
- it('fails loud when wrangler routes pattern is missing', () => {
37
- assert.throws(
38
- () => resolveHealthOrigin({ wranglerConfigText: '{}' }),
39
- (err) => err?.code === 'health_origin_required',
40
- );
41
- });
42
-
43
- it('treats /health ok:true with connector unconfigured as healthy', async () => {
44
- const fetchImpl = async (url) => {
45
- if (String(url).endsWith('/health')) {
46
- return {
47
- status: 200,
48
- json: async () => ({ ok: true, connections: { cloudflare: { configured: false } } }),
49
- };
50
- }
51
- return { status: 200, json: async () => ({}) };
52
- };
53
- const health = await probeDeployHealth('https://agentsam.inneranimalmedia.com', { fetchImpl });
54
- assert.equal(health.ok, true);
55
- assert.equal(health.results['/health'].appOk, true);
56
- assert.equal(health.results['/health'].cloudflareConfigured, false);
57
- assert.equal(health.results['/privacy'].ok, true);
58
- assert.equal(health.results['/terms'].ok, true);
59
- });
60
-
61
- it('fails deploy health when /privacy or /terms are not HTTP 200', async () => {
62
- const fetchImpl = async (url) => {
63
- const path = String(url).replace(/^https?:\/\/[^/]+/, '');
64
- if (path === '/health') {
65
- return {
66
- status: 200,
67
- json: async () => ({ ok: true, connections: { cloudflare: { configured: true } } }),
68
- };
69
- }
70
- if (path === '/privacy' || path === '/terms') {
71
- return { status: 404, json: async () => ({}) };
72
- }
73
- return { status: 200, json: async () => ({}) };
74
- };
75
- const health = await probeDeployHealth('https://agentsam.inneranimalmedia.com', { fetchImpl });
76
- assert.equal(health.ok, false);
77
- assert.equal(health.results['/privacy'].ok, false);
78
- assert.equal(health.results['/terms'].ok, false);
79
- });
80
-
81
- it('sends a browser-safe User-Agent so WAF does not 403 the probe', async () => {
82
- const seen = [];
83
- const fetchImpl = async (url, init = {}) => {
84
- seen.push({ url, init });
85
- return {
86
- status: 200,
87
- json: async () => ({ ok: true, connections: { cloudflare: { configured: false } } }),
88
- };
89
- };
90
- await probeDeployHealth('https://agentsam.inneranimalmedia.com', { fetchImpl, paths: ['/health'] });
91
- assert.equal(seen.length, 1);
92
- assert.equal(seen[0].init.headers['User-Agent'], HEALTH_USER_AGENT);
93
- assert.match(seen[0].init.headers.Accept, /application\/json/);
94
- });
95
- });
@@ -1,91 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import { test } from 'node:test';
3
- import fs from 'node:fs/promises';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import { execFileSync, spawnSync } from 'node:child_process';
7
- import { fileURLToPath } from 'node:url';
8
- import {
9
- captureDeployReceipt,
10
- finalizeDeployReceipt,
11
- showLatestDeployReceipt,
12
- } from '../src/lib/deploy-receipt/index.js';
13
-
14
- const cli = fileURLToPath(new URL('../src/cli.js', import.meta.url));
15
-
16
- async function fixture(t) {
17
- const root = await fs.mkdtemp(path.join(os.tmpdir(), 'agentsam-deploy-receipt-'));
18
- t.after(() => fs.rm(root, { recursive: true, force: true }));
19
- execFileSync('git', ['init', '-q', root]);
20
- execFileSync('git', ['-C', root, 'config', 'user.email', 'receipt-test@example.invalid']);
21
- execFileSync('git', ['-C', root, 'config', 'user.name', 'Receipt Test']);
22
- await fs.mkdir(path.join(root, 'src'), { recursive: true });
23
- await fs.writeFile(path.join(root, 'src/app.js'), 'export const value = 1;\n');
24
- execFileSync('git', ['-C', root, 'add', '.']);
25
- execFileSync('git', ['-C', root, 'commit', '-qm', 'fixture']);
26
- return root;
27
- }
28
-
29
- function run(args, cwd) {
30
- return spawnSync(process.execPath, [cli, 'deploy-receipt', ...args], { cwd, encoding: 'utf8', timeout: 15000 });
31
- }
32
-
33
- test('successful finalize advances baseline while failure preserves the last trusted tree', async (t) => {
34
- const root = await fixture(t);
35
- const first = await captureDeployReceipt({ root, project: 'fixture' });
36
- assert.equal(first.receipt.has_baseline, false);
37
- assert.equal(first.receipt.baseline_source, 'none');
38
- assert.equal(first.receipt.working_tree_dirty, false);
39
- assert.ok(!first.snapshot.entries.some((entry) => entry.path.startsWith('.agentsam/deploy-merkle')));
40
-
41
- const promoted = await finalizeDeployReceipt({ root, status: 'success', deploymentId: 'dep_1' });
42
- assert.equal(promoted.receipt.status, 'success');
43
- assert.equal(promoted.receipt.deployment_id, 'dep_1');
44
- assert.equal((await showLatestDeployReceipt({ root })).root_hash, first.receipt.root_hash);
45
-
46
- const clean = await captureDeployReceipt({ root, project: 'fixture' });
47
- assert.equal(clean.receipt.has_baseline, true);
48
- assert.equal(clean.receipt.baseline_source, 'local');
49
- assert.deepEqual(clean.receipt.diff_stats, { unchanged: 1, modified: 0, added: 0, removed: 0 });
50
- assert.deepEqual(clean.receipt.changed_files, []);
51
- assert.equal(clean.receipt.root_hash, first.receipt.root_hash);
52
- assert.equal(clean.receipt.working_tree_dirty, false, 'runtime receipt state must not make the source tree dirty');
53
-
54
- await fs.writeFile(path.join(root, 'src/app.js'), 'export const value = 2;\n');
55
- const changed = await captureDeployReceipt({ root, project: 'fixture' });
56
- assert.equal(changed.receipt.working_tree_dirty, true);
57
- assert.deepEqual(changed.receipt.diff_stats, { unchanged: 0, modified: 1, added: 0, removed: 0 });
58
- assert.deepEqual(changed.receipt.changed_files, ['src/app.js']);
59
- assert.notEqual(changed.receipt.root_hash, first.receipt.root_hash);
60
-
61
- await finalizeDeployReceipt({ root, status: 'failed', deploymentId: 'dep_2' });
62
- assert.equal((await showLatestDeployReceipt({ root })).root_hash, first.receipt.root_hash, 'failed run must not advance baseline');
63
-
64
- const retry = await captureDeployReceipt({ root, project: 'fixture' });
65
- assert.deepEqual(retry.receipt.changed_files, ['src/app.js']);
66
- await finalizeDeployReceipt({ root, status: 'success', deploymentId: 'dep_3' });
67
- const settled = await captureDeployReceipt({ root, project: 'fixture' });
68
- assert.deepEqual(settled.receipt.diff_stats, { unchanged: 1, modified: 0, added: 0, removed: 0 });
69
- assert.deepEqual(settled.receipt.changed_files, []);
70
- });
71
-
72
- test('deploy-receipt CLI emits machine-readable capture/finalize/show receipts', async (t) => {
73
- const root = await fixture(t);
74
- const capture = run(['capture', '.', '--project', 'cli-fixture', '--json'], root);
75
- assert.equal(capture.status, 0, capture.stderr);
76
- const captured = JSON.parse(capture.stdout);
77
- assert.equal(captured.format, 'agentsam-deploy-merkle');
78
- assert.equal(captured.project, 'cli-fixture');
79
- assert.equal(captured.status, 'captured');
80
-
81
- const success = run(['success', '.', '--deployment-id', 'dep_cli', '--worker-version', 'worker_v1', '--json'], root);
82
- assert.equal(success.status, 0, success.stderr);
83
- const finalized = JSON.parse(success.stdout);
84
- assert.equal(finalized.status, 'success');
85
- assert.equal(finalized.deployment_id, 'dep_cli');
86
- assert.equal(finalized.worker_version_id, 'worker_v1');
87
-
88
- const show = run(['show', '.', '--json'], root);
89
- assert.equal(show.status, 0, show.stderr);
90
- assert.equal(JSON.parse(show.stdout).root_hash, finalized.root_hash);
91
- });
@@ -1,93 +0,0 @@
1
- // Pure unit tests — no Docker daemon required, safe for CI/smoke.
2
- // Integration coverage (actual docker build/run) is manual: see docs/DOCKERIZE.md.
3
- import { test } from 'node:test';
4
- import assert from 'node:assert/strict';
5
- import fs from 'node:fs';
6
- import os from 'node:os';
7
- import path from 'node:path';
8
- import {
9
- DOCKER_APP_TYPES,
10
- DOCKER_APP_TYPE_LABELS,
11
- slugifyForDocker,
12
- generateDockerFileSet,
13
- computeFileSetHash,
14
- buildDockerDeployPlan,
15
- writeDockerFileSet,
16
- readManifest,
17
- } from '../src/lib/dockerize.js';
18
-
19
- test('slugifyForDocker normalizes to a safe image/container name', () => {
20
- assert.equal(slugifyForDocker('My Cool App!'), 'my-cool-app');
21
- assert.equal(slugifyForDocker(' --leading-- '), 'leading');
22
- assert.equal(slugifyForDocker(''), 'app');
23
- });
24
-
25
- test('every declared app type has a label and generates a valid file set', () => {
26
- for (const type of DOCKER_APP_TYPES) {
27
- assert.ok(DOCKER_APP_TYPE_LABELS[type]?.label, `missing label for ${type}`);
28
- const files = generateDockerFileSet(type, { appSlug: 'test-app', port: 9999 });
29
- assert.match(files.dockerfile, /^FROM /m, `${type} Dockerfile must start with FROM`);
30
- assert.ok(files.dockerignore.includes('node_modules'), `${type} .dockerignore should ignore node_modules`);
31
- assert.ok(files.compose.includes('services:'), `${type} compose file must define services`);
32
- }
33
- });
34
-
35
- test('unknown app type throws a clear error instead of generating garbage', () => {
36
- assert.throws(() => generateDockerFileSet('not_a_real_type', { appSlug: 'x' }), /Unknown Docker app type/);
37
- });
38
-
39
- test('buildDockerDeployPlan picks correct container port for static/vite (80) vs service types (host port)', () => {
40
- const staticPlan = buildDockerDeployPlan('static', { appSlug: 'x', port: 8080 });
41
- assert.equal(staticPlan.containerPort, 80);
42
- assert.equal(staticPlan.hostPort, 8080);
43
-
44
- const nodePlan = buildDockerDeployPlan('node_service', { appSlug: 'x', port: 4000 });
45
- assert.equal(nodePlan.containerPort, 4000);
46
- assert.equal(nodePlan.hostPort, 4000);
47
- });
48
-
49
- test('buildDockerDeployPlan falls back to sensible default ports when none given', () => {
50
- const plan = buildDockerDeployPlan('wrangler_dev', { appSlug: 'x' });
51
- assert.equal(plan.hostPort, 8787);
52
- assert.equal(plan.imageTag, 'x:local'.replace('local', plan.hash));
53
- });
54
-
55
- test('computeFileSetHash is deterministic: identical content -> identical hash', () => {
56
- const a = generateDockerFileSet('node_service', { appSlug: 'same', port: 3000 });
57
- const b = generateDockerFileSet('node_service', { appSlug: 'same', port: 3000 });
58
- assert.equal(computeFileSetHash(a), computeFileSetHash(b));
59
- });
60
-
61
- test('computeFileSetHash changes when content changes (different port -> different hash)', () => {
62
- const a = generateDockerFileSet('node_service', { appSlug: 'same', port: 3000 });
63
- const b = generateDockerFileSet('node_service', { appSlug: 'same', port: 4000 });
64
- assert.notEqual(computeFileSetHash(a), computeFileSetHash(b));
65
- });
66
-
67
- test('buildDockerDeployPlan image tag and hashtag are hash-derived and match the slug', () => {
68
- const plan = buildDockerDeployPlan('static', { appSlug: 'My App', port: 8080 });
69
- assert.equal(plan.slug, 'my-app');
70
- assert.equal(plan.imageTag, `my-app:${plan.hash}`);
71
- assert.equal(plan.latestTag, 'my-app:latest');
72
- assert.equal(plan.hashtag, `#docker-my-app-${plan.hash}`);
73
- });
74
-
75
- test('writeDockerFileSet writes into .agentsam/docker/<hash>/ and .dockerignore at root, and the manifest round-trips', () => {
76
- const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-dockerize-test-'));
77
- try {
78
- const files = generateDockerFileSet('static', { appSlug: 'tmp-app', port: 9090 });
79
- const hash = computeFileSetHash(files);
80
- const written = writeDockerFileSet(tmp, files, hash);
81
-
82
- assert.equal(written.dockerfilePath, path.join(tmp, '.agentsam', 'docker', hash, 'Dockerfile'));
83
- assert.ok(fs.existsSync(written.dockerfilePath));
84
- assert.ok(fs.existsSync(written.composePath));
85
- assert.ok(fs.existsSync(path.join(tmp, '.dockerignore')));
86
-
87
- // manifest is populated by dockerize()/writeManifestEntry, not writeDockerFileSet itself —
88
- // confirm readManifest returns {} when nothing has written to it yet
89
- assert.deepEqual(readManifest(tmp), {});
90
- } finally {
91
- fs.rmSync(tmp, { recursive: true, force: true });
92
- }
93
- });