@inneranimalmedia/agentsam-sdk 2.6.7 → 2.6.9

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 (371) hide show
  1. package/README.md +37 -0
  2. package/apps/README.md +25 -0
  3. package/apps/cad-creator/shared/cad/package.json +1 -1
  4. package/apps/client-cms-editor/backend/package.json +4 -6
  5. package/apps/client-cms-editor/frontend/package.json +6 -8
  6. package/apps/client-cms-editor/frontend/tsconfig.json +27 -8
  7. package/apps/client-cms-editor/package.json +1 -1
  8. package/apps/client-cms-editor/shared/cms/package.json +4 -6
  9. package/docs/LOCAL_ENGINE_COMPUTE_AUDIT_PLAN.md +299 -0
  10. package/docs/REPO_FILE_MAP.txt +132 -0
  11. package/migrations/d1/0018_goap_control_plane_remaster.sql +40 -0
  12. package/migrations/d1/0019_agentsam_agent_run_plan_todo.sql +14 -0
  13. package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +20 -9
  14. package/migrations/runtime/0002_goap_blackboard_v1.sql +15 -0
  15. package/migrations/runtime/0004_agent_run_plan_linkage.sql +8 -0
  16. package/native/agentsam-machine/cli/Cargo.toml +8 -1
  17. package/native/agentsam-machine/cli/README.md +21 -0
  18. package/native/agentsam-machine/core/Cargo.toml +7 -0
  19. package/native/agentsam-machine/core/README.md +14 -0
  20. package/native/agentsam-machine/core/build.rs +33 -0
  21. package/native/agentsam-machine/core/contracts/source-types.v1.json +353 -0
  22. package/native/agentsam-machine/core/src/lib.rs +6 -0
  23. package/native/agentsam-machine/core/src/source_types.rs +2 -2
  24. package/package.json +31 -10
  25. package/packages/agentsam-brand/package.json +1 -1
  26. package/packages/agentsam-contracts/package.json +71 -20
  27. package/packages/agentsam-contracts/scripts/build.mjs +18 -0
  28. package/packages/agentsam-contracts/test/contracts.test.mjs +4 -1
  29. package/packages/agentsam-contracts/test/repository.test.mjs +4 -1
  30. package/packages/agentsam-contracts/tsconfig.build.json +10 -0
  31. package/packages/agentsam-errors/package.json +3 -2
  32. package/packages/agentsam-errors/src/index.js +1 -0
  33. package/packages/agentsam-errors/src/tool.js +56 -0
  34. package/packages/agentsam-errors/test/tool.test.mjs +58 -0
  35. package/packages/agentsam-goap/README.md +52 -0
  36. package/packages/agentsam-goap/package.json +37 -0
  37. package/packages/agentsam-goap/src/adapters/d1-sqlite.js +570 -0
  38. package/packages/agentsam-goap/src/adapters/memory.js +199 -0
  39. package/packages/agentsam-goap/src/contracts.js +226 -0
  40. package/packages/agentsam-goap/src/control-plane.js +112 -0
  41. package/packages/agentsam-goap/src/errors.js +157 -0
  42. package/packages/agentsam-goap/src/index.js +5 -0
  43. package/packages/agentsam-goap/src/world.js +202 -0
  44. package/packages/agentsam-goap/test/goap-control-plane.test.mjs +245 -0
  45. package/packages/agentsam-goap/test/world.test.mjs +79 -0
  46. package/packages/agentsam-knowledge/package.json +3 -2
  47. package/packages/agentsam-nav/package.json +1 -1
  48. package/packages/agentsam-queue-control/package.json +1 -1
  49. package/packages/agentsam-rapid-rust/src/main.rs +1 -0
  50. package/packages/agentsam-repository/package.json +3 -2
  51. package/packages/agentsam-repository/src/goap.js +13 -14
  52. package/packages/agentsam-repository/src/tickets.js +15 -22
  53. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +19 -8
  54. package/packages/agentsam-vault/package.json +8 -5
  55. package/packages/agentsam-workbench/package.json +44 -17
  56. package/packages/connectors/cloudflare/package.json +4 -2
  57. package/packages/heuristic-theme/package.json +1 -1
  58. package/packages/identity/package.json +4 -3
  59. package/packages/identity/tests/lane1-packed-consumer.test.mjs +10 -2
  60. package/packages/providers/completeful/package.json +1 -1
  61. package/packages/theme-church-site/README.md +2 -2
  62. package/packages/theme-church-site/package.json +3 -4
  63. package/packages/theme-church-site/src/index.js +1 -1
  64. package/packages/theme-church-site/test/theme.test.mjs +1 -1
  65. package/packages/theme-companions-site/README.md +2 -2
  66. package/packages/theme-companions-site/package.json +3 -4
  67. package/packages/theme-companions-site/src/index.js +1 -1
  68. package/packages/theme-companions-site/test/theme.test.mjs +1 -1
  69. package/packages/theme-floors-site/README.md +2 -2
  70. package/packages/theme-floors-site/package.json +3 -4
  71. package/packages/theme-floors-site/src/index.js +1 -1
  72. package/packages/theme-floors-site/test/theme.test.mjs +1 -1
  73. package/packages/theme-fuelnfree-site/README.md +2 -2
  74. package/packages/theme-fuelnfree-site/package.json +3 -4
  75. package/packages/theme-fuelnfree-site/src/index.js +1 -1
  76. package/packages/theme-fuelnfree-site/test/theme.test.mjs +1 -1
  77. package/packages/theme-handyman-site/README.md +2 -2
  78. package/packages/theme-handyman-site/package.json +3 -4
  79. package/packages/theme-handyman-site/src/index.js +1 -1
  80. package/packages/theme-handyman-site/test/theme.test.mjs +1 -1
  81. package/packages/theme-insurance-site/README.md +2 -2
  82. package/packages/theme-insurance-site/package.json +3 -4
  83. package/packages/theme-insurance-site/src/index.js +1 -1
  84. package/packages/theme-insurance-site/test/theme.test.mjs +1 -1
  85. package/packages/theme-scenes/package.json +1 -1
  86. package/packages/theme-shinshu-site/README.md +2 -2
  87. package/packages/theme-shinshu-site/package.json +3 -4
  88. package/packages/theme-shinshu-site/src/index.js +1 -1
  89. package/packages/theme-shinshu-site/test/theme.test.mjs +1 -1
  90. package/packages/work-graph/package.json +3 -2
  91. package/protocol/local-engine/benchmark.v1.schema.json +14 -0
  92. package/protocol/local-engine/engine.v1.schema.json +17 -0
  93. package/python/agentsam_sdk/repository/intelligence/discovery.py +27 -2
  94. package/python/agentsam_sdk/repository/intelligence/git.py +4 -0
  95. package/python/tests/test_repository_intelligence.py +30 -0
  96. package/src/cli/command-catalog.js +3 -1
  97. package/src/cli.js +20 -1
  98. package/src/commands/app.js +10 -0
  99. package/src/commands/engine.js +10 -0
  100. package/src/commands/goap-world.js +134 -0
  101. package/src/commands/goap.js +11 -4
  102. package/src/commands/machine-binary.js +33 -27
  103. package/src/commands/machine-runtime.js +266 -0
  104. package/src/commands/machine.js +155 -51
  105. package/src/commands/package.js +537 -0
  106. package/src/commands/plan-ledger.js +370 -0
  107. package/src/commands/plan.js +183 -0
  108. package/src/commands/runtime.js +25 -10
  109. package/src/commands/setup.js +30 -6
  110. package/src/commands/skill.js +78 -17
  111. package/src/commands/terminal.js +20 -8
  112. package/src/errors/contract.js +4 -4
  113. package/src/errors/diagnostic.js +1 -1
  114. package/src/errors/index.js +1 -1
  115. package/src/index.js +20 -0
  116. package/src/indexing/ingest/materials.js +237 -30
  117. package/src/knowledge/source.js +1 -1
  118. package/src/lib/setup/runtime.js +4 -2
  119. package/src/lib/slash-commands.js +1 -1
  120. package/src/local/runtime-store.js +24 -2
  121. package/src/local/sqlite.js +17 -0
  122. package/src/local-engine/assets.js +37 -0
  123. package/src/local-engine/audit.js +133 -0
  124. package/src/local-engine/benchmark.js +26 -0
  125. package/src/local-engine/contracts.js +101 -0
  126. package/src/local-engine/engines.js +142 -0
  127. package/src/local-engine/index.js +18 -0
  128. package/src/local-engine/runtime.js +39 -0
  129. package/src/sam/operations/package-audit.js +41 -0
  130. package/src/sam/seed.js +2 -0
  131. package/skills/grok-auth/SKILL.md +0 -110
  132. package/skills/grok-auth/agentsam.skill.json +0 -25
  133. package/skills/grok-auth/references/grok-identity.md +0 -64
  134. package/skills/grok-auth/references/per-user-data.md +0 -49
  135. package/skills/grok-auth/references/prewired-and-env.md +0 -54
  136. package/skills/grok-auth/references/session-ui.md +0 -133
  137. package/skills/grok-auth/references/sign-in-methods.md +0 -55
  138. package/skills/grok-auth/references/wiring.md +0 -71
  139. package/skills/grok-building-games/SKILL.md +0 -213
  140. package/skills/grok-building-games/agentsam.skill.json +0 -25
  141. package/skills/grok-building-games/references/3d-libs.md +0 -64
  142. package/skills/grok-building-games/references/ai-pathfinding.md +0 -122
  143. package/skills/grok-building-games/references/audio.md +0 -129
  144. package/skills/grok-building-games/references/babylon.md +0 -202
  145. package/skills/grok-building-games/references/collision-physics.md +0 -122
  146. package/skills/grok-building-games/references/ecs-architecture.md +0 -111
  147. package/skills/grok-building-games/references/game-feel-juice.md +0 -110
  148. package/skills/grok-building-games/references/genres/board-card-chess.md +0 -89
  149. package/skills/grok-building-games/references/genres/endless-runner.md +0 -83
  150. package/skills/grok-building-games/references/genres/fps.md +0 -105
  151. package/skills/grok-building-games/references/genres/platformer-2d.md +0 -97
  152. package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +0 -131
  153. package/skills/grok-building-games/references/genres/racing-kart.md +0 -106
  154. package/skills/grok-building-games/references/genres/topdown-twin-stick.md +0 -97
  155. package/skills/grok-building-games/references/genres/tower-defense.md +0 -84
  156. package/skills/grok-building-games/references/genres/voxel-minecraft.md +0 -89
  157. package/skills/grok-building-games/references/input.md +0 -139
  158. package/skills/grok-building-games/references/phaser.md +0 -277
  159. package/skills/grok-building-games/references/procedural-generation.md +0 -141
  160. package/skills/grok-building-games/references/save-persistence.md +0 -108
  161. package/skills/grok-building-games/references/threejs-foundational.md +0 -148
  162. package/skills/grok-controls/SKILL.md +0 -274
  163. package/skills/grok-controls/agentsam.skill.json +0 -25
  164. package/skills/grok-design-ui/SKILL.md +0 -122
  165. package/skills/grok-design-ui/agentsam.skill.json +0 -25
  166. package/skills/grok-design-ui/references/animations.md +0 -379
  167. package/skills/grok-design-ui/references/performance.md +0 -88
  168. package/skills/grok-design-ui/references/refined-ui.md +0 -384
  169. package/skills/grok-design-ui/references/surfaces.md +0 -247
  170. package/skills/grok-design-ui/references/typography.md +0 -123
  171. package/skills/grok-game-animation-frames/SKILL.md +0 -84
  172. package/skills/grok-game-animation-frames/agentsam.skill.json +0 -25
  173. package/skills/grok-game-asset-core/SKILL.md +0 -69
  174. package/skills/grok-game-asset-core/agentsam.skill.json +0 -25
  175. package/skills/grok-game-character-consistency/SKILL.md +0 -69
  176. package/skills/grok-game-character-consistency/agentsam.skill.json +0 -25
  177. package/skills/grok-game-tilesets/SKILL.md +0 -65
  178. package/skills/grok-game-tilesets/agentsam.skill.json +0 -25
  179. package/skills/grok-game-ui-icons/SKILL.md +0 -56
  180. package/skills/grok-game-ui-icons/agentsam.skill.json +0 -25
  181. package/skills/grok-generate2dmap/LICENSE +0 -21
  182. package/skills/grok-generate2dmap/SKILL.md +0 -120
  183. package/skills/grok-generate2dmap/SOURCE.md +0 -6
  184. package/skills/grok-generate2dmap/agentsam.skill.json +0 -25
  185. package/skills/grok-generate2dmap/references/deliverables.md +0 -101
  186. package/skills/grok-generate2dmap/references/layered-map-contract.md +0 -209
  187. package/skills/grok-generate2dmap/references/map-strategies.md +0 -341
  188. package/skills/grok-generate2dmap/references/object-production-gate.md +0 -24
  189. package/skills/grok-generate2dmap/references/pipeline.md +0 -149
  190. package/skills/grok-generate2dmap/references/prop-pack-contract.md +0 -174
  191. package/skills/grok-generate2dmap/references/side-scroll-stages.md +0 -29
  192. package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +0 -157
  193. package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +0 -369
  194. package/skills/grok-generate2dsprite/LICENSE +0 -21
  195. package/skills/grok-generate2dsprite/SKILL.md +0 -313
  196. package/skills/grok-generate2dsprite/SOURCE.md +0 -6
  197. package/skills/grok-generate2dsprite/agentsam.skill.json +0 -25
  198. package/skills/grok-generate2dsprite/references/modes.md +0 -124
  199. package/skills/grok-generate2dsprite/references/prompt-rules.md +0 -315
  200. package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +0 -1031
  201. package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +0 -109
  202. package/skills/grok-imagine/SKILL.md +0 -201
  203. package/skills/grok-imagine/agentsam.skill.json +0 -25
  204. package/skills/grok-multiplayer-p2p/SKILL.md +0 -111
  205. package/skills/grok-multiplayer-p2p/agentsam.skill.json +0 -25
  206. package/skills/grok-multiplayer-p2p/references/react-binding.md +0 -144
  207. package/skills/grok-multiplayer-p2p/references/signaling-relay.md +0 -269
  208. package/skills/grok-neon/SKILL.md +0 -157
  209. package/skills/grok-neon/agentsam.skill.json +0 -25
  210. package/skills/grok-og/SKILL.md +0 -102
  211. package/skills/grok-og/agentsam.skill.json +0 -25
  212. package/skills/grok-og/references/brand-pass.md +0 -53
  213. package/skills/grok-og/references/custom-card.md +0 -107
  214. package/skills/grok-og/references/favicon-and-icons.md +0 -48
  215. package/skills/grok-og/references/og-type-contract.md +0 -18
  216. package/skills/grok-og/references/placeholder-card.md +0 -21
  217. package/skills/grok-og/references/x-banner.md +0 -41
  218. package/skills/grok-threejs/SKILL.md +0 -67
  219. package/skills/grok-threejs/agentsam.skill.json +0 -25
  220. package/skills/grok-threejs/references/llms-full.txt +0 -2780
  221. package/skills/grok-video2dsprite/LICENSE +0 -21
  222. package/skills/grok-video2dsprite/SKILL.md +0 -236
  223. package/skills/grok-video2dsprite/SOURCE.md +0 -6
  224. package/skills/grok-video2dsprite/agentsam.skill.json +0 -25
  225. package/skills/grok-video2dsprite/references/pipeline.md +0 -90
  226. package/skills/grok-video2dsprite/references/prompt-rules.md +0 -63
  227. package/skills/grok-video2dsprite/scripts/video2dsprite.py +0 -490
  228. package/skills/grok-xai-api/SKILL.md +0 -152
  229. package/skills/grok-xai-api/agentsam.skill.json +0 -25
  230. package/test/account-session.test.mjs +0 -101
  231. package/test/agent-capabilities.test.mjs +0 -67
  232. package/test/app-authority-context.test.mjs +0 -32
  233. package/test/app-building-skills.test.mjs +0 -61
  234. package/test/apps-scaffold-contract.test.mjs +0 -115
  235. package/test/blender-cad.test.mjs +0 -146
  236. package/test/cad-docker.test.mjs +0 -96
  237. package/test/capabilities.test.mjs +0 -133
  238. package/test/cli/api-key-env-whoami.test.mjs +0 -129
  239. package/test/cli/catalog-authority.test.mjs +0 -64
  240. package/test/cli/codebaseindex-plan-ux.test.mjs +0 -37
  241. package/test/cli/eval-live.test.mjs +0 -219
  242. package/test/cli/go.test.mjs +0 -128
  243. package/test/cli/local-vault-and-provider-setup.test.mjs +0 -268
  244. package/test/cli/machine-command.test.mjs +0 -34
  245. package/test/cli/mcp-client.test.mjs +0 -256
  246. package/test/cli/preferences-runtime.test.mjs +0 -11
  247. package/test/cli/runtime-persist.test.mjs +0 -56
  248. package/test/cli/runtime-ui.test.mjs +0 -141
  249. package/test/cli/rust-command.test.mjs +0 -21
  250. package/test/cli/skill-npm-and-env.test.mjs +0 -52
  251. package/test/cli/status-actions.test.mjs +0 -88
  252. package/test/cli/wireframes-go-registry.test.mjs +0 -139
  253. package/test/cli-preferences.test.mjs +0 -46
  254. package/test/cloudflare-connector.test.mjs +0 -93
  255. package/test/cloudflare-runtime.test.mjs +0 -82
  256. package/test/context.test.mjs +0 -159
  257. package/test/credentials-audit.test.mjs +0 -113
  258. package/test/deploy-health-scan.test.mjs +0 -95
  259. package/test/deploy-receipt.test.mjs +0 -91
  260. package/test/dockerize.test.mjs +0 -93
  261. package/test/error-diagnostics.test.mjs +0 -124
  262. package/test/eval-context.test.mjs +0 -37
  263. package/test/execution-approvals.test.mjs +0 -27
  264. package/test/fixtures/cad/courtyard-house.json +0 -208
  265. package/test/fixtures/knowledge-rpc-worker.mjs +0 -16
  266. package/test/fixtures/project-authority/customer-app/.agentsam/app.json +0 -5
  267. package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +0 -1
  268. package/test/fixtures/project-authority/customer-app/wrangler.toml +0 -17
  269. package/test/gcloud-auth.test.mjs +0 -111
  270. package/test/go/build-source-identity.test.mjs +0 -31
  271. package/test/go/cloudflare-probe.test.mjs +0 -317
  272. package/test/go/distribution.test.mjs +0 -28
  273. package/test/google-cloud-connection.test.mjs +0 -83
  274. package/test/google-cloud-inventory.test.mjs +0 -64
  275. package/test/indexing-provider.test.mjs +0 -29
  276. package/test/init-options.test.mjs +0 -35
  277. package/test/integration/ai-access-onboarding.test.mjs +0 -47
  278. package/test/integration/app-command.test.mjs +0 -85
  279. package/test/integration/autorag-project-authority.integration.test.mjs +0 -51
  280. package/test/integration/autorag-runtime-discovery.test.mjs +0 -107
  281. package/test/integration/cad-discovery.test.mjs +0 -158
  282. package/test/integration/cad-docker-executor.test.mjs +0 -249
  283. package/test/integration/cad-execution.test.mjs +0 -184
  284. package/test/integration/cad-project-app.test.mjs +0 -31
  285. package/test/integration/cad-project-d1.test.mjs +0 -25
  286. package/test/integration/cad-project-native.test.mjs +0 -24
  287. package/test/integration/cad-project-workflow.test.mjs +0 -9
  288. package/test/integration/cad-project.test.mjs +0 -85
  289. package/test/integration/cli-help.test.mjs +0 -41
  290. package/test/integration/cms-app-scaffold.test.mjs +0 -77
  291. package/test/integration/cms-site-tenancy-contract.test.mjs +0 -268
  292. package/test/integration/codebaseindex-ingest.test.mjs +0 -255
  293. package/test/integration/core-client.integration.test.mjs +0 -55
  294. package/test/integration/database-hosted-honesty.test.mjs +0 -49
  295. package/test/integration/desktop-keychain-boundary.test.mjs +0 -45
  296. package/test/integration/error-runtime-rpc.test.mjs +0 -71
  297. package/test/integration/features-resolve.test.mjs +0 -147
  298. package/test/integration/hosted-work-host-authority.test.mjs +0 -47
  299. package/test/integration/icon-registry.test.mjs +0 -67
  300. package/test/integration/ingest-discover-models.test.mjs +0 -30
  301. package/test/integration/inspect-path-cli.test.mjs +0 -46
  302. package/test/integration/install-script.test.mjs +0 -110
  303. package/test/integration/inventory-core.test.mjs +0 -53
  304. package/test/integration/inventory-eligibility.test.mjs +0 -59
  305. package/test/integration/inventory-evidence.test.mjs +0 -125
  306. package/test/integration/knowledge-rpc.test.mjs +0 -112
  307. package/test/integration/local-fs.test.mjs +0 -113
  308. package/test/integration/local-provider-bridge.test.mjs +0 -65
  309. package/test/integration/local-studio-settings-production.test.mjs +0 -40
  310. package/test/integration/lockfile-sync.test.mjs +0 -26
  311. package/test/integration/merkle-cli.test.mjs +0 -61
  312. package/test/integration/merkle-persistence-identity.test.mjs +0 -48
  313. package/test/integration/plugins-cloudflare.integration.test.mjs +0 -28
  314. package/test/integration/provider-env-cli.test.mjs +0 -60
  315. package/test/integration/provider-factory.test.mjs +0 -197
  316. package/test/integration/repository-company-graph.test.mjs +0 -90
  317. package/test/integration/runtime-migrations.test.mjs +0 -87
  318. package/test/integration/runtime-status.integration.test.mjs +0 -227
  319. package/test/integration/sam-activity-recovery.test.mjs +0 -147
  320. package/test/integration/sam-decision.test.mjs +0 -584
  321. package/test/integration/sam-kernel.test.mjs +0 -99
  322. package/test/integration/sam-planning-astar.test.mjs +0 -279
  323. package/test/integration/scaffold-cloudflare.test.mjs +0 -46
  324. package/test/integration/skill-runtime.test.mjs +0 -240
  325. package/test/integration/storage-architecture.test.mjs +0 -154
  326. package/test/integration/store-discovery.test.mjs +0 -44
  327. package/test/integration/studio-fs-pty-e2e.test.mjs +0 -294
  328. package/test/integration/terminal-exec.integration.test.mjs +0 -86
  329. package/test/integration/theme-package-registry.test.mjs +0 -31
  330. package/test/integration/tool-runtime.test.mjs +0 -124
  331. package/test/integration/tool-schema.test.mjs +0 -59
  332. package/test/jr-dev-skill.test.mjs +0 -26
  333. package/test/knowledge-context-pack.test.mjs +0 -19
  334. package/test/knowledge-postgres.test.mjs +0 -40
  335. package/test/knowledge-service.test.mjs +0 -110
  336. package/test/knowledge.test.mjs +0 -206
  337. package/test/live/terminal-transport.live.test.mjs +0 -24
  338. package/test/local-sessions.test.mjs +0 -57
  339. package/test/local-studio-deploy.test.mjs +0 -83
  340. package/test/loopback-oauth.test.mjs +0 -53
  341. package/test/merkle-render.test.mjs +0 -31
  342. package/test/mini.test.mjs +0 -140
  343. package/test/model-catalog.test.mjs +0 -70
  344. package/test/models.test.mjs +0 -309
  345. package/test/npm10-lock.test.mjs +0 -29
  346. package/test/ollama.test.mjs +0 -137
  347. package/test/open-url.test.mjs +0 -64
  348. package/test/openai-responses.test.mjs +0 -155
  349. package/test/portable-context.test.mjs +0 -94
  350. package/test/project-config.test.mjs +0 -81
  351. package/test/project-rules.test.mjs +0 -44
  352. package/test/provider-credentials.test.mjs +0 -106
  353. package/test/rehydrate.test.mjs +0 -25
  354. package/test/release-hygiene.test.mjs +0 -42
  355. package/test/repository-snapshot-view.test.mjs +0 -112
  356. package/test/responses-runner.test.mjs +0 -465
  357. package/test/runtime-activity.test.mjs +0 -98
  358. package/test/sdk-worker-contract.test.mjs +0 -72
  359. package/test/security.test.mjs +0 -266
  360. package/test/setup-planner.test.mjs +0 -74
  361. package/test/setup-runtime.test.mjs +0 -51
  362. package/test/shell.test.mjs +0 -281
  363. package/test/skills.test.mjs +0 -22
  364. package/test/smoke.mjs +0 -122
  365. package/test/telemetry.test.mjs +0 -79
  366. package/test/terminal/local-pty.mock.test.mjs +0 -153
  367. package/test/terminal-machine-identity.test.mjs +0 -88
  368. package/test/theme-portability.test.mjs +0 -14
  369. package/test/tools-search.test.mjs +0 -73
  370. package/test/unit/website-assets-bindings.test.mjs +0 -60
  371. package/test/whoami-resume.test.mjs +0 -157
@@ -1,124 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import test from 'node:test';
3
-
4
- import {
5
- createToolExecutor,
6
- createToolRegistry,
7
- } from '../../src/tools/index.js';
8
- import {
9
- COMPLETEFUL_TOOL_DEFINITIONS,
10
- createCompletefulClient,
11
- createCompletefulProviderAdapter,
12
- } from '../../packages/providers/completeful/src/index.js';
13
-
14
- test('tool runtime owns idempotency, redacts durable receipts, and emits safe events', async () => {
15
- let captured = null;
16
- const client = createCompletefulClient({
17
- apiKey: 'capp_test_example',
18
- fetchImpl: async (url, init) => {
19
- captured = { url, init };
20
- return new Response(
21
- JSON.stringify({
22
- id: 'ord_1',
23
- email: 'customer@example.com',
24
- shipping_address: { line1: 'private street' },
25
- notes: 'private note',
26
- }),
27
- { status: 201, headers: { 'x-request-id': 'req_order_1' } },
28
- );
29
- },
30
- });
31
-
32
- const registry = createToolRegistry({
33
- tools: COMPLETEFUL_TOOL_DEFINITIONS,
34
- adapters: [createCompletefulProviderAdapter(client)],
35
- });
36
-
37
- const recorded = [];
38
- const observed = [];
39
- let sequence = 0;
40
- const executor = createToolExecutor({
41
- registry,
42
- makeId: (prefix) => `${prefix}_test_${++sequence}`,
43
- now: (() => {
44
- let value = 1_800_000_000_000;
45
- return () => ++value;
46
- })(),
47
- recordReceipt: (receipt) => recorded.push(receipt),
48
- onEvent: (event) => observed.push(event),
49
- });
50
-
51
- const result = await executor.execute({
52
- toolKey: 'completeful.order.create',
53
- accountId: 'acct_1',
54
- correlationId: 'corr_1',
55
- input: {
56
- shop_id: 'shop_1',
57
- body: {
58
- shipping_address: { line1: 'private street' },
59
- email: 'customer@example.com',
60
- notes: 'private note',
61
- line_items: [{ product_id: 'prod_1', quantity: 1 }],
62
- },
63
- },
64
- });
65
-
66
- assert.equal(result.ok, true);
67
- assert.equal(result.output.email, 'customer@example.com');
68
- assert.equal(captured.init.headers.get('Idempotency-Key'), result.invocation.id);
69
- assert.equal(result.receipt.input.body.email, '[REDACTED]');
70
- assert.equal(result.receipt.input.body.shipping_address, '[REDACTED]');
71
- assert.equal(result.receipt.output.email, '[REDACTED]');
72
- assert.equal(result.receipt.output.shipping_address, '[REDACTED]');
73
- assert.equal(recorded.length, 1);
74
- assert.equal(observed.length, 1);
75
- assert.equal(observed[0].eventKey, 'completeful.order.created');
76
- assert.equal(observed[0].payload.output.email, '[REDACTED]');
77
- assert.equal(observed[0].causationId, result.invocation.id);
78
- assert.equal(observed[0].correlationId, 'corr_1');
79
- });
80
-
81
- test('tool runtime converts provider errors into the canonical AgentSam envelope', async () => {
82
- const client = createCompletefulClient({
83
- apiKey: 'capp_test_example',
84
- fetchImpl: async () =>
85
- new Response(
86
- JSON.stringify({
87
- error: 'too many requests',
88
- code: 'rate_limited',
89
- request_id: 'req_rate',
90
- }),
91
- { status: 429 },
92
- ),
93
- });
94
-
95
- const registry = createToolRegistry({
96
- tools: COMPLETEFUL_TOOL_DEFINITIONS,
97
- adapters: [createCompletefulProviderAdapter(client)],
98
- });
99
- const executor = createToolExecutor({
100
- registry,
101
- makeId: (prefix) => `${prefix}_failure`,
102
- });
103
-
104
- const result = await executor.execute({
105
- toolKey: 'completeful.catalog.list',
106
- input: { limit: 1 },
107
- });
108
-
109
- assert.equal(result.ok, false);
110
- assert.equal(result.error.reason, 'provider_rate_limited');
111
- assert.equal(result.error.code, 'RESOURCE_EXHAUSTED');
112
- assert.equal(result.error.provider, 'completeful');
113
- assert.equal(result.error.provider_code, 'rate_limited');
114
- assert.equal(result.error.request_id, 'req_rate');
115
- assert.equal(result.receipt.status, 'failed');
116
- });
117
-
118
- test('registry rejects duplicate tool keys instead of silently shadowing definitions', () => {
119
- const definition = COMPLETEFUL_TOOL_DEFINITIONS[0];
120
- assert.throws(
121
- () => createToolRegistry({ tools: [definition, definition] }),
122
- /duplicate tool definition/,
123
- );
124
- });
@@ -1,59 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { compileToolSchema, restoreOptionalArguments } from '../../src/providers/tool-schema.js';
4
- import { createCapabilityAdapter } from '../../src/agent/capability-adapter.js';
5
- import { createOpenAIResponsesAdapter } from '../../src/providers/openai-responses.js';
6
- import { createGeminiGenerateContentAdapter } from '../../src/providers/gemini-generate-content.js';
7
-
8
- const canonical = { $schema: 'https://json-schema.org/draft/2020-12/schema', $id: 'sample', type: 'object', properties: {
9
- text: { type: 'string' }, rows: { type: 'array', items: { type: 'object', properties: { label: { type: 'string', enum: ['x'] } } } },
10
- additionalProperties: { type: 'string' },
11
- }, required: ['text'] };
12
-
13
- test('strict compiler recursively closes objects and makes omitted fields nullable without mutating canonical input', () => {
14
- const original = structuredClone(canonical);
15
- const { providerSchema: s } = compileToolSchema({ provider: 'openai', canonicalSchema: canonical });
16
- assert.equal(s.additionalProperties, false);
17
- assert.deepEqual(s.required, ['text', 'rows', 'additionalProperties']);
18
- assert.equal(s.properties.rows.anyOf[0].items.additionalProperties, false);
19
- assert.deepEqual(s.properties.rows.anyOf[0].items.required, ['label']);
20
- assert.deepEqual(s.properties.rows.anyOf[0].items.properties.label.anyOf, [{ type: 'string', enum: ['x'] }, { type: 'null' }]);
21
- assert.deepEqual(canonical, original);
22
- assert.deepEqual(restoreOptionalArguments({ text: 'x', rows: [{ label: null }], additionalProperties: null }, canonical), { text: 'x', rows: [{}] });
23
- });
24
-
25
- test('all executable capability schemas compile for both providers, including actual knowledge.search arguments', () => {
26
- for (const descriptor of createCapabilityAdapter().toolDescriptors()) {
27
- for (const provider of ['openai', 'gemini']) assert.ok(compileToolSchema({ provider, canonicalSchema: descriptor.input_schema, strict: descriptor.strict !== false, name: descriptor.name }).hash);
28
- if (descriptor.name === 'knowledge.search') assert.equal(descriptor.input_schema.properties.text.type, 'string');
29
- }
30
- });
31
-
32
- test('bad schemas fail before provider fetch, with actionable paths', async () => {
33
- for (const schema of [
34
- { type: 'object', properties: {}, required: ['missing'] },
35
- { type: 'object', properties: { x: { $ref: 'https://remote/schema' } } },
36
- { type: 'object', properties: { x: { type: 'array' } } },
37
- { type: 'object', properties: { x: { type: 'invalid' } } },
38
- ]) {
39
- let requests = 0;
40
- const adapter = createOpenAIResponsesAdapter({ apiKey: 'test', fetchImpl: async () => { requests++; } });
41
- await assert.rejects(adapter.create({ model: 'gpt-6-astra', input: 'test', tools: [{ type: 'function', name: 'broken', parameters: schema }] }), /tool_schema_invalid:openai:broken:/);
42
- assert.equal(requests, 0);
43
- }
44
- });
45
-
46
- test('Gemini uses JSON Schema declaration field and preserves canonical optionality', async () => {
47
- let body;
48
- const adapter = createGeminiGenerateContentAdapter({ apiKey: 'test', fetchImpl: async (_, init) => {
49
- body = JSON.parse(init.body);
50
- return { ok: true, json: async () => ({ candidates: [{ content: { role: 'model', parts: [{ text: 'ok' }] } }] }) };
51
- } });
52
- await adapter.create({ modelRecord: { provider: 'gemini', provider_model_id: 'fixture' }, input: 'test', tools: [{ name: 'sample', parameters: canonical }] });
53
- const declaration = body.tools[0].functionDeclarations[0];
54
- assert.equal(declaration.parameters, undefined);
55
- assert.equal(declaration.parametersJsonSchema.$schema, undefined);
56
- assert.equal(declaration.parametersJsonSchema.$id, undefined);
57
- assert.deepEqual(declaration.parametersJsonSchema.required, ['text']);
58
- assert.equal(declaration.parametersJsonSchema.properties.additionalProperties.type, 'string');
59
- });
@@ -1,26 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import test from 'node:test';
5
-
6
- const root = path.resolve(import.meta.dirname, '..');
7
- const skill = path.join(root, 'skills', 'agentsam-jr-dev', 'SKILL.md');
8
- const fundamentals = path.join(root, 'skills', 'agentsam-jr-dev', 'references', 'web-application-fundamentals.md');
9
- const logic = path.join(root, 'skills', 'agentsam-jr-dev', 'references', 'real-application-logic.md');
10
-
11
- test('agentsam-jr-dev ships as a portable skill with depth references', () => {
12
- for (const file of [skill, fundamentals, logic]) {
13
- assert.equal(fs.existsSync(file), true, `${file} must exist`);
14
- }
15
-
16
- const text = fs.readFileSync(skill, 'utf8');
17
- assert.match(text, /name: agentsam-jr-dev/);
18
- assert.match(text, /Inspect before teaching repo-specific facts/);
19
- assert.match(text, /Real application logic is the standard/);
20
- assert.match(text, /Never invent a repo architecture/);
21
- assert.match(text, /frontend owns presentation/);
22
- assert.match(text, /backend owns trusted execution/);
23
-
24
- const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
25
- assert.ok(pkg.files.includes('skills'), 'root npm package must include portable skills');
26
- });
@@ -1,19 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import test from 'node:test';
3
- import { createContextPack } from '../src/knowledge/context-pack.js';
4
-
5
- test('knowledge ContextPack includes a measurable selection receipt', () => {
6
- const pack = createContextPack({
7
- queryId: 'q1',
8
- query: { text: 'where is auth?', top_k: 2, token_budget: 2000 },
9
- hits: [{ ref: 'file:a', content: 'abcd' }, { ref: 'file:b', content: '12345678' }],
10
- diagnostics: { sources_considered: 7, sources_deferred: 5 },
11
- });
12
- assert.deepEqual(pack.receipt, {
13
- chars: 12,
14
- estimated_tokens: 3,
15
- sources_considered: 7,
16
- sources_included: 2,
17
- sources_deferred: 5,
18
- });
19
- });
@@ -1,40 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import fs from 'node:fs';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import { PGlite } from '@electric-sql/pglite';
7
- import { vector } from '@electric-sql/pglite-pgvector';
8
- import { createPostgresStore, defaultConfig, runIndex, retrieve, scopeKey } from '../src/knowledge/index.js';
9
-
10
- test('real Postgres/pgvector schema, exact retrieval, profile isolation and publication rollback', async t => {
11
- const db = new PGlite({ extensions: { vector } });
12
- // PGlite exposes the same parameterized SQL execution; exec supports DDL batches.
13
- const store = createPostgresStore({ query: (sql, params) => params ? db.query(sql, params) : db.exec(sql).then(results => results.at(-1)), end: () => db.close() });
14
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-pg-'));
15
- t.after(async () => { await store.close(); fs.rmSync(root, { recursive: true, force: true }); });
16
- await store.setup(); await store.setup();
17
- fs.writeFileSync(path.join(root, 'math.ts'), 'export function add(a: number, b: number) { return a + b; }\nexport const name = "math";');
18
- const config = defaultConfig();
19
- config.embedding = { provider: 'fixture', model: 'vector-test', revision: '1', dimensions: 3, parameters: {} };
20
- const embedder = { async embed(text) { return text.includes('add') ? [1, 0, 0] : [0, 1, 0]; } };
21
- const first = await runIndex({ root, config, store, embedder, embed: true });
22
- const result = await retrieve({ config, store, embedder, text: 'add', semantic: true });
23
- assert.equal(result.hits[0].metadata.symbol, 'add'); assert.equal(result.hits[0].score, 1);
24
- assert.equal((await db.query('SELECT count(*)::int AS n FROM agentsam_knowledge.cache WHERE embedding IS NOT NULL')).rows[0].n, 2);
25
- assert.equal((await runIndex({ root, config, store, embedder, embed: true })).embedding_inputs, 0);
26
- // A different-dimensional profile in the same table must not break retrieval.
27
- await store.cachePut('foreign:vector:other', [1, 0, 0, 0]);
28
- assert.equal((await retrieve({ config, store, embedder, text: 'add', semantic: true })).hits[0].score, 1);
29
- const generation = await store.active(scopeKey(config));
30
- await assert.rejects(store.publish({ ...generation, id: 'bad-cas' }, 'wrong-parent'), /concurrently/);
31
- assert.equal((await store.active(scopeKey(config))).id, first.generation_id);
32
- // Force SQL failure after the CAS check; the old generation remains visible.
33
- await assert.rejects(store.publish(generation, generation.id), /duplicate key/);
34
- assert.equal((await store.active(scopeKey(config))).id, first.generation_id);
35
- assert.equal((await store.history(scopeKey(config))).length, 1);
36
- const observation = { id: 'obs-1', created_at: new Date().toISOString(), data: { files: 1 } };
37
- await store.observe('customer', observation);
38
- assert.deepEqual(await store.observations('customer'), [observation]);
39
- assert.deepEqual(await store.observations('another-customer'), []);
40
- });
@@ -1,110 +0,0 @@
1
- import { test } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import fs from 'node:fs';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import { DatabaseSync } from 'node:sqlite';
7
- import { defaultConfig } from '../src/knowledge/config.js';
8
- import { startKnowledgeService } from '../src/knowledge/service/server.js';
9
- import { createKnowledgeServiceClient } from '../src/knowledge/service/client.js';
10
- import { dockerize } from '../src/lib/dockerize.js';
11
-
12
- async function completed(client, id) {
13
- for (let i = 0; i < 200; i++) {
14
- const job = await client.job(id);
15
- if (['completed', 'failed'].includes(job.status)) { assert.equal(job.status, 'completed', job.error); return job; }
16
- await new Promise(resolve => setTimeout(resolve, 25));
17
- }
18
- throw new Error('Job did not complete.');
19
- }
20
-
21
- test('service isolates scopes, authenticates, deduplicates, indexes, searches, and preserves restart state', async () => {
22
- const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-service-'));
23
- const root = path.join(tmp, 'repo'), stateDir = path.join(tmp, 'state');
24
- fs.mkdirSync(path.join(root, 'src'), { recursive: true });
25
- fs.writeFileSync(path.join(root, 'src/math.ts'), 'export function add(a: number,b: number) { return a+b; }\n');
26
- fs.writeFileSync(path.join(root, '.env.json'), '{"password":"must-not-index"}');
27
- const before = fs.readFileSync(path.join(root, 'src/math.ts'), 'utf8');
28
- const token = 't'.repeat(64), repositories = { sample: { root, config: defaultConfig({ include: ['src'] }) } };
29
- let service;
30
- try {
31
- service = await startKnowledgeService({ stateDir, repositories, token, port: 0, maxFiles: 1 });
32
- let baseUrl = `http://127.0.0.1:${service.address.port}`;
33
- let client = createKnowledgeServiceClient({ baseUrl, token });
34
- assert.equal((await fetch(baseUrl + '/healthz')).status, 200);
35
- assert.equal((await fetch(baseUrl + '/v1/repositories')).status, 401);
36
- await assert.rejects(client.submit({ repository: 'missing', operation: 'index' }), e => e.status === 404);
37
- await assert.rejects(client.submit({ repository: 'sample', operation: 'index', include: ['.'] }), e => e.status === 403);
38
- await assert.rejects(client.submit({ repository: 'sample', operation: 'index', include: ['../'] }), e => e.status === 400);
39
- await assert.rejects(client.submit({ repository: 'sample', operation: 'index', embed: true }), e => e.status === 403);
40
- const request = { repository: 'sample', operation: 'index' };
41
- const submitted = await client.submit(request, 'first');
42
- assert.equal((await client.submit(request, 'first')).id, submitted.id);
43
- await assert.rejects(client.submit({ ...request, scope: 'other' }, 'first'), e => e.status === 409);
44
- const first = await completed(client, submitted.id);
45
- assert.equal(first.result.files, 1); assert.equal(first.result.embedding_inputs, 0);
46
- assert.equal(first.result.published, true);
47
- const second = await completed(client, (await client.submit(request)).id);
48
- assert.equal(second.result.no_change, true); assert.equal(second.result.parsed_files, 0);
49
- assert.equal(second.result.generation_id, first.result.generation_id);
50
- fs.writeFileSync(path.join(root, 'src/unindexed.ts'), 'export const later = true;');
51
- const search = await completed(client, (await client.submit({ repository: 'sample', operation: 'search', query: 'add' })).id);
52
- assert.match(JSON.stringify(search.result), /src\/math.ts/);
53
- const narrow = await client.submit({ repository: 'sample', operation: 'search', query: 'add', include: ['src/unindexed.ts'] });
54
- for (let i = 0; i < 200; i++) {
55
- const job = await client.job(narrow.id);
56
- if (job.status === 'failed') { assert.match(job.error, /exceeds the requested scope/); break; }
57
- if (i === 199) assert.fail('Narrowed scope should fail without leaking broader snapshot contents.');
58
- await new Promise(resolve => setTimeout(resolve, 25));
59
- }
60
- fs.unlinkSync(path.join(root, 'src/unindexed.ts'));
61
- const plan = await completed(client, (await client.submit({ repository: 'sample', operation: 'plan', embed: true })).id);
62
- assert.ok(plan.result.embedding_inputs > 0); // Costs can be estimated without credentials.
63
- await service.close(); service = null;
64
- // Simulate an interrupted persisted job, as happens on SIGKILL/power loss.
65
- const db = new DatabaseSync(path.join(stateDir, 'jobs.sqlite'));
66
- db.prepare("UPDATE jobs SET status='running',result=NULL,attempts=1 WHERE id=?").run(second.id); db.close();
67
- service = await startKnowledgeService({ stateDir, repositories, token, port: 0 });
68
- baseUrl = `http://127.0.0.1:${service.address.port}`;
69
- client = createKnowledgeServiceClient({ baseUrl, token });
70
- assert.equal((await client.job(first.id)).result.generation_id, first.result.generation_id);
71
- const recovered = await completed(client, second.id);
72
- assert.equal(recovered.attempts, 2); assert.equal(recovered.result.no_change, true);
73
- assert.equal(fs.readFileSync(path.join(root, 'src/math.ts'), 'utf8'), before);
74
- assert.equal(fs.existsSync(path.join(root, '.agentsam')), false);
75
- } finally { await service?.close(); fs.rmSync(tmp, { recursive: true, force: true }); }
76
- });
77
-
78
- test('portable dockerize stages only SDK runtime, preserves identities/tokens, and generates persistent loopback config', async () => {
79
- const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-service-docker-'));
80
- const root = path.join(tmp, 'customer'); fs.mkdirSync(root);
81
- fs.writeFileSync(path.join(root, 'customer-secret.js'), 'must not enter build context');
82
- try {
83
- const options = { appSlug: 'knowledge-test', repositories: [`customer=${root}`], writeOnly: true };
84
- const result = await dockerize(tmp, 'knowledge_service', options);
85
- assert.match(result.plan.files.compose, /127\.0\.0\.1:8792:8792/);
86
- assert.match(result.plan.files.compose, /unless-stopped/);
87
- assert.match(result.plan.files.compose, /"read_only":true/);
88
- const context = path.join(result.written.versionDir, 'context');
89
- assert.equal(fs.existsSync(path.join(context, 'customer-secret.js')), false);
90
- assert.equal(fs.existsSync(path.join(context, 'src/knowledge/service/server.js')), true);
91
- assert.equal(fs.existsSync(path.join(context, 'src/knowledge/service/grpc-server.js')), true);
92
- assert.equal(fs.existsSync(path.join(context, 'src/rpc/generated/knowledge_pb.js')), true);
93
- assert.equal(fs.existsSync(path.join(context, 'src/rpc/generated/knowledge_grpc_pb.js')), true);
94
- assert.equal(fs.existsSync(path.join(context, 'src/rpc/generated/package.json')), true);
95
- assert.equal(fs.existsSync(path.join(context, 'src/errors/contract.js')), true);
96
- assert.equal(fs.existsSync(path.join(context, 'packages/agentsam-errors/src/index.js')), true);
97
- assert.equal(fs.existsSync(path.join(context, 'packages/agentsam-errors/package.json')), true);
98
- assert.equal(fs.existsSync(path.join(context, 'packages/agentsam-repository/src/merkle/hash.js')), true);
99
- assert.match(result.plan.files.dockerfile, /COPY packages \.\/packages/);
100
- assert.equal(fs.existsSync(path.join(context, 'package-lock.json')), true);
101
- const token = fs.readFileSync(result.tokenFile, 'utf8');
102
- assert.equal(fs.statSync(result.tokenFile).mode & 0o777, 0o600);
103
- assert.ok(!JSON.stringify(result.plan).includes(token.trim()));
104
- const registry = fs.readFileSync(path.join(result.configurationDir, 'repositories.json'), 'utf8');
105
- await dockerize(tmp, 'knowledge_service', options);
106
- assert.equal(fs.readFileSync(result.tokenFile, 'utf8'), token);
107
- assert.equal(fs.readFileSync(path.join(result.configurationDir, 'repositories.json'), 'utf8'), registry);
108
- await assert.rejects(dockerize(tmp, 'knowledge_service', { ...options, timeoutSeconds: 2 }), /persistent/);
109
- } finally { fs.rmSync(tmp, { recursive: true, force: true }); }
110
- });
@@ -1,206 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import fs from 'node:fs';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import { execFileSync } from 'node:child_process';
7
- import { fileURLToPath } from 'node:url';
8
- import { defaultConfig, initRepository, readConfig, scopeKey, embeddingProfileId, openSqliteStore, runIndex, planIndex, retrieve, createGeminiEmbedder, KnowledgeClient } from '../src/knowledge/index.js';
9
- import { inventory, parseSource } from '../src/knowledge/source.js';
10
-
11
- const cli = fileURLToPath(new URL('../src/cli.js', import.meta.url));
12
- const write = (root, name, content) => { fs.mkdirSync(path.dirname(path.join(root, name)), { recursive: true }); fs.writeFileSync(path.join(root, name), content); };
13
- async function fixture(t) {
14
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-knowledge-'));
15
- execFileSync('git', ['init', '-q'], { cwd: root });
16
- write(root, 'src/a.ts', 'export function alpha() { return 1; }\nexport function beta() { return 2; }\n');
17
- write(root, 'other/b.js', 'export const gamma = 3;\n');
18
- const config = defaultConfig({ include: ['src'] });
19
- config.embedding = { provider: 'fixture', model: 'deterministic', revision: '1', dimensions: 3, parameters: {} };
20
- const store = await openSqliteStore(path.join(root, '.agentsam/knowledge/index.sqlite'));
21
- let calls = 0;
22
- const embedder = { async embed(text) { calls++; return [1, text.includes('alpha') ? 1 : 0, text.length / 100]; } };
23
- t.after(async () => { await store.close(); fs.rmSync(root, { recursive: true, force: true }); });
24
- return { root, config, store, embedder, count: () => calls };
25
- }
26
-
27
- test('AST parser observes real syntax, spans and unresolved edges; text is labeled separately', () => {
28
- const code = `import { read } from './io';\nexport class Reader { value() { return read(); } }\n`;
29
- const parsed = parseSource('reader.ts', code);
30
- assert.ok(parsed.symbols.some(s => s.name === 'Reader.value'));
31
- assert.ok(parsed.edges.some(e => e.kind === 'calls' && e.target === 'read' && e.resolved === false));
32
- assert.equal(parsed.chunks.map(c => c.content).join(''), code.trimEnd());
33
- assert.equal(parseSource('schema.sql', 'select 1;').parser, 'text:1');
34
- assert.throws(() => parseSource('bad.ts', 'export function {'), /bad.ts/);
35
- });
36
-
37
- test('Rust sources survive knowledge inventory and persist in the active SQLite generation', async t => {
38
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-knowledge-rust-'));
39
- execFileSync('git', ['init', '-q'], { cwd: root });
40
- write(root, 'core/src/lib.rs', 'pub fn core_value() -> u32 { 7 }\n');
41
- write(root, 'worker/src/lib.rs', 'pub fn worker_value() -> u32 { 8 }\n');
42
- write(root, 'docs/MACHINE-PIPELINE.md', '# Machine pipeline\n');
43
- write(root, 'target/generated.rs', 'pub fn generated() {}\n');
44
-
45
- const config = defaultConfig({ include: ['core', 'worker', 'docs'], exclude: ['target'] });
46
- const store = await openSqliteStore(path.join(root, '.agentsam/knowledge/index.sqlite'));
47
- t.after(async () => {
48
- await store.close();
49
- fs.rmSync(root, { recursive: true, force: true });
50
- });
51
-
52
- const files = inventory(root, config.scope);
53
- assert.ok(files.includes('core/src/lib.rs'));
54
- assert.ok(files.includes('worker/src/lib.rs'));
55
- assert.ok(files.includes('docs/MACHINE-PIPELINE.md'));
56
- assert.equal(files.includes('target/generated.rs'), false);
57
-
58
- const result = await runIndex({ root, config, store, embed: false });
59
- assert.equal(result.published, true);
60
- assert.ok(result.changes.added.includes('core/src/lib.rs'));
61
- assert.ok(result.changes.added.includes('worker/src/lib.rs'));
62
-
63
- const generation = await store.getGeneration(scopeKey(config), result.generation_id);
64
- const persisted = generation.files.map(file => file.path);
65
- assert.ok(persisted.includes('core/src/lib.rs'));
66
- assert.ok(persisted.includes('worker/src/lib.rs'));
67
- assert.ok(persisted.includes('docs/MACHINE-PIPELINE.md'));
68
- assert.equal(generation.files.find(file => file.path === 'core/src/lib.rs')?.parser, 'text:1');
69
- });
70
-
71
- test('incremental indexing reuses unchanged functions, moves and deletions; old knowledge remains retrievable', async t => {
72
- const f = await fixture(t), args = { ...f, embed: true };
73
- const plan = await planIndex(args);
74
- assert.equal(f.count(), 0); assert.equal(await f.store.active(scopeKey(f.config)), null);
75
- assert.equal(plan.receipt.embedding_inputs, 2);
76
- const first = await runIndex(args);
77
- assert.equal(f.count(), 2);
78
- const again = await runIndex(args);
79
- assert.equal(again.published, false); assert.equal(again.parsed_files, 0); assert.equal(f.count(), 2);
80
- fs.renameSync(path.join(f.root, 'src/a.ts'), path.join(f.root, 'src/moved.ts'));
81
- const moved = await runIndex(args);
82
- assert.equal(moved.embedding_inputs, 0); assert.equal(moved.parsed_files, 0); assert.equal(f.count(), 2);
83
- write(f.root, 'src/moved.ts', 'export function alpha() { return 100; }\nexport function beta() { return 2; }\n');
84
- assert.equal((await runIndex(args)).embedding_inputs, 1); assert.equal(f.count(), 3);
85
- const old = await retrieve({ ...f, text: 'alpha', generationId: first.generation_id });
86
- assert.ok(old.hits.some(h => h.content.includes('return 1;') && h.path === 'src/a.ts' && h.stale));
87
- fs.unlinkSync(path.join(f.root, 'src/moved.ts'));
88
- assert.deepEqual((await runIndex(args)).changes.removed, ['src/moved.ts']);
89
- assert.equal((await retrieve({ ...f, text: 'alpha' })).hits.length, 0);
90
- assert.equal((await f.store.history(scopeKey(f.config))).length, 4);
91
- });
92
-
93
- test('scope and repository isolation; profile changes cannot silently reuse vectors', async t => {
94
- const f = await fixture(t);
95
- await runIndex({ ...f, embed: true });
96
- const other = structuredClone(f.config); other.scope = { name: 'other', include: ['other'], exclude: [] };
97
- await runIndex({ ...f, config: other, embed: true });
98
- assert.equal((await f.store.active(scopeKey(f.config))).files[0].path, 'src/a.ts');
99
- const changed = structuredClone(f.config); changed.embedding.revision = '2';
100
- assert.notEqual(embeddingProfileId(changed.embedding), embeddingProfileId(f.config.embedding));
101
- assert.equal((await planIndex({ ...f, config: changed, embed: true })).receipt.embedding_inputs, 2);
102
- await assert.rejects(retrieve({ ...f, config: changed, text: 'alpha', semantic: true }), /different embedding profile/);
103
- const foreign = structuredClone(f.config); foreign.repository_id = 'another-repo';
104
- assert.equal((await planIndex({ ...f, config: foreign, embed: true })).receipt.embedding_inputs, 2);
105
- const wider = structuredClone(f.config); wider.scope.include.push('other');
106
- assert.equal((await planIndex({ ...f, config: wider, embed: true })).receipt.files, 2);
107
- assert.equal((await planIndex({ ...f, config: wider, embed: true })).receipt.embedding_inputs, 0);
108
- });
109
-
110
- test('budgets, invalid vectors and concurrent changes preserve the active generation and useful cached work', async t => {
111
- const f = await fixture(t);
112
- const initial = await runIndex(f);
113
- await assert.rejects(runIndex({ ...f, embed: true, maxInputs: 0 }), /budget/);
114
- assert.equal(f.count(), 0);
115
- let requests = 0;
116
- await assert.rejects(runIndex({ ...f, embed: true, embedder: { async embed() { if (++requests === 2) throw new Error('503'); return [1, 0, 0]; } } }), /503/);
117
- assert.equal((await f.store.active(scopeKey(f.config))).id, initial.generation_id);
118
- assert.equal((await planIndex({ ...f, embed: true })).receipt.embedding_inputs, 1);
119
- await assert.rejects(runIndex({ ...f, embed: true, embedder: { async embed() { return [NaN]; } } }), /finite values/);
120
- assert.equal((await f.store.active(scopeKey(f.config))).id, initial.generation_id);
121
- const resumed = await runIndex({ ...f, embed: true }); assert.equal(resumed.embedding_inputs, 1);
122
- write(f.root, 'src/a.ts', 'export function alpha() { return 33; }');
123
- await assert.rejects(runIndex({ ...f, embed: true, embedder: { async embed() { write(f.root, 'src/a.ts', 'export function alpha() { return 44; }'); return [1, 0, 0]; } } }), /Repository changed/);
124
- assert.equal((await f.store.active(scopeKey(f.config))).id, resumed.generation_id);
125
- const current = await f.store.active(scopeKey(f.config));
126
- await assert.rejects(f.store.publish({ ...current, id: 'race' }, initial.generation_id), /concurrently/);
127
- assert.equal((await f.store.active(scopeKey(f.config))).id, resumed.generation_id);
128
- });
129
-
130
- test('source safety and setup preserve repository files; read-only plan creates no database', async t => {
131
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-adopt-'));
132
- t.after(() => fs.rmSync(root, { recursive: true, force: true }));
133
- execFileSync('git', ['init', '-q'], { cwd: root });
134
- write(root, 'package.json', '{"name":"keep-this"}\n');
135
- write(root, '.env.js', 'SECRET'); write(root, 'src/real.ts', 'export const real = 1;');
136
- write(root, '.gitignore', 'ignored/\n'); write(root, 'ignored/hidden.ts', 'export const hidden = 1;');
137
- fs.symlinkSync(path.join(root, '.env.js'), path.join(root, 'src/link.ts'));
138
- const initial = fs.readFileSync(path.join(root, 'package.json'), 'utf8');
139
- const output = execFileSync(process.execPath, [cli, 'init', '--yes', '--include', 'src'], { cwd: root, encoding: 'utf8' });
140
- assert.equal(JSON.parse(output).storage, 'sqlite');
141
- assert.equal(fs.readFileSync(path.join(root, 'package.json'), 'utf8'), initial);
142
- assert.throws(() => initRepository(root), /EEXIST/);
143
- const plan = JSON.parse(execFileSync(process.execPath, [cli, 'index', 'plan'], { cwd: root, encoding: 'utf8' }));
144
- assert.equal(plan.files, 1); assert.deepEqual(plan.skipped, ['src/link.ts']);
145
- assert.equal(fs.existsSync(path.join(root, '.agentsam/knowledge/index.sqlite')), false);
146
- const all = readConfig(root); all.scope.include = ['.'];
147
- const paths = (await planIndex({ root, config: all })).files.map(f => f.path);
148
- assert.ok(!paths.includes('.env.js')); assert.ok(!paths.includes('ignored/hidden.ts'));
149
- });
150
-
151
- test('index and search derive safe local defaults when knowledge.json is absent', async t => {
152
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-configless-'));
153
- t.after(() => fs.rmSync(root, { recursive: true, force: true }));
154
- execFileSync('git', ['init', '-q'], { cwd: root });
155
- execFileSync('git', ['remote', 'add', 'origin', 'git@github.com:ExampleOrg/ConfiglessRepo.git'], { cwd: root });
156
- write(root, 'src/real.ts', 'export function configlessSymbol() { return 7; }\n');
157
- const run = args => JSON.parse(execFileSync(process.execPath, [cli, ...args], { cwd: root, encoding: 'utf8' }));
158
- assert.equal(fs.existsSync(path.join(root, '.agentsam/knowledge.json')), false);
159
- const plan = run(['index', 'plan']);
160
- assert.ok(plan.files >= 1); assert.equal(plan.embedding_inputs, 0);
161
- assert.equal(fs.existsSync(path.join(root, '.agentsam/knowledge.json')), false);
162
- assert.equal(run(['index', 'run']).published, true);
163
- assert.equal(fs.existsSync(path.join(root, '.agentsam/knowledge.json')), false);
164
- assert.equal(run(['search', 'configlessSymbol']).hits[0].path, 'src/real.ts');
165
- });
166
-
167
- test('two independent repositories work through the same CLI and exported package', async t => {
168
- for (const name of ['customer-a', 'customer-b']) {
169
- const root = fs.mkdtempSync(path.join(os.tmpdir(), name));
170
- t.after(() => fs.rmSync(root, { recursive: true, force: true }));
171
- write(root, 'lib/tool.js', `export function ${name.replace('-', '_')}() { return 1; }`);
172
- const run = args => JSON.parse(execFileSync(process.execPath, [cli, ...args], { cwd: root, encoding: 'utf8' }));
173
- run(['init', '.', '--yes', '--include', 'lib']);
174
- assert.equal(run(['index', 'run']).published, true);
175
- assert.equal(run(['index', 'run']).no_change, true);
176
- assert.equal(run(['search', name.replace('-', '_')]).hits[0].path, 'lib/tool.js');
177
- }
178
- });
179
-
180
- test('Gemini sends task prefixes and configured dimensions, retries transient responses, and rejects unsupported profiles', async () => {
181
- const requests = [], sleeps = [];
182
- const adapter = createGeminiEmbedder({ apiKey: 'fixture-key', sleep: async ms => sleeps.push(ms), fetchImpl: async (_url, request) => {
183
- requests.push(JSON.parse(request.body));
184
- if (requests.length === 1) return new Response('', { status: 503 });
185
- return Response.json({ embedding: { values: Array(128).fill(0.1) } });
186
- } });
187
- const profile = defaultConfig({ dimensions: 128 }).embedding;
188
- await adapter.embed('function useful() {}', profile);
189
- await adapter.embed('find useful', profile, { kind: 'query' });
190
- assert.equal(requests[1].outputDimensionality, 128);
191
- assert.equal(requests[1].content.parts[0].text, 'title: none | text: function useful() {}');
192
- assert.equal(requests[2].content.parts[0].text, 'task: code retrieval | query: find useful');
193
- assert.equal(requests[1].taskType, undefined); assert.equal(sleeps.length, 1);
194
- await assert.rejects(adapter.embed('x', { ...profile, parameters: { taskType: 'CODE_RETRIEVAL' } }), /Unsupported/);
195
- let tries = 0;
196
- const denied = createGeminiEmbedder({ apiKey: 'fixture-key', fetchImpl: async () => { tries++; return new Response('', { status: 403 }); } });
197
- await assert.rejects(denied.embed('x', profile), /403/); assert.equal(tries, 1);
198
- });
199
-
200
- test('recovered KnowledgeClient contracts remain usable with injected transports', async () => {
201
- const operations = [];
202
- const client = new KnowledgeClient({ transport: { async request(op, payload) { operations.push([op, payload]); return { query_id: 'test', hits: [] }; } } });
203
- await client.retrieve({ text: 'find parser', workspace_id: 'customer' });
204
- await client.index('repository');
205
- assert.equal(operations[0][1].top_k, 8); assert.equal(operations[0][1].token_budget, 6000); assert.equal(operations[0][1].result_policy.max_items, 8); assert.equal(operations[1][0], 'knowledge.index');
206
- });
@@ -1,24 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import test from 'node:test';
3
- import { WebSocket } from 'ws';
4
-
5
- const liveUrl = String(process.env.AGENTSAM_LIVE_TERMINAL_WS_URL || '').trim();
6
-
7
- test('live terminal transport accepts a websocket connection', { skip: !liveUrl }, async (t) => {
8
- const ws = new WebSocket(liveUrl, {
9
- headers: process.env.AGENTSAM_LIVE_TERMINAL_AUTH
10
- ? { authorization: process.env.AGENTSAM_LIVE_TERMINAL_AUTH }
11
- : undefined,
12
- });
13
- t.after(() => { try { ws.close(); } catch {} });
14
-
15
- await Promise.race([
16
- new Promise((resolve, reject) => {
17
- ws.once('open', resolve);
18
- ws.once('error', reject);
19
- }),
20
- new Promise((_, reject) => setTimeout(() => reject(new Error('live terminal websocket open timed out')), 8000)),
21
- ]);
22
-
23
- assert.equal(ws.readyState, WebSocket.OPEN);
24
- });