@inneranimalmedia/agentsam-sdk 2.6.7 → 2.6.8

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 (318) hide show
  1. package/README.md +37 -0
  2. package/docs/REPO_FILE_MAP.txt +132 -0
  3. package/migrations/d1/0018_goap_control_plane_remaster.sql +40 -0
  4. package/migrations/d1/0019_agentsam_agent_run_plan_todo.sql +14 -0
  5. package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +20 -9
  6. package/migrations/runtime/0002_goap_blackboard_v1.sql +15 -0
  7. package/migrations/runtime/0004_agent_run_plan_linkage.sql +8 -0
  8. package/native/agentsam-machine/cli/Cargo.toml +8 -1
  9. package/native/agentsam-machine/cli/README.md +21 -0
  10. package/native/agentsam-machine/core/Cargo.toml +7 -0
  11. package/native/agentsam-machine/core/README.md +14 -0
  12. package/native/agentsam-machine/core/build.rs +33 -0
  13. package/native/agentsam-machine/core/contracts/source-types.v1.json +353 -0
  14. package/native/agentsam-machine/core/src/lib.rs +6 -0
  15. package/native/agentsam-machine/core/src/source_types.rs +2 -2
  16. package/package.json +16 -6
  17. package/packages/agentsam-errors/package.json +1 -1
  18. package/packages/agentsam-errors/src/index.js +1 -0
  19. package/packages/agentsam-errors/src/tool.js +56 -0
  20. package/packages/agentsam-errors/test/tool.test.mjs +58 -0
  21. package/packages/agentsam-goap/README.md +52 -0
  22. package/packages/agentsam-goap/package.json +37 -0
  23. package/packages/agentsam-goap/src/adapters/d1-sqlite.js +570 -0
  24. package/packages/agentsam-goap/src/adapters/memory.js +199 -0
  25. package/packages/agentsam-goap/src/contracts.js +226 -0
  26. package/packages/agentsam-goap/src/control-plane.js +112 -0
  27. package/packages/agentsam-goap/src/errors.js +157 -0
  28. package/packages/agentsam-goap/src/index.js +5 -0
  29. package/packages/agentsam-goap/src/world.js +202 -0
  30. package/packages/agentsam-goap/test/goap-control-plane.test.mjs +245 -0
  31. package/packages/agentsam-goap/test/world.test.mjs +79 -0
  32. package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
  33. package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
  34. package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
  35. package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
  36. package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
  37. package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
  38. package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
  39. package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
  40. package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
  41. package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
  42. package/packages/agentsam-nav/dist/browser.d.ts +11 -0
  43. package/packages/agentsam-nav/dist/browser.global.js +135 -0
  44. package/packages/agentsam-nav/dist/browser.js +7290 -0
  45. package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
  46. package/packages/agentsam-nav/dist/index.d.ts +11 -0
  47. package/packages/agentsam-nav/dist/index.js +7291 -0
  48. package/packages/agentsam-nav/dist/legacy.css +83 -0
  49. package/packages/agentsam-nav/dist/shell.css +113 -0
  50. package/packages/agentsam-nav/dist/theme.css +113 -0
  51. package/packages/agentsam-nav/dist/utils.d.ts +1 -0
  52. package/packages/agentsam-repository/src/goap.js +13 -14
  53. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
  54. package/packages/agentsam-repository/src/tickets.js +15 -22
  55. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +19 -8
  56. package/packages/connectors/cloudflare/package.json +3 -1
  57. package/packages/identity/tests/lane1-packed-consumer.test.mjs +1 -1
  58. package/python/agentsam_sdk/repository/intelligence/discovery.py +27 -2
  59. package/python/agentsam_sdk/repository/intelligence/git.py +4 -0
  60. package/python/tests/test_repository_intelligence.py +30 -0
  61. package/src/cli/command-catalog.js +2 -1
  62. package/src/cli.js +10 -1
  63. package/src/commands/goap-world.js +134 -0
  64. package/src/commands/goap.js +11 -4
  65. package/src/commands/machine-binary.js +33 -27
  66. package/src/commands/machine-runtime.js +266 -0
  67. package/src/commands/machine.js +122 -51
  68. package/src/commands/package.js +530 -0
  69. package/src/commands/plan-ledger.js +370 -0
  70. package/src/commands/plan.js +183 -0
  71. package/src/commands/skill.js +78 -17
  72. package/src/knowledge/source.js +1 -1
  73. package/src/lib/slash-commands.js +1 -1
  74. package/src/local/runtime-store.js +24 -2
  75. package/src/local/sqlite.js +17 -0
  76. package/src/sam/operations/package-audit.js +41 -0
  77. package/src/sam/seed.js +2 -0
  78. package/skills/grok-auth/SKILL.md +0 -110
  79. package/skills/grok-auth/agentsam.skill.json +0 -25
  80. package/skills/grok-auth/references/grok-identity.md +0 -64
  81. package/skills/grok-auth/references/per-user-data.md +0 -49
  82. package/skills/grok-auth/references/prewired-and-env.md +0 -54
  83. package/skills/grok-auth/references/session-ui.md +0 -133
  84. package/skills/grok-auth/references/sign-in-methods.md +0 -55
  85. package/skills/grok-auth/references/wiring.md +0 -71
  86. package/skills/grok-building-games/SKILL.md +0 -213
  87. package/skills/grok-building-games/agentsam.skill.json +0 -25
  88. package/skills/grok-building-games/references/3d-libs.md +0 -64
  89. package/skills/grok-building-games/references/ai-pathfinding.md +0 -122
  90. package/skills/grok-building-games/references/audio.md +0 -129
  91. package/skills/grok-building-games/references/babylon.md +0 -202
  92. package/skills/grok-building-games/references/collision-physics.md +0 -122
  93. package/skills/grok-building-games/references/ecs-architecture.md +0 -111
  94. package/skills/grok-building-games/references/game-feel-juice.md +0 -110
  95. package/skills/grok-building-games/references/genres/board-card-chess.md +0 -89
  96. package/skills/grok-building-games/references/genres/endless-runner.md +0 -83
  97. package/skills/grok-building-games/references/genres/fps.md +0 -105
  98. package/skills/grok-building-games/references/genres/platformer-2d.md +0 -97
  99. package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +0 -131
  100. package/skills/grok-building-games/references/genres/racing-kart.md +0 -106
  101. package/skills/grok-building-games/references/genres/topdown-twin-stick.md +0 -97
  102. package/skills/grok-building-games/references/genres/tower-defense.md +0 -84
  103. package/skills/grok-building-games/references/genres/voxel-minecraft.md +0 -89
  104. package/skills/grok-building-games/references/input.md +0 -139
  105. package/skills/grok-building-games/references/phaser.md +0 -277
  106. package/skills/grok-building-games/references/procedural-generation.md +0 -141
  107. package/skills/grok-building-games/references/save-persistence.md +0 -108
  108. package/skills/grok-building-games/references/threejs-foundational.md +0 -148
  109. package/skills/grok-controls/SKILL.md +0 -274
  110. package/skills/grok-controls/agentsam.skill.json +0 -25
  111. package/skills/grok-design-ui/SKILL.md +0 -122
  112. package/skills/grok-design-ui/agentsam.skill.json +0 -25
  113. package/skills/grok-design-ui/references/animations.md +0 -379
  114. package/skills/grok-design-ui/references/performance.md +0 -88
  115. package/skills/grok-design-ui/references/refined-ui.md +0 -384
  116. package/skills/grok-design-ui/references/surfaces.md +0 -247
  117. package/skills/grok-design-ui/references/typography.md +0 -123
  118. package/skills/grok-game-animation-frames/SKILL.md +0 -84
  119. package/skills/grok-game-animation-frames/agentsam.skill.json +0 -25
  120. package/skills/grok-game-asset-core/SKILL.md +0 -69
  121. package/skills/grok-game-asset-core/agentsam.skill.json +0 -25
  122. package/skills/grok-game-character-consistency/SKILL.md +0 -69
  123. package/skills/grok-game-character-consistency/agentsam.skill.json +0 -25
  124. package/skills/grok-game-tilesets/SKILL.md +0 -65
  125. package/skills/grok-game-tilesets/agentsam.skill.json +0 -25
  126. package/skills/grok-game-ui-icons/SKILL.md +0 -56
  127. package/skills/grok-game-ui-icons/agentsam.skill.json +0 -25
  128. package/skills/grok-generate2dmap/LICENSE +0 -21
  129. package/skills/grok-generate2dmap/SKILL.md +0 -120
  130. package/skills/grok-generate2dmap/SOURCE.md +0 -6
  131. package/skills/grok-generate2dmap/agentsam.skill.json +0 -25
  132. package/skills/grok-generate2dmap/references/deliverables.md +0 -101
  133. package/skills/grok-generate2dmap/references/layered-map-contract.md +0 -209
  134. package/skills/grok-generate2dmap/references/map-strategies.md +0 -341
  135. package/skills/grok-generate2dmap/references/object-production-gate.md +0 -24
  136. package/skills/grok-generate2dmap/references/pipeline.md +0 -149
  137. package/skills/grok-generate2dmap/references/prop-pack-contract.md +0 -174
  138. package/skills/grok-generate2dmap/references/side-scroll-stages.md +0 -29
  139. package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +0 -157
  140. package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +0 -369
  141. package/skills/grok-generate2dsprite/LICENSE +0 -21
  142. package/skills/grok-generate2dsprite/SKILL.md +0 -313
  143. package/skills/grok-generate2dsprite/SOURCE.md +0 -6
  144. package/skills/grok-generate2dsprite/agentsam.skill.json +0 -25
  145. package/skills/grok-generate2dsprite/references/modes.md +0 -124
  146. package/skills/grok-generate2dsprite/references/prompt-rules.md +0 -315
  147. package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +0 -1031
  148. package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +0 -109
  149. package/skills/grok-imagine/SKILL.md +0 -201
  150. package/skills/grok-imagine/agentsam.skill.json +0 -25
  151. package/skills/grok-multiplayer-p2p/SKILL.md +0 -111
  152. package/skills/grok-multiplayer-p2p/agentsam.skill.json +0 -25
  153. package/skills/grok-multiplayer-p2p/references/react-binding.md +0 -144
  154. package/skills/grok-multiplayer-p2p/references/signaling-relay.md +0 -269
  155. package/skills/grok-neon/SKILL.md +0 -157
  156. package/skills/grok-neon/agentsam.skill.json +0 -25
  157. package/skills/grok-og/SKILL.md +0 -102
  158. package/skills/grok-og/agentsam.skill.json +0 -25
  159. package/skills/grok-og/references/brand-pass.md +0 -53
  160. package/skills/grok-og/references/custom-card.md +0 -107
  161. package/skills/grok-og/references/favicon-and-icons.md +0 -48
  162. package/skills/grok-og/references/og-type-contract.md +0 -18
  163. package/skills/grok-og/references/placeholder-card.md +0 -21
  164. package/skills/grok-og/references/x-banner.md +0 -41
  165. package/skills/grok-threejs/SKILL.md +0 -67
  166. package/skills/grok-threejs/agentsam.skill.json +0 -25
  167. package/skills/grok-threejs/references/llms-full.txt +0 -2780
  168. package/skills/grok-video2dsprite/LICENSE +0 -21
  169. package/skills/grok-video2dsprite/SKILL.md +0 -236
  170. package/skills/grok-video2dsprite/SOURCE.md +0 -6
  171. package/skills/grok-video2dsprite/agentsam.skill.json +0 -25
  172. package/skills/grok-video2dsprite/references/pipeline.md +0 -90
  173. package/skills/grok-video2dsprite/references/prompt-rules.md +0 -63
  174. package/skills/grok-video2dsprite/scripts/video2dsprite.py +0 -490
  175. package/skills/grok-xai-api/SKILL.md +0 -152
  176. package/skills/grok-xai-api/agentsam.skill.json +0 -25
  177. package/test/account-session.test.mjs +0 -101
  178. package/test/agent-capabilities.test.mjs +0 -67
  179. package/test/app-authority-context.test.mjs +0 -32
  180. package/test/app-building-skills.test.mjs +0 -61
  181. package/test/apps-scaffold-contract.test.mjs +0 -115
  182. package/test/blender-cad.test.mjs +0 -146
  183. package/test/cad-docker.test.mjs +0 -96
  184. package/test/capabilities.test.mjs +0 -133
  185. package/test/cli/api-key-env-whoami.test.mjs +0 -129
  186. package/test/cli/catalog-authority.test.mjs +0 -64
  187. package/test/cli/codebaseindex-plan-ux.test.mjs +0 -37
  188. package/test/cli/eval-live.test.mjs +0 -219
  189. package/test/cli/go.test.mjs +0 -128
  190. package/test/cli/local-vault-and-provider-setup.test.mjs +0 -268
  191. package/test/cli/machine-command.test.mjs +0 -34
  192. package/test/cli/mcp-client.test.mjs +0 -256
  193. package/test/cli/preferences-runtime.test.mjs +0 -11
  194. package/test/cli/runtime-persist.test.mjs +0 -56
  195. package/test/cli/runtime-ui.test.mjs +0 -141
  196. package/test/cli/rust-command.test.mjs +0 -21
  197. package/test/cli/skill-npm-and-env.test.mjs +0 -52
  198. package/test/cli/status-actions.test.mjs +0 -88
  199. package/test/cli/wireframes-go-registry.test.mjs +0 -139
  200. package/test/cli-preferences.test.mjs +0 -46
  201. package/test/cloudflare-connector.test.mjs +0 -93
  202. package/test/cloudflare-runtime.test.mjs +0 -82
  203. package/test/context.test.mjs +0 -159
  204. package/test/credentials-audit.test.mjs +0 -113
  205. package/test/deploy-health-scan.test.mjs +0 -95
  206. package/test/deploy-receipt.test.mjs +0 -91
  207. package/test/dockerize.test.mjs +0 -93
  208. package/test/error-diagnostics.test.mjs +0 -124
  209. package/test/eval-context.test.mjs +0 -37
  210. package/test/execution-approvals.test.mjs +0 -27
  211. package/test/fixtures/cad/courtyard-house.json +0 -208
  212. package/test/fixtures/knowledge-rpc-worker.mjs +0 -16
  213. package/test/fixtures/project-authority/customer-app/.agentsam/app.json +0 -5
  214. package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +0 -1
  215. package/test/fixtures/project-authority/customer-app/wrangler.toml +0 -17
  216. package/test/gcloud-auth.test.mjs +0 -111
  217. package/test/go/build-source-identity.test.mjs +0 -31
  218. package/test/go/cloudflare-probe.test.mjs +0 -317
  219. package/test/go/distribution.test.mjs +0 -28
  220. package/test/google-cloud-connection.test.mjs +0 -83
  221. package/test/google-cloud-inventory.test.mjs +0 -64
  222. package/test/indexing-provider.test.mjs +0 -29
  223. package/test/init-options.test.mjs +0 -35
  224. package/test/integration/ai-access-onboarding.test.mjs +0 -47
  225. package/test/integration/app-command.test.mjs +0 -85
  226. package/test/integration/autorag-project-authority.integration.test.mjs +0 -51
  227. package/test/integration/autorag-runtime-discovery.test.mjs +0 -107
  228. package/test/integration/cad-discovery.test.mjs +0 -158
  229. package/test/integration/cad-docker-executor.test.mjs +0 -249
  230. package/test/integration/cad-execution.test.mjs +0 -184
  231. package/test/integration/cad-project-app.test.mjs +0 -31
  232. package/test/integration/cad-project-d1.test.mjs +0 -25
  233. package/test/integration/cad-project-native.test.mjs +0 -24
  234. package/test/integration/cad-project-workflow.test.mjs +0 -9
  235. package/test/integration/cad-project.test.mjs +0 -85
  236. package/test/integration/cli-help.test.mjs +0 -41
  237. package/test/integration/cms-app-scaffold.test.mjs +0 -77
  238. package/test/integration/cms-site-tenancy-contract.test.mjs +0 -268
  239. package/test/integration/codebaseindex-ingest.test.mjs +0 -255
  240. package/test/integration/core-client.integration.test.mjs +0 -55
  241. package/test/integration/database-hosted-honesty.test.mjs +0 -49
  242. package/test/integration/desktop-keychain-boundary.test.mjs +0 -45
  243. package/test/integration/error-runtime-rpc.test.mjs +0 -71
  244. package/test/integration/features-resolve.test.mjs +0 -147
  245. package/test/integration/hosted-work-host-authority.test.mjs +0 -47
  246. package/test/integration/icon-registry.test.mjs +0 -67
  247. package/test/integration/ingest-discover-models.test.mjs +0 -30
  248. package/test/integration/inspect-path-cli.test.mjs +0 -46
  249. package/test/integration/install-script.test.mjs +0 -110
  250. package/test/integration/inventory-core.test.mjs +0 -53
  251. package/test/integration/inventory-eligibility.test.mjs +0 -59
  252. package/test/integration/inventory-evidence.test.mjs +0 -125
  253. package/test/integration/knowledge-rpc.test.mjs +0 -112
  254. package/test/integration/local-fs.test.mjs +0 -113
  255. package/test/integration/local-provider-bridge.test.mjs +0 -65
  256. package/test/integration/local-studio-settings-production.test.mjs +0 -40
  257. package/test/integration/lockfile-sync.test.mjs +0 -26
  258. package/test/integration/merkle-cli.test.mjs +0 -61
  259. package/test/integration/merkle-persistence-identity.test.mjs +0 -48
  260. package/test/integration/plugins-cloudflare.integration.test.mjs +0 -28
  261. package/test/integration/provider-env-cli.test.mjs +0 -60
  262. package/test/integration/provider-factory.test.mjs +0 -197
  263. package/test/integration/repository-company-graph.test.mjs +0 -90
  264. package/test/integration/runtime-migrations.test.mjs +0 -87
  265. package/test/integration/runtime-status.integration.test.mjs +0 -227
  266. package/test/integration/sam-activity-recovery.test.mjs +0 -147
  267. package/test/integration/sam-decision.test.mjs +0 -584
  268. package/test/integration/sam-kernel.test.mjs +0 -99
  269. package/test/integration/sam-planning-astar.test.mjs +0 -279
  270. package/test/integration/scaffold-cloudflare.test.mjs +0 -46
  271. package/test/integration/skill-runtime.test.mjs +0 -240
  272. package/test/integration/storage-architecture.test.mjs +0 -154
  273. package/test/integration/store-discovery.test.mjs +0 -44
  274. package/test/integration/studio-fs-pty-e2e.test.mjs +0 -294
  275. package/test/integration/terminal-exec.integration.test.mjs +0 -86
  276. package/test/integration/theme-package-registry.test.mjs +0 -31
  277. package/test/integration/tool-runtime.test.mjs +0 -124
  278. package/test/integration/tool-schema.test.mjs +0 -59
  279. package/test/jr-dev-skill.test.mjs +0 -26
  280. package/test/knowledge-context-pack.test.mjs +0 -19
  281. package/test/knowledge-postgres.test.mjs +0 -40
  282. package/test/knowledge-service.test.mjs +0 -110
  283. package/test/knowledge.test.mjs +0 -206
  284. package/test/live/terminal-transport.live.test.mjs +0 -24
  285. package/test/local-sessions.test.mjs +0 -57
  286. package/test/local-studio-deploy.test.mjs +0 -83
  287. package/test/loopback-oauth.test.mjs +0 -53
  288. package/test/merkle-render.test.mjs +0 -31
  289. package/test/mini.test.mjs +0 -140
  290. package/test/model-catalog.test.mjs +0 -70
  291. package/test/models.test.mjs +0 -309
  292. package/test/npm10-lock.test.mjs +0 -29
  293. package/test/ollama.test.mjs +0 -137
  294. package/test/open-url.test.mjs +0 -64
  295. package/test/openai-responses.test.mjs +0 -155
  296. package/test/portable-context.test.mjs +0 -94
  297. package/test/project-config.test.mjs +0 -81
  298. package/test/project-rules.test.mjs +0 -44
  299. package/test/provider-credentials.test.mjs +0 -106
  300. package/test/rehydrate.test.mjs +0 -25
  301. package/test/release-hygiene.test.mjs +0 -42
  302. package/test/repository-snapshot-view.test.mjs +0 -112
  303. package/test/responses-runner.test.mjs +0 -465
  304. package/test/runtime-activity.test.mjs +0 -98
  305. package/test/sdk-worker-contract.test.mjs +0 -72
  306. package/test/security.test.mjs +0 -266
  307. package/test/setup-planner.test.mjs +0 -74
  308. package/test/setup-runtime.test.mjs +0 -51
  309. package/test/shell.test.mjs +0 -281
  310. package/test/skills.test.mjs +0 -22
  311. package/test/smoke.mjs +0 -122
  312. package/test/telemetry.test.mjs +0 -79
  313. package/test/terminal/local-pty.mock.test.mjs +0 -153
  314. package/test/terminal-machine-identity.test.mjs +0 -88
  315. package/test/theme-portability.test.mjs +0 -14
  316. package/test/tools-search.test.mjs +0 -73
  317. package/test/unit/website-assets-bindings.test.mjs +0 -60
  318. package/test/whoami-resume.test.mjs +0 -157
@@ -1,11 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import test from 'node:test';
3
- import { runtimeOptions } from '../../src/commands/preferences.js';
4
-
5
- test('standalone users only see local execution', () => {
6
- assert.deepEqual(runtimeOptions({ accountConnected: false }).map((row) => row.value), ['local']);
7
- });
8
-
9
- test('IAM-connected users can choose enrolled remote and sandbox lanes', () => {
10
- assert.deepEqual(runtimeOptions({ accountConnected: true }).map((row) => row.value), ['local', 'remote', 'sandbox']);
11
- });
@@ -1,56 +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 {
7
- buildWindowsScheduledTaskXml,
8
- buildLaunchAgentPlist,
9
- writeWindowsScheduledTask,
10
- WINDOWS_TASK_NAME,
11
- } from '../../src/lib/setup/runtime-persist.js';
12
-
13
- test('buildWindowsScheduledTaskXml includes binary, listen, logon trigger', () => {
14
- const xml = buildWindowsScheduledTaskXml({
15
- binary: 'C:\\Users\\sam\\.agentsam\\bin\\agentsamd.exe',
16
- listen: '127.0.0.1:18765',
17
- workingDirectory: 'C:\\Users\\sam\\.agentsam\\bin',
18
- });
19
- assert.match(xml, /agentsamd\.exe/);
20
- assert.match(xml, /--listen 127\.0\.0\.1:18765/);
21
- assert.match(xml, /LogonTrigger/);
22
- assert.match(xml, /InteractiveToken/);
23
- assert.match(xml, /RestartOnFailure/);
24
- });
25
-
26
- test('buildLaunchAgentPlist includes KeepAlive and listen', () => {
27
- const plist = buildLaunchAgentPlist({
28
- binary: '/Users/sam/.agentsam/bin/agentsamd',
29
- listen: '127.0.0.1:18765',
30
- stdoutLog: '/tmp/out.log',
31
- stderrLog: '/tmp/err.log',
32
- });
33
- assert.match(plist, /com\.inneranimalmedia\.agentsamd/);
34
- assert.match(plist, /KeepAlive/);
35
- assert.match(plist, /127\.0\.0\.1:18765/);
36
- });
37
-
38
- test('writeWindowsScheduledTask writes XML without calling schtasks when skipRegister', async () => {
39
- const home = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-runtime-'));
40
- try {
41
- const result = await writeWindowsScheduledTask(
42
- home,
43
- path.join(home, '.agentsam', 'bin', 'agentsamd.exe'),
44
- '127.0.0.1:18765',
45
- { forcePlatform: 'win32', skipRegister: true },
46
- );
47
- assert.equal(result.kind, 'scheduled_task');
48
- assert.equal(result.taskName, WINDOWS_TASK_NAME);
49
- assert.equal(result.registered, false);
50
- assert.ok(fs.existsSync(result.xmlPath));
51
- const xml = fs.readFileSync(result.xmlPath, 'utf8');
52
- assert.match(xml, /agentsamd\.exe/);
53
- } finally {
54
- fs.rmSync(home, { recursive: true, force: true });
55
- }
56
- });
@@ -1,141 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import test from 'node:test';
3
- import { createInlineActivity, INTERRUPT_HINT, renderShimmer } from '../../src/ui/cli/activity.js';
4
- import { renderCliFooter, renderDiffPreview } from '../../src/ui/cli/footer.js';
5
- import { createCliRuntimePresenter, normalizeRuntimeEventEnvelope, RUNTIME_EVENT_ENVELOPE_SCHEMA } from '../../src/ui/cli/runtime-events.js';
6
- import { renderWaitingInput } from '../../src/ui/cli/waiting.js';
7
-
8
- const stripAnsi = (text) => String(text || '').replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
9
-
10
- test('CLI footer reports unknown context honestly', () => {
11
- const text = renderCliFooter({
12
- model: 'claude-test',
13
- usageSnapshot: {
14
- current_context: { input_tokens: 1234, window_tokens: 0 },
15
- cumulative: { input_tokens: 5000, output_tokens: 600, cached_input_tokens: 2000 },
16
- },
17
- });
18
- assert.match(text, /claude-test/);
19
- assert.match(text, /ctx 1\.2k \/ unknown/);
20
- assert.match(text, /↑5k ↓600/);
21
- assert.match(text, /cache 2k/);
22
- });
23
-
24
- test('CLI footer shows project identity, branch, and shortcut hints', () => {
25
- const text = stripAnsi(renderCliFooter({
26
- project: 'agentsam-sdk',
27
- cwd: '/Users/sam/agentsam-sdk',
28
- branch: 'feat/cli-interactive-presence',
29
- model: 'claude-test',
30
- }));
31
- assert.match(text, /agentsam-sdk/);
32
- assert.match(text, /feat\/cli-interactive-presence/);
33
- assert.match(text, /ctrl-c to cancel/);
34
- assert.match(text, /\/ commands/);
35
- });
36
-
37
- test('diff preview colors hunks and keeps NO_COLOR output readable', () => {
38
- const diff = [
39
- 'diff --git a/src/ui/cli/footer.js b/src/ui/cli/footer.js',
40
- '--- a/src/ui/cli/footer.js',
41
- '+++ b/src/ui/cli/footer.js',
42
- '@@ -1,3 +1,4 @@',
43
- ' import pc from \'picocolors\';',
44
- '-const old = 1;',
45
- '+const next = 2;',
46
- ' keep',
47
- ].join('\n');
48
- const colored = renderDiffPreview(diff, { color: true });
49
- assert.match(colored, /\x1b\[/);
50
- assert.match(stripAnsi(colored), /\+const next = 2;/);
51
- const plain = renderDiffPreview(diff, { color: false });
52
- assert.doesNotMatch(plain, /\x1b\[/);
53
- assert.match(plain, /-const old = 1;/);
54
- assert.equal(stripAnsi(renderDiffPreview('', { color: false })).trim(), 'no changes');
55
- });
56
-
57
- test('inline activity shows elapsed time and ctrl-c cancel hint', () => {
58
- let output = '';
59
- let now = 0;
60
- let tick = null;
61
- const activity = createInlineActivity({
62
- write: (value) => { output += value; },
63
- interactive: true,
64
- env: { NO_COLOR: '1' },
65
- now: () => now,
66
- setInterval: (fn) => { tick = fn; return 1; },
67
- clearInterval() {},
68
- });
69
- activity.start('Working');
70
- now = 1500;
71
- tick();
72
- const clean = stripAnsi(output);
73
- assert.match(clean, /Working/);
74
- assert.match(clean, /1\.5s/);
75
- assert.match(clean, new RegExp(INTERRUPT_HINT.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
76
- activity.clear();
77
- });
78
-
79
- test('shimmer uses color when allowed and stays plain under NO_COLOR', () => {
80
- const colored = renderShimmer('Working', 4, { env: { COLORTERM: 'truecolor' } });
81
- assert.match(colored, /\x1b\[38;2;/);
82
- assert.match(stripAnsi(colored), /Working/);
83
- const fallback = renderShimmer('Working', 4, { env: { TERM: 'xterm-256color' } });
84
- assert.match(fallback, /\x1b\[38;5;/);
85
- const plain = renderShimmer('Working', 4, { env: { NO_COLOR: '1', COLORTERM: 'truecolor' } });
86
- assert.equal(plain, 'Working');
87
- });
88
-
89
- test('runtime event envelope is the single standalone/platform producer contract', () => {
90
- const envelope = normalizeRuntimeEventEnvelope({
91
- schema_version: 1,
92
- type: 'tool.started',
93
- timestamp: '2026-09-18T00:00:00.000Z',
94
- run_id: 'run_1',
95
- sequence: 3,
96
- payload: { capability_id: 'repo.inspect' },
97
- });
98
- assert.equal(envelope.schema, RUNTIME_EVENT_ENVELOPE_SCHEMA);
99
- assert.equal(envelope.schema_version, 1);
100
- assert.equal(envelope.type, 'tool.started');
101
- assert.equal(envelope.run_id, 'run_1');
102
- assert.equal(envelope.sequence, 3);
103
- assert.deepEqual(envelope.payload, { capability_id: 'repo.inspect' });
104
- assert.throws(() => normalizeRuntimeEventEnvelope({ payload: {} }), /type is required/);
105
- });
106
-
107
- test('runtime presenter turns events into one-line activity and waiting handoff', () => {
108
- let output = '';
109
- let now = 1_000;
110
- const timers = [];
111
- const activity = createInlineActivity({
112
- write: (value) => { output += value; },
113
- interactive: false,
114
- now: () => now,
115
- setInterval: (fn) => { timers.push(fn); return timers.length; },
116
- clearInterval() {},
117
- });
118
- const state = {};
119
- const presenter = createCliRuntimePresenter({ activity, write: (value) => { output += value; }, state });
120
- activity.start('Thinking');
121
- presenter.handle({ type: 'tool.started', payload: { capability_id: 'repo.inspect' } });
122
- presenter.handle({ type: 'usage.snapshot', payload: { current_context: { input_tokens: 10, window_tokens: 100 }, cumulative: {} } });
123
- presenter.handle({ type: 'context.compaction.started', payload: { provider: 'test' } });
124
- now += 500;
125
- presenter.handle({ type: 'context.compaction.completed', payload: { provider: 'test', tokens_before: 80, tokens_after: 20, summary_text: 'kept state' } });
126
- presenter.handle({ type: 'runtime.waiting_input', payload: { reason: 'authentication', auth_url: 'https://example.test/auth', user_code: 'ABCD' } });
127
- assert.equal(state.usageSnapshot.current_context.input_tokens, 10);
128
- assert.equal(state.lastCompaction.tokens_before, 80);
129
- assert.match(output, /Waiting for you/);
130
- assert.match(output, /https:\/\/example\.test\/auth/);
131
- assert.match(output, /ABCD/);
132
- assert.match(presenter.compactionReceipt(), /80 → 20/);
133
- });
134
-
135
- test('waiting renderer gives CLI-native auth instructions', () => {
136
- const text = renderWaitingInput({ awaiting_input_reason: 'otp', auth_url: 'https://example.test/login', user_code: '123456' });
137
- assert.match(text, /Waiting for you/);
138
- assert.match(text, /otp/);
139
- assert.match(text, /Open/);
140
- assert.match(text, /123456/);
141
- });
@@ -1,21 +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
-
8
- const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
9
-
10
- test('rust/wasm command aliases resolve to one catalog authority', () => {
11
- const rust = getCliCommand('rust');
12
- assert.equal(rust?.id, 'rust');
13
- assert.equal(getCliCommand('wasm')?.id, 'rust');
14
- assert.equal(getCliCommand('rapid-rust')?.id, 'rust');
15
- });
16
-
17
- test('rapid rust root bin and native crate ship in source tree', () => {
18
- assert.equal(fs.existsSync(path.join(root, 'bin/agentsam-rapid-rust')), true);
19
- assert.equal(fs.existsSync(path.join(root, 'packages/agentsam-rapid-rust/Cargo.toml')), true);
20
- assert.equal(fs.existsSync(path.join(root, 'scripts/build_rapid_rust_cli.py')), true);
21
- });
@@ -1,52 +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 { spawnSync } from 'node:child_process';
6
- import test from 'node:test';
7
- import { resolveNpmSkillPackage } from '../../src/commands/skill.js';
8
- import { installSkillFromPath } from '../../src/skills/index.js';
9
- import { runEnv } from '../../src/commands/env.js';
10
-
11
- function tmpHome() {
12
- return fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-finish-'));
13
- }
14
-
15
- test('resolveNpmSkillPackage extracts agentsam.skill.json via npm pack', (t) => {
16
- // Build a tiny local package and pack it by path (no registry).
17
- const pkgRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-npm-skill-'));
18
- fs.writeFileSync(
19
- path.join(pkgRoot, 'package.json'),
20
- JSON.stringify({ name: 'tmp-agentsam-skill-fixture', version: '0.0.0', private: true }),
21
- );
22
- fs.writeFileSync(
23
- path.join(pkgRoot, 'agentsam.skill.json'),
24
- JSON.stringify({
25
- schema: 'agentsam.skill.v1',
26
- id: 'npm-fixture',
27
- name: 'NPM Fixture',
28
- slash: { suggested: '/npm-fixture' },
29
- instructions: { source: 'inline', inline: '# npm fixture' },
30
- execution: { mode: 'turn' },
31
- }),
32
- );
33
- const resolved = resolveNpmSkillPackage(pkgRoot, { spawnSyncImpl: spawnSync });
34
- assert.ok(fs.existsSync(path.join(resolved, 'agentsam.skill.json')));
35
-
36
- const home = tmpHome();
37
- const installed = installSkillFromPath(resolved, { home });
38
- assert.equal(installed.id, 'npm-fixture');
39
- assert.equal(installed.trigger, '/npm-fixture');
40
- });
41
-
42
- test('env boot-line prints source load-agent-env command', async () => {
43
- const home = tmpHome();
44
- const lines = [];
45
- const result = await runEnv(['boot-line', 'cursor', 'inneranimalmedia'], {
46
- home,
47
- write: (t) => lines.push(t),
48
- });
49
- assert.equal(result.command, 'source ~/.agentsam/load-agent-env.sh');
50
- assert.ok(lines.join('').includes('load-agent-env.sh'));
51
- assert.ok(lines.join('').includes('agentsam env shell'));
52
- });
@@ -1,88 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import test from 'node:test';
3
- import {
4
- buildStatusActionPlan,
5
- formatStatusNextSteps,
6
- } from '../../src/status/actions.js';
7
- import { renderLocalStatus } from '../../src/ui/ansi.js';
8
-
9
- test('healthy Cloudflare deployment wins over localhost', () => {
10
- const runtime = {
11
- ready: true,
12
- checks: {
13
- account: true,
14
- models: true,
15
- terminal: true,
16
- cloudflare: true,
17
- },
18
- local: {
19
- deployTarget: 'cloudflare',
20
- api: {
21
- online: false,
22
- url: 'http://127.0.0.1:8787/api/health',
23
- },
24
- db: {
25
- ready: true,
26
- exists: true,
27
- },
28
- },
29
- cloudflare: {
30
- configured: true,
31
- worker_name: 'agentsam-sdk',
32
- health: {
33
- ok: true,
34
- status: 200,
35
- url: 'https://agentsam.inneranimalmedia.com/health',
36
- },
37
- },
38
- };
39
-
40
- const plan = buildStatusActionPlan(runtime);
41
- const text = formatStatusNextSteps(plan);
42
-
43
- assert.match(plan.headline, /Live project healthy/);
44
- assert.ok(plan.actions.some((action) =>
45
- action.command === 'https://agentsam.inneranimalmedia.com'
46
- ));
47
- assert.ok(plan.actions.some((action) =>
48
- action.command === 'agentsam cloudflare status'
49
- ));
50
- assert.doesNotMatch(text, /npm run dev/);
51
- assert.match(text, /open https:\/\/agentsam\.inneranimalmedia\.com/);
52
- });
53
-
54
- test('compact local card prefers live deployment', () => {
55
- const text = renderLocalStatus({
56
- configured: true,
57
- project: 'agentsam-sdk',
58
- lane: 'custom',
59
- agent: 'default',
60
- git: {
61
- branch: 'main',
62
- revision: 'abcdef123456',
63
- dirty: false,
64
- },
65
- db: {
66
- ready: true,
67
- tables: [],
68
- },
69
- api: {
70
- online: false,
71
- url: 'http://127.0.0.1:8787/api/health',
72
- },
73
- pty: {
74
- online: true,
75
- url: 'http://127.0.0.1:3099/health',
76
- },
77
- deployTarget: 'cloudflare',
78
- live: {
79
- online: true,
80
- url: 'https://agentsam.inneranimalmedia.com/health',
81
- },
82
- });
83
-
84
- assert.match(text, /● live/);
85
- assert.match(text, /open https:\/\/agentsam\.inneranimalmedia\.com/);
86
- assert.match(text, /agentsam cloudflare status/);
87
- assert.doesNotMatch(text, /npm run dev/);
88
- });
@@ -1,139 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import test from 'node:test';
3
- import { renderArchitectureExplorer, renderOperationInspector, drawBox } from '../../src/ui/wireframes.js';
4
- import { applyInnerAnimalMediaOfficialGoProductRegistry, buildGoProductRegistrySql } from '../../src/go/official-registry.js';
5
-
6
- test('architecture explorer is boxed reasoning scenery', () => {
7
- const view = renderArchitectureExplorer({
8
- repo: 'agentsam-sdk',
9
- focus: { package: 'protocol', owns: 'wire contracts', runtime: 'none', imported_by: 'client', files: '.proto' },
10
- });
11
- assert.match(view, /┌/);
12
- assert.match(view, /package: protocol/);
13
- assert.match(view, /DEPENDENCY MAP/);
14
- assert.match(view, /\[contracts\]/);
15
- });
16
-
17
- test('operation inspector shows intent timeline', () => {
18
- const view = renderOperationInspector({
19
- operation: 'model.export',
20
- op_id: 'op_01H',
21
- active_index: 2,
22
- step: { name: 'converter', artifact: 'GLB' },
23
- receipt: { 'input document revision': 84, 'output artifact hash': 'abc' },
24
- });
25
- assert.match(view, /model\.export/);
26
- assert.match(view, /intent/);
27
- assert.match(view, /converter/);
28
- assert.match(view, /GLB/);
29
- assert.match(view, /input document revision/);
30
- });
31
-
32
- test('drawBox pads visible ANSI width', () => {
33
- const box = drawBox(['hello'], { width: 20, title: 't' });
34
- assert.match(box, /┌/);
35
- assert.match(box, /└/);
36
- });
37
-
38
- test('buildGoProductRegistrySql upserts product + relationships without inventing tables', () => {
39
- const sql = buildGoProductRegistrySql({
40
- product: 'agentsam-go-worker',
41
- status: 'deployed',
42
- url: 'https://agentsam-go-worker.example.workers.dev',
43
- commit: 'abc123',
44
- health: 'healthy',
45
- });
46
- assert.match(sql, /INSERT INTO agentsam_products/);
47
- assert.match(sql, /ON CONFLICT\(slug\) DO UPDATE/);
48
- assert.match(sql, /INSERT INTO asset_relationships/);
49
- assert.match(sql, /sourced_from/);
50
- assert.match(sql, /runs_on/);
51
- assert.match(sql, /deployed_as/);
52
- assert.doesNotMatch(sql, /CREATE TABLE/);
53
- assert.doesNotMatch(sql, /account_id/);
54
- });
55
-
56
-
57
- test('InnerAnimalMedia remote registry requires the explicit official-release guard', () => {
58
- const preferred = process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE;
59
- const legacy = process.env.AGENTSAM_IAM_OFFICIAL_RELEASE;
60
-
61
- delete process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE;
62
- delete process.env.AGENTSAM_IAM_OFFICIAL_RELEASE;
63
-
64
- try {
65
- assert.throws(
66
- () => applyInnerAnimalMediaOfficialGoProductRegistry({
67
- productRoot: '/tmp/agentsam-test-state',
68
- officialRelease: true,
69
- skipRemote: true,
70
- }),
71
- /inneranimalmedia_registry_official_release_required/,
72
- );
73
- } finally {
74
- if (preferred == null) {
75
- delete process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE;
76
- } else {
77
- process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE = preferred;
78
- }
79
-
80
- if (legacy == null) {
81
- delete process.env.AGENTSAM_IAM_OFFICIAL_RELEASE;
82
- } else {
83
- process.env.AGENTSAM_IAM_OFFICIAL_RELEASE = legacy;
84
- }
85
- }
86
- });
87
-
88
- test('InnerAnimalMedia official registry normalizes deployed lifecycle status to D1 production', () => {
89
- const prior = process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE;
90
- process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE = '1';
91
- try {
92
- const result = applyInnerAnimalMediaOfficialGoProductRegistry({
93
- productRoot: null,
94
- officialRelease: true,
95
- status: 'deployed',
96
- dryRun: true,
97
- skipRemote: true,
98
- });
99
- assert.match(result.sql, /'production'/);
100
- assert.doesNotMatch(result.sql, /'deployed',\n 'AgentSam Go runtime/);
101
- } finally {
102
- if (prior == null) delete process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE;
103
- else process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE = prior;
104
- }
105
- });
106
-
107
-
108
- test('legacy AGENTSAM_IAM_OFFICIAL_RELEASE guard remains backward compatible', () => {
109
- const preferred = process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE;
110
- const legacy = process.env.AGENTSAM_IAM_OFFICIAL_RELEASE;
111
-
112
- delete process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE;
113
- process.env.AGENTSAM_IAM_OFFICIAL_RELEASE = '1';
114
-
115
- try {
116
- const result = applyInnerAnimalMediaOfficialGoProductRegistry({
117
- productRoot: null,
118
- officialRelease: true,
119
- status: 'deployed',
120
- dryRun: true,
121
- skipRemote: true,
122
- });
123
-
124
- assert.equal(result.ok, true);
125
- assert.match(result.sql, /'production'/);
126
- } finally {
127
- if (preferred == null) {
128
- delete process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE;
129
- } else {
130
- process.env.AGENTSAM_INNERANIMALMEDIA_OFFICIAL_RELEASE = preferred;
131
- }
132
-
133
- if (legacy == null) {
134
- delete process.env.AGENTSAM_IAM_OFFICIAL_RELEASE;
135
- } else {
136
- process.env.AGENTSAM_IAM_OFFICIAL_RELEASE = legacy;
137
- }
138
- }
139
- });
@@ -1,46 +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 { CLI_PREFERENCES_SCHEMA, detectCliProject, readCliPreferences, writeCliPreferences } from '../src/lib/cli-preferences.js';
7
- import { renderBootSummary } from '../src/ui/boot.js';
8
-
9
- test('CLI preferences persist local model/runtime controls without becoming routing authority', () => {
10
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-cli-prefs-'));
11
- fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify({ name: 'demo-project' }));
12
- const written = writeCliPreferences(root, {
13
- trustedDirectory: true,
14
- runtime: 'sandbox',
15
- terminal: 'zsh',
16
- modelPreference: 'openai:gpt-6-astra',
17
- reasoningEffort: 'high',
18
- serviceTier: 'fast',
19
- });
20
- assert.equal(written.schemaVersion, CLI_PREFERENCES_SCHEMA);
21
- assert.equal(written.modelAuthority, 'preference-only');
22
- assert.equal(written.trustedDirectory, true);
23
- assert.deepEqual(readCliPreferences(root), written);
24
- const identity = detectCliProject(root);
25
- assert.equal(identity.project, 'demo-project');
26
- assert.equal(identity.root, root);
27
- const summary = renderBootSummary({ identity, preferences: written });
28
- assert.match(summary, /Agent Sam/);
29
- assert.match(summary, /demo-project/);
30
- assert.match(summary, /openai:gpt-6-astra/);
31
- assert.match(summary, /high/);
32
- assert.match(summary, /fast/);
33
- });
34
-
35
- test('legacy v1 local preferences migrate in memory without inventing trust', () => {
36
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-cli-legacy-'));
37
- fs.mkdirSync(path.join(root, '.agentsam'));
38
- fs.writeFileSync(path.join(root, '.agentsam', 'cli.json'), JSON.stringify({
39
- schemaVersion: 'agentsam-cli-preferences-v1', runtime: 'local', terminal: 'zsh', modelPreference: 'auto', modelAuthority: 'preference-only',
40
- }));
41
- const read = readCliPreferences(root);
42
- assert.equal(read.schemaVersion, CLI_PREFERENCES_SCHEMA);
43
- assert.equal(read.trustedDirectory, false);
44
- assert.equal(read.reasoningEffort, 'auto');
45
- assert.equal(read.serviceTier, 'default');
46
- });
@@ -1,93 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import { describe, it } from 'node:test';
3
- import { handleCloudflareConnectionRequest } from '../packages/connectors/cloudflare/src/routes.js';
4
- import { rejectUntrustedOwnerHints } from '../packages/connectors/cloudflare/src/owner.js';
5
-
6
- function req(url, { method = 'GET', headers = {}, body } = {}) {
7
- return new Request(url, { method, headers, body });
8
- }
9
-
10
- describe('cloudflare connector routes', () => {
11
- it('rejects unauthenticated status', async () => {
12
- const res = await handleCloudflareConnectionRequest(
13
- req('https://agentsam.inneranimalmedia.com/api/connections/cloudflare'),
14
- {},
15
- );
16
- assert.equal(res.status, 401);
17
- const json = await res.json();
18
- assert.equal(json.error, 'unauthenticated');
19
- });
20
-
21
- it('rejects browser-submitted owner hints', () => {
22
- const url = new URL('https://agentsam.inneranimalmedia.com/api/connections/cloudflare?account_id=evil');
23
- assert.throws(
24
- () => rejectUntrustedOwnerHints(req(url.toString()), url, {}),
25
- /untrusted_owner_hint/,
26
- );
27
- });
28
-
29
- it('returns 503 on start when only fixture credentials exist', async () => {
30
- const env = {
31
- CLOUDFLARE_OAUTH_CLIENT_ID: 'sillynotreal',
32
- fixtureSessions: new Map([['sess_1', 'user-sam']]),
33
- };
34
- const res = await handleCloudflareConnectionRequest(
35
- req('https://agentsam.inneranimalmedia.com/api/connections/cloudflare/start', {
36
- headers: { cookie: 'agentsam_session=sess_1' },
37
- }),
38
- env,
39
- );
40
- assert.equal(res.status, 503);
41
- const json = await res.json();
42
- assert.equal(json.error, 'not_configured');
43
- assert.equal(json.fixture, true);
44
- });
45
-
46
- it('status stays safe and does not treat fixture as production configured', async () => {
47
- const env = {
48
- CLOUDFLARE_OAUTH_CLIENT_ID: 'sillynotreal',
49
- fixtureSessions: new Map([['sess_1', 'user-sam']]),
50
- };
51
- const res = await handleCloudflareConnectionRequest(
52
- req('https://agentsam.inneranimalmedia.com/api/connections/cloudflare', {
53
- headers: { authorization: 'Bearer sess_1' },
54
- }),
55
- env,
56
- );
57
- assert.equal(res.status, 200);
58
- const json = await res.json();
59
- assert.equal(json.ok, true);
60
- assert.equal(json.configured, false);
61
- assert.equal(json.fixture, true);
62
- assert.equal(JSON.stringify(json).includes('sillynotreal-secret'), false);
63
- });
64
-
65
- it('rejects owner_id in the JSON body', async () => {
66
- const env = { fixtureSessions: new Map([['sess_1', 'user-sam']]) };
67
- const res = await handleCloudflareConnectionRequest(
68
- req('https://agentsam.inneranimalmedia.com/api/connections/cloudflare/disconnect', {
69
- method: 'POST',
70
- headers: { cookie: 'agentsam_session=sess_1', 'content-type': 'application/json' },
71
- body: JSON.stringify({ owner_id: 'evil' }),
72
- }),
73
- env,
74
- );
75
- assert.equal(res.status, 400);
76
- const json = await res.json();
77
- assert.equal(json.error, 'untrusted_owner_hint');
78
- });
79
-
80
- it('rejects callback without a stored oauth state', async () => {
81
- const env = {
82
- CLOUDFLARE_OAUTH_CLIENT_ID: 'real-client-id',
83
- oauthState: new Map(),
84
- };
85
- const res = await handleCloudflareConnectionRequest(
86
- req('https://agentsam.inneranimalmedia.com/api/connections/cloudflare/callback?code=abc&state=missing'),
87
- env,
88
- );
89
- assert.equal(res.status, 403);
90
- const json = await res.json();
91
- assert.equal(json.error, 'cloudflare_connection_forbidden');
92
- });
93
- });