@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
@@ -0,0 +1,213 @@
1
+ import type { CmsEditorAdapter } from '../../../shared/cms/src/adapter';
2
+ import type { CmsEditorHost } from '../../../shared/cms/src/host';
3
+ import type { CmsAgentHost } from '../lib/agent-host';
4
+ import { CmsEditorProvider } from './CmsEditorProvider';
5
+ import { useCmsEditorController } from './useCmsEditorController';
6
+ import { PreviewCanvas } from './canvas/PreviewCanvas';
7
+ import { useCmsEditor } from './CmsEditorProvider';
8
+ import '../styles/studio.css';
9
+
10
+ export type CmsEditorProps = {
11
+ adapter: CmsEditorAdapter;
12
+ host?: CmsEditorHost;
13
+ /** Optional agent host slots (render props). */
14
+ agentHost?: CmsAgentHost;
15
+ siteId: string;
16
+ initialPageId?: string | null;
17
+ initialRail?: 'pages' | 'sections' | 'blocks' | 'settings';
18
+ /** True when the attached adapter is temporary (e.g. in-memory preview). Pack content is not temporary. */
19
+ temporaryAdapter?: boolean;
20
+ };
21
+
22
+ function EditorShell() {
23
+ const editor = useCmsEditor();
24
+ const { site, page, section, ui, published, lastDraft } = editor;
25
+
26
+ if (ui.error && !site) {
27
+ return (
28
+ <main className="cms-shell cms-shell--error">
29
+ <h1>CMS failed to load</h1>
30
+ <p>{ui.error}</p>
31
+ <p>A broken adapter must surface the error — never a fake working site.</p>
32
+ <button type="button" onClick={() => void editor.reload()}>
33
+ Retry
34
+ </button>
35
+ </main>
36
+ );
37
+ }
38
+
39
+ if (!site || !page) {
40
+ return (
41
+ <main className="cms-shell cms-shell--loading">
42
+ <p>Loading CMS site…</p>
43
+ </main>
44
+ );
45
+ }
46
+
47
+ return (
48
+ <main className="cms-shell cms-shell--product" data-cms-authority="adapter">
49
+ {ui.temporaryAdapterNotice ? (
50
+ <div className="cms-ephemeral-banner" role="status">
51
+ {ui.temporaryAdapterNotice}
52
+ </div>
53
+ ) : null}
54
+ <header className="cms-topbar">
55
+ <div>
56
+ <strong>{site.name}</strong>
57
+ <span>{site.domain || site.id}</span>
58
+ </div>
59
+ <div className="cms-topbar-actions">
60
+ <span className={ui.dirty ? 'badge draft' : 'badge saved'}>
61
+ {ui.dirty ? 'Unsaved draft' : 'Draft synced'}
62
+ </span>
63
+ <button
64
+ type="button"
65
+ disabled={!ui.dirty || ui.saving}
66
+ onClick={() => void editor.saveDraft()}
67
+ >
68
+ {ui.saving ? 'Saving…' : 'Save Draft'}
69
+ </button>
70
+ <button
71
+ type="button"
72
+ disabled={ui.publishing}
73
+ onClick={() => void editor.publish()}
74
+ >
75
+ {ui.publishing ? 'Publishing…' : 'Publish'}
76
+ </button>
77
+ <button type="button" onClick={() => void editor.reload()}>
78
+ Reload
79
+ </button>
80
+ {editor.host?.navigate ? (
81
+ <button type="button" onClick={() => editor.navigateHost('/cms')}>
82
+ Host CMS
83
+ </button>
84
+ ) : null}
85
+ </div>
86
+ </header>
87
+
88
+ <div className="cms-workspace">
89
+ <aside className="cms-rail">
90
+ {(['pages', 'sections', 'blocks', 'settings'] as const).map((rail) => (
91
+ <button
92
+ key={rail}
93
+ type="button"
94
+ className={ui.rail === rail ? 'active' : ''}
95
+ onClick={() => editor.setRail(rail)}
96
+ >
97
+ {rail}
98
+ </button>
99
+ ))}
100
+ </aside>
101
+
102
+ <aside className="cms-sidebar">
103
+ {ui.rail === 'pages' ? (
104
+ <ul>
105
+ {site.pages.map((entry) => (
106
+ <li key={entry.id}>
107
+ <button
108
+ type="button"
109
+ className={entry.id === page.id ? 'active' : ''}
110
+ onClick={() => editor.selectPage(entry.id)}
111
+ >
112
+ {entry.title}
113
+ <small>{entry.slug}</small>
114
+ </button>
115
+ </li>
116
+ ))}
117
+ </ul>
118
+ ) : null}
119
+ {ui.rail === 'sections' || ui.rail === 'blocks' ? (
120
+ <ul>
121
+ {page.sections.map((entry) => (
122
+ <li key={entry.id}>
123
+ <button
124
+ type="button"
125
+ className={entry.id === section?.id ? 'active' : ''}
126
+ onClick={() => editor.selectSection(entry.id)}
127
+ >
128
+ {entry.name}
129
+ <small>{entry.type}</small>
130
+ </button>
131
+ </li>
132
+ ))}
133
+ </ul>
134
+ ) : null}
135
+ {ui.rail === 'settings' ? (
136
+ <div className="cms-settings">
137
+ <p>Persistence goes only through CmsEditorAdapter.</p>
138
+ <p>Last draft: {lastDraft?.id || '—'}</p>
139
+ <p>Published: {published?.publicationId || '—'}</p>
140
+ </div>
141
+ ) : null}
142
+ </aside>
143
+
144
+ <section className="cms-canvas-wrap">
145
+ <div className="cms-viewport-switch">
146
+ {(['phone', 'tablet', 'desktop'] as const).map((viewport) => (
147
+ <button
148
+ key={viewport}
149
+ type="button"
150
+ className={ui.viewport === viewport ? 'active' : ''}
151
+ onClick={() => editor.setViewport(viewport)}
152
+ >
153
+ {viewport}
154
+ </button>
155
+ ))}
156
+ </div>
157
+ <PreviewCanvas />
158
+ </section>
159
+
160
+ <aside className="cms-inspector">
161
+ {section ? (
162
+ <>
163
+ <h2>{section.name}</h2>
164
+ <p>{section.type}</p>
165
+ {Object.entries(section.fields || {}).map(([key, value]) => (
166
+ <label key={key}>
167
+ <span>{key}</span>
168
+ <input
169
+ value={typeof value === 'string' ? value : JSON.stringify(value)}
170
+ onChange={(event) => editor.updateSectionField(key, event.target.value)}
171
+ />
172
+ </label>
173
+ ))}
174
+ </>
175
+ ) : (
176
+ <p>Select a section</p>
177
+ )}
178
+ {ui.error ? <p className="cms-error">{ui.error}</p> : null}
179
+ </aside>
180
+ </div>
181
+ </main>
182
+ );
183
+ }
184
+
185
+ /**
186
+ * Canonical CMS editor entry — shell composition only.
187
+ * Persistence: CmsEditorAdapter. Host navigation: CmsEditorHost.
188
+ */
189
+ export default function CmsEditor({
190
+ adapter,
191
+ host,
192
+ siteId,
193
+ initialPageId = null,
194
+ initialRail = 'sections',
195
+ temporaryAdapter = false,
196
+ }: CmsEditorProps) {
197
+ const editor = useCmsEditorController({
198
+ adapter,
199
+ host,
200
+ siteId,
201
+ initialPageId,
202
+ initialRail,
203
+ temporaryAdapter,
204
+ });
205
+
206
+ return (
207
+ <CmsEditorProvider value={editor}>
208
+ <EditorShell />
209
+ </CmsEditorProvider>
210
+ );
211
+ }
212
+
213
+ export type { CmsEditorController } from './useCmsEditorController';
@@ -0,0 +1,20 @@
1
+ import { createContext, useContext, type ReactNode } from 'react';
2
+ import type { CmsEditorController } from './useCmsEditorController';
3
+
4
+ const CmsEditorContext = createContext<CmsEditorController | null>(null);
5
+
6
+ export function CmsEditorProvider({
7
+ value,
8
+ children,
9
+ }: {
10
+ value: CmsEditorController;
11
+ children: ReactNode;
12
+ }) {
13
+ return <CmsEditorContext.Provider value={value}>{children}</CmsEditorContext.Provider>;
14
+ }
15
+
16
+ export function useCmsEditor() {
17
+ const ctx = useContext(CmsEditorContext);
18
+ if (!ctx) throw new Error('useCmsEditor requires CmsEditorProvider');
19
+ return ctx;
20
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Structural draft canvas — NOT a second pretend website renderer.
3
+ * Shows the same draft model the adapter owns. Schema-driven CmsRenderer replaces this later.
4
+ */
5
+ import { useCmsEditor } from '../CmsEditorProvider';
6
+
7
+ export function PreviewCanvas() {
8
+ const { page, section, selectSection, ui } = useCmsEditor();
9
+ if (!page) {
10
+ return <div className="cms-canvas-empty">Open a page to preview the draft model.</div>;
11
+ }
12
+
13
+ return (
14
+ <div className={`cms-canvas cms-canvas--${ui.viewport}`} data-cms-preview="draft-model">
15
+ <header className="cms-canvas-meta">
16
+ <strong>{page.title}</strong>
17
+ <span>{page.slug}</span>
18
+ <em>Draft model preview · schema renderer pending</em>
19
+ </header>
20
+ <ol className="cms-canvas-sections">
21
+ {page.sections.map((entry) => (
22
+ <li key={entry.id}>
23
+ <button
24
+ type="button"
25
+ className={entry.id === section?.id ? 'is-selected' : ''}
26
+ onClick={() => selectSection(entry.id)}
27
+ >
28
+ <span>{entry.name}</span>
29
+ <small>{entry.type}</small>
30
+ {!entry.visible ? <em>hidden</em> : null}
31
+ </button>
32
+ {entry.id === section?.id ? (
33
+ <dl>
34
+ {Object.entries(entry.fields || {}).map(([key, value]) => (
35
+ <div key={key}>
36
+ <dt>{key}</dt>
37
+ <dd>{typeof value === 'string' ? value : JSON.stringify(value)}</dd>
38
+ </div>
39
+ ))}
40
+ {(entry.blocks || []).length ? (
41
+ <div>
42
+ <dt>blocks</dt>
43
+ <dd>{entry.blocks.map((b) => b.type).join(', ')}</dd>
44
+ </div>
45
+ ) : null}
46
+ </dl>
47
+ ) : null}
48
+ </li>
49
+ ))}
50
+ </ol>
51
+ </div>
52
+ );
53
+ }
@@ -1,10 +1,9 @@
1
1
  "use client";
2
2
 
3
3
  import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
- import type { AgentPrincipal, AgentWorkbenchAdapter } from "@inneranimalmedia/agentsam-contracts";
5
- import { MiniAgentSam, type AnnotationSelection } from "@inneranimalmedia/agentsam-workbench/agent";
6
- import "@inneranimalmedia/agentsam-workbench/agent/mini-agentsam.css";
4
+ import { createCmsAgentContextProvider } from "@inneranimalmedia/agentsam-cms-shared";
7
5
  import { AgentSamDrawer } from "./AgentSamDrawer";
6
+ import type { CmsAgentHost, CmsAnnotationSelection } from "./lib/agent-host";
8
7
  import { escapeCmsText, safeCmsAssetUrl, safeCmsCssValue, sanitizeCmsRichText } from "./lib/content-safety";
9
8
  import {
10
9
  createCmsEditorBlock,
@@ -124,11 +123,8 @@ function ToastStack({ toasts, dismiss }: { toasts: Toast[]; dismiss: (id: number
124
123
  return <div className="toast-stack">{toasts.slice(-3).map(t => <div className={`toast ${t.type}`} key={t.id}><span className="toast-icon"><Icon name={t.type === "success" ? "check" : t.type === "warning" ? "warning" : t.type === "error" ? "close" : "info"}/></span><span>{t.message}</span>{t.action && <button>{t.action}</button>}<button className="toast-x" onClick={() => dismiss(t.id)}><Icon name="close" size={12}/></button>{t.type !== "error" && <i/>}</div>)}</div>;
125
124
  }
126
125
 
127
- export type CmsEditorAgentConfig = {
128
- adapter: AgentWorkbenchAdapter;
129
- principal: AgentPrincipal;
130
- conversationId?: string;
131
- };
126
+ /** @deprecated Prefer `agentHost` — kept as alias for migration. */
127
+ export type CmsEditorAgentConfig = CmsAgentHost;
132
128
 
133
129
  export type CmsEditorProps = {
134
130
  projectSlug?: string;
@@ -136,7 +132,10 @@ export type CmsEditorProps = {
136
132
  initialPanel?: "pages" | "sections" | "templates" | "imports" | "theme";
137
133
  siteCatalog?: Array<{ slug: string; name?: string; domain?: string | null }>;
138
134
  onSiteChange?: (slug: string) => void;
139
- agent?: CmsEditorAgentConfig;
135
+ /** Optional AgentSam / workbench host. Core editor boots with none attached. */
136
+ agentHost?: CmsAgentHost;
137
+ /** @deprecated Use agentHost */
138
+ agent?: CmsAgentHost;
140
139
  basePath?: string;
141
140
  onNavigate?: (path: string) => void;
142
141
  };
@@ -159,10 +158,12 @@ export default function CmsEditor({
159
158
  initialPanel = "sections",
160
159
  siteCatalog = [],
161
160
  onSiteChange,
161
+ agentHost,
162
162
  agent,
163
163
  basePath = "/cms",
164
164
  onNavigate,
165
165
  }: CmsEditorProps) {
166
+ const host = agentHost || agent;
166
167
  const [sites, setSites] = useState<Site[]>(initialSites);
167
168
  const [siteId, setSiteId] = useStored("cms-active-site", projectSlug);
168
169
  const site = sites.find((s) => s.id === siteId) || sites.find((s) => s.pages?.length) || sites[0] || null;
@@ -419,14 +420,27 @@ const FALLBACK_TEMPLATE_CARDS: TemplateCard[] = [
419
420
  }
420
421
  }, [page, chooseBlock]);
421
422
 
422
- const onAnnotateSubmit = useCallback(async (prompt: string, annotation: AnnotationSelection) => {
423
- selectAnnotatedResource(annotation.id);
423
+ const onAnnotateSubmit = useCallback(async (prompt: string, annotation: CmsAnnotationSelection) => {
424
+ selectAnnotatedResource(String(annotation.id || ""));
424
425
  setAgentSamOpen(true);
425
426
  setInspectorSheetOpen(false);
426
427
  setAnnotatePrompt(prompt);
427
- toast(`Annotated “${annotation.label || annotation.tag}”`, "info");
428
+ toast(`Annotated “${annotation.label || "selection"}”`, "info");
428
429
  window.dispatchEvent(new CustomEvent("agentsam:cms-annotate", { detail: { prompt, annotation } }));
429
430
  }, [selectAnnotatedResource, setAgentSamOpen, toast]);
431
+
432
+ const agentContextProvider = useMemo(() => createCmsAgentContextProvider(() => ({
433
+ principal: host?.principal || {
434
+ accountId: "local",
435
+ authUserId: "local",
436
+ displayName: "Local",
437
+ },
438
+ projectId: site?.id || projectSlug || "site",
439
+ route: page?.slug,
440
+ pageId: page?.id || null,
441
+ sectionId: selected?.id || null,
442
+ blockId: selectedBlock?.id || null,
443
+ })), [host?.principal, site?.id, projectSlug, page?.slug, page?.id, selected?.id, selectedBlock?.id]);
430
444
  const choosePage = (id: string) => { if (dirty && !window.confirm("You have unsaved changes. Discard and continue?")) return; const p = site.pages.find(x => x.id === id); if (!p) return; setPageId(id); setSelectedId(p.sections[0]?.id || ""); setSelectedBlockId(""); setDirty(false); setTab("content"); toast(`Opened ${p.title}`, "info"); };
431
445
  const chooseSite = (id: string) => { const s = sites.find(x => x.id === id); if (!s) return; setSiteSwitcher(false); if (onSiteChange) { onSiteChange(id); toast(`Opening ${s.name}`, "info"); return; } setSiteId(id); if (s.pages[0]) { setPageId(s.pages[0].id); setSelectedId(s.pages[0].sections[0]?.id || ""); setSelectedBlockId(""); } toast(`Switched to ${s.name}`, "info"); };
432
446
 
@@ -948,10 +962,8 @@ const FALLBACK_TEMPLATE_CARDS: TemplateCard[] = [
948
962
  <AgentSamDrawer
949
963
  open={agentSamOpen}
950
964
  onClose={() => setAgentSamOpen(false)}
951
- adapter={agent?.adapter}
952
- principal={agent?.principal}
953
965
  projectId={site.id || projectSlug}
954
- conversationId={agent?.conversationId || `cms:${site.id || projectSlug}`}
966
+ conversationId={host?.conversationId || `cms:${site.id || projectSlug}`}
955
967
  route={page.slug}
956
968
  pageId={page.id}
957
969
  sectionId={selected?.id || null}
@@ -959,17 +971,34 @@ const FALLBACK_TEMPLATE_CARDS: TemplateCard[] = [
959
971
  selectionLabel={selectedBlock ? String(selectedBlock.data?.text || selectedBlock.data?.title || selectedBlock.type) : selected?.name || null}
960
972
  pendingPrompt={annotatePrompt}
961
973
  onPendingPromptConsumed={() => setAnnotatePrompt(null)}
962
- />
974
+ >
975
+ {host?.renderDrawer?.({
976
+ open: agentSamOpen,
977
+ onClose: () => setAgentSamOpen(false),
978
+ projectId: site.id || projectSlug,
979
+ conversationId: host?.conversationId || `cms:${site.id || projectSlug}`,
980
+ contextProvider: agentContextProvider,
981
+ route: page.slug,
982
+ pageId: page.id,
983
+ sectionId: selected?.id || null,
984
+ blockId: selectedBlock?.id || null,
985
+ selectionLabel: selectedBlock ? String(selectedBlock.data?.text || selectedBlock.data?.title || selectedBlock.type) : selected?.name || null,
986
+ pendingPrompt: annotatePrompt,
987
+ onPendingPromptConsumed: () => setAnnotatePrompt(null),
988
+ })}
989
+ </AgentSamDrawer>
963
990
  </div>
964
991
 
965
- <MiniAgentSam
966
- selecting={annotateSelecting}
967
- onSelectingChange={setAnnotateSelecting}
968
- scope={() => canvasScopeRef.current}
969
- onSubmit={onAnnotateSubmit}
970
- />
992
+ {host?.renderMini?.({
993
+ projectId: site.id || projectSlug,
994
+ conversationId: host?.conversationId || `cms:${site.id || projectSlug}`,
995
+ contextProvider: agentContextProvider,
996
+ annotateSelecting,
997
+ onAnnotateToggle: () => setAnnotateSelecting((v) => !v),
998
+ onAnnotateSubmit,
999
+ })}
971
1000
 
972
- <footer className="statusbar"><div><i/> {annotateSelecting ? "Annotate mode" : agentSamOpen ? "AgentSam open" : "Connected"}</div><span>{dirty ? "Unsaved changes" : saving ? "Saving…" : "Saved"}</span><span>{page.slug}</span><span>{page.sections.length} sections · {page.sections.reduce((total, section) => total + (section.blocks?.length || 0), 0)} blocks</span><button onClick={() => setModal("shortcuts")}>Shortcuts <kbd>⌘/</kbd></button></footer>
1001
+ <footer className="statusbar"><div><i/> {annotateSelecting ? "Annotate mode" : agentSamOpen ? "AgentSam open" : host ? "Host ready" : "Local"}</div><span>{dirty ? "Unsaved changes" : saving ? "Saving…" : "Saved"}</span><span>{page.slug}</span><span>{page.sections.length} sections · {page.sections.reduce((total, section) => total + (section.blocks?.length || 0), 0)} blocks</span><button onClick={() => setModal("shortcuts")}>Shortcuts <kbd>⌘/</kbd></button></footer>
973
1002
  <nav className="mobile-tabs">{railItems.slice(0, 5).map((i) => <button key={i.id} className={rail === i.id ? "active" : ""} onClick={() => setRail(i.id)}><Icon name={i.icon}/><span>{i.label}</span></button>)}</nav>
974
1003
  <ToastStack toasts={toasts} dismiss={dismissToast}/>
975
1004
 
@@ -0,0 +1,218 @@
1
+ import { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import type { CmsEditorAdapter } from '../../../shared/cms/src/adapter';
3
+ import type {
4
+ CmsEditorBlock,
5
+ CmsEditorPage,
6
+ CmsEditorSection,
7
+ CmsEditorSite,
8
+ } from '../../../shared/cms/src/editor-types';
9
+ import type { CmsEditorHost } from '../../../shared/cms/src/host';
10
+ import type { CmsPublicationSnapshot, CmsRevision } from '../../../shared/cms/src/adapter';
11
+
12
+ export type CmsEditorUiState = {
13
+ rail: 'pages' | 'sections' | 'blocks' | 'media' | 'settings';
14
+ viewport: 'phone' | 'tablet' | 'desktop';
15
+ dirty: boolean;
16
+ saving: boolean;
17
+ publishing: boolean;
18
+ error: string | null;
19
+ temporaryAdapterNotice: string | null;
20
+ };
21
+
22
+ export type CmsEditorController = {
23
+ adapter: CmsEditorAdapter;
24
+ host?: CmsEditorHost;
25
+ site: CmsEditorSite | null;
26
+ page: CmsEditorPage | null;
27
+ section: CmsEditorSection | null;
28
+ block: CmsEditorBlock | null;
29
+ ui: CmsEditorUiState;
30
+ published: CmsPublicationSnapshot | null;
31
+ lastDraft: CmsRevision | null;
32
+ selectPage: (pageId: string) => void;
33
+ selectSection: (sectionId: string) => void;
34
+ selectBlock: (blockId: string) => void;
35
+ setRail: (rail: CmsEditorUiState['rail']) => void;
36
+ setViewport: (viewport: CmsEditorUiState['viewport']) => void;
37
+ updateSectionField: (key: string, value: unknown) => void;
38
+ saveDraft: () => Promise<void>;
39
+ publish: () => Promise<void>;
40
+ reload: () => Promise<void>;
41
+ navigateHost: (path: string) => void;
42
+ };
43
+
44
+ export type UseCmsEditorControllerArgs = {
45
+ adapter: CmsEditorAdapter;
46
+ host?: CmsEditorHost;
47
+ siteId: string;
48
+ initialPageId?: string | null;
49
+ initialRail?: CmsEditorUiState['rail'];
50
+ temporaryAdapter?: boolean;
51
+ };
52
+
53
+ export function useCmsEditorController({
54
+ adapter,
55
+ host,
56
+ siteId,
57
+ initialPageId = null,
58
+ initialRail = 'sections',
59
+ temporaryAdapter = false,
60
+ }: UseCmsEditorControllerArgs): CmsEditorController {
61
+ const [site, setSite] = useState<CmsEditorSite | null>(null);
62
+ const [pageId, setPageId] = useState<string | null>(initialPageId);
63
+ const [sectionId, setSectionId] = useState<string | null>(null);
64
+ const [blockId, setBlockId] = useState<string | null>(null);
65
+ const [published, setPublished] = useState<CmsPublicationSnapshot | null>(null);
66
+ const [lastDraft, setLastDraft] = useState<CmsRevision | null>(null);
67
+ const [ui, setUi] = useState<CmsEditorUiState>({
68
+ rail: initialRail,
69
+ viewport: 'desktop',
70
+ dirty: false,
71
+ saving: false,
72
+ publishing: false,
73
+ error: null,
74
+ temporaryAdapterNotice: temporaryAdapter
75
+ ? 'Temporary adapter · changes are not durable until a SQLite/D1/HTTP adapter is attached. Starter pack content is real product content.'
76
+ : null,
77
+ });
78
+
79
+ const reload = useCallback(async () => {
80
+ setUi((u) => ({ ...u, error: null }));
81
+ const loaded = await adapter.loadSite(siteId);
82
+ setSite(loaded);
83
+ const page =
84
+ loaded.pages.find((p) => p.id === initialPageId) ||
85
+ loaded.pages.find((p) => p.id === pageId) ||
86
+ loaded.pages[0] ||
87
+ null;
88
+ setPageId(page?.id || null);
89
+ setSectionId(page?.sections[0]?.id || null);
90
+ setBlockId(null);
91
+ setUi((u) => ({ ...u, dirty: false }));
92
+ if (page?.id) {
93
+ const pub = await adapter.getPublishedRevision(page.id);
94
+ setPublished(pub);
95
+ }
96
+ }, [adapter, siteId, initialPageId, pageId]);
97
+
98
+ useEffect(() => {
99
+ reload().catch((error) => {
100
+ setUi((u) => ({ ...u, error: error?.message || String(error) }));
101
+ setSite(null);
102
+ });
103
+ // intentionally load once per site/adapter
104
+ // eslint-disable-next-line react-hooks/exhaustive-deps
105
+ }, [adapter, siteId]);
106
+
107
+ const page = useMemo(
108
+ () => site?.pages.find((p) => p.id === pageId) || site?.pages[0] || null,
109
+ [site, pageId],
110
+ );
111
+ const section = useMemo(
112
+ () => page?.sections.find((s) => s.id === sectionId) || page?.sections[0] || null,
113
+ [page, sectionId],
114
+ );
115
+ const block = useMemo(
116
+ () => section?.blocks.find((b) => b.id === blockId) || null,
117
+ [section, blockId],
118
+ );
119
+
120
+ const selectPage = useCallback((id: string) => {
121
+ setPageId(id);
122
+ setSectionId(null);
123
+ setBlockId(null);
124
+ setUi((u) => ({ ...u, dirty: false, rail: 'sections' }));
125
+ }, []);
126
+
127
+ const selectSection = useCallback((id: string) => {
128
+ setSectionId(id);
129
+ setBlockId(null);
130
+ setUi((u) => ({ ...u, rail: 'sections' }));
131
+ }, []);
132
+
133
+ const selectBlock = useCallback((id: string) => {
134
+ setBlockId(id);
135
+ setUi((u) => ({ ...u, rail: 'blocks' }));
136
+ }, []);
137
+
138
+ const updateSectionField = useCallback(
139
+ (key: string, value: unknown) => {
140
+ if (!site || !page || !section) return;
141
+ setSite((current) => {
142
+ if (!current) return current;
143
+ return {
144
+ ...current,
145
+ pages: current.pages.map((p) =>
146
+ p.id !== page.id
147
+ ? p
148
+ : {
149
+ ...p,
150
+ sections: p.sections.map((s) =>
151
+ s.id !== section.id ? s : { ...s, fields: { ...s.fields, [key]: value } },
152
+ ),
153
+ },
154
+ ),
155
+ };
156
+ });
157
+ setUi((u) => ({ ...u, dirty: true }));
158
+ },
159
+ [site, page, section],
160
+ );
161
+
162
+ const saveDraft = useCallback(async () => {
163
+ if (!page) return;
164
+ setUi((u) => ({ ...u, saving: true, error: null }));
165
+ try {
166
+ const revision = await adapter.saveDraft(page.id, { sections: page.sections });
167
+ setLastDraft(revision);
168
+ setUi((u) => ({ ...u, dirty: false, saving: false }));
169
+ } catch (error: any) {
170
+ setUi((u) => ({ ...u, saving: false, error: error?.message || String(error) }));
171
+ throw error;
172
+ }
173
+ }, [adapter, page]);
174
+
175
+ const publish = useCallback(async () => {
176
+ if (!page) return;
177
+ setUi((u) => ({ ...u, publishing: true, error: null }));
178
+ try {
179
+ if (ui.dirty) await saveDraft();
180
+ const snapshot = await adapter.publish(page.id);
181
+ setPublished(snapshot);
182
+ await reload();
183
+ setUi((u) => ({ ...u, publishing: false, dirty: false }));
184
+ } catch (error: any) {
185
+ setUi((u) => ({ ...u, publishing: false, error: error?.message || String(error) }));
186
+ throw error;
187
+ }
188
+ }, [adapter, page, ui.dirty, saveDraft, reload]);
189
+
190
+ const navigateHost = useCallback(
191
+ (path: string) => {
192
+ if (host?.navigate) host.navigate(path);
193
+ },
194
+ [host],
195
+ );
196
+
197
+ return {
198
+ adapter,
199
+ host,
200
+ site,
201
+ page,
202
+ section,
203
+ block,
204
+ ui,
205
+ published,
206
+ lastDraft,
207
+ selectPage,
208
+ selectSection,
209
+ selectBlock,
210
+ setRail: (rail) => setUi((u) => ({ ...u, rail })),
211
+ setViewport: (viewport) => setUi((u) => ({ ...u, viewport })),
212
+ updateSectionField,
213
+ saveDraft,
214
+ publish,
215
+ reload,
216
+ navigateHost,
217
+ };
218
+ }
@@ -1,8 +1,22 @@
1
- export { default as CmsEditor } from './CmsEditor';
2
- export { default } from './CmsEditor';
3
- export type { CmsEditorProps } from './CmsEditor';
4
- export { mountClientCmsEditor, type ClientCmsEditorBoot } from './mount.tsx';
1
+ export { default as CmsEditor } from './editor/CmsEditor';
2
+ export { default } from './editor/CmsEditor';
3
+ export type { CmsEditorProps } from './editor/CmsEditor';
4
+ export { mountClientCmsEditor, type ClientCmsEditorBoot } from './mount';
5
5
  export { CmsAgentSurface, type CmsAgentSurfaceProps } from './CmsAgentSurface';
6
6
  export { AgentSamDrawer, type AgentSamDrawerProps } from './AgentSamDrawer';
7
+ export type { CmsAgentHost, CmsAnnotationSelection, CmsHostPrincipal } from './lib/agent-host';
8
+ export { MemoryCmsAdapter } from './adapters/memory';
9
+ export { HttpCmsAdapter, createHttpCmsAdapter } from './adapters/http';
10
+ export { previewHeuristicStarter, createHeuristicThemeMemoryAdapter } from './adapters/heuristic';
11
+ export { useCmsEditorController } from './editor/useCmsEditorController';
12
+ export { useCmsEditor } from './editor/CmsEditorProvider';
13
+ export {
14
+ heuristicStarterPack,
15
+ listBuiltinStarterPacks,
16
+ HEURISTIC_STARTER_PACK_ID,
17
+ } from '../../starter-packs/heuristic';
18
+ export { blankStarterPack, BLANK_STARTER_PACK_ID } from '../../starter-packs/blank';
19
+ export { iasfStarterPack, IASF_STARTER_PACK_ID, listIasfStarterPacks } from '../../starter-packs/iasf';
20
+ export { installStarterPack } from '../../shared/cms/src/starter-pack';
21
+ export type { CmsStarterPack } from '../../shared/cms/src/starter-pack';
7
22
  export * from './surfaces/index';
8
-