@inneranimalmedia/agentsam-sdk 2.6.2 → 2.6.3

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 (497) hide show
  1. package/AGENTSAM.md +45 -1
  2. package/README.md +80 -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/docs/AUTORAG.md +58 -0
  17. package/docs/BRAND_INTELLIGENCE.md +30 -0
  18. package/docs/CLI_SHELL.md +4 -2
  19. package/docs/CMS_CONTEXTUAL_COMPOSER.md +38 -0
  20. package/docs/MERKLE.md +4 -0
  21. package/docs/PROJECT_CONFIG.md +3 -0
  22. package/docs/REPOSITORY_KNOWLEDGE.md +2 -0
  23. package/docs/THEME_REFINERY.md +120 -0
  24. package/docs/architecture/PROVIDER-TOOLS-AND-COMPACTION.md +60 -0
  25. package/docs/architecture/STORAGE.md +87 -0
  26. package/docs/cad-project-tools.md +69 -0
  27. package/docs/cms-scaffolding-pattern-reference.md +73 -0
  28. package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS-codex-tui-20260919.md +113 -0
  29. package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS.md +85 -0
  30. package/docs/plans/AGENTSAM-MCP-CLIENT-2026-09-19.md +181 -0
  31. package/docs/plans/ASBD-PORTABLE-WORKGRAPH-UI-DEFERRED.md +34 -0
  32. package/docs/plans/ASTRA-BRIEF-2026-09-18.md +258 -0
  33. package/docs/plans/MULTI-AGENT-SPRINTS-2026-09-19.md +373 -0
  34. package/docs/plans/NEXT-AGENT-HANDOFF.md +167 -0
  35. package/docs/plans/RECONCILIATION-2026-09-19.md +178 -0
  36. package/docs/plugins.md +43 -0
  37. package/docs/tools/README.md +57 -0
  38. package/docs/tools/agent-and-orchestration.md +49 -0
  39. package/docs/tools/browser-and-research.md +46 -0
  40. package/docs/tools/cloudflare-platform.md +32 -0
  41. package/docs/tools/cms.md +25 -0
  42. package/docs/tools/communications.md +41 -0
  43. package/docs/tools/database-and-storage.md +62 -0
  44. package/docs/tools/design-and-media.md +64 -0
  45. package/docs/tools/filesystem-and-code.md +55 -0
  46. package/docs/tools/github.md +56 -0
  47. package/docs/tools/integrations-and-misc.md +16 -0
  48. package/docs/tools/memory.md +21 -0
  49. package/docs/tools/terminal-and-execution.md +29 -0
  50. package/docs/tools/tickets-and-platform.md +30 -0
  51. package/migrations/d1/0001_agentsam_plugin_runtime.sql +177 -0
  52. package/migrations/d1/0002_agentsam_ticket_ownership.sql +8 -0
  53. package/migrations/d1/0002_dynamic_model_policies.sql +23 -0
  54. package/migrations/d1/0003_expand_tool_handler_families.sql +18 -0
  55. package/migrations/d1/0004_project_aware_retrieval_lanes.sql +24 -0
  56. package/migrations/d1/0005_portable_knowledge_identity.sql +104 -0
  57. package/migrations/d1/0006_repair_ops_trail_account_scope.sql +14 -0
  58. package/migrations/d1/0007_repair_ops_trail_agent_run_account.sql +13 -0
  59. package/migrations/d1/0008_backfill_knowledge_run_legacy_tenant.sql +14 -0
  60. package/migrations/d1/0009_normalize_cloudflare_plugin_installations.sql +137 -0
  61. package/migrations/runtime/0001_cli_runtime.sql +67 -0
  62. package/migrations/runtime/0002_project_sessions.sql +15 -0
  63. package/migrations/runtime/0003_provider_continuations.sql +8 -0
  64. package/package.json +92 -12
  65. package/packages/agentsam-brand/README.md +21 -0
  66. package/packages/agentsam-brand/package.json +22 -0
  67. package/packages/agentsam-brand/src/contract.js +59 -0
  68. package/packages/agentsam-brand/src/extract.js +126 -0
  69. package/packages/agentsam-brand/src/goap-actions.js +73 -0
  70. package/packages/agentsam-brand/src/index.js +48 -0
  71. package/packages/agentsam-brand/src/plan.js +115 -0
  72. package/packages/agentsam-brand/src/resolve.js +139 -0
  73. package/packages/agentsam-brand/src/scan.js +250 -0
  74. package/packages/agentsam-brand/test/brand-scan.test.mjs +106 -0
  75. package/packages/agentsam-contracts/README.md +23 -0
  76. package/packages/agentsam-contracts/package.json +32 -0
  77. package/packages/agentsam-contracts/src/adapter.ts +25 -0
  78. package/packages/agentsam-contracts/src/agent.ts +35 -0
  79. package/packages/agentsam-contracts/src/artifacts.ts +33 -0
  80. package/packages/agentsam-contracts/src/authority.ts +29 -0
  81. package/packages/agentsam-contracts/src/context.ts +16 -0
  82. package/packages/agentsam-contracts/src/errors.ts +46 -0
  83. package/packages/agentsam-contracts/src/events.ts +47 -0
  84. package/packages/agentsam-contracts/src/execution.ts +50 -0
  85. package/packages/agentsam-contracts/src/hooks.ts +40 -0
  86. package/packages/agentsam-contracts/src/identity.ts +16 -0
  87. package/packages/agentsam-contracts/src/index.ts +14 -0
  88. package/packages/agentsam-contracts/src/models.ts +9 -0
  89. package/packages/agentsam-contracts/src/providers.ts +33 -0
  90. package/packages/agentsam-contracts/src/repository.ts +64 -0
  91. package/packages/agentsam-contracts/src/tools.ts +98 -0
  92. package/packages/agentsam-contracts/test/contracts.test.mjs +16 -0
  93. package/packages/agentsam-contracts/test/errors-catalog.test.mjs +25 -0
  94. package/packages/agentsam-contracts/test/repository.test.mjs +18 -0
  95. package/packages/agentsam-contracts/tsconfig.json +12 -0
  96. package/packages/agentsam-errors/package.json +17 -0
  97. package/packages/agentsam-errors/src/adapters/anthropic.js +15 -0
  98. package/packages/agentsam-errors/src/adapters/cad.js +109 -0
  99. package/packages/agentsam-errors/src/adapters/cloudflare.js +21 -0
  100. package/packages/agentsam-errors/src/adapters/cursor.js +4 -0
  101. package/packages/agentsam-errors/src/adapters/device.js +38 -0
  102. package/packages/agentsam-errors/src/adapters/docker.js +28 -0
  103. package/packages/agentsam-errors/src/adapters/gcp.js +14 -0
  104. package/packages/agentsam-errors/src/adapters/github.js +22 -0
  105. package/packages/agentsam-errors/src/adapters/google.js +17 -0
  106. package/packages/agentsam-errors/src/adapters/index.js +55 -0
  107. package/packages/agentsam-errors/src/adapters/internal.js +40 -0
  108. package/packages/agentsam-errors/src/adapters/oauth.js +24 -0
  109. package/packages/agentsam-errors/src/adapters/openai.js +17 -0
  110. package/packages/agentsam-errors/src/adapters/process.js +35 -0
  111. package/packages/agentsam-errors/src/adapters/provider.js +114 -0
  112. package/packages/agentsam-errors/src/envelope.js +186 -0
  113. package/packages/agentsam-errors/src/error.js +24 -0
  114. package/packages/agentsam-errors/src/fingerprint.js +35 -0
  115. package/packages/agentsam-errors/src/index.js +10 -0
  116. package/packages/agentsam-errors/src/normalize.js +30 -0
  117. package/packages/agentsam-errors/src/redaction.js +52 -0
  118. package/packages/agentsam-errors/src/render.js +16 -0
  119. package/packages/agentsam-errors/src/retry.js +10 -0
  120. package/packages/agentsam-errors/src/transport.js +52 -0
  121. package/packages/agentsam-errors/src/vocabulary.js +320 -0
  122. package/packages/agentsam-errors/test/envelope.test.mjs +70 -0
  123. package/packages/agentsam-errors/test/providers.test.mjs +99 -0
  124. package/packages/agentsam-errors/test/redaction.test.mjs +21 -0
  125. package/packages/agentsam-errors/test/runtime-cad-device.test.mjs +76 -0
  126. package/packages/agentsam-errors/test/transport.test.mjs +46 -0
  127. package/packages/agentsam-knowledge/package.json +15 -0
  128. package/packages/agentsam-knowledge/src/autorag/index.js +64 -0
  129. package/packages/agentsam-knowledge/src/backends/index.js +26 -0
  130. package/packages/agentsam-knowledge/src/index.js +3 -0
  131. package/packages/agentsam-knowledge/src/providers/index.js +95 -0
  132. package/packages/agentsam-knowledge/test/autorag.test.mjs +42 -0
  133. package/packages/agentsam-nav/README.md +40 -0
  134. package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
  135. package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
  136. package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
  137. package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
  138. package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
  139. package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
  140. package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
  141. package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
  142. package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
  143. package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
  144. package/packages/agentsam-nav/dist/browser.d.ts +11 -0
  145. package/packages/agentsam-nav/dist/browser.global.js +132 -0
  146. package/packages/agentsam-nav/dist/browser.js +613 -0
  147. package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
  148. package/packages/agentsam-nav/dist/index.d.ts +11 -0
  149. package/packages/agentsam-nav/dist/index.js +614 -0
  150. package/packages/agentsam-nav/dist/legacy.css +83 -0
  151. package/packages/agentsam-nav/dist/shell.css +113 -0
  152. package/packages/agentsam-nav/dist/theme.css +113 -0
  153. package/packages/agentsam-nav/dist/utils.d.ts +1 -0
  154. package/packages/agentsam-nav/package.json +43 -0
  155. package/packages/agentsam-queue-control/README.md +107 -0
  156. package/packages/agentsam-queue-control/package.json +31 -0
  157. package/packages/agentsam-queue-control/schemas/job-envelope.schema.json +56 -0
  158. package/packages/agentsam-queue-control/src/adapters/cloudflare.js +152 -0
  159. package/packages/agentsam-queue-control/src/adapters/memory.js +38 -0
  160. package/packages/agentsam-queue-control/src/contracts.js +130 -0
  161. package/packages/agentsam-queue-control/src/control-plane.js +141 -0
  162. package/packages/agentsam-queue-control/src/dispatch.js +43 -0
  163. package/packages/agentsam-queue-control/src/index.js +7 -0
  164. package/packages/agentsam-queue-control/src/policy.js +88 -0
  165. package/packages/agentsam-queue-control/src/topology.js +66 -0
  166. package/packages/agentsam-queue-control/test/queue-control.test.mjs +100 -0
  167. package/packages/agentsam-repository/src/goap.js +718 -0
  168. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
  169. package/packages/agentsam-repository/src/index.js +5 -0
  170. package/packages/agentsam-repository/src/merkle/cloudflare-persistence.js +2 -2
  171. package/packages/agentsam-repository/src/tickets.js +184 -0
  172. package/packages/agentsam-repository/src/work-tracking.js +199 -0
  173. package/packages/agentsam-repository/src/workspace-state.js +176 -0
  174. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +152 -0
  175. package/packages/connectors/cloudflare/src/index.js +297 -15
  176. package/packages/connectors/cloudflare/src/owner.js +43 -40
  177. package/packages/connectors/cloudflare/src/routes.js +167 -26
  178. package/packages/connectors/cloudflare/tests/connector.test.mjs +112 -2
  179. package/packages/heuristic-theme/README.md +11 -0
  180. package/packages/heuristic-theme/package.json +25 -0
  181. package/packages/heuristic-theme/src/index.js +2 -0
  182. package/packages/heuristic-theme/src/registry.js +36 -0
  183. package/packages/heuristic-theme/src/theme.js +41 -0
  184. package/packages/heuristic-theme/test/theme.test.mjs +26 -0
  185. package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +64 -0
  186. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +96 -0
  187. package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +47 -0
  188. package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +74 -0
  189. package/packages/identity/.agentsam/features/oauth-login-portal/ui.json +35 -0
  190. package/packages/identity/package.json +3 -2
  191. package/packages/identity/src/adapters/cloudflare-d1/ids.js +4 -0
  192. package/packages/identity/src/adapters/cloudflare-d1/index.js +39 -1
  193. package/packages/identity/src/contracts/provider.js +3 -2
  194. package/packages/identity/src/frontend/auth-portal/pages/login.html +7 -0
  195. package/packages/identity/src/index.js +2 -0
  196. package/packages/identity/src/oauth/credentials.js +13 -0
  197. package/packages/identity/src/oauth/iam-platform.js +5 -5
  198. package/packages/identity/src/providers/cloudflare/index.js +19 -0
  199. package/packages/identity/src/providers/cloudflare/mapper.js +21 -0
  200. package/packages/identity/src/providers/cloudflare/oauth.js +48 -0
  201. package/packages/identity/src/providers/cloudflare/profile.js +28 -0
  202. package/packages/identity/src/providers/index.js +18 -2
  203. package/packages/identity/src/server/identity-service.js +13 -3
  204. package/packages/identity/src/server/worker-router.js +63 -8
  205. package/packages/identity/tests/identity-service.test.mjs +15 -0
  206. package/packages/providers/completeful/README.md +38 -0
  207. package/packages/providers/completeful/package.json +29 -0
  208. package/packages/providers/completeful/src/client.js +162 -0
  209. package/packages/providers/completeful/src/events.js +49 -0
  210. package/packages/providers/completeful/src/index.js +22 -0
  211. package/packages/providers/completeful/src/tools.js +579 -0
  212. package/packages/providers/completeful/src/webhooks.js +55 -0
  213. package/packages/providers/completeful/test/provider.test.mjs +196 -0
  214. package/packages/theme-church-site/README.md +10 -0
  215. package/packages/theme-church-site/package.json +30 -0
  216. package/packages/theme-church-site/src/harvest.json +14 -0
  217. package/packages/theme-church-site/src/index.js +84 -0
  218. package/packages/theme-church-site/test/theme.test.mjs +19 -0
  219. package/packages/theme-companions-site/README.md +10 -0
  220. package/packages/theme-companions-site/package.json +30 -0
  221. package/packages/theme-companions-site/src/harvest.json +12 -0
  222. package/packages/theme-companions-site/src/index.js +82 -0
  223. package/packages/theme-companions-site/test/theme.test.mjs +19 -0
  224. package/packages/theme-floors-site/README.md +10 -0
  225. package/packages/theme-floors-site/package.json +30 -0
  226. package/packages/theme-floors-site/src/harvest.json +14 -0
  227. package/packages/theme-floors-site/src/index.js +82 -0
  228. package/packages/theme-floors-site/test/theme.test.mjs +19 -0
  229. package/packages/theme-fuelnfree-site/README.md +10 -0
  230. package/packages/theme-fuelnfree-site/package.json +30 -0
  231. package/packages/theme-fuelnfree-site/src/harvest.json +13 -0
  232. package/packages/theme-fuelnfree-site/src/index.js +81 -0
  233. package/packages/theme-fuelnfree-site/test/theme.test.mjs +19 -0
  234. package/packages/theme-handyman-site/README.md +10 -0
  235. package/packages/theme-handyman-site/package.json +30 -0
  236. package/packages/theme-handyman-site/src/harvest.json +10 -0
  237. package/packages/theme-handyman-site/src/index.js +83 -0
  238. package/packages/theme-handyman-site/test/theme.test.mjs +19 -0
  239. package/packages/theme-insurance-site/README.md +10 -0
  240. package/packages/theme-insurance-site/package.json +30 -0
  241. package/packages/theme-insurance-site/src/harvest.json +10 -0
  242. package/packages/theme-insurance-site/src/index.js +83 -0
  243. package/packages/theme-insurance-site/test/theme.test.mjs +19 -0
  244. package/packages/theme-shinshu-site/README.md +10 -0
  245. package/packages/theme-shinshu-site/package.json +30 -0
  246. package/packages/theme-shinshu-site/src/harvest.json +12 -0
  247. package/packages/theme-shinshu-site/src/index.js +83 -0
  248. package/packages/theme-shinshu-site/test/theme.test.mjs +19 -0
  249. package/packages/work-graph/README.md +49 -0
  250. package/packages/work-graph/package.json +19 -0
  251. package/packages/work-graph/prototype/README.md +32 -0
  252. package/packages/work-graph/prototype/data/demo-workgraph.js +47 -0
  253. package/packages/work-graph/prototype/renderers/timeline-model.js +21 -0
  254. package/packages/work-graph/prototype/renderers/workgraph-runtime.js +38 -0
  255. package/packages/work-graph/prototype-gnantt.html +655 -0
  256. package/packages/work-graph/src/adapters/business/projects.js +23 -0
  257. package/packages/work-graph/src/adapters/engineering/git.js +22 -0
  258. package/packages/work-graph/src/adapters/engineering/mcp.js +22 -0
  259. package/packages/work-graph/src/index.js +76 -0
  260. package/packages/work-graph/src/renderers/gantt-model.js +11 -0
  261. package/packages/work-graph/src/renderers/timeline.js +16 -0
  262. package/packages/work-graph/test/work-graph.test.mjs +37 -0
  263. package/protocol/README.md +12 -0
  264. package/protocol/capabilities/cloudflare-cpu-audit-input.schema.json +30 -6
  265. package/protocol/capabilities/cloudflare-cpu-profile-input.schema.json +18 -4
  266. package/protocol/capabilities/cloudflare-wrangler-native-input.schema.json +59 -10
  267. package/protocol/capabilities/knowledge-search-input.schema.json +35 -0
  268. package/protocol/capabilities/manifest.json +163 -1
  269. package/protocol/capabilities/repository-audit-input.schema.json +39 -6
  270. package/protocol/capabilities/repository-snapshot-input.schema.json +15 -3
  271. package/protocol/capabilities/terminal-exec-input.schema.json +55 -0
  272. package/protocol/commerce/catalog.v1.json +50 -0
  273. package/protocol/errors/error-catalog.json +164 -0
  274. package/protocol/errors/error-envelope.schema.json +544 -0
  275. package/protocol/features/README.md +57 -0
  276. package/protocol/features/agentsam.feature.v1.schema.json +290 -0
  277. package/protocol/features/catalog.json +65 -0
  278. package/protocol/features/examples/provider-resend.feature.json +17 -0
  279. package/protocol/go/agentsam-go-runtime.v1.json +17 -0
  280. package/protocol/knowledge/LIFECYCLE.md +140 -0
  281. package/protocol/knowledge/README.md +4 -0
  282. package/protocol/presets/catalog.json +128 -19
  283. package/protocol/rpc/v1/errors.proto +24 -0
  284. package/protocol/theme-refinery/d1-reconciliation.md +48 -0
  285. package/protocol/theme-refinery/product-metadata.schema.json +27 -0
  286. package/protocol/theme-refinery/receipts/products-registry-batch-20260924.json +318 -0
  287. package/protocol/theme-refinery/receipts/theme-harvest-20260924.json +472 -0
  288. package/protocol/theme-refinery/reconciliation-receipt.schema.json +83 -0
  289. package/services/cad/server.py +249 -2
  290. package/src/agent/capability-adapter.js +15 -5
  291. package/src/agent/index.js +2 -1
  292. package/src/agent/model-turn.js +51 -0
  293. package/src/agent/responses-runner.js +304 -38
  294. package/src/capabilities/index.js +1 -0
  295. package/src/capabilities/terminal-exec.js +78 -0
  296. package/src/cli.js +117 -9
  297. package/src/cloudflare/index.js +6 -0
  298. package/src/cloudflare/runtime-status.js +393 -0
  299. package/src/cloudflare/wrangler.js +17 -1
  300. package/src/commands/app.js +106 -0
  301. package/src/commands/autorag.js +77 -0
  302. package/src/commands/brand.js +293 -0
  303. package/src/commands/cad.js +1 -0
  304. package/src/commands/connections.js +126 -29
  305. package/src/commands/context-economics.js +8 -0
  306. package/src/commands/db.js +7 -0
  307. package/src/commands/env.js +5 -4
  308. package/src/commands/eval.js +209 -14
  309. package/src/commands/go.js +365 -0
  310. package/src/commands/goap.js +176 -0
  311. package/src/commands/identity-init.js +27 -3
  312. package/src/commands/identity-protocol.js +195 -0
  313. package/src/commands/knowledge.js +64 -5
  314. package/src/commands/mcp.js +341 -0
  315. package/src/commands/merkle-persist.js +3 -1
  316. package/src/commands/merkle.js +18 -3
  317. package/src/commands/models.js +109 -23
  318. package/src/commands/plugins.js +175 -0
  319. package/src/commands/preferences.js +28 -8
  320. package/src/commands/product.js +53 -10
  321. package/src/commands/providers.js +118 -37
  322. package/src/commands/resume.js +9 -5
  323. package/src/commands/runtime-status.js +154 -0
  324. package/src/commands/shell.js +466 -55
  325. package/src/commands/status.js +82 -7
  326. package/src/commands/tunnel.js +228 -195
  327. package/src/commands/whoami.js +78 -6
  328. package/src/context/budget.js +6 -0
  329. package/src/context/index.js +2 -1
  330. package/src/context/project-card.js +75 -0
  331. package/src/errors/contract.js +34 -211
  332. package/src/errors/diagnostic.js +95 -51
  333. package/src/errors/index.js +6 -13
  334. package/src/eval/index.js +6 -0
  335. package/src/eval/live.js +439 -0
  336. package/src/features/resolve.js +242 -0
  337. package/src/go/build.js +108 -0
  338. package/src/go/cloudflare.js +207 -0
  339. package/src/go/contract.js +139 -0
  340. package/src/go/discover.js +96 -0
  341. package/src/go/index.js +13 -0
  342. package/src/go/receipts.js +77 -0
  343. package/src/go/registry.js +223 -0
  344. package/src/go/verify.js +31 -0
  345. package/src/index.js +100 -1
  346. package/src/knowledge/config.js +13 -5
  347. package/src/knowledge/engine.js +23 -8
  348. package/src/knowledge/index.js +1 -0
  349. package/src/knowledge/lane-registry.js +46 -0
  350. package/src/knowledge/providers/gemini.js +48 -8
  351. package/src/knowledge/service/client.js +13 -1
  352. package/src/knowledge/service/grpc-codec.js +156 -53
  353. package/src/knowledge/service/job-engine.js +133 -11
  354. package/src/knowledge/service/job-worker.js +34 -5
  355. package/src/knowledge/service/server.js +10 -1
  356. package/src/knowledge/store-discovery.js +77 -0
  357. package/src/lib/account-session.js +8 -2
  358. package/src/lib/agent-instructions.js +3 -0
  359. package/src/lib/auth.js +7 -3
  360. package/src/lib/cad/blender.js +42 -3
  361. package/src/lib/cad/d1-project-store.js +43 -0
  362. package/src/lib/cad/discovery.js +616 -0
  363. package/src/lib/cad/docker-executor.js +352 -0
  364. package/src/lib/cad/freecad.js +253 -0
  365. package/src/lib/cad/index.js +40 -0
  366. package/src/lib/cad/openscad.js +198 -0
  367. package/src/lib/cad/project-cli.d.ts +2 -0
  368. package/src/lib/cad/project-cli.js +21 -0
  369. package/src/lib/cad/project-contract.d.ts +3 -0
  370. package/src/lib/cad/project-contract.js +1 -0
  371. package/src/lib/cad/project-recipe.js +30 -0
  372. package/src/lib/cad/project-runtime.d.ts +2 -0
  373. package/src/lib/cad/project-runtime.js +53 -0
  374. package/src/lib/cad/project-store.js +25 -0
  375. package/src/lib/cad/project-workflows.js +31 -0
  376. package/src/lib/cad-docker.js +21 -2
  377. package/src/lib/cli-preferences.js +17 -2
  378. package/src/lib/core-client.js +37 -18
  379. package/src/lib/deploy/local-studio.js +6 -5
  380. package/src/lib/dockerize.js +3 -0
  381. package/src/lib/execution-approvals.js +1 -0
  382. package/src/lib/identity-scaffold.js +4 -1
  383. package/src/lib/knowledge-docker.js +9 -1
  384. package/src/lib/local-sessions.js +124 -34
  385. package/src/lib/local-status.js +35 -14
  386. package/src/lib/project-config.js +9 -0
  387. package/src/lib/provider-credentials.js +73 -11
  388. package/src/lib/scaffold/resolve-cloudflare-account.js +37 -0
  389. package/src/lib/scaffold/wizards/cms.js +2 -8
  390. package/src/lib/scaffold/wizards/worker-api.js +2 -8
  391. package/src/lib/slash-commands.js +9 -2
  392. package/src/local/migrations.js +109 -1
  393. package/src/local/runtime-store.js +31 -5
  394. package/src/local/sqlite.js +36 -1
  395. package/src/mcp/authority.js +348 -0
  396. package/src/mcp/client-adapters.js +431 -0
  397. package/src/mcp/client.js +172 -0
  398. package/src/mcp/index.js +47 -0
  399. package/src/mcp/telemetry.js +103 -0
  400. package/src/models/catalog.js +329 -51
  401. package/src/models/discovery.js +24 -4
  402. package/src/models/index.js +2 -0
  403. package/src/models/inventory-core.js +182 -0
  404. package/src/models/policy.js +20 -0
  405. package/src/plugins/cloudflare.js +103 -0
  406. package/src/plugins/completeful.js +69 -0
  407. package/src/plugins/contracts.js +86 -0
  408. package/src/plugins/index.js +11 -0
  409. package/src/plugins/registry.js +207 -0
  410. package/src/plugins/resource-scope.js +45 -0
  411. package/src/plugins/runtime.js +118 -0
  412. package/src/plugins/vectorize.js +31 -0
  413. package/src/progression/engine.js +171 -0
  414. package/src/progression/index.js +1 -0
  415. package/src/providers/cloudflare-chat.js +1 -1
  416. package/src/providers/gemini-generate-content.js +2 -1
  417. package/src/providers/openai-responses.js +45 -16
  418. package/src/providers/tool-schema.js +85 -0
  419. package/src/repository/index.js +29 -0
  420. package/src/rpc/generated/errors_pb.js +961 -1
  421. package/src/security/local-vault.js +415 -0
  422. package/src/security/process.js +20 -4
  423. package/src/status/actions.js +192 -0
  424. package/src/tools/hydrate.js +5 -1
  425. package/src/tools/index.js +7 -0
  426. package/src/tools/redact.js +64 -0
  427. package/src/tools/registry.js +83 -0
  428. package/src/tools/runtime.js +257 -0
  429. package/src/tools/search.js +21 -8
  430. package/src/ui/ansi.js +117 -3
  431. package/src/ui/cli/activity.js +76 -7
  432. package/src/ui/cli/footer.js +110 -9
  433. package/src/ui/cli/help.js +11 -4
  434. package/src/ui/wireframes.js +166 -0
  435. package/test/account-session.test.mjs +28 -0
  436. package/test/apps-scaffold-contract.test.mjs +16 -1
  437. package/test/capabilities.test.mjs +1 -1
  438. package/test/cli/eval-live.test.mjs +219 -0
  439. package/test/cli/go.test.mjs +71 -0
  440. package/test/cli/local-vault-and-provider-setup.test.mjs +268 -0
  441. package/test/cli/mcp-client.test.mjs +245 -0
  442. package/test/cli/runtime-ui.test.mjs +69 -2
  443. package/test/cli/status-actions.test.mjs +88 -0
  444. package/test/cli/wireframes-go-registry.test.mjs +54 -0
  445. package/test/cloudflare-connector.test.mjs +3 -6
  446. package/test/cloudflare-runtime.test.mjs +8 -1
  447. package/test/context.test.mjs +15 -0
  448. package/test/error-diagnostics.test.mjs +9 -0
  449. package/test/fixtures/cad/courtyard-house.json +208 -0
  450. package/test/go/cloudflare-probe.test.mjs +53 -0
  451. package/test/integration/app-command.test.mjs +55 -0
  452. package/test/integration/cad-discovery.test.mjs +158 -0
  453. package/test/integration/cad-docker-executor.test.mjs +249 -0
  454. package/test/integration/cad-execution.test.mjs +184 -0
  455. package/test/integration/cad-project-app.test.mjs +31 -0
  456. package/test/integration/cad-project-d1.test.mjs +25 -0
  457. package/test/integration/cad-project-native.test.mjs +24 -0
  458. package/test/integration/cad-project-workflow.test.mjs +9 -0
  459. package/test/integration/cad-project.test.mjs +82 -0
  460. package/test/integration/cli-help.test.mjs +4 -0
  461. package/test/integration/cms-site-tenancy-contract.test.mjs +256 -0
  462. package/test/integration/core-client.integration.test.mjs +55 -0
  463. package/test/integration/error-runtime-rpc.test.mjs +71 -0
  464. package/test/integration/features-resolve.test.mjs +128 -0
  465. package/test/integration/install-script.test.mjs +107 -0
  466. package/test/integration/inventory-core.test.mjs +53 -0
  467. package/test/integration/plugins-cloudflare.integration.test.mjs +28 -0
  468. package/test/integration/provider-env-cli.test.mjs +1 -1
  469. package/test/integration/runtime-migrations.test.mjs +6 -1
  470. package/test/integration/runtime-status.integration.test.mjs +211 -0
  471. package/test/integration/scaffold-cloudflare.test.mjs +46 -0
  472. package/test/integration/storage-architecture.test.mjs +154 -0
  473. package/test/integration/store-discovery.test.mjs +44 -0
  474. package/test/integration/terminal-exec.integration.test.mjs +86 -0
  475. package/test/integration/tool-runtime.test.mjs +124 -0
  476. package/test/integration/tool-schema.test.mjs +59 -0
  477. package/test/knowledge-service.test.mjs +4 -0
  478. package/test/local-sessions.test.mjs +11 -2
  479. package/test/local-studio-deploy.test.mjs +1 -1
  480. package/test/model-catalog.test.mjs +28 -1
  481. package/test/models.test.mjs +159 -5
  482. package/test/openai-responses.test.mjs +60 -0
  483. package/test/provider-credentials.test.mjs +15 -5
  484. package/test/responses-runner.test.mjs +321 -6
  485. package/test/shell.test.mjs +149 -4
  486. package/test/smoke.mjs +2 -2
  487. package/test/tools-search.test.mjs +33 -0
  488. package/test/unit/website-assets-bindings.test.mjs +60 -0
  489. package/test/whoami-resume.test.mjs +82 -3
  490. package/examples/gorilla-shell/README.md +0 -15
  491. package/src/lib/gorilla-template.js +0 -54
  492. package/templates/gorilla-shell/App.tsx +0 -639
  493. package/templates/gorilla-shell/README.md +0 -34
  494. package/templates/gorilla-shell/index.html +0 -15
  495. package/templates/gorilla-shell/main.jsx +0 -9
  496. package/templates/gorilla-shell/package.json +0 -19
  497. 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',
@@ -141,10 +149,6 @@ for _agentsam_profile in "$@"; do
141
149
  set -a
142
150
  . "$_agentsam_file"
143
151
  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
152
  done
149
153
  unset _agentsam_file _agentsam_profile
150
154
  `;
@@ -157,8 +161,8 @@ function profileSource(provider, credential = '', options = {}) {
157
161
  if (!spec) throw new Error(`unsupported_provider:${normalizeProviderId(provider)}`);
158
162
  const lines = [`# AgentSam ${spec.label} provider profile`];
159
163
  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))}`);
164
+ lines.push('# CLOUDFLARE_ACCOUNT_ID is your Cloudflare account identifier; it is not a secret.');
165
+ lines.push(`export CLOUDFLARE_ACCOUNT_ID=${envLiteral(normalizeCloudflareAccountId(options.accountId))}`);
162
166
  }
163
167
  lines.push(`export ${spec.env}=${envLiteral(credential)}`);
164
168
  return `${lines.join('\n')}\n`;
@@ -190,9 +194,9 @@ export function ensureProviderEnvProfile(provider, options = {}) {
190
194
  const current = firstEnvValue(source, spec.accountEnv || []);
191
195
  if (!current) {
192
196
  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)
197
+ const line = `export CLOUDFLARE_ACCOUNT_ID=${envLiteral(accountId)}`;
198
+ const next = /^(?:export\s+)?CLOUDFLARE_ACCOUNT_ID=.*$/m.test(source)
199
+ ? source.replace(/^(?:export\s+)?CLOUDFLARE_ACCOUNT_ID=.*$/m, line)
196
200
  : `${line}\n${source}`;
197
201
  atomicWrite(filename, next, 0o600);
198
202
  }
@@ -212,8 +216,46 @@ export function setProviderCredential(provider, credential, options = {}) {
212
216
  const spec = providerCredentialSpec(provider);
213
217
  if (!spec) throw new Error(`unsupported_provider:${normalizeProviderId(provider)}`);
214
218
  const value = validateCredentialValue(spec, credential);
219
+ setSecureProviderKey(spec.provider, { value, accountId: options.accountId }, options);
220
+ if (typeof process !== 'undefined' && process.env) {
221
+ process.env[spec.env] = value;
222
+ if (spec.provider === 'cloudflare' && options.accountId) {
223
+ process.env.CLOUDFLARE_ACCOUNT_ID = options.accountId;
224
+ }
225
+ }
226
+ let file = null;
227
+ let loader = null;
228
+ let sourceCommand = null;
229
+ if (options.exportProfile === true || options.writeEnvProfile === true) {
230
+ const filename = path.join(agentEnvDirectory(options), spec.files[0]);
231
+ atomicWrite(filename, profileSource(spec.provider, value, options), 0o600);
232
+ loader = ensureAgentEnvLoader(options);
233
+ file = filename;
234
+ sourceCommand = `source ~/.agentsam/load-agent-env.sh ${spec.provider}`;
235
+ }
236
+ return Object.freeze({
237
+ provider: spec.provider,
238
+ file,
239
+ loader,
240
+ source_command: sourceCommand,
241
+ });
242
+ }
243
+
244
+ /**
245
+ * Exports a configured provider credential from the secure vault to a plaintext .env file.
246
+ * This is an explicit opt-in action for operators who need to source credentials into external shells.
247
+ * The standard AgentSam setup flows (interactive picker, models --setup, providers add)
248
+ * intentionally do NOT invoke this, keeping the credential strictly inside the encrypted vault.
249
+ */
250
+ export function exportProviderEnvProfile(provider, options = {}) {
251
+ const spec = providerCredentialSpec(provider);
252
+ if (!spec) throw new Error(`unsupported_provider:${normalizeProviderId(provider)}`);
253
+ const resolved = resolveProviderCredential(spec.provider, options);
254
+ if (!resolved.configured || !resolved.value) {
255
+ throw new Error(`provider_not_configured:${spec.provider}`);
256
+ }
215
257
  const filename = path.join(agentEnvDirectory(options), spec.files[0]);
216
- atomicWrite(filename, profileSource(spec.provider, value, options), 0o600);
258
+ atomicWrite(filename, profileSource(spec.provider, resolved.value, { ...options, accountId: resolved.account_id }), 0o600);
217
259
  const loader = ensureAgentEnvLoader(options);
218
260
  return Object.freeze({
219
261
  provider: spec.provider,
@@ -226,6 +268,7 @@ export function setProviderCredential(provider, credential, options = {}) {
226
268
  export function removeProviderCredential(provider, options = {}) {
227
269
  const spec = providerCredentialSpec(provider);
228
270
  if (!spec) throw new Error(`unsupported_provider:${normalizeProviderId(provider)}`);
271
+ deleteSecureProviderKey(spec.provider, options);
229
272
  const dir = agentEnvDirectory(options);
230
273
  let removed = false;
231
274
  for (const basename of spec.files) {
@@ -236,6 +279,9 @@ export function removeProviderCredential(provider, options = {}) {
236
279
  fs.rmSync(filename, { force: true });
237
280
  removed = true;
238
281
  }
282
+ if (typeof process !== 'undefined' && process.env) {
283
+ delete process.env[spec.env];
284
+ }
239
285
  return Object.freeze({ provider: spec.provider, removed });
240
286
  }
241
287
 
@@ -259,6 +305,22 @@ export function resolveProviderCredential(provider, options = {}) {
259
305
  });
260
306
  }
261
307
 
308
+ const secure = getSecureProviderKey(spec.provider, options);
309
+ if (secure && clean(secure.value)) {
310
+ const val = clean(secure.value);
311
+ const prefixError = spec.tokenPrefix && !val.startsWith(spec.tokenPrefix) ? `credential_prefix_required:${spec.tokenPrefix}` : null;
312
+ return Object.freeze({
313
+ provider: spec.provider,
314
+ configured: !prefixError,
315
+ source: secure.source || 'local_vault',
316
+ env: spec.env,
317
+ file: null,
318
+ error: prefixError,
319
+ value: prefixError ? '' : val,
320
+ account_id: accountIdFromEnv || secure.accountId || null,
321
+ });
322
+ }
323
+
262
324
  const dir = agentEnvDirectory({ ...options, env });
263
325
  for (const basename of spec.files) {
264
326
  const filename = path.join(dir, basename);
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared Cloudflare account resolution for scaffold wizards.
3
+ * Reuses the same detection the CLI's `agentsam env init cloudflare` flow
4
+ * already relies on — never ask the user to hand-paste an account ID that
5
+ * `wrangler whoami` (or an existing env override) can already answer.
6
+ */
7
+ import { detectCloudflareAccounts } from '../../commands/env.js';
8
+
9
+ export async function resolveCloudflareAccountId({ text, select, isCancel, cancel, note, pc, detectAccounts = detectCloudflareAccounts }) {
10
+ const detected = detectAccounts();
11
+
12
+ if (detected.accounts.length === 1) {
13
+ const acct = detected.accounts[0];
14
+ note(`Detected Cloudflare account: ${pc.cyan(acct.name || acct.id)}`, 'Cloudflare account');
15
+ return acct.id;
16
+ }
17
+
18
+ if (detected.accounts.length > 1) {
19
+ const choice = await select({
20
+ message: 'Which Cloudflare account?',
21
+ options: detected.accounts.map((a) => ({ value: a.id, label: a.name || a.id, hint: a.id })),
22
+ });
23
+ if (isCancel(choice)) { cancel('Cancelled.'); process.exit(0); }
24
+ return choice;
25
+ }
26
+
27
+ note('Could not auto-detect a Cloudflare account (run `agentsam cloudflare` to check login status).', 'Cloudflare account');
28
+ const cfAccountId = await text({
29
+ message: 'Cloudflare account ID? (from dash.cloudflare.com → right sidebar)',
30
+ placeholder: 'abc123...',
31
+ validate(val) {
32
+ if (!val || val.trim().length === 0) return 'Required.';
33
+ },
34
+ });
35
+ if (isCancel(cfAccountId)) { cancel('Cancelled.'); process.exit(0); }
36
+ return cfAccountId.trim();
37
+ }
@@ -22,6 +22,7 @@ import {
22
22
  import pc from 'picocolors';
23
23
  import { writeFileTree } from '../writer.js';
24
24
  import { cmsTemplates } from '../templates/cms/index.js';
25
+ import { resolveCloudflareAccountId } from '../resolve-cloudflare-account.js';
25
26
 
26
27
  export async function runCmsWizard() {
27
28
  note('A Cloudflare Worker + D1 + R2 CMS site with reusable page templates.', 'CMS Site');
@@ -111,14 +112,7 @@ export async function runCmsWizard() {
111
112
  }
112
113
 
113
114
  // ── Step 7: Cloudflare account details ────────────────────────────────────
114
- const cfAccountId = await text({
115
- message: 'Cloudflare account ID? (from dash.cloudflare.com → right sidebar)',
116
- placeholder: 'abc123...',
117
- validate(val) {
118
- if (!val || val.trim().length === 0) return 'Required for wrangler.toml.';
119
- },
120
- });
121
- if (isCancel(cfAccountId)) { cancel('Cancelled.'); process.exit(0); }
115
+ const cfAccountId = await resolveCloudflareAccountId({ text, select, isCancel, cancel, note, pc });
122
116
 
123
117
  // ── Step 8: Confirm before writing ───────────────────────────────────────
124
118
  const summary = [
@@ -16,6 +16,7 @@ import {
16
16
  import pc from 'picocolors';
17
17
  import { writeFileTree } from '../writer.js';
18
18
  import { workerApiTemplates } from '../templates/worker-api/index.js';
19
+ import { resolveCloudflareAccountId } from '../resolve-cloudflare-account.js';
19
20
 
20
21
  export async function runWorkerApiWizard() {
21
22
  note('A typed Cloudflare Worker with route handlers, D1 binding, and CORS ready.', 'Worker API');
@@ -52,14 +53,7 @@ export async function runWorkerApiWizard() {
52
53
  });
53
54
  if (isCancel(dbKind)) { cancel('Cancelled.'); process.exit(0); }
54
55
 
55
- const cfAccountId = await text({
56
- message: 'Cloudflare account ID?',
57
- placeholder: 'abc123...',
58
- validate(val) {
59
- if (!val || val.trim().length === 0) return 'Required.';
60
- },
61
- });
62
- if (isCancel(cfAccountId)) { cancel('Cancelled.'); process.exit(0); }
56
+ const cfAccountId = await resolveCloudflareAccountId({ text, select, isCancel, cancel, note, pc });
63
57
 
64
58
  const confirmed = await confirm({ message: `Write files to ./${projectName.trim()}/?` });
65
59
  if (isCancel(confirmed) || !confirmed) { cancel('Cancelled.'); process.exit(0); }