@inneranimalmedia/agentsam-sdk 2.6.5 → 2.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/AGENTSAM.md +29 -0
  2. package/apps/README.md +5 -0
  3. package/apps/cad-creator/README.md +4 -4
  4. package/apps/cad-creator/shared/cad/package.json +1 -1
  5. package/apps/client-cms-editor/AGENTS.md +12 -7
  6. package/apps/client-cms-editor/README.md +76 -48
  7. package/apps/client-cms-editor/agentsam.app.json +26 -9
  8. package/apps/client-cms-editor/backend/package.json +20 -3
  9. package/apps/client-cms-editor/backend/src/api/client.ts +134 -101
  10. package/apps/client-cms-editor/backend/src/index.ts +1 -1
  11. package/apps/client-cms-editor/backend/src/model.ts +11 -115
  12. package/apps/client-cms-editor/backend/src/preview/bridge.ts +1 -1
  13. package/apps/client-cms-editor/backend/tsconfig.json +6 -1
  14. package/apps/client-cms-editor/bin/agentsam-cms.js +262 -0
  15. package/apps/client-cms-editor/bin/agentsam-cms.mjs +2 -228
  16. package/apps/client-cms-editor/frontend/package.json +16 -7
  17. package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +9 -41
  18. package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +19 -174
  19. package/apps/client-cms-editor/frontend/src/adapters/heuristic.ts +29 -0
  20. package/apps/client-cms-editor/frontend/src/adapters/http.ts +628 -0
  21. package/apps/client-cms-editor/frontend/src/adapters/memory.ts +510 -0
  22. package/apps/client-cms-editor/frontend/src/editor/CmsEditor.tsx +213 -0
  23. package/apps/client-cms-editor/frontend/src/editor/CmsEditorProvider.tsx +20 -0
  24. package/apps/client-cms-editor/frontend/src/editor/canvas/PreviewCanvas.tsx +53 -0
  25. package/apps/client-cms-editor/frontend/src/{CmsEditor.tsx → editor/legacy/CmsEditorPrototype.tsx} +52 -23
  26. package/apps/client-cms-editor/frontend/src/editor/useCmsEditorController.ts +218 -0
  27. package/apps/client-cms-editor/frontend/src/index.ts +19 -5
  28. package/apps/client-cms-editor/frontend/src/lib/agent-host.ts +24 -0
  29. package/apps/client-cms-editor/frontend/src/main.tsx +82 -8
  30. package/apps/client-cms-editor/frontend/src/mount.tsx +92 -30
  31. package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +1 -1
  32. package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +8 -8
  33. package/apps/client-cms-editor/frontend/src/styles/studio.css +55 -3
  34. package/apps/client-cms-editor/frontend/tsconfig.json +12 -1
  35. package/apps/client-cms-editor/frontend/vite.config.ts +12 -0
  36. package/apps/client-cms-editor/package-lock.json +973 -134
  37. package/apps/client-cms-editor/package.json +118 -6
  38. package/apps/client-cms-editor/reference/harvest/HARVEST_RECEIPT.json +201 -0
  39. package/apps/client-cms-editor/reference/harvest/PROVENANCE_HISTORY.txt +10 -0
  40. package/apps/client-cms-editor/reference/harvest/README.md +8 -0
  41. package/apps/client-cms-editor/reference/harvest/plans/ARCHIVE-INTAKE.md +135 -0
  42. package/apps/client-cms-editor/reference/harvest/plans/CHATGPT-IDENTITY-HARVEST.md +83 -0
  43. package/apps/client-cms-editor/reference/harvest/plans/CMS-EDITOR-HARVEST.md +166 -0
  44. package/apps/client-cms-editor/reference/harvest/plans/HARVEST-INDEX.md +196 -0
  45. package/apps/client-cms-editor/reference/harvest/plans/INNERANIMALS-CONTENT-001.md +137 -0
  46. package/apps/client-cms-editor/reference/harvest/plans/NO-IMPLICIT-SIDE-EFFECTS.md +87 -0
  47. package/apps/client-cms-editor/reference/harvest/plans/STOREFRONT-SURFACE-MAP.md +140 -0
  48. package/apps/client-cms-editor/reference/harvest/plans/THEME-INNERANIMALS-HARVEST.md +137 -0
  49. package/apps/client-cms-editor/reference/harvest/plans/TOOLING-LAB.md +63 -0
  50. package/apps/client-cms-editor/reference/harvest/plans/harvest-manifest.json +97 -0
  51. package/apps/client-cms-editor/reference/harvest/plans/local-cms-harvest-schema.sql +328 -0
  52. package/apps/client-cms-editor/shared/cms/package.json +17 -7
  53. package/apps/client-cms-editor/shared/cms/src/adapter.ts +204 -0
  54. package/apps/client-cms-editor/shared/cms/src/agent-context.ts +7 -5
  55. package/apps/client-cms-editor/shared/cms/src/editor-types.ts +32 -0
  56. package/apps/client-cms-editor/shared/cms/src/host.ts +82 -0
  57. package/apps/client-cms-editor/shared/cms/src/index.ts +4 -0
  58. package/apps/client-cms-editor/shared/cms/src/map.ts +115 -0
  59. package/apps/client-cms-editor/shared/cms/src/starter-pack.ts +158 -0
  60. package/contracts/source-types.v1.json +353 -0
  61. package/docs/CMS_CONTEXTUAL_COMPOSER.md +1 -1
  62. package/docs/PRODUCT_LIFECYCLE.md +566 -0
  63. package/docs/THEME_REFINERY.md +2 -2
  64. package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +40 -20
  65. package/docs/content-studio/REVISION_GATE_2026-09-27.md +1 -1
  66. package/docs/plans/LOCAL_STUDIO_DESKTOP_RELEASE_2026-09-29.md +150 -0
  67. package/migrations/d1/0017_identity_native_oauth.sql +21 -0
  68. package/native/agentsam-machine/Cargo.lock +426 -0
  69. package/native/agentsam-machine/Cargo.toml +9 -0
  70. package/native/agentsam-machine/cli/Cargo.toml +14 -0
  71. package/native/agentsam-machine/cli/src/main.rs +77 -0
  72. package/native/agentsam-machine/core/Cargo.toml +15 -0
  73. package/native/agentsam-machine/core/src/assets.rs +790 -0
  74. package/native/agentsam-machine/core/src/bound.rs +298 -0
  75. package/native/agentsam-machine/core/src/enrich.rs +706 -0
  76. package/native/agentsam-machine/core/src/frontend.rs +442 -0
  77. package/native/agentsam-machine/core/src/lib.rs +1086 -0
  78. package/native/agentsam-machine/core/src/liquid.rs +528 -0
  79. package/native/agentsam-machine/core/src/source_types.rs +78 -0
  80. package/package.json +51 -21
  81. package/packages/agentsam-brand/README.md +1 -1
  82. package/packages/agentsam-brand/package.json +4 -4
  83. package/packages/agentsam-brand/src/index.js +1 -1
  84. package/packages/agentsam-contracts/package.json +13 -3
  85. package/packages/agentsam-contracts/src/tools.ts +22 -0
  86. package/packages/agentsam-errors/package.json +13 -3
  87. package/packages/agentsam-knowledge/package.json +18 -4
  88. package/packages/agentsam-knowledge/src/autorag/index.js +10 -3
  89. package/packages/agentsam-knowledge/src/backends/index.js +33 -1
  90. package/packages/agentsam-knowledge/test/autorag.test.mjs +60 -1
  91. package/packages/agentsam-nav/package.json +24 -6
  92. package/packages/agentsam-queue-control/README.md +1 -1
  93. package/packages/agentsam-queue-control/package.json +7 -2
  94. package/packages/agentsam-rapid-rust/src/main.rs +1 -1
  95. package/packages/agentsam-repository/package.json +13 -3
  96. package/packages/agentsam-repository/src/source-types.js +8 -0
  97. package/packages/agentsam-vault/package.json +14 -4
  98. package/packages/agentsam-workbench/package.json +15 -4
  99. package/packages/agentsam-workbench/src/agent/ToolPermissionRequest.tsx +94 -0
  100. package/packages/agentsam-workbench/src/agent/index.ts +2 -0
  101. package/packages/agentsam-workbench/src/agent/tool-permission.css +134 -0
  102. package/packages/connectors/cloudflare/package.json +13 -3
  103. package/packages/connectors/cloudflare/src/api-client.js +3 -2
  104. package/packages/connectors/cloudflare/src/families/vectorize.js +127 -0
  105. package/packages/connectors/cloudflare/src/index.js +1 -0
  106. package/packages/heuristic-theme/README.md +2 -2
  107. package/packages/heuristic-theme/package.json +8 -3
  108. package/packages/heuristic-theme/src/registry.js +2 -2
  109. package/packages/heuristic-theme/src/theme.js +1 -1
  110. package/packages/heuristic-theme/test/theme.test.mjs +1 -1
  111. package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
  112. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +27 -7
  113. package/packages/identity/README.md +2 -2
  114. package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +18 -15
  115. package/packages/identity/migrations/apply-portable.js +109 -0
  116. package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +1 -1
  117. package/packages/identity/migrations/sqlite/005_identity_company_native.sql +52 -0
  118. package/packages/identity/package.json +27 -6
  119. package/packages/identity/schema/agentsam.identity/manifest.json +101 -0
  120. package/packages/identity/scripts/local-identity-bridge.mjs +13 -7
  121. package/packages/identity/scripts/preview-auth-portal.mjs +6 -6
  122. package/packages/identity/src/adapters/cloudflare-d1/index.js +8 -401
  123. package/packages/identity/src/adapters/iam-compat/index.js +540 -0
  124. package/packages/identity/src/adapters/portable-d1/index.js +18 -0
  125. package/packages/identity/src/adapters/portable-store.js +479 -0
  126. package/packages/identity/src/adapters/sqlite/index.js +13 -312
  127. package/packages/identity/src/contracts/auth-config.js +0 -1
  128. package/packages/identity/src/contracts/identity-store.js +56 -5
  129. package/packages/identity/src/contracts/provider.js +1 -0
  130. package/packages/identity/src/contracts/sign-in-options.js +104 -0
  131. package/packages/identity/src/core/constants.js +1 -1
  132. package/packages/identity/src/core/session-policy.js +31 -0
  133. package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -6
  134. package/packages/identity/src/frontend/auth-portal/pages/reset.html +5 -5
  135. package/packages/identity/src/frontend/auth-portal/pages/signup.html +5 -5
  136. package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
  137. package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +6 -37
  138. package/packages/identity/src/index.js +28 -1
  139. package/packages/identity/src/migrations/README.md +23 -23
  140. package/packages/identity/src/oauth/README.md +1 -1
  141. package/packages/identity/src/oauth/credentials.js +10 -11
  142. package/packages/identity/src/oauth/google-desktop-exchange.js +195 -27
  143. package/packages/identity/src/oauth/iam-platform.js +21 -9
  144. package/packages/identity/src/oauth/native-handoff.js +136 -0
  145. package/packages/identity/src/providers/chatgpt/headers.js +65 -0
  146. package/packages/identity/src/providers/chatgpt/index.js +86 -0
  147. package/packages/identity/src/providers/chatgpt/mapper.js +43 -0
  148. package/packages/identity/src/providers/chatgpt/paths.js +45 -0
  149. package/packages/identity/src/providers/github/oauth.js +1 -2
  150. package/packages/identity/src/providers/github/profile.js +16 -2
  151. package/packages/identity/src/providers/index.js +11 -3
  152. package/packages/identity/src/server/identity-service.js +2 -1
  153. package/packages/identity/src/server/worker-router.js +71 -18
  154. package/packages/identity/tests/chatgpt-provider.test.mjs +75 -0
  155. package/packages/identity/tests/google-desktop-identity-login.test.mjs +210 -0
  156. package/packages/identity/tests/identity-init-scaffold.test.mjs +15 -4
  157. package/packages/identity/tests/lane1-identity-store-parity.test.mjs +527 -0
  158. package/packages/identity/tests/lane1-packed-consumer.test.mjs +175 -0
  159. package/packages/identity/tests/native-oauth-handoff.test.mjs +292 -0
  160. package/packages/identity/tests/oauth-credentials.test.mjs +4 -4
  161. package/packages/identity/tests/preview-auth-portal.test.mjs +4 -2
  162. package/packages/identity/tests/session-routes-policy.test.mjs +13 -1
  163. package/packages/identity/tests/worker-runtime-boundary.test.mjs +11 -0
  164. package/packages/providers/completeful/package.json +7 -2
  165. package/packages/theme-church-site/package.json +17 -6
  166. package/packages/theme-church-site/src/harvest.json +4 -2
  167. package/packages/theme-church-site/src/index.js +7 -3
  168. package/packages/theme-church-site/test/theme.test.mjs +4 -2
  169. package/packages/theme-companions-site/package.json +17 -6
  170. package/packages/theme-companions-site/src/harvest.json +4 -2
  171. package/packages/theme-companions-site/src/index.js +7 -3
  172. package/packages/theme-companions-site/test/theme.test.mjs +4 -2
  173. package/packages/theme-floors-site/package.json +17 -6
  174. package/packages/theme-floors-site/src/harvest.json +4 -2
  175. package/packages/theme-floors-site/src/index.js +7 -3
  176. package/packages/theme-floors-site/test/theme.test.mjs +4 -2
  177. package/packages/theme-fuelnfree-site/package.json +17 -6
  178. package/packages/theme-fuelnfree-site/src/harvest.json +4 -2
  179. package/packages/theme-fuelnfree-site/src/index.js +7 -3
  180. package/packages/theme-fuelnfree-site/test/theme.test.mjs +4 -2
  181. package/packages/theme-handyman-site/package.json +17 -6
  182. package/packages/theme-handyman-site/src/harvest.json +4 -2
  183. package/packages/theme-handyman-site/src/index.js +7 -3
  184. package/packages/theme-handyman-site/test/theme.test.mjs +4 -2
  185. package/packages/theme-insurance-site/package.json +17 -6
  186. package/packages/theme-insurance-site/src/harvest.json +4 -2
  187. package/packages/theme-insurance-site/src/index.js +7 -3
  188. package/packages/theme-insurance-site/test/theme.test.mjs +4 -2
  189. package/packages/theme-scenes/README.md +1 -1
  190. package/packages/theme-scenes/package.json +4 -3
  191. package/packages/theme-scenes/src/registry.js +187 -0
  192. package/packages/theme-shinshu-site/package.json +17 -6
  193. package/packages/theme-shinshu-site/src/harvest.json +4 -2
  194. package/packages/theme-shinshu-site/src/index.js +7 -3
  195. package/packages/theme-shinshu-site/test/theme.test.mjs +4 -2
  196. package/packages/work-graph/package.json +14 -4
  197. package/protocol/FILEMETA_V1.md +2 -2
  198. package/protocol/capabilities/manifest.json +1 -1
  199. package/protocol/database/agentsam.schema-pack.v1.schema.json +72 -0
  200. package/protocol/presets/catalog.json +2 -2
  201. package/protocol/theme-refinery/lineage-registry.json +105 -0
  202. package/protocol/theme-refinery/product-metadata.schema.json +21 -1
  203. package/skills/grok-auth/SKILL.md +110 -0
  204. package/skills/grok-auth/agentsam.skill.json +25 -0
  205. package/skills/grok-auth/references/grok-identity.md +64 -0
  206. package/skills/grok-auth/references/per-user-data.md +49 -0
  207. package/skills/grok-auth/references/prewired-and-env.md +54 -0
  208. package/skills/grok-auth/references/session-ui.md +133 -0
  209. package/skills/grok-auth/references/sign-in-methods.md +55 -0
  210. package/skills/grok-auth/references/wiring.md +71 -0
  211. package/skills/grok-building-games/SKILL.md +213 -0
  212. package/skills/grok-building-games/agentsam.skill.json +25 -0
  213. package/skills/grok-building-games/references/3d-libs.md +64 -0
  214. package/skills/grok-building-games/references/ai-pathfinding.md +122 -0
  215. package/skills/grok-building-games/references/audio.md +129 -0
  216. package/skills/grok-building-games/references/babylon.md +202 -0
  217. package/skills/grok-building-games/references/collision-physics.md +122 -0
  218. package/skills/grok-building-games/references/ecs-architecture.md +111 -0
  219. package/skills/grok-building-games/references/game-feel-juice.md +110 -0
  220. package/skills/grok-building-games/references/genres/board-card-chess.md +89 -0
  221. package/skills/grok-building-games/references/genres/endless-runner.md +83 -0
  222. package/skills/grok-building-games/references/genres/fps.md +105 -0
  223. package/skills/grok-building-games/references/genres/platformer-2d.md +97 -0
  224. package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +131 -0
  225. package/skills/grok-building-games/references/genres/racing-kart.md +106 -0
  226. package/skills/grok-building-games/references/genres/topdown-twin-stick.md +97 -0
  227. package/skills/grok-building-games/references/genres/tower-defense.md +84 -0
  228. package/skills/grok-building-games/references/genres/voxel-minecraft.md +89 -0
  229. package/skills/grok-building-games/references/input.md +139 -0
  230. package/skills/grok-building-games/references/phaser.md +277 -0
  231. package/skills/grok-building-games/references/procedural-generation.md +141 -0
  232. package/skills/grok-building-games/references/save-persistence.md +108 -0
  233. package/skills/grok-building-games/references/threejs-foundational.md +148 -0
  234. package/skills/grok-controls/SKILL.md +274 -0
  235. package/skills/grok-controls/agentsam.skill.json +25 -0
  236. package/skills/grok-design-ui/SKILL.md +122 -0
  237. package/skills/grok-design-ui/agentsam.skill.json +25 -0
  238. package/skills/grok-design-ui/references/animations.md +379 -0
  239. package/skills/grok-design-ui/references/performance.md +88 -0
  240. package/skills/grok-design-ui/references/refined-ui.md +384 -0
  241. package/skills/grok-design-ui/references/surfaces.md +247 -0
  242. package/skills/grok-design-ui/references/typography.md +123 -0
  243. package/skills/grok-game-animation-frames/SKILL.md +84 -0
  244. package/skills/grok-game-animation-frames/agentsam.skill.json +25 -0
  245. package/skills/grok-game-asset-core/SKILL.md +69 -0
  246. package/skills/grok-game-asset-core/agentsam.skill.json +25 -0
  247. package/skills/grok-game-character-consistency/SKILL.md +69 -0
  248. package/skills/grok-game-character-consistency/agentsam.skill.json +25 -0
  249. package/skills/grok-game-tilesets/SKILL.md +65 -0
  250. package/skills/grok-game-tilesets/agentsam.skill.json +25 -0
  251. package/skills/grok-game-ui-icons/SKILL.md +56 -0
  252. package/skills/grok-game-ui-icons/agentsam.skill.json +25 -0
  253. package/skills/grok-generate2dmap/LICENSE +21 -0
  254. package/skills/grok-generate2dmap/SKILL.md +120 -0
  255. package/skills/grok-generate2dmap/SOURCE.md +6 -0
  256. package/skills/grok-generate2dmap/agentsam.skill.json +25 -0
  257. package/skills/grok-generate2dmap/references/deliverables.md +101 -0
  258. package/skills/grok-generate2dmap/references/layered-map-contract.md +209 -0
  259. package/skills/grok-generate2dmap/references/map-strategies.md +341 -0
  260. package/skills/grok-generate2dmap/references/object-production-gate.md +24 -0
  261. package/skills/grok-generate2dmap/references/pipeline.md +149 -0
  262. package/skills/grok-generate2dmap/references/prop-pack-contract.md +174 -0
  263. package/skills/grok-generate2dmap/references/side-scroll-stages.md +29 -0
  264. package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +157 -0
  265. package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +369 -0
  266. package/skills/grok-generate2dsprite/LICENSE +21 -0
  267. package/skills/grok-generate2dsprite/SKILL.md +313 -0
  268. package/skills/grok-generate2dsprite/SOURCE.md +6 -0
  269. package/skills/grok-generate2dsprite/agentsam.skill.json +25 -0
  270. package/skills/grok-generate2dsprite/references/modes.md +124 -0
  271. package/skills/grok-generate2dsprite/references/prompt-rules.md +315 -0
  272. package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +1031 -0
  273. package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +109 -0
  274. package/skills/grok-imagine/SKILL.md +201 -0
  275. package/skills/grok-imagine/agentsam.skill.json +25 -0
  276. package/skills/grok-multiplayer-p2p/SKILL.md +111 -0
  277. package/skills/grok-multiplayer-p2p/agentsam.skill.json +25 -0
  278. package/skills/grok-multiplayer-p2p/references/react-binding.md +144 -0
  279. package/skills/grok-multiplayer-p2p/references/signaling-relay.md +269 -0
  280. package/skills/grok-neon/SKILL.md +157 -0
  281. package/skills/grok-neon/agentsam.skill.json +25 -0
  282. package/skills/grok-og/SKILL.md +102 -0
  283. package/skills/grok-og/agentsam.skill.json +25 -0
  284. package/skills/grok-og/references/brand-pass.md +53 -0
  285. package/skills/grok-og/references/custom-card.md +107 -0
  286. package/skills/grok-og/references/favicon-and-icons.md +48 -0
  287. package/skills/grok-og/references/og-type-contract.md +18 -0
  288. package/skills/grok-og/references/placeholder-card.md +21 -0
  289. package/skills/grok-og/references/x-banner.md +41 -0
  290. package/skills/grok-threejs/SKILL.md +67 -0
  291. package/skills/grok-threejs/agentsam.skill.json +25 -0
  292. package/skills/grok-threejs/references/llms-full.txt +2780 -0
  293. package/skills/grok-video2dsprite/LICENSE +21 -0
  294. package/skills/grok-video2dsprite/SKILL.md +236 -0
  295. package/skills/grok-video2dsprite/SOURCE.md +6 -0
  296. package/skills/grok-video2dsprite/agentsam.skill.json +25 -0
  297. package/skills/grok-video2dsprite/references/pipeline.md +90 -0
  298. package/skills/grok-video2dsprite/references/prompt-rules.md +63 -0
  299. package/skills/grok-video2dsprite/scripts/video2dsprite.py +490 -0
  300. package/skills/grok-xai-api/SKILL.md +152 -0
  301. package/skills/grok-xai-api/agentsam.skill.json +25 -0
  302. package/src/cli/command-catalog.js +46 -4
  303. package/src/cli/dispatch.js +1 -0
  304. package/src/cli.js +10 -0
  305. package/src/cloudflare/runtime-status.js +2 -1
  306. package/src/commands/autorag.js +67 -13
  307. package/src/commands/cheat-sheet.js +29 -4
  308. package/src/commands/codebaseindex.js +45 -2
  309. package/src/commands/knowledge.js +59 -2
  310. package/src/commands/machine-binary.js +103 -0
  311. package/src/commands/machine.js +137 -0
  312. package/src/commands/security.js +67 -4
  313. package/src/commands/setup.js +33 -16
  314. package/src/commands/status.js +8 -1
  315. package/src/features/resolve.js +1 -0
  316. package/src/knowledge/engine.js +21 -2
  317. package/src/knowledge/runtime-discovery.js +127 -0
  318. package/src/lib/identity-scaffold.js +53 -13
  319. package/src/lib/setup/recipes.js +1 -1
  320. package/src/models/discovery.js +40 -22
  321. package/src/models/inventory-core.d.ts +105 -0
  322. package/src/models/inventory-core.js +54 -6
  323. package/src/security/logs.js +3 -0
  324. package/src/ui/cli/help.js +41 -0
  325. package/test/apps-scaffold-contract.test.mjs +3 -2
  326. package/test/cli/api-key-env-whoami.test.mjs +2 -2
  327. package/test/cli/catalog-authority.test.mjs +64 -0
  328. package/test/cli/machine-command.test.mjs +34 -0
  329. package/test/fixtures/project-authority/customer-app/.agentsam/app.json +5 -0
  330. package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +1 -0
  331. package/test/fixtures/project-authority/customer-app/wrangler.toml +17 -0
  332. package/test/integration/autorag-project-authority.integration.test.mjs +51 -0
  333. package/test/integration/autorag-runtime-discovery.test.mjs +107 -0
  334. package/test/integration/cms-app-scaffold.test.mjs +37 -31
  335. package/test/integration/cms-site-tenancy-contract.test.mjs +28 -17
  336. package/test/integration/codebaseindex-ingest.test.mjs +41 -0
  337. package/test/integration/database-hosted-honesty.test.mjs +49 -0
  338. package/test/integration/desktop-keychain-boundary.test.mjs +45 -0
  339. package/test/integration/hosted-work-host-authority.test.mjs +47 -0
  340. package/test/integration/inventory-eligibility.test.mjs +59 -0
  341. package/test/integration/local-provider-bridge.test.mjs +65 -0
  342. package/test/integration/local-studio-settings-production.test.mjs +40 -0
  343. package/test/integration/lockfile-sync.test.mjs +26 -0
  344. package/test/integration/provider-env-cli.test.mjs +13 -3
  345. package/test/integration/runtime-status.integration.test.mjs +16 -1
  346. package/test/integration/theme-package-registry.test.mjs +31 -0
  347. package/test/repository-snapshot-view.test.mjs +2 -2
  348. package/test/security.test.mjs +14 -0
  349. package/test/terminal-machine-identity.test.mjs +2 -2
  350. package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +0 -145
  351. package/packages/agentsam-nav/dist/Nav.d.ts +0 -43
  352. package/packages/agentsam-nav/dist/NavCollapsible.d.ts +0 -10
  353. package/packages/agentsam-nav/dist/NavContent.d.ts +0 -2
  354. package/packages/agentsam-nav/dist/NavFooter.d.ts +0 -2
  355. package/packages/agentsam-nav/dist/NavGroup.d.ts +0 -3
  356. package/packages/agentsam-nav/dist/NavHeader.d.ts +0 -2
  357. package/packages/agentsam-nav/dist/NavMenu.d.ts +0 -22
  358. package/packages/agentsam-nav/dist/NavProvider.d.ts +0 -35
  359. package/packages/agentsam-nav/dist/NavTrigger.d.ts +0 -2
  360. package/packages/agentsam-nav/dist/Surfaces.d.ts +0 -41
  361. package/packages/agentsam-nav/dist/browser.d.ts +0 -11
  362. package/packages/agentsam-nav/dist/browser.global.js +0 -132
  363. package/packages/agentsam-nav/dist/browser.js +0 -613
  364. package/packages/agentsam-nav/dist/contracts.d.ts +0 -76
  365. package/packages/agentsam-nav/dist/index.d.ts +0 -11
  366. package/packages/agentsam-nav/dist/index.js +0 -614
  367. package/packages/agentsam-nav/dist/legacy.css +0 -83
  368. package/packages/agentsam-nav/dist/shell.css +0 -113
  369. package/packages/agentsam-nav/dist/theme.css +0 -113
  370. package/packages/agentsam-nav/dist/utils.d.ts +0 -1
  371. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +0 -670
@@ -0,0 +1,628 @@
1
+ /**
2
+ * HTTP CmsEditorAdapter — hosted Worker CMS authority via /api/cms/*.
3
+ * Durable D1-backed persistence. Never an in-memory substitute.
4
+ */
5
+
6
+ import {
7
+ CmsCapabilityError,
8
+ type CmsAsset,
9
+ type CmsEditorAdapter,
10
+ type CmsPublicationSnapshot,
11
+ type CmsRevision,
12
+ } from '../../../shared/cms/src/adapter';
13
+ import type {
14
+ CmsEditorBlock,
15
+ CmsEditorPage,
16
+ CmsEditorSection,
17
+ CmsEditorSite,
18
+ CmsSiteCreateInput,
19
+ CmsSiteRecord,
20
+ CmsSiteUpdatePatch,
21
+ } from '../../../shared/cms/src/editor-types';
22
+
23
+ type Json = Record<string, any>;
24
+
25
+ function siteQuery(siteId: string) {
26
+ return `site=${encodeURIComponent(siteId)}`;
27
+ }
28
+
29
+ async function api<T = Json>(path: string, init: RequestInit = {}): Promise<T> {
30
+ const headers = new Headers(init.headers || {});
31
+ if (init.body && !(init.body instanceof FormData) && !headers.has('content-type')) {
32
+ headers.set('content-type', 'application/json');
33
+ }
34
+ const response = await fetch(path, {
35
+ credentials: 'same-origin',
36
+ cache: 'no-store',
37
+ ...init,
38
+ headers,
39
+ });
40
+ const body = (await response.json().catch(() => ({}))) as Json;
41
+ if (!response.ok || body?.ok === false) {
42
+ throw new Error(body?.error || body?.detail || `HTTP ${response.status}`);
43
+ }
44
+ return body as T;
45
+ }
46
+
47
+ function parseFields(raw: unknown): Record<string, any> {
48
+ if (!raw) return {};
49
+ if (typeof raw === 'object' && !Array.isArray(raw)) return { ...(raw as object) };
50
+ if (typeof raw === 'string') {
51
+ try {
52
+ const parsed = JSON.parse(raw);
53
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};
54
+ } catch {
55
+ return {};
56
+ }
57
+ }
58
+ return {};
59
+ }
60
+
61
+ function mapStatus(row: Json): CmsEditorPage['status'] {
62
+ const status = String(row.status || '').toLowerCase();
63
+ if (status === 'live' || status === 'published' || row.published === 1 || row.published === true) {
64
+ return 'live';
65
+ }
66
+ if (status === 'new') return 'new';
67
+ return 'draft';
68
+ }
69
+
70
+ function mapZone(row: Json): CmsEditorSection['zone'] {
71
+ const zone = String(row.zone || row.section_zone || '').toUpperCase();
72
+ if (zone === 'HEADER' || zone === 'FOOTER' || zone === 'TEMPLATE') return zone;
73
+ const type = String(row.section_type || row.type || '').toLowerCase();
74
+ if (type.includes('header') || type.includes('nav')) return 'HEADER';
75
+ if (type.includes('footer')) return 'FOOTER';
76
+ return 'BODY';
77
+ }
78
+
79
+ function mapBlock(row: Json, sectionId: string): CmsEditorBlock {
80
+ return {
81
+ id: String(row.id),
82
+ sectionId,
83
+ type: String(row.block_type || row.component_type || row.type || 'text'),
84
+ visible: row.is_visible !== 0 && row.is_visible !== false && row.visible !== false,
85
+ data: parseFields(row.block_data ?? row.component_data ?? row.data),
86
+ sortOrder: Number(row.sort_order || 0) || 0,
87
+ };
88
+ }
89
+
90
+ function mapSection(row: Json, blocks: CmsEditorBlock[] = []): CmsEditorSection {
91
+ const fields = parseFields(row.section_data ?? row.data ?? row.fields);
92
+ const css = parseFields(fields.css_override ?? row.css);
93
+ return {
94
+ id: String(row.id),
95
+ name: String(row.section_name || row.name || row.section_type || 'Section'),
96
+ type: String(row.section_type || row.type || 'section'),
97
+ zone: mapZone(row),
98
+ visible: row.is_visible !== 0 && row.is_visible !== false && row.visible !== false,
99
+ color: String(fields.color || row.color || '#111115'),
100
+ fields,
101
+ css,
102
+ blocks,
103
+ };
104
+ }
105
+
106
+ function mapPage(row: Json, sections: CmsEditorSection[] = []): CmsEditorPage {
107
+ const slugRaw = String(row.slug || row.route_path || row.path || '/').trim() || '/';
108
+ const slug = slugRaw.startsWith('/') ? slugRaw : `/${slugRaw}`;
109
+ return {
110
+ id: String(row.id),
111
+ title: String(row.title || 'Untitled'),
112
+ slug,
113
+ status: mapStatus(row),
114
+ type: String(row.page_type || row.type || 'Interior'),
115
+ parent: row.parent_id ? String(row.parent_id) : undefined,
116
+ sections,
117
+ metaTitle: String(row.meta_title || row.title || ''),
118
+ metaDescription: String(row.meta_description || ''),
119
+ };
120
+ }
121
+
122
+ function initialsFrom(name: string) {
123
+ return (
124
+ name
125
+ .split(/\s+/)
126
+ .filter(Boolean)
127
+ .slice(0, 2)
128
+ .map((part) => part[0])
129
+ .join('')
130
+ .toUpperCase() || 'CMS'
131
+ );
132
+ }
133
+
134
+ function siteRecordFromBootstrap(siteId: string, boot: Json): CmsSiteRecord {
135
+ const name = String(boot.tenant?.name || boot.workspace_label || siteId);
136
+ return {
137
+ id: siteId,
138
+ name,
139
+ initials: initialsFrom(name),
140
+ domain: String(boot.tenant?.domain || boot.public_domain || ''),
141
+ edited: 'synced',
142
+ color: String(boot.tenant?.primary_color || '#1e6a6f'),
143
+ theme: {
144
+ cssVars: parseFields(boot.active_theme?.css_vars || {}),
145
+ },
146
+ schemas: boot.schemas
147
+ ? {
148
+ protocol_version: Number(boot.schemas.protocol_version || 1),
149
+ sections: Array.isArray(boot.schemas.sections) ? boot.schemas.sections : [],
150
+ blocks: Array.isArray(boot.schemas.blocks) ? boot.schemas.blocks : [],
151
+ }
152
+ : undefined,
153
+ };
154
+ }
155
+
156
+ function hydratePages(boot: Json): CmsEditorPage[] {
157
+ const pages = Array.isArray(boot.pages) ? boot.pages : [];
158
+ const sectionsByPage = boot.sections_by_page || {};
159
+ const blocksBySection = boot.blocks_by_section || boot.components_by_section || {};
160
+
161
+ return pages.map((pageRow: Json) => {
162
+ const sectionRows = Array.isArray(sectionsByPage[pageRow.id])
163
+ ? sectionsByPage[pageRow.id]
164
+ : [];
165
+ const sections = sectionRows.map((sectionRow: Json) => {
166
+ const blockRows = Array.isArray(blocksBySection[sectionRow.id])
167
+ ? blocksBySection[sectionRow.id]
168
+ : [];
169
+ return mapSection(
170
+ sectionRow,
171
+ blockRows.map((blockRow: Json) => mapBlock(blockRow, String(sectionRow.id))),
172
+ );
173
+ });
174
+ return mapPage(pageRow, sections);
175
+ });
176
+ }
177
+
178
+ /**
179
+ * Hosted HTTP adapter bound to Worker `/api/cms/*` for a single site id (project_slug).
180
+ */
181
+ export class HttpCmsAdapter implements CmsEditorAdapter {
182
+ readonly temporary = false;
183
+ private readonly base: string;
184
+ private readonly knownSites: Map<string, CmsSiteRecord>;
185
+
186
+ constructor(
187
+ options: {
188
+ base?: string;
189
+ sites?: Array<{ id?: string; slug?: string; name?: string; domain?: string }>;
190
+ } = {},
191
+ ) {
192
+ this.base = String(options.base || '').replace(/\/$/, '');
193
+ this.knownSites = new Map();
194
+ for (const site of options.sites || []) {
195
+ const id = String(site.id || site.slug || '').trim();
196
+ if (!id) continue;
197
+ const name = String(site.name || id);
198
+ this.knownSites.set(id, {
199
+ id,
200
+ name,
201
+ initials: initialsFrom(name),
202
+ domain: String(site.domain || ''),
203
+ edited: 'catalog',
204
+ color: '#1e6a6f',
205
+ });
206
+ }
207
+ }
208
+
209
+ private url(path: string) {
210
+ return `${this.base}${path}`;
211
+ }
212
+
213
+ async listSites(): Promise<CmsSiteRecord[]> {
214
+ if (this.knownSites.size) return [...this.knownSites.values()].map((s) => structuredClone(s));
215
+ // Fallback: bootstrap the default studio site so hub/editor share one authority.
216
+ const boot = await api<Json>(this.url(`/api/cms/bootstrap?${siteQuery('agentsam-sdk')}`));
217
+ const record = siteRecordFromBootstrap('agentsam-sdk', boot);
218
+ this.knownSites.set(record.id, record);
219
+ return [structuredClone(record)];
220
+ }
221
+
222
+ async getSite(siteId: string): Promise<CmsSiteRecord> {
223
+ const boot = await api<Json>(this.url(`/api/cms/bootstrap?${siteQuery(siteId)}`));
224
+ const record = siteRecordFromBootstrap(siteId, boot);
225
+ this.knownSites.set(siteId, record);
226
+ return structuredClone(record);
227
+ }
228
+
229
+ async createSite(_input: CmsSiteCreateInput): Promise<CmsSiteRecord> {
230
+ throw new CmsCapabilityError(
231
+ 'createSite',
232
+ 'Hosted site creation uses the deploy wizard / projects API — not inline CMS create yet.',
233
+ 'cms_capability_unsupported',
234
+ );
235
+ }
236
+
237
+ async updateSite(siteId: string, patch: CmsSiteUpdatePatch): Promise<CmsSiteRecord> {
238
+ const current = await this.getSite(siteId);
239
+ if (patch.theme?.cssVars) {
240
+ await api(this.url(`/api/cms/theme-vars?${siteQuery(siteId)}`), {
241
+ method: 'PATCH',
242
+ body: JSON.stringify({ project_slug: siteId, vars: patch.theme.cssVars }),
243
+ });
244
+ }
245
+ const next = { ...current, ...patch, id: siteId, edited: 'just now' };
246
+ this.knownSites.set(siteId, next);
247
+ return structuredClone(next);
248
+ }
249
+
250
+ async deleteSite(_siteId: string): Promise<void> {
251
+ throw new CmsCapabilityError('deleteSite', 'Hosted site delete is not enabled', 'cms_capability_unsupported');
252
+ }
253
+
254
+ async loadSite(siteId: string): Promise<CmsEditorSite> {
255
+ const boot = await api<Json>(this.url(`/api/cms/bootstrap?${siteQuery(siteId)}`));
256
+ const meta = siteRecordFromBootstrap(siteId, boot);
257
+ this.knownSites.set(siteId, meta);
258
+ return {
259
+ ...meta,
260
+ pages: hydratePages(boot),
261
+ };
262
+ }
263
+
264
+ async listPages(siteId: string): Promise<CmsEditorPage[]> {
265
+ const site = await this.loadSite(siteId);
266
+ return site.pages;
267
+ }
268
+
269
+ async getPage(pageId: string): Promise<CmsEditorPage> {
270
+ // Worker page GET requires site slug — resolve via known sites / bootstrap scan.
271
+ for (const siteId of this.knownSites.keys()) {
272
+ try {
273
+ const body = await api<Json>(
274
+ this.url(`/api/cms/pages/${encodeURIComponent(pageId)}?${siteQuery(siteId)}`),
275
+ );
276
+ const sections = Array.isArray(body.sections)
277
+ ? body.sections.map((row: Json) => mapSection(row, []))
278
+ : [];
279
+ // Hydrate blocks via bootstrap for completeness when section list is bare.
280
+ if (!sections.some((s) => s.blocks.length)) {
281
+ const full = await this.loadSite(siteId);
282
+ const hit = full.pages.find((p) => p.id === pageId);
283
+ if (hit) return structuredClone(hit);
284
+ }
285
+ return mapPage(body.page || { id: pageId }, sections);
286
+ } catch {
287
+ // try next site
288
+ }
289
+ }
290
+ // Last resort: agentsam-sdk
291
+ const full = await this.loadSite('agentsam-sdk');
292
+ const hit = full.pages.find((p) => p.id === pageId);
293
+ if (!hit) {
294
+ throw new CmsCapabilityError('getPage', `page_not_found:${pageId}`, 'cms_source_not_found');
295
+ }
296
+ return structuredClone(hit);
297
+ }
298
+
299
+ async createPage(
300
+ siteId: string,
301
+ input: Partial<CmsEditorPage> & { title: string; slug: string },
302
+ ): Promise<CmsEditorPage> {
303
+ const slug = input.slug.replace(/^\/+/, '');
304
+ const body = await api<Json>(this.url(`/api/cms/pages?${siteQuery(siteId)}`), {
305
+ method: 'POST',
306
+ body: JSON.stringify({
307
+ project_id: siteId,
308
+ project_slug: siteId,
309
+ title: input.title || 'Untitled',
310
+ slug,
311
+ route_path: `/${slug}`,
312
+ page_type: input.type || 'interior',
313
+ status: 'draft',
314
+ }),
315
+ });
316
+ return mapPage(body.page || body, []);
317
+ }
318
+
319
+ async updatePage(pageId: string, patch: Partial<CmsEditorPage>): Promise<CmsEditorPage> {
320
+ const siteId = await this.findPageSiteId(pageId);
321
+ const body = await api<Json>(
322
+ this.url(`/api/cms/pages/${encodeURIComponent(pageId)}?${siteQuery(siteId)}`),
323
+ {
324
+ method: 'PUT',
325
+ body: JSON.stringify({
326
+ title: patch.title,
327
+ slug: patch.slug?.replace(/^\/+/, ''),
328
+ route_path: patch.slug,
329
+ page_type: patch.type,
330
+ status: patch.status,
331
+ meta_title: patch.metaTitle,
332
+ meta_description: patch.metaDescription,
333
+ }),
334
+ },
335
+ );
336
+ return mapPage(body.page || body, patch.sections || []);
337
+ }
338
+
339
+ async deletePage(_pageId: string): Promise<void> {
340
+ throw new CmsCapabilityError('deletePage', 'Hosted page delete not enabled yet', 'cms_capability_unsupported');
341
+ }
342
+
343
+ async listSections(pageId: string): Promise<CmsEditorSection[]> {
344
+ const page = await this.getPage(pageId);
345
+ return page.sections;
346
+ }
347
+
348
+ async getSection(sectionId: string): Promise<CmsEditorSection> {
349
+ const site = await this.loadSite(await this.guessSiteId());
350
+ for (const page of site.pages) {
351
+ const section = page.sections.find((s) => s.id === sectionId);
352
+ if (section) return structuredClone(section);
353
+ }
354
+ throw new CmsCapabilityError('getSection', `section_not_found:${sectionId}`, 'cms_source_not_found');
355
+ }
356
+
357
+ async createSection(
358
+ pageId: string,
359
+ input: Partial<CmsEditorSection> & { name: string },
360
+ ): Promise<CmsEditorSection> {
361
+ const siteId = await this.findPageSiteId(pageId);
362
+ const body = await api<Json>(this.url(`/api/cms/sections?${siteQuery(siteId)}`), {
363
+ method: 'POST',
364
+ body: JSON.stringify({
365
+ page_id: pageId,
366
+ section_type: input.type || 'section',
367
+ section_name: input.name,
368
+ section_data: input.fields || {},
369
+ sort_order: 0,
370
+ }),
371
+ });
372
+ return mapSection(body.section || body, []);
373
+ }
374
+
375
+ async updateSection(
376
+ sectionId: string,
377
+ patch: Partial<CmsEditorSection>,
378
+ ): Promise<CmsEditorSection> {
379
+ const siteId = await this.guessSiteId();
380
+ const body = await api<Json>(
381
+ this.url(`/api/cms/sections/${encodeURIComponent(sectionId)}?${siteQuery(siteId)}`),
382
+ {
383
+ method: 'PUT',
384
+ body: JSON.stringify({
385
+ section_name: patch.name,
386
+ section_data: patch.fields,
387
+ css: patch.css,
388
+ is_visible: patch.visible === false ? 0 : 1,
389
+ }),
390
+ },
391
+ );
392
+ return mapSection(body.section || body, patch.blocks || []);
393
+ }
394
+
395
+ async deleteSection(_sectionId: string): Promise<void> {
396
+ throw new CmsCapabilityError('deleteSection', 'Hosted section delete not enabled yet', 'cms_capability_unsupported');
397
+ }
398
+
399
+ async reorderSections(pageId: string, sectionIds: string[]): Promise<void> {
400
+ const siteId = await this.findPageSiteId(pageId);
401
+ await api(this.url(`/api/cms/sections/reorder?${siteQuery(siteId)}`), {
402
+ method: 'POST',
403
+ body: JSON.stringify({
404
+ page_id: pageId,
405
+ order: sectionIds.map((id, index) => ({ id, sort_order: (index + 1) * 10 })),
406
+ }),
407
+ });
408
+ }
409
+
410
+ async setSectionVisibility(sectionId: string, visible: boolean): Promise<void> {
411
+ const siteId = await this.guessSiteId();
412
+ await api(
413
+ this.url(`/api/cms/sections/${encodeURIComponent(sectionId)}/visibility?${siteQuery(siteId)}`),
414
+ {
415
+ method: 'POST',
416
+ body: JSON.stringify({ is_visible: visible ? 1 : 0 }),
417
+ },
418
+ );
419
+ }
420
+
421
+ async listBlocks(sectionId: string): Promise<CmsEditorBlock[]> {
422
+ const section = await this.getSection(sectionId);
423
+ return section.blocks;
424
+ }
425
+
426
+ async getBlock(blockId: string): Promise<CmsEditorBlock> {
427
+ const site = await this.loadSite(await this.guessSiteId());
428
+ for (const page of site.pages) {
429
+ for (const section of page.sections) {
430
+ const block = section.blocks.find((b) => b.id === blockId);
431
+ if (block) return structuredClone(block);
432
+ }
433
+ }
434
+ throw new CmsCapabilityError('getBlock', `block_not_found:${blockId}`, 'cms_source_not_found');
435
+ }
436
+
437
+ async createBlock(
438
+ sectionId: string,
439
+ input: Partial<CmsEditorBlock> & { type: string },
440
+ ): Promise<CmsEditorBlock> {
441
+ const siteId = await this.guessSiteId();
442
+ const body = await api<Json>(this.url(`/api/cms/blocks?${siteQuery(siteId)}`), {
443
+ method: 'POST',
444
+ body: JSON.stringify({
445
+ section_id: sectionId,
446
+ block_type: input.type,
447
+ type: input.type,
448
+ block_data: input.data || {},
449
+ sort_order: input.sortOrder ?? 10,
450
+ }),
451
+ });
452
+ return mapBlock(body.block || body.component || body, sectionId);
453
+ }
454
+
455
+ async updateBlock(blockId: string, patch: Partial<CmsEditorBlock>): Promise<CmsEditorBlock> {
456
+ const siteId = await this.guessSiteId();
457
+ const body = await api<Json>(
458
+ this.url(`/api/cms/blocks/${encodeURIComponent(blockId)}?${siteQuery(siteId)}`),
459
+ {
460
+ method: 'PUT',
461
+ body: JSON.stringify({
462
+ block_data: patch.data,
463
+ block_type: patch.type,
464
+ type: patch.type,
465
+ }),
466
+ },
467
+ );
468
+ return mapBlock(body.block || body.component || { id: blockId, ...patch }, patch.sectionId || '');
469
+ }
470
+
471
+ async deleteBlock(_blockId: string): Promise<void> {
472
+ throw new CmsCapabilityError('deleteBlock', 'Hosted block delete not enabled yet', 'cms_capability_unsupported');
473
+ }
474
+
475
+ async saveDraft(pageId: string, payload: unknown): Promise<CmsRevision> {
476
+ const siteId = await this.findPageSiteId(pageId);
477
+ const body = payload as { sections?: CmsEditorSection[] };
478
+ if (Array.isArray(body?.sections)) {
479
+ for (const section of body.sections) {
480
+ await api(this.url(`/api/cms/sections/${encodeURIComponent(section.id)}?${siteQuery(siteId)}`), {
481
+ method: 'PUT',
482
+ body: JSON.stringify({
483
+ section_name: section.name,
484
+ section_data: section.fields || {},
485
+ css: section.css || {},
486
+ is_visible: section.visible === false ? 0 : 1,
487
+ }),
488
+ });
489
+ }
490
+ }
491
+ // Mark page draft
492
+ await api(this.url(`/api/cms/pages/${encodeURIComponent(pageId)}?${siteQuery(siteId)}`), {
493
+ method: 'PUT',
494
+ body: JSON.stringify({ status: 'draft' }),
495
+ });
496
+ return {
497
+ id: `rev_${Date.now()}`,
498
+ pageId,
499
+ kind: 'draft',
500
+ createdAt: new Date().toISOString(),
501
+ snapshot: payload,
502
+ };
503
+ }
504
+
505
+ async getRevision(_revisionId: string): Promise<CmsRevision> {
506
+ throw new CmsCapabilityError('getRevision', 'revision history API not wired yet', 'cms_capability_unsupported');
507
+ }
508
+
509
+ async listRevisions(_pageId: string): Promise<CmsRevision[]> {
510
+ return [];
511
+ }
512
+
513
+ async restoreRevision(_pageId: string, _revisionId: string): Promise<CmsEditorPage> {
514
+ throw new CmsCapabilityError('restoreRevision', 'revision restore not wired yet', 'cms_capability_unsupported');
515
+ }
516
+
517
+ async previewDraft(pageId: string): Promise<{ previewUrl?: string; snapshot: unknown }> {
518
+ const siteId = await this.findPageSiteId(pageId);
519
+ const page = await this.getPage(pageId);
520
+ return {
521
+ previewUrl: `/api/cms/render-page?${siteQuery(siteId)}&page_id=${encodeURIComponent(pageId)}&mode=draft`,
522
+ snapshot: page,
523
+ };
524
+ }
525
+
526
+ async publish(pageId: string): Promise<CmsPublicationSnapshot> {
527
+ const siteId = await this.findPageSiteId(pageId);
528
+ const body = await api<Json>(
529
+ this.url(`/api/cms/pages/${encodeURIComponent(pageId)}/publish?${siteQuery(siteId)}`),
530
+ { method: 'POST', body: JSON.stringify({}) },
531
+ );
532
+ const page = mapPage(body.page || { id: pageId, slug: '/' }, []);
533
+ return {
534
+ publicationId: `pub_${pageId}`,
535
+ route: page.slug,
536
+ revision: 1,
537
+ theme: 'default',
538
+ sections: [],
539
+ publishedAt: new Date().toISOString(),
540
+ };
541
+ }
542
+
543
+ async getPublishedRevision(pageId: string): Promise<CmsPublicationSnapshot | null> {
544
+ try {
545
+ const page = await this.getPage(pageId);
546
+ if (page.status !== 'live') return null;
547
+ return {
548
+ publicationId: `pub_${pageId}`,
549
+ route: page.slug,
550
+ revision: 1,
551
+ theme: 'default',
552
+ sections: page.sections.map((section) => ({
553
+ type: section.type,
554
+ props: { ...section.fields, name: section.name, blocks: section.blocks },
555
+ })),
556
+ publishedAt: undefined,
557
+ };
558
+ } catch {
559
+ return null;
560
+ }
561
+ }
562
+
563
+ async listAssets(siteId: string): Promise<CmsAsset[]> {
564
+ const body = await api<Json>(this.url(`/api/cms/assets?${siteQuery(siteId)}`));
565
+ return (body.assets || []).map((row: Json) => ({
566
+ id: String(row.id),
567
+ name: String(row.original_filename || row.filename || row.id),
568
+ mimeType: row.mime_type ? String(row.mime_type) : undefined,
569
+ size: row.content_size_bytes != null ? Number(row.content_size_bytes) : undefined,
570
+ url: row.public_url ? String(row.public_url) : undefined,
571
+ key: String(row.id),
572
+ }));
573
+ }
574
+
575
+ async getAsset(assetId: string): Promise<CmsAsset> {
576
+ for (const siteId of this.knownSites.keys()) {
577
+ const assets = await this.listAssets(siteId);
578
+ const hit = assets.find((a) => a.id === assetId);
579
+ if (hit) return hit;
580
+ }
581
+ throw new CmsCapabilityError('getAsset', `asset_not_found:${assetId}`, 'cms_source_not_found');
582
+ }
583
+
584
+ async uploadAsset(
585
+ _siteId: string,
586
+ _file: Blob,
587
+ _meta?: { name?: string; metadata?: Record<string, unknown> },
588
+ ): Promise<CmsAsset> {
589
+ throw new CmsCapabilityError('uploadAsset', 'Hosted asset upload uses Media studio', 'cms_capability_unsupported');
590
+ }
591
+
592
+ async updateAsset(
593
+ _assetId: string,
594
+ _patch: Partial<Pick<CmsAsset, 'name' | 'metadata' | 'url' | 'key'>>,
595
+ ): Promise<CmsAsset> {
596
+ throw new CmsCapabilityError('updateAsset', 'Hosted asset update not enabled', 'cms_capability_unsupported');
597
+ }
598
+
599
+ async deleteAsset(_assetId: string): Promise<void> {
600
+ throw new CmsCapabilityError('deleteAsset', 'Hosted asset delete not enabled', 'cms_capability_unsupported');
601
+ }
602
+
603
+ private guessSiteId() {
604
+ const first = this.knownSites.keys().next().value;
605
+ return first || 'agentsam-sdk';
606
+ }
607
+
608
+ private async findPageSiteId(pageId: string): Promise<string> {
609
+ if (!this.knownSites.size) {
610
+ await this.listSites();
611
+ }
612
+ for (const siteId of this.knownSites.keys()) {
613
+ try {
614
+ const site = await this.loadSite(siteId);
615
+ if (site.pages.some((p) => p.id === pageId)) return siteId;
616
+ } catch {
617
+ // continue
618
+ }
619
+ }
620
+ return this.guessSiteId();
621
+ }
622
+ }
623
+
624
+ export function createHttpCmsAdapter(
625
+ options?: ConstructorParameters<typeof HttpCmsAdapter>[0],
626
+ ): HttpCmsAdapter {
627
+ return new HttpCmsAdapter(options);
628
+ }