@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
@@ -98,6 +98,7 @@ function generateViteReact(opts) {
98
98
  FROM node:20-alpine AS build
99
99
  WORKDIR /app
100
100
  COPY package*.json ./
101
+ RUN apk add --no-cache python3 make g++
101
102
  RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
102
103
  COPY . .
103
104
  RUN ${buildCmd}
@@ -125,6 +126,7 @@ function generateNodeService(opts) {
125
126
  FROM node:20-alpine
126
127
  WORKDIR /app
127
128
  COPY package*.json ./
129
+ RUN apk add --no-cache python3 make g++
128
130
  RUN if [ -f package-lock.json ]; then npm ci --omit=dev; else npm install --omit=dev; fi
129
131
  COPY . .
130
132
  ENV PORT=${port}
@@ -152,6 +154,7 @@ function generateWranglerDev(opts) {
152
154
  FROM node:20-alpine
153
155
  WORKDIR /app
154
156
  COPY package*.json ./
157
+ RUN apk add --no-cache python3 make g++
155
158
  RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
156
159
  COPY . .
157
160
  EXPOSE ${port}
@@ -33,6 +33,7 @@ export function toolApprovalKey(capabilityId, input = {}) {
33
33
  const id = clean(capabilityId);
34
34
  const command = clean(input?.command);
35
35
  if (id === 'cloudflare.wrangler.native' && /^[A-Za-z0-9._-]+$/.test(command)) return `${id}:${command}`;
36
+ if (id === 'terminal.exec' && /^[A-Za-z0-9._+-]+$/.test(command)) return `${id}:${command}`;
36
37
  return id;
37
38
  }
38
39
 
@@ -9,7 +9,7 @@ const MIGRATION_FILE = path.join(IDENTITY_PKG, 'src', 'migrations', '0001_identi
9
9
  const BRANDING_SCRIPT = path.join(IDENTITY_PKG, 'src', 'frontend', 'auth-portal', 'shared', 'company-branding.js');
10
10
 
11
11
  /**
12
- * @param {{ projectName: string, brandName?: string, logoUrl?: string, sdkVersion?: string }} config
12
+ * @param {{ projectName: string, brandName?: string, logoUrl?: string, sdkVersion?: string, provider?: string }} config
13
13
  * @returns {Record<string, string>}
14
14
  */
15
15
  export function buildIdentityAppScaffold(config) {
@@ -17,6 +17,7 @@ export function buildIdentityAppScaffold(config) {
17
17
  const brandName = config.brandName || projectName;
18
18
  const logoUrl = config.logoUrl || '/brand/logo.svg';
19
19
  const sdkVersion = config.sdkVersion || 'alpha';
20
+ const provider = config.provider || 'inneranimalmedia';
20
21
 
21
22
  const migrationSql = `${fs.readFileSync(MIGRATION_FILE, 'utf8')}\n${buildCompanySeedSql({ brandName, logoUrl })}\n`;
22
23
  const loginHtml = injectBrandingScript(applyBrandTokens(fs.readFileSync(path.join(AUTH_PAGES_DIR, 'login.html'), 'utf8'), {
@@ -95,6 +96,8 @@ migrations_dir = "migrations"
95
96
 
96
97
  Boring scaffold: **app/frontend** (auth UI) + **backend** (Worker API) + **migrations** (D1).
97
98
 
99
+ Provider template: \`${provider}\` (see \`agentsam identity plan --provider ${provider}\`).
100
+
98
101
  ## Quick start
99
102
 
100
103
  \`\`\`bash
@@ -7,7 +7,13 @@ import { CONFIG_PATH, defaultConfig, readConfig } from '../knowledge/config.js';
7
7
 
8
8
  const sdkRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
9
9
  const runtimeFiles = () => {
10
- const files = ['services/knowledge/package.json', 'services/knowledge/package-lock.json', 'packages/agentsam-repository/src/merkle/hash.js', 'src/errors/contract.js'];
10
+ const files = [
11
+ 'services/knowledge/package.json',
12
+ 'services/knowledge/package-lock.json',
13
+ 'packages/agentsam-repository/src/merkle/hash.js',
14
+ 'packages/agentsam-errors/package.json',
15
+ 'src/errors/contract.js',
16
+ ];
11
17
  const walk = dir => { for (const entry of fs.readdirSync(path.join(sdkRoot, dir), { withFileTypes: true })) {
12
18
  const file = `${dir}/${entry.name}`;
13
19
  if (entry.isDirectory()) walk(file);
@@ -15,6 +21,7 @@ const runtimeFiles = () => {
15
21
  } };
16
22
  walk('src/knowledge');
17
23
  walk('src/rpc/generated');
24
+ walk('packages/agentsam-errors/src');
18
25
  return files.sort();
19
26
  };
20
27
 
@@ -31,6 +38,7 @@ WORKDIR /app
31
38
  COPY package.json package-lock.json ./
32
39
  RUN npm ci --omit=dev --ignore-scripts --no-audit --no-fund
33
40
  COPY src ./src
41
+ COPY packages ./packages
34
42
  ENV NODE_ENV=production PORT=${port} GIT_OPTIONAL_LOCKS=0
35
43
  EXPOSE ${port}
36
44
  HEALTHCHECK --interval=15s --timeout=3s --start-period=10s --retries=3 CMD node -e "fetch('http://127.0.0.1:'+process.env.PORT+'/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
@@ -2,6 +2,10 @@ import fs from 'node:fs';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { randomUUID } from 'node:crypto';
5
+ import { findCliProjectRoot } from './cli-preferences.js';
6
+ import { runtimeDatabasePath, SQLITE_RUNTIME_CAPABILITIES } from '../local/runtime-store.js';
7
+ import { createLocalSqliteDatabaseSync } from '../local/sqlite.js';
8
+ import { applyRuntimeMigrationsSync } from '../local/migrations.js';
5
9
 
6
10
  export const LOCAL_SESSION_SCHEMA = 'agentsam-local-session-v1';
7
11
 
@@ -33,13 +37,51 @@ function filenameFor(sessionId, options = {}) {
33
37
  return path.join(localSessionDirectory(options), `${validateSessionId(sessionId)}.json`);
34
38
  }
35
39
 
36
- function ensureDirectory(options = {}) {
37
- const dir = localSessionDirectory(options);
38
- fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
39
- if (process.platform !== 'win32') {
40
- try { fs.chmodSync(dir, 0o700); } catch { /* best effort */ }
40
+ function projectRoot(value = {}, options = {}) {
41
+ return findCliProjectRoot(options.projectRoot || value.project_root || value.cwd || options.cwd || process.cwd());
42
+ }
43
+
44
+ function withSessionDb(root, fn) {
45
+ const db = createLocalSqliteDatabaseSync(runtimeDatabasePath(root));
46
+ try {
47
+ applyRuntimeMigrationsSync(db);
48
+ return fn(db);
49
+ } finally {
50
+ db.close();
41
51
  }
42
- return dir;
52
+ }
53
+
54
+ function safeProviderState(value) {
55
+ if (!value || typeof value !== 'object') return {};
56
+ // Opaque response IDs allow provider-side continuation. Message arrays and
57
+ // compaction input can carry prompts, tool output, or credential values.
58
+ return {
59
+ ...(clean(value.provider) ? { provider: clean(value.provider) } : {}),
60
+ ...(clean(value.previous_response_id) ? { previous_response_id: clean(value.previous_response_id) } : {}),
61
+ ...(value.has_compacted_input === true ? { has_compacted_input: true } : {}),
62
+ };
63
+ }
64
+
65
+ function safeLastError(value) {
66
+ if (!value || typeof value !== 'object') return null;
67
+ return {
68
+ code: clean(value.code) || null,
69
+ kind: clean(value.kind) || null,
70
+ source: clean(value.source) || null,
71
+ };
72
+ }
73
+
74
+ function safeUsageSnapshot(value) {
75
+ if (!value || typeof value !== 'object') return null;
76
+ const inputTokens = Number(value.current_context?.input_tokens);
77
+ const windowTokens = Number(value.current_context?.window_tokens);
78
+ return {
79
+ estimate_kind: value.estimate_kind === 'provider' ? 'provider' : 'local',
80
+ current_context: {
81
+ input_tokens: Number.isFinite(inputTokens) ? Math.max(0, inputTokens) : 0,
82
+ window_tokens: Number.isFinite(windowTokens) ? Math.max(0, windowTokens) : null,
83
+ },
84
+ };
43
85
  }
44
86
 
45
87
  function normalizeUsage(value = {}) {
@@ -72,13 +114,18 @@ export function normalizeLocalSession(value = {}) {
72
114
  const createdAt = clean(value.created_at) || now();
73
115
  const status = clean(value.status) || 'active';
74
116
  const updatedAt = clean(value.updated_at) || createdAt;
117
+ const root = projectRoot(value);
118
+ const dbPath = runtimeDatabasePath(root);
119
+ const relativeDbPath = path.relative(root, dbPath);
75
120
  return {
76
121
  schema_version: LOCAL_SESSION_SCHEMA,
77
122
  id: validateSessionId(value.id || createLocalSessionId()),
78
123
  status,
124
+ project_root: root,
125
+ storage: { runtime: 'sqlite', path: relativeDbPath.startsWith('..') ? dbPath : relativeDbPath, remote: null, capabilities: SQLITE_RUNTIME_CAPABILITIES },
79
126
  cwd: path.resolve(clean(value.cwd) || process.cwd()),
80
- title: clean(value.title) || sessionTitleFromInput(value.last_input),
81
- last_input: clean(value.last_input) || null,
127
+ title: clean(value.title) || 'Agent Sam session',
128
+ last_input: null,
82
129
  created_at: createdAt,
83
130
  updated_at: updatedAt,
84
131
  active_elapsed_ms: Math.max(0, Number(value.active_elapsed_ms || 0)),
@@ -88,26 +135,49 @@ export function normalizeLocalSession(value = {}) {
88
135
  reasoning_effort: clean(value.reasoning_effort) || null,
89
136
  requested_service_tier: clean(value.requested_service_tier) || null,
90
137
  actual_service_tier: clean(value.actual_service_tier) || null,
91
- provider_state: value.provider_state && typeof value.provider_state === 'object' ? { ...value.provider_state } : {},
92
- usage_snapshot: value.usage_snapshot && typeof value.usage_snapshot === 'object' ? structuredClone(value.usage_snapshot) : null,
138
+ provider_state: safeProviderState(value.provider_state),
139
+ latest_compaction: value.latest_compaction ? {
140
+ compaction_id: clean(value.latest_compaction.compaction_id) || null,
141
+ provider: clean(value.latest_compaction.provider) || null,
142
+ model: clean(value.latest_compaction.model) || null,
143
+ created_at: clean(value.latest_compaction.created_at) || null,
144
+ usage: normalizeUsage(value.latest_compaction.usage),
145
+ cost_usd: Number(value.latest_compaction.cost_usd || 0),
146
+ } : null,
147
+ auto_compact: value.auto_compact !== false,
148
+ usage_snapshot: safeUsageSnapshot(value.usage_snapshot),
93
149
  cumulative_usage: normalizeUsage(value.cumulative_usage || {}),
94
150
  total_cost_usd: Number(value.total_cost_usd || 0),
95
151
  cost_breakdown_usd: normalizeCostBreakdown(value.cost_breakdown_usd || {}),
96
152
  approved_projected_call_cost_usd: Number(value.approved_projected_call_cost_usd || 0),
97
- last_error: value.last_error && typeof value.last_error === 'object' ? structuredClone(value.last_error) : null,
153
+ last_error: safeLastError(value.last_error),
98
154
  };
99
155
  }
100
156
 
101
157
  export function saveLocalSession(session, options = {}) {
102
- const normalized = normalizeLocalSession({ ...session, updated_at: now() });
103
- ensureDirectory(options);
104
- const filename = filenameFor(normalized.id, options);
105
- const temp = `${filename}.${process.pid}.tmp`;
106
- fs.writeFileSync(temp, `${JSON.stringify(normalized, null, 2)}\n`, { mode: 0o600 });
107
- if (process.platform !== 'win32') {
108
- try { fs.chmodSync(temp, 0o600); } catch { /* best effort */ }
109
- }
110
- fs.renameSync(temp, filename);
158
+ const normalized = normalizeLocalSession({ ...session, project_root: projectRoot(session, options), updated_at: now() });
159
+ const compactedInput = session.provider_state?.compacted_input;
160
+ const serialized = Array.isArray(compactedInput) ? JSON.stringify(compactedInput) : null;
161
+ if (serialized && Buffer.byteLength(serialized) > 10 * 1024 * 1024) throw new Error('provider_continuation_too_large');
162
+ if (serialized) normalized.provider_state.has_compacted_input = true;
163
+ withSessionDb(normalized.project_root, (db) => {
164
+ db.exec('BEGIN IMMEDIATE');
165
+ try {
166
+ db.prepare(`
167
+ INSERT INTO agentsam_project_sessions (id, project_root, cwd, status, title, state_json, created_at, updated_at)
168
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
169
+ ON CONFLICT(id) DO UPDATE SET
170
+ cwd = excluded.cwd, status = excluded.status, title = excluded.title,
171
+ state_json = excluded.state_json, updated_at = excluded.updated_at
172
+ `).run(normalized.id, normalized.project_root, normalized.cwd, normalized.status,
173
+ normalized.title, JSON.stringify(normalized), normalized.created_at, normalized.updated_at);
174
+ if (serialized) db.prepare(`INSERT INTO agentsam_provider_continuations (session_id, provider, output_json, updated_at)
175
+ VALUES (?, ?, ?, ?) ON CONFLICT(session_id) DO UPDATE SET provider=excluded.provider, output_json=excluded.output_json, updated_at=excluded.updated_at`
176
+ ).run(normalized.id, normalized.provider_state.provider || '', serialized, normalized.updated_at);
177
+ else if (!normalized.provider_state.has_compacted_input) db.prepare('DELETE FROM agentsam_provider_continuations WHERE session_id = ?').run(normalized.id);
178
+ db.exec('COMMIT');
179
+ } catch (error) { db.exec('ROLLBACK'); throw error; }
180
+ });
111
181
  return normalized;
112
182
  }
113
183
 
@@ -116,11 +186,23 @@ export function createLocalSession(value = {}, options = {}) {
116
186
  }
117
187
 
118
188
  export function loadLocalSession(sessionId, options = {}) {
189
+ const root = projectRoot({}, options);
190
+ const dbPath = runtimeDatabasePath(root);
191
+ if (fs.existsSync(dbPath)) {
192
+ const row = withSessionDb(root, (db) => db.prepare(
193
+ 'SELECT state_json FROM agentsam_project_sessions WHERE id = ? AND project_root = ?'
194
+ ).get(validateSessionId(sessionId), root));
195
+ if (row) return normalizeLocalSession(JSON.parse(row.state_json));
196
+ }
197
+ // Read-only compatibility with older ~/.agentsam/sessions/*.json state.
198
+ // Import only when the saved cwd belongs to the selected project; never
199
+ // create new home-level session files or resume a different project's row.
119
200
  const filename = filenameFor(sessionId, options);
120
201
  if (!fs.existsSync(filename)) return null;
121
202
  const parsed = JSON.parse(fs.readFileSync(filename, 'utf8'));
122
203
  if (parsed?.schema_version !== LOCAL_SESSION_SCHEMA) throw new Error(`unsupported_local_session_schema:${parsed?.schema_version || 'missing'}`);
123
- return normalizeLocalSession(parsed);
204
+ if (projectRoot(parsed) !== root) return null;
205
+ return saveLocalSession(parsed, { projectRoot: root });
124
206
  }
125
207
 
126
208
  export function updateLocalSession(sessionId, patch = {}, options = {}) {
@@ -130,19 +212,27 @@ export function updateLocalSession(sessionId, patch = {}, options = {}) {
130
212
  }
131
213
 
132
214
  export function listLocalSessions(options = {}) {
215
+ const root = projectRoot({}, options);
133
216
  const dir = localSessionDirectory(options);
134
- if (!fs.existsSync(dir)) return [];
135
- const cwd = clean(options.cwd) ? path.resolve(options.cwd) : '';
136
- const limit = Number.isInteger(options.limit) && options.limit > 0 ? Math.min(options.limit, 100) : 20;
137
- const rows = [];
138
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
139
- if (!entry.isFile() || !entry.name.startsWith('asess_') || !entry.name.endsWith('.json')) continue;
140
- try {
141
- const parsed = JSON.parse(fs.readFileSync(path.join(dir, entry.name), 'utf8'));
142
- if (parsed?.schema_version !== LOCAL_SESSION_SCHEMA) continue;
143
- const session = normalizeLocalSession(parsed);
144
- if (!cwd || session.cwd === cwd) rows.push(session);
145
- } catch { /* skip corrupt session file */ }
217
+ if (fs.existsSync(dir)) {
218
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
219
+ if (!entry.isFile() || !entry.name.startsWith('asess_') || !entry.name.endsWith('.json')) continue;
220
+ try { loadLocalSession(entry.name.slice(0, -5), { ...options, projectRoot: root }); }
221
+ catch { /* legacy corrupt files remain untouched */ }
222
+ }
146
223
  }
147
- return rows.sort((a, b) => String(b.updated_at).localeCompare(String(a.updated_at))).slice(0, limit);
224
+ if (!fs.existsSync(runtimeDatabasePath(root))) return [];
225
+ const limit = Number.isInteger(options.limit) && options.limit > 0 ? Math.min(options.limit, 100) : 20;
226
+ return withSessionDb(root, (db) => db.prepare(
227
+ 'SELECT state_json FROM agentsam_project_sessions WHERE project_root = ? ORDER BY updated_at DESC LIMIT ?'
228
+ ).all(root, limit).map((row) => normalizeLocalSession(JSON.parse(row.state_json))));
229
+ }
230
+
231
+ export function loadSessionContinuation(session) {
232
+ if (!session?.provider_state?.has_compacted_input) return session?.provider_state || null;
233
+ return withSessionDb(projectRoot(session), db => {
234
+ const row = db.prepare('SELECT provider, output_json FROM agentsam_provider_continuations WHERE session_id = ?').get(validateSessionId(session.id));
235
+ if (!row || row.provider !== session.provider_state.provider) throw new Error('provider_continuation_missing');
236
+ return { ...session.provider_state, compacted_input: JSON.parse(row.output_json) };
237
+ });
148
238
  }
@@ -1,29 +1,37 @@
1
- import fs from 'node:fs';
2
1
  import path from 'node:path';
3
2
  import { tryResolveGitContext } from '../../packages/agentsam-repository/src/git-context.js';
4
3
  import { inspectLocalSqlite } from '../local/sqlite.js';
5
- import { getCreatedWithVersion, getDefaultProfile, getDeployTarget, getLocalDatabasePath, getProjectName, getProjectPreset, getRepositoryId, tryReadProjectConfig } from './project-config.js';
4
+ import {
5
+ getCreatedWithVersion,
6
+ getDefaultProfile,
7
+ getDeployTarget,
8
+ getLocalDatabasePath,
9
+ getProjectName,
10
+ getProjectPreset,
11
+ getRepositoryId,
12
+ tryReadProjectConfig,
13
+ } from './project-config.js';
14
+ import { findCliProjectRoot } from './cli-preferences.js';
6
15
 
7
16
  export function findAgentSamProjectRoot(startDir = process.cwd()) {
8
- let dir = path.resolve(startDir);
9
- for (let i = 0; i < 16; i += 1) {
10
- if (fs.existsSync(path.join(dir, '.agentsam', 'config.json'))) return dir;
11
- const parent = path.dirname(dir);
12
- if (parent === dir) break;
13
- dir = parent;
14
- }
15
- return path.resolve(startDir);
17
+ return findCliProjectRoot(startDir);
16
18
  }
17
19
 
18
20
  async function probe(url) {
19
21
  try {
20
- const response = await fetch(url, { signal: AbortSignal.timeout(500) });
22
+ const response = await fetch(url, { signal: AbortSignal.timeout(1500) });
21
23
  return { online: response.ok, status: response.status, url };
22
24
  } catch {
23
25
  return { online: false, status: null, url };
24
26
  }
25
27
  }
26
28
 
29
+ function resolveLiveHealthUrl(config) {
30
+ const fromDeploy = config?.deployment?.cloudflare?.health_url;
31
+ if (fromDeploy != null && String(fromDeploy).trim()) return String(fromDeploy).trim();
32
+ return null;
33
+ }
34
+
27
35
  export async function collectLocalStatus(cwd = process.cwd()) {
28
36
  const root = findAgentSamProjectRoot(cwd);
29
37
  const config = tryReadProjectConfig(root);
@@ -36,10 +44,16 @@ export async function collectLocalStatus(cwd = process.cwd()) {
36
44
 
37
45
  const devPort = config?.dev_port ?? 8787;
38
46
  const ptyPort = config?.pty_port ?? 3099;
39
- const [api, pty] = await Promise.all([
47
+ const liveUrl = resolveLiveHealthUrl(config);
48
+ const probes = [
40
49
  probe(`http://127.0.0.1:${devPort}/api/health`),
41
50
  probe(`http://127.0.0.1:${ptyPort}/health`),
42
- ]);
51
+ ];
52
+ if (liveUrl) probes.push(probe(liveUrl));
53
+ const results = await Promise.all(probes);
54
+ const api = results[0];
55
+ const pty = results[1];
56
+ const live = liveUrl ? results[2] : null;
43
57
 
44
58
  return {
45
59
  schemaVersion: 'agentsam-local-status-v1',
@@ -60,12 +74,19 @@ export async function collectLocalStatus(cwd = process.cwd()) {
60
74
  }
61
75
  : null,
62
76
  db: {
63
- ready: Boolean(db.exists),
77
+ ready: Boolean(
78
+ db.exists &&
79
+ db.tables?.includes('agentsam_schema_migrations') &&
80
+ db.tables?.includes('agentsam_project_sessions'),
81
+ ),
64
82
  path: db.dbPath || path.join(root, '.agentsam/data/agentsam.sqlite'),
65
83
  tables: db.tables || [],
66
84
  sizeBytes: db.sizeBytes || 0,
67
85
  },
68
86
  api,
69
87
  pty,
88
+ live: liveUrl
89
+ ? live || { online: false, status: null, url: liveUrl }
90
+ : { online: false, status: null, url: null },
70
91
  };
71
92
  }
@@ -76,6 +76,9 @@ export function createProjectManifest({
76
76
  knowledge: {
77
77
  config: '.agentsam/knowledge.json',
78
78
  },
79
+ // Project-owned plugin/resource declarations. Bindings, indexes, models,
80
+ // and dimensions belong here rather than in a global SDK default.
81
+ plugins: {},
79
82
  local: {
80
83
  database: '.agentsam/data/agentsam.sqlite',
81
84
  schema: 'db/schema.sql',
@@ -151,6 +154,12 @@ export function getKnowledgeConfigPath(config) {
151
154
  return clean(config?.knowledge?.config) || '.agentsam/knowledge.json';
152
155
  }
153
156
 
157
+ export function getProjectPluginConfig(config, pluginKey) {
158
+ const key = clean(pluginKey).replace(/^@/, '');
159
+ const plugins = config?.plugins || config?.integrations || {};
160
+ return plugins[key] || plugins[`@${key}`] || null;
161
+ }
162
+
154
163
  export function getLocalDatabasePath(config) {
155
164
  return clean(config?.local?.database || config?.db_path) || '.agentsam/data/agentsam.sqlite';
156
165
  }
@@ -1,6 +1,14 @@
1
1
  import fs from 'node:fs';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
+ import {
5
+ getSecureProviderKey,
6
+ setSecureProviderKey,
7
+ deleteSecureProviderKey,
8
+ hydrateSecureCredentials,
9
+ } from '../security/local-vault.js';
10
+
11
+ export { hydrateSecureCredentials };
4
12
 
5
13
  export const PROVIDER_CREDENTIALS = Object.freeze({
6
14
  openai: Object.freeze({ label: 'OpenAI', env: 'OPENAI_API_KEY', files: ['openai.env'], modelProvider: 'openai' }),
@@ -13,7 +21,7 @@ export const PROVIDER_CREDENTIALS = Object.freeze({
13
21
  env: 'CLOUDFLARE_API_TOKEN',
14
22
  files: ['cloudflare.env'],
15
23
  modelProvider: 'cloudflare',
16
- accountEnv: ['ACCOUNT_ID', 'CLOUDFLARE_ACCOUNT_ID'],
24
+ accountEnv: ['CLOUDFLARE_ACCOUNT_ID'],
17
25
  }),
18
26
  inneranimalmedia: Object.freeze({
19
27
  label: 'InnerAnimalMedia',
@@ -121,32 +129,17 @@ export function agentEnvLoaderPath(options = {}) {
121
129
 
122
130
  export function ensureAgentEnvLoader(options = {}) {
123
131
  const filename = agentEnvLoaderPath(options);
124
- const supported = Object.keys(PROVIDER_CREDENTIALS).join('|');
125
- const source = `# AgentSam provider environment loader. Source this file; do not execute it.
126
- if [ "$#" -eq 0 ]; then
127
- echo "usage: source ~/.agentsam/load-agent-env.sh <profile> [profile ...]" >&2
128
- return 2 2>/dev/null || exit 2
132
+ const source = `# AgentSam environment loader. Source this file; do not execute it.
133
+ # Credentials resolve from the OS keychain / local vault via \`agentsam env shell\`.
134
+ # Do not put plaintext secrets in this file.
135
+ if command -v agentsam >/dev/null 2>&1; then
136
+ eval "$(agentsam env shell --profile default)"
137
+ elif command -v agentsam-env >/dev/null 2>&1; then
138
+ eval "$(agentsam-env shell --profile default)"
139
+ else
140
+ echo "agentsam CLI not found on PATH; cannot load AgentSam credentials" >&2
141
+ return 1 2>/dev/null || exit 1
129
142
  fi
130
- for _agentsam_profile in "$@"; do
131
- case "$_agentsam_profile" in
132
- grok) _agentsam_profile="xai" ;;
133
- ${supported}) ;;
134
- *) echo "unknown AgentSam provider profile: $_agentsam_profile" >&2; return 2 2>/dev/null || exit 2 ;;
135
- esac
136
- _agentsam_file="\${HOME}/.agentsam/env.d/\${_agentsam_profile}.env"
137
- if [ ! -f "$_agentsam_file" ]; then
138
- echo "AgentSam provider profile not found: $_agentsam_file" >&2
139
- return 1 2>/dev/null || exit 1
140
- fi
141
- set -a
142
- . "$_agentsam_file"
143
- set +a
144
- if [ "$_agentsam_profile" = cloudflare ]; then
145
- if [ -z "\${ACCOUNT_ID:-}" ] && [ -n "\${CLOUDFLARE_ACCOUNT_ID:-}" ]; then export ACCOUNT_ID="$CLOUDFLARE_ACCOUNT_ID"; fi
146
- if [ -z "\${CLOUDFLARE_ACCOUNT_ID:-}" ] && [ -n "\${ACCOUNT_ID:-}" ]; then export CLOUDFLARE_ACCOUNT_ID="$ACCOUNT_ID"; fi
147
- fi
148
- done
149
- unset _agentsam_file _agentsam_profile
150
143
  `;
151
144
  atomicWrite(filename, source, 0o700);
152
145
  return filename;
@@ -157,8 +150,8 @@ function profileSource(provider, credential = '', options = {}) {
157
150
  if (!spec) throw new Error(`unsupported_provider:${normalizeProviderId(provider)}`);
158
151
  const lines = [`# AgentSam ${spec.label} provider profile`];
159
152
  if (spec.provider === 'cloudflare') {
160
- lines.push('# ACCOUNT_ID is your Cloudflare account identifier; it is not a secret.');
161
- lines.push(`export ACCOUNT_ID=${envLiteral(normalizeCloudflareAccountId(options.accountId))}`);
153
+ lines.push('# CLOUDFLARE_ACCOUNT_ID is your Cloudflare account identifier; it is not a secret.');
154
+ lines.push(`export CLOUDFLARE_ACCOUNT_ID=${envLiteral(normalizeCloudflareAccountId(options.accountId))}`);
162
155
  }
163
156
  lines.push(`export ${spec.env}=${envLiteral(credential)}`);
164
157
  return `${lines.join('\n')}\n`;
@@ -190,9 +183,9 @@ export function ensureProviderEnvProfile(provider, options = {}) {
190
183
  const current = firstEnvValue(source, spec.accountEnv || []);
191
184
  if (!current) {
192
185
  const accountId = normalizeCloudflareAccountId(options.accountId);
193
- const line = `export ACCOUNT_ID=${envLiteral(accountId)}`;
194
- const next = /^(?:export\s+)?ACCOUNT_ID=.*$/m.test(source)
195
- ? source.replace(/^(?:export\s+)?ACCOUNT_ID=.*$/m, line)
186
+ const line = `export CLOUDFLARE_ACCOUNT_ID=${envLiteral(accountId)}`;
187
+ const next = /^(?:export\s+)?CLOUDFLARE_ACCOUNT_ID=.*$/m.test(source)
188
+ ? source.replace(/^(?:export\s+)?CLOUDFLARE_ACCOUNT_ID=.*$/m, line)
196
189
  : `${line}\n${source}`;
197
190
  atomicWrite(filename, next, 0o600);
198
191
  }
@@ -212,8 +205,46 @@ export function setProviderCredential(provider, credential, options = {}) {
212
205
  const spec = providerCredentialSpec(provider);
213
206
  if (!spec) throw new Error(`unsupported_provider:${normalizeProviderId(provider)}`);
214
207
  const value = validateCredentialValue(spec, credential);
208
+ setSecureProviderKey(spec.provider, { value, accountId: options.accountId }, options);
209
+ if (typeof process !== 'undefined' && process.env) {
210
+ process.env[spec.env] = value;
211
+ if (spec.provider === 'cloudflare' && options.accountId) {
212
+ process.env.CLOUDFLARE_ACCOUNT_ID = options.accountId;
213
+ }
214
+ }
215
+ let file = null;
216
+ let loader = null;
217
+ let sourceCommand = null;
218
+ if (options.exportProfile === true || options.writeEnvProfile === true) {
219
+ const filename = path.join(agentEnvDirectory(options), spec.files[0]);
220
+ atomicWrite(filename, profileSource(spec.provider, value, options), 0o600);
221
+ loader = ensureAgentEnvLoader(options);
222
+ file = filename;
223
+ sourceCommand = `source ~/.agentsam/load-agent-env.sh ${spec.provider}`;
224
+ }
225
+ return Object.freeze({
226
+ provider: spec.provider,
227
+ file,
228
+ loader,
229
+ source_command: sourceCommand,
230
+ });
231
+ }
232
+
233
+ /**
234
+ * Exports a configured provider credential from the secure vault to a plaintext .env file.
235
+ * This is an explicit opt-in action for operators who need to source credentials into external shells.
236
+ * The standard AgentSam setup flows (interactive picker, models --setup, providers add)
237
+ * intentionally do NOT invoke this, keeping the credential strictly inside the encrypted vault.
238
+ */
239
+ export function exportProviderEnvProfile(provider, options = {}) {
240
+ const spec = providerCredentialSpec(provider);
241
+ if (!spec) throw new Error(`unsupported_provider:${normalizeProviderId(provider)}`);
242
+ const resolved = resolveProviderCredential(spec.provider, options);
243
+ if (!resolved.configured || !resolved.value) {
244
+ throw new Error(`provider_not_configured:${spec.provider}`);
245
+ }
215
246
  const filename = path.join(agentEnvDirectory(options), spec.files[0]);
216
- atomicWrite(filename, profileSource(spec.provider, value, options), 0o600);
247
+ atomicWrite(filename, profileSource(spec.provider, resolved.value, { ...options, accountId: resolved.account_id }), 0o600);
217
248
  const loader = ensureAgentEnvLoader(options);
218
249
  return Object.freeze({
219
250
  provider: spec.provider,
@@ -226,6 +257,7 @@ export function setProviderCredential(provider, credential, options = {}) {
226
257
  export function removeProviderCredential(provider, options = {}) {
227
258
  const spec = providerCredentialSpec(provider);
228
259
  if (!spec) throw new Error(`unsupported_provider:${normalizeProviderId(provider)}`);
260
+ deleteSecureProviderKey(spec.provider, options);
229
261
  const dir = agentEnvDirectory(options);
230
262
  let removed = false;
231
263
  for (const basename of spec.files) {
@@ -236,6 +268,9 @@ export function removeProviderCredential(provider, options = {}) {
236
268
  fs.rmSync(filename, { force: true });
237
269
  removed = true;
238
270
  }
271
+ if (typeof process !== 'undefined' && process.env) {
272
+ delete process.env[spec.env];
273
+ }
239
274
  return Object.freeze({ provider: spec.provider, removed });
240
275
  }
241
276
 
@@ -259,6 +294,22 @@ export function resolveProviderCredential(provider, options = {}) {
259
294
  });
260
295
  }
261
296
 
297
+ const secure = getSecureProviderKey(spec.provider, options);
298
+ if (secure && clean(secure.value)) {
299
+ const val = clean(secure.value);
300
+ const prefixError = spec.tokenPrefix && !val.startsWith(spec.tokenPrefix) ? `credential_prefix_required:${spec.tokenPrefix}` : null;
301
+ return Object.freeze({
302
+ provider: spec.provider,
303
+ configured: !prefixError,
304
+ source: secure.source || 'local_vault',
305
+ env: spec.env,
306
+ file: null,
307
+ error: prefixError,
308
+ value: prefixError ? '' : val,
309
+ account_id: accountIdFromEnv || secure.accountId || null,
310
+ });
311
+ }
312
+
262
313
  const dir = agentEnvDirectory({ ...options, env });
263
314
  for (const basename of spec.files) {
264
315
  const filename = path.join(dir, basename);
@@ -297,3 +348,56 @@ export function describeProviderCredential(provider, options = {}) {
297
348
  export function listProviderCredentialStatus(options = {}) {
298
349
  return Object.freeze(Object.keys(PROVIDER_CREDENTIALS).map((provider) => describeProviderCredential(provider, options)));
299
350
  }
351
+
352
+ /**
353
+ * Emit shell `export` lines for configured credentials from vault/keychain/env.
354
+ * Bootstrap-safe: does not require AGENTSAM_API_KEY already present to resolve it.
355
+ * Prefer vault/OS store over ambient env when `preferVault` is true (default for shell).
356
+ */
357
+ export function renderEnvShellExports(options = {}) {
358
+ const profile = clean(options.profile || 'default').toLowerCase();
359
+ const wanted = Array.isArray(options.providers) && options.providers.length
360
+ ? options.providers.map(normalizeProviderId).filter(Boolean)
361
+ : profile === 'default'
362
+ ? Object.keys(PROVIDER_CREDENTIALS)
363
+ : profile.split(/[,\s]+/).map(normalizeProviderId).filter(Boolean);
364
+
365
+ const lines = ['# AgentSam env shell — evaluated by: eval "$(agentsam env shell)"'];
366
+ const emitted = [];
367
+
368
+ for (const provider of wanted) {
369
+ const spec = providerCredentialSpec(provider);
370
+ if (!spec) continue;
371
+
372
+ let resolved;
373
+ if (options.preferVault !== false) {
374
+ // Skip ambient process.env so a stale empty shell does not block keychain.
375
+ const vaultOnly = { ...options, env: { ...(options.env || {}), [spec.env]: undefined } };
376
+ if (spec.accountEnv) {
377
+ for (const name of spec.accountEnv) vaultOnly.env[name] = undefined;
378
+ }
379
+ resolved = resolveProviderCredential(spec.provider, vaultOnly);
380
+ if (!resolved.configured) {
381
+ resolved = resolveProviderCredential(spec.provider, options);
382
+ }
383
+ } else {
384
+ resolved = resolveProviderCredential(spec.provider, options);
385
+ }
386
+
387
+ if (!resolved.configured || !resolved.value) continue;
388
+ lines.push(`export ${spec.env}=${envLiteral(resolved.value)}`);
389
+ if (spec.provider === 'cloudflare' && resolved.account_id) {
390
+ lines.push(`export CLOUDFLARE_ACCOUNT_ID=${envLiteral(resolved.account_id)}`);
391
+ }
392
+ emitted.push(spec.provider);
393
+ }
394
+
395
+ if (!emitted.length) {
396
+ lines.push('# No AgentSam credentials configured. Run: agentsam api-key create --store keychain --activate');
397
+ }
398
+ return Object.freeze({
399
+ profile,
400
+ providers: emitted,
401
+ script: `${lines.join('\n')}\n`,
402
+ });
403
+ }