@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,128 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
- import test from 'node:test';
6
- import { fileURLToPath } from 'node:url';
7
- import { discoverGoRuntime, resolveProductRoot, ensureProductContract, buildGoProduct } from '../../src/go/index.js';
8
- import { runGo } from '../../src/commands/go.js';
9
-
10
- const SDK_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
11
-
12
-
13
- function tempStateRoot() {
14
- return fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-go-test-state-'));
15
- }
16
-
17
- test('discoverGoRuntime finds agentsam-go-worker without inventing a sibling', () => {
18
- const discovery = discoverGoRuntime(SDK_ROOT);
19
- assert.equal(discovery.go.ok, true);
20
- assert.ok(discovery.runtime, 'expected Go runtime');
21
- assert.match(discovery.runtime.module, /agentsam-go-worker/);
22
- assert.equal(path.basename(discovery.runtime.productRoot), 'agentsam-go-worker');
23
- const productRoot = resolveProductRoot(discovery, 'agentsam-go-worker');
24
- const contract = ensureProductContract(productRoot);
25
- assert.equal(contract.product, 'agentsam-go-worker');
26
- assert.equal(contract.existing, true);
27
- assert.deepEqual(contract.created, []);
28
- });
29
-
30
- test('ensureProductContract refuses missing product roots instead of scaffolding siblings', () => {
31
- const missing = path.join(os.tmpdir(), `agentsam-go-missing-${Date.now()}`);
32
- assert.throws(() => ensureProductContract(missing), /product_root_missing/);
33
- });
34
-
35
- test('buildGoProduct emits build receipt after go test/vet/build', () => {
36
- const discovery = discoverGoRuntime(SDK_ROOT);
37
- const productRoot = resolveProductRoot(discovery);
38
- const stateRoot = tempStateRoot();
39
- const result = buildGoProduct({
40
- productRoot,
41
- runtimeRoot: discovery.runtime.runtimeRoot,
42
- repositoryRoot: discovery.repository_root,
43
- stateRoot,
44
- });
45
- assert.equal(result.receipt.schema, 'agentsam.go-build-receipt.v1');
46
- assert.equal(result.tests.ok, true);
47
- assert.equal(result.vet.ok, true);
48
- assert.ok(result.build.binary);
49
- assert.match(result.receipt.artifact.digest, /^sha256:[a-f0-9]{64}$/);
50
- assert.equal(result.receipt.tests.runtime_probe, true);
51
- assert.match(result.receipt.source.identity, /^git:[a-f0-9]{40}$/);
52
- assert.equal(result.probe.checks.source_identity, true);
53
- assert.equal(result.probe.checks.source_commit, true);
54
- assert.equal(result.probe.checks.error_envelope, true);
55
- assert.equal(result.probe.checks.clean_shutdown, true);
56
- assert.ok(fs.existsSync(result.receiptPath));
57
- });
58
-
59
- test('agentsam go build --json exposes only portable build paths', async () => {
60
- const stateRoot = tempStateRoot();
61
- const chunks = [];
62
-
63
- const result = await runGo(
64
- ['build', '--json'],
65
- {
66
- write: (value) => chunks.push(String(value)),
67
- stateRoot,
68
- },
69
- );
70
-
71
- assert.ok(path.isAbsolute(result.receiptPath), 'internal execution keeps absolute receipt path');
72
- assert.ok(path.isAbsolute(result.build.binary), 'internal execution keeps absolute binary path');
73
-
74
- const output = chunks.join('');
75
- const parsed = JSON.parse(output);
76
-
77
- assert.equal(path.isAbsolute(parsed.receiptPath), false);
78
- assert.equal(path.isAbsolute(parsed.build.binary), false);
79
- assert.equal(path.isAbsolute(parsed.receipt.runtime.module_root), false);
80
- assert.equal(Object.hasOwn(parsed.probe || {}, 'origin'), false);
81
- assert.equal(Object.hasOwn(parsed.receipt?.probe || {}, 'origin'), false);
82
- assert.equal(output.includes(SDK_ROOT), false);
83
- });
84
-
85
- test('agentsam go --cloudflare agentsam-go-worker --skip-deploy is idempotent', async () => {
86
- const stateRoot = tempStateRoot();
87
- const chunks = [];
88
- const write = (v) => chunks.push(String(v));
89
- const first = await runGo(
90
- ['--cloudflare', 'agentsam-go-worker', '--skip-deploy', '--json'],
91
- { write, stateRoot },
92
- );
93
- assert.equal(first.ok, true);
94
- assert.equal(first.product, 'agentsam-go-worker');
95
- assert.equal(first.scaffold_changes_required, false);
96
- assert.equal(first.mode, 'self_host');
97
- assert.equal(first.deploy.registry.reason, 'self_host_registry_isolated');
98
-
99
- const chunks2 = [];
100
- const second = await runGo(
101
- ['--cloudflare', 'agentsam-go-worker', '--skip-deploy', '--json'],
102
- {
103
- write: (v) => chunks2.push(String(v)),
104
- stateRoot,
105
- },
106
- );
107
- assert.equal(second.ok, true);
108
- assert.equal(second.existing_product, true);
109
- assert.equal(second.scaffold_changes_required, false);
110
- assert.ok(second.deploy.receiptPath);
111
- assert.ok(fs.existsSync(second.deploy.productPath));
112
- });
113
-
114
- test('agentsam go status --json reports discovery', async () => {
115
- const stateRoot = tempStateRoot();
116
- const chunks = [];
117
- const result = await runGo(
118
- ['status', '--json'],
119
- {
120
- write: (v) => chunks.push(String(v)),
121
- stateRoot,
122
- },
123
- );
124
- assert.equal(result.ok, true);
125
- assert.ok(result.discovery.go.ok);
126
- const parsed = JSON.parse(chunks.join(''));
127
- assert.equal(parsed.product, 'agentsam-go-worker');
128
- });
@@ -1,268 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
- import test from 'node:test';
6
-
7
- import {
8
- getSecureProviderKey,
9
- setSecureProviderKey,
10
- deleteSecureProviderKey,
11
- listSecureConfiguredProviders,
12
- hydrateSecureCredentials,
13
- localVaultPath,
14
- localVaultSaltPath,
15
- } from '../../src/security/local-vault.js';
16
- import { resolveExecutableCommand } from '../../src/security/process.js';
17
- import {
18
- resolveProviderCredential,
19
- setProviderCredential,
20
- removeProviderCredential,
21
- exportProviderEnvProfile,
22
- } from '../../src/lib/provider-credentials.js';
23
- import {
24
- validateAndSaveProviderCredential,
25
- providerChoices,
26
- runProviders,
27
- } from '../../src/commands/providers.js';
28
- import { renderModelsStatus } from '../../src/commands/models.js';
29
-
30
- // picocolors color-detection differs between local runs and CI runners (CI often
31
- // reports TTY-like support that enables ANSI output) - strip escape codes before
32
- // asserting on rendered text content so this test checks content, not incidental
33
- // terminal color state.
34
- // eslint-disable-next-line no-control-regex
35
- const ANSI_PATTERN = /\x1B\[[0-9;]*m/g;
36
- const stripAnsi = (s) => String(s).replace(ANSI_PATTERN, '');
37
-
38
- function createTempHome(t) {
39
- const home = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-vault-test-'));
40
- t.after(() => fs.rmSync(home, { recursive: true, force: true }));
41
- return home;
42
- }
43
-
44
- test('resolveExecutableCommand resolves Windows .cmd shims with shell: true on win32', () => {
45
- const npxWin = resolveExecutableCommand('npx', 'win32');
46
- assert.equal(npxWin.command, 'npx.cmd');
47
- assert.equal(npxWin.shell, true);
48
-
49
- const npmWin = resolveExecutableCommand('npm', 'win32');
50
- assert.equal(npmWin.command, 'npm.cmd');
51
- assert.equal(npmWin.shell, true);
52
-
53
- const wranglerWin = resolveExecutableCommand('wrangler', 'win32');
54
- assert.equal(wranglerWin.command, 'wrangler.cmd');
55
- assert.equal(wranglerWin.shell, true);
56
-
57
- const scriptWin = resolveExecutableCommand('build.bat', 'win32');
58
- assert.equal(scriptWin.command, 'build.bat');
59
- assert.equal(scriptWin.shell, true);
60
-
61
- // Linux and macOS are untouched
62
- const npxMac = resolveExecutableCommand('npx', 'darwin');
63
- assert.equal(npxMac.command, 'npx');
64
- assert.equal(npxMac.shell, false);
65
-
66
- const npmLinux = resolveExecutableCommand('npm', 'linux');
67
- assert.equal(npmLinux.command, 'npm');
68
- assert.equal(npmLinux.shell, false);
69
- });
70
-
71
- test('local vault encrypts with AES-256-GCM and never writes plaintext secrets to disk', (t) => {
72
- const home = createTempHome(t);
73
- const opts = { home, disableOsStore: true };
74
-
75
- const secret = 'sk-proj-testsecret1234567890abcdef';
76
- setSecureProviderKey('openai', secret, opts);
77
-
78
- const retrieved = getSecureProviderKey('openai', opts);
79
- assert.equal(retrieved.value, secret);
80
- assert.equal(retrieved.source, 'local_vault');
81
-
82
- // Verify disk contents
83
- const encFile = localVaultPath(opts);
84
- assert.equal(fs.existsSync(encFile), true);
85
- const rawText = fs.readFileSync(encFile, 'utf8');
86
-
87
- // Plaintext MUST NOT appear anywhere in the file
88
- assert.equal(rawText.includes(secret), false);
89
-
90
- // Must have JSON with iv, tag, and data
91
- const parsed = JSON.parse(rawText);
92
- assert.ok(parsed.secrets.openai.iv);
93
- assert.ok(parsed.secrets.openai.tag);
94
- assert.ok(parsed.secrets.openai.data);
95
-
96
- // Salt file must exist with restrictive permissions
97
- const saltFile = localVaultSaltPath(opts);
98
- assert.equal(fs.existsSync(saltFile), true);
99
- if (process.platform !== 'win32') {
100
- assert.equal(fs.statSync(saltFile).mode & 0o777, 0o600);
101
- assert.equal(fs.statSync(encFile).mode & 0o777, 0o600);
102
- }
103
- });
104
-
105
- test('local vault detects tampering of encrypted ciphertext', (t) => {
106
- const home = createTempHome(t);
107
- const opts = { home, disableOsStore: true };
108
-
109
- setSecureProviderKey('anthropic', 'sk-ant-test-key-12345', opts);
110
-
111
- // Tamper with the ciphertext
112
- const encFile = localVaultPath(opts);
113
- const parsed = JSON.parse(fs.readFileSync(encFile, 'utf8'));
114
- const originalData = parsed.secrets.anthropic.data;
115
- // Flip the last hex byte
116
- const tamperedData = originalData.slice(0, -2) + (originalData.slice(-2) === 'aa' ? 'bb' : 'aa');
117
- parsed.secrets.anthropic.data = tamperedData;
118
- fs.writeFileSync(encFile, JSON.stringify(parsed));
119
-
120
- // Decryption must fail and return null safely rather than corrupt data
121
- const retrieved = getSecureProviderKey('anthropic', opts);
122
- assert.equal(retrieved, null);
123
- });
124
-
125
- test('local vault stores and retrieves Cloudflare accountId alongside token', (t) => {
126
- const home = createTempHome(t);
127
- const opts = { home, disableOsStore: true };
128
-
129
- setSecureProviderKey('cloudflare', { value: 'cf-token-123', accountId: 'abcdef0123456789abcdef0123456789' }, opts);
130
- const retrieved = getSecureProviderKey('cloudflare', opts);
131
-
132
- assert.equal(retrieved.value, 'cf-token-123');
133
- assert.equal(retrieved.accountId, 'abcdef0123456789abcdef0123456789');
134
- });
135
-
136
- test('hydrateSecureCredentials populates process.env for unconfigured providers without overwriting', (t) => {
137
- const home = createTempHome(t);
138
- const opts = { home, disableOsStore: true };
139
-
140
- setSecureProviderKey('gemini', 'gemini-key-val-789', opts);
141
-
142
- const mockEnv = {
143
- EXISTING_KEY: 'pre-existing',
144
- };
145
-
146
- const hydrated = hydrateSecureCredentials(mockEnv, opts);
147
- assert.ok(hydrated.includes('gemini'));
148
- assert.equal(mockEnv.GEMINI_API_KEY, 'gemini-key-val-789');
149
-
150
- // Second run does not overwrite
151
- mockEnv.GEMINI_API_KEY = 'user-override';
152
- hydrateSecureCredentials(mockEnv, opts);
153
- assert.equal(mockEnv.GEMINI_API_KEY, 'user-override');
154
- });
155
-
156
- test('resolveProviderCredential resolves keys from local secure vault across any directory', (t) => {
157
- const home = createTempHome(t);
158
- const opts = { home, disableOsStore: true };
159
-
160
- setProviderCredential('cursor', 'cur-key-secret-456', opts);
161
-
162
- const resolved = resolveProviderCredential('cursor', { env: {}, home, disableOsStore: true });
163
- assert.equal(resolved.configured, true);
164
- assert.equal(resolved.value, 'cur-key-secret-456');
165
-
166
- // Deleting removes it
167
- removeProviderCredential('cursor', opts);
168
- const afterRemove = resolveProviderCredential('cursor', { env: {}, home, disableOsStore: true });
169
- assert.equal(afterRemove.configured, false);
170
- });
171
-
172
- test('validateAndSaveProviderCredential rejects invalid key and does NOT persist it', async (t) => {
173
- const home = createTempHome(t);
174
- const opts = {
175
- home,
176
- disableOsStore: true,
177
- fetchImpl: async () => ({
178
- ok: false,
179
- status: 401,
180
- json: async () => ({ error: { message: 'Incorrect API key provided' } }),
181
- }),
182
- };
183
-
184
- const result = await validateAndSaveProviderCredential('openai', 'sk-invalid-test-key', opts);
185
- assert.equal(result.ok, false);
186
- assert.equal(result.saved, false);
187
- assert.match(result.error, /Incorrect API key/i);
188
-
189
- // Verify it was NOT stored in the vault!
190
- const retrieved = getSecureProviderKey('openai', opts);
191
- assert.equal(retrieved, null);
192
- });
193
-
194
- test('validateAndSaveProviderCredential verifies valid key and saves ONLY to local vault without plaintext file', async (t) => {
195
- const home = createTempHome(t);
196
- const opts = {
197
- home,
198
- disableOsStore: true,
199
- fetchImpl: async () => ({
200
- ok: true,
201
- status: 200,
202
- json: async () => ({
203
- data: [{ id: 'gpt-4o' }, { id: 'gpt-4o-mini' }],
204
- }),
205
- }),
206
- };
207
-
208
- const result = await validateAndSaveProviderCredential('openai', 'sk-valid-key-xyz', opts);
209
- assert.equal(result.ok, true);
210
- assert.equal(result.saved, true);
211
- assert.equal(result.model_count, 2);
212
-
213
- // Verify it was saved to local vault
214
- const retrieved = getSecureProviderKey('openai', opts);
215
- assert.equal(retrieved.value, 'sk-valid-key-xyz');
216
-
217
- // CRITICAL: Plaintext .env profile file MUST NOT be created automatically!
218
- const plaintextFile = path.join(home, '.agentsam', 'env.d', 'openai.env');
219
- assert.equal(fs.existsSync(plaintextFile), false, 'Plaintext .env file must NOT exist after secure provider setup');
220
- });
221
-
222
- test('exportProviderEnvProfile and agentsam providers export create plaintext .env file ONLY on explicit opt-in', async (t) => {
223
- const home = createTempHome(t);
224
- const opts = { home, disableOsStore: true };
225
-
226
- // Set up provider key in secure vault
227
- setProviderCredential('anthropic', 'sk-ant-test-export-key', opts);
228
-
229
- // Confirm NO plaintext file exists yet
230
- const plaintextFile = path.join(home, '.agentsam', 'env.d', 'anthropic.env');
231
- assert.equal(fs.existsSync(plaintextFile), false);
232
-
233
- // Explicit opt-in export via CLI command
234
- let output = '';
235
- const exported = await runProviders(['export', 'anthropic'], {
236
- ...opts,
237
- write: (text) => { output += text; },
238
- });
239
-
240
- assert.equal(exported.provider, 'anthropic');
241
- assert.equal(fs.existsSync(plaintextFile), true);
242
- const content = fs.readFileSync(plaintextFile, 'utf8');
243
- assert.match(content, /ANTHROPIC_API_KEY="sk-ant-test-export-key"/);
244
- assert.match(output, /Exported anthropic profile/);
245
- });
246
-
247
- test('renderModelsStatus shows tip: Select your preferred provider when providers are unconfigured', () => {
248
- const status = {
249
- providers: [
250
- { id: 'openai', label: 'OpenAI', configured: false, credential: 'OPENAI_API_KEY' },
251
- { id: 'anthropic', label: 'Anthropic', configured: false, credential: 'ANTHROPIC_API_KEY' },
252
- ],
253
- discovery: {},
254
- providerModels: {},
255
- local: { online: false, models: [] },
256
- };
257
-
258
- const output = stripAnsi(renderModelsStatus(status));
259
- assert.match(output, /Tip:\s*Select your preferred provider/i);
260
- });
261
-
262
- test('providerChoices returns valid choice list for select picker', () => {
263
- const choices = providerChoices();
264
- assert.ok(choices.length >= 6);
265
- assert.ok(choices.some((c) => c.value === 'openai'));
266
- assert.ok(choices.some((c) => c.value === 'anthropic'));
267
- assert.ok(choices.some((c) => c.value === 'gemini'));
268
- });
@@ -1,34 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
- import { getCliCommand } from '../../src/cli/command-catalog.js';
7
- import { resolveMachineBinary } from '../../src/commands/machine-binary.js';
8
-
9
- const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
10
-
11
- test('machine command is catalogued as machine.inspect', () => {
12
- const entry = getCliCommand('machine');
13
- assert.equal(entry?.id, 'machine');
14
- assert.equal(entry?.operation, 'machine.inspect');
15
- assert.equal(entry?.common, true);
16
- });
17
-
18
- test('machine crate + CLI sources exist for graduation', () => {
19
- assert.equal(fs.existsSync(path.join(root, 'native/agentsam-machine/Cargo.toml')), true);
20
- assert.equal(fs.existsSync(path.join(root, 'native/agentsam-machine/cli/src/main.rs')), true);
21
- assert.equal(fs.existsSync(path.join(root, 'src/commands/machine.js')), true);
22
- assert.equal(fs.existsSync(path.join(root, 'src/commands/machine-binary.js')), true);
23
- });
24
-
25
- test('resolveMachineBinary finds crate binary or cargo fallback in this repo', () => {
26
- const resolution = resolveMachineBinary();
27
- assert.notEqual(resolution.kind, 'missing');
28
- if (resolution.kind === 'binary') {
29
- assert.equal(fs.existsSync(resolution.path), true);
30
- } else {
31
- assert.equal(resolution.kind, 'cargo');
32
- assert.equal(fs.existsSync(resolution.manifest), true);
33
- }
34
- });
@@ -1,256 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
- import test from 'node:test';
6
-
7
- import {
8
- MCP_PRESETS,
9
- deleteMcpServer,
10
- fetchExternalClientRegistry,
11
- fetchMcpServerCatalog,
12
- getClientConfigPath,
13
- getClientRegistryCachePath,
14
- getServerCatalogCachePath,
15
- getSessionToolReceipts,
16
- inspectClientAdapter,
17
- isClientRegistered,
18
- listKnownServers,
19
- listMcpServers,
20
- listRegisteredClients,
21
- readMcpServer,
22
- recordToolReceipt,
23
- removeServerFromClient,
24
- resolveServerPreset,
25
- summarizeToolReceipts,
26
- syncServerToClient,
27
- writeMcpServer,
28
- } from '../../src/mcp/index.js';
29
- import { runMcp } from '../../src/commands/mcp.js';
30
-
31
- function tempHome() {
32
- return fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-mcp-test-'));
33
- }
34
-
35
- test('MCP authority store manages servers under ~/.agentsam/mcp with safe permissions', () => {
36
- const home = tempHome();
37
- const config = {
38
- url: 'https://mcp.inneranimalmedia.com/mcp',
39
- auth: { type: 'bearer', token: 'iam_token_abc' },
40
- clients: ['cursor', 'claude'],
41
- };
42
-
43
- const written = writeMcpServer('inneranimalmedia', config, { home });
44
- assert.equal(written.name, 'inneranimalmedia');
45
- assert.equal(written.url, 'https://mcp.inneranimalmedia.com/mcp');
46
-
47
- const read = readMcpServer('inneranimalmedia', { home });
48
- assert.equal(read.name, 'inneranimalmedia');
49
- assert.equal(read.auth.token, 'iam_token_abc');
50
- assert.deepEqual(read.clients, ['cursor', 'claude']);
51
-
52
- const list = listMcpServers({ home });
53
- assert.equal(list.length, 1);
54
- assert.equal(list[0].name, 'inneranimalmedia');
55
-
56
- const deleted = deleteMcpServer('inneranimalmedia', { home });
57
- assert.equal(deleted, true);
58
- assert.equal(readMcpServer('inneranimalmedia', { home }), null);
59
- });
60
-
61
- test('MCP external client registry recognizes chatgpt, claude, cursor — not CF portals', async () => {
62
- const home = tempHome();
63
-
64
- // Baseline seed / cached client list
65
- const clients = listRegisteredClients({ home });
66
- const keys = clients.map((c) => c.client_key);
67
- assert.ok(keys.includes('chatgpt'), 'ChatGPT is recognized in the external client registry');
68
- assert.ok(keys.includes('cursor'), 'Cursor is recognized in the external client registry');
69
- assert.ok(keys.includes('claude'), 'Claude is recognized in the external client registry');
70
- assert.ok(keys.includes('agentsam'), 'AgentSam is recognized in the external client registry');
71
- assert.equal(keys.some((k) => k.startsWith('cf_')), false, 'CF MCP portals are servers, not clients');
72
-
73
- assert.equal(isClientRegistered('chatgpt', { home }), true);
74
- assert.equal(isClientRegistered('cursor', { home }), true);
75
- assert.equal(isClientRegistered('cf_bindings_mcp', { home }), false);
76
- assert.equal(isClientRegistered('nonexistent_client_xyz', { home }), false);
77
-
78
- // Cache path is created upon writing
79
- const cachePath = getClientRegistryCachePath({ home });
80
- assert.equal(cachePath.endsWith('client-registry-cache.json'), true);
81
- });
82
-
83
- test('MCP client adapters materialize Cursor, Claude, and ChatGPT configurations cleanly', () => {
84
- const home = tempHome();
85
- const serverConfig = {
86
- url: 'https://mcp.inneranimalmedia.com/mcp',
87
- auth: { type: 'bearer', token: 'oauth_cursor_123' },
88
- };
89
-
90
- // Pre-seed an existing server in Cursor config to ensure no clobbering
91
- const cursorConfigPath = getClientConfigPath('cursor', { home });
92
- fs.mkdirSync(path.dirname(cursorConfigPath), { recursive: true });
93
- fs.writeFileSync(
94
- cursorConfigPath,
95
- JSON.stringify({ mcpServers: { other_server: { url: 'http://localhost:8080' } } })
96
- );
97
-
98
- // Sync to Cursor
99
- const cursorResult = syncServerToClient('cursor', 'inneranimalmedia', serverConfig, { home });
100
- assert.equal(cursorResult.synced, true);
101
-
102
- const cursorContent = JSON.parse(fs.readFileSync(cursorConfigPath, 'utf8'));
103
- assert.ok(cursorContent.mcpServers.other_server, 'Preserved other server in Cursor config');
104
- assert.equal(cursorContent.mcpServers.inneranimalmedia.url, 'https://mcp.inneranimalmedia.com/mcp');
105
- assert.equal(cursorContent.mcpServers.inneranimalmedia.headers.Authorization, 'Bearer oauth_cursor_123');
106
- assert.equal(cursorContent.mcpServers.inneranimalmedia.headers.Accept, 'application/json, text/event-stream');
107
-
108
- // Inspect Cursor adapter
109
- const inspection = inspectClientAdapter('cursor', 'inneranimalmedia', { home });
110
- assert.equal(inspection.configured, true);
111
- assert.equal(inspection.present, true);
112
-
113
- // Sync to Claude
114
- const claudeResult = syncServerToClient('claude', 'inneranimalmedia', serverConfig, { home });
115
- assert.equal(claudeResult.synced, true);
116
- const claudeConfigPath = getClientConfigPath('claude', { home });
117
- const claudeContent = JSON.parse(fs.readFileSync(claudeConfigPath, 'utf8'));
118
- assert.equal(claudeContent.mcpServers.inneranimalmedia.url, 'https://mcp.inneranimalmedia.com/mcp');
119
-
120
- // Sync to ChatGPT
121
- const chatgptResult = syncServerToClient('chatgpt', 'inneranimalmedia', serverConfig, { home });
122
- assert.equal(chatgptResult.synced, true);
123
- const chatgptConfigPath = getClientConfigPath('chatgpt', { home });
124
- assert.ok(fs.existsSync(chatgptConfigPath));
125
- const chatgptContent = JSON.parse(fs.readFileSync(chatgptConfigPath, 'utf8'));
126
- assert.equal(chatgptContent.name, 'inneranimalmedia');
127
- assert.equal(chatgptContent.server_url, 'https://mcp.inneranimalmedia.com/mcp');
128
- assert.equal(chatgptContent.schema, 'agentsam.mcp.client-adapter.chatgpt.v1');
129
-
130
- // Sync to AgentSam family adapter (~/.agentsam/mcp.json)
131
- const agentsamResult = syncServerToClient('agentsam', 'inneranimalmedia', serverConfig, { home });
132
- assert.equal(agentsamResult.synced, true);
133
- const agentsamConfigPath = getClientConfigPath('agentsam', { home });
134
- assert.equal(agentsamConfigPath, path.join(home, '.agentsam', 'mcp.json'));
135
- assert.ok(fs.existsSync(agentsamConfigPath));
136
- const agentsamContent = JSON.parse(fs.readFileSync(agentsamConfigPath, 'utf8'));
137
- assert.equal(agentsamContent.mcpServers.inneranimalmedia.url, 'https://mcp.inneranimalmedia.com/mcp');
138
- assert.equal(agentsamContent.mcpServers.inneranimalmedia.headers.Authorization, 'Bearer oauth_cursor_123');
139
-
140
- // Remove from Cursor
141
- const removeResult = removeServerFromClient('cursor', 'inneranimalmedia', { home });
142
- assert.equal(removeResult.removed, true);
143
- const postRemove = JSON.parse(fs.readFileSync(cursorConfigPath, 'utf8'));
144
- assert.equal(postRemove.mcpServers.inneranimalmedia, undefined);
145
- assert.ok(postRemove.mcpServers.other_server, 'Still preserved other server');
146
-
147
- // Remove from AgentSam family adapter
148
- const removeAgentsam = removeServerFromClient('agentsam', 'inneranimalmedia', { home });
149
- assert.equal(removeAgentsam.removed, true);
150
- const postRemoveAgentsam = JSON.parse(fs.readFileSync(agentsamConfigPath, 'utf8'));
151
- assert.equal(postRemoveAgentsam.mcpServers.inneranimalmedia, undefined);
152
-
153
- // Remove from ChatGPT
154
- const removeChatgpt = removeServerFromClient('chatgpt', 'inneranimalmedia', { home });
155
- assert.equal(removeChatgpt.removed, true);
156
- assert.equal(fs.existsSync(chatgptConfigPath), false);
157
- });
158
-
159
- test('MCP server catalog resolves CF portal bundles + IAM without fabricated health', () => {
160
- const home = tempHome();
161
- const catalog = listKnownServers({ home });
162
- assert.ok(catalog.length >= 8);
163
-
164
- const cfApi = resolveServerPreset('cloudflare-api', { home });
165
- assert.ok(cfApi);
166
- assert.equal(cfApi.url, 'https://mcp.cloudflare.com/mcp');
167
- assert.equal(cfApi.provider, 'cloudflare');
168
- assert.equal(cfApi.kind, 'mcp_portal_bundle');
169
- assert.ok(cfApi.portal_manage_scopes.includes('mcp-portals.read'));
170
-
171
- const bindings = resolveServerPreset('cloudflare-bindings', { home });
172
- assert.ok(bindings);
173
- assert.ok(bindings.feature_packs.includes('data'));
174
-
175
- const iam = resolveServerPreset('inneranimalmedia', { home });
176
- assert.ok(iam);
177
- assert.equal(iam.url, 'https://mcp.inneranimalmedia.com/mcp');
178
- });
179
-
180
- test('MCP telemetry logs tool receipts and computes accurate summaries', () => {
181
- const home = tempHome();
182
-
183
- recordToolReceipt({ tool_key: 'github_read', source_client: 'cursor', duration_ms: 120 }, { home });
184
- recordToolReceipt({ tool_key: 'mcp:d1_query', source_client: 'cursor_mcp', duration_ms: 45 }, { home });
185
- recordToolReceipt({ tool_key: 'terminal_exec', source_client: 'agentsam', duration_ms: 800 }, { home });
186
- recordToolReceipt({ tool_key: 'mcp:tool_broken', error_code: 'TIMEOUT', duration_ms: 5000 }, { home });
187
-
188
- const receipts = getSessionToolReceipts({ home });
189
- assert.equal(receipts.length, 4);
190
-
191
- const summary = summarizeToolReceipts(receipts);
192
- assert.equal(summary.tool_call_count, 4);
193
- assert.equal(summary.mcp_call_count, 2);
194
- assert.equal(summary.github_call_count, 1);
195
- assert.equal(summary.d1_call_count, 1);
196
- assert.equal(summary.terminal_call_count, 1);
197
- assert.equal(summary.failure_count, 1);
198
- assert.equal(summary.success_count, 3);
199
- });
200
-
201
- test('agentsam mcp CLI handles add, list, status, doctor, and remove end-to-end', async () => {
202
- const home = tempHome();
203
- const logs = [];
204
- const write = (str) => logs.push(str);
205
-
206
- // Test --help output surfaces chatgpt and known catalog servers
207
- await runMcp(['--help'], { home, write });
208
- const helpText = logs.join('\n');
209
- assert.ok(helpText.includes('chatgpt'), 'Help text displays ChatGPT as a recognized client');
210
- assert.ok(helpText.includes('cloudflare-api'), 'Help text displays cloudflare-api preset');
211
- assert.ok(helpText.includes('bindings.mcp.cloudflare.com') || helpText.includes('cloudflare-bindings'), 'CF portal hostnames remain offerable');
212
- logs.length = 0;
213
-
214
- // Add inneranimalmedia preset for chatgpt client
215
- const addRes = await runMcp(
216
- ['add', 'inneranimalmedia', '--client', 'chatgpt', '--token', 'test_tok_777', '--json'],
217
- { home, write }
218
- );
219
- assert.equal(addRes.ok, true);
220
- assert.equal(addRes.server.name, 'inneranimalmedia');
221
- assert.equal(addRes.server.auth.token, 'test_tok_777');
222
- assert.equal(addRes.syncedAdapters[0].client, 'chatgpt');
223
-
224
- // List
225
- const listRes = await runMcp(['list', '--json'], { home, write });
226
- assert.equal(listRes.length, 1);
227
- assert.equal(listRes[0].name, 'inneranimalmedia');
228
-
229
- // List catalog
230
- const catalogRes = await runMcp(['list', '--catalog', '--json'], { home, write });
231
- assert.ok(catalogRes.length >= 8);
232
-
233
- // Status
234
- const statusRes = await runMcp(['status', 'inneranimalmedia', '--json'], { home, write });
235
- assert.equal(statusRes.name, 'inneranimalmedia');
236
- assert.equal(statusRes.hasAuth, true);
237
-
238
- // Doctor includes catalog / CF pack metadata
239
- const doctorRes = await runMcp(['doctor', 'inneranimalmedia', '--json'], { home, write });
240
- assert.equal(doctorRes.name, 'inneranimalmedia');
241
- assert.equal(doctorRes.authConfigured, true);
242
- assert.equal(doctorRes.catalog?.auth_type, 'bearer');
243
-
244
- // Cloudflare bundle scopes are pack-scoped (includes mcp-portals.*)
245
- const scopeRes = await runMcp(['scopes', 'cloudflare-bindings', '--json'], { home, write });
246
- assert.ok(scopeRes.oauth_scopes.includes('mcp-portals.read'));
247
- assert.ok(scopeRes.oauth_scopes.includes('mcp-portals.write'));
248
- assert.ok(scopeRes.oauth_scopes.includes('d1.read'));
249
-
250
- // Remove
251
- const removeRes = await runMcp(['remove', 'inneranimalmedia', '--client', 'all', '--json'], { home, write });
252
- assert.equal(removeRes.deletedAuthority, true);
253
-
254
- const emptyList = await runMcp(['list', '--json'], { home, write });
255
- assert.equal(emptyList.length, 0);
256
- });