@inneranimalmedia/agentsam-sdk 2.6.5 → 2.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/AGENTSAM.md +29 -0
  2. package/apps/README.md +5 -0
  3. package/apps/cad-creator/README.md +4 -4
  4. package/apps/cad-creator/shared/cad/package.json +1 -1
  5. package/apps/client-cms-editor/AGENTS.md +12 -7
  6. package/apps/client-cms-editor/README.md +76 -48
  7. package/apps/client-cms-editor/agentsam.app.json +26 -9
  8. package/apps/client-cms-editor/backend/package.json +20 -3
  9. package/apps/client-cms-editor/backend/src/api/client.ts +134 -101
  10. package/apps/client-cms-editor/backend/src/index.ts +1 -1
  11. package/apps/client-cms-editor/backend/src/model.ts +11 -115
  12. package/apps/client-cms-editor/backend/src/preview/bridge.ts +1 -1
  13. package/apps/client-cms-editor/backend/tsconfig.json +6 -1
  14. package/apps/client-cms-editor/bin/agentsam-cms.js +262 -0
  15. package/apps/client-cms-editor/bin/agentsam-cms.mjs +2 -228
  16. package/apps/client-cms-editor/frontend/package.json +16 -7
  17. package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +9 -41
  18. package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +19 -174
  19. package/apps/client-cms-editor/frontend/src/adapters/heuristic.ts +29 -0
  20. package/apps/client-cms-editor/frontend/src/adapters/http.ts +628 -0
  21. package/apps/client-cms-editor/frontend/src/adapters/memory.ts +510 -0
  22. package/apps/client-cms-editor/frontend/src/editor/CmsEditor.tsx +213 -0
  23. package/apps/client-cms-editor/frontend/src/editor/CmsEditorProvider.tsx +20 -0
  24. package/apps/client-cms-editor/frontend/src/editor/canvas/PreviewCanvas.tsx +53 -0
  25. package/apps/client-cms-editor/frontend/src/{CmsEditor.tsx → editor/legacy/CmsEditorPrototype.tsx} +52 -23
  26. package/apps/client-cms-editor/frontend/src/editor/useCmsEditorController.ts +218 -0
  27. package/apps/client-cms-editor/frontend/src/index.ts +19 -5
  28. package/apps/client-cms-editor/frontend/src/lib/agent-host.ts +24 -0
  29. package/apps/client-cms-editor/frontend/src/main.tsx +82 -8
  30. package/apps/client-cms-editor/frontend/src/mount.tsx +92 -30
  31. package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +1 -1
  32. package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +8 -8
  33. package/apps/client-cms-editor/frontend/src/styles/studio.css +55 -3
  34. package/apps/client-cms-editor/frontend/tsconfig.json +12 -1
  35. package/apps/client-cms-editor/frontend/vite.config.ts +12 -0
  36. package/apps/client-cms-editor/package-lock.json +973 -134
  37. package/apps/client-cms-editor/package.json +118 -6
  38. package/apps/client-cms-editor/reference/harvest/HARVEST_RECEIPT.json +201 -0
  39. package/apps/client-cms-editor/reference/harvest/PROVENANCE_HISTORY.txt +10 -0
  40. package/apps/client-cms-editor/reference/harvest/README.md +8 -0
  41. package/apps/client-cms-editor/reference/harvest/plans/ARCHIVE-INTAKE.md +135 -0
  42. package/apps/client-cms-editor/reference/harvest/plans/CHATGPT-IDENTITY-HARVEST.md +83 -0
  43. package/apps/client-cms-editor/reference/harvest/plans/CMS-EDITOR-HARVEST.md +166 -0
  44. package/apps/client-cms-editor/reference/harvest/plans/HARVEST-INDEX.md +196 -0
  45. package/apps/client-cms-editor/reference/harvest/plans/INNERANIMALS-CONTENT-001.md +137 -0
  46. package/apps/client-cms-editor/reference/harvest/plans/NO-IMPLICIT-SIDE-EFFECTS.md +87 -0
  47. package/apps/client-cms-editor/reference/harvest/plans/STOREFRONT-SURFACE-MAP.md +140 -0
  48. package/apps/client-cms-editor/reference/harvest/plans/THEME-INNERANIMALS-HARVEST.md +137 -0
  49. package/apps/client-cms-editor/reference/harvest/plans/TOOLING-LAB.md +63 -0
  50. package/apps/client-cms-editor/reference/harvest/plans/harvest-manifest.json +97 -0
  51. package/apps/client-cms-editor/reference/harvest/plans/local-cms-harvest-schema.sql +328 -0
  52. package/apps/client-cms-editor/shared/cms/package.json +17 -7
  53. package/apps/client-cms-editor/shared/cms/src/adapter.ts +204 -0
  54. package/apps/client-cms-editor/shared/cms/src/agent-context.ts +7 -5
  55. package/apps/client-cms-editor/shared/cms/src/editor-types.ts +32 -0
  56. package/apps/client-cms-editor/shared/cms/src/host.ts +82 -0
  57. package/apps/client-cms-editor/shared/cms/src/index.ts +4 -0
  58. package/apps/client-cms-editor/shared/cms/src/map.ts +115 -0
  59. package/apps/client-cms-editor/shared/cms/src/starter-pack.ts +158 -0
  60. package/contracts/source-types.v1.json +353 -0
  61. package/docs/CMS_CONTEXTUAL_COMPOSER.md +1 -1
  62. package/docs/PRODUCT_LIFECYCLE.md +566 -0
  63. package/docs/THEME_REFINERY.md +2 -2
  64. package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +40 -20
  65. package/docs/content-studio/REVISION_GATE_2026-09-27.md +1 -1
  66. package/docs/plans/LOCAL_STUDIO_DESKTOP_RELEASE_2026-09-29.md +150 -0
  67. package/migrations/d1/0017_identity_native_oauth.sql +21 -0
  68. package/native/agentsam-machine/Cargo.lock +426 -0
  69. package/native/agentsam-machine/Cargo.toml +9 -0
  70. package/native/agentsam-machine/cli/Cargo.toml +14 -0
  71. package/native/agentsam-machine/cli/src/main.rs +77 -0
  72. package/native/agentsam-machine/core/Cargo.toml +15 -0
  73. package/native/agentsam-machine/core/src/assets.rs +790 -0
  74. package/native/agentsam-machine/core/src/bound.rs +298 -0
  75. package/native/agentsam-machine/core/src/enrich.rs +706 -0
  76. package/native/agentsam-machine/core/src/frontend.rs +442 -0
  77. package/native/agentsam-machine/core/src/lib.rs +1086 -0
  78. package/native/agentsam-machine/core/src/liquid.rs +528 -0
  79. package/native/agentsam-machine/core/src/source_types.rs +78 -0
  80. package/package.json +51 -21
  81. package/packages/agentsam-brand/README.md +1 -1
  82. package/packages/agentsam-brand/package.json +4 -4
  83. package/packages/agentsam-brand/src/index.js +1 -1
  84. package/packages/agentsam-contracts/package.json +13 -3
  85. package/packages/agentsam-contracts/src/tools.ts +22 -0
  86. package/packages/agentsam-errors/package.json +13 -3
  87. package/packages/agentsam-knowledge/package.json +18 -4
  88. package/packages/agentsam-knowledge/src/autorag/index.js +10 -3
  89. package/packages/agentsam-knowledge/src/backends/index.js +33 -1
  90. package/packages/agentsam-knowledge/test/autorag.test.mjs +60 -1
  91. package/packages/agentsam-nav/package.json +24 -6
  92. package/packages/agentsam-queue-control/README.md +1 -1
  93. package/packages/agentsam-queue-control/package.json +7 -2
  94. package/packages/agentsam-rapid-rust/src/main.rs +1 -1
  95. package/packages/agentsam-repository/package.json +13 -3
  96. package/packages/agentsam-repository/src/source-types.js +8 -0
  97. package/packages/agentsam-vault/package.json +14 -4
  98. package/packages/agentsam-workbench/package.json +15 -4
  99. package/packages/agentsam-workbench/src/agent/ToolPermissionRequest.tsx +94 -0
  100. package/packages/agentsam-workbench/src/agent/index.ts +2 -0
  101. package/packages/agentsam-workbench/src/agent/tool-permission.css +134 -0
  102. package/packages/connectors/cloudflare/package.json +13 -3
  103. package/packages/connectors/cloudflare/src/api-client.js +3 -2
  104. package/packages/connectors/cloudflare/src/families/vectorize.js +127 -0
  105. package/packages/connectors/cloudflare/src/index.js +1 -0
  106. package/packages/heuristic-theme/README.md +2 -2
  107. package/packages/heuristic-theme/package.json +8 -3
  108. package/packages/heuristic-theme/src/registry.js +2 -2
  109. package/packages/heuristic-theme/src/theme.js +1 -1
  110. package/packages/heuristic-theme/test/theme.test.mjs +1 -1
  111. package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
  112. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +27 -7
  113. package/packages/identity/README.md +2 -2
  114. package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +18 -15
  115. package/packages/identity/migrations/apply-portable.js +109 -0
  116. package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +1 -1
  117. package/packages/identity/migrations/sqlite/005_identity_company_native.sql +52 -0
  118. package/packages/identity/package.json +27 -6
  119. package/packages/identity/schema/agentsam.identity/manifest.json +101 -0
  120. package/packages/identity/scripts/local-identity-bridge.mjs +13 -7
  121. package/packages/identity/scripts/preview-auth-portal.mjs +6 -6
  122. package/packages/identity/src/adapters/cloudflare-d1/index.js +8 -401
  123. package/packages/identity/src/adapters/iam-compat/index.js +540 -0
  124. package/packages/identity/src/adapters/portable-d1/index.js +18 -0
  125. package/packages/identity/src/adapters/portable-store.js +479 -0
  126. package/packages/identity/src/adapters/sqlite/index.js +13 -312
  127. package/packages/identity/src/contracts/auth-config.js +0 -1
  128. package/packages/identity/src/contracts/identity-store.js +56 -5
  129. package/packages/identity/src/contracts/provider.js +1 -0
  130. package/packages/identity/src/contracts/sign-in-options.js +104 -0
  131. package/packages/identity/src/core/constants.js +1 -1
  132. package/packages/identity/src/core/session-policy.js +31 -0
  133. package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -6
  134. package/packages/identity/src/frontend/auth-portal/pages/reset.html +5 -5
  135. package/packages/identity/src/frontend/auth-portal/pages/signup.html +5 -5
  136. package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
  137. package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +6 -37
  138. package/packages/identity/src/index.js +28 -1
  139. package/packages/identity/src/migrations/README.md +23 -23
  140. package/packages/identity/src/oauth/README.md +1 -1
  141. package/packages/identity/src/oauth/credentials.js +10 -11
  142. package/packages/identity/src/oauth/google-desktop-exchange.js +195 -27
  143. package/packages/identity/src/oauth/iam-platform.js +21 -9
  144. package/packages/identity/src/oauth/native-handoff.js +136 -0
  145. package/packages/identity/src/providers/chatgpt/headers.js +65 -0
  146. package/packages/identity/src/providers/chatgpt/index.js +86 -0
  147. package/packages/identity/src/providers/chatgpt/mapper.js +43 -0
  148. package/packages/identity/src/providers/chatgpt/paths.js +45 -0
  149. package/packages/identity/src/providers/github/oauth.js +1 -2
  150. package/packages/identity/src/providers/github/profile.js +16 -2
  151. package/packages/identity/src/providers/index.js +11 -3
  152. package/packages/identity/src/server/identity-service.js +2 -1
  153. package/packages/identity/src/server/worker-router.js +71 -18
  154. package/packages/identity/tests/chatgpt-provider.test.mjs +75 -0
  155. package/packages/identity/tests/google-desktop-identity-login.test.mjs +210 -0
  156. package/packages/identity/tests/identity-init-scaffold.test.mjs +15 -4
  157. package/packages/identity/tests/lane1-identity-store-parity.test.mjs +527 -0
  158. package/packages/identity/tests/lane1-packed-consumer.test.mjs +175 -0
  159. package/packages/identity/tests/native-oauth-handoff.test.mjs +292 -0
  160. package/packages/identity/tests/oauth-credentials.test.mjs +4 -4
  161. package/packages/identity/tests/preview-auth-portal.test.mjs +4 -2
  162. package/packages/identity/tests/session-routes-policy.test.mjs +13 -1
  163. package/packages/identity/tests/worker-runtime-boundary.test.mjs +11 -0
  164. package/packages/providers/completeful/package.json +7 -2
  165. package/packages/theme-church-site/package.json +17 -6
  166. package/packages/theme-church-site/src/harvest.json +4 -2
  167. package/packages/theme-church-site/src/index.js +7 -3
  168. package/packages/theme-church-site/test/theme.test.mjs +4 -2
  169. package/packages/theme-companions-site/package.json +17 -6
  170. package/packages/theme-companions-site/src/harvest.json +4 -2
  171. package/packages/theme-companions-site/src/index.js +7 -3
  172. package/packages/theme-companions-site/test/theme.test.mjs +4 -2
  173. package/packages/theme-floors-site/package.json +17 -6
  174. package/packages/theme-floors-site/src/harvest.json +4 -2
  175. package/packages/theme-floors-site/src/index.js +7 -3
  176. package/packages/theme-floors-site/test/theme.test.mjs +4 -2
  177. package/packages/theme-fuelnfree-site/package.json +17 -6
  178. package/packages/theme-fuelnfree-site/src/harvest.json +4 -2
  179. package/packages/theme-fuelnfree-site/src/index.js +7 -3
  180. package/packages/theme-fuelnfree-site/test/theme.test.mjs +4 -2
  181. package/packages/theme-handyman-site/package.json +17 -6
  182. package/packages/theme-handyman-site/src/harvest.json +4 -2
  183. package/packages/theme-handyman-site/src/index.js +7 -3
  184. package/packages/theme-handyman-site/test/theme.test.mjs +4 -2
  185. package/packages/theme-insurance-site/package.json +17 -6
  186. package/packages/theme-insurance-site/src/harvest.json +4 -2
  187. package/packages/theme-insurance-site/src/index.js +7 -3
  188. package/packages/theme-insurance-site/test/theme.test.mjs +4 -2
  189. package/packages/theme-scenes/README.md +1 -1
  190. package/packages/theme-scenes/package.json +4 -3
  191. package/packages/theme-scenes/src/registry.js +187 -0
  192. package/packages/theme-shinshu-site/package.json +17 -6
  193. package/packages/theme-shinshu-site/src/harvest.json +4 -2
  194. package/packages/theme-shinshu-site/src/index.js +7 -3
  195. package/packages/theme-shinshu-site/test/theme.test.mjs +4 -2
  196. package/packages/work-graph/package.json +14 -4
  197. package/protocol/FILEMETA_V1.md +2 -2
  198. package/protocol/capabilities/manifest.json +1 -1
  199. package/protocol/database/agentsam.schema-pack.v1.schema.json +72 -0
  200. package/protocol/presets/catalog.json +2 -2
  201. package/protocol/theme-refinery/lineage-registry.json +105 -0
  202. package/protocol/theme-refinery/product-metadata.schema.json +21 -1
  203. package/skills/grok-auth/SKILL.md +110 -0
  204. package/skills/grok-auth/agentsam.skill.json +25 -0
  205. package/skills/grok-auth/references/grok-identity.md +64 -0
  206. package/skills/grok-auth/references/per-user-data.md +49 -0
  207. package/skills/grok-auth/references/prewired-and-env.md +54 -0
  208. package/skills/grok-auth/references/session-ui.md +133 -0
  209. package/skills/grok-auth/references/sign-in-methods.md +55 -0
  210. package/skills/grok-auth/references/wiring.md +71 -0
  211. package/skills/grok-building-games/SKILL.md +213 -0
  212. package/skills/grok-building-games/agentsam.skill.json +25 -0
  213. package/skills/grok-building-games/references/3d-libs.md +64 -0
  214. package/skills/grok-building-games/references/ai-pathfinding.md +122 -0
  215. package/skills/grok-building-games/references/audio.md +129 -0
  216. package/skills/grok-building-games/references/babylon.md +202 -0
  217. package/skills/grok-building-games/references/collision-physics.md +122 -0
  218. package/skills/grok-building-games/references/ecs-architecture.md +111 -0
  219. package/skills/grok-building-games/references/game-feel-juice.md +110 -0
  220. package/skills/grok-building-games/references/genres/board-card-chess.md +89 -0
  221. package/skills/grok-building-games/references/genres/endless-runner.md +83 -0
  222. package/skills/grok-building-games/references/genres/fps.md +105 -0
  223. package/skills/grok-building-games/references/genres/platformer-2d.md +97 -0
  224. package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +131 -0
  225. package/skills/grok-building-games/references/genres/racing-kart.md +106 -0
  226. package/skills/grok-building-games/references/genres/topdown-twin-stick.md +97 -0
  227. package/skills/grok-building-games/references/genres/tower-defense.md +84 -0
  228. package/skills/grok-building-games/references/genres/voxel-minecraft.md +89 -0
  229. package/skills/grok-building-games/references/input.md +139 -0
  230. package/skills/grok-building-games/references/phaser.md +277 -0
  231. package/skills/grok-building-games/references/procedural-generation.md +141 -0
  232. package/skills/grok-building-games/references/save-persistence.md +108 -0
  233. package/skills/grok-building-games/references/threejs-foundational.md +148 -0
  234. package/skills/grok-controls/SKILL.md +274 -0
  235. package/skills/grok-controls/agentsam.skill.json +25 -0
  236. package/skills/grok-design-ui/SKILL.md +122 -0
  237. package/skills/grok-design-ui/agentsam.skill.json +25 -0
  238. package/skills/grok-design-ui/references/animations.md +379 -0
  239. package/skills/grok-design-ui/references/performance.md +88 -0
  240. package/skills/grok-design-ui/references/refined-ui.md +384 -0
  241. package/skills/grok-design-ui/references/surfaces.md +247 -0
  242. package/skills/grok-design-ui/references/typography.md +123 -0
  243. package/skills/grok-game-animation-frames/SKILL.md +84 -0
  244. package/skills/grok-game-animation-frames/agentsam.skill.json +25 -0
  245. package/skills/grok-game-asset-core/SKILL.md +69 -0
  246. package/skills/grok-game-asset-core/agentsam.skill.json +25 -0
  247. package/skills/grok-game-character-consistency/SKILL.md +69 -0
  248. package/skills/grok-game-character-consistency/agentsam.skill.json +25 -0
  249. package/skills/grok-game-tilesets/SKILL.md +65 -0
  250. package/skills/grok-game-tilesets/agentsam.skill.json +25 -0
  251. package/skills/grok-game-ui-icons/SKILL.md +56 -0
  252. package/skills/grok-game-ui-icons/agentsam.skill.json +25 -0
  253. package/skills/grok-generate2dmap/LICENSE +21 -0
  254. package/skills/grok-generate2dmap/SKILL.md +120 -0
  255. package/skills/grok-generate2dmap/SOURCE.md +6 -0
  256. package/skills/grok-generate2dmap/agentsam.skill.json +25 -0
  257. package/skills/grok-generate2dmap/references/deliverables.md +101 -0
  258. package/skills/grok-generate2dmap/references/layered-map-contract.md +209 -0
  259. package/skills/grok-generate2dmap/references/map-strategies.md +341 -0
  260. package/skills/grok-generate2dmap/references/object-production-gate.md +24 -0
  261. package/skills/grok-generate2dmap/references/pipeline.md +149 -0
  262. package/skills/grok-generate2dmap/references/prop-pack-contract.md +174 -0
  263. package/skills/grok-generate2dmap/references/side-scroll-stages.md +29 -0
  264. package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +157 -0
  265. package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +369 -0
  266. package/skills/grok-generate2dsprite/LICENSE +21 -0
  267. package/skills/grok-generate2dsprite/SKILL.md +313 -0
  268. package/skills/grok-generate2dsprite/SOURCE.md +6 -0
  269. package/skills/grok-generate2dsprite/agentsam.skill.json +25 -0
  270. package/skills/grok-generate2dsprite/references/modes.md +124 -0
  271. package/skills/grok-generate2dsprite/references/prompt-rules.md +315 -0
  272. package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +1031 -0
  273. package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +109 -0
  274. package/skills/grok-imagine/SKILL.md +201 -0
  275. package/skills/grok-imagine/agentsam.skill.json +25 -0
  276. package/skills/grok-multiplayer-p2p/SKILL.md +111 -0
  277. package/skills/grok-multiplayer-p2p/agentsam.skill.json +25 -0
  278. package/skills/grok-multiplayer-p2p/references/react-binding.md +144 -0
  279. package/skills/grok-multiplayer-p2p/references/signaling-relay.md +269 -0
  280. package/skills/grok-neon/SKILL.md +157 -0
  281. package/skills/grok-neon/agentsam.skill.json +25 -0
  282. package/skills/grok-og/SKILL.md +102 -0
  283. package/skills/grok-og/agentsam.skill.json +25 -0
  284. package/skills/grok-og/references/brand-pass.md +53 -0
  285. package/skills/grok-og/references/custom-card.md +107 -0
  286. package/skills/grok-og/references/favicon-and-icons.md +48 -0
  287. package/skills/grok-og/references/og-type-contract.md +18 -0
  288. package/skills/grok-og/references/placeholder-card.md +21 -0
  289. package/skills/grok-og/references/x-banner.md +41 -0
  290. package/skills/grok-threejs/SKILL.md +67 -0
  291. package/skills/grok-threejs/agentsam.skill.json +25 -0
  292. package/skills/grok-threejs/references/llms-full.txt +2780 -0
  293. package/skills/grok-video2dsprite/LICENSE +21 -0
  294. package/skills/grok-video2dsprite/SKILL.md +236 -0
  295. package/skills/grok-video2dsprite/SOURCE.md +6 -0
  296. package/skills/grok-video2dsprite/agentsam.skill.json +25 -0
  297. package/skills/grok-video2dsprite/references/pipeline.md +90 -0
  298. package/skills/grok-video2dsprite/references/prompt-rules.md +63 -0
  299. package/skills/grok-video2dsprite/scripts/video2dsprite.py +490 -0
  300. package/skills/grok-xai-api/SKILL.md +152 -0
  301. package/skills/grok-xai-api/agentsam.skill.json +25 -0
  302. package/src/cli/command-catalog.js +46 -4
  303. package/src/cli/dispatch.js +1 -0
  304. package/src/cli.js +10 -0
  305. package/src/cloudflare/runtime-status.js +2 -1
  306. package/src/commands/autorag.js +67 -13
  307. package/src/commands/cheat-sheet.js +29 -4
  308. package/src/commands/codebaseindex.js +45 -2
  309. package/src/commands/knowledge.js +59 -2
  310. package/src/commands/machine-binary.js +103 -0
  311. package/src/commands/machine.js +137 -0
  312. package/src/commands/security.js +67 -4
  313. package/src/commands/setup.js +33 -16
  314. package/src/commands/status.js +8 -1
  315. package/src/features/resolve.js +1 -0
  316. package/src/knowledge/engine.js +21 -2
  317. package/src/knowledge/runtime-discovery.js +127 -0
  318. package/src/lib/identity-scaffold.js +53 -13
  319. package/src/lib/setup/recipes.js +1 -1
  320. package/src/models/discovery.js +40 -22
  321. package/src/models/inventory-core.d.ts +105 -0
  322. package/src/models/inventory-core.js +54 -6
  323. package/src/security/logs.js +3 -0
  324. package/src/ui/cli/help.js +41 -0
  325. package/test/apps-scaffold-contract.test.mjs +3 -2
  326. package/test/cli/api-key-env-whoami.test.mjs +2 -2
  327. package/test/cli/catalog-authority.test.mjs +64 -0
  328. package/test/cli/machine-command.test.mjs +34 -0
  329. package/test/fixtures/project-authority/customer-app/.agentsam/app.json +5 -0
  330. package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +1 -0
  331. package/test/fixtures/project-authority/customer-app/wrangler.toml +17 -0
  332. package/test/integration/autorag-project-authority.integration.test.mjs +51 -0
  333. package/test/integration/autorag-runtime-discovery.test.mjs +107 -0
  334. package/test/integration/cms-app-scaffold.test.mjs +37 -31
  335. package/test/integration/cms-site-tenancy-contract.test.mjs +28 -17
  336. package/test/integration/codebaseindex-ingest.test.mjs +41 -0
  337. package/test/integration/database-hosted-honesty.test.mjs +49 -0
  338. package/test/integration/desktop-keychain-boundary.test.mjs +45 -0
  339. package/test/integration/hosted-work-host-authority.test.mjs +47 -0
  340. package/test/integration/inventory-eligibility.test.mjs +59 -0
  341. package/test/integration/local-provider-bridge.test.mjs +65 -0
  342. package/test/integration/local-studio-settings-production.test.mjs +40 -0
  343. package/test/integration/lockfile-sync.test.mjs +26 -0
  344. package/test/integration/provider-env-cli.test.mjs +13 -3
  345. package/test/integration/runtime-status.integration.test.mjs +16 -1
  346. package/test/integration/theme-package-registry.test.mjs +31 -0
  347. package/test/repository-snapshot-view.test.mjs +2 -2
  348. package/test/security.test.mjs +14 -0
  349. package/test/terminal-machine-identity.test.mjs +2 -2
  350. package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +0 -145
  351. package/packages/agentsam-nav/dist/Nav.d.ts +0 -43
  352. package/packages/agentsam-nav/dist/NavCollapsible.d.ts +0 -10
  353. package/packages/agentsam-nav/dist/NavContent.d.ts +0 -2
  354. package/packages/agentsam-nav/dist/NavFooter.d.ts +0 -2
  355. package/packages/agentsam-nav/dist/NavGroup.d.ts +0 -3
  356. package/packages/agentsam-nav/dist/NavHeader.d.ts +0 -2
  357. package/packages/agentsam-nav/dist/NavMenu.d.ts +0 -22
  358. package/packages/agentsam-nav/dist/NavProvider.d.ts +0 -35
  359. package/packages/agentsam-nav/dist/NavTrigger.d.ts +0 -2
  360. package/packages/agentsam-nav/dist/Surfaces.d.ts +0 -41
  361. package/packages/agentsam-nav/dist/browser.d.ts +0 -11
  362. package/packages/agentsam-nav/dist/browser.global.js +0 -132
  363. package/packages/agentsam-nav/dist/browser.js +0 -613
  364. package/packages/agentsam-nav/dist/contracts.d.ts +0 -76
  365. package/packages/agentsam-nav/dist/index.d.ts +0 -11
  366. package/packages/agentsam-nav/dist/index.js +0 -614
  367. package/packages/agentsam-nav/dist/legacy.css +0 -83
  368. package/packages/agentsam-nav/dist/shell.css +0 -113
  369. package/packages/agentsam-nav/dist/theme.css +0 -113
  370. package/packages/agentsam-nav/dist/utils.d.ts +0 -1
  371. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +0 -670
@@ -5,9 +5,15 @@ import { fileURLToPath } from 'node:url';
5
5
  const SDK_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
6
6
  const IDENTITY_PKG = path.join(SDK_ROOT, 'packages', 'identity');
7
7
  const AUTH_PAGES_DIR = path.join(IDENTITY_PKG, 'src', 'frontend', 'auth-portal', 'pages');
8
- const MIGRATION_FILE = path.join(IDENTITY_PKG, 'src', 'migrations', '0001_identity_core.sql');
8
+ const PORTABLE_SQL_DIR = path.join(IDENTITY_PKG, 'migrations', 'sqlite');
9
9
  const BRANDING_SCRIPT = path.join(IDENTITY_PKG, 'src', 'frontend', 'auth-portal', 'shared', 'company-branding.js');
10
10
 
11
+ const PORTABLE_SCAFFOLD_FILES = [
12
+ '001_identity_core.sql',
13
+ '002_identity_oauth_client.sql',
14
+ '005_identity_company_native.sql',
15
+ ];
16
+
11
17
  /**
12
18
  * @param {{ projectName: string, brandName?: string, logoUrl?: string, sdkVersion?: string, provider?: string }} config
13
19
  * @returns {Record<string, string>}
@@ -19,7 +25,10 @@ export function buildIdentityAppScaffold(config) {
19
25
  const sdkVersion = config.sdkVersion || 'alpha';
20
26
  const provider = config.provider || 'email';
21
27
 
22
- const migrationSql = `${fs.readFileSync(MIGRATION_FILE, 'utf8')}\n${buildCompanySeedSql({ brandName, logoUrl })}\n`;
28
+ const portableSql = PORTABLE_SCAFFOLD_FILES
29
+ .map((file) => fs.readFileSync(path.join(PORTABLE_SQL_DIR, file), 'utf8'))
30
+ .join('\n\n');
31
+ const migrationSql = `${portableSql}\n${buildCompanySeedSql({ brandName, logoUrl })}\n`;
23
32
  const loginHtml = injectBrandingScript(applyBrandTokens(fs.readFileSync(path.join(AUTH_PAGES_DIR, 'login.html'), 'utf8'), {
24
33
  brandName,
25
34
  logoUrl,
@@ -43,8 +52,8 @@ export function buildIdentityAppScaffold(config) {
43
52
  scripts: {
44
53
  dev: 'wrangler dev',
45
54
  deploy: 'wrangler deploy',
46
- 'db:migrate:local': `wrangler d1 execute ${projectName} --local --file=migrations/0001_identity_core.sql`,
47
- 'db:migrate': `wrangler d1 execute ${projectName} --remote --file=migrations/0001_identity_core.sql`,
55
+ 'db:migrate:local': `wrangler d1 execute ${projectName} --local --file=migrations/0001_identity_portable.sql`,
56
+ 'db:migrate': `wrangler d1 execute ${projectName} --remote --file=migrations/0001_identity_portable.sql`,
48
57
  preview: 'npx agentsam identity preview --open',
49
58
  },
50
59
  dependencies: {
@@ -61,6 +70,9 @@ export function buildIdentityAppScaffold(config) {
61
70
  main = "backend/src/index.js"
62
71
  compatibility_date = "2024-06-01"
63
72
 
73
+ [vars]
74
+ IDENTITY_ADAPTER_PROFILE = "portable"
75
+
64
76
  [assets]
65
77
  directory = "app/frontend"
66
78
  binding = "ASSETS"
@@ -76,7 +88,7 @@ migrations_dir = "migrations"
76
88
  files['.env.example'] = `# Minted at install/build — secrets via wrangler secret put (never commit)
77
89
  # IAM_CLIENT_ID= # plaintext var (public by OAuth design)
78
90
  # IAM_CLIENT_SECRET= # wrangler secret put only
79
- # IAM_ORIGIN=https://inneranimalmedia.com
91
+ # IAM_ORIGIN=
80
92
 
81
93
  # Web browser OAuth (BYOK) — takes /api/oauth/{google|github}/start when set
82
94
  # GOOGLE_CLIENT_ID=
@@ -103,11 +115,12 @@ migrations_dir = "migrations"
103
115
 
104
116
  files['README.md'] = `# ${brandName} — identity app
105
117
 
106
- Boring scaffold: **app/frontend** (auth UI) + **backend** (Worker API) + **migrations** (D1).
118
+ Boring scaffold: **app/frontend** (auth UI) + **backend** (Worker API) + **migrations** (portable \`identity_*\` D1).
107
119
 
108
120
  Provider template: \`${provider}\` (see \`agentsam identity plan --provider ${provider}\`).
109
121
 
110
- **Account SSOT:** \`accounts\` (row of record). \`account_identities\` is IdP linkage only.
122
+ **Schema:** portable \`agentsam.identity\` pack (\`identity_users\`, \`identity_sessions\`, \`identity_companies\`, …).
123
+ Not the hosted IAM \`accounts\` / \`auth_users\` / \`company\` shape.
111
124
 
112
125
  ## Quick start
113
126
 
@@ -135,13 +148,13 @@ npm run dev
135
148
  \`\`\`
136
149
  app/frontend/ Auth portal HTML + dashboard stub
137
150
  backend/src/ Cloudflare Worker (identity routes)
138
- migrations/ D1 schema (+ default \`company\` row)
151
+ migrations/ Portable identity_* schema (+ default identity_companies row)
139
152
 
140
153
  Branding: \`GET /api/company\` (public). Update with \`PATCH /api/company\` when signed in.
141
154
  \`\`\`
142
155
  `;
143
156
 
144
- files['migrations/0001_identity_core.sql'] = migrationSql;
157
+ files['migrations/0001_identity_portable.sql'] = migrationSql;
145
158
 
146
159
  files['app/frontend/auth/login.html'] = loginHtml;
147
160
  files['app/frontend/auth/signup.html'] = signupHtml;
@@ -190,10 +203,31 @@ Branding: \`GET /api/company\` (public). Update with \`PATCH /api/company\` when
190
203
  `;
191
204
 
192
205
  files['backend/src/index.js'] = `import { handleIdentityWorkerRequest } from '@inneranimalmedia/agentsam-sdk/identity/server/worker-router';
206
+ import { IDENTITY_ROUTE_IDS } from '@inneranimalmedia/agentsam-sdk/identity';
207
+ import { createRouteRegistry, defineRouteProjection } from '@inneranimalmedia/agentsam-sdk/identity';
208
+
209
+ const app = { id: '${projectName}' };
210
+ const routeRegistry = createRouteRegistry([
211
+ defineRouteProjection({
212
+ appId: app.id,
213
+ routes: {
214
+ [IDENTITY_ROUTE_IDS.LOGIN]: '/auth/login',
215
+ [IDENTITY_ROUTE_IDS.SIGNUP]: '/auth/signup',
216
+ [IDENTITY_ROUTE_IDS.RESET]: '/auth/reset',
217
+ [IDENTITY_ROUTE_IDS.RECOVERY]: '/auth/reset',
218
+ [IDENTITY_ROUTE_IDS.APP_AUTHENTICATED]: '/dashboard/',
219
+ [IDENTITY_ROUTE_IDS.OAUTH_CALLBACK]: '/api/oauth/:provider/callback',
220
+ },
221
+ }),
222
+ ]);
193
223
 
194
224
  export default {
195
225
  async fetch(request, env, ctx) {
196
- return handleIdentityWorkerRequest(request, env);
226
+ return handleIdentityWorkerRequest(request, env, {
227
+ app,
228
+ routeRegistry,
229
+ identityProfile: 'portable',
230
+ });
197
231
  },
198
232
  };
199
233
  `;
@@ -202,10 +236,15 @@ export default {
202
236
  }
203
237
 
204
238
  function applyBrandTokens(html, { brandName, logoUrl }) {
239
+ // Package HTML ships neutral portable defaults; scaffold stamps the app brand.
205
240
  return html
206
241
  .replace(/Inner Animal Media/g, brandName)
207
242
  .replace(/AgentSam/g, brandName)
243
+ .replace(/<h1 data-company-tagline>Welcome<\/h1>/g, `<h1 data-company-tagline>${brandName}</h1>`)
244
+ .replace(/<span data-company-name>App<\/span>/g, `<span data-company-name>${brandName}</span>`)
245
+ .replace(/alt="Sign in"/g, `alt="${brandName}"`)
208
246
  .replace(/src="\/shared\/agentsam-mark\.svg"/g, `src="${logoUrl}"`)
247
+ .replace(/src="\/shared\/app-icon\.png"/g, `src="${logoUrl}"`)
209
248
  .replace(/src="\/brand\/[^"]*"/g, `src="${logoUrl}"`)
210
249
  .replace(/href="\/brand\/[^"]*"/g, `href="${logoUrl}"`);
211
250
  }
@@ -221,9 +260,9 @@ function sqlLiteral(value) {
221
260
 
222
261
  function buildCompanySeedSql({ brandName, logoUrl }) {
223
262
  const ts = Math.floor(Date.now() / 1000);
224
- return `-- Default company row (branding SSOT for portal + dashboard)
225
- INSERT OR IGNORE INTO company (
226
- id, slug, name, logo_url, auth_bg_color, primary_color, created_at, updated_at
263
+ return `-- Default company row (branding SSOT for portal + dashboard) — portable identity_companies
264
+ INSERT OR IGNORE INTO identity_companies (
265
+ id, slug, name, logo_url, auth_bg_color, primary_color, support_email, created_at, updated_at
227
266
  ) VALUES (
228
267
  'co_default',
229
268
  'default',
@@ -231,6 +270,7 @@ INSERT OR IGNORE INTO company (
231
270
  ${sqlLiteral(logoUrl)},
232
271
  '#050508',
233
272
  '#007AFF',
273
+ ${sqlLiteral('support@example.test')},
234
274
  ${ts},
235
275
  ${ts}
236
276
  );`;
@@ -39,7 +39,7 @@ export const imageRasterTransformCapability = {
39
39
  provider: 'npm',
40
40
  packages: ['sharp'],
41
41
  notes: [
42
- 'Sharp is the portable default (declared dependency of @inneranimalmedia/agentsam-sdk-brand).',
42
+ 'Sharp is the portable default (declared dependency of @inneranimalmedia/agentsam-brand).',
43
43
  'Optional enrichment: Homebrew imagemagick for ICNS / exotic formats.',
44
44
  'Brand packs: agentsam brand promote → pack → preview → optional publish',
45
45
  ' agentsam brand pack --brand acme --asset app-icon --source ./master.png --preset app-icon --out ./acme.zip',
@@ -100,15 +100,9 @@ function baseRecord(provider, id, values = {}) {
100
100
 
101
101
  function openAIModelCapabilities(id) {
102
102
  const fallback = fallbackRecord('openai', id);
103
- if (fallback?.capabilities) return {};
104
- if (/^text-embedding-/i.test(id)) return { agent_runtime: false, embeddings: true };
105
- if (/^(?:gpt-image|chatgpt-image|gpt-audio|gpt-realtime|sora|tts|whisper|omni-moderation)/i.test(id)) {
106
- return { agent_runtime: false };
107
- }
108
- if (/^(?:gpt-(?:4o|4\.1|5|6)|o[1-9])/i.test(id)) {
109
- return { agent_runtime: true, responses: true };
110
- }
111
- return { agent_runtime: false };
103
+ // /v1/models proves credential-scoped availability but does not expose
104
+ // per-model modality / Responses compatibility. Never guess from names.
105
+ return fallback?.capabilities ? {} : {};
112
106
  }
113
107
 
114
108
  async function fetchJson(fetchImpl, url, init) {
@@ -157,8 +151,8 @@ export async function discoverAnthropicModels(apiKey, fetchImpl = fetch) {
157
151
  return baseRecord('anthropic', id, {
158
152
  label: clean(row?.display_name) || id,
159
153
  source_url: 'https://api.anthropic.com/v1/models',
160
- capabilities: { messages: true, function_calling: true, prompt_caching: true },
161
- metadata: { created_at: row?.created_at || null, type: row?.type || null },
154
+ capabilities: { messages: true },
155
+ metadata: { created_at: row?.created_at || null, type: row?.type || null, capability_source: 'provider_endpoint_contract' },
162
156
  });
163
157
  })
164
158
  .filter(Boolean);
@@ -179,6 +173,8 @@ export async function discoverGeminiModels(apiKey, fetchImpl = fetch) {
179
173
  .map((row) => {
180
174
  const id = clean(row?.baseModelId || row?.name).replace(/^models\//, '');
181
175
  if (!id) return null;
176
+ const providerDescription = clean(row?.description);
177
+ const specializedOutput = /(?:text[- ]to[- ]speech|\btts\b|image generation|generate images?|transcription|transcribe|audio generation)/i.test(providerDescription);
182
178
  return baseRecord('gemini', id, {
183
179
  label: clean(row?.displayName) || id,
184
180
  context_window: positiveInt(row?.inputTokenLimit),
@@ -187,12 +183,15 @@ export async function discoverGeminiModels(apiKey, fetchImpl = fetch) {
187
183
  source_url: 'https://generativelanguage.googleapis.com/v1beta/models',
188
184
  capabilities: {
189
185
  generate_content: true,
190
- function_calling: true,
186
+ text_output: !specializedOutput,
191
187
  thinking: row?.thinking === true,
192
188
  },
193
189
  metadata: {
194
190
  version: row?.version || null,
191
+ description: providerDescription || null,
195
192
  supported_generation_methods: row?.supportedGenerationMethods || [],
193
+ capability_source: 'provider_api',
194
+ specialized_output: specializedOutput,
196
195
  },
197
196
  });
198
197
  })
@@ -238,22 +237,39 @@ function xaiPricing(row) {
238
237
  export async function discoverXaiModels(apiKey, fetchImpl = fetch) {
239
238
  if (!clean(apiKey)) return failure('credential unavailable', false);
240
239
  try {
241
- const body = await fetchJson(fetchImpl, 'https://api.x.ai/v1/models', {
242
- headers: { authorization: `Bearer ${clean(apiKey)}` },
243
- });
240
+ const auth = { authorization: 'Bearer ' + clean(apiKey) };
241
+ const body = await fetchJson(fetchImpl, 'https://api.x.ai/v1/models', { headers: auth });
242
+ let languageRows = [];
243
+ try {
244
+ const languageBody = await fetchJson(fetchImpl, 'https://api.x.ai/v1/language-models', { headers: auth });
245
+ languageRows = Array.isArray(languageBody?.models) ? languageBody.models : [];
246
+ } catch {
247
+ // Keep full availability even if capability discovery is temporarily unavailable.
248
+ }
249
+ const languageById = new Map(languageRows.map((row) => [clean(row?.id), row]).filter(([id]) => id));
244
250
  const models = (Array.isArray(body?.data) ? body.data : [])
245
251
  .map((row) => {
246
252
  const id = clean(row?.id);
247
- if (!id || /image|video|voice|embedding/i.test(id)) return null;
248
- return baseRecord('grok', id, {
249
- context_window: positiveInt(row?.context_length),
253
+ if (!id) return null;
254
+ const language = languageById.get(id) || null;
255
+ const outputModalities = Array.isArray(language?.output_modalities)
256
+ ? language.output_modalities.map(clean).filter(Boolean)
257
+ : [];
258
+ return baseRecord('xai', id, {
259
+ context_window: positiveInt(language?.context_length ?? row?.context_length),
250
260
  pricing: xaiPricing(row),
251
261
  source_url: 'https://api.x.ai/v1/models',
252
- capabilities: { responses: true, function_calling: true, prompt_caching: true },
262
+ capabilities: {
263
+ responses: Boolean(language),
264
+ text_output: Boolean(language) && outputModalities.includes('text'),
265
+ },
253
266
  metadata: {
254
- aliases: row?.aliases || [],
255
- created: row?.created || null,
256
- owned_by: row?.owned_by || null,
267
+ aliases: row?.aliases || language?.aliases || [],
268
+ created: row?.created || language?.created || null,
269
+ owned_by: row?.owned_by || language?.owned_by || null,
270
+ input_modalities: Array.isArray(language?.input_modalities) ? language.input_modalities : [],
271
+ output_modalities: outputModalities,
272
+ capability_source: language ? 'provider_api_language_models' : 'provider_api_models_only',
257
273
  },
258
274
  });
259
275
  })
@@ -288,6 +304,7 @@ export async function discoverCursorModels(apiKey, fetchImpl = fetch) {
288
304
  aliases: Array.isArray(row?.aliases) ? row.aliases : [],
289
305
  parameters: params,
290
306
  variants: Array.isArray(row?.variants) ? row.variants : [],
307
+ capability_source: 'provider_api',
291
308
  },
292
309
  });
293
310
  })
@@ -332,6 +349,7 @@ export async function discoverCloudflareModels(apiToken, accountId, fetchImpl =
332
349
  task,
333
350
  author: clean(row?.author) || null,
334
351
  description: clean(row?.description) || null,
352
+ capability_source: 'provider_api_task',
335
353
  },
336
354
  });
337
355
  })
@@ -0,0 +1,105 @@
1
+ export type CredentialPlane = "machine" | "studio_vault" | "mixed" | "platform" | string;
2
+
3
+ export interface ProviderCredentialResolution {
4
+ configured: boolean;
5
+ value?: string;
6
+ source?: string | null;
7
+ error?: string | null;
8
+ account_id?: string | null;
9
+ }
10
+
11
+ export interface DiscoveredModelRecord {
12
+ provider: string;
13
+ provider_model_id: string;
14
+ model_id?: string;
15
+ model_key: string;
16
+ label: string;
17
+ availability: string;
18
+ availability_source?: string | null;
19
+ context_window?: number | null;
20
+ max_output_tokens?: number | null;
21
+ reasoning_efforts?: string[];
22
+ service_tiers?: string[];
23
+ capabilities?: Record<string, unknown>;
24
+ metadata?: Record<string, unknown>;
25
+ source?: Record<string, unknown>;
26
+ }
27
+
28
+ export interface CredentialScopedInventory {
29
+ schemaVersion: string;
30
+ generatedAt: string;
31
+ authority: string;
32
+ credential_plane: CredentialPlane;
33
+ providers: Array<{
34
+ id: string;
35
+ label: string;
36
+ configured: boolean;
37
+ source: string | null;
38
+ credentialError: string | null;
39
+ }>;
40
+ discovery: Record<string, {
41
+ attempted: boolean;
42
+ ok: boolean;
43
+ error: string | null;
44
+ returnedModelCount: number;
45
+ curation?: string;
46
+ }>;
47
+ providerModels: Record<string, DiscoveredModelRecord[]>;
48
+ availableModels: DiscoveredModelRecord[];
49
+ }
50
+
51
+ export const INVENTORY_API_PROVIDERS: readonly Readonly<{
52
+ id: string;
53
+ label: string;
54
+ service: string;
55
+ env: string;
56
+ aliases?: readonly string[];
57
+ }>[];
58
+
59
+ export const WORKERS_AI_CURATED_MODEL_IDS: readonly string[];
60
+
61
+ export function providerIdForService(serviceName: unknown): string | null;
62
+ export function filterWorkersAiCurated(models?: DiscoveredModelRecord[], options?: { curated?: boolean }): DiscoveredModelRecord[];
63
+ export function makeMapCredentialResolver(
64
+ credentialByProvider: Map<string, { value: string; source?: string; account_id?: string }>,
65
+ ): (providerId: string) => Promise<ProviderCredentialResolution>;
66
+ export function collectCredentialScopedInventory(options: {
67
+ fetchImpl?: typeof fetch;
68
+ credentialPlane?: CredentialPlane;
69
+ curateWorkersAi?: boolean;
70
+ discoverRemote?: boolean;
71
+ resolveCredential: (providerId: string) => ProviderCredentialResolution | Promise<ProviderCredentialResolution>;
72
+ }): Promise<CredentialScopedInventory>;
73
+ export function sanitizeInventoryForClient(status?: Partial<CredentialScopedInventory>): {
74
+ schemaVersion?: string;
75
+ generatedAt?: string;
76
+ authority?: string;
77
+ credential_plane?: CredentialPlane;
78
+ providers: CredentialScopedInventory["providers"];
79
+ discovery: CredentialScopedInventory["discovery"];
80
+ availableModels: Array<{
81
+ provider: string;
82
+ model_id: string;
83
+ model_key: string | null;
84
+ label: string;
85
+ availability: string;
86
+ availability_source: string | null;
87
+ context_window: number | null;
88
+ reasoning_efforts: string[];
89
+ service_tiers: string[];
90
+ capabilities: Record<string, unknown>;
91
+ chat_eligible: boolean;
92
+ eligibility_reason: string | null;
93
+ eligibility_source: string;
94
+ }>;
95
+ };
96
+ export function modelChatEligibility(row?: DiscoveredModelRecord): {
97
+ chat_eligible: boolean;
98
+ eligibility_reason: string | null;
99
+ eligibility_source: string;
100
+ };
101
+ export function assertModelAvailableForProvider(
102
+ inventory: { availableModels?: Array<Record<string, unknown>> },
103
+ provider: string,
104
+ modelId: string,
105
+ ): Record<string, unknown>;
@@ -7,7 +7,7 @@ export const INVENTORY_API_PROVIDERS = Object.freeze([
7
7
  { id: 'openai', label: 'OpenAI', service: 'openai', env: 'OPENAI_API_KEY' },
8
8
  { id: 'anthropic', label: 'Anthropic', service: 'anthropic', env: 'ANTHROPIC_API_KEY' },
9
9
  { id: 'gemini', label: 'Gemini', service: 'gemini', env: 'GEMINI_API_KEY' },
10
- { id: 'grok', label: 'Grok / xAI', service: 'xai', env: 'XAI_API_KEY', aliases: ['xai', 'grok'] },
10
+ { id: 'xai', label: 'Grok / xAI', service: 'xai', env: 'XAI_API_KEY', aliases: ['grok'] },
11
11
  { id: 'cursor', label: 'Cursor', service: 'cursor', env: 'CURSOR_API_KEY' },
12
12
  { id: 'cloudflare', label: 'Cloudflare', service: 'cloudflare', env: 'CLOUDFLARE_API_TOKEN' },
13
13
  ]);
@@ -29,8 +29,8 @@ const SERVICE_TO_PROVIDER = Object.freeze({
29
29
  openai: 'openai',
30
30
  anthropic: 'anthropic',
31
31
  gemini: 'gemini',
32
- xai: 'grok',
33
- grok: 'grok',
32
+ xai: 'xai',
33
+ grok: 'xai',
34
34
  cursor: 'cursor',
35
35
  cloudflare: 'cloudflare',
36
36
  });
@@ -70,6 +70,41 @@ export function makeMapCredentialResolver(credentialByProvider) {
70
70
  };
71
71
  }
72
72
 
73
+ const CHAT_ADAPTER_PROVIDERS = new Set(['openai', 'anthropic', 'gemini', 'xai', 'cloudflare']);
74
+
75
+ export function modelChatEligibility(row = {}) {
76
+ const rawProvider = String(row.provider || '').trim().toLowerCase();
77
+ const provider = rawProvider === 'grok' ? 'xai' : rawProvider;
78
+ const caps = row.capabilities && typeof row.capabilities === 'object' ? row.capabilities : {};
79
+ const metadata = row.metadata && typeof row.metadata === 'object' ? row.metadata : {};
80
+ const source = String(metadata.capability_source || (row.source?.fallback?.url ? 'provider_reference' : 'provider_api'));
81
+
82
+ if (!CHAT_ADAPTER_PROVIDERS.has(provider)) {
83
+ return { chat_eligible: false, eligibility_reason: 'provider_adapter_unavailable', eligibility_source: source };
84
+ }
85
+ if (caps.embeddings === true) {
86
+ return { chat_eligible: false, eligibility_reason: 'embedding_model', eligibility_source: source };
87
+ }
88
+ if (caps.agent_runtime === false) {
89
+ return { chat_eligible: false, eligibility_reason: 'capability_excludes_chat', eligibility_source: source };
90
+ }
91
+
92
+ const positive =
93
+ (provider === 'openai' && caps.responses === true && caps.agent_runtime === true)
94
+ || (provider === 'anthropic' && caps.messages === true)
95
+ || (provider === 'gemini' && caps.generate_content === true && caps.text_output === true)
96
+ || (provider === 'xai' && caps.responses === true && caps.text_output === true)
97
+ || (provider === 'cloudflare' && caps.workers_ai === true && caps.agent_runtime === true && caps.embeddings !== true);
98
+
99
+ if (positive) {
100
+ return { chat_eligible: true, eligibility_reason: null, eligibility_source: source };
101
+ }
102
+ if (metadata.specialized_output === true || caps.text_output === false) {
103
+ return { chat_eligible: false, eligibility_reason: 'specialized_output_model', eligibility_source: source };
104
+ }
105
+ return { chat_eligible: false, eligibility_reason: 'capability_unknown', eligibility_source: source };
106
+ }
107
+
73
108
  /**
74
109
  * Merge vault credentials (preferred) with optional platform env credentials.
75
110
  * Never returns secret material in the inventory result.
@@ -131,6 +166,15 @@ export async function collectCredentialScopedInventory(options = {}) {
131
166
  };
132
167
  }
133
168
 
169
+ function sanitizeDiscoveryError(error) {
170
+ const raw = String(error || '').trim();
171
+ if (!raw) return null;
172
+ if (/\b(?:401|403)\b|unauthoriz|forbidden|invalid[_ -]?(?:api[_ -]?)?key|credential.*reject/i.test(raw)) {
173
+ return 'provider_credential_rejected';
174
+ }
175
+ return 'provider_discovery_failed';
176
+ }
177
+
134
178
  export function sanitizeInventoryForClient(status = {}) {
135
179
  const out = {
136
180
  schemaVersion: status.schemaVersion,
@@ -142,11 +186,14 @@ export function sanitizeInventoryForClient(status = {}) {
142
186
  label: row.label,
143
187
  configured: row.configured === true,
144
188
  source: row.source || null,
145
- credentialError: row.credentialError || null,
189
+ credentialError: sanitizeDiscoveryError(row.credentialError),
146
190
  })),
147
- discovery: status.discovery || {},
191
+ discovery: Object.fromEntries(Object.entries(status.discovery || {}).map(([provider, row]) => [provider, {
192
+ ...row,
193
+ error: sanitizeDiscoveryError(row?.error),
194
+ }])) ,
148
195
  availableModels: (status.availableModels || []).map((row) => ({
149
- provider: row.provider,
196
+ provider: row.provider === 'grok' ? 'xai' : row.provider,
150
197
  model_id: row.provider_model_id || row.model_id,
151
198
  model_key: row.model_key || null,
152
199
  label: row.label || row.provider_model_id || row.model_id,
@@ -156,6 +203,7 @@ export function sanitizeInventoryForClient(status = {}) {
156
203
  reasoning_efforts: row.reasoning_efforts || [],
157
204
  service_tiers: row.service_tiers || [],
158
205
  capabilities: row.capabilities || {},
206
+ ...modelChatEligibility(row),
159
207
  })),
160
208
  };
161
209
  if (status.local) {
@@ -17,6 +17,9 @@ export function triageLog(text) {
17
17
  else if (/\b([1-9]\d*)\s+(?:(?:low|moderate|high|critical)\s+(?:severity\s+)?)?vulnerabilit/i.test(raw) || /npm audit fix/i.test(raw)) add('audit', line, 'rescan-current-lockfile');
18
18
  else if (/ExperimentalWarning/.test(raw)) add('experimental-runtime', line, 'informational', { blocking: false });
19
19
  else if (/new (?:release|(?:patch |minor |major )?version).*(?:pip|npm)|(?:pip|npm).*new (?:release|version)/i.test(raw)) add('tool-update', line, 'informational', { blocking: false });
20
+ // package.json allowScripts is the project authority; a user/global .npmrc allow-scripts clash is expected noise.
21
+ else if (/npm (?:warn|warning) allow-scripts.*declares its own allowScripts/i.test(raw)) add('configuration', line, 'informational', { blocking: false });
22
+ else if (/npm (?:warn|warning) allow-scripts/i.test(raw)) add('configuration', line, 'review-package-manager-config');
20
23
  else if (/npm (?:warn|warning).*config/i.test(raw)) add('configuration', line, 'review-package-manager-config');
21
24
  else if (/\b(?:warning|warn|npm ERR!|npm error)\b/i.test(raw)) add('unclassified-warning', line, 'review-log-at-source');
22
25
  }
@@ -89,6 +89,42 @@ export function renderHelpOverview(version, options = {}) {
89
89
  return lines.join('\n');
90
90
  }
91
91
 
92
+ export function renderCommandHelp(entryOrId, version = String(pkg.version || 'unknown')) {
93
+ const entry = typeof entryOrId === 'string' ? getCliCommand(entryOrId) : entryOrId;
94
+ if (!entry) return renderHelpOverview(version);
95
+
96
+ const usage = entry.usage?.length ? entry.usage : [`agentsam ${entry.id}`];
97
+ const lines = [
98
+ '',
99
+ ' ' + pc.bold('Agent Sam') + ' ' + pc.dim('v' + version) + ' ' + pc.dim('·') + ' ' + pc.bold(entry.id),
100
+ ' ' + pc.dim(entry.summary),
101
+ '',
102
+ ' ' + pc.bold('Usage'),
103
+ ...usage.map((row) => ' ' + pc.cyan(row)),
104
+ ];
105
+
106
+ if (entry.options?.length) {
107
+ const width = Math.min(32, Math.max(...entry.options.map((row) => row.flag.length), 0));
108
+ lines.push(
109
+ '',
110
+ ' ' + pc.bold('Options'),
111
+ ...entry.options.map((row) => ' ' + pc.cyan(row.flag.padEnd(width)) + ' ' + pc.dim(row.description)),
112
+ );
113
+ }
114
+
115
+ if (entry.aliases?.length) {
116
+ lines.push('', ' ' + pc.bold('Aliases'), ' ' + entry.aliases.map((alias) => pc.cyan(`agentsam ${alias}`)).join(' · '));
117
+ }
118
+ if (entry.skill) {
119
+ lines.push('', ' ' + pc.dim(`Skill: agentsam skills ${entry.skill}`));
120
+ }
121
+ if (entry.operation) {
122
+ lines.push(' ' + pc.dim(`Operation: ${entry.operation}`));
123
+ }
124
+ lines.push('');
125
+ return lines.join('\n');
126
+ }
127
+
92
128
  export function renderHelpTopic(topic, version) {
93
129
  if (!topic) return renderHelpOverview(version);
94
130
  const skillHint = topic.rows?.[0]?.[1]?.includes('skill')
@@ -153,6 +189,11 @@ export async function runHelp(argv = [], options = {}) {
153
189
 
154
190
  const topicArg = args.find((arg) => !arg.startsWith('-'));
155
191
  if (topicArg) {
192
+ const command = getCliCommand(topicArg);
193
+ if (command) {
194
+ write(renderCommandHelp(command, version));
195
+ return;
196
+ }
156
197
  const topic = resolveHelpTopic(topicArg);
157
198
  if (!topic) {
158
199
  write(renderHelpOverview(version));
@@ -63,7 +63,7 @@ test('CAD creator app package is curated for third-party installation', () => {
63
63
  const pkg = packageJson('apps', 'cad-creator');
64
64
  const manifest = JSON.parse(read('apps', 'cad-creator', 'agentsam.app.json'));
65
65
 
66
- assert.equal(pkg.name, '@inneranimalmedia/agentsam-sdk-cad-creator');
66
+ assert.equal(pkg.name, '@inneranimalmedia/agentsam-cad-creator');
67
67
  assert.notEqual(pkg.private, true);
68
68
  assert.equal(pkg.bin['agentsam-cad-creator'], 'bin/agentsam-cad-creator.mjs');
69
69
  assert.equal(pkg.publishConfig.access, 'public');
@@ -91,7 +91,8 @@ test('client-cms-editor app manifest points to authoritative package name', () =
91
91
  assert.equal(manifest.package, pkg.name);
92
92
  assert.equal(manifest.runtime.local_preview, 'ready');
93
93
  assert.equal(manifest.runtime.source_scaffold, 'ready');
94
- assert.equal(manifest.runtime.cloudflare, 'ready');
94
+ // Cloudflare path is adapter-ready until a graduated CF deploy receipt exists.
95
+ assert.equal(manifest.runtime.cloudflare, 'adapter-ready');
95
96
  });
96
97
 
97
98
  test('CAD creator keeps the robotics runtime lazy and the perception key server-side', () => {
@@ -86,7 +86,7 @@ test('whoami surfaces tokenPermissions and authType from context', async () => {
86
86
  tokenPermissions: ['account:read', 'repository:read', 'models:invoke'],
87
87
  credential: {
88
88
  id: 'aakcred_1',
89
- name: 'Sams-iMac',
89
+ name: 'dev-machine',
90
90
  prefix: 'aak_7fm…',
91
91
  environment: 'development',
92
92
  status: 'active',
@@ -99,7 +99,7 @@ test('whoami surfaces tokenPermissions and authType from context', async () => {
99
99
  assert.equal(status.loggedIn, true);
100
100
  assert.equal(status.authType, 'api_key');
101
101
  assert.deepEqual(status.tokenPermissions, ['account:read', 'repository:read', 'models:invoke']);
102
- assert.equal(status.credential.name, 'Sams-iMac');
102
+ assert.equal(status.credential.name, 'dev-machine');
103
103
  assert.doesNotMatch(JSON.stringify(status), /aak_presented/);
104
104
  });
105
105
 
@@ -0,0 +1,64 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+
4
+ import { getCliCommand } from '../../src/cli/command-catalog.js';
5
+ import { runStatus } from '../../src/commands/status.js';
6
+ import { setupNextCommands } from '../../src/commands/setup.js';
7
+ import { renderRepositoryObservation } from '../../src/commands/knowledge.js';
8
+
9
+ test('status --help is catalog-backed and does not collect runtime state', async () => {
10
+ let output = '';
11
+ let collected = false;
12
+ const result = await runStatus(['--help'], {
13
+ write(value) { output += value; },
14
+ async collectRuntime() {
15
+ collected = true;
16
+ throw new Error('status help must not collect runtime');
17
+ },
18
+ });
19
+
20
+ assert.equal(result, null);
21
+ assert.equal(collected, false);
22
+ assert.match(output, /Agent Sam.*status/);
23
+ assert.match(output, /--offline/);
24
+ assert.match(output, /--json/);
25
+ });
26
+
27
+ test('setup next-actions only reference catalogued top-level commands', () => {
28
+ const commands = setupNextCommands(['google.cloud', 'image.vectorize']);
29
+ assert.ok(commands.includes('agentsam status'));
30
+ assert.ok(commands.includes('agentsam capabilities'));
31
+ assert.ok(commands.includes('agentsam google-cloud doctor'));
32
+ assert.ok(!commands.some((command) => command === 'agentsam doctor'));
33
+ assert.ok(!commands.some((command) => command.startsWith('agentsam image ')));
34
+
35
+ for (const command of commands) {
36
+ const [, id] = command.split(/\s+/);
37
+ assert.ok(getCliCommand(id), `next action must be catalogued: ${command}`);
38
+ }
39
+ });
40
+
41
+ test('repository summary is human-sized while preserving important machine evidence', () => {
42
+ const output = renderRepositoryObservation({
43
+ data: {
44
+ repo_root: '/tmp/example',
45
+ repo_name: 'example',
46
+ git: { branch: 'main', head_sha: 'abcdef1234567890', dirty: true, changed_paths: 2 },
47
+ summary: { file_count: 2995, source_file_count: 2840, total_lines: 491023 },
48
+ top_level: [
49
+ { path: 'apps', files: 1351, lines: 289444 },
50
+ { path: 'packages', files: 757, lines: 77579 },
51
+ ],
52
+ pressure_points: [
53
+ { path: 'apps/local-studio', pressure_score: 89.5, stability_score: 10.2 },
54
+ ],
55
+ },
56
+ });
57
+
58
+ assert.match(output, /Agent Sam · repository/);
59
+ assert.match(output, /example/);
60
+ assert.match(output, /apps\/local-studio/);
61
+ assert.match(output, /not quality grades/);
62
+ assert.match(output, /agentsam repo --json/);
63
+ assert.doesNotMatch(output, /"pressure_points"/);
64
+ });