@inneranimalmedia/agentsam-sdk 2.6.5 → 2.6.8

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 (400) hide show
  1. package/AGENTSAM.md +29 -0
  2. package/README.md +37 -0
  3. package/apps/README.md +5 -0
  4. package/apps/cad-creator/README.md +4 -4
  5. package/apps/cad-creator/shared/cad/package.json +1 -1
  6. package/apps/client-cms-editor/AGENTS.md +12 -7
  7. package/apps/client-cms-editor/README.md +76 -48
  8. package/apps/client-cms-editor/agentsam.app.json +26 -9
  9. package/apps/client-cms-editor/backend/package.json +20 -3
  10. package/apps/client-cms-editor/backend/src/api/client.ts +134 -101
  11. package/apps/client-cms-editor/backend/src/index.ts +1 -1
  12. package/apps/client-cms-editor/backend/src/model.ts +11 -115
  13. package/apps/client-cms-editor/backend/src/preview/bridge.ts +1 -1
  14. package/apps/client-cms-editor/backend/tsconfig.json +6 -1
  15. package/apps/client-cms-editor/bin/agentsam-cms.js +262 -0
  16. package/apps/client-cms-editor/bin/agentsam-cms.mjs +2 -228
  17. package/apps/client-cms-editor/frontend/package.json +16 -7
  18. package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +9 -41
  19. package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +19 -174
  20. package/apps/client-cms-editor/frontend/src/adapters/heuristic.ts +29 -0
  21. package/apps/client-cms-editor/frontend/src/adapters/http.ts +628 -0
  22. package/apps/client-cms-editor/frontend/src/adapters/memory.ts +510 -0
  23. package/apps/client-cms-editor/frontend/src/editor/CmsEditor.tsx +213 -0
  24. package/apps/client-cms-editor/frontend/src/editor/CmsEditorProvider.tsx +20 -0
  25. package/apps/client-cms-editor/frontend/src/editor/canvas/PreviewCanvas.tsx +53 -0
  26. package/apps/client-cms-editor/frontend/src/{CmsEditor.tsx → editor/legacy/CmsEditorPrototype.tsx} +52 -23
  27. package/apps/client-cms-editor/frontend/src/editor/useCmsEditorController.ts +218 -0
  28. package/apps/client-cms-editor/frontend/src/index.ts +19 -5
  29. package/apps/client-cms-editor/frontend/src/lib/agent-host.ts +24 -0
  30. package/apps/client-cms-editor/frontend/src/main.tsx +82 -8
  31. package/apps/client-cms-editor/frontend/src/mount.tsx +92 -30
  32. package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +1 -1
  33. package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +8 -8
  34. package/apps/client-cms-editor/frontend/src/styles/studio.css +55 -3
  35. package/apps/client-cms-editor/frontend/tsconfig.json +12 -1
  36. package/apps/client-cms-editor/frontend/vite.config.ts +12 -0
  37. package/apps/client-cms-editor/package-lock.json +973 -134
  38. package/apps/client-cms-editor/package.json +118 -6
  39. package/apps/client-cms-editor/reference/harvest/HARVEST_RECEIPT.json +201 -0
  40. package/apps/client-cms-editor/reference/harvest/PROVENANCE_HISTORY.txt +10 -0
  41. package/apps/client-cms-editor/reference/harvest/README.md +8 -0
  42. package/apps/client-cms-editor/reference/harvest/plans/ARCHIVE-INTAKE.md +135 -0
  43. package/apps/client-cms-editor/reference/harvest/plans/CHATGPT-IDENTITY-HARVEST.md +83 -0
  44. package/apps/client-cms-editor/reference/harvest/plans/CMS-EDITOR-HARVEST.md +166 -0
  45. package/apps/client-cms-editor/reference/harvest/plans/HARVEST-INDEX.md +196 -0
  46. package/apps/client-cms-editor/reference/harvest/plans/INNERANIMALS-CONTENT-001.md +137 -0
  47. package/apps/client-cms-editor/reference/harvest/plans/NO-IMPLICIT-SIDE-EFFECTS.md +87 -0
  48. package/apps/client-cms-editor/reference/harvest/plans/STOREFRONT-SURFACE-MAP.md +140 -0
  49. package/apps/client-cms-editor/reference/harvest/plans/THEME-INNERANIMALS-HARVEST.md +137 -0
  50. package/apps/client-cms-editor/reference/harvest/plans/TOOLING-LAB.md +63 -0
  51. package/apps/client-cms-editor/reference/harvest/plans/harvest-manifest.json +97 -0
  52. package/apps/client-cms-editor/reference/harvest/plans/local-cms-harvest-schema.sql +328 -0
  53. package/apps/client-cms-editor/shared/cms/package.json +17 -7
  54. package/apps/client-cms-editor/shared/cms/src/adapter.ts +204 -0
  55. package/apps/client-cms-editor/shared/cms/src/agent-context.ts +7 -5
  56. package/apps/client-cms-editor/shared/cms/src/editor-types.ts +32 -0
  57. package/apps/client-cms-editor/shared/cms/src/host.ts +82 -0
  58. package/apps/client-cms-editor/shared/cms/src/index.ts +4 -0
  59. package/apps/client-cms-editor/shared/cms/src/map.ts +115 -0
  60. package/apps/client-cms-editor/shared/cms/src/starter-pack.ts +158 -0
  61. package/contracts/source-types.v1.json +353 -0
  62. package/docs/CMS_CONTEXTUAL_COMPOSER.md +1 -1
  63. package/docs/PRODUCT_LIFECYCLE.md +566 -0
  64. package/docs/REPO_FILE_MAP.txt +132 -0
  65. package/docs/THEME_REFINERY.md +2 -2
  66. package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +40 -20
  67. package/docs/content-studio/REVISION_GATE_2026-09-27.md +1 -1
  68. package/docs/plans/LOCAL_STUDIO_DESKTOP_RELEASE_2026-09-29.md +150 -0
  69. package/migrations/d1/0017_identity_native_oauth.sql +21 -0
  70. package/migrations/d1/0018_goap_control_plane_remaster.sql +40 -0
  71. package/migrations/d1/0019_agentsam_agent_run_plan_todo.sql +14 -0
  72. package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +20 -9
  73. package/migrations/runtime/0002_goap_blackboard_v1.sql +15 -0
  74. package/migrations/runtime/0004_agent_run_plan_linkage.sql +8 -0
  75. package/native/agentsam-machine/Cargo.lock +426 -0
  76. package/native/agentsam-machine/Cargo.toml +9 -0
  77. package/native/agentsam-machine/cli/Cargo.toml +21 -0
  78. package/native/agentsam-machine/cli/README.md +21 -0
  79. package/native/agentsam-machine/cli/src/main.rs +77 -0
  80. package/native/agentsam-machine/core/Cargo.toml +22 -0
  81. package/native/agentsam-machine/core/README.md +14 -0
  82. package/native/agentsam-machine/core/build.rs +33 -0
  83. package/native/agentsam-machine/core/contracts/source-types.v1.json +353 -0
  84. package/native/agentsam-machine/core/src/assets.rs +790 -0
  85. package/native/agentsam-machine/core/src/bound.rs +298 -0
  86. package/native/agentsam-machine/core/src/enrich.rs +706 -0
  87. package/native/agentsam-machine/core/src/frontend.rs +442 -0
  88. package/native/agentsam-machine/core/src/lib.rs +1092 -0
  89. package/native/agentsam-machine/core/src/liquid.rs +528 -0
  90. package/native/agentsam-machine/core/src/source_types.rs +78 -0
  91. package/package.json +64 -24
  92. package/packages/agentsam-brand/README.md +1 -1
  93. package/packages/agentsam-brand/package.json +4 -4
  94. package/packages/agentsam-brand/src/index.js +1 -1
  95. package/packages/agentsam-contracts/package.json +13 -3
  96. package/packages/agentsam-contracts/src/tools.ts +22 -0
  97. package/packages/agentsam-errors/package.json +13 -3
  98. package/packages/agentsam-errors/src/index.js +1 -0
  99. package/packages/agentsam-errors/src/tool.js +56 -0
  100. package/packages/agentsam-errors/test/tool.test.mjs +58 -0
  101. package/packages/agentsam-goap/README.md +52 -0
  102. package/packages/agentsam-goap/package.json +37 -0
  103. package/packages/agentsam-goap/src/adapters/d1-sqlite.js +570 -0
  104. package/packages/agentsam-goap/src/adapters/memory.js +199 -0
  105. package/packages/agentsam-goap/src/contracts.js +226 -0
  106. package/packages/agentsam-goap/src/control-plane.js +112 -0
  107. package/packages/agentsam-goap/src/errors.js +157 -0
  108. package/packages/agentsam-goap/src/index.js +5 -0
  109. package/packages/agentsam-goap/src/world.js +202 -0
  110. package/packages/agentsam-goap/test/goap-control-plane.test.mjs +245 -0
  111. package/packages/agentsam-goap/test/world.test.mjs +79 -0
  112. package/packages/agentsam-knowledge/package.json +18 -4
  113. package/packages/agentsam-knowledge/src/autorag/index.js +10 -3
  114. package/packages/agentsam-knowledge/src/backends/index.js +33 -1
  115. package/packages/agentsam-knowledge/test/autorag.test.mjs +60 -1
  116. package/packages/agentsam-nav/dist/browser.global.js +21 -18
  117. package/packages/agentsam-nav/dist/browser.js +6807 -130
  118. package/packages/agentsam-nav/dist/index.js +6799 -122
  119. package/packages/agentsam-nav/package.json +24 -6
  120. package/packages/agentsam-queue-control/README.md +1 -1
  121. package/packages/agentsam-queue-control/package.json +7 -2
  122. package/packages/agentsam-rapid-rust/src/main.rs +1 -1
  123. package/packages/agentsam-repository/package.json +13 -3
  124. package/packages/agentsam-repository/src/goap.js +13 -14
  125. package/packages/agentsam-repository/src/source-types.js +8 -0
  126. package/packages/agentsam-repository/src/tickets.js +15 -22
  127. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +19 -8
  128. package/packages/agentsam-vault/package.json +14 -4
  129. package/packages/agentsam-workbench/package.json +15 -4
  130. package/packages/agentsam-workbench/src/agent/ToolPermissionRequest.tsx +94 -0
  131. package/packages/agentsam-workbench/src/agent/index.ts +2 -0
  132. package/packages/agentsam-workbench/src/agent/tool-permission.css +134 -0
  133. package/packages/connectors/cloudflare/package.json +15 -3
  134. package/packages/connectors/cloudflare/src/api-client.js +3 -2
  135. package/packages/connectors/cloudflare/src/families/vectorize.js +127 -0
  136. package/packages/connectors/cloudflare/src/index.js +1 -0
  137. package/packages/heuristic-theme/README.md +2 -2
  138. package/packages/heuristic-theme/package.json +8 -3
  139. package/packages/heuristic-theme/src/registry.js +2 -2
  140. package/packages/heuristic-theme/src/theme.js +1 -1
  141. package/packages/heuristic-theme/test/theme.test.mjs +1 -1
  142. package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
  143. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +27 -7
  144. package/packages/identity/README.md +2 -2
  145. package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +18 -15
  146. package/packages/identity/migrations/apply-portable.js +109 -0
  147. package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +1 -1
  148. package/packages/identity/migrations/sqlite/005_identity_company_native.sql +52 -0
  149. package/packages/identity/package.json +27 -6
  150. package/packages/identity/schema/agentsam.identity/manifest.json +101 -0
  151. package/packages/identity/scripts/local-identity-bridge.mjs +13 -7
  152. package/packages/identity/scripts/preview-auth-portal.mjs +6 -6
  153. package/packages/identity/src/adapters/cloudflare-d1/index.js +8 -401
  154. package/packages/identity/src/adapters/iam-compat/index.js +540 -0
  155. package/packages/identity/src/adapters/portable-d1/index.js +18 -0
  156. package/packages/identity/src/adapters/portable-store.js +479 -0
  157. package/packages/identity/src/adapters/sqlite/index.js +13 -312
  158. package/packages/identity/src/contracts/auth-config.js +0 -1
  159. package/packages/identity/src/contracts/identity-store.js +56 -5
  160. package/packages/identity/src/contracts/provider.js +1 -0
  161. package/packages/identity/src/contracts/sign-in-options.js +104 -0
  162. package/packages/identity/src/core/constants.js +1 -1
  163. package/packages/identity/src/core/session-policy.js +31 -0
  164. package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -6
  165. package/packages/identity/src/frontend/auth-portal/pages/reset.html +5 -5
  166. package/packages/identity/src/frontend/auth-portal/pages/signup.html +5 -5
  167. package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
  168. package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +6 -37
  169. package/packages/identity/src/index.js +28 -1
  170. package/packages/identity/src/migrations/README.md +23 -23
  171. package/packages/identity/src/oauth/README.md +1 -1
  172. package/packages/identity/src/oauth/credentials.js +10 -11
  173. package/packages/identity/src/oauth/google-desktop-exchange.js +195 -27
  174. package/packages/identity/src/oauth/iam-platform.js +21 -9
  175. package/packages/identity/src/oauth/native-handoff.js +136 -0
  176. package/packages/identity/src/providers/chatgpt/headers.js +65 -0
  177. package/packages/identity/src/providers/chatgpt/index.js +86 -0
  178. package/packages/identity/src/providers/chatgpt/mapper.js +43 -0
  179. package/packages/identity/src/providers/chatgpt/paths.js +45 -0
  180. package/packages/identity/src/providers/github/oauth.js +1 -2
  181. package/packages/identity/src/providers/github/profile.js +16 -2
  182. package/packages/identity/src/providers/index.js +11 -3
  183. package/packages/identity/src/server/identity-service.js +2 -1
  184. package/packages/identity/src/server/worker-router.js +71 -18
  185. package/packages/identity/tests/chatgpt-provider.test.mjs +75 -0
  186. package/packages/identity/tests/google-desktop-identity-login.test.mjs +210 -0
  187. package/packages/identity/tests/identity-init-scaffold.test.mjs +15 -4
  188. package/packages/identity/tests/lane1-identity-store-parity.test.mjs +527 -0
  189. package/packages/identity/tests/lane1-packed-consumer.test.mjs +175 -0
  190. package/packages/identity/tests/native-oauth-handoff.test.mjs +292 -0
  191. package/packages/identity/tests/oauth-credentials.test.mjs +4 -4
  192. package/packages/identity/tests/preview-auth-portal.test.mjs +4 -2
  193. package/packages/identity/tests/session-routes-policy.test.mjs +13 -1
  194. package/packages/identity/tests/worker-runtime-boundary.test.mjs +11 -0
  195. package/packages/providers/completeful/package.json +7 -2
  196. package/packages/theme-church-site/package.json +17 -6
  197. package/packages/theme-church-site/src/harvest.json +4 -2
  198. package/packages/theme-church-site/src/index.js +7 -3
  199. package/packages/theme-church-site/test/theme.test.mjs +4 -2
  200. package/packages/theme-companions-site/package.json +17 -6
  201. package/packages/theme-companions-site/src/harvest.json +4 -2
  202. package/packages/theme-companions-site/src/index.js +7 -3
  203. package/packages/theme-companions-site/test/theme.test.mjs +4 -2
  204. package/packages/theme-floors-site/package.json +17 -6
  205. package/packages/theme-floors-site/src/harvest.json +4 -2
  206. package/packages/theme-floors-site/src/index.js +7 -3
  207. package/packages/theme-floors-site/test/theme.test.mjs +4 -2
  208. package/packages/theme-fuelnfree-site/package.json +17 -6
  209. package/packages/theme-fuelnfree-site/src/harvest.json +4 -2
  210. package/packages/theme-fuelnfree-site/src/index.js +7 -3
  211. package/packages/theme-fuelnfree-site/test/theme.test.mjs +4 -2
  212. package/packages/theme-handyman-site/package.json +17 -6
  213. package/packages/theme-handyman-site/src/harvest.json +4 -2
  214. package/packages/theme-handyman-site/src/index.js +7 -3
  215. package/packages/theme-handyman-site/test/theme.test.mjs +4 -2
  216. package/packages/theme-insurance-site/package.json +17 -6
  217. package/packages/theme-insurance-site/src/harvest.json +4 -2
  218. package/packages/theme-insurance-site/src/index.js +7 -3
  219. package/packages/theme-insurance-site/test/theme.test.mjs +4 -2
  220. package/packages/theme-scenes/README.md +1 -1
  221. package/packages/theme-scenes/package.json +4 -3
  222. package/packages/theme-scenes/src/registry.js +187 -0
  223. package/packages/theme-shinshu-site/package.json +17 -6
  224. package/packages/theme-shinshu-site/src/harvest.json +4 -2
  225. package/packages/theme-shinshu-site/src/index.js +7 -3
  226. package/packages/theme-shinshu-site/test/theme.test.mjs +4 -2
  227. package/packages/work-graph/package.json +14 -4
  228. package/protocol/FILEMETA_V1.md +2 -2
  229. package/protocol/capabilities/manifest.json +1 -1
  230. package/protocol/database/agentsam.schema-pack.v1.schema.json +72 -0
  231. package/protocol/presets/catalog.json +2 -2
  232. package/protocol/theme-refinery/lineage-registry.json +105 -0
  233. package/protocol/theme-refinery/product-metadata.schema.json +21 -1
  234. package/python/agentsam_sdk/repository/intelligence/discovery.py +27 -2
  235. package/python/agentsam_sdk/repository/intelligence/git.py +4 -0
  236. package/python/tests/test_repository_intelligence.py +30 -0
  237. package/src/cli/command-catalog.js +48 -5
  238. package/src/cli/dispatch.js +1 -0
  239. package/src/cli.js +20 -1
  240. package/src/cloudflare/runtime-status.js +2 -1
  241. package/src/commands/autorag.js +67 -13
  242. package/src/commands/cheat-sheet.js +29 -4
  243. package/src/commands/codebaseindex.js +45 -2
  244. package/src/commands/goap-world.js +134 -0
  245. package/src/commands/goap.js +11 -4
  246. package/src/commands/knowledge.js +59 -2
  247. package/src/commands/machine-binary.js +109 -0
  248. package/src/commands/machine-runtime.js +266 -0
  249. package/src/commands/machine.js +208 -0
  250. package/src/commands/package.js +530 -0
  251. package/src/commands/plan-ledger.js +370 -0
  252. package/src/commands/plan.js +183 -0
  253. package/src/commands/security.js +67 -4
  254. package/src/commands/setup.js +33 -16
  255. package/src/commands/skill.js +78 -17
  256. package/src/commands/status.js +8 -1
  257. package/src/features/resolve.js +1 -0
  258. package/src/knowledge/engine.js +21 -2
  259. package/src/knowledge/runtime-discovery.js +127 -0
  260. package/src/knowledge/source.js +1 -1
  261. package/src/lib/identity-scaffold.js +53 -13
  262. package/src/lib/setup/recipes.js +1 -1
  263. package/src/lib/slash-commands.js +1 -1
  264. package/src/local/runtime-store.js +24 -2
  265. package/src/local/sqlite.js +17 -0
  266. package/src/models/discovery.js +40 -22
  267. package/src/models/inventory-core.d.ts +105 -0
  268. package/src/models/inventory-core.js +54 -6
  269. package/src/sam/operations/package-audit.js +41 -0
  270. package/src/sam/seed.js +2 -0
  271. package/src/security/logs.js +3 -0
  272. package/src/ui/cli/help.js +41 -0
  273. package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +0 -145
  274. package/test/account-session.test.mjs +0 -101
  275. package/test/agent-capabilities.test.mjs +0 -67
  276. package/test/app-authority-context.test.mjs +0 -32
  277. package/test/app-building-skills.test.mjs +0 -61
  278. package/test/apps-scaffold-contract.test.mjs +0 -114
  279. package/test/blender-cad.test.mjs +0 -146
  280. package/test/cad-docker.test.mjs +0 -96
  281. package/test/capabilities.test.mjs +0 -133
  282. package/test/cli/api-key-env-whoami.test.mjs +0 -129
  283. package/test/cli/codebaseindex-plan-ux.test.mjs +0 -37
  284. package/test/cli/eval-live.test.mjs +0 -219
  285. package/test/cli/go.test.mjs +0 -128
  286. package/test/cli/local-vault-and-provider-setup.test.mjs +0 -268
  287. package/test/cli/mcp-client.test.mjs +0 -256
  288. package/test/cli/preferences-runtime.test.mjs +0 -11
  289. package/test/cli/runtime-persist.test.mjs +0 -56
  290. package/test/cli/runtime-ui.test.mjs +0 -141
  291. package/test/cli/rust-command.test.mjs +0 -21
  292. package/test/cli/skill-npm-and-env.test.mjs +0 -52
  293. package/test/cli/status-actions.test.mjs +0 -88
  294. package/test/cli/wireframes-go-registry.test.mjs +0 -139
  295. package/test/cli-preferences.test.mjs +0 -46
  296. package/test/cloudflare-connector.test.mjs +0 -93
  297. package/test/cloudflare-runtime.test.mjs +0 -82
  298. package/test/context.test.mjs +0 -159
  299. package/test/credentials-audit.test.mjs +0 -113
  300. package/test/deploy-health-scan.test.mjs +0 -95
  301. package/test/deploy-receipt.test.mjs +0 -91
  302. package/test/dockerize.test.mjs +0 -93
  303. package/test/error-diagnostics.test.mjs +0 -124
  304. package/test/eval-context.test.mjs +0 -37
  305. package/test/execution-approvals.test.mjs +0 -27
  306. package/test/fixtures/cad/courtyard-house.json +0 -208
  307. package/test/fixtures/knowledge-rpc-worker.mjs +0 -16
  308. package/test/gcloud-auth.test.mjs +0 -111
  309. package/test/go/build-source-identity.test.mjs +0 -31
  310. package/test/go/cloudflare-probe.test.mjs +0 -317
  311. package/test/go/distribution.test.mjs +0 -28
  312. package/test/google-cloud-connection.test.mjs +0 -83
  313. package/test/google-cloud-inventory.test.mjs +0 -64
  314. package/test/indexing-provider.test.mjs +0 -29
  315. package/test/init-options.test.mjs +0 -35
  316. package/test/integration/ai-access-onboarding.test.mjs +0 -47
  317. package/test/integration/app-command.test.mjs +0 -85
  318. package/test/integration/cad-discovery.test.mjs +0 -158
  319. package/test/integration/cad-docker-executor.test.mjs +0 -249
  320. package/test/integration/cad-execution.test.mjs +0 -184
  321. package/test/integration/cad-project-app.test.mjs +0 -31
  322. package/test/integration/cad-project-d1.test.mjs +0 -25
  323. package/test/integration/cad-project-native.test.mjs +0 -24
  324. package/test/integration/cad-project-workflow.test.mjs +0 -9
  325. package/test/integration/cad-project.test.mjs +0 -85
  326. package/test/integration/cli-help.test.mjs +0 -41
  327. package/test/integration/cms-app-scaffold.test.mjs +0 -71
  328. package/test/integration/cms-site-tenancy-contract.test.mjs +0 -257
  329. package/test/integration/codebaseindex-ingest.test.mjs +0 -214
  330. package/test/integration/core-client.integration.test.mjs +0 -55
  331. package/test/integration/error-runtime-rpc.test.mjs +0 -71
  332. package/test/integration/features-resolve.test.mjs +0 -147
  333. package/test/integration/icon-registry.test.mjs +0 -67
  334. package/test/integration/ingest-discover-models.test.mjs +0 -30
  335. package/test/integration/inspect-path-cli.test.mjs +0 -46
  336. package/test/integration/install-script.test.mjs +0 -110
  337. package/test/integration/inventory-core.test.mjs +0 -53
  338. package/test/integration/inventory-evidence.test.mjs +0 -125
  339. package/test/integration/knowledge-rpc.test.mjs +0 -112
  340. package/test/integration/local-fs.test.mjs +0 -113
  341. package/test/integration/merkle-cli.test.mjs +0 -61
  342. package/test/integration/merkle-persistence-identity.test.mjs +0 -48
  343. package/test/integration/plugins-cloudflare.integration.test.mjs +0 -28
  344. package/test/integration/provider-env-cli.test.mjs +0 -50
  345. package/test/integration/provider-factory.test.mjs +0 -197
  346. package/test/integration/repository-company-graph.test.mjs +0 -90
  347. package/test/integration/runtime-migrations.test.mjs +0 -87
  348. package/test/integration/runtime-status.integration.test.mjs +0 -212
  349. package/test/integration/sam-activity-recovery.test.mjs +0 -147
  350. package/test/integration/sam-decision.test.mjs +0 -584
  351. package/test/integration/sam-kernel.test.mjs +0 -99
  352. package/test/integration/sam-planning-astar.test.mjs +0 -279
  353. package/test/integration/scaffold-cloudflare.test.mjs +0 -46
  354. package/test/integration/skill-runtime.test.mjs +0 -240
  355. package/test/integration/storage-architecture.test.mjs +0 -154
  356. package/test/integration/store-discovery.test.mjs +0 -44
  357. package/test/integration/studio-fs-pty-e2e.test.mjs +0 -294
  358. package/test/integration/terminal-exec.integration.test.mjs +0 -86
  359. package/test/integration/tool-runtime.test.mjs +0 -124
  360. package/test/integration/tool-schema.test.mjs +0 -59
  361. package/test/jr-dev-skill.test.mjs +0 -26
  362. package/test/knowledge-context-pack.test.mjs +0 -19
  363. package/test/knowledge-postgres.test.mjs +0 -40
  364. package/test/knowledge-service.test.mjs +0 -110
  365. package/test/knowledge.test.mjs +0 -206
  366. package/test/live/terminal-transport.live.test.mjs +0 -24
  367. package/test/local-sessions.test.mjs +0 -57
  368. package/test/local-studio-deploy.test.mjs +0 -83
  369. package/test/loopback-oauth.test.mjs +0 -53
  370. package/test/merkle-render.test.mjs +0 -31
  371. package/test/mini.test.mjs +0 -140
  372. package/test/model-catalog.test.mjs +0 -70
  373. package/test/models.test.mjs +0 -309
  374. package/test/npm10-lock.test.mjs +0 -29
  375. package/test/ollama.test.mjs +0 -137
  376. package/test/open-url.test.mjs +0 -64
  377. package/test/openai-responses.test.mjs +0 -155
  378. package/test/portable-context.test.mjs +0 -94
  379. package/test/project-config.test.mjs +0 -81
  380. package/test/project-rules.test.mjs +0 -44
  381. package/test/provider-credentials.test.mjs +0 -106
  382. package/test/rehydrate.test.mjs +0 -25
  383. package/test/release-hygiene.test.mjs +0 -42
  384. package/test/repository-snapshot-view.test.mjs +0 -112
  385. package/test/responses-runner.test.mjs +0 -465
  386. package/test/runtime-activity.test.mjs +0 -98
  387. package/test/sdk-worker-contract.test.mjs +0 -72
  388. package/test/security.test.mjs +0 -252
  389. package/test/setup-planner.test.mjs +0 -74
  390. package/test/setup-runtime.test.mjs +0 -51
  391. package/test/shell.test.mjs +0 -281
  392. package/test/skills.test.mjs +0 -22
  393. package/test/smoke.mjs +0 -122
  394. package/test/telemetry.test.mjs +0 -79
  395. package/test/terminal/local-pty.mock.test.mjs +0 -153
  396. package/test/terminal-machine-identity.test.mjs +0 -88
  397. package/test/theme-portability.test.mjs +0 -14
  398. package/test/tools-search.test.mjs +0 -73
  399. package/test/unit/website-assets-bindings.test.mjs +0 -60
  400. package/test/whoami-resume.test.mjs +0 -157
@@ -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
- });