@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,31 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import fs from 'node:fs';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import {spawn} from 'node:child_process';
7
- import {localProjectRuntime} from '../../src/lib/cad/project-cli.js';
8
- test('packaged app API shares CLI revisions, emits events and rejects stale writes',{skip:process.env.AGENTSAM_TEST_CAD_APP!=='1'},async t=>{
9
- const root=fs.mkdtempSync(path.join(os.tmpdir(),'cad-app-proof-')),port=31987;
10
- const app=new URL('../../apps/cad-creator/backend/',import.meta.url);
11
- const child=spawn(process.execPath,['dist/server.mjs'],{cwd:app,env:{...process.env,NODE_ENV:'production',PORT:String(port),HOST:'127.0.0.1',AGENTSAM_CAD_PROJECT_ROOT:root},stdio:['ignore','pipe','pipe']});
12
- let log='';child.stdout.on('data',d=>log+=d);child.stderr.on('data',d=>log+=d);
13
- t.after(()=>{child.kill();fs.rmSync(root,{recursive:true,force:true});});
14
- const base='http://127.0.0.1:'+port;
15
- let ready=false;
16
- for(let i=0;i<80;i++){try{const r=await fetch(base);if(r.ok){ready=true;break;}}catch{}await new Promise(r=>setTimeout(r,100));}
17
- assert.ok(ready,log);
18
- async function call(name,input){const res=await fetch(base+'/api/cad/project/tools/'+name,{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(input)});return {status:res.status,body:await res.json()};}
19
- const project=JSON.parse(fs.readFileSync(new URL('../fixtures/cad/courtyard-house.json',import.meta.url),'utf8'));
20
- const saved=await call('design_project_save',{project,expected_revision:0});assert.equal(saved.status,200);
21
- const runtime=localProjectRuntime(root);assert.equal((await runtime.execute('design_project_get',{project_id:project.id})).content_hash,saved.body.result.content_hash);
22
- const abort=new AbortController();t.after(()=>abort.abort());
23
- const events=await fetch(base+'/api/cad/project/events',{signal:abort.signal});const reader=events.body.getReader();
24
- const edited=await runtime.execute('design_apply_operation',{project_id:project.id,expected_revision:1,operation:{type:'update_wall',wallId:'wall-0',updates:{height3D:132}}});
25
- const event=await Promise.race([reader.read(),new Promise((_,reject)=>setTimeout(()=>reject(new Error('event timeout')),5000))]);
26
- assert.match(new TextDecoder().decode(event.value),/"revision":2/);
27
- const reopened=await call('design_project_get',{project_id:project.id,expected_content_hash:edited.content_hash});assert.equal(reopened.body.result.revision,2);
28
- assert.equal((await call('design_project_save',{project,expected_revision:1})).status,409);
29
- const denied=await fetch(base+'/api/cad/project/tools/design_project_get',{method:'POST',headers:{'content-type':'application/json',origin:'https://other.example'},body:JSON.stringify({project_id:project.id})});assert.equal(denied.status,403);
30
- abort.abort();
31
- });
@@ -1,25 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import fs from 'node:fs';
4
- import {DatabaseSync} from 'node:sqlite';
5
- import {D1ProjectStore} from '../../src/lib/cad/d1-project-store.js';
6
- const schema="CREATE TABLE designstudio_design_blueprints (\n id TEXT PRIMARY KEY DEFAULT ('dsb_' || lower(hex(randomblob(8)))),\n\n tenant_id TEXT NOT NULL DEFAULT 'tenant_inneranimalmedia',\n workspace_id TEXT NOT NULL DEFAULT 'ws_inneranimalmedia',\n project_id TEXT,\n\n title TEXT NOT NULL,\n description TEXT,\n original_prompt TEXT,\n\n intent_json TEXT NOT NULL DEFAULT '{}',\n\n cad_script TEXT,\n cad_engine TEXT DEFAULT 'openscad',\n\n sketch_json TEXT DEFAULT '{}',\n preview_image_url TEXT,\n\n generation_config_json TEXT DEFAULT '{}',\n\n latest_asset_id TEXT,\n latest_run_id TEXT,\n\n status TEXT NOT NULL DEFAULT 'draft'\n CHECK (status IN (\n 'draft',\n 'structured',\n 'generated',\n 'validated',\n 'exported',\n 'failed'\n )),\n\n quality_score REAL DEFAULT 0,\n success_rate REAL DEFAULT 0,\n\n tags TEXT DEFAULT '[]',\n notes TEXT,\n\n total_tokens INTEGER DEFAULT 0,\n total_cost_usd REAL DEFAULT 0,\n avg_latency_ms REAL DEFAULT 0,\n\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n, preview_svg_url TEXT);\nCREATE TABLE \"scene_snapshots\" (\n id TEXT PRIMARY KEY DEFAULT ('scene_' || lower(hex(randomblob(8)))),\n workspace_id TEXT NOT NULL,\n user_id TEXT NOT NULL,\n tenant_id TEXT NOT NULL DEFAULT 'tenant_sam_primeaux',\n name TEXT NOT NULL DEFAULT 'Untitled Scene',\n project_type TEXT NOT NULL DEFAULT 'SANDBOX',\n entity_count INTEGER NOT NULL DEFAULT 0,\n r2_key TEXT NOT NULL,\n r2_bucket TEXT NOT NULL DEFAULT 'inneranimalmedia',\n public_url TEXT,\n thumbnail_r2_key TEXT,\n thumbnail_url TEXT,\n tags TEXT DEFAULT '[]',\n description TEXT,\n is_autosave INTEGER NOT NULL DEFAULT 0,\n version INTEGER NOT NULL DEFAULT 1,\n created_at INTEGER NOT NULL DEFAULT (unixepoch()),\n updated_at INTEGER NOT NULL DEFAULT (unixepoch())\n, project_id TEXT, glb_r2_key TEXT, style_preset TEXT, voxel_count INTEGER, cad_job_id TEXT);";
7
- const project=JSON.parse(fs.readFileSync(new URL('../fixtures/cad/courtyard-house.json',import.meta.url),'utf8'));
8
- test('existing D1 tables support scoped immutable revisions and optimistic concurrency',async t=>{
9
- const sqlite=new DatabaseSync(':memory:');t.after(()=>sqlite.close());sqlite.exec(schema);
10
- const db={prepare(sql){return {bind(...params){return {sql,params,async first(){return sqlite.prepare(sql).get(...params)||null;}};}};},
11
- async batch(statements){sqlite.exec('BEGIN');try{const results=statements.map(s=>({meta:{changes:Number(sqlite.prepare(s.sql).run(...s.params).changes)}}));sqlite.exec('COMMIT');return results;}catch(e){sqlite.exec('ROLLBACK');throw e;}}};
12
- const blobs=new Map(),objects={async put(k,v){blobs.set(k,v);},async get(k){return blobs.has(k)?{async text(){return blobs.get(k);}}:null;}};
13
- const scope={account_id:'test-owner',workspace_id:'test-workspace',tenant_id:'test-tenant'};
14
- const store=new D1ProjectStore({db,objects,bucket:'test-bucket',scope});
15
- await store.save(project,0);
16
- await store.save({...project,name:'Revision two'},1);
17
- await assert.rejects(store.save(project,1),/revision_conflict/);
18
- assert.equal(sqlite.prepare('SELECT count(*) n FROM scene_snapshots').get().n,2);
19
- assert.equal((await store.read(project.id,1)).project.name,project.name);
20
- assert.equal((await store.restore(project.id,1,2)).revision,3);
21
- const other=new D1ProjectStore({db,objects,bucket:'test-bucket',scope:{...scope,account_id:'other'}});
22
- await assert.rejects(other.read(project.id),/project_not_found/);
23
- await assert.rejects(other.save(project,3),/revision_conflict/);
24
- assert.equal((await store.read(project.id)).revision,3);
25
- });
@@ -1,24 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import fs from 'node:fs';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import {localProjectRuntime} from '../../src/lib/cad/project-cli.js';
7
- const enabled=process.env.AGENTSAM_TEST_NATIVE_CAD==='1';
8
- test('courtyard real build inspect export render and restored revision rebuild',{skip:!enabled&&'Set AGENTSAM_TEST_NATIVE_CAD=1; enabled runs must find Blender'},async t=>{
9
- const root=process.env.AGENTSAM_CAD_TEST_OUTPUT||fs.mkdtempSync(path.join(os.tmpdir(),'cad-house-native-'));
10
- if(!process.env.AGENTSAM_CAD_TEST_OUTPUT)t.after(()=>fs.rmSync(root,{recursive:true,force:true}));
11
- const p=JSON.parse(fs.readFileSync(new URL('../fixtures/cad/courtyard-house.json',import.meta.url),'utf8'));
12
- p.id='courtyard-'+Date.now();
13
- const run=localProjectRuntime(root),saved=await run.execute('design_project_save',{project:p,expected_revision:0});
14
- const input={project_id:p.id,revision:saved.revision};
15
- const build=await run.execute('design_model_build',input);assert.ok(build.artifact.size_bytes>0);
16
- const inspection=await run.execute('design_model_inspect',input);assert.ok(inspection.ok);
17
- const glb=await run.execute('design_model_export',{...input,format:'glb'});assert.equal(fs.readFileSync(glb.artifact.path).subarray(0,4).toString(),'glTF');
18
- const png=await run.execute('design_model_render',input);assert.equal(fs.readFileSync(png.artifact.path).subarray(1,4).toString(),'PNG');
19
- const edited=await run.execute('design_apply_operation',{project_id:p.id,expected_revision:1,operation:{type:'update_wall',wallId:'wall-0',updates:{height3D:132}}});
20
- assert.equal(edited.revision,2);
21
- const restored=await run.execute('design_project_restore',{project_id:p.id,revision:1,expected_revision:2});assert.equal(restored.project.walls[0].height3D,120);
22
- await run.execute('design_model_build',{project_id:p.id,revision:3});
23
- console.log(JSON.stringify({root,project_id:p.id,build:build.artifact,glb:glb.artifact,png:png.artifact,restored_revision:3}));
24
- });
@@ -1,9 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import {runProjectWorkflow} from '../../src/lib/cad/project-workflows.js';
4
- test('workflow halts on invalid validation and records no claimed effects',async()=>{
5
- let calls=0;await assert.rejects(runProjectWorkflow({execute:async()=>{calls++;return {valid:false,errors:['bad wall']};}},'cad.house_baseline',{project:{}}),/project_invalid/);assert.equal(calls,1);
6
- });
7
- test('edit workflow refuses stale expected revision before edit',async()=>{
8
- const calls=[];await assert.rejects(runProjectWorkflow({execute:async(name)=>{calls.push(name);return {revision:2,project:{id:'p'}};}},'cad.edit_preview',{project_id:'p',expected_revision:1,operation:{}}),/revision_conflict/);assert.deepEqual(calls,['design_project_get']);
9
- });
@@ -1,85 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import fs from 'node:fs';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import {validateProject,applyProjectOperation} from '../../src/lib/cad/project-contract.js';
7
- import {FileProjectStore} from '../../src/lib/cad/project-store.js';
8
- import {createProjectRuntime} from '../../src/lib/cad/project-runtime.js';
9
- import {localProjectRuntime} from '../../src/lib/cad/project-cli.js';
10
- import {projectToBlenderRecipe} from '../../src/lib/cad/project-recipe.js';
11
- import {createCapabilityAdapter} from '../../src/agent/capability-adapter.js';
12
- const project=JSON.parse(fs.readFileSync(new URL('../fixtures/cad/courtyard-house.json',import.meta.url),'utf8'));
13
- test('invalid references and non-finite geometry fail before mutation',()=>{
14
- const p=structuredClone(project);p.walls[0].x1=Infinity;assert.equal(validateProject(p).valid,false);
15
- p.walls[0].x1=0;p.doors[0].wallId='missing';assert.equal(validateProject(p).valid,false);
16
- assert.equal(validateProject({...p,walls:{}}).valid,false);
17
- });
18
- test('batch is atomic, absent targets fail, and host deletion cascades',()=>{
19
- const before=JSON.stringify(project);
20
- assert.throws(()=>applyProjectOperation(project,{type:'batch_operations',operations:[{type:'delete_wall',wallId:'wall-4'},{type:'update_wall',wallId:'absent',updates:{height3D:96}}]}),/element_not_found/);
21
- assert.equal(JSON.stringify(project),before);
22
- assert.equal(applyProjectOperation(project,{type:'delete_wall',wallId:'wall-4'}).doors.length,0);
23
- });
24
- test('save reopen restore and stale revision checks preserve immutable snapshots',async t=>{
25
- const dir=fs.mkdtempSync(path.join(os.tmpdir(),'cad-project-'));t.after(()=>fs.rmSync(dir,{recursive:true,force:true}));
26
- const store=new FileProjectStore(dir);
27
- await store.save(project,0);
28
- const next=applyProjectOperation(project,{type:'update_wall',wallId:'wall-0',updates:{height3D:132}});
29
- await store.save(next,1);
30
- await assert.rejects(store.save(project,1),/revision_conflict/);
31
- const restored=await new FileProjectStore(dir).restore(project.id,1,2);
32
- assert.equal(restored.revision,3);assert.equal(restored.project.walls[0].height3D,120);assert.equal((await store.read(project.id,2)).project.walls[0].height3D,132);
33
- });
34
- test('native recipe converts inches to metres and preserves a real door gap',()=>{
35
- const recipe=projectToBlenderRecipe(project);
36
- assert.equal(recipe.operations.find(o=>o.name==='wall-0:0').scale[0],864*0.0254);
37
- const pieces=recipe.operations.filter(o=>o.name?.startsWith('wall-4:'));
38
- assert.equal(pieces.length,3);
39
- assert.throws(()=>projectToBlenderRecipe({...project,roofType:'gable'}),/roof_geometry_not_supported/);
40
- });
41
- test('agent and runtime share executable CAD handlers',async t=>{
42
- const root=fs.mkdtempSync(path.join(os.tmpdir(),'cad-agent-'));t.after(()=>fs.rmSync(root,{recursive:true,force:true}));
43
- const adapter=createCapabilityAdapter({projectRoot:root});
44
- assert.ok(adapter.toolDescriptors().some(t=>t.name==='design_project_save'));
45
- await adapter.invoke('design_project_save',{project,expected_revision:0});
46
- const result=await adapter.invoke('design_apply_operation',{project_id:project.id,expected_revision:1,operation:{type:'update_wall',wallId:'wall-0',updates:{height3D:132}}});
47
- assert.equal(result.result.revision,2);
48
- });
49
-
50
-
51
- test('CAD registry projects the app into tools workflows and CLI graph relationships',()=>{
52
- const manifest=JSON.parse(fs.readFileSync(new URL('../../registry/cad-project/manifest.json',import.meta.url),'utf8'));
53
- const migration=fs.readFileSync(new URL('../../registry/cad-project/migration.sql',import.meta.url),'utf8');
54
- assert.equal(manifest.product.app_id,'cad-creator');
55
- assert.equal(manifest.product.slug,'cad-creator');
56
- assert.deepEqual(manifest.product.capability_keys,['design.read','design.write','design.export']);
57
- assert.equal(manifest.product.cli_commands[0].id,'agentsam:cad:project');
58
- assert.equal(manifest.tools.length,9);
59
- assert.equal(manifest.workflows.length,2);
60
- assert.match(migration,/WHERE slug='cad-creator'/);
61
- assert.match(migration,/WHERE slug='agentsam-cad-creator'/);
62
- assert.match(migration,/legacy_slug','agentsam-cad-creator/);
63
- assert.equal((migration.match(/'exposes_tool'/g)||[]).length,9);
64
- assert.equal((migration.match(/'provides_workflow'/g)||[]).length,2);
65
- assert.equal((migration.match(/'exposes_command'/g)||[]).length,1);
66
- assert.match(migration,/'cli_command','agentsam:cad:project'/);
67
- assert.match(migration,/ON CONFLICT\(id\) DO UPDATE SET tool_name=excluded\.tool_name/);
68
- assert.doesNotMatch(migration,/DO UPDATE SET[^;]*is_active=excluded\.is_active/);
69
- assert.doesNotMatch(migration,/DO UPDATE SET[^;]*lifecycle=excluded\.lifecycle/);
70
-
71
- });
72
-
73
-
74
- test('CAD validate requires project or project_id and model-facing CAD tools declare non-strict rich payloads',async()=>{
75
- const root=fs.mkdtempSync(path.join(os.tmpdir(),'cad-validate-source-'));
76
- const runtime=localProjectRuntime(root);
77
- await assert.rejects(()=>runtime.execute('design_project_validate',{}),/argument_required:project_or_project_id/);
78
- const adapter=createCapabilityAdapter({projectRoot:root});
79
- const save=adapter.toolDescriptors().find(t=>t.name==='design_project_save');
80
- const edit=adapter.toolDescriptors().find(t=>t.name==='design_apply_operation');
81
- assert.equal(save.strict,false);
82
- assert.equal(edit.strict,false);
83
- assert.equal(save.input_schema.properties.project.additionalProperties,true);
84
- assert.equal(edit.input_schema.properties.operation.additionalProperties,true);
85
- });
@@ -1,41 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import path from 'node:path';
3
- import { spawnSync } from 'node:child_process';
4
- import test from 'node:test';
5
-
6
- const repoRoot = path.resolve(new URL('../..', import.meta.url).pathname);
7
-
8
- function run(...args) {
9
- return spawnSync(process.execPath, ['src/cli.js', ...args], { cwd: repoRoot, encoding: 'utf8' });
10
- }
11
-
12
- test('agentsam help is concise, topic-aware, and deterministic outside a TTY', () => {
13
- const help = run('help');
14
- assert.equal(help.status, 0, help.stderr);
15
- assert.doesNotMatch(help.stderr, /Unknown command/);
16
- assert.match(help.stdout, /Agent Sam/);
17
- assert.match(help.stdout, /SAM = Systematic Autonomous Machinery/);
18
- assert.match(help.stdout, /agentsam help <topic>/);
19
- assert.match(help.stdout, /press \/ for the command picker/i);
20
- assert.doesNotMatch(help.stdout, /Inspect options:/);
21
-
22
- const topic = run('help', 'runtime');
23
- assert.equal(topic.status, 0, topic.stderr);
24
- assert.match(topic.stdout, /Runtime \/ terminal/);
25
- assert.match(topic.stdout, /agentsam connections/);
26
- assert.match(topic.stdout, /agentsam deploy/);
27
-
28
- const all = run('help', '--all');
29
- assert.equal(all.status, 0, all.stderr);
30
- assert.match(all.stdout, /Build \/ inspect/);
31
- assert.match(all.stdout, /Create \/ extend/);
32
-
33
- const allAlias = run('help', 'all');
34
- assert.equal(allAlias.status, 0, allAlias.stderr);
35
- assert.equal(allAlias.stdout, all.stdout);
36
-
37
- const flag = run('--help');
38
- assert.equal(flag.status, 0, flag.stderr);
39
- assert.match(flag.stdout, /agentsam help <topic>/);
40
- assert.doesNotMatch(flag.stdout, /Inspect options:/);
41
- });
@@ -1,71 +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 { execFileSync } from 'node:child_process';
7
- import { fileURLToPath } from 'node:url';
8
-
9
- const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
10
- const cmsBin = path.join(root, 'apps/client-cms-editor/bin/agentsam-cms.mjs');
11
-
12
- function scaffold(persistence) {
13
- const temp = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-cms-scaffold-'));
14
- const target = path.join(temp, 'editor');
15
- execFileSync(process.execPath, [
16
- cmsBin,
17
- 'scaffold',
18
- target,
19
- '--persistence',
20
- persistence,
21
- ], { cwd: root, stdio: 'pipe' });
22
- return { temp, target };
23
- }
24
-
25
- test('CMS editor scaffold is self-contained and records SQLite authority', () => {
26
- const { temp, target } = scaffold('sqlite');
27
- try {
28
- assert.equal(fs.existsSync(path.join(target, 'bin/agentsam-cms.mjs')), true);
29
- assert.equal(fs.existsSync(path.join(target, 'agentsam.app.json')), true);
30
- assert.equal(fs.existsSync(path.join(target, 'packages/agentsam-contracts/package.json')), true);
31
- assert.equal(fs.existsSync(path.join(target, 'packages/agentsam-workbench/package.json')), true);
32
-
33
- const rootPkg = JSON.parse(fs.readFileSync(path.join(target, 'package.json'), 'utf8'));
34
- assert.ok(rootPkg.workspaces.includes('packages/*'));
35
-
36
- const frontendPkg = JSON.parse(fs.readFileSync(path.join(target, 'frontend/package.json'), 'utf8'));
37
- assert.equal(frontendPkg.dependencies['@inneranimalmedia/agentsam-contracts'], '0.1.0');
38
- assert.equal(frontendPkg.dependencies['@inneranimalmedia/agentsam-workbench'], '0.1.0');
39
-
40
- const sharedPkg = JSON.parse(fs.readFileSync(path.join(target, 'shared/cms/package.json'), 'utf8'));
41
- assert.equal(sharedPkg.dependencies['@inneranimalmedia/agentsam-contracts'], '0.1.0');
42
-
43
- const escaped = [
44
- ...Object.values(frontendPkg.dependencies || {}),
45
- ...Object.values(sharedPkg.dependencies || {}),
46
- ].filter((value) => String(value).startsWith('file:'));
47
- assert.deepEqual(escaped, []);
48
-
49
- const runtime = JSON.parse(fs.readFileSync(path.join(target, '.agentsam/cms-runtime.json'), 'utf8'));
50
- assert.equal(runtime.schema, 'agentsam.cms.runtime.v1');
51
- assert.equal(runtime.app_id, 'client-cms-editor');
52
- assert.equal(runtime.authority, 'sqlite');
53
- assert.equal(runtime.cache, 'localStorage');
54
- assert.equal(runtime.cache_only, false);
55
- } finally {
56
- fs.rmSync(temp, { recursive: true, force: true });
57
- }
58
- });
59
-
60
- test('CMS editor localStorage option is explicitly cache-only', () => {
61
- const { temp, target } = scaffold('localStorage');
62
- try {
63
- const runtime = JSON.parse(fs.readFileSync(path.join(target, '.agentsam/cms-runtime.json'), 'utf8'));
64
- assert.equal(runtime.authority, null);
65
- assert.equal(runtime.cache, 'localStorage');
66
- assert.equal(runtime.cache_only, true);
67
- assert.match(runtime.note, /cache only/i);
68
- } finally {
69
- fs.rmSync(temp, { recursive: true, force: true });
70
- }
71
- });
@@ -1,257 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import test from 'node:test';
5
- import { fileURLToPath } from 'node:url';
6
- import { assertProjectSlug, createCmsDbClient } from '../../apps/local-studio/backend/worker/cms-db.js';
7
- import { injectSitePartials, fetchSitePartial, putSitePartial } from '../../apps/local-studio/backend/worker/site-partials.js';
8
-
9
- const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
10
- const at = (...parts) => path.join(root, ...parts);
11
- const read = (...parts) => fs.readFileSync(at(...parts), 'utf8');
12
-
13
- test('CMS D1 query helper strictly enforces projectSlug tenancy invariant', () => {
14
- // Empty or invalid projectSlug must throw immediately
15
- assert.throws(() => assertProjectSlug(''), /CMS Tenancy Invariant Violation/);
16
- assert.throws(() => assertProjectSlug(' '), /CMS Tenancy Invariant Violation/);
17
- assert.throws(() => assertProjectSlug(null), /CMS Tenancy Invariant Violation/);
18
- assert.throws(() => assertProjectSlug(undefined), /CMS Tenancy Invariant Violation/);
19
- assert.throws(() => createCmsDbClient({}, ''), /CMS Tenancy Invariant Violation/);
20
-
21
- assert.equal(assertProjectSlug('agentsam-sdk'), 'agentsam-sdk');
22
- });
23
-
24
- test('CMS D1 queries all enforce project-scoped tenancy without cross-tenant leaks', async () => {
25
- const capturedQueries = [];
26
- const mockDb = {
27
- prepare(query) {
28
- return {
29
- bind(...args) {
30
- capturedQueries.push({ query, args });
31
- return {
32
- async all() {
33
- if (query.includes('FROM cms_pages WHERE project_slug = ?')) {
34
- return { results: [{ id: 'page_test', project_slug: 'agentsam-sdk', title: 'Test' }] };
35
- }
36
- if (query.includes('FROM cms_pages WHERE id = ? AND project_slug = ?')) {
37
- return { results: [{ id: args[0], project_slug: 'agentsam-sdk', title: 'Test' }] };
38
- }
39
- if (query.includes('SELECT s.id FROM cms_page_sections s')) {
40
- return { results: [{ id: 'sec_test' }] };
41
- }
42
- if (query.includes('SELECT b.* FROM cms_section_components b')) {
43
- return { results: [{ id: 'blk_test', component_type: 'card', component_data: '{}' }] };
44
- }
45
- if (query.includes('SELECT s.* FROM cms_page_sections s')) {
46
- return { results: [{ id: 'sec_test', section_name: 'Test', section_data: '{}' }] };
47
- }
48
- return { results: [] };
49
- },
50
- async run() {
51
- return { success: true };
52
- },
53
- };
54
- },
55
- };
56
- },
57
- };
58
-
59
- const client = createCmsDbClient(mockDb, 'agentsam-sdk');
60
-
61
- await client.getProject();
62
- await client.getPages();
63
- await client.getPageById('page_123');
64
- await client.getSectionsForPage('page_123');
65
- await client.getAllSectionsForSite();
66
- await client.getAllBlocksForSite();
67
- await client.getBlocksForSection('sec_123');
68
- await client.getThemeOverrides();
69
- await client.getLiquidImports();
70
- await client.getActivity();
71
- await client.getTemplates();
72
-
73
- // Audit every captured query
74
- for (const { query, args } of capturedQueries) {
75
- const hasProjectSlugConstraint =
76
- query.includes('project_slug') ||
77
- query.includes('iam_project_slug') ||
78
- query.includes('project_id') ||
79
- query.includes('projects WHERE id = ?');
80
- assert.ok(
81
- hasProjectSlugConstraint,
82
- `Query must enforce project scoping: ${query}`,
83
- );
84
- assert.ok(
85
- args.some((arg) => typeof arg === 'string' && (arg.includes('agentsam-sdk') || arg.includes('agentsam_sdk'))),
86
- `Args must bind project slug: ${JSON.stringify(args)} for ${query}`,
87
- );
88
- }
89
- });
90
-
91
- test('Local Studio package.json explicitly declares client-cms-editor dependencies', () => {
92
- const pkgPath = at('apps', 'local-studio', 'frontend', 'package.json');
93
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
94
-
95
- assert.ok(pkg.dependencies['@inneranimalmedia/agentsam-cms-frontend'], 'missing @inneranimalmedia/agentsam-cms-frontend');
96
- assert.ok(pkg.dependencies['@inneranimalmedia/agentsam-cms-backend'], 'missing @inneranimalmedia/agentsam-cms-backend');
97
- assert.ok(pkg.dependencies['@inneranimalmedia/agentsam-cms-shared'], 'missing @inneranimalmedia/agentsam-cms-shared');
98
-
99
- assert.equal(pkg.dependencies['@inneranimalmedia/agentsam-cms-frontend'], 'file:../../client-cms-editor/frontend');
100
- assert.equal(pkg.dependencies['@inneranimalmedia/agentsam-cms-backend'], 'file:../../client-cms-editor/backend');
101
- assert.equal(pkg.dependencies['@inneranimalmedia/agentsam-cms-shared'], 'file:../../client-cms-editor/shared/cms');
102
- });
103
-
104
- test('Local Studio mounts CMS route with default site agentsam-sdk', () => {
105
- assert.ok(fs.existsSync(at('apps', 'local-studio', 'frontend', 'src', 'routes', '_app', 'cms.tsx')));
106
- const routeContent = read('apps', 'local-studio', 'frontend', 'src', 'routes', '_app', 'cms.tsx');
107
-
108
- // Must default to agentsam-sdk
109
- assert.match(routeContent, /"agentsam-sdk"/);
110
- assert.doesNotMatch(routeContent, /default\s*:\s*["']inneranimalmedia["']/);
111
-
112
- // Must use same-origin relative basePath
113
- assert.match(routeContent, /basePath="\/cms"/);
114
-
115
- // NavRail must include CMS entry
116
- const navRail = read('apps', 'local-studio', 'frontend', 'src', 'components', 'shell', 'nav-rail.tsx');
117
- assert.match(navRail, /to:\s*"\/cms"/);
118
- assert.match(navRail, /label:\s*"CMS"/);
119
- });
120
-
121
- test('Local Studio Worker dispatches /api/cms/* with strict tenant isolation', () => {
122
- const workerContent = read('apps', 'local-studio', 'backend', 'worker', 'index.js');
123
- assert.match(workerContent, /url\.pathname\.startsWith\("\/api\/cms\/"\)/);
124
- assert.match(workerContent, /handleCmsWorkerRequest/);
125
-
126
- const cmsService = read('apps', 'local-studio', 'backend', 'worker', 'cms-service.js');
127
- // Worker requests must name their tenant explicitly; the UI may choose its own default.
128
- assert.match(cmsService, /site_slug_required/);
129
- assert.doesNotMatch(cmsService, /['"]agentsam-sdk['"]/);
130
- assert.match(cmsService, /createCmsDbClient\(env\.DB,\s*siteSlug\)/);
131
- });
132
-
133
- test('homepage.html is decomposed into reusable site partials with relative links and edge injection markers', () => {
134
- assert.ok(fs.existsSync(at('sites', 'agentsam-sdk', 'partials', 'header.html')));
135
- assert.ok(fs.existsSync(at('sites', 'agentsam-sdk', 'partials', 'footer.html')));
136
- assert.ok(fs.existsSync(at('apps', 'frontend', 'public', 'site', 'global', 'asbd-header.html')));
137
- assert.ok(fs.existsSync(at('apps', 'frontend', 'public', 'site', 'global', 'asbd-footer.html')));
138
-
139
- const header = read('sites', 'agentsam-sdk', 'partials', 'header.html');
140
- const footer = read('sites', 'agentsam-sdk', 'partials', 'footer.html');
141
- const homepage = read('apps', 'frontend', 'public', 'site', 'homepage.html');
142
-
143
- // Header and footer are non-empty
144
- assert.ok(header.length > 500, 'header.html must contain full header content');
145
- assert.ok(footer.length > 500, 'footer.html must contain full footer content');
146
-
147
- // AgentSam public header navigation is relative and product-specific (R2 partial SSOT).
148
- assert.match(header, /href="\/"/);
149
- assert.match(header, /href="\/learn\/"/);
150
- assert.match(header, /href="\/themes\/"/);
151
- assert.match(header, /href="\/packages\/sdk\/help\/"/);
152
- assert.match(header, /href="\/auth\/login\?next=\/agentsam"/);
153
- assert.doesNotMatch(header, /href="https:\/\/inneranimalmedia\.com\/(learn|themes|packages\/sdk|agentsam)"/);
154
-
155
- assert.match(footer, /href="\/work"/);
156
- assert.match(footer, /href="\/about"/);
157
- assert.match(footer, /href="\/services"/);
158
- assert.match(footer, /href="\/contact"/);
159
- assert.match(footer, /href="\/privacy"/);
160
- assert.match(footer, /href="\/terms"/);
161
- assert.match(footer, /href="\/sitemap"/);
162
- assert.doesNotMatch(footer, /href="https:\/\/inneranimalmedia\.com\/(work|about|services|contact|privacy|terms|sitemap)"/);
163
-
164
- // Public homepage shell uses ASBD mounts + client inject of global partials
165
- // (R2 sites/{site}/partials remain the publish/edge SSOT via publish-website-assets).
166
- assert.match(homepage, /id="asbd-header-mount"/);
167
- assert.match(homepage, /id="asbd-footer-mount"/);
168
- assert.match(homepage, /inject\('asbd-header-mount',\s*'\/site\/global\/asbd-header\.html'\)/);
169
- assert.match(homepage, /inject\('asbd-footer-mount',\s*'\/site\/global\/asbd-footer\.html'\)/);
170
- assert.doesNotMatch(homepage, /<nav class="iam-sidenav" id="iamSidenav"/, 'inline sidenav should be in partials');
171
- });
172
-
173
- function r2Stub(store = new Map()) {
174
- return {
175
- async get(key) {
176
- if (!store.has(key)) return null;
177
- return { text: async () => store.get(key) };
178
- },
179
- async put(key, content) {
180
- store.set(key, typeof content === 'string' ? content : String(content));
181
- return { key };
182
- },
183
- async head() {
184
- return null;
185
- },
186
- async list() {
187
- return { objects: [] };
188
- },
189
- };
190
- }
191
-
192
- test('site-partials service injects header and footer from R2 into HTML response', async () => {
193
- const store = new Map();
194
- store.set('sites/agentsam-sdk/partials/header.html', '<header id="injected-header">Header Content</header>');
195
- store.set('sites/agentsam-sdk/partials/footer.html', '<footer id="injected-footer">Footer Content</footer>');
196
-
197
- const env = { WEBSITE_ASSETS: r2Stub(store) };
198
-
199
- // Fetch and put partials
200
- const fetchedHeader = await fetchSitePartial(env, 'agentsam-sdk', 'header');
201
- assert.equal(fetchedHeader, '<header id="injected-header">Header Content</header>');
202
-
203
- await putSitePartial(env, 'agentsam-sdk', 'header', '<header id="updated">Updated</header>');
204
- const updatedHeader = await fetchSitePartial(env, 'agentsam-sdk', 'header');
205
- assert.equal(updatedHeader, '<header id="updated">Updated</header>');
206
-
207
- // Test HTML injection
208
- const baseHtml = '<!DOCTYPE html><html><head><title>Test</title></head><body><main>Main Content</main></body></html>';
209
- const initialResponse = new Response(baseHtml, {
210
- headers: { 'content-type': 'text/html; charset=utf-8' },
211
- });
212
-
213
- const injectedResponse = await injectSitePartials(initialResponse, env, 'agentsam-sdk');
214
- const transformedText = await injectedResponse.text();
215
-
216
- assert.ok(transformedText.includes('<header id="updated">Updated</header>'), 'Response must contain injected header');
217
- assert.ok(transformedText.includes('<footer id="injected-footer">Footer Content</footer>'), 'Response must contain injected footer');
218
- assert.ok(transformedText.includes('<main>Main Content</main>'), 'Response must preserve main content');
219
-
220
- // Verify non-text/html responses are guarded and untouched
221
- const jsonResponse = new Response(JSON.stringify({ ok: true }), {
222
- headers: { 'content-type': 'application/json' },
223
- });
224
- const unedited = await injectSitePartials(jsonResponse, env, 'agentsam-sdk');
225
- assert.equal(await unedited.text(), JSON.stringify({ ok: true }));
226
- });
227
-
228
- test('Local Studio canonical homepage serves with edge HTMLRewriter partial injection and text/html', async () => {
229
- const { serveCanonicalHomepage } = await import('../../apps/local-studio/backend/worker/canonical-homepage.js');
230
-
231
- const store = new Map([
232
- ['sites/agentsam-sdk/partials/header.html', '<header id="live-header">SDK Header</header>'],
233
- ['sites/agentsam-sdk/partials/footer.html', '<footer id="live-footer">SDK Footer</footer>'],
234
- ]);
235
- const env = { WEBSITE_ASSETS: r2Stub(store) };
236
-
237
- const rootReq = new Request('https://agentsam.inneranimalmedia.com/', { method: 'GET' });
238
- const rootRes = await serveCanonicalHomepage(rootReq, env, 'agentsam-sdk');
239
- assert.equal(rootRes.status, 200);
240
- assert.ok(rootRes.headers.get('content-type')?.includes('text/html'), 'Content type must be text/html');
241
- const rootText = await rootRes.text();
242
- assert.ok(rootText.includes('<header id="live-header">SDK Header</header>'), 'Edge injection must inject header at /');
243
- assert.ok(rootText.includes('<footer id="live-footer">SDK Footer</footer>'), 'Edge injection must inject footer at /');
244
- assert.ok(rootText.includes('@inneranimalmedia/agentsam-sdk'), 'Canonical homepage content must be present');
245
-
246
- // Verify index.js routes / and /index.html to serveCanonicalHomepage
247
- const indexJsContent = fs.readFileSync(at('apps/local-studio/backend/worker/index.js'), 'utf8');
248
- assert.ok(
249
- indexJsContent.includes('serveCanonicalHomepage(request, env)'),
250
- 'index.js must call serveCanonicalHomepage for root route'
251
- );
252
- assert.ok(
253
- indexJsContent.includes('url.pathname === "/" || url.pathname === "/index.html"'),
254
- 'index.js must match both / and /index.html'
255
- );
256
- });
257
-