History

Replace repository contents with v4 snapshot

Rhys Sullivan committed 7 months ago

Commit 4fcdba41 parent be4bbf5865 files · +36247 −404676Browse files

Unified · Split

429 files
  1. .changeset/README.md +14 −5
  2. .changeset/config.json +23 −1
  3. .changeset/funny-forks-listen.md +0 −5
  4. .changeset/fuzzy-camels-cheer.md +0 −5
  5. .changeset/pre.json +22 −53
  6. .changeset/quick-cars-approve.md +0 −5
  7. .changeset/ripe-yaks-sniff.md +1 −1
  8. .changeset/tame-trains-confess.md +0 −5
  9. .changeset/tasty-geese-cough.md +0 −5
  10. .executor/executor.jsonc +0 −347
  11. .github/workflows/publish-executor-package.yml +6 −8
  12. .github/workflows/release.yml +6 −4
  13. .gitignore +21 −72
  14. .mcp.json +4 −12
  15. .oxlintrc.jsonc +2 −84
  16. .reference/effect +1 −0
  17. .reference/effect-atom +1 −0
  18. .reference/executor +1 −0
  19. .skills/effect-http-testing/SKILL.md +205 −0
  20. .skills/effect-use-pattern/SKILL.md +210 −0
  21. .vscode/settings.json +4 −0
  22. AGENTS.md +1 −0
  23. CLAUDE.md +1 −0
  24. LICENSE +0 −21
  25. README.md +0 −395
  26. RELEASING.md +50 −0
  27. apps/cli/bin/executor.ts +2 −0
  28. apps/cli/package.json +35 −0
  29. apps/cli/src/build.ts +465 −0
  30. apps/cli/src/embedded-web-ui.gen.d.ts +4 −0
  31. apps/cli/src/main.ts +388 −0
  32. apps/cli/src/release.ts +270 −0
  33. apps/cli/tsconfig.json +14 −0
  34. apps/docs/CHANGELOG.md +0 −3
  35. apps/docs/docs.json +0 −32
  36. apps/docs/introduction.mdx +0 −10
  37. apps/docs/package.json +0 −11
  38. apps/executor/CHANGELOG.md +0 −175
  39. apps/executor/bin/executor +0 −10
  40. apps/executor/package.json +0 −65
  41. apps/executor/src/cli/interaction-handling.test.ts +0 −37
  42. apps/executor/src/cli/interaction-handling.ts +0 −18
  43. apps/executor/src/cli/main.ts +0 −1196
  44. apps/executor/src/cli/pending-interaction-output.ts +0 −125
  45. apps/executor/src/cli/runtime-paths.test.ts +0 −47
  46. apps/executor/src/cli/runtime-paths.ts +0 −109
  47. apps/executor/src/cli/session-summary.test.ts +0 −60
  48. apps/executor/src/cli/session-summary.ts +0 −64
  49. apps/executor/src/distribution/artifact.ts +0 −359
  50. apps/executor/src/distribution/distribution.test.ts +0 −110
  51. apps/executor/src/distribution/harness.ts +0 −385
  52. apps/executor/src/distribution/metadata.ts +0 −38
  53. apps/executor/src/distribution/publish.ts +0 −224
  54. apps/executor/src/effect-errors.ts +0 −40
  55. apps/executor/tsconfig.json +0 −16
  56. apps/server/package.json +38 −0
  57. apps/server/src/dev-backend.ts +20 −0
  58. apps/server/src/handlers/executions.ts +67 −0
  59. apps/server/src/handlers/google-discovery.ts +16 −0
  60. apps/server/src/handlers/graphql.ts +17 −0
  61. apps/server/src/handlers/mcp-source.ts +17 −0
  62. apps/server/src/handlers/onepassword.ts +17 −0
  63. apps/server/src/handlers/openapi.ts +17 −0
  64. apps/server/src/handlers/scope.ts +20 −0
  65. apps/server/src/handlers/secrets.ts +70 −0
  66. apps/server/src/handlers/sources.ts +67 −0
  67. apps/server/src/handlers/tools.ts +32 −0
  68. apps/server/src/index.ts +4 −0
  69. apps/server/src/main.ts +128 −0
  70. apps/server/src/mcp.ts +122 −0
  71. apps/server/src/services/engine.ts +7 −0
  72. apps/server/src/services/executor.ts +205 −0
  73. apps/server/tsconfig.json +22 −0
  74. apps/web/CHANGELOG.md +0 −8
  75. apps/web/components.json +5 −6
  76. apps/web/executor.jsonc +3 −0
  77. apps/web/index.html +15 −0
  78. apps/web/package.json +28 −40
  79. apps/web/src/App.tsx +6 −0
  80. apps/web/src/components/code-block.tsx +0 −96
  81. apps/web/src/components/document-panel.tsx +0 −30
  82. apps/web/src/components/icons.tsx +0 −160
  83. apps/web/src/components/loadable.tsx +0 −50
  84. apps/web/src/components/local-mcp-install-card.tsx +0 −213
  85. apps/web/src/components/mcp-install-card.tsx +77 −0
  86. apps/web/src/components/shell.tsx +0 −561
  87. apps/web/src/components/source-favicon.tsx +0 −133
  88. apps/web/src/components/source-not-found-state.tsx +0 −39
  89. apps/web/src/components/source-plugins-reset-state.tsx +0 −27
  90. apps/web/src/components/source-recovery-state.tsx +0 −57
  91. apps/web/src/components/tool-detail.tsx +203 −0
  92. apps/web/src/components/tool-tree.tsx +367 −0
  93. apps/web/src/dev.ts +0 −123
  94. apps/web/src/frontend.tsx +0 −19
  95. apps/web/src/index.html +0 −30
  96. apps/web/src/lib/schema-type-signature.ts +223 −0
  97. apps/web/src/lib/source-favicon.ts +0 −4
  98. apps/web/src/lib/use-scope.ts +1 −0
  99. apps/web/src/lib/utils.ts +0 −6
  100. apps/web/src/main.tsx +6 −137
  101. apps/web/src/pages/secrets.tsx +391 −0
  102. apps/web/src/pages/source-detail.tsx +195 −0
  103. apps/web/src/pages/sources.tsx +377 −0
  104. apps/web/src/pages/tools.tsx +73 −0
  105. apps/web/src/plugins/index.ts +0 −96
  106. apps/web/src/plugins/pages.tsx +0 −260
  107. apps/web/src/plugins/source-presets.ts +0 −657
  108. apps/web/src/router.tsx +73 −0
  109. apps/web/src/server.ts +0 −13
  110. apps/web/src/shell.tsx +473 −0
  111. apps/web/src/views/home.tsx +0 −123
  112. apps/web/src/views/policies.tsx +0 −652
  113. apps/web/src/views/secrets.tsx +0 −1073
  114. apps/web/tsconfig.json +11 −13
  115. apps/web/vite.config.ts +173 −76
  116. architecture.md +0 −124
  117. bun.lock +961 −1311
  118. compose.tracing.yaml +0 −9
  119. examples/mcp-elicitation-demo/CHANGELOG.md +0 −3
  120. examples/mcp-elicitation-demo/package.json +0 −21
  121. examples/mcp-elicitation-demo/src/index.ts +0 −4
  122. examples/mcp-elicitation-demo/src/main.ts +0 −20
  123. examples/mcp-elicitation-demo/src/server.ts +0 −222
  124. examples/mcp-elicitation-demo/tsconfig.json +0 −15
  125. examples/serve-skills-via-mcp/CHANGELOG.md +0 −3
  126. examples/serve-skills-via-mcp/README.md +0 −38
  127. examples/serve-skills-via-mcp/package.json +0 −21
  128. examples/serve-skills-via-mcp/skills/postgres-incident-triage/SKILL.md +0 −28
  129. examples/serve-skills-via-mcp/skills/postgres-incident-triage/references/error-codes.md +0 −6
  130. examples/serve-skills-via-mcp/skills/postgres-incident-triage/scripts/blocked-session-query.sql +0 −26
  131. examples/serve-skills-via-mcp/skills/release-notes-writer/SKILL.md +0 −28
  132. examples/serve-skills-via-mcp/skills/release-notes-writer/assets/release-template.md +0 −16
  133. examples/serve-skills-via-mcp/skills/release-notes-writer/references/style-guide.md +0 −7
  134. examples/serve-skills-via-mcp/skills/release-notes-writer/scripts/validate-headings.ts +0 −10
  135. examples/serve-skills-via-mcp/src/catalog.ts +0 −243
  136. examples/serve-skills-via-mcp/src/index.ts +0 −4
  137. examples/serve-skills-via-mcp/src/main.ts +0 −20
  138. examples/serve-skills-via-mcp/src/server.ts +0 −346
  139. examples/serve-skills-via-mcp/src/smoke.ts +0 −67
  140. examples/serve-skills-via-mcp/tsconfig.json +0 −15
  141. examples/sqlite-sdk-consumer/.gitignore +0 −1
  142. examples/sqlite-sdk-consumer/README.md +0 −41
  143. examples/sqlite-sdk-consumer/package.json +0 −22
  144. examples/sqlite-sdk-consumer/src/index.ts +0 −4
  145. examples/sqlite-sdk-consumer/src/main.ts +0 −54
  146. examples/sqlite-sdk-consumer/src/sqlite-backend.ts +0 −733
  147. examples/sqlite-sdk-consumer/tsconfig.json +0 −15
  148. knip.json +0 −63
  149. opencode.json +0 −17
  150. package.json +48 −23
  151. packages/clients/react/CHANGELOG.md +0 −7
  152. packages/clients/react/components.json +0 −21
  153. packages/clients/react/package.json +13 −39
  154. packages/clients/react/src/atoms.ts +78 −0
  155. packages/clients/react/src/base-url.ts +12 −0
  156. packages/clients/react/src/client.ts +20 −0
  157. packages/clients/react/src/components/secret-reference-field.tsx +0 −444
  158. packages/clients/react/src/core/api-atoms.ts +0 −210
  159. packages/clients/react/src/core/base-url.ts +0 −12
  160. packages/clients/react/src/core/http-client.ts +0 −73
  161. packages/clients/react/src/core/loadable.ts +0 −61
  162. packages/clients/react/src/core/reactivity.ts +0 −77
  163. packages/clients/react/src/core/types.ts +0 −16
  164. packages/clients/react/src/core/workspace.ts +0 −62
  165. packages/clients/react/src/hooks/executions.ts +0 −46
  166. packages/clients/react/src/hooks/local.ts +0 −21
  167. packages/clients/react/src/hooks/mutations.ts +0 −44
  168. packages/clients/react/src/hooks/policies.ts +0 −135
  169. packages/clients/react/src/hooks/secrets.ts +0 −153
  170. packages/clients/react/src/hooks/sources.ts +0 −156
  171. packages/clients/react/src/index.test.tsx +0 −428
  172. packages/clients/react/src/index.ts +42 −92
  173. packages/clients/react/src/plugins/components/code-block.tsx +0 −107
  174. packages/clients/react/src/plugins/components/document-panel.tsx +0 −30
  175. packages/clients/react/src/plugins/components/icons.tsx +0 −90
  176. packages/clients/react/src/plugins/components/loadable.tsx +0 −51
  177. packages/clients/react/src/plugins/components/markdown.tsx +0 −41
  178. packages/clients/react/src/plugins/components/source-tool-explorer-search.ts +0 −24
  179. packages/clients/react/src/plugins/components/source-tool-explorer.tsx +0 −198
  180. packages/clients/react/src/plugins/components/source-tool-workbench.tsx +0 −918
  181. packages/clients/react/src/plugins/components/tool-permission-badge.tsx +0 −137
  182. packages/clients/react/src/plugins/components/ui/alert.tsx +0 −80
  183. packages/clients/react/src/plugins/components/ui/badge.tsx +0 −57
  184. packages/clients/react/src/plugins/components/ui/button.tsx +0 −63
  185. packages/clients/react/src/plugins/components/ui/command.tsx +0 −144
  186. packages/clients/react/src/plugins/components/ui/dialog.tsx +0 −164
  187. packages/clients/react/src/plugins/components/ui/input.tsx +0 −26
  188. packages/clients/react/src/plugins/components/ui/popover.tsx +0 −48
  189. packages/clients/react/src/plugins/components/ui/select.tsx +0 −24
  190. packages/clients/react/src/plugins/components/ui/separator.tsx +0 −23
  191. packages/clients/react/src/plugins/components/ui/textarea.tsx +0 −18
  192. packages/clients/react/src/plugins/index.ts +0 −126
  193. packages/clients/react/src/plugins/lib/cn.ts +0 −6
  194. packages/clients/react/src/plugins/lib/shiki.ts +0 −211
  195. packages/clients/react/src/plugins/lib/utils.ts +0 −6
  196. packages/clients/react/src/plugins/paths.ts +0 −105
  197. packages/clients/react/src/plugins/plugin-route-context.tsx +0 −55
  198. packages/clients/react/src/plugins/registry.ts +0 −108
  199. packages/clients/react/src/plugins/route-context.tsx +0 −64
  200. packages/clients/react/src/plugins/types.ts +0 −76
  201. packages/clients/react/src/provider.tsx +7 −4
  202. packages/clients/react/src/scope-context.tsx +55 −0
  203. packages/clients/react/src/secret-picker.tsx +136 −0
  204. packages/clients/react/src/secret-provider-plugin.ts +26 −0
  205. packages/clients/react/src/source-plugin.ts +71 −0
  206. packages/clients/react/src/source-plugins/index.ts +0 −1
  207. packages/clients/react/src/use-scope.ts +2 −0
  208. packages/clients/react/tsconfig.json +14 −13
  209. packages/core/api/package.json +6 −6
  210. packages/core/api/src/api.ts +31 −0
  211. packages/core/api/src/errors.ts +26 −0
  212. packages/core/api/src/executions/api.ts +65 −0
  213. packages/core/api/src/index.ts +6 −0
  214. packages/core/api/src/scope/api.ts +23 −0
  215. packages/core/api/src/secrets/api.ts +89 −0
  216. packages/core/api/src/sources/api.ts +80 −0
  217. packages/core/api/src/tools/api.ts +57 −0
  218. packages/core/api/tsconfig.json +21 −0
  219. packages/core/config/package.json +25 −0
  220. packages/core/config/src/config-store.ts +190 −0
  221. packages/core/config/src/config.test.ts +304 −0
  222. packages/core/config/src/index.ts +24 −0
  223. packages/core/config/src/load.ts +56 −0
  224. packages/core/config/src/schema.ts +127 −0
  225. packages/core/config/src/write.ts +172 −0
  226. packages/core/config/tsconfig.json +21 −0
  227. packages/core/config/vitest.config.ts +0 −0
  228. packages/core/execution/package.json +6 −5
  229. packages/core/execution/src/description.ts +58 −0
  230. packages/core/execution/src/engine.ts +256 −0
  231. packages/core/execution/src/index.ts +13 −0
  232. packages/core/execution/src/tool-invoker.ts +73 −0
  233. packages/core/execution/tsconfig.json +23 −0
  234. packages/core/sdk/package.json +21 −0
  235. packages/core/sdk/src/elicitation.ts +78 −0
  236. packages/core/sdk/src/errors.ts +39 −0
  237. packages/core/sdk/src/executor.ts +229 −0
  238. packages/core/sdk/src/ids.ts +13 −0
  239. packages/core/sdk/src/in-memory/policy-engine.ts +27 −0
  240. packages/core/sdk/src/in-memory/secret-store.ts +133 −0
  241. packages/core/sdk/src/in-memory/tool-registry.ts +201 −0
  242. packages/core/sdk/src/index.test.ts +682 −0
  243. packages/core/sdk/src/index.ts +101 −0
  244. packages/core/sdk/src/plugin-kv.ts +66 −0
  245. packages/core/sdk/src/plugin.ts +77 −0
  246. packages/core/sdk/src/plugins/in-memory-tools.ts +335 −0
  247. packages/core/sdk/src/policies.ts +37 −0
  248. packages/core/sdk/src/runtime-tools.ts +183 −0
  249. packages/core/sdk/src/schema-refs.ts +144 −0
  250. packages/core/sdk/src/scope.ts +9 −0
  251. packages/core/sdk/src/secrets.ts +106 −0
  252. packages/core/sdk/src/sources.ts +186 −0
  253. packages/core/sdk/src/testing.ts +38 −0
  254. packages/core/sdk/src/tools.ts +214 −0
  255. packages/core/sdk/tsconfig.json +21 −0
  256. packages/core/sdk/vitest.config.ts +0 −0
  257. packages/core/storage-file/package.json +25 −0
  258. packages/core/storage-file/src/index.test.ts +261 −0
  259. packages/core/storage-file/src/index.ts +102 −0
  260. packages/core/storage-file/src/migrations/0001_initial.ts +19 −0
  261. packages/core/storage-file/src/migrations/index.ts +13 −0
  262. packages/core/storage-file/src/plugin-kv.ts +99 −0
  263. packages/core/storage-file/src/policy-engine.ts +65 −0
  264. packages/core/storage-file/src/schema.ts +13 −0
  265. packages/core/storage-file/src/secret-store.ts +176 −0
  266. packages/core/storage-file/src/sql-utils.ts +18 −0
  267. packages/core/storage-file/src/tool-registry.ts +214 −0
  268. packages/core/storage-file/tsconfig.json +21 −0
  269. packages/dev/effect-test-utils/src/index.ts +0 −103
  270. packages/dev/effect-test-utils/tsconfig.json +0 −15
  271. packages/dev/kitchen-sink/CHANGELOG.md +0 −11
  272. packages/dev/kitchen-sink/package.json +0 −26
  273. packages/dev/kitchen-sink/src/effect-errors.ts +0 −13
  274. packages/dev/kitchen-sink/src/index.ts +0 −1
  275. packages/dev/kitchen-sink/src/kitchen-sink.test.ts +0 −134
  276. packages/dev/kitchen-sink/src/playground.ts +0 −55
  277. packages/dev/kitchen-sink/tsconfig.json +0 −15
  278. packages/hosts/ai-sdk/CHANGELOG.md +0 −8
  279. packages/hosts/ai-sdk/package.json +0 −28
  280. packages/hosts/ai-sdk/src/ai.ts +0 −7
  281. packages/hosts/ai-sdk/src/effect-errors.ts +0 −13
  282. packages/hosts/ai-sdk/src/example-codemode-inproc.ts +0 −51
  283. packages/hosts/ai-sdk/src/example-dynamic.ts +0 −50
  284. packages/hosts/ai-sdk/src/example-static.ts +0 −42
  285. packages/hosts/ai-sdk/src/example.ts +0 −3
  286. packages/hosts/ai-sdk/src/index.ts +0 −66
  287. packages/hosts/ai-sdk/tsconfig.json +0 −15
  288. packages/hosts/mcp/CHANGELOG.md +0 −7
  289. packages/hosts/mcp/package.json +9 −12
  290. packages/hosts/mcp/src/index.ts +1 −665
  291. packages/hosts/mcp/src/paused-result.test.ts +0 −101
  292. packages/hosts/mcp/src/paused-result.ts +0 −95
  293. packages/hosts/mcp/src/server.ts +211 −0
  294. packages/hosts/mcp/tsconfig.json +14 −6
  295. packages/kernel/core/CHANGELOG.md +0 −3
  296. packages/kernel/core/package.json +2 −2
  297. packages/kernel/core/src/discovery.ts +0 −486
  298. packages/kernel/core/src/http-request-placements.ts +0 −164
  299. packages/kernel/core/src/index.test.ts +0 −684
  300. packages/kernel/core/src/index.ts +2 −6
  301. packages/kernel/core/src/isomorphic-hash.ts +0 −132
  302. packages/kernel/core/src/schema-types.test.ts +0 −98
  303. packages/kernel/core/src/schema-types.ts +0 −249
  304. packages/kernel/core/src/system-tools.ts +0 −247
  305. packages/kernel/core/src/tool-map.ts +0 −549
  306. packages/kernel/core/src/types.ts +32 −262
  307. packages/kernel/core/src/validation.ts +89 −0
  308. packages/kernel/core/tsconfig.json +11 −1
  309. packages/kernel/ir/README.md +0 −31
  310. packages/kernel/ir/package.json +3 −7
  311. packages/kernel/ir/src/catalog.test.ts +0 −895
  312. packages/kernel/ir/src/catalog.ts +0 −1429
  313. packages/kernel/ir/src/ids.ts +0 −58
  314. packages/kernel/ir/src/index.ts +8 −3
  315. packages/kernel/ir/src/model.ts +0 −919
  316. packages/kernel/ir/src/registry.ts +32 −0
  317. packages/kernel/ir/src/serialize.ts +85 −0
  318. packages/kernel/ir/tsconfig.json +11 −1
  319. packages/kernel/runtime-deno-subprocess/CHANGELOG.md +0 −7
  320. packages/kernel/runtime-deno-subprocess/package.json +2 −2
  321. packages/kernel/runtime-deno-subprocess/src/deno-worker-process.ts +0 −1
  322. packages/kernel/runtime-deno-subprocess/src/index.test.ts +41 −73
  323. packages/kernel/runtime-deno-subprocess/src/index.ts +231 −255
  324. packages/kernel/runtime-deno-subprocess/tsconfig.json +8 −1
  325. packages/kernel/runtime-quickjs/CHANGELOG.md +0 −7
  326. packages/kernel/runtime-quickjs/package.json +2 −2
  327. packages/kernel/runtime-quickjs/src/index.test.ts +127 −255
  328. packages/kernel/runtime-quickjs/src/index.ts +24 −8
  329. packages/kernel/runtime-quickjs/tsconfig.json +11 −1
  330. packages/kernel/runtime-ses/CHANGELOG.md +0 −7
  331. packages/kernel/runtime-ses/src/index.ts +0 −239
  332. packages/kernel/runtime-ses/src/sandbox-worker.mjs +0 −182
  333. packages/kernel/runtime-ses/tsconfig.json +0 −15
  334. packages/platform/api/package.json +0 −39
  335. packages/platform/api/src/api.ts +0 −74
  336. packages/platform/api/src/effect.ts +0 −22
  337. packages/platform/api/src/errors.ts +0 −7
  338. packages/platform/api/src/executions/api.ts +0 −73
  339. packages/platform/api/src/executions/http.ts +0 −32
  340. packages/platform/api/src/executor-context.ts +0 −33
  341. packages/platform/api/src/http.ts +0 −50
  342. packages/platform/api/src/index.ts +0 −62
  343. packages/platform/api/src/local-context.ts +0 −6
  344. packages/platform/api/src/local/api.ts +0 −127
  345. packages/platform/api/src/local/http.ts +0 −120
  346. packages/platform/api/src/plugins.ts +0 −23
  347. packages/platform/api/src/policies/api.ts +0 −81
  348. packages/platform/api/src/policies/http.ts +0 −47
  349. packages/platform/api/src/sources/api.ts +0 −78
  350. packages/platform/api/src/sources/http.ts +0 −64
  351. packages/platform/api/tsconfig.json +0 −13
  352. packages/platform/sdk-file/package.json +0 −33
  353. packages/platform/sdk-file/src/capture-release-workspace-fixture.ts +0 −374
  354. packages/platform/sdk-file/src/client.ts +0 −5
  355. packages/platform/sdk-file/src/config-codec.ts +0 −93
  356. packages/platform/sdk-file/src/config-migrations.test.ts +0 −189
  357. packages/platform/sdk-file/src/config-migrations/index.ts +0 −48
  358. packages/platform/sdk-file/src/config-migrations/legacy-local-config.ts +0 −539
  359. packages/platform/sdk-file/src/config.test.ts +0 −144
  360. packages/platform/sdk-file/src/config.ts +0 −390
  361. packages/platform/sdk-file/src/effect.ts +0 −28
  362. packages/platform/sdk-file/src/errors.ts +0 −105
  363. packages/platform/sdk-file/src/executor-state-codec.ts +0 −82
  364. packages/platform/sdk-file/src/executor-state-migrations.test.ts +0 −231
  365. packages/platform/sdk-file/src/executor-state-migrations/index.ts +0 −32
  366. packages/platform/sdk-file/src/executor-state-migrations/legacy-local-executor-state.ts +0 −356
  367. packages/platform/sdk-file/src/executor-state-store.ts +0 −702
  368. packages/platform/sdk-file/src/index.ts +0 −426
  369. packages/platform/sdk-file/src/installation.test.ts +0 −70
  370. packages/platform/sdk-file/src/installation.ts +0 −39
  371. packages/platform/sdk-file/src/release-upgrade-fixtures.ts +0 −100
  372. packages/platform/sdk-file/src/runtime.ts +0 −2
  373. packages/platform/sdk-file/src/secret-material-providers.test.ts +0 −98
  374. packages/platform/sdk-file/src/secret-material-providers.ts +0 −502
  375. packages/platform/sdk-file/src/source-artifacts.ts +0 −170
  376. packages/platform/sdk-file/src/source-type-declarations.ts +0 −427
  377. packages/platform/sdk-file/src/tools.ts +0 −643
  378. packages/platform/sdk-file/src/workspace-state.ts +0 −80
  379. packages/platform/sdk-file/tsconfig.json +0 −13
  380. packages/platform/sdk/package.json +0 −51
  381. packages/platform/sdk/src/backend.ts +0 −272
  382. packages/platform/sdk/src/contracts.ts +0 −3
  383. packages/platform/sdk/src/effect.ts +0 −1
  384. packages/platform/sdk/src/errors.ts +0 −54
  385. packages/platform/sdk/src/executions/contracts.ts +0 −23
  386. packages/platform/sdk/src/executor-effect.ts +0 −502
  387. packages/platform/sdk/src/executor.ts +0 −175
  388. packages/platform/sdk/src/index.ts +0 −3
  389. packages/platform/sdk/src/local/contracts.ts +0 −159
  390. packages/platform/sdk/src/local/operations.ts +0 −25
  391. packages/platform/sdk/src/local/secret-stores.ts +0 −444
  392. packages/platform/sdk/src/local/secrets.ts +0 −241
  393. packages/platform/sdk/src/operations.ts +0 −5
  394. packages/platform/sdk/src/plugins.ts +0 −1628
  395. packages/platform/sdk/src/policies/contracts.ts +0 −25
  396. packages/platform/sdk/src/policies/operations.ts +0 −429
  397. packages/platform/sdk/src/runtime/__fixtures__/README.md +0 −38
  398. packages/platform/sdk/src/runtime/__fixtures__/v1.2.3-google-calendar-workspace/.executor/artifacts/sources/google-calendar.json +0 −1
  399. packages/platform/sdk/src/runtime/__fixtures__/v1.2.3-google-calendar-workspace/.executor/artifacts/sources/google-calendar/documents/doc_3c24a6731267de91.txt +0 −3294
  400. packages/platform/sdk/src/runtime/__fixtures__/v1.2.3-google-calendar-workspace/.executor/executor.jsonc +0 −19
  401. packages/platform/sdk/src/runtime/__fixtures__/v1.2.3-google-calendar-workspace/.executor/state/workspace-state.json +0 −13
  402. packages/platform/sdk/src/runtime/__fixtures__/v1.2.3-google-calendar-workspace/fixture.json +0 −9
  403. packages/platform/sdk/src/runtime/catalog/catalog-typescript.ts +0 −1264
  404. packages/platform/sdk/src/runtime/catalog/prettier-format.ts +0 −59
  405. packages/platform/sdk/src/runtime/catalog/schema-type-signature.ts +0 −114
  406. packages/platform/sdk/src/runtime/catalog/source/reconcile.ts +0 −94
  407. packages/platform/sdk/src/runtime/catalog/source/runtime.ts +0 −1323
  408. packages/platform/sdk/src/runtime/catalog/source/sync.ts +0 −295
  409. packages/platform/sdk/src/runtime/catalog/source/type-declarations.ts +0 −27
  410. packages/platform/sdk/src/runtime/effect-errors.ts +0 −13
  411. packages/platform/sdk/src/runtime/execution/http.test.ts +0 −176
  412. packages/platform/sdk/src/runtime/execution/ir-execution.ts +0 −85
  413. packages/platform/sdk/src/runtime/execution/live.test.ts +0 −52
  414. packages/platform/sdk/src/runtime/execution/live.ts +0 −278
  415. packages/platform/sdk/src/runtime/execution/runtime-config.test.ts +0 −159
  416. packages/platform/sdk/src/runtime/execution/runtime.ts +0 −36
  417. packages/platform/sdk/src/runtime/execution/scope/authorization.ts +0 −175
  418. packages/platform/sdk/src/runtime/execution/scope/environment.ts +0 −190
  419. packages/platform/sdk/src/runtime/execution/scope/local.ts +0 −12
  420. packages/platform/sdk/src/runtime/execution/scope/source-catalog.test.ts +0 −324
  421. packages/platform/sdk/src/runtime/execution/scope/source-catalog.ts +0 −394
  422. packages/platform/sdk/src/runtime/execution/scope/tool-invoker.ts +0 −297
  423. packages/platform/sdk/src/runtime/execution/service.ts +0 −1024
  424. packages/platform/sdk/src/runtime/execution/state.ts +0 −31
  425. packages/platform/sdk/src/runtime/execution/test-http-client.ts +0 −120
  426. packages/platform/sdk/src/runtime/executor-state-store.ts +0 −162
  427. packages/platform/sdk/src/runtime/fixtures/google-sheets-discovery.json +0 −8314
  428. packages/platform/sdk/src/runtime/fixtures/linear-introspection.json +0 −129477
  429. packages/platform/sdk/src/runtime/fixtures/neon-openapi.json +0 −14358
.changeset/README.md+14−5
@@ -1,8 +1,17 @@
11 # Changesets
22
3−Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4−with multi-package repos, or single-package repos to help you version and publish your code. You can
5−find the full documentation for it [in our repository](https://github.com/changesets/changesets).
3+This repo uses Changesets to drive releases for the published `executor` CLI.
64
7−We have a quick list of common questions to get you started engaging with this project in
8−[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md).
5+## What to put in a changeset
6+
7+Only `executor` is managed directly by Changesets.
8+
9+After `changeset version` runs, `scripts/release/sync-versions.mjs` copies that version to the rest of the repo manifests so the workspace stays aligned without making every internal package independently releasable.
10+
11+## Beta releases
12+
13+Use prerelease mode for beta trains:
14+
15+- `bun run release:beta:start`
16+- merge release PRs while prerelease mode is active
17+- `bun run release:beta:stop` when you want to return to stable releases
.changeset/config.json+23−1
@@ -7,5 +7,27 @@ · 6 unmodified lines
77 "access": "public",
88 "baseBranch": "main",
99 "updateInternalDependencies": "patch",
10− "ignore": []
10+ "ignore": [
11+ "@executor/server",
12+ "@executor/web",
13+ "@executor/react",
14+ "@executor/api",
15+ "@executor/config",
16+ "@executor/execution",
17+ "@executor/sdk",
18+ "@executor/storage-file",
19+ "@executor/host-mcp",
20+ "@executor/codemode-core",
21+ "@executor/ir",
22+ "@executor/runtime-deno-subprocess",
23+ "@executor/runtime-quickjs",
24+ "@executor/plugin-file-secrets",
25+ "@executor/plugin-google-discovery",
26+ "@executor/plugin-graphql",
27+ "@executor/plugin-keychain",
28+ "@executor/plugin-mcp",
29+ "@executor/plugin-onepassword",
30+ "@executor/plugin-openapi",
31+ "@executor/ui"
32+ ]
1133 }
.changeset/funny-forks-listen.md+0−5
@@ -1,5 +0,0 @@
1−---
2−"executor": minor
3−---
4−
5−Prepare the next executor beta minor release.
.changeset/fuzzy-camels-cheer.md+0−5
@@ -1,5 +0,0 @@
1−---
2−"executor": patch
3−---
4−
5−Fix the packaged beta so the bundled 1Password SDK can load its wasm asset after install.
.changeset/pre.json+22−53
@@ -2,59 +2,28 @@ · 1 unmodified line
22 "mode": "pre",
33 "tag": "beta",
44 "initialVersions": {
5− "@executor/docs": "0.0.0",
6− "executor": "1.2.6",
7− "@executor/web": "0.0.0",
8− "@executor/mcp-elicitation-demo": "0.0.0",
9− "@executor/serve-skills-via-mcp-demo": "0.0.0",
10− "@executor/sqlite-sdk-consumer-example": "0.0.0",
11− "@executor/react": "0.0.0",
12− "@executor/effect-test-utils": "0.0.0",
13− "@executor/kitchen-sink": "0.0.0",
14− "@executor/ai-sdk-adapter": "0.0.0",
15− "@executor/executor-mcp": "0.0.0",
16− "@executor/codemode-core": "0.0.0",
17− "@executor/ir": "0.0.0",
5+ "executor": "1.4.0-beta.0",
6+ "@executor/server": "1.4.0-beta.0",
7+ "@executor/web": "1.4.0-beta.0",
8+ "@executor/react": "1.4.0-beta.0",
9+ "@executor/api": "1.4.0-beta.0",
10+ "@executor/config": "1.4.0-beta.0",
11+ "@executor/execution": "1.4.0-beta.0",
12+ "@executor/sdk": "1.4.0-beta.0",
13+ "@executor/storage-file": "1.4.0-beta.0",
14+ "@executor/host-mcp": "1.4.0-beta.0",
15+ "@executor/codemode-core": "1.4.0-beta.0",
16+ "@executor/ir": "1.4.0-beta.0",
1817 "@executor/runtime-deno-subprocess": "0.0.0",
19− "@executor/runtime-quickjs": "0.0.0",
20− "@executor/runtime-ses": "0.0.0",
21− "@executor/platform-api": "0.0.0",
22− "@executor/platform-sdk": "0.0.0",
23− "@executor/platform-sdk-file": "0.0.0",
24− "@executor/server": "0.0.0",
25− "@executor/source-core": "0.0.0",
26− "@executor/plugin-execution-history-react": "0.0.0",
27− "@executor/plugin-google-discovery-http": "0.0.0",
28− "@executor/plugin-google-discovery-react": "0.0.0",
29− "@executor/plugin-google-discovery-sdk": "0.0.0",
30− "@executor/plugin-google-discovery-shared": "0.0.0",
31− "@executor/plugin-graphql-http": "0.0.0",
32− "@executor/plugin-graphql-react": "0.0.0",
33− "@executor/plugin-graphql-sdk": "0.0.0",
34− "@executor/plugin-graphql-shared": "0.0.0",
35− "@executor/plugin-keychain-secret-store-sdk": "0.0.0",
36− "@executor/plugin-local-secret-store-sdk": "0.0.0",
37− "@executor/plugin-local-tools-react": "0.0.0",
38− "@executor/plugin-local-tools-sdk": "0.0.0",
39− "@executor/plugin-mcp-http": "0.0.0",
40− "@executor/plugin-mcp-react": "0.0.0",
41− "@executor/plugin-mcp-sdk": "0.0.0",
42− "@executor/plugin-mcp-shared": "0.0.0",
43− "@executor/plugin-onepassword-http": "0.0.0",
44− "@executor/plugin-onepassword-react": "0.0.0",
45− "@executor/plugin-onepassword-sdk": "0.0.0",
46− "@executor/plugin-onepassword-shared": "0.0.0",
47− "@executor/plugin-openapi-http": "0.0.0",
48− "@executor/plugin-openapi-react": "0.0.0",
49− "@executor/plugin-openapi-sdk": "0.0.0",
50− "@executor/plugin-openapi-shared": "0.0.0"
18+ "@executor/runtime-quickjs": "1.4.0-beta.0",
19+ "@executor/plugin-file-secrets": "1.4.0-beta.0",
20+ "@executor/plugin-google-discovery": "1.4.0-beta.0",
21+ "@executor/plugin-graphql": "1.4.0-beta.0",
22+ "@executor/plugin-keychain": "1.4.0-beta.0",
23+ "@executor/plugin-mcp": "1.4.0-beta.0",
24+ "@executor/plugin-onepassword": "1.4.0-beta.0",
25+ "@executor/plugin-openapi": "1.4.0-beta.0",
26+ "@executor/ui": "1.4.0-beta.0"
5127 },
52− "changesets": [
53− "cute-steaks-sink",
54− "funny-forks-listen",
55− "fuzzy-camels-cheer",
56− "quick-cars-approve",
57− "tame-trains-confess",
58− "tasty-geese-cough"
59− ]
28+ "changesets": []
6029 }
.changeset/quick-cars-approve.md+0−5
@@ -1,5 +0,0 @@
1−---
2−"executor": patch
3−---
4−
5−Improve MCP source setup by auto-detecting OAuth requirements, showing a loading state during discovery, and allowing creation without signing in.
.changeset/ripe-yaks-sniff.mdrenamed from .changeset/cute-steaks-sink.md+1−1
@@ -2,4 +2,4 @@ · 1 unmodified line
22 "executor": patch
33 ---
44
5−Compact openapi sources
5+Release 1.4
.changeset/tame-trains-confess.md+0−5
@@ -1,5 +0,0 @@
1−---
2−"executor": patch
3−---
4−
5−Fix the beta distribution packaging flow so the prerelease publish passes again.
.changeset/tasty-geese-cough.md+0−5
@@ -1,5 +0,0 @@
1−---
2−"executor": patch
3−---
4−
5−Improve Google Discovery sources view
.executor/executor.jsonc+0−347
@@ -1,347 +0,0 @@
1−{
2− "sources": {
3− "vercel": {
4− "name": "Vercel API",
5− "config": {
6− "specUrl": "https://openapi.vercel.sh/",
7− "baseUrl": "https://api.vercel.com/",
8− "auth": {
9− "kind": "none"
10− },
11− "defaultHeaders": null
12− },
13− "kind": "openapi"
14− },
15− "deepwiki-mcp": {
16− "name": "DeepWiki MCP",
17− "namespace": "deepwiki.mcp",
18− "config": {
19− "endpoint": "https://mcp.deepwiki.com/mcp",
20− "transport": "auto",
21− "queryParams": null,
22− "headers": null,
23− "command": null,
24− "args": null,
25− "env": null,
26− "cwd": null,
27− "auth": {
28− "kind": "none"
29− }
30− },
31− "kind": "mcp"
32− },
33− "linear-graphql": {
34− "name": "Linear GraphQL",
35− "namespace": "linear.graphql",
36− "config": {
37− "endpoint": "https://api.linear.app/graphql",
38− "defaultHeaders": null,
39− "auth": {
40− "kind": "none"
41− }
42− },
43− "kind": "graphql"
44− },
45− "axiom-mcp": {
46− "name": "Axiom MCP",
47− "namespace": "axiom.mcp",
48− "config": {
49− "endpoint": "https://mcp.axiom.co/mcp",
50− "transport": "auto",
51− "queryParams": null,
52− "headers": null,
53− "command": null,
54− "args": null,
55− "env": null,
56− "cwd": null,
57− "auth": {
58− "kind": "oauth2",
59− "redirectUri": "http://localhost:8788/v1/plugins/mcp/oauth/callback",
60− "accessTokenRef": {
61− "secretId": "sec_534bd6a9-0bd3-4f66-97ac-ddf22ea2ae82"
62− },
63− "refreshTokenRef": {
64− "secretId": "sec_3e665cbc-2ba9-4d5b-97a4-db811248574f"
65− },
66− "tokenType": "bearer",
67− "expiresAt": 1806390691402,
68− "scope": "",
69− "resourceMetadataUrl": null,
70− "authorizationServerUrl": "https://mcp.axiom.co/",
71− "resourceMetadata": null,
72− "authorizationServerMetadata": {
73− "issuer": "https://mcp.axiom.co",
74− "authorization_endpoint": "https://mcp.axiom.co/authorize",
75− "token_endpoint": "https://mcp.axiom.co/token",
76− "registration_endpoint": "https://mcp.axiom.co/register",
77− "response_types_supported": [
78− "code"
79− ],
80− "response_modes_supported": [
81− "query"
82− ],
83− "grant_types_supported": [
84− "authorization_code",
85− "refresh_token"
86− ],
87− "token_endpoint_auth_methods_supported": [
88− "client_secret_basic",
89− "client_secret_post",
90− "none"
91− ],
92− "revocation_endpoint": "https://mcp.axiom.co/token",
93− "code_challenge_methods_supported": [
94− "plain",
95− "S256"
96− ]
97− },
98− "clientInformation": {
99− "redirect_uris": [
100− "http://localhost:8788/v1/plugins/mcp/oauth/callback"
101− ],
102− "token_endpoint_auth_method": "none",
103− "grant_types": [
104− "authorization_code",
105− "refresh_token"
106− ],
107− "response_types": [
108− "code"
109− ],
110− "client_name": "Executor Local",
111− "client_id": "PgIDrWWSMRBtHHsg",
112− "client_id_issued_at": 1774854684
113− }
114− }
115− },
116− "kind": "mcp"
117− },
118− "mcp-mcp": {
119− "name": "Mcp MCP",
120− "namespace": "mcp.mcp",
121− "config": {
122− "endpoint": "https://mcp.linear.app/mcp",
123− "transport": "auto",
124− "queryParams": null,
125− "headers": null,
126− "command": null,
127− "args": null,
128− "env": null,
129− "cwd": null,
130− "auth": {
131− "kind": "oauth2",
132− "redirectUri": "http://localhost:8788/v1/plugins/mcp/oauth/callback",
133− "accessTokenRef": {
134− "secretId": "sec_ae3503a2-f813-4fe4-8882-1ee7b0e86cab"
135− },
136− "refreshTokenRef": {
137− "secretId": "sec_3e453bf7-9343-41e4-a00e-1b81448591f7"
138− },
139− "tokenType": "bearer",
140− "expiresAt": 1775459747141,
141− "scope": "",
142− "resourceMetadataUrl": null,
143− "authorizationServerUrl": "https://mcp.linear.app",
144− "resourceMetadata": {
145− "resource": "https://mcp.linear.app",
146− "authorization_servers": [
147− "https://mcp.linear.app"
148− ],
149− "bearer_methods_supported": [
150− "header"
151− ]
152− },
153− "authorizationServerMetadata": {
154− "issuer": "https://mcp.linear.app",
155− "authorization_endpoint": "https://mcp.linear.app/authorize",
156− "token_endpoint": "https://mcp.linear.app/token",
157− "registration_endpoint": "https://mcp.linear.app/register",
158− "response_types_supported": [
159− "code"
160− ],
161− "response_modes_supported": [
162− "query"
163− ],
164− "grant_types_supported": [
165− "authorization_code",
166− "refresh_token"
167− ],
168− "token_endpoint_auth_methods_supported": [
169− "client_secret_basic",
170− "client_secret_post",
171− "none"
172− ],
173− "revocation_endpoint": "https://mcp.linear.app/token",
174− "code_challenge_methods_supported": [
175− "plain",
176− "S256"
177− ],
178− "client_id_metadata_document_supported": false
179− },
180− "clientInformation": {
181− "redirect_uris": [
182− "http://localhost:8788/v1/plugins/mcp/oauth/callback"
183− ],
184− "token_endpoint_auth_method": "none",
185− "grant_types": [
186− "authorization_code",
187− "refresh_token"
188− ],
189− "response_types": [
190− "code"
191− ],
192− "client_name": "Executor Local",
193− "client_id": "xYJ-DOv7vWmXjAsi",
194− "client_id_issued_at": 1774854942
195− }
196− }
197− },
198− "kind": "mcp"
199− },
200− "google-calendar": {
201− "name": "Google Calendar",
202− "namespace": "google.calendar",
203− "config": {
204− "service": "calendar",
205− "version": "v3",
206− "discoveryUrl": "https://calendar-json.googleapis.com/$discovery/rest?version=v3",
207− "defaultHeaders": null,
208− "scopes": [
209− "https://www.googleapis.com/auth/calendar"
210− ],
211− "auth": {
212− "kind": "oauth2",
213− "clientId": "171149749557-apegmds63qp2h2u2s55p6rom1j6m3m5k.apps.googleusercontent.com",
214− "clientSecretRef": {
215− "secretId": "sec_f2c1f3ce-97c5-429b-a7bf-22fcd6007de3"
216− },
217− "clientAuthentication": "client_secret_post",
218− "authorizationEndpoint": "https://accounts.google.com/o/oauth2/v2/auth",
219− "tokenEndpoint": "https://oauth2.googleapis.com/token",
220− "scopes": [
221− "https://www.googleapis.com/auth/calendar"
222− ],
223− "accessTokenRef": {
224− "secretId": "sec_023e64bd-8e6b-49cc-b33c-950c31612846"
225− },
226− "refreshTokenRef": {
227− "secretId": "sec_e4c2e96c-b809-4d72-873c-a8ba7d595610"
228− },
229− "expiresAt": 1774859675319
230− }
231− },
232− "kind": "google_discovery"
233− },
234− "google-drive": {
235− "name": "Google Drive",
236− "namespace": "google.drive",
237− "config": {
238− "service": "drive",
239− "version": "v3",
240− "discoveryUrl": "https://www.googleapis.com/discovery/v1/apis/drive/v3/rest",
241− "defaultHeaders": null,
242− "scopes": [
243− "https://www.googleapis.com/auth/drive",
244− "https://www.googleapis.com/auth/drive.apps.readonly"
245− ],
246− "auth": {
247− "kind": "oauth2",
248− "clientId": "171149749557-apegmds63qp2h2u2s55p6rom1j6m3m5k.apps.googleusercontent.com",
249− "clientSecretRef": {
250− "secretId": "sec_f2c1f3ce-97c5-429b-a7bf-22fcd6007de3"
251− },
252− "clientAuthentication": "client_secret_post",
253− "authorizationEndpoint": "https://accounts.google.com/o/oauth2/v2/auth",
254− "tokenEndpoint": "https://oauth2.googleapis.com/token",
255− "scopes": [
256− "https://www.googleapis.com/auth/drive",
257− "https://www.googleapis.com/auth/drive.apps.readonly"
258− ],
259− "accessTokenRef": {
260− "secretId": "sec_39d48e40-634c-4673-8038-8fc7c027c698"
261− },
262− "refreshTokenRef": {
263− "secretId": "sec_ec05b35f-c0ff-4529-b80e-a5638589a6eb"
264− },
265− "expiresAt": 1774859675319
266− }
267− },
268− "kind": "google_discovery"
269− },
270− "google-gmail": {
271− "name": "Gmail",
272− "namespace": "google.gmail",
273− "kind": "google_discovery",
274− "config": {
275− "service": "gmail",
276− "version": "v1",
277− "discoveryUrl": "https://gmail.googleapis.com/$discovery/rest?version=v1",
278− "defaultHeaders": null,
279− "scopes": [
280− "https://mail.google.com/",
281− "https://www.googleapis.com/auth/gmail.settings.basic",
282− "https://www.googleapis.com/auth/gmail.settings.sharing"
283− ],
284− "auth": {
285− "kind": "oauth2",
286− "clientId": "171149749557-apegmds63qp2h2u2s55p6rom1j6m3m5k.apps.googleusercontent.com",
287− "clientSecretRef": {
288− "secretId": "sec_f2c1f3ce-97c5-429b-a7bf-22fcd6007de3"
289− },
290− "clientAuthentication": "client_secret_post",
291− "authorizationEndpoint": "https://accounts.google.com/o/oauth2/v2/auth",
292− "tokenEndpoint": "https://oauth2.googleapis.com/token",
293− "scopes": [
294− "https://mail.google.com/",
295− "https://www.googleapis.com/auth/gmail.settings.basic",
296− "https://www.googleapis.com/auth/gmail.settings.sharing"
297− ],
298− "accessTokenRef": {
299− "secretId": "sec_379eee62-86fe-49fe-93dc-8af40fa04dc3"
300− },
301− "refreshTokenRef": {
302− "secretId": "sec_c58e7cb5-296b-4024-8f22-8b49ef7a7f38"
303− },
304− "expiresAt": 1774859675319
305− }
306− }
307− }
308− },
309− "policies": {
310− "linear.graphql.agentActivities": {
311− "match": "linear.graphql.agentActivities",
312− "action": "allow",
313− "approval": "auto",
314− "priority": 10
315− },
316− "vercel.accessGroups.createAccessGroup": {
317− "match": "vercel.accessGroups.createAccessGroup",
318− "action": "deny",
319− "approval": "auto",
320− "priority": 10
321− },
322− "vercel.dns.createRecord": {
323− "match": "vercel.dns.createRecord",
324− "action": "deny",
325− "approval": "auto",
326− "priority": 10
327− },
328− "vercel.dns.getRecords": {
329− "match": "vercel.dns.getRecords",
330− "action": "deny",
331− "approval": "auto",
332− "priority": 10
333− },
334− "vercel.dns.removeRecord": {
335− "match": "vercel.dns.removeRecord",
336− "action": "deny",
337− "approval": "auto",
338− "priority": 10
339− },
340− "vercel.dns.updateRecord": {
341− "match": "vercel.dns.updateRecord",
342− "action": "allow",
343− "approval": "auto",
344− "priority": 10
345− }
346− }
347−}
.github/workflows/publish-executor-package.yml+6−8
@@ -33,6 +33,8 @@ jobs: · 32 unmodified lines
3333
3434 - name: Setup Bun
3535 uses: oven-sh/setup-bun@v2
36+ with:
37+ bun-version: 1.2.22
3638
3739 - name: Setup Node
3840 uses: actions/setup-node@v4
@@ -48,21 +50,17 @@ jobs: · 9 unmodified lines
4850 - name: Install dependencies
4951 run: bun install --frozen-lockfile
5052
51− - name: Run executor checks
52− run: |
53− bun run --cwd apps/executor typecheck
54− bun run --cwd apps/executor test
53+ - name: Run release checks
54+ run: bun run release:check
5555
5656 - name: Publish package and create release
5757 env:
5858 GH_TOKEN: ${{ github.token }}
5959 NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
60+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
6061 RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
6162 run: |
6263 export GITHUB_REF_TYPE=tag
6364 export GITHUB_REF_NAME="$RELEASE_TAG"
6465 export GITHUB_REF="refs/tags/$RELEASE_TAG"
65− if [ -n "${NPM_TOKEN:-}" ]; then
66− export NODE_AUTH_TOKEN="$NPM_TOKEN"
67− fi
68− bun run --cwd apps/executor release:publish
66+ bun run release:publish
.github/workflows/release.yml+6−4
@@ -1,5 +1,5 @@
11 name: Release
2−run-name: "prepare release"
2+run-name: prepare release
33
44 on:
55 push:
@@ -28,6 +28,8 @@ jobs: · 22 unmodified lines
2828
2929 - name: Setup Bun
3030 uses: oven-sh/setup-bun@v2
31+ with:
32+ bun-version: 1.2.22
3133
3234 - name: Setup Node
3335 uses: actions/setup-node@v4
@@ -57,9 +59,9 @@ jobs: · 23 unmodified lines
5759 before="$(git rev-list --max-count=1 HEAD^ 2>/dev/null || true)"
5860 fi
5961
60− version="$(node -e "console.log(JSON.parse(require('fs').readFileSync('apps/executor/package.json', 'utf8')).version)")"
61− if [ -n "$before" ] && git cat-file -e "$before:apps/executor/package.json" 2>/dev/null; then
62− previous_version="$(git show "$before:apps/executor/package.json" | node -e "let data = ''; process.stdin.setEncoding('utf8'); process.stdin.on('data', (chunk) => { data += chunk; }); process.stdin.on('end', () => { console.log(JSON.parse(data).version ?? ''); });")"
62+ version="$(node -e "console.log(JSON.parse(require('fs').readFileSync('apps/cli/package.json', 'utf8')).version)")"
63+ if [ -n "$before" ] && git cat-file -e "$before:apps/cli/package.json" 2>/dev/null; then
64+ previous_version="$(git show "$before:apps/cli/package.json" | node -e "let data = ''; process.stdin.setEncoding('utf8'); process.stdin.on('data', (chunk) => { data += chunk; }); process.stdin.on('end', () => { console.log(JSON.parse(data).version ?? ''); });")"
6365 else
6466 previous_version=""
6567 fi
.gitignore+21−72
@@ -1,90 +1,39 @@
1−# Environment variables
2−.env
3−.env.*
4−!.env.example
5−.env*.local
6−
7−# Vercel
8−.vercel
9−
10−# Next.js
11−.next/
12−
13−# Turbo
14−.turbo/
15−.turbo-prune-check/
16−
17−# Executor
18−.executor-v2/
19−.executor/*
20−!.executor/executor.json
21−!.executor/executor.jsonc
22−!.executor/tools/
23−!.executor/tools/**
24−.executor/artifacts/
25−.executor/state/
26−.executor/types/
27−
28−# Cloudflare Workers local state
29−**/.wrangler/
30−**/.dev.vars
31−
32−# Dependencies
33−**/node_modules/
34−
35−# TypeScript build info
36−*.tsbuildinfo
1+# dependencies (bun install)
2+node_modules
373
38−# Output / build artifacts
4+# output
395 out
406 dist
417 *.tgz
428
43−# Rust / Cargo build artifacts
44−**/target/
45−tools/openapi-extractor-rs/pkg-*/
46−
47−# Code coverage
9+# code coverage
4810 coverage
4911 *.lcov
5012
51−# Logs
13+# logs
5214 logs
53−*.log
54−report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
15+_.log
16+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
17+
18+# dotenv environment variable files
19+.env
20+.env.development.local
21+.env.test.local
22+.env.production.local
23+.env.local
5524
56−# Caches
25+# caches
5726 .eslintcache
5827 .cache
28+*.tsbuildinfo
29+.turbo
5930
6031 # IntelliJ based IDEs
6132 .idea
6233
63−# Finder (macOS)
34+# Finder (MacOS) folder config
6435 .DS_Store
65−
66−# Convex local backend state
67−convex_local_backend.sqlite3
68−convex_local_storage/
69−
70−# Local OpenAPI sources service state
71−sources/data/*.sqlite
72−sources/data/*.sqlite-shm
73−sources/data/*.sqlite-wal
74−packages/platform/server/:memory:/
75−
76−# Composio toolkit scrape outputs
77−sources/composio-scrape/data/
78−
79−# Dev runner PID file
80−.dev.pids
81−
82−# Misc
83−*.har
84−.chat-links.json
85−.reference/
8636 personal-notes/
87−.tmp/
88−executor/.env.executor-push
89−ignored/
90−agent-notes/
37+*.har.executor
38+executor.har
39+.executor/
.mcp.json+4−12
@@ -1,20 +1,12 @@
11 {
22 "mcpServers": {
3− "executor-stdio": {
3+ "executor": {
44 "command": "bun",
55 "args": [
66 "run",
7− "executor",
8− "mcp",
9− "--stdio"
10− ]
11− },
12− "executor-stdio-prod": {
13− "command": "executor",
14− "args": [
15− "mcp",
16− "--stdio"
7+ "/Users/rhyssullivan/src/v4-executor/apps/cli/src/main.ts",
8+ "mcp"
179 ]
1810 }
1911 }
20−}
12+}
.oxlintrc.jsonc+2−84
@@ -1,87 +1,5 @@
11 {
2− "$schema": "./node_modules/oxlint/configuration_schema.json",
3−
4− // Keep the built-in default plugin set explicit so monorepo lint behavior
5− // does not drift when oxlint changes its defaults.
6− "plugins": ["typescript", "oxc", "unicorn"],
7−
8− "categories": {
9− "correctness": "warn",
10− },
11−
12− "ignorePatterns": [
13− "**/node_modules/**",
14− "**/.turbo/**",
15− "**/dist/**",
16− "**/coverage/**",
17− "**/.next/**",
18− "**/.mint/**",
19− ],
20−
21− "settings": {
22− "executorMonorepo": {
23− "packageScopes": ["@executor/"],
24− },
25− },
26−
27− "jsPlugins": [
28− {
29− "name": "executor-monorepo",
30− "specifier": "./tools/oxlint/plugin.mjs",
31− },
32− ],
33−
342 "rules": {
35− // This repo uses Effect.gen heavily. The underlying generator syntax is an
36− // implementation detail, so "no yield" is not a useful signal here.
37− "require-yield": "off",
38−
39− "no-unused-vars": "warn",
40−
41− // Monorepo-specific rules.
42− "executor-monorepo/no-async-effect-vitest-tests": "error",
43− "executor-monorepo/no-cross-workspace-relative-imports": "error",
44− "executor-monorepo/no-direct-effect-tag-read": "error",
45− "executor-monorepo/no-effect-env-any": "error",
46− "executor-monorepo/no-effect-never-cast": "error",
47− "executor-monorepo/no-effect-run-in-effect-vitest-tests": "error",
48− "executor-monorepo/no-manual-httpapi-openapi-bridge": "error",
49− "executor-monorepo/no-manual-openapi-documents": "error",
50− "executor-monorepo/no-node-fs-with-effect-imports": "error",
51− "executor-monorepo/no-raw-effect-fail-errors": "error",
52− "executor-monorepo/no-yield-effect-fail": "error",
53− "executor-monorepo/no-workspace-src-imports": "warn",
54− },
55−
56− "overrides": [
57− {
58− // SDK tests still use relative workspace imports to avoid introducing
59− // package-graph cycles from test-only dependencies.
60− "files": [
61− "packages/platform/sdk/src/executor.test.ts",
62− "packages/platform/sdk/src/runtime/executor-runtime.test.ts",
63− "packages/platform/server/src/index.test.ts",
64− "packages/clients/react/src/index.test.tsx"
65− ],
66− "rules": {
67− "executor-monorepo/no-cross-workspace-relative-imports": "off"
68− }
69− },
70− {
71− // JSON Schema conditionals legitimately use a `then` key.
72− "files": [
73− "packages/platform/control-plane/src/runtime/catalog/source/runtime.ts",
74− ],
75− "rules": {
76− "unicorn/no-thenable": "off",
77− },
78− },
79− {
80− // This stack-integrity check intentionally prefers invariant failures in cleanup.
81− "files": ["packages/sources/core/src/catalog-json-schema.ts"],
82− "rules": {
83− "no-unsafe-finally": "off",
84− },
85− },
86− ],
3+ "typescript/no-explicit-any": "error"
4+ }
875 }
.reference/effect+1−0
@@ -0,0 +1 @@
1+Subproject commit ec5c50507b1a2f5ad712c148a7da0fadb8cb9f52
.reference/effect-atom+1−0
@@ -0,0 +1 @@
1+Subproject commit 957095fdfc930eae666f78d65f7af8584959bffd
.reference/executor+1−0
@@ -0,0 +1 @@
1+Subproject commit 2d532f8322368eedc835fa09dc9223a9ddef9e1d
.skills/effect-http-testing/SKILL.md+205−0
@@ -0,0 +1,205 @@
1+---
2+name: effect-http-testing
3+description: Testing Effect HttpApi services end-to-end. Use when writing tests that involve Effect's HttpApi, HttpApiBuilder, HttpClient, HttpServer, or when testing any HTTP service/plugin built with @effect/platform. Covers proper layer composition, test server setup, HttpClient injection, and common pitfalls.
4+---
5+
6+# Effect HTTP Testing
7+
8+## Core Pattern
9+
10+Define an API with `HttpApi`, implement handlers with `HttpApiBuilder.group`, serve it with `HttpApiBuilder.serve()`, and use `NodeHttpServer.layerTest` to get an in-process test server + `HttpClient` pointed at it.
11+
12+```ts
13+import { expect, layer } from "@effect/vitest"
14+import { Effect, Layer, Schema } from "effect"
15+import {
16+ HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup,
17+ HttpClient, OpenApi
18+} from "@effect/platform"
19+import { NodeHttpServer } from "@effect/platform-node"
20+
21+// 1. Define the API
22+class Item extends Schema.Class<Item>("Item")({
23+ id: Schema.Number,
24+ name: Schema.String,
25+}) {}
26+
27+const ItemsGroup = HttpApiGroup.make("items")
28+ .add(HttpApiEndpoint.get("listItems", "/items").addSuccess(Schema.Array(Item)))
29+ .add(
30+ HttpApiEndpoint.get("getItem", "/items/:itemId")
31+ .setPath(Schema.Struct({ itemId: Schema.NumberFromString }))
32+ .addSuccess(Item)
33+ )
34+
35+const MyApi = HttpApi.make("myApi").add(ItemsGroup)
36+
37+// 2. Implement handlers
38+const ItemsLive = HttpApiBuilder.group(MyApi, "items", (handlers) =>
39+ handlers
40+ .handle("listItems", () => Effect.succeed([{ id: 1, name: "Widget" }]))
41+ .handle("getItem", (req) => Effect.succeed({ id: req.path.itemId, name: "Widget" }))
42+)
43+
44+// 3. Build test layer
45+const ApiLive = HttpApiBuilder.api(MyApi).pipe(Layer.provide(ItemsLive))
46+
47+const TestLayer = HttpApiBuilder.serve().pipe(
48+ Layer.provide(ApiLive),
49+ Layer.provideMerge(NodeHttpServer.layerTest),
50+)
51+
52+// 4. Use layer() to share across tests
53+layer(TestLayer)("My API", (it) => {
54+ it.effect("works", () =>
55+ Effect.gen(function* () {
56+ const client = yield* HttpClient.HttpClient
57+ // client is already pointed at the test server
58+ const response = yield* client.get("/items")
59+ // ...
60+ })
61+ )
62+})
63+```
64+
65+## Critical Rules
66+
67+### Layer composition order matters
68+
69+`HttpApiBuilder.serve()` consumes `HttpApi.Api`. The API layer must be provided to it, not the other way around:
70+
71+```ts
72+// CORRECT
73+HttpApiBuilder.serve().pipe(
74+ Layer.provide(ApiLive),
75+ Layer.provideMerge(NodeHttpServer.layerTest),
76+)
77+
78+// WRONG — "Service not found: HttpApi.Api"
79+ApiLive.pipe(
80+ Layer.provide(HttpApiBuilder.serve()),
81+ Layer.provideMerge(NodeHttpServer.layerTest),
82+)
83+```
84+
85+### layerTestClient prepends the server URL
86+
87+`NodeHttpServer.layerTest` (and `HttpServer.layerTestClient`) produce an `HttpClient` that automatically prepends the test server's `http://127.0.0.1:<port>` to every request URL.
88+
89+- Use **paths only** (`/items`, `/items/2`) in requests — not full URLs
90+- If your code builds full URLs (e.g. `http://localhost/items`), the client will produce `http://127.0.0.1:PORThttp://localhost/items` — an invalid URL
91+- When injecting the test client into code that normally uses a `baseUrl`, pass `baseUrl: ""` or skip the base URL entirely
92+
93+### Path parameters need setPath()
94+
95+Effect's `HttpApiEndpoint` with `:param` syntax does NOT automatically populate `req.path`. You must call `.setPath()` with a schema:
96+
97+```ts
98+// WRONG — req.path is undefined
99+HttpApiEndpoint.get("getItem", "/items/:itemId").addSuccess(Item)
100+
101+// CORRECT — req.path.itemId is typed and populated
102+HttpApiEndpoint.get("getItem", "/items/:itemId")
103+ .setPath(Schema.Struct({ itemId: Schema.NumberFromString }))
104+ .addSuccess(Item)
105+```
106+
107+### OpenApi.fromApi generates the spec
108+
109+Use `OpenApi.fromApi(api)` to generate an OpenAPI spec from an `HttpApi` definition. The generated spec:
110+- Uses `"Api"` as the default title (not the api id)
111+- Converts `:param` to `{param}` in paths
112+- Does NOT list path parameters in the `parameters` array — they're implicit in the path template
113+- Uses `group.endpoint` format for operationIds (e.g. `items.listItems`)
114+
115+### Grab the test HttpClient from context
116+
117+Inside `layer()` tests, the `HttpClient` is available in the Effect context:
118+
119+```ts
120+layer(TestLayer)("tests", (it) => {
121+ it.effect("test", () =>
122+ Effect.gen(function* () {
123+ const httpClient = yield* HttpClient.HttpClient
124+ // Use it directly or wrap in a Layer for injection
125+ const clientLayer = Layer.succeed(HttpClient.HttpClient, httpClient)
126+ })
127+ )
128+})
129+```
130+
131+### Use HttpClient for HTTP calls, not fetch
132+
133+Production code should use `HttpClient` from `@effect/platform`, not raw `fetch`:
134+
135+```ts
136+import { HttpClient, HttpClientRequest } from "@effect/platform"
137+
138+// Build request
139+let request = HttpClientRequest.get("/items")
140+request = HttpClientRequest.setHeader(request, "accept", "application/json")
141+request = HttpClientRequest.setUrlParam(request, "limit", "10")
142+
143+// Execute — requires HttpClient in context
144+const response = yield* client.execute(request)
145+
146+// Read body
147+const data = yield* response.json // Effect<unknown>
148+const text = yield* response.text // Effect<string>
149+```
150+
151+This makes testing clean — swap in a test client layer, no monkey-patching needed.
152+
153+### Response headers are Record<string, string>
154+
155+Effect's `HttpClientResponse.headers` is a plain `Record<string, string>`, not a Web `Headers` object. Don't call `.forEach()` or `.get()` on it:
156+
157+```ts
158+// WRONG
159+response.headers.forEach((v, k) => ...)
160+response.headers.get("content-type")
161+
162+// CORRECT
163+const ct = response.headers["content-type"]
164+const copy = { ...response.headers }
165+```
166+
167+### HttpClientRequest.make takes uppercase methods
168+
169+```ts
170+// The method parameter to make() must be uppercase
171+HttpClientRequest.make("GET")("/items")
172+
173+// Or use the convenience methods
174+HttpClientRequest.get("/items")
175+HttpClientRequest.post("/items")
176+```
177+
178+### Prepending base URLs to a client
179+
180+Use `HttpClient.mapRequest` with `HttpClientRequest.prependUrl`:
181+
182+```ts
183+const clientWithBase = Layer.effect(
184+ HttpClient.HttpClient,
185+ Effect.map(
186+ HttpClient.HttpClient,
187+ HttpClient.mapRequest(HttpClientRequest.prependUrl("https://api.example.com")),
188+ ),
189+).pipe(Layer.provide(baseClientLayer))
190+```
191+
192+### Error assertions
193+
194+Use `Effect.flip` to turn errors into values for assertion:
195+
196+```ts
197+const error = yield* Effect.flip(someFailingEffect)
198+expect(error._tag).toBe("MyError")
199+```
200+
201+### Dependencies
202+
203+- `@effect/platform` — HttpApi, HttpClient, HttpServer, OpenApi
204+- `@effect/platform-node` — NodeHttpServer.layerTest (for Node/vitest)
205+- `@effect/vitest` — `layer()`, `it.effect()`, `expect`
.skills/effect-use-pattern/SKILL.md+210−0
@@ -0,0 +1,210 @@
1+---
2+name: effect-client-wrapper
3+description: Pattern for wrapping third-party SDK clients (Stripe, Resend, AWS, etc.) with Effect. Use when creating Effect services that wrap external libraries with Promise-based APIs. Provides type-safe error handling, automatic tracing, and clean dependency injection via the "use" pattern.
4+---
5+
6+# Effect Client Wrapper Pattern
7+
8+Wrap third-party SDK clients with Effect using the "use" pattern for consistent error handling, tracing, and dependency injection.
9+
10+## Pattern Structure
11+
12+```typescript
13+import { Context, Data, Effect, Layer, Config, Redacted } from "effect";
14+
15+// 1. Define tagged errors
16+export class MyClientError extends Data.TaggedError("MyClientError")<{
17+ cause: unknown;
18+}> {}
19+
20+export class MyClientInstantiationError extends Data.TaggedError(
21+ "MyClientInstantiationError",
22+)<{
23+ cause: unknown;
24+}> {}
25+
26+// 2. Define service interface with `use` method
27+export type IMyClient = Readonly<{
28+ client: ThirdPartyClient;
29+ use: <A>(
30+ fn: (client: ThirdPartyClient) => Promise<A>,
31+ ) => Effect.Effect<A, MyClientError, never>;
32+}>;
33+
34+// 3. Create the service implementation
35+const make = Effect.gen(function* () {
36+ const apiKey = yield* Config.redacted("MY_CLIENT_API_KEY");
37+
38+ const client = yield* Effect.try({
39+ try: () => new ThirdPartyClient(Redacted.value(apiKey)),
40+ catch: (cause) => new MyClientInstantiationError({ cause }),
41+ });
42+
43+ const use = <A>(fn: (client: ThirdPartyClient) => Promise<A>) =>
44+ Effect.tryPromise({
45+ try: () => fn(client),
46+ catch: (cause) => new MyClientError({ cause }),
47+ }).pipe(Effect.withSpan(`my_client.${fn.name ?? "use"}`));
48+
49+ return { client, use };
50+});
51+
52+// 4. Export as Context.Tag with Default layer
53+export class MyClient extends Context.Tag("MyClient")<MyClient, IMyClient>() {
54+ static Default = Layer.effect(this, make).pipe(
55+ Layer.annotateSpans({ module: "MyClient" }),
56+ );
57+}
58+```
59+
60+## Usage
61+
62+```typescript
63+const program = Effect.gen(function* () {
64+ const myClient = yield* MyClient;
65+
66+ const result = yield* myClient.use((client) =>
67+ client.someMethod({ param: "value" }),
68+ );
69+
70+ return result;
71+});
72+
73+// Run with layer
74+program.pipe(Effect.provide(MyClient.Default));
75+```
76+
77+## Key Benefits
78+
79+1. **Centralized error handling** - All client errors wrapped in typed `MyClientError`
80+2. **Automatic tracing** - Every `use` call creates a span with function name
81+3. **Config-based secrets** - API keys loaded via `Config.redacted`
82+4. **Clean DI** - Consumers inject via `yield* MyClient`
83+5. **Encapsulation** - Raw client hidden behind `use` interface
84+
85+## Variations
86+
87+### Multiple Error Types
88+
89+```typescript
90+export class MyClientNetworkError extends Data.TaggedError(
91+ "MyClientNetworkError",
92+)<{
93+ cause: unknown;
94+}> {}
95+
96+export class MyClientValidationError extends Data.TaggedError(
97+ "MyClientValidationError",
98+)<{
99+ message: string;
100+}> {}
101+
102+const use = <A>(fn: (client: ThirdPartyClient) => Promise<A>) =>
103+ Effect.tryPromise({
104+ try: () => fn(client),
105+ catch: (cause) => {
106+ if (cause instanceof NetworkError) {
107+ return new MyClientNetworkError({ cause });
108+ }
109+ return new MyClientError({ cause });
110+ },
111+ }).pipe(Effect.withSpan(`my_client.${fn.name ?? "use"}`));
112+```
113+
114+### Named Operations
115+
116+Expose specific methods instead of generic `use`:
117+
118+```typescript
119+export type IEmailClient = Readonly<{
120+ sendEmail: (
121+ params: SendEmailParams,
122+ ) => Effect.Effect<EmailResult, EmailError>;
123+ getEmail: (id: string) => Effect.Effect<Email, EmailError>;
124+}>;
125+
126+const make = Effect.gen(function* () {
127+ const resend = yield* ResendClient;
128+
129+ return {
130+ sendEmail: (params) =>
131+ resend
132+ .use((client) => client.emails.send(params))
133+ .pipe(Effect.withSpan("email_client.send")),
134+
135+ getEmail: (id) =>
136+ resend
137+ .use((client) => client.emails.get(id))
138+ .pipe(Effect.withSpan("email_client.get")),
139+ };
140+});
141+```
142+
143+### With Retry Policy
144+
145+```typescript
146+import { Schedule } from "effect";
147+
148+const retryPolicy = Schedule.exponential(100).pipe(
149+ Schedule.intersect(Schedule.recurs(3)),
150+ Schedule.jittered,
151+);
152+
153+const use = <A>(fn: (client: ThirdPartyClient) => Promise<A>) =>
154+ Effect.tryPromise({
155+ try: () => fn(client),
156+ catch: (cause) => new MyClientError({ cause }),
157+ }).pipe(
158+ Effect.retry(retryPolicy),
159+ Effect.withSpan(`my_client.${fn.name ?? "use"}`),
160+ );
161+```
162+
163+## Real-World Example: Stripe
164+
165+```typescript
166+import Stripe from "stripe";
167+import { Context, Data, Effect, Layer, Config, Redacted } from "effect";
168+
169+export class StripeError extends Data.TaggedError("StripeError")<{
170+ cause: unknown;
171+}> {}
172+
173+export type IStripeClient = Readonly<{
174+ use: <A>(fn: (stripe: Stripe) => Promise<A>) => Effect.Effect<A, StripeError>;
175+}>;
176+
177+const make = Effect.gen(function* () {
178+ const secretKey = yield* Config.redacted("STRIPE_SECRET_KEY");
179+
180+ const client = new Stripe(Redacted.value(secretKey));
181+
182+ const use = <A>(fn: (stripe: Stripe) => Promise<A>) =>
183+ Effect.tryPromise({
184+ try: () => fn(client),
185+ catch: (cause) => new StripeError({ cause }),
186+ }).pipe(Effect.withSpan(`stripe.${fn.name ?? "use"}`));
187+
188+ return { use };
189+});
190+
191+export class StripeClient extends Context.Tag("StripeClient")<
192+ StripeClient,
193+ IStripeClient
194+>() {
195+ static Default = Layer.effect(this, make).pipe(
196+ Layer.annotateSpans({ module: "StripeClient" }),
197+ );
198+}
199+
200+// Usage
201+const createCustomer = Effect.gen(function* () {
202+ const stripe = yield* StripeClient;
203+
204+ const customer = yield* stripe.use((client) =>
205+ client.customers.create({ email: "user@example.com" }),
206+ );
207+
208+ return customer;
209+});
210+```
.vscode/settings.json+4−0
@@ -0,0 +1,4 @@
1+{
2+ "typescript.tsdk": "./node_modules/typescript/lib",
3+ "typescript.enablePromptUseWorkspaceTsdk": true
4+}
AGENTS.md+1−0
@@ -0,0 +1 @@
1+use effect vitest and run tests via vitest not bun test
CLAUDE.md+1−0
@@ -0,0 +1 @@
1+use effect vitest and run tests via vitest not bun test
LICENSE+0−21
@@ -1,21 +0,0 @@
1−MIT License
2−
3−Copyright (c) 2026 Rhys Sullivan
4−
5−Permission is hereby granted, free of charge, to any person obtaining a copy
6−of this software and associated documentation files (the "Software"), to deal
7−in the Software without restriction, including without limitation the rights
8−to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9−copies of the Software, and to permit persons to whom the Software is
10−furnished to do so, subject to the following conditions:
11−
12−The above copyright notice and this permission notice shall be included in all
13−copies or substantial portions of the Software.
14−
15−THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16−IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17−FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18−AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19−LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20−OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21−SOFTWARE.
README.md+0−395
@@ -1,395 +0,0 @@
1−# executor
2−
3−
4−https://github.com/user-attachments/assets/11225f83-e848-42ba-99b2-a993bcc88dad
5−
6−
7−`executor` is a local-first execution environment for AI agents.
8−
9−It gives an agent a TypeScript runtime, a discoverable tool catalog, and a single local place to connect external systems such as MCP servers, OpenAPI APIs, and GraphQL APIs. Instead of pasting large MCP manifests into every chat or giving an agent broad shell access, you run code inside `executor` and let it call typed `tools.*` functions.
10−
11−[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/RhysSullivan/executor)
12−
13−## Community
14−
15−Join the Discord community: https://discord.gg/eF29HBHwM6
16−
17−At runtime, `executor` behaves like one local product:
18−
19−- a CLI for starting the runtime and executing code
20−- a local API server
21−- a local web UI for connecting sources, inspecting tools, and managing secrets
22−- an MCP endpoint for hosts that want to drive `executor` through MCP
23−
24−The current codebase lives in `apps/` and `packages/`. Older experiments stay in `legacy/` and `legacy2/`.
25−
26−## Attribution
27−
28−- [Crystian](https://www.linkedin.com/in/crystian/) provided the npm package name `executor`.
29−- The `codemode` concept in this project is inspired by Cloudflare's [Code Mode announcement](https://blog.cloudflare.com/code-mode/).
30−
31−## Why this exists
32−
33−`executor` is built around a simple idea: agents should work against a structured tool environment instead of guessing at raw HTTP calls, carrying huge MCP definitions in context, or running arbitrary local commands with broad permissions.
34−
35−In practice that means:
36−
37−- sources are connected once and turned into a reusable workspace tool catalog
38−- the agent discovers tools by intent, inspects schemas, and then calls typed functions
39−- secrets and OAuth flows stay in the local runtime and web UI instead of being pasted into chat
40−- human interaction can pause an execution and resume it cleanly
41−
42−## Mental model
43−
44−Think of `executor` as a local control plane for agent tool use.
45−
46−1. You start a local `executor` daemon.
47−2. You connect sources such as an MCP server, an OpenAPI document, or a GraphQL endpoint.
48−3. `executor` indexes those sources into a workspace tool catalog.
49−4. An agent runs TypeScript against that catalog through `executor call` or through the MCP bridge.
50−5. If a tool needs credentials or user input, execution pauses, opens a local flow, and then resumes.
51−
52−## What it does today
53−
54−### Connect external tool sources
55−
56−`executor` currently supports these source types:
57−
58−- `mcp`: remote MCP servers, including transport selection for streamable HTTP or SSE
59−- `openapi`: REST APIs described by an OpenAPI document
60−- `graphql`: GraphQL endpoints that can be introspected into callable tools
61−
62−The add-source flow can:
63−
64−- probe a URL and infer what kind of source it is
65−- infer likely authentication requirements
66−- prompt for credentials when discovery or connection needs them
67−- start OAuth when a source requires it
68−- persist the source and its indexed tool metadata in the local workspace
69−
70−The web app also includes templates for common providers so you can start from real examples instead of filling every field by hand.
71−
72−### Run agent code against tools
73−
74−The main CLI workflow is `executor call`.
75−
76−The runtime expects the agent to use the built-in discovery workflow:
77−
78−```ts
79−const matches = await tools.discover({ query: "github issues", limit: 5 });
80−const path = matches.bestPath;
81−const detail = await tools.describe.tool({ path, includeSchemas: true });
82−
83−return await tools.github.issues.list({
84− owner: "vercel",
85− repo: "next.js",
86−});
87−```
88−
89−A few important rules shape the execution model:
90−
91−- write TypeScript, not raw shell pipelines
92−- use `tools.*`, not direct `fetch`
93−- discover first when the exact tool path is not known
94−- inspect schemas before calling complex tools
95−
96−### Handle credentials and user interaction
97−
98−When a source or tool needs human input, `executor` can pause the execution and create an interaction record.
99−
100−That interaction may ask you to:
101−
102−- open a secure local credential page
103−- complete an OAuth flow in the browser
104−- respond to a structured elicitation from a tool host
105−- resume a paused execution from the CLI
106−
107−This is the core human-in-the-loop behavior that lets `executor` keep secrets and approvals outside the agent's raw context.
108−
109−### Inspect the connected tool model
110−
111−The web UI is not just a setup surface. It is also where you can inspect what `executor` learned from a source.
112−
113−For each source you can:
114−
115−- browse its tool tree
116−- search for tools by intent
117−- inspect input and output schemas
118−- view generated manifests, definitions, and raw source documents when available
119−- edit source settings and authentication details
120−
121−## Quick start
122−
123−If you want to use this a package distribution, install it via npm:
124−
125−```bash
126−npm install -g executor
127−executor web
128−```
129−
130−That starts a foreground local session, prints the local web URL, and keeps it alive until you press `Ctrl+C`.
131−
132−If you want the MCP endpoint instead, run:
133−
134−```bash
135−executor mcp
136−```
137−
138−That prints the local MCP URL and keeps the session alive until you press `Ctrl+C`.
139−
140−If you want a local stdio MCP server for agent configs such as Codex or OpenCode, run:
141−
142−```bash
143−executor mcp --stdio
144−```
145−
146−Then you can run the CLI as `executor`.
147−
148−If you are working from this repository locally, the easiest path is:
149−
150−```bash
151−bun install
152−bun dev
153−```
154−
155−That starts the local runtime. The default base URL is:
156−
157−```text
158−http://127.0.0.1:8788
159−```
160−
161−From there:
162−
163−1. Open the web UI in your browser.
164−2. Add a source from `/sources/add`.
165−3. If needed, store credentials in `/secrets`.
166−4. Run TypeScript with `bun run executor call ...`.
167−
168−If you are using a packaged distribution, the command name is simply `executor` instead of `bun run executor`.
169−
170−## Core CLI commands
171−
172−```bash
173−executor web
174−executor mcp
175−executor mcp --stdio
176−executor call --file script.ts
177−executor resume --execution-id exec_123
178−```
179−
180−Compatibility commands for the detached daemon are still available:
181−
182−```bash
183−executor up
184−executor down
185−executor status --json
186−executor doctor --json
187−```
188−
189−`executor call` accepts code in three ways:
190−
191−- inline as a positional argument
192−- from `--file`
193−- from standard input with `--stdin`
194−
195−Examples:
196−
197−```bash
198−executor call 'const matches = await tools.discover({ query: "repo details", limit: 1 }); return matches;'
199−executor call --file script.ts
200−cat script.ts | executor call --stdin
201−executor call --no-open --file script.ts
202−```
203−
204−If an execution pauses, resume it with:
205−
206−```bash
207−executor resume --execution-id exec_123
208−```
209−
210−## Adding a source
211−
212−There are two main ways to add a source.
213−
214−### In the web UI
215−
216−Use the Add Source flow to:
217−
218−- paste a URL
219−- run discovery
220−- review the inferred kind, namespace, transport, and auth
221−- connect the source
222−- complete credential or OAuth setup if required
223−
224−This is the easiest path for most users.
225−
226−### From inside an execution
227−
228−The runtime also exposes `tools.executor.sources.add(...)`, which lets an agent add a source from code.
229−
230−Examples:
231−
232−```ts
233−return await tools.executor.sources.add({
234− kind: "mcp",
235− name: "Example",
236− endpoint: "https://example.com/mcp",
237− transport: "auto",
238− queryParams: null,
239− headers: null,
240− command: null,
241− args: null,
242− env: null,
243− cwd: null,
244− auth: { kind: "none" },
245−});
246−```
247−
248−```ts
249−return await tools.executor.sources.add({
250− kind: "openapi",
251− name: "GitHub",
252− specUrl:
253− "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json",
254− baseUrl: null,
255− auth: { kind: "none" },
256−});
257−```
258−
259−`executor.sources.add(...)` accepts the final plugin-specific source config.
260−Browser OAuth and popup-driven auth flows live on the plugin-owned HTTP and web surfaces.
261−
262−## How execution works
263−
264−At a high level, every execution follows the same loop:
265−
266−1. `executor` resolves the current local installation and workspace.
267−2. It builds a tool catalog from built-in tools plus all connected workspace sources.
268−3. It runs your TypeScript inside the configured sandbox runtime. QuickJS is the default, and `.executor/executor.jsonc` can set `"runtime": "quickjs" | "ses" | "deno"`.
269−4. Tool calls are dispatched through `executor` rather than directly from your code.
270−5. If a tool needs interaction, the run pauses and records a pending interaction.
271−6. Once the interaction is resolved, the execution continues and eventually completes or fails.
272−
273−Example:
274−
275−```jsonc
276−{
277− "runtime": "ses",
278− "sources": {}
279−}
280−```
281−
282−This gives you a stable surface for agent automation:
283−
284−- the agent sees a coherent catalog
285−- connected sources become reusable namespace-based tools
286−- auth stays attached to sources and secret material
287−- the runtime can track execution state instead of losing it inside a one-shot prompt
288−
289−## Web UI overview
290−
291−The React web app is served from the same local server as the API.
292−
293−Main screens:
294−
295−- `/`: list connected sources in the current local workspace
296−- `/sources/add`: discover and connect new sources
297−- `/sources/:sourceId`: inspect tools, search tools, and browse source artifacts
298−- `/sources/:sourceId/edit`: edit source settings and auth
299−- `/secrets`: create, update, and delete locally stored secrets
300−
301−The UI uses the same control-plane API as the CLI, so both surfaces are operating on the same local runtime state.
302−
303−## Local-first runtime behavior
304−
305−By default `executor` runs as a single local daemon process.
306−
307−It serves:
308−
309−- `/v1` for the local control-plane API
310−- `/mcp` for the `executor` MCP endpoint
311−- the web UI for normal browser routes
312−
313−Default network location:
314−
315−- host: `127.0.0.1`
316−- port: `8788`
317−
318−Default data locations are OS-aware:
319−
320−- Linux data: `~/.local/share/executor`
321−- Linux runtime state: `~/.local/state/executor/run`
322−- macOS: `~/Library/Application Support/Executor`
323−- Windows: `%LOCALAPPDATA%\Executor`
324−
325−The server also maintains local PID and log files in its runtime directory.
326−
327−## Persistence and data
328−
329−`executor` persists the local control plane to local files.
330−
331−Persisted concepts include:
332−
333−- local installation identity
334−- connected sources
335−- indexed tool artifacts and related metadata
336−- credentials and secret material bindings
337−- source auth sessions
338−- execution and interaction state
339−- executions and execution interactions
340−- policies
341−
342−On first start, `executor` provisions a local account, a personal organization, and a default workspace automatically.
343−
344−## Security and trust model
345−
346−`executor` is designed to narrow how agents interact with external systems.
347−
348−Compared with direct shell or raw API usage, the model is intentionally more structured:
349−
350−- tool calls are routed through a controlled runtime
351−- secrets are stored separately from prompt text
352−- OAuth and credential capture happen through local flows
353−- executions can pause for interaction instead of guessing or failing silently
354−- source auth and tool metadata live with the workspace rather than inside each prompt
355−
356−This does not make the system magically risk-free, but it gives the runtime places to enforce policy, collect approvals, and keep sensitive material out of the agent's immediate context.
357−
358−## Repository layout
359−
360−If you are exploring the repo, these are the directories that matter most:
361−
362−- `apps/executor`: packaged CLI entrypoint and daemon lifecycle commands
363−- `apps/web`: local React web UI
364−- `packages/platform/server`: local HTTP server that serves API, MCP, and UI
365−- `packages/platform/sdk`: source management, secrets, persistence, execution, and inspection
366−- `packages/platform/api`: thin HTTP adapter over the platform SDK
367−- `packages/platform/internal`: thin internal tool adapter over the platform SDK
368−- `packages/kernel/runtime-deno-subprocess`: optional Deno subprocess runtime for TypeScript execution
369−- `packages/kernel/runtime-quickjs`: default QuickJS sandbox runtime for TypeScript execution
370−- `packages/kernel/runtime-ses`: optional SES sandbox runtime for TypeScript execution
371−- `packages/hosts/mcp`: MCP bridge for `execute` and `resume`
372−- `packages/kernel/core` plus `packages/sources/*`: core tool abstractions and first-party source integrations
373−
374−## Releasing
375−
376−- Add a changeset in any PR that should release: `bun run changeset`.
377−- Merge that PR to `main`. `.github/workflows/release.yml` opens or updates a `Version Packages` release PR for version bumps and changelog updates.
378−- Merge the `Version Packages` PR. The release workflow pushes the matching git tag and dispatches `.github/workflows/publish-executor-package.yml`, which publishes to npm and creates the GitHub release.
379−- Do not edit `apps/executor/package.json` by hand for normal releases. Changesets owns the version.
380−- For a beta train, enter prerelease mode with `bun run release:beta:start`, commit `.changeset/pre.json`, and merge it. Release PRs will then use `-beta.x` versions until you exit with `bun run release:beta:stop`.
381−- `bun run --cwd apps/executor release:publish` remains the publish implementation used by CI.
382−- To build and pack the publish artifact locally without publishing, run `bun run --cwd apps/executor release:publish:dry-run`.
383−- `.github/workflows/publish-executor-package.yml` can also be run manually with a tag input if a publish needs to be retried for an already-created version tag.
384−- One-time npm setup: either configure npm trusted publishing for `RhysSullivan/executor` with the workflow file `.github/workflows/publish-executor-package.yml`, or add a GitHub Actions secret named `NPM_TOKEN` that can publish the `executor` package.
385−- Stable releases use a normal semver like `1.2.3` and publish to npm under `latest`.
386−- Beta releases use a prerelease semver like `1.3.0-beta.1` and publish to npm under `beta`.
387−- When a release should become an upgrade test fixture, capture a real workspace snapshot with `bun run fixture:release:capture -- ...` and commit it under [`packages/platform/sdk/src/runtime/__fixtures__`](./packages/platform/sdk/src/runtime/__fixtures__/README.md).
388−
389−## Project status
390−
391−This repository is explicitly on its third major architecture iteration.
392−
393−- `apps/` and `packages/` are the active implementation
394−- `legacy/` is the original codebase
395−- `legacy2/` is the second generation
RELEASING.md+50−0
@@ -0,0 +1,50 @@
1+# Releasing
2+
3+This repo uses Changesets for version orchestration and a custom publish script for the generated `executor` npm package plus its platform packages.
4+
5+## Normal release flow
6+
7+1. Add a changeset in the PR that should ship:
8+ - `bun run changeset`
9+2. Merge that PR to `main`.
10+3. `.github/workflows/release.yml` opens or updates a `Version Packages` PR.
11+4. Merge the `Version Packages` PR.
12+5. The release workflow tags the commit and dispatches `.github/workflows/publish-executor-package.yml`.
13+6. The publish workflow:
14+ - runs `bun run release:check`
15+ - performs a full dry-run release build before publish
16+ - publishes npm packages under the correct dist-tag
17+ - creates or updates the GitHub release with build artifacts
18+
19+## Beta releases
20+
21+Enter prerelease mode before starting a beta train:
22+
23+- `bun run release:beta:start`
24+
25+That commits `.changeset/pre.json` into the repo and causes future release PRs to produce versions like `1.5.0-beta.0`, `1.5.0-beta.1`, and so on.
26+
27+When the beta train is done:
28+
29+- `bun run release:beta:stop`
30+
31+Stable versions publish to npm under `latest`.
32+Beta versions publish to npm under `beta`.
33+
34+## Local dry run
35+
36+To build the full release payload without publishing to npm or GitHub:
37+
38+- `bun run release:publish:dry-run`
39+
40+That produces:
41+
42+- platform archives in `apps/cli/dist`
43+- the packed wrapper tarball in `apps/cli/dist/release`
44+
45+## Notes
46+
47+- Changesets owns the published CLI version via `apps/cli/package.json`.
48+- `scripts/release/sync-versions.mjs` propagates that version across the rest of the repo manifests after `changeset version` runs.
49+- The publish workflow supports either npm trusted publishing or an `NPM_TOKEN` secret.
50+- Re-running the publish workflow for the same tag is safe for packages that are already on npm; existing versions are skipped.
apps/cli/bin/executor.ts+2−0
@@ -0,0 +1,2 @@
1+#!/usr/bin/env bun
2+import "../src/main.ts";
apps/cli/package.json+35−0
@@ -0,0 +1,35 @@
1+{
2+ "name": "executor",
3+ "version": "1.4.0-beta.0",
4+ "private": true,
5+ "type": "module",
6+ "bin": {
7+ "executor": "./bin/executor.ts"
8+ },
9+ "exports": {
10+ ".": "./src/main.ts"
11+ },
12+ "scripts": {
13+ "build": "bun run src/build.ts binary --single",
14+ "build:all": "bun run src/build.ts binary",
15+ "build:publish": "bun run src/build.ts publish",
16+ "release:publish:dry-run": "bun run src/release.ts --dry-run",
17+ "release:publish": "bun run src/release.ts",
18+ "typecheck": "tsc --noEmit"
19+ },
20+ "dependencies": {
21+ "@effect/cli": "catalog:",
22+ "@effect/platform": "catalog:",
23+ "@effect/platform-bun": "catalog:",
24+ "@executor/api": "workspace:*",
25+ "@executor/runtime-quickjs": "workspace:*",
26+ "@executor/server": "workspace:*",
27+ "@jitl/quickjs-wasmfile-release-sync": "*",
28+ "quickjs-emscripten": "*",
29+ "effect": "catalog:"
30+ },
31+ "devDependencies": {
32+ "bun-types": "catalog:",
33+ "typescript": "^5.9.3"
34+ }
35+}
apps/cli/src/build.ts+465−0
@@ -0,0 +1,465 @@
1+import { cp, mkdir, rm, writeFile, chmod } from "node:fs/promises";
2+import { existsSync } from "node:fs";
3+import { createRequire } from "node:module";
4+import { resolve, join, dirname } from "node:path";
5+import { fileURLToPath } from "node:url";
6+import { $ } from "bun";
7+
8+const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
9+const cliRoot = resolve(repoRoot, "apps/cli");
10+const webRoot = resolve(repoRoot, "apps/web");
11+const distDir = resolve(cliRoot, "dist");
12+
13+const resolveQuickJsWasmPath = (): string => {
14+ const req = createRequire(join(repoRoot, "packages/kernel/runtime-quickjs/package.json"));
15+ const quickJsPkg = req.resolve("quickjs-emscripten/package.json");
16+ const wasmPath = resolve(
17+ dirname(quickJsPkg),
18+ "../@jitl/quickjs-wasmfile-release-sync/dist/emscripten-module.wasm",
19+ );
20+ if (!existsSync(wasmPath)) throw new Error(`QuickJS WASM not found at ${wasmPath}`);
21+ return wasmPath;
22+};
23+
24+// ---------------------------------------------------------------------------
25+// Metadata
26+// ---------------------------------------------------------------------------
27+
28+const readMetadata = async () => {
29+ const rootPkg = await Bun.file(join(repoRoot, "package.json")).json();
30+ const cliPkg = await Bun.file(join(cliRoot, "package.json")).json();
31+ return {
32+ name: "executor",
33+ version: process.env.EXECUTOR_VERSION ?? cliPkg.version ?? rootPkg.version ?? "0.0.0",
34+ description: rootPkg.description ?? "Local AI executor with a CLI, local API server, and web UI.",
35+ keywords: rootPkg.keywords ?? [],
36+ homepage: rootPkg.homepage,
37+ bugs: rootPkg.bugs,
38+ repository: rootPkg.repository,
39+ license: rootPkg.license ?? "MIT",
40+ };
41+};
42+
43+// ---------------------------------------------------------------------------
44+// Targets
45+// ---------------------------------------------------------------------------
46+
47+type Target = {
48+ os: "linux" | "darwin" | "win32";
49+ arch: "x64" | "arm64";
50+ abi?: "musl";
51+};
52+
53+const ALL_TARGETS: Target[] = [
54+ { os: "linux", arch: "x64" },
55+ { os: "linux", arch: "arm64" },
56+ { os: "linux", arch: "x64", abi: "musl" },
57+ { os: "linux", arch: "arm64", abi: "musl" },
58+ { os: "darwin", arch: "x64" },
59+ { os: "darwin", arch: "arm64" },
60+ { os: "win32", arch: "x64" },
61+ { os: "win32", arch: "arm64" },
62+];
63+
64+const platformName = (t: Target) =>
65+ t.os === "win32" ? "windows" : t.os;
66+
67+const targetPackageName = (t: Target) =>
68+ ["executor", platformName(t), t.arch, t.abi].filter(Boolean).join("-");
69+
70+const bunTarget = (t: Target) =>
71+ ["bun", platformName(t), t.arch, t.abi].filter(Boolean).join("-");
72+
73+const binaryName = (t: Target) =>
74+ t.os === "win32" ? "executor.exe" : "executor";
75+
76+const isCurrentPlatform = (t: Target) =>
77+ t.os === process.platform && t.arch === process.arch && !t.abi;
78+
79+// ---------------------------------------------------------------------------
80+// Build web app
81+// ---------------------------------------------------------------------------
82+
83+const buildWeb = async () => {
84+ const webDist = join(webRoot, "dist");
85+ if (existsSync(webDist)) return webDist;
86+
87+ console.log("Building web app...");
88+ const proc = Bun.spawn(["bun", "run", "build"], { cwd: webRoot, stdio: ["ignore", "inherit", "inherit"] });
89+ if ((await proc.exited) !== 0) throw new Error("Web build failed");
90+ return webDist;
91+};
92+
93+// ---------------------------------------------------------------------------
94+// Embedded web UI — generates a virtual module that imports all web assets
95+// using `with { type: "file" }` so Bun bakes them into the compiled binary.
96+// ---------------------------------------------------------------------------
97+
98+const createEmbeddedWebUISource = async () => {
99+ const webDist = await buildWeb();
100+ const files = (await Array.fromAsync(new Bun.Glob("**/*").scan({ cwd: webDist })))
101+ .map((f) => f.replaceAll("\\", "/"))
102+ .sort();
103+
104+ const imports = files.map((file, i) => {
105+ const spec = join(webDist, file).replaceAll("\\", "/");
106+ return `import file_${i} from ${JSON.stringify(spec)} with { type: "file" };`;
107+ });
108+
109+ const entries = files.map((file, i) => ` ${JSON.stringify(file)}: file_${i},`);
110+
111+ return [
112+ "// Auto-generated — maps web UI paths to embedded file references",
113+ ...imports,
114+ "export default {",
115+ ...entries,
116+ "} as Record<string, string>;",
117+ ].join("\n");
118+};
119+
120+// ---------------------------------------------------------------------------
121+// Build platform binaries
122+// ---------------------------------------------------------------------------
123+
124+const buildBinaries = async (targets: Target[]) => {
125+ const meta = await readMetadata();
126+ const binaries: Record<string, string> = {};
127+
128+ await rm(distDir, { recursive: true, force: true });
129+
130+ console.log("Generating embedded web UI bundle...");
131+ const embeddedWebUI = await createEmbeddedWebUISource();
132+ const quickJsWasmPath = resolveQuickJsWasmPath();
133+
134+ for (const target of targets) {
135+ const name = targetPackageName(target);
136+ const outDir = join(distDir, name);
137+ const binDir = join(outDir, "bin");
138+ await mkdir(binDir, { recursive: true });
139+
140+ console.log(`Building ${name}...`);
141+
142+ await Bun.build({
143+ entrypoints: [join(cliRoot, "src/main.ts"), "embedded-web-ui.gen.ts"],
144+ minify: true,
145+ files: {
146+ "embedded-web-ui.gen.ts": embeddedWebUI,
147+ },
148+ compile: {
149+ target: bunTarget(target) as any,
150+ outfile: join(binDir, binaryName(target)),
151+ },
152+ });
153+
154+ // Copy QuickJS WASM next to binary — loaded at runtime by the server
155+ await cp(quickJsWasmPath, join(binDir, "emscripten-module.wasm"));
156+
157+ // Smoke test on current platform
158+ if (isCurrentPlatform(target)) {
159+ const bin = join(binDir, binaryName(target));
160+ console.log(` Smoke test: ${bin} --version`);
161+ const version = await $`${bin} --version`.text();
162+ console.log(` OK: ${version.trim()}`);
163+ }
164+
165+ // Platform package.json
166+ await writeFile(
167+ join(outDir, "package.json"),
168+ JSON.stringify(
169+ {
170+ name,
171+ version: meta.version,
172+ os: [target.os],
173+ cpu: [target.arch],
174+ bin: { executor: `bin/${binaryName(target)}` },
175+ },
176+ null,
177+ 2,
178+ ) + "\n",
179+ );
180+
181+ binaries[name] = meta.version;
182+ }
183+
184+ return binaries;
185+};
186+
187+// ---------------------------------------------------------------------------
188+// Build wrapper npm package
189+// ---------------------------------------------------------------------------
190+
191+const buildWrapperPackage = async (binaries: Record<string, string>) => {
192+ const meta = await readMetadata();
193+ const wrapperDir = join(distDir, meta.name);
194+ const binDir = join(wrapperDir, "bin");
195+
196+ await mkdir(binDir, { recursive: true });
197+
198+ // Node.js shim that finds + spawns the right platform binary
199+ await writeFile(join(binDir, "executor"), NODE_SHIM);
200+ await chmod(join(binDir, "executor"), 0o755);
201+
202+ // Postinstall: hardlink the platform binary for faster startup
203+ await writeFile(join(wrapperDir, "postinstall.mjs"), POSTINSTALL_SCRIPT);
204+
205+ // Package.json
206+ await writeFile(
207+ join(wrapperDir, "package.json"),
208+ JSON.stringify(
209+ {
210+ name: meta.name,
211+ version: meta.version,
212+ description: meta.description,
213+ keywords: meta.keywords,
214+ homepage: meta.homepage,
215+ bugs: meta.bugs,
216+ repository: meta.repository,
217+ license: meta.license,
218+ bin: { executor: "bin/executor" },
219+ scripts: {
220+ postinstall: "node ./postinstall.mjs",
221+ },
222+ optionalDependencies: binaries,
223+ },
224+ null,
225+ 2,
226+ ) + "\n",
227+ );
228+
229+ // README
230+ const readmePath = join(repoRoot, "README.md");
231+ if (existsSync(readmePath)) {
232+ await cp(readmePath, join(wrapperDir, "README.md"));
233+ }
234+
235+ console.log(`\nWrapper package: ${wrapperDir}`);
236+ console.log(` ${meta.name}@${meta.version}`);
237+ console.log(` optionalDependencies: ${Object.keys(binaries).join(", ")}`);
238+};
239+
240+// ---------------------------------------------------------------------------
241+// Publish
242+// ---------------------------------------------------------------------------
243+
244+const packageAlreadyPublished = async (pkgDir: string) => {
245+ const pkg = await Bun.file(join(pkgDir, "package.json")).json() as {
246+ name?: string;
247+ version?: string;
248+ };
249+
250+ if (!pkg.name || !pkg.version) {
251+ throw new Error(`Missing name/version in ${join(pkgDir, "package.json")}`);
252+ }
253+
254+ const proc = Bun.spawn(["npm", "view", `${pkg.name}@${pkg.version}`, "version"], {
255+ cwd: pkgDir,
256+ stdio: ["ignore", "ignore", "ignore"],
257+ });
258+
259+ return (await proc.exited) === 0;
260+};
261+
262+const publishPackedPackage = async (pkgDir: string, channel: string) => {
263+ if (await packageAlreadyPublished(pkgDir)) {
264+ console.log(`Skipping ${pkgDir}; package version already exists on npm.`);
265+ return;
266+ }
267+
268+ await $`bun pm pack`.cwd(pkgDir);
269+
270+ if (process.env.GITHUB_ACTIONS === "true") {
271+ await $`npm publish *.tgz --access public --tag ${channel} --provenance`.cwd(pkgDir);
272+ } else {
273+ await $`npm publish *.tgz --access public --tag ${channel}`.cwd(pkgDir);
274+ }
275+};
276+
277+const publish = async (channel: string) => {
278+ const meta = await readMetadata();
279+
280+ // Publish platform packages
281+ for (const entry of new Bun.Glob("executor-*/package.json").scanSync({ cwd: distDir })) {
282+ const pkgDir = join(distDir, dirname(entry));
283+ console.log(`Publishing ${pkgDir}...`);
284+ await publishPackedPackage(pkgDir, channel);
285+ }
286+
287+ // Publish wrapper package
288+ const wrapperDir = join(distDir, meta.name);
289+ console.log(`Publishing ${wrapperDir}...`);
290+ await publishPackedPackage(wrapperDir, channel);
291+};
292+
293+// ---------------------------------------------------------------------------
294+// GitHub release assets
295+// ---------------------------------------------------------------------------
296+
297+const ZIP_ASSET_SCRIPT = [
298+ "import pathlib, sys, zipfile",
299+ "output = pathlib.Path(sys.argv[1])",
300+ "with zipfile.ZipFile(output, 'w', compression=zipfile.ZIP_DEFLATED) as archive:",
301+ " for path in pathlib.Path('.').rglob('*'):",
302+ " if path.is_file():",
303+ " archive.write(path, path.as_posix())",
304+].join("\n");
305+
306+const createReleaseAssets = async () => {
307+ for (const entry of new Bun.Glob("executor-*/package.json").scanSync({ cwd: distDir })) {
308+ const pkgDir = join(distDir, dirname(entry));
309+ const pkg = await Bun.file(join(pkgDir, "package.json")).json();
310+ const name = pkg.name as string;
311+
312+ if (name.includes("linux")) {
313+ await $`tar -czf ${join(distDir, `${name}.tar.gz`)} *`.cwd(join(pkgDir, "bin"));
314+ } else {
315+ await $`python3 -c ${ZIP_ASSET_SCRIPT} ${join(distDir, `${name}.zip`)}`.cwd(join(pkgDir, "bin"));
316+ }
317+
318+ console.log(`Created release asset: ${name}`);
319+ }
320+};
321+
322+// ---------------------------------------------------------------------------
323+// Node.js shim — finds the right platform binary and spawns it
324+// ---------------------------------------------------------------------------
325+
326+const NODE_SHIM = `#!/usr/bin/env node
327+const childProcess = require("child_process");
328+const fs = require("fs");
329+const path = require("path");
330+const os = require("os");
331+
332+function run(target) {
333+ const result = childProcess.spawnSync(target, process.argv.slice(2), { stdio: "inherit" });
334+ if (result.error) { console.error(result.error.message); process.exit(1); }
335+ process.exit(typeof result.status === "number" ? result.status : 0);
336+}
337+
338+// Check env override
339+if (process.env.EXECUTOR_BIN_PATH) run(process.env.EXECUTOR_BIN_PATH);
340+
341+// Check cached binary from postinstall
342+const scriptDir = path.dirname(fs.realpathSync(__filename));
343+const cached = path.join(scriptDir, ".executor");
344+if (fs.existsSync(cached)) run(cached);
345+
346+// Resolve platform
347+const platformMap = { darwin: "darwin", linux: "linux", win32: "windows" };
348+const platform = platformMap[os.platform()] || os.platform();
349+const arch = os.arch() === "arm64" ? "arm64" : "x64";
350+const binary = platform === "windows" ? "executor.exe" : "executor";
351+
352+// Detect musl
353+const isMusl = (() => {
354+ if (platform !== "linux") return false;
355+ try { if (fs.existsSync("/etc/alpine-release")) return true; } catch {}
356+ try {
357+ const r = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" });
358+ if (((r.stdout || "") + (r.stderr || "")).toLowerCase().includes("musl")) return true;
359+ } catch {}
360+ return false;
361+})();
362+
363+// Build candidate list
364+const base = "executor-" + platform + "-" + arch;
365+const names = (() => {
366+ if (platform === "linux" && isMusl) {
367+ return [base + "-musl", base];
368+ }
369+ if (platform === "linux") {
370+ return [base, base + "-musl"];
371+ }
372+ return [base];
373+})();
374+
375+// Walk up to find node_modules
376+function findBinary(startDir) {
377+ let current = startDir;
378+ for (;;) {
379+ const modules = path.join(current, "node_modules");
380+ if (fs.existsSync(modules)) {
381+ for (const name of names) {
382+ const candidate = path.join(modules, name, "bin", binary);
383+ if (fs.existsSync(candidate)) return candidate;
384+ }
385+ }
386+ const parent = path.dirname(current);
387+ if (parent === current) return;
388+ current = parent;
389+ }
390+}
391+
392+const resolved = findBinary(scriptDir);
393+if (!resolved) {
394+ console.error("Could not find executor binary for your platform. Try installing " + names.map(n => '"' + n + '"').join(" or "));
395+ process.exit(1);
396+}
397+run(resolved);
398+`;
399+
400+// ---------------------------------------------------------------------------
401+// Postinstall — hardlink/copy the platform binary for fast startup
402+// ---------------------------------------------------------------------------
403+
404+const POSTINSTALL_SCRIPT = `#!/usr/bin/env node
405+const fs = require("fs");
406+const path = require("path");
407+const os = require("os");
408+const { createRequire } = require("module");
409+
410+const __dirname_resolved = path.dirname(fs.realpathSync(__filename));
411+const require_ = createRequire(__filename);
412+
413+const platformMap = { darwin: "darwin", linux: "linux", win32: "windows" };
414+const platform = platformMap[os.platform()] || os.platform();
415+const arch = os.arch() === "arm64" ? "arm64" : "x64";
416+const binary = platform === "windows" ? "executor.exe" : "executor";
417+const base = "executor-" + platform + "-" + arch;
418+
419+const names = platform === "linux" ? [base, base + "-musl"] : [base];
420+
421+for (const name of names) {
422+ try {
423+ const pkgJson = require_.resolve(name + "/package.json");
424+ const binaryPath = path.join(path.dirname(pkgJson), "bin", binary);
425+ if (!fs.existsSync(binaryPath)) continue;
426+
427+ const target = path.join(__dirname_resolved, "bin", ".executor");
428+ const binDir = path.join(__dirname_resolved, "bin");
429+ if (!fs.existsSync(binDir)) fs.mkdirSync(binDir, { recursive: true });
430+ if (fs.existsSync(target)) fs.unlinkSync(target);
431+
432+ try { fs.linkSync(binaryPath, target); }
433+ catch { fs.copyFileSync(binaryPath, target); }
434+ fs.chmodSync(target, 0o755);
435+ console.log("executor: binary linked for " + name);
436+ break;
437+ } catch {}
438+}
439+`;
440+
441+// ---------------------------------------------------------------------------
442+// CLI
443+// ---------------------------------------------------------------------------
444+
445+const command = process.argv[2];
446+const singleFlag = process.argv.includes("--single");
447+
448+if (command === "binary") {
449+ const targets = singleFlag
450+ ? ALL_TARGETS.filter(isCurrentPlatform)
451+ : ALL_TARGETS;
452+ const binaries = await buildBinaries(targets);
453+ await buildWrapperPackage(binaries);
454+} else if (command === "release-assets") {
455+ await createReleaseAssets();
456+} else if (command === "publish") {
457+ const channel = process.argv[3] ?? "latest";
458+ await publish(channel);
459+} else {
460+ console.log(`Usage:
461+ bun run build.ts binary [--single] Build platform binaries + wrapper package
462+ bun run build.ts release-assets Create .tar.gz/.zip from built binaries
463+ bun run build.ts publish [channel] Publish all packages to npm`);
464+ process.exit(1);
465+}
apps/cli/src/embedded-web-ui.gen.d.ts+4−0
@@ -0,0 +1,4 @@
1+declare module "embedded-web-ui.gen.ts" {
2+ const files: Record<string, string>;
3+ export default files;
4+}
apps/cli/src/main.ts+388−0
@@ -0,0 +1,388 @@
1+// Pre-load QuickJS WASM for compiled binaries — must run before server imports
2+import { dirname, join } from "node:path";
3+const wasmOnDisk = join(dirname(process.execPath), "emscripten-module.wasm");
4+if (typeof Bun !== "undefined" && await Bun.file(wasmOnDisk).exists()) {
5+ const { setQuickJSModule } = await import("@executor/runtime-quickjs");
6+ const { newQuickJSWASMModule } = await import("quickjs-emscripten");
7+ const wasmBinary = await Bun.file(wasmOnDisk).arrayBuffer();
8+ const variant = {
9+ type: "sync" as const,
10+ importFFI: () => import("@jitl/quickjs-wasmfile-release-sync/ffi").then((m: any) => m.QuickJSFFI),
11+ importModuleLoader: () =>
12+ import("@jitl/quickjs-wasmfile-release-sync/emscripten-module").then((m: any) => {
13+ const original = m.default;
14+ return (moduleArg: any = {}) => original({ ...moduleArg, wasmBinary });
15+ }),
16+ };
17+ const mod = await newQuickJSWASMModule(variant as any);
18+ setQuickJSModule(mod);
19+}
20+
21+import { spawn } from "node:child_process";
22+import { resolve } from "node:path";
23+import { Command, Options, Args } from "@effect/cli";
24+import { BunRuntime } from "@effect/platform-bun";
25+import { FetchHttpClient, HttpApiClient } from "@effect/platform";
26+import * as Effect from "effect/Effect";
27+import * as Option from "effect/Option";
28+import * as Cause from "effect/Cause";
29+
30+import { ExecutorApi } from "@executor/api";
31+import { createServerHandlers, runMcpStdioServer, getExecutor } from "@executor/server";
32+
33+// ---------------------------------------------------------------------------
34+// Constants
35+// ---------------------------------------------------------------------------
36+
37+const CLI_NAME = "executor";
38+const { version: CLI_VERSION } = await import("../package.json");
39+const DEFAULT_PORT = 8788;
40+const DEFAULT_BASE_URL = `http://localhost:${DEFAULT_PORT}`;
41+
42+// Embedded web UI — baked into compiled binaries via `with { type: "file" }`
43+const embeddedWebUI: Record<string, string> | null =
44+ await import("embedded-web-ui.gen.ts")
45+ .then((m) => m.default as Record<string, string>)
46+ .catch(() => null);
47+
48+// ---------------------------------------------------------------------------
49+// Helpers
50+// ---------------------------------------------------------------------------
51+
52+const waitForShutdownSignal = () =>
53+ Effect.async<void, never>((resume) => {
54+ const shutdown = () => resume(Effect.void);
55+ process.once("SIGINT", shutdown);
56+ process.once("SIGTERM", shutdown);
57+ return Effect.sync(() => {
58+ process.off("SIGINT", shutdown);
59+ process.off("SIGTERM", shutdown);
60+ });
61+ });
62+
63+const appendUrlPath = (baseUrl: string, pathname: string): string =>
64+ new URL(pathname, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`).toString();
65+
66+const renderSessionSummary = (kind: "web" | "mcp", baseUrl: string): string => {
67+ const displayKind = kind === "mcp" ? "MCP" : "web";
68+ const primaryLabel = kind === "web" ? "Web" : "MCP";
69+ const primaryUrl = kind === "web" ? baseUrl : appendUrlPath(baseUrl, "mcp");
70+ const secondaryLabel = kind === "web" ? "MCP" : "Web";
71+ const secondaryUrl = kind === "web" ? appendUrlPath(baseUrl, "mcp") : baseUrl;
72+ const guidance =
73+ kind === "web"
74+ ? "Keep this process running while you use the browser session."
75+ : "Use this MCP URL in your client and keep this process running.";
76+
77+ return [
78+ `Executor ${displayKind} session is ready.`,
79+ `${primaryLabel}: ${primaryUrl}`,
80+ `${secondaryLabel}: ${secondaryUrl}`,
81+ `OpenAPI: ${appendUrlPath(baseUrl, "docs")}`,
82+ "",
83+ guidance,
84+ "Press Ctrl+C to stop.",
85+ ].join("\n");
86+};
87+
88+// ---------------------------------------------------------------------------
89+// Background server management
90+// ---------------------------------------------------------------------------
91+
92+const isServerReachable = async (baseUrl: string): Promise<boolean> => {
93+ try {
94+ const res = await fetch(`${baseUrl}/docs`, { signal: AbortSignal.timeout(2000) });
95+ return res.ok;
96+ } catch {
97+ return false;
98+ }
99+};
100+
101+const script = process.argv[1];
102+const isDevMode = script?.endsWith(".ts") || script?.endsWith(".js");
103+const cliPrefix = isDevMode ? `bun run ${script}` : "executor";
104+
105+const startBackgroundServer = (port: number): void => {
106+ const args = isDevMode
107+ ? ["run", script, "web", "--port", String(port)]
108+ : ["web", "--port", String(port)];
109+ const child = spawn(process.execPath, args, {
110+ detached: true,
111+ stdio: "ignore",
112+ });
113+ child.unref();
114+};
115+
116+const ensureServer = (baseUrl: string) =>
117+ Effect.gen(function* () {
118+ if (yield* Effect.promise(() => isServerReachable(baseUrl))) return;
119+
120+ const url = new URL(baseUrl);
121+ const port = Number(url.port) || DEFAULT_PORT;
122+ console.error(`Starting background server on port ${port}...`);
123+ startBackgroundServer(port);
124+
125+ const deadline = Date.now() + 30_000;
126+ while (Date.now() < deadline) {
127+ yield* Effect.promise(() => new Promise((r) => setTimeout(r, 200)));
128+ if (yield* Effect.promise(() => isServerReachable(baseUrl))) return;
129+ }
130+
131+ return yield* Effect.fail(new Error(`Server failed to start within 30s at ${baseUrl}`));
132+ });
133+
134+// ---------------------------------------------------------------------------
135+// Typed API client
136+// ---------------------------------------------------------------------------
137+
138+const makeApiClient = (baseUrl: string) =>
139+ HttpApiClient.make(ExecutorApi, { baseUrl }).pipe(
140+ Effect.provide(FetchHttpClient.layer),
141+ );
142+
143+// ---------------------------------------------------------------------------
144+// Static file serving from embedded web UI
145+// ---------------------------------------------------------------------------
146+
147+const WEB_DIST_DIR = resolve(import.meta.dirname, "../../web/dist");
148+
149+const serveStatic = async (pathname: string): Promise<Response | null> => {
150+ const key = pathname.replace(/^\//, "");
151+
152+ // Compiled binary: serve from embedded bunfs
153+ if (embeddedWebUI) {
154+ const match = embeddedWebUI[key] ?? embeddedWebUI["index.html"] ?? null;
155+ if (!match) return null;
156+ const file = Bun.file(match);
157+ if (await file.exists()) {
158+ return new Response(file, {
159+ headers: { "content-type": file.type || "application/octet-stream" },
160+ });
161+ }
162+ return null;
163+ }
164+
165+ // Dev mode: serve from apps/web/dist on disk
166+ const filePath = resolve(WEB_DIST_DIR, key);
167+ if (!filePath.startsWith(WEB_DIST_DIR)) return null;
168+
169+ const file = Bun.file(filePath);
170+ if (await file.exists()) {
171+ return new Response(file, {
172+ headers: { "content-type": file.type || "application/octet-stream" },
173+ });
174+ }
175+
176+ // SPA fallback
177+ const index = Bun.file(resolve(WEB_DIST_DIR, "index.html"));
178+ if (await index.exists()) {
179+ return new Response(index, { headers: { "content-type": "text/html" } });
180+ }
181+
182+ return null;
183+};
184+
185+// ---------------------------------------------------------------------------
186+// Foreground session — API + MCP + Web UI on one Bun.serve()
187+// ---------------------------------------------------------------------------
188+
189+const runForegroundSession = (input: { kind: "web" | "mcp"; port: number }) =>
190+ Effect.gen(function* () {
191+ const handlers = yield* Effect.promise(() => createServerHandlers());
192+
193+ const server = Bun.serve({
194+ port: input.port,
195+ async fetch(request) {
196+ const url = new URL(request.url);
197+
198+ if (url.pathname.startsWith("/mcp")) {
199+ return handlers.mcp.handleRequest(request);
200+ }
201+
202+ if (
203+ url.pathname.startsWith("/v1/") ||
204+ url.pathname.startsWith("/docs") ||
205+ url.pathname === "/openapi.json"
206+ ) {
207+ return handlers.api.handler(request);
208+ }
209+
210+ const staticResponse = await serveStatic(url.pathname);
211+ if (staticResponse) return staticResponse;
212+
213+ return new Response("Not Found", { status: 404 });
214+ },
215+ });
216+
217+ const baseUrl = `http://localhost:${server.port}`;
218+ console.log(renderSessionSummary(input.kind, baseUrl));
219+
220+ yield* waitForShutdownSignal();
221+
222+ server.stop(true);
223+ yield* Effect.promise(() => handlers.mcp.close());
224+ yield* Effect.promise(() => handlers.api.dispose());
225+ });
226+
227+// ---------------------------------------------------------------------------
228+// Stdio MCP session
229+// ---------------------------------------------------------------------------
230+
231+const runStdioMcpSession = () =>
232+ Effect.gen(function* () {
233+ const executor = yield* Effect.promise(() => getExecutor());
234+ yield* Effect.promise(() => runMcpStdioServer({ executor }));
235+ });
236+
237+// ---------------------------------------------------------------------------
238+// Code resolution — positional arg > --file > stdin
239+// ---------------------------------------------------------------------------
240+
241+const readCode = (input: {
242+ code: Option.Option<string>;
243+ file: Option.Option<string>;
244+ stdin: boolean;
245+}): Effect.Effect<string, Error> =>
246+ Effect.gen(function* () {
247+ const code = Option.getOrUndefined(input.code);
248+ if (code && code.trim().length > 0) return code;
249+
250+ const file = Option.getOrUndefined(input.file);
251+ if (file && file.trim().length > 0) {
252+ const contents = yield* Effect.tryPromise({
253+ try: () => Bun.file(file).text(),
254+ catch: (e) => new Error(`Failed to read file: ${e}`),
255+ });
256+ if (contents.trim().length > 0) return contents;
257+ }
258+
259+ if (input.stdin || !process.stdin.isTTY) {
260+ const chunks: string[] = [];
261+ process.stdin.setEncoding("utf8");
262+ const contents = yield* Effect.tryPromise({
263+ try: async () => {
264+ for await (const chunk of process.stdin) chunks.push(chunk as string);
265+ return chunks.join("");
266+ },
267+ catch: (e) => new Error(`Failed to read stdin: ${e}`),
268+ });
269+ if (contents.trim().length > 0) return contents;
270+ }
271+
272+ return yield* Effect.fail(
273+ new Error("No code provided. Pass code as an argument, --file, or pipe to stdin."),
274+ );
275+ });
276+
277+// ---------------------------------------------------------------------------
278+// Commands
279+// ---------------------------------------------------------------------------
280+
281+const callCommand = Command.make(
282+ "call",
283+ {
284+ code: Args.text({ name: "code" }).pipe(Args.optional),
285+ file: Options.text("file").pipe(Options.optional),
286+ stdin: Options.boolean("stdin").pipe(Options.withDefault(false)),
287+ baseUrl: Options.text("base-url").pipe(Options.withDefault(DEFAULT_BASE_URL)),
288+ },
289+ ({ code, file, stdin, baseUrl }) =>
290+ Effect.gen(function* () {
291+ const resolvedCode = yield* readCode({ code, file, stdin });
292+ yield* ensureServer(baseUrl);
293+
294+ const client = yield* makeApiClient(baseUrl);
295+ const result = yield* client.executions.execute({ payload: { code: resolvedCode } });
296+
297+ if (result.status === "completed") {
298+ if (result.isError) {
299+ console.error(result.text);
300+ process.exitCode = 1;
301+ } else {
302+ console.log(result.text);
303+ }
304+ } else {
305+ console.log(result.text);
306+ const executionId = (result.structured as any)?.executionId;
307+ if (executionId) {
308+ console.log(
309+ `\nTo resume:\n ${cliPrefix} resume --execution-id ${executionId} --action accept`,
310+ );
311+ }
312+ }
313+ }),
314+).pipe(Command.withDescription("Execute code against the local executor"));
315+
316+const resumeCommand = Command.make(
317+ "resume",
318+ {
319+ executionId: Options.text("execution-id"),
320+ action: Options.text("action").pipe(Options.withDefault("accept")),
321+ content: Options.text("content").pipe(Options.optional),
322+ baseUrl: Options.text("base-url").pipe(Options.withDefault(DEFAULT_BASE_URL)),
323+ },
324+ ({ executionId, action, content, baseUrl }) =>
325+ Effect.gen(function* () {
326+ yield* ensureServer(baseUrl);
327+
328+ const parsedContent = Option.getOrUndefined(content);
329+ const contentObj = parsedContent ? JSON.parse(parsedContent) : undefined;
330+
331+ const client = yield* makeApiClient(baseUrl);
332+ const result = yield* client.executions.resume({
333+ path: { executionId },
334+ payload: { action: action as "accept" | "decline" | "cancel", content: contentObj },
335+ });
336+
337+ if (result.isError) {
338+ console.error(result.text);
339+ process.exitCode = 1;
340+ } else {
341+ console.log(result.text);
342+ }
343+ }),
344+).pipe(Command.withDescription("Resume a paused execution"));
345+
346+const webCommand = Command.make(
347+ "web",
348+ {
349+ port: Options.integer("port").pipe(Options.withDefault(DEFAULT_PORT)),
350+ },
351+ ({ port }) => runForegroundSession({ kind: "web", port }),
352+).pipe(Command.withDescription("Start a foreground web session"));
353+
354+const mcpCommand = Command.make(
355+ "mcp",
356+ {},
357+ () => runStdioMcpSession(),
358+).pipe(Command.withDescription("Start an MCP server over stdio"));
359+
360+// ---------------------------------------------------------------------------
361+// Root command
362+// ---------------------------------------------------------------------------
363+
364+const root = Command.make("executor").pipe(
365+ Command.withSubcommands([callCommand, resumeCommand, webCommand, mcpCommand] as const),
366+ Command.withDescription("Executor local CLI"),
367+);
368+
369+// ---------------------------------------------------------------------------
370+// Run
371+// ---------------------------------------------------------------------------
372+
373+const runCli = Command.run(root, {
374+ name: CLI_NAME,
375+ version: CLI_VERSION,
376+ executable: CLI_NAME,
377+});
378+
379+const program = runCli(process.argv).pipe(
380+ Effect.catchAllCause((cause) =>
381+ Effect.sync(() => {
382+ console.error(Cause.pretty(cause));
383+ process.exitCode = 1;
384+ }),
385+ ),
386+);
387+
388+BunRuntime.runMain(program as Effect.Effect<void, never, never>);
apps/cli/src/release.ts+270−0
@@ -0,0 +1,270 @@
1+import { existsSync } from "node:fs";
2+import { mkdir, readdir, rename, rm } from "node:fs/promises";
3+import { dirname, join, resolve } from "node:path";
4+import { fileURLToPath } from "node:url";
5+
6+type ReleaseChannel = "latest" | "beta";
7+
8+type ReleaseCliOptions = {
9+ readonly dryRun: boolean;
10+};
11+
12+type CommandInput = {
13+ readonly command: string;
14+ readonly args: ReadonlyArray<string>;
15+ readonly cwd: string;
16+ readonly captureOutput?: boolean;
17+};
18+
19+type CommandOutput = {
20+ readonly stdout: string;
21+ readonly stderr: string;
22+};
23+
24+const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
25+const cliRoot = resolve(repoRoot, "apps/cli");
26+const distDir = resolve(cliRoot, "dist");
27+const releaseDir = resolve(distDir, "release");
28+const wrapperDir = resolve(distDir, "executor");
29+const versionPackagePath = resolve(cliRoot, "package.json");
30+const semverPattern =
31+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
32+
33+const parseArgs = (argv: ReadonlyArray<string>): ReleaseCliOptions => {
34+ let dryRun = false;
35+
36+ for (const arg of argv) {
37+ if (arg === "--dry-run") {
38+ dryRun = true;
39+ continue;
40+ }
41+
42+ throw new Error(`Unknown argument: ${arg}`);
43+ }
44+
45+ return { dryRun };
46+};
47+
48+const runCommand = async (input: CommandInput): Promise<CommandOutput> => {
49+ const proc = Bun.spawn([input.command, ...input.args], {
50+ cwd: input.cwd,
51+ env: process.env,
52+ stdio: input.captureOutput ? ["ignore", "pipe", "pipe"] : ["ignore", "inherit", "inherit"],
53+ });
54+
55+ const exitCode = await proc.exited;
56+ const stdout = input.captureOutput && proc.stdout ? await new Response(proc.stdout).text() : "";
57+ const stderr = input.captureOutput && proc.stderr ? await new Response(proc.stderr).text() : "";
58+
59+ if (exitCode !== 0) {
60+ throw new Error(
61+ [
62+ `${input.command} ${input.args.join(" ")} exited with code ${exitCode}`,
63+ stdout.trim().length > 0 ? `stdout:\n${stdout.trim()}` : null,
64+ stderr.trim().length > 0 ? `stderr:\n${stderr.trim()}` : null,
65+ ]
66+ .filter((part) => part !== null)
67+ .join("\n\n"),
68+ );
69+ }
70+
71+ return {
72+ stdout: stdout.trim(),
73+ stderr: stderr.trim(),
74+ };
75+};
76+
77+const readVersion = async (): Promise<string> => {
78+ const pkg = await Bun.file(versionPackagePath).json() as { version?: string };
79+ const version = pkg.version?.trim();
80+
81+ if (!version) {
82+ throw new Error(`Missing version in ${versionPackagePath}`);
83+ }
84+
85+ return version;
86+};
87+
88+const validateVersion = (version: string): void => {
89+ if (!semverPattern.test(version)) {
90+ throw new Error(`${versionPackagePath} version is not valid semver: ${version}`);
91+ }
92+};
93+
94+const resolveChannel = (version: string): ReleaseChannel =>
95+ version.includes("-") ? "beta" : "latest";
96+
97+const resolveTagFromEnvironment = (): string | undefined => {
98+ const refName = process.env.GITHUB_REF_NAME?.trim();
99+ if (process.env.GITHUB_REF_TYPE === "tag" && refName) {
100+ return refName;
101+ }
102+
103+ const ref = process.env.GITHUB_REF?.trim();
104+ if (ref?.startsWith("refs/tags/")) {
105+ return ref.slice("refs/tags/".length);
106+ }
107+
108+ return undefined;
109+};
110+
111+const resolveGitHubRepository = (): string => {
112+ const repository = process.env.GH_REPO?.trim() || process.env.GITHUB_REPOSITORY?.trim();
113+ if (!repository) {
114+ throw new Error("Set GH_REPO or GITHUB_REPOSITORY before creating a GitHub release.");
115+ }
116+
117+ return repository;
118+};
119+
120+const packWrapperPackage = async (): Promise<string> => {
121+ if (!existsSync(wrapperDir)) {
122+ throw new Error(`Wrapper package directory not found: ${wrapperDir}`);
123+ }
124+
125+ await mkdir(releaseDir, { recursive: true });
126+
127+ const before = new Set((await readdir(wrapperDir)).filter((entry) => entry.endsWith(".tgz")));
128+ await runCommand({
129+ command: "bun",
130+ args: ["pm", "pack"],
131+ cwd: wrapperDir,
132+ });
133+
134+ const after = (await readdir(wrapperDir)).filter((entry) => entry.endsWith(".tgz"));
135+ const archiveName = after.find((entry) => !before.has(entry)) ?? after[0];
136+
137+ if (!archiveName) {
138+ throw new Error(`bun pm pack did not create a .tgz archive in ${wrapperDir}`);
139+ }
140+
141+ const sourcePath = join(wrapperDir, archiveName);
142+ const destinationPath = join(releaseDir, archiveName);
143+
144+ await rm(destinationPath, { force: true });
145+ await rename(sourcePath, destinationPath);
146+
147+ return destinationPath;
148+};
149+
150+const collectReleaseAssetPaths = async (wrapperArchivePath: string): Promise<ReadonlyArray<string>> => {
151+ const assetNames = (await readdir(distDir))
152+ .filter((entry) => /^executor-.*\.(?:tar\.gz|zip)$/.test(entry))
153+ .sort();
154+
155+ return [
156+ wrapperArchivePath,
157+ ...assetNames.map((entry) => join(distDir, entry)),
158+ ];
159+};
160+
161+const githubReleaseExists = async (tag: string, repository: string): Promise<boolean> => {
162+ const proc = Bun.spawn(["gh", "release", "view", tag, "--repo", repository], {
163+ cwd: repoRoot,
164+ env: process.env,
165+ stdio: ["ignore", "ignore", "ignore"],
166+ });
167+
168+ return (await proc.exited) === 0;
169+};
170+
171+const syncGitHubRelease = async (input: {
172+ readonly tag: string;
173+ readonly channel: ReleaseChannel;
174+ readonly assetPaths: ReadonlyArray<string>;
175+}): Promise<void> => {
176+ if (!process.env.GH_TOKEN?.trim()) {
177+ throw new Error("GH_TOKEN is required to create or update a GitHub release.");
178+ }
179+
180+ const repository = resolveGitHubRepository();
181+
182+ if (await githubReleaseExists(input.tag, repository)) {
183+ await runCommand({
184+ command: "gh",
185+ args: ["release", "upload", input.tag, ...input.assetPaths, "--repo", repository, "--clobber"],
186+ cwd: repoRoot,
187+ });
188+ return;
189+ }
190+
191+ const args = [
192+ "release",
193+ "create",
194+ input.tag,
195+ ...input.assetPaths,
196+ "--repo",
197+ repository,
198+ "--title",
199+ input.tag,
200+ "--generate-notes",
201+ "--verify-tag",
202+ ];
203+
204+ if (input.channel === "beta") {
205+ args.push("--prerelease");
206+ } else {
207+ args.push("--latest");
208+ }
209+
210+ await runCommand({
211+ command: "gh",
212+ args,
213+ cwd: repoRoot,
214+ });
215+};
216+
217+const main = async () => {
218+ const options = parseArgs(process.argv.slice(2));
219+ const version = await readVersion();
220+ const tag = `v${version}`;
221+ const refTag = resolveTagFromEnvironment();
222+ const channel = resolveChannel(version);
223+
224+ validateVersion(version);
225+
226+ if (refTag && refTag !== tag) {
227+ throw new Error(`GitHub tag ${refTag} does not match ${versionPackagePath} version ${version}`);
228+ }
229+
230+ await rm(releaseDir, { recursive: true, force: true });
231+ await mkdir(releaseDir, { recursive: true });
232+
233+ await runCommand({
234+ command: "bun",
235+ args: ["run", "src/build.ts", "binary"],
236+ cwd: cliRoot,
237+ });
238+
239+ await runCommand({
240+ command: "bun",
241+ args: ["run", "src/build.ts", "release-assets"],
242+ cwd: cliRoot,
243+ });
244+
245+ const wrapperArchivePath = await packWrapperPackage();
246+ const assetPaths = await collectReleaseAssetPaths(wrapperArchivePath);
247+
248+ console.log(`Prepared executor@${version} for ${channel}`);
249+ for (const assetPath of assetPaths) {
250+ console.log(`- ${assetPath}`);
251+ }
252+
253+ if (options.dryRun) {
254+ return;
255+ }
256+
257+ await runCommand({
258+ command: "bun",
259+ args: ["run", "src/build.ts", "publish", channel],
260+ cwd: cliRoot,
261+ });
262+
263+ await syncGitHubRelease({
264+ tag,
265+ channel,
266+ assetPaths,
267+ });
268+};
269+
270+await main();
apps/cli/tsconfig.json+14−0
@@ -0,0 +1,14 @@
1+{
2+ "compilerOptions": {
3+ "strict": true,
4+ "target": "ESNext",
5+ "module": "ESNext",
6+ "moduleResolution": "bundler",
7+ "esModuleInterop": true,
8+ "skipLibCheck": true,
9+ "noEmit": true,
10+ "declaration": true,
11+ "types": ["bun-types"]
12+ },
13+ "include": ["src", "bin"]
14+}
apps/docs/CHANGELOG.md+0−3
@@ -1,3 +0,0 @@
1−# @executor/docs
2−
3−## null
apps/docs/docs.json+0−32
@@ -1,32 +0,0 @@
1−{
2− "$schema": "https://mintlify.com/docs.json",
3− "theme": "mint",
4− "name": "Executor",
5− "description": "A local-first execution environment for AI agents.",
6− "colors": {
7− "primary": "#0D9373",
8− "light": "#07C983",
9− "dark": "#0D9373"
10− },
11− "navigation": {
12− "tabs": [
13− {
14− "tab": "Docs",
15− "groups": [
16− {
17− "group": "Status",
18− "pages": [
19− "introduction"
20− ]
21− }
22− ]
23− }
24− ]
25− },
26− "footer": {
27− "socials": {
28− "github": "https://github.com/anomalyco/executor",
29− "discord": "https://discord.gg/eF29HBHwM6"
30− }
31− }
32−}
apps/docs/introduction.mdx+0−10
@@ -1,10 +0,0 @@
1−---
2−title: "Introduction"
3−description: "A local-first execution environment for AI agents."
4−---
5−
6−`executor` is a local-first execution environment for AI agents. It gives an agent a TypeScript runtime, a discoverable tool catalog, and a single local place to connect external systems such as MCP servers, OpenAPI APIs, and GraphQL APIs.
7−
8−The docs set has been intentionally removed for now while the plugin architecture is still shifting.
9−
10−Use the repository source directly if you need current implementation details.
apps/docs/package.json+0−11
@@ -1,11 +0,0 @@
1−{
2− "name": "@executor/docs",
3− "private": true,
4− "type": "module",
5− "scripts": {
6− "dev": "bunx --bun mint dev --no-open --port 3337",
7− "typecheck": "echo 'No typecheck for @executor/docs'",
8− "validate": "bunx --bun mint validate"
9− },
10− "version": "0.0.0"
11−}
apps/executor/CHANGELOG.md+0−175
@@ -1,175 +0,0 @@
1−# executor
2−
3−## 1.3.0-beta.5
4−
5−### Patch Changes
6−
7−- 0316b25: Compact openapi sources
8−
9−## 1.3.0-beta.4
10−
11−### Patch Changes
12−
13−- 787dd66: Improve Google Discovery sources view
14−
15−## 1.3.0-beta.3
16−
17−### Patch Changes
18−
19−- Improve MCP source setup by auto-detecting OAuth requirements, showing a loading state during discovery, and allowing creation without signing in.
20−
21−## 1.3.0-beta.2
22−
23−### Patch Changes
24−
25−- Fix the packaged beta so the bundled 1Password SDK can load its wasm asset after install.
26−
27−## 1.3.0-beta.1
28−
29−### Patch Changes
30−
31−- Fix the beta distribution packaging flow so the prerelease publish passes again.
32−
33−## 1.3.0-beta.0
34−
35−### Minor Changes
36−
37−- e4b1359: Prepare the next executor beta minor release.
38−
39−## 1.2.6
40−
41−### Patch Changes
42−
43−- 54d39e4: Disable executor injected tools
44−
45−## 1.2.5
46−
47−### Patch Changes
48−
49−- d95a087: Add stdio MCP support via `executor mcp --stdio`, make foreground `web` and `mcp` sessions first-class CLI entrypoints, and update the dashboard MCP install card to default to the stdio install flow with an HTTP toggle.
50−
51−## 1.2.5-beta.0
52−
53−### Patch Changes
54−
55−- d95a087: Add stdio MCP support via `executor mcp --stdio`, make foreground `web` and `mcp` sessions first-class CLI entrypoints, and update the dashboard MCP install card to default to the stdio install flow with an HTTP toggle.
56−
57−## 1.2.4
58−
59−### Patch Changes
60−
61−- 5617247: Prewarm the lean workspace source index at startup and reuse it across discovery requests so the first tool search no longer pays the full catalog hydration cost.
62−- dc94998: Auto migrate sources on startup
63−- 74185a9: Move execution to adapters rather than IR model
64−- 1f82a22: Avoid generating source tool type previews when building namespace metadata, and cap MCP execute help examples to five tools per source.
65−- 5e3cb3e: Add GitHub source support, migrate legacy executor state on load, and fix execute-path runtime regressions.
66−- f0a3802: Fix legacy format parsing
67−- 44ce032: Avoid ever building a full schema workspace catalog during tool description, and resolve schemaful tool details through direct one-tool lookup instead.
68−- ec5e3a3: Fix Google Discovery tool execution for sources stored with discovery document endpoints
69−- 839dcb6: Make `executor up` output more helpful and less debug-oriented.
70−- 5869ddb: Fix build
71−
72−## 1.2.4-beta.9
73−
74−### Patch Changes
75−
76−- 44ce032: Avoid ever building a full schema workspace catalog during tool description, and resolve schemaful tool details through direct one-tool lookup instead.
77−
78−## 1.2.4-beta.8
79−
80−### Patch Changes
81−
82−- 5617247: Prewarm the lean workspace source index at startup and reuse it across discovery requests so the first tool search no longer pays the full catalog hydration cost.
83−
84−## 1.2.4-beta.7
85−
86−### Patch Changes
87−
88−- 1f82a22: Avoid generating source tool type previews when building namespace metadata, and cap MCP execute help examples to five tools per source.
89−
90−## 1.2.4-beta.6
91−
92−### Patch Changes
93−
94−- 839dcb6: Make `executor up` output more helpful and less debug-oriented.
95−
96−## 1.2.4-beta.5
97−
98−### Patch Changes
99−
100−- 5e3cb3e: Add GitHub source support, migrate legacy executor state on load, and fix execute-path runtime regressions.
101−
102−## 1.2.4-beta.4
103−
104−### Patch Changes
105−
106−- ec5e3a3: Fix Google Discovery tool execution for sources stored with discovery document endpoints
107−
108−## 1.2.4-beta.3
109−
110−### Patch Changes
111−
112−- dc94998: Auto migrate sources on startup
113−
114−## 1.2.4-beta.2
115−
116−### Patch Changes
117−
118−- f0a3802: Fix legacy format parsing
119−
120−## 1.2.4-beta.1
121−
122−### Patch Changes
123−
124−- 5869ddb: Fix build
125−
126−## 1.2.4-beta.0
127−
128−### Patch Changes
129−
130−- 74185a9: Move execution to adapters rather than IR model
131−
132−## 1.2.3
133−
134−### Patch Changes
135−
136−- eda1217: Always request maximal scope for Google Apis
137−
138−## 1.2.2
139−
140−### Patch Changes
141−
142−- 661ed29: Support selecting runtime
143−
144−## 1.2.1
145−
146−### Patch Changes
147−
148−- 329cc41: fix migration
149−- 86d4d4d: package the PGlite runtime assets in the published CLI bundle
150−
151−## 1.2.0
152−
153−### Minor Changes
154−
155−- 7574535: add multiple sources at same time
156−
157−### Patch Changes
158−
159−- a2ada62: Google workspace support, folder based config
160− - @executor/codemode-core@null
161− - @executor/control-plane@null
162− - @executor/executor-mcp@null
163− - @executor/server@null
164−
165−## 1.2.0-beta.7
166−
167−### Minor Changes
168−
169−- 7574535: add multiple sources at same time
170−
171−## 1.1.10-beta.6
172−
173−### Patch Changes
174−
175−- a2ada62: Google workspace support, folder based config
apps/executor/bin/executor+0−10
@@ -1,10 +0,0 @@
1−#!/usr/bin/env bash
2−set -euo pipefail
3−SOURCE="$0"
4−while [ -L "$SOURCE" ]; do
5− DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
6− SOURCE="$(readlink "$SOURCE")"
7− [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE"
8−done
9−SCRIPT_DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
10−exec bun "$SCRIPT_DIR/../src/cli/main.ts" "$@"
apps/executor/package.json+0−65
@@ -1,65 +0,0 @@
1−{
2− "name": "executor",
3− "version": "1.3.0-beta.5",
4− "description": "Local AI executor with a CLI, local API server, and web UI.",
5− "keywords": [
6− "executor",
7− "ai",
8− "agent",
9− "cli",
10− "automation",
11− "local-first"
12− ],
13− "homepage": "https://github.com/RhysSullivan/executor",
14− "bugs": {
15− "url": "https://github.com/RhysSullivan/executor/issues"
16− },
17− "repository": {
18− "type": "git",
19− "url": "git+https://github.com/RhysSullivan/executor.git"
20− },
21− "license": "MIT",
22− "private": true,
23− "type": "module",
24− "bin": {
25− "executor": "bin/executor"
26− },
27− "scripts": {
28− "typecheck": "bunx tsc --noEmit -p tsconfig.json",
29− "test": "vitest run",
30− "test:watch": "vitest",
31− "start": "bun src/cli/main.ts",
32− "release:publish:dry-run": "bun src/distribution/publish.ts --dry-run",
33− "release:publish": "bun src/distribution/publish.ts"
34− },
35− "dependencies": {
36− "@effect/cli": "catalog:",
37− "@effect/platform": "catalog:",
38− "@effect/platform-node": "catalog:",
39− "@executor/codemode-core": "workspace:*",
40− "@executor/executor-mcp": "workspace:*",
41− "@executor/plugin-google-discovery-sdk": "workspace:*",
42− "@executor/plugin-graphql-sdk": "workspace:*",
43− "@executor/plugin-keychain-secret-store-sdk": "workspace:*",
44− "@executor/plugin-local-secret-store-sdk": "workspace:*",
45− "@executor/plugin-local-tools-sdk": "workspace:*",
46− "@executor/plugin-mcp-sdk": "workspace:*",
47− "@executor/plugin-openapi-sdk": "workspace:*",
48− "@executor/platform-api": "workspace:*",
49− "@executor/platform-sdk": "workspace:*",
50− "@executor/platform-sdk-file": "workspace:*",
51− "@executor/server": "workspace:*",
52− "effect": "catalog:"
53− },
54− "devDependencies": {
55− "@executor/effect-test-utils": "workspace:*",
56− "@executor/mcp-elicitation-demo": "workspace:*",
57− "@executor/runtime-ses": "workspace:*",
58− "@effect/vitest": "catalog:",
59− "@modelcontextprotocol/sdk": "^1.26.0",
60− "@types/node": "catalog:",
61− "bun-types": "catalog:",
62− "vitest": "catalog:",
63− "zod": "catalog:"
64− }
65−}
apps/executor/src/cli/interaction-handling.test.ts+0−37
@@ -1,37 +0,0 @@
1−import { describe, expect, it } from "@effect/vitest";
2−
3−import { decideInteractionHandling } from "./interaction-handling";
4−
5−describe("interaction-handling", () => {
6− it("keeps URL interactions distinct even when the terminal is non-interactive", () => {
7− expect(decideInteractionHandling({
8− parsed: {
9− mode: "url",
10− message: "Connect Axiom",
11− url: "https://mcp.axiom.co/authorize",
12− },
13− isInteractiveTerminal: false,
14− })).toBe("url_paused");
15− });
16−
17− it("waits on URL interactions in an interactive terminal", () => {
18− expect(decideInteractionHandling({
19− parsed: {
20− mode: "url",
21− message: "Connect Axiom",
22− url: "https://mcp.axiom.co/authorize",
23− },
24− isInteractiveTerminal: true,
25− })).toBe("url_interactive");
26− });
27−
28− it("falls back to form pause handling for non-interactive prompts", () => {
29− expect(decideInteractionHandling({
30− parsed: {
31− mode: "form",
32− message: "Approve tool call",
33− },
34− isInteractiveTerminal: false,
35− })).toBe("form_paused");
36− });
37−});
apps/executor/src/cli/interaction-handling.ts+0−18
@@ -1,18 +0,0 @@
1−import type { ParsedInteractionPayload } from "./pending-interaction-output";
2−
3−export type InteractionHandling =
4− | "url_interactive"
5− | "url_paused"
6− | "form_interactive"
7− | "form_paused";
8−
9−export const decideInteractionHandling = (input: {
10− parsed: ParsedInteractionPayload | null;
11− isInteractiveTerminal: boolean;
12−}): InteractionHandling => {
13− if (input.parsed?.mode === "url") {
14− return input.isInteractiveTerminal ? "url_interactive" : "url_paused";
15− }
16−
17− return input.isInteractiveTerminal ? "form_interactive" : "form_paused";
18−};
apps/executor/src/cli/main.ts+0−1196
@@ -1,1196 +0,0 @@
1−import { spawn } from "node:child_process";
2−import { createRequire } from "node:module";
3−import { dirname } from "node:path";
4−import { createInterface } from "node:readline/promises";
5−import { FileSystem } from "@effect/platform";
6−import { Args, Command, Options } from "@effect/cli";
7−import {
8− NodeFileSystem,
9− NodePath,
10− NodeRuntime,
11−} from "@effect/platform-node";
12−import {
13− createExecutorApiEffectClient as createExecutorApiClient,
14− type ExecutorApiEffectClient as ExecutorApiClient,
15−} from "@executor/platform-api/effect";
16−import { runExecutorMcpStdioServer } from "@executor/executor-mcp";
17−import {
18− googleDiscoverySdkPlugin,
19−} from "@executor/plugin-google-discovery-sdk";
20−import {
21− graphqlSdkPlugin,
22−} from "@executor/plugin-graphql-sdk";
23−import {
24− keychainSecretStoreSdkPlugin,
25−} from "@executor/plugin-keychain-secret-store-sdk";
26−import {
27− localSecretStoreSdkPlugin,
28−} from "@executor/plugin-local-secret-store-sdk";
29−import {
30− localToolsSdkPlugin,
31−} from "@executor/plugin-local-tools-sdk";
32−import {
33− mcpSdkPlugin,
34−} from "@executor/plugin-mcp-sdk";
35−import {
36− openApiSdkPlugin,
37−} from "@executor/plugin-openapi-sdk";
38−import {
39− getExecutorInternalToolHelpLines,
40− RuntimeExecutionResolverService,
41−} from "@executor/platform-sdk/runtime";
42−import type {
43− ExecutorSdkPluginRegistry,
44−} from "@executor/platform-sdk/plugins";
45−import {
46− createExecutorEffect,
47− type ExecutorEffect as Executor,
48−} from "@executor/platform-sdk/effect";
49−import {
50− createLocalExecutorBackend,
51−} from "@executor/platform-sdk-file";
52−import {
53− ExecutionIdSchema,
54− type ExecutionEnvelope,
55− type ExecutionInteraction,
56−} from "@executor/platform-sdk/schema";
57−import type { ToolCatalog } from "@executor/codemode-core";
58−
59−import * as Effect from "effect/Effect";
60−import * as Schema from "effect/Schema";
61−import * as Option from "effect/Option";
62−import * as Cause from "effect/Cause";
63−
64−import {
65− createFileGoogleDiscoveryOAuthSessionStorage,
66− createFileGoogleDiscoverySourceStorage,
67− createFileGraphqlSourceStorage,
68− createFileMcpOAuthSessionStorage,
69− createFileMcpSourceStorage,
70− createFileOpenApiSourceStorage,
71− createLocalExecutorServer,
72− DEFAULT_SERVER_BASE_URL,
73− DEFAULT_SERVER_HOST,
74− DEFAULT_SERVER_LOG_FILE,
75− DEFAULT_SERVER_PID_FILE,
76− DEFAULT_SERVER_PORT,
77− SERVER_POLL_INTERVAL_MS,
78− SERVER_START_TIMEOUT_MS,
79− runLocalExecutorServer,
80−} from "@executor/server";
81−import {
82− resolveCliLocalDataDir,
83− resolveRuntimeWebAssetsDir,
84− resolveSelfCommand,
85−} from "./runtime-paths";
86−import {
87− buildPausedExecutionOutput,
88− parseInteractionPayload,
89−} from "./pending-interaction-output";
90−import { decideInteractionHandling } from "./interaction-handling";
91−import {
92− renderMcpSessionSummary,
93− renderWebSessionSummary,
94−} from "./session-summary";
95−import {
96− executorAppEffectError,
97− type LocalServerReachabilityTimeoutError,
98− localServerReachabilityTimeoutError,
99−} from "../effect-errors";
100−
101−const toError = (cause: unknown): Error =>
102− cause instanceof Error ? cause : new Error(String(cause));
103−const sleep = (ms: number) =>
104− Effect.promise(() => new Promise<void>((resolve) => setTimeout(resolve, ms)));
105−
106−const openUrlInBrowser = (url: string): Effect.Effect<void, never, never> =>
107− Effect.sync(() => {
108− const cmd =
109− process.platform === "darwin"
110− ? ["open", url]
111− : process.platform === "win32"
112− ? ["cmd", "/c", "start", "", url]
113− : ["xdg-open", url];
114−
115− try {
116− const child = spawn(cmd[0]!, cmd.slice(1), {
117− detached: true,
118− stdio: "ignore",
119− });
120− child.on("error", () => undefined);
121− child.unref();
122− } catch {
123− // Best-effort browser launch only; always leave the URL in stdout.
124− }
125− }).pipe(Effect.catchAll(() => Effect.void));
126−
127−const promptLine = (prompt: string): Effect.Effect<string, Error, never> =>
128− Effect.tryPromise({
129− try: async () => {
130− const rl = createInterface({
131− input: process.stdin,
132− output: process.stdout,
133− });
134−
135− try {
136− return await rl.question(prompt);
137− } finally {
138− rl.close();
139− }
140− },
141− catch: toError,
142− });
143−
144−const readStdin = (): Effect.Effect<string, Error, never> =>
145− Effect.tryPromise({
146− try: async () => {
147− let contents = "";
148− process.stdin.setEncoding("utf8");
149− for await (const chunk of process.stdin) {
150− contents += chunk;
151− }
152− return contents;
153− },
154− catch: toError,
155− });
156−
157−const readCode = (input: {
158− code?: string;
159− file?: string;
160− stdin?: boolean;
161−}): Effect.Effect<string, Error, FileSystem.FileSystem> =>
162− Effect.gen(function* () {
163− if (input.code && input.code.trim().length > 0) {
164− return input.code;
165− }
166−
167− if (input.file && input.file.trim().length > 0) {
168− const fs = yield* FileSystem.FileSystem;
169− const contents = yield* fs.readFileString(input.file!, "utf8").pipe(
170− Effect.mapError(toError),
171− );
172− if (contents.trim().length > 0) {
173− return contents;
174− }
175− }
176−
177− const shouldReadStdin = input.stdin === true || !process.stdin.isTTY;
178− if (shouldReadStdin) {
179− const contents = yield* readStdin();
180− if (contents.trim().length > 0) {
181− return contents;
182− }
183− }
184−
185− return yield* executorAppEffectError("cli/main", "Provide code as a positional argument, use --file, or pipe code over stdin.");
186− });
187−
188−const getBootstrapClient = (baseUrl: string = DEFAULT_SERVER_BASE_URL) =>
189− createExecutorApiClient({ baseUrl });
190−
191−const decodeExecutionId = Schema.decodeUnknown(ExecutionIdSchema);
192−const require = createRequire(import.meta.url);
193−const CLI_NAME = "executor";
194−const CLI_LOCAL_DATA_DIR = resolveCliLocalDataDir();
195−const CLI_VERSION = (() => {
196− const candidatePaths = [
197− "../package.json",
198− "../../package.json",
199− ];
200−
201− for (const candidatePath of candidatePaths) {
202− try {
203− const metadata = require(candidatePath) as { version?: string };
204− if (metadata.version && metadata.version.trim().length > 0) {
205− return metadata.version;
206− }
207− } catch {
208− // Fall through to the default version below.
209− }
210− }
211−
212− return "0.0.0-local";
213−})();
214−const HELP_TOKENS = ["--help", "-h", "help"] as const;
215−
216−const isHelpToken = (value: string | undefined): boolean =>
217− value !== undefined && HELP_TOKENS.includes(value as (typeof HELP_TOKENS)[number]);
218−
219−const normalizeCliArgs = (rawArgs: readonly string[]): string[] => {
220− return rawArgs[0] === "run"
221− ? ["call", ...rawArgs.slice(1)]
222− : [...rawArgs];
223−};
224−
225−const getCliArgs = (): string[] => normalizeCliArgs(process.argv.slice(2));
226−
227−const toEffectCliArgv = (args: readonly string[]): string[] => [
228− process.execPath || CLI_NAME,
229− CLI_NAME,
230− ...args,
231−];
232−
233−const buildWorkflowText = (
234− namespaces: readonly string[] = [],
235− pluginRegistry?: ExecutorSdkPluginRegistry,
236−): string =>
237− [
238− "Execute TypeScript in sandbox; call tools via discovery workflow.",
239− ...(namespaces.length > 0
240− ? [
241− "Available namespaces:",
242− ...namespaces.map((namespace) => `- ${namespace}`),
243− ]
244− : []),
245− "Workflow:",
246− '1) const { results, bestPath } = await tools.discover({ query: "<intent>", limit: 12 });',
247− '2) const path = bestPath ?? results[0]?.path; if (!path) return "No matching tools found.";',
248− "3) const details = await tools.describe.tool({ path, includeSchemas: true });",
249− "4) Call selected tools.<path>(input).",
250− "5) Use source plugins to inspect or add API sources.",
251− ...(pluginRegistry
252− ? getExecutorInternalToolHelpLines(pluginRegistry)
253− : ["Use executor.* tools to inspect or manage API sources."]),
254− "6) If execution pauses for interaction, resume it with `executor resume --execution-id ...`.",
255− "The tools object is a lazy proxy, so Object.keys(tools) is not a useful way to discover capabilities.",
256− "Do not use fetch; use tools.* only.",
257− ].join("\n");
258−
259−const getDefaultRunWorkflow = (pluginRegistry?: ExecutorSdkPluginRegistry) =>
260− buildWorkflowText([], pluginRegistry);
261−
262−const indentBlock = (value: string, prefix: string = " "): string =>
263− value
264− .split("\n")
265− .map((line) => (line.length > 0 ? `${prefix}${line}` : ""))
266− .join("\n");
267−
268−const formatCauseMessage = (cause: Cause.Cause<unknown>): string => {
269− const failure = Option.getOrUndefined(Cause.failureOption(cause));
270− if (failure instanceof Error && failure.message.length > 0) {
271− return failure.message;
272− }
273− if (typeof failure === "string" && failure.length > 0) {
274− return failure;
275− }
276−
277− const defect = Option.getOrUndefined(Cause.dieOption(cause));
278− if (defect instanceof Error && defect.message.length > 0) {
279− return defect.message;
280− }
281− if (typeof defect === "string" && defect.length > 0) {
282− return defect;
283− }
284−
285− return Cause.pretty(cause).split("\n").find((line) => line.trim().length > 0) ?? "unknown error";
286−};
287−
288−const formatCatalogUnavailableMessage = (cause: Cause.Cause<unknown>): string => {
289− const message = formatCauseMessage(cause);
290− return message === "Error: An error has occurred"
291− ? "Current workspace catalog unavailable."
292− : `Current workspace catalog unavailable: ${message}`;
293−};
294−
295−const closeExecutor = (executor: Executor) =>
296− Effect.tryPromise({
297− try: () => executor.close(),
298− catch: toError,
299− }).pipe(Effect.catchAll(() => Effect.void));
300−
301−const buildRunWorkflowText = (
302− catalog?: ToolCatalog,
303− pluginRegistry?: ExecutorSdkPluginRegistry,
304−): Effect.Effect<string, Error, never> => {
305− if (!catalog) {
306− return Effect.succeed(getDefaultRunWorkflow(pluginRegistry));
307− }
308−
309− return catalog.listNamespaces({ limit: 200 }).pipe(
310− Effect.map((namespaces) =>
311− buildWorkflowText(
312− namespaces.length > 0
313− ? namespaces.map((namespace) => namespace.displayName ?? namespace.namespace)
314− : ["none discovered yet"],
315− pluginRegistry,
316− )
317− ),
318− Effect.mapError(toError),
319− );
320−};
321−
322−const loadRunWorkflowText = (): Effect.Effect<string, Error, never> =>
323− Effect.acquireUseRelease(
324− createExecutorEffect({
325− backend: createLocalExecutorBackend({
326− cwd: process.cwd(),
327− localDataDir: CLI_LOCAL_DATA_DIR,
328− }),
329− plugins: [
330− localSecretStoreSdkPlugin,
331− keychainSecretStoreSdkPlugin,
332− localToolsSdkPlugin(),
333− graphqlSdkPlugin({
334− storage: createFileGraphqlSourceStorage({
335− rootDir: `${CLI_LOCAL_DATA_DIR}/plugins/graphql/sources`,
336− }),
337− }),
338− googleDiscoverySdkPlugin({
339− storage: createFileGoogleDiscoverySourceStorage({
340− rootDir: `${CLI_LOCAL_DATA_DIR}/plugins/google-discovery/sources`,
341− }),
342− oauthSessions: createFileGoogleDiscoveryOAuthSessionStorage({
343− rootDir: `${CLI_LOCAL_DATA_DIR}/plugins/google-discovery/oauth-sessions`,
344− }),
345− }),
346− mcpSdkPlugin({
347− storage: createFileMcpSourceStorage({
348− rootDir: `${CLI_LOCAL_DATA_DIR}/plugins/mcp/sources`,
349− }),
350− oauthSessions: createFileMcpOAuthSessionStorage({
351− rootDir: `${CLI_LOCAL_DATA_DIR}/plugins/mcp/oauth-sessions`,
352− }),
353− }),
354− openApiSdkPlugin({
355− storage: createFileOpenApiSourceStorage({
356− rootDir: `${CLI_LOCAL_DATA_DIR}/plugins/openapi/sources`,
357− }),
358− }),
359− ] as const,
360− }).pipe(Effect.mapError(toError)),
361− (executor) =>
362− Effect.gen(function* () {
363− const environment = yield* Effect.gen(function* () {
364− const resolveExecutionEnvironment = yield* RuntimeExecutionResolverService;
365− return yield* resolveExecutionEnvironment({
366− scopeId: executor.scopeId,
367− actorScopeId: executor.actorScopeId,
368− executionId: ExecutionIdSchema.make("exec_help"),
369− });
370− }).pipe(
371− Effect.provide(executor.runtime.runtimeLayer),
372− Effect.mapError(toError),
373− );
374−
375− return yield* buildRunWorkflowText(
376− environment.catalog,
377− executor.runtime.pluginRegistry,
378− );
379− }),
380− closeExecutor,
381− ).pipe(
382− Effect.catchAllCause((cause) =>
383− Effect.succeed(
384− [
385− getDefaultRunWorkflow(),
386− "",
387− formatCatalogUnavailableMessage(cause),
388− ].join("\n"),
389− )
390− ),
391− );
392−
393−const printRootHelp = (workflow: string) =>
394− Effect.sync(() => {
395− console.log([
396− `${CLI_NAME} ${CLI_VERSION}`,
397− "",
398− "USAGE",
399− "",
400− " executor web [--port integer]",
401− " executor mcp [--port integer] [--stdio] [--web-port integer]",
402− " executor call [code] [--file text] [--stdin] [--base-url text] [--no-open]",
403− " executor resume --execution-id text [--base-url text] [--no-open]",
404− "",
405− "CALL WORKFLOW",
406− "",
407− indentBlock(workflow),
408− "",
409− "COMMANDS",
410− "",
411− " web",
412− " Start a foreground web session and print the local URL.",
413− " mcp",
414− " Start a foreground MCP session, or run stdio MCP with --stdio.",
415− " call",
416− " Execute code against the local executor server.",
417− " resume",
418− " Resume a paused execution.",
419− "",
420− "TIP",
421− "",
422− " Run `executor web` for the browser UI, `executor mcp` for HTTP MCP, or `executor mcp --stdio` for local stdio MCP.",
423− ].join("\n"));
424− });
425−
426−const printCallHelp = (workflow: string) =>
427− Effect.sync(() => {
428− console.log([
429− "executor call",
430− "",
431− "USAGE",
432− "",
433− " executor call [code] [--file text] [--stdin] [--base-url text] [--no-open]",
434− "",
435− "DESCRIPTION",
436− "",
437− " Execute code against the local executor server.",
438− "",
439− "WORKFLOW",
440− "",
441− indentBlock(workflow),
442− "",
443− "OPTIONS",
444− "",
445− " [code]",
446− " Inline code to execute.",
447− " --file text",
448− " Read code from a file.",
449− " --stdin",
450− " Read code from stdin.",
451− " --base-url text",
452− " Override the executor server base URL.",
453− " --no-open",
454− " Print interaction URLs without opening a browser.",
455− "",
456− "EXAMPLES",
457− "",
458− ' executor call \'const { results } = await tools.discover({ query: "github issues", limit: 5 }); return results.map((match) => match.path);\'',
459− ' executor call \'const { results, bestPath } = await tools.discover({ query: "repo details", limit: 1 }); const path = bestPath ?? results[0]?.path; return path ? await tools.describe.tool({ path, includeSchemas: true }) : null;\'',
460− " cat script.ts | executor call --stdin",
461− " executor call --file script.ts",
462− " executor call --no-open --file script.ts",
463− " executor resume --execution-id exec_123",
464− ].join("\n"));
465− });
466−
467−const helpOverride = (): Effect.Effect<void, Error, never> | null => {
468− const args = getCliArgs();
469−
470− if (args.length === 0 || (args.length === 1 && isHelpToken(args[0]))) {
471− return loadRunWorkflowText().pipe(Effect.flatMap(printRootHelp));
472− }
473−
474− if (args[0] === "call" && args.length === 2 && isHelpToken(args[1])) {
475− return loadRunWorkflowText().pipe(Effect.flatMap(printCallHelp));
476− }
477−
478− return null;
479−};
480−
481−const getLocalAuthedClient = (baseUrl: string = DEFAULT_SERVER_BASE_URL) =>
482− Effect.gen(function* () {
483− const bootstrapClient = yield* getBootstrapClient(baseUrl);
484− const installation = yield* bootstrapClient.local.installation({});
485− const client = yield* createExecutorApiClient({
486− baseUrl,
487− });
488−
489− return {
490− installation,
491− client,
492− } as const;
493− });
494−
495−const isServerReachable = (baseUrl: string) =>
496− getBootstrapClient(baseUrl).pipe(
497− Effect.flatMap((client) => client.local.installation({})),
498− Effect.as(true),
499− Effect.catchAll(() => Effect.succeed(false)),
500− );
501−
502−const getDefaultServerOptions = (port: number = DEFAULT_SERVER_PORT) => {
503− const assetsDir = resolveRuntimeWebAssetsDir();
504−
505− return {
506− host: DEFAULT_SERVER_HOST,
507− port,
508− localDataDir: CLI_LOCAL_DATA_DIR,
509− pidFile: DEFAULT_SERVER_PID_FILE,
510− ui: assetsDir ? { assetsDir } : undefined,
511− };
512−};
513−
514−const startServerInBackground = (port: number) =>
515− Effect.scoped(
516− Effect.gen(function* () {
517− const fs = yield* FileSystem.FileSystem;
518− const command = resolveSelfCommand(["__local-server", "--port", String(port)]);
519− yield* fs.makeDirectory(dirname(DEFAULT_SERVER_LOG_FILE), {
520− recursive: true,
521− }).pipe(Effect.mapError(toError));
522− const logHandle = yield* fs.open(DEFAULT_SERVER_LOG_FILE, {
523− flag: "a",
524− }).pipe(Effect.mapError(toError));
525−
526− yield* Effect.try({
527− try: () => {
528− const fd = Number(logHandle.fd);
529− const child = spawn(command[0]!, command.slice(1), {
530− detached: true,
531− stdio: ["ignore", fd, fd],
532− });
533− child.unref();
534− },
535− catch: toError,
536− });
537− }),
538− );
539−
540−const readServerLogTail = (
541− logFile: string = DEFAULT_SERVER_LOG_FILE,
542− maxLines: number = 40,
543− maxChars: number = 6000,
544−): Effect.Effect<string | null, never, FileSystem.FileSystem> =>
545− Effect.gen(function* () {
546− const fs = yield* FileSystem.FileSystem;
547− const contents = yield* fs.readFileString(logFile, "utf8").pipe(
548− Effect.catchAll(() => Effect.succeed<string | null>(null)),
549− );
550−
551− if (contents === null) {
552− return null;
553− }
554−
555− const lines = contents.split(/\r?\n/u).filter((line) => line.length > 0);
556− const tail = lines.slice(-maxLines).join("\n");
557− return tail.length > maxChars ? tail.slice(-maxChars) : tail;
558− });
559−
560−const failReachabilityTimeout = (input: {
561− baseUrl: string;
562− expected: boolean;
563− logFile?: string;
564−}): Effect.Effect<never, LocalServerReachabilityTimeoutError, FileSystem.FileSystem> =>
565− Effect.gen(function* () {
566− const logFile = input.logFile ?? DEFAULT_SERVER_LOG_FILE;
567− const logTail = yield* readServerLogTail(logFile);
568−
569− return yield* localServerReachabilityTimeoutError({
570− baseUrl: input.baseUrl,
571− expected: input.expected,
572− logFile,
573− logTail,
574− });
575− });
576−
577−const waitForReachability = (baseUrl: string, expected: boolean) =>
578− Effect.gen(function* () {
579− const startedAt = Date.now();
580− while (Date.now() - startedAt < SERVER_START_TIMEOUT_MS) {
581− const reachable = yield* isServerReachable(baseUrl);
582− if (reachable === expected) {
583− return;
584− }
585− yield* sleep(SERVER_POLL_INTERVAL_MS);
586− }
587−
588− return yield* failReachabilityTimeout({ baseUrl, expected });
589− });
590−
591−const printText = (value: string) =>
592− Effect.sync(() => {
593− console.log(value);
594− });
595−
596−const ensureServer = (baseUrl: string = DEFAULT_SERVER_BASE_URL) =>
597− Effect.gen(function* () {
598− const reachable = yield* isServerReachable(baseUrl);
599− if (reachable) {
600− return {
601− started: false,
602− } as const;
603− }
604−
605− const url = new URL(baseUrl);
606− const port = Number(url.port || DEFAULT_SERVER_PORT);
607− yield* startServerInBackground(port);
608−
609− yield* waitForReachability(baseUrl, true);
610−
611− return {
612− started: true,
613− } as const;
614− });
615−
616−const waitForShutdownSignal = () =>
617− Effect.async<void, never>((resume) => {
618− const shutdown = () => resume(Effect.void);
619− process.once("SIGINT", shutdown);
620− process.once("SIGTERM", shutdown);
621−
622− return Effect.sync(() => {
623− process.off("SIGINT", shutdown);
624− process.off("SIGTERM", shutdown);
625− });
626− });
627−
628−const runForegroundSession = (input: {
629− kind: "web" | "mcp";
630− port: number;
631−}) =>
632− Effect.scoped(
633− Effect.gen(function* () {
634− const server = yield* createLocalExecutorServer(getDefaultServerOptions(input.port));
635− const workspaceId = server.runtime.localInstallation.scopeId;
636− const summary = input.kind === "web"
637− ? renderWebSessionSummary({
638− baseUrl: server.baseUrl,
639− workspaceId,
640− })
641− : renderMcpSessionSummary({
642− baseUrl: server.baseUrl,
643− workspaceId,
644− });
645−
646− yield* printText(summary);
647− yield* waitForShutdownSignal();
648− }),
649− );
650−
651−const runStdioMcpSession = (webPort?: number) =>
652− Effect.scoped(
653− Effect.gen(function* () {
654− const server = yield* createLocalExecutorServer(
655− getDefaultServerOptions(webPort ?? 0),
656− );
657− yield* Effect.tryPromise({
658− try: () => runExecutorMcpStdioServer(server.runtime),
659− catch: toError,
660− });
661− }),
662− );
663−
664−
665−
666−const isRecord = (value: unknown): value is Record<string, unknown> =>
667− typeof value === "object" && value !== null && !Array.isArray(value);
668−
669−type PromptField = {
670− name: string;
671− label: string;
672− description?: string;
673− type: string;
674− required: boolean;
675− enumValues?: readonly unknown[];
676−};
677−
678−const getPromptFields = (requestedSchema: Record<string, unknown> | undefined): PromptField[] => {
679− if (!requestedSchema || !isRecord(requestedSchema.properties)) {
680− return [];
681− }
682−
683− const required = new Set(
684− Array.isArray(requestedSchema.required)
685− ? requestedSchema.required.filter((value): value is string => typeof value === "string")
686− : [],
687− );
688−
689− return Object.entries(requestedSchema.properties).flatMap(([name, property]) => {
690− if (!isRecord(property)) {
691− return [];
692− }
693−
694− return [{
695− name,
696− label:
697− typeof property.title === "string" && property.title.trim().length > 0
698− ? property.title.trim()
699− : name,
700− description:
701− typeof property.description === "string" && property.description.trim().length > 0
702− ? property.description.trim()
703− : undefined,
704− type: typeof property.type === "string" ? property.type : "string",
705− required: required.has(name),
706− enumValues: Array.isArray(property.enum) ? property.enum : undefined,
707− }];
708− });
709−};
710−
711−const parsePromptValue = (field: PromptField, raw: string):
712− | { ok: true; value: unknown }
713− | { ok: false; message: string } => {
714− if (field.enumValues && field.enumValues.length > 0) {
715− const normalized = field.enumValues.map((value) => String(value));
716− if (!normalized.includes(raw)) {
717− return {
718− ok: false,
719− message: `Enter one of: ${normalized.join(", ")}`,
720− };
721− }
722− }
723−
724− if (field.type === "boolean") {
725− const normalized = raw.trim().toLowerCase();
726− if (["y", "yes", "true"].includes(normalized)) {
727− return { ok: true, value: true };
728− }
729− if (["n", "no", "false"].includes(normalized)) {
730− return { ok: true, value: false };
731− }
732− return { ok: false, message: "Enter yes or no" };
733− }
734−
735− if (field.type === "number" || field.type === "integer") {
736− const value = Number(raw);
737− if (!Number.isFinite(value)) {
738− return { ok: false, message: "Enter a number" };
739− }
740− if (field.type === "integer" && !Number.isInteger(value)) {
741− return { ok: false, message: "Enter an integer" };
742− }
743− return { ok: true, value };
744− }
745−
746− if (field.type === "object" || field.type === "array") {
747− try {
748− return { ok: true, value: JSON.parse(raw) };
749− } catch {
750− return { ok: false, message: "Enter valid JSON" };
751− }
752− }
753−
754− return { ok: true, value: raw };
755−};
756−
757−const promptStructuredInteraction = (parsed: {
758− message: string;
759− requestedSchema?: Record<string, unknown>;
760−}) =>
761− Effect.gen(function* () {
762− const fields = getPromptFields(parsed.requestedSchema);
763− if (fields.length === 0) {
764− return null as Record<string, unknown> | null;
765− }
766−
767− yield* Effect.sync(() => {
768− process.stdout.write(`${parsed.message}\n`);
769− });
770−
771− const content: Record<string, unknown> = {};
772− for (const field of fields) {
773− if (field.description) {
774− yield* Effect.sync(() => {
775− process.stdout.write(`${field.description}\n`);
776− });
777− }
778−
779− while (true) {
780− const raw = yield* promptLine(
781− `${field.label}${field.required ? "" : " (optional)"}: `,
782− );
783− const trimmed = raw.trim();
784− if (trimmed.length === 0) {
785− if (field.required) {
786− return null;
787− }
788− break;
789− }
790−
791− const parsedValue = parsePromptValue(field, trimmed);
792− if (parsedValue.ok) {
793− content[field.name] = parsedValue.value;
794− break;
795− }
796−
797− yield* Effect.sync(() => {
798− process.stdout.write(`${parsedValue.message}\n`);
799− });
800− }
801− }
802−
803− return content;
804− });
805−
806−const printUrlInteraction = (input: {
807− message: string;
808− url: string | null;
809− shouldOpen: boolean;
810−}) =>
811− Effect.gen(function* () {
812− yield* Effect.sync(() => {
813− process.stdout.write(`${input.message}\n${input.url ?? ""}\n`);
814− });
815−
816− if (input.shouldOpen && input.url) {
817− yield* openUrlInBrowser(input.url);
818− }
819− });
820−
821−const executionInteractionMode = (): "live_form" | "detach" =>
822− process.stdin.isTTY && process.stdout.isTTY ? "live_form" : "detach";
823−
824−const promptInteraction = (input: {
825− interaction: ExecutionInteraction;
826− shouldOpenUrls: boolean;
827−}) =>
828− Effect.gen(function* () {
829− const parsed = parseInteractionPayload(input.interaction);
830−
831− if (!process.stdin.isTTY || !process.stdout.isTTY || parsed === null) {
832− return null;
833− }
834−
835− if (parsed.mode === "url") {
836− yield* printUrlInteraction({
837− message: parsed.message,
838− url: parsed.url ?? null,
839− shouldOpen: input.shouldOpenUrls,
840− });
841− return null;
842− }
843−
844− const structured = yield* promptStructuredInteraction(parsed);
845− if (structured !== null) {
846− return JSON.stringify({
847− action: "accept",
848− content: structured,
849− });
850− }
851−
852− const line = yield* promptLine(`${parsed.message} [y/N] `);
853− const normalized = line.trim().toLowerCase();
854− if (normalized.length === 0) {
855− return null;
856− }
857− if (normalized !== "y" && normalized !== "yes" && normalized !== "n" && normalized !== "no") {
858− return null;
859− }
860− const accepted = normalized === "y" || normalized === "yes";
861−
862− return JSON.stringify({
863− action: accepted ? "accept" : "decline",
864− content: {
865− approve: accepted,
866− },
867− });
868− });
869−
870−const waitForExecutionProgress = (input: {
871− client: ExecutorApiClient;
872− workspaceId: ExecutionEnvelope["execution"]["scopeId"];
873− executionId: ExecutionEnvelope["execution"]["id"];
874− pendingInteractionId: ExecutionInteraction["id"];
875−}) =>
876− Effect.gen(function* () {
877− while (true) {
878− yield* sleep(SERVER_POLL_INTERVAL_MS);
879−
880− const next = yield* input.client.executions.get({
881− path: {
882− workspaceId: input.workspaceId,
883− executionId: input.executionId,
884− },
885− });
886−
887− if (
888− next.execution.status !== "waiting_for_interaction"
889− || next.pendingInteraction === null
890− || next.pendingInteraction.id !== input.pendingInteractionId
891− ) {
892− return next;
893− }
894− }
895− });
896−
897−const printExecution = (envelope: ExecutionEnvelope) =>
898− Effect.sync(() => {
899− const execution = envelope.execution;
900− if (execution.status === "completed") {
901− if (execution.resultJson) {
902− console.log(execution.resultJson);
903− } else {
904− console.log("completed");
905− }
906− return;
907− }
908−
909− if (execution.status === "failed") {
910− console.error(execution.errorText ?? "Execution failed");
911− process.exitCode = 1;
912− return;
913− }
914− if (execution.status === "waiting_for_interaction" && envelope.pendingInteraction !== null) {
915− return;
916− }
917−
918−
919− console.log(JSON.stringify({
920− id: execution.id,
921− status: execution.status,
922− }));
923− });
924−
925−const driveExecution = (input: {
926− client: ExecutorApiClient;
927− workspaceId: ExecutionEnvelope["execution"]["scopeId"];
928− envelope: ExecutionEnvelope;
929− baseUrl: string;
930− shouldOpenUrls: boolean;
931−}) =>
932− Effect.gen(function* () {
933− let current = input.envelope;
934−
935− while (current.execution.status === "waiting_for_interaction") {
936− const pending = current.pendingInteraction;
937−
938− if (pending === null) {
939− return current;
940− }
941−
942− const parsed = parseInteractionPayload(pending);
943− const handling = decideInteractionHandling({
944− parsed,
945− isInteractiveTerminal: process.stdin.isTTY && process.stdout.isTTY,
946− });
947−
948− if (handling === "url_interactive" && parsed?.mode === "url") {
949− yield* printUrlInteraction({
950− message: parsed.message,
951− url: parsed.url ?? null,
952− shouldOpen: input.shouldOpenUrls,
953− });
954−
955− current = yield* waitForExecutionProgress({
956− client: input.client,
957− workspaceId: input.workspaceId,
958− executionId: current.execution.id,
959− pendingInteractionId: pending.id,
960− });
961− continue;
962− }
963−
964− if (handling === "url_paused") {
965− if (input.shouldOpenUrls && parsed?.mode === "url" && parsed.url) {
966− yield* openUrlInBrowser(parsed.url);
967− }
968−
969− const paused = buildPausedExecutionOutput({
970− executionId: current.execution.id,
971− interaction: pending,
972− baseUrl: input.baseUrl,
973− shouldOpenUrls: input.shouldOpenUrls,
974− cliName: CLI_NAME,
975− });
976− yield* Effect.sync(() => {
977− console.log(JSON.stringify(paused));
978− process.exitCode = 20;
979− });
980− return current;
981− }
982−
983− if (handling === "form_paused") {
984− const paused = buildPausedExecutionOutput({
985− executionId: current.execution.id,
986− interaction: pending,
987− baseUrl: input.baseUrl,
988− shouldOpenUrls: input.shouldOpenUrls,
989− cliName: CLI_NAME,
990− });
991− yield* Effect.sync(() => {
992− console.log(JSON.stringify(paused));
993− process.exitCode = 20;
994− });
995− return current;
996− }
997−
998− const responseJson = yield* promptInteraction({
999− interaction: pending,
1000− shouldOpenUrls: input.shouldOpenUrls,
1001− });
1002− if (responseJson === null) {
1003− const paused = buildPausedExecutionOutput({
1004− executionId: current.execution.id,
1005− interaction: pending,
1006− baseUrl: input.baseUrl,
1007− shouldOpenUrls: input.shouldOpenUrls,
1008− cliName: CLI_NAME,
1009− });
1010− yield* Effect.sync(() => {
1011− console.log(JSON.stringify(paused));
1012− process.exitCode = 20;
1013− });
1014− return current;
1015− }
1016−
1017− current = yield* input.client.executions.resume({
1018− path: {
1019− workspaceId: input.workspaceId,
1020− executionId: current.execution.id,
1021− },
1022− payload: {
1023− responseJson,
1024− interactionMode: executionInteractionMode(),
1025− },
1026− });
1027− }
1028−
1029− return current;
1030− });
1031−
1032−const serverStartCommand = Command.make(
1033− "start",
1034− {
1035− port: Options.integer("port").pipe(Options.withDefault(DEFAULT_SERVER_PORT)),
1036− },
1037− ({ port }) => runLocalExecutorServer(getDefaultServerOptions(port)),
1038−).pipe(Command.withDescription("Start the local executor server"));
1039−
1040−const serverCommand = Command.make("server").pipe(
1041− Command.withSubcommands([serverStartCommand] as const),
1042− Command.withDescription("Local server commands"),
1043−);
1044−
1045−const webCommand = Command.make(
1046− "web",
1047− {
1048− port: Options.integer("port").pipe(Options.withDefault(DEFAULT_SERVER_PORT)),
1049− },
1050− ({ port }) => runForegroundSession({ kind: "web", port }),
1051−).pipe(Command.withDescription("Start a foreground web session and print the local URL"));
1052−
1053−const mcpCommand = Command.make(
1054− "mcp",
1055− {
1056− port: Options.integer("port").pipe(Options.withDefault(DEFAULT_SERVER_PORT)),
1057− stdio: Options.boolean("stdio").pipe(Options.withDefault(false)),
1058− webPort: Options.integer("web-port").pipe(Options.optional),
1059− },
1060− ({ port, stdio, webPort }) =>
1061− stdio
1062− ? runStdioMcpSession(Option.getOrUndefined(webPort))
1063− : runForegroundSession({ kind: "mcp", port }),
1064−).pipe(Command.withDescription("Start a foreground MCP session, or run stdio MCP with --stdio"));
1065−
1066−const callCommand = Command.make(
1067− "call",
1068− {
1069− code: Args.text({ name: "code" }).pipe(
1070− Args.withDescription("Inline code to execute."),
1071− Args.optional,
1072− ),
1073− file: Options.text("file").pipe(Options.optional),
1074− stdin: Options.boolean("stdin").pipe(Options.withDefault(false)),
1075− baseUrl: Options.text("base-url").pipe(Options.withDefault(DEFAULT_SERVER_BASE_URL)),
1076− noOpen: Options.boolean("no-open").pipe(Options.withDefault(false)),
1077− },
1078− ({ code, file, stdin, baseUrl, noOpen }) =>
1079− Effect.gen(function* () {
1080− const resolvedCode = yield* readCode({
1081− code: Option.getOrUndefined(code),
1082− file: Option.getOrUndefined(file),
1083− stdin,
1084− });
1085−
1086− yield* ensureServer(baseUrl);
1087− const { installation, client } = yield* getLocalAuthedClient(baseUrl);
1088− const created = yield* client.executions.create({
1089− path: {
1090− workspaceId: installation.scopeId,
1091− },
1092− payload: {
1093− code: resolvedCode,
1094− interactionMode: executionInteractionMode(),
1095− },
1096− });
1097−
1098− const settled = yield* driveExecution({
1099− client,
1100− workspaceId: installation.scopeId,
1101− envelope: created,
1102− baseUrl,
1103− shouldOpenUrls: !noOpen,
1104− });
1105−
1106− yield* printExecution(settled);
1107− }),
1108−).pipe(Command.withDescription("Execute code against the local executor server"));
1109−
1110−const resumeCommand = Command.make(
1111− "resume",
1112− {
1113− executionId: Options.text("execution-id"),
1114− baseUrl: Options.text("base-url").pipe(Options.withDefault(DEFAULT_SERVER_BASE_URL)),
1115− noOpen: Options.boolean("no-open").pipe(Options.withDefault(false)),
1116− },
1117− ({ executionId, baseUrl, noOpen }) =>
1118− Effect.gen(function* () {
1119− yield* ensureServer(baseUrl);
1120− const { installation, client } = yield* getLocalAuthedClient(baseUrl);
1121− const decodedExecutionId = yield* decodeExecutionId(executionId).pipe(
1122− Effect.mapError((cause) => toError(cause)),
1123− );
1124− const execution = yield* client.executions.get({
1125− path: {
1126− workspaceId: installation.scopeId,
1127− executionId: decodedExecutionId,
1128− },
1129− });
1130−
1131− const settled = yield* driveExecution({
1132− client,
1133− workspaceId: installation.scopeId,
1134− envelope: execution,
1135− baseUrl,
1136− shouldOpenUrls: !noOpen,
1137− });
1138−
1139− yield* printExecution(settled);
1140− }),
1141−).pipe(Command.withDescription("Resume a paused execution"));
1142−
1143−const devCommand = Command.make("dev").pipe(
1144− Command.withDescription("Development helpers"),
1145−);
1146−
1147−const root = Command.make("executor").pipe(
1148− Command.withSubcommands([
1149− serverCommand,
1150− webCommand,
1151− mcpCommand,
1152− callCommand,
1153− resumeCommand,
1154− devCommand,
1155− ] as const),
1156− Command.withDescription("Executor local CLI"),
1157−);
1158−
1159−const runCli = Command.run(root, {
1160− name: CLI_NAME,
1161− version: CLI_VERSION,
1162− executable: CLI_NAME,
1163−});
1164−
1165−const hiddenServer = (): Effect.Effect<void, Error, never> | null => {
1166− const args = getCliArgs();
1167− if (args[0] !== "__local-server") {
1168− return null;
1169− }
1170−
1171− const portFlagIndex = args.findIndex((arg) => arg === "--port");
1172− const port = portFlagIndex >= 0 ? Number(args[portFlagIndex + 1]) : DEFAULT_SERVER_PORT;
1173−
1174− return runLocalExecutorServer({
1175− ...getDefaultServerOptions(
1176− Number.isInteger(port) && port > 0 ? port : DEFAULT_SERVER_PORT,
1177− ),
1178− });
1179−};
1180−
1181−const program = (hiddenServer()
1182− ?? helpOverride()
1183− ?? runCli(toEffectCliArgv(getCliArgs())).pipe(Effect.mapError(toError)))
1184− .pipe(Effect.provide(NodeFileSystem.layer))
1185− .pipe(Effect.provide(NodePath.layer))
1186− .pipe(
1187− Effect.catchAllCause((cause) =>
1188− Effect.sync(() => {
1189− console.error(Cause.pretty(cause));
1190− process.exitCode = 1;
1191− }),
1192− ),
1193− );
1194−
1195−// Effect CLI's environment does not fully narrow at the process boundary.
1196−NodeRuntime.runMain(program as Effect.Effect<void, never, never>);
apps/executor/src/cli/pending-interaction-output.ts+0−125
@@ -1,125 +0,0 @@
1−import type { ExecutionInteraction } from "@executor/platform-sdk/schema";
2−
3−const isRecord = (value: unknown): value is Record<string, unknown> =>
4− typeof value === "object" && value !== null && !Array.isArray(value);
5−
6−export type ParsedInteractionPayload = {
7− message: string;
8− mode: "form" | "url";
9− url?: string;
10− requestedSchema?: Record<string, unknown>;
11−};
12−
13−export const parseInteractionPayload = (
14− interaction: ExecutionInteraction,
15−): ParsedInteractionPayload | null => {
16− try {
17− const parsed = JSON.parse(interaction.payloadJson) as {
18− elicitation?: {
19− message?: string;
20− mode?: "form" | "url";
21− url?: string;
22− requestedSchema?: Record<string, unknown>;
23− };
24− };
25−
26− if (!parsed.elicitation || typeof parsed.elicitation.message !== "string") {
27− return null;
28− }
29−
30− return {
31− message: parsed.elicitation.message,
32− mode: parsed.elicitation.mode === "url" ? "url" : "form",
33− url: parsed.elicitation.url,
34− requestedSchema:
35− isRecord(parsed.elicitation.requestedSchema)
36− ? parsed.elicitation.requestedSchema
37− : undefined,
38− };
39− } catch {
40− return null;
41− }
42−};
43−
44−const shellEscape = (value: string): string => {
45− if (/^[A-Za-z0-9_./:=+-]+$/.test(value)) {
46− return value;
47− }
48−
49− return `'${value.replace(/'/g, `'"'"'`)}'`;
50−};
51−
52−const renderCommand = (argv: readonly string[]): string => argv.map(shellEscape).join(" ");
53−
54−const describePauseReason = (interaction: ExecutionInteraction): string => {
55− switch (interaction.purpose) {
56− case "tool_execution_gate":
57− return "this tool call requires approval before executor can continue";
58− default:
59− return "executor needs additional input before it can continue";
60− }
61−};
62−
63−const buildInstruction = (input: {
64− interaction: ExecutionInteraction;
65− parsed: ParsedInteractionPayload | null;
66− resumeCommand: string;
67−}): string => {
68− const reason = describePauseReason(input.interaction);
69− const prompt = input.parsed?.message ?? "Interaction required";
70−
71− if (input.parsed?.mode === "url") {
72− const url = input.parsed.url?.trim();
73− return url && url.length > 0
74− ? `Execution paused because ${reason}. Open ${url} and complete the requested flow for "${prompt}", then run ${input.resumeCommand} to continue if it does not resume automatically.`
75− : `Execution paused because ${reason}. Run ${input.resumeCommand} to continue and complete the requested flow for "${prompt}".`;
76− }
77−
78− if (input.parsed?.requestedSchema) {
79− return `Execution paused because ${reason}. The interaction prompt is "${prompt}". Run ${input.resumeCommand} in an interactive terminal and respond with input matching interaction.requestedSchema.`;
80− }
81−
82− return `Execution paused because ${reason}. The interaction prompt is "${prompt}". Run ${input.resumeCommand} in an interactive terminal to continue.`;
83−};
84−
85−export const buildPausedExecutionOutput = (input: {
86− executionId: string;
87− interaction: ExecutionInteraction;
88− baseUrl: string;
89− shouldOpenUrls: boolean;
90− cliName?: string;
91−}) => {
92− const cliName = input.cliName ?? "executor";
93− const argv = [cliName, "resume", "--execution-id", input.executionId, "--base-url", input.baseUrl];
94− if (!input.shouldOpenUrls) {
95− argv.push("--no-open");
96− }
97−
98− const command = renderCommand(argv);
99− const parsed = parseInteractionPayload(input.interaction);
100−
101− return {
102− id: input.executionId,
103− status: "waiting_for_interaction" as const,
104− interactionId: input.interaction.id,
105− message: parsed?.message ?? "Interaction required",
106− resumeCommand: command,
107− interaction: {
108− id: input.interaction.id,
109− purpose: input.interaction.purpose,
110− mode: parsed?.mode ?? (input.interaction.kind === "url" ? "url" : "form"),
111− message: parsed?.message ?? "Interaction required",
112− url: parsed?.url ?? null,
113− requestedSchema: parsed?.requestedSchema ?? null,
114− },
115− resume: {
116− command,
117− argv,
118− },
119− instruction: buildInstruction({
120− interaction: input.interaction,
121− parsed,
122− resumeCommand: command,
123− }),
124− };
125−};
apps/executor/src/cli/runtime-paths.test.ts+0−47
@@ -1,47 +0,0 @@
1−import { join } from "node:path";
2−import { describe, expect, it } from "@effect/vitest";
3−
4−import {
5− DEFAULT_EXECUTOR_DATA_DIR,
6− DEFAULT_LOCAL_DATA_DIR,
7−} from "@executor/server";
8−
9−import {
10− resolveCliLocalDataDir,
11−} from "./runtime-paths";
12−
13−describe("runtime-paths", () => {
14− it("uses the web dev local data dir for source-launched CLI runs", () => {
15− const originalArgv1 = process.argv[1];
16−
17− try {
18− process.argv[1] = "/tmp/executor.ts";
19−
20− expect(resolveCliLocalDataDir()).toBe(
21− join(DEFAULT_EXECUTOR_DATA_DIR, "control-plane-web-dev"),
22− );
23− } finally {
24− if (originalArgv1 === undefined) {
25− delete process.argv[1];
26− } else {
27− process.argv[1] = originalArgv1;
28− }
29− }
30− });
31−
32− it("keeps the default local data dir for bundled launches", () => {
33− const originalArgv1 = process.argv[1];
34−
35− try {
36− process.argv[1] = "/tmp/executor";
37−
38− expect(resolveCliLocalDataDir()).toBe(DEFAULT_LOCAL_DATA_DIR);
39− } finally {
40− if (originalArgv1 === undefined) {
41− delete process.argv[1];
42− } else {
43− process.argv[1] = originalArgv1;
44− }
45− }
46− });
47−});
apps/executor/src/cli/runtime-paths.ts+0−109
@@ -1,109 +0,0 @@
1−import { existsSync } from "node:fs";
2−import { dirname, extname, join, resolve } from "node:path";
3−import { fileURLToPath } from "node:url";
4−
5−import {
6− DEFAULT_EXECUTOR_DATA_DIR,
7− DEFAULT_LOCAL_DATA_DIR,
8− EXECUTOR_LOCAL_DATA_DIR_ENV,
9− EXECUTOR_WEB_ASSETS_DIR_ENV,
10−} from "@executor/server";
11−
12−const sourceDir = dirname(fileURLToPath(import.meta.url));
13−
14−const trim = (value: string | undefined): string | undefined => {
15− const candidate = value?.trim();
16− return candidate && candidate.length > 0 ? candidate : undefined;
17−};
18−
19−const resolveIfExists = (value: string | undefined): string | null => {
20− const candidate = trim(value);
21− if (!candidate) {
22− return null;
23− }
24−
25− const resolved = resolve(candidate);
26− return existsSync(resolved) ? resolved : null;
27−};
28−
29−const getSourceEntrypoint = (): string | null => {
30− const candidate = trim(process.argv[1]);
31− if (!candidate) {
32− return null;
33− }
34−
35− const resolved = resolve(candidate);
36− const extension = extname(resolved).toLowerCase();
37− return [".ts", ".tsx", ".js", ".mjs", ".cjs"].includes(extension)
38− ? resolved
39− : null;
40−};
41−
42−const isSourceCliLaunch = (): boolean => getSourceEntrypoint() !== null;
43−
44−const resolveBundledNodeLauncher = (): string | null => {
45− const candidate = resolve(sourceDir, "executor.js");
46− return existsSync(candidate) ? candidate : null;
47−};
48−
49−
50−const resolveRuntimeResourcesRoot = (): string | null => {
51− const compiledCandidate = resolve(dirname(process.execPath), "../resources");
52− if (existsSync(compiledCandidate)) {
53− return compiledCandidate;
54− }
55−
56− const bundledCandidateFromModule = resolve(sourceDir, "../resources");
57− if (existsSync(bundledCandidateFromModule)) {
58− return bundledCandidateFromModule;
59− }
60−
61− const sourceEntrypoint = getSourceEntrypoint();
62− if (sourceEntrypoint) {
63− const bundledCandidate = resolve(dirname(sourceEntrypoint), "../resources");
64− if (existsSync(bundledCandidate)) {
65− return bundledCandidate;
66− }
67− }
68−
69− return null;
70−};
71−
72−export const resolveSelfCommand = (args: readonly string[]): readonly string[] => {
73− const bundledLauncher = resolveBundledNodeLauncher();
74− if (bundledLauncher !== null) {
75− return [process.execPath, bundledLauncher, ...args];
76− }
77−
78− const sourceEntrypoint = getSourceEntrypoint();
79− return sourceEntrypoint === null
80− ? [process.execPath, ...args]
81− : [process.execPath, sourceEntrypoint, ...args];
82−};
83−
84−export const resolveCliLocalDataDir = (): string => {
85− if (trim(process.env[EXECUTOR_LOCAL_DATA_DIR_ENV])) {
86− return DEFAULT_LOCAL_DATA_DIR;
87− }
88−
89− return isSourceCliLaunch()
90− ? join(DEFAULT_EXECUTOR_DATA_DIR, "control-plane-web-dev")
91− : DEFAULT_LOCAL_DATA_DIR;
92−};
93−
94−export const resolveRuntimeWebAssetsDir = (): string | null => {
95− const explicit = resolveIfExists(process.env[EXECUTOR_WEB_ASSETS_DIR_ENV]);
96− if (explicit) {
97− return explicit;
98− }
99−
100− const resourcesRoot = resolveRuntimeResourcesRoot();
101− const bundled = resourcesRoot
102− ? resolveIfExists(resolve(resourcesRoot, "web"))
103− : null;
104− if (bundled) {
105− return bundled;
106− }
107−
108− return resolveIfExists(resolve(sourceDir, "../../../web/dist"));
109−};
apps/executor/src/cli/session-summary.test.ts+0−60
@@ -1,60 +0,0 @@
1−import { describe, expect, it } from "@effect/vitest";
2−
3−import {
4− appendUrlPath,
5− renderMcpSessionSummary,
6− renderUpSummary,
7− renderWebSessionSummary,
8−} from "./session-summary";
9−
10−describe("session-summary", () => {
11− it("appends paths against a base url", () => {
12− expect(appendUrlPath("http://127.0.0.1:8788", "mcp")).toBe("http://127.0.0.1:8788/mcp");
13− expect(appendUrlPath("http://127.0.0.1:8788/", "v1/openapi.json")).toBe(
14− "http://127.0.0.1:8788/v1/openapi.json",
15− );
16− });
17−
18− it("renders the web session summary around the browser url", () => {
19− const output = renderWebSessionSummary({
20− baseUrl: "http://127.0.0.1:8788",
21− workspaceId: "ws_123",
22− });
23−
24− expect(output).toContain("Executor web session is ready.");
25− expect(output).toContain("Web: http://127.0.0.1:8788");
26− expect(output).toContain("MCP: http://127.0.0.1:8788/mcp");
27− expect(output).toContain("Workspace: ws_123");
28− expect(output).toContain("Press Ctrl+C to stop this session.");
29− });
30−
31− it("renders the MCP session summary around the MCP url", () => {
32− const output = renderMcpSessionSummary({
33− baseUrl: "http://127.0.0.1:8788",
34− workspaceId: "ws_456",
35− });
36−
37− expect(output).toContain("Executor MCP session is ready.");
38− expect(output).toContain("MCP: http://127.0.0.1:8788/mcp");
39− expect(output).toContain("Web: http://127.0.0.1:8788");
40− expect(output).toContain("Workspace: ws_456");
41− expect(output).toContain("Use this MCP URL in your client and keep this process running.");
42− });
43−
44− it("adds session-first next steps to the up summary", () => {
45− const output = renderUpSummary({
46− started: true,
47− status: {
48− baseUrl: "http://127.0.0.1:8788",
49− installation: {
50− workspaceId: "ws_789",
51− },
52− },
53− });
54−
55− expect(output).toContain("Executor is ready.");
56− expect(output).toContain("executor web");
57− expect(output).toContain("executor mcp");
58− expect(output).toContain("executor call 'return 1 + 1'");
59− });
60−});
apps/executor/src/cli/session-summary.ts+0−64
@@ -1,64 +0,0 @@
1−export const appendUrlPath = (baseUrl: string, pathname: string): string =>
2− new URL(pathname, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`).toString();
3−
4−type SessionSummaryInput = {
5− readonly baseUrl: string;
6− readonly workspaceId?: string | null;
7−};
8−
9−const renderSessionSummary = (
10− kind: "web" | "mcp",
11− input: SessionSummaryInput,
12−): string => {
13− const displayKind = kind === "mcp" ? "MCP" : "web";
14− const primaryLabel = kind === "web" ? "Web" : "MCP";
15− const primaryUrl = kind === "web" ? input.baseUrl : appendUrlPath(input.baseUrl, "mcp");
16− const secondaryLabel = kind === "web" ? "MCP" : "Web";
17− const secondaryUrl = kind === "web" ? appendUrlPath(input.baseUrl, "mcp") : input.baseUrl;
18− const guidance = kind === "web"
19− ? "Keep this process running while you use the browser session."
20− : "Use this MCP URL in your client and keep this process running.";
21−
22− return [
23− `Executor ${displayKind} session is ready.`,
24− `${primaryLabel}: ${primaryUrl}`,
25− `${secondaryLabel}: ${secondaryUrl}`,
26− `OpenAPI: ${appendUrlPath(input.baseUrl, "v1/openapi.json")}`,
27− `Workspace: ${input.workspaceId ?? "unavailable"}`,
28− "",
29− guidance,
30− "Press Ctrl+C to stop this session.",
31− ].join("\n");
32−};
33−
34−export const renderWebSessionSummary = (input: SessionSummaryInput): string =>
35− renderSessionSummary("web", input);
36−
37−export const renderMcpSessionSummary = (input: SessionSummaryInput): string =>
38− renderSessionSummary("mcp", input);
39−
40−type UpSummaryInput = {
41− readonly started: boolean;
42− readonly status: {
43− readonly baseUrl: string;
44− readonly installation: {
45− readonly workspaceId: string;
46− } | null;
47− };
48−};
49−
50−export const renderUpSummary = (input: UpSummaryInput): string =>
51− [
52− input.started ? "Executor is ready." : "Executor is already running.",
53− `API: ${input.status.baseUrl}`,
54− `MCP: ${appendUrlPath(input.status.baseUrl, "mcp")}`,
55− `OpenAPI: ${appendUrlPath(input.status.baseUrl, "v1/openapi.json")}`,
56− `Workspace: ${input.status.installation?.workspaceId ?? "unavailable"}`,
57− "",
58− "Try next:",
59− " executor web",
60− " executor mcp",
61− " executor call 'return 1 + 1'",
62− " executor status",
63− " executor down",
64− ].join("\n");
apps/executor/src/distribution/artifact.ts+0−359
@@ -1,359 +0,0 @@
1−import { spawn } from "node:child_process";
2−import { existsSync, readFileSync } from "node:fs";
3−import { chmod, cp, mkdir, rename, rm, writeFile } from "node:fs/promises";
4−import { createRequire } from "node:module";
5−import { dirname, join, resolve } from "node:path";
6−
7−import { readDistributionPackageMetadata, repoRoot } from "./metadata";
8−
9−const defaultOutputDir = resolve(repoRoot, "apps/executor/dist/npm");
10−
11−
12−export type BuildDistributionPackageOptions = {
13− outputDir?: string;
14− packageName?: string;
15− packageVersion?: string;
16− buildWeb?: boolean;
17−};
18−
19−export type DistributionPackageArtifact = {
20− packageDir: string;
21− launcherPath: string;
22− bundlePath: string;
23− resourcesDir: string;
24−};
25−
26−type BundledDependency = {
27− name: string;
28− version: string;
29− packageDir: string;
30−};
31−
32−type CommandInput = {
33− command: string;
34− args: ReadonlyArray<string>;
35− cwd: string;
36−};
37−
38−const runCommand = async (input: CommandInput): Promise<void> => {
39− const child = spawn(input.command, [...input.args], {
40− cwd: input.cwd,
41− env: process.env,
42− stdio: ["ignore", "pipe", "pipe"],
43− });
44−
45− let stdout = "";
46− let stderr = "";
47−
48− child.stdout?.setEncoding("utf8");
49− child.stdout?.on("data", (chunk) => {
50− stdout += chunk;
51− });
52−
53− child.stderr?.setEncoding("utf8");
54− child.stderr?.on("data", (chunk) => {
55− stderr += chunk;
56− });
57−
58− const exitCode = await new Promise<number>((resolveExitCode, reject) => {
59− child.once("error", reject);
60− child.once("close", (code) => {
61− resolveExitCode(code ?? -1);
62− });
63− });
64−
65− if (exitCode === 0) {
66− return;
67− }
68−
69− throw new Error(
70− [
71− `${input.command} ${input.args.join(" ")} exited with code ${exitCode}`,
72− stdout.trim().length > 0 ? `stdout:\n${stdout.trim()}` : null,
73− stderr.trim().length > 0 ? `stderr:\n${stderr.trim()}` : null,
74− ]
75− .filter((part) => part !== null)
76− .join("\n\n"),
77− );
78−};
79−
80−const resolveQuickJsWasmPath = (): string => {
81− const requireFromQuickJsRuntime = createRequire(
82− join(repoRoot, "packages/kernel/runtime-quickjs/package.json"),
83− );
84− const quickJsPackagePath = requireFromQuickJsRuntime.resolve(
85− "quickjs-emscripten/package.json",
86− );
87− const wasmPath = resolve(
88− dirname(quickJsPackagePath),
89− "../@jitl/quickjs-wasmfile-release-sync/dist/emscripten-module.wasm",
90− );
91−
92− if (!existsSync(wasmPath)) {
93− throw new Error(`Unable to locate QuickJS wasm asset at ${wasmPath}`);
94− }
95−
96− return wasmPath;
97−};
98−
99−const resolveInstalledPackage = (input: {
100− packageName: string;
101− fromPackageJsonPath: string;
102−}): BundledDependency => {
103− const requireFromPackage = createRequire(input.fromPackageJsonPath);
104− const packageEntrypointPath = requireFromPackage.resolve(input.packageName);
105− let packageDir = dirname(packageEntrypointPath);
106− let packageJsonPath = join(packageDir, "package.json");
107−
108− while (!existsSync(packageJsonPath)) {
109− const parentDir = dirname(packageDir);
110− if (parentDir === packageDir) {
111− throw new Error(`Unable to locate package.json for ${input.packageName} from ${packageEntrypointPath}`);
112− }
113− packageDir = parentDir;
114− packageJsonPath = join(packageDir, "package.json");
115− }
116−
117− const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8")) as {
118− name?: string;
119− version?: string;
120− };
121−
122− if (!packageJson.name || !packageJson.version) {
123− throw new Error(`Invalid package metadata at ${packageJsonPath}`);
124− }
125−
126− return {
127− name: packageJson.name,
128− version: packageJson.version,
129− packageDir,
130− };
131−};
132−
133−const resolveBundledDependencies = (): ReadonlyArray<BundledDependency> => {
134− const onePasswordSdk = resolveInstalledPackage({
135− packageName: "@1password/sdk",
136− fromPackageJsonPath: join(repoRoot, "plugins/onepassword/sdk/package.json"),
137− });
138− const onePasswordSdkCore = resolveInstalledPackage({
139− packageName: "@1password/sdk-core",
140− fromPackageJsonPath: join(onePasswordSdk.packageDir, "package.json"),
141− });
142−
143− return [
144− onePasswordSdk,
145− onePasswordSdkCore,
146− ];
147−};
148−
149−
150−const createPackageJson = (input: {
151− packageName: string;
152− packageVersion: string;
153− description: string;
154− keywords: ReadonlyArray<string>;
155− homepage?: string;
156− bugs?: {
157− url?: string;
158− };
159− repository?: {
160− type?: string;
161− url?: string;
162− };
163− license?: string;
164− dependencies?: Readonly<Record<string, string>>;
165− bundleDependencies?: ReadonlyArray<string>;
166−}) => {
167− const packageJson = {
168− name: input.packageName,
169− version: input.packageVersion,
170− description: input.description,
171− keywords: input.keywords,
172− homepage: input.homepage,
173− bugs: input.bugs,
174− repository: input.repository,
175− license: input.license ?? "MIT",
176− type: "module",
177− private: false,
178− bin: {
179− executor: "bin/executor.js",
180− },
181− files: [
182− "bin",
183− "node_modules",
184− "resources",
185− "README.md",
186− "package.json",
187− ],
188− engines: {
189− node: ">=20",
190− },
191− dependencies: input.dependencies,
192− bundleDependencies: input.bundleDependencies,
193− };
194−
195− return JSON.stringify(packageJson, null, 2) + "\n";
196−};
197−
198−const createLauncherSource = () => [
199− "#!/usr/bin/env node",
200− 'import { readFileSync, readdirSync } from "node:fs";',
201− 'import { dirname, join } from "node:path";',
202− 'import { fileURLToPath } from "node:url";',
203− "",
204− "const isMusl = () => {",
205− ' try {',
206− ' return readFileSync("/usr/bin/ldd", "utf8").includes("musl");',
207− " } catch {}",
208− "",
209− ' if (typeof process.report?.getReport === "function") {',
210− " const report = process.report.getReport();",
211− " if (report?.header?.glibcVersionRuntime) {",
212− " return false;",
213− " }",
214− " if (Array.isArray(report?.sharedObjects)) {",
215− ' return report.sharedObjects.some((file) => file.includes("libc.musl-") || file.includes("ld-musl-"));',
216− " }",
217− " }",
218− "",
219− " return false;",
220− "};",
221− "",
222− "const resolveBundledKeyringNativeLibraryPath = () => {",
223− ' if (process.platform !== "linux" || process.arch !== "x64") {',
224− " return null;",
225− " }",
226− "",
227− " const binDir = dirname(fileURLToPath(import.meta.url));",
228− ' const pattern = isMusl()',
229− ' ? /^keyring\\.linux-x64-musl-.*\\.node$/',
230− ' : /^keyring\\.linux-x64-gnu-.*\\.node$/;',
231− ' const match = readdirSync(binDir).find((entry) => pattern.test(entry));',
232− " return match ? join(binDir, match) : null;",
233− "};",
234− "",
235− "const bundledKeyringNativeLibraryPath = resolveBundledKeyringNativeLibraryPath();",
236− 'if (bundledKeyringNativeLibraryPath && !process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {',
237− " process.env.NAPI_RS_NATIVE_LIBRARY_PATH = bundledKeyringNativeLibraryPath;",
238− "}",
239− "",
240− 'await import("./executor.mjs");',
241− "",
242−].join("\n");
243−
244−const buildCliBundle = async (input: {
245− binDir: string;
246− bundlePath: string;
247−}): Promise<void> => {
248− const builtEntrypointPath = join(input.binDir, "main.js");
249−
250− await runCommand({
251− command: "bun",
252− args: [
253− "build",
254− "./apps/executor/src/cli/main.ts",
255− "--target",
256− "node",
257− "--outdir",
258− input.binDir,
259− "--external=@1password/sdk",
260− ],
261− cwd: repoRoot,
262− });
263−
264− if (!existsSync(builtEntrypointPath)) {
265− throw new Error(`Missing bundled CLI entrypoint at ${builtEntrypointPath}`);
266− }
267−
268− await rm(input.bundlePath, { force: true });
269− await rename(builtEntrypointPath, input.bundlePath);
270−};
271−
272−export const buildDistributionPackage = async (
273− options: BuildDistributionPackageOptions = {},
274−): Promise<DistributionPackageArtifact> => {
275− const defaults = await readDistributionPackageMetadata();
276− const packageDir = resolve(options.outputDir ?? defaultOutputDir);
277− const binDir = join(packageDir, "bin");
278− const resourcesDir = join(packageDir, "resources");
279− const webDir = join(resourcesDir, "web");
280− const bundlePath = join(binDir, "executor.mjs");
281− const launcherPath = join(binDir, "executor.js");
282− const nodeModulesDir = join(packageDir, "node_modules");
283− const quickJsWasmPath = resolveQuickJsWasmPath();
284− const bundledDependencies = resolveBundledDependencies();
285−
286− const webDistDir = join(repoRoot, "apps/web/dist");
287− const readmePath = join(repoRoot, "README.md");
288− const packageName = options.packageName ?? defaults.name;
289− const packageVersion = options.packageVersion ?? defaults.version;
290− await rm(packageDir, { recursive: true, force: true });
291− await mkdir(binDir, { recursive: true });
292− await mkdir(nodeModulesDir, { recursive: true });
293− await mkdir(resourcesDir, { recursive: true });
294−
295− if ((options.buildWeb ?? true) || !existsSync(webDistDir)) {
296− await runCommand({
297− command: "bun",
298− args: ["run", "build"],
299− cwd: join(repoRoot, "apps/web"),
300− });
301− }
302−
303− if (!existsSync(webDistDir)) {
304− throw new Error(`Missing built web assets at ${webDistDir}`);
305− }
306−
307− await buildCliBundle({
308− binDir,
309− bundlePath,
310− });
311−
312− await cp(webDistDir, webDir, { recursive: true });
313− for (const dependency of bundledDependencies) {
314− const destinationDir = join(nodeModulesDir, ...dependency.name.split("/"));
315− await mkdir(dirname(destinationDir), { recursive: true });
316− await cp(dependency.packageDir, destinationDir, { recursive: true });
317− }
318− await cp(quickJsWasmPath, join(binDir, "emscripten-module.wasm"));
319− await cp(
320− join(repoRoot, "packages/kernel/runtime-deno-subprocess/src/deno-subprocess-worker.mjs"),
321− join(binDir, "deno-subprocess-worker.mjs"),
322− );
323− await runCommand({
324− command: "bun",
325− args: [
326− "build",
327− "./packages/kernel/runtime-ses/src/sandbox-worker.mjs",
328− "--target",
329− "node",
330− "--outfile",
331− join(binDir, "sandbox-worker.mjs"),
332− ],
333− cwd: repoRoot,
334− });
335− await writeFile(join(packageDir, "package.json"), createPackageJson({
336− packageName,
337− packageVersion,
338− description: defaults.description,
339− keywords: defaults.keywords,
340− homepage: defaults.homepage,
341− bugs: defaults.bugs,
342− repository: defaults.repository,
343− license: defaults.license,
344− dependencies: Object.fromEntries(
345− bundledDependencies.map((dependency) => [dependency.name, dependency.version]),
346− ),
347− bundleDependencies: bundledDependencies.map((dependency) => dependency.name),
348− }));
349− await cp(readmePath, join(packageDir, "README.md"));
350− await writeFile(launcherPath, createLauncherSource());
351− await chmod(launcherPath, 0o755);
352−
353− return {
354− packageDir,
355− launcherPath,
356− bundlePath,
357− resourcesDir,
358− };
359−};
apps/executor/src/distribution/distribution.test.ts+0−110
@@ -1,110 +0,0 @@
1−import { existsSync, readFileSync } from "node:fs";
2−import { join } from "node:path";
3−
4−import { describe, expect, it } from "@effect/vitest";
5−import * as Effect from "effect/Effect";
6−
7−import {
8− DistributionHarness,
9− LocalDistributionHarnessLive,
10−} from "./harness";
11−
12−describe("distribution flow", () => {
13− const verifyInstallFlow = <R>(
14− runCommand: (
15− args: ReadonlyArray<string>,
16− options?: {
17− readonly okExitCodes?: ReadonlyArray<number>;
18− },
19− ) => Effect.Effect<{ stdout: string; stderr: string }, Error, R>,
20− ) =>
21− Effect.gen(function* () {
22− const harness = yield* DistributionHarness;
23− const bundleSource = readFileSync(join(harness.packageDir, "bin/executor.mjs"), "utf8");
24−
25− expect(bundleSource).not.toContain("core_bg.wasm");
26− expect(
27− existsSync(join(harness.packageDir, "node_modules/@1password/sdk-core/nodejs/core_bg.wasm")),
28− ).toBe(true);
29−
30− yield* harness.writeProjectConfig(`{
31− "runtime": "ses",
32− // local workspace config
33− "sources": {},
34−}
35−`);
36−
37− expect(yield* harness.isReachable()).toBe(false);
38−
39− const initialCall = yield* runCommand([
40− "call",
41− "return 1 + 1;",
42− "--base-url",
43− harness.baseUrl,
44− "--no-open",
45− ]);
46− expect(initialCall.stdout).toBe("2");
47− expect(yield* harness.isReachable()).toBe(true);
48−
49− const html = yield* harness.fetchText("/");
50− expect(html.status).toBe(200);
51− expect(html.contentType).toContain("text/html");
52− expect(html.body).toContain("<div id=\"root\"></div>");
53−
54− const installationResponse = yield* harness.fetchText("/v1/local/installation");
55− expect(installationResponse.status).toBe(200);
56− const installation = JSON.parse(installationResponse.body) as {
57− scopeId: string;
58− actorScopeId: string;
59− };
60−
61− const sesCall = yield* runCommand(
62− [
63− "call",
64− 'await fetch("https://example.com"); return 1;',
65− "--base-url",
66− harness.baseUrl,
67− ],
68− { okExitCodes: [1] },
69− );
70− expect(sesCall.stderr).toContain("fetch is disabled in SES executor");
71−
72− yield* harness.stopServer();
73− expect(yield* harness.isReachable()).toBe(false);
74−
75− const restartedCall = yield* runCommand([
76− "call",
77− "return 3;",
78− "--base-url",
79− harness.baseUrl,
80− "--no-open",
81− ]);
82− expect(restartedCall.stdout).toBe("3");
83−
84− const installationAfterRestartResponse = yield* harness.fetchText("/v1/local/installation");
85− expect(installationAfterRestartResponse.status).toBe(200);
86− const installationAfterRestart = JSON.parse(
87− installationAfterRestartResponse.body,
88− ) as {
89− scopeId: string;
90− actorScopeId: string;
91− };
92−
93− expect(installationAfterRestart.scopeId).toBe(installation.scopeId);
94− expect(installationAfterRestart.actorScopeId).toBe(installation.actorScopeId);
95−
96− yield* harness.stopServer();
97− expect(yield* harness.isReachable()).toBe(false);
98− });
99−
100− it.live("boots a staged package artifact in a fresh home", () =>
101− verifyInstallFlow((args, options) =>
102− Effect.flatMap(DistributionHarness, (harness) => harness.run(args, options))
103− )
104− .pipe(Effect.provide(LocalDistributionHarnessLive)), 240_000);
105−
106− it.live("boots an npm-installed package in a fresh home", () =>
107− verifyInstallFlow((args, options) =>
108− Effect.flatMap(DistributionHarness, (harness) => harness.runInstalled(args, options))
109− ).pipe(Effect.provide(LocalDistributionHarnessLive)), 240_000);
110−});
apps/executor/src/distribution/harness.ts+0−385
@@ -1,385 +0,0 @@
1−import { spawn } from "node:child_process";
2−import { createServer } from "node:net";
3−import { tmpdir } from "node:os";
4−import { dirname, join } from "node:path";
5−
6−import { FileSystem } from "@effect/platform";
7−import { NodeFileSystem } from "@effect/platform-node";
8−import * as Context from "effect/Context";
9−import * as Effect from "effect/Effect";
10−import * as Layer from "effect/Layer";
11−
12−import { buildDistributionPackage } from "./artifact";
13−import { executorAppEffectError } from "../effect-errors";
14−
15−const toError = (cause: unknown): Error =>
16− cause instanceof Error ? cause : new Error(String(cause));
17−
18−type CommandResult = {
19− readonly stdout: string;
20− readonly stderr: string;
21− readonly exitCode: number;
22−};
23−
24−export class DistributionHarness extends Context.Tag(
25− "@executor/apps/executor/distribution/DistributionHarness",
26−)<
27− DistributionHarness,
28− {
29− readonly packageDir: string;
30− readonly launcherPath: string;
31− readonly tarballPath: string;
32− readonly executorHome: string;
33− readonly baseUrl: string;
34− readonly writeProjectConfig: (
35− contents: string,
36− ) => Effect.Effect<void, Error, never>;
37− readonly run: (
38− args: ReadonlyArray<string>,
39− options?: {
40− readonly okExitCodes?: ReadonlyArray<number>;
41− },
42− ) => Effect.Effect<CommandResult, Error, never>;
43− readonly runInstalled: (
44− args: ReadonlyArray<string>,
45− options?: {
46− readonly okExitCodes?: ReadonlyArray<number>;
47− },
48− ) => Effect.Effect<CommandResult, Error, never>;
49− readonly fetchText: (
50− pathname: string,
51− ) => Effect.Effect<{
52− readonly status: number;
53− readonly body: string;
54− readonly contentType: string | null;
55− }, Error, never>;
56− readonly isReachable: () => Effect.Effect<boolean, Error, never>;
57− readonly stopServer: () => Effect.Effect<void, Error, never>;
58− }
59−>() {}
60−
61−const SERVER_WAIT_TIMEOUT_MS = 5_000;
62−const SERVER_POLL_INTERVAL_MS = 100;
63−
64−const runCommand = (input: {
65− readonly command: string;
66− readonly args: ReadonlyArray<string>;
67− readonly cwd: string;
68− readonly env?: NodeJS.ProcessEnv;
69− readonly okExitCodes?: ReadonlyArray<number>;
70−}): Effect.Effect<CommandResult, Error, never> =>
71− Effect.async((resume) => {
72− const child = spawn(input.command, [...input.args], {
73− cwd: input.cwd,
74− env: input.env,
75− stdio: ["ignore", "pipe", "pipe"],
76− });
77−
78− let stdout = "";
79− let stderr = "";
80−
81− child.stdout?.setEncoding("utf8");
82− child.stdout?.on("data", (chunk) => {
83− stdout += chunk;
84− });
85−
86− child.stderr?.setEncoding("utf8");
87− child.stderr?.on("data", (chunk) => {
88− stderr += chunk;
89− });
90−
91− child.once("error", (error) => {
92− resume(Effect.fail(error));
93− });
94−
95− child.once("close", (code) => {
96− const exitCode = code ?? -1;
97− const result = {
98− stdout: stdout.trim(),
99− stderr: stderr.trim(),
100− exitCode,
101− } satisfies CommandResult;
102− const okExitCodes = input.okExitCodes ?? [0];
103−
104− if (okExitCodes.includes(exitCode)) {
105− resume(Effect.succeed(result));
106− return;
107− }
108−
109− resume(Effect.fail(executorAppEffectError("distribution/harness",
110− [
111− `${input.command} ${input.args.join(" ")} exited with code ${exitCode}`,
112− stdout.length > 0 ? `stdout:\n${stdout.trim()}` : null,
113− stderr.length > 0 ? `stderr:\n${stderr.trim()}` : null,
114− ].filter((part) => part !== null).join("\n\n"),
115− )));
116− });
117−
118− return Effect.sync(() => {
119− child.kill("SIGTERM");
120− });
121− });
122−
123−const allocatePort = (): Effect.Effect<number, Error, never> =>
124− Effect.tryPromise({
125− try: async () => {
126− return await new Promise<number>((resolvePort, reject) => {
127− const server = createServer();
128− server.once("error", reject);
129− server.listen(0, "127.0.0.1", () => {
130− const address = server.address();
131− if (!address || typeof address === "string") {
132− server.close(() => reject(new Error("Failed to allocate test port")));
133− return;
134− }
135−
136− server.close((error) => {
137− if (error) {
138− reject(error);
139− return;
140− }
141−
142− resolvePort(address.port);
143− });
144− });
145− });
146− },
147− catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)),
148− });
149−
150−const buildPackage = (packageDir: string) =>
151− Effect.tryPromise({
152− try: () => buildDistributionPackage({
153− outputDir: packageDir,
154− buildWeb: false,
155− }),
156− catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)),
157− });
158−
159−const packPackage = (packageDir: string, outputDir: string) =>
160− runCommand({
161− command: "npm",
162− args: ["pack", packageDir],
163− cwd: outputDir,
164− }).pipe(
165− Effect.flatMap((result) => {
166− const tarballName = result.stdout
167− .split(/\s+/)
168− .map((part) => part.trim())
169− .filter((part) => part.length > 0)
170− .at(-1);
171−
172− if (!tarballName) {
173− return Effect.fail(
174− executorAppEffectError("distribution/harness", `Unable to determine tarball name from npm pack output: ${result.stdout}`),
175− );
176− }
177−
178− return Effect.succeed(join(outputDir, tarballName));
179− }),
180− );
181−
182−const waitForReachability = (input: {
183− baseUrl: string;
184− expected: boolean;
185−}): Effect.Effect<void, Error, never> =>
186− Effect.gen(function* () {
187− const startedAt = Date.now();
188−
189− while (Date.now() - startedAt < SERVER_WAIT_TIMEOUT_MS) {
190− const reachable = yield* Effect.tryPromise({
191− try: async () => {
192− const response = await fetch(new URL("/", input.baseUrl));
193− return response.ok;
194− },
195− catch: toError,
196− }).pipe(Effect.catchAll(() => Effect.succeed(false)));
197−
198− if (reachable === input.expected) {
199− return;
200− }
201−
202− yield* Effect.sleep(`${SERVER_POLL_INTERVAL_MS} millis`);
203− }
204−
205− return yield* Effect.fail(
206− new Error(
207− `Timed out waiting for executor server to become ${input.expected ? "reachable" : "unreachable"} at ${input.baseUrl}`,
208− ),
209− );
210− });
211−
212−export const LocalDistributionHarnessLive = Layer.scoped(
213− DistributionHarness,
214− Effect.gen(function* () {
215− const fs = yield* FileSystem.FileSystem;
216− const tempRoot = yield* Effect.acquireRelease(
217− fs.makeTempDirectory({
218− directory: tmpdir(),
219− prefix: "executor-distribution-",
220− }).pipe(Effect.mapError(toError)),
221− (path) =>
222− fs.remove(path, { recursive: true, force: true }).pipe(
223− Effect.mapError(toError),
224− Effect.orDie,
225− ),
226− );
227−
228− const packageDir = join(tempRoot, "package");
229− const prefixDir = join(tempRoot, "prefix");
230− const homeDir = join(tempRoot, "home");
231− const executorHome = join(homeDir, ".executor");
232− const stagedWorkspaceRoot = packageDir;
233− const installedWorkspaceRoot = tempRoot;
234− const baseUrl = `http://127.0.0.1:${yield* allocatePort()}`;
235−
236− yield* Effect.all([
237− fs.makeDirectory(prefixDir, { recursive: true }),
238− fs.makeDirectory(homeDir, { recursive: true }),
239− fs.makeDirectory(executorHome, { recursive: true }),
240− ]).pipe(Effect.mapError(toError));
241−
242− const artifact = yield* buildPackage(packageDir);
243− const tarballPath = yield* packPackage(packageDir, tempRoot);
244−
245−
246− const env = {
247− ...process.env,
248− HOME: homeDir,
249− EXECUTOR_HOME: executorHome,
250− } satisfies NodeJS.ProcessEnv;
251−
252− const installedEnv = {
253− ...env,
254− NPM_CONFIG_PREFIX: prefixDir,
255− PATH: `${join(prefixDir, "bin")}:${process.env.PATH ?? ""}`,
256− } satisfies NodeJS.ProcessEnv;
257−
258− yield* runCommand({
259− command: "npm",
260− args: ["install", "-g", tarballPath],
261− cwd: tempRoot,
262− env: installedEnv,
263− });
264−
265− const run = (
266− args: ReadonlyArray<string>,
267− options?: { readonly okExitCodes?: ReadonlyArray<number> },
268− ) =>
269− runCommand({
270− command: "node",
271− args: [artifact.launcherPath, ...args],
272− cwd: dirname(artifact.launcherPath),
273− env,
274− okExitCodes: options?.okExitCodes,
275− });
276−
277− const runInstalled = (
278− args: ReadonlyArray<string>,
279− options?: { readonly okExitCodes?: ReadonlyArray<number> },
280− ) =>
281− runCommand({
282− command: "executor",
283− args,
284− cwd: tempRoot,
285− env: installedEnv,
286− okExitCodes: options?.okExitCodes,
287− });
288−
289− const fetchText = (pathname: string) =>
290− Effect.tryPromise({
291− try: async () => {
292− const response = await fetch(new URL(pathname, baseUrl));
293− return {
294− status: response.status,
295− body: await response.text(),
296− contentType: response.headers.get("content-type"),
297− };
298− },
299− catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)),
300− });
301−
302− const isReachable = () =>
303− Effect.tryPromise({
304− try: async () => {
305− const response = await fetch(new URL("/", baseUrl));
306− return response.ok;
307− },
308− catch: toError,
309− }).pipe(Effect.catchAll(() => Effect.succeed(false)));
310−
311− const stopServer = () =>
312− Effect.gen(function* () {
313− const pidFile = join(executorHome, "run", "server.pid");
314− const exists = yield* fs.exists(pidFile).pipe(Effect.mapError(toError));
315− if (!exists) {
316− return;
317− }
318−
319− const contents = yield* fs.readFileString(pidFile).pipe(
320− Effect.mapError(toError),
321− );
322− const parsed = JSON.parse(contents) as { pid?: number };
323− const pid = parsed.pid;
324−
325− if (typeof pid === "number" && Number.isInteger(pid) && pid > 0) {
326− yield* Effect.try({
327− try: () => process.kill(pid, "SIGTERM"),
328− catch: toError,
329− }).pipe(Effect.catchAll(() => Effect.void));
330−
331− const stopped = yield* waitForReachability({
332− baseUrl,
333− expected: false,
334− }).pipe(
335− Effect.as(true),
336− Effect.catchAll(() => Effect.succeed(false)),
337− );
338− if (stopped) {
339− return;
340− }
341−
342− yield* Effect.try({
343− try: () => process.kill(pid, "SIGKILL"),
344− catch: toError,
345− }).pipe(Effect.catchAll(() => Effect.void));
346− }
347−
348− yield* waitForReachability({
349− baseUrl,
350− expected: false,
351− });
352− });
353−
354− const writeProjectConfig = (contents: string) =>
355− Effect.forEach(
356− [stagedWorkspaceRoot, installedWorkspaceRoot],
357− (workspaceRoot) =>
358− Effect.gen(function* () {
359− const configDir = join(workspaceRoot, ".executor");
360− yield* fs.makeDirectory(configDir, { recursive: true }).pipe(
361− Effect.mapError(toError),
362− );
363− yield* fs.writeFileString(
364− join(configDir, "executor.jsonc"),
365− contents,
366− ).pipe(Effect.mapError(toError));
367− }),
368− { discard: true },
369− );
370−
371− return DistributionHarness.of({
372− packageDir,
373− launcherPath: artifact.launcherPath,
374− tarballPath,
375− executorHome,
376− baseUrl,
377− writeProjectConfig,
378− run,
379− runInstalled,
380− fetchText,
381− isReachable,
382− stopServer,
383− });
384− }).pipe(Effect.provide(NodeFileSystem.layer)),
385−);
apps/executor/src/distribution/metadata.ts+0−38
@@ -1,38 +0,0 @@
1−import { readFile } from "node:fs/promises";
2−import { dirname, resolve } from "node:path";
3−import { fileURLToPath } from "node:url";
4−
5−export const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../../..");
6−const packageMetadataPath = resolve(repoRoot, "apps/executor/package.json");
7−
8−export type DistributionPackageMetadata = {
9− name: string;
10− version: string;
11− description: string;
12− keywords: ReadonlyArray<string>;
13− homepage?: string;
14− bugs?: {
15− url?: string;
16− };
17− repository?: {
18− type?: string;
19− url?: string;
20− };
21− license?: string;
22−};
23−
24−export const readDistributionPackageMetadata = async (): Promise<DistributionPackageMetadata> => {
25− const contents = await readFile(packageMetadataPath, "utf8");
26− const metadata = JSON.parse(contents) as Partial<DistributionPackageMetadata>;
27−
28− return {
29− name: metadata.name ?? "executor",
30− version: metadata.version ?? "0.0.0-local",
31− description: metadata.description ?? "Local AI executor with a CLI, local API server, and web UI.",
32− keywords: Array.isArray(metadata.keywords) ? metadata.keywords.filter((value): value is string => typeof value === "string") : ["executor", "ai", "agent", "cli"],
33− homepage: metadata.homepage,
34− bugs: metadata.bugs,
35− repository: metadata.repository,
36− license: metadata.license ?? "MIT",
37− };
38−};
apps/executor/src/distribution/publish.ts+0−224
@@ -1,224 +0,0 @@
1−import { spawn } from "node:child_process";
2−import { mkdir, rm } from "node:fs/promises";
3−import { join, resolve } from "node:path";
4−
5−import { buildDistributionPackage } from "./artifact";
6−import { readDistributionPackageMetadata, repoRoot } from "./metadata";
7−
8−const defaultReleaseDir = resolve(repoRoot, "apps/executor/dist/release");
9−const semverPattern =
10− /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
11−
12−type PublishCliOptions = {
13− dryRun: boolean;
14−};
15−
16−type CommandInput = {
17− command: string;
18− args: ReadonlyArray<string>;
19− cwd: string;
20−};
21−
22−type CommandOutput = {
23− stdout: string;
24− stderr: string;
25−};
26−
27−type PackResult = {
28− filename?: string;
29−};
30−
31−const parseArgs = (argv: ReadonlyArray<string>): PublishCliOptions => {
32− const options: PublishCliOptions = {
33− dryRun: false,
34− };
35−
36− for (const arg of argv) {
37− if (arg === "--dry-run") {
38− options.dryRun = true;
39− continue;
40− }
41−
42− throw new Error(`Unknown argument: ${arg}`);
43− }
44−
45− return options;
46−};
47−
48−const runCommand = async (input: CommandInput): Promise<CommandOutput> => {
49− const child = spawn(input.command, [...input.args], {
50− cwd: input.cwd,
51− env: process.env,
52− stdio: ["ignore", "pipe", "pipe"],
53− });
54−
55− let stdout = "";
56− let stderr = "";
57−
58− child.stdout?.setEncoding("utf8");
59− child.stdout?.on("data", (chunk) => {
60− stdout += chunk;
61− });
62−
63− child.stderr?.setEncoding("utf8");
64− child.stderr?.on("data", (chunk) => {
65− stderr += chunk;
66− });
67−
68− const exitCode = await new Promise<number>((resolveExitCode, reject) => {
69− child.once("error", reject);
70− child.once("close", (code) => {
71− resolveExitCode(code ?? -1);
72− });
73− });
74−
75− if (exitCode !== 0) {
76− throw new Error(
77− [
78− `${input.command} ${input.args.join(" ")} exited with code ${exitCode}`,
79− stdout.trim().length > 0 ? `stdout:\n${stdout.trim()}` : null,
80− stderr.trim().length > 0 ? `stderr:\n${stderr.trim()}` : null,
81− ]
82− .filter((part) => part !== null)
83− .join("\n\n"),
84− );
85− }
86−
87− return {
88− stdout: stdout.trim(),
89− stderr: stderr.trim(),
90− };
91−};
92−
93−const resolveTagFromEnvironment = (): string | undefined => {
94− const refName = process.env.GITHUB_REF_NAME?.trim();
95− if (process.env.GITHUB_REF_TYPE === "tag" && refName) {
96− return refName;
97− }
98−
99− const ref = process.env.GITHUB_REF?.trim();
100− if (ref?.startsWith("refs/tags/")) {
101− return ref.slice("refs/tags/".length);
102− }
103−
104− return undefined;
105−};
106−
107−const resolveGitHubRepository = (): string => {
108− const repository = process.env.GH_REPO?.trim() || process.env.GITHUB_REPOSITORY?.trim();
109− if (!repository) {
110− throw new Error("Set GH_REPO or GITHUB_REPOSITORY before creating a GitHub release.");
111− }
112−
113− return repository;
114−};
115−
116−const validateVersion = (version: string): void => {
117− if (!semverPattern.test(version)) {
118− throw new Error(`apps/executor/package.json version is not valid semver: ${version}`);
119− }
120−};
121−
122−const resolveChannel = (version: string): "latest" | "beta" =>
123− version.includes("-") ? "beta" : "latest";
124−
125−const packDistributionPackage = async (releaseDir: string): Promise<string> => {
126− const output = await runCommand({
127− command: "npm",
128− args: ["pack", "./apps/executor/dist/npm", "--pack-destination", releaseDir, "--json"],
129− cwd: repoRoot,
130− });
131− const [result] = JSON.parse(output.stdout) as ReadonlyArray<PackResult>;
132− const filename = result?.filename;
133−
134− if (!filename) {
135− throw new Error(`npm pack did not report an output filename. stdout:\n${output.stdout}`);
136− }
137−
138− return join(releaseDir, filename);
139−};
140−
141−const publishDistributionPackage = async (channel: "latest" | "beta"): Promise<void> => {
142− const args = ["publish", "./dist/npm", "--access", "public", "--tag", channel];
143− if (process.env.GITHUB_ACTIONS === "true") {
144− args.push("--provenance");
145− }
146−
147− await runCommand({
148− command: "npm",
149− args,
150− cwd: resolve(repoRoot, "apps/executor"),
151− });
152−};
153−
154−const createGitHubRelease = async (input: {
155− tag: string;
156− channel: "latest" | "beta";
157− assetPath: string;
158−}): Promise<void> => {
159− if (!process.env.GH_TOKEN?.trim()) {
160− throw new Error("GH_TOKEN is required to create a GitHub release.");
161− }
162−
163− const args = [
164− "release",
165− "create",
166− input.tag,
167− input.assetPath,
168− "--repo",
169− resolveGitHubRepository(),
170− "--title",
171− input.tag,
172− "--generate-notes",
173− "--verify-tag",
174− ];
175−
176− if (input.channel === "beta") {
177− args.push("--prerelease");
178− } else {
179− args.push("--latest");
180− }
181−
182− await runCommand({
183− command: "gh",
184− args,
185− cwd: repoRoot,
186− });
187−};
188−
189−const main = async () => {
190− const options = parseArgs(process.argv.slice(2));
191− const metadata = await readDistributionPackageMetadata();
192− const version = metadata.version;
193− const tag = `v${version}`;
194− const refTag = resolveTagFromEnvironment();
195−
196− validateVersion(version);
197−
198− if (refTag && refTag !== tag) {
199− throw new Error(`GitHub tag ${refTag} does not match apps/executor/package.json version ${version}`);
200− }
201−
202− const channel = resolveChannel(version);
203− await rm(defaultReleaseDir, { recursive: true, force: true });
204− await mkdir(defaultReleaseDir, { recursive: true });
205−
206− await buildDistributionPackage();
207− const archivePath = await packDistributionPackage(defaultReleaseDir);
208−
209− process.stdout.write(`Prepared executor@${version} for ${channel}\n`);
210− process.stdout.write(`${archivePath}\n`);
211−
212− if (options.dryRun) {
213− return;
214− }
215−
216− await publishDistributionPackage(channel);
217− await createGitHubRelease({
218− tag,
219− channel,
220− assetPath: archivePath,
221− });
222−};
223−
224−await main();
apps/executor/src/effect-errors.ts+0−40
@@ -1,40 +0,0 @@
1−import * as Data from "effect/Data";
2−
3−export class ExecutorAppEffectError extends Data.TaggedError(
4− "ExecutorAppEffectError",
5−)<{
6− readonly module: string;
7− readonly message: string;
8−}> {}
9−
10−export const executorAppEffectError = (
11− module: string,
12− message: string,
13−) => new ExecutorAppEffectError({ module, message });
14−
15−export class LocalServerReachabilityTimeoutError extends Data.TaggedError(
16− "LocalServerReachabilityTimeoutError",
17−)<{
18− readonly baseUrl: string;
19− readonly action: "start" | "shutdown";
20− readonly logFile: string;
21− readonly logTail: string | null;
22− readonly message: string;
23−}> {}
24−
25−export const localServerReachabilityTimeoutError = (input: {
26− baseUrl: string;
27− expected: boolean;
28− logFile: string;
29− logTail: string | null;
30−}) =>
31− new LocalServerReachabilityTimeoutError({
32− baseUrl: input.baseUrl,
33− action: input.expected ? "start" : "shutdown",
34− logFile: input.logFile,
35− logTail: input.logTail,
36− message:
37− input.logTail === null
38− ? `Timed out waiting for local executor server ${input.expected ? "start" : "shutdown"} at ${input.baseUrl}\n\nDaemon log: ${input.logFile}`
39− : `Timed out waiting for local executor server ${input.expected ? "start" : "shutdown"} at ${input.baseUrl}\n\nRecent daemon log (${input.logFile}):\n${input.logTail}`,
40− });
apps/executor/tsconfig.json+0−16
@@ -1,16 +0,0 @@
1−{
2− "compilerOptions": {
3− "target": "ES2022",
4− "module": "ESNext",
5− "moduleResolution": "Bundler",
6− "strict": true,
7− "skipLibCheck": true,
8− "noEmit": true,
9− "lib": ["ES2022"],
10− "types": ["bun-types", "node"]
11− },
12− "include": [
13− "src/**/*.ts",
14− "src/**/*.d.ts"
15− ]
16−}
apps/server/package.json+38−0
@@ -0,0 +1,38 @@
1+{
2+ "name": "@executor/server",
3+ "version": "1.4.0-beta.0",
4+ "private": true,
5+ "type": "module",
6+ "exports": {
7+ ".": "./src/index.ts"
8+ },
9+ "dependencies": {
10+ "@effect/platform": "catalog:",
11+ "@effect/platform-node": "catalog:",
12+ "@effect/sql": "catalog:",
13+ "@effect/sql-sqlite-bun": "catalog:",
14+ "@executor/config": "workspace:*",
15+ "@executor/api": "workspace:*",
16+ "@executor/execution": "workspace:*",
17+ "@executor/plugin-file-secrets": "workspace:*",
18+ "@executor/plugin-google-discovery": "workspace:*",
19+ "@executor/plugin-keychain": "workspace:*",
20+ "@executor/plugin-onepassword": "workspace:*",
21+ "@executor/plugin-mcp": "workspace:*",
22+ "@executor/plugin-graphql": "workspace:*",
23+ "@executor/plugin-openapi": "workspace:*",
24+ "@executor/sdk": "workspace:*",
25+ "@executor/host-mcp": "workspace:*",
26+ "@modelcontextprotocol/sdk": "^1.12.1",
27+ "@executor/storage-file": "workspace:*",
28+ "effect": "catalog:"
29+ },
30+ "devDependencies": {
31+ "@types/node": "catalog:",
32+ "bun-types": "catalog:",
33+ "typescript": "^5.9.3"
34+ },
35+ "scripts": {
36+ "typecheck": "tsc --noEmit"
37+ }
38+}
apps/server/src/dev-backend.ts+20−0
@@ -0,0 +1,20 @@
1+import { createServerHandlersWithExecutor, type ServerHandlers } from "./main";
2+import { createServerExecutorHandle } from "./services/executor";
3+
4+export type HotBackend = ServerHandlers & {
5+ readonly dispose: () => Promise<void>;
6+};
7+
8+export const createHotBackend = async (): Promise<HotBackend> => {
9+ const handle = await createServerExecutorHandle();
10+ const handlers = await createServerHandlersWithExecutor(handle.executor);
11+
12+ return {
13+ ...handlers,
14+ dispose: async () => {
15+ await handlers.api.dispose().catch(() => undefined);
16+ await handlers.mcp.close().catch(() => undefined);
17+ await handle.dispose();
18+ },
19+ };
20+};
apps/server/src/handlers/executions.ts+67−0
@@ -0,0 +1,67 @@
1+import { HttpApiBuilder } from "@effect/platform";
2+import { Effect } from "effect";
3+
4+import { ExecutorApi } from "@executor/api";
5+import {
6+ formatExecuteResult,
7+ formatPausedExecution,
8+ type ExecutionEngine,
9+} from "@executor/execution";
10+import { ExecutionEngineService } from "../services/engine";
11+
12+export const ExecutionsHandlers = HttpApiBuilder.group(
13+ ExecutorApi,
14+ "executions",
15+ (handlers) =>
16+ handlers
17+ .handle("execute", ({ payload }) =>
18+ Effect.gen(function* () {
19+ const engine = yield* ExecutionEngineService;
20+ const outcome = yield* Effect.promise(() =>
21+ engine.executeWithPause(payload.code),
22+ );
23+
24+ if (outcome.status === "completed") {
25+ const formatted = formatExecuteResult(outcome.result);
26+ return {
27+ status: "completed" as const,
28+ text: formatted.text,
29+ structured: formatted.structured,
30+ isError: formatted.isError,
31+ };
32+ }
33+
34+ const formatted = formatPausedExecution(outcome.execution);
35+ return {
36+ status: "paused" as const,
37+ text: formatted.text,
38+ structured: formatted.structured,
39+ };
40+ }),
41+ )
42+ .handle("resume", ({ path, payload }) =>
43+ Effect.gen(function* () {
44+ const engine = yield* ExecutionEngineService;
45+ const result = yield* Effect.promise(() =>
46+ engine.resume(path.executionId, {
47+ action: payload.action,
48+ content: payload.content as Record<string, unknown> | undefined,
49+ }),
50+ );
51+
52+ if (!result) {
53+ return yield* Effect.fail({
54+ _tag: "ExecutionNotFoundError" as const,
55+ executionId: path.executionId,
56+ });
57+ }
58+
59+ const formatted = formatExecuteResult(result);
60+ return {
61+ text: formatted.text,
62+ structured: formatted.structured,
63+ isError: formatted.isError,
64+ };
65+ }),
66+ ),
67+);
apps/server/src/handlers/google-discovery.ts+16−0
@@ -0,0 +1,16 @@
1+import { Effect, Layer } from "effect";
2+import {
3+ GoogleDiscoveryExtensionService,
4+ GoogleDiscoveryHandlers,
5+} from "@executor/plugin-google-discovery/api";
6+import { ExecutorService } from "../services/executor";
7+
8+const GoogleDiscoveryExtensionLive = Layer.effect(
9+ GoogleDiscoveryExtensionService,
10+ Effect.map(ExecutorService, (executor) => executor.googleDiscovery),
11+);
12+
13+export const GoogleDiscoveryHandlersLive = Layer.provide(
14+ GoogleDiscoveryHandlers,
15+ GoogleDiscoveryExtensionLive,
16+);
apps/server/src/handlers/graphql.ts+17−0
@@ -0,0 +1,17 @@
1+import { Effect, Layer } from "effect";
2+import {
3+ GraphqlHandlers,
4+ GraphqlExtensionService,
5+} from "@executor/plugin-graphql/api";
6+import { ExecutorService } from "../services/executor";
7+
8+// Wire GraphqlExtensionService from the executor's graphql extension
9+const GraphqlExtensionLive = Layer.effect(
10+ GraphqlExtensionService,
11+ Effect.map(ExecutorService, (executor) => executor.graphql),
12+);
13+
14+export const GraphqlHandlersLive = Layer.provide(
15+ GraphqlHandlers,
16+ GraphqlExtensionLive,
17+);
apps/server/src/handlers/mcp-source.ts+17−0
@@ -0,0 +1,17 @@
1+import { Effect, Layer } from "effect";
2+import {
3+ McpHandlers,
4+ McpExtensionService,
5+} from "@executor/plugin-mcp/api";
6+import { ExecutorService } from "../services/executor";
7+
8+// Wire McpExtensionService from the executor's mcp extension
9+const McpExtensionLive = Layer.effect(
10+ McpExtensionService,
11+ Effect.map(ExecutorService, (executor) => executor.mcp),
12+);
13+
14+export const McpSourceHandlersLive = Layer.provide(
15+ McpHandlers,
16+ McpExtensionLive,
17+);
apps/server/src/handlers/onepassword.ts+17−0
@@ -0,0 +1,17 @@
1+import { Effect, Layer } from "effect";
2+import {
3+ OnePasswordHandlers,
4+ OnePasswordExtensionService,
5+} from "@executor/plugin-onepassword/api";
6+import { ExecutorService } from "../services/executor";
7+
8+// Wire OnePasswordExtensionService from the executor's onepassword extension
9+const OnePasswordExtensionLive = Layer.effect(
10+ OnePasswordExtensionService,
11+ Effect.map(ExecutorService, (executor) => executor.onepassword),
12+);
13+
14+export const OnePasswordHandlersLive = Layer.provide(
15+ OnePasswordHandlers,
16+ OnePasswordExtensionLive,
17+);
apps/server/src/handlers/openapi.ts+17−0
@@ -0,0 +1,17 @@
1+import { Effect, Layer } from "effect";
2+import {
3+ OpenApiHandlers,
4+ OpenApiExtensionService,
5+} from "@executor/plugin-openapi/api";
6+import { ExecutorService } from "../services/executor";
7+
8+// Wire OpenApiExtensionService from the executor's openapi extension
9+const OpenApiExtensionLive = Layer.effect(
10+ OpenApiExtensionService,
11+ Effect.map(ExecutorService, (executor) => executor.openapi),
12+);
13+
14+export const OpenApiHandlersLive = Layer.provide(
15+ OpenApiHandlers,
16+ OpenApiExtensionLive,
17+);
apps/server/src/handlers/scope.ts+20−0
@@ -0,0 +1,20 @@
1+import { HttpApiBuilder } from "@effect/platform";
2+import { Effect } from "effect";
3+
4+import { ExecutorApi } from "@executor/api";
5+import { ExecutorService } from "../services/executor";
6+
7+export const ScopeHandlers = HttpApiBuilder.group(
8+ ExecutorApi,
9+ "scope",
10+ (handlers) =>
11+ handlers.handle("info", () =>
12+ Effect.gen(function* () {
13+ const executor = yield* ExecutorService;
14+ return {
15+ id: executor.scope.id,
16+ name: executor.scope.name,
17+ };
18+ }),
19+ ),
20+);
apps/server/src/handlers/secrets.ts+70−0
@@ -0,0 +1,70 @@
1+import { HttpApiBuilder } from "@effect/platform";
2+import { Effect, Option } from "effect";
3+import type { SecretId, ScopeId } from "@executor/sdk";
4+
5+import { ExecutorApi } from "@executor/api";
6+import { ExecutorService } from "../services/executor";
7+
8+const refToResponse = (ref: {
9+ id: SecretId;
10+ scopeId: ScopeId;
11+ name: string;
12+ provider: Option.Option<string>;
13+ purpose?: string;
14+ createdAt: Date;
15+}) => ({
16+ id: ref.id,
17+ scopeId: ref.scopeId,
18+ name: ref.name,
19+ provider: Option.getOrUndefined(ref.provider),
20+ purpose: ref.purpose,
21+ createdAt: ref.createdAt.getTime(),
22+});
23+
24+export const SecretsHandlers = HttpApiBuilder.group(
25+ ExecutorApi,
26+ "secrets",
27+ (handlers) =>
28+ handlers
29+ .handle("list", ({ path }) =>
30+ Effect.gen(function* () {
31+ const executor = yield* ExecutorService;
32+ const refs = yield* executor.secrets.list();
33+ return refs.map(refToResponse);
34+ }),
35+ )
36+ .handle("status", ({ path }) =>
37+ Effect.gen(function* () {
38+ const executor = yield* ExecutorService;
39+ const status = yield* executor.secrets.status(path.secretId);
40+ return { secretId: path.secretId, status };
41+ }),
42+ )
43+ .handle("set", ({ path, payload }) =>
44+ Effect.gen(function* () {
45+ const executor = yield* ExecutorService;
46+ const ref = yield* executor.secrets.set({
47+ id: payload.id,
48+ name: payload.name,
49+ value: payload.value,
50+ purpose: payload.purpose,
51+ provider: payload.provider,
52+ });
53+ return refToResponse(ref);
54+ }),
55+ )
56+ .handle("resolve", ({ path }) =>
57+ Effect.gen(function* () {
58+ const executor = yield* ExecutorService;
59+ const value = yield* executor.secrets.resolve(path.secretId);
60+ return { secretId: path.secretId, value };
61+ }),
62+ )
63+ .handle("remove", ({ path }) =>
64+ Effect.gen(function* () {
65+ const executor = yield* ExecutorService;
66+ const removed = yield* executor.secrets.remove(path.secretId);
67+ return { removed };
68+ }),
69+ ),
70+);
apps/server/src/handlers/sources.ts+67−0
@@ -0,0 +1,67 @@
1+import { HttpApiBuilder } from "@effect/platform";
2+import { Effect } from "effect";
3+
4+import { ExecutorApi } from "@executor/api";
5+import { ExecutorService } from "../services/executor";
6+
7+export const SourcesHandlers = HttpApiBuilder.group(
8+ ExecutorApi,
9+ "sources",
10+ (handlers) =>
11+ handlers
12+ .handle("list", ({ path }) =>
13+ Effect.gen(function* () {
14+ const executor = yield* ExecutorService;
15+ const sources = yield* executor.sources.list();
16+ return sources.map((s) => ({
17+ id: s.id,
18+ name: s.name,
19+ kind: s.kind,
20+ runtime: s.runtime,
21+ canRemove: s.canRemove,
22+ canRefresh: s.canRefresh,
23+ }));
24+ }),
25+ )
26+ .handle("remove", ({ path }) =>
27+ Effect.gen(function* () {
28+ const executor = yield* ExecutorService;
29+ yield* executor.sources.remove(path.sourceId);
30+ return { removed: true };
31+ }),
32+ )
33+ .handle("refresh", ({ path }) =>
34+ Effect.gen(function* () {
35+ const executor = yield* ExecutorService;
36+ yield* executor.sources.refresh(path.sourceId);
37+ return { refreshed: true };
38+ }),
39+ )
40+ .handle("tools", ({ path }) =>
41+ Effect.gen(function* () {
42+ const executor = yield* ExecutorService;
43+ const tools = yield* executor.tools.list({ sourceId: path.sourceId });
44+ return tools.map((t) => ({
45+ id: t.id,
46+ pluginKey: t.pluginKey,
47+ sourceId: t.sourceId,
48+ name: t.name,
49+ description: t.description,
50+ mayElicit: t.mayElicit,
51+ }));
52+ }),
53+ )
54+ .handle("detect", ({ path, payload }) =>
55+ Effect.gen(function* () {
56+ const executor = yield* ExecutorService;
57+ const results = yield* executor.sources.detect(payload.url);
58+ return results.map((r) => ({
59+ kind: r.kind,
60+ confidence: r.confidence,
61+ endpoint: r.endpoint,
62+ name: r.name,
63+ namespace: r.namespace,
64+ }));
65+ }),
66+ ),
67+);
apps/server/src/handlers/tools.ts+32−0
@@ -0,0 +1,32 @@
1+import { HttpApiBuilder } from "@effect/platform";
2+import { Effect } from "effect";
3+
4+import { ExecutorApi } from "@executor/api";
5+import { ExecutorService } from "../services/executor";
6+
7+export const ToolsHandlers = HttpApiBuilder.group(
8+ ExecutorApi,
9+ "tools",
10+ (handlers) =>
11+ handlers
12+ .handle("list", ({ path }) =>
13+ Effect.gen(function* () {
14+ const executor = yield* ExecutorService;
15+ const tools = yield* executor.tools.list();
16+ return tools.map((t) => ({
17+ id: t.id,
18+ pluginKey: t.pluginKey,
19+ sourceId: t.sourceId,
20+ name: t.name,
21+ description: t.description,
22+ mayElicit: t.mayElicit,
23+ }));
24+ }),
25+ )
26+ .handle("schema", ({ path }) =>
27+ Effect.gen(function* () {
28+ const executor = yield* ExecutorService;
29+ return yield* executor.tools.schema(path.toolId);
30+ }),
31+ ),
32+);
apps/server/src/index.ts+4−0
@@ -0,0 +1,4 @@
1+export { createApiHandler, createServerHandlers, type ApiHandler, type ServerHandlers, ApiLayer } from "./main";
2+export { createServerHandlersWithExecutor } from "./main";
3+export { ExecutorServiceLayer, createServerExecutorHandle, disposeExecutor, getExecutor, reloadExecutor } from "./services/executor";
4+export { createMcpRequestHandler, runMcpStdioServer, type McpRequestHandler } from "./mcp";
apps/server/src/main.ts+128−0
@@ -0,0 +1,128 @@
1+import {
2+ HttpApiBuilder,
3+ HttpApiSwagger,
4+ HttpMiddleware,
5+ HttpServer,
6+} from "@effect/platform";
7+import { Effect, Layer } from "effect";
8+
9+import { addGroup } from "@executor/api";
10+import { createExecutionEngine } from "@executor/execution";
11+import { OpenApiGroup } from "@executor/plugin-openapi/api";
12+import { McpGroup } from "@executor/plugin-mcp/api";
13+import { GoogleDiscoveryGroup } from "@executor/plugin-google-discovery/api";
14+import { OnePasswordGroup } from "@executor/plugin-onepassword/api";
15+import { GraphqlGroup } from "@executor/plugin-graphql/api";
16+import { ToolsHandlers } from "./handlers/tools";
17+import { SourcesHandlers } from "./handlers/sources";
18+import { SecretsHandlers } from "./handlers/secrets";
19+import { ExecutionsHandlers } from "./handlers/executions";
20+import { ScopeHandlers } from "./handlers/scope";
21+import { OpenApiHandlersLive } from "./handlers/openapi";
22+import { McpSourceHandlersLive } from "./handlers/mcp-source";
23+import { GoogleDiscoveryHandlersLive } from "./handlers/google-discovery";
24+import { OnePasswordHandlersLive } from "./handlers/onepassword";
25+import { GraphqlHandlersLive } from "./handlers/graphql";
26+import { ExecutorService, ExecutorServiceLayer, getExecutor, type ServerExecutor } from "./services/executor";
27+import { ExecutionEngineService } from "./services/engine";
28+import { createMcpRequestHandler, type McpRequestHandler } from "./mcp";
29+
30+// ---------------------------------------------------------------------------
31+// Composed API — core + plugin groups
32+// ---------------------------------------------------------------------------
33+
34+const ExecutorApiWithPlugins = addGroup(OpenApiGroup)
35+ .add(McpGroup)
36+ .add(GoogleDiscoveryGroup)
37+ .add(OnePasswordGroup)
38+ .add(GraphqlGroup);
39+
40+// ---------------------------------------------------------------------------
41+// API Layer
42+// ---------------------------------------------------------------------------
43+
44+const ApiBase = HttpApiBuilder.api(ExecutorApiWithPlugins).pipe(
45+ Layer.provide([
46+ ToolsHandlers,
47+ SourcesHandlers,
48+ SecretsHandlers,
49+ ExecutionsHandlers,
50+ ScopeHandlers,
51+ OpenApiHandlersLive,
52+ McpSourceHandlersLive,
53+ GoogleDiscoveryHandlersLive,
54+ OnePasswordHandlersLive,
55+ GraphqlHandlersLive,
56+ ]),
57+);
58+
59+// ---------------------------------------------------------------------------
60+// Composable API layer — for use with Effect platform HTTP servers
61+// ---------------------------------------------------------------------------
62+
63+export const ApiLayer = HttpApiSwagger.layer().pipe(
64+ Layer.provideMerge(HttpApiBuilder.middlewareOpenApi()),
65+ Layer.provideMerge(ApiBase),
66+);
67+
68+// ---------------------------------------------------------------------------
69+// Shared server — API + MCP from the same executor + engine instance
70+// ---------------------------------------------------------------------------
71+
72+export type ServerHandlers = {
73+ readonly api: {
74+ readonly handler: (request: Request) => Promise<Response>;
75+ readonly dispose: () => Promise<void>;
76+ };
77+ readonly mcp: McpRequestHandler;
78+};
79+
80+const createApiHandlerWithExecutor = (executor: ServerExecutor, engine: ReturnType<typeof createExecutionEngine>) =>
81+ HttpApiBuilder.toWebHandler(
82+ HttpApiSwagger.layer().pipe(
83+ Layer.provideMerge(HttpApiBuilder.middlewareOpenApi()),
84+ Layer.provideMerge(ApiBase),
85+ Layer.provideMerge(Layer.succeed(ExecutorService, executor)),
86+ Layer.provideMerge(Layer.succeed(ExecutionEngineService, engine)),
87+ Layer.provideMerge(HttpServer.layerContext),
88+ ),
89+ { middleware: HttpMiddleware.logger },
90+ );
91+
92+export const createServerHandlersWithExecutor = async (
93+ executor: ServerExecutor,
94+): Promise<ServerHandlers> => {
95+ const engine = createExecutionEngine({ executor });
96+ const api = createApiHandlerWithExecutor(executor, engine);
97+ const mcp = createMcpRequestHandler({ engine });
98+
99+ return { api, mcp };
100+};
101+
102+export const createServerHandlers = async (): Promise<ServerHandlers> =>
103+ createServerHandlersWithExecutor(await getExecutor());
104+
105+// ---------------------------------------------------------------------------
106+// Backwards compat — standalone API handler (no MCP)
107+// ---------------------------------------------------------------------------
108+
109+const ExecutionEngineLayer = Layer.effect(
110+ ExecutionEngineService,
111+ Effect.map(ExecutorService, (executor) => createExecutionEngine({ executor })),
112+);
113+
114+export const createApiHandler = () =>
115+ HttpApiBuilder.toWebHandler(
116+ HttpApiSwagger.layer().pipe(
117+ Layer.provideMerge(HttpApiBuilder.middlewareOpenApi()),
118+ Layer.provideMerge(ApiBase),
119+ Layer.provideMerge(ExecutionEngineLayer),
120+ Layer.provideMerge(ExecutorServiceLayer),
121+ Layer.provideMerge(HttpServer.layerContext),
122+ ),
123+ { middleware: HttpMiddleware.logger },
124+ );
125+
126+export type ApiHandler = ReturnType<typeof createApiHandler>;
127+
128+export { ExecutorServiceLayer } from "./services/executor";
apps/server/src/mcp.ts+122−0
@@ -0,0 +1,122 @@
1+import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2+import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3+import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
4+
5+import { createExecutorMcpServer, type ExecutorMcpServerConfig } from "@executor/host-mcp";
6+
7+// ---------------------------------------------------------------------------
8+// Streamable HTTP handler
9+// ---------------------------------------------------------------------------
10+
11+export type McpRequestHandler = {
12+ readonly handleRequest: (request: Request) => Promise<Response>;
13+ readonly close: () => Promise<void>;
14+};
15+
16+const jsonError = (status: number, code: number, message: string): Response =>
17+ new Response(
18+ JSON.stringify({ jsonrpc: "2.0", error: { code, message }, id: null }),
19+ { status, headers: { "content-type": "application/json" } },
20+ );
21+
22+export const createMcpRequestHandler = (
23+ config: ExecutorMcpServerConfig,
24+): McpRequestHandler => {
25+ const transports = new Map<string, WebStandardStreamableHTTPServerTransport>();
26+ const servers = new Map<string, McpServer>();
27+
28+ const dispose = async (
29+ id: string,
30+ opts: { transport?: boolean; server?: boolean } = {},
31+ ) => {
32+ const t = transports.get(id);
33+ const s = servers.get(id);
34+ transports.delete(id);
35+ servers.delete(id);
36+ if (opts.transport) await t?.close().catch(() => undefined);
37+ if (opts.server) await s?.close().catch(() => undefined);
38+ };
39+
40+ return {
41+ handleRequest: async (request) => {
42+ const sessionId = request.headers.get("mcp-session-id");
43+
44+ if (sessionId) {
45+ const transport = transports.get(sessionId);
46+ if (!transport) return jsonError(404, -32001, "Session not found");
47+ return transport.handleRequest(request);
48+ }
49+
50+ let created: McpServer | undefined;
51+ const transport = new WebStandardStreamableHTTPServerTransport({
52+ sessionIdGenerator: () => crypto.randomUUID(),
53+ enableJsonResponse: true,
54+ onsessioninitialized: (sid) => {
55+ transports.set(sid, transport);
56+ if (created) servers.set(sid, created);
57+ },
58+ onsessionclosed: (sid) => void dispose(sid, { server: true }),
59+ });
60+
61+ transport.onclose = () => {
62+ const sid = transport.sessionId;
63+ if (sid) void dispose(sid, { server: true });
64+ };
65+
66+ try {
67+ created = await createExecutorMcpServer(config);
68+ await created.connect(transport);
69+ const response = await transport.handleRequest(request);
70+
71+ if (!transport.sessionId) {
72+ await transport.close().catch(() => undefined);
73+ await created.close().catch(() => undefined);
74+ }
75+ return response;
76+ } catch (error) {
77+ if (!transport.sessionId) {
78+ await transport.close().catch(() => undefined);
79+ await created?.close().catch(() => undefined);
80+ }
81+ return jsonError(500, -32603, error instanceof Error ? error.message : "Internal server error");
82+ }
83+ },
84+
85+ close: async () => {
86+ const ids = new Set([...transports.keys(), ...servers.keys()]);
87+ await Promise.all([...ids].map((id) => dispose(id, { transport: true, server: true })));
88+ },
89+ };
90+};
91+
92+// ---------------------------------------------------------------------------
93+// Stdio transport
94+// ---------------------------------------------------------------------------
95+
96+export const runMcpStdioServer = async (config: ExecutorMcpServerConfig): Promise<void> => {
97+ const server = await createExecutorMcpServer(config);
98+ const transport = new StdioServerTransport();
99+
100+ const waitForExit = () =>
101+ new Promise<void>((resolve) => {
102+ const finish = () => {
103+ process.off("SIGINT", finish);
104+ process.off("SIGTERM", finish);
105+ process.stdin.off("end", finish);
106+ process.stdin.off("close", finish);
107+ resolve();
108+ };
109+ process.once("SIGINT", finish);
110+ process.once("SIGTERM", finish);
111+ process.stdin.once("end", finish);
112+ process.stdin.once("close", finish);
113+ });
114+
115+ try {
116+ await server.connect(transport);
117+ await waitForExit();
118+ } finally {
119+ await transport.close().catch(() => undefined);
120+ await server.close().catch(() => undefined);
121+ }
122+};
apps/server/src/services/engine.ts+7−0
@@ -0,0 +1,7 @@
1+import { Context } from "effect";
2+import type { ExecutionEngine } from "@executor/execution";
3+
4+export class ExecutionEngineService extends Context.Tag("ExecutionEngineService")<
5+ ExecutionEngineService,
6+ ExecutionEngine
7+>() {}
apps/server/src/services/executor.ts+205−0
@@ -0,0 +1,205 @@
1+import { Context, Effect, Layer, ManagedRuntime } from "effect";
2+import { SqliteClient } from "@effect/sql-sqlite-bun";
3+import * as SqlClient from "@effect/sql/SqlClient";
4+import { NodeFileSystem } from "@effect/platform-node";
5+import * as fs from "node:fs";
6+
7+import { createExecutor, scopeKv } from "@executor/sdk";
8+import {
9+ makeSqliteKv,
10+ makeKvConfig,
11+ makeScopedKv,
12+ migrate,
13+} from "@executor/storage-file";
14+import { withConfigFile } from "@executor/config";
15+import {
16+ openApiPlugin,
17+ makeKvOperationStore,
18+ type OpenApiPluginExtension,
19+} from "@executor/plugin-openapi";
20+import {
21+ mcpPlugin,
22+ makeKvBindingStore,
23+ type McpPluginExtension,
24+} from "@executor/plugin-mcp";
25+import {
26+ googleDiscoveryPlugin,
27+ makeKvBindingStore as makeKvGoogleDiscoveryBindingStore,
28+ type GoogleDiscoveryPluginExtension,
29+} from "@executor/plugin-google-discovery";
30+import {
31+ graphqlPlugin,
32+ makeKvOperationStore as makeKvGraphqlOperationStore,
33+ type GraphqlPluginExtension,
34+} from "@executor/plugin-graphql";
35+import { keychainPlugin } from "@executor/plugin-keychain";
36+import { fileSecretsPlugin } from "@executor/plugin-file-secrets";
37+import {
38+ onepasswordPlugin,
39+ type OnePasswordExtension,
40+} from "@executor/plugin-onepassword";
41+
42+import type { Executor, ExecutorPlugin } from "@executor/sdk";
43+
44+type ServerPlugins = readonly [
45+ ExecutorPlugin<"openapi", OpenApiPluginExtension>,
46+ ExecutorPlugin<"mcp", McpPluginExtension>,
47+ ExecutorPlugin<"googleDiscovery", GoogleDiscoveryPluginExtension>,
48+ ExecutorPlugin<"graphql", GraphqlPluginExtension>,
49+ ReturnType<typeof fileSecretsPlugin>,
50+ ExecutorPlugin<"onepassword", OnePasswordExtension>,
51+];
52+export type ServerExecutor = Executor<ServerPlugins>;
53+export type ServerExecutorHandle = {
54+ readonly executor: ServerExecutor;
55+ readonly dispose: () => Promise<void>;
56+};
57+
58+// ---------------------------------------------------------------------------
59+// Service tag
60+// ---------------------------------------------------------------------------
61+
62+export class ExecutorService extends Context.Tag("ExecutorService")<
63+ ExecutorService,
64+ ServerExecutor
65+>() {}
66+
67+// ---------------------------------------------------------------------------
68+// Data directory
69+// ---------------------------------------------------------------------------
70+
71+import { homedir } from "node:os";
72+import { join } from "node:path";
73+
74+const resolveDataDir = (): string => {
75+ if (process.env.EXECUTOR_DATA_DIR) return process.env.EXECUTOR_DATA_DIR;
76+ return join(homedir(), ".executor");
77+};
78+
79+const DATA_DIR = resolveDataDir();
80+
81+fs.mkdirSync(DATA_DIR, { recursive: true });
82+
83+const DB_PATH = `${DATA_DIR}/data.db`;
84+
85+// ---------------------------------------------------------------------------
86+// Executor Layer — SQLite-backed, scoped to ManagedRuntime lifetime
87+// ---------------------------------------------------------------------------
88+
89+const ExecutorLayer = Layer.effect(
90+ ExecutorService,
91+ Effect.gen(function* () {
92+ const sql = yield* SqlClient.SqlClient;
93+
94+ yield* migrate.pipe(Effect.catchAll((e) => Effect.die(e)));
95+
96+ const cwd = process.cwd();
97+ const kv = makeSqliteKv(sql);
98+ const config = makeKvConfig(kv, { cwd });
99+ const scopedKv = makeScopedKv(kv, cwd);
100+
101+ const configPath = join(process.cwd(), "executor.jsonc");
102+ const fsLayer = NodeFileSystem.layer;
103+
104+ return yield* createExecutor({
105+ ...config,
106+ plugins: [
107+ openApiPlugin({
108+ operationStore: withConfigFile.openapi(
109+ makeKvOperationStore(scopedKv, "openapi"),
110+ configPath,
111+ fsLayer,
112+ ),
113+ }),
114+ mcpPlugin({
115+ bindingStore: withConfigFile.mcp(
116+ makeKvBindingStore(scopedKv, "mcp"),
117+ configPath,
118+ fsLayer,
119+ ),
120+ }),
121+ googleDiscoveryPlugin({
122+ bindingStore: makeKvGoogleDiscoveryBindingStore(
123+ scopedKv,
124+ "google-discovery",
125+ ),
126+ }),
127+ graphqlPlugin({
128+ operationStore: withConfigFile.graphql(
129+ makeKvGraphqlOperationStore(scopedKv, "graphql"),
130+ configPath,
131+ fsLayer,
132+ ),
133+ }),
134+ // keychainPlugin(),
135+ fileSecretsPlugin(),
136+ onepasswordPlugin({
137+ kv: scopeKv(scopedKv, "onepassword"),
138+ }),
139+ ] as const,
140+ });
141+ }),
142+).pipe(Layer.provide(SqliteClient.layer({ filename: DB_PATH })));
143+
144+// ---------------------------------------------------------------------------
145+// ManagedRuntime — shared singleton for production, scoped handles for dev HMR
146+// ---------------------------------------------------------------------------
147+
148+export const createServerExecutorHandle =
149+ async (): Promise<ServerExecutorHandle> => {
150+ const runtime = ManagedRuntime.make(ExecutorLayer);
151+ const executor = await runtime.runPromise(ExecutorService);
152+
153+ return {
154+ executor,
155+ dispose: async () => {
156+ await Effect.runPromise(executor.close()).catch(() => undefined);
157+ await runtime.dispose().catch(() => undefined);
158+ },
159+ };
160+ };
161+
162+let sharedHandlePromise: Promise<ServerExecutorHandle> | null = null;
163+
164+const loadSharedHandle = (): Promise<ServerExecutorHandle> => {
165+ if (!sharedHandlePromise) {
166+ sharedHandlePromise = createServerExecutorHandle();
167+ }
168+ return sharedHandlePromise;
169+};
170+
171+/**
172+ * Get the shared executor instance. The ManagedRuntime keeps the SQLite
173+ * connection (and everything else) alive until the process exits.
174+ */
175+export const getExecutor = (): Promise<ServerExecutor> =>
176+ loadSharedHandle().then((handle) => handle.executor);
177+
178+/**
179+ * Dispose the shared executor/runtime. Mainly useful in development when the
180+ * backend module graph is hot-reloaded and we need fresh plugin init.
181+ */
182+export const disposeExecutor = async (): Promise<void> => {
183+ const currentHandlePromise = sharedHandlePromise;
184+ sharedHandlePromise = null;
185+
186+ const handle = await currentHandlePromise?.catch(() => null);
187+ await handle?.dispose().catch(() => undefined);
188+};
189+
190+/**
191+ * Dispose and eagerly recreate the shared executor.
192+ */
193+export const reloadExecutor = async (): Promise<ServerExecutor> => {
194+ await disposeExecutor();
195+ return getExecutor();
196+};
197+
198+/**
199+ * Provide `ExecutorService` to an Effect layer using the shared runtime.
200+ * Used by the API handler.
201+ */
202+export const ExecutorServiceLayer = Layer.effect(
203+ ExecutorService,
204+ Effect.promise(() => getExecutor()),
205+);
apps/server/tsconfig.json+22−0
@@ -0,0 +1,22 @@
1+{
2+ "compilerOptions": {
3+ "target": "ESNext",
4+ "module": "ESNext",
5+ "moduleResolution": "bundler",
6+ "strict": true,
7+ "esModuleInterop": true,
8+ "skipLibCheck": true,
9+ "outDir": "dist",
10+ "rootDir": "src",
11+ "declaration": true,
12+ "declarationMap": true,
13+ "sourceMap": true,
14+ "jsx": "react-jsx",
15+ "plugins": [
16+ {
17+ "name": "@effect/language-service"
18+ }
19+ ]
20+ },
21+ "include": ["src"]
22+}
apps/web/CHANGELOG.md+0−8
@@ -1,8 +0,0 @@
1−# @executor/web
2−
3−## null
4−
5−### Patch Changes
6−
7−- @executor/react@null
8−- @executor/server@null
apps/web/components.json+5−6
@@ -1,21 +1,20 @@
11 {
22 "$schema": "https://ui.shadcn.com/schema.json",
3− "style": "base-nova",
3+ "style": "new-york",
44 "rsc": false,
55 "tsx": true,
66 "tailwind": {
77 "config": "",
8− "css": "src/globals.css",
8+ "css": "../../packages/ui/src/styles/globals.css",
99 "baseColor": "neutral",
10− "cssVariables": true,
11− "prefix": ""
10+ "cssVariables": true
1211 },
1312 "iconLibrary": "lucide",
1413 "aliases": {
1514 "components": "@/components",
1615 "hooks": "@/hooks",
1716 "lib": "@/lib",
18− "utils": "@/lib/utils",
19− "ui": "@/components/ui"
17+ "utils": "@executor/ui/lib/utils",
18+ "ui": "@executor/ui/components"
2019 }
2120 }
apps/web/executor.jsonc+3−0
@@ -0,0 +1,3 @@
1+{
2+ "sources": []
3+}
apps/web/index.html+15−0
@@ -0,0 +1,15 @@
1+<!doctype html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>Executor</title>
7+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9+ <link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300..700;1,9..40,300..700&family=Instrument+Serif&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
10+ </head>
11+ <body>
12+ <div id="root"></div>
13+ <script type="module" src="/src/main.tsx"></script>
14+ </body>
15+</html>
apps/web/package.json+28−40
@@ -1,51 +1,39 @@
11 {
22 "name": "@executor/web",
3+ "version": "1.4.0-beta.0",
34 "private": true,
45 "type": "module",
5− "scripts": {
6− "dev": "bunx --bun vite dev",
7− "build": "bunx vite build --config vite.config.ts",
8− "typecheck": "bunx tsc --noEmit -p tsconfig.json",
9− "start": "NODE_ENV=production bun src/server.ts"
10− },
116 "dependencies": {
12− "@base-ui/react": "^1.3.0",
13− "@executor/plugin-execution-history-react": "workspace:*",
14− "@executor/plugin-google-discovery-react": "workspace:*",
15− "@executor/plugin-graphql-react": "workspace:*",
16− "@executor/plugin-local-tools-react": "workspace:*",
17− "@executor/plugin-mcp-react": "workspace:*",
18− "@executor/plugin-onepassword-react": "workspace:*",
19− "@executor/plugin-openapi-react": "workspace:*",
7+ "@executor/plugin-onepassword": "workspace:*",
8+ "@executor/plugin-mcp": "workspace:*",
9+ "@executor/plugin-google-discovery": "workspace:*",
10+ "@executor/plugin-graphql": "workspace:*",
11+ "@executor/plugin-openapi": "workspace:*",
12+ "@executor/sdk": "workspace:*",
2013 "@executor/react": "workspace:*",
2114 "@executor/server": "workspace:*",
22− "@executor/source-core": "workspace:*",
23− "@shikijs/langs": "^4.0.1",
24− "@shikijs/themes": "^4.0.1",
25− "@tanstack/react-router": "^1.132.7",
26− "class-variance-authority": "^0.7.1",
27− "clsx": "^2.1.1",
28− "effect": "catalog:",
29− "lucide-react": "^1.7.0",
30− "react": "^19.2.0",
31− "react-dom": "^19.2.0",
32− "react-grab": "^0.1.26",
33− "shadcn": "^4.1.1",
34− "shiki": "^4.0.1",
35− "streamdown": "^2.3.0",
36− "tailwind-merge": "^3.5.0",
37− "tldts": "^7.0.23"
15+ "@executor/ui": "workspace:*",
16+ "@shikijs/langs": "^4.0.2",
17+ "@shikijs/themes": "^4.0.2",
18+ "@tanstack/react-router": "^1.168.10",
19+ "react": "^19.1.0",
20+ "react-dom": "^19.1.0",
21+ "shiki": "^4.0.2",
22+ "streamdown": "^2.5.0",
23+ "tailwindcss": "^4.1.10"
3824 },
3925 "devDependencies": {
40− "@hono/vite-dev-server": "^0.25.0",
41− "@tailwindcss/vite": "^4.2.1",
42− "@types/react": "^19.2.10",
43− "@types/react-dom": "^19.2.3",
44− "@vitejs/plugin-react": "^5.1.4",
45− "bun-types": "catalog:",
46− "tailwindcss": "^4.2.1",
47− "tw-animate-css": "^1.4.0",
48− "vite": "^7.3.1"
26+ "@types/react": "^19.1.0",
27+ "@types/react-dom": "^19.1.0",
28+ "@types/node": "catalog:",
29+ "@tailwindcss/vite": "^4.1.10",
30+ "@vitejs/plugin-react": "^4.5.2",
31+ "typescript": "^5.9.3",
32+ "vite": "^6.3.5"
4933 },
50− "version": "0.0.0"
34+ "scripts": {
35+ "dev": "bunx --bun vite",
36+ "build": "vite build",
37+ "typecheck": "tsc --noEmit"
38+ }
5139 }
apps/web/src/App.tsx+6−0
@@ -0,0 +1,6 @@
1+import { RouterProvider } from "@tanstack/react-router";
2+import { router } from "./router";
3+
4+export function App() {
5+ return <RouterProvider router={router} />;
6+}
apps/web/src/components/code-block.tsx+0−96
@@ -1,96 +0,0 @@
1−import { useEffect, useState, useRef, useCallback } from "react";
2−import { Button } from "@executor/react/plugins";
3−import { codeToHtml, resolveLang } from "../lib/shiki";
4−import { cn } from "../lib/utils";
5−import { IconCopy, IconCheck } from "./icons";
6−
7−// Lazily loaded, cached across renders
8−const highlightCache = new Map<string, string>();
9−
10−function cacheKey(code: string, lang: string) {
11− return `${lang}::${code.length}::${code.slice(0, 64)}`;
12−}
13−
14−function detectLanguage(code: string, hint?: string): string {
15− if (hint) return resolveLang(hint) ?? "json";
16− const trimmed = code.trimStart();
17− if (trimmed.startsWith("{") || trimmed.startsWith("[")) return "json";
18− if (trimmed.startsWith("<")) return "xml";
19− if (trimmed.startsWith("---")) return "yaml";
20− return "json";
21−}
22−
23−export function CodeBlock(props: {
24− code: string;
25− lang?: string;
26− className?: string;
27−}) {
28− const { code, lang: langHint, className } = props;
29− const [html, setHtml] = useState<string | null>(null);
30− const [copied, setCopied] = useState(false);
31− const mountedRef = useRef(true);
32−
33− const language = detectLanguage(code, langHint);
34− const key = cacheKey(code, language);
35−
36− useEffect(() => {
37− mountedRef.current = true;
38− return () => {
39− mountedRef.current = false;
40− };
41− }, []);
42−
43− useEffect(() => {
44− const cached = highlightCache.get(key);
45− if (cached) {
46− setHtml(cached);
47− return;
48− }
49−
50− let cancelled = false;
51− codeToHtml(code, { lang: language }).then((result) => {
52− if (cancelled) return;
53− highlightCache.set(key, result);
54− if (mountedRef.current) setHtml(result);
55− });
56−
57− return () => {
58− cancelled = true;
59− };
60− }, [code, key, language]);
61−
62− const handleCopy = useCallback(() => {
63− void navigator.clipboard.writeText(code).then(() => {
64− setCopied(true);
65− setTimeout(() => setCopied(false), 1500);
66− });
67− }, [code]);
68−
69− return (
70− <div className={cn("group relative overflow-auto", className)}>
71− {/* Copy button */}
72− <Button
73− type="button"
74− variant="ghost"
75− size="icon"
76− onClick={handleCopy}
77− className="absolute right-2 top-2 z-10 size-7 rounded-md border border-border bg-card/90 text-muted-foreground/40 opacity-0 backdrop-blur-sm transition-all hover:text-foreground group-hover:opacity-100"
78− title="Copy to clipboard"
79− >
80− {copied ? <IconCheck className="size-3" /> : <IconCopy className="size-3" />}
81− </Button>
82−
83− {html ? (
84− <div
85− className="shiki-container text-[12px] leading-relaxed [&_pre]:!bg-transparent [&_pre]:p-3 [&_code]:font-mono"
86− dangerouslySetInnerHTML={{ __html: html }}
87− />
88− ) : (
89− // Fallback while shiki loads
90− <pre className="p-3 font-mono text-[12px] leading-relaxed text-foreground/60">
91− {code}
92− </pre>
93− )}
94− </div>
95− );
96−}
apps/web/src/components/document-panel.tsx+0−30
@@ -1,30 +0,0 @@
1−import { cn } from "../lib/utils";
2−import { CodeBlock } from "./code-block";
3−
4−export function DocumentPanel(props: {
5− title: string;
6− body: string | null;
7− lang?: string;
8− empty: string;
9− compact?: boolean;
10−}) {
11− return (
12− <section
13− className={cn(
14− "overflow-hidden rounded-lg border border-border bg-card/60",
15− props.compact && "min-h-48",
16− )}
17− >
18− <div className="border-b border-border px-3 py-2 text-[11px] font-medium uppercase tracking-wider text-muted-foreground/70">
19− {props.title}
20− </div>
21− {props.body ? (
22− <CodeBlock code={props.body} lang={props.lang} className="max-h-[32rem]" />
23− ) : (
24− <div className="flex items-center justify-center p-6 text-[13px] text-muted-foreground/40">
25− {props.empty}
26− </div>
27− )}
28− </section>
29− );
30−}
apps/web/src/components/icons.tsx+0−160
@@ -1,160 +0,0 @@
1−import type { SVGProps } from "react";
2−import { cn } from "../lib/utils";
3−
4−type IconProps = SVGProps<SVGSVGElement> & { className?: string };
5−
6−export function IconSources({ className, ...props }: IconProps) {
7− return (
8− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
9− <rect x="2" y="2" width="5" height="5" rx="1" stroke="currentColor" strokeWidth="1.3" />
10− <rect x="9" y="2" width="5" height="5" rx="1" stroke="currentColor" strokeWidth="1.3" />
11− <rect x="2" y="9" width="5" height="5" rx="1" stroke="currentColor" strokeWidth="1.3" />
12− <rect x="9" y="9" width="5" height="5" rx="1" stroke="currentColor" strokeWidth="1.3" />
13− </svg>
14− );
15−}
16−
17−export function IconTool({ className, ...props }: IconProps) {
18− return (
19− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
20− <path d="M4 8h8M8 4v8" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" />
21− </svg>
22− );
23−}
24−
25−export function IconSearch({ className, ...props }: IconProps) {
26− return (
27− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
28− <circle cx="7" cy="7" r="4.5" stroke="currentColor" strokeWidth="1.3" />
29− <path d="M10.5 10.5L14 14" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" />
30− </svg>
31− );
32−}
33−
34−export function IconChevron({ className, ...props }: IconProps) {
35− return (
36− <svg viewBox="0 0 16 16" fill="none" className={cn("size-3", className)} {...props}>
37− <path d="M6 4l4 4-4 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
38− </svg>
39− );
40−}
41−
42−export function IconFolder({ className, ...props }: IconProps) {
43− return (
44− <svg viewBox="0 0 16 16" fill="none" className={cn("size-3", className)} {...props}>
45− <path d="M2 4h5l2 2h5v7H2V4z" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" />
46− </svg>
47− );
48−}
49−
50−export function IconDocument({ className, ...props }: IconProps) {
51− return (
52− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
53− <path d="M4 2h5l3 3v9H4V2z" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round" />
54− <path d="M6 8h4M6 10.5h3" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
55− </svg>
56− );
57−}
58−
59−export function IconDiscover({ className, ...props }: IconProps) {
60− return (
61− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
62− <circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.3" />
63− <path d="M6.5 5.5l4.5 2-2 4.5-4.5-2z" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" />
64− </svg>
65− );
66−}
67−
68−export function IconCopy({ className, ...props }: IconProps) {
69− return (
70− <svg viewBox="0 0 16 16" fill="none" className={cn("size-3.5", className)} {...props}>
71− <rect x="5" y="5" width="8" height="8" rx="1" stroke="currentColor" strokeWidth="1.2" />
72− <path d="M11 3H4a1 1 0 00-1 1v7" stroke="currentColor" strokeWidth="1.2" />
73− </svg>
74− );
75−}
76−
77−export function IconCheck({ className, ...props }: IconProps) {
78− return (
79− <svg viewBox="0 0 16 16" fill="none" className={cn("size-3.5", className)} {...props}>
80− <path d="M4 8.5l3 3 5-6" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round" />
81− </svg>
82− );
83−}
84−
85−export function IconClose({ className, ...props }: IconProps) {
86− return (
87− <svg viewBox="0 0 16 16" fill="none" className={cn("size-3", className)} {...props}>
88− <path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
89− </svg>
90− );
91−}
92−
93−export function IconEmpty({ className, ...props }: IconProps) {
94− return (
95− <svg viewBox="0 0 48 48" fill="none" className={cn("size-12", className)} {...props}>
96− <rect x="6" y="6" width="36" height="36" rx="4" stroke="currentColor" strokeWidth="1.5" />
97− <path d="M16 18h16M16 24h12M16 30h8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
98− </svg>
99− );
100−}
101−
102−export function IconSpinner({ className, ...props }: IconProps) {
103− return (
104− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4 animate-spin", className)} {...props}>
105− <circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.5" opacity="0.2" />
106− <path d="M14 8a6 6 0 00-6-6" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
107− </svg>
108− );
109−}
110−
111−export function IconInfo({ className, ...props }: IconProps) {
112− return (
113− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
114− <circle cx="8" cy="8" r="5.75" stroke="currentColor" strokeWidth="1.2" />
115− <path d="M8 7v3.25" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
116− <circle cx="8" cy="4.75" r="0.8" fill="currentColor" />
117− </svg>
118− );
119−}
120−
121−export function IconPlus({ className, ...props }: IconProps) {
122− return (
123− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
124− <path d="M8 3.25v9.5M3.25 8h9.5" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
125− </svg>
126− );
127−}
128−
129−export function IconPencil({ className, ...props }: IconProps) {
130− return (
131− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
132− <path d="M3 11.75L11.6 3.15a1.2 1.2 0 011.7 0l.55.55a1.2 1.2 0 010 1.7L5.25 14H3v-2.25z" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" />
133− <path d="M9.75 5l1.25 1.25" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
134− </svg>
135− );
136−}
137−
138−export function IconTrash({ className, ...props }: IconProps) {
139− return (
140− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
141− <path d="M3.5 4.5h9M6 2.75h4M5 4.5v7.25m3-7.25v7.25m3-7.25v7.25M4.5 4.5l.4 8.1c.03.52.46.9.98.9h4.24c.52 0 .95-.38.98-.9l.4-8.1" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />
142− </svg>
143− );
144−}
145−
146−export function IconArrowLeft({ className, ...props }: IconProps) {
147− return (
148− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
149− <path d="M12.75 8H3.25M6.75 4.5L3.25 8l3.5 3.5" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
150− </svg>
151− );
152−}
153−
154−export function IconMenu({ className, ...props }: IconProps) {
155− return (
156− <svg viewBox="0 0 16 16" fill="none" className={cn("size-4", className)} {...props}>
157− <path d="M3 4.5h10M3 8h10M3 11.5h10" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
158− </svg>
159− );
160−}
apps/web/src/components/loadable.tsx+0−50
@@ -1,50 +0,0 @@
1−import type { ReactNode } from "react";
2−import type { Loadable } from "@executor/react";
3−import { IconSpinner, IconEmpty } from "./icons";
4−
5−export function LoadableBlock<T>(props: {
6− loadable: Loadable<T>;
7− loading?: string;
8− children: (data: T) => ReactNode;
9−}) {
10− if (props.loadable.status === "loading") {
11− return (
12− <div className="flex h-full min-h-48 items-center justify-center">
13− <div className="flex items-center gap-3 text-sm text-muted-foreground">
14− <IconSpinner />
15− <span>{props.loading ?? "Loading..."}</span>
16− </div>
17− </div>
18− );
19− }
20−
21− if (props.loadable.status === "error") {
22− return (
23− <div className="flex h-full min-h-48 items-center justify-center">
24− <div className="rounded-lg border border-destructive/25 bg-destructive/5 px-4 py-3 text-sm text-destructive">
25− {props.loadable.error.message}
26− </div>
27− </div>
28− );
29− }
30−
31− return <>{props.children(props.loadable.data)}</>;
32−}
33−
34−export function EmptyState(props: {
35− title: string;
36− description?: string;
37− className?: string;
38−}) {
39− return (
40− <div className={`flex h-full items-center justify-center ${props.className ?? ""}`}>
41− <div className="text-center">
42− <IconEmpty className="mx-auto mb-3 text-muted-foreground/20" />
43− <p className="text-[13px] text-muted-foreground/60">{props.title}</p>
44− {props.description && (
45− <p className="mt-1 text-[11px] text-muted-foreground/40">{props.description}</p>
46− )}
47− </div>
48− </div>
49− );
50−}
apps/web/src/components/local-mcp-install-card.tsx+0−213
@@ -1,213 +0,0 @@
1−import { useEffect, useRef, useState } from "react";
2−import { Button } from "@executor/react/plugins";
3−import { CodeBlock } from "./code-block";
4−
5−type LocalMcpInstallMode = "stdio" | "http";
6−
7−const isDevBuild = import.meta.env.DEV;
8−
9−/**
10− * Fetch the execute tool description from the local MCP server using the
11− * Streamable HTTP transport. Performs initialize → tools/list → returns the
12− * description of the "execute" tool.
13− */
14−async function fetchExecuteToolDescription(
15− mcpOrigin: string,
16−): Promise<string | null> {
17− const endpoint = `${mcpOrigin}/mcp`;
18−
19− const jsonRpcHeaders = {
20− "Content-Type": "application/json",
21− "Accept": "application/json, text/event-stream",
22− };
23−
24− // 1. Initialize – get a session id
25− const initRes = await fetch(endpoint, {
26− method: "POST",
27− headers: jsonRpcHeaders,
28− body: JSON.stringify({
29− jsonrpc: "2.0",
30− id: 1,
31− method: "initialize",
32− params: {
33− protocolVersion: "2025-03-26",
34− capabilities: {},
35− clientInfo: { name: "executor-web", version: "0.1.0" },
36− },
37− }),
38− });
39−
40− const sessionId = initRes.headers.get("mcp-session-id");
41− if (!sessionId) return null;
42−
43− // 2. List tools
44− const listRes = await fetch(endpoint, {
45− method: "POST",
46− headers: {
47− ...jsonRpcHeaders,
48− "mcp-session-id": sessionId,
49− },
50− body: JSON.stringify({
51− jsonrpc: "2.0",
52− id: 2,
53− method: "tools/list",
54− params: {},
55− }),
56− });
57−
58− const listBody = await listRes.json();
59− const tools: Array<{ name: string; description?: string }> =
60− listBody?.result?.tools ?? [];
61−
62− const executeTool = tools.find((t) => t.name === "execute");
63−
64− // 3. Tear down the session (best-effort)
65− void fetch(endpoint, {
66− method: "DELETE",
67− headers: { "mcp-session-id": sessionId },
68− }).catch(() => {});
69−
70− return executeTool?.description ?? null;
71−}
72−
73−function ToolDescriptionDisclosure() {
74− const [open, setOpen] = useState(false);
75− const [description, setDescription] = useState<string | null>(null);
76− const [loading, setLoading] = useState(false);
77− const fetchedRef = useRef(false);
78− const bodyRef = useRef<HTMLDivElement>(null);
79− const [height, setHeight] = useState(0);
80−
81− // Fetch lazily on first open
82− useEffect(() => {
83− if (!open || fetchedRef.current) return;
84− fetchedRef.current = true;
85− setLoading(true);
86− fetchExecuteToolDescription(window.location.origin)
87− .then(setDescription)
88− .catch(() => setDescription(null))
89− .finally(() => setLoading(false));
90− }, [open]);
91−
92− useEffect(() => {
93− if (bodyRef.current) {
94− setHeight(bodyRef.current.scrollHeight);
95− }
96− }, [open, description, loading]);
97−
98− return (
99− <div className="mt-3">
100− <button
101− type="button"
102− onClick={() => setOpen((v) => !v)}
103− className="flex items-center gap-1.5 text-[12px] font-medium text-muted-foreground/70 transition-colors hover:text-foreground/80"
104− >
105− <svg
106− viewBox="0 0 10 10"
107− className="size-2.5 fill-current transition-transform duration-200"
108− style={{ transform: open ? "rotate(90deg)" : "rotate(0deg)" }}
109− >
110− <path d="M3 1.5 L7 5 L3 8.5Z" />
111− </svg>
112− <span>View tool description</span>
113− </button>
114− <div
115− className="overflow-hidden transition-[max-height,opacity] duration-200 ease-out"
116− style={{
117− maxHeight: open ? height : 0,
118− opacity: open ? 1 : 0,
119− }}
120− >
121− <div ref={bodyRef}>
122− {loading ? (
123− <p className="mt-2 text-[11px] text-muted-foreground/60">
124− Loading...
125− </p>
126− ) : description ? (
127− <pre className="mt-2 max-h-64 overflow-y-auto rounded-lg border border-border/60 bg-background/50 p-3 font-mono text-[11px] leading-relaxed text-muted-foreground whitespace-pre-wrap">
128− {description}
129− </pre>
130− ) : open && !loading ? (
131− <p className="mt-2 text-[11px] text-muted-foreground/60">
132− Could not load tool description.
133− </p>
134− ) : null}
135− </div>
136− </div>
137− </div>
138− );
139−}
140−
141−export function LocalMcpInstallCard(props: {
142− title?: string;
143− description?: string;
144− className?: string;
145−}) {
146− const [origin, setOrigin] = useState<string | null>(null);
147− const [mode, setMode] = useState<LocalMcpInstallMode>("stdio");
148−
149− useEffect(() => {
150− setOrigin(window.location.origin);
151− }, []);
152−
153− const command = mode === "stdio"
154− ? isDevBuild
155− ? 'npx add-mcp "bun run executor mcp --stdio" --name "executor-stdio"'
156− : 'npx add-mcp "executor mcp --stdio" --name "executor-stdio"'
157− : origin
158− ? `npx add-mcp "${origin}/mcp" --transport http --name "executor"`
159− : 'npx add-mcp "<this-server>/mcp" --transport http --name "executor"';
160−
161− return (
162− <section className={props.className ?? "rounded-2xl border border-border bg-card/80 p-5"}>
163− <div className="mb-3 space-y-1">
164− <h2 className="text-sm font-semibold text-foreground">
165− {props.title ?? "Install local MCP"}
166− </h2>
167− <p className="text-[13px] text-muted-foreground">
168− {props.description
169− ?? (mode === "stdio"
170− ? "Preferred for local agents. This installs executor as a stdio MCP command and starts a local web sidecar automatically when needed."
171− : "Use the current web origin as a remote MCP endpoint over HTTP.")}
172− </p>
173− </div>
174− <div className="mb-3 inline-flex rounded-lg border border-border bg-background/70 p-1">
175− {[
176− { key: "stdio" as const, label: "Standard I/O" },
177− { key: "http" as const, label: "Remote HTTP" },
178− ].map((option) => (
179− <Button
180− key={option.key}
181− type="button"
182− variant={mode === option.key ? "default" : "ghost"}
183− size="sm"
184− onClick={() => setMode(option.key)}
185− className="rounded-md px-3 py-1.5"
186− >
187− {option.label}
188− </Button>
189− ))}
190− </div>
191− <CodeBlock code={command} lang="bash" className="rounded-xl border border-border bg-background/70" />
192− <ToolDescriptionDisclosure />
193− {mode === "stdio" ? (
194− <div className="mt-3 space-y-1 text-[12px] text-muted-foreground">
195− {!isDevBuild ? (
196− <p>
197− Requires the `executor` CLI on your PATH. Uses a distinct MCP name to avoid colliding with an existing remote `executor` entry.
198− </p>
199− ) : (
200− <>
201− <p>
202− Uses the repo-local dev CLI: <code>bun run executor mcp --stdio</code>.
203− </p>
204− <p>
205− Run the `add-mcp` command from the repository root, or set your MCP client working directory to this repo before using the saved entry.
206− </p>
207− </>
208− )}
209− </div>
210− ) : null}
211− </section>
212− );
213−}
apps/web/src/components/mcp-install-card.tsx+77−0
@@ -0,0 +1,77 @@
1+import { useEffect, useState } from "react";
2+import { Button } from "@executor/ui/components/button";
3+import { CodeBlock } from "@executor/ui/components/code-block";
4+
5+type TransportMode = "stdio" | "http";
6+
7+const isDev = import.meta.env.DEV;
8+
9+export function McpInstallCard(props: { className?: string }) {
10+ const [mode, setMode] = useState<TransportMode>("http");
11+ const [origin, setOrigin] = useState<string | null>(null);
12+
13+ useEffect(() => {
14+ setOrigin(window.location.origin);
15+ }, []);
16+
17+ const command =
18+ mode === "stdio"
19+ ? isDev
20+ ? 'npx add-mcp "bun run executor mcp --stdio" --name "executor-stdio"'
21+ : 'npx add-mcp "executor mcp --stdio" --name "executor-stdio"'
22+ : origin
23+ ? `npx add-mcp "${origin}/mcp" --transport http --name "executor"`
24+ : 'npx add-mcp "<this-server>/mcp" --transport http --name "executor"';
25+
26+ const description =
27+ mode === "stdio"
28+ ? "Starts executor as a local stdio MCP server. Best for CLI agents like Claude Code."
29+ : "Use the current web origin as a remote MCP endpoint over streamable HTTP.";
30+
31+ return (
32+ <section
33+ className={
34+ props.className ??
35+ "rounded-2xl border border-border bg-card/80 p-5"
36+ }
37+ >
38+ <div className="mb-3 space-y-1">
39+ <h2 className="text-sm font-semibold text-foreground">
40+ Connect an agent
41+ </h2>
42+ <p className="text-[13px] text-muted-foreground">{description}</p>
43+ </div>
44+
45+ {/* Transport toggle */}
46+ <div className="mb-3 inline-flex rounded-lg border border-border bg-background/70 p-1">
47+ {(
48+ [
49+ { key: "http", label: "Remote HTTP" },
50+ { key: "stdio", label: "Standard I/O" },
51+ ] as const
52+ ).map((opt) => (
53+ <Button
54+ key={opt.key}
55+ type="button"
56+ variant={mode === opt.key ? "default" : "ghost"}
57+ size="sm"
58+ onClick={() => setMode(opt.key)}
59+ className="rounded-md px-3 py-1.5"
60+ >
61+ {opt.label}
62+ </Button>
63+ ))}
64+ </div>
65+
66+ <CodeBlock code={command} lang="bash" />
67+
68+ {mode === "stdio" && (
69+ <p className="mt-3 text-[12px] text-muted-foreground">
70+ {isDev
71+ ? "Uses the repo-local dev CLI. Run from the repository root."
72+ : "Requires the executor CLI on your PATH."}
73+ </p>
74+ )}
75+ </section>
76+ );
77+}
apps/web/src/components/shell.tsx+0−561
@@ -1,561 +0,0 @@
1−import { Link, Outlet, useLocation, useMatchRoute } from "@tanstack/react-router";
2−import { useCallback, useEffect, useState } from "react";
3−import { useSources, type Source } from "@executor/react";
4−import { Button, sourcePluginsIndexPath } from "@executor/react/plugins";
5−import { cn } from "../lib/utils";
6−import { IconPlus, IconCopy, IconCheck, IconClose, IconMenu } from "./icons";
7−import { LoadableBlock } from "./loadable";
8−import { SourceFavicon } from "./source-favicon";
9−import {
10− getSourceFrontendPaths,
11− registeredFrontendPluginNavRoutes,
12−} from "../plugins";
13−
14−// ── Status dot color ─────────────────────────────────────────────────────
15−
16−const statusColor: Record<string, string> = {
17− connected: "bg-primary",
18− probing: "bg-amber-400",
19− draft: "bg-muted-foreground/30",
20− auth_required: "bg-amber-500",
21− error: "bg-destructive",
22−};
23−
24−type AppMetaEnv = {
25− readonly VITE_APP_VERSION: string;
26− readonly VITE_GITHUB_URL: string;
27−};
28−
29−const { VITE_APP_VERSION, VITE_GITHUB_URL } = (import.meta as ImportMeta & {
30− readonly env: AppMetaEnv;
31−}).env;
32−
33−type UpdateChannel = "latest" | "beta";
34−
35−const EXECUTOR_DIST_TAGS_PATH = "/v1/app/npm/dist-tags";
36−
37−type ParsedVersion = {
38− readonly major: number;
39− readonly minor: number;
40− readonly patch: number;
41− readonly prerelease: ReadonlyArray<string | number> | null;
42−};
43−
44−const semverPattern =
45− /^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<prerelease>[0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
46−
47−const resolveUpdateChannel = (version: string): UpdateChannel =>
48− version.includes("-beta.") ? "beta" : "latest";
49−
50−const parseVersion = (version: string): ParsedVersion | null => {
51− const match = version.trim().match(semverPattern);
52− if (!match?.groups) {
53− return null;
54− }
55−
56− return {
57− major: Number(match.groups.major),
58− minor: Number(match.groups.minor),
59− patch: Number(match.groups.patch),
60− prerelease: match.groups.prerelease
61− ? match.groups.prerelease.split(".").map((identifier) =>
62− /^\d+$/.test(identifier) ? Number(identifier) : identifier,
63− )
64− : null,
65− };
66−};
67−
68−const comparePrereleaseIdentifiers = (
69− left: ReadonlyArray<string | number> | null,
70− right: ReadonlyArray<string | number> | null,
71−): number => {
72− if (left === null && right === null) {
73− return 0;
74− }
75−
76− if (left === null) {
77− return 1;
78− }
79−
80− if (right === null) {
81− return -1;
82− }
83−
84− const length = Math.max(left.length, right.length);
85− for (let index = 0; index < length; index += 1) {
86− const leftIdentifier = left[index];
87− const rightIdentifier = right[index];
88−
89− if (leftIdentifier === rightIdentifier) {
90− continue;
91− }
92−
93− if (leftIdentifier === undefined) {
94− return -1;
95− }
96−
97− if (rightIdentifier === undefined) {
98− return 1;
99− }
100−
101− if (typeof leftIdentifier === "number" && typeof rightIdentifier === "number") {
102− return leftIdentifier < rightIdentifier ? -1 : 1;
103− }
104−
105− if (typeof leftIdentifier === "number") {
106− return -1;
107− }
108−
109− if (typeof rightIdentifier === "number") {
110− return 1;
111− }
112−
113− return leftIdentifier < rightIdentifier ? -1 : 1;
114− }
115−
116− return 0;
117−};
118−
119−const compareVersions = (left: string, right: string): number | null => {
120− const leftVersion = parseVersion(left);
121− const rightVersion = parseVersion(right);
122− if (!leftVersion || !rightVersion) {
123− return null;
124− }
125−
126− if (leftVersion.major !== rightVersion.major) {
127− return leftVersion.major < rightVersion.major ? -1 : 1;
128− }
129−
130− if (leftVersion.minor !== rightVersion.minor) {
131− return leftVersion.minor < rightVersion.minor ? -1 : 1;
132− }
133−
134− if (leftVersion.patch !== rightVersion.patch) {
135− return leftVersion.patch < rightVersion.patch ? -1 : 1;
136− }
137−
138− return comparePrereleaseIdentifiers(leftVersion.prerelease, rightVersion.prerelease);
139−};
140−
141−// ── useLatestVersion ─────────────────────────────────────────────────────
142−
143−function useLatestVersion(currentVersion: string) {
144− const channel = resolveUpdateChannel(currentVersion);
145− const [latestVersion, setLatestVersion] = useState<string | null>(null);
146−
147− useEffect(() => {
148− let cancelled = false;
149− fetch(EXECUTOR_DIST_TAGS_PATH)
150− .then(async (res) => {
151− if (!res.ok) {
152− throw new Error(`Failed to load dist tags: ${res.status}`);
153− }
154− return res.json() as Promise<Partial<Record<UpdateChannel, string>>>;
155− })
156− .then((data: Partial<Record<UpdateChannel, string>>) => {
157− if (!cancelled) {
158− setLatestVersion(data[channel] ?? null);
159− }
160− })
161− .catch(() => {});
162− return () => {
163− cancelled = true;
164− };
165− }, [channel]);
166−
167− const updateAvailable =
168− latestVersion !== null && compareVersions(currentVersion, latestVersion) === -1;
169−
170− return { latestVersion, updateAvailable, channel };
171−}
172−
173−// ── UpdateCard ───────────────────────────────────────────────────────────
174−
175−function UpdateCard(props: { latestVersion: string; channel: UpdateChannel }) {
176− const command = `npm i -g executor@${props.channel}`;
177− const [copied, setCopied] = useState(false);
178−
179− const handleCopy = useCallback(() => {
180− void navigator.clipboard.writeText(command).then(() => {
181− setCopied(true);
182− setTimeout(() => setCopied(false), 1500);
183− });
184− }, [command]);
185−
186− return (
187− <div className="mx-2 mb-2 rounded-xl border border-primary/25 bg-primary/[0.06] p-3">
188− <div className="flex items-center gap-2">
189− <div className="flex size-5 shrink-0 items-center justify-center rounded-full bg-primary/15">
190− <svg viewBox="0 0 16 16" fill="none" className="size-3 text-primary">
191− <path d="M8 3v7M5 7l3 3 3-3" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
192− <path d="M3 12h10" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
193− </svg>
194− </div>
195− <div className="min-w-0">
196− <p className="text-[11px] font-semibold text-foreground">Update available</p>
197− <p className="text-[10px] text-muted-foreground">
198− v{props.latestVersion}
199− </p>
200− </div>
201− </div>
202− <Button
203− type="button"
204− variant="outline"
205− onClick={handleCopy}
206− className="mt-2.5 flex w-full items-center justify-between gap-2 rounded-lg border-border/60 bg-background/50 px-2.5 py-1.5 text-left hover:bg-background/80"
207− >
208− <code className="truncate font-mono text-[10px] text-sidebar-foreground">
209− {command}
210− </code>
211− <span className="shrink-0 text-muted-foreground transition-colors group-hover:text-foreground">
212− {copied ? (
213− <IconCheck className="size-3 text-primary" />
214− ) : (
215− <IconCopy className="size-3" />
216− )}
217− </span>
218− </Button>
219− </div>
220− );
221−}
222−
223−// ── AppShell ─────────────────────────────────────────────────────────────
224−export function AppShell() {
225− const sources = useSources();
226− const location = useLocation();
227− const matchRoute = useMatchRoute();
228− const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
229− const isHome = matchRoute({ to: "/" });
230− const isSecrets = matchRoute({ to: "/secrets" });
231− const isPolicies = matchRoute({ to: "/policies" });
232− const { latestVersion, updateAvailable, channel } = useLatestVersion(VITE_APP_VERSION);
233− const mainPluginNavItems = registeredFrontendPluginNavRoutes.filter(
234− ({ route }) => (route.nav?.section ?? "main") === "main",
235− );
236− const sourcePluginNavItems = registeredFrontendPluginNavRoutes.filter(
237− ({ route }) => route.nav?.section === "sources",
238− );
239−
240− useEffect(() => {
241− setMobileSidebarOpen(false);
242− }, [location.pathname]);
243−
244− useEffect(() => {
245− if (!mobileSidebarOpen) {
246− return;
247− }
248−
249− const previousOverflow = document.body.style.overflow;
250− document.body.style.overflow = "hidden";
251− return () => {
252− document.body.style.overflow = previousOverflow;
253− };
254− }, [mobileSidebarOpen]);
255−
256− return (
257− <div className="flex h-screen overflow-hidden">
258− <aside className="hidden w-52 shrink-0 border-r border-sidebar-border bg-sidebar md:flex md:flex-col lg:w-56">
259− <SidebarContent
260− isHome={!!isHome}
261− isSecrets={!!isSecrets}
262− isPolicies={!!isPolicies}
263− latestVersion={latestVersion}
264− updateAvailable={updateAvailable}
265− channel={channel}
266− locationPathname={location.pathname}
267− mainPluginNavItems={mainPluginNavItems}
268− sourcePluginNavItems={sourcePluginNavItems}
269− sources={sources}
270− />
271− </aside>
272−
273− {mobileSidebarOpen && (
274− <div className="fixed inset-0 z-50 flex md:hidden">
275− <button
276− type="button"
277− aria-label="Close navigation"
278− className="absolute inset-0 bg-black/45 backdrop-blur-[1px]"
279− onClick={() => setMobileSidebarOpen(false)}
280− />
281− <div className="relative flex h-full w-[84vw] max-w-xs flex-col border-r border-sidebar-border bg-sidebar shadow-2xl">
282− <div className="flex h-12 shrink-0 items-center justify-between border-b border-sidebar-border px-4">
283− <Link to="/" className="flex items-center gap-1.5">
284− <span className="font-display text-base tracking-tight text-foreground">
285− executor
286− </span>
287− <span className="rounded bg-primary/15 px-1.5 py-0.5 text-[10px] font-medium text-primary">
288− v3
289− </span>
290− </Link>
291− <Button
292− type="button"
293− variant="ghost"
294− size="icon"
295− aria-label="Close navigation"
296− onClick={() => setMobileSidebarOpen(false)}
297− className="size-8 text-sidebar-foreground hover:bg-sidebar-active hover:text-foreground"
298− >
299− <IconClose className="size-3.5" />
300− </Button>
301− </div>
302− <SidebarContent
303− isHome={!!isHome}
304− isSecrets={!!isSecrets}
305− isPolicies={!!isPolicies}
306− latestVersion={latestVersion}
307− updateAvailable={updateAvailable}
308− channel={channel}
309− locationPathname={location.pathname}
310− mainPluginNavItems={mainPluginNavItems}
311− sourcePluginNavItems={sourcePluginNavItems}
312− sources={sources}
313− onNavigate={() => setMobileSidebarOpen(false)}
314− showBrand={false}
315− />
316− </div>
317− </div>
318− )}
319−
320− {/* Main content */}
321− <main className="flex min-h-0 flex-1 flex-col min-w-0 overflow-hidden">
322− <div className="flex h-12 shrink-0 items-center justify-between border-b border-border bg-background px-4 md:hidden">
323− <Button
324− type="button"
325− variant="outline"
326− size="icon"
327− aria-label="Open navigation"
328− onClick={() => setMobileSidebarOpen(true)}
329− className="size-8 bg-card hover:bg-accent/50"
330− >
331− <IconMenu className="size-4" />
332− </Button>
333− <Link to="/" className="flex items-center gap-1.5">
334− <span className="font-display text-base tracking-tight text-foreground">
335− executor
336− </span>
337− <span className="rounded bg-primary/15 px-1.5 py-0.5 text-[10px] font-medium text-primary">
338− v3
339− </span>
340− </Link>
341− <div className="w-8 shrink-0" />
342− </div>
343− <Outlet />
344− </main>
345− </div>
346− );
347−}
348−
349−function SidebarContent(props: {
350− isHome: boolean;
351− isSecrets: boolean;
352− isPolicies: boolean;
353− latestVersion: string | null;
354− updateAvailable: boolean;
355− channel: UpdateChannel;
356− locationPathname: string;
357− mainPluginNavItems: typeof registeredFrontendPluginNavRoutes;
358− sourcePluginNavItems: typeof registeredFrontendPluginNavRoutes;
359− sources: ReturnType<typeof useSources>;
360− onNavigate?: () => void;
361− showBrand?: boolean;
362−}) {
363− return (
364− <>
365− {props.showBrand !== false && (
366− <div className="flex h-12 shrink-0 items-center border-b border-sidebar-border px-4">
367− <Link to="/" className="flex items-center gap-1.5">
368− <span className="font-display text-base tracking-tight text-foreground">
369− executor
370− </span>
371− <span className="rounded bg-primary/15 px-1.5 py-0.5 text-[10px] font-medium text-primary">
372− v3
373− </span>
374− </Link>
375− </div>
376− )}
377−
378− <nav className="flex flex-1 flex-col overflow-y-auto p-2">
379− <NavItem
380− to="/"
381− label="Dashboard"
382− active={props.isHome}
383− onNavigate={props.onNavigate}
384− />
385− <NavItem
386− to="/secrets"
387− label="Secrets"
388− active={props.isSecrets}
389− onNavigate={props.onNavigate}
390− />
391− <NavItem
392− to="/policies"
393− label="Policies"
394− active={props.isPolicies}
395− onNavigate={props.onNavigate}
396− />
397− {props.mainPluginNavItems.map(({ plugin, route, to }) => (
398− <NavItem
399− key={`${plugin.key}:${route.key}`}
400− to={to}
401− label={route.nav?.label ?? route.key}
402− active={
403− props.locationPathname === to
404− || props.locationPathname.startsWith(`${to}/`)
405− }
406− onNavigate={props.onNavigate}
407− />
408− ))}
409−
410− <div className="mt-5 mb-1 px-2.5 text-[10px] font-medium uppercase tracking-widest text-muted-foreground/50">
411− <div className="flex items-center justify-between gap-2">
412− <span>Sources</span>
413− <Link
414− to={sourcePluginsIndexPath}
415− onClick={props.onNavigate}
416− className="inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-[10px] font-medium normal-case tracking-normal text-primary transition-colors hover:bg-sidebar-active hover:text-foreground"
417− >
418− <IconPlus className="size-3" />
419− Add
420− </Link>
421− </div>
422− </div>
423− {props.sourcePluginNavItems.length > 0 && (
424− <div className="mb-2 flex flex-col gap-px">
425− {props.sourcePluginNavItems.map(({ plugin, route, to }) => (
426− <NavItem
427− key={`${plugin.key}:${route.key}`}
428− to={to}
429− label={route.nav?.label ?? route.key}
430− active={
431− props.locationPathname === to
432− || props.locationPathname.startsWith(`${to}/`)
433− }
434− onNavigate={props.onNavigate}
435− />
436− ))}
437− </div>
438− )}
439− <LoadableBlock loadable={props.sources} loading="Loading...">
440− {(items) =>
441− !Array.isArray(items) ? (
442− <div className="px-2.5 py-2 text-[11px] leading-relaxed text-destructive">
443− Sources returned an unexpected payload.
444− </div>
445− ) : items.length === 0 ? (
446− <div className="px-2.5 py-2 text-[11px] leading-relaxed text-muted-foreground/40">
447− No sources yet
448− </div>
449− ) : (
450− <div className="flex flex-col gap-px">
451− {items.map((source) => (
452− <SourceItem
453− key={source.id}
454− pathname={props.locationPathname}
455− source={source}
456− onNavigate={props.onNavigate}
457− />
458− ))}
459− </div>
460− )
461− }
462− </LoadableBlock>
463− </nav>
464−
465− {props.updateAvailable && props.latestVersion && (
466− <UpdateCard latestVersion={props.latestVersion} channel={props.channel} />
467− )}
468−
469− <div className="shrink-0 border-t border-sidebar-border px-4 py-2.5">
470− <div className="flex items-center justify-between text-[10px] leading-none">
471− <span className="text-muted-foreground/70 tabular-nums">v{VITE_APP_VERSION}</span>
472− <a
473− href={VITE_GITHUB_URL}
474− target="_blank"
475− rel="noreferrer"
476− className="text-muted-foreground/70 transition-colors hover:text-foreground"
477− >
478− GitHub
479− </a>
480− </div>
481− </div>
482− </>
483− );
484−}
485−
486−// ── SourceItem ───────────────────────────────────────────────────────────
487−
488−function SourceItem(props: {
489− pathname: string;
490− source: Source;
491− onNavigate?: () => void;
492−}) {
493− const paths = getSourceFrontendPaths(props.source.kind);
494−
495− if (!paths) {
496− return (
497− <div className="group flex items-center gap-2 rounded-md px-2.5 py-1.5 text-[13px] text-sidebar-foreground/60">
498− <div className="flex size-3 shrink-0 items-center justify-center text-muted-foreground/50">
499− <SourceFavicon source={props.source} className="size-3" />
500− </div>
501− <span className="flex-1 truncate">{props.source.name}</span>
502− <span
503− className={cn("size-1.5 shrink-0 rounded-full", statusColor[props.source.status] ?? "bg-muted-foreground/30")}
504− title={props.source.status}
505− />
506− </div>
507− );
508− }
509−
510− const detailPath = paths.detail(props.source.id);
511− const active =
512− props.pathname === detailPath
513− || props.pathname.startsWith(`${detailPath}/`);
514−
515− return (
516− <Link
517− to={detailPath}
518− search={{ tab: "model" }}
519− onClick={props.onNavigate}
520− className={cn(
521− "group flex items-center gap-2 rounded-md px-2.5 py-1.5 text-[13px] transition-colors",
522− active
523− ? "bg-sidebar-active text-foreground font-medium"
524− : "text-sidebar-foreground hover:bg-sidebar-active/60 hover:text-foreground",
525− )}
526− >
527− <div className="flex size-3 shrink-0 items-center justify-center text-muted-foreground/50">
528− <SourceFavicon source={props.source} className="size-3" />
529− </div>
530− <span className="flex-1 truncate">{props.source.name}</span>
531− <span
532− className={cn("size-1.5 shrink-0 rounded-full", statusColor[props.source.status] ?? "bg-muted-foreground/30")}
533− title={props.source.status}
534− />
535− </Link>
536− );
537−}
538−
539−// ── NavItem ──────────────────────────────────────────────────────────────
540−
541−function NavItem(props: {
542− to: string;
543− label: string;
544− active: boolean;
545− onNavigate?: () => void;
546−}) {
547− return (
548− <Link
549− to={props.to}
550− onClick={props.onNavigate}
551− className={cn(
552− "flex items-center gap-2.5 rounded-md px-2.5 py-1.5 text-[13px] transition-colors",
553− props.active
554− ? "bg-sidebar-active text-foreground font-medium"
555− : "text-sidebar-foreground hover:bg-sidebar-active/60 hover:text-foreground",
556− )}
557− >
558− {props.label}
559− </Link>
560− );
561−}
apps/web/src/components/source-favicon.tsx+0−133
@@ -1,133 +0,0 @@
1−import { useState } from "react";
2−import type { Source } from "@executor/react";
3−import { getGoogleDiscoveryIconUrlForService } from "@executor/plugin-google-discovery-react";
4−import { getSourceFrontendIconUrl } from "../plugins";
5−import type { SourcePreset } from "../plugins/source-presets";
6−import { getSourceFaviconUrl } from "../lib/source-favicon";
7−import { cn } from "../lib/utils";
8−
9−type SourceKind = Source["kind"] | SourcePreset["kind"] | string;
10−
11−export function SourceFavicon({
12− source,
13− className,
14− size = 16,
15−}: {
16− source: Source;
17− className?: string;
18− size?: number;
19−}) {
20− return (
21− <ResolvedSourceIcon
22− kind={source.kind}
23− faviconUrl={getSourceFrontendIconUrl(source)}
24− className={className}
25− size={size}
26− />
27− );
28−}
29−
30−export function SourcePresetFavicon({
31− preset,
32− className,
33− size = 16,
34−}: {
35− preset: SourcePreset;
36− className?: string;
37− size?: number;
38−}) {
39− const faviconUrl = preset.kind === "google_discovery"
40− ? getGoogleDiscoveryIconUrlForService(preset.service)
41− : getSourceFaviconUrl(preset.previewUrl);
42−
43− return (
44− <ResolvedSourceIcon
45− kind={preset.kind}
46− faviconUrl={faviconUrl ?? getSourceFaviconUrl(preset.name)}
47− className={className}
48− size={size}
49− />
50− );
51−}
52−
53−function ResolvedSourceIcon({
54− kind,
55− faviconUrl,
56− className,
57− size = 16,
58−}: {
59− kind: SourceKind;
60− faviconUrl: string | null;
61− className?: string;
62− size?: number;
63−}) {
64− const [failedUrl, setFailedUrl] = useState<string | null>(null);
65− const isFailed = Boolean(faviconUrl && failedUrl === faviconUrl);
66−
67− if (!faviconUrl || isFailed) {
68− return <DefaultSourceIcon kind={kind} className={className} />;
69− }
70−
71− return (
72− <img
73− key={faviconUrl}
74− src={faviconUrl}
75− alt=""
76− width={size}
77− height={size}
78− className={cn("size-full object-contain", className)}
79− loading="lazy"
80− referrerPolicy="no-referrer"
81− onError={() => setFailedUrl(faviconUrl)}
82− />
83− );
84−}
85−
86−export function DefaultSourceIcon({
87− kind,
88− className,
89−}: {
90− kind: SourceKind;
91− className?: string;
92−}) {
93− const base = cn("shrink-0", className);
94−
95− switch (kind) {
96− case "mcp":
97− return (
98− <svg viewBox="0 0 16 16" fill="none" className={base}>
99− <rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" strokeWidth="1.2" />
100− <path d="M5 7h1M5 9h4" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
101− </svg>
102− );
103− case "graphql":
104− return (
105− <svg viewBox="0 0 16 16" fill="none" className={base}>
106− <path d="M8 2L14 5.5V10.5L8 14L2 10.5V5.5L8 2Z" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" />
107− <circle cx="8" cy="8" r="1.5" fill="currentColor" opacity="0.5" />
108− </svg>
109− );
110− case "google_discovery":
111− return (
112− <svg viewBox="0 0 16 16" fill="none" className={base}>
113− <path d="M8 2.5a5.5 5.5 0 1 0 0 11 5.3 5.3 0 0 0 3.82-1.55" stroke="currentColor" strokeWidth="1.2" />
114− <path d="M13 8H8" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
115− <circle cx="12.5" cy="8" r="1.2" fill="currentColor" />
116− </svg>
117− );
118− case "openapi":
119− return (
120− <svg viewBox="0 0 16 16" fill="none" className={base}>
121− <circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.2" />
122− <path d="M5 6h6M5 8h4M5 10h5" stroke="currentColor" strokeWidth="1.1" strokeLinecap="round" />
123− </svg>
124− );
125− default:
126− return (
127− <svg viewBox="0 0 16 16" fill="none" className={base}>
128− <rect x="2.5" y="2.5" width="11" height="11" rx="2" stroke="currentColor" strokeWidth="1.2" />
129− <path d="M5 6h6M5 8h4M5 10h3" stroke="currentColor" strokeWidth="1.1" strokeLinecap="round" />
130− </svg>
131− );
132− }
133−}
apps/web/src/components/source-not-found-state.tsx+0−39
@@ -1,39 +0,0 @@
1−import { Link } from "@tanstack/react-router";
2−import { sourcePluginsIndexPath } from "@executor/react/plugins";
3−
4−import { IconEmpty } from "./icons";
5−import { cn } from "../lib/utils";
6−
7−export function SourceNotFoundState() {
8− return (
9− <div className="flex h-full min-h-48 items-center justify-center px-6">
10− <div className="flex max-w-sm flex-col items-center text-center">
11− <IconEmpty className="mb-4 text-muted-foreground/20" />
12− <h2 className="text-sm font-semibold text-foreground">Source not found</h2>
13− <p className="mt-2 text-sm text-muted-foreground">
14− This source no longer exists in the current workspace.
15− </p>
16− <div className="mt-5 flex items-center gap-2">
17− <Link
18− to="/"
19− className={cn(
20− "inline-flex h-7 items-center justify-center rounded-md border border-input bg-transparent px-2.5 text-xs font-medium transition-all",
21− "hover:bg-accent hover:text-accent-foreground",
22− )}
23− >
24− Back to dashboard
25− </Link>
26− <Link
27− to={sourcePluginsIndexPath}
28− className={cn(
29− "inline-flex h-7 items-center justify-center rounded-md bg-primary px-2.5 text-xs font-medium text-primary-foreground transition-all",
30− "hover:bg-primary/90",
31− )}
32− >
33− Add source
34− </Link>
35− </div>
36− </div>
37− </div>
38− );
39−}
apps/web/src/components/source-plugins-reset-state.tsx+0−27
@@ -1,27 +0,0 @@
1−import type { ReactNode } from "react";
2−
3−type SourcePluginsResetStateProps = {
4− title: string;
5− message: string;
6− action?: ReactNode;
7−};
8−
9−export function SourcePluginsResetState(
10− input: SourcePluginsResetStateProps,
11−) {
12− return (
13− <div className="min-h-0 flex-1 overflow-y-auto">
14− <div className="mx-auto max-w-3xl px-6 py-10 lg:px-10 lg:py-14">
15− <div className="rounded-2xl border border-border bg-card p-8">
16− <h2 className="font-display text-xl tracking-tight text-foreground">
17− {input.title}
18− </h2>
19− <p className="mt-2 max-w-2xl text-sm leading-6 text-muted-foreground">
20− {input.message}
21− </p>
22− {input.action ? <div className="mt-5">{input.action}</div> : null}
23− </div>
24− </div>
25− </div>
26− );
27−}
apps/web/src/components/source-recovery-state.tsx+0−57
@@ -1,57 +0,0 @@
1−import type { Source } from "@executor/react";
2−
3−import { Badge, Button } from "@executor/react/plugins";
4−import { cn } from "../lib/utils";
5−import { IconSpinner, IconTool } from "./icons";
6−
7−export function SourceRecoveryState(props: {
8− source: Source;
9− title: string;
10− description: string;
11− refreshLabel?: string;
12− refreshTitle?: string;
13− refreshDisabled?: boolean;
14− refreshPending?: boolean;
15− feedback?: {
16− tone: "success" | "error";
17− text: string;
18− } | null;
19− onRefresh: () => void;
20−}) {
21− return (
22− <div className="flex h-full min-h-48 items-center justify-center px-6">
23− <div className="flex max-w-md flex-col items-center text-center">
24− <div className="mb-4 flex size-12 items-center justify-center rounded-2xl bg-muted text-muted-foreground">
25− <IconTool className="size-5" />
26− </div>
27− <h2 className="text-sm font-semibold text-foreground">{props.title}</h2>
28− <div className="mt-2 flex items-center gap-2">
29− <span className="text-sm text-muted-foreground">{props.source.name}</span>
30− <Badge variant="outline">{props.source.kind}</Badge>
31− </div>
32− <p className="mt-3 text-sm text-muted-foreground">{props.description}</p>
33− {props.feedback && (
34− <p
35− className={cn(
36− "mt-4 text-sm font-medium",
37− props.feedback.tone === "success" ? "text-primary" : "text-destructive",
38− )}
39− >
40− {props.feedback.text}
41− </p>
42− )}
43− <div className="mt-5 flex items-center gap-2">
44− <Button
45− size="sm"
46− onClick={props.onRefresh}
47− disabled={props.refreshDisabled}
48− title={props.refreshTitle}
49− >
50− {props.refreshPending ? <IconSpinner className="size-3" /> : null}
51− {props.refreshLabel ?? "Refresh source"}
52− </Button>
53− </div>
54− </div>
55− </div>
56− );
57−}
apps/web/src/components/tool-detail.tsx+203−0
@@ -0,0 +1,203 @@
1+import { useMemo, useState } from "react";
2+import { useAtomValue, toolSchemaAtom, Result, ScopeId, ToolId } from "@executor/react";
3+import { CodeBlock } from "@executor/ui/components/code-block";
4+import { Markdown } from "@executor/ui/components/markdown";
5+import { schemaToTypeDeclaration } from "../lib/schema-type-signature";
6+
7+// ---------------------------------------------------------------------------
8+// Copy button
9+// ---------------------------------------------------------------------------
10+
11+function CopyButton(props: { text: string; label?: string }) {
12+ const [copied, setCopied] = useState(false);
13+
14+ return (
15+ <button
16+ type="button"
17+ onClick={() => {
18+ void navigator.clipboard.writeText(props.text).then(() => {
19+ setCopied(true);
20+ setTimeout(() => setCopied(false), 1500);
21+ });
22+ }}
23+ className="size-6 shrink-0 flex items-center justify-center text-muted-foreground/30 hover:text-muted-foreground transition-colors"
24+ title={props.label ?? "Copy"}
25+ >
26+ {copied ? (
27+ <svg viewBox="0 0 16 16" className="size-3.5">
28+ <path d="M3 8l3 3 7-7" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
29+ </svg>
30+ ) : (
31+ <svg viewBox="0 0 16 16" className="size-3.5">
32+ <rect x="5" y="5" width="8" height="8" rx="1" fill="none" stroke="currentColor" strokeWidth="1.2" />
33+ <path d="M3 11V3h8" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
34+ </svg>
35+ )}
36+ </button>
37+ );
38+}
39+
40+// ---------------------------------------------------------------------------
41+// Build type declarations from schemas
42+// ---------------------------------------------------------------------------
43+
44+const buildCallSignature = (
45+ toolName: string,
46+ inputSchema: unknown,
47+ outputSchema: unknown,
48+): string => {
49+ const inputType = inputSchema
50+ ? schemaToTypeDeclaration(inputSchema)
51+ : "void";
52+ const outputType = outputSchema
53+ ? schemaToTypeDeclaration(outputSchema)
54+ : "void";
55+
56+ const leaf = toolName.split(".").pop() ?? toolName;
57+ return `declare function ${leaf}(input: ${inputType}): ${outputType}`;
58+};
59+
60+// ---------------------------------------------------------------------------
61+// ToolDetail
62+// ---------------------------------------------------------------------------
63+
64+export function ToolDetail(props: {
65+ toolId: string;
66+ toolName: string;
67+ toolDescription?: string;
68+ scopeId: ScopeId;
69+}) {
70+ const schema = useAtomValue(
71+ toolSchemaAtom(props.scopeId, props.toolId as ToolId),
72+ );
73+
74+ const types = useMemo(() => {
75+ if (!Result.isSuccess(schema)) return null;
76+ const v = schema.value;
77+ return {
78+ input: v.inputSchema ? schemaToTypeDeclaration(v.inputSchema, "Input") : null,
79+ output: v.outputSchema ? schemaToTypeDeclaration(v.outputSchema, "Output") : null,
80+ callSignature: buildCallSignature(props.toolName, v.inputSchema, v.outputSchema),
81+ inputJson: v.inputSchema ? JSON.stringify(v.inputSchema, null, 2) : null,
82+ outputJson: v.outputSchema ? JSON.stringify(v.outputSchema, null, 2) : null,
83+ };
84+ }, [schema, props.toolName]);
85+
86+ return (
87+ <div className="flex h-full flex-col overflow-hidden">
88+ {/* Header */}
89+ <div className="shrink-0 max-h-[40%] overflow-y-auto border-b border-border bg-background/95 backdrop-blur-sm">
90+ <div className="flex items-start gap-3 px-5 py-3.5">
91+ <div className="flex size-8 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary">
92+ <svg viewBox="0 0 16 16" className="size-4">
93+ <path
94+ d="M4 2h8l1 3H3l1-3zM3 6h10v8H3V6z"
95+ fill="none"
96+ stroke="currentColor"
97+ strokeWidth="1.2"
98+ />
99+ </svg>
100+ </div>
101+ <div className="min-w-0 flex-1">
102+ <div className="flex items-center gap-2">
103+ <h3 className="truncate text-sm font-semibold text-foreground font-mono">
104+ {props.toolName}
105+ </h3>
106+ <CopyButton text={props.toolId} label="Copy tool ID" />
107+ </div>
108+ {props.toolDescription && (
109+ <div className="mt-1">
110+ <Markdown>{props.toolDescription}</Markdown>
111+ </div>
112+ )}
113+ </div>
114+ </div>
115+ </div>
116+
117+ {/* Content */}
118+ <div className="flex-1 overflow-y-auto">
119+ {Result.match(schema, {
120+ onInitial: () => (
121+ <div className="p-5 text-sm text-muted-foreground">Loading schema…</div>
122+ ),
123+ onFailure: () => (
124+ <div className="p-5 text-sm text-destructive">Failed to load schema</div>
125+ ),
126+ onSuccess: () => (
127+ <div className="space-y-4 px-5 py-4">
128+ {/* Call signature */}
129+ {types?.callSignature && (
130+ <CodeBlock
131+ title="Call Signature"
132+ code={types.callSignature}
133+ lang="typescript"
134+ />
135+ )}
136+
137+ {/* Type declarations */}
138+ <div className="grid grid-cols-1 gap-3 xl:grid-cols-2">
139+ {types?.input ? (
140+ <CodeBlock title="Input" code={types.input} lang="typescript" />
141+ ) : (
142+ <div className="rounded-lg border border-border bg-card/60 px-3 py-6 text-center text-[13px] text-muted-foreground/40">
143+ No input
144+ </div>
145+ )}
146+ {types?.output ? (
147+ <CodeBlock title="Output" code={types.output} lang="typescript" />
148+ ) : (
149+ <div className="rounded-lg border border-border bg-card/60 px-3 py-6 text-center text-[13px] text-muted-foreground/40">
150+ No output
151+ </div>
152+ )}
153+ </div>
154+
155+ {/* JSON Schemas */}
156+ <div className="grid grid-cols-1 gap-3 xl:grid-cols-2">
157+ {types?.inputJson ? (
158+ <CodeBlock title="Input Schema" code={types.inputJson} />
159+ ) : (
160+ <div className="rounded-lg border border-border bg-card/60 px-3 py-6 text-center text-[13px] text-muted-foreground/40">
161+ No input schema
162+ </div>
163+ )}
164+ {types?.outputJson ? (
165+ <CodeBlock title="Output Schema" code={types.outputJson} />
166+ ) : (
167+ <div className="rounded-lg border border-border bg-card/60 px-3 py-6 text-center text-[13px] text-muted-foreground/40">
168+ No output schema
169+ </div>
170+ )}
171+ </div>
172+ </div>
173+ ),
174+ })}
175+ </div>
176+ </div>
177+ );
178+}
179+
180+// ---------------------------------------------------------------------------
181+// Empty state
182+// ---------------------------------------------------------------------------
183+
184+export function ToolDetailEmpty(props: { hasTools: boolean }) {
185+ return (
186+ <div className="flex h-full items-center justify-center">
187+ <div className="text-center">
188+ <p className="text-sm font-medium text-foreground/70">
189+ {props.hasTools ? "Select a tool" : "No tools available"}
190+ </p>
191+ {props.hasTools && (
192+ <p className="mt-1 text-xs text-muted-foreground">
193+ Choose from the list or press{" "}
194+ <kbd className="rounded border border-border bg-muted px-1 py-px text-[10px]">
195+ /
196+ </kbd>{" "}
197+ to search.
198+ </p>
199+ )}
200+ </div>
201+ </div>
202+ );
203+}
apps/web/src/components/tool-tree.tsx+367−0
@@ -0,0 +1,367 @@
1+import { useEffect, useMemo, useRef, useState } from "react";
2+
3+// ---------------------------------------------------------------------------
4+// Types
5+// ---------------------------------------------------------------------------
6+
7+export interface ToolSummary {
8+ readonly id: string;
9+ readonly name: string;
10+ readonly pluginKey: string;
11+ readonly description?: string;
12+}
13+
14+type TreeNode = {
15+ segment: string;
16+ tool?: ToolSummary;
17+ children: Map<string, TreeNode>;
18+};
19+
20+// ---------------------------------------------------------------------------
21+// Tree builder
22+// ---------------------------------------------------------------------------
23+
24+const buildTree = (tools: readonly ToolSummary[]): TreeNode => {
25+ const root: TreeNode = { segment: "", children: new Map() };
26+
27+ for (const tool of tools) {
28+ const parts = tool.name.split(".");
29+ let node = root;
30+ for (const part of parts) {
31+ let child = node.children.get(part);
32+ if (!child) {
33+ child = { segment: part, children: new Map() };
34+ node.children.set(part, child);
35+ }
36+ node = child;
37+ }
38+ node.tool = tool;
39+ }
40+
41+ return root;
42+};
43+
44+const countLeaves = (node: TreeNode): number => {
45+ let count = node.tool ? 1 : 0;
46+ for (const child of node.children.values()) {
47+ count += countLeaves(child);
48+ }
49+ return count;
50+};
51+
52+// ---------------------------------------------------------------------------
53+// Highlight
54+// ---------------------------------------------------------------------------
55+
56+const highlightMatch = (text: string, search: string) => {
57+ if (!search.trim()) return text;
58+
59+ const terms = search.trim().toLowerCase().split(/\s+/);
60+ const lower = text.toLowerCase();
61+ const ranges: [number, number][] = [];
62+
63+ for (const term of terms) {
64+ let idx = 0;
65+ while (idx < lower.length) {
66+ const found = lower.indexOf(term, idx);
67+ if (found === -1) break;
68+ ranges.push([found, found + term.length]);
69+ idx = found + 1;
70+ }
71+ }
72+
73+ if (ranges.length === 0) return text;
74+
75+ ranges.sort((a, b) => a[0] - b[0]);
76+ const merged: [number, number][] = [ranges[0]!];
77+ for (let i = 1; i < ranges.length; i++) {
78+ const last = merged[merged.length - 1]!;
79+ const cur = ranges[i]!;
80+ if (cur[0] <= last[1]) {
81+ last[1] = Math.max(last[1], cur[1]);
82+ } else {
83+ merged.push(cur);
84+ }
85+ }
86+
87+ const parts: { text: string; hl: boolean }[] = [];
88+ let cursor = 0;
89+ for (const [start, end] of merged) {
90+ if (cursor < start) parts.push({ text: text.slice(cursor, start), hl: false });
91+ parts.push({ text: text.slice(start, end), hl: true });
92+ cursor = end;
93+ }
94+ if (cursor < text.length) parts.push({ text: text.slice(cursor), hl: false });
95+
96+ return (
97+ <>
98+ {parts.map((p, i) =>
99+ p.hl ? (
100+ <mark key={i} className="rounded-sm bg-primary/20 px-px text-foreground">
101+ {p.text}
102+ </mark>
103+ ) : (
104+ <span key={i}>{p.text}</span>
105+ ),
106+ )}
107+ </>
108+ );
109+};
110+
111+// ---------------------------------------------------------------------------
112+// Tree node view
113+// ---------------------------------------------------------------------------
114+
115+function TreeNodeView(props: {
116+ node: TreeNode;
117+ depth: number;
118+ selectedToolId: string | null;
119+ onSelect: (toolId: string) => void;
120+ search: string;
121+ defaultOpen: boolean;
122+}) {
123+ const { node, depth, selectedToolId, onSelect, search, defaultOpen } = props;
124+ const hasChildren = node.children.size > 0;
125+ const isLeaf = !!node.tool && !hasChildren;
126+
127+ const hasSelectedDescendant = useMemo(() => {
128+ if (!selectedToolId) return false;
129+ const check = (n: TreeNode): boolean => {
130+ if (n.tool?.id === selectedToolId) return true;
131+ for (const child of n.children.values()) {
132+ if (check(child)) return true;
133+ }
134+ return false;
135+ };
136+ return check(node);
137+ }, [node, selectedToolId]);
138+
139+ const [open, setOpen] = useState(defaultOpen || hasSelectedDescendant);
140+
141+ useEffect(() => {
142+ if (defaultOpen || hasSelectedDescendant) setOpen(true);
143+ }, [defaultOpen, hasSelectedDescendant]);
144+
145+ const paddingLeft = 8 + depth * 16;
146+
147+ if (isLeaf) {
148+ return (
149+ <ToolLeafItem
150+ tool={node.tool!}
151+ active={node.tool!.id === selectedToolId}
152+ onSelect={() => onSelect(node.tool!.id)}
153+ search={search}
154+ depth={depth}
155+ />
156+ );
157+ }
158+
159+ const sorted = [...node.children.values()].sort((a, b) =>
160+ a.segment.localeCompare(b.segment),
161+ );
162+ const leafCount = countLeaves(node);
163+
164+ return (
165+ <div>
166+ <button
167+ type="button"
168+ onClick={() => setOpen((v) => !v)}
169+ aria-expanded={open}
170+ className="group flex h-auto w-full items-center gap-1.5 rounded-md py-1 pr-2.5 text-[12px] hover:bg-accent/40 text-left"
171+ style={{ paddingLeft }}
172+ >
173+ <svg
174+ viewBox="0 0 8 8"
175+ className="size-2 shrink-0 text-muted-foreground/30 transition-transform duration-150"
176+ style={{ transform: open ? "rotate(90deg)" : "rotate(0deg)" }}
177+ >
178+ <path d="M2 1l4 3-4 3z" fill="currentColor" />
179+ </svg>
180+ <svg viewBox="0 0 16 16" className="size-3 shrink-0 text-muted-foreground/30">
181+ <path
182+ d="M2 4h5l2 2h5v7H2V4z"
183+ fill="none"
184+ stroke="currentColor"
185+ strokeWidth="1.2"
186+ />
187+ </svg>
188+ <span className="flex-1 truncate font-mono text-foreground/70">
189+ {highlightMatch(node.segment, search)}
190+ </span>
191+ <span className="shrink-0 tabular-nums text-[10px] text-muted-foreground/25">
192+ {leafCount}
193+ </span>
194+ </button>
195+
196+ {open && hasChildren && (
197+ <div className="relative flex flex-col gap-px">
198+ <span
199+ className="absolute bottom-1 top-0 w-px bg-border/40"
200+ style={{ left: paddingLeft + 5 }}
201+ aria-hidden
202+ />
203+ {sorted.map((child) => (
204+ <TreeNodeView
205+ key={child.segment}
206+ node={child}
207+ depth={depth + 1}
208+ selectedToolId={selectedToolId}
209+ onSelect={onSelect}
210+ search={search}
211+ defaultOpen={defaultOpen}
212+ />
213+ ))}
214+ </div>
215+ )}
216+ </div>
217+ );
218+}
219+
220+// ---------------------------------------------------------------------------
221+// Leaf item
222+// ---------------------------------------------------------------------------
223+
224+function ToolLeafItem(props: {
225+ tool: ToolSummary;
226+ active: boolean;
227+ onSelect: () => void;
228+ search: string;
229+ depth: number;
230+}) {
231+ const ref = useRef<HTMLButtonElement>(null);
232+ const paddingLeft = 8 + props.depth * 16 + 8;
233+ const label = props.tool.name.split(".").pop() ?? props.tool.name;
234+
235+ useEffect(() => {
236+ if (props.active && ref.current) {
237+ ref.current.scrollIntoView({ block: "nearest" });
238+ }
239+ }, [props.active]);
240+
241+ return (
242+ <button
243+ ref={ref}
244+ type="button"
245+ onClick={props.onSelect}
246+ className={[
247+ "group flex h-auto w-full items-center gap-2 rounded-md py-1.5 pr-2.5 text-left",
248+ props.active
249+ ? "border-l-2 border-l-primary bg-primary/10 text-foreground"
250+ : "text-foreground/70 hover:bg-accent/50 hover:text-foreground",
251+ ].join(" ")}
252+ style={{ paddingLeft }}
253+ >
254+ <svg viewBox="0 0 16 16" className="size-3 shrink-0 text-muted-foreground/40">
255+ <path
256+ d="M4 2h8l1 3H3l1-3zM3 6h10v8H3V6z"
257+ fill="none"
258+ stroke="currentColor"
259+ strokeWidth="1.2"
260+ />
261+ </svg>
262+ <span className="flex-1 truncate font-mono text-[12px]">
263+ {highlightMatch(label, props.search)}
264+ </span>
265+ </button>
266+ );
267+}
268+
269+// ---------------------------------------------------------------------------
270+// ToolTree — main export
271+// ---------------------------------------------------------------------------
272+
273+export function ToolTree(props: {
274+ tools: readonly ToolSummary[];
275+ selectedToolId: string | null;
276+ onSelect: (toolId: string) => void;
277+}) {
278+ const [search, setSearch] = useState("");
279+ const searchRef = useRef<HTMLInputElement>(null);
280+ const terms = search.trim().toLowerCase().split(/\s+/).filter(Boolean);
281+
282+ const filteredTools = useMemo(() => {
283+ if (terms.length === 0) return props.tools;
284+ return props.tools.filter((t) => {
285+ const corpus = [t.name, t.description ?? ""].join(" ").toLowerCase();
286+ return terms.every((term) => corpus.includes(term));
287+ });
288+ }, [props.tools, terms]);
289+
290+ const tree = useMemo(() => buildTree(filteredTools), [filteredTools]);
291+
292+ useEffect(() => {
293+ const handler = (e: KeyboardEvent) => {
294+ if (e.key === "/" && document.activeElement?.tagName !== "INPUT") {
295+ e.preventDefault();
296+ searchRef.current?.focus();
297+ }
298+ if (e.key === "Escape") {
299+ searchRef.current?.blur();
300+ if (search.length > 0) setSearch("");
301+ }
302+ };
303+ document.addEventListener("keydown", handler);
304+ return () => document.removeEventListener("keydown", handler);
305+ }, [search]);
306+
307+ const entries = [...tree.children.values()].sort((a, b) =>
308+ a.segment.localeCompare(b.segment),
309+ );
310+
311+ return (
312+ <div className="flex h-full flex-col">
313+ {/* Search */}
314+ <div className="shrink-0 border-b border-border px-3 py-2">
315+ <div className="flex h-8 items-center gap-2 rounded-md border border-input bg-background px-2.5">
316+ <svg viewBox="0 0 16 16" className="size-3.5 shrink-0 text-muted-foreground/40">
317+ <circle cx="6.5" cy="6.5" r="5" fill="none" stroke="currentColor" strokeWidth="1.2" />
318+ <path d="M10 10l4.5 4.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
319+ </svg>
320+ <input
321+ ref={searchRef}
322+ value={search}
323+ onChange={(e) => setSearch(e.target.value)}
324+ placeholder={`Filter ${props.tools.length} tools…`}
325+ className="min-w-0 flex-1 border-0 bg-transparent p-0 text-[13px] shadow-none outline-none placeholder:text-muted-foreground/40"
326+ />
327+ {search.length > 0 ? (
328+ <button
329+ type="button"
330+ onClick={() => setSearch("")}
331+ className="size-5 shrink-0 flex items-center justify-center text-muted-foreground/40 hover:text-foreground"
332+ >
333+ ×
334+ </button>
335+ ) : (
336+ <kbd className="shrink-0 rounded border border-border bg-muted px-1 py-px text-[10px] leading-none text-muted-foreground/50">
337+ /
338+ </kbd>
339+ )}
340+ </div>
341+ </div>
342+
343+ {/* Tree */}
344+ <div className="flex-1 overflow-y-auto p-1.5">
345+ {filteredTools.length === 0 ? (
346+ <div className="p-4 text-center text-[13px] text-muted-foreground/50">
347+ {terms.length > 0 ? "No tools match your filter" : "No tools available"}
348+ </div>
349+ ) : (
350+ <div className="flex flex-col gap-px">
351+ {entries.map((node) => (
352+ <TreeNodeView
353+ key={node.segment}
354+ node={node}
355+ depth={0}
356+ selectedToolId={props.selectedToolId}
357+ onSelect={props.onSelect}
358+ search={search}
359+ defaultOpen={terms.length > 0}
360+ />
361+ ))}
362+ </div>
363+ )}
364+ </div>
365+ </div>
366+ );
367+}
apps/web/src/dev.ts+0−123
@@ -1,123 +0,0 @@
1−/**
2− * Dev entry point for @hono/vite-dev-server.
3− *
4− * Exports `{ fetch }` so Vite can forward API requests to the executor
5− * control-plane handler. Everything else (frontend assets, HMR) is
6− * handled by Vite itself.
7− */
8−import { join } from "node:path";
9−import * as Cause from "effect/Cause";
10−import * as Effect from "effect/Effect";
11−import * as Exit from "effect/Exit";
12−import * as Runtime from "effect/Runtime";
13−import * as Scope from "effect/Scope";
14−import {
15− createLocalExecutorRequestHandler,
16− DEFAULT_EXECUTOR_DATA_DIR,
17−} from "@executor/server";
18−
19−const MAX_LOGGED_ERROR_BODY_LENGTH = 4_000;
20−const EXECUTOR_WEB_DEV_LOCAL_DATA_DIR_ENV = "EXECUTOR_WEB_DEV_LOCAL_DATA_DIR";
21−const DEFAULT_WEB_DEV_LOCAL_DATA_DIR = join(
22− DEFAULT_EXECUTOR_DATA_DIR,
23− "control-plane-web-dev",
24−);
25−
26−const truncateForLog = (value: string): string =>
27− value.length > MAX_LOGGED_ERROR_BODY_LENGTH
28− ? `${value.slice(0, MAX_LOGGED_ERROR_BODY_LENGTH)}... [truncated]`
29− : value;
30−
31−const resolveWebDevLocalDataDir = (): string => {
32− const configured = process.env[EXECUTOR_WEB_DEV_LOCAL_DATA_DIR_ENV]?.trim();
33− return configured && configured.length > 0
34− ? configured
35− : DEFAULT_WEB_DEV_LOCAL_DATA_DIR;
36−};
37−
38−/**
39− * Extract a detailed, human-readable description from an error.
40− *
41− * When Effect rejects via `runPromise`, the thrown value is a
42− * `FiberFailure` wrapping a `Cause`. `Cause.pretty` renders the full
43− * failure tree (defects, interrupts, tagged errors, etc.) rather than the
44− * opaque fallback message ("An error has occurred").
45− */
46−const formatErrorForLog = (error: unknown): string => {
47− if (Runtime.isFiberFailure(error)) {
48− const cause = error[Runtime.FiberFailureCauseId];
49− return Cause.pretty(cause);
50− }
51−
52− if (error instanceof Error) {
53− return error.stack ?? error.message;
54− }
55−
56− return String(error);
57−};
58−
59−// Create a long-lived scope that stays open for the lifetime of the process.
60−const handlerPromise = (async () => {
61− const exit = await Effect.runPromiseExit(
62− Effect.gen(function* () {
63− const scope = yield* Scope.make();
64− const handler = yield* createLocalExecutorRequestHandler({
65− localDataDir: resolveWebDevLocalDataDir(),
66− }).pipe(
67− Effect.provideService(Scope.Scope, scope),
68− );
69− return handler;
70− }),
71− );
72−
73− if (Exit.isSuccess(exit)) {
74− return exit.value;
75− }
76−
77− // Log the full Cause tree — this captures typed errors, defects (uncaught
78− // throws), and interrupts with their original stack traces.
79− console.error(
80− "[executor dev api] failed to initialize request handler\n\n" +
81− Cause.pretty(exit.cause),
82− );
83−
84− // Re-throw so every subsequent request sees the init failure.
85− throw Cause.squash(exit.cause);
86−})();
87−
88−export default {
89− async fetch(request: Request) {
90− const url = new URL(request.url);
91−
92− try {
93− const handler = await handlerPromise;
94− handler.setBaseUrl(url.origin);
95−
96− const response = await handler.handleApiRequest(request);
97−
98− if (url.pathname.startsWith("/v1/") && response.status >= 500) {
99− let bodyText = "<unavailable>";
100− try {
101− bodyText = truncateForLog(await response.clone().text());
102− } catch {}
103−
104− console.error("[executor dev api] request failed", {
105− method: request.method,
106− url: url.toString(),
107− status: response.status,
108− contentType: response.headers.get("content-type"),
109− body: bodyText,
110− });
111− }
112−
113− return response;
114− } catch (error) {
115− console.error("[executor dev api] unhandled request error", {
116− method: request.method,
117− url: url.toString(),
118− error: formatErrorForLog(error),
119− });
120− throw error;
121− }
122− },
123−};
apps/web/src/frontend.tsx+0−19
@@ -1,19 +0,0 @@
1−import { createRoot } from "react-dom/client";
2−
3−class BrowserBuffer extends Uint8Array {}
4−
5−const browserGlobal = globalThis as any;
6−
7−if (browserGlobal.Buffer === undefined) {
8− browserGlobal.Buffer = BrowserBuffer;
9−}
10−
11−const { App } = await import("./main");
12−
13−const rootElement = document.getElementById("root");
14−
15−if (!rootElement) {
16− throw new Error("Missing #root element");
17−}
18−
19−createRoot(rootElement).render(<App />);
apps/web/src/index.html+0−30
@@ -1,30 +0,0 @@
1−<!doctype html>
2−<html lang="en">
3− <head>
4− <meta charset="UTF-8" />
5− <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6− <meta name="color-scheme" content="light dark" />
7− <title>Executor</title>
8− <meta
9− name="description"
10− content="Executor — manage sources, inspect tools, and monitor executions."
11− />
12− <link rel="preconnect" href="https://fonts.googleapis.com" />
13− <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
14− <script type="module">
15− // first npm i react-grab
16− // then in head:
17− if (import.meta.env.DEV) {
18− import("react-grab");
19− }
20− </script>
21− <link
22− href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=Instrument+Serif&family=JetBrains+Mono:wght@400;500&display=swap"
23− rel="stylesheet"
24− />
25− </head>
26− <body>
27− <div id="root"></div>
28− <script type="module" src="./frontend.tsx"></script>
29− </body>
30−</html>
apps/web/src/lib/schema-type-signature.ts+223−0
@@ -0,0 +1,223 @@
1+/**
2+ * Convert a JSON Schema into TypeScript-like type signatures.
3+ *
4+ * Two modes:
5+ * - `schemaToTypeSignature(schema)` — compact single-line for badges/previews
6+ * - `schemaToTypeDeclaration(schema)` — multi-line with indentation for code blocks
7+ *
8+ * TODO: Ugly file, has limitations
9+ */
10+
11+type JsonSchemaRecord = Record<string, unknown>;
12+
13+const asRecord = (value: unknown): JsonSchemaRecord =>
14+ typeof value === "object" && value !== null && !Array.isArray(value)
15+ ? (value as JsonSchemaRecord)
16+ : {};
17+
18+const asStringArray = (value: unknown): string[] =>
19+ Array.isArray(value)
20+ ? value.filter((item): item is string => typeof item === "string")
21+ : [];
22+
23+// ---------------------------------------------------------------------------
24+// Compact single-line signature
25+// ---------------------------------------------------------------------------
26+
27+const truncate = (value: string, maxLength: number): string =>
28+ value.length <= maxLength
29+ ? value
30+ : `${value.slice(0, Math.max(0, maxLength - 4))} ...`;
31+
32+const propertyLabel = (
33+ name: string,
34+ schema: JsonSchemaRecord,
35+ optional: boolean,
36+): string => `${name}${optional ? "?" : ""}: ${schemaToTypeSignature(schema)}`;
37+
38+const compositeLabel = (
39+ key: "oneOf" | "anyOf" | "allOf",
40+ schema: JsonSchemaRecord,
41+): string | null => {
42+ const items = Array.isArray(schema[key]) ? schema[key].map(asRecord) : [];
43+ if (items.length === 0) return null;
44+ const labels = items
45+ .map((item) => schemaToTypeSignature(item))
46+ .filter((label) => label.length > 0);
47+ if (labels.length === 0) return null;
48+ return labels.join(key === "allOf" ? " & " : " | ");
49+};
50+
51+export const schemaToTypeSignature = (
52+ input: unknown,
53+ maxLength: number = 220,
54+): string => {
55+ const schema = asRecord(input);
56+
57+ if (typeof schema.$ref === "string") {
58+ const ref = schema.$ref.trim();
59+ return ref.length > 0 ? ref.split("/").at(-1) ?? ref : "unknown";
60+ }
61+ if ("const" in schema) return JSON.stringify(schema.const);
62+
63+ const enumValues = Array.isArray(schema.enum) ? schema.enum : [];
64+ if (enumValues.length > 0) {
65+ return truncate(enumValues.map((v) => JSON.stringify(v)).join(" | "), maxLength);
66+ }
67+
68+ const composite =
69+ compositeLabel("oneOf", schema) ??
70+ compositeLabel("anyOf", schema) ??
71+ compositeLabel("allOf", schema);
72+ if (composite) return truncate(composite, maxLength);
73+
74+ if (schema.type === "array") {
75+ const itemLabel = schema.items
76+ ? schemaToTypeSignature(schema.items, maxLength)
77+ : "unknown";
78+ return truncate(`${itemLabel}[]`, maxLength);
79+ }
80+
81+ if (schema.type === "object" || schema.properties) {
82+ const properties = asRecord(schema.properties);
83+ const keys = Object.keys(properties);
84+ if (keys.length === 0) {
85+ return schema.additionalProperties ? "Record<string, unknown>" : "object";
86+ }
87+ const required = new Set(asStringArray(schema.required));
88+ const parts = keys.map((key) =>
89+ propertyLabel(key, asRecord(properties[key]), !required.has(key)),
90+ );
91+ return truncate(`{ ${parts.join(", ")} }`, maxLength);
92+ }
93+
94+ if (Array.isArray(schema.type)) return truncate(schema.type.join(" | "), maxLength);
95+ if (typeof schema.type === "string") return schema.type;
96+ return "unknown";
97+};
98+
99+// ---------------------------------------------------------------------------
100+// Multi-line type declaration
101+// ---------------------------------------------------------------------------
102+
103+const INDENT = " ";
104+
105+const refName = (ref: string): string => {
106+ const trimmed = ref.trim();
107+ return trimmed.length > 0 ? trimmed.split("/").at(-1) ?? trimmed : "unknown";
108+};
109+
110+const compositeDecl = (
111+ key: "oneOf" | "anyOf" | "allOf",
112+ schema: JsonSchemaRecord,
113+ depth: number,
114+): string | null => {
115+ const items = Array.isArray(schema[key]) ? schema[key].map(asRecord) : [];
116+ if (items.length === 0) return null;
117+
118+ const sep = key === "allOf" ? " & " : " | ";
119+ const parts = items.map((item) => formatNode(item, depth));
120+ if (parts.length === 0) return null;
121+
122+ // If all parts are short primitives, inline
123+ const joined = parts.join(sep);
124+ if (joined.length < 80 && !joined.includes("\n")) return joined;
125+
126+ // Multi-line
127+ const prefix = INDENT.repeat(depth);
128+ return parts.join(`\n${prefix}${sep.trim()} `);
129+};
130+
131+const formatNode = (input: unknown, depth: number): string => {
132+ const schema = asRecord(input);
133+ const prefix = INDENT.repeat(depth);
134+ const innerPrefix = INDENT.repeat(depth + 1);
135+
136+ // $ref
137+ if (typeof schema.$ref === "string") return refName(schema.$ref);
138+
139+ // const
140+ if ("const" in schema) return JSON.stringify(schema.const);
141+
142+ // enum
143+ const enumValues = Array.isArray(schema.enum) ? schema.enum : [];
144+ if (enumValues.length > 0) {
145+ const joined = enumValues.map((v) => JSON.stringify(v)).join(" | ");
146+ return joined.length < 80 ? joined : enumValues.map((v) => JSON.stringify(v)).join(`\n${prefix}| `);
147+ }
148+
149+ // composites
150+ const composite =
151+ compositeDecl("oneOf", schema, depth) ??
152+ compositeDecl("anyOf", schema, depth) ??
153+ compositeDecl("allOf", schema, depth);
154+ if (composite) return composite;
155+
156+ // array
157+ if (schema.type === "array") {
158+ const itemType = schema.items ? formatNode(schema.items, depth) : "unknown";
159+ if (itemType.includes("\n")) {
160+ return `Array<\n${innerPrefix}${itemType}\n${prefix}>`;
161+ }
162+ return `${itemType}[]`;
163+ }
164+
165+ // object
166+ if (schema.type === "object" || schema.properties) {
167+ const properties = asRecord(schema.properties);
168+ const keys = Object.keys(properties);
169+
170+ if (keys.length === 0) {
171+ return schema.additionalProperties ? "Record<string, unknown>" : "{}";
172+ }
173+
174+ const required = new Set(asStringArray(schema.required));
175+ const lines = keys.map((key) => {
176+ const propSchema = asRecord(properties[key]);
177+ const opt = required.has(key) ? "" : "?";
178+ const typeStr = formatNode(propSchema, depth + 1);
179+
180+ // Add description as comment if present
181+ const desc = typeof propSchema.description === "string" ? propSchema.description : null;
182+ const comment = desc ? `${innerPrefix}/** ${desc} */\n` : "";
183+
184+ if (typeStr.includes("\n")) {
185+ return `${comment}${innerPrefix}${key}${opt}: ${typeStr};`;
186+ }
187+ return `${comment}${innerPrefix}${key}${opt}: ${typeStr};`;
188+ });
189+
190+ return `{\n${lines.join("\n")}\n${prefix}}`;
191+ }
192+
193+ // union type array
194+ if (Array.isArray(schema.type)) return schema.type.join(" | ");
195+
196+ // primitive
197+ if (typeof schema.type === "string") {
198+ switch (schema.type) {
199+ case "string": return "string";
200+ case "number": case "integer": return "number";
201+ case "boolean": return "boolean";
202+ case "null": return "null";
203+ default: return schema.type;
204+ }
205+ }
206+
207+ return "unknown";
208+};
209+
210+/**
211+ * Convert a JSON Schema to a multi-line TypeScript-like type declaration.
212+ * Suitable for rendering in a code block with syntax highlighting.
213+ */
214+export const schemaToTypeDeclaration = (
215+ input: unknown,
216+ name?: string,
217+): string => {
218+ const body = formatNode(input, 0);
219+ if (name) {
220+ return `type ${name} = ${body}`;
221+ }
222+ return body;
223+};
apps/web/src/lib/source-favicon.ts+0−4
@@ -1,4 +0,0 @@
1−export {
2− getFallbackSourceFaviconUrl,
3− getSourceFaviconUrl,
4−} from "@executor/source-core";
apps/web/src/lib/use-scope.ts+1−0
@@ -0,0 +1 @@
1+export { useScope } from "@executor/react";
apps/web/src/lib/utils.ts+0−6
@@ -1,6 +0,0 @@
1−import { clsx, type ClassValue } from "clsx"
2−import { twMerge } from "tailwind-merge"
3−
4−export function cn(...inputs: ClassValue[]) {
5− return twMerge(clsx(inputs))
6−}
apps/web/src/main.tsx+6−137
@@ -1,138 +1,7 @@
1−import {
2− RouterProvider,
3− createRootRoute,
4− createRoute,
5− createRouter,
6− useNavigate,
7−} from "@tanstack/react-router";
8−import { ExecutorReactProvider } from "@executor/react";
9−import {
10− createExecutorPluginPaths,
11− sourcePluginsIndexPath,
12− type ExecutorPluginNavigation,
13− type FrontendPluginRouteSearch,
14−} from "@executor/react/plugins";
1+import React from "react";
2+import { createRoot } from "react-dom/client";
3+import "@executor/ui/globals.css";
4+import { App } from "./App";
155
16−import "./globals.css";
17−
18−import { AppShell } from "./components/shell";
19−import {
20− registeredFrontendPluginRoutes,
21−} from "./plugins";
22−import {
23− ExecutorPluginRoutePage,
24− SourcePluginsIndexPage,
25−} from "./plugins/pages";
26−import { HomePage } from "./views/home";
27−import { PoliciesPage } from "./views/policies";
28−import { SecretsPage } from "./views/secrets";
29−
30−const rootRoute = createRootRoute({
31− component: AppShell,
32−});
33−
34−const homeRoute = createRoute({
35− getParentRoute: () => rootRoute,
36− path: "/",
37− component: HomePage,
38−});
39−
40−const sourcePluginsIndexRoute = createRoute({
41− getParentRoute: () => rootRoute,
42− path: sourcePluginsIndexPath,
43− component: SourcePluginsIndexPage,
44−});
45−
46−const secretsRoute = createRoute({
47− getParentRoute: () => rootRoute,
48− path: "/secrets",
49− component: SecretsPage,
50−});
51−
52−const policiesRoute = createRoute({
53− getParentRoute: () => rootRoute,
54− path: "/policies",
55− component: PoliciesPage,
56−});
57−
58−const createExecutorPluginNavigation = (
59− pluginKey: string,
60− input: {
61− navigateTo: (
62− to: string,
63− search?: FrontendPluginRouteSearch,
64− ) => void | Promise<void>;
65− updateSearch?: (
66− search: FrontendPluginRouteSearch,
67− ) => void | Promise<void>;
68− },
69−): ExecutorPluginNavigation => {
70− const paths = createExecutorPluginPaths(pluginKey);
71−
72− return {
73− paths,
74− home: () => input.navigateTo("/"),
75− route: (path = "", search) => input.navigateTo(paths.route(path), search),
76− updateSearch: (search) => input.updateSearch?.(search),
77− };
78−};
79−
80−const frontendPluginRoutes = registeredFrontendPluginRoutes.map(({ plugin, route }) => {
81− const paths = createExecutorPluginPaths(plugin.key);
82−
83− const PluginRouteComponent = () => {
84− const params = pluginRoute.useParams() as Record<string, string | undefined>;
85− const search = pluginRoute.useSearch();
86− const navigate = useNavigate();
87− const navigateFromRoute = useNavigate({ from: pluginRoute.fullPath });
88− const navigation = createExecutorPluginNavigation(plugin.key, {
89− navigateTo: (to, nextSearch) =>
90− nextSearch === undefined ? navigate({ to }) : navigate({ to, search: nextSearch }),
91− updateSearch: (nextSearch) => navigateFromRoute({ search: nextSearch }),
92− });
93−
94− return (
95− <ExecutorPluginRoutePage
96− pluginKey={plugin.key}
97− routeKey={route.key}
98− params={params}
99− search={search}
100− navigation={navigation}
101− />
102− );
103− };
104−
105− const pluginRoute = createRoute({
106− getParentRoute: () => rootRoute,
107− path: paths.routePattern(route.path ?? ""),
108− component: PluginRouteComponent,
109− });
110−
111− return pluginRoute;
112−});
113−
114−const routeTree = rootRoute.addChildren([
115− homeRoute,
116− secretsRoute,
117− policiesRoute,
118− sourcePluginsIndexRoute,
119− ...frontendPluginRoutes,
120−]);
121−
122−const router = createRouter({
123− routeTree,
124− defaultPreload: "intent",
125− defaultPreloadStaleTime: 0,
126−});
127−
128−declare module "@tanstack/react-router" {
129− interface Register {
130− router: typeof router;
131− }
132−}
133−
134−export const App = () => (
135− <ExecutorReactProvider>
136− <RouterProvider router={router} />
137− </ExecutorReactProvider>
138−);
6+const root = createRoot(document.getElementById("root")!);
7+root.render(<App />);
apps/web/src/pages/secrets.tsx+391−0
@@ -0,0 +1,391 @@
1+import { useState, Suspense } from "react";
2+import {
3+ useAtomValue,
4+ useAtomSet,
5+ useAtomRefresh,
6+ Result,
7+ secretsAtom,
8+ setSecret,
9+ removeSecret,
10+} from "@executor/react";
11+import type { SecretProviderPlugin } from "@executor/react";
12+import { SecretId } from "@executor/sdk";
13+import { useScope } from "../lib/use-scope";
14+import { onePasswordSecretProviderPlugin } from "@executor/plugin-onepassword/react";
15+import {
16+ Dialog,
17+ DialogContent,
18+ DialogHeader,
19+ DialogTitle,
20+ DialogDescription,
21+ DialogFooter,
22+ DialogClose,
23+} from "@executor/ui/components/dialog";
24+import { Button } from "@executor/ui/components/button";
25+import { Input } from "@executor/ui/components/input";
26+import { Label } from "@executor/ui/components/label";
27+import { Badge } from "@executor/ui/components/badge";
28+import {
29+ DropdownMenu,
30+ DropdownMenuContent,
31+ DropdownMenuItem,
32+ DropdownMenuTrigger,
33+} from "@executor/ui/components/dropdown-menu";
34+import {
35+ Select,
36+ SelectContent,
37+ SelectItem,
38+ SelectTrigger,
39+ SelectValue,
40+} from "@executor/ui/components/select";
41+
42+// ---------------------------------------------------------------------------
43+// Add secret dialog
44+// ---------------------------------------------------------------------------
45+
46+function AddSecretDialog(props: { open: boolean; onOpenChange: (v: boolean) => void }) {
47+ const [id, setId] = useState("");
48+ const [name, setName] = useState("");
49+ const [value, setValue] = useState("");
50+ const [purpose, setPurpose] = useState("");
51+ const [provider, setProvider] = useState("auto");
52+ const [saving, setSaving] = useState(false);
53+ const [error, setError] = useState<string | null>(null);
54+
55+ const scopeId = useScope();
56+ const doSet = useAtomSet(setSecret, { mode: "promise" });
57+ const refresh = useAtomRefresh(secretsAtom(scopeId));
58+
59+ const reset = () => {
60+ setId("");
61+ setName("");
62+ setValue("");
63+ setPurpose("");
64+ setProvider("auto");
65+ setError(null);
66+ setSaving(false);
67+ };
68+
69+ const handleSave = async () => {
70+ if (!id.trim() || !name.trim() || !value.trim()) return;
71+ setSaving(true);
72+ setError(null);
73+ try {
74+ await doSet({
75+ path: { scopeId },
76+ payload: {
77+ id: SecretId.make(id.trim()),
78+ name: name.trim(),
79+ value: value.trim(),
80+ purpose: purpose.trim() || undefined,
81+ provider: provider === "auto" ? undefined : provider,
82+ },
83+ });
84+ reset();
85+ props.onOpenChange(false);
86+ refresh();
87+ } catch (e) {
88+ setError(e instanceof Error ? e.message : "Failed to save secret");
89+ setSaving(false);
90+ }
91+ };
92+
93+ return (
94+ <Dialog
95+ open={props.open}
96+ onOpenChange={(v) => {
97+ if (!v) reset();
98+ props.onOpenChange(v);
99+ }}
100+ >
101+ <DialogContent className="sm:max-w-[440px]">
102+ <DialogHeader>
103+ <DialogTitle className="font-display text-xl">New secret</DialogTitle>
104+ <DialogDescription className="text-[13px] leading-relaxed">
105+ Store a credential or API key. Values are kept in your system
106+ keychain when available, with a local encrypted file fallback.
107+ </DialogDescription>
108+ </DialogHeader>
109+
110+ <div className="grid gap-5 py-3">
111+ <div className="grid grid-cols-2 gap-3">
112+ <div className="grid gap-1.5">
113+ <Label htmlFor="secret-id" className="text-[11px] font-medium uppercase tracking-wider text-muted-foreground">
114+ ID
115+ </Label>
116+ <Input
117+ id="secret-id"
118+ placeholder="github-token"
119+ value={id}
120+ onChange={(e) => setId((e.target as HTMLInputElement).value)}
121+ className="font-mono text-[13px] h-9"
122+ />
123+ </div>
124+ <div className="grid gap-1.5">
125+ <Label htmlFor="secret-name" className="text-[11px] font-medium uppercase tracking-wider text-muted-foreground">
126+ Name
127+ </Label>
128+ <Input
129+ id="secret-name"
130+ placeholder="GitHub PAT"
131+ value={name}
132+ onChange={(e) => setName((e.target as HTMLInputElement).value)}
133+ className="text-[13px] h-9"
134+ />
135+ </div>
136+ </div>
137+
138+ <div className="grid gap-1.5">
139+ <Label htmlFor="secret-value" className="text-[11px] font-medium uppercase tracking-wider text-muted-foreground">
140+ Value
141+ </Label>
142+ <Input
143+ id="secret-value"
144+ type="password"
145+ placeholder="ghp_xxxxxxxxxxxxxxxxxxxx"
146+ value={value}
147+ onChange={(e) => setValue((e.target as HTMLInputElement).value)}
148+ className="font-mono text-[13px] h-9"
149+ />
150+ </div>
151+
152+ <div className="grid grid-cols-2 gap-3">
153+ <div className="grid gap-1.5">
154+ <Label htmlFor="secret-purpose" className="text-[11px] font-medium uppercase tracking-wider text-muted-foreground">
155+ Purpose <span className="normal-case tracking-normal font-normal text-muted-foreground/60">(opt.)</span>
156+ </Label>
157+ <Input
158+ id="secret-purpose"
159+ placeholder="GitHub API auth"
160+ value={purpose}
161+ onChange={(e) => setPurpose((e.target as HTMLInputElement).value)}
162+ className="text-[13px] h-9"
163+ />
164+ </div>
165+ <div className="grid gap-1.5">
166+ <Label htmlFor="secret-provider" className="text-[11px] font-medium uppercase tracking-wider text-muted-foreground">
167+ Storage
168+ </Label>
169+ <Select value={provider} onValueChange={setProvider}>
170+ <SelectTrigger id="secret-provider" className="h-9 text-[13px]">
171+ <SelectValue />
172+ </SelectTrigger>
173+ <SelectContent>
174+ <SelectItem value="auto">Auto</SelectItem>
175+ <SelectItem value="keychain">Keychain</SelectItem>
176+ <SelectItem value="file">File</SelectItem>
177+ </SelectContent>
178+ </Select>
179+ </div>
180+ </div>
181+
182+ {error && (
183+ <div className="rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2">
184+ <p className="text-[12px] text-destructive">{error}</p>
185+ </div>
186+ )}
187+ </div>
188+
189+ <DialogFooter>
190+ <DialogClose asChild>
191+ <Button variant="ghost" size="sm">Cancel</Button>
192+ </DialogClose>
193+ <Button
194+ size="sm"
195+ onClick={handleSave}
196+ disabled={!id.trim() || !name.trim() || !value.trim() || saving}
197+ >
198+ {saving ? "Saving…" : "Save secret"}
199+ </Button>
200+ </DialogFooter>
201+ </DialogContent>
202+ </Dialog>
203+ );
204+}
205+
206+// ---------------------------------------------------------------------------
207+// Secret row
208+// ---------------------------------------------------------------------------
209+
210+function SecretRow(props: {
211+ secret: { id: string; name: string; purpose?: string; provider?: string };
212+ onRemove: () => void;
213+}) {
214+ const { secret } = props;
215+
216+ return (
217+ <div className="group relative flex items-center gap-4 rounded-lg border border-border/60 bg-card px-4 py-3 transition-all hover:border-border hover:shadow-[0_1px_3px_rgba(0,0,0,0.04)]">
218+ {/* Content */}
219+ <div className="min-w-0 flex-1">
220+ <div className="flex items-center gap-2">
221+ <p className="text-[13px] font-medium text-foreground leading-none">{secret.name}</p>
222+ <span className="rounded bg-muted px-1.5 py-0.5 font-mono text-[10px] leading-none text-muted-foreground">
223+ {secret.id}
224+ </span>
225+ </div>
226+ {secret.purpose && (
227+ <p className="mt-1 text-[12px] text-muted-foreground/70 leading-none">{secret.purpose}</p>
228+ )}
229+ </div>
230+
231+ {/* Provider + actions */}
232+ <div className="flex items-center gap-1.5">
233+ {secret.provider && (
234+ <span className="rounded-full border border-border/60 px-2 py-0.5 text-[10px] font-medium text-muted-foreground leading-none">
235+ {secret.provider}
236+ </span>
237+ )}
238+ <DropdownMenu>
239+ <DropdownMenuTrigger asChild>
240+ <Button
241+ variant="ghost"
242+ size="icon"
243+ className="size-7 opacity-0 group-hover:opacity-100 transition-opacity"
244+ >
245+ <svg viewBox="0 0 16 16" className="size-3">
246+ <circle cx="8" cy="3" r="1.2" fill="currentColor" />
247+ <circle cx="8" cy="8" r="1.2" fill="currentColor" />
248+ <circle cx="8" cy="13" r="1.2" fill="currentColor" />
249+ </svg>
250+ </Button>
251+ </DropdownMenuTrigger>
252+ <DropdownMenuContent align="end" className="w-40">
253+ <DropdownMenuItem
254+ className="text-destructive focus:text-destructive text-[12px]"
255+ onClick={props.onRemove}
256+ >
257+ Remove secret
258+ </DropdownMenuItem>
259+ </DropdownMenuContent>
260+ </DropdownMenu>
261+ </div>
262+ </div>
263+ );
264+}
265+
266+// ---------------------------------------------------------------------------
267+// Secret provider plugins
268+// ---------------------------------------------------------------------------
269+
270+const secretProviderPlugins: SecretProviderPlugin[] = [
271+ onePasswordSecretProviderPlugin,
272+];
273+
274+// ---------------------------------------------------------------------------
275+// Page
276+// ---------------------------------------------------------------------------
277+
278+export function SecretsPage() {
279+ const [addOpen, setAddOpen] = useState(false);
280+ const scopeId = useScope();
281+ const secrets = useAtomValue(secretsAtom(scopeId));
282+ const doRemove = useAtomSet(removeSecret, { mode: "promise" });
283+ const refresh = useAtomRefresh(secretsAtom(scopeId));
284+
285+ const handleRemove = async (secretId: string) => {
286+ try {
287+ await doRemove({
288+ path: {
289+ scopeId,
290+ secretId: SecretId.make(secretId),
291+ },
292+ });
293+ refresh();
294+ } catch {
295+ // TODO: toast
296+ }
297+ };
298+
299+ return (
300+ <div className="min-h-0 flex-1 overflow-y-auto">
301+ <div className="mx-auto max-w-3xl px-6 py-10 lg:px-8 lg:py-14">
302+ {/* Header */}
303+ <div className="flex items-end justify-between mb-10">
304+ <div>
305+ <h1 className="font-display text-[2rem] tracking-tight text-foreground leading-none">
306+ Secrets
307+ </h1>
308+ <p className="mt-2 text-[13px] text-muted-foreground leading-relaxed">
309+ Credentials and API keys used by your connected sources.
310+ </p>
311+ </div>
312+ <Button size="sm" onClick={() => setAddOpen(true)}>
313+ Add secret
314+ </Button>
315+ </div>
316+
317+ {/* Provider plugins */}
318+ {secretProviderPlugins.length > 0 && (
319+ <div className="mb-10">
320+ <div className="flex items-center gap-3 mb-4">
321+ <h2 className="text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground/60">
322+ Providers
323+ </h2>
324+ <div className="flex-1 h-px bg-border/50" />
325+ </div>
326+ <div className="grid gap-3">
327+ {secretProviderPlugins.map((plugin) => (
328+ <Suspense
329+ key={plugin.key}
330+ fallback={
331+ <div className="rounded-xl border border-border/60 bg-card p-5 animate-pulse">
332+ <div className="h-4 w-24 rounded bg-muted" />
333+ </div>
334+ }
335+ >
336+ <plugin.settings />
337+ </Suspense>
338+ ))}
339+ </div>
340+ </div>
341+ )}
342+
343+ {/* Secrets list */}
344+ {Result.match(secrets, {
345+ onInitial: () => (
346+ <div className="flex items-center gap-2 py-8">
347+ <div className="size-1.5 rounded-full bg-muted-foreground/30 animate-pulse" />
348+ <p className="text-[13px] text-muted-foreground/60">Loading secrets…</p>
349+ </div>
350+ ),
351+ onFailure: () => (
352+ <div className="rounded-lg border border-destructive/30 bg-destructive/5 px-4 py-3">
353+ <p className="text-[13px] text-destructive">Failed to load secrets</p>
354+ </div>
355+ ),
356+ onSuccess: ({ value }) =>
357+ value.length === 0 ? (
358+ <div className="flex flex-col items-center justify-center rounded-xl border border-dashed border-border/70 py-16">
359+ <p className="text-[13px] font-medium text-foreground/60 mb-1">
360+ No secrets yet
361+ </p>
362+ <p className="text-[12px] text-muted-foreground/50 mb-5 max-w-[240px] text-center leading-relaxed">
363+ Add API keys and credentials to authenticate your sources.
364+ </p>
365+ <Button variant="outline" size="sm" onClick={() => setAddOpen(true)}>
366+ Add your first secret
367+ </Button>
368+ </div>
369+ ) : (
370+ <div className="grid gap-1.5">
371+ {value.map((s) => (
372+ <SecretRow
373+ key={s.id}
374+ secret={{
375+ id: s.id,
376+ name: s.name,
377+ purpose: s.purpose,
378+ provider: s.provider ? String(s.provider) : undefined,
379+ }}
380+ onRemove={() => handleRemove(s.id)}
381+ />
382+ ))}
383+ </div>
384+ ),
385+ })}
386+
387+ <AddSecretDialog open={addOpen} onOpenChange={setAddOpen} />
388+ </div>
389+ </div>
390+ );
391+}
apps/web/src/pages/source-detail.tsx+195−0
@@ -0,0 +1,195 @@
1+import { useEffect, useMemo, useState } from "react";
2+import { useNavigate } from "@tanstack/react-router";
3+import {
4+ useAtomValue,
5+ useAtomSet,
6+ useAtomRefresh,
7+ sourceToolsAtom,
8+ sourcesAtom,
9+ sourceAtom,
10+ removeSource,
11+ refreshSource,
12+ Result,
13+} from "@executor/react";
14+import { ToolTree } from "../components/tool-tree";
15+import { ToolDetail, ToolDetailEmpty } from "../components/tool-detail";
16+import type { ToolSummary } from "../components/tool-tree";
17+import { useScope } from "../lib/use-scope";
18+
19+export function SourceDetailPage(props: { namespace: string }) {
20+ const { namespace } = props;
21+ const scopeId = useScope();
22+ const source = useAtomValue(sourceAtom(namespace, scopeId));
23+ const tools = useAtomValue(sourceToolsAtom(namespace, scopeId));
24+ const refreshSources = useAtomRefresh(sourcesAtom(scopeId));
25+ const refreshTools = useAtomRefresh(sourceToolsAtom(namespace, scopeId));
26+ const doRemove = useAtomSet(removeSource, { mode: "promise" });
27+ const doRefresh = useAtomSet(refreshSource, { mode: "promise" });
28+ const navigate = useNavigate();
29+
30+ // HMR: refresh source tools when the backend is hot-reloaded
31+ useEffect(() => {
32+ if (!import.meta.hot) return;
33+ const refresh = () => { refreshTools(); refreshSources(); };
34+ import.meta.hot.on("executor:backend-updated", refresh);
35+ return () => { import.meta.hot?.off("executor:backend-updated", refresh); };
36+ }, [refreshTools, refreshSources]);
37+
38+ const [selectedToolId, setSelectedToolId] = useState<string | null>(null);
39+ const [confirmDelete, setConfirmDelete] = useState(false);
40+ const [deleting, setDeleting] = useState(false);
41+ const [refreshing, setRefreshing] = useState(false);
42+
43+ const sourceData = Result.isSuccess(source) ? source.value : null;
44+ const canRefresh = sourceData ? (sourceData.canRefresh ?? true) : false;
45+ const canRemove = sourceData ? (sourceData.canRemove ?? true) : false;
46+
47+ const sourceTools: ToolSummary[] = useMemo(() => {
48+ if (!Result.isSuccess(tools)) return [];
49+ return tools.value.map((t) => ({
50+ id: t.id,
51+ name: t.name,
52+ pluginKey: t.pluginKey,
53+ description: t.description,
54+ }));
55+ }, [tools]);
56+
57+ const selectedTool = useMemo(
58+ () => sourceTools.find((t) => t.id === selectedToolId) ?? null,
59+ [sourceTools, selectedToolId],
60+ );
61+
62+ const handleDelete = async () => {
63+ setDeleting(true);
64+ try {
65+ await doRemove({
66+ path: { scopeId, sourceId: namespace },
67+ });
68+ refreshSources();
69+ void navigate({ to: "/" });
70+ } catch {
71+ setDeleting(false);
72+ setConfirmDelete(false);
73+ }
74+ };
75+
76+ const handleRefresh = async () => {
77+ setRefreshing(true);
78+ try {
79+ await doRefresh({
80+ path: { scopeId, sourceId: namespace },
81+ });
82+ refreshTools();
83+ refreshSources();
84+ } finally {
85+ setRefreshing(false);
86+ }
87+ };
88+
89+ return (
90+ <div className="flex min-h-0 flex-1 flex-col overflow-hidden">
91+ {/* Header bar */}
92+ <div className="flex h-12 shrink-0 items-center justify-between border-b border-border bg-background/95 px-4 backdrop-blur-sm">
93+ <div className="flex min-w-0 items-center gap-3">
94+ <h2 className="truncate text-sm font-semibold text-foreground">
95+ {sourceData?.name ?? namespace}
96+ </h2>
97+ {sourceData?.runtime && (
98+ <span className="rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
99+ built-in
100+ </span>
101+ )}
102+ <span className="rounded bg-secondary px-1.5 py-0.5 text-[10px] font-medium text-secondary-foreground">
103+ {sourceData?.kind ?? "source"}
104+ </span>
105+ {Result.isSuccess(tools) && (
106+ <span className="hidden text-[11px] tabular-nums text-muted-foreground/50 sm:block">
107+ {sourceTools.length} {sourceTools.length === 1 ? "tool" : "tools"}
108+ </span>
109+ )}
110+ </div>
111+
112+ <div className="flex shrink-0 items-center gap-2">
113+ {canRefresh && (
114+ <button
115+ type="button"
116+ onClick={() => void handleRefresh()}
117+ disabled={refreshing}
118+ className="inline-flex items-center gap-1.5 rounded-md border border-border bg-background px-2.5 py-1 text-[12px] font-medium text-foreground transition-colors hover:bg-accent disabled:opacity-50"
119+ >
120+ {refreshing ? "Refreshing…" : "Refresh"}
121+ </button>
122+ )}
123+
124+ {canRemove && (confirmDelete ? (
125+ <div className="flex items-center gap-2">
126+ <span className="text-[11px] font-medium text-destructive">
127+ Confirm?
128+ </span>
129+ <button
130+ type="button"
131+ onClick={() => setConfirmDelete(false)}
132+ disabled={deleting}
133+ className="inline-flex items-center rounded-md border border-border bg-background px-2.5 py-1 text-[12px] font-medium text-foreground transition-colors hover:bg-accent disabled:opacity-50"
134+ >
135+ Cancel
136+ </button>
137+ <button
138+ type="button"
139+ onClick={() => void handleDelete()}
140+ disabled={deleting}
141+ className="inline-flex items-center rounded-md border border-destructive/30 bg-destructive/10 px-2.5 py-1 text-[12px] font-medium text-destructive transition-colors hover:bg-destructive/20 disabled:opacity-50"
142+ >
143+ {deleting ? "Deleting…" : "Delete"}
144+ </button>
145+ </div>
146+ ) : (
147+ <button
148+ type="button"
149+ onClick={() => setConfirmDelete(true)}
150+ className="inline-flex items-center rounded-md border border-destructive/30 bg-background px-2.5 py-1 text-[12px] font-medium text-destructive transition-colors hover:bg-destructive/10"
151+ >
152+ Delete
153+ </button>
154+ ))}
155+ </div>
156+ </div>
157+
158+ {/* Content — split pane */}
159+ {Result.match(tools, {
160+ onInitial: () => (
161+ <div className="p-6 text-sm text-muted-foreground">Loading…</div>
162+ ),
163+ onFailure: () => (
164+ <div className="p-6 text-sm text-destructive">Failed to load tools</div>
165+ ),
166+ onSuccess: () => (
167+ <div className="flex min-h-0 flex-1 overflow-hidden">
168+ {/* Left: tool tree */}
169+ <div className="flex w-72 shrink-0 flex-col border-r border-border bg-card/30 lg:w-80 xl:w-[22rem]">
170+ <ToolTree
171+ tools={sourceTools}
172+ selectedToolId={selectedToolId}
173+ onSelect={setSelectedToolId}
174+ />
175+ </div>
176+
177+ {/* Right: tool detail */}
178+ <div className="flex min-w-0 flex-1 flex-col overflow-hidden">
179+ {selectedTool ? (
180+ <ToolDetail
181+ toolId={selectedTool.id}
182+ toolName={selectedTool.name}
183+ toolDescription={selectedTool.description}
184+ scopeId={scopeId}
185+ />
186+ ) : (
187+ <ToolDetailEmpty hasTools={sourceTools.length > 0} />
188+ )}
189+ </div>
190+ </div>
191+ ),
192+ })}
193+ </div>
194+ );
195+}
apps/web/src/pages/sources.tsx+377−0
@@ -0,0 +1,377 @@
1+import { useReducer, useCallback, useMemo, Suspense } from "react";
2+import { Link } from "@tanstack/react-router";
3+import { Result, useAtomValue, useAtomRefresh, useAtomSet, sourcesAtom, detectSource } from "@executor/react";
4+import { useScope } from "../lib/use-scope";
5+import type { SourcePlugin, SourcePreset } from "@executor/react";
6+import { openApiSourcePlugin } from "@executor/plugin-openapi/react";
7+import { mcpSourcePlugin } from "@executor/plugin-mcp/react";
8+import { googleDiscoverySourcePlugin } from "@executor/plugin-google-discovery/react";
9+import { graphqlSourcePlugin } from "@executor/plugin-graphql/react";
10+import { McpInstallCard } from "../components/mcp-install-card";
11+
12+// ---------------------------------------------------------------------------
13+// Registered source plugins
14+// ---------------------------------------------------------------------------
15+
16+const sourcePlugins: SourcePlugin[] = [
17+ openApiSourcePlugin,
18+ mcpSourcePlugin,
19+ googleDiscoverySourcePlugin,
20+ graphqlSourcePlugin,
21+];
22+
23+const KIND_TO_PLUGIN_KEY: Record<string, string> = {
24+ openapi: "openapi",
25+ mcp: "mcp",
26+ graphql: "graphql",
27+ googleDiscovery: "googleDiscovery",
28+};
29+
30+// ---------------------------------------------------------------------------
31+// State machine
32+// ---------------------------------------------------------------------------
33+
34+type State = {
35+ step: "list" | "detecting" | "adding";
36+ url: string;
37+ error: string | null;
38+ pluginKey: string | null;
39+ initialUrl: string | undefined;
40+};
41+
42+type Action =
43+ | { type: "set-url"; url: string }
44+ | { type: "detect-start" }
45+ | { type: "detect-ok"; pluginKey: string; url: string }
46+ | { type: "detect-no-match" }
47+ | { type: "detect-unknown-kind"; kind: string }
48+ | { type: "detect-fail" }
49+ | { type: "add-manual"; pluginKey: string }
50+ | { type: "add-preset"; pluginKey: string; url: string }
51+ | { type: "back" };
52+
53+const init: State = { step: "list", url: "", error: null, pluginKey: null, initialUrl: undefined };
54+
55+function reducer(state: State, action: Action): State {
56+ switch (action.type) {
57+ case "set-url":
58+ return { ...state, step: "list", url: action.url, error: null };
59+ case "detect-start":
60+ return { ...state, step: "detecting", error: null };
61+ case "detect-ok":
62+ return { ...state, step: "adding", pluginKey: action.pluginKey, initialUrl: action.url };
63+ case "detect-no-match":
64+ return { ...state, step: "list", error: "Could not detect a source type from this URL. Try adding manually." };
65+ case "detect-unknown-kind":
66+ return { ...state, step: "list", error: `Detected source type "${action.kind}" but no plugin is available for it.` };
67+ case "detect-fail":
68+ return { ...state, step: "list", error: "Detection failed. Try adding a source manually." };
69+ case "add-manual":
70+ return { ...state, step: "adding", pluginKey: action.pluginKey, initialUrl: undefined };
71+ case "add-preset":
72+ return { ...state, step: "adding", pluginKey: action.pluginKey, initialUrl: action.url };
73+ case "back":
74+ return init;
75+ default:
76+ return state;
77+ }
78+}
79+
80+// ---------------------------------------------------------------------------
81+// Page
82+// ---------------------------------------------------------------------------
83+
84+export function SourcesPage() {
85+ const [state, dispatch] = useReducer(reducer, init);
86+ const scopeId = useScope();
87+ const sources = useAtomValue(sourcesAtom(scopeId));
88+ const refreshSources = useAtomRefresh(sourcesAtom(scopeId));
89+ const doDetect = useAtomSet(detectSource, { mode: "promise" });
90+
91+ const handleDetect = useCallback(async () => {
92+ const trimmed = state.url.trim();
93+ if (!trimmed) return;
94+ dispatch({ type: "detect-start" });
95+ try {
96+ const results = await doDetect({
97+ path: { scopeId },
98+ payload: { url: trimmed },
99+ });
100+ if (results.length === 0) {
101+ dispatch({ type: "detect-no-match" });
102+ return;
103+ }
104+ const pluginKey = KIND_TO_PLUGIN_KEY[results[0].kind];
105+ if (pluginKey) {
106+ dispatch({ type: "detect-ok", pluginKey, url: trimmed });
107+ } else {
108+ dispatch({ type: "detect-unknown-kind", kind: results[0].kind });
109+ }
110+ } catch {
111+ dispatch({ type: "detect-fail" });
112+ }
113+ }, [state.url, doDetect]);
114+
115+ // ---------------------------------------------------------------------------
116+ // Adding view
117+ // ---------------------------------------------------------------------------
118+
119+ if (state.step === "adding" && state.pluginKey) {
120+ const plugin = sourcePlugins.find((p) => p.key === state.pluginKey);
121+ if (!plugin) return null;
122+ const AddComponent = plugin.add;
123+ return (
124+ <div className="min-h-0 flex-1 overflow-y-auto">
125+ <div className="mx-auto max-w-4xl px-6 py-10 lg:px-10 lg:py-14">
126+ <Suspense fallback={<p className="text-sm text-muted-foreground">Loading…</p>}>
127+ <AddComponent
128+ initialUrl={state.initialUrl}
129+ onComplete={() => {
130+ dispatch({ type: "back" });
131+ refreshSources();
132+ }}
133+ onCancel={() => dispatch({ type: "back" })}
134+ />
135+ </Suspense>
136+ </div>
137+ </div>
138+ );
139+ }
140+
141+ // ---------------------------------------------------------------------------
142+ // List view
143+ // ---------------------------------------------------------------------------
144+
145+ const isDetecting = state.step === "detecting";
146+ const error = state.step === "list" ? state.error : null;
147+
148+ return (
149+ <div className="min-h-0 flex-1 overflow-y-auto">
150+ <div className="mx-auto max-w-4xl px-6 py-10 lg:px-10 lg:py-14">
151+ {/* Header */}
152+ <div className="mb-8">
153+ <div className="flex items-end justify-between">
154+ <div>
155+ <h1 className="font-display text-3xl tracking-tight text-foreground lg:text-4xl">
156+ Sources
157+ </h1>
158+ <p className="mt-1.5 text-[14px] text-muted-foreground">
159+ Tool providers available in this workspace.
160+ </p>
161+ </div>
162+ </div>
163+
164+ {/* URL detection input */}
165+ <div className="mt-5">
166+ <div className="flex gap-2">
167+ <input
168+ type="url"
169+ value={state.url}
170+ onChange={(e) => dispatch({ type: "set-url", url: e.target.value })}
171+ onKeyDown={(e) => { if (e.key === "Enter") handleDetect(); }}
172+ placeholder="Paste a URL to auto-detect source type..."
173+ disabled={isDetecting}
174+ className="flex-1 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50"
175+ />
176+ <button
177+ onClick={handleDetect}
178+ disabled={isDetecting || !state.url.trim()}
179+ className="inline-flex items-center gap-1.5 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:opacity-50 disabled:pointer-events-none"
180+ >
181+ {isDetecting ? "Detecting..." : "Detect"}
182+ </button>
183+ </div>
184+ {error && (
185+ <p className="mt-2 text-sm text-destructive">{error}</p>
186+ )}
187+ <div className="mt-3 flex items-center gap-2 text-xs text-muted-foreground">
188+ <span>Or add manually:</span>
189+ {sourcePlugins.map((p) => (
190+ <button
191+ key={p.key}
192+ onClick={() => dispatch({ type: "add-manual", pluginKey: p.key })}
193+ className="rounded-md border border-border px-2 py-1 text-xs font-medium transition-colors hover:bg-muted"
194+ >
195+ {p.label}
196+ </button>
197+ ))}
198+ </div>
199+ </div>
200+ </div>
201+
202+ <McpInstallCard className="mb-8 rounded-2xl border border-border bg-card/80 p-5" />
203+
204+ <PresetGrid plugins={sourcePlugins} dispatch={dispatch} />
205+
206+ {Result.match(sources, {
207+ onInitial: () => (
208+ <p className="text-sm text-muted-foreground">Loading…</p>
209+ ),
210+ onFailure: () => (
211+ <p className="text-sm text-destructive">Failed to load sources</p>
212+ ),
213+ onSuccess: ({ value }) => {
214+ const builtInSources = value.filter((source) => source.runtime);
215+ const connectedSources = value.filter((source) => !source.runtime);
216+
217+ return value.length === 0 ? (
218+ <div className="flex flex-col items-center justify-center rounded-2xl border border-dashed border-border py-20">
219+ <div className="flex size-12 items-center justify-center rounded-2xl bg-muted text-muted-foreground mb-4">
220+ <svg viewBox="0 0 24 24" fill="none" className="size-5">
221+ <path d="M12 6v12M6 12h12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
222+ </svg>
223+ </div>
224+ <p className="text-[14px] font-medium text-foreground/70 mb-1">
225+ No sources yet
226+ </p>
227+ <p className="text-[13px] text-muted-foreground/60 mb-5">
228+ Add a source to get started.
229+ </p>
230+ </div>
231+ ) : (
232+ <div className="space-y-8">
233+ {builtInSources.length > 0 && (
234+ <section className="space-y-3">
235+ <div>
236+ <h2 className="text-sm font-semibold text-foreground">
237+ Built-in
238+ </h2>
239+ <p className="mt-1 text-[13px] text-muted-foreground">
240+ Runtime sources exposed by the loaded executor plugins.
241+ </p>
242+ </div>
243+ <SourceGrid sources={builtInSources} />
244+ </section>
245+ )}
246+
247+ {connectedSources.length > 0 && (
248+ <section className="space-y-3">
249+ <div>
250+ <h2 className="text-sm font-semibold text-foreground">
251+ Connected
252+ </h2>
253+ <p className="mt-1 text-[13px] text-muted-foreground">
254+ User-configured sources available in this workspace.
255+ </p>
256+ </div>
257+ <SourceGrid sources={connectedSources} />
258+ </section>
259+ )}
260+ </div>
261+ );
262+ },
263+ })}
264+ </div>
265+ </div>
266+ );
267+}
268+
269+// ---------------------------------------------------------------------------
270+// Preset grid
271+// ---------------------------------------------------------------------------
272+
273+function PresetGrid(props: {
274+ plugins: readonly SourcePlugin[];
275+ dispatch: React.Dispatch<Action>;
276+}) {
277+ const allPresets = useMemo(() => {
278+ const out: { preset: SourcePreset; pluginKey: string; pluginLabel: string }[] = [];
279+ for (const plugin of props.plugins) {
280+ for (const preset of plugin.presets ?? []) {
281+ out.push({ preset, pluginKey: plugin.key, pluginLabel: plugin.label });
282+ }
283+ }
284+ return out;
285+ }, [props.plugins]);
286+
287+ if (allPresets.length === 0) return null;
288+
289+ return (
290+ <section className="mb-8 space-y-3">
291+ <div>
292+ <h2 className="text-sm font-semibold text-foreground">Presets</h2>
293+ <p className="mt-1 text-[13px] text-muted-foreground">
294+ One-click setup for common APIs and services.
295+ </p>
296+ </div>
297+ <div className="grid gap-2 sm:grid-cols-2 lg:grid-cols-3">
298+ {allPresets.map(({ preset, pluginKey, pluginLabel }) => (
299+ <button
300+ key={`${pluginKey}-${preset.id}`}
301+ onClick={() => props.dispatch({ type: "add-preset", pluginKey, url: preset.url })}
302+ className="flex items-start gap-3 rounded-xl border border-border bg-card px-4 py-3 text-left transition-colors hover:border-primary/25 hover:bg-card/90"
303+ >
304+ <div className="flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground overflow-hidden">
305+ {preset.icon ? (
306+ <img src={preset.icon} alt="" className="size-5 object-contain" loading="lazy" />
307+ ) : (
308+ <svg viewBox="0 0 16 16" className="size-3.5" fill="none">
309+ <circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.2" />
310+ </svg>
311+ )}
312+ </div>
313+ <div className="min-w-0 flex-1">
314+ <div className="flex items-center gap-2">
315+ <span className="truncate text-sm font-medium text-foreground">{preset.name}</span>
316+ <span className="shrink-0 rounded bg-secondary px-1.5 py-0.5 text-[10px] font-medium text-secondary-foreground">
317+ {pluginLabel}
318+ </span>
319+ </div>
320+ <p className="mt-0.5 text-xs text-muted-foreground line-clamp-1">{preset.summary}</p>
321+ </div>
322+ </button>
323+ ))}
324+ </div>
325+ </section>
326+ );
327+}
328+
329+// ---------------------------------------------------------------------------
330+// Source grid
331+// ---------------------------------------------------------------------------
332+
333+function SourceGrid(props: {
334+ sources: readonly { id: string; name: string; kind: string; runtime?: boolean }[];
335+}) {
336+ return (
337+ <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
338+ {props.sources.map((s) => (
339+ <Link
340+ key={s.id}
341+ to="/sources/$namespace"
342+ params={{ namespace: s.id }}
343+ className="flex h-full flex-col rounded-2xl border border-border bg-card px-5 py-4 transition-colors hover:border-primary/25 hover:bg-card/90"
344+ >
345+ <div className="flex items-start gap-3">
346+ <div className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground">
347+ <svg viewBox="0 0 16 16" className="size-4">
348+ <circle cx="8" cy="8" r="6" fill="none" stroke="currentColor" strokeWidth="1.2" />
349+ <path d="M8 5v6M5 8h6" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
350+ </svg>
351+ </div>
352+ <div className="min-w-0 flex-1">
353+ <div className="flex items-start justify-between gap-2">
354+ <div className="truncate text-sm font-semibold text-foreground">
355+ {s.name}
356+ </div>
357+ <div className="flex shrink-0 items-center gap-1.5">
358+ {s.runtime && (
359+ <span className="rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
360+ built-in
361+ </span>
362+ )}
363+ <span className="rounded bg-secondary px-1.5 py-0.5 text-[10px] font-medium text-secondary-foreground">
364+ {s.kind}
365+ </span>
366+ </div>
367+ </div>
368+ <div className="mt-0.5 text-xs text-muted-foreground">
369+ {s.id}
370+ </div>
371+ </div>
372+ </div>
373+ </Link>
374+ ))}
375+ </div>
376+ );
377+}
apps/web/src/pages/tools.tsx+73−0
@@ -0,0 +1,73 @@
1+import { useAtomValue, Result, toolsAtom } from "@executor/react";
2+import { useScope } from "../lib/use-scope";
3+
4+export function ToolsPage() {
5+ const scopeId = useScope();
6+ const tools = useAtomValue(toolsAtom(scopeId));
7+
8+ return (
9+ <div className="min-h-0 flex-1 overflow-y-auto">
10+ <div className="mx-auto max-w-4xl px-6 py-10 lg:px-10 lg:py-14">
11+ {/* Header */}
12+ <div className="flex items-end justify-between mb-8">
13+ <div>
14+ <h1 className="font-display text-3xl tracking-tight text-foreground lg:text-4xl">
15+ Tools
16+ </h1>
17+ <p className="mt-1.5 text-[14px] text-muted-foreground">
18+ All registered tools across your connected sources.
19+ </p>
20+ </div>
21+ </div>
22+
23+ {Result.match(tools, {
24+ onInitial: () => (
25+ <p className="text-sm text-muted-foreground">Loading tools…</p>
26+ ),
27+ onFailure: () => (
28+ <p className="text-sm text-destructive">Failed to load tools</p>
29+ ),
30+ onSuccess: ({ value }) =>
31+ value.length === 0 ? (
32+ <div className="flex flex-col items-center justify-center rounded-2xl border border-dashed border-border py-20">
33+ <div className="flex size-12 items-center justify-center rounded-2xl bg-muted text-muted-foreground mb-4">
34+ <svg viewBox="0 0 16 16" className="size-5">
35+ <path d="M4 2h8l1 3H3l1-3zM3 6h10v8H3V6z" fill="none" stroke="currentColor" strokeWidth="1.2" />
36+ </svg>
37+ </div>
38+ <p className="text-[14px] font-medium text-foreground/70 mb-1">
39+ No tools registered
40+ </p>
41+ <p className="text-[13px] text-muted-foreground/60">
42+ Add a source to start discovering tools.
43+ </p>
44+ </div>
45+ ) : (
46+ <div className="grid gap-2">
47+ {value.map((t) => (
48+ <div
49+ key={t.id}
50+ className="flex items-start justify-between gap-3 rounded-xl border border-border bg-card px-5 py-3.5 transition-colors hover:border-primary/25 hover:bg-card/90"
51+ >
52+ <div className="min-w-0 flex-1">
53+ <p className="text-sm font-semibold text-foreground truncate font-mono">
54+ {t.name}
55+ </p>
56+ {t.description && (
57+ <p className="mt-0.5 text-xs text-muted-foreground line-clamp-2">
58+ {t.description}
59+ </p>
60+ )}
61+ </div>
62+ <span className="shrink-0 rounded bg-secondary px-1.5 py-0.5 text-[10px] font-medium text-secondary-foreground">
63+ {t.sourceId}
64+ </span>
65+ </div>
66+ ))}
67+ </div>
68+ ),
69+ })}
70+ </div>
71+ </div>
72+ );
73+}
apps/web/src/plugins/index.ts+0−96
@@ -1,96 +0,0 @@
1−import type {
2− Source,
3−} from "@executor/react";
4−import {
5− ExecutionHistoryReactPlugin,
6−} from "@executor/plugin-execution-history-react";
7−import {
8− GoogleDiscoveryReactPlugin,
9− getGoogleDiscoveryIconUrl,
10−} from "@executor/plugin-google-discovery-react";
11−import {
12− GraphqlReactPlugin,
13−} from "@executor/plugin-graphql-react";
14−import {
15− McpReactPlugin,
16−} from "@executor/plugin-mcp-react";
17−import {
18− OpenApiReactPlugin,
19−} from "@executor/plugin-openapi-react";
20−import {
21− createExecutorPluginPaths,
22− createSourcePluginPaths,
23− registerExecutorFrontendPlugins,
24− type ExecutorFrontendPlugin,
25−} from "@executor/react/plugins";
26−import { getFallbackSourceFaviconUrl } from "../lib/source-favicon";
27−
28−const frontendPlugins = [
29− ExecutionHistoryReactPlugin,
30− McpReactPlugin,
31− GraphqlReactPlugin,
32− GoogleDiscoveryReactPlugin,
33− OpenApiReactPlugin,
34−] as const satisfies readonly ExecutorFrontendPlugin[];
35−
36−const frontendPluginRegistry = registerExecutorFrontendPlugins(frontendPlugins);
37−
38−const hasRouteKey = (
39− plugin: ExecutorFrontendPlugin,
40− routeKey: string,
41−): boolean =>
42− (plugin.routes ?? []).some((route) => route.key === routeKey);
43−
44−const isSourceFrontendPlugin = (
45− plugin: ExecutorFrontendPlugin,
46−): boolean =>
47− hasRouteKey(plugin, "add")
48− && hasRouteKey(plugin, "detail");
49−
50−export const registeredFrontendPlugins = frontendPluginRegistry.plugins;
51−export const registeredFrontendPluginRoutes = frontendPluginRegistry.routes;
52−export const registeredFrontendPluginNavRoutes =
53− registeredFrontendPluginRoutes
54− .filter(({ route }) => route.nav !== undefined)
55− .map(({ plugin, route }) => ({
56− plugin,
57− route,
58− to: createExecutorPluginPaths(plugin.key).route(route.path ?? ""),
59− }));
60−export const registeredSourceFrontendPlugins =
61− registeredFrontendPlugins.filter(isSourceFrontendPlugin);
62−
63−export const getFrontendPlugin = (key: string) =>
64− frontendPluginRegistry.getPlugin(key);
65−
66−export const getFrontendPluginRoute = (
67− pluginKey: string,
68− routeKey: string,
69−) => frontendPluginRegistry.getRoute(pluginKey, routeKey);
70−
71−const resolveSourcePluginKey = (kind: string): string =>
72− isGoogleDiscoverySource(kind) ? "google-discovery" : kind;
73−
74−export const getSourceFrontendPlugin = (kind: string) => {
75− const plugin = getFrontendPlugin(resolveSourcePluginKey(kind));
76− return plugin && isSourceFrontendPlugin(plugin) ? plugin : null;
77−};
78−
79−export const getSourceFrontendPaths = (kind: string) => {
80− const plugin = getSourceFrontendPlugin(kind);
81− return plugin ? createSourcePluginPaths(plugin.key) : null;
82−};
83−
84−const isGoogleDiscoverySource = (kind: string): boolean =>
85− kind === "google_discovery"
86− || kind === "google-discovery";
87−
88−export const getSourceFrontendIconUrl = (source: Source) =>
89− source.iconUrl
90− ?? (isGoogleDiscoverySource(source.kind)
91− ? getGoogleDiscoveryIconUrl(source)
92− : null)
93− ?? getFallbackSourceFaviconUrl(source);
94−
95−export const getSecretStoreFrontendPlugin = (kind: string) =>
96− registeredFrontendPlugins.find((plugin) => plugin.secretStore?.kind === kind) ?? null;
apps/web/src/plugins/pages.tsx+0−260
@@ -1,260 +0,0 @@
1−import { useState, type FormEvent } from "react";
2−import { Link, useNavigate } from "@tanstack/react-router";
3−import {
4− Alert,
5− Button,
6− Card,
7− Input,
8− ExecutorPluginRouteProvider,
9− createSourcePluginPaths,
10− type ExecutorPluginNavigation,
11− type FrontendPluginRouteDefinition,
12− type FrontendPluginRouteParams,
13− type FrontendPluginRouteSearch,
14−} from "@executor/react/plugins";
15−
16−import { SourcePresetFavicon } from "../components/source-favicon";
17−import { LocalMcpInstallCard } from "../components/local-mcp-install-card";
18−import { SourcePluginsResetState } from "../components/source-plugins-reset-state";
19−import {
20− getFrontendPlugin,
21− getFrontendPluginRoute,
22− registeredSourceFrontendPlugins,
23−} from "./index";
24−import {
25− buildSourcePresetSearch,
26− resolveQuickSourceInput,
27− sourcePresets,
28−} from "./source-presets";
29−
30−const FrontendPluginUnavailableState = () => (
31− <SourcePluginsResetState
32− title="Plugins unavailable"
33− message="No plugins are available in this build."
34− />
35−);
36−
37−const SourcePluginUnavailableState = () => (
38− <SourcePluginsResetState
39− title="No source plugins available"
40− message="No source plugins are available in this build."
41− />
42−);
43−
44−const SourceQuickEntry = () => {
45− const navigate = useNavigate();
46− const [value, setValue] = useState("");
47− const [error, setError] = useState<string | null>(null);
48−
49− const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
50− event.preventDefault();
51−
52− const resolved = resolveQuickSourceInput(value);
53− if (resolved === null) {
54− setError(
55− "Could not recognize that input. Try a GraphQL endpoint, MCP URL, Google Discovery URL, OpenAPI spec URL, or a local MCP command.",
56− );
57− return;
58− }
59−
60− setError(null);
61− void navigate({
62− to: createSourcePluginPaths(resolved.pluginKey).add,
63− search: resolved.search,
64− });
65− };
66−
67− return (
68− <Card className="rounded-2xl">
69− <h2 className="font-display text-lg font-semibold tracking-tight text-foreground">
70− Quick add
71− </h2>
72− <p className="mt-1 text-sm leading-6 text-muted-foreground">
73− Paste a URL or command and we'll detect the right plugin automatically.
74− </p>
75−
76− <form onSubmit={handleSubmit} className="mt-4">
77− <div className="flex flex-col gap-3 sm:flex-row">
78− <Input
79− value={value}
80− onChange={(event) => setValue(event.target.value)}
81− placeholder="https://api.github.com/graphql or npx -y chrome-devtools-mcp@latest"
82− className="h-10 flex-1 px-3.5 text-sm"
83− />
84− <Button type="submit" className="h-10">
85− Add source
86− </Button>
87− </div>
88−
89− {error && (
90− <Alert variant="destructive" className="mt-3">
91− {error}
92− </Alert>
93− )}
94− </form>
95− </Card>
96− );
97−};
98−
99−export function ExecutorPluginRoutePage(input: {
100− pluginKey: string;
101− routeKey: FrontendPluginRouteDefinition["key"];
102− params: FrontendPluginRouteParams;
103− search: FrontendPluginRouteSearch;
104− navigation: ExecutorPluginNavigation;
105−}) {
106− const plugin = getFrontendPlugin(input.pluginKey);
107− if (plugin === null) {
108− return <FrontendPluginUnavailableState />;
109− }
110−
111− const routeEntry = getFrontendPluginRoute(input.pluginKey, input.routeKey);
112− if (routeEntry === null) {
113− return (
114− <SourcePluginsResetState
115− title="Route unavailable"
116− message={`The route "${input.routeKey}" is not available for this plugin.`}
117− />
118− );
119− }
120−
121− const PluginPage = routeEntry.route.component;
122−
123− return (
124− <ExecutorPluginRouteProvider
125− value={{
126− plugin,
127− route: routeEntry.route,
128− params: input.params,
129− search: input.search,
130− navigation: input.navigation,
131− }}
132− >
133− <div className="flex h-full min-h-0 flex-col overflow-hidden">
134− <PluginPage />
135− </div>
136− </ExecutorPluginRouteProvider>
137− );
138−}
139−
140−export function SourcePluginsIndexPage() {
141− if (registeredSourceFrontendPlugins.length === 0) {
142− return <SourcePluginUnavailableState />;
143− }
144−
145− const hasMcpPlugin = registeredSourceFrontendPlugins.some(
146− (plugin) => plugin.key === "mcp",
147− );
148−
149− const presetsByPlugin = registeredSourceFrontendPlugins
150− .map((plugin) => ({
151− plugin,
152− presets: sourcePresets.filter((preset) => preset.pluginKey === plugin.key),
153− }))
154− .filter((entry) => entry.presets.length > 0);
155−
156− return (
157− <div className="min-h-0 flex-1 overflow-y-auto">
158− <div className="mx-auto max-w-5xl px-6 py-10 lg:px-10 lg:py-14">
159− <div className="mb-8">
160− <h1 className="font-display text-3xl tracking-tight text-foreground lg:text-4xl">
161− Add source
162− </h1>
163− <p className="mt-1.5 text-[14px] text-muted-foreground">
164− Connect a new tool provider to this workspace.
165− </p>
166− </div>
167−
168− <SourceQuickEntry />
169−
170− {hasMcpPlugin && (
171− <LocalMcpInstallCard
172− className="mt-8"
173− title="Install this executor as MCP"
174− description="Prefer a one-command setup? Install this local executor server into your MCP client, or add an external MCP source below."
175− />
176− )}
177−
178− {presetsByPlugin.length > 0 && (
179− <div className="mt-10">
180− <h2 className="text-lg font-semibold text-foreground">Popular sources</h2>
181− <p className="mt-1 text-sm leading-6 text-muted-foreground">
182− One-click presets for common APIs and tools.
183− </p>
184−
185− <div className="mt-5 space-y-8">
186− {presetsByPlugin.map(({ plugin, presets }) => {
187− const paths = createSourcePluginPaths(plugin.key);
188−
189− return (
190− <section key={plugin.key}>
191− <h3 className="mb-3 text-sm font-semibold text-foreground">
192− {plugin.displayName ?? plugin.key}
193− </h3>
194−
195− <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
196− {presets.map((preset) => (
197− <Link
198− key={preset.id}
199− to={paths.add}
200− search={buildSourcePresetSearch(preset)}
201− className="rounded-xl border border-border bg-card px-4 py-3 text-left transition-colors hover:border-primary/25 hover:bg-card/90"
202− >
203− <div className="mb-2 flex items-center gap-2.5">
204− <div className="flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground">
205− <SourcePresetFavicon preset={preset} className="size-4" />
206− </div>
207− <div className="min-w-0">
208− <div className="truncate text-sm font-semibold text-foreground">
209− {preset.name}
210− </div>
211− <div className="mt-0.5 text-[11px] text-muted-foreground">
212− {preset.kind}
213− </div>
214− </div>
215− </div>
216−
217− <p className="text-sm leading-6 text-muted-foreground">
218− {preset.summary}
219− </p>
220− </Link>
221− ))}
222− </div>
223− </section>
224− );
225− })}
226− </div>
227− </div>
228− )}
229−
230− <div className="mt-10">
231− <h2 className="text-lg font-semibold text-foreground">All source plugins</h2>
232− <p className="mt-1 text-sm leading-6 text-muted-foreground">
233− Start from a clean configuration page for any installed source plugin.
234− </p>
235−
236− <div className="mt-5 grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
237− {registeredSourceFrontendPlugins.map((plugin) => {
238− const paths = createSourcePluginPaths(plugin.key);
239−
240− return (
241− <Link
242− key={plugin.key}
243− to={paths.add}
244− className="rounded-xl border border-border bg-card px-4 py-3 text-left transition-colors hover:border-primary/25 hover:bg-card/90"
245− >
246− <div className="mb-2 text-sm font-semibold text-foreground">
247− {plugin.displayName ?? plugin.key}
248− </div>
249− <p className="text-sm leading-6 text-muted-foreground">
250− {plugin.description ?? "Configure a new source for this plugin."}
251− </p>
252− </Link>
253− );
254− })}
255− </div>
256− </div>
257− </div>
258− </div>
259− );
260−}
apps/web/src/plugins/source-presets.ts+0−657
@@ -1,657 +0,0 @@
1−const GOOGLE_DISCOVERY_PLUGIN_KEY = "google-discovery" as const;
2−const GOOGLE_DISCOVERY_SOURCE_KIND = "google_discovery" as const;
3−
4−export type SourcePreset =
5− | {
6− id: string;
7− pluginKey: "mcp";
8− kind: "mcp";
9− name: string;
10− summary: string;
11− previewUrl: string;
12− endpoint?: string;
13− transport?: "auto" | "streamable-http" | "sse" | "stdio";
14− command?: string;
15− args?: string[];
16− env?: Record<string, string>;
17− cwd?: string;
18− }
19− | {
20− id: string;
21− pluginKey: "openapi";
22− kind: "openapi";
23− name: string;
24− summary: string;
25− previewUrl: string;
26− baseUrl: string;
27− specUrl: string;
28− }
29− | {
30− id: string;
31− pluginKey: "graphql";
32− kind: "graphql";
33− name: string;
34− summary: string;
35− previewUrl: string;
36− endpoint: string;
37− }
38− | {
39− id: string;
40− pluginKey: typeof GOOGLE_DISCOVERY_PLUGIN_KEY;
41− kind: typeof GOOGLE_DISCOVERY_SOURCE_KIND;
42− name: string;
43− summary: string;
44− previewUrl: string;
45− service: string;
46− version: string;
47− discoveryUrl: string;
48− };
49−
50−const googleDiscoveryPreset = (input: {
51− id: string;
52− name: string;
53− summary: string;
54− service: string;
55− version: string;
56− discoveryUrl: string;
57−}): SourcePreset => ({
58− id: input.id,
59− pluginKey: GOOGLE_DISCOVERY_PLUGIN_KEY,
60− kind: GOOGLE_DISCOVERY_SOURCE_KIND,
61− name: input.name,
62− summary: input.summary,
63− previewUrl: input.discoveryUrl,
64− service: input.service,
65− version: input.version,
66− discoveryUrl: input.discoveryUrl,
67−});
68−
69−export const sourcePresets: ReadonlyArray<SourcePreset> = [
70− {
71− id: "deepwiki-mcp",
72− pluginKey: "mcp",
73− kind: "mcp",
74− name: "DeepWiki MCP",
75− summary: "Repository docs and knowledge graphs via MCP.",
76− previewUrl: "https://mcp.deepwiki.com/mcp",
77− endpoint: "https://mcp.deepwiki.com/mcp",
78− transport: "auto",
79− },
80− {
81− id: "axiom-mcp",
82− pluginKey: "mcp",
83− kind: "mcp",
84− name: "Axiom MCP",
85− summary: "Query, stream, and analyze logs, traces, and event data.",
86− previewUrl: "https://mcp.axiom.co/mcp",
87− endpoint: "https://mcp.axiom.co/mcp",
88− transport: "auto",
89− },
90− {
91− id: "neon-mcp",
92− pluginKey: "mcp",
93− kind: "mcp",
94− name: "Neon MCP",
95− summary: "Manage Postgres databases, branches, and queries via MCP.",
96− previewUrl: "https://mcp.neon.tech/mcp",
97− endpoint: "https://mcp.neon.tech/mcp",
98− transport: "auto",
99− },
100− {
101− id: "chrome-devtools-mcp",
102− pluginKey: "mcp",
103− kind: "mcp",
104− name: "Chrome DevTools MCP",
105− summary: "Debug a live Chrome browser session over a local MCP stdio transport.",
106− previewUrl: "npx -y chrome-devtools-mcp@latest",
107− transport: "stdio",
108− command: "npx",
109− args: ["-y", "chrome-devtools-mcp@latest"],
110− },
111− {
112− id: "neon-api",
113− pluginKey: "openapi",
114− kind: "openapi",
115− name: "Neon API",
116− summary: "Projects, branches, endpoints, databases, and API keys.",
117− previewUrl: "https://console.neon.tech/api/v2",
118− baseUrl: "https://console.neon.tech/api/v2",
119− specUrl: "https://neon.com/api_spec/release/v2.json",
120− },
121− {
122− id: "github-rest",
123− pluginKey: "openapi",
124− kind: "openapi",
125− name: "GitHub REST API",
126− summary: "Repos, issues, pull requests, actions, and org settings.",
127− previewUrl: "https://api.github.com",
128− baseUrl: "https://api.github.com",
129− specUrl: "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.yaml",
130− },
131− {
132− id: "github-graphql",
133− pluginKey: "graphql",
134− kind: "graphql",
135− name: "GitHub GraphQL",
136− summary: "Issues, pull requests, discussions, and repository objects via GraphQL.",
137− previewUrl: "https://api.github.com/graphql",
138− endpoint: "https://api.github.com/graphql",
139− },
140− {
141− id: "gitlab-graphql",
142− pluginKey: "graphql",
143− kind: "graphql",
144− name: "GitLab GraphQL",
145− summary: "Projects, merge requests, issues, CI pipelines, and users.",
146− previewUrl: "https://gitlab.com/api/graphql",
147− endpoint: "https://gitlab.com/api/graphql",
148− },
149− {
150− id: "openai-api",
151− pluginKey: "openapi",
152− kind: "openapi",
153− name: "OpenAI API",
154− summary: "Models, files, responses, and fine-tuning.",
155− previewUrl: "https://api.openai.com/v1",
156− baseUrl: "https://api.openai.com/v1",
157− specUrl: "https://app.stainless.com/api/spec/documented/openai/openapi.documented.yml",
158− },
159− {
160− id: "vercel-api",
161− pluginKey: "openapi",
162− kind: "openapi",
163− name: "Vercel API",
164− summary: "Deployments, projects, domains, and environments.",
165− previewUrl: "https://api.vercel.com",
166− baseUrl: "https://api.vercel.com",
167− specUrl: "https://openapi.vercel.sh",
168− },
169− {
170− id: "stripe-api",
171− pluginKey: "openapi",
172− kind: "openapi",
173− name: "Stripe API",
174− summary: "Payments, billing, subscriptions, and invoices.",
175− previewUrl: "https://api.stripe.com",
176− baseUrl: "https://api.stripe.com",
177− specUrl: "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json",
178− },
179− {
180− id: "linear-graphql",
181− pluginKey: "graphql",
182− kind: "graphql",
183− name: "Linear GraphQL",
184− summary: "Issues, teams, cycles, and projects.",
185− previewUrl: "https://api.linear.app/graphql",
186− endpoint: "https://api.linear.app/graphql",
187− },
188− {
189− id: "monday-graphql",
190− pluginKey: "graphql",
191− kind: "graphql",
192− name: "Monday GraphQL",
193− summary: "Boards, items, updates, users, and workspace metadata.",
194− previewUrl: "https://api.monday.com/v2",
195− endpoint: "https://api.monday.com/v2",
196− },
197− {
198− id: "anilist-graphql",
199− pluginKey: "graphql",
200− kind: "graphql",
201− name: "AniList GraphQL",
202− summary: "Anime, manga, characters, media lists, and recommendations.",
203− previewUrl: "https://graphql.anilist.co",
204− endpoint: "https://graphql.anilist.co",
205− },
206− googleDiscoveryPreset({
207− id: "google-calendar",
208− name: "Google Calendar",
209− summary: "Calendars, events, ACLs, and scheduling workflows.",
210− service: "calendar",
211− version: "v3",
212− discoveryUrl: "https://calendar-json.googleapis.com/$discovery/rest?version=v3",
213− }),
214− googleDiscoveryPreset({
215− id: "google-drive",
216− name: "Google Drive",
217− summary: "Files, folders, permissions, comments, and shared drives.",
218− service: "drive",
219− version: "v3",
220− discoveryUrl: "https://www.googleapis.com/discovery/v1/apis/drive/v3/rest",
221− }),
222− googleDiscoveryPreset({
223− id: "google-gmail",
224− name: "Gmail",
225− summary: "Messages, threads, labels, drafts, and mailbox automation.",
226− service: "gmail",
227− version: "v1",
228− discoveryUrl: "https://gmail.googleapis.com/$discovery/rest?version=v1",
229− }),
230− googleDiscoveryPreset({
231− id: "google-docs",
232− name: "Google Docs",
233− summary: "Documents, structural edits, text ranges, and formatting.",
234− service: "docs",
235− version: "v1",
236− discoveryUrl: "https://docs.googleapis.com/$discovery/rest?version=v1",
237− }),
238− googleDiscoveryPreset({
239− id: "google-sheets",
240− name: "Google Sheets",
241− summary: "Spreadsheets, values, ranges, formatting, and batch updates.",
242− service: "sheets",
243− version: "v4",
244− discoveryUrl: "https://sheets.googleapis.com/$discovery/rest?version=v4",
245− }),
246− googleDiscoveryPreset({
247− id: "google-slides",
248− name: "Google Slides",
249− summary: "Presentations, slides, page elements, and deck updates.",
250− service: "slides",
251− version: "v1",
252− discoveryUrl: "https://slides.googleapis.com/$discovery/rest?version=v1",
253− }),
254− googleDiscoveryPreset({
255− id: "google-forms",
256− name: "Google Forms",
257− summary: "Forms, questions, responses, quizzes, and form metadata.",
258− service: "forms",
259− version: "v1",
260− discoveryUrl: "https://forms.googleapis.com/$discovery/rest?version=v1",
261− }),
262− googleDiscoveryPreset({
263− id: "google-search-console",
264− name: "Google Search Console",
265− summary: "Sites, sitemaps, URL inspection, and search and Discover performance.",
266− service: "searchconsole",
267− version: "v1",
268− discoveryUrl: "https://searchconsole.googleapis.com/$discovery/rest?version=v1",
269− }),
270− googleDiscoveryPreset({
271− id: "google-people",
272− name: "Google People",
273− summary: "Contacts, profiles, directory people, and contact groups.",
274− service: "people",
275− version: "v1",
276− discoveryUrl: "https://people.googleapis.com/$discovery/rest?version=v1",
277− }),
278− googleDiscoveryPreset({
279− id: "google-tasks",
280− name: "Google Tasks",
281− summary: "Task lists, task items, notes, and due dates.",
282− service: "tasks",
283− version: "v1",
284− discoveryUrl: "https://tasks.googleapis.com/$discovery/rest?version=v1",
285− }),
286− googleDiscoveryPreset({
287− id: "google-chat",
288− name: "Google Chat",
289− summary: "Spaces, messages, members, reactions, and chat workflows.",
290− service: "chat",
291− version: "v1",
292− discoveryUrl: "https://chat.googleapis.com/$discovery/rest?version=v1",
293− }),
294− googleDiscoveryPreset({
295− id: "google-keep",
296− name: "Google Keep",
297− summary: "Notes, lists, attachments, and collaborative annotations.",
298− service: "keep",
299− version: "v1",
300− discoveryUrl: "https://keep.googleapis.com/$discovery/rest?version=v1",
301− }),
302− googleDiscoveryPreset({
303− id: "google-classroom",
304− name: "Google Classroom",
305− summary: "Courses, rosters, coursework, submissions, and grading data.",
306− service: "classroom",
307− version: "v1",
308− discoveryUrl: "https://classroom.googleapis.com/$discovery/rest?version=v1",
309− }),
310− googleDiscoveryPreset({
311− id: "google-admin-directory",
312− name: "Google Admin Directory",
313− summary: "Users, groups, org units, roles, and domain directory resources.",
314− service: "admin",
315− version: "directory_v1",
316− discoveryUrl: "https://admin.googleapis.com/$discovery/rest?version=directory_v1",
317− }),
318− googleDiscoveryPreset({
319− id: "google-admin-reports",
320− name: "Google Admin Reports",
321− summary: "Audit events, usage reports, and admin activity logs.",
322− service: "admin",
323− version: "reports_v1",
324− discoveryUrl: "https://admin.googleapis.com/$discovery/rest?version=reports_v1",
325− }),
326− googleDiscoveryPreset({
327− id: "google-apps-script",
328− name: "Google Apps Script",
329− summary: "Projects, deployments, script execution, and Apps Script metadata.",
330− service: "script",
331− version: "v1",
332− discoveryUrl: "https://script.googleapis.com/$discovery/rest?version=v1",
333− }),
334− googleDiscoveryPreset({
335− id: "google-bigquery",
336− name: "Google BigQuery",
337− summary: "Datasets, tables, jobs, routines, and analytical query workflows.",
338− service: "bigquery",
339− version: "v2",
340− discoveryUrl: "https://bigquery.googleapis.com/$discovery/rest?version=v2",
341− }),
342− googleDiscoveryPreset({
343− id: "google-cloud-resource-manager",
344− name: "Google Cloud Resource Manager",
345− summary: "Projects, folders, organizations, and IAM-oriented resource hierarchy.",
346− service: "cloudresourcemanager",
347− version: "v3",
348− discoveryUrl: "https://cloudresourcemanager.googleapis.com/$discovery/rest?version=v3",
349− }),
350− googleDiscoveryPreset({
351− id: "google-youtube-data",
352− name: "YouTube Data",
353− summary: "Channels, playlists, videos, comments, captions, and uploads.",
354− service: "youtube",
355− version: "v3",
356− discoveryUrl: "https://youtube.googleapis.com/$discovery/rest?version=v3",
357− }),
358−] as const;
359−
360−export const buildSourcePresetSearch = (
361− preset: SourcePreset,
362−): Record<string, string> => {
363− switch (preset.pluginKey) {
364− case "openapi":
365− return {
366− preset: preset.id,
367− presetName: preset.name,
368− presetBaseUrl: preset.baseUrl,
369− presetSpecUrl: preset.specUrl,
370− };
371− case "graphql":
372− return {
373− preset: preset.id,
374− presetName: preset.name,
375− presetEndpoint: preset.endpoint,
376− };
377− case "mcp":
378− return {
379− preset: preset.id,
380− presetName: preset.name,
381− ...(preset.endpoint ? { presetEndpoint: preset.endpoint } : {}),
382− ...(preset.transport ? { presetTransport: preset.transport } : {}),
383− ...(preset.command ? { presetCommand: preset.command } : {}),
384− ...(preset.args ? { presetArgs: JSON.stringify(preset.args) } : {}),
385− ...(preset.env ? { presetEnv: JSON.stringify(preset.env) } : {}),
386− ...(preset.cwd ? { presetCwd: preset.cwd } : {}),
387− };
388− default:
389− return {
390− preset: preset.id,
391− presetName: preset.name,
392− presetService: preset.service,
393− presetVersion: preset.version,
394− presetDiscoveryUrl: preset.discoveryUrl,
395− };
396− }
397−};
398−
399−const normalizeComparableUrl = (value: string): string => {
400− const trimmed = value.trim();
401− try {
402− const url = new URL(trimmed);
403− if (url.pathname.length > 1 && url.pathname.endsWith("/")) {
404− url.pathname = url.pathname.slice(0, -1);
405− }
406− return url.toString();
407− } catch {
408− return trimmed;
409− }
410−};
411−
412−const tryParseUrl = (value: string): URL | null => {
413− try {
414− return new URL(value.trim());
415− } catch {
416− return null;
417− }
418−};
419−
420−const sourceNameFromUrl = (url: URL, fallback: string): string => {
421− const hostname = url.hostname.replace(/^www\./, "");
422− if (hostname.length === 0) {
423− return fallback;
424− }
425−
426− const head = hostname.split(".")[0]?.trim();
427− if (!head) {
428− return fallback;
429− }
430−
431− return `${head.charAt(0).toUpperCase()}${head.slice(1)} ${fallback}`;
432−};
433−
434−const parseGoogleDiscoveryUrl = (value: string): {
435− service: string;
436− version: string;
437− discoveryUrl: string;
438−} | null => {
439− const url = tryParseUrl(value);
440− if (!url) {
441− return null;
442− }
443−
444− const byDirectory = url.pathname.match(
445− /^\/discovery\/v1\/apis\/([^/]+)\/([^/]+)\/rest$/,
446− );
447− if (byDirectory) {
448− return {
449− service: decodeURIComponent(byDirectory[1] ?? ""),
450− version: decodeURIComponent(byDirectory[2] ?? ""),
451− discoveryUrl: url.toString(),
452− };
453− }
454−
455− const versionParam = url.searchParams.get("version")?.trim();
456− const isHostScopedDiscovery =
457− url.pathname === "/$discovery/rest"
458− && url.hostname.endsWith(".googleapis.com")
459− && url.hostname !== "www.googleapis.com";
460−
461− if (versionParam && isHostScopedDiscovery) {
462− const service = url.hostname.split(".")[0]?.trim();
463− if (!service) {
464− return null;
465− }
466−
467− return {
468− service,
469− version: versionParam,
470− discoveryUrl: url.toString(),
471− };
472− }
473−
474− return null;
475−};
476−
477−const isGraphqlUrl = (url: URL): boolean => {
478− const path = url.pathname.toLowerCase();
479− const hostname = url.hostname.toLowerCase();
480− return (
481− path.endsWith("/graphql")
482− || path === "/graphql"
483− || hostname.startsWith("graphql.")
484− || hostname.includes("graphql")
485− );
486−};
487−
488−const isMcpUrl = (url: URL): boolean => {
489− const path = url.pathname.toLowerCase();
490− const hostname = url.hostname.toLowerCase();
491− return path.endsWith("/mcp") || path.includes("/mcp/") || hostname.startsWith("mcp.");
492−};
493−
494−const isLikelyOpenApiSpecUrl = (url: URL): boolean => {
495− const path = url.pathname.toLowerCase();
496− return (
497− path.endsWith(".json")
498− || path.endsWith(".yaml")
499− || path.endsWith(".yml")
500− || path.includes("openapi")
501− || path.includes("swagger")
502− );
503−};
504−
505−const findPresetByInput = (value: string): SourcePreset | null => {
506− const comparable = normalizeComparableUrl(value);
507− for (const preset of sourcePresets) {
508− if (normalizeComparableUrl(preset.previewUrl) === comparable) {
509− return preset;
510− }
511−
512− if (preset.pluginKey === "openapi") {
513− if (normalizeComparableUrl(preset.baseUrl) === comparable) {
514− return preset;
515− }
516− if (normalizeComparableUrl(preset.specUrl) === comparable) {
517− return preset;
518− }
519− continue;
520− }
521−
522− if (preset.pluginKey === "graphql" || preset.pluginKey === "mcp") {
523− if (preset.endpoint && normalizeComparableUrl(preset.endpoint) === comparable) {
524− return preset;
525− }
526− continue;
527− }
528−
529− if (normalizeComparableUrl(preset.discoveryUrl) === comparable) {
530− return preset;
531− }
532− }
533−
534− return null;
535−};
536−
537−export type ResolvedQuickSourceInput = {
538− pluginKey: SourcePreset["pluginKey"];
539− search: Record<string, string>;
540−};
541−
542−export const resolveQuickSourceInput = (
543− rawValue: string,
544−): ResolvedQuickSourceInput | null => {
545− const trimmed = rawValue.trim();
546− if (trimmed.length === 0) {
547− return null;
548− }
549−
550− const commandParts =
551− trimmed.match(/[^\s"]+|"([^"]*)"/g)?.map((part) =>
552− part.startsWith("\"") && part.endsWith("\"")
553− ? part.slice(1, -1)
554− : part
555− ) ?? null;
556− if (commandParts && commandParts.length > 0) {
557− const [command, ...args] = commandParts;
558− const isKnownCommand =
559− command === "npx"
560− || command === "bunx"
561− || command === "uvx"
562− || (command === "pnpm" && args[0] === "dlx");
563−
564− if (isKnownCommand) {
565− return {
566− pluginKey: "mcp",
567− search: {
568− presetName: "Local MCP",
569− presetTransport: "stdio",
570− presetCommand: command,
571− ...(args.length > 0 ? { presetArgs: JSON.stringify(args) } : {}),
572− quickInput: trimmed,
573− },
574− };
575− }
576− }
577−
578− const preset = findPresetByInput(trimmed);
579− if (preset) {
580− return {
581− pluginKey: preset.pluginKey,
582− search: buildSourcePresetSearch(preset),
583− };
584− }
585−
586− const googleDiscovery = parseGoogleDiscoveryUrl(trimmed);
587− if (googleDiscovery) {
588− const googlePreset = sourcePresets.find(
589− (presetEntry) =>
590− presetEntry.pluginKey === GOOGLE_DISCOVERY_PLUGIN_KEY
591− && presetEntry.service === googleDiscovery.service
592− && presetEntry.version === googleDiscovery.version,
593− );
594−
595− return {
596− pluginKey: GOOGLE_DISCOVERY_PLUGIN_KEY,
597− search: {
598− ...(googlePreset ? buildSourcePresetSearch(googlePreset) : {}),
599− presetName:
600− googlePreset?.name
601− ?? `Google ${googleDiscovery.service} ${googleDiscovery.version}`,
602− presetService: googleDiscovery.service,
603− presetVersion: googleDiscovery.version,
604− presetDiscoveryUrl: googleDiscovery.discoveryUrl,
605− quickInput: trimmed,
606− },
607− };
608− }
609−
610− const url = tryParseUrl(trimmed);
611− if (!url) {
612− return null;
613− }
614−
615− if (isGraphqlUrl(url)) {
616− return {
617− pluginKey: "graphql",
618− search: {
619− presetName: sourceNameFromUrl(url, "GraphQL"),
620− presetEndpoint: trimmed,
621− quickInput: trimmed,
622− },
623− };
624− }
625−
626− if (isMcpUrl(url)) {
627− return {
628− pluginKey: "mcp",
629− search: {
630− presetName: sourceNameFromUrl(url, "MCP"),
631− presetEndpoint: trimmed,
632− presetTransport: "auto",
633− quickInput: trimmed,
634− },
635− };
636− }
637−
638− if (isLikelyOpenApiSpecUrl(url)) {
639− return {
640− pluginKey: "openapi",
641− search: {
642− presetName: sourceNameFromUrl(url, "OpenAPI"),
643− presetSpecUrl: trimmed,
644− quickInput: trimmed,
645− },
646− };
647− }
648−
649− return {
650− pluginKey: "openapi",
651− search: {
652− presetName: sourceNameFromUrl(url, "OpenAPI"),
653− presetBaseUrl: trimmed,
654− quickInput: trimmed,
655− },
656− };
657−};
apps/web/src/router.tsx+73−0
@@ -0,0 +1,73 @@
1+import {
2+ createRouter,
3+ createRootRoute,
4+ createRoute,
5+} from "@tanstack/react-router";
6+import { ExecutorProvider } from "@executor/react";
7+import { ToolsPage } from "./pages/tools";
8+import { SourcesPage } from "./pages/sources";
9+import { SourceDetailPage } from "./pages/source-detail";
10+import { SecretsPage } from "./pages/secrets";
11+import { Shell } from "./shell";
12+
13+// ---------------------------------------------------------------------------
14+// Root layout — Shell renders <Outlet /> directly
15+// ---------------------------------------------------------------------------
16+
17+const rootRoute = createRootRoute({
18+ component: () => (
19+ <ExecutorProvider>
20+ <Shell />
21+ </ExecutorProvider>
22+ ),
23+});
24+
25+// ---------------------------------------------------------------------------
26+// Routes
27+// ---------------------------------------------------------------------------
28+
29+const indexRoute = createRoute({
30+ getParentRoute: () => rootRoute,
31+ path: "/",
32+ component: SourcesPage,
33+});
34+
35+const toolsRoute = createRoute({
36+ getParentRoute: () => rootRoute,
37+ path: "/tools",
38+ component: ToolsPage,
39+});
40+
41+const sourceDetailRoute = createRoute({
42+ getParentRoute: () => rootRoute,
43+ path: "/sources/$namespace",
44+ component: () => {
45+ const { namespace } = sourceDetailRoute.useParams();
46+ return <SourceDetailPage namespace={namespace} />;
47+ },
48+});
49+
50+const secretsRoute = createRoute({
51+ getParentRoute: () => rootRoute,
52+ path: "/secrets",
53+ component: SecretsPage,
54+});
55+
56+// ---------------------------------------------------------------------------
57+// Router
58+// ---------------------------------------------------------------------------
59+
60+const routeTree = rootRoute.addChildren([
61+ indexRoute,
62+ toolsRoute,
63+ sourceDetailRoute,
64+ secretsRoute,
65+]);
66+
67+export const router = createRouter({ routeTree });
68+
69+declare module "@tanstack/react-router" {
70+ interface Register {
71+ router: typeof router;
72+ }
73+}
apps/web/src/server.ts+0−13
@@ -1,13 +0,0 @@
1−/**
2− * Production server. Serves the API + Vite-built static assets.
3− *
4− * In development, use `bun run dev` which starts Vite with
5− * @hono/vite-dev-server embedding the API via dev.ts.
6− */
7−import { runLocalExecutorServer } from "@executor/server";
8−
9−await runLocalExecutorServer({
10− ui: {
11− assetsDir: new URL("../dist", import.meta.url).pathname,
12− },
13−});
apps/web/src/shell.tsx+473−0
@@ -0,0 +1,473 @@
1+import { Link, Outlet, useLocation } from "@tanstack/react-router";
2+import { useCallback, useEffect, useRef, useState } from "react";
3+import {
4+ useAtomRefresh,
5+ useAtomValue,
6+ Result,
7+ sourcesAtom,
8+ toolsAtom,
9+ useScope,
10+ useScopeInfo,
11+} from "@executor/react";
12+import { Button } from "@executor/ui/components/button";
13+
14+// ── Env ─────────────────────────────────────────────────────────────────
15+
16+type AppMetaEnv = {
17+ readonly VITE_APP_VERSION: string;
18+ readonly VITE_GITHUB_URL: string;
19+};
20+
21+const { VITE_APP_VERSION, VITE_GITHUB_URL } = (import.meta as ImportMeta & {
22+ readonly env: AppMetaEnv;
23+}).env;
24+
25+// ── Version helpers ─────────────────────────────────────────────────────
26+
27+type UpdateChannel = "latest" | "beta";
28+
29+const EXECUTOR_DIST_TAGS_PATH = "/v1/app/npm/dist-tags";
30+
31+type ParsedVersion = {
32+ readonly major: number;
33+ readonly minor: number;
34+ readonly patch: number;
35+ readonly prerelease: ReadonlyArray<string | number> | null;
36+};
37+
38+const semverPattern =
39+ /^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<prerelease>[0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
40+
41+const resolveUpdateChannel = (version: string): UpdateChannel =>
42+ version.includes("-beta.") ? "beta" : "latest";
43+
44+const parseVersion = (version: string): ParsedVersion | null => {
45+ const match = version.trim().match(semverPattern);
46+ if (!match?.groups) return null;
47+ return {
48+ major: Number(match.groups.major),
49+ minor: Number(match.groups.minor),
50+ patch: Number(match.groups.patch),
51+ prerelease: match.groups.prerelease
52+ ? match.groups.prerelease.split(".").map((id) =>
53+ /^\d+$/.test(id) ? Number(id) : id,
54+ )
55+ : null,
56+ };
57+};
58+
59+const comparePrereleaseIdentifiers = (
60+ left: ReadonlyArray<string | number> | null,
61+ right: ReadonlyArray<string | number> | null,
62+): number => {
63+ if (left === null && right === null) return 0;
64+ if (left === null) return 1;
65+ if (right === null) return -1;
66+ const max = Math.max(left.length, right.length);
67+ for (let i = 0; i < max; i++) {
68+ const l = left[i];
69+ const r = right[i];
70+ if (l === undefined) return -1;
71+ if (r === undefined) return 1;
72+ if (l === r) continue;
73+ if (typeof l === "number" && typeof r === "number") return l < r ? -1 : 1;
74+ if (typeof l === "number") return -1;
75+ if (typeof r === "number") return 1;
76+ return l < r ? -1 : 1;
77+ }
78+ return 0;
79+};
80+
81+const compareVersions = (left: string, right: string): number | null => {
82+ const lv = parseVersion(left);
83+ const rv = parseVersion(right);
84+ if (!lv || !rv) return null;
85+ if (lv.major !== rv.major) return lv.major < rv.major ? -1 : 1;
86+ if (lv.minor !== rv.minor) return lv.minor < rv.minor ? -1 : 1;
87+ if (lv.patch !== rv.patch) return lv.patch < rv.patch ? -1 : 1;
88+ return comparePrereleaseIdentifiers(lv.prerelease, rv.prerelease);
89+};
90+
91+// ── useLatestVersion ────────────────────────────────────────────────────
92+
93+function useLatestVersion(currentVersion: string) {
94+ const channel = resolveUpdateChannel(currentVersion);
95+ const [latestVersion, setLatestVersion] = useState<string | null>(null);
96+
97+ useEffect(() => {
98+ let cancelled = false;
99+ fetch(EXECUTOR_DIST_TAGS_PATH)
100+ .then(async (res) => {
101+ if (!res.ok) throw new Error(`Failed to load dist tags: ${res.status}`);
102+ return res.json() as Promise<Partial<Record<UpdateChannel, string>>>;
103+ })
104+ .then((data) => {
105+ if (!cancelled) setLatestVersion(data[channel] ?? null);
106+ })
107+ .catch(() => {});
108+ return () => { cancelled = true; };
109+ }, [channel]);
110+
111+ const updateAvailable =
112+ latestVersion !== null && compareVersions(currentVersion, latestVersion) === -1;
113+
114+ return { latestVersion, updateAvailable, channel };
115+}
116+
117+// ── UpdateCard ──────────────────────────────────────────────────────────
118+
119+function UpdateCard(props: { latestVersion: string; channel: UpdateChannel }) {
120+ const command = `npm i -g executor@${props.channel}`;
121+ const [copied, setCopied] = useState(false);
122+
123+ const handleCopy = useCallback(() => {
124+ void navigator.clipboard.writeText(command).then(() => {
125+ setCopied(true);
126+ setTimeout(() => setCopied(false), 1500);
127+ });
128+ }, [command]);
129+
130+ return (
131+ <div className="mx-2 mb-2 rounded-xl border border-primary/25 bg-primary/[0.06] p-3">
132+ <div className="flex items-center gap-2">
133+ <div className="flex size-5 shrink-0 items-center justify-center rounded-full bg-primary/15">
134+ <svg viewBox="0 0 16 16" fill="none" className="size-3 text-primary">
135+ <path d="M8 3v7M5 7l3 3 3-3" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
136+ <path d="M3 12h10" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
137+ </svg>
138+ </div>
139+ <div className="min-w-0">
140+ <p className="text-[11px] font-semibold text-foreground">Update available</p>
141+ <p className="text-[10px] text-muted-foreground">
142+ v{props.latestVersion}
143+ </p>
144+ </div>
145+ </div>
146+ <Button
147+ type="button"
148+ variant="outline"
149+ onClick={handleCopy}
150+ className="mt-2.5 flex w-full items-center justify-between gap-2 rounded-lg border-border/60 bg-background/50 px-2.5 py-1.5 text-left hover:bg-background/80"
151+ >
152+ <code className="truncate font-mono text-[10px] text-sidebar-foreground">
153+ {command}
154+ </code>
155+ <span className="shrink-0 text-muted-foreground transition-colors group-hover:text-foreground">
156+ {copied ? (
157+ <svg viewBox="0 0 16 16" fill="none" className="size-3 text-primary">
158+ <path d="M3 8.5l3.5 3.5L13 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
159+ </svg>
160+ ) : (
161+ <svg viewBox="0 0 16 16" fill="none" className="size-3">
162+ <rect x="5" y="5" width="8" height="8" rx="1.5" stroke="currentColor" strokeWidth="1.2" />
163+ <path d="M3 11V3.5A.5.5 0 013.5 3H11" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
164+ </svg>
165+ )}
166+ </span>
167+ </Button>
168+ </div>
169+ );
170+}
171+
172+// ── NavItem ──────────────────────────────────────────────────────────────
173+
174+function NavItem(props: { to: string; label: string; active: boolean; onNavigate?: () => void }) {
175+ return (
176+ <Link
177+ to={props.to}
178+ onClick={props.onNavigate}
179+ className={[
180+ "flex items-center gap-2.5 rounded-md px-2.5 py-1.5 text-[13px] transition-colors",
181+ props.active
182+ ? "bg-sidebar-active text-foreground font-medium"
183+ : "text-sidebar-foreground hover:bg-sidebar-active/60 hover:text-foreground",
184+ ].join(" ")}
185+ >
186+ {props.label}
187+ </Link>
188+ );
189+}
190+
191+// ── SourceList ───────────────────────────────────────────────────────────
192+
193+function SourceList(props: { pathname: string; onNavigate?: () => void }) {
194+ const scopeId = useScope();
195+ const sources = useAtomValue(sourcesAtom(scopeId));
196+
197+ return Result.match(sources, {
198+ onInitial: () => (
199+ <div className="px-2.5 py-2 text-[11px] text-muted-foreground/40">Loading…</div>
200+ ),
201+ onFailure: () => (
202+ <div className="px-2.5 py-2 text-[11px] text-muted-foreground/40">No sources yet</div>
203+ ),
204+ onSuccess: ({ value }) =>
205+ value.length === 0 ? (
206+ <div className="px-2.5 py-2 text-[11px] leading-relaxed text-muted-foreground/40">
207+ No sources yet
208+ </div>
209+ ) : (
210+ <div className="flex flex-col gap-px">
211+ {value.map((s) => {
212+ const detailPath = `/sources/${s.id}`;
213+ const active =
214+ props.pathname === detailPath ||
215+ props.pathname.startsWith(`${detailPath}/`);
216+ return (
217+ <Link
218+ key={s.id}
219+ to="/sources/$namespace"
220+ params={{ namespace: s.id }}
221+ onClick={props.onNavigate}
222+ className={[
223+ "group flex items-center gap-2 rounded-md px-2.5 py-1.5 text-[13px] transition-colors",
224+ active
225+ ? "bg-sidebar-active text-foreground font-medium"
226+ : "text-sidebar-foreground hover:bg-sidebar-active/60 hover:text-foreground",
227+ ].join(" ")}
228+ >
229+ <span className="flex-1 truncate">{s.name}</span>
230+ <span className="rounded bg-secondary/50 px-1 py-px text-[9px] font-medium text-muted-foreground/50">
231+ {s.kind}
232+ </span>
233+ </Link>
234+ );
235+ })}
236+ </div>
237+ ),
238+ });
239+}
240+
241+// ── ScopeLabel ───────────────────────────────────────────────────────────
242+
243+function ScopeLabel() {
244+ const { name } = useScopeInfo();
245+ // Show just the last folder name, with full path as tooltip
246+ const parts = name.replace(/\/+$/, "").split("/");
247+ const folder = parts[parts.length - 1] || name;
248+
249+ return (
250+ <div className="mb-1.5 flex items-center gap-1.5 rounded-md px-2.5 py-1.5" title={name}>
251+ <svg viewBox="0 0 16 16" fill="none" className="size-3.5 shrink-0 text-muted-foreground/50">
252+ <path
253+ d="M2 4.5C2 3.67 2.67 3 3.5 3h3.09a1 1 0 0 1 .7.29l1.42 1.42a1 1 0 0 0 .7.29H12.5c.83 0 1.5.67 1.5 1.5v5.5c0 .83-.67 1.5-1.5 1.5h-9A1.5 1.5 0 0 1 2 12V4.5z"
254+ stroke="currentColor"
255+ strokeWidth="1.2"
256+ />
257+ </svg>
258+ <span className="truncate text-[12px] font-medium text-foreground/80">
259+ {folder}
260+ </span>
261+ </div>
262+ );
263+}
264+
265+// ── SidebarContent ───────────────────────────────────────────────────────
266+
267+function SidebarContent(props: {
268+ pathname: string;
269+ onNavigate?: () => void;
270+ showBrand?: boolean;
271+ updateAvailable: boolean;
272+ latestVersion: string | null;
273+ channel: UpdateChannel;
274+}) {
275+ const isHome = props.pathname === "/";
276+ const isSecrets = props.pathname === "/secrets";
277+
278+ return (
279+ <>
280+ {props.showBrand !== false && (
281+ <div className="flex h-12 shrink-0 items-center border-b border-sidebar-border px-4">
282+ <Link to="/" className="flex items-center gap-1.5">
283+ <span className="font-display text-base tracking-tight text-foreground">
284+ executor
285+ </span>
286+ <span className="rounded bg-primary/15 px-1.5 py-0.5 text-[10px] font-medium text-primary">
287+ v4
288+ </span>
289+ </Link>
290+ </div>
291+ )}
292+
293+ <nav className="flex flex-1 flex-col overflow-y-auto p-2">
294+ <ScopeLabel />
295+ <NavItem
296+ to="/"
297+ label="Sources"
298+ active={isHome}
299+ onNavigate={props.onNavigate}
300+ />
301+ <NavItem
302+ to="/secrets"
303+ label="Secrets"
304+ active={isSecrets}
305+ onNavigate={props.onNavigate}
306+ />
307+
308+ {/* Sources list */}
309+ <div className="mt-5 mb-1 px-2.5 text-[10px] font-medium uppercase tracking-widest text-muted-foreground/50">
310+ <span>Configured</span>
311+ </div>
312+
313+ <SourceList pathname={props.pathname} onNavigate={props.onNavigate} />
314+ </nav>
315+
316+ {props.updateAvailable && props.latestVersion && (
317+ <UpdateCard latestVersion={props.latestVersion} channel={props.channel} />
318+ )}
319+
320+ {/* Footer */}
321+ <div className="shrink-0 border-t border-sidebar-border px-4 py-2.5">
322+ <div className="flex flex-col gap-1.5 text-[11px] leading-none">
323+ <a
324+ href={`${VITE_GITHUB_URL}/issues`}
325+ target="_blank"
326+ rel="noreferrer"
327+ className="text-muted-foreground/70 transition-colors hover:text-foreground"
328+ >
329+ Feedback / bug?
330+ </a>
331+ <a
332+ href={VITE_GITHUB_URL}
333+ target="_blank"
334+ rel="noreferrer"
335+ className="text-muted-foreground/70 transition-colors hover:text-foreground"
336+ >
337+ Star on GitHub
338+ </a>
339+ <span className="mt-0.5 text-[10px] text-muted-foreground/50 tabular-nums">v{VITE_APP_VERSION}</span>
340+ </div>
341+ </div>
342+ </>
343+ );
344+}
345+
346+// ── Shell ─────────────────────────────────────────────────────────────────
347+
348+export function Shell() {
349+ const location = useLocation();
350+ const pathname = location.pathname;
351+ const scopeId = useScope();
352+ const refreshSources = useAtomRefresh(sourcesAtom(scopeId));
353+ const refreshTools = useAtomRefresh(toolsAtom(scopeId));
354+ const { latestVersion, updateAvailable, channel } = useLatestVersion(VITE_APP_VERSION);
355+ const lastPathname = useRef(pathname);
356+ const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
357+ if (lastPathname.current !== pathname) {
358+ lastPathname.current = pathname;
359+ if (mobileSidebarOpen) setMobileSidebarOpen(false);
360+ }
361+
362+ // Lock scroll when mobile sidebar open
363+ useEffect(() => {
364+ if (!mobileSidebarOpen) return;
365+ const prev = document.body.style.overflow;
366+ document.body.style.overflow = "hidden";
367+ return () => {
368+ document.body.style.overflow = prev;
369+ };
370+ }, [mobileSidebarOpen]);
371+
372+ useEffect(() => {
373+ if (!import.meta.hot) {
374+ return;
375+ }
376+
377+ const refreshBackendData = () => {
378+ refreshSources();
379+ refreshTools();
380+ };
381+
382+ import.meta.hot.on("executor:backend-updated", refreshBackendData);
383+
384+ return () => {
385+ import.meta.hot?.off("executor:backend-updated", refreshBackendData);
386+ };
387+ }, [refreshSources, refreshTools]);
388+
389+ return (
390+ <div className="flex h-screen overflow-hidden">
391+ {/* Desktop sidebar */}
392+ <aside className="hidden w-52 shrink-0 border-r border-sidebar-border bg-sidebar md:flex md:flex-col lg:w-56">
393+ <SidebarContent
394+ pathname={pathname}
395+ updateAvailable={updateAvailable}
396+ latestVersion={latestVersion}
397+ channel={channel}
398+ />
399+ </aside>
400+
401+ {/* Mobile sidebar overlay */}
402+ {mobileSidebarOpen && (
403+ <div className="fixed inset-0 z-50 flex md:hidden">
404+ <button
405+ type="button"
406+ aria-label="Close navigation"
407+ className="absolute inset-0 bg-black/45 backdrop-blur-[1px]"
408+ onClick={() => setMobileSidebarOpen(false)}
409+ />
410+ <div className="relative flex h-full w-[84vw] max-w-xs flex-col border-r border-sidebar-border bg-sidebar shadow-2xl">
411+ <div className="flex h-12 shrink-0 items-center justify-between border-b border-sidebar-border px-4">
412+ <Link to="/" className="flex items-center gap-1.5">
413+ <span className="font-display text-base tracking-tight text-foreground">
414+ executor
415+ </span>
416+ <span className="rounded bg-primary/15 px-1.5 py-0.5 text-[10px] font-medium text-primary">
417+ v4
418+ </span>
419+ </Link>
420+ <button
421+ type="button"
422+ aria-label="Close navigation"
423+ onClick={() => setMobileSidebarOpen(false)}
424+ className="size-8 flex items-center justify-center rounded-md text-sidebar-foreground hover:bg-sidebar-active hover:text-foreground"
425+ >
426+ <svg viewBox="0 0 16 16" className="size-3.5">
427+ <path d="M3 3l10 10M13 3L3 13" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
428+ </svg>
429+ </button>
430+ </div>
431+ <SidebarContent
432+ pathname={pathname}
433+ onNavigate={() => setMobileSidebarOpen(false)}
434+ showBrand={false}
435+ updateAvailable={updateAvailable}
436+ latestVersion={latestVersion}
437+ channel={channel}
438+ />
439+ </div>
440+ </div>
441+ )}
442+
443+ {/* Main content */}
444+ <main className="flex min-h-0 flex-1 flex-col min-w-0 overflow-hidden">
445+ {/* Mobile top bar */}
446+ <div className="flex h-12 shrink-0 items-center justify-between border-b border-border bg-background px-4 md:hidden">
447+ <button
448+ type="button"
449+ aria-label="Open navigation"
450+ onClick={() => setMobileSidebarOpen(true)}
451+ className="size-8 flex items-center justify-center rounded-md border border-border bg-card hover:bg-accent/50"
452+ >
453+ <svg viewBox="0 0 16 16" className="size-4">
454+ <path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
455+ </svg>
456+ </button>
457+ <Link to="/" className="flex items-center gap-1.5">
458+ <span className="font-display text-base tracking-tight text-foreground">
459+ executor
460+ </span>
461+ <span className="rounded bg-primary/15 px-1.5 py-0.5 text-[10px] font-medium text-primary">
462+ v4
463+ </span>
464+ </Link>
465+ <div className="w-8 shrink-0" />
466+ </div>
467+
468+ {/* Outlet — pages control their own padding/scroll */}
469+ <Outlet />
470+ </main>
471+ </div>
472+ );
473+}
apps/web/src/views/home.tsx+0−123
@@ -1,123 +0,0 @@
1−import { Link } from "@tanstack/react-router";
2−import { useSources } from "@executor/react";
3−import { sourcePluginsIndexPath } from "@executor/react/plugins";
4−import { LoadableBlock } from "../components/loadable";
5−import { LocalMcpInstallCard } from "../components/local-mcp-install-card";
6−import { SourceFavicon } from "../components/source-favicon";
7−import { Alert, Badge, Button, Card } from "@executor/react/plugins";
8−import { IconSources, IconPlus } from "../components/icons";
9−import {
10− getSourceFrontendPaths,
11−} from "../plugins";
12−
13−const statusVariant = (status: string) =>
14− status === "connected"
15− ? "default" as const
16− : status === "error"
17− ? "destructive" as const
18− : "muted" as const;
19−
20−export function HomePage() {
21− const sources = useSources();
22−
23− return (
24− <div className="min-h-0 flex-1 overflow-y-auto">
25− <div className="mx-auto max-w-4xl px-6 py-10 lg:px-10 lg:py-14">
26− {/* Header */}
27− <div className="flex items-end justify-between mb-8">
28− <div>
29− <h1 className="font-display text-3xl tracking-tight text-foreground lg:text-4xl">
30− Sources
31− </h1>
32− <p className="mt-1.5 text-[14px] text-muted-foreground">
33− Connected tool providers in this workspace.
34− </p>
35− </div>
36− <Link to={sourcePluginsIndexPath}>
37− <Button size="sm">
38− <IconPlus className="size-3.5" />
39− Add source
40− </Button>
41− </Link>
42− </div>
43−
44− <LocalMcpInstallCard className="mb-8" />
45−
46− {/* Source list */}
47− <LoadableBlock loadable={sources} loading="Loading sources...">
48− {(items) =>
49− !Array.isArray(items) ? (
50− <Alert variant="destructive" className="px-5 py-4">
51− Sources returned an unexpected payload.
52− </Alert>
53− ) : items.length === 0 ? (
54− <div className="flex flex-col items-center justify-center rounded-2xl border border-dashed border-border py-20">
55− <div className="flex size-12 items-center justify-center rounded-2xl bg-muted text-muted-foreground mb-4">
56− <IconSources className="size-5" />
57− </div>
58− <p className="text-[14px] font-medium text-foreground/70 mb-1">
59− No sources yet
60− </p>
61− <p className="text-[13px] text-muted-foreground/60 mb-5">
62− Add a source to get started.
63− </p>
64− <Link to={sourcePluginsIndexPath}>
65− <Button size="sm">
66− <IconPlus className="size-3.5" />
67− Add source
68− </Button>
69− </Link>
70− </div>
71− ) : (
72− <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
73− {items.map((source) => {
74− const paths = getSourceFrontendPaths(source.kind);
75− const card = (
76− <Card className="flex h-full flex-col rounded-2xl px-5 py-4 transition-colors hover:border-primary/25 hover:bg-card/90">
77− <div className="flex items-start gap-3">
78− <div className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground">
79− <SourceFavicon source={source} className="size-4" />
80− </div>
81− <div className="min-w-0 flex-1">
82− <div className="flex items-start justify-between gap-2">
83− <div className="truncate text-sm font-semibold text-foreground">
84− {source.name}
85− </div>
86− <Badge variant={statusVariant(source.status)} className="shrink-0">
87− {source.status}
88− </Badge>
89− </div>
90− <div className="mt-0.5 text-xs text-muted-foreground">
91− {source.kind}
92− </div>
93− </div>
94− </div>
95− </Card>
96− );
97−
98− if (!paths) {
99− return (
100− <div key={source.id}>
101− {card}
102− </div>
103− );
104− }
105−
106− return (
107− <Link
108− key={source.id}
109− to={paths.detail(source.id)}
110− search={{ tab: "model" }}
111− >
112− {card}
113− </Link>
114− );
115− })}
116− </div>
117− )
118− }
119− </LoadableBlock>
120− </div>
121− </div>
122− );
123−}
apps/web/src/views/policies.tsx+0−652
@@ -1,652 +0,0 @@
1−import { useState, type ReactNode } from "react";
2−import {
3− type LocalScopePolicy,
4− type LocalScopePolicyApprovalMode,
5− type LocalScopePolicyEffect,
6− useCreatePolicy,
7− usePolicies,
8− useRemovePolicy,
9− useUpdatePolicy,
10−} from "@executor/react";
11−
12−import { LoadableBlock } from "../components/loadable";
13−import {
14− Alert,
15− Badge,
16− Button,
17− Card,
18− Input,
19− Label,
20− Select,
21−} from "@executor/react/plugins";
22−import {
23− IconPencil,
24− IconPlus,
25− IconSpinner,
26− IconTrash,
27−} from "../components/icons";
28−import { cn } from "../lib/utils";
29−
30−// ── Permission state helpers ────────────────────────────────────────────
31−
32−type PermissionLevel = "auto-run" | "requires-approval" | "denied";
33−
34−const resolvePermissionLevel = (
35− effect: LocalScopePolicyEffect,
36− approvalMode: LocalScopePolicyApprovalMode,
37−): PermissionLevel => {
38− if (effect === "deny") return "denied";
39− if (approvalMode === "required") return "requires-approval";
40− return "auto-run";
41−};
42−
43−const permissionConfig: Record<
44− PermissionLevel,
45− { label: string; className: string; dotClassName: string }
46−> = {
47− "auto-run": {
48− label: "Auto-run",
49− className:
50− "border-emerald-500/20 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
51− dotClassName: "bg-emerald-500",
52− },
53− "requires-approval": {
54− label: "Approval",
55− className:
56− "border-amber-500/20 bg-amber-500/10 text-amber-600 dark:text-amber-400",
57− dotClassName: "bg-amber-500",
58− },
59− denied: {
60− label: "Denied",
61− className:
62− "border-red-500/20 bg-red-500/10 text-red-600 dark:text-red-400",
63− dotClassName: "bg-red-500",
64− },
65−};
66−
67−const PermissionBadge = (props: {
68− effect: LocalScopePolicyEffect;
69− approvalMode: LocalScopePolicyApprovalMode;
70−}) => {
71− const level = resolvePermissionLevel(props.effect, props.approvalMode);
72− const config = permissionConfig[level];
73−
74− return (
75− <span
76− className={cn(
77− "inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide",
78− config.className,
79− )}
80− >
81− <span className={cn("size-1.5 rounded-full", config.dotClassName)} />
82− {config.label}
83− </span>
84− );
85−};
86−
87−// ── Page ────────────────────────────────────────────────────────────────
88−
89−export function PoliciesPage() {
90− const policies = usePolicies();
91− const [showCreate, setShowCreate] = useState(false);
92− const [editingId, setEditingId] = useState<string | null>(null);
93−
94− return (
95− <div className="min-h-0 flex-1 overflow-y-auto">
96− <div className="mx-auto flex max-w-4xl flex-col gap-8 px-6 py-10 lg:px-10 lg:py-14">
97− <div className="flex flex-wrap items-end justify-between gap-4">
98− <div>
99− <h1 className="font-display text-3xl tracking-tight text-foreground lg:text-4xl">
100− Policies
101− </h1>
102− <p className="mt-1.5 text-[14px] text-muted-foreground">
103− Control which tools can auto-run, require approval, or are
104− completely denied.
105− </p>
106− </div>
107− <Button
108− size="sm"
109− onClick={() => {
110− setShowCreate(true);
111− setEditingId(null);
112− }}
113− >
114− <IconPlus className="size-3.5" />
115− Add policy
116− </Button>
117− </div>
118−
119− {showCreate && (
120− <CreatePolicyForm
121− className="mb-2"
122− onClose={() => setShowCreate(false)}
123− />
124− )}
125−
126− <section className="space-y-4">
127− <div>
128− <h2 className="text-sm font-semibold text-foreground">
129− Active Policies
130− </h2>
131− <p className="mt-1 text-[13px] text-muted-foreground">
132− Policies are matched by resource pattern using glob syntax.
133− Higher priority rules take precedence.
134− </p>
135− </div>
136−
137− <LoadableBlock loadable={policies} loading="Loading policies...">
138− {(items) =>
139− items.length === 0 && !showCreate ? (
140− <SectionEmptyState
141− title="No policies configured"
142− description="Add a policy to control tool permissions. By default all tools require approval."
143− actionLabel="Add policy"
144− onAction={() => {
145− setShowCreate(true);
146− setEditingId(null);
147− }}
148− />
149− ) : (
150− <Card className="overflow-hidden p-0">
151− {[...items]
152− .sort((a, b) => b.priority - a.priority)
153− .map((policy, index) => (
154− <div
155− key={policy.id}
156− className={cn(
157− "px-5 py-3.5",
158− index > 0 && "border-t border-border",
159− !policy.enabled && "opacity-50",
160− )}
161− >
162− <PolicyRow
163− policy={policy}
164− isEditing={editingId === policy.id}
165− onEdit={() =>
166− setEditingId(
167− editingId === policy.id ? null : policy.id,
168− )
169− }
170− onCancelEdit={() => setEditingId(null)}
171− />
172− </div>
173− ))}
174− </Card>
175− )
176− }
177− </LoadableBlock>
178− </section>
179−
180− <section className="space-y-3">
181− <h2 className="text-sm font-semibold text-foreground">
182− How policies work
183− </h2>
184− <div className="grid gap-3 md:grid-cols-3">
185− <HelpCard level="auto-run">
186− <strong>Auto-run</strong> tools execute immediately without
187− asking. Use for trusted, read-only operations.
188− </HelpCard>
189− <HelpCard level="requires-approval">
190− <strong>Approval</strong> tools pause and ask before running.
191− The default for most tools.
192− </HelpCard>
193− <HelpCard level="denied">
194− <strong>Denied</strong> tools are blocked completely and cannot
195− be invoked.
196− </HelpCard>
197− </div>
198− <p className="text-[12px] text-muted-foreground/60">
199− Patterns use glob syntax: <code className="rounded bg-muted px-1 py-0.5 font-mono text-[11px]">*</code> matches
200− all tools, <code className="rounded bg-muted px-1 py-0.5 font-mono text-[11px]">github.*</code> matches all
201− GitHub tools, <code className="rounded bg-muted px-1 py-0.5 font-mono text-[11px]">*.delete</code> matches
202− all delete operations.
203− </p>
204− </section>
205− </div>
206− </div>
207− );
208−}
209−
210−// ── Create form ─────────────────────────────────────────────────────────
211−
212−function CreatePolicyForm(props: { className?: string; onClose: () => void }) {
213− const createPolicy = useCreatePolicy();
214− const [pattern, setPattern] = useState("*");
215− const [effect, setEffect] = useState<LocalScopePolicyEffect>("allow");
216− const [approvalMode, setApprovalMode] =
217− useState<LocalScopePolicyApprovalMode>("auto");
218− const [priority, setPriority] = useState("0");
219− const [error, setError] = useState<string | null>(null);
220−
221− const handleSubmit = async () => {
222− setError(null);
223−
224− const trimmedPattern = pattern.trim();
225− if (!trimmedPattern) {
226− setError("Resource pattern is required.");
227− return;
228− }
229−
230− try {
231− await createPolicy.mutateAsync({
232− resourcePattern: trimmedPattern,
233− effect,
234− approvalMode,
235− priority: Number(priority) || 0,
236− enabled: true,
237− });
238− props.onClose();
239− } catch (cause) {
240− setError(
241− cause instanceof Error ? cause.message : "Failed creating policy.",
242− );
243− }
244− };
245−
246− return (
247− <FormCard
248− className={props.className}
249− title="New policy"
250− onClose={props.onClose}
251− >
252− {error && <ErrorBanner>{error}</ErrorBanner>}
253− <div className="grid gap-4 sm:grid-cols-2">
254− <div className="grid gap-2 sm:col-span-2">
255− <Label>Resource pattern</Label>
256− <Input
257− value={pattern}
258− onChange={(event) => setPattern(event.target.value)}
259− placeholder="github.* or *.delete"
260− className="font-mono text-[12px]"
261− autoFocus
262− />
263− <p className="text-[11px] text-muted-foreground/60">
264− Glob pattern matched against tool paths.
265− </p>
266− </div>
267− <div className="grid gap-2">
268− <Label>Permission</Label>
269− <Select
270− value={`${effect}:${approvalMode}`}
271− onChange={(event) => {
272− const [newEffect, newApproval] = event.target.value.split(":") as [
273− LocalScopePolicyEffect,
274− LocalScopePolicyApprovalMode,
275− ];
276− setEffect(newEffect);
277− setApprovalMode(newApproval);
278− }}
279− >
280− <option value="allow:auto">Auto-run</option>
281− <option value="allow:required">Requires approval</option>
282− <option value="deny:auto">Denied</option>
283− </Select>
284− </div>
285− <div className="grid gap-2">
286− <Label>Priority</Label>
287− <Input
288− type="number"
289− value={priority}
290− onChange={(event) => setPriority(event.target.value)}
291− placeholder="0"
292− />
293− <p className="text-[11px] text-muted-foreground/60">
294− Higher priority rules win when multiple patterns match.
295− </p>
296− </div>
297− </div>
298− <div className="flex items-center justify-between">
299− <PermissionBadge effect={effect} approvalMode={approvalMode} />
300− <Button
301− size="sm"
302− onClick={handleSubmit}
303− disabled={createPolicy.status === "pending"}
304− >
305− {createPolicy.status === "pending" ? (
306− <IconSpinner className="size-3.5" />
307− ) : (
308− <IconPlus className="size-3.5" />
309− )}
310− Create policy
311− </Button>
312− </div>
313− </FormCard>
314− );
315−}
316−
317−// ── Policy row ──────────────────────────────────────────────────────────
318−
319−function PolicyRow(props: {
320− policy: LocalScopePolicy;
321− isEditing: boolean;
322− onEdit: () => void;
323− onCancelEdit: () => void;
324−}) {
325− const removePolicy = useRemovePolicy();
326− const [isDeleting, setIsDeleting] = useState(false);
327− const [confirmDelete, setConfirmDelete] = useState(false);
328−
329− const handleDelete = async () => {
330− setIsDeleting(true);
331− try {
332− await removePolicy.mutateAsync(props.policy.id);
333− } catch {
334− // refresh state will keep the policy visible
335− } finally {
336− setIsDeleting(false);
337− setConfirmDelete(false);
338− }
339− };
340−
341− return (
342− <>
343− <div className="flex items-center justify-between gap-4">
344− <div className="min-w-0">
345− <div className="flex flex-wrap items-center gap-2">
346− <span className="truncate font-mono text-[13px] font-medium text-foreground">
347− {props.policy.resourcePattern}
348− </span>
349− <PermissionBadge
350− effect={props.policy.effect}
351− approvalMode={props.policy.approvalMode}
352− />
353− {!props.policy.enabled && (
354− <Badge variant="outline" className="text-[9px] uppercase">
355− disabled
356− </Badge>
357− )}
358− {props.policy.priority !== 0 && (
359− <Badge variant="outline" className="text-[9px]">
360− priority {props.policy.priority}
361− </Badge>
362− )}
363− </div>
364− <div className="mt-0.5 flex flex-wrap items-center gap-2 text-[11px] text-muted-foreground/50">
365− <span className="font-mono">{props.policy.id}</span>
366− <span>{formatDate(props.policy.createdAt)}</span>
367− </div>
368− </div>
369− <div className="flex shrink-0 items-center gap-1.5">
370− <Button
371− variant="ghost"
372− size="sm"
373− onClick={props.onEdit}
374− className={cn(
375− props.isEditing
376− ? "bg-primary/10 text-primary"
377− : "text-muted-foreground hover:bg-accent/50 hover:text-foreground",
378− )}
379− >
380− <IconPencil className="size-3" />
381− Edit
382− </Button>
383− {confirmDelete ? (
384− <>
385− <Button
386− variant="ghost"
387− size="sm"
388− onClick={() => setConfirmDelete(false)}
389− disabled={isDeleting}
390− >
391− Cancel
392− </Button>
393− <Button
394− variant="destructive-outline"
395− size="sm"
396− onClick={() => {
397− void handleDelete();
398− }}
399− disabled={isDeleting}
400− >
401− {isDeleting ? (
402− <IconSpinner className="size-3" />
403− ) : (
404− <IconTrash className="size-3" />
405− )}
406− Delete
407− </Button>
408− </>
409− ) : (
410− <Button
411− variant="ghost"
412− size="sm"
413− onClick={() => setConfirmDelete(true)}
414− disabled={isDeleting}
415− className="text-muted-foreground hover:bg-destructive/8 hover:text-destructive"
416− >
417− {isDeleting ? (
418− <IconSpinner className="size-3" />
419− ) : (
420− <IconTrash className="size-3" />
421− )}
422− Delete
423− </Button>
424− )}
425− </div>
426− </div>
427−
428− {props.isEditing && (
429− <EditPolicyForm policy={props.policy} onClose={props.onCancelEdit} />
430− )}
431− </>
432− );
433−}
434−
435−// ── Edit form ───────────────────────────────────────────────────────────
436−
437−function EditPolicyForm(props: {
438− policy: LocalScopePolicy;
439− onClose: () => void;
440−}) {
441− const updatePolicy = useUpdatePolicy();
442− const [pattern, setPattern] = useState(props.policy.resourcePattern);
443− const [effect, setEffect] = useState<LocalScopePolicyEffect>(
444− props.policy.effect,
445− );
446− const [approvalMode, setApprovalMode] =
447− useState<LocalScopePolicyApprovalMode>(props.policy.approvalMode);
448− const [priority, setPriority] = useState(String(props.policy.priority));
449− const [enabled, setEnabled] = useState(props.policy.enabled);
450− const [error, setError] = useState<string | null>(null);
451−
452− const handleSubmit = async () => {
453− setError(null);
454−
455− const payload: Record<string, unknown> = {};
456− const trimmedPattern = pattern.trim();
457−
458− if (trimmedPattern && trimmedPattern !== props.policy.resourcePattern) {
459− payload.resourcePattern = trimmedPattern;
460− }
461− if (effect !== props.policy.effect) {
462− payload.effect = effect;
463− }
464− if (approvalMode !== props.policy.approvalMode) {
465− payload.approvalMode = approvalMode;
466− }
467− const numPriority = Number(priority) || 0;
468− if (numPriority !== props.policy.priority) {
469− payload.priority = numPriority;
470− }
471− if (enabled !== props.policy.enabled) {
472− payload.enabled = enabled;
473− }
474−
475− if (Object.keys(payload).length === 0) {
476− props.onClose();
477− return;
478− }
479−
480− try {
481− await updatePolicy.mutateAsync({
482− policyId: props.policy.id,
483− payload,
484− });
485− props.onClose();
486− } catch (cause) {
487− setError(
488− cause instanceof Error ? cause.message : "Failed updating policy.",
489− );
490− }
491− };
492−
493− return (
494− <div className="mt-3 border-t border-border/50 pt-3">
495− {error && <ErrorBanner className="mb-3">{error}</ErrorBanner>}
496− <div className="grid gap-3 sm:grid-cols-2">
497− <div className="grid gap-2 sm:col-span-2">
498− <Label>Resource pattern</Label>
499− <Input
500− value={pattern}
501− onChange={(event) => setPattern(event.target.value)}
502− placeholder="github.* or *.delete"
503− className="h-8 font-mono text-[12px]"
504− autoFocus
505− />
506− </div>
507− <div className="grid gap-2">
508− <Label>Permission</Label>
509− <Select
510− value={`${effect}:${approvalMode}`}
511− onChange={(event) => {
512− const [newEffect, newApproval] = event.target.value.split(":") as [
513− LocalScopePolicyEffect,
514− LocalScopePolicyApprovalMode,
515− ];
516− setEffect(newEffect);
517− setApprovalMode(newApproval);
518− }}
519− className="h-8 text-[12px]"
520− >
521− <option value="allow:auto">Auto-run</option>
522− <option value="allow:required">Requires approval</option>
523− <option value="deny:auto">Denied</option>
524− </Select>
525− </div>
526− <div className="grid gap-2">
527− <Label>Priority</Label>
528− <Input
529− type="number"
530− value={priority}
531− onChange={(event) => setPriority(event.target.value)}
532− placeholder="0"
533− className="h-8 text-[12px]"
534− />
535− </div>
536− </div>
537− <div className="mt-3 flex items-center justify-between">
538− <label className="flex items-center gap-2 text-[12px] text-muted-foreground">
539− <input
540− type="checkbox"
541− checked={enabled}
542− onChange={(event) => setEnabled(event.target.checked)}
543− className="rounded border-border"
544− />
545− Enabled
546− </label>
547− <div className="flex items-center gap-2">
548− <PermissionBadge effect={effect} approvalMode={approvalMode} />
549− <Button variant="ghost" size="sm" onClick={props.onClose}>
550− Cancel
551− </Button>
552− <Button
553− size="sm"
554− onClick={handleSubmit}
555− disabled={updatePolicy.status === "pending"}
556− >
557− {updatePolicy.status === "pending" && (
558− <IconSpinner className="size-3" />
559− )}
560− Save
561− </Button>
562− </div>
563− </div>
564− </div>
565− );
566−}
567−
568−// ── Shared components ───────────────────────────────────────────────────
569−
570−function HelpCard(props: { level: PermissionLevel; children: ReactNode }) {
571− const config = permissionConfig[props.level];
572−
573− return (
574− <div
575− className={cn(
576− "rounded-xl border px-4 py-3 text-[12px] leading-relaxed",
577− config.className,
578− )}
579− >
580− <div className="mb-1.5 flex items-center gap-1.5">
581− <span className={cn("size-2 rounded-full", config.dotClassName)} />
582− <span className="text-[10px] font-semibold uppercase tracking-wide">
583− {config.label}
584− </span>
585− </div>
586− <p className="text-foreground/70">{props.children}</p>
587− </div>
588− );
589−}
590−
591−function FormCard(props: {
592− title: string;
593− onClose: () => void;
594− className?: string;
595− children: ReactNode;
596−}) {
597− return (
598− <Card className={cn("border-primary/20 p-0", props.className)}>
599− <div className="flex items-center justify-between border-b border-border px-5 py-3">
600− <h3 className="text-sm font-semibold text-foreground">{props.title}</h3>
601− <Button variant="ghost" size="sm" onClick={props.onClose}>
602− Cancel
603− </Button>
604− </div>
605− <div className="space-y-4 p-5">{props.children}</div>
606− </Card>
607− );
608−}
609−
610−function ErrorBanner(props: { children: ReactNode; className?: string }) {
611− return (
612− <Alert
613− variant="destructive"
614− className={cn("text-[13px]", props.className)}
615− >
616− {props.children}
617− </Alert>
618− );
619−}
620−
621−function SectionEmptyState(props: {
622− title: string;
623− description: string;
624− actionLabel?: string;
625− onAction?: () => void;
626−}) {
627− return (
628− <div className="rounded-xl border border-dashed border-border px-6 py-10 text-center">
629− <p className="text-[14px] font-medium text-foreground/75">
630− {props.title}
631− </p>
632− <p className="mt-1 text-[13px] text-muted-foreground">
633− {props.description}
634− </p>
635− {props.actionLabel && props.onAction && (
636− <div className="mt-4 flex justify-center">
637− <Button size="sm" onClick={props.onAction}>
638− <IconPlus className="size-3.5" />
639− {props.actionLabel}
640− </Button>
641− </div>
642− )}
643− </div>
644− );
645−}
646−
647−const formatDate = (value: number): string =>
648− new Date(value).toLocaleDateString(undefined, {
649− month: "short",
650− day: "numeric",
651− year: "numeric",
652− });
apps/web/src/views/secrets.tsx+0−1073
@@ -1,1073 +0,0 @@
1−import { useCallback, useEffect, useState, type ReactNode } from "react";
2−import {
3− type BrowseSecretStoreResult,
4− getExecutorApiBaseUrl,
5− type InstanceConfig,
6− type Loadable,
7− type SecretListItem,
8− type SecretStore,
9− useCreateSecret,
10− useCreateSecretStore,
11− useDeleteSecret,
12− useDeleteSecretStore,
13− useExecutorMutation,
14− useInstanceConfig,
15− useRefreshSecrets,
16− useSecretStores,
17− useSecrets,
18− useUpdateSecret,
19−} from "@executor/react";
20−
21−import { LoadableBlock } from "../components/loadable";
22−import { Badge } from "@executor/react/plugins";
23−import {
24− Alert,
25− Button,
26− Card,
27− Input,
28− Label,
29− Select,
30−} from "@executor/react/plugins";
31−import {
32− IconPencil,
33− IconPlus,
34− IconSpinner,
35− IconTrash,
36−} from "../components/icons";
37−import { cn } from "../lib/utils";
38−import { getSecretStoreFrontendPlugin } from "../plugins";
39−
40−const creatableStorePluginsFromConfig = (config: Loadable<InstanceConfig>) =>
41− config.status === "ready"
42− ? config.data.secretStorePlugins.filter((plugin) => plugin.canCreate)
43− : [];
44−
45−const canManageStoreKind = (
46− config: Loadable<InstanceConfig>,
47− kind: string,
48−): boolean =>
49− config.status === "ready"
50− ? config.data.secretStorePlugins.some((plugin) =>
51− plugin.kind === kind && plugin.canCreate
52− )
53− : false;
54−
55−const defaultStoreLabel = (
56− config: Loadable<InstanceConfig>,
57− stores: Loadable<ReadonlyArray<SecretStore>>,
58−): string | null => {
59− if (
60− config.status !== "ready"
61− || stores.status !== "ready"
62− || config.data.defaultSecretStoreId === null
63− ) {
64− return null;
65− }
66−
67− return stores.data.find((store) =>
68− store.id === config.data.defaultSecretStoreId
69− )?.name ?? null;
70−};
71−
72−type SecretStoreBrowserEntry = BrowseSecretStoreResult["entries"][number];
73−type SecretStoreBrowserCrumb = {
74− key: string;
75− label: string;
76−};
77−
78−const canBrowseAndImportStore = (store: SecretStore | null): boolean =>
79− store?.capabilities.canBrowseSecrets === true
80− && store.capabilities.canImportSecrets === true;
81−
82−export function SecretsPage() {
83− const instanceConfig = useInstanceConfig();
84− const secretStores = useSecretStores();
85− const secrets = useSecrets();
86− const [showCreateStore, setShowCreateStore] = useState(false);
87− const [showCreateSecret, setShowCreateSecret] = useState(false);
88− const [editingId, setEditingId] = useState<string | null>(null);
89−
90− const creatableStorePlugins = creatableStorePluginsFromConfig(instanceConfig);
91− const defaultLabel = defaultStoreLabel(instanceConfig, secretStores);
92−
93− return (
94− <div className="min-h-0 flex-1 overflow-y-auto">
95− <div className="mx-auto flex max-w-4xl flex-col gap-8 px-6 py-10 lg:px-10 lg:py-14">
96− <div className="flex flex-wrap items-end justify-between gap-4">
97− <div>
98− <h1 className="font-display text-3xl tracking-tight text-foreground lg:text-4xl">
99− Secrets
100− </h1>
101− <p className="mt-1.5 text-[14px] text-muted-foreground">
102− Manage secret stores and the secrets linked into sources.
103− {defaultLabel ? ` New secrets default to ${defaultLabel}.` : ""}
104− </p>
105− </div>
106− <div className="flex gap-2">
107− <Button
108− size="sm"
109− onClick={() => {
110− setShowCreateSecret(true);
111− setEditingId(null);
112− }}
113− >
114− <IconPlus className="size-3.5" />
115− Add secret
116− </Button>
117− </div>
118− </div>
119−
120− <section className="space-y-4">
121− <div>
122− <h2 className="text-sm font-semibold text-foreground">Stores</h2>
123− <p className="mt-1 text-[13px] text-muted-foreground">
124− Local and external backends that hold managed secrets.
125− </p>
126− </div>
127−
128− {showCreateStore && (
129− <CreateSecretStoreForm
130− className="mb-2"
131− onClose={() => setShowCreateStore(false)}
132− pluginOptions={creatableStorePlugins}
133− secrets={secrets}
134− />
135− )}
136−
137− <LoadableBlock loadable={secretStores} loading="Loading stores...">
138− {(items) =>
139− items.length === 0 ? (
140− <SectionEmptyState
141− title="No secret stores yet"
142− description="External secret stores are currently unavailable in this app."
143− />
144− ) : (
145− <div className="grid gap-3 md:grid-cols-2">
146− {items.map((store) => (
147− <SecretStoreCard
148− key={store.id}
149− store={store}
150− canManage={canManageStoreKind(instanceConfig, store.kind)}
151− />
152− ))}
153− </div>
154− )
155− }
156− </LoadableBlock>
157− </section>
158−
159− <section className="space-y-4">
160− <div>
161− <h2 className="text-sm font-semibold text-foreground">Managed Secrets</h2>
162− <p className="mt-1 text-[13px] text-muted-foreground">
163− Secret records stay stable even if their underlying store handle changes.
164− </p>
165− </div>
166−
167− {showCreateSecret && (
168− <CreateSecretForm
169− className="mb-2"
170− onClose={() => setShowCreateSecret(false)}
171− storeOptions={secretStores.status === "ready" ? secretStores.data : []}
172− defaultStoreId={
173− instanceConfig.status === "ready"
174− ? instanceConfig.data.defaultSecretStoreId
175− : null
176− }
177− />
178− )}
179−
180− <LoadableBlock loadable={secrets} loading="Loading secrets...">
181− {(items) =>
182− items.length === 0 && !showCreateSecret ? (
183− <SectionEmptyState
184− title="No secrets stored"
185− description="Add a secret to use it in source authentication and runtime resolution."
186− actionLabel="Add secret"
187− onAction={() => {
188− setShowCreateSecret(true);
189− setEditingId(null);
190− }}
191− />
192− ) : (
193− <Card className="overflow-hidden p-0">
194− {items.map((secret, index) => (
195− <div
196− key={secret.id}
197− className={cn(
198− "px-5 py-3.5",
199− index > 0 && "border-t border-border",
200− )}
201− >
202− <SecretRow
203− secret={secret}
204− isEditing={editingId === secret.id}
205− onEdit={() =>
206− setEditingId(editingId === secret.id ? null : secret.id)}
207− onCancelEdit={() => setEditingId(null)}
208− />
209− </div>
210− ))}
211− </Card>
212− )
213− }
214− </LoadableBlock>
215− </section>
216− </div>
217− </div>
218− );
219−}
220−
221−function CreateSecretStoreForm(props: {
222− className?: string;
223− onClose: () => void;
224− pluginOptions: ReadonlyArray<{
225− kind: string;
226− displayName: string;
227− canCreate: boolean;
228− }>;
229− secrets: Loadable<ReadonlyArray<SecretListItem>>;
230−}) {
231− const createSecretStore = useCreateSecretStore();
232− const [kind, setKind] = useState(props.pluginOptions[0]?.kind ?? "");
233− const [name, setName] = useState("");
234− const [error, setError] = useState<string | null>(null);
235− const selectedFrontendPlugin = getSecretStoreFrontendPlugin(kind);
236− const StoreCreateForm = selectedFrontendPlugin?.secretStore?.CreateStoreForm;
237−
238− useEffect(() => {
239− if (kind.length > 0 || props.pluginOptions.length === 0) {
240− return;
241− }
242− setKind(props.pluginOptions[0]!.kind);
243− }, [kind, props.pluginOptions]);
244−
245− const handleSubmit = async () => {
246− setError(null);
247−
248− const trimmedName = name.trim();
249− if (!trimmedName) {
250− setError("Store name is required.");
251− return;
252− }
253−
254− try {
255− await createSecretStore.mutateAsync({
256− kind,
257− name: trimmedName,
258− config: {},
259− });
260− props.onClose();
261− } catch (cause) {
262− setError(
263− cause instanceof Error ? cause.message : "Failed creating secret store.",
264− );
265− }
266− };
267−
268− return (
269− <FormCard
270− className={props.className}
271− title="New secret store"
272− onClose={props.onClose}
273− >
274− {error && <ErrorBanner>{error}</ErrorBanner>}
275− {props.pluginOptions.length === 0 ? (
276− <div className="rounded-lg border border-border bg-background/40 px-4 py-3 text-[13px] text-muted-foreground">
277− No external secret store plugins are available in this runtime.
278− </div>
279− ) : (
280− <>
281− <div className="grid gap-4 sm:grid-cols-2">
282− <div className="grid gap-2">
283− <Label>Store type</Label>
284− <Select
285− value={kind}
286− onChange={(event) => setKind(event.target.value)}
287− >
288− {props.pluginOptions.map((plugin) => (
289− <option key={plugin.kind} value={plugin.kind}>
290− {plugin.displayName}
291− </option>
292− ))}
293− </Select>
294− </div>
295− {!StoreCreateForm && (
296− <div className="grid gap-2">
297− <Label>Name</Label>
298− <Input
299− value={name}
300− onChange={(event) => setName(event.target.value)}
301− placeholder="Secret store"
302− autoFocus
303− />
304− </div>
305− )}
306− </div>
307−
308− {StoreCreateForm ? (
309− <StoreCreateForm
310− isSubmitting={createSecretStore.status === "pending"}
311− onCancel={props.onClose}
312− onSubmit={async (input) => {
313− await createSecretStore.mutateAsync({
314− kind,
315− name: input.name,
316− config: input.config,
317− });
318− props.onClose();
319− }}
320− secrets={props.secrets}
321− />
322− ) : (
323− <div className="flex justify-end">
324− <Button
325− size="sm"
326− onClick={handleSubmit}
327− disabled={createSecretStore.status === "pending"}
328− >
329− {createSecretStore.status === "pending"
330− ? <IconSpinner className="size-3.5" />
331− : <IconPlus className="size-3.5" />}
332− Create store
333− </Button>
334− </div>
335− )}
336− </>
337− )}
338− </FormCard>
339− );
340−}
341−
342−function CreateSecretForm(props: {
343− className?: string;
344− onClose: () => void;
345− storeOptions: ReadonlyArray<SecretStore>;
346− defaultStoreId: string | null;
347−}) {
348− const createSecret = useCreateSecret();
349− const refreshSecrets = useRefreshSecrets();
350− const [mode, setMode] = useState<"create" | "import">("create");
351− const [name, setName] = useState("");
352− const [value, setValue] = useState("");
353− const [storeId, setStoreId] = useState(props.defaultStoreId ?? "");
354− const [browserStack, setBrowserStack] = useState<ReadonlyArray<SecretStoreBrowserCrumb>>(
355− [],
356− );
357− const [browserQuery, setBrowserQuery] = useState("");
358− const [browserEntries, setBrowserEntries] = useState<
359− ReadonlyArray<SecretStoreBrowserEntry>
360− >([]);
361− const [browserStatus, setBrowserStatus] = useState<"idle" | "pending">("idle");
362− const [browserError, setBrowserError] = useState<string | null>(null);
363− const [selectedImportKey, setSelectedImportKey] = useState("");
364− const [selectedImportLabel, setSelectedImportLabel] = useState("");
365− const [error, setError] = useState<string | null>(null);
366− const selectedStore = props.storeOptions.find((store) => store.id === storeId) ?? null;
367− const canImportSecrets = canBrowseAndImportStore(selectedStore);
368− const canCreateSecrets = selectedStore?.capabilities.canCreateSecrets !== false;
369− const currentParentKey = browserStack[browserStack.length - 1]?.key ?? null;
370−
371− const browseStore = useCallback(
372− async (input: {
373− storeId: string;
374− parentKey?: string | null;
375− query?: string | null;
376− }) => {
377− const response = await fetch(
378− `${getExecutorApiBaseUrl()}/v1/local/secret-stores/${input.storeId}/browse`,
379− {
380− method: "POST",
381− headers: {
382− "content-type": "application/json",
383− },
384− body: JSON.stringify({
385− ...(input.parentKey ? { parentKey: input.parentKey } : {}),
386− ...(input.query?.trim() ? { query: input.query.trim() } : {}),
387− }),
388− },
389− );
390−
391− if (!response.ok) {
392− let message = "Failed browsing secret store.";
393− try {
394− const payload = await response.json() as {
395− message?: string;
396− details?: string;
397− };
398− message = payload.message ?? payload.details ?? message;
399− } catch {
400− // ignore response parsing errors
401− }
402− throw new Error(message);
403− }
404−
405− return await response.json() as BrowseSecretStoreResult;
406− },
407− [],
408− );
409− const importSecretMutation = useExecutorMutation<void, { id: string }>(async () => {
410− const response = await fetch(
411− `${getExecutorApiBaseUrl()}/v1/local/secret-stores/${storeId}/import`,
412− {
413− method: "POST",
414− headers: {
415− "content-type": "application/json",
416− },
417− body: JSON.stringify({
418− selectionKey: selectedImportKey,
419− ...(name.trim() ? { name: name.trim() } : {}),
420− }),
421− },
422− );
423−
424− if (!response.ok) {
425− let message = "Failed importing secret.";
426− try {
427− const payload = await response.json() as {
428− message?: string;
429− details?: string;
430− };
431− message = payload.message ?? payload.details ?? message;
432− } catch {
433− // ignore response parsing errors
434− }
435− throw new Error(message);
436− }
437−
438− return await response.json() as { id: string };
439− });
440−
441− useEffect(() => {
442− if (storeId.length > 0) {
443− return;
444− }
445− if (props.defaultStoreId) {
446− setStoreId(props.defaultStoreId);
447− return;
448− }
449− if (props.storeOptions.length > 0) {
450− setStoreId(props.storeOptions[0]!.id);
451− }
452− }, [props.defaultStoreId, props.storeOptions, storeId]);
453−
454− useEffect(() => {
455− setBrowserStack([]);
456− setBrowserQuery("");
457− setBrowserEntries([]);
458− setBrowserStatus("idle");
459− setBrowserError(null);
460− setSelectedImportKey("");
461− setSelectedImportLabel("");
462− if (canImportSecrets && !canCreateSecrets) {
463− setMode("import");
464− return;
465− }
466− if (!canImportSecrets && canCreateSecrets) {
467− setMode("create");
468− return;
469− }
470− if (canImportSecrets) {
471− setMode("import");
472− return;
473− }
474− setMode("create");
475− }, [canCreateSecrets, canImportSecrets, selectedStore?.id]);
476−
477− useEffect(() => {
478− if (mode !== "import" || !canImportSecrets || !storeId) {
479− return;
480− }
481−
482− let active = true;
483− setBrowserStatus("pending");
484− void browseStore({
485− storeId,
486− parentKey: currentParentKey,
487− query: browserQuery,
488− })
489− .then((result) => {
490− if (!active) {
491− return;
492− }
493− setBrowserEntries(result.entries);
494− setBrowserError(null);
495− setBrowserStatus("idle");
496− })
497− .catch((cause) => {
498− if (!active) {
499− return;
500− }
501− setBrowserEntries([]);
502− setBrowserError(
503− cause instanceof Error ? cause.message : "Failed browsing secret store.",
504− );
505− setBrowserStatus("idle");
506− });
507−
508− return () => {
509− active = false;
510− };
511− }, [browserQuery, browseStore, canImportSecrets, currentParentKey, mode, storeId]);
512−
513− useEffect(() => {
514− if (mode !== "import" || !selectedImportLabel || name.trim().length > 0) {
515− return;
516− }
517− setName(selectedImportLabel);
518− }, [mode, name, selectedImportLabel]);
519−
520− const handleBrowserEntryClick = (entry: SecretStoreBrowserEntry) => {
521− setError(null);
522− if (entry.kind === "group") {
523− setSelectedImportKey("");
524− setSelectedImportLabel("");
525− setBrowserStack((current) => [...current, {
526− key: entry.key,
527− label: entry.label,
528− }]);
529− setBrowserQuery("");
530− return;
531− }
532−
533− setSelectedImportKey(entry.key);
534− setSelectedImportLabel(entry.label);
535− };
536−
537− const handleSubmit = async () => {
538− setError(null);
539− const trimmedName = name.trim();
540−
541− try {
542− if (mode === "import") {
543− if (!selectedImportKey) {
544− setError("Select a secret to import.");
545− return;
546− }
547−
548− await importSecretMutation.mutateAsync();
549− refreshSecrets();
550− } else {
551− if (!trimmedName) {
552− setError("Name is required.");
553− return;
554− }
555− if (!value) {
556− setError("Value is required.");
557− return;
558− }
559−
560− await createSecret.mutateAsync({
561− name: trimmedName,
562− value,
563− ...(storeId ? { storeId } : {}),
564− });
565− }
566−
567− props.onClose();
568− } catch (cause) {
569− setError(cause instanceof Error ? cause.message : "Failed creating secret.");
570− }
571− };
572−
573− return (
574− <FormCard
575− className={props.className}
576− title="New managed secret"
577− onClose={props.onClose}
578− >
579− {error && <ErrorBanner>{error}</ErrorBanner>}
580− <div className="grid gap-4 sm:grid-cols-2">
581− <div className="grid gap-2">
582− <Label>Store</Label>
583− <Select
584− value={storeId}
585− onChange={(event) => setStoreId(event.target.value)}
586− >
587− {props.storeOptions.map((store) => (
588− <option key={store.id} value={store.id}>
589− {store.name}
590− </option>
591− ))}
592− </Select>
593− </div>
594− {canImportSecrets && canCreateSecrets && (
595− <div className="grid gap-2">
596− <Label>Mode</Label>
597− <Select
598− value={mode}
599− onChange={(event) => setMode(event.target.value as "create" | "import")}
600− >
601− <option value="import">Import from store</option>
602− <option value="create">Create new secret</option>
603− </Select>
604− </div>
605− )}
606− <div className="grid gap-2">
607− <Label>Name</Label>
608− <Input
609− value={name}
610− onChange={(event) => setName(event.target.value)}
611− placeholder={mode === "import" ? "Optional override name" : "GitHub PAT"}
612− autoFocus
613− />
614− </div>
615− {mode === "create" && (
616− <div className="grid gap-2">
617− <Label>Value</Label>
618− <Input
619− type="password"
620− value={value}
621− onChange={(event) => setValue(event.target.value)}
622− placeholder="ghp_..."
623− className="font-mono text-[12px]"
624− />
625− </div>
626− )}
627− </div>
628− {mode === "import" && canImportSecrets && (
629− <div className="mt-4 space-y-4">
630− <div className="flex flex-wrap items-center gap-2">
631− {browserStack.length > 0 && (
632− <Button
633− size="sm"
634− variant="outline"
635− onClick={() => {
636− setSelectedImportKey("");
637− setSelectedImportLabel("");
638− setBrowserStack((current) => current.slice(0, -1));
639− }}
640− >
641− Back
642− </Button>
643− )}
644− <Input
645− value={browserQuery}
646− onChange={(event) => setBrowserQuery(event.target.value)}
647− placeholder="Search this store"
648− className="min-w-0 flex-1"
649− />
650− </div>
651− {browserStack.length > 0 && (
652− <div className="text-[11px] text-muted-foreground">
653− {browserStack.map((crumb, index) => (
654− <span key={crumb.key}>
655− {index > 0 ? " / " : ""}
656− {crumb.label}
657− </span>
658− ))}
659− </div>
660− )}
661− <div className="rounded-xl border border-border bg-background/40">
662− {browserStatus === "pending" ? (
663− <div className="flex items-center gap-2 px-4 py-3 text-[13px] text-muted-foreground">
664− <IconSpinner className="size-3.5" />
665− Loading store contents...
666− </div>
667− ) : browserEntries.length === 0 ? (
668− <div className="px-4 py-3 text-[13px] text-muted-foreground">
669− {browserError ?? "No importable secrets found here."}
670− </div>
671− ) : (
672− browserEntries.map((entry, index) => (
673− <Button
674− key={entry.key}
675− variant="ghost"
676− onClick={() => handleBrowserEntryClick(entry)}
677− className={cn(
678− "flex h-auto w-full items-center justify-between gap-3 rounded-none px-4 py-3 text-left",
679− index > 0 && "border-t border-border",
680− selectedImportKey === entry.key && "bg-accent/60",
681− )}
682− >
683− <div className="min-w-0">
684− <div className="truncate text-[13px] font-medium text-foreground">
685− {entry.label}
686− </div>
687− {entry.description && (
688− <div className="truncate text-[11px] text-muted-foreground">
689− {entry.description}
690− </div>
691− )}
692− </div>
693− <Badge variant="outline">
694− {entry.kind === "group" ? "Open" : "Secret"}
695− </Badge>
696− </Button>
697− ))
698− )}
699− </div>
700− {browserError && browserEntries.length > 0 && (
701− <div className="text-[12px] text-destructive">{browserError}</div>
702− )}
703− </div>
704− )}
705− <div className="flex justify-end">
706− <Button
707− size="sm"
708− onClick={handleSubmit}
709− disabled={createSecret.status === "pending" || importSecretMutation.status === "pending"}
710− >
711− {(createSecret.status === "pending" || importSecretMutation.status === "pending")
712− ? <IconSpinner className="size-3.5" />
713− : <IconPlus className="size-3.5" />}
714− {mode === "import" ? "Import secret" : "Store secret"}
715− </Button>
716− </div>
717− </FormCard>
718− );
719−}
720−
721−function SecretStoreCard(props: {
722− store: SecretStore;
723− canManage: boolean;
724−}) {
725− const deleteSecretStore = useDeleteSecretStore();
726− const [confirmDelete, setConfirmDelete] = useState(false);
727− const [isDeleting, setIsDeleting] = useState(false);
728−
729− const handleDelete = async () => {
730− setIsDeleting(true);
731− try {
732− await deleteSecretStore.mutateAsync(props.store.id);
733− } catch {
734− // refresh state will keep the store visible
735− } finally {
736− setIsDeleting(false);
737− setConfirmDelete(false);
738− }
739− };
740−
741− return (
742− <Card className="p-4">
743− <div className="flex items-start justify-between gap-3">
744− <div className="min-w-0">
745− <div className="flex flex-wrap items-center gap-2">
746− <span className="truncate text-[13px] font-medium text-foreground">
747− {props.store.name}
748− </span>
749− <Badge variant="outline" className="text-[9px] uppercase">
750− {props.store.kind}
751− </Badge>
752− <Badge variant="outline" className="text-[9px]">
753− {props.store.status}
754− </Badge>
755− </div>
756− <div className="mt-1 flex flex-wrap items-center gap-2 text-[11px] text-muted-foreground/55">
757− <span className="font-mono">{props.store.id}</span>
758− <span>Created {formatDate(props.store.createdAt)}</span>
759− </div>
760− </div>
761− {props.canManage ? (
762− confirmDelete ? (
763− <div className="flex items-center gap-1">
764− <Button
765− variant="ghost"
766− size="sm"
767− onClick={() => setConfirmDelete(false)}
768− disabled={isDeleting}
769− >
770− Cancel
771− </Button>
772− <Button
773− variant="destructive-outline"
774− size="sm"
775− onClick={() => {
776− void handleDelete();
777− }}
778− disabled={isDeleting}
779− >
780− {isDeleting
781− ? <IconSpinner className="size-3" />
782− : <IconTrash className="size-3" />}
783− Delete
784− </Button>
785− </div>
786− ) : (
787− <Button
788− variant="ghost"
789− size="sm"
790− onClick={() => setConfirmDelete(true)}
791− disabled={isDeleting}
792− className="text-muted-foreground hover:bg-destructive/8 hover:text-destructive"
793− >
794− {isDeleting
795− ? <IconSpinner className="size-3" />
796− : <IconTrash className="size-3" />}
797− Remove
798− </Button>
799− )
800− ) : (
801− <span className="text-[10px] font-medium uppercase tracking-[0.12em] text-muted-foreground/45">
802− Built-in
803− </span>
804− )}
805− </div>
806− </Card>
807− );
808−}
809−
810−function SecretRow(props: {
811− secret: SecretListItem;
812− isEditing: boolean;
813− onEdit: () => void;
814− onCancelEdit: () => void;
815−}) {
816− const deleteSecret = useDeleteSecret();
817− const [isDeleting, setIsDeleting] = useState(false);
818− const [confirmDelete, setConfirmDelete] = useState(false);
819−
820− const handleDelete = async () => {
821− setIsDeleting(true);
822− try {
823− await deleteSecret.mutateAsync(props.secret.id);
824− } catch {
825− // refresh state will keep the secret visible
826− } finally {
827− setIsDeleting(false);
828− setConfirmDelete(false);
829− }
830− };
831−
832− return (
833− <>
834− <div className="flex items-center justify-between gap-4">
835− <div className="min-w-0">
836− <div className="flex flex-wrap items-center gap-2">
837− <span className="truncate text-[13px] font-medium text-foreground">
838− {props.secret.name || "Unnamed secret"}
839− </span>
840− <Badge variant="outline" className="text-[9px] shrink-0">
841− {props.secret.purpose.replace(/_/g, " ")}
842− </Badge>
843− <Badge variant="outline" className="text-[9px] shrink-0">
844− {props.secret.storeName}
845− </Badge>
846− <Badge variant="outline" className="text-[9px] shrink-0 uppercase">
847− {props.secret.storeKind}
848− </Badge>
849− </div>
850− <div className="mt-0.5 flex flex-wrap items-center gap-2 text-[11px] text-muted-foreground/50">
851− <span className="font-mono">{props.secret.id}</span>
852− <span>{formatDate(props.secret.createdAt)}</span>
853− </div>
854− {props.secret.linkedSources.length > 0 && (
855− <div className="mt-1 flex flex-wrap items-center gap-1.5">
856− <span className="text-[10px] text-muted-foreground/50">Used by</span>
857− {props.secret.linkedSources.map((linkedSource) => (
858− <span
859− key={linkedSource.sourceId}
860− className="inline-flex items-center rounded-md bg-accent/60 px-1.5 py-0.5 text-[10px] font-medium text-foreground/70"
861− >
862− {linkedSource.sourceName}
863− </span>
864− ))}
865− </div>
866− )}
867− </div>
868− <div className="flex shrink-0 items-center gap-1.5">
869− <Button
870− variant="ghost"
871− size="sm"
872− onClick={props.onEdit}
873− className={cn(
874− props.isEditing
875− ? "bg-primary/10 text-primary"
876− : "text-muted-foreground hover:bg-accent/50 hover:text-foreground",
877− )}
878− >
879− <IconPencil className="size-3" />
880− Edit
881− </Button>
882− {confirmDelete ? (
883− <>
884− <Button
885− variant="ghost"
886− size="sm"
887− onClick={() => setConfirmDelete(false)}
888− disabled={isDeleting}
889− >
890− Cancel
891− </Button>
892− <Button
893− variant="destructive-outline"
894− size="sm"
895− onClick={() => {
896− void handleDelete();
897− }}
898− disabled={isDeleting}
899− >
900− {isDeleting
901− ? <IconSpinner className="size-3" />
902− : <IconTrash className="size-3" />}
903− Delete
904− </Button>
905− </>
906− ) : (
907− <Button
908− variant="ghost"
909− size="sm"
910− onClick={() => setConfirmDelete(true)}
911− disabled={isDeleting}
912− className="text-muted-foreground hover:bg-destructive/8 hover:text-destructive"
913− >
914− {isDeleting
915− ? <IconSpinner className="size-3" />
916− : <IconTrash className="size-3" />}
917− Delete
918− </Button>
919− )}
920− </div>
921− </div>
922−
923− {props.isEditing && (
924− <EditSecretForm secret={props.secret} onClose={props.onCancelEdit} />
925− )}
926− </>
927− );
928−}
929−
930−function EditSecretForm(props: {
931− secret: SecretListItem;
932− onClose: () => void;
933−}) {
934− const updateSecret = useUpdateSecret();
935− const [name, setName] = useState(props.secret.name ?? "");
936− const [value, setValue] = useState("");
937− const [error, setError] = useState<string | null>(null);
938−
939− const handleSubmit = async () => {
940− setError(null);
941−
942− const payload: { name?: string; value?: string } = {};
943− const trimmedName = name.trim();
944− if (trimmedName && trimmedName !== (props.secret.name ?? "")) {
945− payload.name = trimmedName;
946− }
947− if (value.length > 0) {
948− payload.value = value;
949− }
950− if (Object.keys(payload).length === 0) {
951− props.onClose();
952− return;
953− }
954−
955− try {
956− await updateSecret.mutateAsync({
957− secretId: props.secret.id,
958− payload,
959− });
960− props.onClose();
961− } catch (cause) {
962− setError(cause instanceof Error ? cause.message : "Failed updating secret.");
963− }
964− };
965−
966− return (
967− <div className="mt-3 border-t border-border/50 pt-3">
968− {error && <ErrorBanner className="mb-3">{error}</ErrorBanner>}
969− <div className="grid gap-3 sm:grid-cols-2">
970− <div className="grid gap-2">
971− <Label>Name</Label>
972− <Input
973− value={name}
974− onChange={(event) => setName(event.target.value)}
975− placeholder="Secret name"
976− className="h-8 text-[12px]"
977− autoFocus
978− />
979− </div>
980− <div className="grid gap-2">
981− <Label>New value</Label>
982− <Input
983− type="password"
984− value={value}
985− onChange={(event) => setValue(event.target.value)}
986− placeholder="Leave empty to keep existing"
987− className="h-8 font-mono text-[11px]"
988− />
989− </div>
990− </div>
991− <div className="mt-3 flex items-center justify-end gap-2">
992− <Button
993− variant="ghost"
994− size="sm"
995− onClick={props.onClose}
996− >
997− Cancel
998− </Button>
999− <Button
1000− size="sm"
1001− onClick={handleSubmit}
1002− disabled={updateSecret.status === "pending"}
1003− >
1004− {updateSecret.status === "pending" && <IconSpinner className="size-3" />}
1005− Save
1006− </Button>
1007− </div>
1008− </div>
1009− );
1010−}
1011−
1012−function FormCard(props: {
1013− title: string;
1014− onClose: () => void;
1015− className?: string;
1016− children: ReactNode;
1017−}) {
1018− return (
1019− <Card className={cn("border-primary/20 p-0", props.className)}>
1020− <div className="flex items-center justify-between border-b border-border px-5 py-3">
1021− <h3 className="text-sm font-semibold text-foreground">{props.title}</h3>
1022− <Button
1023− variant="ghost"
1024− size="sm"
1025− onClick={props.onClose}
1026− >
1027− Cancel
1028− </Button>
1029− </div>
1030− <div className="space-y-4 p-5">{props.children}</div>
1031− </Card>
1032− );
1033−}
1034−
1035−function ErrorBanner(props: {
1036− children: ReactNode;
1037− className?: string;
1038−}) {
1039− return (
1040− <Alert variant="destructive" className={cn("text-[13px]", props.className)}>
1041− {props.children}
1042− </Alert>
1043− );
1044−}
1045−
1046−function SectionEmptyState(props: {
1047− title: string;
1048− description: string;
1049− actionLabel?: string;
1050− onAction?: () => void;
1051−}) {
1052− return (
1053− <div className="rounded-xl border border-dashed border-border px-6 py-10 text-center">
1054− <p className="text-[14px] font-medium text-foreground/75">{props.title}</p>
1055− <p className="mt-1 text-[13px] text-muted-foreground">{props.description}</p>
1056− {props.actionLabel && props.onAction && (
1057− <div className="mt-4 flex justify-center">
1058− <Button size="sm" onClick={props.onAction}>
1059− <IconPlus className="size-3.5" />
1060− {props.actionLabel}
1061− </Button>
1062− </div>
1063− )}
1064− </div>
1065− );
1066−}
1067−
1068−const formatDate = (value: number): string =>
1069− new Date(value).toLocaleDateString(undefined, {
1070− month: "short",
1071− day: "numeric",
1072− year: "numeric",
1073− });
apps/web/tsconfig.json+11−13
@@ -1,21 +1,19 @@
11 {
22 "compilerOptions": {
3− "target": "ES2022",
3+ "target": "ESNext",
44 "module": "ESNext",
5− "moduleResolution": "Bundler",
5+ "moduleResolution": "bundler",
66 "strict": true,
7+ "esModuleInterop": true,
78 "skipLibCheck": true,
8− "noEmit": true,
9− "lib": ["ES2022", "DOM", "DOM.Iterable"],
9+ "outDir": "dist",
10+ "rootDir": ".",
1011 "jsx": "react-jsx",
11− "types": ["bun-types"],
12− "baseUrl": ".",
13− "paths": {
14− "@/*": ["./src/*"]
15− }
12+ "plugins": [
13+ {
14+ "name": "@effect/language-service"
15+ }
16+ ]
1617 },
17− "include": [
18− "src/**/*.ts",
19− "src/**/*.tsx"
20− ]
18+ "include": ["src", "vite.config.ts"]
2119 }
apps/web/vite.config.ts+173−76
@@ -1,99 +1,196 @@
11 import { readFileSync } from "node:fs";
2−import path from "node:path";
2+import { resolve } from "node:path";
33 import { defineConfig } from "vite";
44 import react from "@vitejs/plugin-react";
55 import tailwindcss from "@tailwindcss/vite";
6−import devServer from "@hono/vite-dev-server";
76
8−type ExecutorPackageMetadata = {
9− version: string;
10− homepage?: string;
11− repository?: string | { url?: string };
7+type HotBackend = {
8+ readonly api: {
9+ readonly handler: (request: Request) => Promise<Response>;
10+ readonly dispose: () => Promise<void>;
11+ };
12+ readonly mcp: {
13+ readonly handleRequest: (request: Request) => Promise<Response>;
14+ readonly close: () => Promise<void>;
15+ };
16+ readonly dispose: () => Promise<void>;
1217 };
1318
14−const executorPackage = JSON.parse(
15− readFileSync(new URL("../executor/package.json", import.meta.url), "utf8"),
16−) as ExecutorPackageMetadata;
19+const DEV_BACKEND_MODULE_ID = `/@fs/${resolve(
20+ process.cwd(),
21+ "../server/src/dev-backend.ts",
22+).replace(/\\/g, "/")}`;
1723
18−const repositoryUrl =
19− typeof executorPackage.repository === "string"
20− ? executorPackage.repository
21− : executorPackage.repository?.url;
24+// Build a Web Request from a Node IncomingMessage
25+const toWebRequest = async (
26+ req: import("http").IncomingMessage,
27+): Promise<Request> => {
28+ const headers = new Headers();
29+ for (const [key, value] of Object.entries(req.headers)) {
30+ if (value === undefined) continue;
31+ if (Array.isArray(value)) {
32+ for (const v of value) headers.append(key, v);
33+ } else {
34+ headers.set(key, value);
35+ }
36+ }
2237
23−const githubUrl = (executorPackage.homepage ?? repositoryUrl ?? "https://github.com/RhysSullivan/executor")
24− .replace(/^git\+/, "")
25− .replace(/\.git$/, "");
38+ const host = req.headers.host ?? "localhost";
39+ const url = `http://${host}${req.url}`;
2640
27−const webPackage = JSON.parse(
28− readFileSync(new URL("./package.json", import.meta.url), "utf8"),
29−) as {
30− dependencies?: Record<string, string>;
41+ return new Request(url, {
42+ method: req.method,
43+ headers,
44+ body:
45+ req.method !== "GET" && req.method !== "HEAD"
46+ ? (await new Promise<Buffer>((resolve) => {
47+ const chunks: Buffer[] = [];
48+ req.on("data", (c: Buffer) => chunks.push(c));
49+ req.on("end", () => resolve(Buffer.concat(chunks)));
50+ }) as unknown as BodyInit)
51+ : undefined,
52+ duplex: "half" as const,
53+ });
3154 };
3255
33−const workspaceExecutorPackages = Object.keys(webPackage.dependencies ?? {}).filter(
34− (name) => name.startsWith("@executor/"),
35−);
56+// Pipe a Web Response back to a Node ServerResponse, streaming if needed
57+const sendWebResponse = async (
58+ webRes: Response,
59+ nodeRes: import("http").ServerResponse,
60+) => {
61+ nodeRes.statusCode = webRes.status;
62+ webRes.headers.forEach((value, key) => nodeRes.setHeader(key, value));
3663
37−const pluginsWorkspaceRoot = path.resolve(import.meta.dirname, "../../plugins") + path.sep;
64+ if (!webRes.body) {
65+ nodeRes.end();
66+ return;
67+ }
3868
39−const reloadOnPluginChange = () => ({
40− name: "executor-reload-on-plugin-change",
41− handleHotUpdate({ file, server }: { file: string; server: { hot: { send: (payload: { type: "full-reload" }) => void } } }) {
42− if (!file.startsWith(pluginsWorkspaceRoot)) {
43− return;
69+ const reader = webRes.body.getReader();
70+ try {
71+ for (;;) {
72+ const { done, value } = await reader.read();
73+ if (done) break;
74+ nodeRes.write(value);
4475 }
76+ } finally {
77+ nodeRes.end();
78+ }
79+};
4580
46− server.hot.send({ type: "full-reload" });
47− return [];
48− },
49−});
81+const rootPackage = JSON.parse(
82+ readFileSync(new URL("../../package.json", import.meta.url), "utf8"),
83+) as { version: string; homepage?: string; repository?: string | { url?: string } };
84+
85+const cliPackage = JSON.parse(
86+ readFileSync(new URL("../cli/package.json", import.meta.url), "utf8"),
87+) as { version?: string };
88+
89+const repositoryUrl =
90+ typeof rootPackage.repository === "string"
91+ ? rootPackage.repository
92+ : rootPackage.repository?.url;
93+
94+const EXECUTOR_VERSION = cliPackage.version ?? rootPackage.version;
95+const EXECUTOR_GITHUB_URL = (rootPackage.homepage ?? repositoryUrl ?? "https://github.com/RhysSullivan/executor")
96+ .replace(/^git\+/, "")
97+ .replace(/\.git$/, "");
5098
5199 export default defineConfig({
52− root: "src",
53− resolve: {
54− alias: {
55− "@": path.resolve(import.meta.dirname, "./src"),
56− },
100+ define: {
101+ "import.meta.env.VITE_APP_VERSION": JSON.stringify(EXECUTOR_VERSION),
102+ "import.meta.env.VITE_GITHUB_URL": JSON.stringify(EXECUTOR_GITHUB_URL),
57103 },
58104 plugins: [
59− reloadOnPluginChange(),
60− tailwindcss(),
61105 react(),
62− devServer({
63− entry: "src/dev.ts",
64− exclude: [
65− // Only let /v1 and /mcp requests reach the API handler
66− /^\/(?!(v1|mcp)(\/|$))/,
67− /^\/(src|node_modules|@vite|@id|@react-refresh)/,
68− /\.(css|ts|tsx|js|jsx|svg|png|jpg|gif|ico|woff2?|json|map)(\?.*)?$/,
69− ],
70− injectClientScript: false,
71− }),
72− ],
73− define: {
74− "import.meta.env.VITE_APP_VERSION": JSON.stringify(executorPackage.version),
75− "import.meta.env.VITE_GITHUB_URL": JSON.stringify(githubUrl),
76− },
77− build: {
78− outDir: "../dist",
79− emptyOutDir: true,
80− },
81− optimizeDeps: {
82− exclude: workspaceExecutorPackages,
83− },
84− server: {
85− port: 8788,
86− allowedHosts: [
87− "rhyss-laptop.tail5665af.ts.net",
88− ".tail5665af.ts.net",
89− ],
90− watch: {
91− ignored: [
92− "!**/node_modules/@executor/**",
93− ],
94− // WSL2 inotify doesn't reliably detect changes through symlinked workspace packages
95− usePolling: true,
96− interval: 500,
106+ tailwindcss(),
107+ {
108+ name: "executor-api",
109+ configureServer(server) {
110+ let backendPromise: Promise<HotBackend> | null = null;
111+ let reloadPromise: Promise<void> | null = null;
112+
113+ const loadBackend = () =>
114+ server
115+ .ssrLoadModule(DEV_BACKEND_MODULE_ID)
116+ .then((mod) => mod.createHotBackend() as Promise<HotBackend>);
117+
118+ const getBackend = () => {
119+ if (!backendPromise) {
120+ backendPromise = loadBackend();
121+ }
122+ return backendPromise;
123+ };
124+
125+ const shouldReloadBackend = (file: string) =>
126+ /\.(ts|tsx)$/.test(file) &&
127+ !file.includes("/apps/web/") &&
128+ (
129+ file.includes("/apps/server/") ||
130+ file.includes("/packages/core/") ||
131+ file.includes("/packages/plugins/") ||
132+ file.includes("/packages/hosts/")
133+ );
134+
135+ server.httpServer?.once("close", () => {
136+ const pending = backendPromise;
137+ backendPromise = null;
138+ void pending?.then((backend) => backend.dispose()).catch(() => undefined);
139+ });
140+
141+ server.watcher.on("change", (file) => {
142+ if (!shouldReloadBackend(file) || reloadPromise) {
143+ return;
144+ }
145+
146+ reloadPromise = (async () => {
147+ server.config.logger.info(`[executor-api] hot reloading backend: ${file}`);
148+
149+ const previous = await getBackend().catch(() => null);
150+
151+ server.moduleGraph.invalidateAll();
152+ backendPromise = loadBackend();
153+
154+ await backendPromise;
155+ await previous?.dispose().catch(() => undefined);
156+
157+ server.ws.send({
158+ type: "custom",
159+ event: "executor:backend-updated",
160+ data: { file },
161+ });
162+ })()
163+ .catch((error) => {
164+ server.config.logger.error(
165+ `[executor-api] backend reload failed: ${error instanceof Error ? error.message : String(error)}`,
166+ );
167+ })
168+ .finally(() => {
169+ reloadPromise = null;
170+ });
171+ });
172+
173+ server.middlewares.use(async (req, res, next) => {
174+ const url = req.url ?? "/";
175+
176+ const isApi =
177+ url.startsWith("/v1/") ||
178+ url.startsWith("/docs") ||
179+ url === "/openapi.json";
180+ const isMcp = url.startsWith("/mcp");
181+
182+ if (!isApi && !isMcp) return next();
183+
184+ const backend = await getBackend();
185+ const request = await toWebRequest(req);
186+
187+ const response = isMcp
188+ ? await backend.mcp.handleRequest(request)
189+ : await backend.api.handler(request);
190+
191+ await sendWebResponse(response, res);
192+ });
193+ },
97194 },
98− },
195+ ],
99196 });
architecture.md+0−124
@@ -1,124 +0,0 @@
1−# Notes on the architecture of Executor.
2−
3−## What is Executor?
4−
5−Executor is meant to be a replacement for how agents use bash and CLIs today, replacing it with code execution.
6−
7−The philosophy behind this is that bash + CLIs is a fundamentally flawed approach in that it is not going to be able to scale to organizations securely, is too dependant on having a vm to execute in, and has too many security flaws for things that can be generally run in a sandbox
8−
9−It is important to call out however what bash gets right, bash and CLIs are not bad primitives - they're the best approach agents have for calling services today
10−
11−### Why is bash the wrong primitive?
12−
13−Look at the attempts to make bash secure, namely [https://github.com/NVIDIA/OpenShell](https://github.com/NVIDIA/OpenShell)
14−
15−- Requires having docker running
16−- Single player
17−
18−### Why is code mode likely the right primitive?
19−
20−Portability, types, searchable index of all tools, unified interface
21−
22−[https://sunilpai.dev/posts/after-wimp/](https://sunilpai.dev/posts/after-wimp/)
23−
24−### What is Executor doing right that others haven't?
25−
26−Configuring itself, normalize to a TypeScript SDK but that's it, preserve complexity inside of plugins don't try to force a shared schema
27−
28−### What is going to be hard?
29−
30−- Distribution
31−
32−## Targets
33−
34−SaaS:
35−
36−- Organizations are able to use it to allow their employees to connect to services, examples:
37− - "Give all of my sales team access to Salesforce via just setting 1 API key and then they can OAuth"
38− - "All of my employees can OAuth with their own Google Workspace to setup their connections"
39−- Products embedding it inside of them, i.e "bring your own integrations" to another persons AI assistant
40−
41−Local:
42−
43−- Locally installable desktop application
44−- Be able to npx add-mcp executor and just start using it
45−
46−SDK:
47−
48−- Bring your AI SDK tools
49−- Leverage the plugin ecosystem to convert OpenAPI / GraphQL / etc into callable tools
50−
51−## Architecture
52−
53−All of these build on similar concepts and primitives
54−
55−The underlying concept is that you can generate a TypeScript SDK for literally anything you want to interact with, and the LLMs can call it
56−
57−Scope contains:
58−
59−- Secrets
60−- Policies
61−- Sources
62− - Tools
63−
64−### Scopes
65−
66−Scopes contain sources, sources contain tools
67−Scopes can be merged, for instance you may have:
68−
69−- Remote organization scope
70−- Remote workspace scope
71−- Local scope
72−
73−### Secrets
74−
75−#### Merging Scopes
76−
77−Q) How does merging secrets work with scopes? i.e I need to enforce people set their own tokens on sources
78−
79−A) TBD no idea
80−
81−Q) How does merging poliices work with scopes? i.e people can override
82−
83−A) TBD no idea
84−
85−### Tools
86−
87−A tool is a function call
88−
89−Requirements to think through:
90−
91−- Do tools have access to the full JS ecosystem? i.e streams
92−- Tools are seralizable in some form to enable workflow style use
93−
94−## Plugins
95−
96−Plugin list (non comphrensive):
97−
98−- Import / Manage OpenAPI
99−- Import / Manage GraphQL
100−- Import / Manage Google Discovery sources
101−- Import / Manage MCP
102−- Execution history
103−- 1password secrets
104−- Keychain secrets
105−- Storage backed secrets
106−- MCP apps
107−- Custom tools plugin
108− - Allows the agent to write .ts files w/ custom tools, plugs in to whatever relevant storage
109− - Agent gets install commands for packages, typecheck etc mini dev environment to work in
110−
111−Plugins:
112−
113−- Can register frontend routes
114−- Can register themselves in the app sidebar
115−- Can register HTTP routes
116−- Can extend the core sdk
117−
118−Plugins get access to the core sdk and so they are able to extend off of it
119−
120−## Is this work still relevant post AGI?
121−
122−While my day to day experience with the models begs to differ, if we assume the token sellers are correct most software is obsolete by 2028
123−
124−Where I believe this is relevant still is that
bun.lock+961−1311
@@ -3,240 +3,212 @@ · 2 unmodified lines
33 "configVersion": 1,
44 "workspaces": {
55 "": {
6− "name": "executor",
6+ "name": "v4-executor",
77 "devDependencies": {
88 "@changesets/cli": "^2.30.0",
9− "@oxlint/plugins": "^1.57.0",
10− "knip": "^5.85.0",
9+ "@effect/language-service": "^0.84.2",
10+ "@effect/platform": "catalog:",
11+ "@effect/vitest": "catalog:",
12+ "effect": "catalog:",
1113 "oxlint": "^1.56.0",
1214 "turbo": "^2.5.6",
1315 "typescript": "^5.9.3",
16+ "vitest": "catalog:",
1417 },
1518 },
16− "apps/docs": {
17− "name": "@executor/docs",
18− "version": "0.0.0",
19− },
20− "apps/executor": {
19+ "apps/cli": {
2120 "name": "executor",
22− "version": "1.3.0-beta.3",
21+ "version": "1.4.0-beta.0",
2322 "bin": {
24− "executor": "bin/executor",
23+ "executor": "./bin/executor.ts",
2524 },
2625 "dependencies": {
2726 "@effect/cli": "catalog:",
2827 "@effect/platform": "catalog:",
29− "@effect/platform-node": "catalog:",
30− "@executor/codemode-core": "workspace:*",
31− "@executor/executor-mcp": "workspace:*",
32− "@executor/platform-api": "workspace:*",
33− "@executor/platform-sdk": "workspace:*",
34− "@executor/platform-sdk-file": "workspace:*",
35− "@executor/plugin-google-discovery-sdk": "workspace:*",
36− "@executor/plugin-graphql-sdk": "workspace:*",
37− "@executor/plugin-keychain-secret-store-sdk": "workspace:*",
38− "@executor/plugin-local-secret-store-sdk": "workspace:*",
39− "@executor/plugin-local-tools-sdk": "workspace:*",
40− "@executor/plugin-mcp-sdk": "workspace:*",
41− "@executor/plugin-openapi-sdk": "workspace:*",
28+ "@effect/platform-bun": "catalog:",
29+ "@executor/api": "workspace:*",
30+ "@executor/runtime-quickjs": "workspace:*",
4231 "@executor/server": "workspace:*",
32+ "@jitl/quickjs-wasmfile-release-sync": "*",
4333 "effect": "catalog:",
34+ "quickjs-emscripten": "*",
4435 },
4536 "devDependencies": {
46− "@effect/vitest": "catalog:",
47− "@executor/effect-test-utils": "workspace:*",
48− "@executor/mcp-elicitation-demo": "workspace:*",
49− "@executor/runtime-ses": "workspace:*",
50− "@modelcontextprotocol/sdk": "^1.26.0",
51− "@types/node": "catalog:",
5237 "bun-types": "catalog:",
53− "vitest": "catalog:",
54− "zod": "catalog:",
38+ "typescript": "^5.9.3",
5539 },
5640 },
57− "apps/web": {
58− "name": "@executor/web",
59− "version": "0.0.0",
41+ "apps/server": {
42+ "name": "@executor/server",
43+ "version": "1.4.0-beta.0",
6044 "dependencies": {
61− "@base-ui/react": "^1.3.0",
62− "@executor/plugin-execution-history-react": "workspace:*",
63− "@executor/plugin-google-discovery-react": "workspace:*",
64− "@executor/plugin-graphql-react": "workspace:*",
65− "@executor/plugin-local-tools-react": "workspace:*",
66− "@executor/plugin-mcp-react": "workspace:*",
67− "@executor/plugin-onepassword-react": "workspace:*",
68− "@executor/plugin-openapi-react": "workspace:*",
69− "@executor/react": "workspace:*",
70− "@executor/server": "workspace:*",
71− "@executor/source-core": "workspace:*",
72− "@shikijs/langs": "^4.0.1",
73− "@shikijs/themes": "^4.0.1",
74− "@tanstack/react-router": "^1.132.7",
75− "class-variance-authority": "^0.7.1",
76− "clsx": "^2.1.1",
45+ "@effect/platform": "catalog:",
46+ "@effect/platform-node": "catalog:",
47+ "@effect/sql": "catalog:",
48+ "@effect/sql-sqlite-bun": "catalog:",
49+ "@executor/api": "workspace:*",
50+ "@executor/config": "workspace:*",
51+ "@executor/execution": "workspace:*",
52+ "@executor/host-mcp": "workspace:*",
53+ "@executor/plugin-file-secrets": "workspace:*",
54+ "@executor/plugin-google-discovery": "workspace:*",
55+ "@executor/plugin-graphql": "workspace:*",
56+ "@executor/plugin-keychain": "workspace:*",
57+ "@executor/plugin-mcp": "workspace:*",
58+ "@executor/plugin-onepassword": "workspace:*",
59+ "@executor/plugin-openapi": "workspace:*",
60+ "@executor/sdk": "workspace:*",
61+ "@executor/storage-file": "workspace:*",
62+ "@modelcontextprotocol/sdk": "^1.12.1",
7763 "effect": "catalog:",
78− "lucide-react": "^1.7.0",
79− "react": "^19.2.0",
80− "react-dom": "^19.2.0",
81− "react-grab": "^0.1.26",
82− "shadcn": "^4.1.1",
83− "shiki": "^4.0.1",
84− "streamdown": "^2.3.0",
85− "tailwind-merge": "^3.5.0",
86− "tldts": "^7.0.23",
8764 },
8865 "devDependencies": {
89− "@hono/vite-dev-server": "^0.25.0",
90− "@tailwindcss/vite": "^4.2.1",
91− "@types/react": "^19.2.10",
92− "@types/react-dom": "^19.2.3",
93− "@vitejs/plugin-react": "^5.1.4",
66+ "@types/node": "catalog:",
9467 "bun-types": "catalog:",
95− "tailwindcss": "^4.2.1",
96− "tw-animate-css": "^1.4.0",
97− "vite": "^7.3.1",
68+ "typescript": "^5.9.3",
9869 },
9970 },
100− "examples/mcp-elicitation-demo": {
101− "name": "@executor/mcp-elicitation-demo",
102− "version": "0.0.0",
71+ "apps/web": {
72+ "name": "@executor/web",
73+ "version": "1.4.0-beta.0",
10374 "dependencies": {
104− "@modelcontextprotocol/sdk": "^1.26.0",
105− "zod": "catalog:",
75+ "@executor/plugin-google-discovery": "workspace:*",
76+ "@executor/plugin-graphql": "workspace:*",
77+ "@executor/plugin-mcp": "workspace:*",
78+ "@executor/plugin-onepassword": "workspace:*",
79+ "@executor/plugin-openapi": "workspace:*",
80+ "@executor/react": "workspace:*",
81+ "@executor/sdk": "workspace:*",
82+ "@executor/server": "workspace:*",
83+ "@executor/ui": "workspace:*",
84+ "@shikijs/langs": "^4.0.2",
85+ "@shikijs/themes": "^4.0.2",
86+ "@tanstack/react-router": "^1.168.10",
87+ "react": "^19.1.0",
88+ "react-dom": "^19.1.0",
89+ "shiki": "^4.0.2",
90+ "streamdown": "^2.5.0",
91+ "tailwindcss": "^4.1.10",
10692 },
10793 "devDependencies": {
94+ "@tailwindcss/vite": "^4.1.10",
10895 "@types/node": "catalog:",
109− "bun-types": "catalog:",
96+ "@types/react": "^19.1.0",
97+ "@types/react-dom": "^19.1.0",
98+ "@vitejs/plugin-react": "^4.5.2",
99+ "typescript": "^5.9.3",
100+ "vite": "^6.3.5",
110101 },
111102 },
112− "examples/serve-skills-via-mcp": {
113− "name": "@executor/serve-skills-via-mcp-demo",
114− "version": "0.0.0",
103+ "packages/clients/react": {
104+ "name": "@executor/react",
105+ "version": "1.4.0-beta.0",
115106 "dependencies": {
116− "@modelcontextprotocol/sdk": "^1.26.0",
107+ "@effect-atom/atom": "^0.5.3",
108+ "@effect-atom/atom-react": "^0.5.0",
109+ "@effect/platform": "catalog:",
110+ "@executor/api": "workspace:*",
111+ "@executor/sdk": "workspace:*",
112+ "@executor/ui": "workspace:*",
113+ "effect": "catalog:",
114+ "react": "^19.1.0",
117115 },
118116 "devDependencies": {
119117 "@types/node": "catalog:",
120− "bun-types": "catalog:",
118+ "@types/react": "^19.1.0",
119+ "typescript": "^5.9.3",
121120 },
122121 },
123− "examples/sqlite-sdk-consumer": {
124− "name": "@executor/sqlite-sdk-consumer-example",
125− "version": "0.0.0",
122+ "packages/core/api": {
123+ "name": "@executor/api",
124+ "version": "1.4.0-beta.0",
126125 "dependencies": {
127− "@executor/platform-sdk": "workspace:*",
128− "@executor/source-core": "workspace:*",
129− "drizzle-orm": "^0.44.5",
126+ "@effect/platform": "catalog:",
127+ "@executor/sdk": "workspace:*",
128+ "effect": "catalog:",
130129 },
131130 "devDependencies": {
132131 "@types/node": "catalog:",
133132 "bun-types": "catalog:",
133+ "typescript": "^5.9.3",
134134 },
135135 },
136− "packages/clients/react": {
137− "name": "@executor/react",
138− "version": "0.0.0",
136+ "packages/core/config": {
137+ "name": "@executor/config",
138+ "version": "1.4.0-beta.0",
139139 "dependencies": {
140− "@base-ui/react": "^1.3.0",
141− "@effect-atom/atom": "0.5.3",
142− "@effect-atom/atom-react": "0.5.0",
143140 "@effect/platform": "catalog:",
144− "@executor/platform-api": "workspace:*",
145− "@executor/platform-sdk": "workspace:*",
146− "@shikijs/langs": "^4.0.1",
147− "@shikijs/themes": "^4.0.1",
148− "class-variance-authority": "^0.7.1",
149− "clsx": "^2.1.1",
150− "cmdk": "^1.1.1",
141+ "@executor/sdk": "workspace:*",
151142 "effect": "catalog:",
152− "shiki": "^4.0.1",
153− "streamdown": "^2.3.0",
154− "tailwind-merge": "^3.5.0",
143+ "jsonc-parser": "^3.3.1",
155144 },
156145 "devDependencies": {
157146 "@effect/platform-node": "catalog:",
158147 "@effect/vitest": "catalog:",
159− "@executor/effect-test-utils": "workspace:*",
160− "@executor/platform-sdk-file": "workspace:*",
161− "@types/jsdom": "^21.1.7",
162− "@types/node": "catalog:",
163− "@types/react": "^19.2.10",
164− "@types/react-dom": "^19.2.3",
165− "bun-types": "catalog:",
166− "jsdom": "^26.1.0",
167− "react-dom": "^19.2.0",
148+ "typescript": "latest",
168149 "vitest": "catalog:",
169150 },
170− "peerDependencies": {
171− "react": ">=18 <20",
172− },
173151 },
174− "packages/dev/effect-test-utils": {
175− "name": "@executor/effect-test-utils",
176− "version": "0.0.0",
152+ "packages/core/execution": {
153+ "name": "@executor/execution",
154+ "version": "1.4.0-beta.0",
177155 "dependencies": {
178− "@effect/platform": "catalog:",
179− "@effect/platform-node": "catalog:",
156+ "@executor/codemode-core": "workspace:*",
157+ "@executor/runtime-quickjs": "workspace:*",
158+ "@executor/sdk": "workspace:*",
180159 "effect": "catalog:",
181160 },
182161 "devDependencies": {
183162 "@types/node": "catalog:",
184163 "bun-types": "catalog:",
185− "typescript": "^5.9.3",
186164 },
187165 },
188− "packages/dev/kitchen-sink": {
189− "name": "@executor/kitchen-sink",
190− "version": "0.0.0",
166+ "packages/core/sdk": {
167+ "name": "@executor/sdk",
168+ "version": "1.4.0-beta.0",
191169 "dependencies": {
192− "@effect/platform": "catalog:",
193− "@executor/ai-sdk-adapter": "workspace:*",
194− "@executor/codemode-core": "workspace:*",
195− "@executor/platform-sdk": "workspace:*",
196− "@executor/runtime-ses": "workspace:*",
197170 "effect": "catalog:",
198171 },
199172 "devDependencies": {
200173 "@effect/vitest": "catalog:",
201− "@types/node": "catalog:",
202− "bun-types": "catalog:",
174+ "typescript": "latest",
203175 "vitest": "catalog:",
204176 },
205177 },
206− "packages/hosts/ai-sdk": {
207− "name": "@executor/ai-sdk-adapter",
208− "version": "0.0.0",
178+ "packages/core/storage-file": {
179+ "name": "@executor/storage-file",
180+ "version": "1.4.0-beta.0",
209181 "dependencies": {
210− "@executor/codemode-core": "workspace:*",
211− "@executor/runtime-ses": "workspace:*",
212− "ai": "^6.0.0",
182+ "@effect/sql": "catalog:",
183+ "@executor/sdk": "workspace:*",
213184 "effect": "catalog:",
214− "zod": "catalog:",
215185 },
216186 "devDependencies": {
217− "@types/node": "catalog:",
218− "bun-types": "catalog:",
187+ "@effect/experimental": "catalog:",
188+ "@effect/sql-sqlite-node": "catalog:",
189+ "@effect/vitest": "catalog:",
190+ "typescript": "^5.9.3",
191+ "vitest": "catalog:",
219192 },
220193 },
221194 "packages/hosts/mcp": {
222− "name": "@executor/executor-mcp",
223− "version": "0.0.0",
195+ "name": "@executor/host-mcp",
196+ "version": "1.4.0-beta.0",
224197 "dependencies": {
225− "@executor/platform-sdk": "workspace:*",
226− "@modelcontextprotocol/sdk": "^1.26.0",
198+ "@executor/execution": "workspace:*",
199+ "@executor/sdk": "workspace:*",
200+ "@modelcontextprotocol/sdk": "^1.12.1",
227201 "effect": "catalog:",
228− "zod": "catalog:",
202+ "zod": "^4.3.0",
229203 },
230204 "devDependencies": {
231− "@effect/vitest": "catalog:",
232205 "@types/node": "catalog:",
233206 "bun-types": "catalog:",
234− "vitest": "catalog:",
235207 },
236208 },
237209 "packages/kernel/core": {
238210 "name": "@executor/codemode-core",
239− "version": "0.0.0",
211+ "version": "1.4.0-beta.0",
240212 "dependencies": {
241213 "@standard-schema/spec": "^1.0.0",
242214 "ajv": "^8.17.1",
@@ -252,9 +224,8 @@ · 9 unmodified lines
252224 },
253225 "packages/kernel/ir": {
254226 "name": "@executor/ir",
255− "version": "0.0.0",
227+ "version": "1.4.0-beta.0",
256228 "dependencies": {
257− "@executor/codemode-core": "workspace:*",
258229 "effect": "catalog:",
259230 },
260231 "devDependencies": {
@@ -280,7 +251,7 @@ · 19 unmodified lines
280251 },
281252 "packages/kernel/runtime-quickjs": {
282253 "name": "@executor/runtime-quickjs",
283− "version": "0.0.0",
254+ "version": "1.4.0-beta.0",
284255 "dependencies": {
285256 "@executor/codemode-core": "workspace:*",
286257 "effect": "catalog:",
@@ -293,199 +264,99 @@ · 6 unmodified lines
293264 "vitest": "catalog:",
294265 },
295266 },
296− "packages/kernel/runtime-ses": {
297− "name": "@executor/runtime-ses",
298− "version": "0.0.0",
299− "dependencies": {
300− "@executor/codemode-core": "workspace:*",
301− "effect": "catalog:",
302− "ses": "^1.15.0",
303− },
304− "devDependencies": {
305− "@types/node": "catalog:",
306− "bun-types": "catalog:",
307− },
308− },
309− "packages/platform/api": {
310− "name": "@executor/platform-api",
311− "version": "0.0.0",
312− "dependencies": {
313− "@effect/platform": "catalog:",
314− "@executor/platform-sdk": "workspace:*",
315− "effect": "catalog:",
316− },
317− "devDependencies": {
318− "@effect/vitest": "catalog:",
319− "bun-types": "catalog:",
320− "typescript": "^5.9.3",
321− "vitest": "catalog:",
322− },
323− },
324− "packages/platform/sdk": {
325− "name": "@executor/platform-sdk",
326− "version": "0.0.0",
267+ "packages/plugins/file-secrets": {
268+ "name": "@executor/plugin-file-secrets",
269+ "version": "1.4.0-beta.0",
327270 "dependencies": {
328− "@effect/platform": "catalog:",
329− "@effect/platform-node": "catalog:",
330− "@executor/codemode-core": "workspace:*",
331− "@executor/ir": "workspace:*",
332− "@executor/runtime-deno-subprocess": "workspace:*",
333− "@executor/runtime-quickjs": "workspace:*",
334− "@executor/runtime-ses": "workspace:*",
335− "@executor/source-core": "workspace:*",
271+ "@executor/sdk": "workspace:*",
336272 "effect": "catalog:",
337273 },
338274 "devDependencies": {
339275 "@effect/vitest": "catalog:",
340− "@executor/effect-test-utils": "workspace:*",
341− "@modelcontextprotocol/sdk": "^1.26.0",
342276 "@types/node": "catalog:",
343277 "bun-types": "catalog:",
344− "jsonc-parser": "3.3.1",
345− "prettier": "^3.8.1",
346− "typescript": "^5.9.3",
347278 "vitest": "catalog:",
348− "zod": "catalog:",
349279 },
350280 },
351− "packages/platform/sdk-file": {
352− "name": "@executor/platform-sdk-file",
353− "version": "0.0.0",
281+ "packages/plugins/google-discovery": {
282+ "name": "@executor/plugin-google-discovery",
283+ "version": "1.4.0-beta.0",
354284 "dependencies": {
355285 "@effect/platform": "catalog:",
356− "@effect/platform-node": "catalog:",
357− "@executor/codemode-core": "workspace:*",
358− "@executor/ir": "workspace:*",
359− "@executor/platform-sdk": "workspace:*",
360− "@executor/source-core": "workspace:*",
286+ "@executor/api": "workspace:*",
287+ "@executor/sdk": "workspace:*",
361288 "effect": "catalog:",
362− "jsonc-parser": "3.3.1",
363289 },
364290 "devDependencies": {
291+ "@effect-atom/atom-react": "^0.5.0",
365292 "@effect/vitest": "catalog:",
293+ "@executor/react": "workspace:*",
294+ "@executor/ui": "workspace:*",
366295 "@types/node": "catalog:",
296+ "@types/react": "^19.1.0",
367297 "bun-types": "catalog:",
368− "typescript": "^5.9.3",
298+ "react": "^19.1.0",
369299 "vitest": "catalog:",
370300 },
301+ "peerDependencies": {
302+ "@effect-atom/atom-react": "^0.5.0",
303+ "@executor/react": "workspace:*",
304+ "@executor/ui": "workspace:*",
305+ "@tanstack/react-router": "^1.168.10",
306+ "react": "^19.1.0",
307+ },
308+ "optionalPeers": [
309+ "@effect-atom/atom-react",
310+ "@executor/react",
311+ "@executor/ui",
312+ "@tanstack/react-router",
313+ "react",
314+ ],
371315 },
372− "packages/platform/server": {
373− "name": "@executor/server",
374− "version": "0.0.0",
316+ "packages/plugins/graphql": {
317+ "name": "@executor/plugin-graphql",
318+ "version": "1.4.0-beta.0",
375319 "dependencies": {
376− "@effect/opentelemetry": "^0.61.0",
377320 "@effect/platform": "catalog:",
378321 "@effect/platform-node": "catalog:",
379− "@executor/executor-mcp": "workspace:*",
380− "@executor/platform-api": "workspace:*",
381− "@executor/platform-sdk": "workspace:*",
382− "@executor/platform-sdk-file": "workspace:*",
383− "@executor/plugin-google-discovery-http": "workspace:*",
384− "@executor/plugin-google-discovery-sdk": "workspace:*",
385− "@executor/plugin-google-discovery-shared": "workspace:*",
386− "@executor/plugin-graphql-http": "workspace:*",
387− "@executor/plugin-graphql-sdk": "workspace:*",
388− "@executor/plugin-graphql-shared": "workspace:*",
389− "@executor/plugin-keychain-secret-store-sdk": "workspace:*",
390− "@executor/plugin-local-secret-store-sdk": "workspace:*",
391− "@executor/plugin-local-tools-sdk": "workspace:*",
392− "@executor/plugin-mcp-http": "workspace:*",
393− "@executor/plugin-mcp-sdk": "workspace:*",
394− "@executor/plugin-mcp-shared": "workspace:*",
395− "@executor/plugin-onepassword-http": "workspace:*",
396− "@executor/plugin-onepassword-sdk": "workspace:*",
397− "@executor/plugin-onepassword-shared": "workspace:*",
398− "@executor/plugin-openapi-http": "workspace:*",
399− "@executor/plugin-openapi-sdk": "workspace:*",
400− "@executor/plugin-openapi-shared": "workspace:*",
401− "@opentelemetry/api": "^1.9.0",
402− "@opentelemetry/exporter-trace-otlp-grpc": "^0.213.0",
403− "@opentelemetry/resources": "^2.6.0",
404− "@opentelemetry/sdk-trace-base": "^2.6.0",
405− "@opentelemetry/sdk-trace-node": "^2.6.0",
406− "@opentelemetry/semantic-conventions": "^1.40.0",
322+ "@executor/sdk": "workspace:*",
407323 "effect": "catalog:",
408324 },
409325 "devDependencies": {
326+ "@effect-atom/atom-react": "^0.5.0",
410327 "@effect/vitest": "catalog:",
411− "@executor/effect-test-utils": "workspace:*",
412− "@executor/mcp-elicitation-demo": "workspace:*",
413− "@executor/runtime-ses": "workspace:*",
414− "@modelcontextprotocol/sdk": "^1.26.0",
415− "@types/node": "catalog:",
416− "bun-types": "catalog:",
417− "vitest": "catalog:",
418− "zod": "catalog:",
419− },
420− },
421− "packages/sources/core": {
422− "name": "@executor/source-core",
423− "version": "0.0.0",
424− "dependencies": {
425− "@executor/codemode-core": "workspace:*",
426− "@executor/ir": "workspace:*",
427− "@modelcontextprotocol/sdk": "^1.26.0",
428− "effect": "catalog:",
429− "tldts": "^7.0.27",
430− },
431− "devDependencies": {
432− "@types/node": "catalog:",
433− "bun-types": "catalog:",
434− },
435− },
436− "plugins/execution-history/react": {
437− "name": "@executor/plugin-execution-history-react",
438− "version": "0.0.0",
439− "dependencies": {
328+ "@executor/api": "workspace:*",
440329 "@executor/react": "workspace:*",
441− "react": "^19.2.0",
442− },
443− "devDependencies": {
444− "@types/node": "catalog:",
445− "@types/react": "^19.2.10",
446− "bun-types": "catalog:",
447− },
448− },
449− "plugins/google-discovery/http": {
450− "name": "@executor/plugin-google-discovery-http",
451− "version": "0.0.0",
452− "dependencies": {
453− "@effect/platform": "catalog:",
454− "@executor/platform-api": "workspace:*",
455− "@executor/platform-sdk": "workspace:*",
456− "@executor/plugin-google-discovery-shared": "workspace:*",
457− "effect": "catalog:",
458− },
459− "devDependencies": {
330+ "@executor/ui": "workspace:*",
460331 "@types/node": "catalog:",
332+ "@types/react": "^19.1.0",
461333 "bun-types": "catalog:",
334+ "react": "^19.1.0",
335+ "vitest": "catalog:",
462336 },
463− },
464− "plugins/google-discovery/react": {
465− "name": "@executor/plugin-google-discovery-react",
466− "version": "0.0.0",
467− "dependencies": {
468− "@executor/plugin-google-discovery-http": "workspace:*",
469− "@executor/plugin-google-discovery-shared": "workspace:*",
337+ "peerDependencies": {
338+ "@effect-atom/atom-react": "^0.5.0",
339+ "@executor/api": "workspace:*",
470340 "@executor/react": "workspace:*",
471− "react": "^19.2.0",
472− },
473− "devDependencies": {
474− "@types/node": "catalog:",
475− "@types/react": "^19.2.10",
476− "bun-types": "catalog:",
477− },
341+ "@executor/ui": "workspace:*",
342+ "@tanstack/react-router": "^1.168.10",
343+ "react": "^19.1.0",
344+ },
345+ "optionalPeers": [
346+ "@effect-atom/atom-react",
347+ "@executor/api",
348+ "@executor/react",
349+ "@executor/ui",
350+ "@tanstack/react-router",
351+ "react",
352+ ],
478353 },
479− "plugins/google-discovery/sdk": {
480− "name": "@executor/plugin-google-discovery-sdk",
481− "version": "0.0.0",
354+ "packages/plugins/keychain": {
355+ "name": "@executor/plugin-keychain",
356+ "version": "1.4.0-beta.0",
482357 "dependencies": {
483− "@effect/platform": "catalog:",
484− "@executor/codemode-core": "workspace:*",
485− "@executor/ir": "workspace:*",
486− "@executor/platform-sdk": "workspace:*",
487− "@executor/plugin-google-discovery-shared": "workspace:*",
488− "@executor/source-core": "workspace:*",
358+ "@executor/sdk": "workspace:*",
359+ "@napi-rs/keyring": "^1.2.0",
489360 "effect": "catalog:",
490361 },
491362 "devDependencies": {
@@ -495,345 +366,186 @@ · 3 unmodified lines
495366 "vitest": "catalog:",
496367 },
497368 },
498− "plugins/google-discovery/shared": {
499− "name": "@executor/plugin-google-discovery-shared",
500− "version": "0.0.0",
501− "dependencies": {
502− "@executor/platform-sdk": "workspace:*",
503− "@executor/source-core": "workspace:*",
504− "effect": "catalog:",
505− },
506− "devDependencies": {
507− "@types/node": "catalog:",
508− "bun-types": "catalog:",
509− },
510− },
511− "plugins/graphql/http": {
512− "name": "@executor/plugin-graphql-http",
513− "version": "0.0.0",
369+ "packages/plugins/mcp": {
370+ "name": "@executor/plugin-mcp",
371+ "version": "1.4.0-beta.0",
514372 "dependencies": {
515373 "@effect/platform": "catalog:",
516− "@executor/platform-api": "workspace:*",
517− "@executor/platform-sdk": "workspace:*",
518− "@executor/plugin-graphql-shared": "workspace:*",
519− "effect": "catalog:",
520− },
521− "devDependencies": {
522− "@types/node": "catalog:",
523− "bun-types": "catalog:",
524− },
525− },
526− "plugins/graphql/react": {
527− "name": "@executor/plugin-graphql-react",
528− "version": "0.0.0",
529− "dependencies": {
530− "@executor/plugin-graphql-http": "workspace:*",
531− "@executor/plugin-graphql-shared": "workspace:*",
532− "@executor/react": "workspace:*",
533− "react": "^19.2.0",
534− },
535− "devDependencies": {
536− "@types/node": "catalog:",
537− "@types/react": "^19.2.10",
538− "bun-types": "catalog:",
539− },
540− },
541− "plugins/graphql/sdk": {
542− "name": "@executor/plugin-graphql-sdk",
543− "version": "0.0.0",
544− "dependencies": {
545− "@executor/codemode-core": "workspace:*",
546− "@executor/ir": "workspace:*",
547− "@executor/platform-sdk": "workspace:*",
548− "@executor/plugin-graphql-shared": "workspace:*",
549− "@executor/source-core": "workspace:*",
374+ "@effect/platform-node": "catalog:",
375+ "@executor/sdk": "workspace:*",
376+ "@modelcontextprotocol/sdk": "^1.29.0",
550377 "effect": "catalog:",
551− "graphql": "^16.12.0",
552378 },
553379 "devDependencies": {
380+ "@effect-atom/atom-react": "^0.5.0",
554381 "@effect/vitest": "catalog:",
382+ "@executor/api": "workspace:*",
383+ "@executor/react": "workspace:*",
384+ "@executor/ui": "workspace:*",
555385 "@types/node": "catalog:",
386+ "@types/react": "^19.1.0",
556387 "bun-types": "catalog:",
388+ "react": "^19.1.0",
557389 "vitest": "catalog:",
558390 },
559− },
560− "plugins/graphql/shared": {
561− "name": "@executor/plugin-graphql-shared",
562− "version": "0.0.0",
563− "dependencies": {
564− "@executor/platform-sdk": "workspace:*",
565− "@executor/source-core": "workspace:*",
566− "effect": "catalog:",
567− },
568− "devDependencies": {
569− "@types/node": "catalog:",
570− "bun-types": "catalog:",
571− },
572− },
573− "plugins/keychain-secret-store/sdk": {
574− "name": "@executor/plugin-keychain-secret-store-sdk",
575− "version": "0.0.0",
576− "dependencies": {
577− "@executor/platform-sdk": "workspace:*",
578− "@napi-rs/keyring": "^1.2.0",
579− "effect": "catalog:",
580− },
581− "devDependencies": {
582− "@types/node": "catalog:",
583− "bun-types": "catalog:",
584− },
585− },
586− "plugins/local-secret-store/sdk": {
587− "name": "@executor/plugin-local-secret-store-sdk",
588− "version": "0.0.0",
589− "dependencies": {
590− "@executor/platform-sdk": "workspace:*",
591− "effect": "catalog:",
592− },
593− "devDependencies": {
594− "@types/node": "catalog:",
595− "bun-types": "catalog:",
596− },
597− },
598− "plugins/local-tools/react": {
599− "name": "@executor/plugin-local-tools-react",
600− "version": "0.0.0",
601− "dependencies": {
391+ "peerDependencies": {
392+ "@effect-atom/atom-react": "^0.5.0",
393+ "@executor/api": "workspace:*",
602394 "@executor/react": "workspace:*",
603− "react": "^19.2.0",
604− },
605− "devDependencies": {
606− "@types/node": "catalog:",
607− "@types/react": "^19.2.10",
608− "bun-types": "catalog:",
609− },
610− },
611− "plugins/local-tools/sdk": {
612− "name": "@executor/plugin-local-tools-sdk",
613− "version": "0.0.0",
614− "dependencies": {
615− "@executor/codemode-core": "workspace:*",
616− "@executor/ir": "workspace:*",
617− "@executor/platform-sdk": "workspace:*",
618− "@executor/source-core": "workspace:*",
619− "effect": "catalog:",
620− },
621− "devDependencies": {
622− "@types/node": "catalog:",
623− "bun-types": "catalog:",
624− },
395+ "@executor/ui": "workspace:*",
396+ "@tanstack/react-router": "^1.168.10",
397+ "react": "^19.1.0",
398+ },
399+ "optionalPeers": [
400+ "@effect-atom/atom-react",
401+ "@executor/api",
402+ "@executor/react",
403+ "@executor/ui",
404+ "@tanstack/react-router",
405+ "react",
406+ ],
625407 },
626− "plugins/mcp/http": {
627− "name": "@executor/plugin-mcp-http",
628− "version": "0.0.0",
408+ "packages/plugins/onepassword": {
409+ "name": "@executor/plugin-onepassword",
410+ "version": "1.4.0-beta.0",
629411 "dependencies": {
412+ "@1password/op-js": "^0.1.13",
413+ "@1password/sdk": "^0.4.1-beta.1",
414+ "@effect-atom/atom-react": "^0.5.0",
630415 "@effect/platform": "catalog:",
631− "@executor/platform-api": "workspace:*",
632− "@executor/platform-sdk": "workspace:*",
633− "@executor/plugin-mcp-shared": "workspace:*",
634− "effect": "catalog:",
635− },
636− "devDependencies": {
637− "@types/node": "catalog:",
638− "bun-types": "catalog:",
639− },
640− },
641− "plugins/mcp/react": {
642− "name": "@executor/plugin-mcp-react",
643− "version": "0.0.0",
644− "dependencies": {
645− "@executor/plugin-mcp-http": "workspace:*",
646− "@executor/plugin-mcp-shared": "workspace:*",
647− "@executor/react": "workspace:*",
648− "react": "^19.2.0",
649− },
650− "devDependencies": {
651− "@types/node": "catalog:",
652− "@types/react": "^19.2.10",
653− "bun-types": "catalog:",
654− },
655− },
656− "plugins/mcp/sdk": {
657− "name": "@executor/plugin-mcp-sdk",
658− "version": "0.0.0",
659− "dependencies": {
660− "@executor/codemode-core": "workspace:*",
661− "@executor/ir": "workspace:*",
662− "@executor/platform-sdk": "workspace:*",
663− "@executor/plugin-mcp-shared": "workspace:*",
664− "@executor/source-core": "workspace:*",
665− "@modelcontextprotocol/sdk": "^1.26.0",
416+ "@executor/api": "workspace:*",
417+ "@executor/sdk": "workspace:*",
666418 "effect": "catalog:",
667419 },
668420 "devDependencies": {
669421 "@effect/vitest": "catalog:",
670− "@executor/runtime-ses": "workspace:*",
671422 "@types/node": "catalog:",
672423 "bun-types": "catalog:",
673424 "vitest": "catalog:",
674− "zod": "catalog:",
675− },
676− },
677− "plugins/mcp/shared": {
678− "name": "@executor/plugin-mcp-shared",
679− "version": "0.0.0",
680− "dependencies": {
681− "@executor/platform-sdk": "workspace:*",
682− "@executor/source-core": "workspace:*",
683− "effect": "catalog:",
684− },
685− "devDependencies": {
686− "@types/node": "catalog:",
687− "bun-types": "catalog:",
688425 },
689− },
690− "plugins/onepassword/http": {
691− "name": "@executor/plugin-onepassword-http",
692− "version": "0.0.0",
693− "dependencies": {
694− "@effect/platform": "catalog:",
695− "@executor/platform-api": "workspace:*",
696− "@executor/platform-sdk": "workspace:*",
697− "@executor/plugin-onepassword-shared": "workspace:*",
698− "effect": "catalog:",
699− },
700− "devDependencies": {
701− "@types/node": "catalog:",
702− "bun-types": "catalog:",
703− },
704− },
705− "plugins/onepassword/react": {
706− "name": "@executor/plugin-onepassword-react",
707− "version": "0.0.0",
708− "dependencies": {
709− "@executor/plugin-onepassword-shared": "workspace:*",
426+ "peerDependencies": {
427+ "@effect-atom/atom-react": "^0.5.0",
710428 "@executor/react": "workspace:*",
711− "react": "^19.2.0",
712− },
713− "devDependencies": {
714− "@types/node": "catalog:",
715− "@types/react": "^19.2.10",
716− "bun-types": "catalog:",
717− },
718− },
719− "plugins/onepassword/sdk": {
720− "name": "@executor/plugin-onepassword-sdk",
721− "version": "0.0.0",
722− "dependencies": {
723− "@1password/sdk": "0.4.1-beta.1",
724− "@executor/platform-sdk": "workspace:*",
725− "@executor/plugin-onepassword-shared": "workspace:*",
726− "effect": "catalog:",
727− },
728− "devDependencies": {
729− "@types/node": "catalog:",
730− "bun-types": "catalog:",
731− },
429+ "@executor/ui": "workspace:*",
430+ "react": ">=18",
431+ },
432+ "optionalPeers": [
433+ "@effect-atom/atom-react",
434+ "@executor/react",
435+ "@executor/ui",
436+ "react",
437+ ],
732438 },
733− "plugins/onepassword/shared": {
734− "name": "@executor/plugin-onepassword-shared",
735− "version": "0.0.0",
439+ "packages/plugins/openapi": {
440+ "name": "@executor/plugin-openapi",
441+ "version": "1.4.0-beta.0",
736442 "dependencies": {
443+ "@apidevtools/swagger-parser": "^12.1.0",
737444 "@effect/platform": "catalog:",
738− "@executor/platform-sdk": "workspace:*",
739− "effect": "catalog:",
740− },
741− "devDependencies": {
742− "@types/node": "catalog:",
743− "bun-types": "catalog:",
744− },
745− },
746− "plugins/openapi/http": {
747− "name": "@executor/plugin-openapi-http",
748− "version": "0.0.0",
749− "dependencies": {
750− "@effect/platform": "catalog:",
751− "@executor/platform-api": "workspace:*",
752− "@executor/platform-sdk": "workspace:*",
753− "@executor/plugin-openapi-shared": "workspace:*",
445+ "@effect/platform-node": "catalog:",
446+ "@executor/sdk": "workspace:*",
754447 "effect": "catalog:",
448+ "openapi-types": "^12.1.3",
449+ "yaml": "^2.7.1",
755450 },
756451 "devDependencies": {
757− "@types/node": "catalog:",
758− "bun-types": "catalog:",
759− },
760− },
761− "plugins/openapi/react": {
762− "name": "@executor/plugin-openapi-react",
763− "version": "0.0.0",
764− "dependencies": {
765− "@executor/plugin-openapi-http": "workspace:*",
766− "@executor/plugin-openapi-shared": "workspace:*",
452+ "@effect-atom/atom-react": "^0.5.0",
453+ "@effect/vitest": "catalog:",
454+ "@executor/api": "workspace:*",
767455 "@executor/react": "workspace:*",
768− "react": "^19.2.0",
769− },
770− "devDependencies": {
771− "@types/node": "catalog:",
772− "@types/react": "^19.2.10",
773− "bun-types": "catalog:",
774− },
775− },
776− "plugins/openapi/sdk": {
777− "name": "@executor/plugin-openapi-sdk",
778− "version": "0.0.0",
779− "dependencies": {
780− "@executor/codemode-core": "workspace:*",
781− "@executor/ir": "workspace:*",
782− "@executor/platform-sdk": "workspace:*",
783− "@executor/plugin-openapi-shared": "workspace:*",
784− "@executor/source-core": "workspace:*",
785− "effect": "catalog:",
786− "yaml": "^2.8.1",
787− },
788− "devDependencies": {
789− "@effect/platform": "catalog:",
790− "@effect/platform-node": "catalog:",
791− "@executor/effect-test-utils": "workspace:*",
456+ "@executor/ui": "workspace:*",
792457 "@types/node": "catalog:",
458+ "@types/react": "^19.1.0",
793459 "bun-types": "catalog:",
460+ "react": "^19.1.0",
794461 "vitest": "catalog:",
795462 },
463+ "peerDependencies": {
464+ "@effect-atom/atom-react": "^0.5.0",
465+ "@executor/api": "workspace:*",
466+ "@executor/react": "workspace:*",
467+ "@executor/ui": "workspace:*",
468+ "@tanstack/react-router": "^1.168.10",
469+ "react": "^19.1.0",
470+ },
471+ "optionalPeers": [
472+ "@effect-atom/atom-react",
473+ "@executor/api",
474+ "@executor/react",
475+ "@executor/ui",
476+ "@tanstack/react-router",
477+ "react",
478+ ],
796479 },
797− "plugins/openapi/shared": {
798− "name": "@executor/plugin-openapi-shared",
799− "version": "0.0.0",
480+ "packages/ui": {
481+ "name": "@executor/ui",
482+ "version": "1.4.0-beta.0",
800483 "dependencies": {
801− "@executor/platform-sdk": "workspace:*",
802− "@executor/source-core": "workspace:*",
803− "effect": "catalog:",
804− "yaml": "^2.8.1",
484+ "@base-ui/react": "^1.3.0",
485+ "@hookform/resolvers": "^5.2.2",
486+ "@shikijs/langs": "^4.0.2",
487+ "@shikijs/themes": "^4.0.2",
488+ "class-variance-authority": "^0.7.1",
489+ "clsx": "^2.1.1",
490+ "cmdk": "^1.1.1",
491+ "date-fns": "^4.1.0",
492+ "embla-carousel-react": "^8.6.0",
493+ "input-otp": "^1.4.2",
494+ "lucide-react": "^1.7.0",
495+ "next-themes": "^0.4.6",
496+ "radix-ui": "^1.4.3",
497+ "react": "^19.1.0",
498+ "react-day-picker": "^9.14.0",
499+ "react-hook-form": "^7.72.0",
500+ "react-resizable-panels": "^4",
501+ "recharts": "3.8.0",
502+ "shiki": "^4.0.2",
503+ "sonner": "^2.0.7",
504+ "streamdown": "^2.5.0",
505+ "tailwind-merge": "^3.3.0",
506+ "vaul": "^1.1.2",
507+ "zod": "^4.3.6",
805508 },
806509 "devDependencies": {
807− "@types/node": "catalog:",
808− "bun-types": "catalog:",
510+ "@types/react": "^19.1.0",
511+ "hast-util-to-jsx-runtime": "^2.3.6",
512+ "tailwindcss": "^4.1.10",
513+ "typescript": "^5.9.3",
809514 },
810515 },
811516 },
812517 "catalog": {
813518 "@effect/cli": "^0.73.2",
814− "@effect/platform": "^0.94.5",
815− "@effect/platform-node": "^0.104.1",
519+ "@effect/cluster": "^0.58.0",
520+ "@effect/experimental": "^0.60.0",
521+ "@effect/platform": "^0.96.0",
522+ "@effect/platform-bun": "^0.89.0",
523+ "@effect/platform-node": "^0.106.0",
524+ "@effect/sql": "^0.51.0",
525+ "@effect/sql-sqlite-bun": "^0.52.0",
526+ "@effect/sql-sqlite-node": "^0.52.0",
816527 "@effect/vitest": "^0.27.0",
817528 "@types/node": "^24.3.1",
818529 "bun-types": "^1.2.22",
819− "effect": "^3.19.19",
530+ "effect": "^3.21.0",
820531 "vitest": "^3.2.4",
821− "zod": "^4.3.6",
822532 },
823533 "packages": {
534+ "@1password/op-js": ["@1password/op-js@0.1.13", "", { "dependencies": { "lookpath": "^1.2.2", "semver": "^7.6.2" } }, "sha512-ZZBLxVqywFdvIbLv2xWw2N1ImSi183rRKf90vV19KRMReNyLwuD0dv6IrKrIdrJU33IuV3Gz85Z4K2a1PJTBDg=="],
535+
824536 "@1password/sdk": ["@1password/sdk@0.4.1-beta.1", "", { "dependencies": { "@1password/sdk-core": "0.4.1-beta.1" } }, "sha512-QWY6eIIEs9at6kAFbgjZ1vVxg7ygp/MwXJ6/BoBdPkqIk8vfulXu4pjDsVQ87HhddJAD5LVGBXSbQIa+svI3bA=="],
825537
826538 "@1password/sdk-core": ["@1password/sdk-core@0.4.1-beta.1", "", {}, "sha512-/otbg1JVhsEn6oUIeReoT9TmFr8J7KBwr9UuRVfJFwwGG3bHPF8ewT+LhRimQeJtypqQ69ZVuOYkxknD4iQHxw=="],
827539
828− "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.66", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.19", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-SIQ0YY0iMuv+07HLsZ+bB990zUJ6S4ujORAh+Jv1V2KGNn73qQKnGO0JBk+w+Res8YqOFSycwDoWcFlQrVxS4A=="],
540+ "@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
829541
830− "@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="],
542+ "@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@14.0.1", "", { "dependencies": { "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0" } }, "sha512-Oc96zvmxx1fqoSEdUmfmvvb59/KDOnUoJ7s2t7bISyAn0XEz57LCCw8k2Y4Pf3mwKaZLMciESALORLgfe2frCw=="],
831543
832− "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.19", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-3eG55CrSWCu2SXlqq2QCsFjo3+E7+Gmg7i/oRVoSZzIodTuDSfLb3MRje67xE9RFea73Zao7Lm4mADIfUETKGg=="],
544+ "@apidevtools/openapi-schemas": ["@apidevtools/openapi-schemas@2.1.0", "", {}, "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ=="],
833545
834− "@antfu/ni": ["@antfu/ni@0.23.2", "", { "bin": { "na": "bin/na.mjs", "ni": "bin/ni.mjs", "nr": "bin/nr.mjs", "nu": "bin/nu.mjs", "nci": "bin/nci.mjs", "nlx": "bin/nlx.mjs", "nun": "bin/nun.mjs" } }, "sha512-FSEVWXvwroExDXUu8qV6Wqp2X3D1nJ0Li4LFymCyvCVrm7I3lNfG0zZWSWvGU1RE7891eTnFTyh31L3igOwNKQ=="],
546+ "@apidevtools/swagger-methods": ["@apidevtools/swagger-methods@3.0.2", "", {}, "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg=="],
835547
836− "@asamuzakjp/css-color": ["@asamuzakjp/css-color@3.2.0", "", { "dependencies": { "@csstools/css-calc": "^2.1.3", "@csstools/css-color-parser": "^3.0.9", "@csstools/css-parser-algorithms": "^3.0.4", "@csstools/css-tokenizer": "^3.0.3", "lru-cache": "^10.4.3" } }, "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw=="],
548+ "@apidevtools/swagger-parser": ["@apidevtools/swagger-parser@12.1.0", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "14.0.1", "@apidevtools/openapi-schemas": "^2.1.0", "@apidevtools/swagger-methods": "^3.0.2", "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", "call-me-maybe": "^1.0.2" }, "peerDependencies": { "openapi-types": ">=7" } }, "sha512-e5mJoswsnAX0jG+J09xHFYQXb/bUc5S3pLpMxUuRUA2H8T2kni3yEoyz2R3Dltw5f4A6j6rPNMpWTK+iVDFlng=="],
837549
838550 "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
839551
@@ -843,53 +555,31 @@ · 3 unmodified lines
843555
844556 "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="],
845557
846− "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="],
847−
848558 "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="],
849559
850− "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow=="],
851−
852560 "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
853561
854− "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.28.5", "", { "dependencies": { "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5" } }, "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg=="],
855−
856562 "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="],
857563
858564 "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="],
859565
860− "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="],
861−
862566 "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="],
863567
864− "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.28.6", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg=="],
865−
866− "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="],
867−
868568 "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
869569
870570 "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
871571
872572 "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
873573
874− "@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="],
875−
876− "@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],
877−
878− "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w=="],
879−
880− "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A=="],
574+ "@babel/helpers": ["@babel/helpers@7.29.2", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.29.0" } }, "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw=="],
881575
882− "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.28.6", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA=="],
576+ "@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
883577
884578 "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="],
885579
886580 "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
887581
888− "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw=="],
889−
890− "@babel/preset-typescript": ["@babel/preset-typescript@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g=="],
891−
892− "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="],
582+ "@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="],
893583
894584 "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="],
895585
@@ -901,6 +591,8 @@ · 5 unmodified lines
901591
902592 "@base-ui/utils": ["@base-ui/utils@0.2.6", "", { "dependencies": { "@babel/runtime": "^7.28.6", "@floating-ui/utils": "^0.2.11", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-yQ+qeuqohwhsNpoYDqqXaLllYAkPCP4vYdDrVo8FQXaAPfHWm1pG/Vm+jmGTA5JFS0BAIjookyapuJFY8F9PIw=="],
903593
594+ "@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.2", "", {}, "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA=="],
595+
904596 "@changesets/apply-release-plan": ["@changesets/apply-release-plan@7.1.0", "", { "dependencies": { "@changesets/config": "^3.1.3", "@changesets/get-version-range-type": "^0.4.0", "@changesets/git": "^3.0.4", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "detect-indent": "^6.0.0", "fs-extra": "^7.0.1", "lodash.startcase": "^4.4.0", "outdent": "^0.5.0", "prettier": "^2.7.1", "resolve-from": "^5.0.0", "semver": "^7.5.3" } }, "sha512-yq8ML3YS7koKQ/9bk1PqO0HMzApIFNwjlwCnwFEXMzNe8NpzeeYYKCmnhWJGkN8g7E51MnWaSbqRcTcdIxUgnQ=="],
905597
906598 "@changesets/assemble-release-plan": ["@changesets/assemble-release-plan@6.0.9", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "semver": "^7.5.3" } }, "sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ=="],
@@ -935,19 +627,17 @@ · 28 unmodified lines
935627
936628 "@changesets/write": ["@changesets/write@0.4.0", "", { "dependencies": { "@changesets/types": "^6.1.0", "fs-extra": "^7.0.1", "human-id": "^4.1.1", "prettier": "^2.7.1" } }, "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q=="],
937629
938− "@csstools/color-helpers": ["@csstools/color-helpers@5.1.0", "", {}, "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA=="],
939−
940− "@csstools/css-calc": ["@csstools/css-calc@2.1.4", "", { "peerDependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4" } }, "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ=="],
630+ "@chevrotain/cst-dts-gen": ["@chevrotain/cst-dts-gen@11.1.2", "", { "dependencies": { "@chevrotain/gast": "11.1.2", "@chevrotain/types": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-XTsjvDVB5nDZBQB8o0o/0ozNelQtn2KrUVteIHSlPd2VAV2utEb6JzyCJaJ8tGxACR4RiBNWy5uYUHX2eji88Q=="],
941631
942− "@csstools/css-color-parser": ["@csstools/css-color-parser@3.1.0", "", { "dependencies": { "@csstools/color-helpers": "^5.1.0", "@csstools/css-calc": "^2.1.4" }, "peerDependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4" } }, "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA=="],
632+ "@chevrotain/gast": ["@chevrotain/gast@11.1.2", "", { "dependencies": { "@chevrotain/types": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-Z9zfXR5jNZb1Hlsd/p+4XWeUFugrHirq36bKzPWDSIacV+GPSVXdk+ahVWZTwjhNwofAWg/sZg58fyucKSQx5g=="],
943633
944− "@csstools/css-parser-algorithms": ["@csstools/css-parser-algorithms@3.0.5", "", { "peerDependencies": { "@csstools/css-tokenizer": "^3.0.4" } }, "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ=="],
634+ "@chevrotain/regexp-to-ast": ["@chevrotain/regexp-to-ast@11.1.2", "", {}, "sha512-nMU3Uj8naWer7xpZTYJdxbAs6RIv/dxYzkYU8GSwgUtcAAlzjcPfX1w+RKRcYG8POlzMeayOQ/znfwxEGo5ulw=="],
945635
946− "@csstools/css-tokenizer": ["@csstools/css-tokenizer@3.0.4", "", {}, "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw=="],
636+ "@chevrotain/types": ["@chevrotain/types@11.1.2", "", {}, "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw=="],
947637
948− "@dotenvx/dotenvx": ["@dotenvx/dotenvx@1.59.1", "", { "dependencies": { "commander": "^11.1.0", "dotenv": "^17.2.1", "eciesjs": "^0.4.10", "execa": "^5.1.1", "fdir": "^6.2.0", "ignore": "^5.3.0", "object-treeify": "1.1.33", "picomatch": "^4.0.2", "which": "^4.0.0" }, "bin": { "dotenvx": "src/cli/dotenvx.js" } }, "sha512-Qg+meC+XFxliuVSDlEPkKnaUjdaJKK6FNx/Wwl2UxhQR8pyPIuLhMavsF7ePdB9qFZUWV1jEK3ckbJir/WmF4w=="],
638+ "@chevrotain/utils": ["@chevrotain/utils@11.1.2", "", {}, "sha512-4mudFAQ6H+MqBTfqLmU7G1ZwRzCLfJEooL/fsF6rCX5eePMbGhoy5n4g+G4vlh2muDcsCTJtL+uKbOzWxs5LHA=="],
949639
950− "@ecies/ciphers": ["@ecies/ciphers@0.2.5", "", { "peerDependencies": { "@noble/ciphers": "^1.0.0" } }, "sha512-GalEZH4JgOMHYYcYmVqnFirFsjZHeoGMDt9IxEnM9F7GRUUyUksJ7Ou53L83WHJq3RWKD3AcBpo0iQh0oMpf8A=="],
640+ "@date-fns/tz": ["@date-fns/tz@1.4.1", "", {}, "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="],
951641
952642 "@effect-atom/atom": ["@effect-atom/atom@0.5.3", "", { "peerDependencies": { "@effect/experimental": "^0.58.0", "@effect/platform": "^0.94.2", "@effect/rpc": "^0.73.0", "effect": "^3.19.15" } }, "sha512-TRZv/i+YT3TtnN0oFORJqXdxSs1fc7lrJlH+1xZvDFyjC9hgoVnrcKbeZsDFmr6r0wYRqVo7U3IftxiQNjpNZA=="],
953643
@@ -955,167 +645,115 @@ · 1 unmodified line
955645
956646 "@effect/cli": ["@effect/cli@0.73.2", "", { "dependencies": { "ini": "^4.1.3", "toml": "^3.0.0", "yaml": "^2.5.0" }, "peerDependencies": { "@effect/platform": "^0.94.3", "@effect/printer": "^0.47.0", "@effect/printer-ansi": "^0.47.0", "effect": "^3.19.16" } }, "sha512-K8IJo81+qa1LU8dhxcDU4QO/bIjL/dPd3zUOSCpLiuUNz8Y3/T+WNs3GqIXEhMfCFMSlRZERN0YgmtRlEZUREA=="],
957647
958− "@effect/cluster": ["@effect/cluster@0.56.4", "", { "dependencies": { "kubernetes-types": "^1.30.0" }, "peerDependencies": { "@effect/platform": "^0.94.5", "@effect/rpc": "^0.73.1", "@effect/sql": "^0.49.0", "@effect/workflow": "^0.16.0", "effect": "^3.19.17" } }, "sha512-7Je5/JlbZOlsSxsbKjr97dJed2cNGWsb+TLNgMcr5mRDbcWlFOTUGvsrisEJV6waosYLIg+2omPdvnvRoYKdhA=="],
648+ "@effect/cluster": ["@effect/cluster@0.58.0", "", { "dependencies": { "kubernetes-types": "^1.30.0" }, "peerDependencies": { "@effect/platform": "^0.96.0", "@effect/rpc": "^0.75.0", "@effect/sql": "^0.51.0", "@effect/workflow": "^0.18.0", "effect": "^3.21.0" } }, "sha512-0Zog7s7XdntWcTqdqWPoj6nc7hPaWIzp0k0DsFUWyCynXNPK9dAtgFrSce04NhddNqqbhtZck/lhuqJwNBrprQ=="],
959649
960− "@effect/experimental": ["@effect/experimental@0.58.0", "", { "dependencies": { "uuid": "^11.0.3" }, "peerDependencies": { "@effect/platform": "^0.94.0", "effect": "^3.19.13", "ioredis": "^5", "lmdb": "^3" }, "optionalPeers": ["ioredis", "lmdb"] }, "sha512-IEP9sapjF6rFy5TkoqDPc86st/fnqUfjT7Xa3pWJrFGr1hzaMXHo+mWsYOZS9LAOVKnpHuVziDK97EP5qsCHVA=="],
650+ "@effect/experimental": ["@effect/experimental@0.60.0", "", { "dependencies": { "uuid": "^11.0.3" }, "peerDependencies": { "@effect/platform": "^0.96.0", "effect": "^3.21.0", "ioredis": "^5", "lmdb": "^3" }, "optionalPeers": ["ioredis", "lmdb"] }, "sha512-i5zIg7Xup2KgHyqHlYtkgqSE1bNzCL0GbbTQxrpIzKF0q/ebknOk/ox8B/gIq2vImjoEE81h/oxU+6i1NH210g=="],
961651
962− "@effect/opentelemetry": ["@effect/opentelemetry@0.61.0", "", { "peerDependencies": { "@effect/platform": "^0.94.2", "@opentelemetry/api": "^1.9", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", "@opentelemetry/sdk-trace-node": "^2.0.0", "@opentelemetry/sdk-trace-web": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.33.0", "effect": "^3.19.15" } }, "sha512-aTg4qWzMxGDoUZKSyws/dMZqVNoSCQIvHaPDJnWitUAVuWDAPOXiaiHJDWO39cwDlySBTCSF6rEanm3+nR/2Mg=="],
652+ "@effect/language-service": ["@effect/language-service@0.84.2", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-l04qNxpiA8rY5yXWckRPJ7Mk5MNerXuNymSFf+IdflfI5i8jgL1bpBNLuP6ijg7wgjdHc/KmTnCj2kT0SCntuA=="],
963653
964− "@effect/platform": ["@effect/platform@0.94.5", "", { "dependencies": { "find-my-way-ts": "^0.1.6", "msgpackr": "^1.11.4", "multipasta": "^0.2.7" }, "peerDependencies": { "effect": "^3.19.17" } }, "sha512-z05APUiDDPbodhTkH/RJqOLoCU11bU2IZLfcwLFrld03+ob1VeqRnELQlmueLIYm6NZifHAtjl32V+GRt34y4A=="],
654+ "@effect/platform": ["@effect/platform@0.96.0", "", { "dependencies": { "find-my-way-ts": "^0.1.6", "msgpackr": "^1.11.4", "multipasta": "^0.2.7" }, "peerDependencies": { "effect": "^3.21.0" } }, "sha512-U7PLhkVzg7zzrgFvyWATOzD6reL87KG/fcdOxgLWBQ/J5CCU6qdPAVG+0o6o+IxcsLoqGwxs+rFxaFzrdtDV1A=="],
965655
966− "@effect/platform-node": ["@effect/platform-node@0.104.1", "", { "dependencies": { "@effect/platform-node-shared": "^0.57.1", "mime": "^3.0.0", "undici": "^7.10.0", "ws": "^8.18.2" }, "peerDependencies": { "@effect/cluster": "^0.56.1", "@effect/platform": "^0.94.2", "@effect/rpc": "^0.73.0", "@effect/sql": "^0.49.0", "effect": "^3.19.15" } }, "sha512-jT1a/z98niK6fnEU8pWHPPCdJMVDRCIdB65lolcOjse5rsTwVbczMjvKkhVQpF63mNWoOnol7OTRNkw5L54llg=="],
656+ "@effect/platform-bun": ["@effect/platform-bun@0.89.0", "", { "dependencies": { "@effect/platform-node-shared": "^0.59.0", "multipasta": "^0.2.7" }, "peerDependencies": { "@effect/cluster": "^0.58.0", "@effect/platform": "^0.96.0", "@effect/rpc": "^0.75.0", "@effect/sql": "^0.51.0", "effect": "^3.21.0" } }, "sha512-ReT5f2vujJfffMOBexrgwJd2RLxgfr2G0c1FyCsoflcjdQJ7RZE3cwHDp1M3hAzmG67wWAssMHqLsX6H/n27sQ=="],
967657
968− "@effect/platform-node-shared": ["@effect/platform-node-shared@0.57.1", "", { "dependencies": { "@parcel/watcher": "^2.5.1", "multipasta": "^0.2.7", "ws": "^8.18.2" }, "peerDependencies": { "@effect/cluster": "^0.56.1", "@effect/platform": "^0.94.2", "@effect/rpc": "^0.73.0", "@effect/sql": "^0.49.0", "effect": "^3.19.15" } }, "sha512-oX/bApMdoKsyrDiNdJxo7U9Rz1RXsjRv+ecfAPp1qGlSdGIo32wVRvJ2XCHqYj0sqaYJS0pU0/GCulRfVGuJag=="],
658+ "@effect/platform-node": ["@effect/platform-node@0.106.0", "", { "dependencies": { "@effect/platform-node-shared": "^0.59.0", "mime": "^3.0.0", "undici": "^7.10.0", "ws": "^8.18.2" }, "peerDependencies": { "@effect/cluster": "^0.58.0", "@effect/platform": "^0.96.0", "@effect/rpc": "^0.75.0", "@effect/sql": "^0.51.0", "effect": "^3.21.0" } }, "sha512-mpsJK2jNLVd0jQAjHKBo8j3wdKWznSGvfnKBcAuG/9Rr4mb8bMRZFLXHHT9wUP7EvnZ0tDZJgEDxkC+j+ByRag=="],
659+
660+ "@effect/platform-node-shared": ["@effect/platform-node-shared@0.59.0", "", { "dependencies": { "@parcel/watcher": "^2.5.1", "multipasta": "^0.2.7", "ws": "^8.18.2" }, "peerDependencies": { "@effect/cluster": "^0.58.0", "@effect/platform": "^0.96.0", "@effect/rpc": "^0.75.0", "@effect/sql": "^0.51.0", "effect": "^3.21.0" } }, "sha512-3bq2YKKfLY7UFauZSxqZUneCXoA3SMSls82V+0RKunvRlfPuPQW0hVn6t1RkvEdh0PDoygWG2mZXYQa6Iqgp9A=="],
969661
970662 "@effect/printer": ["@effect/printer@0.47.0", "", { "peerDependencies": { "@effect/typeclass": "^0.38.0", "effect": "^3.19.0" } }, "sha512-VgR8e+YWWhMEAh9qFOjwiZ3OXluAbcVLIOtvp2S5di1nSrPOZxj78g8LE77JSvyfp5y5bS2gmFW+G7xD5uU+2Q=="],
971663
972664 "@effect/printer-ansi": ["@effect/printer-ansi@0.47.0", "", { "dependencies": { "@effect/printer": "^0.47.0" }, "peerDependencies": { "@effect/typeclass": "^0.38.0", "effect": "^3.19.0" } }, "sha512-tDEQ9XJpXDNYoWMQJHFRMxKGmEOu6z32x3Kb8YLOV5nkauEKnKmWNs7NBp8iio/pqoJbaSwqDwUg9jXVquxfWQ=="],
973665
974− "@effect/rpc": ["@effect/rpc@0.73.2", "", { "dependencies": { "msgpackr": "^1.11.4" }, "peerDependencies": { "@effect/platform": "^0.94.5", "effect": "^3.19.18" } }, "sha512-td7LHDgBOYKg+VgGWEelD8rSAmvjXz7am17vfxZROX5qIYuvH7drL/z4p5xQFadhHZ7DYdlFpqdO9ggc77OCIw=="],
975−
976− "@effect/sql": ["@effect/sql@0.49.0", "", { "dependencies": { "uuid": "^11.0.3" }, "peerDependencies": { "@effect/experimental": "^0.58.0", "@effect/platform": "^0.94.0", "effect": "^3.19.13" } }, "sha512-9UEKR+z+MrI/qMAmSvb/RiD9KlgIazjZUCDSpwNgm0lEK9/Q6ExEyfziiYFVCPiptp52cBw8uBHRic8hHnwqXA=="],
977−
978− "@effect/typeclass": ["@effect/typeclass@0.38.0", "", { "peerDependencies": { "effect": "^3.19.0" } }, "sha512-lMUcJTRtG8KXhXoczapZDxbLK5os7M6rn0zkvOgncJW++A0UyelZfMVMKdT5R+fgpZcsAU/1diaqw3uqLJwGxA=="],
979−
980− "@effect/vitest": ["@effect/vitest@0.27.0", "", { "peerDependencies": { "effect": "^3.19.0", "vitest": "^3.2.0" } }, "sha512-8bM7n9xlMUYw9GqPIVgXFwFm2jf27m/R7psI64PGpwU5+26iwyxp9eAXEsfT5S6lqztYfpQQ1Ubp5o6HfNYzJQ=="],
981−
982− "@effect/workflow": ["@effect/workflow@0.16.0", "", { "peerDependencies": { "@effect/experimental": "^0.58.0", "@effect/platform": "^0.94.0", "@effect/rpc": "^0.73.0", "effect": "^3.19.13" } }, "sha512-MiAdlxx3TixkgHdbw+Yf1Z3tHAAE0rOQga12kIydJqj05Fnod+W/I+kQGRMY/XWRg+QUsVxhmh1qTr7Ype6lrw=="],
666+ "@effect/rpc": ["@effect/rpc@0.75.0", "", { "dependencies": { "msgpackr": "^1.11.4" }, "peerDependencies": { "@effect/platform": "^0.96.0", "effect": "^3.21.0" } }, "sha512-VFeJ16cZUXqiIzG9UHOVKGuiBPJ7fV+0lEbJU6xi12JnnxXe/19BQPpOwiRawCUbPOR3/xIURDUgGxU+Ft0pvQ=="],
983667
984− "@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
668+ "@effect/sql": ["@effect/sql@0.51.0", "", { "dependencies": { "uuid": "^11.0.3" }, "peerDependencies": { "@effect/experimental": "^0.60.0", "@effect/platform": "^0.96.0", "effect": "^3.21.0" } }, "sha512-e7hWe46QD15eMCr4kNBMVdItIVK/WLHJG+d8DLL1FjVf5Ra82k2mwUYIXplJewVbHjt3my6GSKPPd1ZrQjVd5A=="],
985669
986− "@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
670+ "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@0.52.0", "", { "peerDependencies": { "@effect/experimental": "^0.60.0", "@effect/platform": "^0.96.0", "@effect/sql": "^0.51.0", "effect": "^3.21.0" } }, "sha512-iqQ7SvSNxq0HLjKW5IQ29FsCTzOD1CuX1wuBEuPLLgPCvuEykEHLn4zDrs2qJ+O3CBEUm4kiCy29tmfHE7uAdw=="],
987671
988− "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
672+ "@effect/sql-sqlite-node": ["@effect/sql-sqlite-node@0.52.0", "", { "dependencies": { "better-sqlite3": "^12.6.2" }, "peerDependencies": { "@effect/experimental": "^0.60.0", "@effect/platform": "^0.96.0", "@effect/sql": "^0.51.0", "effect": "^3.21.0" } }, "sha512-yijDbly4MwxAPebvd2ZBI62qDpGdXKL96drMzflXDnjEh2JiVr/xVyy1VB0JsVxqw8IJ9TUIgOvAJWQ88oVMXA=="],
989673
990− "@endo/cache-map": ["@endo/cache-map@1.1.0", "", {}, "sha512-owFGshs/97PDw9oguZqU/px8Lv1d0KjAUtDUiPwKHNXRVUE/jyettEbRoTbNJR1OaI8biMn6bHr9kVJsOh6dXw=="],
674+ "@effect/typeclass": ["@effect/typeclass@0.38.0", "", { "peerDependencies": { "effect": "^3.19.0" } }, "sha512-lMUcJTRtG8KXhXoczapZDxbLK5os7M6rn0zkvOgncJW++A0UyelZfMVMKdT5R+fgpZcsAU/1diaqw3uqLJwGxA=="],
991675
992− "@endo/env-options": ["@endo/env-options@1.1.11", "", {}, "sha512-p9OnAPsdqoX4YJsE98e3NBVhIr2iW9gNZxHhAI2/Ul5TdRfoOViItzHzTqrgUVopw6XxA1u1uS6CykLMDUxarA=="],
676+ "@effect/vitest": ["@effect/vitest@0.27.0", "", { "peerDependencies": { "effect": "^3.19.0", "vitest": "^3.2.0" } }, "sha512-8bM7n9xlMUYw9GqPIVgXFwFm2jf27m/R7psI64PGpwU5+26iwyxp9eAXEsfT5S6lqztYfpQQ1Ubp5o6HfNYzJQ=="],
993677
994− "@endo/immutable-arraybuffer": ["@endo/immutable-arraybuffer@1.1.2", "", {}, "sha512-u+NaYB2aqEugQ3u7w3c5QNkPogf8q/xGgsPaqdY6pUiGWtYiTiFspKFcha6+oeZhWXWQ23rf0KrUq0kfuzqYyQ=="],
678+ "@effect/workflow": ["@effect/workflow@0.18.0", "", { "peerDependencies": { "@effect/experimental": "^0.60.0", "@effect/platform": "^0.96.0", "@effect/rpc": "^0.75.0", "effect": "^3.21.0" } }, "sha512-9Zp+x9ADtR0H6CRhU6wLyPcIRjO1PXjvSpUlFlBQ8piw7ldjPmnUWEY8YQuH6eExV2dalQ4z2LMiZ5Bd7XAJbA=="],
995679
996− "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],
680+ "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
997681
998− "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="],
682+ "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],
999683
1000− "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="],
684+ "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="],
1001685
1002− "@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="],
686+ "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="],
1003687
1004− "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="],
688+ "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="],
1005689
1006− "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="],
690+ "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="],
1007691
1008− "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="],
692+ "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="],
1009693
1010− "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="],
694+ "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="],
1011695
1012− "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="],
696+ "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="],
1013697
1014− "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="],
698+ "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="],
1015699
1016− "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="],
700+ "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="],
1017701
1018− "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="],
702+ "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="],
1019703
1020− "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="],
704+ "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="],
1021705
1022− "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="],
706+ "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="],
1023707
1024− "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="],
708+ "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="],
1025709
1026− "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="],
710+ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="],
1027711
1028− "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="],
712+ "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="],
1029713
1030− "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="],
714+ "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="],
1031715
1032− "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="],
716+ "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="],
1033717
1034− "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="],
718+ "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="],
1035719
1036− "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="],
720+ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="],
1037721
1038− "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="],
722+ "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="],
1039723
1040− "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="],
724+ "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="],
1041725
1042− "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="],
726+ "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="],
1043727
1044− "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="],
728+ "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="],
1045729
1046− "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="],
730+ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
1047731
1048− "@executor/ai-sdk-adapter": ["@executor/ai-sdk-adapter@workspace:packages/hosts/ai-sdk"],
732+ "@executor/api": ["@executor/api@workspace:packages/core/api"],
1049733
1050734 "@executor/codemode-core": ["@executor/codemode-core@workspace:packages/kernel/core"],
1051735
1052− "@executor/docs": ["@executor/docs@workspace:apps/docs"],
736+ "@executor/config": ["@executor/config@workspace:packages/core/config"],
1053737
1054− "@executor/effect-test-utils": ["@executor/effect-test-utils@workspace:packages/dev/effect-test-utils"],
738+ "@executor/execution": ["@executor/execution@workspace:packages/core/execution"],
1055739
1056− "@executor/executor-mcp": ["@executor/executor-mcp@workspace:packages/hosts/mcp"],
740+ "@executor/host-mcp": ["@executor/host-mcp@workspace:packages/hosts/mcp"],
1057741
1058742 "@executor/ir": ["@executor/ir@workspace:packages/kernel/ir"],
1059743
1060− "@executor/kitchen-sink": ["@executor/kitchen-sink@workspace:packages/dev/kitchen-sink"],
1061−
1062− "@executor/mcp-elicitation-demo": ["@executor/mcp-elicitation-demo@workspace:examples/mcp-elicitation-demo"],
1063−
1064− "@executor/platform-api": ["@executor/platform-api@workspace:packages/platform/api"],
1065−
1066− "@executor/platform-sdk": ["@executor/platform-sdk@workspace:packages/platform/sdk"],
1067−
1068− "@executor/platform-sdk-file": ["@executor/platform-sdk-file@workspace:packages/platform/sdk-file"],
1069−
1070− "@executor/plugin-execution-history-react": ["@executor/plugin-execution-history-react@workspace:plugins/execution-history/react"],
1071−
1072− "@executor/plugin-google-discovery-http": ["@executor/plugin-google-discovery-http@workspace:plugins/google-discovery/http"],
1073−
1074− "@executor/plugin-google-discovery-react": ["@executor/plugin-google-discovery-react@workspace:plugins/google-discovery/react"],
1075−
1076− "@executor/plugin-google-discovery-sdk": ["@executor/plugin-google-discovery-sdk@workspace:plugins/google-discovery/sdk"],
1077−
1078− "@executor/plugin-google-discovery-shared": ["@executor/plugin-google-discovery-shared@workspace:plugins/google-discovery/shared"],
1079−
1080− "@executor/plugin-graphql-http": ["@executor/plugin-graphql-http@workspace:plugins/graphql/http"],
1081−
1082− "@executor/plugin-graphql-react": ["@executor/plugin-graphql-react@workspace:plugins/graphql/react"],
1083−
1084− "@executor/plugin-graphql-sdk": ["@executor/plugin-graphql-sdk@workspace:plugins/graphql/sdk"],
744+ "@executor/plugin-file-secrets": ["@executor/plugin-file-secrets@workspace:packages/plugins/file-secrets"],
1085745
1086− "@executor/plugin-graphql-shared": ["@executor/plugin-graphql-shared@workspace:plugins/graphql/shared"],
746+ "@executor/plugin-google-discovery": ["@executor/plugin-google-discovery@workspace:packages/plugins/google-discovery"],
1087747
1088− "@executor/plugin-keychain-secret-store-sdk": ["@executor/plugin-keychain-secret-store-sdk@workspace:plugins/keychain-secret-store/sdk"],
748+ "@executor/plugin-graphql": ["@executor/plugin-graphql@workspace:packages/plugins/graphql"],
1089749
1090− "@executor/plugin-local-secret-store-sdk": ["@executor/plugin-local-secret-store-sdk@workspace:plugins/local-secret-store/sdk"],
750+ "@executor/plugin-keychain": ["@executor/plugin-keychain@workspace:packages/plugins/keychain"],
1091751
1092− "@executor/plugin-local-tools-react": ["@executor/plugin-local-tools-react@workspace:plugins/local-tools/react"],
752+ "@executor/plugin-mcp": ["@executor/plugin-mcp@workspace:packages/plugins/mcp"],
1093753
1094− "@executor/plugin-local-tools-sdk": ["@executor/plugin-local-tools-sdk@workspace:plugins/local-tools/sdk"],
754+ "@executor/plugin-onepassword": ["@executor/plugin-onepassword@workspace:packages/plugins/onepassword"],
1095755
1096− "@executor/plugin-mcp-http": ["@executor/plugin-mcp-http@workspace:plugins/mcp/http"],
1097−
1098− "@executor/plugin-mcp-react": ["@executor/plugin-mcp-react@workspace:plugins/mcp/react"],
1099−
1100− "@executor/plugin-mcp-sdk": ["@executor/plugin-mcp-sdk@workspace:plugins/mcp/sdk"],
1101−
1102− "@executor/plugin-mcp-shared": ["@executor/plugin-mcp-shared@workspace:plugins/mcp/shared"],
1103−
1104− "@executor/plugin-onepassword-http": ["@executor/plugin-onepassword-http@workspace:plugins/onepassword/http"],
1105−
1106− "@executor/plugin-onepassword-react": ["@executor/plugin-onepassword-react@workspace:plugins/onepassword/react"],
1107−
1108− "@executor/plugin-onepassword-sdk": ["@executor/plugin-onepassword-sdk@workspace:plugins/onepassword/sdk"],
1109−
1110− "@executor/plugin-onepassword-shared": ["@executor/plugin-onepassword-shared@workspace:plugins/onepassword/shared"],
1111−
1112− "@executor/plugin-openapi-http": ["@executor/plugin-openapi-http@workspace:plugins/openapi/http"],
1113−
1114− "@executor/plugin-openapi-react": ["@executor/plugin-openapi-react@workspace:plugins/openapi/react"],
1115−
1116− "@executor/plugin-openapi-sdk": ["@executor/plugin-openapi-sdk@workspace:plugins/openapi/sdk"],
1117−
1118− "@executor/plugin-openapi-shared": ["@executor/plugin-openapi-shared@workspace:plugins/openapi/shared"],
756+ "@executor/plugin-openapi": ["@executor/plugin-openapi@workspace:packages/plugins/openapi"],
1119757
1120758 "@executor/react": ["@executor/react@workspace:packages/clients/react"],
1121759
@@ -1123,15 +761,13 @@ · 1 unmodified line
1123761
1124762 "@executor/runtime-quickjs": ["@executor/runtime-quickjs@workspace:packages/kernel/runtime-quickjs"],
1125763
1126− "@executor/runtime-ses": ["@executor/runtime-ses@workspace:packages/kernel/runtime-ses"],
1127−
1128− "@executor/serve-skills-via-mcp-demo": ["@executor/serve-skills-via-mcp-demo@workspace:examples/serve-skills-via-mcp"],
764+ "@executor/sdk": ["@executor/sdk@workspace:packages/core/sdk"],
1129765
1130− "@executor/server": ["@executor/server@workspace:packages/platform/server"],
766+ "@executor/server": ["@executor/server@workspace:apps/server"],
1131767
1132− "@executor/source-core": ["@executor/source-core@workspace:packages/sources/core"],
768+ "@executor/storage-file": ["@executor/storage-file@workspace:packages/core/storage-file"],
1133769
1134− "@executor/sqlite-sdk-consumer-example": ["@executor/sqlite-sdk-consumer-example@workspace:examples/sqlite-sdk-consumer"],
770+ "@executor/ui": ["@executor/ui@workspace:packages/ui"],
1135771
1136772 "@executor/web": ["@executor/web@workspace:apps/web"],
1137773
@@ -1143,26 +779,16 @@ · 5 unmodified lines
1143779
1144780 "@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="],
1145781
1146− "@grpc/grpc-js": ["@grpc/grpc-js@1.14.3", "", { "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA=="],
1147−
1148− "@grpc/proto-loader": ["@grpc/proto-loader@0.8.0", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.5.3", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ=="],
1149−
1150− "@hono/node-server": ["@hono/node-server@1.19.11", "", { "peerDependencies": { "hono": "^4" } }, "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g=="],
1151−
1152− "@hono/vite-dev-server": ["@hono/vite-dev-server@0.25.0", "", { "dependencies": { "@hono/node-server": "^1.14.2", "minimatch": "^9.0.3" }, "peerDependencies": { "hono": "*", "miniflare": "*", "wrangler": "*" }, "optionalPeers": ["miniflare", "wrangler"] }, "sha512-4j5rs7yUTOObU2/yCEHeWbf3C8m95SD9lhdUUE6CJ462Emp9vS94yiza2dsA8+ly5pdaIQW0cd4nhNVcwYL5tA=="],
782+ "@hono/node-server": ["@hono/node-server@1.19.12", "", { "peerDependencies": { "hono": "^4" } }, "sha512-txsUW4SQ1iilgE0l9/e9VQWmELXifEFvmdA1j6WFh/aFPj99hIntrSsq/if0UWyGVkmrRPKA1wCeP+UCr1B9Uw=="],
1153783
1154− "@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="],
784+ "@hookform/resolvers": ["@hookform/resolvers@5.2.2", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.55.0" } }, "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA=="],
1155785
1156− "@inquirer/confirm": ["@inquirer/confirm@5.1.21", "", { "dependencies": { "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ=="],
786+ "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
1157787
1158− "@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="],
788+ "@iconify/utils": ["@iconify/utils@3.1.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.0" } }, "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw=="],
1159789
1160790 "@inquirer/external-editor": ["@inquirer/external-editor@1.0.3", "", { "dependencies": { "chardet": "^2.1.1", "iconv-lite": "^0.7.0" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA=="],
1161791
1162− "@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="],
1163−
1164− "@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="],
1165−
1166792 "@jitl/quickjs-ffi-types": ["@jitl/quickjs-ffi-types@0.31.0", "", {}, "sha512-1yrgvXlmXH2oNj3eFTrkwacGJbmM0crwipA3ohCrjv52gBeDaD7PsTvFYinlAnqU8iPME3LGP437yk05a2oejw=="],
1167793
1168794 "@jitl/quickjs-wasmfile-debug-asyncify": ["@jitl/quickjs-wasmfile-debug-asyncify@0.31.0", "", { "dependencies": { "@jitl/quickjs-ffi-types": "0.31.0" } }, "sha512-YkdzQdr1uaftFhgEnTRjTTZHk2SFZdpWO7XhOmRVbi6CEVsH9g5oNF8Ta1q3OuSJHRwwT8YsuR1YzEiEIJEk6w=="],
@@ -1183,15 +809,13 @@ · 14 unmodified lines
1183809
1184810 "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
1185811
1186− "@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="],
1187−
1188812 "@manypkg/find-root": ["@manypkg/find-root@1.1.0", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@types/node": "^12.7.1", "find-up": "^4.1.0", "fs-extra": "^8.1.0" } }, "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA=="],
1189813
1190814 "@manypkg/get-packages": ["@manypkg/get-packages@1.1.3", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@changesets/types": "^4.0.1", "@manypkg/find-root": "^1.1.0", "fs-extra": "^8.1.0", "globby": "^11.0.0", "read-yaml-file": "^1.1.0" } }, "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A=="],
1191815
1192− "@medv/finder": ["@medv/finder@4.0.2", "", {}, "sha512-RraNY9SCcx4KZV0Dh6BEW6XEW2swkqYca74pkFFRw6hHItSHiy+O/xMnpbofjYbzXj0tSpBGthUF1hHTsr3vIQ=="],
816+ "@mermaid-js/parser": ["@mermaid-js/parser@1.1.0", "", { "dependencies": { "langium": "^4.0.0" } }, "sha512-gxK9ZX2+Fex5zu8LhRQoMeMPEHbc73UKZ0FQ54YrQtUxE1VVhMwzeNtKRPAu5aXks4FasbMe4xB4bWrmq6Jlxw=="],
1193817
1194− "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.27.1", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA=="],
818+ "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="],
1195819
1196820 "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="],
1197821
@@ -1205,8 +829,6 @@ · 7 unmodified lines
1205829
1206830 "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="],
1207831
1208− "@mswjs/interceptors": ["@mswjs/interceptors@0.41.3", "", { "dependencies": { "@open-draft/deferred-promise": "^2.2.0", "@open-draft/logger": "^0.3.0", "@open-draft/until": "^2.0.0", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "strict-event-emitter": "^0.5.1" } }, "sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA=="],
1209−
1210832 "@napi-rs/keyring": ["@napi-rs/keyring@1.2.0", "", { "optionalDependencies": { "@napi-rs/keyring-darwin-arm64": "1.2.0", "@napi-rs/keyring-darwin-x64": "1.2.0", "@napi-rs/keyring-freebsd-x64": "1.2.0", "@napi-rs/keyring-linux-arm-gnueabihf": "1.2.0", "@napi-rs/keyring-linux-arm64-gnu": "1.2.0", "@napi-rs/keyring-linux-arm64-musl": "1.2.0", "@napi-rs/keyring-linux-riscv64-gnu": "1.2.0", "@napi-rs/keyring-linux-x64-gnu": "1.2.0", "@napi-rs/keyring-linux-x64-musl": "1.2.0", "@napi-rs/keyring-win32-arm64-msvc": "1.2.0", "@napi-rs/keyring-win32-ia32-msvc": "1.2.0", "@napi-rs/keyring-win32-x64-msvc": "1.2.0" } }, "sha512-d0d4Oyxm+v980PEq1ZH2PmS6cvpMIRc17eYpiU47KgW+lzxklMu6+HOEOPmxrpnF/XQZ0+Q78I2mgMhbIIo/dg=="],
1211833
1212834 "@napi-rs/keyring-darwin-arm64": ["@napi-rs/keyring-darwin-arm64@1.2.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-CA83rDeyONDADO25JLZsh3eHY8yTEtm/RS6ecPsY+1v+dSawzT9GywBMu2r6uOp1IEhQs/xAfxgybGAFr17lSA=="],
@@ -1233,349 +855,399 @@ · 20 unmodified lines
1233855
1234856 "@napi-rs/keyring-win32-x64-msvc": ["@napi-rs/keyring-win32-x64-msvc@1.2.0", "", { "os": "win32", "cpu": "x64" }, "sha512-xFlx/TsmqmCwNU9v+AVnEJgoEAlBYgzFF5Ihz1rMpPAt4qQWWkMd4sCyM1gMJ1A/GnRqRegDiQpwaxGUHFtFbA=="],
1235857
1236− "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
858+ "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
859+
860+ "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
861+
862+ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
1237863
1238− "@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
864+ "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.58.0", "", { "os": "android", "cpu": "arm" }, "sha512-1T7UN3SsWWxpWyWGn1cT3ASNJOo+pI3eUkmEl7HgtowapcV8kslYpFQcYn431VuxghXakPNlbjRwhqmR37PFOg=="],
1239865
1240− "@noble/curves": ["@noble/curves@1.9.7", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw=="],
866+ "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.58.0", "", { "os": "android", "cpu": "arm64" }, "sha512-GryzujxuiRv2YFF7bRy8mKcxlbuAN+euVUtGJt9KKbLT8JBUIosamVhcthLh+VEr6KE6cjeVMAQxKAzJcoN7dg=="],
1241867
1242− "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
868+ "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.58.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-7/bRSJIwl4GxeZL9rPZ11anNTyUO9epZrfEJH/ZMla3+/gbQ6xZixh9nOhsZ0QwsTW7/5J2A/fHbD1udC5DQQA=="],
1243869
1244− "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
870+ "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.58.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-EqdtJSiHweS2vfILNrpyJ6HUwpEq2g7+4Zx1FPi4hu3Hu7tC3znF6ufbXO8Ub2LD4mGgznjI7kSdku9NDD1Mkg=="],
1245871
1246− "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
872+ "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.58.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-VQt5TH4M42mY20F545G637RKxV/yjwVtKk2vfXuazfReSIiuvWBnv+FVSvIV5fKVTJNjt3GSJibh6JecbhGdBw=="],
1247873
1248− "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
874+ "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.58.0", "", { "os": "linux", "cpu": "arm" }, "sha512-fBYcj4ucwpAtjJT3oeBdFBYKvNyjRSK+cyuvBOTQjh0jvKp4yeA4S/D0IsCHus/VPaNG5L48qQkh+Vjy3HL2/Q=="],
875+
876+ "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.58.0", "", { "os": "linux", "cpu": "arm" }, "sha512-0BeuFfwlUHlJ1xpEdSD1YO3vByEFGPg36uLjK1JgFaxFb4W6w17F8ET8sz5cheZ4+x5f2xzdnRrrWv83E3Yd8g=="],
877+
878+ "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.58.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-TXlZgnPTlxrQzxG9ZXU7BNwx1Ilrr17P3GwZY0If2EzrinqRH3zXPc3HrRcBJgcsoZNMuNL5YivtkJYgp467UQ=="],
1249879
1250− "@open-draft/deferred-promise": ["@open-draft/deferred-promise@2.2.0", "", {}, "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA=="],
880+ "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.58.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-zSoYRo5dxHLcUx93Stl2hW3hSNjPt99O70eRVWt5A1zwJ+FPjeCCANCD2a9R4JbHsdcl11TIQOjyigcRVOH2mw=="],
1251881
1252− "@open-draft/logger": ["@open-draft/logger@0.3.0", "", { "dependencies": { "is-node-process": "^1.2.0", "outvariant": "^1.4.0" } }, "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ=="],
882+ "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.58.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NQ0U/lqxH2/VxBYeAIvMNUK1y0a1bJ3ZicqkF2c6wfakbEciP9jvIE4yNzCFpZaqeIeRYaV7AVGqEO1yrfVPjA=="],
1253883
1254− "@open-draft/until": ["@open-draft/until@2.1.0", "", {}, "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg=="],
884+ "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.58.0", "", { "os": "linux", "cpu": "none" }, "sha512-X9J+kr3gIC9FT8GuZt0ekzpNUtkBVzMVU4KiKDSlocyQuEgi3gBbXYN8UkQiV77FTusLDPsovjo95YedHr+3yg=="],
1255885
1256− "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
886+ "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.58.0", "", { "os": "linux", "cpu": "none" }, "sha512-CDze3pi1OO3Wvb/QsXjmLEY4XPKGM6kIo82ssNOgmcl1IdndF9VSGAE38YLhADWmOac7fjqhBw82LozuUVxD0Q=="],
1257887
1258− "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.213.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-zRM5/Qj6G84Ej3F1yt33xBVY/3tnMxtL1fiDIxYbDWYaZ/eudVw3/PBiZ8G7JwUxXxjW8gU4g6LnOyfGKYHYgw=="],
888+ "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.58.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-b/89glbxFaEAcA6Uf1FvCNecBJEgcUTsV1quzrqXM/o4R1M4u+2KCVuyGCayN2UpsRWtGGLb+Ver0tBBpxaPog=="],
1259889
1260− "@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.6.0", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-L8UyDwqpTcbkIK5cgwDRDYDoEhQoj8wp8BwsO19w3LB1Z41yEQm2VJyNfAi9DrLP/YTqXqWpKHyZfR9/tFYo1Q=="],
890+ "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.58.0", "", { "os": "linux", "cpu": "x64" }, "sha512-0/yYpkq9VJFCEcuRlrViGj8pJUFFvNS4EkEREaN7CB1EcLXJIaVSSa5eCihwBGXtOZxhnblWgxks9juRdNQI7w=="],
1261891
1262− "@opentelemetry/core": ["@opentelemetry/core@2.6.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-HLM1v2cbZ4TgYN6KEOj+Bbj8rAKriOdkF9Ed3tG25FoprSiQl7kYc+RRT6fUZGOvx0oMi5U67GoFdT+XUn8zEg=="],
892+ "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.58.0", "", { "os": "linux", "cpu": "x64" }, "sha512-hr6FNvmcAXiH+JxSvaJ4SJ1HofkdqEElXICW9sm3/Rd5eC3t7kzvmLyRAB3NngKO2wzXRCAm4Z/mGWfrsS4X8w=="],
1263893
1264− "@opentelemetry/exporter-trace-otlp-grpc": ["@opentelemetry/exporter-trace-otlp-grpc@0.213.0", "", { "dependencies": { "@grpc/grpc-js": "^1.14.3", "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-grpc-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/sdk-trace-base": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-L8y6piP4jBIIx1Nv7/9hkx25ql6/Cro/kQrs+f9e8bPF0Ar5Dm991v7PnbtubKz6Q4fT872H56QXUWVnz/Cs4Q=="],
894+ "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.58.0", "", { "os": "none", "cpu": "arm64" }, "sha512-R+O368VXgRql1K6Xar+FEo7NEwfo13EibPMoTv3sesYQedRXd6m30Dh/7lZMxnrQVFfeo4EOfYIP4FpcgWQNHg=="],
1265895
1266− "@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MegxAP1/n09Ob2dQvY5NBDVjAFkZRuKtWKxYev1R2M8hrsgXzQGkaMgoEKeUOyQ0FUyYcO29UOnYdQWmWa0PXg=="],
896+ "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.58.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Q0FZiAY/3c4YRj4z3h9K1PgaByrifrfbBoODSeX7gy97UtB7pySPUQfC2B/GbxWU6k7CzQrRy5gME10PltLAFQ=="],
1267897
1268− "@opentelemetry/otlp-grpc-exporter-base": ["@opentelemetry/otlp-grpc-exporter-base@0.213.0", "", { "dependencies": { "@grpc/grpc-js": "^1.14.3", "@opentelemetry/core": "2.6.0", "@opentelemetry/otlp-exporter-base": "0.213.0", "@opentelemetry/otlp-transformer": "0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-XgRGuLE9usFNlnw2lgMIM4HTwpcIyjdU/xPoJ8v3LbBLBfjaDkIugjc9HoWa7ZSJ/9Bhzgvm/aD0bGdYUFgnTw=="],
898+ "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.58.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-Y8FKBABrSPp9H0QkRLHDHOSUgM/309a3IvOVgPcVxYcX70wxJrk608CuTg7w+C6vEd724X5wJoNkBcGYfH7nNQ=="],
1269899
1270− "@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.213.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.213.0", "@opentelemetry/core": "2.6.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/sdk-logs": "0.213.0", "@opentelemetry/sdk-metrics": "2.6.0", "@opentelemetry/sdk-trace-base": "2.6.0", "protobufjs": "^7.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-RSuAlxFFPjeK4d5Y6ps8L2WhaQI6CXWllIjvo5nkAlBpmq2XdYWEBGiAbOF4nDs8CX4QblJDv5BbMUft3sEfDw=="],
900+ "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.58.0", "", { "os": "win32", "cpu": "x64" }, "sha512-bCn5rbiz5My+Bj7M09sDcnqW0QJyINRVxdZ65x1/Y2tGrMwherwK/lpk+HRQCKvXa8pcaQdF5KY5j54VGZLwNg=="],
1271901
1272− "@opentelemetry/resources": ["@opentelemetry/resources@2.6.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-D4y/+OGe3JSuYUCBxtH5T9DSAWNcvCb/nQWIga8HNtXTVPQn59j0nTBAgaAXxUVBDl40mG3Tc76b46wPlZaiJQ=="],
902+ "@parcel/watcher": ["@parcel/watcher@2.5.6", "", { "dependencies": { "detect-libc": "^2.0.3", "is-glob": "^4.0.3", "node-addon-api": "^7.0.0", "picomatch": "^4.0.3" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.6", "@parcel/watcher-darwin-arm64": "2.5.6", "@parcel/watcher-darwin-x64": "2.5.6", "@parcel/watcher-freebsd-x64": "2.5.6", "@parcel/watcher-linux-arm-glibc": "2.5.6", "@parcel/watcher-linux-arm-musl": "2.5.6", "@parcel/watcher-linux-arm64-glibc": "2.5.6", "@parcel/watcher-linux-arm64-musl": "2.5.6", "@parcel/watcher-linux-x64-glibc": "2.5.6", "@parcel/watcher-linux-x64-musl": "2.5.6", "@parcel/watcher-win32-arm64": "2.5.6", "@parcel/watcher-win32-ia32": "2.5.6", "@parcel/watcher-win32-x64": "2.5.6" } }, "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ=="],
1273903
1274− "@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.213.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.213.0", "@opentelemetry/core": "2.6.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-00xlU3GZXo3kXKve4DLdrAL0NAFUaZ9appU/mn00S/5kSUdAvyYsORaDUfR04Mp2CLagAOhrzfUvYozY/EZX2g=="],
904+ "@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.6", "", { "os": "android", "cpu": "arm64" }, "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A=="],
1275905
1276− "@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.6.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/resources": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-CicxWZxX6z35HR83jl+PLgtFgUrKRQ9LCXyxgenMnz5A1lgYWfAog7VtdOvGkJYyQgMNPhXQwkYrDLujk7z1Iw=="],
906+ "@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA=="],
1277907
1278− "@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.6.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/resources": "2.6.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-g/OZVkqlxllgFM7qMKqbPV9c1DUPhQ7d4n3pgZFcrnrNft9eJXZM2TNHTPYREJBrtNdRytYyvwjgL5geDKl3EQ=="],
908+ "@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg=="],
1279909
1280− "@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@2.6.0", "", { "dependencies": { "@opentelemetry/context-async-hooks": "2.6.0", "@opentelemetry/core": "2.6.0", "@opentelemetry/sdk-trace-base": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-YhswtasmsbIGEFvLGvR9p/y3PVRTfFf+mgY8van4Ygpnv4sA3vooAjvh+qAn9PNWxs4/IwGGqiQS0PPsaRJ0vQ=="],
910+ "@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.6", "", { "os": "freebsd", "cpu": "x64" }, "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng=="],
1281911
1282− "@opentelemetry/sdk-trace-web": ["@opentelemetry/sdk-trace-web@2.6.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/sdk-trace-base": "2.6.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-xyYmLFatwUeYnB7NtQ2Ydl9Y8uiblN+EDo5YEjnk7ZRMhGFyt1wgPqb8EYvATLuDiRVtxid1fJsL6RH1fCQMIA=="],
912+ "@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.6", "", { "os": "linux", "cpu": "arm" }, "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ=="],
1283913
1284− "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="],
914+ "@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.6", "", { "os": "linux", "cpu": "arm" }, "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg=="],
1285915
1286− "@oxc-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.19.1", "", { "os": "android", "cpu": "arm" }, "sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg=="],
916+ "@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA=="],
1287917
1288− "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.19.1", "", { "os": "android", "cpu": "arm64" }, "sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA=="],
918+ "@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA=="],
1289919
1290− "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.19.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ=="],
920+ "@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.6", "", { "os": "linux", "cpu": "x64" }, "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ=="],
1291921
1292− "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.19.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ=="],
922+ "@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.6", "", { "os": "linux", "cpu": "x64" }, "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg=="],
1293923
1294− "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.19.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw=="],
924+ "@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q=="],
1295925
1296− "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1", "", { "os": "linux", "cpu": "arm" }, "sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A=="],
926+ "@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.6", "", { "os": "win32", "cpu": "ia32" }, "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g=="],
1297927
1298− "@oxc-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.19.1", "", { "os": "linux", "cpu": "arm" }, "sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ=="],
928+ "@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.6", "", { "os": "win32", "cpu": "x64" }, "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw=="],
1299929
1300− "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.19.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig=="],
930+ "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
1301931
1302− "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.19.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew=="],
932+ "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
1303933
1304− "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.19.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ=="],
934+ "@radix-ui/react-accessible-icon": ["@radix-ui/react-accessible-icon@1.1.7", "", { "dependencies": { "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A=="],
1305935
1306− "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@11.19.1", "", { "os": "linux", "cpu": "none" }, "sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w=="],
936+ "@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA=="],
1307937
1308− "@oxc-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.19.1", "", { "os": "linux", "cpu": "none" }, "sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw=="],
938+ "@radix-ui/react-alert-dialog": ["@radix-ui/react-alert-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dialog": "1.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw=="],
1309939
1310− "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@11.19.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA=="],
940+ "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
1311941
1312− "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.19.1", "", { "os": "linux", "cpu": "x64" }, "sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ=="],
942+ "@radix-ui/react-aspect-ratio": ["@radix-ui/react-aspect-ratio@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g=="],
1313943
1314− "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@11.19.1", "", { "os": "linux", "cpu": "x64" }, "sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw=="],
944+ "@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.1.10", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog=="],
1315945
1316− "@oxc-resolver/binding-openharmony-arm64": ["@oxc-resolver/binding-openharmony-arm64@11.19.1", "", { "os": "none", "cpu": "arm64" }, "sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA=="],
946+ "@radix-ui/react-checkbox": ["@radix-ui/react-checkbox@1.3.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw=="],
1317947
1318− "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@11.19.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg=="],
948+ "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA=="],
1319949
1320− "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@11.19.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ=="],
950+ "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
1321951
1322− "@oxc-resolver/binding-win32-ia32-msvc": ["@oxc-resolver/binding-win32-ia32-msvc@11.19.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA=="],
952+ "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
1323953
1324− "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.19.1", "", { "os": "win32", "cpu": "x64" }, "sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw=="],
954+ "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
1325955
1326− "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.56.0", "", { "os": "android", "cpu": "arm" }, "sha512-IyfYPthZyiSKwAv/dLjeO18SaK8MxLI9Yss2JrRDyweQAkuL3LhEy7pwIwI7uA3KQc1Vdn20kdmj3q0oUIQL6A=="],
956+ "@radix-ui/react-context-menu": ["@radix-ui/react-context-menu@2.2.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww=="],
1327957
1328− "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.56.0", "", { "os": "android", "cpu": "arm64" }, "sha512-Ga5zYrzH6vc/VFxhn6MmyUnYEfy9vRpwTIks99mY3j6Nz30yYpIkWryI0QKPCgvGUtDSXVLEaMum5nA+WrNOSg=="],
958+ "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="],
1329959
1330− "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.56.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ogmbdJysnw/D4bDcpf1sPLpFThZ48lYp4aKYm10Z/6Nh1SON6NtnNhTNOlhEY296tDFItsZUz+2tgcSYqh8Eyw=="],
960+ "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
1331961
1332− "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.56.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-x8QE1h+RAtQ2g+3KPsP6Fk/tdz6zJQUv5c7fTrJxXV3GHOo+Ry5p/PsogU4U+iUZg0rj6hS+E4xi+mnwwlDCWQ=="],
962+ "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
1333963
1334− "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.56.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-6G+WMZvwJpMvY7my+/SHEjb7BTk/PFbePqLpmVmUJRIsJMy/UlyYqjpuh0RCgYYkPLcnXm1rUM04kbTk8yS1Yg=="],
964+ "@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw=="],
1335965
1336− "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.56.0", "", { "os": "linux", "cpu": "arm" }, "sha512-YYHBsk/sl7fYwQOok+6W5lBPeUEvisznV/HZD2IfZmF3Bns6cPC3Z0vCtSEOaAWTjYWN3jVsdu55jMxKlsdlhg=="],
966+ "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="],
1337967
1338− "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.56.0", "", { "os": "linux", "cpu": "arm" }, "sha512-+AZK8rOUr78y8WT6XkDb04IbMRqauNV+vgT6f8ZLOH8wnpQ9i7Nol0XLxAu+Cq7Sb+J9wC0j6Km5hG8rj47/yQ=="],
968+ "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="],
1339969
1340− "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.56.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-urse2SnugwJRojUkGSSeH2LPMaje5Q50yQtvtL9HFckiyeqXzoFwOAZqD5TR29R2lq7UHidfFDM9EGcchcbb8A=="],
970+ "@radix-ui/react-form": ["@radix-ui/react-form@0.1.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-label": "2.1.7", "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ=="],
1341971
1342− "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.56.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-rkTZkBfJ4TYLjansjSzL6mgZOdN5IvUnSq3oNJSLwBcNvy3dlgQtpHPrRxrCEbbcp7oQ6If0tkNaqfOsphYZ9g=="],
972+ "@radix-ui/react-hover-card": ["@radix-ui/react-hover-card@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg=="],
1343973
1344− "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.56.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-uqL1kMH3u69/e1CH2EJhP3CP28jw2ExLsku4o8RVAZ7fySo9zOyI2fy9pVlTAp4voBLVgzndXi3SgtdyCTa2aA=="],
974+ "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
1345975
1346− "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.56.0", "", { "os": "linux", "cpu": "none" }, "sha512-j0CcMBOgV6KsRaBdsebIeiy7hCjEvq2KdEsiULf2LZqAq0v1M1lWjelhCV57LxsqaIGChXFuFJ0RiFrSRHPhSg=="],
976+ "@radix-ui/react-label": ["@radix-ui/react-label@2.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ=="],
1347977
1348− "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.56.0", "", { "os": "linux", "cpu": "none" }, "sha512-7VDOiL8cDG3DQ/CY3yKjbV1c4YPvc4vH8qW09Vv+5ukq3l/Kcyr6XGCd5NvxUmxqDb2vjMpM+eW/4JrEEsUetA=="],
978+ "@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg=="],
1349979
1350− "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.56.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-JGRpX0M+ikD3WpwJ7vKcHKV6Kg0dT52BW2Eu2BupXotYeqGXBrbY+QPkAyKO6MNgKozyTNaRh3r7g+VWgyAQYQ=="],
980+ "@radix-ui/react-menubar": ["@radix-ui/react-menubar@1.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA=="],
1351981
1352− "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.56.0", "", { "os": "linux", "cpu": "x64" }, "sha512-dNaICPvtmuxFP/VbqdofrLqdS3bM/AKJN3LMJD52si44ea7Be1cBk6NpfIahaysG9Uo+L98QKddU9CD5L8UHnQ=="],
982+ "@radix-ui/react-navigation-menu": ["@radix-ui/react-navigation-menu@1.2.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w=="],
1353983
1354− "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.56.0", "", { "os": "linux", "cpu": "x64" }, "sha512-pF1vOtM+GuXmbklM1hV8WMsn6tCNPvkUzklj/Ej98JhlanbmA2RB1BILgOpwSuCTRTIYx2MXssmEyQQ90QF5aA=="],
984+ "@radix-ui/react-one-time-password-field": ["@radix-ui/react-one-time-password-field@0.1.8", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg=="],
1355985
1356− "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.56.0", "", { "os": "none", "cpu": "arm64" }, "sha512-bp8NQ4RE6fDIFLa4bdBiOA+TAvkNkg+rslR+AvvjlLTYXLy9/uKAYLQudaQouWihLD/hgkrXIKKzXi5IXOewwg=="],
986+ "@radix-ui/react-password-toggle-field": ["@radix-ui/react-password-toggle-field@0.1.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-is-hydrated": "0.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw=="],
1357987
1358− "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.56.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-PxT4OJDfMOQBzo3OlzFb9gkoSD+n8qSBxyVq2wQSZIHFQYGEqIRTo9M0ZStvZm5fdhMqaVYpOnJvH2hUMEDk/g=="],
988+ "@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA=="],
1359989
1360− "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.56.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-PTRy6sIEPqy2x8PTP1baBNReN/BNEFmde0L+mYeHmjXE1Vlcc9+I5nsqENsB2yAm5wLkzPoTNCMY/7AnabT4/A=="],
990+ "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.8", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw=="],
1361991
1362− "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.56.0", "", { "os": "win32", "cpu": "x64" }, "sha512-ZHa0clocjLmIDr+1LwoWtxRcoYniAvERotvwKUYKhH41NVfl0Y4LNbyQkwMZzwDvKklKGvGZ5+DAG58/Ik47tQ=="],
992+ "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],
1363993
1364− "@oxlint/plugins": ["@oxlint/plugins@1.57.0", "", {}, "sha512-4mAGdfUZNQSZwUbHs0xoUcKjByrdBSJ9iaCI3STn/d1ZVRKhW/82oCA6rdfSzO4vxrWH3/l+qYWh/tyrwPSpag=="],
994+ "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
1365995
1366− "@parcel/watcher": ["@parcel/watcher@2.5.6", "", { "dependencies": { "detect-libc": "^2.0.3", "is-glob": "^4.0.3", "node-addon-api": "^7.0.0", "picomatch": "^4.0.3" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.6", "@parcel/watcher-darwin-arm64": "2.5.6", "@parcel/watcher-darwin-x64": "2.5.6", "@parcel/watcher-freebsd-x64": "2.5.6", "@parcel/watcher-linux-arm-glibc": "2.5.6", "@parcel/watcher-linux-arm-musl": "2.5.6", "@parcel/watcher-linux-arm64-glibc": "2.5.6", "@parcel/watcher-linux-arm64-musl": "2.5.6", "@parcel/watcher-linux-x64-glibc": "2.5.6", "@parcel/watcher-linux-x64-musl": "2.5.6", "@parcel/watcher-win32-arm64": "2.5.6", "@parcel/watcher-win32-ia32": "2.5.6", "@parcel/watcher-win32-x64": "2.5.6" } }, "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ=="],
996+ "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
1367997
1368− "@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.6", "", { "os": "android", "cpu": "arm64" }, "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A=="],
998+ "@radix-ui/react-progress": ["@radix-ui/react-progress@1.1.7", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg=="],
1369999
1370− "@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA=="],
1000+ "@radix-ui/react-radio-group": ["@radix-ui/react-radio-group@1.3.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ=="],
13711001
1372− "@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg=="],
1002+ "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="],
13731003
1374− "@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.6", "", { "os": "freebsd", "cpu": "x64" }, "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng=="],
1004+ "@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.10", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A=="],
13751005
1376− "@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.6", "", { "os": "linux", "cpu": "arm" }, "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ=="],
1006+ "@radix-ui/react-select": ["@radix-ui/react-select@2.2.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ=="],
13771007
1378− "@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.6", "", { "os": "linux", "cpu": "arm" }, "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg=="],
1008+ "@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA=="],
1009+
1010+ "@radix-ui/react-slider": ["@radix-ui/react-slider@1.3.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw=="],
1011+
1012+ "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
1013+
1014+ "@radix-ui/react-switch": ["@radix-ui/react-switch@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ=="],
1015+
1016+ "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="],
1017+
1018+ "@radix-ui/react-toast": ["@radix-ui/react-toast@1.2.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g=="],
1019+
1020+ "@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ=="],
1021+
1022+ "@radix-ui/react-toggle-group": ["@radix-ui/react-toggle-group@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-toggle": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q=="],
1023+
1024+ "@radix-ui/react-toolbar": ["@radix-ui/react-toolbar@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-separator": "1.1.7", "@radix-ui/react-toggle-group": "1.1.11" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg=="],
1025+
1026+ "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="],
1027+
1028+ "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
1029+
1030+ "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
1031+
1032+ "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
1033+
1034+ "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
1035+
1036+ "@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.0", "", { "dependencies": { "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA=="],
1037+
1038+ "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
1039+
1040+ "@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ=="],
1041+
1042+ "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="],
1043+
1044+ "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="],
1045+
1046+ "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.3", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug=="],
1047+
1048+ "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
1049+
1050+ "@reduxjs/toolkit": ["@reduxjs/toolkit@2.11.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", "immer": "^11.0.0", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, "optionalPeers": ["react", "react-redux"] }, "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ=="],
13791051
1380− "@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA=="],
1052+ "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="],
13811053
1382− "@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA=="],
1054+ "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.1", "", { "os": "android", "cpu": "arm" }, "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA=="],
13831055
1384− "@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.6", "", { "os": "linux", "cpu": "x64" }, "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ=="],
1056+ "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.1", "", { "os": "android", "cpu": "arm64" }, "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA=="],
13851057
1386− "@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.6", "", { "os": "linux", "cpu": "x64" }, "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg=="],
1058+ "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.60.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw=="],
13871059
1388− "@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q=="],
1060+ "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.60.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew=="],
13891061
1390− "@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.6", "", { "os": "win32", "cpu": "ia32" }, "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g=="],
1062+ "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.60.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w=="],
13911063
1392− "@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.6", "", { "os": "win32", "cpu": "x64" }, "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw=="],
1064+ "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.60.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g=="],
13931065
1394− "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="],
1066+ "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.60.1", "", { "os": "linux", "cpu": "arm" }, "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g=="],
13951067
1396− "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="],
1068+ "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.60.1", "", { "os": "linux", "cpu": "arm" }, "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg=="],
13971069
1398− "@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="],
1070+ "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.60.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ=="],
13991071
1400− "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="],
1072+ "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.60.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA=="],
14011073
1402− "@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="],
1074+ "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ=="],
14031075
1404− "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="],
1076+ "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw=="],
14051077
1406− "@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="],
1078+ "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.60.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw=="],
14071079
1408− "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="],
1080+ "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.60.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg=="],
14091081
1410− "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="],
1082+ "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg=="],
14111083
1412− "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="],
1084+ "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg=="],
14131085
1414− "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
1086+ "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.60.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ=="],
14151087
1416− "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
1088+ "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.60.1", "", { "os": "linux", "cpu": "x64" }, "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg=="],
14171089
1418− "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
1090+ "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.60.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w=="],
14191091
1420− "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="],
1092+ "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.60.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw=="],
14211093
1422− "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
1094+ "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.60.1", "", { "os": "none", "cpu": "arm64" }, "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA=="],
14231095
1424− "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="],
1096+ "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.60.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g=="],
14251097
1426− "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="],
1098+ "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.60.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg=="],
14271099
1428− "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
1100+ "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.60.1", "", { "os": "win32", "cpu": "x64" }, "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg=="],
14291101
1430− "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],
1102+ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.60.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ=="],
14311103
1432− "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
1104+ "@shikijs/core": ["@shikijs/core@4.0.2", "", { "dependencies": { "@shikijs/primitive": "4.0.2", "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw=="],
14331105
1434− "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
1106+ "@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-7PW0Nm49DcoUIQEXlJhNNBHyoGMjalRETTCcjMqEaMoJRLljy1Bi/EGV3/qLBgLKQejdspiiYuHGQW6dX94Nag=="],
14351107
1436− "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
1108+ "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-UpCB9Y2sUKlS9z8juFSKz7ZtysmeXCgnRF0dlhXBkmQnek7lAToPte8DkxmEYGNTMii72zU/lyXiCB6StuZeJg=="],
14371109
1438− "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
1110+ "@shikijs/langs": ["@shikijs/langs@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2" } }, "sha512-KaXby5dvoeuZzN0rYQiPMjFoUrz4hgwIE+D6Du9owcHcl6/g16/yT5BQxSW5cGt2MZBz6Hl0YuRqf12omRfUUg=="],
14391111
1440− "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
1112+ "@shikijs/primitive": ["@shikijs/primitive@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-M6UMPrSa3fN5ayeJwFVl9qWofl273wtK1VG8ySDZ1mQBfhCpdd8nEx7nPZ/tk7k+TYcpqBZzj/AnwxT9lO+HJw=="],
14411113
1442− "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
1114+ "@shikijs/themes": ["@shikijs/themes@4.0.2", "", { "dependencies": { "@shikijs/types": "4.0.2" } }, "sha512-mjCafwt8lJJaVSsQvNVrJumbnnj1RI8jbUKrPKgE6E3OvQKxnuRoBaYC51H4IGHePsGN/QtALglWBU7DoKDFnA=="],
14431115
1444− "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
1116+ "@shikijs/types": ["@shikijs/types@4.0.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg=="],
14451117
1446− "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
1118+ "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
14471119
1448− "@react-grab/cli": ["@react-grab/cli@0.1.26", "", { "dependencies": { "@antfu/ni": "^0.23.0", "commander": "^14.0.0", "ignore": "^7.0.5", "jsonc-parser": "^3.3.1", "ora": "^8.2.0", "picocolors": "^1.1.1", "prompts": "^2.4.2", "smol-toml": "^1.6.0" }, "bin": { "react-grab": "dist/cli.js" } }, "sha512-nNOBdrJ2K7jji6L/X9ARCpU1o/CQ33KYZUtW7vAtrfDM2hyvAIA224ps+Syl97FxhS7pO8b59Bnhc7YLG6h3nA=="],
1120+ "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
14491121
1450− "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.3", "", {}, "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q=="],
1122+ "@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="],
14511123
1452− "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="],
1124+ "@tabby_ai/hijri-converter": ["@tabby_ai/hijri-converter@1.0.5", "", {}, "sha512-r5bClKrcIusDoo049dSL8CawnHR6mRdDwhlQuIgZRNty68q0x8k3Lf1BtPAMxRf/GgnHBnIO4ujd3+GQdLWzxQ=="],
14531125
1454− "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="],
1126+ "@tailwindcss/node": ["@tailwindcss/node@4.2.2", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.2" } }, "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA=="],
14551127
1456− "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="],
1128+ "@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.2", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.2", "@tailwindcss/oxide-darwin-arm64": "4.2.2", "@tailwindcss/oxide-darwin-x64": "4.2.2", "@tailwindcss/oxide-freebsd-x64": "4.2.2", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.2", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.2", "@tailwindcss/oxide-linux-arm64-musl": "4.2.2", "@tailwindcss/oxide-linux-x64-gnu": "4.2.2", "@tailwindcss/oxide-linux-x64-musl": "4.2.2", "@tailwindcss/oxide-wasm32-wasi": "4.2.2", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.2", "@tailwindcss/oxide-win32-x64-msvc": "4.2.2" } }, "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg=="],
14571129
1458− "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="],
1130+ "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.2", "", { "os": "android", "cpu": "arm64" }, "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg=="],
14591131
1460− "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="],
1132+ "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg=="],
14611133
1462− "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="],
1134+ "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw=="],
14631135
1464− "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="],
1136+ "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ=="],
14651137
1466− "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="],
1138+ "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2", "", { "os": "linux", "cpu": "arm" }, "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ=="],
14671139
1468− "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="],
1140+ "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw=="],
14691141
1470− "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="],
1142+ "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag=="],
14711143
1472− "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="],
1144+ "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg=="],
14731145
1474− "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="],
1146+ "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ=="],
14751147
1476− "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="],
1148+ "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.2", "", { "dependencies": { "@emnapi/core": "^1.8.1", "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q=="],
14771149
1478− "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="],
1150+ "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ=="],
14791151
1480− "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="],
1152+ "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.2", "", { "os": "win32", "cpu": "x64" }, "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA=="],
14811153
1482− "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="],
1154+ "@tailwindcss/vite": ["@tailwindcss/vite@4.2.2", "", { "dependencies": { "@tailwindcss/node": "4.2.2", "@tailwindcss/oxide": "4.2.2", "tailwindcss": "4.2.2" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w=="],
14831155
1484− "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="],
1156+ "@tanstack/history": ["@tanstack/history@1.161.6", "", {}, "sha512-NaOGLRrddszbQj9upGat6HG/4TKvXLvu+osAIgfxPYA+eIvYKv8GKDJOrY2D3/U9MRnKfMWD7bU4jeD4xmqyIg=="],
14851157
1486− "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="],
1158+ "@tanstack/react-router": ["@tanstack/react-router@1.168.10", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-store": "^0.9.3", "@tanstack/router-core": "1.168.9", "isbot": "^5.1.22" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-/RmDlOwDkCug609KdPB3U+U1zmrtadJpvsmRg2zEn8TRCKRNri7dYZIjQZbNg8PgUiRL4T6njrZBV1ChzblNaA=="],
14871159
1488− "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="],
1160+ "@tanstack/react-store": ["@tanstack/react-store@0.9.3", "", { "dependencies": { "@tanstack/store": "0.9.3", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg=="],
14891161
1490− "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="],
1162+ "@tanstack/router-core": ["@tanstack/router-core@1.168.9", "", { "dependencies": { "@tanstack/history": "1.161.6", "cookie-es": "^2.0.0", "seroval": "^1.4.2", "seroval-plugins": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-18oeEwEDyXOIuO1VBP9ACaK7tYHZUjynGDCoUh/5c/BNhia9vCJCp9O0LfhZXOorDc/PmLSgvmweFhVmIxF10g=="],
14911163
1492− "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="],
1164+ "@tanstack/store": ["@tanstack/store@0.9.3", "", {}, "sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw=="],
14931165
1494− "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="],
1166+ "@turbo/darwin-64": ["@turbo/darwin-64@2.9.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-yg0qdthTUuV/K0oJB9t8YGweW1hOefQ+NTiSA6gw/mwAqqifCvAXH/kDkvVj/fFP9+wzoQ4WjyAF5/syDbCIHA=="],
14951167
1496− "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="],
1168+ "@turbo/darwin-arm64": ["@turbo/darwin-arm64@2.9.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-x4H9U8cXZob3oqTleKOEdY89OCWwLX3qVRpW0NeZg+CHDXemYD+PhACjwjvh7orIlhmmq2Lk+7iO7b34kphFig=="],
14971169
1498− "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="],
1170+ "@turbo/linux-64": ["@turbo/linux-64@2.9.2", "", { "os": "linux", "cpu": "x64" }, "sha512-fxbpor8zvRtaf75sfloNTaBkl487JECSVDrXXMGlwR3+Qmq7yStUE+ccQddPu+nKqYD46QxDspk8KZvT78SBSg=="],
14991171
1500− "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="],
1172+ "@turbo/linux-arm64": ["@turbo/linux-arm64@2.9.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-ufMQcCQMi8kzHbEA+FihPaRdrPQC1vUO0LQ9oU/LGWlnc+RVyDlvH9l9x0BWoS7HLyHK8hbqLf3O2ml/ZLMEIw=="],
15011173
1502− "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="],
1174+ "@turbo/windows-64": ["@turbo/windows-64@2.9.2", "", { "os": "win32", "cpu": "x64" }, "sha512-SOELKum/pjdJWKQb+RU/OEAlNtWJKfjjYUA9QhYxBvIT26SyfWgY+ecZ7QlVWt+xnEdQyC6BkYlWR546KxPO5w=="],
15031175
1504− "@shikijs/core": ["@shikijs/core@4.0.1", "", { "dependencies": { "@shikijs/primitive": "4.0.1", "@shikijs/types": "4.0.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-vWvqi9JNgz1dRL9Nvog5wtx7RuNkf7MEPl2mU/cyUUxJeH1CAr3t+81h8zO8zs7DK6cKLMoU9TvukWIDjP4Lzg=="],
1176+ "@turbo/windows-arm64": ["@turbo/windows-arm64@2.9.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-qPFjErR4MrKo71lNfqgUNaajftZN2nyaOsSxMSb2NI+5r/zlB26yjXUKYvADGg4EWvaLTJPIzgZDT9ZX+WN9bw=="],
15051177
1506− "@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.0.1", "", { "dependencies": { "@shikijs/types": "4.0.1", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-DJK9NiwtGYqMuKCRO4Ip0FKNDQpmaiS+K5bFjJ7DWFn4zHueDWgaUG8kAofkrnXF6zPPYYQY7J5FYVW9MbZyBg=="],
1178+ "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
15071179
1508− "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@4.0.1", "", { "dependencies": { "@shikijs/types": "4.0.1", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-oCWdCTDch3J8Kc0OZJ98KuUPC02O1VqIE3W/e2uvrHqTxYRR21RGEJMtchrgrxhsoJJCzmIciKsqG+q/yD+Cxg=="],
1180+ "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
15091181
1510− "@shikijs/langs": ["@shikijs/langs@4.0.1", "", { "dependencies": { "@shikijs/types": "4.0.1" } }, "sha512-v/mluaybWdnGJR4GqAR6zh8qAZohW9k+cGYT28Y7M8+jLbC0l4yG085O1A+WkseHTn+awd+P3UBymb2+MXFc8w=="],
1182+ "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
15111183
1512− "@shikijs/primitive": ["@shikijs/primitive@4.0.1", "", { "dependencies": { "@shikijs/types": "4.0.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-ns0hHZc5eWZuvuIEJz2pTx3Qecz0aRVYumVQJ8JgWY2tq/dH8WxdcVM49Fc2NsHEILNIT6vfdW9MF26RANWiTA=="],
1184+ "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
15131185
1514− "@shikijs/themes": ["@shikijs/themes@4.0.1", "", { "dependencies": { "@shikijs/types": "4.0.1" } }, "sha512-FW41C/D6j/yKQkzVdjrRPiJCtgeDaYRJFEyCKFCINuRJRj9WcmubhP4KQHPZ4+9eT87jruSrYPyoblNRyDFzvA=="],
1186+ "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
15151187
1516− "@shikijs/types": ["@shikijs/types@4.0.1", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-EaygPEn57+jJ76mw+nTLvIpJMAcMPokFbrF8lufsZP7Ukk+ToJYEcswN1G0e49nUZAq7aCQtoeW219A8HK1ZOw=="],
1188+ "@types/d3": ["@types/d3@7.4.3", "", { "dependencies": { "@types/d3-array": "*", "@types/d3-axis": "*", "@types/d3-brush": "*", "@types/d3-chord": "*", "@types/d3-color": "*", "@types/d3-contour": "*", "@types/d3-delaunay": "*", "@types/d3-dispatch": "*", "@types/d3-drag": "*", "@types/d3-dsv": "*", "@types/d3-ease": "*", "@types/d3-fetch": "*", "@types/d3-force": "*", "@types/d3-format": "*", "@types/d3-geo": "*", "@types/d3-hierarchy": "*", "@types/d3-interpolate": "*", "@types/d3-path": "*", "@types/d3-polygon": "*", "@types/d3-quadtree": "*", "@types/d3-random": "*", "@types/d3-scale": "*", "@types/d3-scale-chromatic": "*", "@types/d3-selection": "*", "@types/d3-shape": "*", "@types/d3-time": "*", "@types/d3-time-format": "*", "@types/d3-timer": "*", "@types/d3-transition": "*", "@types/d3-zoom": "*" } }, "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww=="],
15171189
1518− "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
1190+ "@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="],
15191191
1520− "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="],
1192+ "@types/d3-axis": ["@types/d3-axis@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw=="],
15211193
1522− "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
1194+ "@types/d3-brush": ["@types/d3-brush@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A=="],
15231195
1524− "@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="],
1196+ "@types/d3-chord": ["@types/d3-chord@3.0.6", "", {}, "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg=="],
15251197
1526− "@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="],
1198+ "@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="],
15271199
1528− "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg=="],
1200+ "@types/d3-contour": ["@types/d3-contour@3.0.6", "", { "dependencies": { "@types/d3-array": "*", "@types/geojson": "*" } }, "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg=="],
15291201
1530− "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw=="],
1202+ "@types/d3-delaunay": ["@types/d3-delaunay@6.0.4", "", {}, "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw=="],
15311203
1532− "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw=="],
1204+ "@types/d3-dispatch": ["@types/d3-dispatch@3.0.7", "", {}, "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA=="],
15331205
1534− "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA=="],
1206+ "@types/d3-drag": ["@types/d3-drag@3.0.7", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ=="],
15351207
1536− "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw=="],
1208+ "@types/d3-dsv": ["@types/d3-dsv@3.0.7", "", {}, "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g=="],
15371209
1538− "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ=="],
1210+ "@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="],
15391211
1540− "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ=="],
1212+ "@types/d3-fetch": ["@types/d3-fetch@3.0.7", "", { "dependencies": { "@types/d3-dsv": "*" } }, "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA=="],
15411213
1542− "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g=="],
1214+ "@types/d3-force": ["@types/d3-force@3.0.10", "", {}, "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw=="],
15431215
1544− "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g=="],
1216+ "@types/d3-format": ["@types/d3-format@3.0.4", "", {}, "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g=="],
15451217
1546− "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.1", "", { "dependencies": { "@emnapi/core": "^1.8.1", "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q=="],
1218+ "@types/d3-geo": ["@types/d3-geo@3.1.0", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ=="],
15471219
1548− "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA=="],
1220+ "@types/d3-hierarchy": ["@types/d3-hierarchy@3.1.7", "", {}, "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg=="],
15491221
1550− "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="],
1222+ "@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="],
15511223
1552− "@tailwindcss/vite": ["@tailwindcss/vite@4.2.1", "", { "dependencies": { "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "tailwindcss": "4.2.1" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w=="],
1224+ "@types/d3-path": ["@types/d3-path@3.1.1", "", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="],
15531225
1554− "@tanstack/history": ["@tanstack/history@1.161.4", "", {}, "sha512-Kp/WSt411ZWYvgXy6uiv5RmhHrz9cAml05AQPrtdAp7eUqvIDbMGPnML25OKbzR3RJ1q4wgENxDTvlGPa9+Mww=="],
1226+ "@types/d3-polygon": ["@types/d3-polygon@3.0.2", "", {}, "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA=="],
15551227
1556− "@tanstack/react-router": ["@tanstack/react-router@1.166.2", "", { "dependencies": { "@tanstack/history": "1.161.4", "@tanstack/react-store": "^0.9.1", "@tanstack/router-core": "1.166.2", "isbot": "^5.1.22", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-pKhUtrvVLlhjWhsHkJSuIzh1J4LcP+8ErbIqRLORX9Js8dUFMKoT0+8oFpi+P8QRpuhm/7rzjYiWfcyTsqQZtA=="],
1228+ "@types/d3-quadtree": ["@types/d3-quadtree@3.0.6", "", {}, "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg=="],
15571229
1558− "@tanstack/react-store": ["@tanstack/react-store@0.9.2", "", { "dependencies": { "@tanstack/store": "0.9.2", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Vt5usJE5sHG/cMechQfmwvwne6ktGCELe89Lmvoxe3LKRoFrhPa8OCKWs0NliG8HTJElEIj7PLtaBQIcux5pAQ=="],
1230+ "@types/d3-random": ["@types/d3-random@3.0.3", "", {}, "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ=="],
15591231
1560− "@tanstack/router-core": ["@tanstack/router-core@1.166.2", "", { "dependencies": { "@tanstack/history": "1.161.4", "@tanstack/store": "^0.9.1", "cookie-es": "^2.0.0", "seroval": "^1.4.2", "seroval-plugins": "^1.4.2", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" } }, "sha512-zn3NhENOAX9ToQiX077UV2OH3aJKOvV2ZMNZZxZ3gDG3i3WqL8NfWfEgetEAfMN37/Mnt90PpotYgf7IyuoKqQ=="],
1232+ "@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="],
15611233
1562− "@tanstack/store": ["@tanstack/store@0.9.2", "", {}, "sha512-K013lUJEFJK2ofFQ/hZKJUmCnpcV00ebLyOyFOWQvyQHUOZp/iYO84BM6aOGiV81JzwbX0APTVmW8YI7yiG5oA=="],
1234+ "@types/d3-scale-chromatic": ["@types/d3-scale-chromatic@3.1.0", "", {}, "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ=="],
15631235
1564− "@ts-morph/common": ["@ts-morph/common@0.27.0", "", { "dependencies": { "fast-glob": "^3.3.3", "minimatch": "^10.0.1", "path-browserify": "^1.0.1" } }, "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ=="],
1236+ "@types/d3-selection": ["@types/d3-selection@3.0.11", "", {}, "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w=="],
15651237
1566− "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
1238+ "@types/d3-shape": ["@types/d3-shape@3.1.8", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w=="],
15671239
1568− "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
1240+ "@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="],
15691241
1570− "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
1242+ "@types/d3-time-format": ["@types/d3-time-format@4.0.3", "", {}, "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg=="],
15711243
1572− "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
1244+ "@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="],
15731245
1574− "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
1246+ "@types/d3-transition": ["@types/d3-transition@3.0.9", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg=="],
15751247
1576− "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
1248+ "@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="],
15771249
1578− "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
1250+ "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="],
15791251
15801252 "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
15811253
@@ -1583,35 +1255,33 @@ · 1 unmodified line
15831255
15841256 "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
15851257
1258+ "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
1259+
15861260 "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
15871261
1588− "@types/jsdom": ["@types/jsdom@21.1.7", "", { "dependencies": { "@types/node": "*", "@types/tough-cookie": "*", "parse5": "^7.0.0" } }, "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA=="],
1262+ "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
15891263
15901264 "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
15911265
15921266 "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
15931267
1594− "@types/node": ["@types/node@24.11.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw=="],
1268+ "@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
15951269
15961270 "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
15971271
15981272 "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
15991273
1600− "@types/react-reconciler": ["@types/react-reconciler@0.28.9", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg=="],
1601−
1602− "@types/statuses": ["@types/statuses@2.0.6", "", {}, "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA=="],
1603−
1604− "@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="],
1274+ "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
16051275
16061276 "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
16071277
1608− "@types/validate-npm-package-name": ["@types/validate-npm-package-name@4.0.2", "", {}, "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw=="],
1278+ "@types/use-sync-external-store": ["@types/use-sync-external-store@0.0.6", "", {}, "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="],
16091279
16101280 "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
16111281
1612− "@vercel/oidc": ["@vercel/oidc@3.1.0", "", {}, "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w=="],
1282+ "@upsetjs/venn.js": ["@upsetjs/venn.js@2.0.0", "", { "optionalDependencies": { "d3-selection": "^3.0.0", "d3-transition": "^3.0.1" } }, "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw=="],
16131283
1614− "@vitejs/plugin-react": ["@vitejs/plugin-react@5.1.4", "", { "dependencies": { "@babel/core": "^7.29.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-rc.3", "@types/babel__core": "^7.20.5", "react-refresh": "^0.18.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA=="],
1284+ "@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="],
16151285
16161286 "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
16171287
@@ -1629,20 +1299,18 @@ · 11 unmodified lines
16291299
16301300 "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
16311301
1632− "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
1633−
1634− "ai": ["ai@6.0.116", "", { "dependencies": { "@ai-sdk/gateway": "3.0.66", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.19", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7yM+cTmyRLeNIXwt4Vj+mrrJgVQ9RMIW5WO0ydoLoYkewIvsMcvUmqS4j2RJTUXaF1HphwmSKUMQ/HypNRGOmA=="],
1302+ "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
16351303
16361304 "ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="],
16371305
1306+ "ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="],
1307+
16381308 "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
16391309
16401310 "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
16411311
16421312 "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
16431313
1644− "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
1645−
16461314 "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
16471315
16481316 "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
@@ -1651,29 +1319,29 @@ · 2 unmodified lines
16511319
16521320 "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
16531321
1654− "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="],
1655−
16561322 "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
16571323
1658− "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
1324+ "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
16591325
1660− "baseline-browser-mapping": ["baseline-browser-mapping@2.10.0", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA=="],
1326+ "baseline-browser-mapping": ["baseline-browser-mapping@2.10.13", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw=="],
16611327
16621328 "better-path-resolve": ["better-path-resolve@1.0.0", "", { "dependencies": { "is-windows": "^1.0.0" } }, "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g=="],
16631329
1664− "bippy": ["bippy@0.5.32", "", { "dependencies": { "@types/react-reconciler": "^0.28.9" }, "peerDependencies": { "react": ">=17.0.1" } }, "sha512-yt1mC8eReTxjfg41YBZdN4PvsDwHFWxltoiQX0Q+Htlbf41aSniopb7ECZits01HwNAvXEh69RGk/ImlswDTEw=="],
1330+ "better-sqlite3": ["better-sqlite3@12.8.0", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ=="],
16651331
1666− "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
1332+ "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
1333+
1334+ "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
16671335
1668− "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
1336+ "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
16691337
16701338 "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
16711339
1672− "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
1340+ "browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="],
16731341
1674− "bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="],
1342+ "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
16751343
1676− "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
1344+ "bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="],
16771345
16781346 "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
16791347
@@ -1683,16 +1351,14 @@ · 3 unmodified lines
16831351
16841352 "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
16851353
1686− "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
1354+ "call-me-maybe": ["call-me-maybe@1.0.2", "", {}, "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ=="],
16871355
1688− "caniuse-lite": ["caniuse-lite@1.0.30001777", "", {}, "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ=="],
1356+ "caniuse-lite": ["caniuse-lite@1.0.30001784", "", {}, "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw=="],
16891357
16901358 "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
16911359
16921360 "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="],
16931361
1694− "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
1695−
16961362 "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
16971363
16981364 "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],
@@ -1705,29 +1371,23 @@ · 6 unmodified lines
17051371
17061372 "check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="],
17071373
1708− "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
1709−
1710− "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
1374+ "chevrotain": ["chevrotain@11.1.2", "", { "dependencies": { "@chevrotain/cst-dts-gen": "11.1.2", "@chevrotain/gast": "11.1.2", "@chevrotain/regexp-to-ast": "11.1.2", "@chevrotain/types": "11.1.2", "@chevrotain/utils": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg=="],
17111375
1712− "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
1376+ "chevrotain-allstar": ["chevrotain-allstar@0.3.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^11.0.0" } }, "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw=="],
17131377
1714− "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],
1378+ "chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
17151379
1716− "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
1380+ "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
17171381
17181382 "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
17191383
17201384 "cmdk": ["cmdk@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "^1.1.1", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-id": "^1.1.0", "@radix-ui/react-primitive": "^2.0.2" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg=="],
17211385
1722− "code-block-writer": ["code-block-writer@13.0.3", "", {}, "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg=="],
1723−
1724− "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
1725−
1726− "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
1727−
17281386 "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
17291387
1730− "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="],
1388+ "commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
1389+
1390+ "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
17311391
17321392 "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="],
17331393
@@ -1743,37 +1403,103 @@ · 9 unmodified lines
17431403
17441404 "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="],
17451405
1746− "cosmiconfig": ["cosmiconfig@9.0.1", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ=="],
1406+ "cose-base": ["cose-base@1.0.3", "", { "dependencies": { "layout-base": "^1.0.0" } }, "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg=="],
17471407
17481408 "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
17491409
1750− "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
1410+ "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
1411+
1412+ "cytoscape": ["cytoscape@3.33.1", "", {}, "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ=="],
17511413
1752− "cssstyle": ["cssstyle@4.6.0", "", { "dependencies": { "@asamuzakjp/css-color": "^3.2.0", "rrweb-cssom": "^0.8.0" } }, "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg=="],
1414+ "cytoscape-cose-bilkent": ["cytoscape-cose-bilkent@4.1.0", "", { "dependencies": { "cose-base": "^1.0.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ=="],
17531415
1754− "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
1416+ "cytoscape-fcose": ["cytoscape-fcose@2.2.0", "", { "dependencies": { "cose-base": "^2.2.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ=="],
1417+
1418+ "d3": ["d3@7.9.0", "", { "dependencies": { "d3-array": "3", "d3-axis": "3", "d3-brush": "3", "d3-chord": "3", "d3-color": "3", "d3-contour": "4", "d3-delaunay": "6", "d3-dispatch": "3", "d3-drag": "3", "d3-dsv": "3", "d3-ease": "3", "d3-fetch": "3", "d3-force": "3", "d3-format": "3", "d3-geo": "3", "d3-hierarchy": "3", "d3-interpolate": "3", "d3-path": "3", "d3-polygon": "3", "d3-quadtree": "3", "d3-random": "3", "d3-scale": "4", "d3-scale-chromatic": "3", "d3-selection": "3", "d3-shape": "3", "d3-time": "3", "d3-time-format": "4", "d3-timer": "3", "d3-transition": "3", "d3-zoom": "3" } }, "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA=="],
1419+
1420+ "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="],
1421+
1422+ "d3-axis": ["d3-axis@3.0.0", "", {}, "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw=="],
1423+
1424+ "d3-brush": ["d3-brush@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "3", "d3-transition": "3" } }, "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ=="],
1425+
1426+ "d3-chord": ["d3-chord@3.0.1", "", { "dependencies": { "d3-path": "1 - 3" } }, "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g=="],
1427+
1428+ "d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="],
17551429
1756− "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="],
1430+ "d3-contour": ["d3-contour@4.0.2", "", { "dependencies": { "d3-array": "^3.2.0" } }, "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA=="],
17571431
1758− "data-urls": ["data-urls@5.0.0", "", { "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0" } }, "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg=="],
1432+ "d3-delaunay": ["d3-delaunay@6.0.4", "", { "dependencies": { "delaunator": "5" } }, "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A=="],
1433+
1434+ "d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="],
1435+
1436+ "d3-drag": ["d3-drag@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-selection": "3" } }, "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg=="],
1437+
1438+ "d3-dsv": ["d3-dsv@3.0.1", "", { "dependencies": { "commander": "7", "iconv-lite": "0.6", "rw": "1" }, "bin": { "csv2json": "bin/dsv2json.js", "csv2tsv": "bin/dsv2dsv.js", "dsv2dsv": "bin/dsv2dsv.js", "dsv2json": "bin/dsv2json.js", "json2csv": "bin/json2dsv.js", "json2dsv": "bin/json2dsv.js", "json2tsv": "bin/json2dsv.js", "tsv2csv": "bin/dsv2dsv.js", "tsv2json": "bin/dsv2json.js" } }, "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q=="],
1439+
1440+ "d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="],
1441+
1442+ "d3-fetch": ["d3-fetch@3.0.1", "", { "dependencies": { "d3-dsv": "1 - 3" } }, "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw=="],
1443+
1444+ "d3-force": ["d3-force@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", "d3-timer": "1 - 3" } }, "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg=="],
1445+
1446+ "d3-format": ["d3-format@3.1.2", "", {}, "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg=="],
1447+
1448+ "d3-geo": ["d3-geo@3.1.1", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q=="],
1449+
1450+ "d3-hierarchy": ["d3-hierarchy@3.1.2", "", {}, "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="],
1451+
1452+ "d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="],
1453+
1454+ "d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="],
1455+
1456+ "d3-polygon": ["d3-polygon@3.0.1", "", {}, "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg=="],
1457+
1458+ "d3-quadtree": ["d3-quadtree@3.0.1", "", {}, "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="],
1459+
1460+ "d3-random": ["d3-random@3.0.1", "", {}, "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="],
1461+
1462+ "d3-sankey": ["d3-sankey@0.12.3", "", { "dependencies": { "d3-array": "1 - 2", "d3-shape": "^1.2.0" } }, "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ=="],
1463+
1464+ "d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="],
1465+
1466+ "d3-scale-chromatic": ["d3-scale-chromatic@3.1.0", "", { "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" } }, "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ=="],
1467+
1468+ "d3-selection": ["d3-selection@3.0.0", "", {}, "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="],
1469+
1470+ "d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="],
1471+
1472+ "d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="],
1473+
1474+ "d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="],
1475+
1476+ "d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="],
1477+
1478+ "d3-transition": ["d3-transition@3.0.1", "", { "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", "d3-ease": "1 - 3", "d3-interpolate": "1 - 3", "d3-timer": "1 - 3" }, "peerDependencies": { "d3-selection": "2 - 3" } }, "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w=="],
1479+
1480+ "d3-zoom": ["d3-zoom@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "2 - 3", "d3-transition": "2 - 3" } }, "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw=="],
1481+
1482+ "dagre-d3-es": ["dagre-d3-es@7.0.14", "", { "dependencies": { "d3": "^7.9.0", "lodash-es": "^4.17.21" } }, "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg=="],
1483+
1484+ "date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="],
1485+
1486+ "date-fns-jalali": ["date-fns-jalali@4.1.0-0", "", {}, "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg=="],
1487+
1488+ "dayjs": ["dayjs@1.11.20", "", {}, "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="],
17591489
17601490 "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
17611491
1762− "decimal.js": ["decimal.js@10.6.0", "", {}, "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="],
1492+ "decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="],
17631493
17641494 "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="],
17651495
1766− "dedent": ["dedent@1.7.2", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA=="],
1496+ "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
17671497
17681498 "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
17691499
1770− "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
1500+ "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
17711501
1772− "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],
1773−
1774− "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],
1775−
1776− "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
1502+ "delaunator": ["delaunator@5.1.0", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ=="],
17771503
17781504 "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
17791505
@@ -1787,38 +1513,34 @@ · 7 unmodified lines
17871513
17881514 "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
17891515
1790− "diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
1791−
17921516 "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="],
17931517
1794− "dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="],
1795−
1796− "drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="],
1518+ "dompurify": ["dompurify@3.3.3", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA=="],
17971519
17981520 "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
17991521
1800− "eciesjs": ["eciesjs@0.4.18", "", { "dependencies": { "@ecies/ciphers": "^0.2.5", "@noble/ciphers": "^1.3.0", "@noble/curves": "^1.9.7", "@noble/hashes": "^1.8.0" } }, "sha512-wG99Zcfcys9fZux7Cft8BAX/YrOJLJSZ3jyYPfhZHqN2E+Ffx+QXBDsv3gubEgPtV6dTzJMSQUwk1H98/t/0wQ=="],
1801−
18021522 "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
18031523
1804− "effect": ["effect@3.19.19", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-Yc8U/SVXo2dHnaP7zNBlAo83h/nzSJpi7vph6Hzyl4ulgMBIgPmz3UzOjb9sBgpFE00gC0iETR244sfXDNLHRg=="],
1524+ "effect": ["effect@3.21.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-PPN80qRokCd1f015IANNhrwOnLO7GrrMQfk4/lnZRE/8j7UPWrNNjPV0uBrZutI/nHzernbW+J0hdqQysHiSnQ=="],
1525+
1526+ "electron-to-chromium": ["electron-to-chromium@1.5.330", "", {}, "sha512-jFNydB5kFtYUobh4IkWUnXeyDbjf/r9gcUEXe1xcrcUxIGfTdzPXA+ld6zBRbwvgIGVzDll/LTIiDztEtckSnA=="],
18051527
1806− "electron-to-chromium": ["electron-to-chromium@1.5.307", "", {}, "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg=="],
1528+ "embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="],
18071529
1808− "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
1530+ "embla-carousel-react": ["embla-carousel-react@8.6.0", "", { "dependencies": { "embla-carousel": "8.6.0", "embla-carousel-reactive-utils": "8.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA=="],
1531+
1532+ "embla-carousel-reactive-utils": ["embla-carousel-reactive-utils@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A=="],
18091533
18101534 "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
18111535
1812− "enhanced-resolve": ["enhanced-resolve@5.20.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ=="],
1536+ "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
1537+
1538+ "enhanced-resolve": ["enhanced-resolve@5.20.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA=="],
18131539
18141540 "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="],
18151541
18161542 "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
18171543
1818− "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
1819−
1820− "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
1821−
18221544 "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
18231545
18241546 "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
@@ -1827,7 +1549,9 @@ · 2 unmodified lines
18271549
18281550 "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
18291551
1830− "esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="],
1552+ "es-toolkit": ["es-toolkit@1.45.1", "", {}, "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw=="],
1553+
1554+ "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
18311555
18321556 "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
18331557
@@ -1843,19 +1567,21 @@ · 9 unmodified lines
18431567
18441568 "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
18451569
1570+ "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="],
1571+
18461572 "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
18471573
18481574 "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="],
18491575
1850− "execa": ["execa@9.6.1", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.1", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA=="],
1576+ "executor": ["executor@workspace:apps/cli"],
18511577
1852− "executor": ["executor@workspace:apps/executor"],
1578+ "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
18531579
18541580 "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
18551581
18561582 "express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
18571583
1858− "express-rate-limit": ["express-rate-limit@8.2.1", "", { "dependencies": { "ip-address": "10.0.1" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g=="],
1584+ "express-rate-limit": ["express-rate-limit@8.3.2", "", { "dependencies": { "ip-address": "10.1.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-77VmFeJkO0/rvimEDuUC5H30oqUC4EyOhyGccfqoLebB0oiEYfM7nwPrsDsBL1gsTpwfzX8SFy2MT3TDyRq+bg=="],
18591585
18601586 "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
18611587
@@ -1871,13 +1597,9 @@ · 9 unmodified lines
18711597
18721598 "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
18731599
1874− "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="],
1875−
18761600 "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
18771601
1878− "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
1879−
1880− "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="],
1602+ "file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
18811603
18821604 "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
18831605
@@ -1887,37 +1609,27 @@ · 3 unmodified lines
18871609
18881610 "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
18891611
1890− "formatly": ["formatly@0.3.0", "", { "dependencies": { "fd-package-json": "^2.0.0" }, "bin": { "formatly": "bin/index.mjs" } }, "sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w=="],
1891−
1892− "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
1893−
18941612 "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
18951613
18961614 "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
18971615
1616+ "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
1617+
18981618 "fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="],
18991619
19001620 "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
19011621
19021622 "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
19031623
1904− "fuzzysort": ["fuzzysort@3.1.0", "", {}, "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ=="],
1905−
19061624 "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
19071625
1908− "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
1909−
1910− "get-east-asian-width": ["get-east-asian-width@1.5.0", "", {}, "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA=="],
1911−
19121626 "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
19131627
19141628 "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="],
19151629
1916− "get-own-enumerable-keys": ["get-own-enumerable-keys@1.0.0", "", {}, "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA=="],
1917−
19181630 "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
19191631
1920− "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
1632+ "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="],
19211633
19221634 "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
19231635
@@ -1927,7 +1639,7 @@ · 3 unmodified lines
19271639
19281640 "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
19291641
1930− "graphql": ["graphql@16.13.1", "", {}, "sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ=="],
1642+ "hachure-fill": ["hachure-fill@0.5.2", "", {}, "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg=="],
19311643
19321644 "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
19331645
@@ -1951,11 +1663,7 @@ · 17 unmodified lines
19511663
19521664 "hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="],
19531665
1954− "headers-polyfill": ["headers-polyfill@4.0.3", "", {}, "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ=="],
1955−
1956− "hono": ["hono@4.12.5", "", {}, "sha512-3qq+FUBtlTHhtYxbxheZgY8NIFnkkC/MR8u5TTsr7YZ3wixryQ3cCwn3iZbg8p8B88iDBBAYSfZDS75t8MN7Vg=="],
1957−
1958− "html-encoding-sniffer": ["html-encoding-sniffer@4.0.0", "", { "dependencies": { "whatwg-encoding": "^3.1.1" } }, "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ=="],
1666+ "hono": ["hono@4.12.9", "", {}, "sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA=="],
19591667
19601668 "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],
19611669
@@ -1963,19 +1671,15 @@ · 1 unmodified line
19631671
19641672 "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
19651673
1966− "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
1967−
1968− "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
1969−
19701674 "human-id": ["human-id@4.1.3", "", { "bin": { "human-id": "dist/cli.js" } }, "sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q=="],
19711675
1972− "human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="],
1973−
19741676 "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
19751677
1976− "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
1678+ "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
19771679
1978− "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
1680+ "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
1681+
1682+ "immer": ["immer@10.2.0", "", {}, "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw=="],
19791683
19801684 "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
19811685
@@ -1983,7 +1687,11 @@ · 1 unmodified line
19831687
19841688 "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
19851689
1986− "ip-address": ["ip-address@10.0.1", "", {}, "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA=="],
1690+ "input-otp": ["input-otp@1.4.2", "", { "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA=="],
1691+
1692+ "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="],
1693+
1694+ "ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],
19871695
19881696 "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
19891697
@@ -1991,70 +1699,38 @@ · 1 unmodified line
19911699
19921700 "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],
19931701
1994− "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
1995−
19961702 "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],
19971703
1998− "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
1999−
20001704 "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
20011705
2002− "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
2003−
20041706 "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
20051707
20061708 "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="],
20071709
2008− "is-in-ssh": ["is-in-ssh@1.0.0", "", {}, "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw=="],
2009−
2010− "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
2011−
2012− "is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="],
2013−
2014− "is-node-process": ["is-node-process@1.2.0", "", {}, "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw=="],
2015−
20161710 "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
20171711
2018− "is-obj": ["is-obj@3.0.0", "", {}, "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ=="],
2019−
20201712 "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
20211713
2022− "is-potential-custom-element-name": ["is-potential-custom-element-name@1.0.1", "", {}, "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="],
2023−
20241714 "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],
20251715
2026− "is-regexp": ["is-regexp@3.1.0", "", {}, "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA=="],
2027−
2028− "is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
2029−
20301716 "is-subdir": ["is-subdir@1.2.0", "", { "dependencies": { "better-path-resolve": "1.0.0" } }, "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw=="],
20311717
2032− "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
2033−
20341718 "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="],
20351719
2036− "is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="],
2037−
2038− "isbot": ["isbot@5.1.35", "", {}, "sha512-waFfC72ZNfwLLuJ2iLaoVaqcNo+CAaLR7xCpAn0Y5WfGzkNHv7ZN39Vbi1y+kb+Zs46XHOX3tZNExroFUPX+Kg=="],
1720+ "isbot": ["isbot@5.1.37", "", {}, "sha512-5bcicX81xf6NlTEV8rWdg7Pk01LFizDetuYGHx6d/f6y3lR2/oo8IfxjzJqn1UdDEyCcwT9e7NRloj8DwCYujQ=="],
20391721
20401722 "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
20411723
20421724 "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
20431725
2044− "jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="],
1726+ "jose": ["jose@6.2.2", "", {}, "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ=="],
20451727
20461728 "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
20471729
20481730 "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
20491731
2050− "jsdom": ["jsdom@26.1.0", "", { "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", "decimal.js": "^10.5.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", "is-potential-custom-element-name": "^1.0.1", "nwsapi": "^2.2.16", "parse5": "^7.2.1", "rrweb-cssom": "^0.8.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^5.1.1", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.1.1", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^3.0.0" }, "optionalPeers": ["canvas"] }, "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg=="],
2051−
20521732 "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
20531733
2054− "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
2055−
2056− "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
2057−
20581734 "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
20591735
20601736 "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],
@@ -2065,53 +1741,53 @@ · 4 unmodified lines
20651741
20661742 "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
20671743
2068− "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
1744+ "katex": ["katex@0.16.44", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-EkxoDTk8ufHqHlf9QxGwcxeLkWRR3iOuYfRpfORgYfqc8s13bgb+YtRY59NK5ZpRaCwq1kqA6a5lpX8C/eLphQ=="],
20691745
2070− "knip": ["knip@5.85.0", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "jiti": "^2.6.0", "js-yaml": "^4.1.1", "minimist": "^1.2.8", "oxc-resolver": "^11.15.0", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.5.2", "strip-json-comments": "5.0.3", "zod": "^4.1.11" }, "peerDependencies": { "@types/node": ">=18", "typescript": ">=5.0.4 <7" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-V2kyON+DZiYdNNdY6GALseiNCwX7dYdpz9Pv85AUn69Gk0UKCts+glOKWfe5KmaMByRjM9q17Mzj/KinTVOyxg=="],
1746+ "khroma": ["khroma@2.1.0", "", {}, "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="],
20711747
20721748 "kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="],
20731749
2074− "lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="],
1750+ "langium": ["langium@4.2.1", "", { "dependencies": { "chevrotain": "~11.1.1", "chevrotain-allstar": "~0.3.1", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", "vscode-uri": "~3.1.0" } }, "sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ=="],
1751+
1752+ "layout-base": ["layout-base@1.0.2", "", {}, "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="],
20751753
2076− "lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
1754+ "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
20771755
2078− "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],
1756+ "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
20791757
2080− "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="],
1758+ "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
20811759
2082− "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="],
1760+ "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
20831761
2084− "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="],
1762+ "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
20851763
2086− "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="],
1764+ "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
20871765
2088− "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="],
1766+ "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
20891767
2090− "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="],
1768+ "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
20911769
2092− "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="],
1770+ "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
20931771
2094− "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="],
1772+ "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
20951773
2096− "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="],
1774+ "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
20971775
2098− "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
1776+ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
20991777
21001778 "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
21011779
2102− "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="],
1780+ "lodash-es": ["lodash-es@4.17.23", "", {}, "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg=="],
21031781
21041782 "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="],
21051783
2106− "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="],
2107−
2108− "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
2109−
21101784 "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
21111785
1786+ "lookpath": ["lookpath@1.2.3", "", { "bin": { "lookpath": "bin/lookpath.js" } }, "sha512-kthRVhf4kH4+HW3anM4UBHxsw/XFESf13euCEldhXr6GpBdmBoa7rDd7WO5G0Mhd4G5XtKTcEy8OR0iRZXpS3Q=="],
1787+
21121788 "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
21131789
2114− "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
1790+ "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
21151791
21161792 "lucide-react": ["lucide-react@1.7.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-yI7BeItCLZJTXikmK4KNUGCKoGzSvbKlfCvw44bU4fXAL6v3gYS4uHD1jzsLkfwODYwI6Drw5Tu9Z5ulDe0TSg=="],
21171793
@@ -2119,7 +1795,7 @@ · 1 unmodified line
21191795
21201796 "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="],
21211797
2122− "marked": ["marked@17.0.4", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-NOmVMM+KAokHMvjWmC5N/ZOvgmSWuqJB8FoYI019j4ogb/PeRMKoKIjReZ2w3376kkA8dSJIP8uD993Kxc0iRQ=="],
1798+ "marked": ["marked@17.0.5", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-6hLvc0/JEbRjRgzI6wnT2P1XuM1/RrrDEX0kPt0N7jGm1133g6X7DlxFasUIx+72aKAr904GTxhSLDrd5DIlZg=="],
21231799
21241800 "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
21251801
@@ -2157,10 +1833,10 @@ · 31 unmodified lines
21571833
21581834 "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
21591835
2160− "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
2161−
21621836 "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
21631837
1838+ "mermaid": ["mermaid@11.14.0", "", { "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.2", "@mermaid-js/parser": "^1.1.0", "@types/d3": "^7.4.3", "@upsetjs/venn.js": "^2.0.0", "cytoscape": "^3.33.1", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.14", "dayjs": "^1.11.19", "dompurify": "^3.3.1", "katex": "^0.16.25", "khroma": "^2.1.0", "lodash-es": "^4.17.23", "marked": "^16.3.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0" } }, "sha512-GSGloRsBs+JINmmhl0JDwjpuezCsHB4WGI4NASHxL3fHo3o/BRXTxhDLKnln8/Q0lRFRyDdEjmk1/d5Sn1Xz8g=="],
1839+
21641840 "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="],
21651841
21661842 "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="],
@@ -2225,73 +1901,57 @@ · 58 unmodified lines
22251901
22261902 "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
22271903
2228− "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
1904+ "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
22291905
2230− "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
1906+ "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
22311907
2232− "minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
1908+ "mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="],
22331909
2234− "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
1910+ "mlly": ["mlly@1.8.2", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="],
22351911
22361912 "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
22371913
22381914 "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
22391915
2240− "msgpackr": ["msgpackr@1.11.8", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-bC4UGzHhVvgDNS7kn9tV8fAucIYUBuGojcaLiz7v+P63Lmtm0Xeji8B/8tYKddALXxJLpwIeBmUN3u64C4YkRA=="],
1916+ "msgpackr": ["msgpackr@1.11.9", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-FkoAAyyA6HM8wL882EcEyFZ9s7hVADSwG9xrVx3dxxNQAtgADTrJoEWivID82Iv1zWDsv/OtbrrcZAzGzOMdNw=="],
22411917
22421918 "msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="],
22431919
2244− "msw": ["msw@2.12.14", "", { "dependencies": { "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.41.2", "@open-draft/deferred-promise": "^2.2.0", "@types/statuses": "^2.0.6", "cookie": "^1.0.2", "graphql": "^16.12.0", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "rettime": "^0.10.1", "statuses": "^2.0.2", "strict-event-emitter": "^0.5.1", "tough-cookie": "^6.0.0", "type-fest": "^5.2.0", "until-async": "^3.0.2", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": ">= 4.8.x" }, "optionalPeers": ["typescript"], "bin": { "msw": "cli/index.js" } }, "sha512-4KXa4nVBIBjbDbd7vfQNuQ25eFxug0aropCQFoI0JdOBuJWamkT1yLVIWReFI8SiTRc+H1hKzaNk+cLk2N9rtQ=="],
2245−
22461920 "multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="],
22471921
2248− "mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="],
2249−
22501922 "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
22511923
1924+ "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="],
1925+
22521926 "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
22531927
2254− "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
1928+ "next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
22551929
2256− "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
1930+ "node-abi": ["node-abi@3.89.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA=="],
22571931
2258− "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
1932+ "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
22591933
22601934 "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="],
22611935
22621936 "node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="],
22631937
2264− "npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="],
2265−
2266− "nwsapi": ["nwsapi@2.2.23", "", {}, "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ=="],
2267−
22681938 "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
22691939
22701940 "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
22711941
2272− "object-treeify": ["object-treeify@1.1.33", "", {}, "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A=="],
2273−
22741942 "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
22751943
22761944 "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
22771945
2278− "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
2279−
22801946 "oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="],
22811947
2282− "oniguruma-to-es": ["oniguruma-to-es@4.3.4", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA=="],
1948+ "oniguruma-to-es": ["oniguruma-to-es@4.3.5", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.1.0", "regex-recursion": "^6.0.2" } }, "sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ=="],
22831949
2284− "open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="],
2285−
2286− "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="],
1950+ "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
22871951
22881952 "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="],
22891953
2290− "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="],
2291−
2292− "oxc-resolver": ["oxc-resolver@11.19.1", "", { "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.19.1", "@oxc-resolver/binding-android-arm64": "11.19.1", "@oxc-resolver/binding-darwin-arm64": "11.19.1", "@oxc-resolver/binding-darwin-x64": "11.19.1", "@oxc-resolver/binding-freebsd-x64": "11.19.1", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.19.1", "@oxc-resolver/binding-linux-arm-musleabihf": "11.19.1", "@oxc-resolver/binding-linux-arm64-gnu": "11.19.1", "@oxc-resolver/binding-linux-arm64-musl": "11.19.1", "@oxc-resolver/binding-linux-ppc64-gnu": "11.19.1", "@oxc-resolver/binding-linux-riscv64-gnu": "11.19.1", "@oxc-resolver/binding-linux-riscv64-musl": "11.19.1", "@oxc-resolver/binding-linux-s390x-gnu": "11.19.1", "@oxc-resolver/binding-linux-x64-gnu": "11.19.1", "@oxc-resolver/binding-linux-x64-musl": "11.19.1", "@oxc-resolver/binding-openharmony-arm64": "11.19.1", "@oxc-resolver/binding-wasm32-wasi": "11.19.1", "@oxc-resolver/binding-win32-arm64-msvc": "11.19.1", "@oxc-resolver/binding-win32-ia32-msvc": "11.19.1", "@oxc-resolver/binding-win32-x64-msvc": "11.19.1" } }, "sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg=="],
2293−
2294− "oxlint": ["oxlint@1.56.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.56.0", "@oxlint/binding-android-arm64": "1.56.0", "@oxlint/binding-darwin-arm64": "1.56.0", "@oxlint/binding-darwin-x64": "1.56.0", "@oxlint/binding-freebsd-x64": "1.56.0", "@oxlint/binding-linux-arm-gnueabihf": "1.56.0", "@oxlint/binding-linux-arm-musleabihf": "1.56.0", "@oxlint/binding-linux-arm64-gnu": "1.56.0", "@oxlint/binding-linux-arm64-musl": "1.56.0", "@oxlint/binding-linux-ppc64-gnu": "1.56.0", "@oxlint/binding-linux-riscv64-gnu": "1.56.0", "@oxlint/binding-linux-riscv64-musl": "1.56.0", "@oxlint/binding-linux-s390x-gnu": "1.56.0", "@oxlint/binding-linux-x64-gnu": "1.56.0", "@oxlint/binding-linux-x64-musl": "1.56.0", "@oxlint/binding-openharmony-arm64": "1.56.0", "@oxlint/binding-win32-arm64-msvc": "1.56.0", "@oxlint/binding-win32-ia32-msvc": "1.56.0", "@oxlint/binding-win32-x64-msvc": "1.56.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.15.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-Q+5Mj5PVaH/R6/fhMMFzw4dT+KPB+kQW4kaL8FOIq7tfhlnEVp6+3lcWqFruuTNlUo9srZUW3qH7Id4pskeR6g=="],
1954+ "oxlint": ["oxlint@1.58.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.58.0", "@oxlint/binding-android-arm64": "1.58.0", "@oxlint/binding-darwin-arm64": "1.58.0", "@oxlint/binding-darwin-x64": "1.58.0", "@oxlint/binding-freebsd-x64": "1.58.0", "@oxlint/binding-linux-arm-gnueabihf": "1.58.0", "@oxlint/binding-linux-arm-musleabihf": "1.58.0", "@oxlint/binding-linux-arm64-gnu": "1.58.0", "@oxlint/binding-linux-arm64-musl": "1.58.0", "@oxlint/binding-linux-ppc64-gnu": "1.58.0", "@oxlint/binding-linux-riscv64-gnu": "1.58.0", "@oxlint/binding-linux-riscv64-musl": "1.58.0", "@oxlint/binding-linux-s390x-gnu": "1.58.0", "@oxlint/binding-linux-x64-gnu": "1.58.0", "@oxlint/binding-linux-x64-musl": "1.58.0", "@oxlint/binding-openharmony-arm64": "1.58.0", "@oxlint/binding-win32-arm64-msvc": "1.58.0", "@oxlint/binding-win32-ia32-msvc": "1.58.0", "@oxlint/binding-win32-x64-msvc": "1.58.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.18.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-t4s9leczDMqlvOSjnbCQe7gtoLkWgBGZ7sBdCJ9EOj5IXFSG/X7OAzK4yuH4iW+4cAYe8kLFbC8tuYMwWZm+Cg=="],
22951955
22961956 "p-filter": ["p-filter@2.1.0", "", { "dependencies": { "p-map": "^2.0.0" } }, "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw=="],
22971957
@@ -2305,25 +1965,19 @@ · 7 unmodified lines
23051965
23061966 "package-manager-detector": ["package-manager-detector@0.2.11", "", { "dependencies": { "quansync": "^0.2.7" } }, "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ=="],
23071967
2308− "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
2309−
23101968 "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="],
23111969
2312− "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
2313−
2314− "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="],
2315−
23161970 "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
23171971
23181972 "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
23191973
2320− "path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="],
1974+ "path-data-parser": ["path-data-parser@0.1.0", "", {}, "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w=="],
23211975
23221976 "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
23231977
23241978 "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
23251979
2326− "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
1980+ "path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
23271981
23281982 "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
23291983
@@ -2333,31 +1987,29 @@ · 3 unmodified lines
23331987
23341988 "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
23351989
2336− "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
1990+ "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
23371991
23381992 "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="],
23391993
23401994 "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="],
23411995
2342− "postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="],
1996+ "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
23431997
2344− "postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="],
1998+ "points-on-curve": ["points-on-curve@0.2.0", "", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="],
23451999
2346− "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="],
2000+ "points-on-path": ["points-on-path@0.2.1", "", { "dependencies": { "path-data-parser": "0.1.0", "points-on-curve": "0.2.0" } }, "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="],
23472001
2348− "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
2002+ "postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="],
23492003
2350− "pretty-ms": ["pretty-ms@9.3.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ=="],
2004+ "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="],
23512005
2352− "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
2006+ "prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="],
23532007
23542008 "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
23552009
2356− "protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
2357−
23582010 "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
23592011
2360− "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
2012+ "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="],
23612013
23622014 "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
23632015
@@ -2371,27 +2023,45 @@ · 7 unmodified lines
23712023
23722024 "quickjs-emscripten-core": ["quickjs-emscripten-core@0.31.0", "", { "dependencies": { "@jitl/quickjs-ffi-types": "0.31.0" } }, "sha512-oQz8p0SiKDBc1TC7ZBK2fr0GoSHZKA0jZIeXxsnCyCs4y32FStzCW4d1h6E1sE0uHDMbGITbk2zhNaytaoJwXQ=="],
23732025
2026+ "radix-ui": ["radix-ui@1.4.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-accessible-icon": "1.1.7", "@radix-ui/react-accordion": "1.2.12", "@radix-ui/react-alert-dialog": "1.1.15", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-aspect-ratio": "1.1.7", "@radix-ui/react-avatar": "1.1.10", "@radix-ui/react-checkbox": "1.3.3", "@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-context-menu": "2.2.16", "@radix-ui/react-dialog": "1.1.15", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-dropdown-menu": "2.1.16", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-form": "0.1.8", "@radix-ui/react-hover-card": "1.1.15", "@radix-ui/react-label": "2.1.7", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-menubar": "1.1.16", "@radix-ui/react-navigation-menu": "1.2.14", "@radix-ui/react-one-time-password-field": "0.1.8", "@radix-ui/react-password-toggle-field": "0.1.3", "@radix-ui/react-popover": "1.1.15", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-progress": "1.1.7", "@radix-ui/react-radio-group": "1.3.8", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-scroll-area": "1.2.10", "@radix-ui/react-select": "2.2.6", "@radix-ui/react-separator": "1.1.7", "@radix-ui/react-slider": "1.3.6", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-switch": "1.2.6", "@radix-ui/react-tabs": "1.1.13", "@radix-ui/react-toast": "1.2.15", "@radix-ui/react-toggle": "1.1.10", "@radix-ui/react-toggle-group": "1.1.11", "@radix-ui/react-toolbar": "1.1.11", "@radix-ui/react-tooltip": "1.2.8", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-escape-keydown": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA=="],
2027+
23742028 "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
23752029
23762030 "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
23772031
2032+ "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
2033+
23782034 "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
23792035
2036+ "react-day-picker": ["react-day-picker@9.14.0", "", { "dependencies": { "@date-fns/tz": "^1.4.1", "@tabby_ai/hijri-converter": "1.0.5", "date-fns": "^4.1.0", "date-fns-jalali": "4.1.0-0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-tBaoDWjPwe0M5pGrum4H0SR6Lyk+BO9oHnp9JbKpGKW2mlraNPgP9BMfsg5pWpwrssARmeqk7YBl2oXutZTaHA=="],
2037+
23802038 "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
23812039
2382− "react-grab": ["react-grab@0.1.26", "", { "dependencies": { "@medv/finder": "^4.0.2", "@react-grab/cli": "0.1.26", "bippy": "^0.5.32", "solid-js": "^1.9.10" }, "peerDependencies": { "react": ">=17.0.0" }, "optionalPeers": ["react"], "bin": { "react-grab": "bin/cli.js" } }, "sha512-ubpS3jvxuO47J3/GGYYXVQ0L/EfIojpLg8a+2Ii+8doGJmnZw0nw2Ez1cGpNaZeSHbmY4+8qADWoIFOMWD008A=="],
2040+ "react-hook-form": ["react-hook-form@7.72.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-V4v6jubaf6JAurEaVnT9aUPKFbNtDgohj5CIgVGyPHvT9wRx5OZHVjz31GsxnPNI278XMu+ruFz+wGOscHaLKw=="],
2041+
2042+ "react-is": ["react-is@19.2.4", "", {}, "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA=="],
2043+
2044+ "react-redux": ["react-redux@9.2.0", "", { "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "@types/react": "^18.2.25 || ^19", "react": "^18.0 || ^19", "redux": "^5.0.0" }, "optionalPeers": ["@types/react", "redux"] }, "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g=="],
23832045
2384− "react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="],
2046+ "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="],
23852047
23862048 "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="],
23872049
23882050 "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
23892051
2052+ "react-resizable-panels": ["react-resizable-panels@4.8.0", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-2uEABkewb3ky/ZgIlAUxWa1W/LjsK494fdV1QsXxst7CDRHCzo7h22tWWu3NNaBjmiuriOCt3CvhipnaYcpoIw=="],
2053+
23902054 "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
23912055
23922056 "read-yaml-file": ["read-yaml-file@1.1.0", "", { "dependencies": { "graceful-fs": "^4.1.5", "js-yaml": "^3.6.1", "pify": "^4.0.1", "strip-bom": "^3.0.0" } }, "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA=="],
23932057
2394− "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="],
2058+ "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
2059+
2060+ "recharts": ["recharts@3.8.0", "", { "dependencies": { "@reduxjs/toolkit": "^1.9.0 || 2.x.x", "clsx": "^2.1.1", "decimal.js-light": "^2.5.1", "es-toolkit": "^1.39.3", "eventemitter3": "^5.0.1", "immer": "^10.1.1", "react-redux": "8.x.x || 9.x.x", "reselect": "5.1.1", "tiny-invariant": "^1.3.3", "use-sync-external-store": "^1.2.2", "victory-vendor": "^37.0.2" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Z/m38DX3L73ExO4Tpc9/iZWHmHnlzWG4njQbxsF5aSjwqmHNDDIm0rdEBArkwsBvR8U6EirlEHiQNYWCVh9sGQ=="],
2061+
2062+ "redux": ["redux@5.0.1", "", {}, "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="],
2063+
2064+ "redux-thunk": ["redux-thunk@3.1.0", "", { "peerDependencies": { "redux": "^5.0.0" } }, "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw=="],
23952065
23962066 "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],
23972067
@@ -2413,9 +2083,7 @@ · 15 unmodified lines
24132083
24142084 "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="],
24152085
2416− "remend": ["remend@1.2.2", "", {}, "sha512-4ZJgIB9EG9fQE41mOJCRHMmnxDTKHWawQoJWZyUbZuj680wVyogu2ihnj8Edqm7vh2mo/TWHyEZpn2kqeDvS7w=="],
2417−
2418− "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
2086+ "remend": ["remend@1.3.0", "", {}, "sha512-iIhggPkhW3hFImKtB10w0dz4EZbs28mV/dmbcYVonWEJ6UGHHpP+bFZnTh6GNWJONg5m+U56JrL+8IxZRdgWjw=="],
24192087
24202088 "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
24212089
@@ -2423,49 +2091,43 @@ · 1 unmodified line
24232091
24242092 "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
24252093
2426− "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
2094+ "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
24272095
2428− "rettime": ["rettime@0.10.1", "", {}, "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw=="],
2096+ "robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="],
24292097
2430− "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
2098+ "rollup": ["rollup@4.60.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.1", "@rollup/rollup-android-arm64": "4.60.1", "@rollup/rollup-darwin-arm64": "4.60.1", "@rollup/rollup-darwin-x64": "4.60.1", "@rollup/rollup-freebsd-arm64": "4.60.1", "@rollup/rollup-freebsd-x64": "4.60.1", "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", "@rollup/rollup-linux-arm-musleabihf": "4.60.1", "@rollup/rollup-linux-arm64-gnu": "4.60.1", "@rollup/rollup-linux-arm64-musl": "4.60.1", "@rollup/rollup-linux-loong64-gnu": "4.60.1", "@rollup/rollup-linux-loong64-musl": "4.60.1", "@rollup/rollup-linux-ppc64-gnu": "4.60.1", "@rollup/rollup-linux-ppc64-musl": "4.60.1", "@rollup/rollup-linux-riscv64-gnu": "4.60.1", "@rollup/rollup-linux-riscv64-musl": "4.60.1", "@rollup/rollup-linux-s390x-gnu": "4.60.1", "@rollup/rollup-linux-x64-gnu": "4.60.1", "@rollup/rollup-linux-x64-musl": "4.60.1", "@rollup/rollup-openbsd-x64": "4.60.1", "@rollup/rollup-openharmony-arm64": "4.60.1", "@rollup/rollup-win32-arm64-msvc": "4.60.1", "@rollup/rollup-win32-ia32-msvc": "4.60.1", "@rollup/rollup-win32-x64-gnu": "4.60.1", "@rollup/rollup-win32-x64-msvc": "4.60.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w=="],
24312099
2432− "rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="],
2100+ "roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="],
24332101
24342102 "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
24352103
2436− "rrweb-cssom": ["rrweb-cssom@0.8.0", "", {}, "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw=="],
2104+ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
24372105
2438− "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],
2106+ "rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="],
24392107
2440− "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
2108+ "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
24412109
24422110 "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
24432111
2444− "saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="],
2445−
24462112 "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
24472113
24482114 "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
24492115
24502116 "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
24512117
2452− "seroval": ["seroval@1.5.0", "", {}, "sha512-OE4cvmJ1uSPrKorFIH9/w/Qwuvi/IMcGbv5RKgcJ/zjA/IohDLU6SVaxFN9FwajbP7nsX0dQqMDes1whk3y+yw=="],
2118+ "seroval": ["seroval@1.5.1", "", {}, "sha512-OwrZRZAfhHww0WEnKHDY8OM0U/Qs8OTfIDWhUD4BLpNJUfXK4cGmjiagGze086m+mhI+V2nD0gfbHEnJjb9STA=="],
24532119
2454− "seroval-plugins": ["seroval-plugins@1.5.0", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-EAHqADIQondwRZIdeW2I636zgsODzoBDwb3PT/+7TLDWyw1Dy/Xv7iGUIEXXav7usHDE9HVhOU61irI3EnyyHA=="],
2120+ "seroval-plugins": ["seroval-plugins@1.5.1", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-4FbuZ/TMl02sqv0RTFexu0SP6V+ywaIe5bAWCCEik0fk17BhALgwvUDVF7e3Uvf9pxmwCEJsRPmlkUE6HdzLAw=="],
24552121
24562122 "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="],
24572123
2458− "ses": ["ses@1.15.0", "", { "dependencies": { "@endo/cache-map": "^1.1.0", "@endo/env-options": "^1.1.11", "@endo/immutable-arraybuffer": "^1.1.2" } }, "sha512-Y7RvgVXhkwQEqVActNn44QBxB2BCUbPfexAaMiUFjbJkDXDnxPisQC5jYQeWOZ3QBOfecnmLfPn0sQKLiYGBAQ=="],
2459−
24602124 "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
24612125
2462− "shadcn": ["shadcn@4.1.1", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "https-proxy-agent": "^7.0.6", "kleur": "^4.1.5", "msw": "^2.10.4", "node-fetch": "^3.3.2", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-nBj+7LYC9kzV9v9QmRPpoOhfW4KctJVQejywdAt/K+K+z4RYlJOcO2a4AaF7elrRWkfCbgXeGK02liV0KB9HvQ=="],
2463−
24642126 "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
24652127
24662128 "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
24672129
2468− "shiki": ["shiki@4.0.1", "", { "dependencies": { "@shikijs/core": "4.0.1", "@shikijs/engine-javascript": "4.0.1", "@shikijs/engine-oniguruma": "4.0.1", "@shikijs/langs": "4.0.1", "@shikijs/themes": "4.0.1", "@shikijs/types": "4.0.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-EkAEhDTN5WhpoQFXFw79OHIrSAfHhlImeCdSyg4u4XvrpxKEmdo/9x/HWSowujAnUrFsGOwWiE58a6GVentMnQ=="],
2130+ "shiki": ["shiki@4.0.2", "", { "dependencies": { "@shikijs/core": "4.0.2", "@shikijs/engine-javascript": "4.0.2", "@shikijs/engine-oniguruma": "4.0.2", "@shikijs/langs": "4.0.2", "@shikijs/themes": "4.0.2", "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-eAVKTMedR5ckPo4xne/PjYQYrU3qx78gtJZ+sHlXEg5IHhhoQhMfZVzetTYuaJS0L2Ef3AcCRzCHV8T0WI6nIQ=="],
24692131
24702132 "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
24712133
@@ -2479,15 +2141,13 @@ · 7 unmodified lines
24792141
24802142 "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
24812143
2482− "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
2144+ "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
24832145
2484− "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
2485−
2486− "smol-toml": ["smol-toml@1.6.0", "", {}, "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw=="],
2146+ "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="],
24872147
2488− "solid-js": ["solid-js@1.9.11", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", "seroval-plugins": "~1.5.0" } }, "sha512-WEJtcc5mkh/BnHA6Yrg4whlF8g6QwpmXXRg4P2ztPmcKeHHlH4+djYecBLhSpecZY2RRECXYUwIc/C2r3yzQ4Q=="],
2148+ "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
24892149
2490− "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
2150+ "sonner": ["sonner@2.0.7", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w=="],
24912151
24922152 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
24932153
@@ -2503,25 +2163,17 @@ · 9 unmodified lines
25032163
25042164 "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
25052165
2506− "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="],
2507−
2508− "streamdown": ["streamdown@2.4.0", "", { "dependencies": { "clsx": "^2.1.1", "hast-util-to-jsx-runtime": "^2.3.6", "html-url-attributes": "^3.0.1", "marked": "^17.0.1", "rehype-harden": "^1.1.8", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remend": "1.2.2", "tailwind-merge": "^3.4.0", "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-fRk4HEYNznRLmxoVeT8wsGBwHF6/Yrdey6k+ZrE1Qtp4NyKwm7G/6e2Iw8penY4yLx31TlAHWT5Bsg1weZ9FZg=="],
2166+ "streamdown": ["streamdown@2.5.0", "", { "dependencies": { "clsx": "^2.1.1", "hast-util-to-jsx-runtime": "^2.3.6", "html-url-attributes": "^3.0.1", "marked": "^17.0.1", "mermaid": "^11.12.2", "rehype-harden": "^1.1.8", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remend": "1.3.0", "tailwind-merge": "^3.4.0", "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-/tTnURfIOxZK/pqJAxsfCvETG/XCJHoWnk3jq9xLcuz6CSpnjjuxSRBTTL4PKGhxiZQf0lqPxGhImdpwcZ2XwA=="],
25092167
2510− "strict-event-emitter": ["strict-event-emitter@0.5.1", "", {}, "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ=="],
2511−
2512− "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
2168+ "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
25132169
25142170 "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
25152171
2516− "stringify-object": ["stringify-object@5.0.0", "", { "dependencies": { "get-own-enumerable-keys": "^1.0.0", "is-obj": "^3.0.0", "is-regexp": "^3.1.0" } }, "sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg=="],
2517−
25182172 "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
25192173
25202174 "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
25212175
2522− "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="],
2523−
2524− "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="],
2176+ "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
25252177
25262178 "strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="],
25272179
@@ -2529,24 +2181,24 @@ · 1 unmodified line
25292181
25302182 "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
25312183
2532− "symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="],
2184+ "stylis": ["stylis@4.3.6", "", {}, "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="],
25332185
25342186 "tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],
25352187
2536− "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
2537−
25382188 "tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="],
25392189
2540− "tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="],
2190+ "tailwindcss": ["tailwindcss@4.2.2", "", {}, "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q=="],
25412191
2542− "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
2192+ "tapable": ["tapable@2.3.2", "", {}, "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA=="],
2193+
2194+ "tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="],
2195+
2196+ "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
25432197
25442198 "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="],
25452199
25462200 "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
25472201
2548− "tiny-warning": ["tiny-warning@1.0.3", "", {}, "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="],
2549−
25502202 "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
25512203
25522204 "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
@@ -2559,57 +2211,33 @@ · 6 unmodified lines
25592211
25602212 "tinyspy": ["tinyspy@4.0.4", "", {}, "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q=="],
25612213
2562− "tldts": ["tldts@7.0.27", "", { "dependencies": { "tldts-core": "^7.0.27" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-I4FZcVFcqCRuT0ph6dCDpPuO4Xgzvh+spkcTr1gK7peIvxWauoloVO0vuy1FQnijT63ss6AsHB6+OIM4aXHbPg=="],
2563−
2564− "tldts-core": ["tldts-core@7.0.27", "", {}, "sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg=="],
2565−
25662214 "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
25672215
25682216 "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
25692217
25702218 "toml": ["toml@3.0.0", "", {}, "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="],
25712219
2572− "tough-cookie": ["tough-cookie@5.1.2", "", { "dependencies": { "tldts": "^6.1.32" } }, "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A=="],
2573−
2574− "tr46": ["tr46@5.1.1", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw=="],
2575−
25762220 "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
25772221
25782222 "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
25792223
2580− "ts-morph": ["ts-morph@26.0.0", "", { "dependencies": { "@ts-morph/common": "~0.27.0", "code-block-writer": "^13.0.3" } }, "sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug=="],
2581−
2582− "tsconfig-paths": ["tsconfig-paths@4.2.0", "", { "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg=="],
2224+ "ts-dedent": ["ts-dedent@2.2.0", "", {}, "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="],
25832225
25842226 "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
25852227
2586− "turbo": ["turbo@2.8.14", "", { "optionalDependencies": { "turbo-darwin-64": "2.8.14", "turbo-darwin-arm64": "2.8.14", "turbo-linux-64": "2.8.14", "turbo-linux-arm64": "2.8.14", "turbo-windows-64": "2.8.14", "turbo-windows-arm64": "2.8.14" }, "bin": { "turbo": "bin/turbo" } }, "sha512-UCTxeMNYT1cKaHiIFdLCQ7ulI+jw5i5uOnJOrRXsgUD7G3+OjlUjwVd7JfeVt2McWSVGjYA3EVW/v1FSsJ5DtA=="],
2587−
2588− "turbo-darwin-64": ["turbo-darwin-64@2.8.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-9sFi7n2lLfEsGWi5OEoA/eTtQU2BPKtzSYKqufMtDeRmqMT9vKjbv9gJCRkllSVE9BOXA0qXC3diyX8V8rKIKw=="],
2589−
2590− "turbo-darwin-arm64": ["turbo-darwin-arm64@2.8.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-aS4yJuy6A1PCLws+PJpZP0qCURG8Y5iVx13z/WAbKyeDTY6W6PiGgcEllSaeLGxyn++382ztN/EZH85n2zZ6VQ=="],
2591−
2592− "turbo-linux-64": ["turbo-linux-64@2.8.14", "", { "os": "linux", "cpu": "x64" }, "sha512-XC6wPUDJkakjhNLaS0NrHDMiujRVjH+naEAwvKLArgqRaFkNxjmyNDRM4eu3soMMFmjym6NTxYaF74rvET+Orw=="],
2593−
2594− "turbo-linux-arm64": ["turbo-linux-arm64@2.8.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-ChfE7isyVNjZrVSPDwcfqcHLG/FuIBbOFxnt1FM8vSuBGzHAs8AlTdwFNIxlEMJfZ8Ad9mdMxdmsCUPIWiQ6cg=="],
2228+ "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
25952229
2596− "turbo-windows-64": ["turbo-windows-64@2.8.14", "", { "os": "win32", "cpu": "x64" }, "sha512-FTbIeQL1ycLFW2t9uQNMy+bRSzi3Xhwun/e7ZhFBdM+U0VZxxrtfYEBM9CHOejlfqomk6Jh7aRz0sJoqYn39Hg=="],
2597−
2598− "turbo-windows-arm64": ["turbo-windows-arm64@2.8.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-KgZX12cTyhY030qS7ieT8zRkhZZE2VWJasDFVUSVVn17nR7IShpv68/7j5UqJNeRLIGF1XPK0phsP5V5yw3how=="],
2599−
2600− "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
2601−
2602− "type-fest": ["type-fest@5.5.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g=="],
2230+ "turbo": ["turbo@2.9.2", "", { "optionalDependencies": { "@turbo/darwin-64": "2.9.2", "@turbo/darwin-arm64": "2.9.2", "@turbo/linux-64": "2.9.2", "@turbo/linux-arm64": "2.9.2", "@turbo/windows-64": "2.9.2", "@turbo/windows-arm64": "2.9.2" }, "bin": { "turbo": "bin/turbo" } }, "sha512-DUUWysctg/vax8W05UJcyrHm4LvxtX0umAT4bZB5lab4inNXTbwoYSFpdgqzBxON23j8ls3xGxvx0kwQz6Q8wQ=="],
26032231
26042232 "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
26052233
26062234 "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
26072235
2608− "undici": ["undici@7.22.0", "", {}, "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg=="],
2236+ "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
26092237
2610− "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
2238+ "undici": ["undici@7.24.6", "", {}, "sha512-Xi4agocCbRzt0yYMZGMA6ApD7gvtUFaxm4ZmeacWI4cZxaF6C+8I8QfofC20NAePiB/IcvZmzkJ7XPa471AEtA=="],
26112239
2612− "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],
2240+ "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
26132241
26142242 "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="],
26152243
@@ -2627,8 +2255,6 @@ · 11 unmodified lines
26272255
26282256 "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
26292257
2630− "until-async": ["until-async@3.0.2", "", {}, "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw=="],
2631−
26322258 "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
26332259
26342260 "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
@@ -2641,210 +2267,234 @@ · 6 unmodified lines
26412267
26422268 "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
26432269
2644− "validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="],
2645−
26462270 "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
26472271
2272+ "vaul": ["vaul@1.1.2", "", { "dependencies": { "@radix-ui/react-dialog": "^1.1.1" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA=="],
2273+
26482274 "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
26492275
26502276 "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
26512277
26522278 "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
26532279
2654− "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="],
2280+ "victory-vendor": ["victory-vendor@37.3.6", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ=="],
2281+
2282+ "vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],
26552283
26562284 "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="],
26572285
26582286 "vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="],
26592287
2660− "w3c-xmlserializer": ["w3c-xmlserializer@5.0.0", "", { "dependencies": { "xml-name-validator": "^5.0.0" } }, "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA=="],
2661−
2662− "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="],
2288+ "vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="],
26632289
2664− "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
2290+ "vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="],
26652291
2666− "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
2292+ "vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.5", "", { "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg=="],
26672293
2668− "webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="],
2294+ "vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.12", "", {}, "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="],
26692295
2670− "whatwg-encoding": ["whatwg-encoding@3.1.1", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="],
2296+ "vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="],
26712297
2672− "whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="],
2298+ "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="],
26732299
2674− "whatwg-url": ["whatwg-url@14.2.0", "", { "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" } }, "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw=="],
2300+ "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
26752301
26762302 "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
26772303
26782304 "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
26792305
2680− "wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
2681−
26822306 "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
26832307
2684− "ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],
2308+ "ws": ["ws@8.20.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA=="],
26852309
2686− "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="],
2310+ "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
26872311
2688− "xml-name-validator": ["xml-name-validator@5.0.0", "", {}, "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg=="],
2312+ "yaml": ["yaml@2.8.3", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg=="],
26892313
2690− "xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="],
2314+ "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
26912315
2692− "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
2316+ "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="],
26932317
2694− "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
2318+ "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
26952319
2696− "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="],
2320+ "@antfu/install-pkg/package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="],
26972321
2698− "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
2322+ "@antfu/install-pkg/tinyexec": ["tinyexec@1.0.4", "", {}, "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw=="],
26992323
2700− "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
2324+ "@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
27012325
2702− "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="],
2326+ "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
27032327
2704− "yoctocolors-cjs": ["yoctocolors-cjs@2.1.3", "", {}, "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw=="],
2328+ "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
27052329
2706− "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
2330+ "@executor/config/typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
27072331
2708− "zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
2332+ "@executor/sdk/typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
27092333
2710− "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
2334+ "@manypkg/find-root/@types/node": ["@types/node@12.20.55", "", {}, "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="],
27112335
2712− "@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
2336+ "@manypkg/find-root/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
27132337
2714− "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
2338+ "@manypkg/get-packages/@changesets/types": ["@changesets/types@4.1.0", "", {}, "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw=="],
27152339
2716− "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
2340+ "@manypkg/get-packages/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
27172341
2718− "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
2342+ "@reduxjs/toolkit/immer": ["immer@11.1.4", "", {}, "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw=="],
27192343
2720− "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
2344+ "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
27212345
2722− "@changesets/apply-release-plan/prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="],
2346+ "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="],
27232347
2724− "@changesets/write/prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="],
2348+ "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
27252349
2726− "@dotenvx/dotenvx/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
2350+ "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw=="],
27272351
2728− "@dotenvx/dotenvx/execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
2352+ "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
27292353
2730− "@dotenvx/dotenvx/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
2354+ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
27312355
2732− "@dotenvx/dotenvx/which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="],
2356+ "bun-types/@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
27332357
2734− "@manypkg/find-root/@types/node": ["@types/node@12.20.55", "", {}, "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="],
2358+ "cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="],
27352359
2736− "@manypkg/find-root/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
2360+ "d3-dsv/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
27372361
2738− "@manypkg/get-packages/@changesets/types": ["@changesets/types@4.1.0", "", {}, "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw=="],
2362+ "d3-dsv/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
27392363
2740− "@manypkg/get-packages/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
2364+ "d3-sankey/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="],
2365+
2366+ "d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="],
27412367
2742− "@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
2368+ "mermaid/marked": ["marked@16.4.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="],
27432369
2744− "@radix-ui/react-dismissable-layer/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
2370+ "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
27452371
2746− "@radix-ui/react-focus-scope/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
2372+ "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
27472373
2748− "@radix-ui/react-portal/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
2374+ "rc/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
27492375
2750− "@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
2376+ "read-yaml-file/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
27512377
2752− "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
2378+ "vite-node/vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="],
27532379
2754− "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
2380+ "vitest/vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="],
27552381
2756− "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
2382+ "bun-types/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
27572383
2758− "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
2384+ "cytoscape-fcose/cose-base/layout-base": ["layout-base@2.0.1", "", {}, "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="],
27592385
2760− "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
2386+ "d3-sankey/d3-array/internmap": ["internmap@1.0.1", "", {}, "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="],
27612387
2762− "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
2388+ "d3-sankey/d3-shape/d3-path": ["d3-path@1.0.9", "", {}, "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="],
27632389
2764− "@ts-morph/common/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
2390+ "read-yaml-file/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
27652391
2766− "cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
2392+ "vite-node/vite/esbuild": ["esbuild@0.27.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.4", "@esbuild/android-arm": "0.27.4", "@esbuild/android-arm64": "0.27.4", "@esbuild/android-x64": "0.27.4", "@esbuild/darwin-arm64": "0.27.4", "@esbuild/darwin-x64": "0.27.4", "@esbuild/freebsd-arm64": "0.27.4", "@esbuild/freebsd-x64": "0.27.4", "@esbuild/linux-arm": "0.27.4", "@esbuild/linux-arm64": "0.27.4", "@esbuild/linux-ia32": "0.27.4", "@esbuild/linux-loong64": "0.27.4", "@esbuild/linux-mips64el": "0.27.4", "@esbuild/linux-ppc64": "0.27.4", "@esbuild/linux-riscv64": "0.27.4", "@esbuild/linux-s390x": "0.27.4", "@esbuild/linux-x64": "0.27.4", "@esbuild/netbsd-arm64": "0.27.4", "@esbuild/netbsd-x64": "0.27.4", "@esbuild/openbsd-arm64": "0.27.4", "@esbuild/openbsd-x64": "0.27.4", "@esbuild/openharmony-arm64": "0.27.4", "@esbuild/sunos-x64": "0.27.4", "@esbuild/win32-arm64": "0.27.4", "@esbuild/win32-ia32": "0.27.4", "@esbuild/win32-x64": "0.27.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ=="],
27672393
2768− "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
2394+ "vitest/vite/esbuild": ["esbuild@0.27.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.4", "@esbuild/android-arm": "0.27.4", "@esbuild/android-arm64": "0.27.4", "@esbuild/android-x64": "0.27.4", "@esbuild/darwin-arm64": "0.27.4", "@esbuild/darwin-x64": "0.27.4", "@esbuild/freebsd-arm64": "0.27.4", "@esbuild/freebsd-x64": "0.27.4", "@esbuild/linux-arm": "0.27.4", "@esbuild/linux-arm64": "0.27.4", "@esbuild/linux-ia32": "0.27.4", "@esbuild/linux-loong64": "0.27.4", "@esbuild/linux-mips64el": "0.27.4", "@esbuild/linux-ppc64": "0.27.4", "@esbuild/linux-riscv64": "0.27.4", "@esbuild/linux-s390x": "0.27.4", "@esbuild/linux-x64": "0.27.4", "@esbuild/netbsd-arm64": "0.27.4", "@esbuild/netbsd-x64": "0.27.4", "@esbuild/openbsd-arm64": "0.27.4", "@esbuild/openbsd-x64": "0.27.4", "@esbuild/openharmony-arm64": "0.27.4", "@esbuild/sunos-x64": "0.27.4", "@esbuild/win32-arm64": "0.27.4", "@esbuild/win32-ia32": "0.27.4", "@esbuild/win32-x64": "0.27.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ=="],
27692395
2770− "globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
2396+ "vite-node/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="],
27712397
2772− "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
2398+ "vite-node/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.4", "", { "os": "android", "cpu": "arm" }, "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ=="],
27732399
2774− "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="],
2400+ "vite-node/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.4", "", { "os": "android", "cpu": "arm64" }, "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw=="],
27752401
2776− "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
2402+ "vite-node/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.4", "", { "os": "android", "cpu": "x64" }, "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw=="],
27772403
2778− "msw/cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
2404+ "vite-node/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ=="],
27792405
2780− "msw/tough-cookie": ["tough-cookie@6.0.1", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw=="],
2406+ "vite-node/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw=="],
27812407
2782− "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
2408+ "vite-node/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw=="],
27832409
2784− "ora/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
2410+ "vite-node/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ=="],
27852411
2786− "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
2412+ "vite-node/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.4", "", { "os": "linux", "cpu": "arm" }, "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg=="],
27872413
2788− "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
2414+ "vite-node/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA=="],
27892415
2790− "read-yaml-file/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
2416+ "vite-node/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA=="],
27912417
2792− "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
2418+ "vite-node/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA=="],
27932419
2794− "router/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="],
2420+ "vite-node/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw=="],
27952421
2796− "shadcn/fs-extra": ["fs-extra@11.3.4", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA=="],
2422+ "vite-node/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA=="],
27972423
2798− "shadcn/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
2424+ "vite-node/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw=="],
27992425
2800− "string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
2426+ "vite-node/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA=="],
28012427
2802− "tough-cookie/tldts": ["tldts@6.1.86", "", { "dependencies": { "tldts-core": "^6.1.86" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ=="],
2428+ "vite-node/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.4", "", { "os": "linux", "cpu": "x64" }, "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA=="],
28032429
2804− "whatwg-encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
2430+ "vite-node/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q=="],
28052431
2806− "wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
2432+ "vite-node/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.4", "", { "os": "none", "cpu": "x64" }, "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg=="],
28072433
2808− "yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
2434+ "vite-node/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow=="],
28092435
2810− "@dotenvx/dotenvx/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
2436+ "vite-node/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ=="],
28112437
2812− "@dotenvx/dotenvx/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
2438+ "vite-node/vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg=="],
28132439
2814− "@dotenvx/dotenvx/execa/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
2440+ "vite-node/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g=="],
28152441
2816− "@dotenvx/dotenvx/execa/npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
2442+ "vite-node/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg=="],
28172443
2818− "@dotenvx/dotenvx/execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
2444+ "vite-node/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw=="],
28192445
2820− "@dotenvx/dotenvx/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
2446+ "vite-node/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg=="],
28212447
2822− "@dotenvx/dotenvx/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="],
2448+ "vitest/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="],
28232449
2824− "@ts-morph/common/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
2450+ "vitest/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.4", "", { "os": "android", "cpu": "arm" }, "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ=="],
28252451
2826− "cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
2452+ "vitest/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.4", "", { "os": "android", "cpu": "arm64" }, "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw=="],
28272453
2828− "msw/tough-cookie/tldts": ["tldts@7.0.25", "", { "dependencies": { "tldts-core": "^7.0.25" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w=="],
2454+ "vitest/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.4", "", { "os": "android", "cpu": "x64" }, "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw=="],
28292455
2830− "ora/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
2456+ "vitest/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ=="],
28312457
2832− "read-yaml-file/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
2458+ "vitest/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw=="],
2459+
2460+ "vitest/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw=="],
2461+
2462+ "vitest/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ=="],
2463+
2464+ "vitest/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.4", "", { "os": "linux", "cpu": "arm" }, "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg=="],
2465+
2466+ "vitest/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA=="],
2467+
2468+ "vitest/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA=="],
2469+
2470+ "vitest/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA=="],
2471+
2472+ "vitest/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw=="],
2473+
2474+ "vitest/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA=="],
2475+
2476+ "vitest/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw=="],
2477+
2478+ "vitest/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA=="],
2479+
2480+ "vitest/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.4", "", { "os": "linux", "cpu": "x64" }, "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA=="],
2481+
2482+ "vitest/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q=="],
28332483
2834− "shadcn/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],
2484+ "vitest/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.4", "", { "os": "none", "cpu": "x64" }, "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg=="],
28352485
2836− "shadcn/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
2486+ "vitest/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow=="],
28372487
2838− "string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
2488+ "vitest/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ=="],
28392489
2840− "tough-cookie/tldts/tldts-core": ["tldts-core@6.1.86", "", {}, "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA=="],
2490+ "vitest/vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg=="],
28412491
2842− "wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
2492+ "vitest/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g=="],
28432493
2844− "yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
2494+ "vitest/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg=="],
28452495
2846− "@ts-morph/common/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
2496+ "vitest/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw=="],
28472497
2848− "msw/tough-cookie/tldts/tldts-core": ["tldts-core@7.0.25", "", {}, "sha512-ZjCZK0rppSBu7rjHYDYsEaMOIbbT+nWF57hKkv4IUmZWBNrBWBOjIElc0mKRgLM8bm7x/BBlof6t2gi/Oq/Asw=="],
2498+ "vitest/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg=="],
28492499 }
28502500 }
compose.tracing.yaml+0−9
@@ -1,9 +0,0 @@
1−services:
2− jaeger:
3− image: jaegertracing/all-in-one:1.65.0
4− ports:
5− - "16686:16686"
6− - "4317:4317"
7− - "4318:4318"
8− environment:
9− COLLECTOR_OTLP_ENABLED: "true"
examples/mcp-elicitation-demo/CHANGELOG.md+0−3
@@ -1,3 +0,0 @@
1−# @executor/mcp-elicitation-demo
2−
3−## null
examples/mcp-elicitation-demo/package.json+0−21
@@ -1,21 +0,0 @@
1−{
2− "name": "@executor/mcp-elicitation-demo",
3− "private": true,
4− "type": "module",
5− "exports": {
6− ".": "./src/index.ts"
7− },
8− "scripts": {
9− "typecheck": "bunx tsc --noEmit -p tsconfig.json",
10− "start": "bun src/main.ts"
11− },
12− "dependencies": {
13− "@modelcontextprotocol/sdk": "^1.26.0",
14− "zod": "catalog:"
15− },
16− "devDependencies": {
17− "@types/node": "catalog:",
18− "bun-types": "catalog:"
19− },
20− "version": "0.0.0"
21−}
examples/mcp-elicitation-demo/src/index.ts+0−4
@@ -1,4 +0,0 @@
1−export {
2− startMcpElicitationDemoServer,
3− type McpElicitationDemoServer,
4−} from "./server";
examples/mcp-elicitation-demo/src/main.ts+0−20
@@ -1,20 +0,0 @@
1−import { startMcpElicitationDemoServer } from "./server";
2−
3−const host = process.env.HOST ?? "127.0.0.1";
4−const port = process.env.PORT ? Number(process.env.PORT) : 58506;
5−
6−const server = await startMcpElicitationDemoServer({ host, port });
7−console.error(`mcp-elicitation-demo listening on ${server.endpoint}`);
8−
9−const shutdown = async () => {
10− await server.close();
11− process.exit(0);
12−};
13−
14−process.once("SIGINT", () => {
15− void shutdown();
16−});
17−
18−process.once("SIGTERM", () => {
19− void shutdown();
20−});
examples/mcp-elicitation-demo/src/server.ts+0−222
@@ -1,222 +0,0 @@
1−import { randomUUID } from "node:crypto";
2−
3−import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
4−import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5−import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
6−import { z } from "zod/v4";
7−
8−export type McpElicitationDemoServer = {
9− readonly endpoint: string;
10− readonly close: () => Promise<void>;
11−};
12−
13−const registerDemoTools = (server: McpServer) => {
14− server.registerTool(
15− "gated_echo",
16− {
17− description: "Ask for approval before echoing the provided value.",
18− inputSchema: {
19− value: z.string(),
20− },
21− },
22− async ({ value }: { value: string }) => {
23− const response = await server.server.elicitInput({
24− mode: "form",
25− message: `Approve gated echo for ${value}?`,
26− requestedSchema: {
27− type: "object",
28− properties: {
29− approve: {
30− type: "boolean",
31− title: "Approve",
32− },
33− },
34− required: ["approve"],
35− },
36− });
37−
38− if (
39− response.action !== "accept"
40− || !response.content
41− || response.content.approve !== true
42− ) {
43− return {
44− content: [{ type: "text", text: "denied" }],
45− };
46− }
47−
48− return {
49− content: [{ type: "text", text: `approved:${value}` }],
50− };
51− },
52− );
53−};
54−
55−export const startMcpElicitationDemoServer = async (input: {
56− readonly host?: string;
57− readonly port?: number;
58−} = {}): Promise<McpElicitationDemoServer> => {
59− const host = input.host ?? "127.0.0.1";
60− const app = createMcpExpressApp({ host });
61− const transports: Record<string, StreamableHTTPServerTransport> = {};
62− const servers: Record<string, McpServer> = {};
63−
64− const createServer = () => {
65− const server = new McpServer(
66− {
67− name: "executor-mcp-elicitation-demo",
68− version: "1.0.0",
69− },
70− {
71− capabilities: {
72− tools: {},
73− },
74− },
75− );
76−
77− registerDemoTools(server);
78− return server;
79− };
80−
81− app.post("/mcp", async (req: any, res: any) => {
82− const sessionIdHeader = req.headers["mcp-session-id"];
83− const sessionId =
84− typeof sessionIdHeader === "string"
85− ? sessionIdHeader
86− : Array.isArray(sessionIdHeader)
87− ? sessionIdHeader[0]
88− : undefined;
89−
90− try {
91− let transport: StreamableHTTPServerTransport;
92−
93− if (sessionId && transports[sessionId]) {
94− transport = transports[sessionId];
95− } else {
96− transport = new StreamableHTTPServerTransport({
97− sessionIdGenerator: () => randomUUID(),
98− onsessioninitialized: (newSessionId) => {
99− transports[newSessionId] = transport;
100− },
101− });
102−
103− transport.onclose = () => {
104− const closedSessionId = transport.sessionId;
105− if (closedSessionId && transports[closedSessionId]) {
106− delete transports[closedSessionId];
107− }
108− if (closedSessionId && servers[closedSessionId]) {
109− void servers[closedSessionId].close().catch(() => undefined);
110− delete servers[closedSessionId];
111− }
112− };
113−
114− const server = createServer();
115− await server.connect(transport);
116− const newSessionId = transport.sessionId;
117− if (newSessionId) {
118− servers[newSessionId] = server;
119− }
120− }
121−
122− await transport.handleRequest(req, res, req.body);
123− } catch (error) {
124− if (!res.headersSent) {
125− res.status(500).json({
126− jsonrpc: "2.0",
127− error: {
128− code: -32603,
129− message: error instanceof Error ? error.message : "Internal server error",
130− },
131− id: null,
132− });
133− }
134− }
135− });
136−
137− app.get("/mcp", async (req: any, res: any) => {
138− const sessionIdHeader = req.headers["mcp-session-id"];
139− const sessionId =
140− typeof sessionIdHeader === "string"
141− ? sessionIdHeader
142− : Array.isArray(sessionIdHeader)
143− ? sessionIdHeader[0]
144− : undefined;
145−
146− if (!sessionId || !transports[sessionId]) {
147− res.status(400).send("Invalid or missing session ID");
148− return;
149− }
150−
151− await transports[sessionId].handleRequest(req, res);
152− });
153−
154− app.delete("/mcp", async (req: any, res: any) => {
155− const sessionIdHeader = req.headers["mcp-session-id"];
156− const sessionId =
157− typeof sessionIdHeader === "string"
158− ? sessionIdHeader
159− : Array.isArray(sessionIdHeader)
160− ? sessionIdHeader[0]
161− : undefined;
162−
163− if (!sessionId || !transports[sessionId]) {
164− res.status(400).send("Invalid or missing session ID");
165− return;
166− }
167−
168− const transport = transports[sessionId];
169− await transport.handleRequest(req, res, req.body);
170− await transport.close();
171− delete transports[sessionId];
172−
173− if (servers[sessionId]) {
174− await servers[sessionId].close().catch(() => undefined);
175− delete servers[sessionId];
176− }
177− });
178−
179− const listener = await new Promise<import("node:http").Server>((resolve, reject) => {
180− const server = app.listen(input.port ?? 0, host);
181−
182− const onListening = () => {
183− server.off("error", onError);
184− resolve(server);
185− };
186−
187− const onError = (error: Error) => {
188− server.off("listening", onListening);
189− reject(error);
190− };
191−
192− server.once("listening", onListening);
193− server.once("error", onError);
194− });
195−
196− const address = listener.address();
197− if (!address || typeof address === "string") {
198− if (listener.listening) {
199− await new Promise<void>((resolve, reject) => {
200− listener.close((error) => (error ? reject(error) : resolve()));
201− });
202− }
203− throw new Error("Failed to resolve MCP elicitation demo server address");
204− }
205−
206− return {
207− endpoint: `http://${host}:${address.port}/mcp`,
208− close: async () => {
209− for (const transport of Object.values(transports)) {
210− await transport.close().catch(() => undefined);
211− }
212−
213− for (const server of Object.values(servers)) {
214− await server.close().catch(() => undefined);
215− }
216−
217− await new Promise<void>((resolve, reject) => {
218− listener.close((error) => (error ? reject(error) : resolve()));
219− });
220− },
221− };
222−};
examples/mcp-elicitation-demo/tsconfig.json+0−15
@@ -1,15 +0,0 @@
1−{
2− "compilerOptions": {
3− "target": "ES2022",
4− "module": "ESNext",
5− "moduleResolution": "Bundler",
6− "strict": true,
7− "skipLibCheck": true,
8− "noEmit": true,
9− "lib": ["ES2022"],
10− "types": ["bun-types", "node"]
11− },
12− "include": [
13− "src/**/*.ts"
14− ]
15−}
examples/serve-skills-via-mcp/CHANGELOG.md+0−3
@@ -1,3 +0,0 @@
1−# @executor/serve-skills-via-mcp-demo
2−
3−## null
examples/serve-skills-via-mcp/README.md+0−38
@@ -1,38 +0,0 @@
1−# Serve Skills Via MCP
2−
3−This demo shows one practical way to distribute [Agent Skills](https://agentskills.io)
4−over MCP resources.
5−
6−It exposes:
7−
8−- a catalog resource that lists available skill bundles
9−- one manifest resource per skill bundle
10−- one direct `SKILL.md` resource per bundle
11−- a `skill://demo/{skill}/{version}/{+path}` resource template for bundled files
12−
13−The important boundary is that MCP resources only transport the bundle. The host still
14−owns activation logic:
15−
16−1. list resources
17−2. read the catalog or a manifest
18−3. choose a skill
19−4. read that skill's `SKILL.md`
20−5. fetch additional files from the manifest on demand
21−
22−## Run
23−
24−```bash
25−bun run --filter @executor/serve-skills-via-mcp-demo start
26−```
27−
28−The server listens on `http://127.0.0.1:<port>/mcp` and logs the final endpoint to
29−stderr.
30−
31−## Smoke Test
32−
33−```bash
34−bun run --filter @executor/serve-skills-via-mcp-demo smoke
35−```
36−
37−The smoke script starts the server, connects with an MCP client, lists resources,
38−reads a skill manifest, then reads `SKILL.md` and one support file.
examples/serve-skills-via-mcp/package.json+0−21
@@ -1,21 +0,0 @@
1−{
2− "name": "@executor/serve-skills-via-mcp-demo",
3− "private": true,
4− "type": "module",
5− "exports": {
6− ".": "./src/index.ts"
7− },
8− "scripts": {
9− "typecheck": "bunx tsc --noEmit -p tsconfig.json",
10− "start": "bun src/main.ts",
11− "smoke": "bun src/smoke.ts"
12− },
13− "dependencies": {
14− "@modelcontextprotocol/sdk": "^1.26.0"
15− },
16− "devDependencies": {
17− "@types/node": "catalog:",
18− "bun-types": "catalog:"
19− },
20− "version": "0.0.0"
21−}
examples/serve-skills-via-mcp/skills/postgres-incident-triage/SKILL.md+0−28
@@ -1,28 +0,0 @@
1−---
2−name: postgres-incident-triage
3−description: Triage production PostgreSQL incidents involving lock contention, slow queries, or saturation. Use when the user asks for database incident diagnosis or immediate next steps.
4−compatibility: Assumes SQL access to pg_stat_activity and pg_locks.
5−allowed-tools: Bash(psql:*) Read
6−---
7−
8−# Postgres Incident Triage
9−
10−## When to use this skill
11−
12−Use this skill for live operational diagnosis of PostgreSQL incidents, especially when
13−latency spikes or blocked sessions appear.
14−
15−## Workflow
16−
17−1. Read `references/error-codes.md` for common failure patterns.
18−2. Use `scripts/blocked-session-query.sql` to inspect blockers and waiters.
19−3. Separate symptoms from root cause: CPU saturation, I/O pressure, lock chains, or
20− connection pileups.
21−4. Recommend the least-destructive mitigation first.
22−5. If proposing session termination, identify the blocker and expected blast radius.
23−
24−## Output rules
25−
26−- Summarize the current condition in one paragraph.
27−- List the most likely root causes in order.
28−- Provide immediate next commands before longer-term remediation.
examples/serve-skills-via-mcp/skills/postgres-incident-triage/references/error-codes.md+0−6
@@ -1,6 +0,0 @@
1−# Common PostgreSQL Incident Signals
2−
3−- `55P03` often points to lock contention or explicit lock timeouts.
4−- `53300` indicates too many connections.
5−- Long idle-in-transaction sessions are frequently the hidden blocker behind lock trees.
6−- A high count of active queries is not enough to prove saturation; check wait events.
examples/serve-skills-via-mcp/skills/postgres-incident-triage/scripts/blocked-session-query.sql+0−26
@@ -1,26 +0,0 @@
1−select
2− blocked.pid as blocked_pid,
3− blocked.query as blocked_query,
4− blocking.pid as blocking_pid,
5− blocking.query as blocking_query,
6− blocked.wait_event_type,
7− blocked.wait_event
8−from pg_stat_activity blocked
9−join pg_locks blocked_locks
10− on blocked.pid = blocked_locks.pid
11−join pg_locks blocking_locks
12− on blocked_locks.locktype = blocking_locks.locktype
13− and blocked_locks.database is not distinct from blocking_locks.database
14− and blocked_locks.relation is not distinct from blocking_locks.relation
15− and blocked_locks.page is not distinct from blocking_locks.page
16− and blocked_locks.tuple is not distinct from blocking_locks.tuple
17− and blocked_locks.virtualxid is not distinct from blocking_locks.virtualxid
18− and blocked_locks.transactionid is not distinct from blocking_locks.transactionid
19− and blocked_locks.classid is not distinct from blocking_locks.classid
20− and blocked_locks.objid is not distinct from blocking_locks.objid
21− and blocked_locks.objsubid is not distinct from blocking_locks.objsubid
22−join pg_stat_activity blocking
23− on blocking.pid = blocking_locks.pid
24−where not blocked_locks.granted
25− and blocking_locks.granted
26− and blocked.pid <> blocking.pid;
examples/serve-skills-via-mcp/skills/release-notes-writer/SKILL.md+0−28
@@ -1,28 +0,0 @@
1−---
2−name: release-notes-writer
3−description: Draft product release notes from commits, changelogs, and issue summaries. Use when the user asks for release notes, launch notes, or upgrade summaries.
4−compatibility: Requires markdown output and access to bundled templates.
5−allowed-tools: Read Write
6−---
7−
8−# Release Notes Writer
9−
10−## When to use this skill
11−
12−Use this skill when the user wants polished release notes, changelog summaries, or
13−customer-facing upgrade notes.
14−
15−## Workflow
16−
17−1. Read the release template in `assets/release-template.md`.
18−2. Read the voice and structure rules in `references/style-guide.md`.
19−3. Group changes into user-facing themes instead of commit-by-commit narration.
20−4. Prefer concrete impact statements over internal implementation details.
21−5. Call out breaking changes, migrations, and feature flags explicitly.
22−
23−## Output rules
24−
25−- Start with a short overview paragraph.
26−- Include sections only for categories that actually changed.
27−- End with a short rollout or migration note when relevant.
28−- Keep internal ticket IDs out of the final draft unless the user asked for them.
examples/serve-skills-via-mcp/skills/release-notes-writer/assets/release-template.md+0−16
@@ -1,16 +0,0 @@
1−# [Release Name]
2−
3−## Overview
4−[Two to four sentences describing the release in user language.]
5−
6−## New
7−- [New capability]
8−
9−## Improved
10−- [Improvement]
11−
12−## Fixed
13−- [Bug fix]
14−
15−## Upgrade Notes
16−- [Migration or rollout note if needed]
examples/serve-skills-via-mcp/skills/release-notes-writer/references/style-guide.md+0−7
@@ -1,7 +0,0 @@
1−# Release Notes Style Guide
2−
3−- Write for product users first, operators second, engineers last.
4−- Lead with outcomes: faster setup, clearer workflows, lower failure rates.
5−- Replace vague claims like "enhanced performance" with specific behavior changes.
6−- Mention removals and breaking changes directly instead of hiding them in "Improved".
7−- Keep bullets parallel and concrete.
examples/serve-skills-via-mcp/skills/release-notes-writer/scripts/validate-headings.ts+0−10
@@ -1,10 +0,0 @@
1−const requiredHeadings = [
2− "## Overview",
3− "## New",
4− "## Improved",
5− "## Fixed",
6−];
7−
8−for (const heading of requiredHeadings) {
9− console.log(`Expect heading: ${heading}`);
10−}
examples/serve-skills-via-mcp/src/catalog.ts+0−243
@@ -1,243 +0,0 @@
1−import { readdir, readFile, stat } from "node:fs/promises";
2−import { extname, join, posix, relative } from "node:path";
3−import { fileURLToPath } from "node:url";
4−
5−export type SkillFrontmatter = {
6− readonly name: string;
7− readonly description: string;
8− readonly compatibility?: string;
9− readonly license?: string;
10− readonly allowedTools?: string;
11−};
12−
13−export type DistributedSkillFile = {
14− readonly path: string;
15− readonly uri: string;
16− readonly mimeType: string;
17− readonly size: number;
18− readonly role: "instructions" | "script" | "reference" | "asset" | "other";
19−};
20−
21−export type SkillManifest = {
22− readonly kind: "agent-skill-distribution";
23− readonly publisher: string;
24− readonly version: string;
25− readonly skill: SkillFrontmatter;
26− readonly instructionsUri: string;
27− readonly manifestUri: string;
28− readonly fileTemplate: string;
29− readonly files: readonly DistributedSkillFile[];
30−};
31−
32−export type DistributedSkillBundle = {
33− readonly publisher: string;
34− readonly version: string;
35− readonly rootDir: string;
36− readonly skill: SkillFrontmatter;
37− readonly manifestUri: string;
38− readonly instructionsUri: string;
39− readonly fileTemplate: string;
40− readonly files: readonly DistributedSkillFile[];
41− readonly manifest: SkillManifest;
42−};
43−
44−const demoPublisher = "demo";
45−const catalogUri = "skill://catalog/index.json";
46−const fileTemplate = "skill://demo/{skill}/{version}/{+path}";
47−
48−const bundleVersions = {
49− "postgres-incident-triage": "1.1.0",
50− "release-notes-writer": "1.0.0",
51−} as const;
52−
53−const skillsDir = fileURLToPath(new URL("../skills", import.meta.url));
54−
55−const mimeTypeFor = (filePath: string): string => {
56− switch (extname(filePath)) {
57− case ".json":
58− return "application/json";
59− case ".md":
60− return "text/markdown";
61− case ".sql":
62− return "application/sql";
63− case ".ts":
64− return "text/typescript";
65− default:
66− return "text/plain";
67− }
68−};
69−
70−const roleFor = (filePath: string): DistributedSkillFile["role"] => {
71− if (filePath === "SKILL.md") {
72− return "instructions";
73− }
74− if (filePath.startsWith("scripts/")) {
75− return "script";
76− }
77− if (filePath.startsWith("references/")) {
78− return "reference";
79− }
80− if (filePath.startsWith("assets/")) {
81− return "asset";
82− }
83− return "other";
84−};
85−
86−const parseFrontmatter = (content: string): SkillFrontmatter => {
87− const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/u.exec(content);
88− if (!match) {
89− throw new Error("Expected SKILL.md to start with YAML frontmatter");
90− }
91−
92− const fields: Record<string, string> = {};
93− for (const line of match[1].split(/\r?\n/u)) {
94− const trimmed = line.trim();
95− if (trimmed.length === 0 || trimmed.startsWith("#")) {
96− continue;
97− }
98−
99− const entry = /^([A-Za-z0-9-]+):\s*(.+)$/u.exec(trimmed);
100− if (!entry) {
101− continue;
102− }
103−
104− fields[entry[1]] = entry[2];
105− }
106−
107− if (!fields.name || !fields.description) {
108− throw new Error("Expected SKILL.md frontmatter to include name and description");
109− }
110−
111− return {
112− name: fields.name,
113− description: fields.description,
114− compatibility: fields.compatibility,
115− license: fields.license,
116− allowedTools: fields["allowed-tools"],
117− };
118−};
119−
120−const collectFiles = async (rootDir: string): Promise<string[]> => {
121− const output: string[] = [];
122−
123− const visit = async (directory: string) => {
124− const entries = await readdir(directory, { withFileTypes: true });
125− entries.sort((left, right) => left.name.localeCompare(right.name));
126−
127− for (const entry of entries) {
128− const absolutePath = join(directory, entry.name);
129− if (entry.isDirectory()) {
130− await visit(absolutePath);
131− continue;
132− }
133− output.push(posix.join(...relative(rootDir, absolutePath).split("\\").filter(Boolean)));
134− }
135− };
136−
137− await visit(rootDir);
138− return output;
139−};
140−
141−export const getCatalogUri = (): string => catalogUri;
142−
143−export const getFileTemplate = (): string => fileTemplate;
144−
145−export const loadDistributedSkillBundles = async (): Promise<readonly DistributedSkillBundle[]> => {
146− const bundles = await Promise.all(
147− Object.entries(bundleVersions).map(async ([directoryName, version]) => {
148− const rootDir = join(skillsDir, directoryName);
149− const skillContent = await readFile(join(rootDir, "SKILL.md"), "utf8");
150− const skill = parseFrontmatter(skillContent);
151− const files = await collectFiles(rootDir);
152−
153− const distributedFiles = await Promise.all(
154− files.map(async (filePath) => {
155− const absolutePath = join(rootDir, filePath);
156− const fileStats = await stat(absolutePath);
157− return {
158− path: filePath,
159− uri: `skill://${demoPublisher}/${skill.name}/${version}/${filePath}`,
160− mimeType: mimeTypeFor(filePath),
161− size: fileStats.size,
162− role: roleFor(filePath),
163− } satisfies DistributedSkillFile;
164− }),
165− );
166−
167− const manifestUri = `skill://${demoPublisher}/${skill.name}/${version}/manifest.json`;
168− const instructionsUri = `skill://${demoPublisher}/${skill.name}/${version}/SKILL.md`;
169−
170− const manifest: SkillManifest = {
171− kind: "agent-skill-distribution",
172− publisher: demoPublisher,
173− version,
174− skill,
175− instructionsUri,
176− manifestUri,
177− fileTemplate,
178− files: distributedFiles,
179− };
180−
181− return {
182− publisher: demoPublisher,
183− version,
184− rootDir,
185− skill,
186− manifestUri,
187− instructionsUri,
188− fileTemplate,
189− files: distributedFiles,
190− manifest,
191− } satisfies DistributedSkillBundle;
192− }),
193− );
194−
195− return bundles.sort((left, right) => left.skill.name.localeCompare(right.skill.name));
196−};
197−
198−export const renderCatalog = (bundles: readonly DistributedSkillBundle[]): string =>
199− JSON.stringify(
200− {
201− kind: "agent-skill-catalog",
202− distributionMethod: "mcp-resources",
203− catalogUri,
204− fileTemplate,
205− activationGuidance: [
206− "Use this catalog for discovery only.",
207− "Read a skill manifest next to find the concrete SKILL.md URI.",
208− "Load SKILL.md into the model only when the task matches the skill description.",
209− "Fetch support files from the manifest on demand.",
210− ],
211− skills: bundles.map((bundle) => ({
212− name: bundle.skill.name,
213− description: bundle.skill.description,
214− version: bundle.version,
215− manifestUri: bundle.manifestUri,
216− instructionsUri: bundle.instructionsUri,
217− })),
218− },
219− null,
220− 2,
221− );
222−
223−export const findBundleByName = (
224− bundles: readonly DistributedSkillBundle[],
225− skillName: string,
226−): DistributedSkillBundle | undefined =>
227− bundles.find((bundle) => bundle.skill.name === skillName);
228−
229−export const findBundleFile = (
230− bundles: readonly DistributedSkillBundle[],
231− skillName: string,
232− version: string,
233− filePath: string,
234−): DistributedSkillFile | undefined =>
235− bundles
236− .find((bundle) => bundle.skill.name === skillName && bundle.version === version)
237− ?.files.find((file) => file.path === filePath);
238−
239−export const readBundleFileText = async (
240− bundle: DistributedSkillBundle,
241− filePath: string,
242−): Promise<string> =>
243− readFile(join(bundle.rootDir, filePath), "utf8");
examples/serve-skills-via-mcp/src/index.ts+0−4
@@ -1,4 +0,0 @@
1−export {
2− startServeSkillsViaMcpDemoServer,
3− type ServeSkillsViaMcpDemoServer,
4−} from "./server";
examples/serve-skills-via-mcp/src/main.ts+0−20
@@ -1,20 +0,0 @@
1−import { startServeSkillsViaMcpDemoServer } from "./server";
2−
3−const host = process.env.HOST ?? "127.0.0.1";
4−const port = process.env.PORT ? Number(process.env.PORT) : 58507;
5−
6−const server = await startServeSkillsViaMcpDemoServer({ host, port });
7−console.error(`serve-skills-via-mcp listening on ${server.endpoint}`);
8−
9−const shutdown = async () => {
10− await server.close();
11− process.exit(0);
12−};
13−
14−process.once("SIGINT", () => {
15− void shutdown();
16−});
17−
18−process.once("SIGTERM", () => {
19− void shutdown();
20−});
examples/serve-skills-via-mcp/src/server.ts+0−346
@@ -1,346 +0,0 @@
1−import { randomUUID } from "node:crypto";
2−import type { Server as HttpServer } from "node:http";
3−
4−import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
5−import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
6−import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7−
8−import {
9− type DistributedSkillBundle,
10− findBundleByName,
11− findBundleFile,
12− getCatalogUri,
13− getFileTemplate,
14− loadDistributedSkillBundles,
15− readBundleFileText,
16− renderCatalog,
17−} from "./catalog";
18−
19−export type ServeSkillsViaMcpDemoServer = {
20− readonly endpoint: string;
21− readonly close: () => Promise<void>;
22−};
23−
24−const registerSkillResources = (
25− server: McpServer,
26− bundles: readonly DistributedSkillBundle[],
27−) => {
28− server.registerResource(
29− "skill-catalog",
30− getCatalogUri(),
31− {
32− title: "Distributed Agent Skills Catalog",
33− description: "Catalog of skill bundles exposed over MCP resources.",
34− mimeType: "application/json",
35− annotations: {
36− audience: ["assistant", "user"],
37− priority: 0.7,
38− },
39− },
40− async () => ({
41− contents: [
42− {
43− uri: getCatalogUri(),
44− mimeType: "application/json",
45− text: renderCatalog(bundles),
46− },
47− ],
48− }),
49− );
50−
51− for (const bundle of bundles) {
52− server.registerResource(
53− `${bundle.skill.name}-manifest`,
54− bundle.manifestUri,
55− {
56− title: `${bundle.skill.name} manifest`,
57− description: `Distribution manifest for ${bundle.skill.name}.`,
58− mimeType: "application/json",
59− annotations: {
60− audience: ["assistant"],
61− priority: 0.85,
62− },
63− },
64− async () => ({
65− contents: [
66− {
67− uri: bundle.manifestUri,
68− mimeType: "application/json",
69− text: JSON.stringify(bundle.manifest, null, 2),
70− },
71− ],
72− }),
73− );
74−
75− server.registerResource(
76− `${bundle.skill.name}-instructions`,
77− bundle.instructionsUri,
78− {
79− title: `${bundle.skill.name} SKILL.md`,
80− description: bundle.skill.description,
81− mimeType: "text/markdown",
82− annotations: {
83− audience: ["assistant"],
84− priority: 1,
85− },
86− },
87− async () => ({
88− contents: [
89− {
90− uri: bundle.instructionsUri,
91− mimeType: "text/markdown",
92− text: await readBundleFileText(bundle, "SKILL.md"),
93− },
94− ],
95− }),
96− );
97− }
98−
99− server.registerResource(
100− "skill-bundle-file",
101− new ResourceTemplate(getFileTemplate(), {
102− list: undefined,
103− complete: {
104− skill: (value) =>
105− bundles
106− .map((bundle) => bundle.skill.name)
107− .filter((skillName) => skillName.startsWith(value)),
108− version: (value, context) => {
109− const skillName = context?.arguments?.skill;
110− if (!skillName) {
111− return bundles
112− .map((bundle) => bundle.version)
113− .filter((version) => version.startsWith(value));
114− }
115−
116− const bundle = findBundleByName(bundles, skillName);
117− if (!bundle) {
118− return [];
119− }
120−
121− return bundle.version.startsWith(value) ? [bundle.version] : [];
122− },
123− path: (value, context) => {
124− const skillName = context?.arguments?.skill;
125− const version = context?.arguments?.version;
126− if (!skillName || !version) {
127− return [];
128− }
129−
130− const bundle = bundles.find((entry) =>
131− entry.skill.name === skillName && entry.version === version
132− );
133− if (!bundle) {
134− return [];
135− }
136−
137− return bundle.files
138− .map((file) => file.path)
139− .filter((filePath) => filePath.startsWith(value));
140− },
141− },
142− }),
143− {
144− title: "Skill bundle files",
145− description: "Read any file inside a distributed skill bundle.",
146− mimeType: "text/plain",
147− annotations: {
148− audience: ["assistant"],
149− priority: 0.5,
150− },
151− },
152− async (_uri, variables) => {
153− const skillName = typeof variables.skill === "string" ? variables.skill : undefined;
154− const version = typeof variables.version === "string" ? variables.version : undefined;
155− const filePath = typeof variables.path === "string" ? variables.path : undefined;
156−
157− if (!skillName || !version || !filePath) {
158− throw new Error("Expected skill, version, and path variables");
159− }
160−
161− const bundle = bundles.find((entry) =>
162− entry.skill.name === skillName && entry.version === version
163− );
164− const file = findBundleFile(bundles, skillName, version, filePath);
165− if (!bundle || !file) {
166− throw new Error(`Unknown distributed skill file: ${skillName}@${version}/${filePath}`);
167− }
168−
169− return {
170− contents: [
171− {
172− uri: file.uri,
173− mimeType: file.mimeType,
174− text: await readBundleFileText(bundle, filePath),
175− },
176− ],
177− };
178− },
179− );
180−};
181−
182−const createSessionServer = (bundles: readonly DistributedSkillBundle[]): McpServer => {
183− const server = new McpServer(
184− {
185− name: "executor-serve-skills-via-mcp-demo",
186− version: "1.0.0",
187− },
188− {
189− capabilities: {
190− resources: {
191− listChanged: true,
192− },
193− },
194− instructions: [
195− "This server demonstrates one way to distribute Agent Skills over MCP resources.",
196− "Read the catalog and a skill manifest first, then load SKILL.md only when you decide to activate that skill.",
197− ].join(" "),
198− },
199− );
200−
201− registerSkillResources(server, bundles);
202− return server;
203−};
204−
205−const resolveSessionId = (headers: Record<string, string | string[] | undefined>): string | undefined => {
206− const value = headers["mcp-session-id"];
207− if (typeof value === "string") {
208− return value;
209− }
210− if (Array.isArray(value)) {
211− return value[0];
212− }
213− return undefined;
214−};
215−
216−const listen = async (app: ReturnType<typeof createMcpExpressApp>, port: number, host: string) =>
217− new Promise<HttpServer>((resolve, reject) => {
218− const listener = app.listen(port, host);
219−
220− const onListening = () => {
221− listener.off("error", onError);
222− resolve(listener);
223− };
224−
225− const onError = (error: Error) => {
226− listener.off("listening", onListening);
227− reject(error);
228− };
229−
230− listener.once("listening", onListening);
231− listener.once("error", onError);
232− });
233−
234−export const startServeSkillsViaMcpDemoServer = async (input: {
235− readonly host?: string;
236− readonly port?: number;
237−} = {}): Promise<ServeSkillsViaMcpDemoServer> => {
238− const host = input.host ?? "127.0.0.1";
239− const bundles = await loadDistributedSkillBundles();
240− const app = createMcpExpressApp({ host });
241− const transports: Record<string, StreamableHTTPServerTransport> = {};
242− const servers: Record<string, McpServer> = {};
243−
244− app.post("/mcp", async (req: any, res: any) => {
245− const sessionId = resolveSessionId(req.headers);
246−
247− try {
248− let transport: StreamableHTTPServerTransport;
249−
250− if (sessionId && transports[sessionId]) {
251− transport = transports[sessionId];
252− } else {
253− transport = new StreamableHTTPServerTransport({
254− sessionIdGenerator: () => randomUUID(),
255− onsessioninitialized: (newSessionId) => {
256− transports[newSessionId] = transport;
257− },
258− });
259−
260− transport.onclose = () => {
261− const closedSessionId = transport.sessionId;
262− if (closedSessionId && transports[closedSessionId]) {
263− delete transports[closedSessionId];
264− }
265− if (closedSessionId && servers[closedSessionId]) {
266− void servers[closedSessionId].close().catch(() => undefined);
267− delete servers[closedSessionId];
268− }
269− };
270−
271− const server = createSessionServer(bundles);
272− await server.connect(transport);
273− if (transport.sessionId) {
274− servers[transport.sessionId] = server;
275− }
276− }
277−
278− await transport.handleRequest(req, res, req.body);
279− } catch (error) {
280− if (!res.headersSent) {
281− res.status(500).json({
282− jsonrpc: "2.0",
283− error: {
284− code: -32603,
285− message: error instanceof Error ? error.message : "Internal server error",
286− },
287− id: null,
288− });
289− }
290− }
291− });
292−
293− app.get("/mcp", async (req: any, res: any) => {
294− const sessionId = resolveSessionId(req.headers);
295− if (!sessionId || !transports[sessionId]) {
296− res.status(400).send("Invalid or missing session ID");
297− return;
298− }
299−
300− await transports[sessionId].handleRequest(req, res);
301− });
302−
303− app.delete("/mcp", async (req: any, res: any) => {
304− const sessionId = resolveSessionId(req.headers);
305− if (!sessionId || !transports[sessionId]) {
306− res.status(400).send("Invalid or missing session ID");
307− return;
308− }
309−
310− const transport = transports[sessionId];
311− await transport.handleRequest(req, res, req.body);
312− await transport.close();
313− delete transports[sessionId];
314−
315− if (servers[sessionId]) {
316− await servers[sessionId].close().catch(() => undefined);
317− delete servers[sessionId];
318− }
319− });
320−
321− const listener = await listen(app, input.port ?? 0, host);
322− const address = listener.address();
323− if (!address || typeof address === "string") {
324− await new Promise<void>((resolve, reject) => {
325− listener.close((error) => (error ? reject(error) : resolve()));
326− });
327− throw new Error("Failed to resolve serve-skills-via-mcp demo address");
328− }
329−
330− return {
331− endpoint: `http://${host}:${address.port}/mcp`,
332− close: async () => {
333− for (const transport of Object.values(transports)) {
334− await transport.close().catch(() => undefined);
335− }
336−
337− for (const server of Object.values(servers)) {
338− await server.close().catch(() => undefined);
339− }
340−
341− await new Promise<void>((resolve, reject) => {
342− listener.close((error) => (error ? reject(error) : resolve()));
343− });
344− },
345− };
346−};
examples/serve-skills-via-mcp/src/smoke.ts+0−67
@@ -1,67 +0,0 @@
1−import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2−import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3−
4−import { startServeSkillsViaMcpDemoServer } from "./server";
5−
6−const server = await startServeSkillsViaMcpDemoServer();
7−const client = new Client({
8− name: "serve-skills-via-mcp-smoke",
9− version: "1.0.0",
10−});
11−const transport = new StreamableHTTPClientTransport(new URL(server.endpoint));
12−
13−try {
14− await client.connect(transport);
15−
16− const resources = await client.listResources();
17− console.log(`resources: ${resources.resources.length}`);
18− for (const resource of resources.resources) {
19− console.log(`- ${resource.uri}`);
20− }
21−
22− const templates = await client.listResourceTemplates();
23− console.log(`resourceTemplates: ${templates.resourceTemplates.length}`);
24− for (const template of templates.resourceTemplates) {
25− console.log(`- ${template.uriTemplate}`);
26− }
27−
28− const catalog = await client.readResource({ uri: "skill://catalog/index.json" });
29− const catalogText = "text" in catalog.contents[0]! ? catalog.contents[0]!.text : "";
30− const parsedCatalog = JSON.parse(catalogText) as {
31− readonly skills: ReadonlyArray<{
32− readonly name: string;
33− readonly manifestUri: string;
34− readonly instructionsUri: string;
35− }>;
36− };
37−
38− const selectedSkill = parsedCatalog.skills[0]!;
39− console.log(`selectedSkill: ${selectedSkill.name}`);
40−
41− const manifest = await client.readResource({ uri: selectedSkill.manifestUri });
42− const manifestText = "text" in manifest.contents[0]! ? manifest.contents[0]!.text : "";
43− const parsedManifest = JSON.parse(manifestText) as {
44− readonly instructionsUri: string;
45− readonly files: ReadonlyArray<{
46− readonly path: string;
47− readonly uri: string;
48− readonly role: string;
49− }>;
50− };
51−
52− const instructions = await client.readResource({ uri: parsedManifest.instructionsUri });
53− const instructionsText = "text" in instructions.contents[0]! ? instructions.contents[0]!.text : "";
54− console.log(`instructionsPreview: ${instructionsText.split("\n").slice(0, 6).join("\n")}`);
55−
56− const supportFile = parsedManifest.files.find((file) => file.role !== "instructions");
57− if (supportFile) {
58− const support = await client.readResource({ uri: supportFile.uri });
59− const supportText = "text" in support.contents[0]! ? support.contents[0]!.text : "";
60− console.log(`supportFile: ${supportFile.path}`);
61− console.log(`supportPreview: ${supportText.split("\n").slice(0, 4).join("\n")}`);
62− }
63−} finally {
64− await client.close().catch(() => undefined);
65− await transport.close().catch(() => undefined);
66− await server.close().catch(() => undefined);
67−}
examples/serve-skills-via-mcp/tsconfig.json+0−15
@@ -1,15 +0,0 @@
1−{
2− "compilerOptions": {
3− "target": "ES2022",
4− "module": "ESNext",
5− "moduleResolution": "Bundler",
6− "strict": true,
7− "skipLibCheck": true,
8− "noEmit": true,
9− "lib": ["ES2022"],
10− "types": ["bun-types", "node"]
11− },
12− "include": [
13− "src/**/*.ts"
14− ]
15−}
examples/sqlite-sdk-consumer/.gitignore+0−1
@@ -1 +0,0 @@
1−.data/
examples/sqlite-sdk-consumer/README.md+0−41
@@ -1,41 +0,0 @@
1−# SQLite SDK Consumer Example
2−
3−This example shows how an embedder can implement a custom SQLite-backed adapter
4−using the public Promise-facing `@executor/platform-sdk`.
5−
6−The adapter is intentionally simple:
7−
8−- installation state is stored in SQLite
9−- scope config and scope state are stored in SQLite
10−- source artifacts are stored in SQLite
11−- executor state is stored in SQLite
12−- secret material is stored in SQLite
13−
14−There is no direct `effect` usage in the example.
15−
16−## Run
17−
18−```sh
19−bun run --cwd examples/sqlite-sdk-consumer start
20−```
21−
22−To keep the demo ephemeral:
23−
24−```sh
25−DATABASE_PATH=:memory: bun run --cwd examples/sqlite-sdk-consumer start
26−```
27−
28−## Shape
29−
30−The important bit is the consumer-facing construction:
31−
32−```ts
33−import { createExecutor } from "@executor/platform-sdk";
34−import { createSqliteExecutorBackend } from "@executor/sqlite-sdk-consumer-example";
35−
36−const executor = await createExecutor({
37− backend: createSqliteExecutorBackend({
38− databasePath: "./executor.sqlite",
39− }),
40−});
41−```
examples/sqlite-sdk-consumer/package.json+0−22
@@ -1,22 +0,0 @@
1−{
2− "name": "@executor/sqlite-sdk-consumer-example",
3− "private": true,
4− "type": "module",
5− "exports": {
6− ".": "./src/index.ts"
7− },
8− "scripts": {
9− "typecheck": "bunx tsc --noEmit -p tsconfig.json",
10− "start": "bun src/main.ts"
11− },
12− "dependencies": {
13− "@executor/platform-sdk": "workspace:*",
14− "@executor/source-core": "workspace:*",
15− "drizzle-orm": "^0.44.5"
16− },
17− "devDependencies": {
18− "@types/node": "catalog:",
19− "bun-types": "catalog:"
20− },
21− "version": "0.0.0"
22−}
examples/sqlite-sdk-consumer/src/index.ts+0−4
@@ -1,4 +0,0 @@
1−export {
2− createSqliteExecutorBackend,
3− type CreateSqliteExecutorBackendOptions,
4−} from "./sqlite-backend";
examples/sqlite-sdk-consumer/src/main.ts+0−54
@@ -1,54 +0,0 @@
1−import { createExecutor } from "@executor/platform-sdk";
2−
3−import { createSqliteExecutorBackend } from "./sqlite-backend";
4−
5−const databasePath = process.env.DATABASE_PATH
6− ?? new URL("../.data/executor.sqlite", import.meta.url).pathname;
7−
8−const executor = await createExecutor({
9− backend: createSqliteExecutorBackend({
10− databasePath,
11− }),
12−});
13−
14−try {
15− const installation = await executor.local.installation();
16−
17− const policy = await executor.policies.create({
18− resourcePattern: "math.add",
19− effect: "allow",
20− approvalMode: "auto",
21− });
22−
23− const secret = await executor.secrets.create({
24− name: "demo-api-key",
25− value: "secret-value",
26− });
27−
28− const execution = await executor.executions.create({
29− code: "return 20 + 22;",
30− });
31−
32− const sources = await executor.sources.list();
33− const secrets = await executor.secrets.list();
34− const policies = await executor.policies.list();
35−
36− console.log(JSON.stringify({
37− databasePath,
38− installation,
39− createdPolicyId: policy.id,
40− createdSecretId: secret.id,
41− execution: {
42− id: execution.execution.id,
43− status: execution.execution.status,
44− resultJson: execution.execution.resultJson,
45− },
46− counts: {
47− sources: sources.length,
48− secrets: secrets.length,
49− policies: policies.length,
50− },
51− }, null, 2));
52−} finally {
53− await executor.close();
54−}
examples/sqlite-sdk-consumer/src/sqlite-backend.ts+0−733
@@ -1,733 +0,0 @@
1−import { createHash, randomUUID } from "node:crypto";
2−import { mkdirSync } from "node:fs";
3−import { dirname, resolve as resolvePath } from "node:path";
4−
5−import { Database } from "bun:sqlite";
6−import { and, eq } from "drizzle-orm";
7−import { drizzle } from "drizzle-orm/bun-sqlite";
8−import {
9− integer,
10− sqliteTable,
11− text,
12−} from "drizzle-orm/sqlite-core";
13−
14−import {
15− createExecutorBackend,
16− type ExecutorBackend,
17− type ExecutorBackendRepositories,
18− type ExecutorWorkspaceConfigRepository,
19− type ExecutorWorkspaceStateRepository,
20− type ExecutorWorkspaceSourceArtifactRepository,
21−} from "@executor/platform-sdk";
22−import type {
23− Execution,
24− ExecutionInteraction,
25− ExecutionStep,
26− ExecutorScopeConfig,
27− LocalInstallation,
28− SecretMaterial,
29− SecretRef,
30− SecretStore,
31−} from "@executor/platform-sdk/schema";
32−import {
33− ScopeIdSchema,
34− SecretMaterialIdSchema,
35− SourceCatalogIdSchema,
36− SourceCatalogRevisionIdSchema,
37−} from "@executor/platform-sdk/schema";
38−import type {
39− SecretMaterialStoredDataRecord,
40−} from "@executor/platform-sdk/runtime";
41−import {
42− contentHash,
43− snapshotFromSourceCatalogSyncResult,
44−} from "@executor/source-core";
45−
46−export type CreateSqliteExecutorBackendOptions = {
47− databasePath?: string;
48− scopeId?: string;
49− actorScopeId?: string;
50−};
51−
52−type ScopeConfig = Awaited<ReturnType<ExecutorWorkspaceConfigRepository["load"]>>;
53−type ScopeState = Awaited<ReturnType<ExecutorWorkspaceStateRepository["load"]>>;
54−type SourceArtifact =
55− ReturnType<ExecutorWorkspaceSourceArtifactRepository["build"]>;
56−type SourceArtifactBuildInput = Parameters<
57− ExecutorWorkspaceSourceArtifactRepository["build"]
58−>[0];
59−
60−type SecretMaterialSummary = {
61− id: string;
62− storeId: string;
63− name: string | null;
64− purpose: string;
65− createdAt: number;
66− updatedAt: number;
67−};
68−
69−type SqliteSecretStoredData = {
70− value: string;
71−};
72−
73−const SQLITE_SECRET_STORE_KIND = "sqlite";
74−const SQLITE_SECRET_STORE_ID = "sts_sqlite";
75−
76−const installations = sqliteTable("installations", {
77− key: text("key").primaryKey(),
78− scopeId: text("scope_id").notNull(),
79− actorScopeId: text("actor_scope_id").notNull(),
80−});
81−
82−const scopeConfigs = sqliteTable("scope_configs", {
83− key: text("key").primaryKey(),
84− projectConfigJson: text("project_config_json").notNull(),
85−});
86−
87−const scopeStates = sqliteTable("scope_states", {
88− key: text("key").primaryKey(),
89− stateJson: text("state_json").notNull(),
90−});
91−
92−const sourceArtifacts = sqliteTable("source_artifacts", {
93− sourceId: text("source_id").primaryKey(),
94− artifactJson: text("artifact_json").notNull(),
95−});
96−
97−const secretMaterials = sqliteTable("secret_materials", {
98− id: text("id").primaryKey(),
99− storeId: text("store_id").notNull(),
100− name: text("name"),
101− purpose: text("purpose").notNull(),
102− createdAt: integer("created_at").notNull(),
103− updatedAt: integer("updated_at").notNull(),
104− json: text("json").notNull(),
105−});
106−
107−const secretMaterialStoredData = sqliteTable("secret_material_stored_data", {
108− secretId: text("secret_id").primaryKey(),
109− json: text("json").notNull(),
110−});
111−
112−const executions = sqliteTable("executions", {
113− id: text("id").primaryKey(),
114− scopeId: text("scope_id").notNull(),
115− json: text("json").notNull(),
116−});
117−
118−const executionInteractions = sqliteTable("execution_interactions", {
119− id: text("id").primaryKey(),
120− executionId: text("execution_id").notNull(),
121− status: text("status").notNull(),
122− json: text("json").notNull(),
123−});
124−
125−const executionSteps = sqliteTable("execution_steps", {
126− id: text("id").primaryKey(),
127− executionId: text("execution_id").notNull(),
128− sequence: integer("sequence").notNull(),
129− json: text("json").notNull(),
130−});
131−
132−const makeHash = (value: string): string =>
133− createHash("sha256").update(value).digest("hex").slice(0, 24);
134−
135−const parseJson = <T>(value: string): T => JSON.parse(value) as T;
136−
137−const createSourceArtifact = (input: SourceArtifactBuildInput): SourceArtifact => {
138− const snapshot = snapshotFromSourceCatalogSyncResult(input.syncResult);
139− const sourceConfigJson = JSON.stringify({
140− kind: input.source.kind,
141− namespace: input.source.namespace,
142− name: input.source.name,
143− enabled: input.source.enabled,
144− });
145− const importMetadataJson = JSON.stringify(snapshot.import);
146− const catalogId = SourceCatalogIdSchema.make(`src_catalog_${makeHash(sourceConfigJson)}`);
147− const revisionId = SourceCatalogRevisionIdSchema.make(
148− `src_catalog_rev_${makeHash(sourceConfigJson)}`,
149− );
150−
151− return {
152− version: 4,
153− sourceId: input.source.id,
154− catalogId,
155− generatedAt: Date.now(),
156− revision: {
157− id: revisionId,
158− catalogId,
159− revisionNumber: 1,
160− sourceConfigJson,
161− importMetadataJson,
162− importMetadataHash: contentHash(importMetadataJson),
163− snapshotHash: contentHash(JSON.stringify(snapshot)),
164− createdAt: input.source.createdAt,
165− updatedAt: input.source.updatedAt,
166− },
167− snapshot,
168− };
169−};
170−
171−const defaultScopeState = (): ScopeState => ({
172− version: 1,
173− sources: {},
174− policies: {},
175−});
176−
177−const createInstallation = (
178− options: CreateSqliteExecutorBackendOptions,
179−): LocalInstallation => {
180− const scopeId = ScopeIdSchema.make(options.scopeId ?? "scope_sqlite_example");
181− const actorScopeId = ScopeIdSchema.make(
182− options.actorScopeId ?? "account_sqlite_example",
183− );
184−
185− return {
186− scopeId,
187− actorScopeId,
188− };
189−};
190−
191−const openSqliteStore = (databasePath: string) => {
192− if (databasePath !== ":memory:") {
193− mkdirSync(dirname(databasePath), { recursive: true });
194− }
195−
196− const sqlite = new Database(databasePath, { create: true, strict: true });
197− const db = drizzle(sqlite);
198−
199− sqlite.exec(`
200− CREATE TABLE IF NOT EXISTS installations (
201− key TEXT PRIMARY KEY NOT NULL,
202− scope_id TEXT NOT NULL,
203− actor_scope_id TEXT NOT NULL
204− );
205−
206− CREATE TABLE IF NOT EXISTS scope_configs (
207− key TEXT PRIMARY KEY NOT NULL,
208− project_config_json TEXT NOT NULL
209− );
210−
211− CREATE TABLE IF NOT EXISTS scope_states (
212− key TEXT PRIMARY KEY NOT NULL,
213− state_json TEXT NOT NULL
214− );
215−
216− CREATE TABLE IF NOT EXISTS source_artifacts (
217− source_id TEXT PRIMARY KEY NOT NULL,
218− artifact_json TEXT NOT NULL
219− );
220−
221− CREATE TABLE IF NOT EXISTS secret_materials (
222− id TEXT PRIMARY KEY NOT NULL,
223− store_id TEXT NOT NULL,
224− name TEXT,
225− purpose TEXT NOT NULL,
226− created_at INTEGER NOT NULL,
227− updated_at INTEGER NOT NULL,
228− json TEXT NOT NULL
229− );
230−
231− CREATE TABLE IF NOT EXISTS secret_material_stored_data (
232− secret_id TEXT PRIMARY KEY NOT NULL,
233− json TEXT NOT NULL
234− );
235−
236− CREATE TABLE IF NOT EXISTS executions (
237− id TEXT PRIMARY KEY NOT NULL,
238− scope_id TEXT NOT NULL,
239− json TEXT NOT NULL
240− );
241−
242− CREATE TABLE IF NOT EXISTS execution_interactions (
243− id TEXT PRIMARY KEY NOT NULL,
244− execution_id TEXT NOT NULL,
245− status TEXT NOT NULL,
246− json TEXT NOT NULL
247− );
248−
249− CREATE TABLE IF NOT EXISTS execution_steps (
250− id TEXT PRIMARY KEY NOT NULL,
251− execution_id TEXT NOT NULL,
252− sequence INTEGER NOT NULL,
253− json TEXT NOT NULL
254− );
255− `);
256−
257− return {
258− sqlite,
259− db,
260− close: () => {
261− sqlite.close();
262− },
263− };
264−};
265−
266−type SqliteStore = ReturnType<typeof openSqliteStore>;
267−
268−const createStorageDomains = (
269− store: SqliteStore,
270− installation: LocalInstallation,
271−) => ({
272− secrets: {
273− secretStores: {
274− getById: (id: SecretStore["id"]) =>
275− id === SQLITE_SECRET_STORE_ID
276− ? {
277− id: SQLITE_SECRET_STORE_ID as SecretStore["id"],
278− scopeId: installation.scopeId,
279− kind: SQLITE_SECRET_STORE_KIND,
280− name: "SQLite Store",
281− status: "connected" as const,
282− enabled: true,
283− createdAt: 0,
284− updatedAt: 0,
285− }
286− : null,
287− listAll: () => [{
288− id: SQLITE_SECRET_STORE_ID,
289− scopeId: installation.scopeId,
290− kind: SQLITE_SECRET_STORE_KIND,
291− name: "SQLite Store",
292− status: "connected",
293− enabled: true,
294− createdAt: 0,
295− updatedAt: 0,
296− }],
297− upsert: (_secretStore: SecretStore) => {},
298− updateById: (_id: SecretStore["id"], _update: Partial<Pick<SecretStore, "name" | "status" | "enabled">>) => null,
299− removeById: (_id: SecretStore["id"]) => false,
300− },
301− getById: (id: SecretMaterial["id"]) => {
302− const row = store.db.select().from(secretMaterials).where(eq(secretMaterials.id, id)).get();
303− return row ? parseJson<SecretMaterial>(row.json) : null;
304− },
305− listAll: (): readonly SecretMaterialSummary[] =>
306− store.db.select().from(secretMaterials).all().map((row) => ({
307− id: row.id,
308− storeId: row.storeId,
309− name: row.name,
310− purpose: row.purpose,
311− createdAt: row.createdAt,
312− updatedAt: row.updatedAt,
313− })),
314− upsert: (material: SecretMaterial) =>
315− store.db.insert(secretMaterials).values({
316− id: material.id,
317− storeId: material.storeId,
318− name: material.name,
319− purpose: material.purpose,
320− createdAt: material.createdAt,
321− updatedAt: material.updatedAt,
322− json: JSON.stringify(material),
323− }).onConflictDoUpdate({
324− target: secretMaterials.id,
325− set: {
326− storeId: material.storeId,
327− name: material.name,
328− purpose: material.purpose,
329− createdAt: material.createdAt,
330− updatedAt: material.updatedAt,
331− json: JSON.stringify(material),
332− },
333− }).run(),
334− updateById: (
335− id: SecretMaterial["id"],
336− update: { name?: string | null },
337− ) => {
338− const row = store.db.select().from(secretMaterials).where(eq(secretMaterials.id, id)).get();
339− if (!row) return null;
340− const current = parseJson<SecretMaterial>(row.json);
341− const next = {
342− ...current,
343− name: update.name === undefined ? current.name : update.name,
344− updatedAt: Date.now(),
345− };
346− store.db.update(secretMaterials).set({
347− storeId: next.storeId,
348− name: next.name,
349− purpose: next.purpose,
350− createdAt: next.createdAt,
351− updatedAt: next.updatedAt,
352− json: JSON.stringify(next),
353− }).where(eq(secretMaterials.id, id)).run();
354− return {
355− id: next.id,
356− storeId: next.storeId,
357− name: next.name,
358− purpose: next.purpose,
359− createdAt: next.createdAt,
360− updatedAt: next.updatedAt,
361− } satisfies SecretMaterialSummary;
362− },
363− removeById: (id: SecretMaterial["id"]) => {
364− const row = store.db.select({ id: secretMaterials.id }).from(secretMaterials).where(
365− eq(secretMaterials.id, id),
366− ).get();
367− if (!row) return false;
368− store.db.delete(secretMaterials).where(eq(secretMaterials.id, id)).run();
369− return true;
370− },
371− secretMaterialStoredData: {
372− getBySecretId: (secretId: SecretMaterial["id"]) => {
373− const row = store.db.select().from(secretMaterialStoredData).where(
374− eq(secretMaterialStoredData.secretId, secretId),
375− ).get();
376− return row
377− ? {
378− secretId,
379− data: parseJson<SqliteSecretStoredData>(row.json),
380− }
381− : null;
382− },
383− upsert: (record: SecretMaterialStoredDataRecord) => {
384− store.db.insert(secretMaterialStoredData).values({
385− secretId: record.secretId,
386− json: JSON.stringify(record.data),
387− }).onConflictDoUpdate({
388− target: secretMaterialStoredData.secretId,
389− set: {
390− json: JSON.stringify(record.data),
391− },
392− }).run();
393− },
394− removeBySecretId: (secretId: SecretMaterial["id"]) => {
395− const row = store.db.select({ secretId: secretMaterialStoredData.secretId }).from(
396− secretMaterialStoredData,
397− ).where(eq(secretMaterialStoredData.secretId, secretId)).get();
398− if (!row) return false;
399− store.db.delete(secretMaterialStoredData).where(
400− eq(secretMaterialStoredData.secretId, secretId),
401− ).run();
402− return true;
403− },
404− },
405− },
406− executions: {
407− runs: {
408− listByScope: (scopeId: Execution["scopeId"]) =>
409− store.db.select().from(executions).where(
410− eq(executions.scopeId, scopeId),
411− ).all()
412− .map((row) => parseJson<Execution>(row.json))
413− .sort((left, right) => right.createdAt - left.createdAt),
414− getById: (executionId: Execution["id"]) => {
415− const row = store.db.select().from(executions).where(eq(executions.id, executionId)).get();
416− return row ? parseJson<Execution>(row.json) : null;
417− },
418− getByScopeAndId: (
419− scopeId: Execution["scopeId"],
420− executionId: Execution["id"],
421− ) => {
422− const row = store.db.select().from(executions).where(
423− and(eq(executions.scopeId, scopeId), eq(executions.id, executionId)),
424− ).get();
425− return row ? parseJson<Execution>(row.json) : null;
426− },
427− insert: (execution: Execution) =>
428− store.db.insert(executions).values({
429− id: execution.id,
430− scopeId: execution.scopeId,
431− json: JSON.stringify(execution),
432− }).run(),
433− update: (
434− executionId: Execution["id"],
435− patch: Partial<Omit<Execution, "id" | "scopeId" | "createdByScopeId" | "createdAt">>,
436− ) => {
437− const row = store.db.select().from(executions).where(eq(executions.id, executionId)).get();
438− if (!row) return null;
439− const next = { ...parseJson<Execution>(row.json), ...patch };
440− store.db.update(executions).set({
441− scopeId: next.scopeId,
442− json: JSON.stringify(next),
443− }).where(eq(executions.id, executionId)).run();
444− return next;
445− },
446− },
447− interactions: {
448− getById: (interactionId: ExecutionInteraction["id"]) => {
449− const row = store.db.select().from(executionInteractions).where(
450− eq(executionInteractions.id, interactionId),
451− ).get();
452− return row ? parseJson<ExecutionInteraction>(row.json) : null;
453− },
454− listByExecutionId: (executionId: ExecutionInteraction["executionId"]) =>
455− store.db.select().from(executionInteractions).where(
456− eq(executionInteractions.executionId, executionId),
457− ).all().map((row) => parseJson<ExecutionInteraction>(row.json)),
458− getPendingByExecutionId: (executionId: ExecutionInteraction["executionId"]) => {
459− const row = store.db.select().from(executionInteractions).where(
460− and(
461− eq(executionInteractions.executionId, executionId),
462− eq(executionInteractions.status, "pending"),
463− ),
464− ).get();
465− return row ? parseJson<ExecutionInteraction>(row.json) : null;
466− },
467− insert: (interaction: ExecutionInteraction) =>
468− store.db.insert(executionInteractions).values({
469− id: interaction.id,
470− executionId: interaction.executionId,
471− status: interaction.status,
472− json: JSON.stringify(interaction),
473− }).run(),
474− update: (
475− interactionId: ExecutionInteraction["id"],
476− patch: Partial<Omit<ExecutionInteraction, "id" | "executionId" | "createdAt">>,
477− ) => {
478− const row = store.db.select().from(executionInteractions).where(
479− eq(executionInteractions.id, interactionId),
480− ).get();
481− if (!row) return null;
482− const next = { ...parseJson<ExecutionInteraction>(row.json), ...patch };
483− store.db.update(executionInteractions).set({
484− executionId: next.executionId,
485− status: next.status,
486− json: JSON.stringify(next),
487− }).where(eq(executionInteractions.id, interactionId)).run();
488− return next;
489− },
490− },
491− steps: {
492− getByExecutionAndSequence: (
493− executionId: ExecutionStep["executionId"],
494− sequence: ExecutionStep["sequence"],
495− ) => {
496− const row = store.db.select().from(executionSteps).where(
497− and(
498− eq(executionSteps.executionId, executionId),
499− eq(executionSteps.sequence, sequence),
500− ),
501− ).get();
502− return row ? parseJson<ExecutionStep>(row.json) : null;
503− },
504− listByExecutionId: (executionId: ExecutionStep["executionId"]) =>
505− store.db.select().from(executionSteps).where(
506− eq(executionSteps.executionId, executionId),
507− ).orderBy(executionSteps.sequence).all().map((row) => parseJson<ExecutionStep>(row.json)),
508− insert: (step: ExecutionStep) =>
509− store.db.insert(executionSteps).values({
510− id: step.id,
511− executionId: step.executionId,
512− sequence: step.sequence,
513− json: JSON.stringify(step),
514− }).run(),
515− deleteByExecutionId: (executionId: ExecutionStep["executionId"]) => {
516− store.db.delete(executionSteps).where(eq(executionSteps.executionId, executionId)).run();
517− },
518− updateByExecutionAndSequence: (
519− executionId: ExecutionStep["executionId"],
520− sequence: ExecutionStep["sequence"],
521− patch: Partial<Omit<ExecutionStep, "id" | "executionId" | "sequence" | "createdAt">>,
522− ) => {
523− const row = store.db.select().from(executionSteps).where(
524− and(
525− eq(executionSteps.executionId, executionId),
526− eq(executionSteps.sequence, sequence),
527− ),
528− ).get();
529− if (!row) return null;
530− const next = { ...parseJson<ExecutionStep>(row.json), ...patch };
531− store.db.update(executionSteps).set({
532− id: next.id,
533− executionId: next.executionId,
534− sequence: next.sequence,
535− json: JSON.stringify(next),
536− }).where(eq(executionSteps.id, row.id)).run();
537− return next;
538− },
539− },
540− },
541−});
542−
543−export const createSqliteExecutorBackend = (
544− options: CreateSqliteExecutorBackendOptions = {},
545−): ExecutorBackend => {
546− const databasePath = options.databasePath && options.databasePath !== ":memory:"
547− ? resolvePath(options.databasePath)
548− : (options.databasePath ?? ":memory:");
549−
550− return createExecutorBackend({
551− loadRepositories: () => {
552− const store = openSqliteStore(databasePath);
553− const installation = (() => {
554− const row = store.db.select().from(installations).where(eq(installations.key, "active")).get();
555− return row
556− ? {
557− scopeId: row.scopeId as LocalInstallation["scopeId"],
558− actorScopeId: row.actorScopeId as LocalInstallation["actorScopeId"],
559− }
560− : createInstallation(options);
561− })();
562− const { secrets, executions } = createStorageDomains(store, installation);
563−
564− return {
565− scope: {
566− metadata: {
567− kind: "sqlite",
568− databasePath,
569− },
570− },
571− installation: {
572− load: () => {
573− return installation;
574− },
575− getOrProvision: () => {
576− store.db.insert(installations).values({
577− key: "active",
578− scopeId: installation.scopeId,
579− actorScopeId: installation.actorScopeId,
580− }).onConflictDoUpdate({
581− target: installations.key,
582− set: {
583− scopeId: installation.scopeId,
584− actorScopeId: installation.actorScopeId,
585− },
586− }).run();
587− return installation;
588− },
589− },
590− workspace: {
591− config: {
592− load: () => {
593− const row = store.db.select().from(scopeConfigs).where(eq(scopeConfigs.key, "project")).get();
594− const projectConfig = row
595− ? parseJson<ExecutorScopeConfig>(row.projectConfigJson)
596− : {};
597− return {
598− config: projectConfig,
599− homeConfig: null,
600− projectConfig,
601− } satisfies ScopeConfig;
602− },
603− writeProject: (config) => {
604− store.db.insert(scopeConfigs).values({
605− key: "project",
606− projectConfigJson: JSON.stringify(config),
607− }).onConflictDoUpdate({
608− target: scopeConfigs.key,
609− set: { projectConfigJson: JSON.stringify(config) },
610− }).run();
611− },
612− },
613− state: {
614− load: () => {

119 more lines aren’t shown here.

examples/sqlite-sdk-consumer/tsconfig.json+0−15

This diff is large: its 16 lines aren’t shown here.

knip.json+0−63

This diff is large: its 64 lines aren’t shown here.

opencode.json+0−17

This diff is large: its 18 lines aren’t shown here.

package.json+48−23

This diff is large: its 100 lines aren’t shown here.

packages/clients/react/CHANGELOG.md+0−7

This diff is large: its 8 lines aren’t shown here.

packages/clients/react/components.json+0−21

This diff is large: its 22 lines aren’t shown here.

packages/clients/react/package.json+13−39

This diff is large: its 67 lines aren’t shown here.

packages/clients/react/src/atoms.ts+78−0

This diff is large: its 79 lines aren’t shown here.

packages/clients/react/src/base-url.ts+12−0

This diff is large: its 13 lines aren’t shown here.

packages/clients/react/src/client.ts+20−0

This diff is large: its 21 lines aren’t shown here.

packages/clients/react/src/components/secret-reference-field.tsx+0−444

This diff is large: its 445 lines aren’t shown here.

packages/clients/react/src/core/api-atoms.ts+0−210

This diff is large: its 211 lines aren’t shown here.

packages/clients/react/src/core/base-url.ts+0−12

This diff is large: its 13 lines aren’t shown here.

packages/clients/react/src/core/http-client.ts+0−73

This diff is large: its 74 lines aren’t shown here.

packages/clients/react/src/core/loadable.ts+0−61

This diff is large: its 62 lines aren’t shown here.

packages/clients/react/src/core/reactivity.ts+0−77

This diff is large: its 78 lines aren’t shown here.

packages/clients/react/src/core/types.ts+0−16

This diff is large: its 17 lines aren’t shown here.

packages/clients/react/src/core/workspace.ts+0−62

This diff is large: its 63 lines aren’t shown here.

packages/clients/react/src/hooks/executions.ts+0−46

This diff is large: its 47 lines aren’t shown here.

packages/clients/react/src/hooks/local.ts+0−21

This diff is large: its 22 lines aren’t shown here.

packages/clients/react/src/hooks/mutations.ts+0−44

This diff is large: its 45 lines aren’t shown here.

packages/clients/react/src/hooks/policies.ts+0−135

This diff is large: its 136 lines aren’t shown here.

packages/clients/react/src/hooks/secrets.ts+0−153

This diff is large: its 154 lines aren’t shown here.

packages/clients/react/src/hooks/sources.ts+0−156

This diff is large: its 157 lines aren’t shown here.

packages/clients/react/src/index.test.tsx+0−428

This diff is large: its 429 lines aren’t shown here.

packages/clients/react/src/index.ts+42−92

This diff is large: its 147 lines aren’t shown here.

packages/clients/react/src/plugins/components/code-block.tsx+0−107

This diff is large: its 108 lines aren’t shown here.

packages/clients/react/src/plugins/components/document-panel.tsx+0−30

This diff is large: its 31 lines aren’t shown here.

packages/clients/react/src/plugins/components/icons.tsx+0−90

This diff is large: its 91 lines aren’t shown here.

packages/clients/react/src/plugins/components/loadable.tsx+0−51

This diff is large: its 52 lines aren’t shown here.

packages/clients/react/src/plugins/components/markdown.tsx+0−41

This diff is large: its 42 lines aren’t shown here.

packages/clients/react/src/plugins/components/source-tool-explorer-search.ts+0−24

This diff is large: its 25 lines aren’t shown here.

packages/clients/react/src/plugins/components/source-tool-explorer.tsx+0−198

This diff is large: its 199 lines aren’t shown here.

packages/clients/react/src/plugins/components/source-tool-workbench.tsx+0−918

This diff is large: its 919 lines aren’t shown here.

packages/clients/react/src/plugins/components/tool-permission-badge.tsx+0−137

This diff is large: its 138 lines aren’t shown here.

packages/clients/react/src/plugins/components/ui/alert.tsx+0−80

This diff is large: its 81 lines aren’t shown here.

packages/clients/react/src/plugins/components/ui/badge.tsx+0−57

This diff is large: its 58 lines aren’t shown here.

packages/clients/react/src/plugins/components/ui/button.tsx+0−63

This diff is large: its 64 lines aren’t shown here.

packages/clients/react/src/plugins/components/ui/command.tsx+0−144

This diff is large: its 145 lines aren’t shown here.

packages/clients/react/src/plugins/components/ui/dialog.tsx+0−164

This diff is large: its 165 lines aren’t shown here.

packages/clients/react/src/plugins/components/ui/input.tsx+0−26

This diff is large: its 27 lines aren’t shown here.

packages/clients/react/src/plugins/components/ui/popover.tsx+0−48

This diff is large: its 49 lines aren’t shown here.

packages/clients/react/src/plugins/components/ui/select.tsx+0−24

This diff is large: its 25 lines aren’t shown here.

packages/clients/react/src/plugins/components/ui/separator.tsx+0−23

This diff is large: its 24 lines aren’t shown here.

packages/clients/react/src/plugins/components/ui/textarea.tsx+0−18

This diff is large: its 19 lines aren’t shown here.

packages/clients/react/src/plugins/index.ts+0−126

This diff is large: its 127 lines aren’t shown here.

packages/clients/react/src/plugins/lib/cn.ts+0−6

This diff is large: its 7 lines aren’t shown here.

packages/clients/react/src/plugins/lib/shiki.ts+0−211

This diff is large: its 212 lines aren’t shown here.

packages/clients/react/src/plugins/lib/utils.ts+0−6

This diff is large: its 7 lines aren’t shown here.

packages/clients/react/src/plugins/paths.ts+0−105

This diff is large: its 106 lines aren’t shown here.

packages/clients/react/src/plugins/plugin-route-context.tsx+0−55

This diff is large: its 56 lines aren’t shown here.

packages/clients/react/src/plugins/registry.ts+0−108

This diff is large: its 109 lines aren’t shown here.

packages/clients/react/src/plugins/route-context.tsx+0−64

This diff is large: its 65 lines aren’t shown here.

packages/clients/react/src/plugins/types.ts+0−76

This diff is large: its 77 lines aren’t shown here.

packages/clients/react/src/provider.tsx+7−4

This diff is large: its 14 lines aren’t shown here.

packages/clients/react/src/scope-context.tsx+55−0

This diff is large: its 56 lines aren’t shown here.

packages/clients/react/src/secret-picker.tsx+136−0

This diff is large: its 137 lines aren’t shown here.

packages/clients/react/src/secret-provider-plugin.ts+26−0

This diff is large: its 27 lines aren’t shown here.

packages/clients/react/src/source-plugin.ts+71−0

This diff is large: its 72 lines aren’t shown here.

packages/clients/react/src/source-plugins/index.ts+0−1

This diff is large: its 2 lines aren’t shown here.

packages/clients/react/src/use-scope.ts+2−0

This diff is large: its 3 lines aren’t shown here.

packages/clients/react/tsconfig.json+14−13

This diff is large: its 36 lines aren’t shown here.

packages/core/api/package.jsonrenamed from packages/dev/effect-test-utils/package.json+6−6

This diff is large: its 29 lines aren’t shown here.

packages/core/api/src/api.ts+31−0

This diff is large: its 32 lines aren’t shown here.

packages/core/api/src/errors.ts+26−0

This diff is large: its 27 lines aren’t shown here.

packages/core/api/src/executions/api.ts+65−0

This diff is large: its 66 lines aren’t shown here.

packages/core/api/src/index.ts+6−0

This diff is large: its 7 lines aren’t shown here.

packages/core/api/src/scope/api.ts+23−0

This diff is large: its 24 lines aren’t shown here.

packages/core/api/src/secrets/api.ts+89−0

This diff is large: its 90 lines aren’t shown here.

packages/core/api/src/sources/api.ts+80−0

This diff is large: its 81 lines aren’t shown here.

packages/core/api/src/tools/api.ts+57−0

This diff is large: its 58 lines aren’t shown here.

packages/core/api/tsconfig.json+21−0

This diff is large: its 22 lines aren’t shown here.

packages/core/config/package.json+25−0

This diff is large: its 26 lines aren’t shown here.

packages/core/config/src/config-store.ts+190−0

This diff is large: its 191 lines aren’t shown here.

packages/core/config/src/config.test.ts+304−0

This diff is large: its 305 lines aren’t shown here.

packages/core/config/src/index.ts+24−0

This diff is large: its 25 lines aren’t shown here.

packages/core/config/src/load.ts+56−0

This diff is large: its 57 lines aren’t shown here.

packages/core/config/src/schema.ts+127−0

This diff is large: its 128 lines aren’t shown here.

packages/core/config/src/write.ts+172−0

This diff is large: its 173 lines aren’t shown here.

packages/core/config/tsconfig.json+21−0

This diff is large: its 22 lines aren’t shown here.

packages/core/config/vitest.config.tsrenamed from packages/dev/kitchen-sink/vitest.config.ts+0−0

File renamed without changes.

packages/core/execution/package.jsonrenamed from packages/kernel/runtime-ses/package.json+6−5

This diff is large: its 28 lines aren’t shown here.

packages/core/execution/src/description.ts+58−0

This diff is large: its 59 lines aren’t shown here.

packages/core/execution/src/engine.ts+256−0

This diff is large: its 257 lines aren’t shown here.

packages/core/execution/src/index.ts+13−0

This diff is large: its 14 lines aren’t shown here.

packages/core/execution/src/tool-invoker.ts+73−0

This diff is large: its 74 lines aren’t shown here.

packages/core/execution/tsconfig.json+23−0

This diff is large: its 24 lines aren’t shown here.

packages/core/sdk/package.json+21−0

This diff is large: its 22 lines aren’t shown here.

packages/core/sdk/src/elicitation.ts+78−0

This diff is large: its 79 lines aren’t shown here.

packages/core/sdk/src/errors.ts+39−0

This diff is large: its 40 lines aren’t shown here.

packages/core/sdk/src/executor.ts+229−0

This diff is large: its 230 lines aren’t shown here.

packages/core/sdk/src/ids.ts+13−0

This diff is large: its 14 lines aren’t shown here.

packages/core/sdk/src/in-memory/policy-engine.ts+27−0

This diff is large: its 28 lines aren’t shown here.

packages/core/sdk/src/in-memory/secret-store.ts+133−0

This diff is large: its 134 lines aren’t shown here.

packages/core/sdk/src/in-memory/tool-registry.ts+201−0

This diff is large: its 202 lines aren’t shown here.

packages/core/sdk/src/index.test.ts+682−0

This diff is large: its 683 lines aren’t shown here.

packages/core/sdk/src/index.ts+101−0

This diff is large: its 102 lines aren’t shown here.

packages/core/sdk/src/plugin-kv.ts+66−0

This diff is large: its 67 lines aren’t shown here.

packages/core/sdk/src/plugin.ts+77−0

This diff is large: its 78 lines aren’t shown here.

packages/core/sdk/src/plugins/in-memory-tools.ts+335−0

This diff is large: its 336 lines aren’t shown here.

packages/core/sdk/src/policies.ts+37−0

This diff is large: its 38 lines aren’t shown here.

packages/core/sdk/src/runtime-tools.ts+183−0

This diff is large: its 184 lines aren’t shown here.

packages/core/sdk/src/schema-refs.ts+144−0

This diff is large: its 145 lines aren’t shown here.

packages/core/sdk/src/scope.ts+9−0

This diff is large: its 10 lines aren’t shown here.

packages/core/sdk/src/secrets.ts+106−0

This diff is large: its 107 lines aren’t shown here.

packages/core/sdk/src/sources.ts+186−0

This diff is large: its 187 lines aren’t shown here.

packages/core/sdk/src/testing.ts+38−0

This diff is large: its 39 lines aren’t shown here.

packages/core/sdk/src/tools.ts+214−0

This diff is large: its 215 lines aren’t shown here.

packages/core/sdk/tsconfig.json+21−0

This diff is large: its 22 lines aren’t shown here.

packages/core/sdk/vitest.config.tsrenamed from packages/kernel/core/vitest.config.ts+0−0

File renamed without changes.

packages/core/storage-file/package.json+25−0

This diff is large: its 26 lines aren’t shown here.

packages/core/storage-file/src/index.test.ts+261−0

This diff is large: its 262 lines aren’t shown here.

packages/core/storage-file/src/index.ts+102−0

This diff is large: its 103 lines aren’t shown here.

packages/core/storage-file/src/migrations/0001_initial.ts+19−0

This diff is large: its 20 lines aren’t shown here.

packages/core/storage-file/src/migrations/index.ts+13−0

This diff is large: its 14 lines aren’t shown here.

packages/core/storage-file/src/plugin-kv.ts+99−0

This diff is large: its 100 lines aren’t shown here.

packages/core/storage-file/src/policy-engine.ts+65−0

This diff is large: its 66 lines aren’t shown here.

packages/core/storage-file/src/schema.ts+13−0

This diff is large: its 14 lines aren’t shown here.

packages/core/storage-file/src/secret-store.ts+176−0

This diff is large: its 177 lines aren’t shown here.

packages/core/storage-file/src/sql-utils.ts+18−0

This diff is large: its 19 lines aren’t shown here.

packages/core/storage-file/src/tool-registry.ts+214−0

This diff is large: its 215 lines aren’t shown here.

packages/core/storage-file/tsconfig.json+21−0

This diff is large: its 22 lines aren’t shown here.

packages/dev/effect-test-utils/src/index.ts+0−103

This diff is large: its 104 lines aren’t shown here.

packages/dev/effect-test-utils/tsconfig.json+0−15

This diff is large: its 16 lines aren’t shown here.

packages/dev/kitchen-sink/CHANGELOG.md+0−11

This diff is large: its 12 lines aren’t shown here.

packages/dev/kitchen-sink/package.json+0−26

This diff is large: its 27 lines aren’t shown here.

packages/dev/kitchen-sink/src/effect-errors.ts+0−13

This diff is large: its 14 lines aren’t shown here.

packages/dev/kitchen-sink/src/index.ts+0−1

This diff is large: its 2 lines aren’t shown here.

packages/dev/kitchen-sink/src/kitchen-sink.test.ts+0−134

This diff is large: its 135 lines aren’t shown here.

packages/dev/kitchen-sink/src/playground.ts+0−55

This diff is large: its 56 lines aren’t shown here.

packages/dev/kitchen-sink/tsconfig.json+0−15

This diff is large: its 16 lines aren’t shown here.

packages/hosts/ai-sdk/CHANGELOG.md+0−8

This diff is large: its 9 lines aren’t shown here.

packages/hosts/ai-sdk/package.json+0−28

This diff is large: its 29 lines aren’t shown here.

packages/hosts/ai-sdk/src/ai.ts+0−7

This diff is large: its 8 lines aren’t shown here.

packages/hosts/ai-sdk/src/effect-errors.ts+0−13

This diff is large: its 14 lines aren’t shown here.

packages/hosts/ai-sdk/src/example-codemode-inproc.ts+0−51

This diff is large: its 52 lines aren’t shown here.

packages/hosts/ai-sdk/src/example-dynamic.ts+0−50

This diff is large: its 51 lines aren’t shown here.

packages/hosts/ai-sdk/src/example-static.ts+0−42

This diff is large: its 43 lines aren’t shown here.

packages/hosts/ai-sdk/src/example.ts+0−3

This diff is large: its 4 lines aren’t shown here.

packages/hosts/ai-sdk/src/index.ts+0−66

This diff is large: its 67 lines aren’t shown here.

packages/hosts/ai-sdk/tsconfig.json+0−15

This diff is large: its 16 lines aren’t shown here.

packages/hosts/mcp/CHANGELOG.md+0−7

This diff is large: its 8 lines aren’t shown here.

packages/hosts/mcp/package.json+9−12

This diff is large: its 36 lines aren’t shown here.

packages/hosts/mcp/src/index.ts+1−665

This diff is large: its 667 lines aren’t shown here.

packages/hosts/mcp/src/paused-result.test.ts+0−101

This diff is large: its 102 lines aren’t shown here.

packages/hosts/mcp/src/paused-result.ts+0−95

This diff is large: its 96 lines aren’t shown here.

packages/hosts/mcp/src/server.ts+211−0

This diff is large: its 212 lines aren’t shown here.

packages/hosts/mcp/tsconfig.json+14−6

This diff is large: its 25 lines aren’t shown here.

packages/kernel/core/CHANGELOG.md+0−3

This diff is large: its 4 lines aren’t shown here.

packages/kernel/core/package.json+2−2

This diff is large: its 16 lines aren’t shown here.

packages/kernel/core/src/discovery.ts+0−486

This diff is large: its 487 lines aren’t shown here.

packages/kernel/core/src/http-request-placements.ts+0−164

This diff is large: its 165 lines aren’t shown here.

packages/kernel/core/src/index.test.ts+0−684

This diff is large: its 685 lines aren’t shown here.

packages/kernel/core/src/index.ts+2−6

This diff is large: its 11 lines aren’t shown here.

packages/kernel/core/src/isomorphic-hash.ts+0−132

This diff is large: its 133 lines aren’t shown here.

packages/kernel/core/src/schema-types.test.ts+0−98

This diff is large: its 99 lines aren’t shown here.

packages/kernel/core/src/schema-types.ts+0−249

This diff is large: its 250 lines aren’t shown here.

packages/kernel/core/src/system-tools.ts+0−247

This diff is large: its 248 lines aren’t shown here.

packages/kernel/core/src/tool-map.ts+0−549

This diff is large: its 550 lines aren’t shown here.

packages/kernel/core/src/types.ts+32−262

This diff is large: its 319 lines aren’t shown here.

packages/kernel/core/src/validation.ts+89−0

This diff is large: its 90 lines aren’t shown here.

packages/kernel/core/tsconfig.json+11−1

This diff is large: its 19 lines aren’t shown here.

packages/kernel/ir/README.md+0−31

This diff is large: its 32 lines aren’t shown here.

packages/kernel/ir/package.json+3−7

This diff is large: its 30 lines aren’t shown here.

packages/kernel/ir/src/catalog.test.ts+0−895

This diff is large: its 896 lines aren’t shown here.

packages/kernel/ir/src/catalog.ts+0−1429

This diff is large: its 1430 lines aren’t shown here.

packages/kernel/ir/src/ids.ts+0−58

This diff is large: its 59 lines aren’t shown here.

packages/kernel/ir/src/index.ts+8−3

This diff is large: its 12 lines aren’t shown here.

packages/kernel/ir/src/model.ts+0−919

This diff is large: its 920 lines aren’t shown here.

packages/kernel/ir/src/registry.ts+32−0

This diff is large: its 33 lines aren’t shown here.

packages/kernel/ir/src/serialize.ts+85−0

This diff is large: its 86 lines aren’t shown here.

packages/kernel/ir/tsconfig.json+11−1

This diff is large: its 19 lines aren’t shown here.

packages/kernel/runtime-deno-subprocess/CHANGELOG.md+0−7

This diff is large: its 8 lines aren’t shown here.

packages/kernel/runtime-deno-subprocess/package.json+2−2

This diff is large: its 16 lines aren’t shown here.

packages/kernel/runtime-deno-subprocess/src/deno-worker-process.ts+0−1

This diff is large: its 8 lines aren’t shown here.

packages/kernel/runtime-deno-subprocess/src/index.test.ts+41−73

This diff is large: its 206 lines aren’t shown here.

packages/kernel/runtime-deno-subprocess/src/index.ts+231−255

This diff is large: its 598 lines aren’t shown here.

packages/kernel/runtime-deno-subprocess/tsconfig.json+8−1

This diff is large: its 16 lines aren’t shown here.

packages/kernel/runtime-quickjs/CHANGELOG.md+0−7

This diff is large: its 8 lines aren’t shown here.

packages/kernel/runtime-quickjs/package.json+2−2

This diff is large: its 16 lines aren’t shown here.

packages/kernel/runtime-quickjs/src/index.test.ts+127−255

This diff is large: its 442 lines aren’t shown here.

packages/kernel/runtime-quickjs/src/index.ts+24−8

This diff is large: its 86 lines aren’t shown here.

packages/kernel/runtime-quickjs/tsconfig.json+11−1

This diff is large: its 19 lines aren’t shown here.

packages/kernel/runtime-ses/CHANGELOG.md+0−7

This diff is large: its 8 lines aren’t shown here.

packages/kernel/runtime-ses/src/index.ts+0−239

This diff is large: its 240 lines aren’t shown here.

packages/kernel/runtime-ses/src/sandbox-worker.mjs+0−182

This diff is large: its 183 lines aren’t shown here.

packages/kernel/runtime-ses/tsconfig.json+0−15

This diff is large: its 16 lines aren’t shown here.

packages/platform/api/package.json+0−39

This diff is large: its 40 lines aren’t shown here.

packages/platform/api/src/api.ts+0−74

This diff is large: its 75 lines aren’t shown here.

packages/platform/api/src/effect.ts+0−22

This diff is large: its 23 lines aren’t shown here.

packages/platform/api/src/errors.ts+0−7

This diff is large: its 8 lines aren’t shown here.

packages/platform/api/src/executions/api.ts+0−73

This diff is large: its 74 lines aren’t shown here.

packages/platform/api/src/executions/http.ts+0−32

This diff is large: its 33 lines aren’t shown here.

packages/platform/api/src/executor-context.ts+0−33

This diff is large: its 34 lines aren’t shown here.

packages/platform/api/src/http.ts+0−50

This diff is large: its 51 lines aren’t shown here.

packages/platform/api/src/index.ts+0−62

This diff is large: its 63 lines aren’t shown here.

packages/platform/api/src/local-context.ts+0−6

This diff is large: its 7 lines aren’t shown here.

packages/platform/api/src/local/api.ts+0−127

This diff is large: its 128 lines aren’t shown here.

packages/platform/api/src/local/http.ts+0−120

This diff is large: its 121 lines aren’t shown here.

packages/platform/api/src/plugins.ts+0−23

This diff is large: its 24 lines aren’t shown here.

packages/platform/api/src/policies/api.ts+0−81

This diff is large: its 82 lines aren’t shown here.

packages/platform/api/src/policies/http.ts+0−47

This diff is large: its 48 lines aren’t shown here.

packages/platform/api/src/sources/api.ts+0−78

This diff is large: its 79 lines aren’t shown here.

packages/platform/api/src/sources/http.ts+0−64

This diff is large: its 65 lines aren’t shown here.

packages/platform/api/tsconfig.json+0−13

This diff is large: its 14 lines aren’t shown here.

packages/platform/sdk-file/package.json+0−33

This diff is large: its 34 lines aren’t shown here.

packages/platform/sdk-file/src/capture-release-workspace-fixture.ts+0−374

This diff is large: its 375 lines aren’t shown here.

packages/platform/sdk-file/src/client.ts+0−5

This diff is large: its 6 lines aren’t shown here.

packages/platform/sdk-file/src/config-codec.ts+0−93

This diff is large: its 94 lines aren’t shown here.

packages/platform/sdk-file/src/config-migrations.test.ts+0−189

This diff is large: its 190 lines aren’t shown here.

packages/platform/sdk-file/src/config-migrations/index.ts+0−48

This diff is large: its 49 lines aren’t shown here.

packages/platform/sdk-file/src/config-migrations/legacy-local-config.ts+0−539

This diff is large: its 540 lines aren’t shown here.

packages/platform/sdk-file/src/config.test.ts+0−144

This diff is large: its 145 lines aren’t shown here.

packages/platform/sdk-file/src/config.ts+0−390

This diff is large: its 391 lines aren’t shown here.

packages/platform/sdk-file/src/effect.ts+0−28

This diff is large: its 29 lines aren’t shown here.

packages/platform/sdk-file/src/errors.ts+0−105

This diff is large: its 106 lines aren’t shown here.

packages/platform/sdk-file/src/executor-state-codec.ts+0−82

This diff is large: its 83 lines aren’t shown here.

packages/platform/sdk-file/src/executor-state-migrations.test.ts+0−231

This diff is large: its 232 lines aren’t shown here.

packages/platform/sdk-file/src/executor-state-migrations/index.ts+0−32

This diff is large: its 33 lines aren’t shown here.

packages/platform/sdk-file/src/executor-state-migrations/legacy-local-executor-state.ts+0−356

This diff is large: its 357 lines aren’t shown here.

packages/platform/sdk-file/src/executor-state-store.ts+0−702

This diff is large: its 703 lines aren’t shown here.

packages/platform/sdk-file/src/index.ts+0−426

This diff is large: its 427 lines aren’t shown here.

packages/platform/sdk-file/src/installation.test.ts+0−70

This diff is large: its 71 lines aren’t shown here.

packages/platform/sdk-file/src/installation.ts+0−39

This diff is large: its 40 lines aren’t shown here.

packages/platform/sdk-file/src/release-upgrade-fixtures.ts+0−100

This diff is large: its 101 lines aren’t shown here.

packages/platform/sdk-file/src/runtime.ts+0−2

This diff is large: its 3 lines aren’t shown here.

packages/platform/sdk-file/src/secret-material-providers.test.ts+0−98

This diff is large: its 99 lines aren’t shown here.

packages/platform/sdk-file/src/secret-material-providers.ts+0−502

This diff is large: its 503 lines aren’t shown here.

packages/platform/sdk-file/src/source-artifacts.ts+0−170

This diff is large: its 171 lines aren’t shown here.

packages/platform/sdk-file/src/source-type-declarations.ts+0−427

This diff is large: its 428 lines aren’t shown here.

packages/platform/sdk-file/src/tools.ts+0−643

This diff is large: its 644 lines aren’t shown here.

packages/platform/sdk-file/src/workspace-state.ts+0−80

This diff is large: its 81 lines aren’t shown here.

packages/platform/sdk-file/tsconfig.json+0−13

This diff is large: its 14 lines aren’t shown here.

packages/platform/sdk/package.json+0−51

This diff is large: its 52 lines aren’t shown here.

packages/platform/sdk/src/backend.ts+0−272

This diff is large: its 273 lines aren’t shown here.

packages/platform/sdk/src/contracts.ts+0−3

This diff is large: its 4 lines aren’t shown here.

packages/platform/sdk/src/effect.ts+0−1

This diff is large: its 2 lines aren’t shown here.

packages/platform/sdk/src/errors.ts+0−54

This diff is large: its 55 lines aren’t shown here.

packages/platform/sdk/src/executions/contracts.ts+0−23

This diff is large: its 24 lines aren’t shown here.

packages/platform/sdk/src/executor-effect.ts+0−502

This diff is large: its 503 lines aren’t shown here.

packages/platform/sdk/src/executor.ts+0−175

This diff is large: its 176 lines aren’t shown here.

packages/platform/sdk/src/index.ts+0−3

This diff is large: its 4 lines aren’t shown here.

packages/platform/sdk/src/local/contracts.ts+0−159

This diff is large: its 160 lines aren’t shown here.

packages/platform/sdk/src/local/operations.ts+0−25

This diff is large: its 26 lines aren’t shown here.

packages/platform/sdk/src/local/secret-stores.ts+0−444

This diff is large: its 445 lines aren’t shown here.

packages/platform/sdk/src/local/secrets.ts+0−241

This diff is large: its 242 lines aren’t shown here.

packages/platform/sdk/src/operations.ts+0−5

This diff is large: its 6 lines aren’t shown here.

packages/platform/sdk/src/plugins.ts+0−1628

This diff is large: its 1629 lines aren’t shown here.

packages/platform/sdk/src/policies/contracts.ts+0−25

This diff is large: its 26 lines aren’t shown here.

packages/platform/sdk/src/policies/operations.ts+0−429

This diff is large: its 430 lines aren’t shown here.

packages/platform/sdk/src/runtime/__fixtures__/README.md+0−38

This diff is large: its 39 lines aren’t shown here.

packages/platform/sdk/src/runtime/__fixtures__/v1.2.3-google-calendar-workspace/.executor/artifacts/sources/google-calendar.json+0−1

This diff is large: its 2 lines aren’t shown here.

packages/platform/sdk/src/runtime/__fixtures__/v1.2.3-google-calendar-workspace/.executor/artifacts/sources/google-calendar/documents/doc_3c24a6731267de91.txt+0−3294

This diff is large: its 3295 lines aren’t shown here.

packages/platform/sdk/src/runtime/__fixtures__/v1.2.3-google-calendar-workspace/.executor/executor.jsonc+0−19

This diff is large: its 20 lines aren’t shown here.

packages/platform/sdk/src/runtime/__fixtures__/v1.2.3-google-calendar-workspace/.executor/state/workspace-state.json+0−13

This diff is large: its 14 lines aren’t shown here.

packages/platform/sdk/src/runtime/__fixtures__/v1.2.3-google-calendar-workspace/fixture.json+0−9

This diff is large: its 10 lines aren’t shown here.

packages/platform/sdk/src/runtime/catalog/catalog-typescript.ts+0−1264

This diff is large: its 1265 lines aren’t shown here.

packages/platform/sdk/src/runtime/catalog/prettier-format.ts+0−59

This diff is large: its 60 lines aren’t shown here.

packages/platform/sdk/src/runtime/catalog/schema-type-signature.ts+0−114

This diff is large: its 115 lines aren’t shown here.

packages/platform/sdk/src/runtime/catalog/source/reconcile.ts+0−94

This diff is large: its 95 lines aren’t shown here.

packages/platform/sdk/src/runtime/catalog/source/runtime.ts+0−1323

This diff is large: its 1324 lines aren’t shown here.

packages/platform/sdk/src/runtime/catalog/source/sync.ts+0−295

This diff is large: its 296 lines aren’t shown here.

packages/platform/sdk/src/runtime/catalog/source/type-declarations.ts+0−27

This diff is large: its 28 lines aren’t shown here.

packages/platform/sdk/src/runtime/effect-errors.ts+0−13

This diff is large: its 14 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/http.test.ts+0−176

This diff is large: its 177 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/ir-execution.ts+0−85

This diff is large: its 86 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/live.test.ts+0−52

This diff is large: its 53 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/live.ts+0−278

This diff is large: its 279 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/runtime-config.test.ts+0−159

This diff is large: its 160 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/runtime.ts+0−36

This diff is large: its 37 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/scope/authorization.ts+0−175

This diff is large: its 176 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/scope/environment.ts+0−190

This diff is large: its 191 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/scope/local.ts+0−12

This diff is large: its 13 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/scope/source-catalog.test.ts+0−324

This diff is large: its 325 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/scope/source-catalog.ts+0−394

This diff is large: its 395 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/scope/tool-invoker.ts+0−297

This diff is large: its 298 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/service.ts+0−1024

This diff is large: its 1025 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/state.ts+0−31

This diff is large: its 32 lines aren’t shown here.

packages/platform/sdk/src/runtime/execution/test-http-client.ts+0−120

This diff is large: its 121 lines aren’t shown here.

packages/platform/sdk/src/runtime/executor-state-store.ts+0−162

This diff is large: its 163 lines aren’t shown here.

packages/platform/sdk/src/runtime/fixtures/google-sheets-discovery.json+0−8314

This diff is large: its 8315 lines aren’t shown here.

packages/platform/sdk/src/runtime/fixtures/linear-introspection.json+0−129477

This diff is large: its 129478 lines aren’t shown here.

packages/platform/sdk/src/runtime/fixtures/neon-openapi.json+0−14358

This diff is large: its 14359 lines aren’t shown here.

This diff is larger than a page shows: the files after these aren’t listed. Clone the repository to see all of it.