@inneranimalmedia/agentsam-sdk 2.6.2 → 2.6.4

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 (661) hide show
  1. package/AGENTSAM.md +51 -1
  2. package/README.md +95 -0
  3. package/apps/README.md +34 -0
  4. package/apps/cad-creator/README.md +728 -0
  5. package/apps/cad-creator/shared/cad/package.json +19 -0
  6. package/apps/cad-creator/shared/cad/src/domain/operations.ts +7 -0
  7. package/apps/cad-creator/shared/cad/src/domain/project-contract.d.ts +3 -0
  8. package/apps/cad-creator/shared/cad/src/domain/project-contract.js +75 -0
  9. package/apps/cad-creator/shared/cad/src/domain/project-tools.d.ts +1 -0
  10. package/apps/cad-creator/shared/cad/src/domain/project-tools.js +24 -0
  11. package/apps/cad-creator/shared/cad/src/domain/validation.ts +191 -0
  12. package/apps/cad-creator/shared/cad/src/index.ts +4 -0
  13. package/apps/cad-creator/shared/cad/src/robotics/types.ts +232 -0
  14. package/apps/cad-creator/shared/cad/src/types.ts +507 -0
  15. package/apps/cad-creator/shared/cad/tsconfig.json +14 -0
  16. package/bin/agentsam +16 -1
  17. package/docs/AUTORAG.md +58 -0
  18. package/docs/BRAND_INTELLIGENCE.md +30 -0
  19. package/docs/CLI_SHELL.md +4 -2
  20. package/docs/CMS_CONTEXTUAL_COMPOSER.md +38 -0
  21. package/docs/MERKLE.md +4 -0
  22. package/docs/PROJECT_CONFIG.md +3 -0
  23. package/docs/REPOSITORY_KNOWLEDGE.md +2 -0
  24. package/docs/THEME_REFINERY.md +120 -0
  25. package/docs/architecture/AGENTSAM_DISTRIBUTION_OWNERSHIP.md +176 -0
  26. package/docs/architecture/AGENTSAM_GO_RUNTIME.md +282 -0
  27. package/docs/architecture/CODEBASEINDEX_GUIDED_PATH.md +202 -0
  28. package/docs/architecture/FS_E2E_CLOSURE_RECEIPT.md +59 -0
  29. package/docs/architecture/LOCAL_FS_AUTHORITY.md +38 -0
  30. package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +28 -0
  31. package/docs/architecture/PLAN_CLI_AND_LOCAL_STUDIO_DESKTOP.md +96 -0
  32. package/docs/architecture/PROVIDER-TOOLS-AND-COMPACTION.md +60 -0
  33. package/docs/architecture/SAM_ACTIVITY_RECOVERY_RECEIPT.md +39 -0
  34. package/docs/architecture/SAM_DECISION_WORK_RECEIPT.md +54 -0
  35. package/docs/architecture/SAM_KERNEL.md +181 -0
  36. package/docs/architecture/SAM_MACHINE_NORMALIZATION_PRECOMMIT_REPORT.md +208 -0
  37. package/docs/architecture/SLASH_SKILLS_PORTABLE.md +116 -0
  38. package/docs/architecture/STORAGE.md +87 -0
  39. package/docs/architecture/fs-e2e-receipt.latest.json +42 -0
  40. package/docs/architecture/previews/codebaseindex-guided-path/CODEBASEINDEX_GUIDED_PATH.md +202 -0
  41. package/docs/architecture/previews/codebaseindex-guided-path/index.html +321 -0
  42. package/docs/cad-project-tools.md +69 -0
  43. package/docs/cms-scaffolding-pattern-reference.md +73 -0
  44. package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS-codex-tui-20260919.md +113 -0
  45. package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS.md +85 -0
  46. package/docs/plans/AGENTSAM-MCP-CLIENT-2026-09-19.md +181 -0
  47. package/docs/plans/ASBD-PORTABLE-WORKGRAPH-UI-DEFERRED.md +34 -0
  48. package/docs/plans/ASTRA-BRIEF-2026-09-18.md +258 -0
  49. package/docs/plans/MULTI-AGENT-SPRINTS-2026-09-19.md +373 -0
  50. package/docs/plans/NEXT-AGENT-HANDOFF.md +167 -0
  51. package/docs/plans/RECONCILIATION-2026-09-19.md +178 -0
  52. package/docs/plugins.md +43 -0
  53. package/docs/tools/README.md +57 -0
  54. package/docs/tools/agent-and-orchestration.md +49 -0
  55. package/docs/tools/browser-and-research.md +46 -0
  56. package/docs/tools/cloudflare-platform.md +32 -0
  57. package/docs/tools/cms.md +25 -0
  58. package/docs/tools/communications.md +41 -0
  59. package/docs/tools/database-and-storage.md +62 -0
  60. package/docs/tools/design-and-media.md +64 -0
  61. package/docs/tools/filesystem-and-code.md +55 -0
  62. package/docs/tools/github.md +56 -0
  63. package/docs/tools/integrations-and-misc.md +16 -0
  64. package/docs/tools/memory.md +21 -0
  65. package/docs/tools/terminal-and-execution.md +29 -0
  66. package/docs/tools/tickets-and-platform.md +30 -0
  67. package/migrations/d1/0001_agentsam_plugin_runtime.sql +177 -0
  68. package/migrations/d1/0002_agentsam_ticket_ownership.sql +8 -0
  69. package/migrations/d1/0002_dynamic_model_policies.sql +23 -0
  70. package/migrations/d1/0003_expand_tool_handler_families.sql +18 -0
  71. package/migrations/d1/0004_project_aware_retrieval_lanes.sql +24 -0
  72. package/migrations/d1/0005_portable_knowledge_identity.sql +104 -0
  73. package/migrations/d1/0006_repair_ops_trail_account_scope.sql +14 -0
  74. package/migrations/d1/0007_repair_ops_trail_agent_run_account.sql +13 -0
  75. package/migrations/d1/0008_backfill_knowledge_run_legacy_tenant.sql +14 -0
  76. package/migrations/d1/0009_normalize_cloudflare_plugin_installations.sql +137 -0
  77. package/migrations/d1/0010_portable_tickets_memory.sql +140 -0
  78. package/migrations/d1/0011_agentsam_skill_v2.sql +185 -0
  79. package/migrations/d1/0011b_agentsam_skill_v2_cutover.sql +22 -0
  80. package/migrations/d1/0011c_agentsam_skill_v2_backfill.sql +76 -0
  81. package/migrations/d1/0011d_agentsam_skill_v2_retrieval_revisions.sql +50 -0
  82. package/migrations/d1/0012_agentsam_tools_required_seed.sql +67 -0
  83. package/migrations/d1/0013_identity_oauth_states.sql +15 -0
  84. package/migrations/d1/0014_auth_event_log.sql +20 -0
  85. package/migrations/d1/0015_identity_oauth_state_app_id.sql +3 -0
  86. package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +16 -0
  87. package/migrations/runtime/0001_cli_runtime.sql +67 -0
  88. package/migrations/runtime/0002_project_sessions.sql +15 -0
  89. package/migrations/runtime/0003_provider_continuations.sql +8 -0
  90. package/migrations/sqlite/agentsam_skill_retrieval.portable.sql +42 -0
  91. package/package.json +107 -12
  92. package/packages/agentsam-brand/README.md +21 -0
  93. package/packages/agentsam-brand/package.json +22 -0
  94. package/packages/agentsam-brand/src/contract.js +59 -0
  95. package/packages/agentsam-brand/src/extract.js +126 -0
  96. package/packages/agentsam-brand/src/goap-actions.js +73 -0
  97. package/packages/agentsam-brand/src/index.js +48 -0
  98. package/packages/agentsam-brand/src/plan.js +115 -0
  99. package/packages/agentsam-brand/src/resolve.js +139 -0
  100. package/packages/agentsam-brand/src/scan.js +250 -0
  101. package/packages/agentsam-brand/test/brand-scan.test.mjs +106 -0
  102. package/packages/agentsam-contracts/README.md +23 -0
  103. package/packages/agentsam-contracts/package.json +32 -0
  104. package/packages/agentsam-contracts/src/adapter.ts +25 -0
  105. package/packages/agentsam-contracts/src/agent.ts +35 -0
  106. package/packages/agentsam-contracts/src/artifacts.ts +33 -0
  107. package/packages/agentsam-contracts/src/authority.ts +29 -0
  108. package/packages/agentsam-contracts/src/context.ts +16 -0
  109. package/packages/agentsam-contracts/src/errors.ts +62 -0
  110. package/packages/agentsam-contracts/src/events.ts +47 -0
  111. package/packages/agentsam-contracts/src/execution.ts +50 -0
  112. package/packages/agentsam-contracts/src/hooks.ts +40 -0
  113. package/packages/agentsam-contracts/src/identity.ts +16 -0
  114. package/packages/agentsam-contracts/src/index.ts +14 -0
  115. package/packages/agentsam-contracts/src/models.ts +9 -0
  116. package/packages/agentsam-contracts/src/providers.ts +33 -0
  117. package/packages/agentsam-contracts/src/repository.ts +64 -0
  118. package/packages/agentsam-contracts/src/tools.ts +98 -0
  119. package/packages/agentsam-contracts/test/contracts.test.mjs +16 -0
  120. package/packages/agentsam-contracts/test/errors-catalog.test.mjs +25 -0
  121. package/packages/agentsam-contracts/test/repository.test.mjs +18 -0
  122. package/packages/agentsam-contracts/tsconfig.json +12 -0
  123. package/packages/agentsam-errors/package.json +17 -0
  124. package/packages/agentsam-errors/src/adapters/anthropic.js +15 -0
  125. package/packages/agentsam-errors/src/adapters/cad.js +109 -0
  126. package/packages/agentsam-errors/src/adapters/cloudflare.js +21 -0
  127. package/packages/agentsam-errors/src/adapters/cursor.js +4 -0
  128. package/packages/agentsam-errors/src/adapters/device.js +38 -0
  129. package/packages/agentsam-errors/src/adapters/docker.js +28 -0
  130. package/packages/agentsam-errors/src/adapters/gcp.js +14 -0
  131. package/packages/agentsam-errors/src/adapters/github.js +22 -0
  132. package/packages/agentsam-errors/src/adapters/google.js +17 -0
  133. package/packages/agentsam-errors/src/adapters/index.js +55 -0
  134. package/packages/agentsam-errors/src/adapters/internal.js +40 -0
  135. package/packages/agentsam-errors/src/adapters/oauth.js +24 -0
  136. package/packages/agentsam-errors/src/adapters/openai.js +17 -0
  137. package/packages/agentsam-errors/src/adapters/process.js +35 -0
  138. package/packages/agentsam-errors/src/adapters/provider.js +114 -0
  139. package/packages/agentsam-errors/src/envelope.js +239 -0
  140. package/packages/agentsam-errors/src/error.js +24 -0
  141. package/packages/agentsam-errors/src/fingerprint.js +35 -0
  142. package/packages/agentsam-errors/src/index.js +11 -0
  143. package/packages/agentsam-errors/src/normalize.js +30 -0
  144. package/packages/agentsam-errors/src/recovery.js +301 -0
  145. package/packages/agentsam-errors/src/redaction.js +52 -0
  146. package/packages/agentsam-errors/src/render.js +16 -0
  147. package/packages/agentsam-errors/src/retry.js +10 -0
  148. package/packages/agentsam-errors/src/transport.js +52 -0
  149. package/packages/agentsam-errors/src/vocabulary.js +320 -0
  150. package/packages/agentsam-errors/test/envelope.test.mjs +70 -0
  151. package/packages/agentsam-errors/test/providers.test.mjs +99 -0
  152. package/packages/agentsam-errors/test/redaction.test.mjs +21 -0
  153. package/packages/agentsam-errors/test/runtime-cad-device.test.mjs +76 -0
  154. package/packages/agentsam-errors/test/transport.test.mjs +46 -0
  155. package/packages/agentsam-knowledge/package.json +15 -0
  156. package/packages/agentsam-knowledge/src/autorag/index.js +64 -0
  157. package/packages/agentsam-knowledge/src/backends/index.js +26 -0
  158. package/packages/agentsam-knowledge/src/index.js +3 -0
  159. package/packages/agentsam-knowledge/src/providers/index.js +107 -0
  160. package/packages/agentsam-knowledge/test/autorag.test.mjs +42 -0
  161. package/packages/agentsam-nav/README.md +40 -0
  162. package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
  163. package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
  164. package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
  165. package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
  166. package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
  167. package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
  168. package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
  169. package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
  170. package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
  171. package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
  172. package/packages/agentsam-nav/dist/browser.d.ts +11 -0
  173. package/packages/agentsam-nav/dist/browser.global.js +132 -0
  174. package/packages/agentsam-nav/dist/browser.js +613 -0
  175. package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
  176. package/packages/agentsam-nav/dist/index.d.ts +11 -0
  177. package/packages/agentsam-nav/dist/index.js +614 -0
  178. package/packages/agentsam-nav/dist/legacy.css +83 -0
  179. package/packages/agentsam-nav/dist/shell.css +113 -0
  180. package/packages/agentsam-nav/dist/theme.css +113 -0
  181. package/packages/agentsam-nav/dist/utils.d.ts +1 -0
  182. package/packages/agentsam-nav/package.json +43 -0
  183. package/packages/agentsam-queue-control/README.md +107 -0
  184. package/packages/agentsam-queue-control/package.json +31 -0
  185. package/packages/agentsam-queue-control/schemas/job-envelope.schema.json +56 -0
  186. package/packages/agentsam-queue-control/src/adapters/cloudflare.js +152 -0
  187. package/packages/agentsam-queue-control/src/adapters/memory.js +38 -0
  188. package/packages/agentsam-queue-control/src/contracts.js +130 -0
  189. package/packages/agentsam-queue-control/src/control-plane.js +141 -0
  190. package/packages/agentsam-queue-control/src/dispatch.js +43 -0
  191. package/packages/agentsam-queue-control/src/index.js +7 -0
  192. package/packages/agentsam-queue-control/src/policy.js +88 -0
  193. package/packages/agentsam-queue-control/src/topology.js +66 -0
  194. package/packages/agentsam-queue-control/test/queue-control.test.mjs +100 -0
  195. package/packages/agentsam-repository/src/goap.js +718 -0
  196. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
  197. package/packages/agentsam-repository/src/index.js +5 -0
  198. package/packages/agentsam-repository/src/merkle/cloudflare-persistence.js +2 -2
  199. package/packages/agentsam-repository/src/tickets.js +184 -0
  200. package/packages/agentsam-repository/src/work-tracking.js +199 -0
  201. package/packages/agentsam-repository/src/workspace-state.js +176 -0
  202. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +152 -0
  203. package/packages/connectors/cloudflare/src/index.js +297 -15
  204. package/packages/connectors/cloudflare/src/owner.js +43 -40
  205. package/packages/connectors/cloudflare/src/routes.js +176 -26
  206. package/packages/connectors/cloudflare/tests/connector.test.mjs +137 -2
  207. package/packages/heuristic-theme/README.md +11 -0
  208. package/packages/heuristic-theme/package.json +25 -0
  209. package/packages/heuristic-theme/src/index.js +2 -0
  210. package/packages/heuristic-theme/src/registry.js +36 -0
  211. package/packages/heuristic-theme/src/theme.js +41 -0
  212. package/packages/heuristic-theme/test/theme.test.mjs +26 -0
  213. package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +64 -0
  214. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +96 -0
  215. package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +47 -0
  216. package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +83 -0
  217. package/packages/identity/.agentsam/features/oauth-login-portal/ui.json +35 -0
  218. package/packages/identity/docs/PORTABLE_IDENTITY_ARCHITECTURE.md +50 -0
  219. package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +31 -0
  220. package/packages/identity/migrations/sqlite/001_identity_core.sql +99 -0
  221. package/packages/identity/migrations/sqlite/002_identity_oauth_client.sql +38 -0
  222. package/packages/identity/migrations/sqlite/003_identity_oauth_server.sql +64 -0
  223. package/packages/identity/package.json +4 -3
  224. package/packages/identity/src/adapters/cloudflare-d1/ids.js +4 -0
  225. package/packages/identity/src/adapters/cloudflare-d1/index.js +156 -18
  226. package/packages/identity/src/adapters/sqlite/index.js +319 -0
  227. package/packages/identity/src/app/verify-app.js +95 -0
  228. package/packages/identity/src/contracts/identity-store.js +115 -0
  229. package/packages/identity/src/contracts/provider.js +3 -2
  230. package/packages/identity/src/contracts/route-ids.js +30 -0
  231. package/packages/identity/src/contracts/route-projection.js +218 -0
  232. package/packages/identity/src/contracts/routes.js +11 -0
  233. package/packages/identity/src/core/browser-paths.js +4 -5
  234. package/packages/identity/src/core/constants.js +13 -8
  235. package/packages/identity/src/core/session-policy.js +32 -0
  236. package/packages/identity/src/frontend/auth-portal/pages/login.html +16 -9
  237. package/packages/identity/src/frontend/auth-portal/pages/reset.html +3 -3
  238. package/packages/identity/src/frontend/auth-portal/pages/signup.html +3 -3
  239. package/packages/identity/src/frontend/auth-portal/preview/dashboard-stub.html +1 -1
  240. package/packages/identity/src/index.js +27 -0
  241. package/packages/identity/src/oauth/README.md +10 -4
  242. package/packages/identity/src/oauth/credentials.js +31 -11
  243. package/packages/identity/src/oauth/finalize-inbound.js +1 -1
  244. package/packages/identity/src/oauth/iam-platform.js +13 -12
  245. package/packages/identity/src/oauth/redirect-paths.js +27 -36
  246. package/packages/identity/src/providers/cloudflare/index.js +19 -0
  247. package/packages/identity/src/providers/cloudflare/mapper.js +21 -0
  248. package/packages/identity/src/providers/cloudflare/oauth.js +48 -0
  249. package/packages/identity/src/providers/cloudflare/profile.js +28 -0
  250. package/packages/identity/src/providers/index.js +18 -2
  251. package/packages/identity/src/server/identity-service.js +35 -8
  252. package/packages/identity/src/server/mount-policy.js +30 -0
  253. package/packages/identity/src/server/post-auth.js +79 -0
  254. package/packages/identity/src/server/worker-router.js +153 -66
  255. package/packages/identity/tests/finalize-inbound-oauth.test.mjs +6 -6
  256. package/packages/identity/tests/iam-provider.test.mjs +1 -1
  257. package/packages/identity/tests/identity-service.test.mjs +47 -1
  258. package/packages/identity/tests/oauth-credentials.test.mjs +3 -1
  259. package/packages/identity/tests/portable-identity-architecture.test.mjs +157 -0
  260. package/packages/identity/tests/session-routes-policy.test.mjs +21 -0
  261. package/packages/providers/completeful/README.md +38 -0
  262. package/packages/providers/completeful/package.json +29 -0
  263. package/packages/providers/completeful/src/client.js +162 -0
  264. package/packages/providers/completeful/src/events.js +49 -0
  265. package/packages/providers/completeful/src/index.js +22 -0
  266. package/packages/providers/completeful/src/tools.js +579 -0
  267. package/packages/providers/completeful/src/webhooks.js +55 -0
  268. package/packages/providers/completeful/test/provider.test.mjs +196 -0
  269. package/packages/theme-church-site/README.md +10 -0
  270. package/packages/theme-church-site/package.json +31 -0
  271. package/packages/theme-church-site/src/harvest.json +14 -0
  272. package/packages/theme-church-site/src/index.js +85 -0
  273. package/packages/theme-church-site/test/theme.test.mjs +19 -0
  274. package/packages/theme-companions-site/README.md +10 -0
  275. package/packages/theme-companions-site/package.json +31 -0
  276. package/packages/theme-companions-site/src/harvest.json +12 -0
  277. package/packages/theme-companions-site/src/index.js +83 -0
  278. package/packages/theme-companions-site/test/theme.test.mjs +19 -0
  279. package/packages/theme-floors-site/README.md +10 -0
  280. package/packages/theme-floors-site/package.json +31 -0
  281. package/packages/theme-floors-site/src/harvest.json +14 -0
  282. package/packages/theme-floors-site/src/index.js +83 -0
  283. package/packages/theme-floors-site/test/theme.test.mjs +19 -0
  284. package/packages/theme-fuelnfree-site/README.md +10 -0
  285. package/packages/theme-fuelnfree-site/package.json +31 -0
  286. package/packages/theme-fuelnfree-site/src/harvest.json +13 -0
  287. package/packages/theme-fuelnfree-site/src/index.js +82 -0
  288. package/packages/theme-fuelnfree-site/test/theme.test.mjs +19 -0
  289. package/packages/theme-handyman-site/README.md +10 -0
  290. package/packages/theme-handyman-site/package.json +31 -0
  291. package/packages/theme-handyman-site/src/harvest.json +10 -0
  292. package/packages/theme-handyman-site/src/index.js +84 -0
  293. package/packages/theme-handyman-site/test/theme.test.mjs +19 -0
  294. package/packages/theme-insurance-site/README.md +10 -0
  295. package/packages/theme-insurance-site/package.json +31 -0
  296. package/packages/theme-insurance-site/src/harvest.json +10 -0
  297. package/packages/theme-insurance-site/src/index.js +84 -0
  298. package/packages/theme-insurance-site/test/theme.test.mjs +19 -0
  299. package/packages/theme-shinshu-site/README.md +10 -0
  300. package/packages/theme-shinshu-site/package.json +31 -0
  301. package/packages/theme-shinshu-site/src/harvest.json +12 -0
  302. package/packages/theme-shinshu-site/src/index.js +84 -0
  303. package/packages/theme-shinshu-site/test/theme.test.mjs +19 -0
  304. package/packages/work-graph/README.md +49 -0
  305. package/packages/work-graph/package.json +19 -0
  306. package/packages/work-graph/prototype/README.md +32 -0
  307. package/packages/work-graph/prototype/data/demo-workgraph.js +47 -0
  308. package/packages/work-graph/prototype/renderers/timeline-model.js +21 -0
  309. package/packages/work-graph/prototype/renderers/workgraph-runtime.js +38 -0
  310. package/packages/work-graph/prototype-gnantt.html +655 -0
  311. package/packages/work-graph/src/adapters/business/projects.js +23 -0
  312. package/packages/work-graph/src/adapters/engineering/git.js +22 -0
  313. package/packages/work-graph/src/adapters/engineering/mcp.js +22 -0
  314. package/packages/work-graph/src/index.js +76 -0
  315. package/packages/work-graph/src/renderers/gantt-model.js +11 -0
  316. package/packages/work-graph/src/renderers/timeline.js +16 -0
  317. package/packages/work-graph/test/work-graph.test.mjs +37 -0
  318. package/protocol/README.md +12 -0
  319. package/protocol/apps/agentsam.app.v1.schema.json +51 -0
  320. package/protocol/brand/brandpack.v1.schema.json +43 -0
  321. package/protocol/capabilities/cloudflare-cpu-audit-input.schema.json +30 -6
  322. package/protocol/capabilities/cloudflare-cpu-profile-input.schema.json +18 -4
  323. package/protocol/capabilities/cloudflare-wrangler-native-input.schema.json +59 -10
  324. package/protocol/capabilities/knowledge-search-input.schema.json +35 -0
  325. package/protocol/capabilities/manifest.json +163 -1
  326. package/protocol/capabilities/repository-audit-input.schema.json +39 -6
  327. package/protocol/capabilities/repository-snapshot-input.schema.json +15 -3
  328. package/protocol/capabilities/terminal-exec-input.schema.json +55 -0
  329. package/protocol/commerce/catalog.v1.json +50 -0
  330. package/protocol/credentials/issue.v1.schema.json +38 -0
  331. package/protocol/database/connection.v1.schema.json +41 -0
  332. package/protocol/embeddings/embedding-profile.v1.schema.json +20 -0
  333. package/protocol/errors/error-catalog.json +164 -0
  334. package/protocol/errors/error-envelope.schema.json +678 -0
  335. package/protocol/errors/recovery.v1.schema.json +50 -0
  336. package/protocol/features/README.md +57 -0
  337. package/protocol/features/agentsam.feature.v1.schema.json +290 -0
  338. package/protocol/features/catalog.json +65 -0
  339. package/protocol/features/examples/provider-resend.feature.json +17 -0
  340. package/protocol/go/agentsam-go-runtime.v1.json +17 -0
  341. package/protocol/knowledge/LIFECYCLE.md +140 -0
  342. package/protocol/knowledge/README.md +4 -0
  343. package/protocol/presets/catalog.json +128 -19
  344. package/protocol/rpc/v1/errors.proto +24 -0
  345. package/protocol/runtime/workspace-fs.v1.schema.json +71 -0
  346. package/protocol/sam/activity.v1.schema.json +48 -0
  347. package/protocol/sam/answer.v1.schema.json +35 -0
  348. package/protocol/sam/calibration.v1.schema.json +21 -0
  349. package/protocol/sam/decision-receipt.v1.schema.json +29 -0
  350. package/protocol/sam/evaluation.v1.schema.json +19 -0
  351. package/protocol/sam/operation.schema.json +66 -0
  352. package/protocol/sam/outcome.v1.schema.json +36 -0
  353. package/protocol/sam/question.v1.schema.json +26 -0
  354. package/protocol/sam/registry.seed.json +153 -0
  355. package/protocol/sam/result.schema.json +53 -0
  356. package/protocol/sam/state.v1.schema.json +23 -0
  357. package/protocol/skills/agentsam.interaction.v1.schema.json +50 -0
  358. package/protocol/skills/agentsam.skill.v1.schema.json +57 -0
  359. package/protocol/theme-refinery/d1-reconciliation.md +48 -0
  360. package/protocol/theme-refinery/product-metadata.schema.json +27 -0
  361. package/protocol/theme-refinery/receipts/products-registry-batch-20260924.json +318 -0
  362. package/protocol/theme-refinery/receipts/theme-harvest-20260924.json +472 -0
  363. package/protocol/theme-refinery/reconciliation-receipt.schema.json +83 -0
  364. package/protocol/ui/icon-registry.mjs +226 -0
  365. package/protocol/ui/icon.v1.schema.json +51 -0
  366. package/services/cad/server.py +249 -2
  367. package/skills/README.md +22 -9
  368. package/skills/agentsam-codebaseindex/SKILL.md +225 -0
  369. package/skills/catalog.json +14 -0
  370. package/src/agent/capability-adapter.js +15 -5
  371. package/src/agent/index.js +2 -1
  372. package/src/agent/model-turn.js +51 -0
  373. package/src/agent/responses-runner.js +304 -38
  374. package/src/capabilities/index.js +1 -0
  375. package/src/capabilities/terminal-exec.js +78 -0
  376. package/src/cli/command-catalog.js +130 -0
  377. package/src/cli/dispatch.js +48 -0
  378. package/src/cli.js +160 -10
  379. package/src/cloudflare/index.js +6 -0
  380. package/src/cloudflare/runtime-status.js +393 -0
  381. package/src/cloudflare/wrangler.js +17 -1
  382. package/src/commands/api-key.js +244 -0
  383. package/src/commands/app.js +138 -0
  384. package/src/commands/autorag.js +77 -0
  385. package/src/commands/brand.js +291 -0
  386. package/src/commands/cad.js +1 -0
  387. package/src/commands/codebaseindex.js +688 -0
  388. package/src/commands/connections.js +126 -29
  389. package/src/commands/context-economics.js +8 -0
  390. package/src/commands/db.js +7 -0
  391. package/src/commands/env.js +155 -27
  392. package/src/commands/eval.js +209 -14
  393. package/src/commands/go.js +678 -0
  394. package/src/commands/goap.js +176 -0
  395. package/src/commands/identity-init.js +27 -3
  396. package/src/commands/identity-protocol.js +195 -0
  397. package/src/commands/interaction-clack.js +115 -0
  398. package/src/commands/knowledge.js +64 -5
  399. package/src/commands/mcp.js +341 -0
  400. package/src/commands/merkle-persist.js +3 -1
  401. package/src/commands/merkle.js +18 -3
  402. package/src/commands/models.js +110 -24
  403. package/src/commands/plugins.js +175 -0
  404. package/src/commands/preferences.js +28 -8
  405. package/src/commands/product.js +53 -10
  406. package/src/commands/providers.js +173 -44
  407. package/src/commands/resume.js +9 -5
  408. package/src/commands/runtime-status.js +154 -0
  409. package/src/commands/shell.js +508 -56
  410. package/src/commands/skill.js +248 -0
  411. package/src/commands/skills.js +1 -1
  412. package/src/commands/start-local.js +4 -0
  413. package/src/commands/status.js +82 -7
  414. package/src/commands/tunnel.js +228 -195
  415. package/src/commands/whoami.js +156 -12
  416. package/src/context/budget.js +6 -0
  417. package/src/context/index.js +2 -1
  418. package/src/context/project-card.js +75 -0
  419. package/src/errors/contract.js +34 -211
  420. package/src/errors/diagnostic.js +95 -51
  421. package/src/errors/index.js +6 -13
  422. package/src/eval/index.js +6 -0
  423. package/src/eval/live.js +439 -0
  424. package/src/features/resolve.js +242 -0
  425. package/src/go/build.js +298 -0
  426. package/src/go/cloudflare.js +608 -0
  427. package/src/go/container.js +120 -0
  428. package/src/go/contract.js +144 -0
  429. package/src/go/discover.js +212 -0
  430. package/src/go/index.js +25 -0
  431. package/src/go/native-probe-runner.mjs +119 -0
  432. package/src/go/official-registry.js +280 -0
  433. package/src/go/official-release.js +10 -0
  434. package/src/go/receipts.js +144 -0
  435. package/src/go/verify.js +38 -0
  436. package/src/index.js +127 -1
  437. package/src/indexing/ingest/discover-models.js +298 -0
  438. package/src/indexing/ingest/inventory.js +243 -0
  439. package/src/indexing/ingest/job-graph.js +181 -0
  440. package/src/indexing/ingest/materials.js +210 -0
  441. package/src/knowledge/config.js +13 -5
  442. package/src/knowledge/engine.js +23 -8
  443. package/src/knowledge/index.js +1 -0
  444. package/src/knowledge/lane-registry.js +46 -0
  445. package/src/knowledge/providers/gemini.js +48 -8
  446. package/src/knowledge/service/client.js +13 -1
  447. package/src/knowledge/service/grpc-codec.js +156 -53
  448. package/src/knowledge/service/job-engine.js +133 -11
  449. package/src/knowledge/service/job-worker.js +34 -5
  450. package/src/knowledge/service/server.js +10 -1
  451. package/src/knowledge/store-discovery.js +77 -0
  452. package/src/lib/account-session.js +8 -2
  453. package/src/lib/agent-instructions.js +3 -0
  454. package/src/lib/auth.js +7 -3
  455. package/src/lib/cad/blender.js +42 -3
  456. package/src/lib/cad/d1-project-store.js +43 -0
  457. package/src/lib/cad/discovery.js +616 -0
  458. package/src/lib/cad/docker-executor.js +352 -0
  459. package/src/lib/cad/freecad.js +253 -0
  460. package/src/lib/cad/index.js +40 -0
  461. package/src/lib/cad/openscad.js +198 -0
  462. package/src/lib/cad/project-cli.d.ts +2 -0
  463. package/src/lib/cad/project-cli.js +21 -0
  464. package/src/lib/cad/project-contract.d.ts +3 -0
  465. package/src/lib/cad/project-contract.js +1 -0
  466. package/src/lib/cad/project-recipe.js +30 -0
  467. package/src/lib/cad/project-runtime.d.ts +2 -0
  468. package/src/lib/cad/project-runtime.js +53 -0
  469. package/src/lib/cad/project-store.js +25 -0
  470. package/src/lib/cad/project-workflows.js +31 -0
  471. package/src/lib/cad-docker.js +21 -2
  472. package/src/lib/cli-preferences.js +17 -2
  473. package/src/lib/core-client.js +37 -18
  474. package/src/lib/deploy/local-studio.js +6 -5
  475. package/src/lib/dockerize.js +3 -0
  476. package/src/lib/execution-approvals.js +1 -0
  477. package/src/lib/identity-scaffold.js +4 -1
  478. package/src/lib/knowledge-docker.js +9 -1
  479. package/src/lib/local-sessions.js +124 -34
  480. package/src/lib/local-status.js +35 -14
  481. package/src/lib/project-config.js +9 -0
  482. package/src/lib/provider-credentials.js +136 -32
  483. package/src/lib/scaffold/resolve-cloudflare-account.js +37 -0
  484. package/src/lib/scaffold/wizards/cms.js +2 -8
  485. package/src/lib/scaffold/wizards/worker-api.js +2 -8
  486. package/src/lib/slash-commands.js +10 -2
  487. package/src/local/migrations.js +109 -1
  488. package/src/local/runtime-store.js +31 -5
  489. package/src/local/sqlite.js +36 -1
  490. package/src/local-fs/capability.js +121 -0
  491. package/src/local-fs/freshness.js +75 -0
  492. package/src/local-fs/index.js +385 -0
  493. package/src/local-fs/paths.js +100 -0
  494. package/src/local-pty/server.js +295 -19
  495. package/src/mcp/authority.js +348 -0
  496. package/src/mcp/client-adapters.js +431 -0
  497. package/src/mcp/client.js +172 -0
  498. package/src/mcp/index.js +47 -0
  499. package/src/mcp/telemetry.js +103 -0
  500. package/src/models/ai-access-onboarding.js +112 -0
  501. package/src/models/catalog.js +329 -51
  502. package/src/models/discovery.js +34 -6
  503. package/src/models/index.js +2 -0
  504. package/src/models/inventory-core.js +190 -0
  505. package/src/models/policy.js +20 -0
  506. package/src/plugins/cloudflare.js +103 -0
  507. package/src/plugins/completeful.js +69 -0
  508. package/src/plugins/contracts.js +86 -0
  509. package/src/plugins/index.js +11 -0
  510. package/src/plugins/registry.js +207 -0
  511. package/src/plugins/resource-scope.js +45 -0
  512. package/src/plugins/runtime.js +118 -0
  513. package/src/plugins/vectorize.js +31 -0
  514. package/src/progression/engine.js +171 -0
  515. package/src/progression/index.js +1 -0
  516. package/src/providers/cloudflare-chat.js +1 -1
  517. package/src/providers/gemini-generate-content.js +2 -1
  518. package/src/providers/openai-responses.js +45 -16
  519. package/src/providers/tool-schema.js +85 -0
  520. package/src/repository/index.js +29 -0
  521. package/src/rpc/generated/errors_pb.js +961 -1
  522. package/src/sam/activity/index.js +183 -0
  523. package/src/sam/client.js +252 -0
  524. package/src/sam/decision/calibration.js +109 -0
  525. package/src/sam/decision/confidence.js +126 -0
  526. package/src/sam/decision/evaluate.js +157 -0
  527. package/src/sam/decision/evaluators/deterministic.js +341 -0
  528. package/src/sam/decision/evaluators/heuristic.js +61 -0
  529. package/src/sam/decision/evaluators/select.js +50 -0
  530. package/src/sam/decision/evaluators/semantic.js +149 -0
  531. package/src/sam/decision/hierarchical.js +61 -0
  532. package/src/sam/decision/index.js +53 -0
  533. package/src/sam/decision/policy.js +86 -0
  534. package/src/sam/decision/questions.js +120 -0
  535. package/src/sam/decision/receipt.js +148 -0
  536. package/src/sam/decision/state.js +117 -0
  537. package/src/sam/decision/types.js +22 -0
  538. package/src/sam/decision/validate.js +200 -0
  539. package/src/sam/define.js +51 -0
  540. package/src/sam/index.js +65 -0
  541. package/src/sam/operations/brand-scan.js +62 -0
  542. package/src/sam/operations/cad-blender-inspect.js +36 -0
  543. package/src/sam/operations/codebaseindex-ingest.js +49 -0
  544. package/src/sam/operations/decision-evaluate.js +59 -0
  545. package/src/sam/operations/planning-astar.js +77 -0
  546. package/src/sam/operations/planning-goap.js +60 -0
  547. package/src/sam/operations/repository-inspect.js +72 -0
  548. package/src/sam/operations/security-scan.js +33 -0
  549. package/src/sam/operations/terminal-exec.js +29 -0
  550. package/src/sam/planning/astar.js +311 -0
  551. package/src/sam/planning/goap.js +177 -0
  552. package/src/sam/planning/index.js +21 -0
  553. package/src/sam/planning/state.js +84 -0
  554. package/src/sam/registry.js +48 -0
  555. package/src/sam/result.js +77 -0
  556. package/src/sam/seed.js +44 -0
  557. package/src/sam/types.js +91 -0
  558. package/src/security/local-vault.js +415 -0
  559. package/src/security/process.js +20 -4
  560. package/src/skills/catalog.js +64 -0
  561. package/src/skills/content-resolver.js +124 -0
  562. package/src/skills/hosted-store.js +37 -0
  563. package/src/skills/index.js +29 -64
  564. package/src/skills/interaction.js +102 -0
  565. package/src/skills/local-store.js +228 -0
  566. package/src/skills/manifest.js +104 -0
  567. package/src/skills/metrics.js +31 -0
  568. package/src/skills/registry.js +184 -0
  569. package/src/skills/runtime.js +287 -0
  570. package/src/skills/slash.js +44 -0
  571. package/src/status/actions.js +192 -0
  572. package/src/tools/hydrate.js +5 -1
  573. package/src/tools/index.js +7 -0
  574. package/src/tools/redact.js +64 -0
  575. package/src/tools/registry.js +83 -0
  576. package/src/tools/runtime.js +257 -0
  577. package/src/tools/search.js +21 -8
  578. package/src/ui/ansi.js +117 -3
  579. package/src/ui/cli/activity.js +76 -7
  580. package/src/ui/cli/footer.js +110 -9
  581. package/src/ui/cli/help.js +96 -96
  582. package/src/ui/wireframes.js +166 -0
  583. package/test/account-session.test.mjs +28 -0
  584. package/test/apps-scaffold-contract.test.mjs +16 -1
  585. package/test/capabilities.test.mjs +1 -1
  586. package/test/cli/api-key-env-whoami.test.mjs +129 -0
  587. package/test/cli/codebaseindex-plan-ux.test.mjs +37 -0
  588. package/test/cli/eval-live.test.mjs +219 -0
  589. package/test/cli/go.test.mjs +128 -0
  590. package/test/cli/local-vault-and-provider-setup.test.mjs +268 -0
  591. package/test/cli/mcp-client.test.mjs +245 -0
  592. package/test/cli/runtime-ui.test.mjs +69 -2
  593. package/test/cli/skill-npm-and-env.test.mjs +52 -0
  594. package/test/cli/status-actions.test.mjs +88 -0
  595. package/test/cli/wireframes-go-registry.test.mjs +139 -0
  596. package/test/cloudflare-connector.test.mjs +3 -6
  597. package/test/cloudflare-runtime.test.mjs +8 -1
  598. package/test/context.test.mjs +15 -0
  599. package/test/error-diagnostics.test.mjs +9 -0
  600. package/test/fixtures/cad/courtyard-house.json +208 -0
  601. package/test/go/build-source-identity.test.mjs +31 -0
  602. package/test/go/cloudflare-probe.test.mjs +317 -0
  603. package/test/go/distribution.test.mjs +28 -0
  604. package/test/integration/ai-access-onboarding.test.mjs +47 -0
  605. package/test/integration/app-command.test.mjs +55 -0
  606. package/test/integration/cad-discovery.test.mjs +158 -0
  607. package/test/integration/cad-docker-executor.test.mjs +249 -0
  608. package/test/integration/cad-execution.test.mjs +184 -0
  609. package/test/integration/cad-project-app.test.mjs +31 -0
  610. package/test/integration/cad-project-d1.test.mjs +25 -0
  611. package/test/integration/cad-project-native.test.mjs +24 -0
  612. package/test/integration/cad-project-workflow.test.mjs +9 -0
  613. package/test/integration/cad-project.test.mjs +82 -0
  614. package/test/integration/cli-help.test.mjs +5 -1
  615. package/test/integration/cms-site-tenancy-contract.test.mjs +256 -0
  616. package/test/integration/codebaseindex-ingest.test.mjs +166 -0
  617. package/test/integration/core-client.integration.test.mjs +55 -0
  618. package/test/integration/error-runtime-rpc.test.mjs +71 -0
  619. package/test/integration/features-resolve.test.mjs +128 -0
  620. package/test/integration/icon-registry.test.mjs +67 -0
  621. package/test/integration/ingest-discover-models.test.mjs +30 -0
  622. package/test/integration/install-script.test.mjs +110 -0
  623. package/test/integration/inventory-core.test.mjs +53 -0
  624. package/test/integration/local-fs.test.mjs +113 -0
  625. package/test/integration/plugins-cloudflare.integration.test.mjs +28 -0
  626. package/test/integration/provider-env-cli.test.mjs +3 -2
  627. package/test/integration/runtime-migrations.test.mjs +6 -1
  628. package/test/integration/runtime-status.integration.test.mjs +211 -0
  629. package/test/integration/sam-activity-recovery.test.mjs +147 -0
  630. package/test/integration/sam-decision.test.mjs +584 -0
  631. package/test/integration/sam-kernel.test.mjs +99 -0
  632. package/test/integration/sam-planning-astar.test.mjs +279 -0
  633. package/test/integration/scaffold-cloudflare.test.mjs +46 -0
  634. package/test/integration/skill-runtime.test.mjs +240 -0
  635. package/test/integration/storage-architecture.test.mjs +154 -0
  636. package/test/integration/store-discovery.test.mjs +44 -0
  637. package/test/integration/studio-fs-pty-e2e.test.mjs +294 -0
  638. package/test/integration/terminal-exec.integration.test.mjs +86 -0
  639. package/test/integration/tool-runtime.test.mjs +124 -0
  640. package/test/integration/tool-schema.test.mjs +59 -0
  641. package/test/knowledge-service.test.mjs +4 -0
  642. package/test/local-sessions.test.mjs +11 -2
  643. package/test/local-studio-deploy.test.mjs +1 -1
  644. package/test/model-catalog.test.mjs +28 -1
  645. package/test/models.test.mjs +172 -11
  646. package/test/openai-responses.test.mjs +60 -0
  647. package/test/provider-credentials.test.mjs +15 -5
  648. package/test/responses-runner.test.mjs +321 -6
  649. package/test/shell.test.mjs +151 -6
  650. package/test/smoke.mjs +2 -2
  651. package/test/tools-search.test.mjs +33 -0
  652. package/test/unit/website-assets-bindings.test.mjs +60 -0
  653. package/test/whoami-resume.test.mjs +82 -3
  654. package/examples/gorilla-shell/README.md +0 -15
  655. package/src/lib/gorilla-template.js +0 -54
  656. package/templates/gorilla-shell/App.tsx +0 -639
  657. package/templates/gorilla-shell/README.md +0 -34
  658. package/templates/gorilla-shell/index.html +0 -15
  659. package/templates/gorilla-shell/main.jsx +0 -9
  660. package/templates/gorilla-shell/package.json +0 -19
  661. package/templates/gorilla-shell/vite.config.js +0 -21
@@ -0,0 +1,175 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { AGENTSAM_MCP_PLUGIN_MANIFEST, normalizePluginKey } from '../plugins/index.js';
4
+ import { authenticateViaBrowser } from '../lib/auth.js';
5
+ import { promptToOpenUrl } from '../lib/open-url.js';
6
+ import { readAccountSession, resolveAccountApiKey, saveAccountSession } from '../lib/account-session.js';
7
+
8
+ const CATALOG = Object.freeze({ 'agentsam-mcp': AGENTSAM_MCP_PLUGIN_MANIFEST });
9
+ const PLUGIN_MIGRATION = '0001_agentsam_plugin_runtime.sql';
10
+
11
+ function statePath(cwd) { return path.join(path.resolve(cwd), '.agentsam', 'plugins.json'); }
12
+ function readState(cwd) {
13
+ const filename = statePath(cwd);
14
+ if (!fs.existsSync(filename)) return { schema_version: 1, plugins: {} };
15
+ const parsed = JSON.parse(fs.readFileSync(filename, 'utf8'));
16
+ return { schema_version: 1, plugins: parsed?.plugins || {} };
17
+ }
18
+
19
+ function installMigration(cwd) {
20
+ const source = new URL(`../../migrations/d1/${PLUGIN_MIGRATION}`, import.meta.url);
21
+ const migrationsDir = path.join(path.resolve(cwd), 'migrations', 'd1');
22
+ const destination = path.join(migrationsDir, PLUGIN_MIGRATION);
23
+ fs.mkdirSync(migrationsDir, { recursive: true });
24
+ if (!fs.existsSync(destination)) fs.copyFileSync(source, destination);
25
+ return path.relative(path.resolve(cwd), destination);
26
+ }
27
+ function parse(argv) {
28
+ const out = {
29
+ action: argv[0] || 'list', key: '', cwd: process.cwd(), json: false,
30
+ origin: process.env.AGENTSAM_ORIGIN || process.env.AGENTSAM_API_ORIGIN || 'https://agentsam.inneranimalmedia.com',
31
+ timeoutMs: 180_000, noOpen: false,
32
+ };
33
+ for (let i = 1; i < argv.length; i += 1) {
34
+ if (argv[i] === '--cwd') out.cwd = argv[++i] || out.cwd;
35
+ else if (argv[i] === '--json') out.json = true;
36
+ else if (argv[i] === '--origin') out.origin = argv[++i] || out.origin;
37
+ else if (argv[i] === '--timeout') out.timeoutMs = Math.max(1_000, Number(argv[++i]) || out.timeoutMs);
38
+ else if (argv[i] === '--no-open') out.noOpen = true;
39
+ else if (!out.key) out.key = argv[i];
40
+ else throw new Error(`unknown plugins option:${argv[i]}`);
41
+ }
42
+ return out;
43
+ }
44
+
45
+ function writeJson(value) { process.stdout.write(`${JSON.stringify(value, null, 2)}\n`); }
46
+
47
+ async function resolveCliBearer(opts) {
48
+ const apiKey = resolveAccountApiKey();
49
+ if (apiKey.value) return { token: apiKey.value, source: apiKey.source };
50
+ let session = readAccountSession();
51
+ if (!session?.access_token) {
52
+ if (opts.json) writeJson({ ok: false, step: 'account_login_required' });
53
+ else console.log('\n No AgentSam account session found. Opening account sign-in first.\n');
54
+ session = await authenticateViaBrowser();
55
+ if (!readAccountSession()) saveAccountSession(session);
56
+ }
57
+ if (!session?.access_token) throw new Error('account_login_did_not_return_access_token');
58
+ return { token: session.access_token, source: 'agentsam_browser_oauth' };
59
+ }
60
+
61
+ async function fetchConnector(opts, token, pathname, init = {}) {
62
+ const origin = String(opts.origin).replace(/\/$/, '');
63
+ const headers = new Headers(init.headers || {});
64
+ headers.set('accept', 'application/json');
65
+ headers.set('authorization', `Bearer ${token}`);
66
+ return fetch(`${origin}${pathname}`, { ...init, headers });
67
+ }
68
+
69
+ async function connectPlugin(opts, key) {
70
+ if (key !== 'agentsam-mcp') throw new Error(`plugin_connect_not_supported:${key}`);
71
+ const state = readState(opts.cwd);
72
+ if (!state.plugins[key]) {
73
+ state.plugins[key] = { plugin_key: key, installed_at: new Date().toISOString(), manifest: CATALOG[key] };
74
+ fs.mkdirSync(path.dirname(statePath(opts.cwd)), { recursive: true, mode: 0o700 });
75
+ fs.writeFileSync(statePath(opts.cwd), `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
76
+ installMigration(opts.cwd);
77
+ if (!opts.json) console.log(`\n Installed @${key}.`);
78
+ }
79
+
80
+ const { token } = await resolveCliBearer(opts);
81
+ const start = await fetchConnector(opts, token, '/api/connections/cloudflare/start');
82
+ const startBody = await start.json().catch(() => ({}));
83
+ if (!start.ok || !startBody.authorize_url) {
84
+ throw new Error(`plugin_connect_start_failed:${startBody.error || start.status}`);
85
+ }
86
+
87
+ if (!opts.json) {
88
+ console.log('\n Connect @agentsam-mcp to Cloudflare');
89
+ console.log(' Your browser will ask you to approve the requested Cloudflare access.');
90
+ }
91
+ if (opts.noOpen) {
92
+ process.stdout.write(`${startBody.authorize_url}\n`);
93
+ } else {
94
+ await promptToOpenUrl(startBody.authorize_url, {
95
+ heading: 'Open Cloudflare authorization:',
96
+ prompt: 'Press ENTER to open Cloudflare in your browser, or copy the URL above.',
97
+ });
98
+ }
99
+
100
+ const started = Date.now();
101
+ let statusBody = {};
102
+ while (Date.now() - started < opts.timeoutMs) {
103
+ const status = await fetchConnector(opts, token, '/api/connections/cloudflare');
104
+ statusBody = await status.json().catch(() => ({}));
105
+ if (statusBody?.status === 'connected' || statusBody?.connection?.status === 'connected') break;
106
+ if (!opts.json) process.stdout.write('.');
107
+ await new Promise((resolve) => setTimeout(resolve, 2_000));
108
+ }
109
+ const connected = statusBody?.status === 'connected' || statusBody?.connection?.status === 'connected';
110
+ const result = {
111
+ ok: connected,
112
+ action: 'connect',
113
+ plugin_key: key,
114
+ provider: 'cloudflare',
115
+ status: connected ? 'connected' : (statusBody?.status || 'pending'),
116
+ cloudflare_account_id: statusBody?.cloudflareAccountId
117
+ || statusBody?.connection?.cloudflareAccountId
118
+ || statusBody?.connection?.cloudflare_account_id
119
+ || null,
120
+ scopes: statusBody?.scopes || statusBody?.connection?.scopes || [],
121
+ };
122
+ if (opts.json) writeJson(result);
123
+ else console.log(connected ? `\n\n ✓ Connected @${key}\n` : `\n\n Authorization is still pending. Run \'agentsam plugins status @${key}\' to check again.\n`);
124
+ return result;
125
+ }
126
+
127
+ async function statusPlugin(opts, key) {
128
+ if (key !== 'agentsam-mcp') throw new Error(`unknown_plugin:${key}`);
129
+ const { token } = await resolveCliBearer(opts);
130
+ const response = await fetchConnector(opts, token, '/api/connections/cloudflare');
131
+ const body = await response.json().catch(() => ({}));
132
+ if (!response.ok) throw new Error(`plugin_status_failed:${body.error || response.status}`);
133
+ const result = { ok: true, plugin_key: key, provider: 'cloudflare', ...body };
134
+ if (opts.json) writeJson(result);
135
+ else console.log(`\n ${result.status === 'connected' ? '✓' : '○'} @${key} ${result.status || 'not_configured'}\n`);
136
+ return result;
137
+ }
138
+
139
+ export async function runPlugins(argv = []) {
140
+ const opts = parse(argv);
141
+ if (opts.action === 'list') {
142
+ const state = readState(opts.cwd);
143
+ const rows = Object.values(CATALOG).map((manifest) => ({
144
+ plugin_key: manifest.plugin_key,
145
+ display_name: manifest.display_name,
146
+ description: manifest.description,
147
+ installed: Boolean(state.plugins[manifest.plugin_key]),
148
+ tools: manifest.tools.map((tool) => tool.tool_key),
149
+ }));
150
+ if (opts.json) process.stdout.write(`${JSON.stringify(rows, null, 2)}\n`);
151
+ else for (const row of rows) console.log(` ${row.installed ? '✓' : '○'} @${row.plugin_key.padEnd(16)} ${row.description}`);
152
+ return rows;
153
+ }
154
+ const key = normalizePluginKey(opts.key || 'agentsam-mcp');
155
+ const manifest = CATALOG[key];
156
+ if (!manifest) throw new Error(`unknown_plugin:${key}`);
157
+ if (opts.action === 'connect') return connectPlugin(opts, key);
158
+ if (opts.action === 'status') return statusPlugin(opts, key);
159
+ if (opts.action !== 'install' && opts.action !== 'remove') throw new Error(`unknown plugins action:${opts.action}`);
160
+ const state = readState(opts.cwd);
161
+ let migration = null;
162
+ if (opts.action === 'install') {
163
+ state.plugins[key] = { plugin_key: key, installed_at: new Date().toISOString(), manifest };
164
+ migration = installMigration(opts.cwd);
165
+ } else {
166
+ delete state.plugins[key];
167
+ }
168
+ const filename = statePath(opts.cwd);
169
+ fs.mkdirSync(path.dirname(filename), { recursive: true, mode: 0o700 });
170
+ fs.writeFileSync(filename, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
171
+ const result = { ok: true, action: opts.action, plugin_key: key, state_file: '.agentsam/plugins.json', migration };
172
+ if (opts.json) process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
173
+ else console.log(`\n${opts.action === 'install' ? 'Installed' : 'Removed'} @${key}\n state: ${result.state_file}${migration ? `\n migration: ${migration}` : ''}\n`);
174
+ return result;
175
+ }
@@ -3,7 +3,7 @@ import path from 'node:path';
3
3
  import { spawnSync } from 'node:child_process';
4
4
  import { cancel, confirm, intro, isCancel, outro, select, text } from '@clack/prompts';
5
5
  import { collectModelsStatus } from './models.js';
6
- import { getModelRecord } from '../models/index.js';
6
+ import { getModelRecord, mergeModelReference } from '../models/index.js';
7
7
  import { detectCliProject, readCliPreferences, writeCliPreferences } from '../lib/cli-preferences.js';
8
8
  import { readAccountSession } from '../lib/account-session.js';
9
9
 
@@ -42,6 +42,7 @@ export function availableShells(env = process.env) {
42
42
  export function modelOptions(status) {
43
43
  const options = [{ value: 'auto', label: 'Automatic', hint: 'runtime chooses from this credential\'s verified inventory', model: null }];
44
44
  for (const model of status.availableModels || []) {
45
+ if (model.provider === 'openai' && model.capabilities?.agent_runtime !== true) continue;
45
46
  const context = Number(model.context_window) > 0 ? ` · ctx ${Math.round(Number(model.context_window) / 1000)}k` : ' · ctx unknown';
46
47
  options.push({
47
48
  value: model.model_key,
@@ -62,22 +63,36 @@ export function modelOptions(status) {
62
63
  },
63
64
  });
64
65
  }
66
+ options.push({
67
+ value: '__configure_provider__',
68
+ label: '+ Configure an AI Provider',
69
+ hint: 'Add OpenAI, Anthropic, Gemini, Cursor, or Grok API key',
70
+ model: null,
71
+ });
65
72
  return options;
66
73
  }
67
74
 
68
75
  function resolvedModel(modelPreference, modelSnapshot) {
69
- if (modelSnapshot?.model_key === modelPreference) return modelSnapshot;
76
+ if (modelSnapshot?.model_key === modelPreference) return mergeModelReference(modelSnapshot);
70
77
  return getModelRecord(modelPreference);
71
78
  }
72
79
 
73
80
  function reasoningOptions(modelPreference, modelSnapshot) {
74
81
  const record = resolvedModel(modelPreference, modelSnapshot);
75
82
  if (!record) return [{ value: 'auto', label: 'Automatic', hint: 'runtime/provider default' }];
76
- return record.reasoning_efforts.map((value) => ({
77
- value,
78
- label: value === 'xhigh' ? 'Extra high' : value === 'max' ? 'Max' : value[0].toUpperCase() + value.slice(1),
79
- hint: value === 'low' ? 'lighter reasoning' : value === 'max' ? 'highest supported reasoning depth' : undefined,
80
- }));
83
+ const providerDefault = record.default_reasoning_effort || 'provider default';
84
+ return [
85
+ { value: 'auto', label: 'Automatic', hint: 'omit reasoning.effort · provider default ' + providerDefault },
86
+ ...record.reasoning_efforts.map((value) => ({
87
+ value,
88
+ label: value === 'xhigh' ? 'Extra high' : value === 'max' ? 'Max' : value[0].toUpperCase() + value.slice(1),
89
+ hint: value === record.default_reasoning_effort
90
+ ? 'provider default'
91
+ : value === 'low' ? 'lighter reasoning'
92
+ : value === 'max' ? 'highest supported reasoning depth'
93
+ : undefined,
94
+ })),
95
+ ];
81
96
  }
82
97
 
83
98
  function serviceTierOptions(modelPreference, modelSnapshot) {
@@ -96,8 +111,13 @@ async function promptModelPreferences(identity, existing, options = {}) {
96
111
  const models = modelOptions(status);
97
112
  const initialModel = models.some((row) => row.value === existing.modelPreference) ? existing.modelPreference : 'auto';
98
113
  const modelPreference = stopIfCancelled(await select({ message: 'Model', initialValue: initialModel, options: models.map(({ model, ...row }) => row) }));
114
+ if (modelPreference === '__configure_provider__') {
115
+ const { runProviders } = await import('./providers.js');
116
+ await runProviders([], { interactive: true, ...(options.modelStatusOptions || {}) });
117
+ return promptModelPreferences(identity, existing, options);
118
+ }
99
119
  const selected = models.find((row) => row.value === modelPreference)?.model || null;
100
- const modelSnapshot = selected || (existing.modelSnapshot?.model_key === modelPreference ? existing.modelSnapshot : null);
120
+ const modelSnapshot = selected || (existing.modelSnapshot?.model_key === modelPreference ? mergeModelReference(existing.modelSnapshot) : null);
101
121
 
102
122
  const reasoning = reasoningOptions(modelPreference, modelSnapshot);
103
123
  const initialReasoning = reasoning.some((row) => row.value === existing.reasoningEffort) ? existing.reasoningEffort : reasoning[0].value;
@@ -126,6 +126,18 @@ export async function runCapabilities(argv = []) {
126
126
 
127
127
  function featureStatePath(cwd) { return path.join(cwd, '.agentsam', 'features.json'); }
128
128
 
129
+ function parseAddArgs(argv = []) {
130
+ const opts = parseCommon(argv);
131
+ opts.provider = '';
132
+ opts.schemaProfile = '';
133
+ for (let i = 0; i < argv.length; i += 1) {
134
+ const arg = argv[i];
135
+ if (arg === '--provider') opts.provider = argv[++i] || '';
136
+ else if (arg === '--schema' || arg === '--schema-profile') opts.schemaProfile = argv[++i] || '';
137
+ }
138
+ return opts;
139
+ }
140
+
129
141
  export function applyPresetSelection(cwd, preset) {
130
142
  const filename = projectConfigPath(cwd);
131
143
  if (!fs.existsSync(filename)) throw new Error('not_agentsam_project');
@@ -136,31 +148,62 @@ export function applyPresetSelection(cwd, preset) {
136
148
  }
137
149
 
138
150
  export async function runAdd(argv = []) {
139
- const opts = parseCommon(argv);
151
+ const opts = parseAddArgs(argv);
140
152
  const id = opts.positionals[0];
141
153
  if (!id || id === '--help') {
142
154
  const rows = listAddons();
143
- console.log(`agentsam add <${rows.map(x => x.id).join('|')}> [--cwd PATH] [--json]`);
155
+ console.log(`agentsam add <${rows.map(x => x.id).join('|')}> [--cwd PATH] [--provider <id>] [--schema <profile>] [--json]`);
144
156
  return null;
145
157
  }
146
158
  const addon = getAddon(id);
147
159
  if (!addon) throw new Error(`unknown_addon:${id}`);
148
160
  const cwd = path.resolve(opts.cwd);
149
161
  if (!fs.existsSync(projectConfigPath(cwd))) throw new Error('not_agentsam_project');
150
- fs.mkdirSync(path.dirname(featureStatePath(cwd)), { recursive: true });
151
- let state = { schema_version: 1, features: {} };
152
- if (fs.existsSync(featureStatePath(cwd))) state = JSON.parse(fs.readFileSync(featureStatePath(cwd), 'utf8'));
153
- state.features ||= {};
154
- state.features[addon.id] = { selected: true, capabilities: addon.capabilities, selected_at: new Date().toISOString() };
155
- fs.writeFileSync(featureStatePath(cwd), `${JSON.stringify(state, null, 2)}\n`, 'utf8');
162
+
163
+ const { writeFeatureSelections } = await import('../features/resolve.js');
164
+ let state = { schema_version: 2, features: {} };
165
+ if (fs.existsSync(featureStatePath(cwd))) {
166
+ state = JSON.parse(fs.readFileSync(featureStatePath(cwd), 'utf8'));
167
+ state.schema_version = 2;
168
+ state.features ||= {};
169
+ }
170
+
171
+ /** @type {Record<string, unknown>} */
172
+ const entry = {
173
+ selected: true,
174
+ capabilities: addon.capabilities,
175
+ selected_at: new Date().toISOString(),
176
+ };
177
+ if (addon.id === 'auth') {
178
+ const { normalizeProviderTemplateId } = await import('../features/resolve.js');
179
+ entry.provider_template = normalizeProviderTemplateId(opts.provider) || 'inneranimalmedia';
180
+ if (opts.schemaProfile) entry.schema_profile = opts.schemaProfile;
181
+ }
182
+ state.features[addon.id] = entry;
183
+
184
+ const written = writeFeatureSelections(cwd, state);
156
185
  if (addon.id === 'deploy-cloudflare') {
157
186
  const config = readProjectConfig(cwd);
158
187
  setDeployTarget(config, 'cloudflare');
159
188
  writeProjectConfig(cwd, config);
160
189
  }
161
- const result = { ok: true, feature: addon.id, capabilities: addon.capabilities, description: addon.description, state_file: '.agentsam/features.json' };
190
+ const result = {
191
+ ok: true,
192
+ feature: addon.id,
193
+ capabilities: addon.capabilities,
194
+ description: addon.description,
195
+ state_file: '.agentsam/features.json',
196
+ resolved_file: 'generated/.agentsam/features-resolved.json',
197
+ provider_template: entry.provider_template || null,
198
+ schema_profile: entry.schema_profile || null,
199
+ resources: written.snapshot?.features?.[addon.id]?.resources || null,
200
+ };
162
201
  if (opts.json) process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
163
- else console.log(`\nAdded ${addon.id}\n ${addon.description}\n state: ${result.state_file}\n`);
202
+ else {
203
+ console.log(`\nAdded ${addon.id}\n ${addon.description}\n state: ${result.state_file}`);
204
+ if (entry.provider_template) console.log(` provider: ${entry.provider_template}`);
205
+ console.log(` resolved: ${result.resolved_file}\n`);
206
+ }
164
207
  return result;
165
208
  }
166
209
 
@@ -6,6 +6,7 @@ import {
6
6
  multiselect,
7
7
  outro,
8
8
  password,
9
+ select,
9
10
  spinner,
10
11
  text,
11
12
  } from '@clack/prompts';
@@ -13,6 +14,7 @@ import { getJson } from '../lib/core-client.js';
13
14
  import {
14
15
  PROVIDER_CREDENTIALS,
15
16
  describeProviderCredential,
17
+ exportProviderEnvProfile,
16
18
  listProviderCredentialStatus,
17
19
  normalizeProviderId,
18
20
  providerCredentialSpec,
@@ -117,15 +119,74 @@ export function renderProviderStatus(rows = []) {
117
119
  lines.push(` ${String(row.label || row.provider).padEnd(18)} ${state}${verification}`);
118
120
  }
119
121
  lines.push('');
120
- lines.push(' Profiles: ~/.agentsam/env.d/<provider>.env · mode 0600');
121
- lines.push(' Load one or many: source ~/.agentsam/load-agent-env.sh openai gemini cursor');
122
+ lines.push(' Storage: Encrypted local vault (AES-256-GCM / OS keychain) — no plaintext on disk.');
123
+ lines.push(' Optional export for non-AgentSam shells: agentsam providers export <provider>');
122
124
  lines.push('');
123
125
  return lines.join('\n');
124
126
  }
125
127
 
126
- async function promptProviderCredential(provider, options = {}) {
127
- const spec = providerCredentialSpec(provider);
128
- if (!spec) throw new Error(`unsupported_provider:${provider}`);
128
+ export async function validateAndSaveProviderCredential(provider, secret, options = {}) {
129
+ const id = normalizeProviderId(provider);
130
+ const spec = providerCredentialSpec(id);
131
+ if (!spec) throw new Error(`unsupported_provider:${id}`);
132
+ const cleanSecret = clean(secret);
133
+ if (!cleanSecret) return { attempted: false, ok: false, error: 'Credential is required', models: [] };
134
+ if (spec.tokenPrefix && !cleanSecret.startsWith(spec.tokenPrefix)) {
135
+ return { attempted: false, ok: false, error: `Expected ${spec.tokenPrefix}…`, models: [] };
136
+ }
137
+
138
+ const accountId = clean(options.accountId);
139
+ if (id === 'cloudflare' && !accountId) {
140
+ return { attempted: false, ok: false, error: 'Cloudflare account ID is required', models: [] };
141
+ }
142
+
143
+ const tempCredential = {
144
+ provider: id,
145
+ configured: true,
146
+ value: cleanSecret,
147
+ account_id: accountId || null,
148
+ };
149
+
150
+ let verification;
151
+ if (id === 'inneranimalmedia') {
152
+ verification = await verifyInnerAnimalMedia(tempCredential, options);
153
+ } else {
154
+ verification = await discoverProviderModels(id, tempCredential, { fetchImpl: options.fetchImpl || fetch });
155
+ }
156
+
157
+ if (!verification.ok) {
158
+ return {
159
+ attempted: true,
160
+ ok: false,
161
+ error: verification.error || 'Provider verification failed',
162
+ models: [],
163
+ saved: false,
164
+ };
165
+ }
166
+
167
+ // Key is verified. Persist securely to the OS store + AES-256-GCM vault.
168
+ // Plaintext shell profiles remain explicit opt-in only.
169
+ setProviderCredential(id, cleanSecret, {
170
+ ...options,
171
+ accountId,
172
+ writeEnvProfile: options.writeEnvProfile === true,
173
+ });
174
+
175
+ return {
176
+ attempted: true,
177
+ ok: true,
178
+ error: null,
179
+ models: verification.models || [],
180
+ model_count: verification.models?.length || 0,
181
+ identity: verification.identity || null,
182
+ saved: true,
183
+ };
184
+ }
185
+
186
+ export async function promptAndConfigureProvider(provider, options = {}) {
187
+ const id = normalizeProviderId(provider);
188
+ const spec = providerCredentialSpec(id);
189
+ if (!spec) throw new Error(`unsupported_provider:${id}`);
129
190
  const promptPassword = options.passwordImpl || password;
130
191
  const promptText = options.textImpl || text;
131
192
  const secret = await promptPassword({
@@ -140,59 +201,82 @@ async function promptProviderCredential(provider, options = {}) {
140
201
  if (isCancel(secret)) return null;
141
202
 
142
203
  let accountId = '';
143
- if (provider === 'cloudflare') {
204
+ if (id === 'cloudflare') {
144
205
  const answer = await promptText({
145
206
  message: 'Cloudflare account ID',
146
207
  placeholder: '32-character account ID',
147
208
  validate(value) {
148
- const id = clean(value);
149
- if (!id) return 'Cloudflare account ID is required';
150
- if (!/^[a-f0-9]{32}$/i.test(id)) return 'Expected a 32-character hexadecimal account ID';
209
+ const val = clean(value);
210
+ if (!val) return 'Cloudflare account ID is required';
211
+ if (!/^[a-f0-9]{32}$/i.test(val)) return 'Expected a 32-character hexadecimal account ID';
151
212
  },
152
213
  });
153
214
  if (isCancel(answer)) return null;
154
215
  accountId = clean(answer);
155
216
  }
156
217
 
157
- setProviderCredential(provider, String(secret), { ...options, accountId });
158
- return verifyProviderCredential(provider, options);
159
- }
218
+ const spin = options.spinnerImpl ? options.spinnerImpl() : spinner();
219
+ spin.start(`Verifying ${spec.label} API credential`);
160
220
 
161
- async function runInteractiveProviders(options = {}) {
162
- const promptMultiselect = options.multiselectImpl || multiselect;
163
- const selected = await promptMultiselect({
164
- message: 'Providers to configure',
165
- required: false,
166
- options: providerChoices(options),
221
+ const result = await validateAndSaveProviderCredential(id, String(secret), {
222
+ ...options,
223
+ accountId,
224
+ writeEnvProfile: options.writeEnvProfile === true,
167
225
  });
168
- if (isCancel(selected)) {
169
- cancel('Provider setup cancelled.');
170
- return collectProviderStatus(options);
226
+
227
+ if (!result.ok) {
228
+ spin.stop(`Verification failed: ${result.error || 'invalid key'} · Key was NOT saved`, 1);
229
+ return { ...result, saved: false };
171
230
  }
172
- if (!selected.length) return collectProviderStatus(options);
231
+
232
+ const count = result.models?.length || 0;
233
+ const suffix = count ? ` · ${count} models visible` : '';
234
+ spin.stop(`Verified${suffix} · saved securely to local vault`);
235
+
236
+ return { ...result, saved: true };
237
+ }
238
+
239
+ async function runInteractiveProviders(options = {}) {
240
+ const promptSelect = options.selectImpl || select;
173
241
 
174
242
  intro('Agent Sam provider setup');
175
- const spin = options.spinnerImpl ? options.spinnerImpl() : spinner();
176
- for (const provider of selected) {
177
- const result = await promptProviderCredential(provider, options);
178
- if (!result) continue;
179
- spin.start(`Verifying ${providerCredentialSpec(provider)?.label || provider}`);
180
- if (result.ok) {
181
- const suffix = result.models?.length ? ` · ${result.models.length} models` : '';
182
- spin.stop(`Verified${suffix}`);
183
- } else {
184
- spin.stop(`Saved · verification failed: ${result.error || 'unknown'}`, 1);
243
+
244
+ while (true) {
245
+ const choices = [
246
+ ...providerChoices(options),
247
+ { value: '__done__', label: 'Done / Return to shell', hint: 'finish provider setup' },
248
+ ];
249
+
250
+ const choice = await promptSelect({
251
+ message: 'Select your preferred provider to continue',
252
+ options: choices,
253
+ });
254
+
255
+ if (isCancel(choice) || choice === '__done__') {
256
+ break;
185
257
  }
258
+
259
+ await promptAndConfigureProvider(choice, options);
186
260
  }
261
+
187
262
  outro('Provider setup complete');
188
263
  return collectProviderStatus(options);
189
264
  }
190
265
 
191
266
  function parseArgs(argv = []) {
192
- const out = { command: 'interactive', provider: '', json: false, verify: false, yes: false, fromEnv: '' };
267
+ const out = {
268
+ command: 'interactive',
269
+ provider: '',
270
+ json: false,
271
+ verify: false,
272
+ yes: false,
273
+ fromEnv: '',
274
+ fromStdin: false,
275
+ exportProfile: true,
276
+ };
193
277
  const args = [...argv];
194
278
  if (args[0] && !args[0].startsWith('-')) out.command = args.shift();
195
- if (['add', 'set', 'remove', 'verify', 'status'].includes(out.command) && args[0] && !args[0].startsWith('-')) {
279
+ if (['add', 'set', 'remove', 'verify', 'status', 'export', 'roll'].includes(out.command) && args[0] && !args[0].startsWith('-')) {
196
280
  out.provider = normalizeProviderId(args.shift());
197
281
  }
198
282
  while (args.length) {
@@ -201,6 +285,9 @@ function parseArgs(argv = []) {
201
285
  else if (arg === '--verify') out.verify = true;
202
286
  else if (arg === '--yes' || arg === '-y') out.yes = true;
203
287
  else if (arg === '--from-env') out.fromEnv = clean(args.shift());
288
+ else if (arg === '--from-stdin') out.fromStdin = true;
289
+ else if (arg === '--no-export') out.exportProfile = false;
290
+ else if (arg === '--export') out.exportProfile = true;
204
291
  else if (arg === '--help' || arg === '-h') out.command = 'help';
205
292
  else throw new Error(`unknown providers option: ${arg}`);
206
293
  }
@@ -215,12 +302,17 @@ export async function runProviders(argv = [], options = {}) {
215
302
  write([
216
303
  'agentsam providers',
217
304
  'agentsam providers status [provider] [--verify] [--json]',
218
- 'agentsam providers add <provider> [--from-env NAME]',
305
+ 'agentsam providers add <provider> [--from-env NAME|--from-stdin] [--no-export]',
306
+ 'agentsam providers roll <provider> [--from-env NAME|--from-stdin] replace + export env.d',
307
+ 'agentsam providers export <provider>',
219
308
  'agentsam providers verify [provider] [--json]',
220
309
  'agentsam providers remove <provider> [--yes]',
221
310
  '',
222
311
  `Providers: ${PROVIDER_ORDER.join(', ')}`,
223
312
  '',
313
+ 'Boot load: source ~/.agentsam/load-agent-env.sh <provider…>',
314
+ ' agentsam env boot-line',
315
+ '',
224
316
  ].join('\n'));
225
317
  return;
226
318
  }
@@ -271,20 +363,57 @@ export async function runProviders(argv = [], options = {}) {
271
363
  return results;
272
364
  }
273
365
 
274
- if (parsed.command === 'add' || parsed.command === 'set') {
366
+ if (parsed.command === 'add' || parsed.command === 'set' || parsed.command === 'roll') {
275
367
  if (!parsed.provider) throw new Error('providers add requires a provider');
276
- if (parsed.fromEnv) {
277
- const value = clean((options.env || process.env)[parsed.fromEnv]);
278
- if (!value) throw new Error(`environment credential missing: ${parsed.fromEnv}`);
279
- setProviderCredential(parsed.provider, value, options);
280
- return verifyProviderCredential(parsed.provider, options);
368
+ if (parsed.command === 'roll') {
369
+ removeProviderCredential(parsed.provider, options);
370
+ }
371
+ let secretValue = '';
372
+ if (parsed.fromStdin) {
373
+ const chunks = [];
374
+ for await (const chunk of options.stdin || process.stdin) chunks.push(chunk);
375
+ secretValue = Buffer.concat(chunks.map((c) => (Buffer.isBuffer(c) ? c : Buffer.from(c)))).toString('utf8').trim();
376
+ if (!secretValue) throw new Error('stdin credential missing');
377
+ } else if (parsed.fromEnv) {
378
+ secretValue = clean((options.env || process.env)[parsed.fromEnv]);
379
+ if (!secretValue) throw new Error(`environment credential missing: ${parsed.fromEnv}`);
380
+ }
381
+ if (secretValue) {
382
+ const verified = await validateAndSaveProviderCredential(parsed.provider, secretValue, {
383
+ ...options,
384
+ writeEnvProfile: parsed.exportProfile,
385
+ });
386
+ if (!verified.ok) {
387
+ throw new Error(`Provider verification failed: ${verified.error}. Credential was not saved.`);
388
+ }
389
+ writeLine(write, ` ${parsed.provider} verified · saved${parsed.exportProfile ? ' · env.d exported' : ''}`);
390
+ if (parsed.exportProfile) {
391
+ writeLine(write, ` source ~/.agentsam/load-agent-env.sh ${parsed.provider}`);
392
+ }
393
+ return verified;
281
394
  }
282
395
  if (options.interactive === false || !(options.interactive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY))) {
283
- throw new Error('providers add requires an interactive terminal or --from-env NAME');
396
+ throw new Error('providers add requires an interactive terminal, --from-env NAME, or --from-stdin');
284
397
  }
285
- const result = await promptProviderCredential(parsed.provider, options);
398
+ const result = await promptAndConfigureProvider(parsed.provider, {
399
+ ...options,
400
+ writeEnvProfile: parsed.exportProfile,
401
+ });
286
402
  if (!result) return null;
287
- writeLine(write, result.ok ? ` ${parsed.provider} verified` : ` ${parsed.provider} saved · verification failed: ${result.error}`);
403
+ writeLine(write, result.ok ? ` ${parsed.provider} verified` : ` ${parsed.provider} verification failed: ${result.error}`);
404
+ if (result.ok && parsed.exportProfile) {
405
+ writeLine(write, ` source ~/.agentsam/load-agent-env.sh ${parsed.provider}`);
406
+ }
407
+ return result;
408
+ }
409
+
410
+ if (parsed.command === 'export') {
411
+ if (!parsed.provider) throw new Error('providers export requires a provider');
412
+ const result = exportProviderEnvProfile(parsed.provider, options);
413
+ writeLine(write, '');
414
+ writeLine(write, ` Exported ${parsed.provider} profile: ${result.file} (mode 0600)`);
415
+ writeLine(write, ` Load into external shell: ${result.source_command}`);
416
+ writeLine(write, '');
288
417
  return result;
289
418
  }
290
419