@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
@@ -3,6 +3,7 @@ import { validateConfig, fingerprint, scopeKey, cacheNamespace, gitEvidence } fr
3
3
  import { PARSER, inventory, readSource, parseSource } from './source.js';
4
4
  import { createContextPack } from './context-pack.js';
5
5
  import { normalizeResultPolicy } from '../context/result-policy.js';
6
+ import { buildMerkleTree } from '../../packages/agentsam-repository/src/merkle/index.js';
6
7
 
7
8
  export const embeddingProfileId = profile => fingerprint({ ...profile, input_format: 'agentsam-code-content:1' });
8
9
  export function validateVector(vector, dimensions) {
@@ -14,20 +15,27 @@ function changes(before = [], after = []) {
14
15
  return { added: after.filter(f => !old.has(f.path)).map(f => f.path), changed: after.filter(f => old.has(f.path) && old.get(f.path) !== f.hash).map(f => f.path), removed: before.filter(f => !now.has(f.path)).map(f => f.path) };
15
16
  }
16
17
  /** Planning never persists, calls an embedding provider, or changes active state. */
17
- export async function planIndex({ root, config: input, store, embed = false }) {
18
+ export async function planIndex({ root, config: input, store, embed = false, limits = null }) {
18
19
  const config = validateConfig(input), scope = scopeKey(config), namespace = cacheNamespace(config);
20
+ if (embed && config.embedding.provider === 'none') throw new Error('Embedding is explicitly disabled for this knowledge profile. Configure a provider before --embed.');
21
+ const maxFiles = limits?.maxFiles == null ? Infinity : Number(limits.maxFiles);
22
+ const maxChunks = limits?.maxChunks == null ? Infinity : Number(limits.maxChunks);
23
+ if ((maxFiles !== Infinity && (!Number.isInteger(maxFiles) || maxFiles < 1)) || (maxChunks !== Infinity && (!Number.isInteger(maxChunks) || maxChunks < 1))) throw new Error('Index limits must be positive integers.');
19
24
  const previous = await store?.active(scope), profileId = embed ? embeddingProfileId(config.embedding) : null;
20
25
  const files = [], chunks = [], symbols = [], edges = [], parseWrites = [], skipped = [];
21
26
  const parseProfile = fingerprint([PARSER, config.chunking]);
22
27
  let parsedFiles = 0;
23
- for (const file of inventory(root, config.scope)) {
28
+ for (const file of inventory(root, config.scope).slice(0, maxFiles)) {
24
29
  const source = readSource(root, file);
25
30
  if (!source) { skipped.push(file); continue; }
26
31
  const key = `${namespace}:parse:${fingerprint([source.hash, file.split('.').pop(), parseProfile])}`;
27
32
  let parsed = await store?.cacheGet(key);
28
33
  if (!parsed) { parsed = parseSource(file, source.content, config.chunking.max_chars); parseWrites.push([key, parsed]); parsedFiles++; }
29
34
  files.push({ path: file, hash: source.hash, bytes: source.bytes, parser: parsed.parser });
30
- for (const [ordinal, c] of parsed.chunks.entries()) chunks.push({ ...c, path: file, ordinal, id: fingerprint([file, ordinal, c.content_hash]), embedding_key: embed ? `${namespace}:vector:${profileId}:${c.content_hash}` : null });
35
+ for (const [ordinal, c] of parsed.chunks.entries()) {
36
+ if (chunks.length >= maxChunks) break;
37
+ chunks.push({ ...c, path: file, ordinal, id: fingerprint([file, ordinal, c.content_hash]), embedding_key: embed ? `${namespace}:vector:${profileId}:${c.content_hash}` : null });
38
+ }
31
39
  symbols.push(...parsed.symbols.map(s => ({ ...s, path: file })));
32
40
  edges.push(...parsed.edges.map(e => ({ ...e, path: file })));
33
41
  }
@@ -36,19 +44,25 @@ export async function planIndex({ root, config: input, store, embed = false }) {
36
44
  if (!missing.has(chunk.embedding_key) && !(await store?.cacheGet(chunk.embedding_key))) missing.set(chunk.embedding_key, chunk.content);
37
45
  }
38
46
  const sourceHash = fingerprint(files.map(f => [f.path, f.hash]));
39
- const configHash = fingerprint([config.scope, config.chunking, PARSER, profileId]);
47
+ const configHash = fingerprint([config.scope, config.chunking, PARSER, profileId, Number.isFinite(maxFiles) ? maxFiles : null, Number.isFinite(maxChunks) ? maxChunks : null]);
48
+ let merkle = null;
49
+ try { merkle = await buildMerkleTree(root, { semantic: true }); } catch { merkle = null; }
50
+ const previousMerkle = previous?.receipt?.merkle_root || null;
51
+ const changedMerklePaths = merkle && previousMerkle !== merkle.rootHash ? files.filter(file => !previous?.files?.some(before => before.path === file.path && before.hash === file.hash)).map(file => file.path) : [];
40
52
  const noChange = previous?.source_hash === sourceHash && previous?.config_hash === configHash && !missing.size;
41
53
  return { root, config, previous, files, chunks, symbols, edges, parseWrites, missing,
42
54
  receipt: { scope: config.scope, files: files.length, chunks: chunks.length, symbols: symbols.length, edges: edges.length,
43
55
  parsed_files: parsedFiles, embedding_inputs: missing.size, embedding_characters: [...missing.values()].reduce((n, s) => n + s.length, 0),
44
56
  estimated_tokens: Math.ceil([...missing.values()].reduce((n, s) => n + s.length + 24, 0) / 4), token_estimate_method: 'characters / 4; not billable usage',
45
- profile_id: profileId, skipped, changes: changes(previous?.files, files), no_change: Boolean(noChange), source_hash: sourceHash, config_hash: configHash } };
57
+ profile_id: profileId, skipped, changes: changes(previous?.files, files), no_change: Boolean(noChange), source_hash: sourceHash, config_hash: configHash,
58
+ merkle_root: merkle?.rootHash || null, semantic_metadata_root: merkle?.semantic?.rootHash || null, merkle_changed_paths: changedMerklePaths,
59
+ limits: Number.isFinite(maxFiles) || Number.isFinite(maxChunks) ? { max_files: maxFiles, max_chunks: maxChunks } : null } };
46
60
  }
47
61
 
48
- export async function runIndex({ root, config, store, embedder, embed = false, maxInputs = 100, maxCharacters = 200000 }) {
62
+ export async function runIndex({ root, config, store, embedder, embed = false, maxInputs = 100, maxCharacters = 200000, limits = null }) {
49
63
  if (!store) throw new Error('A writable knowledge store is required.');
50
64
  if (!Number.isInteger(maxInputs) || maxInputs < 0 || !Number.isInteger(maxCharacters) || maxCharacters < 0) throw new Error('Embedding budgets must be nonnegative integers.');
51
- const plan = await planIndex({ root, config, store, embed });
65
+ const plan = await planIndex({ root, config, store, embed, limits });
52
66
  const { receipt } = plan;
53
67
  if (receipt.no_change) return { ...receipt, generation_id: plan.previous.id, published: false };
54
68
  if (receipt.embedding_inputs > maxInputs || receipt.embedding_characters > maxCharacters) throw new Error(`Embedding budget exceeded: ${receipt.embedding_inputs} unique inputs / ${receipt.embedding_characters} characters. Review index plan before raising limits.`);
@@ -64,7 +78,8 @@ export async function runIndex({ root, config, store, embedder, embed = false, m
64
78
  }
65
79
  // A generation describes one coherent source snapshot. Never publish after a mid-run edit.
66
80
  const check = [];
67
- for (const file of inventory(root, plan.config.scope)) { const source = readSource(root, file); if (source) check.push([file, source.hash]); }
81
+ const checkFiles = inventory(root, plan.config.scope).slice(0, limits?.maxFiles == null ? Infinity : limits.maxFiles);
82
+ for (const file of checkFiles) { const source = readSource(root, file); if (source) check.push([file, source.hash]); }
68
83
  if (fingerprint(check) !== receipt.source_hash) throw new Error('Repository changed while indexing; cached work retained, active generation unchanged. Rerun.');
69
84
  const generation = { id: randomUUID(), scope_key: scopeKey(plan.config), created_at: new Date().toISOString(),
70
85
  source_hash: receipt.source_hash, config_hash: receipt.config_hash, config: plan.config, profile_id: receipt.profile_id,
@@ -8,3 +8,4 @@ export { openSqliteStore } from './stores/sqlite.js';
8
8
  export { createPostgresStore, openPostgresStore, postgresSchema } from './stores/postgres.js';
9
9
  export { createGeminiEmbedder } from './providers/gemini.js';
10
10
  export { compareObservations } from './evolution.js';
11
+ export { normalizeRetrievalLane, selectProjectRetrievalLanes, loadProjectRetrievalLanes } from './lane-registry.js';
@@ -0,0 +1,46 @@
1
+ function clean(value) { return value == null ? '' : String(value).trim(); }
2
+ function json(value, fallback = {}) { try { return JSON.parse(String(value || '')); } catch { return fallback; } }
3
+
4
+ export function normalizeRetrievalLane(row = {}) {
5
+ return Object.freeze({
6
+ id: clean(row.id),
7
+ account_id: clean(row.account_id) || null,
8
+ repository_id: clean(row.repository_id) || null,
9
+ database_id: clean(row.database_id) || null,
10
+ backend_kind: clean(row.backend_kind || 'pgvector'),
11
+ provider_key: clean(row.provider_key) || null,
12
+ resource_id: clean(row.resource_id) || null,
13
+ binding_name: clean(row.binding_name) || null,
14
+ index_name: clean(row.index_name) || null,
15
+ // Namespace is provider/project-owned. Never silently force the shared
16
+ // `agentsam` schema onto a new application's retrieval lane.
17
+ schema_name: clean(row.schema_name) || null,
18
+ table_name: clean(row.table_name),
19
+ purpose: clean(row.purpose),
20
+ dimensions: Number(row.dimensions) || null,
21
+ metric: clean(row.metric || 'cosine'),
22
+ embedding_model: clean(row.embedding_model) || null,
23
+ metadata: json(row.metadata_json, {}),
24
+ is_active: Number(row.is_active) === 1,
25
+ });
26
+ }
27
+
28
+ /** Project selection is explicit; no global preferred vector store exists. */
29
+ export function selectProjectRetrievalLanes(rows, { accountId, repositoryId, purpose } = {}) {
30
+ const account = clean(accountId);
31
+ const repository = clean(repositoryId);
32
+ if (!account || !repository) throw new Error('project_retrieval_identity_required');
33
+ return (Array.isArray(rows) ? rows : [])
34
+ .map(normalizeRetrievalLane)
35
+ .filter((lane) => lane.is_active && lane.account_id === account && lane.repository_id === repository && (!purpose || lane.purpose === purpose));
36
+ }
37
+
38
+ export async function loadProjectRetrievalLanes(db, identity = {}) {
39
+ if (!db?.prepare) throw new TypeError('database_required');
40
+ const result = await db.prepare(`
41
+ SELECT * FROM agentsam_pgvector_lane_registry
42
+ WHERE account_id = ? AND repository_id = ? AND is_active = 1
43
+ ORDER BY purpose, id
44
+ `).bind(clean(identity.accountId), clean(identity.repositoryId)).all();
45
+ return selectProjectRetrievalLanes(result?.results || [], identity);
46
+ }
@@ -1,12 +1,20 @@
1
+ import { AgentSamError, classifyGeminiFailure } from '../../errors/index.js';
2
+
1
3
  /** Gemini Embedding 2 adapter; profile is supplied per job, never read globally. */
2
4
  export function createGeminiEmbedder({ apiKey, fetchImpl = globalThis.fetch, sleep = ms => new Promise(r => setTimeout(r, ms)), maxAttempts = 3, timeoutMs = 30000 } = {}) {
3
- if (!apiKey) throw new Error('GEMINI_API_KEY is required only for embedding/search with --semantic.');
4
- if (!Number.isInteger(maxAttempts) || maxAttempts < 1 || maxAttempts > 5) throw new Error('maxAttempts must be 1..5.');
5
+ if (!apiKey) throw new AgentSamError(classifyGeminiFailure({
6
+ credential_state: 'missing',
7
+ message: 'GEMINI_API_KEY is required only for embedding/search with --semantic.',
8
+ }, { domain: 'knowledge', tool: 'gemini', stage: 'embedding' }));
9
+ if (!Number.isInteger(maxAttempts) || maxAttempts < 1 || maxAttempts > 5) throw new AgentSamError(classifyGeminiFailure({
10
+ status: 400,
11
+ message: 'maxAttempts must be 1..5.',
12
+ }, { domain: 'knowledge', tool: 'gemini', stage: 'configuration', request_origin: 'user' }));
5
13
  return {
6
14
  validate(profile) {
7
- if (profile.provider !== 'gemini' || profile.model !== 'gemini-embedding-2') throw new Error('This adapter supports gemini-embedding-2; inject a different adapter for other models.');
8
- if (profile.dimensions < 128 || profile.dimensions > 3072) throw new Error('Gemini Embedding 2 dimensions must be 128..3072.');
9
- if (Object.keys(profile.parameters).some(k => k !== 'task') || !['code retrieval', 'search result', 'question answering'].includes(profile.parameters.task)) throw new Error('Unsupported Gemini embedding parameters.');
15
+ if (profile.provider !== 'gemini' || profile.model !== 'gemini-embedding-2') throw new AgentSamError(classifyGeminiFailure({ status: 400, message: 'This adapter supports gemini-embedding-2; inject a different adapter for other models.' }, { domain: 'knowledge', tool: 'gemini', stage: 'configuration', request_origin: 'user' }));
16
+ if (profile.dimensions < 128 || profile.dimensions > 3072) throw new AgentSamError(classifyGeminiFailure({ status: 400, message: 'Gemini Embedding 2 dimensions must be 128..3072.' }, { domain: 'knowledge', tool: 'gemini', stage: 'configuration', request_origin: 'user' }));
17
+ if (Object.keys(profile.parameters).some(k => k !== 'task') || !['code retrieval', 'search result', 'question answering'].includes(profile.parameters.task)) throw new AgentSamError(classifyGeminiFailure({ status: 400, message: 'Unsupported Gemini embedding parameters.' }, { domain: 'knowledge', tool: 'gemini', stage: 'configuration', request_origin: 'user' }));
10
18
  },
11
19
  async embed(text, profile, { kind = 'document' } = {}) {
12
20
  this.validate(profile);
@@ -19,10 +27,42 @@ export function createGeminiEmbedder({ apiKey, fetchImpl = globalThis.fetch, sle
19
27
  method: 'POST', headers: { 'Content-Type': 'application/json', 'x-goog-api-key': apiKey }, signal: AbortSignal.timeout(timeoutMs),
20
28
  body: JSON.stringify({ model: `models/${profile.model}`, content: { parts: [{ text: input }] }, outputDimensionality: profile.dimensions }),
21
29
  });
22
- } catch { if (attempt + 1 === maxAttempts) throw new Error('Gemini embedding request failed or timed out.'); }
30
+ } catch (cause) {
31
+ if (attempt + 1 === maxAttempts) {
32
+ throw new AgentSamError(classifyGeminiFailure({
33
+ status: 504,
34
+ status_name: 'UNAVAILABLE',
35
+ message: 'Gemini embedding request failed or timed out.',
36
+ exception_type: cause?.name,
37
+ stack: cause?.stack,
38
+ }, { domain: 'knowledge', tool: 'gemini', stage: 'embedding', reason: 'transport_timeout' }), { cause });
39
+ }
40
+ }
23
41
  if (response?.ok) return (await response.json()).embedding?.values;
24
- if (response && ![408, 429, 500, 502, 503, 504].includes(response.status)) throw new Error(`Gemini embedding failed (HTTP ${response.status}).`);
25
- if (attempt + 1 === maxAttempts) throw new Error(`Gemini embedding retry limit reached${response ? ` (HTTP ${response.status})` : ''}.`);
42
+ let providerBody = null;
43
+ if (response) {
44
+ try { providerBody = await response.clone().json(); } catch { providerBody = null; }
45
+ }
46
+ if (response && ![408, 429, 500, 502, 503, 504].includes(response.status)) {
47
+ throw new AgentSamError(classifyGeminiFailure({
48
+ status: response.status,
49
+ status_name: providerBody?.error?.status,
50
+ code: providerBody?.error?.code,
51
+ message: providerBody?.error?.message || `Gemini embedding failed (HTTP ${response.status}).`,
52
+ headers: response.headers,
53
+ body: providerBody,
54
+ }, { domain: 'knowledge', tool: 'gemini', stage: 'embedding', request_origin: 'agentsam' }));
55
+ }
56
+ if (attempt + 1 === maxAttempts) {
57
+ throw new AgentSamError(classifyGeminiFailure({
58
+ status: response?.status || 503,
59
+ status_name: providerBody?.error?.status,
60
+ code: providerBody?.error?.code,
61
+ message: providerBody?.error?.message || `Gemini embedding retry limit reached${response ? ` (HTTP ${response.status})` : ''}.`,
62
+ headers: response?.headers,
63
+ body: providerBody,
64
+ }, { domain: 'knowledge', tool: 'gemini', stage: 'embedding' }));
65
+ }
26
66
  await response?.body?.cancel();
27
67
  await sleep(Math.min(10000, 500 * 2 ** attempt + Math.floor(Math.random() * 250)));
28
68
  }
@@ -1,3 +1,5 @@
1
+ import { AgentSamError, fromHttpError } from '../../errors/index.js';
2
+
1
3
  /** Fetch-only client: safe to import in Cloudflare Workers; no Node runtime dependencies. */
2
4
  export function createKnowledgeServiceClient({ baseUrl, token, fetchImpl = globalThis.fetch, timeoutMs = 15000 } = {}) {
3
5
  const url = new URL(baseUrl);
@@ -10,7 +12,17 @@ export function createKnowledgeServiceClient({ baseUrl, token, fetchImpl = globa
10
12
  const response = await fetchImpl(new URL(route, url), { method: body ? 'POST' : 'GET', headers,
11
13
  body: body ? JSON.stringify(body) : undefined, signal: AbortSignal.timeout(timeoutMs), redirect: 'error' });
12
14
  const value = await response.json();
13
- if (!response.ok) throw Object.assign(new Error(value.error || `Knowledge service returned ${response.status}`), { status: response.status });
15
+ if (!response.ok) {
16
+ const envelope = fromHttpError({
17
+ status: response.status,
18
+ body: value,
19
+ headers: response.headers,
20
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'http_server' },
21
+ domain: 'knowledge',
22
+ stage: 'request',
23
+ });
24
+ throw new AgentSamError(envelope);
25
+ }
14
26
  return value;
15
27
  };
16
28
  return { repositories: () => call('/v1/repositories'), submit: (body, idempotencyKey) => call('/v1/jobs', { body, idempotencyKey }),
@@ -8,6 +8,11 @@ import {
8
8
  defaultHttpStatusForCode,
9
9
  grpcStatusForCode,
10
10
  } from '../../errors/contract.js';
11
+ import {
12
+ AgentSamError,
13
+ isErrorEnvelope,
14
+ normalizeError,
15
+ } from '../../errors/index.js';
11
16
 
12
17
  const require = createRequire(import.meta.url);
13
18
  const knowledgePb = require('../../rpc/generated/knowledge_pb.js');
@@ -47,6 +52,84 @@ function jobId(value) {
47
52
  id.setValue(value || '');
48
53
  return id;
49
54
  }
55
+ function json(value) { return value == null ? '' : JSON.stringify(value); }
56
+ function parseJson(value) {
57
+ if (!value) return null;
58
+ try { return JSON.parse(value); } catch { return null; }
59
+ }
60
+
61
+ export function encodeErrorDetail(value) {
62
+ const envelope = isErrorEnvelope(value) ? value : normalizeError(value);
63
+ const detail = new errorsPb.ErrorDetail();
64
+ detail.setCode(protoErrorCode(envelope.code));
65
+ detail.setMessage(envelope.message);
66
+ detail.setRetryable(envelope.retryable);
67
+ detail.setReason(envelope.reason);
68
+ if (envelope.http_status != null) detail.setHttpStatus(envelope.http_status);
69
+ if (envelope.retry_after_ms != null) detail.setRetryAfterMs(envelope.retry_after_ms);
70
+ if (envelope.provider) detail.setProvider(envelope.provider);
71
+ if (envelope.provider_code) detail.setProviderCode(envelope.provider_code);
72
+ detail.setSeverity(envelope.severity);
73
+ detail.setSourceKind(envelope.source.kind);
74
+ detail.setSourceName(envelope.source.name);
75
+ if (envelope.source.service) detail.setSourceService(envelope.source.service);
76
+ detail.setResolutionOwner(envelope.resolution_owner);
77
+ detail.setDomain(envelope.domain);
78
+ if (envelope.tool) detail.setTool(envelope.tool);
79
+ if (envelope.stage) detail.setStage(envelope.stage);
80
+ detail.setRemediationAction(envelope.remediation.action);
81
+ if (envelope.remediation.message) detail.setRemediationMessage(envelope.remediation.message);
82
+ detail.setFingerprint(envelope.fingerprint);
83
+ if (envelope.trace_id) detail.setTraceId(envelope.trace_id);
84
+ if (envelope.transport) detail.setTransport(envelope.transport);
85
+ if (envelope.resource) detail.setResourceJson(json(envelope.resource));
86
+ if (envelope.native) detail.setNativeJson(json(envelope.native));
87
+ if (envelope.environment) detail.setEnvironmentJson(json(envelope.environment));
88
+ if (envelope.details != null) detail.setDetailsJson(json(envelope.details));
89
+ detail.setOccurrenceCount(envelope.occurrence_count || 1);
90
+ if (envelope.request_id) detail.setRequestId(envelope.request_id);
91
+ detail.setSchemaVersion(envelope.schema_version || 1);
92
+ return detail;
93
+ }
94
+
95
+ export function decodeErrorDetail(detail) {
96
+ if (!detail) return null;
97
+ const code = errorCodeNames.get(detail.getCode()) || ERROR_CODE.UNKNOWN;
98
+ const provider = detail.hasProvider?.() ? detail.getProvider() : null;
99
+ return createErrorEnvelope({
100
+ code,
101
+ reason: detail.getReason?.() || ERROR_REASON.UNKNOWN,
102
+ message: detail.getMessage?.() || 'Operation failed',
103
+ retryable: detail.getRetryable?.() || false,
104
+ retry_after_ms: detail.hasRetryAfterMs?.() ? detail.getRetryAfterMs() : null,
105
+ http_status: detail.hasHttpStatus?.() ? detail.getHttpStatus() : defaultHttpStatusForCode(code),
106
+ provider,
107
+ provider_code: detail.hasProviderCode?.() ? detail.getProviderCode() : null,
108
+ severity: detail.hasSeverity?.() ? detail.getSeverity() : undefined,
109
+ source: {
110
+ kind: detail.hasSourceKind?.() ? detail.getSourceKind() : (provider ? 'provider' : 'agentsam'),
111
+ name: detail.hasSourceName?.() ? detail.getSourceName() : (provider || 'agentsam-sdk'),
112
+ service: detail.hasSourceService?.() ? detail.getSourceService() : null,
113
+ },
114
+ resolution_owner: detail.hasResolutionOwner?.() ? detail.getResolutionOwner() : undefined,
115
+ domain: detail.hasDomain?.() ? detail.getDomain() : 'runtime',
116
+ tool: detail.hasTool?.() ? detail.getTool() : null,
117
+ stage: detail.hasStage?.() ? detail.getStage() : null,
118
+ remediation: {
119
+ action: detail.hasRemediationAction?.() ? detail.getRemediationAction() : undefined,
120
+ message: detail.hasRemediationMessage?.() ? detail.getRemediationMessage() : null,
121
+ },
122
+ fingerprint: detail.hasFingerprint?.() ? detail.getFingerprint() : undefined,
123
+ trace_id: detail.hasTraceId?.() ? detail.getTraceId() : null,
124
+ transport: detail.hasTransport?.() ? detail.getTransport() : null,
125
+ resource: detail.hasResourceJson?.() ? parseJson(detail.getResourceJson()) : null,
126
+ native: detail.hasNativeJson?.() ? parseJson(detail.getNativeJson()) : null,
127
+ environment: detail.hasEnvironmentJson?.() ? parseJson(detail.getEnvironmentJson()) : null,
128
+ details: detail.hasDetailsJson?.() ? parseJson(detail.getDetailsJson()) : null,
129
+ occurrence_count: detail.hasOccurrenceCount?.() ? detail.getOccurrenceCount() : 1,
130
+ request_id: detail.hasRequestId?.() ? detail.getRequestId() : null,
131
+ });
132
+ }
50
133
 
51
134
  export { grpc, knowledgePb, errorsPb, KnowledgeServiceService, KnowledgeServiceClient };
52
135
 
@@ -58,21 +141,20 @@ export function encodeJob(job) {
58
141
  message.setCreatedAt(timestamp(job.created_at));
59
142
  message.setUpdatedAt(timestamp(job.updated_at));
60
143
  if (job.result !== null && job.result !== undefined) message.setResultJson(JSON.stringify(job.result));
61
- if (job.error) {
62
- const failure = new errorsPb.ErrorDetail();
63
- failure.setCode(protoErrorCode(ERROR_CODE.INTERNAL));
64
- failure.setMessage(job.error);
65
- failure.setRetryable(false);
66
- failure.setReason(ERROR_REASON.EXECUTION_FAILED);
67
- failure.setHttpStatus(500);
68
- message.setFailure(failure);
69
- }
144
+ const failure = job.failure || (job.error ? createErrorEnvelope({
145
+ reason: ERROR_REASON.EXECUTION_FAILED,
146
+ message: job.error,
147
+ source: { kind: 'agentsam', name: 'agentsam-knowledge' },
148
+ domain: 'knowledge',
149
+ stage: 'execute',
150
+ }) : null);
151
+ if (failure) message.setFailure(encodeErrorDetail(failure));
70
152
  return message;
71
153
  }
72
154
 
73
155
  export function decodeJob(message) {
74
156
  const resultJson = message.getResultJson();
75
- const failure = message.hasFailure() ? message.getFailure() : null;
157
+ const failure = message.hasFailure() ? decodeErrorDetail(message.getFailure()) : null;
76
158
  return {
77
159
  id: message.hasId() ? message.getId().getValue() : '',
78
160
  status: statusFromProto.get(message.getStatus()) || 'unknown',
@@ -80,7 +162,8 @@ export function decodeJob(message) {
80
162
  created_at: iso(message.getCreatedAt()),
81
163
  updated_at: iso(message.getUpdatedAt()),
82
164
  result: resultJson ? JSON.parse(resultJson) : null,
83
- error: failure ? failure.getMessage() : null,
165
+ failure,
166
+ error: failure?.message || null,
84
167
  };
85
168
  }
86
169
 
@@ -174,42 +257,46 @@ export function authorizationFromMetadata(metadata) {
174
257
  }
175
258
 
176
259
  export function toGrpcError(error) {
177
- const safeMessage = error?.status ? error.message : 'Service request failed.';
178
- const legacyCode = error?.code === 'CONFLICT' ? ERROR_CODE.ABORTED : error?.code;
179
- const code = Object.values(ERROR_CODE).includes(legacyCode) ? legacyCode : canonicalCodeFromHttpStatus(error?.status);
180
- const reason = error?.reason || (code === ERROR_CODE.UNAUTHENTICATED ? ERROR_REASON.AUTH_INVALID
181
- : code === ERROR_CODE.PERMISSION_DENIED ? ERROR_REASON.PERMISSION_DENIED
182
- : code === ERROR_CODE.NOT_FOUND ? ERROR_REASON.TARGET_NOT_FOUND
183
- : code === ERROR_CODE.ABORTED ? ERROR_REASON.CONFLICT
184
- : code === ERROR_CODE.RESOURCE_EXHAUSTED ? ERROR_REASON.CAPACITY_EXHAUSTED
185
- : code === ERROR_CODE.UNAVAILABLE ? ERROR_REASON.PROVIDER_UNAVAILABLE
186
- : code === ERROR_CODE.INVALID_ARGUMENT ? ERROR_REASON.INPUT_INVALID
187
- : ERROR_REASON.INTERNAL);
188
- const envelope = createErrorEnvelope({
189
- code,
190
- reason,
191
- message: safeMessage,
192
- retryable: error?.retryable ?? (error?.status === 429 || error?.status === 503),
193
- retry_after_ms: error?.retry_after_ms ?? null,
194
- http_status: error?.status ?? defaultHttpStatusForCode(code),
195
- provider: error?.provider ?? null,
196
- provider_code: error?.provider_code ?? null,
197
- });
198
- const detail = new errorsPb.ErrorDetail();
199
- detail.setCode(protoErrorCode(envelope.code));
200
- detail.setMessage(envelope.message);
201
- detail.setRetryable(envelope.retryable);
202
- detail.setReason(envelope.reason);
203
- if (envelope.http_status != null) detail.setHttpStatus(envelope.http_status);
204
- if (envelope.retry_after_ms != null) detail.setRetryAfterMs(envelope.retry_after_ms);
205
- if (envelope.provider) detail.setProvider(envelope.provider);
206
- if (envelope.provider_code) detail.setProviderCode(envelope.provider_code);
260
+ let envelope;
261
+ if (isErrorEnvelope(error) || error instanceof AgentSamError || isErrorEnvelope(error?.envelope)) {
262
+ envelope = normalizeError(error);
263
+ } else {
264
+ const safeMessage = error?.status ? error.message : 'Service request failed.';
265
+ const legacyCode = error?.code === 'CONFLICT' ? ERROR_CODE.ABORTED : error?.code;
266
+ const code = Object.values(ERROR_CODE).includes(legacyCode) ? legacyCode : canonicalCodeFromHttpStatus(error?.status);
267
+ const reason = error?.reason || (code === ERROR_CODE.UNAUTHENTICATED ? ERROR_REASON.AUTH_INVALID
268
+ : code === ERROR_CODE.PERMISSION_DENIED ? ERROR_REASON.PERMISSION_DENIED
269
+ : code === ERROR_CODE.NOT_FOUND ? ERROR_REASON.TARGET_NOT_FOUND
270
+ : code === ERROR_CODE.ABORTED ? ERROR_REASON.CONFLICT
271
+ : code === ERROR_CODE.RESOURCE_EXHAUSTED ? ERROR_REASON.CAPACITY_EXHAUSTED
272
+ : code === ERROR_CODE.UNAVAILABLE ? ERROR_REASON.TRANSPORT_UNREACHABLE
273
+ : code === ERROR_CODE.DEADLINE_EXCEEDED ? ERROR_REASON.DEADLINE_EXCEEDED
274
+ : code === ERROR_CODE.INVALID_ARGUMENT ? ERROR_REASON.INPUT_INVALID
275
+ : ERROR_REASON.INTERNAL);
276
+ envelope = createErrorEnvelope({
277
+ code,
278
+ reason,
279
+ message: safeMessage,
280
+ retryable: error?.retryable ?? (error?.status === 429 || error?.status === 503 || error?.status === 504),
281
+ retry_after_ms: error?.retry_after_ms ?? null,
282
+ http_status: error?.status ?? defaultHttpStatusForCode(code),
283
+ provider: error?.provider ?? null,
284
+ provider_code: error?.provider_code ?? null,
285
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'grpc' },
286
+ resolution_owner: code === ERROR_CODE.UNAVAILABLE ? 'agentsam' : undefined,
287
+ domain: 'knowledge',
288
+ stage: 'request',
289
+ trace_id: error?.trace_id ?? null,
290
+ });
291
+ }
292
+ const detail = encodeErrorDetail(envelope);
207
293
  const metadata = new grpc.Metadata();
208
294
  metadata.set('agentsam-error-bin', Buffer.from(detail.serializeBinary()));
209
- return Object.assign(new Error(safeMessage), {
295
+ return Object.assign(new Error(envelope.message), {
210
296
  code: grpcStatusForCode(envelope.code),
211
- details: safeMessage,
297
+ details: envelope.message,
212
298
  metadata,
299
+ envelope,
213
300
  });
214
301
  }
215
302
 
@@ -220,17 +307,33 @@ export function fromGrpcError(error) {
220
307
  const binary = values.find(value => Buffer.isBuffer(value));
221
308
  if (binary) detail = errorsPb.ErrorDetail.deserializeBinary(new Uint8Array(binary));
222
309
  } catch { /* fall back to gRPC status */ }
223
- const message = detail?.getMessage() || error?.details || error?.message || 'Knowledge RPC failed.';
224
- const rpcCode = detail ? errorCodeNames.get(detail.getCode()) || 'UNKNOWN' : undefined;
225
- return Object.assign(new Error(message), {
226
- status: detail?.hasHttpStatus?.() ? detail.getHttpStatus() : grpcToHttp.get(error?.code) ?? 500,
310
+ let envelope;
311
+ if (detail) {
312
+ envelope = decodeErrorDetail(detail);
313
+ } else {
314
+ const status = grpcToHttp.get(error?.code) ?? 500;
315
+ const code = canonicalCodeFromHttpStatus(status);
316
+ envelope = createErrorEnvelope({
317
+ code,
318
+ reason: code === ERROR_CODE.UNAUTHENTICATED ? ERROR_REASON.AUTH_INVALID
319
+ : code === ERROR_CODE.PERMISSION_DENIED ? ERROR_REASON.PERMISSION_DENIED
320
+ : code === ERROR_CODE.NOT_FOUND ? ERROR_REASON.TARGET_NOT_FOUND
321
+ : code === ERROR_CODE.RESOURCE_EXHAUSTED ? ERROR_REASON.CAPACITY_EXHAUSTED
322
+ : code === ERROR_CODE.UNAVAILABLE ? ERROR_REASON.TRANSPORT_UNREACHABLE
323
+ : code === ERROR_CODE.DEADLINE_EXCEEDED ? ERROR_REASON.DEADLINE_EXCEEDED
324
+ : code === ERROR_CODE.INVALID_ARGUMENT ? ERROR_REASON.INPUT_INVALID
325
+ : ERROR_REASON.INTERNAL,
326
+ message: error?.details || error?.message || 'Knowledge RPC failed.',
327
+ http_status: status,
328
+ retryable: [8, 14, 4].includes(Number(error?.code)),
329
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'grpc' },
330
+ domain: 'knowledge',
331
+ stage: 'request',
332
+ });
333
+ }
334
+ return Object.assign(new AgentSamError(envelope), {
227
335
  grpcCode: error?.code,
228
- rpcCode,
229
- reason: detail?.getReason?.() || ERROR_REASON.UNKNOWN,
230
- retryable: detail?.getRetryable() || false,
231
- retry_after_ms: detail?.hasRetryAfterMs?.() ? detail.getRetryAfterMs() : null,
232
- provider: detail?.hasProvider?.() ? detail.getProvider() : null,
233
- provider_code: detail?.hasProviderCode?.() ? detail.getProviderCode() : null,
336
+ rpcCode: envelope.code,
234
337
  });
235
338
  }
236
339