@inneranimalmedia/agentsam-sdk 2.6.2 → 2.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (661) hide show
  1. package/AGENTSAM.md +51 -1
  2. package/README.md +95 -0
  3. package/apps/README.md +34 -0
  4. package/apps/cad-creator/README.md +728 -0
  5. package/apps/cad-creator/shared/cad/package.json +19 -0
  6. package/apps/cad-creator/shared/cad/src/domain/operations.ts +7 -0
  7. package/apps/cad-creator/shared/cad/src/domain/project-contract.d.ts +3 -0
  8. package/apps/cad-creator/shared/cad/src/domain/project-contract.js +75 -0
  9. package/apps/cad-creator/shared/cad/src/domain/project-tools.d.ts +1 -0
  10. package/apps/cad-creator/shared/cad/src/domain/project-tools.js +24 -0
  11. package/apps/cad-creator/shared/cad/src/domain/validation.ts +191 -0
  12. package/apps/cad-creator/shared/cad/src/index.ts +4 -0
  13. package/apps/cad-creator/shared/cad/src/robotics/types.ts +232 -0
  14. package/apps/cad-creator/shared/cad/src/types.ts +507 -0
  15. package/apps/cad-creator/shared/cad/tsconfig.json +14 -0
  16. package/bin/agentsam +16 -1
  17. package/docs/AUTORAG.md +58 -0
  18. package/docs/BRAND_INTELLIGENCE.md +30 -0
  19. package/docs/CLI_SHELL.md +4 -2
  20. package/docs/CMS_CONTEXTUAL_COMPOSER.md +38 -0
  21. package/docs/MERKLE.md +4 -0
  22. package/docs/PROJECT_CONFIG.md +3 -0
  23. package/docs/REPOSITORY_KNOWLEDGE.md +2 -0
  24. package/docs/THEME_REFINERY.md +120 -0
  25. package/docs/architecture/AGENTSAM_DISTRIBUTION_OWNERSHIP.md +176 -0
  26. package/docs/architecture/AGENTSAM_GO_RUNTIME.md +282 -0
  27. package/docs/architecture/CODEBASEINDEX_GUIDED_PATH.md +202 -0
  28. package/docs/architecture/FS_E2E_CLOSURE_RECEIPT.md +59 -0
  29. package/docs/architecture/LOCAL_FS_AUTHORITY.md +38 -0
  30. package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +28 -0
  31. package/docs/architecture/PLAN_CLI_AND_LOCAL_STUDIO_DESKTOP.md +96 -0
  32. package/docs/architecture/PROVIDER-TOOLS-AND-COMPACTION.md +60 -0
  33. package/docs/architecture/SAM_ACTIVITY_RECOVERY_RECEIPT.md +39 -0
  34. package/docs/architecture/SAM_DECISION_WORK_RECEIPT.md +54 -0
  35. package/docs/architecture/SAM_KERNEL.md +181 -0
  36. package/docs/architecture/SAM_MACHINE_NORMALIZATION_PRECOMMIT_REPORT.md +208 -0
  37. package/docs/architecture/SLASH_SKILLS_PORTABLE.md +116 -0
  38. package/docs/architecture/STORAGE.md +87 -0
  39. package/docs/architecture/fs-e2e-receipt.latest.json +42 -0
  40. package/docs/architecture/previews/codebaseindex-guided-path/CODEBASEINDEX_GUIDED_PATH.md +202 -0
  41. package/docs/architecture/previews/codebaseindex-guided-path/index.html +321 -0
  42. package/docs/cad-project-tools.md +69 -0
  43. package/docs/cms-scaffolding-pattern-reference.md +73 -0
  44. package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS-codex-tui-20260919.md +113 -0
  45. package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS.md +85 -0
  46. package/docs/plans/AGENTSAM-MCP-CLIENT-2026-09-19.md +181 -0
  47. package/docs/plans/ASBD-PORTABLE-WORKGRAPH-UI-DEFERRED.md +34 -0
  48. package/docs/plans/ASTRA-BRIEF-2026-09-18.md +258 -0
  49. package/docs/plans/MULTI-AGENT-SPRINTS-2026-09-19.md +373 -0
  50. package/docs/plans/NEXT-AGENT-HANDOFF.md +167 -0
  51. package/docs/plans/RECONCILIATION-2026-09-19.md +178 -0
  52. package/docs/plugins.md +43 -0
  53. package/docs/tools/README.md +57 -0
  54. package/docs/tools/agent-and-orchestration.md +49 -0
  55. package/docs/tools/browser-and-research.md +46 -0
  56. package/docs/tools/cloudflare-platform.md +32 -0
  57. package/docs/tools/cms.md +25 -0
  58. package/docs/tools/communications.md +41 -0
  59. package/docs/tools/database-and-storage.md +62 -0
  60. package/docs/tools/design-and-media.md +64 -0
  61. package/docs/tools/filesystem-and-code.md +55 -0
  62. package/docs/tools/github.md +56 -0
  63. package/docs/tools/integrations-and-misc.md +16 -0
  64. package/docs/tools/memory.md +21 -0
  65. package/docs/tools/terminal-and-execution.md +29 -0
  66. package/docs/tools/tickets-and-platform.md +30 -0
  67. package/migrations/d1/0001_agentsam_plugin_runtime.sql +177 -0
  68. package/migrations/d1/0002_agentsam_ticket_ownership.sql +8 -0
  69. package/migrations/d1/0002_dynamic_model_policies.sql +23 -0
  70. package/migrations/d1/0003_expand_tool_handler_families.sql +18 -0
  71. package/migrations/d1/0004_project_aware_retrieval_lanes.sql +24 -0
  72. package/migrations/d1/0005_portable_knowledge_identity.sql +104 -0
  73. package/migrations/d1/0006_repair_ops_trail_account_scope.sql +14 -0
  74. package/migrations/d1/0007_repair_ops_trail_agent_run_account.sql +13 -0
  75. package/migrations/d1/0008_backfill_knowledge_run_legacy_tenant.sql +14 -0
  76. package/migrations/d1/0009_normalize_cloudflare_plugin_installations.sql +137 -0
  77. package/migrations/d1/0010_portable_tickets_memory.sql +140 -0
  78. package/migrations/d1/0011_agentsam_skill_v2.sql +185 -0
  79. package/migrations/d1/0011b_agentsam_skill_v2_cutover.sql +22 -0
  80. package/migrations/d1/0011c_agentsam_skill_v2_backfill.sql +76 -0
  81. package/migrations/d1/0011d_agentsam_skill_v2_retrieval_revisions.sql +50 -0
  82. package/migrations/d1/0012_agentsam_tools_required_seed.sql +67 -0
  83. package/migrations/d1/0013_identity_oauth_states.sql +15 -0
  84. package/migrations/d1/0014_auth_event_log.sql +20 -0
  85. package/migrations/d1/0015_identity_oauth_state_app_id.sql +3 -0
  86. package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +16 -0
  87. package/migrations/runtime/0001_cli_runtime.sql +67 -0
  88. package/migrations/runtime/0002_project_sessions.sql +15 -0
  89. package/migrations/runtime/0003_provider_continuations.sql +8 -0
  90. package/migrations/sqlite/agentsam_skill_retrieval.portable.sql +42 -0
  91. package/package.json +107 -12
  92. package/packages/agentsam-brand/README.md +21 -0
  93. package/packages/agentsam-brand/package.json +22 -0
  94. package/packages/agentsam-brand/src/contract.js +59 -0
  95. package/packages/agentsam-brand/src/extract.js +126 -0
  96. package/packages/agentsam-brand/src/goap-actions.js +73 -0
  97. package/packages/agentsam-brand/src/index.js +48 -0
  98. package/packages/agentsam-brand/src/plan.js +115 -0
  99. package/packages/agentsam-brand/src/resolve.js +139 -0
  100. package/packages/agentsam-brand/src/scan.js +250 -0
  101. package/packages/agentsam-brand/test/brand-scan.test.mjs +106 -0
  102. package/packages/agentsam-contracts/README.md +23 -0
  103. package/packages/agentsam-contracts/package.json +32 -0
  104. package/packages/agentsam-contracts/src/adapter.ts +25 -0
  105. package/packages/agentsam-contracts/src/agent.ts +35 -0
  106. package/packages/agentsam-contracts/src/artifacts.ts +33 -0
  107. package/packages/agentsam-contracts/src/authority.ts +29 -0
  108. package/packages/agentsam-contracts/src/context.ts +16 -0
  109. package/packages/agentsam-contracts/src/errors.ts +62 -0
  110. package/packages/agentsam-contracts/src/events.ts +47 -0
  111. package/packages/agentsam-contracts/src/execution.ts +50 -0
  112. package/packages/agentsam-contracts/src/hooks.ts +40 -0
  113. package/packages/agentsam-contracts/src/identity.ts +16 -0
  114. package/packages/agentsam-contracts/src/index.ts +14 -0
  115. package/packages/agentsam-contracts/src/models.ts +9 -0
  116. package/packages/agentsam-contracts/src/providers.ts +33 -0
  117. package/packages/agentsam-contracts/src/repository.ts +64 -0
  118. package/packages/agentsam-contracts/src/tools.ts +98 -0
  119. package/packages/agentsam-contracts/test/contracts.test.mjs +16 -0
  120. package/packages/agentsam-contracts/test/errors-catalog.test.mjs +25 -0
  121. package/packages/agentsam-contracts/test/repository.test.mjs +18 -0
  122. package/packages/agentsam-contracts/tsconfig.json +12 -0
  123. package/packages/agentsam-errors/package.json +17 -0
  124. package/packages/agentsam-errors/src/adapters/anthropic.js +15 -0
  125. package/packages/agentsam-errors/src/adapters/cad.js +109 -0
  126. package/packages/agentsam-errors/src/adapters/cloudflare.js +21 -0
  127. package/packages/agentsam-errors/src/adapters/cursor.js +4 -0
  128. package/packages/agentsam-errors/src/adapters/device.js +38 -0
  129. package/packages/agentsam-errors/src/adapters/docker.js +28 -0
  130. package/packages/agentsam-errors/src/adapters/gcp.js +14 -0
  131. package/packages/agentsam-errors/src/adapters/github.js +22 -0
  132. package/packages/agentsam-errors/src/adapters/google.js +17 -0
  133. package/packages/agentsam-errors/src/adapters/index.js +55 -0
  134. package/packages/agentsam-errors/src/adapters/internal.js +40 -0
  135. package/packages/agentsam-errors/src/adapters/oauth.js +24 -0
  136. package/packages/agentsam-errors/src/adapters/openai.js +17 -0
  137. package/packages/agentsam-errors/src/adapters/process.js +35 -0
  138. package/packages/agentsam-errors/src/adapters/provider.js +114 -0
  139. package/packages/agentsam-errors/src/envelope.js +239 -0
  140. package/packages/agentsam-errors/src/error.js +24 -0
  141. package/packages/agentsam-errors/src/fingerprint.js +35 -0
  142. package/packages/agentsam-errors/src/index.js +11 -0
  143. package/packages/agentsam-errors/src/normalize.js +30 -0
  144. package/packages/agentsam-errors/src/recovery.js +301 -0
  145. package/packages/agentsam-errors/src/redaction.js +52 -0
  146. package/packages/agentsam-errors/src/render.js +16 -0
  147. package/packages/agentsam-errors/src/retry.js +10 -0
  148. package/packages/agentsam-errors/src/transport.js +52 -0
  149. package/packages/agentsam-errors/src/vocabulary.js +320 -0
  150. package/packages/agentsam-errors/test/envelope.test.mjs +70 -0
  151. package/packages/agentsam-errors/test/providers.test.mjs +99 -0
  152. package/packages/agentsam-errors/test/redaction.test.mjs +21 -0
  153. package/packages/agentsam-errors/test/runtime-cad-device.test.mjs +76 -0
  154. package/packages/agentsam-errors/test/transport.test.mjs +46 -0
  155. package/packages/agentsam-knowledge/package.json +15 -0
  156. package/packages/agentsam-knowledge/src/autorag/index.js +64 -0
  157. package/packages/agentsam-knowledge/src/backends/index.js +26 -0
  158. package/packages/agentsam-knowledge/src/index.js +3 -0
  159. package/packages/agentsam-knowledge/src/providers/index.js +107 -0
  160. package/packages/agentsam-knowledge/test/autorag.test.mjs +42 -0
  161. package/packages/agentsam-nav/README.md +40 -0
  162. package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
  163. package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
  164. package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
  165. package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
  166. package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
  167. package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
  168. package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
  169. package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
  170. package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
  171. package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
  172. package/packages/agentsam-nav/dist/browser.d.ts +11 -0
  173. package/packages/agentsam-nav/dist/browser.global.js +132 -0
  174. package/packages/agentsam-nav/dist/browser.js +613 -0
  175. package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
  176. package/packages/agentsam-nav/dist/index.d.ts +11 -0
  177. package/packages/agentsam-nav/dist/index.js +614 -0
  178. package/packages/agentsam-nav/dist/legacy.css +83 -0
  179. package/packages/agentsam-nav/dist/shell.css +113 -0
  180. package/packages/agentsam-nav/dist/theme.css +113 -0
  181. package/packages/agentsam-nav/dist/utils.d.ts +1 -0
  182. package/packages/agentsam-nav/package.json +43 -0
  183. package/packages/agentsam-queue-control/README.md +107 -0
  184. package/packages/agentsam-queue-control/package.json +31 -0
  185. package/packages/agentsam-queue-control/schemas/job-envelope.schema.json +56 -0
  186. package/packages/agentsam-queue-control/src/adapters/cloudflare.js +152 -0
  187. package/packages/agentsam-queue-control/src/adapters/memory.js +38 -0
  188. package/packages/agentsam-queue-control/src/contracts.js +130 -0
  189. package/packages/agentsam-queue-control/src/control-plane.js +141 -0
  190. package/packages/agentsam-queue-control/src/dispatch.js +43 -0
  191. package/packages/agentsam-queue-control/src/index.js +7 -0
  192. package/packages/agentsam-queue-control/src/policy.js +88 -0
  193. package/packages/agentsam-queue-control/src/topology.js +66 -0
  194. package/packages/agentsam-queue-control/test/queue-control.test.mjs +100 -0
  195. package/packages/agentsam-repository/src/goap.js +718 -0
  196. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
  197. package/packages/agentsam-repository/src/index.js +5 -0
  198. package/packages/agentsam-repository/src/merkle/cloudflare-persistence.js +2 -2
  199. package/packages/agentsam-repository/src/tickets.js +184 -0
  200. package/packages/agentsam-repository/src/work-tracking.js +199 -0
  201. package/packages/agentsam-repository/src/workspace-state.js +176 -0
  202. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +152 -0
  203. package/packages/connectors/cloudflare/src/index.js +297 -15
  204. package/packages/connectors/cloudflare/src/owner.js +43 -40
  205. package/packages/connectors/cloudflare/src/routes.js +176 -26
  206. package/packages/connectors/cloudflare/tests/connector.test.mjs +137 -2
  207. package/packages/heuristic-theme/README.md +11 -0
  208. package/packages/heuristic-theme/package.json +25 -0
  209. package/packages/heuristic-theme/src/index.js +2 -0
  210. package/packages/heuristic-theme/src/registry.js +36 -0
  211. package/packages/heuristic-theme/src/theme.js +41 -0
  212. package/packages/heuristic-theme/test/theme.test.mjs +26 -0
  213. package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +64 -0
  214. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +96 -0
  215. package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +47 -0
  216. package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +83 -0
  217. package/packages/identity/.agentsam/features/oauth-login-portal/ui.json +35 -0
  218. package/packages/identity/docs/PORTABLE_IDENTITY_ARCHITECTURE.md +50 -0
  219. package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +31 -0
  220. package/packages/identity/migrations/sqlite/001_identity_core.sql +99 -0
  221. package/packages/identity/migrations/sqlite/002_identity_oauth_client.sql +38 -0
  222. package/packages/identity/migrations/sqlite/003_identity_oauth_server.sql +64 -0
  223. package/packages/identity/package.json +4 -3
  224. package/packages/identity/src/adapters/cloudflare-d1/ids.js +4 -0
  225. package/packages/identity/src/adapters/cloudflare-d1/index.js +156 -18
  226. package/packages/identity/src/adapters/sqlite/index.js +319 -0
  227. package/packages/identity/src/app/verify-app.js +95 -0
  228. package/packages/identity/src/contracts/identity-store.js +115 -0
  229. package/packages/identity/src/contracts/provider.js +3 -2
  230. package/packages/identity/src/contracts/route-ids.js +30 -0
  231. package/packages/identity/src/contracts/route-projection.js +218 -0
  232. package/packages/identity/src/contracts/routes.js +11 -0
  233. package/packages/identity/src/core/browser-paths.js +4 -5
  234. package/packages/identity/src/core/constants.js +13 -8
  235. package/packages/identity/src/core/session-policy.js +32 -0
  236. package/packages/identity/src/frontend/auth-portal/pages/login.html +16 -9
  237. package/packages/identity/src/frontend/auth-portal/pages/reset.html +3 -3
  238. package/packages/identity/src/frontend/auth-portal/pages/signup.html +3 -3
  239. package/packages/identity/src/frontend/auth-portal/preview/dashboard-stub.html +1 -1
  240. package/packages/identity/src/index.js +27 -0
  241. package/packages/identity/src/oauth/README.md +10 -4
  242. package/packages/identity/src/oauth/credentials.js +31 -11
  243. package/packages/identity/src/oauth/finalize-inbound.js +1 -1
  244. package/packages/identity/src/oauth/iam-platform.js +13 -12
  245. package/packages/identity/src/oauth/redirect-paths.js +27 -36
  246. package/packages/identity/src/providers/cloudflare/index.js +19 -0
  247. package/packages/identity/src/providers/cloudflare/mapper.js +21 -0
  248. package/packages/identity/src/providers/cloudflare/oauth.js +48 -0
  249. package/packages/identity/src/providers/cloudflare/profile.js +28 -0
  250. package/packages/identity/src/providers/index.js +18 -2
  251. package/packages/identity/src/server/identity-service.js +35 -8
  252. package/packages/identity/src/server/mount-policy.js +30 -0
  253. package/packages/identity/src/server/post-auth.js +79 -0
  254. package/packages/identity/src/server/worker-router.js +153 -66
  255. package/packages/identity/tests/finalize-inbound-oauth.test.mjs +6 -6
  256. package/packages/identity/tests/iam-provider.test.mjs +1 -1
  257. package/packages/identity/tests/identity-service.test.mjs +47 -1
  258. package/packages/identity/tests/oauth-credentials.test.mjs +3 -1
  259. package/packages/identity/tests/portable-identity-architecture.test.mjs +157 -0
  260. package/packages/identity/tests/session-routes-policy.test.mjs +21 -0
  261. package/packages/providers/completeful/README.md +38 -0
  262. package/packages/providers/completeful/package.json +29 -0
  263. package/packages/providers/completeful/src/client.js +162 -0
  264. package/packages/providers/completeful/src/events.js +49 -0
  265. package/packages/providers/completeful/src/index.js +22 -0
  266. package/packages/providers/completeful/src/tools.js +579 -0
  267. package/packages/providers/completeful/src/webhooks.js +55 -0
  268. package/packages/providers/completeful/test/provider.test.mjs +196 -0
  269. package/packages/theme-church-site/README.md +10 -0
  270. package/packages/theme-church-site/package.json +31 -0
  271. package/packages/theme-church-site/src/harvest.json +14 -0
  272. package/packages/theme-church-site/src/index.js +85 -0
  273. package/packages/theme-church-site/test/theme.test.mjs +19 -0
  274. package/packages/theme-companions-site/README.md +10 -0
  275. package/packages/theme-companions-site/package.json +31 -0
  276. package/packages/theme-companions-site/src/harvest.json +12 -0
  277. package/packages/theme-companions-site/src/index.js +83 -0
  278. package/packages/theme-companions-site/test/theme.test.mjs +19 -0
  279. package/packages/theme-floors-site/README.md +10 -0
  280. package/packages/theme-floors-site/package.json +31 -0
  281. package/packages/theme-floors-site/src/harvest.json +14 -0
  282. package/packages/theme-floors-site/src/index.js +83 -0
  283. package/packages/theme-floors-site/test/theme.test.mjs +19 -0
  284. package/packages/theme-fuelnfree-site/README.md +10 -0
  285. package/packages/theme-fuelnfree-site/package.json +31 -0
  286. package/packages/theme-fuelnfree-site/src/harvest.json +13 -0
  287. package/packages/theme-fuelnfree-site/src/index.js +82 -0
  288. package/packages/theme-fuelnfree-site/test/theme.test.mjs +19 -0
  289. package/packages/theme-handyman-site/README.md +10 -0
  290. package/packages/theme-handyman-site/package.json +31 -0
  291. package/packages/theme-handyman-site/src/harvest.json +10 -0
  292. package/packages/theme-handyman-site/src/index.js +84 -0
  293. package/packages/theme-handyman-site/test/theme.test.mjs +19 -0
  294. package/packages/theme-insurance-site/README.md +10 -0
  295. package/packages/theme-insurance-site/package.json +31 -0
  296. package/packages/theme-insurance-site/src/harvest.json +10 -0
  297. package/packages/theme-insurance-site/src/index.js +84 -0
  298. package/packages/theme-insurance-site/test/theme.test.mjs +19 -0
  299. package/packages/theme-shinshu-site/README.md +10 -0
  300. package/packages/theme-shinshu-site/package.json +31 -0
  301. package/packages/theme-shinshu-site/src/harvest.json +12 -0
  302. package/packages/theme-shinshu-site/src/index.js +84 -0
  303. package/packages/theme-shinshu-site/test/theme.test.mjs +19 -0
  304. package/packages/work-graph/README.md +49 -0
  305. package/packages/work-graph/package.json +19 -0
  306. package/packages/work-graph/prototype/README.md +32 -0
  307. package/packages/work-graph/prototype/data/demo-workgraph.js +47 -0
  308. package/packages/work-graph/prototype/renderers/timeline-model.js +21 -0
  309. package/packages/work-graph/prototype/renderers/workgraph-runtime.js +38 -0
  310. package/packages/work-graph/prototype-gnantt.html +655 -0
  311. package/packages/work-graph/src/adapters/business/projects.js +23 -0
  312. package/packages/work-graph/src/adapters/engineering/git.js +22 -0
  313. package/packages/work-graph/src/adapters/engineering/mcp.js +22 -0
  314. package/packages/work-graph/src/index.js +76 -0
  315. package/packages/work-graph/src/renderers/gantt-model.js +11 -0
  316. package/packages/work-graph/src/renderers/timeline.js +16 -0
  317. package/packages/work-graph/test/work-graph.test.mjs +37 -0
  318. package/protocol/README.md +12 -0
  319. package/protocol/apps/agentsam.app.v1.schema.json +51 -0
  320. package/protocol/brand/brandpack.v1.schema.json +43 -0
  321. package/protocol/capabilities/cloudflare-cpu-audit-input.schema.json +30 -6
  322. package/protocol/capabilities/cloudflare-cpu-profile-input.schema.json +18 -4
  323. package/protocol/capabilities/cloudflare-wrangler-native-input.schema.json +59 -10
  324. package/protocol/capabilities/knowledge-search-input.schema.json +35 -0
  325. package/protocol/capabilities/manifest.json +163 -1
  326. package/protocol/capabilities/repository-audit-input.schema.json +39 -6
  327. package/protocol/capabilities/repository-snapshot-input.schema.json +15 -3
  328. package/protocol/capabilities/terminal-exec-input.schema.json +55 -0
  329. package/protocol/commerce/catalog.v1.json +50 -0
  330. package/protocol/credentials/issue.v1.schema.json +38 -0
  331. package/protocol/database/connection.v1.schema.json +41 -0
  332. package/protocol/embeddings/embedding-profile.v1.schema.json +20 -0
  333. package/protocol/errors/error-catalog.json +164 -0
  334. package/protocol/errors/error-envelope.schema.json +678 -0
  335. package/protocol/errors/recovery.v1.schema.json +50 -0
  336. package/protocol/features/README.md +57 -0
  337. package/protocol/features/agentsam.feature.v1.schema.json +290 -0
  338. package/protocol/features/catalog.json +65 -0
  339. package/protocol/features/examples/provider-resend.feature.json +17 -0
  340. package/protocol/go/agentsam-go-runtime.v1.json +17 -0
  341. package/protocol/knowledge/LIFECYCLE.md +140 -0
  342. package/protocol/knowledge/README.md +4 -0
  343. package/protocol/presets/catalog.json +128 -19
  344. package/protocol/rpc/v1/errors.proto +24 -0
  345. package/protocol/runtime/workspace-fs.v1.schema.json +71 -0
  346. package/protocol/sam/activity.v1.schema.json +48 -0
  347. package/protocol/sam/answer.v1.schema.json +35 -0
  348. package/protocol/sam/calibration.v1.schema.json +21 -0
  349. package/protocol/sam/decision-receipt.v1.schema.json +29 -0
  350. package/protocol/sam/evaluation.v1.schema.json +19 -0
  351. package/protocol/sam/operation.schema.json +66 -0
  352. package/protocol/sam/outcome.v1.schema.json +36 -0
  353. package/protocol/sam/question.v1.schema.json +26 -0
  354. package/protocol/sam/registry.seed.json +153 -0
  355. package/protocol/sam/result.schema.json +53 -0
  356. package/protocol/sam/state.v1.schema.json +23 -0
  357. package/protocol/skills/agentsam.interaction.v1.schema.json +50 -0
  358. package/protocol/skills/agentsam.skill.v1.schema.json +57 -0
  359. package/protocol/theme-refinery/d1-reconciliation.md +48 -0
  360. package/protocol/theme-refinery/product-metadata.schema.json +27 -0
  361. package/protocol/theme-refinery/receipts/products-registry-batch-20260924.json +318 -0
  362. package/protocol/theme-refinery/receipts/theme-harvest-20260924.json +472 -0
  363. package/protocol/theme-refinery/reconciliation-receipt.schema.json +83 -0
  364. package/protocol/ui/icon-registry.mjs +226 -0
  365. package/protocol/ui/icon.v1.schema.json +51 -0
  366. package/services/cad/server.py +249 -2
  367. package/skills/README.md +22 -9
  368. package/skills/agentsam-codebaseindex/SKILL.md +225 -0
  369. package/skills/catalog.json +14 -0
  370. package/src/agent/capability-adapter.js +15 -5
  371. package/src/agent/index.js +2 -1
  372. package/src/agent/model-turn.js +51 -0
  373. package/src/agent/responses-runner.js +304 -38
  374. package/src/capabilities/index.js +1 -0
  375. package/src/capabilities/terminal-exec.js +78 -0
  376. package/src/cli/command-catalog.js +130 -0
  377. package/src/cli/dispatch.js +48 -0
  378. package/src/cli.js +160 -10
  379. package/src/cloudflare/index.js +6 -0
  380. package/src/cloudflare/runtime-status.js +393 -0
  381. package/src/cloudflare/wrangler.js +17 -1
  382. package/src/commands/api-key.js +244 -0
  383. package/src/commands/app.js +138 -0
  384. package/src/commands/autorag.js +77 -0
  385. package/src/commands/brand.js +291 -0
  386. package/src/commands/cad.js +1 -0
  387. package/src/commands/codebaseindex.js +688 -0
  388. package/src/commands/connections.js +126 -29
  389. package/src/commands/context-economics.js +8 -0
  390. package/src/commands/db.js +7 -0
  391. package/src/commands/env.js +155 -27
  392. package/src/commands/eval.js +209 -14
  393. package/src/commands/go.js +678 -0
  394. package/src/commands/goap.js +176 -0
  395. package/src/commands/identity-init.js +27 -3
  396. package/src/commands/identity-protocol.js +195 -0
  397. package/src/commands/interaction-clack.js +115 -0
  398. package/src/commands/knowledge.js +64 -5
  399. package/src/commands/mcp.js +341 -0
  400. package/src/commands/merkle-persist.js +3 -1
  401. package/src/commands/merkle.js +18 -3
  402. package/src/commands/models.js +110 -24
  403. package/src/commands/plugins.js +175 -0
  404. package/src/commands/preferences.js +28 -8
  405. package/src/commands/product.js +53 -10
  406. package/src/commands/providers.js +173 -44
  407. package/src/commands/resume.js +9 -5
  408. package/src/commands/runtime-status.js +154 -0
  409. package/src/commands/shell.js +508 -56
  410. package/src/commands/skill.js +248 -0
  411. package/src/commands/skills.js +1 -1
  412. package/src/commands/start-local.js +4 -0
  413. package/src/commands/status.js +82 -7
  414. package/src/commands/tunnel.js +228 -195
  415. package/src/commands/whoami.js +156 -12
  416. package/src/context/budget.js +6 -0
  417. package/src/context/index.js +2 -1
  418. package/src/context/project-card.js +75 -0
  419. package/src/errors/contract.js +34 -211
  420. package/src/errors/diagnostic.js +95 -51
  421. package/src/errors/index.js +6 -13
  422. package/src/eval/index.js +6 -0
  423. package/src/eval/live.js +439 -0
  424. package/src/features/resolve.js +242 -0
  425. package/src/go/build.js +298 -0
  426. package/src/go/cloudflare.js +608 -0
  427. package/src/go/container.js +120 -0
  428. package/src/go/contract.js +144 -0
  429. package/src/go/discover.js +212 -0
  430. package/src/go/index.js +25 -0
  431. package/src/go/native-probe-runner.mjs +119 -0
  432. package/src/go/official-registry.js +280 -0
  433. package/src/go/official-release.js +10 -0
  434. package/src/go/receipts.js +144 -0
  435. package/src/go/verify.js +38 -0
  436. package/src/index.js +127 -1
  437. package/src/indexing/ingest/discover-models.js +298 -0
  438. package/src/indexing/ingest/inventory.js +243 -0
  439. package/src/indexing/ingest/job-graph.js +181 -0
  440. package/src/indexing/ingest/materials.js +210 -0
  441. package/src/knowledge/config.js +13 -5
  442. package/src/knowledge/engine.js +23 -8
  443. package/src/knowledge/index.js +1 -0
  444. package/src/knowledge/lane-registry.js +46 -0
  445. package/src/knowledge/providers/gemini.js +48 -8
  446. package/src/knowledge/service/client.js +13 -1
  447. package/src/knowledge/service/grpc-codec.js +156 -53
  448. package/src/knowledge/service/job-engine.js +133 -11
  449. package/src/knowledge/service/job-worker.js +34 -5
  450. package/src/knowledge/service/server.js +10 -1
  451. package/src/knowledge/store-discovery.js +77 -0
  452. package/src/lib/account-session.js +8 -2
  453. package/src/lib/agent-instructions.js +3 -0
  454. package/src/lib/auth.js +7 -3
  455. package/src/lib/cad/blender.js +42 -3
  456. package/src/lib/cad/d1-project-store.js +43 -0
  457. package/src/lib/cad/discovery.js +616 -0
  458. package/src/lib/cad/docker-executor.js +352 -0
  459. package/src/lib/cad/freecad.js +253 -0
  460. package/src/lib/cad/index.js +40 -0
  461. package/src/lib/cad/openscad.js +198 -0
  462. package/src/lib/cad/project-cli.d.ts +2 -0
  463. package/src/lib/cad/project-cli.js +21 -0
  464. package/src/lib/cad/project-contract.d.ts +3 -0
  465. package/src/lib/cad/project-contract.js +1 -0
  466. package/src/lib/cad/project-recipe.js +30 -0
  467. package/src/lib/cad/project-runtime.d.ts +2 -0
  468. package/src/lib/cad/project-runtime.js +53 -0
  469. package/src/lib/cad/project-store.js +25 -0
  470. package/src/lib/cad/project-workflows.js +31 -0
  471. package/src/lib/cad-docker.js +21 -2
  472. package/src/lib/cli-preferences.js +17 -2
  473. package/src/lib/core-client.js +37 -18
  474. package/src/lib/deploy/local-studio.js +6 -5
  475. package/src/lib/dockerize.js +3 -0
  476. package/src/lib/execution-approvals.js +1 -0
  477. package/src/lib/identity-scaffold.js +4 -1
  478. package/src/lib/knowledge-docker.js +9 -1
  479. package/src/lib/local-sessions.js +124 -34
  480. package/src/lib/local-status.js +35 -14
  481. package/src/lib/project-config.js +9 -0
  482. package/src/lib/provider-credentials.js +136 -32
  483. package/src/lib/scaffold/resolve-cloudflare-account.js +37 -0
  484. package/src/lib/scaffold/wizards/cms.js +2 -8
  485. package/src/lib/scaffold/wizards/worker-api.js +2 -8
  486. package/src/lib/slash-commands.js +10 -2
  487. package/src/local/migrations.js +109 -1
  488. package/src/local/runtime-store.js +31 -5
  489. package/src/local/sqlite.js +36 -1
  490. package/src/local-fs/capability.js +121 -0
  491. package/src/local-fs/freshness.js +75 -0
  492. package/src/local-fs/index.js +385 -0
  493. package/src/local-fs/paths.js +100 -0
  494. package/src/local-pty/server.js +295 -19
  495. package/src/mcp/authority.js +348 -0
  496. package/src/mcp/client-adapters.js +431 -0
  497. package/src/mcp/client.js +172 -0
  498. package/src/mcp/index.js +47 -0
  499. package/src/mcp/telemetry.js +103 -0
  500. package/src/models/ai-access-onboarding.js +112 -0
  501. package/src/models/catalog.js +329 -51
  502. package/src/models/discovery.js +34 -6
  503. package/src/models/index.js +2 -0
  504. package/src/models/inventory-core.js +190 -0
  505. package/src/models/policy.js +20 -0
  506. package/src/plugins/cloudflare.js +103 -0
  507. package/src/plugins/completeful.js +69 -0
  508. package/src/plugins/contracts.js +86 -0
  509. package/src/plugins/index.js +11 -0
  510. package/src/plugins/registry.js +207 -0
  511. package/src/plugins/resource-scope.js +45 -0
  512. package/src/plugins/runtime.js +118 -0
  513. package/src/plugins/vectorize.js +31 -0
  514. package/src/progression/engine.js +171 -0
  515. package/src/progression/index.js +1 -0
  516. package/src/providers/cloudflare-chat.js +1 -1
  517. package/src/providers/gemini-generate-content.js +2 -1
  518. package/src/providers/openai-responses.js +45 -16
  519. package/src/providers/tool-schema.js +85 -0
  520. package/src/repository/index.js +29 -0
  521. package/src/rpc/generated/errors_pb.js +961 -1
  522. package/src/sam/activity/index.js +183 -0
  523. package/src/sam/client.js +252 -0
  524. package/src/sam/decision/calibration.js +109 -0
  525. package/src/sam/decision/confidence.js +126 -0
  526. package/src/sam/decision/evaluate.js +157 -0
  527. package/src/sam/decision/evaluators/deterministic.js +341 -0
  528. package/src/sam/decision/evaluators/heuristic.js +61 -0
  529. package/src/sam/decision/evaluators/select.js +50 -0
  530. package/src/sam/decision/evaluators/semantic.js +149 -0
  531. package/src/sam/decision/hierarchical.js +61 -0
  532. package/src/sam/decision/index.js +53 -0
  533. package/src/sam/decision/policy.js +86 -0
  534. package/src/sam/decision/questions.js +120 -0
  535. package/src/sam/decision/receipt.js +148 -0
  536. package/src/sam/decision/state.js +117 -0
  537. package/src/sam/decision/types.js +22 -0
  538. package/src/sam/decision/validate.js +200 -0
  539. package/src/sam/define.js +51 -0
  540. package/src/sam/index.js +65 -0
  541. package/src/sam/operations/brand-scan.js +62 -0
  542. package/src/sam/operations/cad-blender-inspect.js +36 -0
  543. package/src/sam/operations/codebaseindex-ingest.js +49 -0
  544. package/src/sam/operations/decision-evaluate.js +59 -0
  545. package/src/sam/operations/planning-astar.js +77 -0
  546. package/src/sam/operations/planning-goap.js +60 -0
  547. package/src/sam/operations/repository-inspect.js +72 -0
  548. package/src/sam/operations/security-scan.js +33 -0
  549. package/src/sam/operations/terminal-exec.js +29 -0
  550. package/src/sam/planning/astar.js +311 -0
  551. package/src/sam/planning/goap.js +177 -0
  552. package/src/sam/planning/index.js +21 -0
  553. package/src/sam/planning/state.js +84 -0
  554. package/src/sam/registry.js +48 -0
  555. package/src/sam/result.js +77 -0
  556. package/src/sam/seed.js +44 -0
  557. package/src/sam/types.js +91 -0
  558. package/src/security/local-vault.js +415 -0
  559. package/src/security/process.js +20 -4
  560. package/src/skills/catalog.js +64 -0
  561. package/src/skills/content-resolver.js +124 -0
  562. package/src/skills/hosted-store.js +37 -0
  563. package/src/skills/index.js +29 -64
  564. package/src/skills/interaction.js +102 -0
  565. package/src/skills/local-store.js +228 -0
  566. package/src/skills/manifest.js +104 -0
  567. package/src/skills/metrics.js +31 -0
  568. package/src/skills/registry.js +184 -0
  569. package/src/skills/runtime.js +287 -0
  570. package/src/skills/slash.js +44 -0
  571. package/src/status/actions.js +192 -0
  572. package/src/tools/hydrate.js +5 -1
  573. package/src/tools/index.js +7 -0
  574. package/src/tools/redact.js +64 -0
  575. package/src/tools/registry.js +83 -0
  576. package/src/tools/runtime.js +257 -0
  577. package/src/tools/search.js +21 -8
  578. package/src/ui/ansi.js +117 -3
  579. package/src/ui/cli/activity.js +76 -7
  580. package/src/ui/cli/footer.js +110 -9
  581. package/src/ui/cli/help.js +96 -96
  582. package/src/ui/wireframes.js +166 -0
  583. package/test/account-session.test.mjs +28 -0
  584. package/test/apps-scaffold-contract.test.mjs +16 -1
  585. package/test/capabilities.test.mjs +1 -1
  586. package/test/cli/api-key-env-whoami.test.mjs +129 -0
  587. package/test/cli/codebaseindex-plan-ux.test.mjs +37 -0
  588. package/test/cli/eval-live.test.mjs +219 -0
  589. package/test/cli/go.test.mjs +128 -0
  590. package/test/cli/local-vault-and-provider-setup.test.mjs +268 -0
  591. package/test/cli/mcp-client.test.mjs +245 -0
  592. package/test/cli/runtime-ui.test.mjs +69 -2
  593. package/test/cli/skill-npm-and-env.test.mjs +52 -0
  594. package/test/cli/status-actions.test.mjs +88 -0
  595. package/test/cli/wireframes-go-registry.test.mjs +139 -0
  596. package/test/cloudflare-connector.test.mjs +3 -6
  597. package/test/cloudflare-runtime.test.mjs +8 -1
  598. package/test/context.test.mjs +15 -0
  599. package/test/error-diagnostics.test.mjs +9 -0
  600. package/test/fixtures/cad/courtyard-house.json +208 -0
  601. package/test/go/build-source-identity.test.mjs +31 -0
  602. package/test/go/cloudflare-probe.test.mjs +317 -0
  603. package/test/go/distribution.test.mjs +28 -0
  604. package/test/integration/ai-access-onboarding.test.mjs +47 -0
  605. package/test/integration/app-command.test.mjs +55 -0
  606. package/test/integration/cad-discovery.test.mjs +158 -0
  607. package/test/integration/cad-docker-executor.test.mjs +249 -0
  608. package/test/integration/cad-execution.test.mjs +184 -0
  609. package/test/integration/cad-project-app.test.mjs +31 -0
  610. package/test/integration/cad-project-d1.test.mjs +25 -0
  611. package/test/integration/cad-project-native.test.mjs +24 -0
  612. package/test/integration/cad-project-workflow.test.mjs +9 -0
  613. package/test/integration/cad-project.test.mjs +82 -0
  614. package/test/integration/cli-help.test.mjs +5 -1
  615. package/test/integration/cms-site-tenancy-contract.test.mjs +256 -0
  616. package/test/integration/codebaseindex-ingest.test.mjs +166 -0
  617. package/test/integration/core-client.integration.test.mjs +55 -0
  618. package/test/integration/error-runtime-rpc.test.mjs +71 -0
  619. package/test/integration/features-resolve.test.mjs +128 -0
  620. package/test/integration/icon-registry.test.mjs +67 -0
  621. package/test/integration/ingest-discover-models.test.mjs +30 -0
  622. package/test/integration/install-script.test.mjs +110 -0
  623. package/test/integration/inventory-core.test.mjs +53 -0
  624. package/test/integration/local-fs.test.mjs +113 -0
  625. package/test/integration/plugins-cloudflare.integration.test.mjs +28 -0
  626. package/test/integration/provider-env-cli.test.mjs +3 -2
  627. package/test/integration/runtime-migrations.test.mjs +6 -1
  628. package/test/integration/runtime-status.integration.test.mjs +211 -0
  629. package/test/integration/sam-activity-recovery.test.mjs +147 -0
  630. package/test/integration/sam-decision.test.mjs +584 -0
  631. package/test/integration/sam-kernel.test.mjs +99 -0
  632. package/test/integration/sam-planning-astar.test.mjs +279 -0
  633. package/test/integration/scaffold-cloudflare.test.mjs +46 -0
  634. package/test/integration/skill-runtime.test.mjs +240 -0
  635. package/test/integration/storage-architecture.test.mjs +154 -0
  636. package/test/integration/store-discovery.test.mjs +44 -0
  637. package/test/integration/studio-fs-pty-e2e.test.mjs +294 -0
  638. package/test/integration/terminal-exec.integration.test.mjs +86 -0
  639. package/test/integration/tool-runtime.test.mjs +124 -0
  640. package/test/integration/tool-schema.test.mjs +59 -0
  641. package/test/knowledge-service.test.mjs +4 -0
  642. package/test/local-sessions.test.mjs +11 -2
  643. package/test/local-studio-deploy.test.mjs +1 -1
  644. package/test/model-catalog.test.mjs +28 -1
  645. package/test/models.test.mjs +172 -11
  646. package/test/openai-responses.test.mjs +60 -0
  647. package/test/provider-credentials.test.mjs +15 -5
  648. package/test/responses-runner.test.mjs +321 -6
  649. package/test/shell.test.mjs +151 -6
  650. package/test/smoke.mjs +2 -2
  651. package/test/tools-search.test.mjs +33 -0
  652. package/test/unit/website-assets-bindings.test.mjs +60 -0
  653. package/test/whoami-resume.test.mjs +82 -3
  654. package/examples/gorilla-shell/README.md +0 -15
  655. package/src/lib/gorilla-template.js +0 -54
  656. package/templates/gorilla-shell/App.tsx +0 -639
  657. package/templates/gorilla-shell/README.md +0 -34
  658. package/templates/gorilla-shell/index.html +0 -15
  659. package/templates/gorilla-shell/main.jsx +0 -9
  660. package/templates/gorilla-shell/package.json +0 -19
  661. package/templates/gorilla-shell/vite.config.js +0 -21
@@ -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
 
@@ -5,23 +5,83 @@ import { fork } from 'node:child_process';
5
5
  import { DatabaseSync } from 'node:sqlite';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import { fingerprint, validateConfig } from '../config.js';
8
+ import {
9
+ AgentSamError,
10
+ ERROR_CODE,
11
+ ERROR_REASON,
12
+ createErrorEnvelope,
13
+ normalizeError,
14
+ parseError,
15
+ } from '../../errors/index.js';
8
16
 
9
17
  const defaultWorkerPath = fileURLToPath(new URL('./job-worker.js', import.meta.url));
10
18
  const TERMINAL_STATUSES = new Set(['completed', 'failed']);
11
19
 
20
+ function serviceReason(code) {
21
+ switch (code) {
22
+ case ERROR_CODE.UNAUTHENTICATED: return ERROR_REASON.AUTH_INVALID;
23
+ case ERROR_CODE.PERMISSION_DENIED: return ERROR_REASON.PERMISSION_DENIED;
24
+ case ERROR_CODE.NOT_FOUND: return ERROR_REASON.TARGET_NOT_FOUND;
25
+ case ERROR_CODE.ABORTED: return ERROR_REASON.CONFLICT;
26
+ case ERROR_CODE.RESOURCE_EXHAUSTED: return ERROR_REASON.CAPACITY_EXHAUSTED;
27
+ case ERROR_CODE.UNAVAILABLE: return ERROR_REASON.TRANSPORT_UNREACHABLE;
28
+ case ERROR_CODE.DEADLINE_EXCEEDED: return ERROR_REASON.DEADLINE_EXCEEDED;
29
+ case ERROR_CODE.INVALID_ARGUMENT: return ERROR_REASON.INPUT_INVALID;
30
+ default: return ERROR_REASON.INTERNAL;
31
+ }
32
+ }
33
+
12
34
  export function serviceError(status, message, code) {
13
- return Object.assign(new Error(message), { status, code });
35
+ const canonical = code === 'CONFLICT' ? ERROR_CODE.ABORTED : (Object.values(ERROR_CODE).includes(code) ? code : ERROR_CODE.INTERNAL);
36
+ const envelope = createErrorEnvelope({
37
+ code: canonical,
38
+ reason: serviceReason(canonical),
39
+ message,
40
+ http_status: status,
41
+ retryable: [429, 503, 504].includes(Number(status)),
42
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_engine' },
43
+ resolution_owner: canonical === ERROR_CODE.UNAVAILABLE ? 'agentsam' : undefined,
44
+ domain: 'knowledge',
45
+ stage: 'request',
46
+ });
47
+ return new AgentSamError(envelope);
48
+ }
49
+
50
+ function decodeFailure(row) {
51
+ if (row?.failure_json) {
52
+ try { return parseError(row.failure_json); }
53
+ catch {
54
+ return createErrorEnvelope({
55
+ reason: ERROR_REASON.INTERNAL_CONTRACT_VIOLATION,
56
+ message: 'Stored knowledge failure could not be decoded.',
57
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_engine' },
58
+ domain: 'knowledge',
59
+ stage: 'persistence',
60
+ });
61
+ }
62
+ }
63
+ if (!row?.error) return null;
64
+ return createErrorEnvelope({
65
+ reason: ERROR_REASON.EXECUTION_FAILED,
66
+ message: row.error,
67
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'legacy_job_row' },
68
+ domain: 'knowledge',
69
+ stage: 'execute',
70
+ });
14
71
  }
15
72
 
16
73
  function decode(row) {
17
- return row && {
74
+ if (!row) return null;
75
+ const failure = decodeFailure(row);
76
+ return {
18
77
  id: row.id,
19
78
  status: row.status,
20
79
  attempts: row.attempts,
21
80
  created_at: row.created_at,
22
81
  updated_at: row.updated_at,
23
82
  result: row.result ? JSON.parse(row.result) : null,
24
- error: row.error,
83
+ failure,
84
+ error: failure?.message || row.error || null,
25
85
  };
26
86
  }
27
87
 
@@ -100,10 +160,22 @@ export function createKnowledgeJobEngine({
100
160
  db.exec(`PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;
101
161
  CREATE TABLE IF NOT EXISTS jobs (id TEXT PRIMARY KEY, idem TEXT UNIQUE, digest TEXT NOT NULL,
102
162
  payload TEXT NOT NULL, status TEXT NOT NULL, attempts INTEGER NOT NULL DEFAULT 0,
103
- created_at TEXT NOT NULL, updated_at TEXT NOT NULL, result TEXT, error TEXT);
163
+ created_at TEXT NOT NULL, updated_at TEXT NOT NULL, result TEXT, error TEXT, failure_json TEXT);
104
164
  CREATE INDEX IF NOT EXISTS jobs_pending ON jobs(status, created_at);`);
165
+ const columns = new Set(db.prepare('PRAGMA table_info(jobs)').all().map(row => row.name));
166
+ if (!columns.has('failure_json')) db.exec('ALTER TABLE jobs ADD COLUMN failure_json TEXT');
105
167
  fs.chmodSync(jobsFile, 0o600);
106
- db.prepare("UPDATE jobs SET status=CASE WHEN attempts>=3 THEN 'failed' ELSE 'queued' END, error=CASE WHEN attempts>=3 THEN 'Interrupted three times; submit a new job after investigation.' ELSE NULL END WHERE status='running'").run();
168
+ const interruptedFailure = createErrorEnvelope({
169
+ reason: ERROR_REASON.EXECUTION_FAILED,
170
+ message: 'Interrupted three times; submit a new job after investigation.',
171
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_engine' },
172
+ domain: 'knowledge',
173
+ stage: 'recovery',
174
+ });
175
+ db.prepare("UPDATE jobs SET status=CASE WHEN attempts>=3 THEN 'failed' ELSE 'queued' END, error=CASE WHEN attempts>=3 THEN ? ELSE NULL END, failure_json=CASE WHEN attempts>=3 THEN ? ELSE NULL END WHERE status='running'").run(
176
+ interruptedFailure.message,
177
+ JSON.stringify(interruptedFailure),
178
+ );
107
179
 
108
180
  let child = null;
109
181
  let closing = false;
@@ -120,11 +192,17 @@ export function createKnowledgeJobEngine({
120
192
  }
121
193
  if (TERMINAL_STATUSES.has(job.status)) watchers.delete(job.id);
122
194
  };
123
- const updateStatus = (id, status, { result = null, error = null } = {}) => {
124
- db.prepare('UPDATE jobs SET status=?,result=?,error=?,updated_at=? WHERE id=?').run(
195
+ const updateStatus = (id, status, { result = null, failure = null, error = null } = {}) => {
196
+ const normalizedFailure = failure
197
+ ? normalizeError(failure, { source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_engine' }, domain: 'knowledge', stage: 'execute' })
198
+ : error
199
+ ? createErrorEnvelope({ reason: ERROR_REASON.EXECUTION_FAILED, message: error, source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_engine' }, domain: 'knowledge', stage: 'execute' })
200
+ : null;
201
+ db.prepare('UPDATE jobs SET status=?,result=?,error=?,failure_json=?,updated_at=? WHERE id=?').run(
125
202
  status,
126
203
  result === null ? null : JSON.stringify(result),
127
- error,
204
+ normalizedFailure?.message || null,
205
+ normalizedFailure ? JSON.stringify(normalizedFailure) : null,
128
206
  new Date().toISOString(),
129
207
  id,
130
208
  );
@@ -145,15 +223,49 @@ export function createKnowledgeJobEngine({
145
223
  child = fork(workerPath, [], { execArgv: [], stdio: ['ignore', 'ignore', 'ignore', 'ipc'], env: { ...process.env, GIT_OPTIONAL_LOCKS: '0' } });
146
224
  const timer = setTimeout(() => { timedOut = true; child?.kill('SIGKILL'); }, jobTimeoutMs);
147
225
  child.once('message', value => { response = value; });
148
- child.once('error', () => { response = { ok: false, error: 'Could not start indexing process.' }; });
226
+ child.once('error', (cause) => {
227
+ response = {
228
+ ok: false,
229
+ failure: createErrorEnvelope({
230
+ reason: ERROR_REASON.INTERNAL_DEPENDENCY_FAILED,
231
+ message: 'Could not start indexing process.',
232
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_worker' },
233
+ domain: 'knowledge',
234
+ stage: 'spawn',
235
+ native: { code: cause?.code || null, exception_type: cause?.name || null, stack: cause?.stack || null },
236
+ }),
237
+ };
238
+ });
149
239
  child.once('close', () => {
150
240
  clearTimeout(timer);
151
241
  child = null;
152
242
  if (!closing) {
153
243
  const ok = response?.ok && !timedOut;
244
+ let failure = null;
245
+ if (!ok) {
246
+ if (timedOut) {
247
+ failure = createErrorEnvelope({
248
+ reason: ERROR_REASON.EXECUTION_TIMEOUT,
249
+ message: 'Knowledge job exceeded its time limit; narrow the scope and retry.',
250
+ source: { kind: 'runtime', name: 'agentsam-knowledge-worker' },
251
+ domain: 'knowledge',
252
+ stage: 'execute',
253
+ });
254
+ } else if (response?.failure) {
255
+ failure = normalizeError(response.failure, { source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_worker' }, domain: 'knowledge', stage: 'execute' });
256
+ } else {
257
+ failure = createErrorEnvelope({
258
+ reason: ERROR_REASON.EXECUTION_FAILED,
259
+ message: response?.error || 'Indexing process exited unexpectedly.',
260
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_worker' },
261
+ domain: 'knowledge',
262
+ stage: 'execute',
263
+ });
264
+ }
265
+ }
154
266
  updateStatus(row.id, ok ? 'completed' : 'failed', {
155
267
  result: ok ? response.result : null,
156
- error: ok ? null : timedOut ? 'Job exceeded its time limit; narrow the scope.' : response?.error || 'Indexing process exited unexpectedly.',
268
+ failure,
157
269
  });
158
270
  }
159
271
  pumping = false;
@@ -162,7 +274,17 @@ export function createKnowledgeJobEngine({
162
274
  const payload = JSON.parse(row.payload);
163
275
  const registered = registry[payload.request.repository];
164
276
  if (!registered || registered.config.repository_id !== payload.config.repository_id || fingerprint(registered.config.scope) !== payload.registered_scope || (!allowEmbeddings && ((payload.request.embed && payload.request.operation !== 'plan') || payload.request.semantic))) {
165
- response = { ok: false, error: 'Repository registration changed; resubmit this job.' };
277
+ response = {
278
+ ok: false,
279
+ failure: createErrorEnvelope({
280
+ reason: ERROR_REASON.REPOSITORY_CHANGED,
281
+ message: 'Repository registration changed; resubmit this job.',
282
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'repository_registry' },
283
+ domain: 'repository',
284
+ stage: 'execute',
285
+ resource: { type: 'repository', id: payload.config.repository_id || null },
286
+ }),
287
+ };
166
288
  child.kill();
167
289
  return;
168
290
  }
@@ -3,12 +3,27 @@ import { openSqliteStore } from '../stores/sqlite.js';
3
3
  import { createGeminiEmbedder } from '../providers/gemini.js';
4
4
  import { inventory } from '../source.js';
5
5
  import { scopeKey } from '../config.js';
6
+ import {
7
+ AgentSamError,
8
+ ERROR_REASON,
9
+ createErrorEnvelope,
10
+ normalizeError,
11
+ } from '../../errors/index.js';
6
12
 
7
13
  // Parsing and vector ranking run in a child process, keeping HTTP acceptance responsive.
8
14
  process.once('message', async ({ root, config, filename, request, maxFiles }) => {
9
15
  let store;
10
16
  try {
11
- if (request.operation !== 'search' && inventory(root, config.scope).length > maxFiles) throw new Error(`Scope exceeds ${maxFiles} files; choose a smaller include set.`);
17
+ if (request.operation !== 'search' && inventory(root, config.scope).length > maxFiles) throw new AgentSamError(createErrorEnvelope({
18
+ reason: ERROR_REASON.INPUT_OUT_OF_RANGE,
19
+ message: `Scope exceeds ${maxFiles} files; choose a smaller include set.`,
20
+ source: { kind: 'user', name: 'knowledge_request' },
21
+ resolution_owner: 'user',
22
+ domain: 'knowledge',
23
+ stage: 'inventory',
24
+ remediation: { action: 'reduce_scope', message: 'Narrow the repository include scope and retry.' },
25
+ resource: { type: 'repository', id: config.repository_id || null },
26
+ }));
12
27
  store = await openSqliteStore(filename);
13
28
  const embedder = request.operation !== 'plan' && (request.embed || request.semantic) ? createGeminiEmbedder({ apiKey: process.env.GEMINI_API_KEY }) : undefined;
14
29
  let result;
@@ -18,7 +33,15 @@ process.once('message', async ({ root, config, filename, request, maxFiles }) =>
18
33
  const generation = request.generation_id ? await store.getGeneration(scopeKey(config), request.generation_id) : await store.active(scopeKey(config));
19
34
  const under = (file, selection) => selection === '.' || file === selection || file.startsWith(selection + '/');
20
35
  if (generation?.files.some(file => !config.scope.include.some(p => under(file.path, p)) || config.scope.exclude.some(p => under(file.path, p)))) {
21
- throw new Error('Generation exceeds the requested scope; select a matching scope or reindex.');
36
+ throw new AgentSamError(createErrorEnvelope({
37
+ reason: ERROR_REASON.PRECONDITION_FAILED,
38
+ message: 'Generation exceeds the requested scope; select a matching scope or reindex.',
39
+ source: { kind: 'user', name: 'knowledge_request' },
40
+ domain: 'knowledge',
41
+ stage: 'search',
42
+ remediation: { action: 'change_configuration', message: 'Select a matching indexed scope or reindex the requested scope.' },
43
+ resource: { type: 'repository', id: config.repository_id || null },
44
+ }));
22
45
  }
23
46
  result = await retrieve({ store, config, text: request.query, semantic: request.semantic, embedder,
24
47
  topK: request.top_k, tokenBudget: request.token_budget, generationId: request.generation_id });
@@ -27,8 +50,14 @@ process.once('message', async ({ root, config, filename, request, maxFiles }) =>
27
50
  process.send({ ok: true, result }, () => process.exit(0));
28
51
  } catch (error) {
29
52
  await store?.close();
30
- // Provider error strings may include sensitive request details. Never persist them.
31
- const message = request.embed || request.semantic ? 'Embedding job failed; check provider configuration, budgets, and availability.' : String(error.message).slice(0, 500);
32
- process.send({ ok: false, error: message }, () => process.exit(1));
53
+ const failure = normalizeError(error, {
54
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'job_worker' },
55
+ domain: 'knowledge',
56
+ stage: request.embed || request.semantic ? 'embedding' : request.operation || 'execute',
57
+ message: request.embed || request.semantic
58
+ ? 'Embedding job failed; inspect the canonical failure for provider/configuration details.'
59
+ : undefined,
60
+ });
61
+ process.send({ ok: false, failure }, () => process.exit(1));
33
62
  }
34
63
  });
@@ -4,6 +4,7 @@ import path from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { createBearerTokenVerifier } from './auth.js';
6
6
  import { createKnowledgeJobEngine, serviceError } from './job-engine.js';
7
+ import { normalizeError, toHttpError } from '../../errors/index.js';
7
8
 
8
9
  async function readBody(req) {
9
10
  const chunks = [];
@@ -44,7 +45,15 @@ export async function startKnowledgeHttpServer({ engine, token, verifyToken, por
44
45
  const { job, created } = engine.submitJob(await readBody(req), { idempotencyKey: req.headers['idempotency-key'] });
45
46
  return send(created ? 202 : 200, job);
46
47
  } catch (error) {
47
- if (!res.writableEnded) send(error.status || 500, { error: error.status ? error.message : 'Service request failed.' });
48
+ if (!res.writableEnded) {
49
+ const envelope = normalizeError(error, {
50
+ source: { kind: 'agentsam', name: 'agentsam-knowledge', service: 'http_server' },
51
+ domain: 'knowledge',
52
+ stage: 'request',
53
+ });
54
+ const httpError = toHttpError(envelope);
55
+ send(httpError.status, httpError.body);
56
+ }
48
57
  }
49
58
  });
50
59
  server.requestTimeout = 15000;
@@ -0,0 +1,77 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { CONFIG_PATH, readConfig, validateConfig, defaultConfig } from './config.js';
4
+ import { findCliProjectRoot } from '../lib/cli-preferences.js';
5
+ import { runtimeDatabasePath } from '../local/runtime-store.js';
6
+ import { getRepositoryId, portableRepositoryIdFromGit, tryReadProjectConfig } from '../lib/project-config.js';
7
+
8
+ // Configuration evidence only. No connection probes, credential reads, or schema writes.
9
+ export async function discoverProjectStores(cwd, env = process.env) {
10
+ const root = findCliProjectRoot(cwd);
11
+ const config = fs.existsSync(path.join(root, CONFIG_PATH)) ? readConfig(root) : null;
12
+ const candidates = [
13
+ { id: 'runtime:sqlite', driver: 'sqlite', role: 'runtime', path: runtimeDatabasePath(root), selected: true },
14
+ { id: 'knowledge:sqlite', driver: 'sqlite', role: 'knowledge', path: path.join(root, '.agentsam/knowledge/index.sqlite'), selected: !config || config.storage.driver === 'sqlite', selectable: true },
15
+ ];
16
+ const envNames = new Set(['AGENTSAM_DATABASE_URL', 'DATABASE_URL', 'POSTGRES_URL', config?.storage?.connection_env].filter(Boolean));
17
+ for (const name of envNames) {
18
+ if (!Object.hasOwn(env, name) && name !== config?.storage?.connection_env) continue;
19
+ candidates.push({ id: `knowledge:postgres:${name}`, driver: 'postgres', role: 'knowledge', connection_env: name, configured: Boolean(env[name]), selected: config?.storage?.driver === 'postgres' && config.storage.connection_env === name, selectable: true });
20
+ }
21
+ const warnings = [];
22
+ let visited = 0;
23
+ const skip = new Set(['node_modules', '.git', '.agentsam', '.output', 'dist', 'build', 'vendor', '.wrangler']);
24
+ const configs = [];
25
+ function scan(dir, depth) {
26
+ if (depth > 5 || visited >= 4000) return;
27
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
28
+ if (++visited >= 4000) break;
29
+ if (entry.isSymbolicLink() || skip.has(entry.name)) continue;
30
+ const file = path.join(dir, entry.name);
31
+ if (entry.isDirectory()) scan(file, depth + 1);
32
+ else if (['wrangler.json', 'wrangler.jsonc'].includes(entry.name)) configs.push(file);
33
+ else if (entry.name === 'wrangler.toml') warnings.push(`${path.relative(root, file)}: TOML discovery is not implemented; inspect this configuration explicitly.`);
34
+ }
35
+ }
36
+ scan(root, 0);
37
+ if (visited >= 4000) warnings.push('Discovery reached its 4000-entry bound; inspect additional config paths explicitly.');
38
+ if (configs.length) {
39
+ const { parseConfigFileTextToJson } = await import('typescript');
40
+ for (const file of configs) {
41
+ const source = path.relative(root, file);
42
+ if (fs.statSync(file).size > 1024 * 1024) { warnings.push(`${source}: configuration too large`); continue; }
43
+ const parsed = parseConfigFileTextToJson(file, fs.readFileSync(file, 'utf8'));
44
+ if (parsed.error) { warnings.push(`${source}: invalid JSONC`); continue; }
45
+ const add = (cfg, environment = null) => {
46
+ for (const [key, driver, label] of [['d1_databases', 'd1', 'database_name'], ['hyperdrive', 'postgres-hyperdrive', 'id'], ['r2_buckets', 'r2', 'bucket_name']]) {
47
+ for (const binding of Array.isArray(cfg?.[key]) ? cfg[key] : []) {
48
+ candidates.push({ id: `${source}:${environment || 'default'}:${binding.binding}`, driver, role: 'application', binding: binding.binding, name: binding[label], source, environment, selectable: false, status: 'declared; connectivity not verified' });
49
+ }
50
+ }
51
+ };
52
+ add(parsed.config);
53
+ for (const [environment, cfg] of Object.entries(parsed.config?.env || {})) add(cfg, environment);
54
+ }
55
+ }
56
+ return { root, candidates, warnings, knowledge_config: CONFIG_PATH };
57
+ }
58
+
59
+ export function selectKnowledgeStore(cwd, driver, connectionEnv) {
60
+ const root = findCliProjectRoot(cwd);
61
+ if (!['sqlite', 'postgres'].includes(driver)) throw new Error('knowledge_store_adapter_unavailable: choose sqlite or postgres; D1 application bindings retain their existing authority');
62
+ const filename = path.join(root, CONFIG_PATH);
63
+ let config;
64
+ if (fs.existsSync(filename)) config = readConfig(root);
65
+ else {
66
+ const repositoryId = getRepositoryId(tryReadProjectConfig(root)) || portableRepositoryIdFromGit(root);
67
+ if (!repositoryId) throw new Error('repository_identity_required: run agentsam init . --yes first');
68
+ config = defaultConfig({ repositoryId });
69
+ }
70
+ config.storage = driver === 'sqlite' ? { driver } : { driver, connection_env: connectionEnv || 'AGENTSAM_DATABASE_URL' };
71
+ config = validateConfig(config);
72
+ fs.mkdirSync(path.dirname(filename), { recursive: true, mode: 0o700 });
73
+ const temp = `${filename}.${process.pid}.tmp`;
74
+ fs.writeFileSync(temp, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
75
+ fs.renameSync(temp, filename);
76
+ return { storage: config.storage, config: CONFIG_PATH, next: driver === 'sqlite' ? 'agentsam index run' : 'agentsam index setup-store', note: 'Selection saved. Existing data remains in its original store; no migration or connection probe ran.' };
77
+ }