@inneranimalmedia/agentsam-sdk 2.6.4 → 2.6.5

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 (418) hide show
  1. package/AGENTSAM.md +11 -0
  2. package/README.md +15 -9
  3. package/apps/client-cms-editor/AGENTS.md +12 -0
  4. package/apps/client-cms-editor/IMPORT_PROVENANCE.json +8 -0
  5. package/apps/client-cms-editor/README.md +72 -0
  6. package/apps/client-cms-editor/agentsam.app.json +57 -0
  7. package/apps/client-cms-editor/backend/README.md +5 -0
  8. package/apps/client-cms-editor/backend/package.json +22 -0
  9. package/apps/client-cms-editor/backend/src/api/client.ts +200 -0
  10. package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +145 -0
  11. package/apps/client-cms-editor/backend/src/index.ts +6 -0
  12. package/apps/client-cms-editor/backend/src/model.ts +115 -0
  13. package/apps/client-cms-editor/backend/src/preview/bridge.ts +79 -0
  14. package/apps/client-cms-editor/backend/src/preview/urls.ts +55 -0
  15. package/apps/client-cms-editor/backend/src/routing/cms-route.js +293 -0
  16. package/apps/client-cms-editor/backend/src/routing/index.js +10 -0
  17. package/apps/client-cms-editor/backend/src/storefront.ts +52 -0
  18. package/apps/client-cms-editor/backend/tsconfig.json +15 -0
  19. package/apps/client-cms-editor/backend/worker/index.js +34 -0
  20. package/apps/client-cms-editor/backend/wrangler.jsonc +11 -0
  21. package/apps/client-cms-editor/bin/agentsam-cms.mjs +229 -0
  22. package/apps/client-cms-editor/frontend/index.html +12 -0
  23. package/apps/client-cms-editor/frontend/package.json +33 -0
  24. package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +188 -0
  25. package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +191 -0
  26. package/apps/client-cms-editor/frontend/src/CmsEditor.tsx +1345 -0
  27. package/apps/client-cms-editor/frontend/src/env.d.ts +14 -0
  28. package/apps/client-cms-editor/frontend/src/index.ts +8 -0
  29. package/apps/client-cms-editor/frontend/src/lib/content-safety.ts +63 -0
  30. package/apps/client-cms-editor/frontend/src/main.tsx +17 -0
  31. package/apps/client-cms-editor/frontend/src/mount.tsx +51 -0
  32. package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +214 -0
  33. package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +1739 -0
  34. package/apps/client-cms-editor/frontend/src/styles/studio.css +106 -0
  35. package/apps/client-cms-editor/frontend/src/surfaces/CmsDashboard.tsx +313 -0
  36. package/apps/client-cms-editor/frontend/src/surfaces/CmsGuidedChatHero.tsx +121 -0
  37. package/apps/client-cms-editor/frontend/src/surfaces/CmsHubPage.tsx +132 -0
  38. package/apps/client-cms-editor/frontend/src/surfaces/CmsSiteSwitcher.tsx +176 -0
  39. package/apps/client-cms-editor/frontend/src/surfaces/index.ts +5 -0
  40. package/apps/client-cms-editor/frontend/src/surfaces/types.ts +48 -0
  41. package/apps/client-cms-editor/frontend/tsconfig.json +25 -0
  42. package/apps/client-cms-editor/frontend/vite.config.ts +13 -0
  43. package/apps/client-cms-editor/package-lock.json +3832 -0
  44. package/apps/client-cms-editor/package.json +23 -0
  45. package/apps/client-cms-editor/reference/DONOR_README.md +52 -0
  46. package/apps/client-cms-editor/reference/DONOR_package-lock.json +1253 -0
  47. package/apps/client-cms-editor/reference/DONOR_tsconfig.json +15 -0
  48. package/apps/client-cms-editor/shared/cms/package.json +21 -0
  49. package/apps/client-cms-editor/shared/cms/src/agent-context.ts +35 -0
  50. package/apps/client-cms-editor/shared/cms/src/cloudflare-bindings.ts +51 -0
  51. package/apps/client-cms-editor/shared/cms/src/editor-types.ts +58 -0
  52. package/apps/client-cms-editor/shared/cms/src/index.ts +5 -0
  53. package/apps/client-cms-editor/shared/cms/src/publication.ts +24 -0
  54. package/apps/client-cms-editor/shared/cms/src/routes.ts +11 -0
  55. package/apps/client-cms-editor/shared/cms/tsconfig.json +12 -0
  56. package/bin/agentsam-rapid-rust +36 -0
  57. package/docs/AUTH_IDENTITY_CONTRACT.md +2 -0
  58. package/docs/MACHINE_INTELLIGENCE.md +120 -0
  59. package/docs/WINDOWS_RUNTIME_INSTALL.md +30 -0
  60. package/docs/architecture/AGENTSAM_APPLICATION_CONTRACT.md +188 -0
  61. package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +151 -0
  62. package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +12 -4
  63. package/docs/architecture/R2_SLUG_NAMESPACE.md +20 -0
  64. package/docs/architecture/WORK_PRODUCT_EXTRACTION.md +97 -0
  65. package/docs/brand/AGENT_SAM_ICON_GRAMMAR.md +70 -0
  66. package/docs/content-studio/HOST_MOUNT_CHECKLIST.md +71 -0
  67. package/docs/content-studio/REVISION_GATE_2026-09-27.md +501 -0
  68. package/docs/contracts/capability-install-planner.md +67 -0
  69. package/docs/contracts/environment-vocabulary.md +195 -0
  70. package/docs/contracts/google-cloud-oauth-setup.md +199 -0
  71. package/docs/local-studio/WORKMODE_DONOR_NOTES.md +1 -1
  72. package/docs/plans/LOCAL-STUDIO-GRADUATION-2026-09-26.md +290 -0
  73. package/docs/plans/LOCAL-STUDIO-REAL-APP-CONTRACT-ADDENDUM-2026-09-27.md +394 -0
  74. package/docs/plans/MACHINE-FIRST-APPS-TUI-2026-09-24.md +227 -0
  75. package/docs/plans/TOMORROW-EXTENSIVE-TODO-2026-09-26.md +221 -0
  76. package/docs/plans/TOMORROW-MACHINE-FIRST-BRIEFING.md +145 -0
  77. package/docs/plans/UNIVERSAL-INGEST-MACHINE-FIRST-2026-09-24.md +215 -0
  78. package/docs/plugins.md +2 -2
  79. package/docs/product/AGENTSAM_PRODUCT_EXPERIENCE_STANDARD.md +280 -0
  80. package/docs/product/LOCAL_STUDIO_DESKTOP_EXPERIENCE.md +139 -0
  81. package/docs/product/README.md +8 -0
  82. package/docs/rapid-rust-wasm.md +35 -0
  83. package/migrations/d1/0016_cloudflare_oauth_user_oauth_tokens_ssot.sql +14 -0
  84. package/package.json +73 -14
  85. package/packages/agentsam-brand/README.md +106 -11
  86. package/packages/agentsam-brand/bin/agentsam-brand.mjs +9 -0
  87. package/packages/agentsam-brand/package.json +39 -7
  88. package/packages/agentsam-brand/src/adapters/cloudflare-images.js +453 -0
  89. package/packages/agentsam-brand/src/adapters/cloudflare-r2.js +74 -0
  90. package/packages/agentsam-brand/src/adapters/d1-registry.js +26 -0
  91. package/packages/agentsam-brand/src/adapters/filesystem.js +59 -0
  92. package/packages/agentsam-brand/src/adapters/memory.js +31 -0
  93. package/packages/agentsam-brand/src/cli/controller.js +503 -0
  94. package/packages/agentsam-brand/src/cli/wizard.js +526 -0
  95. package/packages/agentsam-brand/src/core/capabilities.js +201 -0
  96. package/packages/agentsam-brand/src/core/derivatives.js +211 -0
  97. package/packages/agentsam-brand/src/core/errors.js +12 -0
  98. package/packages/agentsam-brand/src/core/ingest.js +195 -0
  99. package/packages/agentsam-brand/src/core/inspect.js +109 -0
  100. package/packages/agentsam-brand/src/core/keys.js +83 -0
  101. package/packages/agentsam-brand/src/core/naming.js +142 -0
  102. package/packages/agentsam-brand/src/core/optimize.js +316 -0
  103. package/packages/agentsam-brand/src/core/pack.js +305 -0
  104. package/packages/agentsam-brand/src/core/plan.js +276 -0
  105. package/packages/agentsam-brand/src/core/preview.js +159 -0
  106. package/packages/agentsam-brand/src/core/processors/cloudflare.js +68 -0
  107. package/packages/agentsam-brand/src/core/processors/contract.js +203 -0
  108. package/packages/agentsam-brand/src/core/processors/index.js +148 -0
  109. package/packages/agentsam-brand/src/core/processors/native.js +82 -0
  110. package/packages/agentsam-brand/src/core/processors/sharp.js +113 -0
  111. package/packages/agentsam-brand/src/core/processors/squoosh-binary.js +195 -0
  112. package/packages/agentsam-brand/src/core/promote.js +288 -0
  113. package/packages/agentsam-brand/src/core/receipts.js +155 -0
  114. package/packages/agentsam-brand/src/core/v2/compile.js +280 -0
  115. package/packages/agentsam-brand/src/core/v2/derivatives-semantic.js +207 -0
  116. package/packages/agentsam-brand/src/core/v2/ingest-graph.js +387 -0
  117. package/packages/agentsam-brand/src/core/v2/roles.js +180 -0
  118. package/packages/agentsam-brand/src/core/v2/schema.js +209 -0
  119. package/packages/agentsam-brand/src/core/v2/templates.js +114 -0
  120. package/packages/agentsam-brand/src/index.js +193 -36
  121. package/packages/agentsam-brand/src/presets/app-icon.json +16 -0
  122. package/packages/agentsam-brand/src/presets/favicon.json +17 -0
  123. package/packages/agentsam-brand/src/presets/hero.json +12 -0
  124. package/packages/agentsam-brand/src/presets/index.js +40 -0
  125. package/packages/agentsam-brand/src/presets/logo.json +12 -0
  126. package/packages/agentsam-brand/src/presets/model.json +8 -0
  127. package/packages/agentsam-brand/src/presets/og-image.json +10 -0
  128. package/packages/agentsam-brand/src/presets/product-shot.json +11 -0
  129. package/packages/agentsam-brand/src/presets/social-image.json +10 -0
  130. package/packages/agentsam-brand/src/presets/web-image.json +10 -0
  131. package/packages/agentsam-contracts/src/artifacts.ts +41 -0
  132. package/packages/agentsam-knowledge/src/autorag/index.js +1 -1
  133. package/packages/agentsam-knowledge/src/providers/index.js +6 -4
  134. package/packages/agentsam-knowledge/src/providers/ollama-endpoint.js +31 -0
  135. package/packages/agentsam-knowledge/test/autorag.test.mjs +22 -1
  136. package/packages/agentsam-nav/package.json +2 -2
  137. package/packages/agentsam-rapid-rust/Cargo.lock +344 -0
  138. package/packages/agentsam-rapid-rust/Cargo.toml +18 -0
  139. package/packages/agentsam-rapid-rust/README.md +5 -0
  140. package/packages/agentsam-rapid-rust/src/main.rs +718 -0
  141. package/packages/agentsam-rapid-rust/templates/api/Cargo.toml.tmpl +18 -0
  142. package/packages/agentsam-rapid-rust/templates/api/src/lib.rs.tmpl +17 -0
  143. package/packages/agentsam-rapid-rust/templates/common/README.md.tmpl +22 -0
  144. package/packages/agentsam-rapid-rust/templates/common/package.json.tmpl +12 -0
  145. package/packages/agentsam-rapid-rust/templates/common/wrangler.toml.tmpl +6 -0
  146. package/packages/agentsam-rapid-rust/templates/crypto-auth/Cargo.toml.tmpl +21 -0
  147. package/packages/agentsam-rapid-rust/templates/crypto-auth/src/lib.rs.tmpl +32 -0
  148. package/packages/agentsam-rapid-rust/templates/data-processor/Cargo.toml.tmpl +18 -0
  149. package/packages/agentsam-rapid-rust/templates/data-processor/src/lib.rs.tmpl +41 -0
  150. package/packages/agentsam-rapid-rust/templates/shared-core/Cargo.toml.tmpl +9 -0
  151. package/packages/agentsam-rapid-rust/templates/shared-core/core/Cargo.toml.tmpl +7 -0
  152. package/packages/agentsam-rapid-rust/templates/shared-core/core/src/lib.rs.tmpl +23 -0
  153. package/packages/agentsam-rapid-rust/templates/shared-core/worker/Cargo.toml.tmpl +12 -0
  154. package/packages/agentsam-rapid-rust/templates/shared-core/worker/src/lib.rs.tmpl +16 -0
  155. package/packages/agentsam-rapid-rust/templates/shared-core/wrangler.toml.tmpl +6 -0
  156. package/packages/agentsam-repository/src/index.js +1 -0
  157. package/packages/agentsam-repository/src/merkle/semantic.js +3 -10
  158. package/packages/agentsam-repository/src/source-types.js +85 -0
  159. package/packages/agentsam-vault/README.md +96 -0
  160. package/packages/agentsam-vault/package.json +32 -0
  161. package/packages/agentsam-vault/src/contracts/credential.d.ts +78 -0
  162. package/packages/agentsam-vault/src/contracts/credential.js +132 -0
  163. package/packages/agentsam-vault/src/crypto/aes-gcm.d.ts +30 -0
  164. package/packages/agentsam-vault/src/crypto/aes-gcm.js +107 -0
  165. package/packages/agentsam-vault/src/crypto/oauth-envelope.js +150 -0
  166. package/packages/agentsam-vault/src/index.d.ts +9 -0
  167. package/packages/agentsam-vault/src/index.js +27 -0
  168. package/packages/agentsam-vault/src/providers/registry.js +90 -0
  169. package/packages/agentsam-vault/src/runtime/resolver.js +77 -0
  170. package/packages/agentsam-workbench/README.md +24 -0
  171. package/packages/agentsam-workbench/package.json +38 -0
  172. package/packages/agentsam-workbench/src/agent/AgentPanel.tsx +41 -0
  173. package/packages/agentsam-workbench/src/agent/ArtifactCard.tsx +9 -0
  174. package/packages/agentsam-workbench/src/agent/Composer.tsx +102 -0
  175. package/packages/agentsam-workbench/src/agent/ConnectedAgentPanel.tsx +194 -0
  176. package/packages/agentsam-workbench/src/agent/ContextualComposer.tsx +788 -0
  177. package/packages/agentsam-workbench/src/agent/GoalStatusStrip.tsx +38 -0
  178. package/packages/agentsam-workbench/src/agent/MiniAgentSam.tsx +86 -0
  179. package/packages/agentsam-workbench/src/agent/ModelSelect.tsx +19 -0
  180. package/packages/agentsam-workbench/src/agent/Thread.tsx +56 -0
  181. package/packages/agentsam-workbench/src/agent/ToolReceipt.tsx +11 -0
  182. package/packages/agentsam-workbench/src/agent/contextual-composer.css +611 -0
  183. package/packages/agentsam-workbench/src/agent/index.ts +10 -0
  184. package/packages/agentsam-workbench/src/agent/mini-agentsam.css +12 -0
  185. package/packages/agentsam-workbench/src/browser/BrowserFrame.tsx +37 -0
  186. package/packages/agentsam-workbench/src/browser/index.ts +1 -0
  187. package/packages/agentsam-workbench/src/index.ts +6 -0
  188. package/packages/agentsam-workbench/src/project-control.css +160 -0
  189. package/packages/agentsam-workbench/src/projects/ProjectsSurface.tsx +131 -0
  190. package/packages/agentsam-workbench/src/projects/index.ts +1 -0
  191. package/packages/agentsam-workbench/src/shell/Breadcrumb.tsx +35 -0
  192. package/packages/agentsam-workbench/src/shell/ResizableStage.tsx +99 -0
  193. package/packages/agentsam-workbench/src/shell/SidePanel.tsx +5 -0
  194. package/packages/agentsam-workbench/src/shell/index.ts +4 -0
  195. package/packages/agentsam-workbench/src/shell/surfaceRegistry.ts +29 -0
  196. package/packages/agentsam-workbench/src/terminal/TerminalSurface.tsx +5 -0
  197. package/packages/agentsam-workbench/src/terminal/index.ts +1 -0
  198. package/packages/agentsam-workbench/src/timeline/GanttBoard.tsx +258 -0
  199. package/packages/agentsam-workbench/src/timeline/index.ts +1 -0
  200. package/packages/agentsam-workbench/tsconfig.json +13 -0
  201. package/packages/connectors/cloudflare/OAUTH_STORAGE_AUDIT.md +53 -0
  202. package/packages/connectors/cloudflare/package.json +3 -1
  203. package/packages/connectors/cloudflare/src/api-client.js +279 -0
  204. package/packages/connectors/cloudflare/src/capabilities.js +585 -0
  205. package/packages/connectors/cloudflare/src/credential.js +318 -0
  206. package/packages/connectors/cloudflare/src/families/brand-protection.js +123 -0
  207. package/packages/connectors/cloudflare/src/families/keyless.js +114 -0
  208. package/packages/connectors/cloudflare/src/families/pages.js +151 -0
  209. package/packages/connectors/cloudflare/src/families/scanner.js +123 -0
  210. package/packages/connectors/cloudflare/src/families/snippets.js +207 -0
  211. package/packages/connectors/cloudflare/src/families/tag-gateway.js +46 -0
  212. package/packages/connectors/cloudflare/src/families/tags.js +124 -0
  213. package/packages/connectors/cloudflare/src/families/token-validation.js +95 -0
  214. package/packages/connectors/cloudflare/src/families/workflows.js +156 -0
  215. package/packages/connectors/cloudflare/src/index.js +102 -265
  216. package/packages/connectors/cloudflare/src/oauth-persist.js +336 -0
  217. package/packages/connectors/cloudflare/src/owner.js +42 -12
  218. package/packages/connectors/cloudflare/src/permission-options.js +1064 -0
  219. package/packages/connectors/cloudflare/src/routes.js +309 -144
  220. package/packages/connectors/cloudflare/src/scope-catalog.js +345 -0
  221. package/packages/connectors/cloudflare/src/vault.js +2 -2
  222. package/packages/connectors/cloudflare/tests/capabilities.test.mjs +276 -0
  223. package/packages/connectors/cloudflare/tests/connector.test.mjs +26 -30
  224. package/packages/connectors/cloudflare/tests/oauth-persist.test.mjs +125 -0
  225. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +22 -2
  226. package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +10 -4
  227. package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +20 -0
  228. package/packages/identity/README.md +1 -1
  229. package/packages/identity/backend/README.md +1 -1
  230. package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +3 -2
  231. package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +48 -0
  232. package/packages/identity/package.json +4 -3
  233. package/packages/identity/scripts/local-identity-bridge.mjs +184 -0
  234. package/packages/identity/scripts/preview-auth-portal.mjs +7 -7
  235. package/packages/identity/src/adapters/cloudflare-d1/index.js +31 -2
  236. package/packages/identity/src/adapters/sqlite/index.js +4 -1
  237. package/packages/identity/src/contracts/auth-config.js +28 -8
  238. package/packages/identity/src/contracts/external-identity.js +1 -1
  239. package/packages/identity/src/contracts/provider.js +1 -0
  240. package/packages/identity/src/frontend/auth-portal/README.md +2 -1
  241. package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -5
  242. package/packages/identity/src/frontend/auth-portal/pages/reset.html +6 -5
  243. package/packages/identity/src/frontend/auth-portal/pages/signup.html +6 -5
  244. package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
  245. package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +207 -0
  246. package/packages/identity/src/index.js +16 -0
  247. package/packages/identity/src/migrations/0001_identity_core.sql +19 -2
  248. package/packages/identity/src/migrations/0003_accounts_ssot.sql +20 -0
  249. package/packages/identity/src/migrations/README.md +5 -2
  250. package/packages/identity/src/oauth/README.md +10 -5
  251. package/packages/identity/src/oauth/consent-view.js +388 -0
  252. package/packages/identity/src/oauth/credentials.js +31 -11
  253. package/packages/identity/src/oauth/google-desktop-exchange.js +173 -0
  254. package/packages/identity/src/providers/cloudflare/oauth.js +3 -4
  255. package/packages/identity/src/providers/cloudflare/profile.js +49 -14
  256. package/packages/identity/src/providers/iam/index.js +27 -5
  257. package/packages/identity/src/server/identity-service.js +31 -2
  258. package/packages/identity/src/server/worker-router.js +111 -81
  259. package/packages/identity/tests/auth-config.test.mjs +3 -2
  260. package/packages/identity/tests/identity-init-scaffold.test.mjs +3 -0
  261. package/packages/identity/tests/identity-service.test.mjs +16 -0
  262. package/packages/identity/tests/native-session-worker.test.mjs +64 -0
  263. package/packages/identity/tests/oauth-consent-view.test.mjs +106 -0
  264. package/packages/identity/tests/oauth-credentials.test.mjs +17 -4
  265. package/packages/identity/tests/oauth-presets-accounts-ssot.test.mjs +58 -0
  266. package/packages/identity/tests/preview-auth-portal.test.mjs +3 -3
  267. package/packages/runtime-protocol/src/index.js +154 -0
  268. package/packages/theme-scenes/README.md +164 -0
  269. package/packages/theme-scenes/package.json +53 -0
  270. package/packages/theme-scenes/src/blocks/index.js +30 -0
  271. package/packages/theme-scenes/src/contracts/index.js +286 -0
  272. package/packages/theme-scenes/src/demos/index.js +65 -0
  273. package/packages/theme-scenes/src/index.js +75 -0
  274. package/packages/theme-scenes/src/presets/index.js +263 -0
  275. package/packages/theme-scenes/src/runtime/compile.js +119 -0
  276. package/packages/theme-scenes/src/scenes/index.js +146 -0
  277. package/packages/theme-scenes/src/shell/index.js +47 -0
  278. package/packages/theme-scenes/src/themes/index.js +129 -0
  279. package/packages/theme-scenes/src/visuals/index.js +41 -0
  280. package/packages/theme-scenes/test/theme-scenes.test.mjs +179 -0
  281. package/packages/work-graph/src/index.js +34 -1
  282. package/packages/work-graph/src/renderers/gantt-model.js +24 -0
  283. package/packages/work-graph/test/work-graph.test.mjs +27 -7
  284. package/protocol/README.md +15 -7
  285. package/protocol/apps/agentsam.app.v1.schema.json +89 -7
  286. package/protocol/apps/agentsam.host-install.v1.schema.json +36 -0
  287. package/protocol/assets/README.md +9 -0
  288. package/protocol/assets/asset-record.v1.schema.json +64 -0
  289. package/protocol/runtime/agentsam.runtime.v1.schema.json +75 -0
  290. package/protocol/scoring/README.md +10 -0
  291. package/protocol/scoring/scorecard.v1.schema.json +65 -0
  292. package/protocol/ui/icon-registry.mjs +1 -0
  293. package/registry/cms-rust-machine-20260928/installable-products.json +31 -0
  294. package/registry/cms-rust-machine-20260928/manifest.json +22 -0
  295. package/registry/cms-rust-machine-20260928/migration.sql +237 -0
  296. package/registry/cms-rust-machine-20260928/receipt.json +21 -0
  297. package/registry/cms-rust-machine-20260928/receipt.sql +27 -0
  298. package/scripts/build_rapid_rust_cli.py +83 -0
  299. package/src/attachments/index.js +6 -0
  300. package/src/attachments/intake.js +235 -0
  301. package/src/capabilities/repository-snapshot.js +19 -2
  302. package/src/cli/command-catalog.js +8 -0
  303. package/src/cli.js +182 -26
  304. package/src/commands/account-auth.js +94 -8
  305. package/src/commands/app.js +307 -3
  306. package/src/commands/billing.js +127 -0
  307. package/src/commands/brand.js +74 -60
  308. package/src/commands/cheat-sheet.js +154 -0
  309. package/src/commands/cloudflare-login.js +222 -0
  310. package/src/commands/cloudflare.js +453 -23
  311. package/src/commands/codebaseindex.js +6 -1
  312. package/src/commands/compute.js +4 -0
  313. package/src/commands/connections.js +11 -5
  314. package/src/commands/credentials.js +116 -0
  315. package/src/commands/gcloud-auth.js +427 -0
  316. package/src/commands/google-cloud.js +375 -0
  317. package/src/commands/identity-init.js +2 -2
  318. package/src/commands/mcp.js +226 -33
  319. package/src/commands/ollama.js +3 -2
  320. package/src/commands/plugins.js +7 -2
  321. package/src/commands/product.js +36 -0
  322. package/src/commands/runtime-status.js +28 -9
  323. package/src/commands/runtime.js +313 -0
  324. package/src/commands/rust.js +24 -0
  325. package/src/commands/setup.js +279 -0
  326. package/src/commands/shell.js +16 -3
  327. package/src/commands/start-local.js +2 -2
  328. package/src/commands/terminal.js +171 -0
  329. package/src/commands/update.js +140 -0
  330. package/src/commands/whoami.js +329 -65
  331. package/src/features/resolve.js +1 -0
  332. package/src/index.js +4 -0
  333. package/src/indexing/ingest/inventory.js +254 -19
  334. package/src/indexing/ingest/materials.js +3 -9
  335. package/src/indexing/ingest/style-evidence.js +181 -0
  336. package/src/knowledge/source.js +3 -3
  337. package/src/lib/account-session.js +11 -4
  338. package/src/lib/app-authority.js +172 -0
  339. package/src/lib/auth.js +94 -21
  340. package/src/lib/core-client.js +5 -6
  341. package/src/lib/credentials-audit.js +451 -0
  342. package/src/lib/deploy/health.js +24 -6
  343. package/src/lib/detect-context.js +7 -1
  344. package/src/lib/google-cloud-connection.js +270 -0
  345. package/src/lib/google-cloud-inventory.js +385 -0
  346. package/src/lib/google-desktop-oauth.js +372 -0
  347. package/src/lib/google-studio-brokered-oauth.js +158 -0
  348. package/src/lib/identity-scaffold.js +24 -6
  349. package/src/lib/init-options.js +192 -0
  350. package/src/lib/local-scaffold.js +48 -16
  351. package/src/lib/provider-command-remediation.js +308 -0
  352. package/src/lib/provider-credentials.js +8 -0
  353. package/src/lib/scaffold/index.js +8 -2
  354. package/src/lib/scaffold/mcp-server.js +43 -0
  355. package/src/lib/scaffold/templates/mcp-server/index.js +397 -0
  356. package/src/lib/scaffold/templates/mcp-server/presets.js +39 -0
  357. package/src/lib/scaffold/wizards/cms.js +93 -0
  358. package/src/lib/scaffold/wizards/mcp-server.js +61 -0
  359. package/src/lib/setup/contract.js +26 -0
  360. package/src/lib/setup/discover.js +116 -0
  361. package/src/lib/setup/execute.js +205 -0
  362. package/src/lib/setup/planner.js +134 -0
  363. package/src/lib/setup/recipes.js +235 -0
  364. package/src/lib/setup/runtime-persist.js +197 -0
  365. package/src/lib/setup/runtime.js +394 -0
  366. package/src/lib/slash-commands.js +2 -0
  367. package/src/lib/terminal/machine-identity.js +95 -0
  368. package/src/lib/terminal-local.js +164 -0
  369. package/src/lib/terminal-scopes.js +52 -0
  370. package/src/lib/whoami-capabilities.js +184 -0
  371. package/src/local-pty/server.js +34 -5
  372. package/src/mcp/authority.js +58 -108
  373. package/src/mcp/client-adapters.js +68 -144
  374. package/src/mcp/client.js +142 -122
  375. package/src/mcp/cloudflare-bundles.js +225 -0
  376. package/src/mcp/index.js +12 -0
  377. package/src/plugins/cloudflare.js +1 -1
  378. package/src/providers/ollama-chat.js +2 -1
  379. package/src/sam/types.js +27 -2
  380. package/src/security/inventory.js +12 -2
  381. package/src/security/local-vault.js +2 -0
  382. package/src/security/scan.js +1 -1
  383. package/test/account-session.test.mjs +3 -3
  384. package/test/app-authority-context.test.mjs +32 -0
  385. package/test/cli/codebaseindex-plan-ux.test.mjs +1 -1
  386. package/test/cli/mcp-client.test.mjs +21 -10
  387. package/test/cli/runtime-persist.test.mjs +56 -0
  388. package/test/cli/rust-command.test.mjs +21 -0
  389. package/test/credentials-audit.test.mjs +113 -0
  390. package/test/deploy-health-scan.test.mjs +29 -1
  391. package/test/gcloud-auth.test.mjs +111 -0
  392. package/test/google-cloud-connection.test.mjs +83 -0
  393. package/test/google-cloud-inventory.test.mjs +64 -0
  394. package/test/init-options.test.mjs +35 -0
  395. package/test/integration/app-command.test.mjs +30 -0
  396. package/test/integration/cad-project.test.mjs +4 -1
  397. package/test/integration/cms-app-scaffold.test.mjs +71 -0
  398. package/test/integration/cms-site-tenancy-contract.test.mjs +3 -2
  399. package/test/integration/codebaseindex-ingest.test.mjs +48 -0
  400. package/test/integration/features-resolve.test.mjs +30 -11
  401. package/test/integration/inspect-path-cli.test.mjs +46 -0
  402. package/test/integration/inventory-evidence.test.mjs +125 -0
  403. package/test/integration/runtime-status.integration.test.mjs +2 -1
  404. package/test/knowledge.test.mjs +35 -1
  405. package/test/loopback-oauth.test.mjs +53 -0
  406. package/test/ollama.test.mjs +22 -0
  407. package/test/security.test.mjs +23 -0
  408. package/test/setup-planner.test.mjs +74 -0
  409. package/test/setup-runtime.test.mjs +51 -0
  410. package/test/terminal/local-pty.mock.test.mjs +3 -1
  411. package/test/terminal-machine-identity.test.mjs +88 -0
  412. package/test/whoami-resume.test.mjs +27 -6
  413. package/packages/agentsam-brand/test/brand-scan.test.mjs +0 -106
  414. package/packages/work-graph/prototype/README.md +0 -32
  415. package/packages/work-graph/prototype/data/demo-workgraph.js +0 -47
  416. package/packages/work-graph/prototype/renderers/timeline-model.js +0 -21
  417. package/packages/work-graph/prototype/renderers/workgraph-runtime.js +0 -38
  418. package/packages/work-graph/prototype-gnantt.html +0 -655
@@ -1,21 +1,116 @@
1
1
  # @inneranimalmedia/agentsam-sdk-brand
2
2
 
3
- Deterministic **Brand Intelligence** for AgentSam.
3
+ **Brand compiler** — not just an image optimizer CLI.
4
4
 
5
5
  ```text
6
- repository.snapshot → brand.scan → brand.resolve → brand.plan → (apply/verify)
6
+ drop anything → ingest/classify → brand.pack.json (source of truth)
7
+ │
8
+ ┌─────────────────┼─────────────────┐
9
+ ▼ ▼ ▼
10
+ localhost studio ZIP export production publish
7
11
  ```
8
12
 
9
- - **Brand ≠ Theme.** Theme is a projection; Brand is authority.
10
- - **No LLM required** for scan/resolve/plan skeleton.
11
- - **Same file authority** as security/knowledge (Merkle + gitignore via snapshot).
12
- - States stay separated: `observed` → `inferred` → `declared` → `resolved`.
13
+ ## BrandPack v2
14
+
15
+ `brand.pack.json` owns:
16
+
17
+ | Graph node | Purpose |
18
+ |---|---|
19
+ | `assets[]` | Role-tagged masters + semantic derivatives |
20
+ | `tokens` | color / type / space / radius / motion |
21
+ | `rules` | logo clearspace, forbidden ops, template requirements |
22
+ | `provenance` | source → transforms → sha256 |
23
+ | `delivery` | Images / Stream / R2 policy (`role_canonical`) |
24
+
25
+ ZIP, `studio.html`, CSS tokens, icons, and CF uploads are **compiled representations**.
26
+
27
+ ### CLI
28
+
29
+ ```bash
30
+ # Ingest folder, previous build zip/tar/gz, or HTML/CSS for token extraction
31
+ agentsam brand ingest ./exports --brand acme --template product-saas
32
+
33
+ # Compile dist + studio + zip export
34
+ agentsam brand build --from .agentsam/brand/packs/acme
35
+
36
+ # Preview studio (prefers studio.html)
37
+ agentsam brand preview --from .agentsam/brand/dist/acme
38
+
39
+ agentsam brand templates
40
+ agentsam brand roles
41
+ agentsam brand presets
42
+ ```
43
+
44
+ ### Asset roles (examples)
45
+
46
+ `logo.primary` · `favicon` · `icon.app` · `hero.landscape` · `social.og` · `product.raw` · `motion.hero` · `model.product` · `type.body` · `token.color`
47
+
48
+ A 512px logo and a 512px app icon are **different assets**.
49
+
50
+ ### Semantic derivatives
51
+
52
+ - **DERIVABLE** — system knows how to make it (often on-demand via Cloudflare Images)
53
+ - **MATERIALIZED** — file included in this pack export
54
+
55
+ Shared responsive ladder: `320…2560` — roles pick a subset. Logos get raster fallbacks (256/512/1024), not a giant ladder.
56
+
57
+ ### Format families
58
+
59
+ Logo/vector, raster, photography, favicon, app-icon, social, video, motion-graphics, 3D, fonts (licensing gate), tokens, theme, docs, archives (zip/tar/gz containers).
60
+
61
+ Fonts default to `licensing.redistributable: false` — never dumped into client ZIPs until confirmed.
62
+
63
+ ### Templates
64
+
65
+ `web-app` · `mobile-app` · `marketing-site` · `product-saas` · `spatial-3d`
66
+
67
+ ### V1 still works
68
+
69
+ ```bash
70
+ agentsam brand pack --brand acme --asset app-icon --source ./master.png --preset app-icon --out ./acme.zip
71
+ agentsam brand promote --brand acme --asset logo --source - --preset logo
72
+ ```
73
+
74
+ Delivery policy id: **`canonical_png`** / per-role **`role_canonical`**. Prefer high-quality masters; let Cloudflare Images negotiate AVIF/WebP.
75
+
76
+ No product brand defaults (`agentsam` as brand id is rejected in the wizard).
77
+
78
+ ## Image / media processors (pluggable)
79
+
80
+ **Do not** depend on abandoned `@squoosh/cli` (npm 0.7.3 — Node 12–16 only; crashes on Node 22+).
81
+
82
+ Public UX:
83
+
84
+ ```bash
85
+ agentsam brand optimize ./hero.png --role hero.landscape --target web
86
+ agentsam brand optimize ./logo.png --role logo.primary --processor sharp
87
+ agentsam brand processors # sharp | squoosh (binary) | native | cloudflare
88
+ ```
89
+
90
+ Internally:
91
+
92
+ ```text
93
+ Asset Pipeline
94
+ ├── sharp ← dependable Node path
95
+ ├── squoosh ← maintained Homebrew/Scoop binary (optional)
96
+ ├── native ← ImageMagick
97
+ ├── cloudflare ← edge DERIVABLE (retain master)
98
+ ├── wasm / go ← Studio preview / heavy queued jobs (scheduler hooks)
99
+ ```
100
+
101
+ Role-aware policies choose formats (logo → lossless/SVG path; hero → AVIF+WebP; screenshots → sharper WebP). Semantic delivery names (`acme-showroom-hero-1280.avif`) are aliases — `asset.id` stays the machine identity. Cloudflare custom metadata / R2 `customMetadata` / BrandPack own SEO+provenance — not EXIF alone.
102
+
103
+ ## Website composition (sibling package)
104
+
105
+ BrandPack owns **what the brand is**. Page experiences live in **`@inneranimalmedia/theme-scenes`**:
106
+
107
+ - `SECTION_CONTENT` → scene kinds (hero, bridge, product.demo, gallery, …)
108
+ - Route refs + asset roles (no hardcoded CDN / nav URLs in scenes)
109
+ - Demo adapters (`agentsam-mini-composer`, `database-editor`) — real product surfaces, not fake Meaux cards
110
+ - Themes: `foundation` → `inneranimal` → `agentsam` / `autodidact`
13
111
 
14
112
  ```bash
15
- agentsam brand scan --json
16
- agentsam brand resolve
17
- agentsam plan brand --goap
18
- agentsam brand --write # writes .agentsam/brand/{evidence,resolved,contract}.json
113
+ npm --prefix packages/theme-scenes test
19
114
  ```
20
115
 
21
- Progression (generic, not brand-only): `@inneranimalmedia/agentsam-sdk/progression`
116
+ See `packages/theme-scenes/README.md`. Studio shell (Moon Glass → Brand Studio) sits above both packages in a later tranche.
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import { runBrandAssetCommand, runBrandPromoteWizard } from '../src/index.js';
3
+ import { cancel, confirm, intro, isCancel, note, outro, select, text } from '@clack/prompts';
4
+
5
+ const code = await runBrandAssetCommand(process.argv.slice(2), {
6
+ runWizard: runBrandPromoteWizard,
7
+ prompts: { intro, outro, cancel, isCancel, select, text, confirm, note },
8
+ });
9
+ process.exitCode = typeof code === 'number' ? code : 0;
@@ -1,22 +1,54 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-sdk-brand",
3
3
  "version": "0.1.0",
4
- "private": true,
4
+ "description": "Deterministic Brand Intelligence + portable brand-asset promotion SDK for AgentSam (inspect, derive, plan, promote, publish, verify).",
5
5
  "type": "module",
6
- "description": "Deterministic Brand Intelligence for AgentSam — scan/resolve/contract evidence on shared repository.snapshot authority",
6
+ "license": "MIT",
7
+ "engines": {
8
+ "node": ">=22 <25"
9
+ },
10
+ "dependencies": {
11
+ "sharp": "^0.34.5"
12
+ },
7
13
  "main": "./src/index.js",
14
+ "bin": {
15
+ "agentsam-brand": "./bin/agentsam-brand.mjs"
16
+ },
8
17
  "exports": {
9
18
  ".": "./src/index.js",
10
19
  "./scan": "./src/scan.js",
11
20
  "./resolve": "./src/resolve.js",
12
21
  "./contract": "./src/contract.js",
13
22
  "./plan": "./src/plan.js",
14
- "./goap-actions": "./src/goap-actions.js"
23
+ "./goap-actions": "./src/goap-actions.js",
24
+ "./assets": "./src/index.js",
25
+ "./presets": "./src/presets/index.js",
26
+ "./cli": "./src/cli/controller.js",
27
+ "./package.json": "./package.json"
15
28
  },
29
+ "files": [
30
+ "bin",
31
+ "src",
32
+ "README.md"
33
+ ],
16
34
  "scripts": {
17
- "test": "node --test test/*.test.mjs"
35
+ "test": "node --test test/*.test.mjs",
36
+ "pack:dry": "npm pack --dry-run"
18
37
  },
19
- "engines": {
20
- "node": ">=22 <25"
21
- }
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/SamPrimeaux/agentsam-sdk.git",
41
+ "directory": "packages/agentsam-brand"
42
+ },
43
+ "publishConfig": {
44
+ "access": "restricted"
45
+ },
46
+ "keywords": [
47
+ "agentsam",
48
+ "brand",
49
+ "assets",
50
+ "promotion",
51
+ "r2",
52
+ "images"
53
+ ]
22
54
  }
@@ -0,0 +1,453 @@
1
+ /**
2
+ * Cloudflare Images delivery adapter.
3
+ *
4
+ * Prefer shared transport `@inneranimalmedia/agentsam-cloudflare-images` for
5
+ * credentials, delivery URLs, and HTTP. This Brand adapter retains BrandPack
6
+ * publish policy (canonical PNG) and will thin-wrap the shared package next.
7
+ *
8
+ * HARD RULE: An asset is "on Cloudflare Images" ONLY when POST
9
+ * /accounts/{account_id}/images/v1 returns success + non-empty result.id.
10
+ *
11
+ * Account-level identity (never infer from R2):
12
+ * CLOUDFLARE_ACCOUNT_ID — management/API identity (non-secret)
13
+ * CLOUDFLARE_IMAGES_ACCOUNT_HASH — delivery namespace (non-secret)
14
+ * CLOUDFLARE_IMAGES_API_TOKEN — secret Bearer credential (canonical)
15
+ * CLOUDFLARE_API_TOKEN — broader compatibility fallback
16
+ *
17
+ * R2 keys, WEBSITE_ASSETS bindings, and D1 rows are never evidence of Images.
18
+ */
19
+
20
+ /** Cloudflare-hosted Images accepts these inputs (plan-dependent for some). */
21
+ export const CLOUDFLARE_IMAGES_PLATFORM_INPUT_TYPES = Object.freeze([
22
+ 'image/png',
23
+ 'image/jpeg',
24
+ 'image/gif',
25
+ 'image/webp',
26
+ 'image/svg+xml',
27
+ 'image/heic',
28
+ 'image/avif',
29
+ ]);
30
+
31
+ /**
32
+ * Canonical PNG publishing policy (not a Cloudflare limitation):
33
+ * prefer a canonical PNG as the Images delivery source so CF can negotiate
34
+ * WebP/AVIF output. Explicit WebP/AVIF/SVG archives stay in storage (R2).
35
+ */
36
+ export const CANONICAL_PNG_DELIVERY_POLICY_TYPES = Object.freeze(['image/png']);
37
+
38
+ /** @deprecated Use CANONICAL_PNG_DELIVERY_POLICY_TYPES */
39
+ export const AGENTSAM_IMAGES_DELIVERY_POLICY_TYPES = CANONICAL_PNG_DELIVERY_POLICY_TYPES;
40
+
41
+ export function resolveCloudflareImagesCredentials(env = process.env) {
42
+ const accountId = String(env.CLOUDFLARE_ACCOUNT_ID || '').trim();
43
+ const accountHash = String(env.CLOUDFLARE_IMAGES_ACCOUNT_HASH || '').trim();
44
+ // Canonical least-privilege token first; broader session token as fallback.
45
+ // CLOUDFLARE_IMAGES_TOKEN retained as deprecated alias only.
46
+ const tokenSource = env.CLOUDFLARE_IMAGES_API_TOKEN
47
+ ? 'CLOUDFLARE_IMAGES_API_TOKEN'
48
+ : env.CLOUDFLARE_API_TOKEN
49
+ ? 'CLOUDFLARE_API_TOKEN'
50
+ : env.CLOUDFLARE_IMAGES_TOKEN
51
+ ? 'CLOUDFLARE_IMAGES_TOKEN'
52
+ : null;
53
+ const apiToken = tokenSource ? String(env[tokenSource] || '').trim() : '';
54
+ return {
55
+ accountId,
56
+ accountHash,
57
+ apiToken,
58
+ tokenEnv: tokenSource,
59
+ // Opaque credential — never validate by shape/prefix (cfat_ or otherwise)
60
+ tokenConfigured: Boolean(apiToken),
61
+ };
62
+ }
63
+
64
+ /** Public delivery base — derived from account hash, not independently configured. */
65
+ export function cloudflareImagesDeliveryBase(accountHash) {
66
+ const hash = String(accountHash || '').trim();
67
+ if (!hash) return null;
68
+ return `https://imagedelivery.net/${hash}`;
69
+ }
70
+
71
+ /**
72
+ * Construct a delivery URL only from verified Images identity.
73
+ * Prefer Cloudflare-returned variants[] over reconstruction when available.
74
+ */
75
+ export function cloudflareImageUrl({ accountHash, imageId, variant = 'public' } = {}) {
76
+ const hash = String(accountHash || '').trim();
77
+ const id = String(imageId || '').trim();
78
+ const v = String(variant || 'public').trim() || 'public';
79
+ if (!hash || !id) return null;
80
+ return `https://imagedelivery.net/${hash}/${id}/${v}`;
81
+ }
82
+
83
+ export function resolveCloudflareImagesConfig(env = process.env) {
84
+ const creds = resolveCloudflareImagesCredentials(env);
85
+ const deliveryBase = cloudflareImagesDeliveryBase(creds.accountHash);
86
+ return {
87
+ provider: 'cloudflare-images',
88
+ accountId: creds.accountId || null,
89
+ accountHash: creds.accountHash || null,
90
+ deliveryBase,
91
+ apiTokenConfigured: creds.tokenConfigured,
92
+ tokenEnv: creds.tokenEnv,
93
+ authMode: 'bearer_api_token',
94
+ requiredPermission: 'Account → Images → Write',
95
+ apiUploadPath: '/accounts/{account_id}/images/v1',
96
+ };
97
+ }
98
+
99
+ export class CloudflareImagesDeliveryAdapter {
100
+ constructor({
101
+ accountId,
102
+ accountHash,
103
+ apiToken,
104
+ env = process.env,
105
+ /**
106
+ * Default: canonical PNG-only delivery source.
107
+ * Pass CLOUDFLARE_IMAGES_PLATFORM_INPUT_TYPES to allow full CF input set.
108
+ */
109
+ acceptedContentTypes = [...CANONICAL_PNG_DELIVERY_POLICY_TYPES],
110
+ fetchImpl = globalThis.fetch,
111
+ } = {}) {
112
+ const resolved = resolveCloudflareImagesCredentials(env);
113
+ this.provider = 'cloudflare-images';
114
+ this.accountId = String(accountId ?? resolved.accountId ?? '').trim();
115
+ this.accountHash = String(accountHash ?? resolved.accountHash ?? '').trim();
116
+ this.apiToken = String(apiToken ?? resolved.apiToken ?? '').trim();
117
+ this.tokenEnv = apiToken
118
+ ? 'constructor'
119
+ : resolved.tokenEnv;
120
+ this.acceptedContentTypes = new Set(acceptedContentTypes);
121
+ this.policy = 'canonical_png';
122
+ this.fetchImpl = fetchImpl;
123
+ }
124
+
125
+ get deliveryBase() {
126
+ return cloudflareImagesDeliveryBase(this.accountHash);
127
+ }
128
+
129
+ authHeaders() {
130
+ return { Authorization: `Bearer ${this.apiToken}` };
131
+ }
132
+
133
+ /**
134
+ * Capability snapshot. `authorized` stays false until verifyConnection() succeeds.
135
+ */
136
+ async capabilities() {
137
+ const configured = Boolean(this.accountId && this.apiToken);
138
+ return {
139
+ provider: this.provider,
140
+ available: true,
141
+ configured,
142
+ authorized: false,
143
+ account_resolved: Boolean(this.accountId),
144
+ account_hash_resolved: Boolean(this.accountHash),
145
+ delivery_base: this.deliveryBase,
146
+ token_env: this.tokenEnv,
147
+ auth_mode: 'bearer_api_token',
148
+ required_permission: 'Account → Images → Write',
149
+ api_path: '/accounts/{account_id}/images/v1',
150
+ // Policy vs platform — do not conflate
151
+ delivery_policy_types: [...CANONICAL_PNG_DELIVERY_POLICY_TYPES],
152
+ /** @deprecated alias */
153
+ agentsam_delivery_policy_types: [...CANONICAL_PNG_DELIVERY_POLICY_TYPES],
154
+ cloudflare_platform_input_types: [...CLOUDFLARE_IMAGES_PLATFORM_INPUT_TYPES],
155
+ accepted_content_types: [...this.acceptedContentTypes],
156
+ policy: this.policy,
157
+ };
158
+ }
159
+
160
+ /**
161
+ * Live verify against Cloudflare Images API (stats).
162
+ * Env presence alone is never proof of authorization.
163
+ */
164
+ async verifyConnection() {
165
+ const config = {
166
+ account_id: this.accountId || null,
167
+ account_hash: this.accountHash || null,
168
+ delivery_base: this.deliveryBase,
169
+ token_env: this.tokenEnv,
170
+ auth_mode: 'bearer_api_token',
171
+ required_permission: 'Account → Images → Write',
172
+ };
173
+
174
+ if (!this.accountId || !this.apiToken) {
175
+ return {
176
+ ok: false,
177
+ provider: this.provider,
178
+ configured: false,
179
+ authorized: false,
180
+ reason: 'not_configured',
181
+ error: 'cloudflare_images_credentials_required',
182
+ hint: 'Set CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_IMAGES_API_TOKEN (Images Write)',
183
+ config,
184
+ };
185
+ }
186
+
187
+ const url = `https://api.cloudflare.com/client/v4/accounts/${this.accountId}/images/v1/stats`;
188
+ let res;
189
+ let body;
190
+ try {
191
+ res = await this.fetchImpl(url, {
192
+ method: 'GET',
193
+ headers: this.authHeaders(),
194
+ });
195
+ body = await res.json().catch(() => ({}));
196
+ } catch (err) {
197
+ return {
198
+ ok: false,
199
+ provider: this.provider,
200
+ configured: true,
201
+ authorized: false,
202
+ reason: 'network_error',
203
+ error: String(err?.message || err),
204
+ config,
205
+ };
206
+ }
207
+
208
+ const authorized = Boolean(res.ok && body?.success !== false);
209
+ return {
210
+ ok: authorized,
211
+ provider: this.provider,
212
+ configured: true,
213
+ authorized,
214
+ reason: authorized ? 'verified' : 'api_unauthorized',
215
+ error: authorized
216
+ ? null
217
+ : (body?.errors?.[0]?.message || `cf_images_verify_failed:${res.status}`),
218
+ http_status: res.status,
219
+ stats: authorized ? (body?.result || null) : null,
220
+ config: {
221
+ ...config,
222
+ // Mirror Local Studio / dashboard vocabulary
223
+ authentication: 'API token',
224
+ permission: authorized ? 'Images Write ✓' : 'Images Write unverified',
225
+ },
226
+ };
227
+ }
228
+
229
+ async supports({ contentType } = {}) {
230
+ const mime = String(contentType || '').toLowerCase();
231
+ return this.acceptedContentTypes.has(mime);
232
+ }
233
+
234
+ /**
235
+ * @returns {Promise<{
236
+ * ok: boolean,
237
+ * provider: 'cloudflare-images',
238
+ * status: 'planned'|'published'|'failed'|'skipped',
239
+ * provider_receipt?: object,
240
+ * error?: string,
241
+ * }>}
242
+ */
243
+ async upload({
244
+ filePath,
245
+ fileName,
246
+ contentType = 'image/png',
247
+ metadata = {},
248
+ dryRun = false,
249
+ sourceSha256 = null,
250
+ sourceStorage = null,
251
+ } = {}) {
252
+ const mime = String(contentType || metadata.contentType || 'image/png').toLowerCase();
253
+ if (!(await this.supports({ contentType: mime }))) {
254
+ return {
255
+ ok: true,
256
+ provider: this.provider,
257
+ status: 'skipped',
258
+ reason: 'canonical_png_delivery_policy',
259
+ content_type: mime,
260
+ note: 'Canonical PNG policy: prefer PNG as Images delivery source; other formats remain storage-only. Cloudflare itself accepts broader inputs.',
261
+ };
262
+ }
263
+
264
+ if (dryRun) {
265
+ return {
266
+ ok: true,
267
+ provider: this.provider,
268
+ status: 'planned',
269
+ dry_run: true,
270
+ provider_receipt: null,
271
+ account_id: this.accountId || null,
272
+ account_hash: this.accountHash || null,
273
+ source: sourceStorage || null,
274
+ };
275
+ }
276
+
277
+ if (!this.accountId || !this.apiToken) {
278
+ return {
279
+ ok: false,
280
+ provider: this.provider,
281
+ status: 'failed',
282
+ error: 'cloudflare_images_credentials_required',
283
+ reason: 'not_configured',
284
+ };
285
+ }
286
+
287
+ const fs = await import('node:fs');
288
+ const form = new FormData();
289
+ const buf = fs.readFileSync(filePath);
290
+ form.append('file', new Blob([buf], { type: mime }), fileName || 'image.png');
291
+ const metaPayload = {
292
+ ...metadata,
293
+ ...(sourceSha256 ? { source_sha256: String(sourceSha256).replace(/^sha256:/, '') } : {}),
294
+ };
295
+ if (Object.keys(metaPayload).length) {
296
+ form.append('metadata', JSON.stringify(metaPayload));
297
+ }
298
+
299
+ const url = `https://api.cloudflare.com/client/v4/accounts/${this.accountId}/images/v1`;
300
+ let res;
301
+ let body;
302
+ try {
303
+ res = await this.fetchImpl(url, {
304
+ method: 'POST',
305
+ headers: this.authHeaders(),
306
+ body: form,
307
+ });
308
+ body = await res.json().catch(() => ({}));
309
+ } catch (err) {
310
+ return {
311
+ ok: false,
312
+ provider: this.provider,
313
+ status: 'failed',
314
+ error: String(err?.message || err),
315
+ reason: 'network_error',
316
+ };
317
+ }
318
+
319
+ const imageId = body?.result?.id ? String(body.result.id).trim() : '';
320
+ const errCode = body?.errors?.[0]?.code;
321
+ const errMsg = body?.errors?.[0]?.message || '';
322
+ // Idempotent: CF Images 5409 Resource already exists — treat as skip, not fatal
323
+ if (errCode === 5409 || /already exists/i.test(errMsg)) {
324
+ const existingId = String(metadata?.id || metadata?.image_id || fileName || '').trim();
325
+ return {
326
+ ok: true,
327
+ provider: this.provider,
328
+ status: 'exists',
329
+ reason: 'resource_already_exists',
330
+ http_status: res.status,
331
+ error_code: 5409,
332
+ provider_receipt: existingId
333
+ ? {
334
+ account_id: this.accountId,
335
+ account_hash: this.accountHash || null,
336
+ delivery_base: this.deliveryBase,
337
+ image_id: existingId,
338
+ provider_asset_id: existingId,
339
+ variants: [],
340
+ note: 'Image id already present in Cloudflare Images; upload skipped',
341
+ }
342
+ : null,
343
+ note: 'Cloudflare Images id already exists (5409). Pass --force with a new --version or delete the remote id.',
344
+ };
345
+ }
346
+ if (!res.ok || body?.success === false || !imageId) {
347
+ return {
348
+ ok: false,
349
+ provider: this.provider,
350
+ status: 'failed',
351
+ error:
352
+ errMsg
353
+ || (!imageId && res.ok ? 'cloudflare_images_missing_result_id' : `cf_images_upload_failed:${res.status}`),
354
+ reason: !imageId && res.ok ? 'missing_result_id' : 'api_error',
355
+ http_status: res.status,
356
+ error_code: errCode ?? null,
357
+ };
358
+ }
359
+
360
+ const variants = Array.isArray(body.result?.variants) ? body.result.variants : [];
361
+ return {
362
+ ok: true,
363
+ provider: this.provider,
364
+ status: 'published',
365
+ provider_receipt: {
366
+ // Account-level + image-level identity — never from R2
367
+ account_id: this.accountId,
368
+ account_hash: this.accountHash || null,
369
+ delivery_base: this.deliveryBase,
370
+ image_id: imageId,
371
+ provider_asset_id: imageId,
372
+ filename: body.result?.filename || fileName || null,
373
+ // Receipt truth from Cloudflare — prefer over reconstructed URLs
374
+ variants,
375
+ uploaded_at: body.result?.uploaded || null,
376
+ requireSignedURLs: body.result?.requireSignedURLs ?? null,
377
+ source_sha256: sourceSha256 || null,
378
+ // Provenance only — NEVER evidence that Images ≡ R2
379
+ source: sourceStorage
380
+ ? {
381
+ storage_provider: sourceStorage.provider || null,
382
+ bucket: sourceStorage.bucket || null,
383
+ key: sourceStorage.key || null,
384
+ }
385
+ : null,
386
+ },
387
+ };
388
+ }
389
+
390
+ /** Fetch one image by id — used by integration verify. */
391
+ async get(imageId) {
392
+ if (!this.accountId || !this.apiToken || !imageId) {
393
+ return { ok: false, error: 'not_configured_or_missing_id' };
394
+ }
395
+ const url = `https://api.cloudflare.com/client/v4/accounts/${this.accountId}/images/v1/${encodeURIComponent(imageId)}`;
396
+ const res = await this.fetchImpl(url, {
397
+ headers: this.authHeaders(),
398
+ });
399
+ const body = await res.json().catch(() => ({}));
400
+ const id = body?.result?.id ? String(body.result.id) : '';
401
+ return {
402
+ ok: Boolean(res.ok && body?.success && id),
403
+ provider: this.provider,
404
+ provider_receipt: id
405
+ ? {
406
+ account_id: this.accountId,
407
+ account_hash: this.accountHash || null,
408
+ delivery_base: this.deliveryBase,
409
+ image_id: id,
410
+ provider_asset_id: id,
411
+ variants: body.result?.variants || [],
412
+ filename: body.result?.filename || null,
413
+ uploaded_at: body.result?.uploaded || null,
414
+ }
415
+ : null,
416
+ http_status: res.status,
417
+ };
418
+ }
419
+
420
+ async delete(imageId) {
421
+ if (!this.accountId || !this.apiToken || !imageId) {
422
+ return { ok: false, error: 'not_configured_or_missing_id' };
423
+ }
424
+ const url = `https://api.cloudflare.com/client/v4/accounts/${this.accountId}/images/v1/${encodeURIComponent(imageId)}`;
425
+ const res = await this.fetchImpl(url, {
426
+ method: 'DELETE',
427
+ headers: this.authHeaders(),
428
+ });
429
+ const body = await res.json().catch(() => ({}));
430
+ return { ok: Boolean(res.ok && body?.success !== false), http_status: res.status };
431
+ }
432
+ }
433
+
434
+ /** True only when a real Images publish receipt exists. */
435
+ export function isCloudflareImagesPublished(delivery) {
436
+ if (!delivery || delivery.provider !== 'cloudflare-images') return false;
437
+ if (delivery.status !== 'published') return false;
438
+ const id = delivery.provider_receipt?.provider_asset_id
439
+ || delivery.provider_receipt?.image_id
440
+ || delivery.provider_asset_id;
441
+ return Boolean(id && String(id).trim());
442
+ }
443
+
444
+ /**
445
+ * Canonical PNG delivery-source policy.
446
+ * Not a Cloudflare API limitation — CF accepts broader inputs.
447
+ * policy: 'canonical_png' | 'agentsam' (alias) | 'platform'
448
+ */
449
+ export function mayUploadToCloudflareImages(contentType, { policy = 'canonical_png' } = {}) {
450
+ const mime = String(contentType || '').toLowerCase();
451
+ if (policy === 'platform') return CLOUDFLARE_IMAGES_PLATFORM_INPUT_TYPES.includes(mime);
452
+ return CANONICAL_PNG_DELIVERY_POLICY_TYPES.includes(mime);
453
+ }