@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
@@ -0,0 +1,352 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+
5
+ export const DEFAULT_CAD_DOCKER_PORT = 8793;
6
+ export const DEFAULT_CAD_DOCKER_URL = `http://127.0.0.1:${DEFAULT_CAD_DOCKER_PORT}`;
7
+
8
+ function isFile(value) {
9
+ try {
10
+ return Boolean(value) && fs.existsSync(value) && fs.statSync(value).isFile();
11
+ } catch {
12
+ return false;
13
+ }
14
+ }
15
+
16
+ /**
17
+ * Resolves the Docker CAD service URL and authentication token.
18
+ * Searches environment variables and local configuration token files.
19
+ */
20
+ export function resolveDockerServiceConfig(options = {}) {
21
+ const env = options.env || process.env;
22
+ const rawUrl = String(
23
+ options.serviceUrl ||
24
+ env.AGENTSAM_CAD_SERVICE_URL ||
25
+ DEFAULT_CAD_DOCKER_URL
26
+ ).trim();
27
+ const url = rawUrl.replace(/\/+$/, '');
28
+
29
+ // AGENTSAM_CAD_TOKEN is an explicit override; otherwise reuse
30
+ // AGENTSAM_BRIDGE_KEY, the machine-to-machine secret iam-cad-worker's
31
+ // /cad/run lane already trusts, rather than requiring a second credential
32
+ // provisioned just for this route.
33
+ let token = String(
34
+ options.token ||
35
+ env.AGENTSAM_CAD_TOKEN ||
36
+ env.AGENTSAM_BRIDGE_KEY ||
37
+ ''
38
+ ).trim();
39
+
40
+ if (!token) {
41
+ const cwd = options.cwd || process.cwd();
42
+ const candidates = [
43
+ path.join(cwd, '.agentsam/docker/cad/agentsam-cad/service.token'),
44
+ path.join(os.homedir(), '.agentsam/docker/cad/agentsam-cad/service.token'),
45
+ path.join(cwd, '.agentsam/docker/cad/service.token'),
46
+ path.join(os.homedir(), '.agentsam/docker/cad/service.token'),
47
+ ];
48
+
49
+ for (const candidate of candidates) {
50
+ if (isFile(candidate)) {
51
+ try {
52
+ const contents = fs.readFileSync(candidate, 'utf8').trim();
53
+ if (contents) {
54
+ token = contents;
55
+ break;
56
+ }
57
+ } catch {}
58
+ }
59
+ }
60
+ }
61
+
62
+ return {
63
+ url,
64
+ token: token || null,
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Quickly checks if the CAD Docker container service is running and healthy.
70
+ */
71
+ export async function probeDockerServiceHealth(options = {}) {
72
+ const { url, token } = resolveDockerServiceConfig(options);
73
+ const fetchFn = options.fetchImpl || globalThis.fetch;
74
+ const timeoutMs = options.timeoutMs ?? 2500;
75
+
76
+ if (typeof fetchFn !== 'function') {
77
+ return {
78
+ available: false,
79
+ url,
80
+ error: 'fetch is not available in runtime',
81
+ };
82
+ }
83
+
84
+ const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
85
+ const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
86
+
87
+ try {
88
+ const headers = {};
89
+ if (token) {
90
+ headers.Authorization = `Bearer ${token}`;
91
+ }
92
+
93
+ const res = await fetchFn(`${url}/healthz`, {
94
+ method: 'GET',
95
+ headers,
96
+ signal: controller?.signal,
97
+ });
98
+
99
+ if (timer) clearTimeout(timer);
100
+
101
+ if (!res.ok) {
102
+ return {
103
+ available: false,
104
+ url,
105
+ status: `http_${res.status}`,
106
+ error: `HTTP ${res.status}: ${res.statusText}`,
107
+ };
108
+ }
109
+
110
+ const data = await res.json();
111
+ return {
112
+ available: Boolean(data?.ok),
113
+ url,
114
+ service: data?.service || 'agentsam-cad',
115
+ version: data?.version || null,
116
+ tools: data?.tools || {},
117
+ endpoints: data?.endpoints || {},
118
+ };
119
+ } catch (err) {
120
+ if (timer) clearTimeout(timer);
121
+ return {
122
+ available: false,
123
+ url,
124
+ error: err?.message || 'Connection refused',
125
+ };
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Compiles OpenSCAD script using the containerized Docker CAD service.
131
+ */
132
+ export async function executeOpenScadDocker(options = {}) {
133
+ const { url, token } = resolveDockerServiceConfig(options);
134
+ const fetchFn = options.fetchImpl || globalThis.fetch;
135
+ const startTime = Date.now();
136
+ const format = String(options.outputFormat || options.format || 'stl').toLowerCase().replace(/^\./, '');
137
+ const filename = options.filename || `model.${format}`;
138
+ const timeoutMs = options.timeoutMs || 30_000;
139
+
140
+ const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
141
+ const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
142
+
143
+ try {
144
+ const headers = { 'Content-Type': 'application/json' };
145
+ if (token) headers.Authorization = `Bearer ${token}`;
146
+
147
+ const res = await fetchFn(`${url}/v1/openscad/compile`, {
148
+ method: 'POST',
149
+ headers,
150
+ body: JSON.stringify({
151
+ source: options.source,
152
+ format,
153
+ parameters: options.parameters || {},
154
+ filename,
155
+ timeout_seconds: Math.ceil(timeoutMs / 1000),
156
+ }),
157
+ signal: controller?.signal,
158
+ });
159
+
160
+ if (timer) clearTimeout(timer);
161
+
162
+ const body = await res.json();
163
+ if (!res.ok || !body?.ok) {
164
+ throw new Error(body?.error || `Docker OpenSCAD compilation failed with HTTP ${res.status}`);
165
+ }
166
+
167
+ const durationMs = Date.now() - startTime;
168
+ const base64Data = body.artifact_base64 || '';
169
+ const buffer = Buffer.from(base64Data, 'base64');
170
+ const isText = format === 'stl' || format === 'dxf' || format === 'svg' || format === 'scad' || format === 'csg';
171
+ const artifactContent = isText ? buffer.toString('utf8') : base64Data;
172
+
173
+ const mimeType =
174
+ format === 'stl'
175
+ ? 'model/stl'
176
+ : format === 'dxf'
177
+ ? 'image/vnd.dxf'
178
+ : format === 'svg'
179
+ ? 'image/svg+xml'
180
+ : format === '3mf'
181
+ ? 'model/3mf'
182
+ : 'text/plain';
183
+
184
+ return {
185
+ success: true,
186
+ engine: 'openscad-docker',
187
+ artifactContent,
188
+ artifactBase64: base64Data,
189
+ mimeType,
190
+ filename: body.filename || filename,
191
+ outputFormat: format,
192
+ sizeBytes: body.size_bytes || buffer.length,
193
+ sha256: body.sha256 || null,
194
+ durationMs,
195
+ executionTimeMs: durationMs,
196
+ logs: [
197
+ `[KERNEL] AgentSam CAD Docker Service (${url})`,
198
+ `[CONTAINER] Executed in isolated read-only debian container`,
199
+ ...(body.logs ? String(body.logs).split(/\r?\n/).filter(Boolean) : []),
200
+ ],
201
+ };
202
+ } catch (err) {
203
+ if (timer) clearTimeout(timer);
204
+ throw err;
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Builds precision solid geometry using FreeCAD OpenCASCADE kernel inside Docker.
210
+ */
211
+ export async function executeFreeCadDocker(options = {}) {
212
+ const { url, token } = resolveDockerServiceConfig(options);
213
+ const fetchFn = options.fetchImpl || globalThis.fetch;
214
+ const startTime = Date.now();
215
+ const format = String(options.format || 'step').toLowerCase().replace(/^\./, '');
216
+ const filename = options.filename || `model.${format}`;
217
+ const timeoutMs = options.timeoutMs || 35_000;
218
+
219
+ const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
220
+ const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
221
+
222
+ try {
223
+ const headers = { 'Content-Type': 'application/json' };
224
+ if (token) headers.Authorization = `Bearer ${token}`;
225
+
226
+ const res = await fetchFn(`${url}/v1/freecad/execute`, {
227
+ method: 'POST',
228
+ headers,
229
+ body: JSON.stringify({
230
+ operations: options.operations || options.recipe?.operations || [],
231
+ recipe: options.recipe,
232
+ format,
233
+ filename,
234
+ timeout_seconds: Math.ceil(timeoutMs / 1000),
235
+ }),
236
+ signal: controller?.signal,
237
+ });
238
+
239
+ if (timer) clearTimeout(timer);
240
+
241
+ const body = await res.json();
242
+ if (!res.ok || !body?.ok) {
243
+ throw new Error(body?.error || `Docker FreeCAD execution failed with HTTP ${res.status}`);
244
+ }
245
+
246
+ const durationMs = Date.now() - startTime;
247
+ const base64Data = body.artifact_base64 || '';
248
+ const buffer = Buffer.from(base64Data, 'base64');
249
+
250
+ return {
251
+ ok: true,
252
+ success: true,
253
+ capability: 'freecad.build',
254
+ engine: 'freecad-docker',
255
+ format: body.format || format,
256
+ filename: body.filename || filename,
257
+ sizeBytes: body.size_bytes || buffer.length,
258
+ sha256: body.sha256 || null,
259
+ artifactBase64: base64Data,
260
+ artifactText: format === 'step' || format === 'stp' || format === 'brep' ? buffer.toString('utf8') : undefined,
261
+ metrics: body.metrics || {},
262
+ durationMs,
263
+ logs: [
264
+ `[KERNEL] AgentSam CAD Docker Service (${url})`,
265
+ `[CONTAINER] FreeCAD OpenCASCADE kernel execution`,
266
+ ...(body.logs ? String(body.logs).split(/\r?\n/).filter(Boolean) : []),
267
+ ],
268
+ };
269
+ } catch (err) {
270
+ if (timer) clearTimeout(timer);
271
+ throw err;
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Builds or renders 3D scenes using Blender inside Docker.
277
+ */
278
+ export async function executeBlenderDocker(options = {}) {
279
+ const { url, token } = resolveDockerServiceConfig(options);
280
+ const fetchFn = options.fetchImpl || globalThis.fetch;
281
+ const startTime = Date.now();
282
+ const format = String(options.format || 'glb').toLowerCase().replace(/^\./, '');
283
+ const operation = options.operation || 'build';
284
+ const filename = options.filename || `model.${format}`;
285
+ const timeoutMs = options.timeoutMs || 45_000;
286
+
287
+ // Full operation-specific request (recipe for build; scene/camera/width/height
288
+ // for render_preview; format/objects/collection/apply_modifiers for export;
289
+ // {} for inspect) — falls back to the legacy recipe/operations-only shape
290
+ // for callers that haven't been updated.
291
+ const requestPayload = options.request
292
+ || (options.recipe ? { recipe: options.recipe }
293
+ : (options.operations ? { recipe: { schema_version: 1, operations: options.operations } } : {}));
294
+
295
+ const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
296
+ const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
297
+
298
+ try {
299
+ const headers = { 'Content-Type': 'application/json' };
300
+ if (token) headers.Authorization = `Bearer ${token}`;
301
+
302
+ const res = await fetchFn(`${url}/v1/blender/execute`, {
303
+ method: 'POST',
304
+ headers,
305
+ body: JSON.stringify({
306
+ operation,
307
+ request: { format, ...requestPayload },
308
+ // Base64 bytes of the source .blend when this operation edits an
309
+ // existing file (inspect/render_preview/export/edit-build); the
310
+ // container has no access to the caller's local filesystem.
311
+ input_base64: options.inputBase64 || null,
312
+ filename,
313
+ timeout_seconds: Math.ceil(timeoutMs / 1000),
314
+ }),
315
+ signal: controller?.signal,
316
+ });
317
+
318
+ if (timer) clearTimeout(timer);
319
+
320
+ const body = await res.json();
321
+ if (!res.ok || !body?.ok) {
322
+ throw new Error(body?.error || `Docker Blender execution failed with HTTP ${res.status}`);
323
+ }
324
+
325
+ const durationMs = Date.now() - startTime;
326
+ const base64Data = body.artifact_base64 || '';
327
+ const buffer = Buffer.from(base64Data, 'base64');
328
+
329
+ return {
330
+ ok: true,
331
+ success: true,
332
+ capability: `blender.${operation}`,
333
+ engine: 'blender-docker',
334
+ operation,
335
+ format: body.format || format,
336
+ filename: body.filename || filename,
337
+ sizeBytes: body.size_bytes || buffer.length,
338
+ sha256: body.sha256 || null,
339
+ artifactBase64: base64Data,
340
+ result: body.result || {},
341
+ durationMs,
342
+ logs: [
343
+ `[KERNEL] AgentSam CAD Docker Service (${url})`,
344
+ `[CONTAINER] Blender headless engine execution`,
345
+ ...(body.logs ? String(body.logs).split(/\r?\n/).filter(Boolean) : []),
346
+ ],
347
+ };
348
+ } catch (err) {
349
+ if (timer) clearTimeout(timer);
350
+ throw err;
351
+ }
352
+ }
@@ -0,0 +1,253 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { runProcess } from '../../security/process.js';
6
+ import { discoverFreeCad, freeCadStatus } from './discovery.js';
7
+ import { probeDockerServiceHealth, executeFreeCadDocker } from './docker-executor.js';
8
+
9
+ const sdkRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..');
10
+ export const FREECAD_ADAPTER_PATH = path.join(sdkRoot, 'services/cad/freecad/adapter.py');
11
+ export const FREECAD_RESULT_PREFIX = 'AGENTSAM_RESULT=';
12
+ export const FREECAD_EXPORT_FORMATS = Object.freeze(['step', 'stp', 'iges', 'brep', 'stl']);
13
+
14
+ function isFile(value) {
15
+ try {
16
+ return Boolean(value) && fs.existsSync(value) && fs.statSync(value).isFile();
17
+ } catch {
18
+ return false;
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Discovers the Python executable with FreeCAD / OpenCASCADE bindings.
24
+ */
25
+ export function discoverFreeCadPython({
26
+ freecadBin,
27
+ env = process.env,
28
+ platform = process.platform,
29
+ } = {}) {
30
+ // 1. Direct explicit environment override
31
+ if (env.AGENTSAM_FREECAD_PYTHON && isFile(env.AGENTSAM_FREECAD_PYTHON)) {
32
+ return {
33
+ pythonBin: env.AGENTSAM_FREECAD_PYTHON,
34
+ libDir: env.AGENTSAM_FREECAD_LIB || null,
35
+ };
36
+ }
37
+
38
+ // 2. Discover FreeCAD base installation
39
+ const { binary } = discoverFreeCad({ freecadBin, env, platform });
40
+ if (binary) {
41
+ if (platform === 'darwin') {
42
+ const appRoot = binary.includes('.app') ? binary.split('.app')[0] + '.app' : null;
43
+ if (appRoot) {
44
+ const bundledPython = path.join(appRoot, 'Contents/Resources/bin/python');
45
+ const bundledLib = path.join(appRoot, 'Contents/Resources/lib');
46
+ if (isFile(bundledPython)) {
47
+ return { pythonBin: bundledPython, libDir: bundledLib };
48
+ }
49
+ }
50
+ }
51
+ }
52
+
53
+ // 3. Fallback candidates on system
54
+ const candidates = [
55
+ ...(platform === 'darwin'
56
+ ? ['/Applications/FreeCAD.app/Contents/Resources/bin/python']
57
+ : []),
58
+ ...(platform === 'linux'
59
+ ? ['/usr/lib/freecad/bin/python', '/usr/bin/python3']
60
+ : []),
61
+ ...(platform === 'win32'
62
+ ? [path.join(env.ProgramFiles || 'C:\\Program Files', 'FreeCAD', 'bin', 'python.exe')]
63
+ : []),
64
+ ];
65
+
66
+ for (const c of candidates) {
67
+ if (isFile(c)) {
68
+ return { pythonBin: c, libDir: null };
69
+ }
70
+ }
71
+
72
+ return { pythonBin: null, libDir: null };
73
+ }
74
+
75
+ export function parseFreeCadResult(stdout) {
76
+ const line = String(stdout || '').split(/\r?\n/).reverse().find(value => value.startsWith(FREECAD_RESULT_PREFIX));
77
+ if (!line) throw new Error('FreeCAD did not return an AgentSam result envelope');
78
+ let value;
79
+ try {
80
+ value = JSON.parse(line.slice(FREECAD_RESULT_PREFIX.length));
81
+ } catch {
82
+ throw new Error('FreeCAD returned malformed AgentSam JSON');
83
+ }
84
+ if (!value || typeof value !== 'object') throw new Error('FreeCAD returned an invalid AgentSam result envelope');
85
+ return value;
86
+ }
87
+
88
+ /**
89
+ * Builds a precision boundary solid geometry with OpenCASCADE kernel and exports to STEP/IGES/BREP/STL.
90
+ */
91
+ export async function freeCadBuild({
92
+ recipe,
93
+ output,
94
+ format = 'step',
95
+ freecadBin,
96
+ timeoutSeconds = 60,
97
+ cwd = process.cwd(),
98
+ runProcessImpl = runProcess,
99
+ } = {}) {
100
+ const { pythonBin, libDir } = discoverFreeCadPython({ freecadBin });
101
+ if (!pythonBin || !fs.existsSync(FREECAD_ADAPTER_PATH)) {
102
+ try {
103
+ const dockerHealth = await probeDockerServiceHealth();
104
+ if (dockerHealth.available && dockerHealth.tools?.freecad?.installed) {
105
+ const dockerRes = await executeFreeCadDocker({
106
+ recipe,
107
+ operations: recipe?.operations || [],
108
+ format,
109
+ filename: output ? path.basename(output) : undefined,
110
+ timeoutMs: timeoutSeconds * 1000,
111
+ });
112
+ if (output) {
113
+ const outputPath = path.resolve(cwd, output);
114
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
115
+ fs.writeFileSync(outputPath, Buffer.from(dockerRes.artifactBase64, 'base64'));
116
+ }
117
+ return {
118
+ ...dockerRes,
119
+ engine: 'freecad-docker',
120
+ };
121
+ }
122
+ } catch {}
123
+ throw new Error('FreeCAD Python environment is not available; install FreeCAD, set AGENTSAM_FREECAD_PYTHON, or launch AgentSam CAD Docker service');
124
+ }
125
+
126
+ const outputPath = path.resolve(cwd, output);
127
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
128
+
129
+ const requestDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-freecad-'));
130
+ const requestPath = path.join(requestDir, 'request.json');
131
+
132
+ const request = {
133
+ schema_version: 1,
134
+ output: outputPath,
135
+ format,
136
+ operations: recipe?.operations || [],
137
+ };
138
+
139
+ fs.writeFileSync(requestPath, JSON.stringify(request, null, 2), { mode: 0o600 });
140
+
141
+ const env = { ...process.env };
142
+ if (libDir) {
143
+ env.PYTHONPATH = [libDir, env.PYTHONPATH].filter(Boolean).join(path.delimiter);
144
+ }
145
+
146
+ const started = Date.now();
147
+ try {
148
+ const proc = await runProcessImpl(
149
+ pythonBin,
150
+ [FREECAD_ADAPTER_PATH, '--operation', 'build', '--request', requestPath],
151
+ {
152
+ cwd,
153
+ env,
154
+ timeoutMs: timeoutSeconds * 1000,
155
+ maxBytes: 8 * 1024 * 1024,
156
+ }
157
+ );
158
+
159
+ const result = parseFreeCadResult(proc.stdout);
160
+ if (!result.ok) {
161
+ throw new Error(result.error || `FreeCAD build failed with exit code ${proc.code}`);
162
+ }
163
+
164
+ if (!fs.existsSync(outputPath)) {
165
+ throw new Error(`FreeCAD build did not create output file: ${outputPath}`);
166
+ }
167
+
168
+ const durationMs = Date.now() - started;
169
+ return {
170
+ schema_version: 1,
171
+ capability: 'freecad.build',
172
+ ok: true,
173
+ execution_lane: 'native',
174
+ format,
175
+ output: outputPath,
176
+ sizeBytes: fs.statSync(outputPath).size,
177
+ metrics: result.metrics,
178
+ durationMs,
179
+ logs: String(proc.stderr || proc.stdout || '').slice(-8000),
180
+ };
181
+ } finally {
182
+ fs.rmSync(requestDir, { recursive: true, force: true });
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Inspects a STEP / IGES / BREP solid model and returns exact geometric volume and bounding box.
188
+ */
189
+ export async function freeCadInspect({
190
+ input,
191
+ freecadBin,
192
+ timeoutSeconds = 30,
193
+ cwd = process.cwd(),
194
+ runProcessImpl = runProcess,
195
+ } = {}) {
196
+ const { pythonBin, libDir } = discoverFreeCadPython({ freecadBin });
197
+ if (!pythonBin) {
198
+ throw new Error('FreeCAD Python environment is not available');
199
+ }
200
+
201
+ const inputPath = path.resolve(cwd, input);
202
+ if (!fs.existsSync(inputPath)) {
203
+ throw new Error(`FreeCAD input file not found: ${inputPath}`);
204
+ }
205
+
206
+ const requestDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-freecad-inspect-'));
207
+ const requestPath = path.join(requestDir, 'request.json');
208
+
209
+ const request = {
210
+ schema_version: 1,
211
+ input: inputPath,
212
+ };
213
+
214
+ fs.writeFileSync(requestPath, JSON.stringify(request, null, 2), { mode: 0o600 });
215
+
216
+ const env = { ...process.env };
217
+ if (libDir) {
218
+ env.PYTHONPATH = [libDir, env.PYTHONPATH].filter(Boolean).join(path.delimiter);
219
+ }
220
+
221
+ const started = Date.now();
222
+ try {
223
+ const proc = await runProcessImpl(
224
+ pythonBin,
225
+ [FREECAD_ADAPTER_PATH, '--operation', 'inspect', '--request', requestPath],
226
+ {
227
+ cwd,
228
+ env,
229
+ timeoutMs: timeoutSeconds * 1000,
230
+ maxBytes: 8 * 1024 * 1024,
231
+ }
232
+ );
233
+
234
+ const result = parseFreeCadResult(proc.stdout);
235
+ if (!result.ok) {
236
+ throw new Error(result.error || `FreeCAD inspect failed with exit code ${proc.code}`);
237
+ }
238
+
239
+ return {
240
+ schema_version: 1,
241
+ capability: 'freecad.inspect',
242
+ ok: true,
243
+ execution_lane: 'native',
244
+ input: inputPath,
245
+ metrics: result.metrics,
246
+ durationMs: Date.now() - started,
247
+ };
248
+ } finally {
249
+ fs.rmSync(requestDir, { recursive: true, force: true });
250
+ }
251
+ }
252
+
253
+ export { freeCadStatus };
@@ -13,3 +13,43 @@ export {
13
13
  sha256File,
14
14
  validateBlenderRecipe,
15
15
  } from './blender.js';
16
+
17
+ export {
18
+ discoverOpenScad,
19
+ openScadStatus,
20
+ discoverFreeCad,
21
+ freeCadStatus,
22
+ meshyStatus,
23
+ mujocoStatus,
24
+ discoverAllCadTools,
25
+ getCadConfigPath,
26
+ loadCadConfig,
27
+ saveCadConfig,
28
+ getInstallGuidance,
29
+ } from './discovery.js';
30
+
31
+ export {
32
+ openScadCompile,
33
+ validateOpenScadSource,
34
+ FORBIDDEN_OPENSCAD_PATTERNS,
35
+ } from './openscad.js';
36
+
37
+ export {
38
+ FREECAD_ADAPTER_PATH,
39
+ FREECAD_EXPORT_FORMATS,
40
+ discoverFreeCadPython,
41
+ freeCadBuild,
42
+ freeCadInspect,
43
+ } from './freecad.js';
44
+
45
+ export {
46
+ DEFAULT_CAD_DOCKER_PORT,
47
+ DEFAULT_CAD_DOCKER_URL,
48
+ resolveDockerServiceConfig,
49
+ probeDockerServiceHealth,
50
+ executeOpenScadDocker,
51
+ executeFreeCadDocker,
52
+ executeBlenderDocker,
53
+ } from './docker-executor.js';
54
+
55
+