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 @@
1# Changesets1# Changesets
2 2
3Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works3This repo uses Changesets to drive releases for the published `executor` CLI.
4with multi-package repos, or single-package repos to help you version and publish your code. You can
5find the full documentation for it [in our repository](https://github.com/changesets/changesets).
6 4
7We have a quick list of common questions to get you started engaging with this project in5## What to put in a changeset
8[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md).6
7Only `executor` is managed directly by Changesets.
8
9After `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
13Use 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
7 "access": "public",7 "access": "public",
8 "baseBranch": "main",8 "baseBranch": "main",
9 "updateInternalDependencies": "patch",9 "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 ]
11}33}
.changeset/funny-forks-listen.md+0−5
@@ -1,5 +0,0 @@
1---
2"executor": minor
3---
4
5Prepare the next executor beta minor release.
.changeset/fuzzy-camels-cheer.md+0−5
@@ -1,5 +0,0 @@
1---
2"executor": patch
3---
4
5Fix 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
2 "mode": "pre",2 "mode": "pre",
3 "tag": "beta",3 "tag": "beta",
4 "initialVersions": {4 "initialVersions": {
5 "@executor/docs": "0.0.0",5 "executor": "1.4.0-beta.0",
6 "executor": "1.2.6",6 "@executor/server": "1.4.0-beta.0",
7 "@executor/web": "0.0.0",7 "@executor/web": "1.4.0-beta.0",
8 "@executor/mcp-elicitation-demo": "0.0.0",8 "@executor/react": "1.4.0-beta.0",
9 "@executor/serve-skills-via-mcp-demo": "0.0.0",9 "@executor/api": "1.4.0-beta.0",
10 "@executor/sqlite-sdk-consumer-example": "0.0.0",10 "@executor/config": "1.4.0-beta.0",
11 "@executor/react": "0.0.0",11 "@executor/execution": "1.4.0-beta.0",
12 "@executor/effect-test-utils": "0.0.0",12 "@executor/sdk": "1.4.0-beta.0",
13 "@executor/kitchen-sink": "0.0.0",13 "@executor/storage-file": "1.4.0-beta.0",
14 "@executor/ai-sdk-adapter": "0.0.0",14 "@executor/host-mcp": "1.4.0-beta.0",
15 "@executor/executor-mcp": "0.0.0",15 "@executor/codemode-core": "1.4.0-beta.0",
16 "@executor/codemode-core": "0.0.0",16 "@executor/ir": "1.4.0-beta.0",
17 "@executor/ir": "0.0.0",
18 "@executor/runtime-deno-subprocess": "0.0.0",17 "@executor/runtime-deno-subprocess": "0.0.0",
19 "@executor/runtime-quickjs": "0.0.0",18 "@executor/runtime-quickjs": "1.4.0-beta.0",
20 "@executor/runtime-ses": "0.0.0",19 "@executor/plugin-file-secrets": "1.4.0-beta.0",
21 "@executor/platform-api": "0.0.0",20 "@executor/plugin-google-discovery": "1.4.0-beta.0",
22 "@executor/platform-sdk": "0.0.0",21 "@executor/plugin-graphql": "1.4.0-beta.0",
23 "@executor/platform-sdk-file": "0.0.0",22 "@executor/plugin-keychain": "1.4.0-beta.0",
24 "@executor/server": "0.0.0",23 "@executor/plugin-mcp": "1.4.0-beta.0",
25 "@executor/source-core": "0.0.0",24 "@executor/plugin-onepassword": "1.4.0-beta.0",
26 "@executor/plugin-execution-history-react": "0.0.0",25 "@executor/plugin-openapi": "1.4.0-beta.0",
27 "@executor/plugin-google-discovery-http": "0.0.0",26 "@executor/ui": "1.4.0-beta.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"
51 },27 },
52 "changesets": [28 "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 ]
60}29}
.changeset/quick-cars-approve.md+0−5
@@ -1,5 +0,0 @@
1---
2"executor": patch
3---
4
5Improve 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
2"executor": patch2"executor": patch
3---3---
4 4
5Compact openapi sources5Release 1.4
.changeset/tame-trains-confess.md+0−5
@@ -1,5 +0,0 @@
1---
2"executor": patch
3---
4
5Fix 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
5Improve 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
33 33
34 - name: Setup Bun34 - name: Setup Bun
35 uses: oven-sh/setup-bun@v235 uses: oven-sh/setup-bun@v2
36 with:
37 bun-version: 1.2.22
36 38
37 - name: Setup Node39 - name: Setup Node
38 uses: actions/setup-node@v440 uses: actions/setup-node@v4
@@ -48,21 +50,17 @@ jobs: · 9 unmodified lines
48 - name: Install dependencies50 - name: Install dependencies
49 run: bun install --frozen-lockfile51 run: bun install --frozen-lockfile
50 52
51 - name: Run executor checks53 - name: Run release checks
52 run: |54 run: bun run release:check
53 bun run --cwd apps/executor typecheck
54 bun run --cwd apps/executor test
55 55
56 - name: Publish package and create release56 - name: Publish package and create release
57 env:57 env:
58 GH_TOKEN: ${{ github.token }}58 GH_TOKEN: ${{ github.token }}
59 NPM_TOKEN: ${{ secrets.NPM_TOKEN }}59 NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
60 NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
60 RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}61 RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
61 run: |62 run: |
62 export GITHUB_REF_TYPE=tag63 export GITHUB_REF_TYPE=tag
63 export GITHUB_REF_NAME="$RELEASE_TAG"64 export GITHUB_REF_NAME="$RELEASE_TAG"
64 export GITHUB_REF="refs/tags/$RELEASE_TAG"65 export GITHUB_REF="refs/tags/$RELEASE_TAG"
65 if [ -n "${NPM_TOKEN:-}" ]; then66 bun run release:publish
66 export NODE_AUTH_TOKEN="$NPM_TOKEN"
67 fi
68 bun run --cwd apps/executor release:publish
.github/workflows/release.yml+6−4
@@ -1,5 +1,5 @@
1name: Release1name: Release
2run-name: "prepare release"2run-name: prepare release
3 3
4on:4on:
5 push:5 push:
@@ -28,6 +28,8 @@ jobs: · 22 unmodified lines
28 28
29 - name: Setup Bun29 - name: Setup Bun
30 uses: oven-sh/setup-bun@v230 uses: oven-sh/setup-bun@v2
31 with:
32 bun-version: 1.2.22
31 33
32 - name: Setup Node34 - name: Setup Node
33 uses: actions/setup-node@v435 uses: actions/setup-node@v4
@@ -57,9 +59,9 @@ jobs: · 23 unmodified lines
57 before="$(git rev-list --max-count=1 HEAD^ 2>/dev/null || true)"59 before="$(git rev-list --max-count=1 HEAD^ 2>/dev/null || true)"
58 fi60 fi
59 61
60 version="$(node -e "console.log(JSON.parse(require('fs').readFileSync('apps/executor/package.json', 'utf8')).version)")"62 version="$(node -e "console.log(JSON.parse(require('fs').readFileSync('apps/cli/package.json', 'utf8')).version)")"
61 if [ -n "$before" ] && git cat-file -e "$before:apps/executor/package.json" 2>/dev/null; then63 if [ -n "$before" ] && git cat-file -e "$before:apps/cli/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 ?? ''); });")"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 ?? ''); });")"
63 else65 else
64 previous_version=""66 previous_version=""
65 fi67 fi
.gitignore+21−72
@@ -1,90 +1,39 @@
1# Environment variables1# dependencies (bun install)
2.env2node_modules
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
37 3
38# Output / build artifacts4# output
39out5out
40dist6dist
41*.tgz7*.tgz
42 8
43# Rust / Cargo build artifacts9# code coverage
44**/target/
45tools/openapi-extractor-rs/pkg-*/
46
47# Code coverage
48coverage10coverage
49*.lcov11*.lcov
50 12
51# Logs13# logs
52logs14logs
53*.log15_.log
54report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json16report.[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
55 24
56# Caches25# caches
57.eslintcache26.eslintcache
58.cache27.cache
28*.tsbuildinfo
29.turbo
59 30
60# IntelliJ based IDEs31# IntelliJ based IDEs
61.idea32.idea
62 33
63# Finder (macOS)34# Finder (MacOS) folder config
64.DS_Store35.DS_Store
65
66# Convex local backend state
67convex_local_backend.sqlite3
68convex_local_storage/
69
70# Local OpenAPI sources service state
71sources/data/*.sqlite
72sources/data/*.sqlite-shm
73sources/data/*.sqlite-wal
74packages/platform/server/:memory:/
75
76# Composio toolkit scrape outputs
77sources/composio-scrape/data/
78
79# Dev runner PID file
80.dev.pids
81
82# Misc
83*.har
84.chat-links.json
85.reference/
86personal-notes/36personal-notes/
87.tmp/37*.har.executor
88executor/.env.executor-push38executor.har
89ignored/39.executor/
90agent-notes/
.mcp.json+4−12
@@ -1,20 +1,12 @@
1{1{
2 "mcpServers": {2 "mcpServers": {
3 "executor-stdio": {3 "executor": {
4 "command": "bun",4 "command": "bun",
5 "args": [5 "args": [
6 "run",6 "run",
7 "executor",7 "/Users/rhyssullivan/src/v4-executor/apps/cli/src/main.ts",
8 "mcp",8 "mcp"
9 "--stdio"
10 ]
11 },
12 "executor-stdio-prod": {
13 "command": "executor",
14 "args": [
15 "mcp",
16 "--stdio"
17 ]9 ]
18 }10 }
19 }11 }
20}12}
.oxlintrc.jsonc+2−84
@@ -1,87 +1,5 @@
1{1{
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
34 "rules": {2 "rules": {
35 // This repo uses Effect.gen heavily. The underlying generator syntax is an3 "typescript/no-explicit-any": "error"
36 // implementation detail, so "no yield" is not a useful signal here.4 }
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 ],
87}5}
.reference/effect+1−0
@@ -0,0 +1 @@
1Subproject commit ec5c50507b1a2f5ad712c148a7da0fadb8cb9f52
.reference/effect-atom+1−0
@@ -0,0 +1 @@
1Subproject commit 957095fdfc930eae666f78d65f7af8584959bffd
.reference/executor+1−0
@@ -0,0 +1 @@
1Subproject commit 2d532f8322368eedc835fa09dc9223a9ddef9e1d
.skills/effect-http-testing/SKILL.md+205−0
@@ -0,0 +1,205 @@
1---
2name: effect-http-testing
3description: 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
10Define 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
13import { expect, layer } from "@effect/vitest"
14import { Effect, Layer, Schema } from "effect"
15import {
16 HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup,
17 HttpClient, OpenApi
18} from "@effect/platform"
19import { NodeHttpServer } from "@effect/platform-node"
20
21// 1. Define the API
22class Item extends Schema.Class<Item>("Item")({
23 id: Schema.Number,
24 name: Schema.String,
25}) {}
26
27const 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
35const MyApi = HttpApi.make("myApi").add(ItemsGroup)
36
37// 2. Implement handlers
38const 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
45const ApiLive = HttpApiBuilder.api(MyApi).pipe(Layer.provide(ItemsLive))
46
47const TestLayer = HttpApiBuilder.serve().pipe(
48 Layer.provide(ApiLive),
49 Layer.provideMerge(NodeHttpServer.layerTest),
50)
51
52// 4. Use layer() to share across tests
53layer(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
73HttpApiBuilder.serve().pipe(
74 Layer.provide(ApiLive),
75 Layer.provideMerge(NodeHttpServer.layerTest),
76)
77
78// WRONG — "Service not found: HttpApi.Api"
79ApiLive.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
95Effect'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
99HttpApiEndpoint.get("getItem", "/items/:itemId").addSuccess(Item)
100
101// CORRECT — req.path.itemId is typed and populated
102HttpApiEndpoint.get("getItem", "/items/:itemId")
103 .setPath(Schema.Struct({ itemId: Schema.NumberFromString }))
104 .addSuccess(Item)
105```
106
107### OpenApi.fromApi generates the spec
108
109Use `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
117Inside `layer()` tests, the `HttpClient` is available in the Effect context:
118
119```ts
120layer(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
133Production code should use `HttpClient` from `@effect/platform`, not raw `fetch`:
134
135```ts
136import { HttpClient, HttpClientRequest } from "@effect/platform"
137
138// Build request
139let request = HttpClientRequest.get("/items")
140request = HttpClientRequest.setHeader(request, "accept", "application/json")
141request = HttpClientRequest.setUrlParam(request, "limit", "10")
142
143// Execute — requires HttpClient in context
144const response = yield* client.execute(request)
145
146// Read body
147const data = yield* response.json // Effect<unknown>
148const text = yield* response.text // Effect<string>
149```
150
151This makes testing clean — swap in a test client layer, no monkey-patching needed.
152
153### Response headers are Record<string, string>
154
155Effect'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
159response.headers.forEach((v, k) => ...)
160response.headers.get("content-type")
161
162// CORRECT
163const ct = response.headers["content-type"]
164const copy = { ...response.headers }
165```
166
167### HttpClientRequest.make takes uppercase methods
168
169```ts
170// The method parameter to make() must be uppercase
171HttpClientRequest.make("GET")("/items")
172
173// Or use the convenience methods
174HttpClientRequest.get("/items")
175HttpClientRequest.post("/items")
176```
177
178### Prepending base URLs to a client
179
180Use `HttpClient.mapRequest` with `HttpClientRequest.prependUrl`:
181
182```ts
183const 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
194Use `Effect.flip` to turn errors into values for assertion:
195
196```ts
197const error = yield* Effect.flip(someFailingEffect)
198expect(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---
2name: effect-client-wrapper
3description: 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
8Wrap 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
13import { Context, Data, Effect, Layer, Config, Redacted } from "effect";
14
15// 1. Define tagged errors
16export class MyClientError extends Data.TaggedError("MyClientError")<{
17 cause: unknown;
18}> {}
19
20export class MyClientInstantiationError extends Data.TaggedError(
21 "MyClientInstantiationError",
22)<{
23 cause: unknown;
24}> {}
25
26// 2. Define service interface with `use` method
27export 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
35const 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
53export 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
63const 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
74program.pipe(Effect.provide(MyClient.Default));
75```
76
77## Key Benefits
78
791. **Centralized error handling** - All client errors wrapped in typed `MyClientError`
802. **Automatic tracing** - Every `use` call creates a span with function name
813. **Config-based secrets** - API keys loaded via `Config.redacted`
824. **Clean DI** - Consumers inject via `yield* MyClient`
835. **Encapsulation** - Raw client hidden behind `use` interface
84
85## Variations
86
87### Multiple Error Types
88
89```typescript
90export class MyClientNetworkError extends Data.TaggedError(
91 "MyClientNetworkError",
92)<{
93 cause: unknown;
94}> {}
95
96export class MyClientValidationError extends Data.TaggedError(
97 "MyClientValidationError",
98)<{
99 message: string;
100}> {}
101
102const 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
116Expose specific methods instead of generic `use`:
117
118```typescript
119export type IEmailClient = Readonly<{
120 sendEmail: (
121 params: SendEmailParams,
122 ) => Effect.Effect<EmailResult, EmailError>;
123 getEmail: (id: string) => Effect.Effect<Email, EmailError>;
124}>;
125
126const 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
146import { Schedule } from "effect";
147
148const retryPolicy = Schedule.exponential(100).pipe(
149 Schedule.intersect(Schedule.recurs(3)),
150 Schedule.jittered,
151);
152
153const 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
166import Stripe from "stripe";
167import { Context, Data, Effect, Layer, Config, Redacted } from "effect";
168
169export class StripeError extends Data.TaggedError("StripeError")<{
170 cause: unknown;
171}> {}
172
173export type IStripeClient = Readonly<{
174 use: <A>(fn: (stripe: Stripe) => Promise<A>) => Effect.Effect<A, StripeError>;
175}>;
176
177const 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
191export 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
201const 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 @@
1use effect vitest and run tests via vitest not bun test
CLAUDE.md+1−0
@@ -0,0 +1 @@
1use effect vitest and run tests via vitest not bun test
LICENSE+0−21
@@ -1,21 +0,0 @@
1MIT License
2
3Copyright (c) 2026 Rhys Sullivan
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
README.md+0−395
@@ -1,395 +0,0 @@
1# executor
2
3
4https://github.com/user-attachments/assets/11225f83-e848-42ba-99b2-a993bcc88dad
5
6
7`executor` is a local-first execution environment for AI agents.
8
9It 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
15Join the Discord community: https://discord.gg/eF29HBHwM6
16
17At 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
24The 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
35In 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
44Think of `executor` as a local control plane for agent tool use.
45
461. You start a local `executor` daemon.
472. You connect sources such as an MCP server, an OpenAPI document, or a GraphQL endpoint.
483. `executor` indexes those sources into a workspace tool catalog.
494. An agent runs TypeScript against that catalog through `executor call` or through the MCP bridge.
505. 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
62The 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
70The 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
74The main CLI workflow is `executor call`.
75
76The runtime expects the agent to use the built-in discovery workflow:
77
78```ts
79const matches = await tools.discover({ query: "github issues", limit: 5 });
80const path = matches.bestPath;
81const detail = await tools.describe.tool({ path, includeSchemas: true });
82
83return await tools.github.issues.list({
84 owner: "vercel",
85 repo: "next.js",
86});
87```
88
89A 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
98When a source or tool needs human input, `executor` can pause the execution and create an interaction record.
99
100That 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
107This 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
111The web UI is not just a setup surface. It is also where you can inspect what `executor` learned from a source.
112
113For 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
123If you want to use this a package distribution, install it via npm:
124
125```bash
126npm install -g executor
127executor web
128```
129
130That starts a foreground local session, prints the local web URL, and keeps it alive until you press `Ctrl+C`.
131
132If you want the MCP endpoint instead, run:
133
134```bash
135executor mcp
136```
137
138That prints the local MCP URL and keeps the session alive until you press `Ctrl+C`.
139
140If you want a local stdio MCP server for agent configs such as Codex or OpenCode, run:
141
142```bash
143executor mcp --stdio
144```
145
146Then you can run the CLI as `executor`.
147
148If you are working from this repository locally, the easiest path is:
149
150```bash
151bun install
152bun dev
153```
154
155That starts the local runtime. The default base URL is:
156
157```text
158http://127.0.0.1:8788
159```
160
161From there:
162
1631. Open the web UI in your browser.
1642. Add a source from `/sources/add`.
1653. If needed, store credentials in `/secrets`.
1664. Run TypeScript with `bun run executor call ...`.
167
168If 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
173executor web
174executor mcp
175executor mcp --stdio
176executor call --file script.ts
177executor resume --execution-id exec_123
178```
179
180Compatibility commands for the detached daemon are still available:
181
182```bash
183executor up
184executor down
185executor status --json
186executor 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
195Examples:
196
197```bash
198executor call 'const matches = await tools.discover({ query: "repo details", limit: 1 }); return matches;'
199executor call --file script.ts
200cat script.ts | executor call --stdin
201executor call --no-open --file script.ts
202```
203
204If an execution pauses, resume it with:
205
206```bash
207executor resume --execution-id exec_123
208```
209
210## Adding a source
211
212There are two main ways to add a source.
213
214### In the web UI
215
216Use 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
224This is the easiest path for most users.
225
226### From inside an execution
227
228The runtime also exposes `tools.executor.sources.add(...)`, which lets an agent add a source from code.
229
230Examples:
231
232```ts
233return 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
249return 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.
260Browser OAuth and popup-driven auth flows live on the plugin-owned HTTP and web surfaces.
261
262## How execution works
263
264At a high level, every execution follows the same loop:
265
2661. `executor` resolves the current local installation and workspace.
2672. It builds a tool catalog from built-in tools plus all connected workspace sources.
2683. It runs your TypeScript inside the configured sandbox runtime. QuickJS is the default, and `.executor/executor.jsonc` can set `"runtime": "quickjs" | "ses" | "deno"`.
2694. Tool calls are dispatched through `executor` rather than directly from your code.
2705. If a tool needs interaction, the run pauses and records a pending interaction.
2716. Once the interaction is resolved, the execution continues and eventually completes or fails.
272
273Example:
274
275```jsonc
276{
277 "runtime": "ses",
278 "sources": {}
279}
280```
281
282This 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
291The React web app is served from the same local server as the API.
292
293Main 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
301The 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
305By default `executor` runs as a single local daemon process.
306
307It 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
313Default network location:
314
315- host: `127.0.0.1`
316- port: `8788`
317
318Default 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
325The 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
331Persisted 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
342On 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
348Compared 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
356This 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
360If 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
391This 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
3This 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
71. Add a changeset in the PR that should ship:
8 - `bun run changeset`
92. Merge that PR to `main`.
103. `.github/workflows/release.yml` opens or updates a `Version Packages` PR.
114. Merge the `Version Packages` PR.
125. The release workflow tags the commit and dispatches `.github/workflows/publish-executor-package.yml`.
136. 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
21Enter prerelease mode before starting a beta train:
22
23- `bun run release:beta:start`
24
25That 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
27When the beta train is done:
28
29- `bun run release:beta:stop`
30
31Stable versions publish to npm under `latest`.
32Beta versions publish to npm under `beta`.
33
34## Local dry run
35
36To build the full release payload without publishing to npm or GitHub:
37
38- `bun run release:publish:dry-run`
39
40That 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
2import "../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 @@
1import { cp, mkdir, rm, writeFile, chmod } from "node:fs/promises";
2import { existsSync } from "node:fs";
3import { createRequire } from "node:module";
4import { resolve, join, dirname } from "node:path";
5import { fileURLToPath } from "node:url";
6import { $ } from "bun";
7
8const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
9const cliRoot = resolve(repoRoot, "apps/cli");
10const webRoot = resolve(repoRoot, "apps/web");
11const distDir = resolve(cliRoot, "dist");
12
13const 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
28const 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
47type Target = {
48 os: "linux" | "darwin" | "win32";
49 arch: "x64" | "arm64";
50 abi?: "musl";
51};
52
53const 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
64const platformName = (t: Target) =>
65 t.os === "win32" ? "windows" : t.os;
66
67const targetPackageName = (t: Target) =>
68 ["executor", platformName(t), t.arch, t.abi].filter(Boolean).join("-");
69
70const bunTarget = (t: Target) =>
71 ["bun", platformName(t), t.arch, t.abi].filter(Boolean).join("-");
72
73const binaryName = (t: Target) =>
74 t.os === "win32" ? "executor.exe" : "executor";
75
76const isCurrentPlatform = (t: Target) =>
77 t.os === process.platform && t.arch === process.arch && !t.abi;
78
79// ---------------------------------------------------------------------------
80// Build web app
81// ---------------------------------------------------------------------------
82
83const 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
98const 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
124const 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
191const 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
244const 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
262const 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
277const 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
297const 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
306const 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
326const NODE_SHIM = `#!/usr/bin/env node
327const childProcess = require("child_process");
328const fs = require("fs");
329const path = require("path");
330const os = require("os");
331
332function 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
339if (process.env.EXECUTOR_BIN_PATH) run(process.env.EXECUTOR_BIN_PATH);
340
341// Check cached binary from postinstall
342const scriptDir = path.dirname(fs.realpathSync(__filename));
343const cached = path.join(scriptDir, ".executor");
344if (fs.existsSync(cached)) run(cached);
345
346// Resolve platform
347const platformMap = { darwin: "darwin", linux: "linux", win32: "windows" };
348const platform = platformMap[os.platform()] || os.platform();
349const arch = os.arch() === "arm64" ? "arm64" : "x64";
350const binary = platform === "windows" ? "executor.exe" : "executor";
351
352// Detect musl
353const 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
364const base = "executor-" + platform + "-" + arch;
365const 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
376function 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
392const resolved = findBinary(scriptDir);
393if (!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}
397run(resolved);
398`;
399
400// ---------------------------------------------------------------------------
401// Postinstall — hardlink/copy the platform binary for fast startup
402// ---------------------------------------------------------------------------
403
404const POSTINSTALL_SCRIPT = `#!/usr/bin/env node
405const fs = require("fs");
406const path = require("path");
407const os = require("os");
408const { createRequire } = require("module");
409
410const __dirname_resolved = path.dirname(fs.realpathSync(__filename));
411const require_ = createRequire(__filename);
412
413const platformMap = { darwin: "darwin", linux: "linux", win32: "windows" };
414const platform = platformMap[os.platform()] || os.platform();
415const arch = os.arch() === "arm64" ? "arm64" : "x64";
416const binary = platform === "windows" ? "executor.exe" : "executor";
417const base = "executor-" + platform + "-" + arch;
418
419const names = platform === "linux" ? [base, base + "-musl"] : [base];
420
421for (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
445const command = process.argv[2];
446const singleFlag = process.argv.includes("--single");
447
448if (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 @@
1declare 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
2import { dirname, join } from "node:path";
3const wasmOnDisk = join(dirname(process.execPath), "emscripten-module.wasm");
4if (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
21import { spawn } from "node:child_process";
22import { resolve } from "node:path";
23import { Command, Options, Args } from "@effect/cli";
24import { BunRuntime } from "@effect/platform-bun";
25import { FetchHttpClient, HttpApiClient } from "@effect/platform";
26import * as Effect from "effect/Effect";
27import * as Option from "effect/Option";
28import * as Cause from "effect/Cause";
29
30import { ExecutorApi } from "@executor/api";
31import { createServerHandlers, runMcpStdioServer, getExecutor } from "@executor/server";
32
33// ---------------------------------------------------------------------------
34// Constants
35// ---------------------------------------------------------------------------
36
37const CLI_NAME = "executor";
38const { version: CLI_VERSION } = await import("../package.json");
39const DEFAULT_PORT = 8788;
40const DEFAULT_BASE_URL = `http://localhost:${DEFAULT_PORT}`;
41
42// Embedded web UI — baked into compiled binaries via `with { type: "file" }`
43const 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
52const 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
63const appendUrlPath = (baseUrl: string, pathname: string): string =>
64 new URL(pathname, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`).toString();
65
66const 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
92const 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
101const script = process.argv[1];
102const isDevMode = script?.endsWith(".ts") || script?.endsWith(".js");
103const cliPrefix = isDevMode ? `bun run ${script}` : "executor";
104
105const 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
116const 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
138const 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
147const WEB_DIST_DIR = resolve(import.meta.dirname, "../../web/dist");
148
149const 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
189const 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
231const 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
241const 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
281const 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
316const 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
346const 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
354const 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
364const 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
373const runCli = Command.run(root, {
374 name: CLI_NAME,
375 version: CLI_VERSION,
376 executable: CLI_NAME,
377});
378
379const 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
388BunRuntime.runMain(program as Effect.Effect<void, never, never>);
apps/cli/src/release.ts+270−0
@@ -0,0 +1,270 @@
1import { existsSync } from "node:fs";
2import { mkdir, readdir, rename, rm } from "node:fs/promises";
3import { dirname, join, resolve } from "node:path";
4import { fileURLToPath } from "node:url";
5
6type ReleaseChannel = "latest" | "beta";
7
8type ReleaseCliOptions = {
9 readonly dryRun: boolean;
10};
11
12type CommandInput = {
13 readonly command: string;
14 readonly args: ReadonlyArray<string>;
15 readonly cwd: string;
16 readonly captureOutput?: boolean;
17};
18
19type CommandOutput = {
20 readonly stdout: string;
21 readonly stderr: string;
22};
23
24const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
25const cliRoot = resolve(repoRoot, "apps/cli");
26const distDir = resolve(cliRoot, "dist");
27const releaseDir = resolve(distDir, "release");
28const wrapperDir = resolve(distDir, "executor");
29const versionPackagePath = resolve(cliRoot, "package.json");
30const 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
33const 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
48const 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
77const 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
88const validateVersion = (version: string): void => {
89 if (!semverPattern.test(version)) {
90 throw new Error(`${versionPackagePath} version is not valid semver: ${version}`);
91 }
92};
93
94const resolveChannel = (version: string): ReleaseChannel =>
95 version.includes("-") ? "beta" : "latest";
96
97const 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
111const 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
120const 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
150const 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
161const 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
171const 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
217const 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
270await 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---
2title: "Introduction"
3description: "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
8The docs set has been intentionally removed for now while the plugin architecture is still shifting.
9
10Use 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
2set -euo pipefail
3SOURCE="$0"
4while [ -L "$SOURCE" ]; do
5 DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
6 SOURCE="$(readlink "$SOURCE")"
7 [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE"
8done
9SCRIPT_DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
10exec 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 @@
1import { describe, expect, it } from "@effect/vitest";
2
3import { decideInteractionHandling } from "./interaction-handling";
4
5describe("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 @@
1import type { ParsedInteractionPayload } from "./pending-interaction-output";
2
3export type InteractionHandling =
4 | "url_interactive"
5 | "url_paused"
6 | "form_interactive"
7 | "form_paused";
8
9export 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 @@
1import { spawn } from "node:child_process";
2import { createRequire } from "node:module";
3import { dirname } from "node:path";
4import { createInterface } from "node:readline/promises";
5import { FileSystem } from "@effect/platform";
6import { Args, Command, Options } from "@effect/cli";
7import {
8 NodeFileSystem,
9 NodePath,
10 NodeRuntime,
11} from "@effect/platform-node";
12import {
13 createExecutorApiEffectClient as createExecutorApiClient,
14 type ExecutorApiEffectClient as ExecutorApiClient,
15} from "@executor/platform-api/effect";
16import { runExecutorMcpStdioServer } from "@executor/executor-mcp";
17import {
18 googleDiscoverySdkPlugin,
19} from "@executor/plugin-google-discovery-sdk";
20import {
21 graphqlSdkPlugin,
22} from "@executor/plugin-graphql-sdk";
23import {
24 keychainSecretStoreSdkPlugin,
25} from "@executor/plugin-keychain-secret-store-sdk";
26import {
27 localSecretStoreSdkPlugin,
28} from "@executor/plugin-local-secret-store-sdk";
29import {
30 localToolsSdkPlugin,
31} from "@executor/plugin-local-tools-sdk";
32import {
33 mcpSdkPlugin,
34} from "@executor/plugin-mcp-sdk";
35import {
36 openApiSdkPlugin,
37} from "@executor/plugin-openapi-sdk";
38import {
39 getExecutorInternalToolHelpLines,
40 RuntimeExecutionResolverService,
41} from "@executor/platform-sdk/runtime";
42import type {
43 ExecutorSdkPluginRegistry,
44} from "@executor/platform-sdk/plugins";
45import {
46 createExecutorEffect,
47 type ExecutorEffect as Executor,
48} from "@executor/platform-sdk/effect";
49import {
50 createLocalExecutorBackend,
51} from "@executor/platform-sdk-file";
52import {
53 ExecutionIdSchema,
54 type ExecutionEnvelope,
55 type ExecutionInteraction,
56} from "@executor/platform-sdk/schema";
57import type { ToolCatalog } from "@executor/codemode-core";
58
59import * as Effect from "effect/Effect";
60import * as Schema from "effect/Schema";
61import * as Option from "effect/Option";
62import * as Cause from "effect/Cause";
63
64import {
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";
81import {
82 resolveCliLocalDataDir,
83 resolveRuntimeWebAssetsDir,
84 resolveSelfCommand,
85} from "./runtime-paths";
86import {
87 buildPausedExecutionOutput,
88 parseInteractionPayload,
89} from "./pending-interaction-output";
90import { decideInteractionHandling } from "./interaction-handling";
91import {
92 renderMcpSessionSummary,
93 renderWebSessionSummary,
94} from "./session-summary";
95import {
96 executorAppEffectError,
97 type LocalServerReachabilityTimeoutError,
98 localServerReachabilityTimeoutError,
99} from "../effect-errors";
100
101const toError = (cause: unknown): Error =>
102 cause instanceof Error ? cause : new Error(String(cause));
103const sleep = (ms: number) =>
104 Effect.promise(() => new Promise<void>((resolve) => setTimeout(resolve, ms)));
105
106const 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
127const 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
144const 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
157const 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
188const getBootstrapClient = (baseUrl: string = DEFAULT_SERVER_BASE_URL) =>
189 createExecutorApiClient({ baseUrl });
190
191const decodeExecutionId = Schema.decodeUnknown(ExecutionIdSchema);
192const require = createRequire(import.meta.url);
193const CLI_NAME = "executor";
194const CLI_LOCAL_DATA_DIR = resolveCliLocalDataDir();
195const 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})();
214const HELP_TOKENS = ["--help", "-h", "help"] as const;
215
216const isHelpToken = (value: string | undefined): boolean =>
217 value !== undefined && HELP_TOKENS.includes(value as (typeof HELP_TOKENS)[number]);
218
219const normalizeCliArgs = (rawArgs: readonly string[]): string[] => {
220 return rawArgs[0] === "run"
221 ? ["call", ...rawArgs.slice(1)]
222 : [...rawArgs];
223};
224
225const getCliArgs = (): string[] => normalizeCliArgs(process.argv.slice(2));
226
227const toEffectCliArgv = (args: readonly string[]): string[] => [
228 process.execPath || CLI_NAME,
229 CLI_NAME,
230 ...args,
231];
232
233const 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
259const getDefaultRunWorkflow = (pluginRegistry?: ExecutorSdkPluginRegistry) =>
260 buildWorkflowText([], pluginRegistry);
261
262const indentBlock = (value: string, prefix: string = " "): string =>
263 value
264 .split("\n")
265 .map((line) => (line.length > 0 ? `${prefix}${line}` : ""))
266 .join("\n");
267
268const 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
288const 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
295const closeExecutor = (executor: Executor) =>
296 Effect.tryPromise({
297 try: () => executor.close(),
298 catch: toError,
299 }).pipe(Effect.catchAll(() => Effect.void));
300
301const 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
322const 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
393const 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
426const 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
467const 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
481const 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
495const 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
502const 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
514const 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
540const 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
560const 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
577const 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
591const printText = (value: string) =>
592 Effect.sync(() => {
593 console.log(value);
594 });
595
596const 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
616const 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
628const 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
651const 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
666const isRecord = (value: unknown): value is Record<string, unknown> =>
667 typeof value === "object" && value !== null && !Array.isArray(value);
668
669type PromptField = {
670 name: string;
671 label: string;
672 description?: string;
673 type: string;
674 required: boolean;
675 enumValues?: readonly unknown[];
676};
677
678const 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
711const 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
757const 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
806const 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
821const executionInteractionMode = (): "live_form" | "detach" =>
822 process.stdin.isTTY && process.stdout.isTTY ? "live_form" : "detach";
823
824const 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
870const 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
897const 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
925const 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
1032const 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
1040const serverCommand = Command.make("server").pipe(
1041 Command.withSubcommands([serverStartCommand] as const),
1042 Command.withDescription("Local server commands"),
1043);
1044
1045const 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
1053const 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
1066const 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
1110const 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
1143const devCommand = Command.make("dev").pipe(
1144 Command.withDescription("Development helpers"),
1145);
1146
1147const 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
1159const runCli = Command.run(root, {
1160 name: CLI_NAME,
1161 version: CLI_VERSION,
1162 executable: CLI_NAME,
1163});
1164
1165const 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
1181const 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.
1196NodeRuntime.runMain(program as Effect.Effect<void, never, never>);
apps/executor/src/cli/pending-interaction-output.ts+0−125
@@ -1,125 +0,0 @@
1import type { ExecutionInteraction } from "@executor/platform-sdk/schema";
2
3const isRecord = (value: unknown): value is Record<string, unknown> =>
4 typeof value === "object" && value !== null && !Array.isArray(value);
5
6export type ParsedInteractionPayload = {
7 message: string;
8 mode: "form" | "url";
9 url?: string;
10 requestedSchema?: Record<string, unknown>;
11};
12
13export 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
44const shellEscape = (value: string): string => {
45 if (/^[A-Za-z0-9_./:=+-]+$/.test(value)) {
46 return value;
47 }
48
49 return `'${value.replace(/'/g, `'"'"'`)}'`;
50};
51
52const renderCommand = (argv: readonly string[]): string => argv.map(shellEscape).join(" ");
53
54const 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
63const 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
85export 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 @@
1import { join } from "node:path";
2import { describe, expect, it } from "@effect/vitest";
3
4import {
5 DEFAULT_EXECUTOR_DATA_DIR,
6 DEFAULT_LOCAL_DATA_DIR,
7} from "@executor/server";
8
9import {
10 resolveCliLocalDataDir,
11} from "./runtime-paths";
12
13describe("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 @@
1import { existsSync } from "node:fs";
2import { dirname, extname, join, resolve } from "node:path";
3import { fileURLToPath } from "node:url";
4
5import {
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
12const sourceDir = dirname(fileURLToPath(import.meta.url));
13
14const trim = (value: string | undefined): string | undefined => {
15 const candidate = value?.trim();
16 return candidate && candidate.length > 0 ? candidate : undefined;
17};
18
19const 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
29const 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
42const isSourceCliLaunch = (): boolean => getSourceEntrypoint() !== null;
43
44const resolveBundledNodeLauncher = (): string | null => {
45 const candidate = resolve(sourceDir, "executor.js");
46 return existsSync(candidate) ? candidate : null;
47};
48
49
50const 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
72export 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
84export 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
94export 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 @@
1import { describe, expect, it } from "@effect/vitest";
2
3import {
4 appendUrlPath,
5 renderMcpSessionSummary,
6 renderUpSummary,
7 renderWebSessionSummary,
8} from "./session-summary";
9
10describe("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 @@
1export const appendUrlPath = (baseUrl: string, pathname: string): string =>
2 new URL(pathname, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`).toString();
3
4type SessionSummaryInput = {
5 readonly baseUrl: string;
6 readonly workspaceId?: string | null;
7};
8
9const 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
34export const renderWebSessionSummary = (input: SessionSummaryInput): string =>
35 renderSessionSummary("web", input);
36
37export const renderMcpSessionSummary = (input: SessionSummaryInput): string =>
38 renderSessionSummary("mcp", input);
39
40type UpSummaryInput = {
41 readonly started: boolean;
42 readonly status: {
43 readonly baseUrl: string;
44 readonly installation: {
45 readonly workspaceId: string;
46 } | null;
47 };
48};
49
50export 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 @@
1import { spawn } from "node:child_process";
2import { existsSync, readFileSync } from "node:fs";
3import { chmod, cp, mkdir, rename, rm, writeFile } from "node:fs/promises";
4import { createRequire } from "node:module";
5import { dirname, join, resolve } from "node:path";
6
7import { readDistributionPackageMetadata, repoRoot } from "./metadata";
8
9const defaultOutputDir = resolve(repoRoot, "apps/executor/dist/npm");
10
11
12export type BuildDistributionPackageOptions = {
13 outputDir?: string;
14 packageName?: string;
15 packageVersion?: string;
16 buildWeb?: boolean;
17};
18
19export type DistributionPackageArtifact = {
20 packageDir: string;
21 launcherPath: string;
22 bundlePath: string;
23 resourcesDir: string;
24};
25
26type BundledDependency = {
27 name: string;
28 version: string;
29 packageDir: string;
30};
31
32type CommandInput = {
33 command: string;
34 args: ReadonlyArray<string>;
35 cwd: string;
36};
37
38const 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
80const 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
99const 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
133const 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
150const 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
198const 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
244const 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
272export 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 @@
1import { existsSync, readFileSync } from "node:fs";
2import { join } from "node:path";
3
4import { describe, expect, it } from "@effect/vitest";
5import * as Effect from "effect/Effect";
6
7import {
8 DistributionHarness,
9 LocalDistributionHarnessLive,
10} from "./harness";
11
12describe("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 @@
1import { spawn } from "node:child_process";
2import { createServer } from "node:net";
3import { tmpdir } from "node:os";
4import { dirname, join } from "node:path";
5
6import { FileSystem } from "@effect/platform";
7import { NodeFileSystem } from "@effect/platform-node";
8import * as Context from "effect/Context";
9import * as Effect from "effect/Effect";
10import * as Layer from "effect/Layer";
11
12import { buildDistributionPackage } from "./artifact";
13import { executorAppEffectError } from "../effect-errors";
14
15const toError = (cause: unknown): Error =>
16 cause instanceof Error ? cause : new Error(String(cause));
17
18type CommandResult = {
19 readonly stdout: string;
20 readonly stderr: string;
21 readonly exitCode: number;
22};
23
24export 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
61const SERVER_WAIT_TIMEOUT_MS = 5_000;
62const SERVER_POLL_INTERVAL_MS = 100;
63
64const 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
123const 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
150const 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
159const 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
182const 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
212export 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 @@
1import { readFile } from "node:fs/promises";
2import { dirname, resolve } from "node:path";
3import { fileURLToPath } from "node:url";
4
5export const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../../..");
6const packageMetadataPath = resolve(repoRoot, "apps/executor/package.json");
7
8export 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
24export 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 @@
1import { spawn } from "node:child_process";
2import { mkdir, rm } from "node:fs/promises";
3import { join, resolve } from "node:path";
4
5import { buildDistributionPackage } from "./artifact";
6import { readDistributionPackageMetadata, repoRoot } from "./metadata";
7
8const defaultReleaseDir = resolve(repoRoot, "apps/executor/dist/release");
9const 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
12type PublishCliOptions = {
13 dryRun: boolean;
14};
15
16type CommandInput = {
17 command: string;
18 args: ReadonlyArray<string>;
19 cwd: string;
20};
21
22type CommandOutput = {
23 stdout: string;
24 stderr: string;
25};
26
27type PackResult = {
28 filename?: string;
29};
30
31const 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
48const 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
93const 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
107const 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
116const 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
122const resolveChannel = (version: string): "latest" | "beta" =>
123 version.includes("-") ? "beta" : "latest";
124
125const 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
141const 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
154const 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
189const 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
224await main();
apps/executor/src/effect-errors.ts+0−40
@@ -1,40 +0,0 @@
1import * as Data from "effect/Data";
2
3export class ExecutorAppEffectError extends Data.TaggedError(
4 "ExecutorAppEffectError",
5)<{
6 readonly module: string;
7 readonly message: string;
8}> {}
9
10export const executorAppEffectError = (
11 module: string,
12 message: string,
13) => new ExecutorAppEffectError({ module, message });
14
15export 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
25export 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 @@
1import { createServerHandlersWithExecutor, type ServerHandlers } from "./main";
2import { createServerExecutorHandle } from "./services/executor";
3
4export type HotBackend = ServerHandlers & {
5 readonly dispose: () => Promise<void>;
6};
7
8export 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 @@
1import { HttpApiBuilder } from "@effect/platform";
2import { Effect } from "effect";
3
4import { ExecutorApi } from "@executor/api";
5import {
6 formatExecuteResult,
7 formatPausedExecution,
8 type ExecutionEngine,
9} from "@executor/execution";
10import { ExecutionEngineService } from "../services/engine";
11
12export 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 @@
1import { Effect, Layer } from "effect";
2import {
3 GoogleDiscoveryExtensionService,
4 GoogleDiscoveryHandlers,
5} from "@executor/plugin-google-discovery/api";
6import { ExecutorService } from "../services/executor";
7
8const GoogleDiscoveryExtensionLive = Layer.effect(
9 GoogleDiscoveryExtensionService,
10 Effect.map(ExecutorService, (executor) => executor.googleDiscovery),
11);
12
13export const GoogleDiscoveryHandlersLive = Layer.provide(
14 GoogleDiscoveryHandlers,
15 GoogleDiscoveryExtensionLive,
16);
apps/server/src/handlers/graphql.ts+17−0
@@ -0,0 +1,17 @@
1import { Effect, Layer } from "effect";
2import {
3 GraphqlHandlers,
4 GraphqlExtensionService,
5} from "@executor/plugin-graphql/api";
6import { ExecutorService } from "../services/executor";
7
8// Wire GraphqlExtensionService from the executor's graphql extension
9const GraphqlExtensionLive = Layer.effect(
10 GraphqlExtensionService,
11 Effect.map(ExecutorService, (executor) => executor.graphql),
12);
13
14export const GraphqlHandlersLive = Layer.provide(
15 GraphqlHandlers,
16 GraphqlExtensionLive,
17);
apps/server/src/handlers/mcp-source.ts+17−0
@@ -0,0 +1,17 @@
1import { Effect, Layer } from "effect";
2import {
3 McpHandlers,
4 McpExtensionService,
5} from "@executor/plugin-mcp/api";
6import { ExecutorService } from "../services/executor";
7
8// Wire McpExtensionService from the executor's mcp extension
9const McpExtensionLive = Layer.effect(
10 McpExtensionService,
11 Effect.map(ExecutorService, (executor) => executor.mcp),
12);
13
14export const McpSourceHandlersLive = Layer.provide(
15 McpHandlers,
16 McpExtensionLive,
17);
apps/server/src/handlers/onepassword.ts+17−0
@@ -0,0 +1,17 @@
1import { Effect, Layer } from "effect";
2import {
3 OnePasswordHandlers,
4 OnePasswordExtensionService,
5} from "@executor/plugin-onepassword/api";
6import { ExecutorService } from "../services/executor";
7
8// Wire OnePasswordExtensionService from the executor's onepassword extension
9const OnePasswordExtensionLive = Layer.effect(
10 OnePasswordExtensionService,
11 Effect.map(ExecutorService, (executor) => executor.onepassword),
12);
13
14export const OnePasswordHandlersLive = Layer.provide(
15 OnePasswordHandlers,
16 OnePasswordExtensionLive,
17);
apps/server/src/handlers/openapi.ts+17−0
@@ -0,0 +1,17 @@
1import { Effect, Layer } from "effect";
2import {
3 OpenApiHandlers,
4 OpenApiExtensionService,
5} from "@executor/plugin-openapi/api";
6import { ExecutorService } from "../services/executor";
7
8// Wire OpenApiExtensionService from the executor's openapi extension
9const OpenApiExtensionLive = Layer.effect(
10 OpenApiExtensionService,
11 Effect.map(ExecutorService, (executor) => executor.openapi),
12);
13
14export const OpenApiHandlersLive = Layer.provide(
15 OpenApiHandlers,
16 OpenApiExtensionLive,
17);
apps/server/src/handlers/scope.ts+20−0
@@ -0,0 +1,20 @@
1import { HttpApiBuilder } from "@effect/platform";
2import { Effect } from "effect";
3
4import { ExecutorApi } from "@executor/api";
5import { ExecutorService } from "../services/executor";
6
7export 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 @@
1import { HttpApiBuilder } from "@effect/platform";
2import { Effect, Option } from "effect";
3import type { SecretId, ScopeId } from "@executor/sdk";
4
5import { ExecutorApi } from "@executor/api";
6import { ExecutorService } from "../services/executor";
7
8const 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
24export 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 @@
1import { HttpApiBuilder } from "@effect/platform";
2import { Effect } from "effect";
3
4import { ExecutorApi } from "@executor/api";
5import { ExecutorService } from "../services/executor";
6
7export 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 @@
1import { HttpApiBuilder } from "@effect/platform";
2import { Effect } from "effect";
3
4import { ExecutorApi } from "@executor/api";
5import { ExecutorService } from "../services/executor";
6
7export 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 @@
1export { createApiHandler, createServerHandlers, type ApiHandler, type ServerHandlers, ApiLayer } from "./main";
2export { createServerHandlersWithExecutor } from "./main";
3export { ExecutorServiceLayer, createServerExecutorHandle, disposeExecutor, getExecutor, reloadExecutor } from "./services/executor";
4export { createMcpRequestHandler, runMcpStdioServer, type McpRequestHandler } from "./mcp";
apps/server/src/main.ts+128−0
@@ -0,0 +1,128 @@
1import {
2 HttpApiBuilder,
3 HttpApiSwagger,
4 HttpMiddleware,
5 HttpServer,
6} from "@effect/platform";
7import { Effect, Layer } from "effect";
8
9import { addGroup } from "@executor/api";
10import { createExecutionEngine } from "@executor/execution";
11import { OpenApiGroup } from "@executor/plugin-openapi/api";
12import { McpGroup } from "@executor/plugin-mcp/api";
13import { GoogleDiscoveryGroup } from "@executor/plugin-google-discovery/api";
14import { OnePasswordGroup } from "@executor/plugin-onepassword/api";
15import { GraphqlGroup } from "@executor/plugin-graphql/api";
16import { ToolsHandlers } from "./handlers/tools";
17import { SourcesHandlers } from "./handlers/sources";
18import { SecretsHandlers } from "./handlers/secrets";
19import { ExecutionsHandlers } from "./handlers/executions";
20import { ScopeHandlers } from "./handlers/scope";
21import { OpenApiHandlersLive } from "./handlers/openapi";
22import { McpSourceHandlersLive } from "./handlers/mcp-source";
23import { GoogleDiscoveryHandlersLive } from "./handlers/google-discovery";
24import { OnePasswordHandlersLive } from "./handlers/onepassword";
25import { GraphqlHandlersLive } from "./handlers/graphql";
26import { ExecutorService, ExecutorServiceLayer, getExecutor, type ServerExecutor } from "./services/executor";
27import { ExecutionEngineService } from "./services/engine";
28import { createMcpRequestHandler, type McpRequestHandler } from "./mcp";
29
30// ---------------------------------------------------------------------------
31// Composed API — core + plugin groups
32// ---------------------------------------------------------------------------
33
34const ExecutorApiWithPlugins = addGroup(OpenApiGroup)
35 .add(McpGroup)
36 .add(GoogleDiscoveryGroup)
37 .add(OnePasswordGroup)
38 .add(GraphqlGroup);
39
40// ---------------------------------------------------------------------------
41// API Layer
42// ---------------------------------------------------------------------------
43
44const 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
63export 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
72export type ServerHandlers = {
73 readonly api: {
74 readonly handler: (request: Request) => Promise<Response>;
75 readonly dispose: () => Promise<void>;
76 };
77 readonly mcp: McpRequestHandler;
78};
79
80const 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
92export 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
102export const createServerHandlers = async (): Promise<ServerHandlers> =>
103 createServerHandlersWithExecutor(await getExecutor());
104
105// ---------------------------------------------------------------------------
106// Backwards compat — standalone API handler (no MCP)
107// ---------------------------------------------------------------------------
108
109const ExecutionEngineLayer = Layer.effect(
110 ExecutionEngineService,
111 Effect.map(ExecutorService, (executor) => createExecutionEngine({ executor })),
112);
113
114export 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
126export type ApiHandler = ReturnType<typeof createApiHandler>;
127
128export { ExecutorServiceLayer } from "./services/executor";
apps/server/src/mcp.ts+122−0
@@ -0,0 +1,122 @@
1import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
4
5import { createExecutorMcpServer, type ExecutorMcpServerConfig } from "@executor/host-mcp";
6
7// ---------------------------------------------------------------------------
8// Streamable HTTP handler
9// ---------------------------------------------------------------------------
10
11export type McpRequestHandler = {
12 readonly handleRequest: (request: Request) => Promise<Response>;
13 readonly close: () => Promise<void>;
14};
15
16const 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
22export 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
96export 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 @@
1import { Context } from "effect";
2import type { ExecutionEngine } from "@executor/execution";
3
4export class ExecutionEngineService extends Context.Tag("ExecutionEngineService")<
5 ExecutionEngineService,
6 ExecutionEngine
7>() {}
apps/server/src/services/executor.ts+205−0
@@ -0,0 +1,205 @@
1import { Context, Effect, Layer, ManagedRuntime } from "effect";
2import { SqliteClient } from "@effect/sql-sqlite-bun";
3import * as SqlClient from "@effect/sql/SqlClient";
4import { NodeFileSystem } from "@effect/platform-node";
5import * as fs from "node:fs";
6
7import { createExecutor, scopeKv } from "@executor/sdk";
8import {
9 makeSqliteKv,
10 makeKvConfig,
11 makeScopedKv,
12 migrate,
13} from "@executor/storage-file";
14import { withConfigFile } from "@executor/config";
15import {
16 openApiPlugin,
17 makeKvOperationStore,
18 type OpenApiPluginExtension,
19} from "@executor/plugin-openapi";
20import {
21 mcpPlugin,
22 makeKvBindingStore,
23 type McpPluginExtension,
24} from "@executor/plugin-mcp";
25import {
26 googleDiscoveryPlugin,
27 makeKvBindingStore as makeKvGoogleDiscoveryBindingStore,
28 type GoogleDiscoveryPluginExtension,
29} from "@executor/plugin-google-discovery";
30import {
31 graphqlPlugin,
32 makeKvOperationStore as makeKvGraphqlOperationStore,
33 type GraphqlPluginExtension,
34} from "@executor/plugin-graphql";
35import { keychainPlugin } from "@executor/plugin-keychain";
36import { fileSecretsPlugin } from "@executor/plugin-file-secrets";
37import {
38 onepasswordPlugin,
39 type OnePasswordExtension,
40} from "@executor/plugin-onepassword";
41
42import type { Executor, ExecutorPlugin } from "@executor/sdk";
43
44type 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];
52export type ServerExecutor = Executor<ServerPlugins>;
53export type ServerExecutorHandle = {
54 readonly executor: ServerExecutor;
55 readonly dispose: () => Promise<void>;
56};
57
58// ---------------------------------------------------------------------------
59// Service tag
60// ---------------------------------------------------------------------------
61
62export class ExecutorService extends Context.Tag("ExecutorService")<
63 ExecutorService,
64 ServerExecutor
65>() {}
66
67// ---------------------------------------------------------------------------
68// Data directory
69// ---------------------------------------------------------------------------
70
71import { homedir } from "node:os";
72import { join } from "node:path";
73
74const resolveDataDir = (): string => {
75 if (process.env.EXECUTOR_DATA_DIR) return process.env.EXECUTOR_DATA_DIR;
76 return join(homedir(), ".executor");
77};
78
79const DATA_DIR = resolveDataDir();
80
81fs.mkdirSync(DATA_DIR, { recursive: true });
82
83const DB_PATH = `${DATA_DIR}/data.db`;
84
85// ---------------------------------------------------------------------------
86// Executor Layer — SQLite-backed, scoped to ManagedRuntime lifetime
87// ---------------------------------------------------------------------------
88
89const 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
148export 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
162let sharedHandlePromise: Promise<ServerExecutorHandle> | null = null;
163
164const 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 */
175export 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 */
182export 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 */
193export 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 */
202export 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 @@
1{1{
2 "$schema": "https://ui.shadcn.com/schema.json",2 "$schema": "https://ui.shadcn.com/schema.json",
3 "style": "base-nova",3 "style": "new-york",
4 "rsc": false,4 "rsc": false,
5 "tsx": true,5 "tsx": true,
6 "tailwind": {6 "tailwind": {
7 "config": "",7 "config": "",
8 "css": "src/globals.css",8 "css": "../../packages/ui/src/styles/globals.css",
9 "baseColor": "neutral",9 "baseColor": "neutral",
10 "cssVariables": true,10 "cssVariables": true
11 "prefix": ""
12 },11 },
13 "iconLibrary": "lucide",12 "iconLibrary": "lucide",
14 "aliases": {13 "aliases": {
15 "components": "@/components",14 "components": "@/components",
16 "hooks": "@/hooks",15 "hooks": "@/hooks",
17 "lib": "@/lib",16 "lib": "@/lib",
18 "utils": "@/lib/utils",17 "utils": "@executor/ui/lib/utils",
19 "ui": "@/components/ui"18 "ui": "@executor/ui/components"
20 }19 }
21}20}
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 @@
1{1{
2 "name": "@executor/web",2 "name": "@executor/web",
3 "version": "1.4.0-beta.0",
3 "private": true,4 "private": true,
4 "type": "module",5 "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 },
11 "dependencies": {6 "dependencies": {
12 "@base-ui/react": "^1.3.0",7 "@executor/plugin-onepassword": "workspace:*",
13 "@executor/plugin-execution-history-react": "workspace:*",8 "@executor/plugin-mcp": "workspace:*",
14 "@executor/plugin-google-discovery-react": "workspace:*",9 "@executor/plugin-google-discovery": "workspace:*",
15 "@executor/plugin-graphql-react": "workspace:*",10 "@executor/plugin-graphql": "workspace:*",
16 "@executor/plugin-local-tools-react": "workspace:*",11 "@executor/plugin-openapi": "workspace:*",
17 "@executor/plugin-mcp-react": "workspace:*",12 "@executor/sdk": "workspace:*",
18 "@executor/plugin-onepassword-react": "workspace:*",
19 "@executor/plugin-openapi-react": "workspace:*",
20 "@executor/react": "workspace:*",13 "@executor/react": "workspace:*",
21 "@executor/server": "workspace:*",14 "@executor/server": "workspace:*",
22 "@executor/source-core": "workspace:*",15 "@executor/ui": "workspace:*",
23 "@shikijs/langs": "^4.0.1",16 "@shikijs/langs": "^4.0.2",
24 "@shikijs/themes": "^4.0.1",17 "@shikijs/themes": "^4.0.2",
25 "@tanstack/react-router": "^1.132.7",18 "@tanstack/react-router": "^1.168.10",
26 "class-variance-authority": "^0.7.1",19 "react": "^19.1.0",
27 "clsx": "^2.1.1",20 "react-dom": "^19.1.0",
28 "effect": "catalog:",21 "shiki": "^4.0.2",
29 "lucide-react": "^1.7.0",22 "streamdown": "^2.5.0",
30 "react": "^19.2.0",23 "tailwindcss": "^4.1.10"
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"
38 },24 },
39 "devDependencies": {25 "devDependencies": {
40 "@hono/vite-dev-server": "^0.25.0",26 "@types/react": "^19.1.0",
41 "@tailwindcss/vite": "^4.2.1",27 "@types/react-dom": "^19.1.0",
42 "@types/react": "^19.2.10",28 "@types/node": "catalog:",
43 "@types/react-dom": "^19.2.3",29 "@tailwindcss/vite": "^4.1.10",
44 "@vitejs/plugin-react": "^5.1.4",30 "@vitejs/plugin-react": "^4.5.2",
45 "bun-types": "catalog:",31 "typescript": "^5.9.3",
46 "tailwindcss": "^4.2.1",32 "vite": "^6.3.5"
47 "tw-animate-css": "^1.4.0",
48 "vite": "^7.3.1"
49 },33 },
50 "version": "0.0.0"34 "scripts": {
35 "dev": "bunx --bun vite",
36 "build": "vite build",
37 "typecheck": "tsc --noEmit"
38 }
51}39}
apps/web/src/App.tsx+6−0
@@ -0,0 +1,6 @@
1import { RouterProvider } from "@tanstack/react-router";
2import { router } from "./router";
3
4export function App() {
5 return <RouterProvider router={router} />;
6}
apps/web/src/components/code-block.tsx+0−96
@@ -1,96 +0,0 @@
1import { useEffect, useState, useRef, useCallback } from "react";
2import { Button } from "@executor/react/plugins";
3import { codeToHtml, resolveLang } from "../lib/shiki";
4import { cn } from "../lib/utils";
5import { IconCopy, IconCheck } from "./icons";
6
7// Lazily loaded, cached across renders
8const highlightCache = new Map<string, string>();
9
10function cacheKey(code: string, lang: string) {
11 return `${lang}::${code.length}::${code.slice(0, 64)}`;
12}
13
14function 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
23export 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 @@
1import { cn } from "../lib/utils";
2import { CodeBlock } from "./code-block";
3
4export 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 @@
1import type { SVGProps } from "react";
2import { cn } from "../lib/utils";
3
4type IconProps = SVGProps<SVGSVGElement> & { className?: string };
5
6export 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
17export 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
25export 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
34export 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
42export 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
50export 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
59export 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
68export 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
77export 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
85export 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
93export 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
102export 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
111export 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
121export 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
129export 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
138export 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
146export 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
154export 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 @@
1import type { ReactNode } from "react";
2import type { Loadable } from "@executor/react";
3import { IconSpinner, IconEmpty } from "./icons";
4
5export 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
34export 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 @@
1import { useEffect, useRef, useState } from "react";
2import { Button } from "@executor/react/plugins";
3import { CodeBlock } from "./code-block";
4
5type LocalMcpInstallMode = "stdio" | "http";
6
7const 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 */
14async 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
73function 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
141export 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 @@
1import { useEffect, useState } from "react";
2import { Button } from "@executor/ui/components/button";
3import { CodeBlock } from "@executor/ui/components/code-block";
4
5type TransportMode = "stdio" | "http";
6
7const isDev = import.meta.env.DEV;
8
9export 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 @@
1import { Link, Outlet, useLocation, useMatchRoute } from "@tanstack/react-router";
2import { useCallback, useEffect, useState } from "react";
3import { useSources, type Source } from "@executor/react";
4import { Button, sourcePluginsIndexPath } from "@executor/react/plugins";
5import { cn } from "../lib/utils";
6import { IconPlus, IconCopy, IconCheck, IconClose, IconMenu } from "./icons";
7import { LoadableBlock } from "./loadable";
8import { SourceFavicon } from "./source-favicon";
9import {
10 getSourceFrontendPaths,
11 registeredFrontendPluginNavRoutes,
12} from "../plugins";
13
14// ── Status dot color ─────────────────────────────────────────────────────
15
16const 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
24type AppMetaEnv = {
25 readonly VITE_APP_VERSION: string;
26 readonly VITE_GITHUB_URL: string;
27};
28
29const { VITE_APP_VERSION, VITE_GITHUB_URL } = (import.meta as ImportMeta & {
30 readonly env: AppMetaEnv;
31}).env;
32
33type UpdateChannel = "latest" | "beta";
34
35const EXECUTOR_DIST_TAGS_PATH = "/v1/app/npm/dist-tags";
36
37type ParsedVersion = {
38 readonly major: number;
39 readonly minor: number;
40 readonly patch: number;
41 readonly prerelease: ReadonlyArray<string | number> | null;
42};
43
44const semverPattern =
45 /^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<prerelease>[0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
46
47const resolveUpdateChannel = (version: string): UpdateChannel =>
48 version.includes("-beta.") ? "beta" : "latest";
49
50const 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
68const 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
119const 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
143function 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
175function 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 ─────────────────────────────────────────────────────────────
224export 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
349function 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
488function 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
541function 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 @@
1import { useState } from "react";
2import type { Source } from "@executor/react";
3import { getGoogleDiscoveryIconUrlForService } from "@executor/plugin-google-discovery-react";
4import { getSourceFrontendIconUrl } from "../plugins";
5import type { SourcePreset } from "../plugins/source-presets";
6import { getSourceFaviconUrl } from "../lib/source-favicon";
7import { cn } from "../lib/utils";
8
9type SourceKind = Source["kind"] | SourcePreset["kind"] | string;
10
11export 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
30export 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
53function 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
86export 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 @@
1import { Link } from "@tanstack/react-router";
2import { sourcePluginsIndexPath } from "@executor/react/plugins";
3
4import { IconEmpty } from "./icons";
5import { cn } from "../lib/utils";
6
7export 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 @@
1import type { ReactNode } from "react";
2
3type SourcePluginsResetStateProps = {
4 title: string;
5 message: string;
6 action?: ReactNode;
7};
8
9export 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 @@
1import type { Source } from "@executor/react";
2
3import { Badge, Button } from "@executor/react/plugins";
4import { cn } from "../lib/utils";
5import { IconSpinner, IconTool } from "./icons";
6
7export 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 @@
1import { useMemo, useState } from "react";
2import { useAtomValue, toolSchemaAtom, Result, ScopeId, ToolId } from "@executor/react";
3import { CodeBlock } from "@executor/ui/components/code-block";
4import { Markdown } from "@executor/ui/components/markdown";
5import { schemaToTypeDeclaration } from "../lib/schema-type-signature";
6
7// ---------------------------------------------------------------------------
8// Copy button
9// ---------------------------------------------------------------------------
10
11function 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
44const 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
64export 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
184export 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 @@
1import { useEffect, useMemo, useRef, useState } from "react";
2
3// ---------------------------------------------------------------------------
4// Types
5// ---------------------------------------------------------------------------
6
7export interface ToolSummary {
8 readonly id: string;
9 readonly name: string;
10 readonly pluginKey: string;
11 readonly description?: string;
12}
13
14type TreeNode = {
15 segment: string;
16 tool?: ToolSummary;
17 children: Map<string, TreeNode>;
18};
19
20// ---------------------------------------------------------------------------
21// Tree builder
22// ---------------------------------------------------------------------------
23
24const 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
44const 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
56const 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
115function 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
224function 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
273export 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 */
8import { join } from "node:path";
9import * as Cause from "effect/Cause";
10import * as Effect from "effect/Effect";
11import * as Exit from "effect/Exit";
12import * as Runtime from "effect/Runtime";
13import * as Scope from "effect/Scope";
14import {
15 createLocalExecutorRequestHandler,
16 DEFAULT_EXECUTOR_DATA_DIR,
17} from "@executor/server";
18
19const MAX_LOGGED_ERROR_BODY_LENGTH = 4_000;
20const EXECUTOR_WEB_DEV_LOCAL_DATA_DIR_ENV = "EXECUTOR_WEB_DEV_LOCAL_DATA_DIR";
21const DEFAULT_WEB_DEV_LOCAL_DATA_DIR = join(
22 DEFAULT_EXECUTOR_DATA_DIR,
23 "control-plane-web-dev",
24);
25
26const 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
31const 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 */
46const 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.
60const 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
88export 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 @@
1import { createRoot } from "react-dom/client";
2
3class BrowserBuffer extends Uint8Array {}
4
5const browserGlobal = globalThis as any;
6
7if (browserGlobal.Buffer === undefined) {
8 browserGlobal.Buffer = BrowserBuffer;
9}
10
11const { App } = await import("./main");
12
13const rootElement = document.getElementById("root");
14
15if (!rootElement) {
16 throw new Error("Missing #root element");
17}
18
19createRoot(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
11type JsonSchemaRecord = Record<string, unknown>;
12
13const asRecord = (value: unknown): JsonSchemaRecord =>
14 typeof value === "object" && value !== null && !Array.isArray(value)
15 ? (value as JsonSchemaRecord)
16 : {};
17
18const 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
27const truncate = (value: string, maxLength: number): string =>
28 value.length <= maxLength
29 ? value
30 : `${value.slice(0, Math.max(0, maxLength - 4))} ...`;
31
32const propertyLabel = (
33 name: string,
34 schema: JsonSchemaRecord,
35 optional: boolean,
36): string => `${name}${optional ? "?" : ""}: ${schemaToTypeSignature(schema)}`;
37
38const 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
51export 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
103const INDENT = " ";
104
105const refName = (ref: string): string => {
106 const trimmed = ref.trim();
107 return trimmed.length > 0 ? trimmed.split("/").at(-1) ?? trimmed : "unknown";
108};
109
110const 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
131const 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 */
214export 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 @@
1export {
2 getFallbackSourceFaviconUrl,
3 getSourceFaviconUrl,
4} from "@executor/source-core";
apps/web/src/lib/use-scope.ts+1−0
@@ -0,0 +1 @@
1export { useScope } from "@executor/react";
apps/web/src/lib/utils.ts+0−6
@@ -1,6 +0,0 @@
1import { clsx, type ClassValue } from "clsx"
2import { twMerge } from "tailwind-merge"
3
4export function cn(...inputs: ClassValue[]) {
5 return twMerge(clsx(inputs))
6}
apps/web/src/main.tsx+6−137
@@ -1,138 +1,7 @@
1import {1import React from "react";
2 RouterProvider,2import { createRoot } from "react-dom/client";
3 createRootRoute,3import "@executor/ui/globals.css";
4 createRoute,4import { App } from "./App";
5 createRouter,
6 useNavigate,
7} from "@tanstack/react-router";
8import { ExecutorReactProvider } from "@executor/react";
9import {
10 createExecutorPluginPaths,
11 sourcePluginsIndexPath,
12 type ExecutorPluginNavigation,
13 type FrontendPluginRouteSearch,
14} from "@executor/react/plugins";
15 5
16import "./globals.css";6const root = createRoot(document.getElementById("root")!);
17 7root.render(<App />);
18import { AppShell } from "./components/shell";
19import {
20 registeredFrontendPluginRoutes,
21} from "./plugins";
22import {
23 ExecutorPluginRoutePage,
24 SourcePluginsIndexPage,
25} from "./plugins/pages";
26import { HomePage } from "./views/home";
27import { PoliciesPage } from "./views/policies";
28import { SecretsPage } from "./views/secrets";
29
30const rootRoute = createRootRoute({
31 component: AppShell,
32});
33
34const homeRoute = createRoute({
35 getParentRoute: () => rootRoute,
36 path: "/",
37 component: HomePage,
38});
39
40const sourcePluginsIndexRoute = createRoute({
41 getParentRoute: () => rootRoute,
42 path: sourcePluginsIndexPath,
43 component: SourcePluginsIndexPage,
44});
45
46const secretsRoute = createRoute({
47 getParentRoute: () => rootRoute,
48 path: "/secrets",
49 component: SecretsPage,
50});
51
52const policiesRoute = createRoute({
53 getParentRoute: () => rootRoute,
54 path: "/policies",
55 component: PoliciesPage,
56});
57
58const 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
80const 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
114const routeTree = rootRoute.addChildren([
115 homeRoute,
116 secretsRoute,
117 policiesRoute,
118 sourcePluginsIndexRoute,
119 ...frontendPluginRoutes,
120]);
121
122const router = createRouter({
123 routeTree,
124 defaultPreload: "intent",
125 defaultPreloadStaleTime: 0,
126});
127
128declare module "@tanstack/react-router" {
129 interface Register {
130 router: typeof router;
131 }
132}
133
134export const App = () => (
135 <ExecutorReactProvider>
136 <RouterProvider router={router} />
137 </ExecutorReactProvider>
138);
apps/web/src/pages/secrets.tsx+391−0
@@ -0,0 +1,391 @@
1import { useState, Suspense } from "react";
2import {
3 useAtomValue,
4 useAtomSet,
5 useAtomRefresh,
6 Result,
7 secretsAtom,
8 setSecret,
9 removeSecret,
10} from "@executor/react";
11import type { SecretProviderPlugin } from "@executor/react";
12import { SecretId } from "@executor/sdk";
13import { useScope } from "../lib/use-scope";
14import { onePasswordSecretProviderPlugin } from "@executor/plugin-onepassword/react";
15import {
16 Dialog,
17 DialogContent,
18 DialogHeader,
19 DialogTitle,
20 DialogDescription,
21 DialogFooter,
22 DialogClose,
23} from "@executor/ui/components/dialog";
24import { Button } from "@executor/ui/components/button";
25import { Input } from "@executor/ui/components/input";
26import { Label } from "@executor/ui/components/label";
27import { Badge } from "@executor/ui/components/badge";
28import {
29 DropdownMenu,
30 DropdownMenuContent,
31 DropdownMenuItem,
32 DropdownMenuTrigger,
33} from "@executor/ui/components/dropdown-menu";
34import {
35 Select,
36 SelectContent,
37 SelectItem,
38 SelectTrigger,
39 SelectValue,
40} from "@executor/ui/components/select";
41
42// ---------------------------------------------------------------------------
43// Add secret dialog
44// ---------------------------------------------------------------------------
45
46function 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
210function 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
270const secretProviderPlugins: SecretProviderPlugin[] = [
271 onePasswordSecretProviderPlugin,
272];
273
274// ---------------------------------------------------------------------------
275// Page
276// ---------------------------------------------------------------------------
277
278export 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 @@
1import { useEffect, useMemo, useState } from "react";
2import { useNavigate } from "@tanstack/react-router";
3import {
4 useAtomValue,
5 useAtomSet,
6 useAtomRefresh,
7 sourceToolsAtom,
8 sourcesAtom,
9 sourceAtom,
10 removeSource,
11 refreshSource,
12 Result,
13} from "@executor/react";
14import { ToolTree } from "../components/tool-tree";
15import { ToolDetail, ToolDetailEmpty } from "../components/tool-detail";
16import type { ToolSummary } from "../components/tool-tree";
17import { useScope } from "../lib/use-scope";
18
19export 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 @@
1import { useReducer, useCallback, useMemo, Suspense } from "react";
2import { Link } from "@tanstack/react-router";
3import { Result, useAtomValue, useAtomRefresh, useAtomSet, sourcesAtom, detectSource } from "@executor/react";
4import { useScope } from "../lib/use-scope";
5import type { SourcePlugin, SourcePreset } from "@executor/react";
6import { openApiSourcePlugin } from "@executor/plugin-openapi/react";
7import { mcpSourcePlugin } from "@executor/plugin-mcp/react";
8import { googleDiscoverySourcePlugin } from "@executor/plugin-google-discovery/react";
9import { graphqlSourcePlugin } from "@executor/plugin-graphql/react";
10import { McpInstallCard } from "../components/mcp-install-card";
11
12// ---------------------------------------------------------------------------
13// Registered source plugins
14// ---------------------------------------------------------------------------
15
16const sourcePlugins: SourcePlugin[] = [
17 openApiSourcePlugin,
18 mcpSourcePlugin,
19 googleDiscoverySourcePlugin,
20 graphqlSourcePlugin,
21];
22
23const 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
34type State = {
35 step: "list" | "detecting" | "adding";
36 url: string;
37 error: string | null;
38 pluginKey: string | null;
39 initialUrl: string | undefined;
40};
41
42type 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
53const init: State = { step: "list", url: "", error: null, pluginKey: null, initialUrl: undefined };
54
55function 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
84export 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
273function 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
333function 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 @@
1import { useAtomValue, Result, toolsAtom } from "@executor/react";
2import { useScope } from "../lib/use-scope";
3
4export 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 @@
1import type {
2 Source,
3} from "@executor/react";
4import {
5 ExecutionHistoryReactPlugin,
6} from "@executor/plugin-execution-history-react";
7import {
8 GoogleDiscoveryReactPlugin,
9 getGoogleDiscoveryIconUrl,
10} from "@executor/plugin-google-discovery-react";
11import {
12 GraphqlReactPlugin,
13} from "@executor/plugin-graphql-react";
14import {
15 McpReactPlugin,
16} from "@executor/plugin-mcp-react";
17import {
18 OpenApiReactPlugin,
19} from "@executor/plugin-openapi-react";
20import {
21 createExecutorPluginPaths,
22 createSourcePluginPaths,
23 registerExecutorFrontendPlugins,
24 type ExecutorFrontendPlugin,
25} from "@executor/react/plugins";
26import { getFallbackSourceFaviconUrl } from "../lib/source-favicon";
27
28const frontendPlugins = [
29 ExecutionHistoryReactPlugin,
30 McpReactPlugin,
31 GraphqlReactPlugin,
32 GoogleDiscoveryReactPlugin,
33 OpenApiReactPlugin,
34] as const satisfies readonly ExecutorFrontendPlugin[];
35
36const frontendPluginRegistry = registerExecutorFrontendPlugins(frontendPlugins);
37
38const hasRouteKey = (
39 plugin: ExecutorFrontendPlugin,
40 routeKey: string,
41): boolean =>
42 (plugin.routes ?? []).some((route) => route.key === routeKey);
43
44const isSourceFrontendPlugin = (
45 plugin: ExecutorFrontendPlugin,
46): boolean =>
47 hasRouteKey(plugin, "add")
48 && hasRouteKey(plugin, "detail");
49
50export const registeredFrontendPlugins = frontendPluginRegistry.plugins;
51export const registeredFrontendPluginRoutes = frontendPluginRegistry.routes;
52export 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 }));
60export const registeredSourceFrontendPlugins =
61 registeredFrontendPlugins.filter(isSourceFrontendPlugin);
62
63export const getFrontendPlugin = (key: string) =>
64 frontendPluginRegistry.getPlugin(key);
65
66export const getFrontendPluginRoute = (
67 pluginKey: string,
68 routeKey: string,
69) => frontendPluginRegistry.getRoute(pluginKey, routeKey);
70
71const resolveSourcePluginKey = (kind: string): string =>
72 isGoogleDiscoverySource(kind) ? "google-discovery" : kind;
73
74export const getSourceFrontendPlugin = (kind: string) => {
75 const plugin = getFrontendPlugin(resolveSourcePluginKey(kind));
76 return plugin && isSourceFrontendPlugin(plugin) ? plugin : null;
77};
78
79export const getSourceFrontendPaths = (kind: string) => {
80 const plugin = getSourceFrontendPlugin(kind);
81 return plugin ? createSourcePluginPaths(plugin.key) : null;
82};
83
84const isGoogleDiscoverySource = (kind: string): boolean =>
85 kind === "google_discovery"
86 || kind === "google-discovery";
87
88export const getSourceFrontendIconUrl = (source: Source) =>
89 source.iconUrl
90 ?? (isGoogleDiscoverySource(source.kind)
91 ? getGoogleDiscoveryIconUrl(source)
92 : null)
93 ?? getFallbackSourceFaviconUrl(source);
94
95export 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 @@
1import { useState, type FormEvent } from "react";
2import { Link, useNavigate } from "@tanstack/react-router";
3import {
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
16import { SourcePresetFavicon } from "../components/source-favicon";
17import { LocalMcpInstallCard } from "../components/local-mcp-install-card";
18import { SourcePluginsResetState } from "../components/source-plugins-reset-state";
19import {
20 getFrontendPlugin,
21 getFrontendPluginRoute,
22 registeredSourceFrontendPlugins,
23} from "./index";
24import {
25 buildSourcePresetSearch,
26 resolveQuickSourceInput,
27 sourcePresets,
28} from "./source-presets";
29
30const FrontendPluginUnavailableState = () => (
31 <SourcePluginsResetState
32 title="Plugins unavailable"
33 message="No plugins are available in this build."
34 />
35);
36
37const SourcePluginUnavailableState = () => (
38 <SourcePluginsResetState
39 title="No source plugins available"
40 message="No source plugins are available in this build."
41 />
42);
43
44const 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
99export 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
140export 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 @@
1const GOOGLE_DISCOVERY_PLUGIN_KEY = "google-discovery" as const;
2const GOOGLE_DISCOVERY_SOURCE_KIND = "google_discovery" as const;
3
4export 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
50const 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
69export 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
360export 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
399const 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
412const tryParseUrl = (value: string): URL | null => {
413 try {
414 return new URL(value.trim());
415 } catch {
416 return null;
417 }
418};
419
420const 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
434const 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
477const 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
488const 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
494const 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
505const 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
537export type ResolvedQuickSourceInput = {
538 pluginKey: SourcePreset["pluginKey"];
539 search: Record<string, string>;
540};
541
542export 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 @@
1import {
2 createRouter,
3 createRootRoute,
4 createRoute,
5} from "@tanstack/react-router";
6import { ExecutorProvider } from "@executor/react";
7import { ToolsPage } from "./pages/tools";
8import { SourcesPage } from "./pages/sources";
9import { SourceDetailPage } from "./pages/source-detail";
10import { SecretsPage } from "./pages/secrets";
11import { Shell } from "./shell";
12
13// ---------------------------------------------------------------------------
14// Root layout — Shell renders <Outlet /> directly
15// ---------------------------------------------------------------------------
16
17const rootRoute = createRootRoute({
18 component: () => (
19 <ExecutorProvider>
20 <Shell />
21 </ExecutorProvider>
22 ),
23});
24
25// ---------------------------------------------------------------------------
26// Routes
27// ---------------------------------------------------------------------------
28
29const indexRoute = createRoute({
30 getParentRoute: () => rootRoute,
31 path: "/",
32 component: SourcesPage,
33});
34
35const toolsRoute = createRoute({
36 getParentRoute: () => rootRoute,
37 path: "/tools",
38 component: ToolsPage,
39});
40
41const sourceDetailRoute = createRoute({
42 getParentRoute: () => rootRoute,
43 path: "/sources/$namespace",
44 component: () => {
45 const { namespace } = sourceDetailRoute.useParams();
46 return <SourceDetailPage namespace={namespace} />;
47 },
48});
49
50const secretsRoute = createRoute({
51 getParentRoute: () => rootRoute,
52 path: "/secrets",
53 component: SecretsPage,
54});
55
56// ---------------------------------------------------------------------------
57// Router
58// ---------------------------------------------------------------------------
59
60const routeTree = rootRoute.addChildren([
61 indexRoute,
62 toolsRoute,
63 sourceDetailRoute,
64 secretsRoute,
65]);
66
67export const router = createRouter({ routeTree });
68
69declare 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 */
7import { runLocalExecutorServer } from "@executor/server";
8
9await 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 @@
1import { Link, Outlet, useLocation } from "@tanstack/react-router";
2import { useCallback, useEffect, useRef, useState } from "react";
3import {
4 useAtomRefresh,
5 useAtomValue,
6 Result,
7 sourcesAtom,
8 toolsAtom,
9 useScope,
10 useScopeInfo,
11} from "@executor/react";
12import { Button } from "@executor/ui/components/button";
13
14// ── Env ─────────────────────────────────────────────────────────────────
15
16type AppMetaEnv = {
17 readonly VITE_APP_VERSION: string;
18 readonly VITE_GITHUB_URL: string;
19};
20
21const { VITE_APP_VERSION, VITE_GITHUB_URL } = (import.meta as ImportMeta & {
22 readonly env: AppMetaEnv;
23}).env;
24
25// ── Version helpers ─────────────────────────────────────────────────────
26
27type UpdateChannel = "latest" | "beta";
28
29const EXECUTOR_DIST_TAGS_PATH = "/v1/app/npm/dist-tags";
30
31type ParsedVersion = {
32 readonly major: number;
33 readonly minor: number;
34 readonly patch: number;
35 readonly prerelease: ReadonlyArray<string | number> | null;
36};
37
38const semverPattern =
39 /^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<prerelease>[0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
40
41const resolveUpdateChannel = (version: string): UpdateChannel =>
42 version.includes("-beta.") ? "beta" : "latest";
43
44const 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
59const 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
81const 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
93function 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
119function 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
174function 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
193function 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
243function 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
267function 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
348export 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 @@
1import { Link } from "@tanstack/react-router";
2import { useSources } from "@executor/react";
3import { sourcePluginsIndexPath } from "@executor/react/plugins";
4import { LoadableBlock } from "../components/loadable";
5import { LocalMcpInstallCard } from "../components/local-mcp-install-card";
6import { SourceFavicon } from "../components/source-favicon";
7import { Alert, Badge, Button, Card } from "@executor/react/plugins";
8import { IconSources, IconPlus } from "../components/icons";
9import {
10 getSourceFrontendPaths,
11} from "../plugins";
12
13const statusVariant = (status: string) =>
14 status === "connected"
15 ? "default" as const
16 : status === "error"
17 ? "destructive" as const
18 : "muted" as const;
19
20export 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 @@
1import { useState, type ReactNode } from "react";
2import {
3 type LocalScopePolicy,
4 type LocalScopePolicyApprovalMode,
5 type LocalScopePolicyEffect,
6 useCreatePolicy,
7 usePolicies,
8 useRemovePolicy,
9 useUpdatePolicy,
10} from "@executor/react";
11
12import { LoadableBlock } from "../components/loadable";
13import {
14 Alert,
15 Badge,
16 Button,
17 Card,
18 Input,
19 Label,
20 Select,
21} from "@executor/react/plugins";
22import {
23 IconPencil,
24 IconPlus,
25 IconSpinner,
26 IconTrash,
27} from "../components/icons";
28import { cn } from "../lib/utils";
29
30// ── Permission state helpers ────────────────────────────────────────────
31
32type PermissionLevel = "auto-run" | "requires-approval" | "denied";
33
34const 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
43const 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
67const 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
89export 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
212function 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
319function 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
437function 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
570function 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
591function 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
610function 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
621function 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
647const 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 @@
1import { useCallback, useEffect, useState, type ReactNode } from "react";
2import {
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
21import { LoadableBlock } from "../components/loadable";
22import { Badge } from "@executor/react/plugins";
23import {
24 Alert,
25 Button,
26 Card,
27 Input,
28 Label,
29 Select,
30} from "@executor/react/plugins";
31import {
32 IconPencil,
33 IconPlus,
34 IconSpinner,
35 IconTrash,
36} from "../components/icons";
37import { cn } from "../lib/utils";
38import { getSecretStoreFrontendPlugin } from "../plugins";
39
40const creatableStorePluginsFromConfig = (config: Loadable<InstanceConfig>) =>
41 config.status === "ready"
42 ? config.data.secretStorePlugins.filter((plugin) => plugin.canCreate)
43 : [];
44
45const 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
55const 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
72type SecretStoreBrowserEntry = BrowseSecretStoreResult["entries"][number];
73type SecretStoreBrowserCrumb = {
74 key: string;
75 label: string;
76};
77
78const canBrowseAndImportStore = (store: SecretStore | null): boolean =>
79 store?.capabilities.canBrowseSecrets === true
80 && store.capabilities.canImportSecrets === true;
81
82export 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
221function 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
342function 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
721function 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
810function 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
930function 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
1012function 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
1035function 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
1046function 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
1068const 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 @@
1{1{
2 "compilerOptions": {2 "compilerOptions": {
3 "target": "ES2022",3 "target": "ESNext",
4 "module": "ESNext",4 "module": "ESNext",
5 "moduleResolution": "Bundler",5 "moduleResolution": "bundler",
6 "strict": true,6 "strict": true,
7 "esModuleInterop": true,
7 "skipLibCheck": true,8 "skipLibCheck": true,
8 "noEmit": true,9 "outDir": "dist",
9 "lib": ["ES2022", "DOM", "DOM.Iterable"],10 "rootDir": ".",
10 "jsx": "react-jsx",11 "jsx": "react-jsx",
11 "types": ["bun-types"],12 "plugins": [
12 "baseUrl": ".",13 {
13 "paths": {14 "name": "@effect/language-service"
14 "@/*": ["./src/*"]15 }
15 }16 ]
16 },17 },
17 "include": [18 "include": ["src", "vite.config.ts"]
18 "src/**/*.ts",
19 "src/**/*.tsx"
20 ]
21}19}
apps/web/vite.config.ts+173−76
@@ -1,99 +1,196 @@
1import { readFileSync } from "node:fs";1import { readFileSync } from "node:fs";
2import path from "node:path";2import { resolve } from "node:path";
3import { defineConfig } from "vite";3import { defineConfig } from "vite";
4import react from "@vitejs/plugin-react";4import react from "@vitejs/plugin-react";
5import tailwindcss from "@tailwindcss/vite";5import tailwindcss from "@tailwindcss/vite";
6import devServer from "@hono/vite-dev-server";
7 6
8type ExecutorPackageMetadata = {7type HotBackend = {
9 version: string;8 readonly api: {
10 homepage?: string;9 readonly handler: (request: Request) => Promise<Response>;
11 repository?: string | { url?: string };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>;
12};17};
13 18
14const executorPackage = JSON.parse(19const DEV_BACKEND_MODULE_ID = `/@fs/${resolve(
15 readFileSync(new URL("../executor/package.json", import.meta.url), "utf8"),20 process.cwd(),
16) as ExecutorPackageMetadata;21 "../server/src/dev-backend.ts",
22).replace(/\\/g, "/")}`;
17 23
18const repositoryUrl =24// Build a Web Request from a Node IncomingMessage
19 typeof executorPackage.repository === "string"25const toWebRequest = async (
20 ? executorPackage.repository26 req: import("http").IncomingMessage,
21 : executorPackage.repository?.url;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 }
22 37
23const githubUrl = (executorPackage.homepage ?? repositoryUrl ?? "https://github.com/RhysSullivan/executor")38 const host = req.headers.host ?? "localhost";
24 .replace(/^git\+/, "")39 const url = `http://${host}${req.url}`;
25 .replace(/\.git$/, "");
26 40
27const webPackage = JSON.parse(41 return new Request(url, {
28 readFileSync(new URL("./package.json", import.meta.url), "utf8"),42 method: req.method,
29) as {43 headers,
30 dependencies?: Record<string, string>;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 });
31};54};
32 55
33const workspaceExecutorPackages = Object.keys(webPackage.dependencies ?? {}).filter(56// Pipe a Web Response back to a Node ServerResponse, streaming if needed
34 (name) => name.startsWith("@executor/"),57const sendWebResponse = async (
35);58 webRes: Response,
59 nodeRes: import("http").ServerResponse,
60) => {
61 nodeRes.statusCode = webRes.status;
62 webRes.headers.forEach((value, key) => nodeRes.setHeader(key, value));
36 63
37const pluginsWorkspaceRoot = path.resolve(import.meta.dirname, "../../plugins") + path.sep;64 if (!webRes.body) {
65 nodeRes.end();
66 return;
67 }
38 68
39const reloadOnPluginChange = () => ({69 const reader = webRes.body.getReader();
40 name: "executor-reload-on-plugin-change",70 try {
41 handleHotUpdate({ file, server }: { file: string; server: { hot: { send: (payload: { type: "full-reload" }) => void } } }) {71 for (;;) {
42 if (!file.startsWith(pluginsWorkspaceRoot)) {72 const { done, value } = await reader.read();
43 return;73 if (done) break;
74 nodeRes.write(value);
44 }75 }
76 } finally {
77 nodeRes.end();
78 }
79};
45 80
46 server.hot.send({ type: "full-reload" });81const rootPackage = JSON.parse(
47 return [];82 readFileSync(new URL("../../package.json", import.meta.url), "utf8"),
48 },83) as { version: string; homepage?: string; repository?: string | { url?: string } };
49});84
85const cliPackage = JSON.parse(
86 readFileSync(new URL("../cli/package.json", import.meta.url), "utf8"),
87) as { version?: string };
88
89const repositoryUrl =
90 typeof rootPackage.repository === "string"
91 ? rootPackage.repository
92 : rootPackage.repository?.url;
93
94const EXECUTOR_VERSION = cliPackage.version ?? rootPackage.version;
95const EXECUTOR_GITHUB_URL = (rootPackage.homepage ?? repositoryUrl ?? "https://github.com/RhysSullivan/executor")
96 .replace(/^git\+/, "")
97 .replace(/\.git$/, "");
50 98
51export default defineConfig({99export default defineConfig({
52 root: "src",100 define: {
53 resolve: {101 "import.meta.env.VITE_APP_VERSION": JSON.stringify(EXECUTOR_VERSION),
54 alias: {102 "import.meta.env.VITE_GITHUB_URL": JSON.stringify(EXECUTOR_GITHUB_URL),
55 "@": path.resolve(import.meta.dirname, "./src"),
56 },
57 },103 },
58 plugins: [104 plugins: [
59 reloadOnPluginChange(),
60 tailwindcss(),
61 react(),105 react(),
62 devServer({106 tailwindcss(),
63 entry: "src/dev.ts",107 {
64 exclude: [108 name: "executor-api",
65 // Only let /v1 and /mcp requests reach the API handler109 configureServer(server) {
66 /^\/(?!(v1|mcp)(\/|$))/,110 let backendPromise: Promise<HotBackend> | null = null;
67 /^\/(src|node_modules|@vite|@id|@react-refresh)/,111 let reloadPromise: Promise<void> | null = null;
68 /\.(css|ts|tsx|js|jsx|svg|png|jpg|gif|ico|woff2?|json|map)(\?.*)?$/,112
69 ],113 const loadBackend = () =>
70 injectClientScript: false,114 server
71 }),115 .ssrLoadModule(DEV_BACKEND_MODULE_ID)
72 ],116 .then((mod) => mod.createHotBackend() as Promise<HotBackend>);
73 define: {117
74 "import.meta.env.VITE_APP_VERSION": JSON.stringify(executorPackage.version),118 const getBackend = () => {
75 "import.meta.env.VITE_GITHUB_URL": JSON.stringify(githubUrl),119 if (!backendPromise) {
76 },120 backendPromise = loadBackend();
77 build: {121 }
78 outDir: "../dist",122 return backendPromise;
79 emptyOutDir: true,123 };
80 },124
81 optimizeDeps: {125 const shouldReloadBackend = (file: string) =>
82 exclude: workspaceExecutorPackages,126 /\.(ts|tsx)$/.test(file) &&
83 },127 !file.includes("/apps/web/") &&
84 server: {128 (
85 port: 8788,129 file.includes("/apps/server/") ||
86 allowedHosts: [130 file.includes("/packages/core/") ||
87 "rhyss-laptop.tail5665af.ts.net",131 file.includes("/packages/plugins/") ||
88 ".tail5665af.ts.net",132 file.includes("/packages/hosts/")
89 ],133 );
90 watch: {134
91 ignored: [135 server.httpServer?.once("close", () => {
92 "!**/node_modules/@executor/**",136 const pending = backendPromise;
93 ],137 backendPromise = null;
94 // WSL2 inotify doesn't reliably detect changes through symlinked workspace packages138 void pending?.then((backend) => backend.dispose()).catch(() => undefined);
95 usePolling: true,139 });
96 interval: 500,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 },
97 },194 },
98 },195 ],
99});196});
architecture.md+0−124
@@ -1,124 +0,0 @@
1# Notes on the architecture of Executor.
2
3## What is Executor?
4
5Executor is meant to be a replacement for how agents use bash and CLIs today, replacing it with code execution.
6
7The 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
9It 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
13Look 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
20Portability, 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
26Configuring 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
34SaaS:
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
41Local:
42
43- Locally installable desktop application
44- Be able to npx add-mcp executor and just start using it
45
46SDK:
47
48- Bring your AI SDK tools
49- Leverage the plugin ecosystem to convert OpenAPI / GraphQL / etc into callable tools
50
51## Architecture
52
53All of these build on similar concepts and primitives
54
55The 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
57Scope contains:
58
59- Secrets
60- Policies
61- Sources
62 - Tools
63
64### Scopes
65
66Scopes contain sources, sources contain tools
67Scopes 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
77Q) How does merging secrets work with scopes? i.e I need to enforce people set their own tokens on sources
78
79A) TBD no idea
80
81Q) How does merging poliices work with scopes? i.e people can override
82
83A) TBD no idea
84
85### Tools
86
87A tool is a function call
88
89Requirements 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
96Plugin 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
111Plugins:
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
118Plugins 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
122While 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
124Where I believe this is relevant still is that
bun.lock+961−1311
@@ -3,240 +3,212 @@ · 2 unmodified lines
3 "configVersion": 1,3 "configVersion": 1,
4 "workspaces": {4 "workspaces": {
5 "": {5 "": {
6 "name": "executor",6 "name": "v4-executor",
7 "devDependencies": {7 "devDependencies": {
8 "@changesets/cli": "^2.30.0",8 "@changesets/cli": "^2.30.0",
9 "@oxlint/plugins": "^1.57.0",9 "@effect/language-service": "^0.84.2",
10 "knip": "^5.85.0",10 "@effect/platform": "catalog:",
11 "@effect/vitest": "catalog:",
12 "effect": "catalog:",
11 "oxlint": "^1.56.0",13 "oxlint": "^1.56.0",
12 "turbo": "^2.5.6",14 "turbo": "^2.5.6",
13 "typescript": "^5.9.3",15 "typescript": "^5.9.3",
16 "vitest": "catalog:",
14 },17 },
15 },18 },
16 "apps/docs": {19 "apps/cli": {
17 "name": "@executor/docs",
18 "version": "0.0.0",
19 },
20 "apps/executor": {
21 "name": "executor",20 "name": "executor",
22 "version": "1.3.0-beta.3",21 "version": "1.4.0-beta.0",
23 "bin": {22 "bin": {
24 "executor": "bin/executor",23 "executor": "./bin/executor.ts",
25 },24 },
26 "dependencies": {25 "dependencies": {
27 "@effect/cli": "catalog:",26 "@effect/cli": "catalog:",
28 "@effect/platform": "catalog:",27 "@effect/platform": "catalog:",
29 "@effect/platform-node": "catalog:",28 "@effect/platform-bun": "catalog:",
30 "@executor/codemode-core": "workspace:*",29 "@executor/api": "workspace:*",
31 "@executor/executor-mcp": "workspace:*",30 "@executor/runtime-quickjs": "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:*",
42 "@executor/server": "workspace:*",31 "@executor/server": "workspace:*",
32 "@jitl/quickjs-wasmfile-release-sync": "*",
43 "effect": "catalog:",33 "effect": "catalog:",
34 "quickjs-emscripten": "*",
44 },35 },
45 "devDependencies": {36 "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:",
52 "bun-types": "catalog:",37 "bun-types": "catalog:",
53 "vitest": "catalog:",38 "typescript": "^5.9.3",
54 "zod": "catalog:",
55 },39 },
56 },40 },
57 "apps/web": {41 "apps/server": {
58 "name": "@executor/web",42 "name": "@executor/server",
59 "version": "0.0.0",43 "version": "1.4.0-beta.0",
60 "dependencies": {44 "dependencies": {
61 "@base-ui/react": "^1.3.0",45 "@effect/platform": "catalog:",
62 "@executor/plugin-execution-history-react": "workspace:*",46 "@effect/platform-node": "catalog:",
63 "@executor/plugin-google-discovery-react": "workspace:*",47 "@effect/sql": "catalog:",
64 "@executor/plugin-graphql-react": "workspace:*",48 "@effect/sql-sqlite-bun": "catalog:",
65 "@executor/plugin-local-tools-react": "workspace:*",49 "@executor/api": "workspace:*",
66 "@executor/plugin-mcp-react": "workspace:*",50 "@executor/config": "workspace:*",
67 "@executor/plugin-onepassword-react": "workspace:*",51 "@executor/execution": "workspace:*",
68 "@executor/plugin-openapi-react": "workspace:*",52 "@executor/host-mcp": "workspace:*",
69 "@executor/react": "workspace:*",53 "@executor/plugin-file-secrets": "workspace:*",
70 "@executor/server": "workspace:*",54 "@executor/plugin-google-discovery": "workspace:*",
71 "@executor/source-core": "workspace:*",55 "@executor/plugin-graphql": "workspace:*",
72 "@shikijs/langs": "^4.0.1",56 "@executor/plugin-keychain": "workspace:*",
73 "@shikijs/themes": "^4.0.1",57 "@executor/plugin-mcp": "workspace:*",
74 "@tanstack/react-router": "^1.132.7",58 "@executor/plugin-onepassword": "workspace:*",
75 "class-variance-authority": "^0.7.1",59 "@executor/plugin-openapi": "workspace:*",
76 "clsx": "^2.1.1",60 "@executor/sdk": "workspace:*",
61 "@executor/storage-file": "workspace:*",
62 "@modelcontextprotocol/sdk": "^1.12.1",
77 "effect": "catalog:",63 "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",
87 },64 },
88 "devDependencies": {65 "devDependencies": {
89 "@hono/vite-dev-server": "^0.25.0",66 "@types/node": "catalog:",
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",
94 "bun-types": "catalog:",67 "bun-types": "catalog:",
95 "tailwindcss": "^4.2.1",68 "typescript": "^5.9.3",
96 "tw-animate-css": "^1.4.0",
97 "vite": "^7.3.1",
98 },69 },
99 },70 },
100 "examples/mcp-elicitation-demo": {71 "apps/web": {
101 "name": "@executor/mcp-elicitation-demo",72 "name": "@executor/web",
102 "version": "0.0.0",73 "version": "1.4.0-beta.0",
103 "dependencies": {74 "dependencies": {
104 "@modelcontextprotocol/sdk": "^1.26.0",75 "@executor/plugin-google-discovery": "workspace:*",
105 "zod": "catalog:",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",
106 },92 },
107 "devDependencies": {93 "devDependencies": {
94 "@tailwindcss/vite": "^4.1.10",
108 "@types/node": "catalog:",95 "@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",
110 },101 },
111 },102 },
112 "examples/serve-skills-via-mcp": {103 "packages/clients/react": {
113 "name": "@executor/serve-skills-via-mcp-demo",104 "name": "@executor/react",
114 "version": "0.0.0",105 "version": "1.4.0-beta.0",
115 "dependencies": {106 "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",
117 },115 },
118 "devDependencies": {116 "devDependencies": {
119 "@types/node": "catalog:",117 "@types/node": "catalog:",
120 "bun-types": "catalog:",118 "@types/react": "^19.1.0",
119 "typescript": "^5.9.3",
121 },120 },
122 },121 },
123 "examples/sqlite-sdk-consumer": {122 "packages/core/api": {
124 "name": "@executor/sqlite-sdk-consumer-example",123 "name": "@executor/api",
125 "version": "0.0.0",124 "version": "1.4.0-beta.0",
126 "dependencies": {125 "dependencies": {
127 "@executor/platform-sdk": "workspace:*",126 "@effect/platform": "catalog:",
128 "@executor/source-core": "workspace:*",127 "@executor/sdk": "workspace:*",
129 "drizzle-orm": "^0.44.5",128 "effect": "catalog:",
130 },129 },
131 "devDependencies": {130 "devDependencies": {
132 "@types/node": "catalog:",131 "@types/node": "catalog:",
133 "bun-types": "catalog:",132 "bun-types": "catalog:",
133 "typescript": "^5.9.3",
134 },134 },
135 },135 },
136 "packages/clients/react": {136 "packages/core/config": {
137 "name": "@executor/react",137 "name": "@executor/config",
138 "version": "0.0.0",138 "version": "1.4.0-beta.0",
139 "dependencies": {139 "dependencies": {
140 "@base-ui/react": "^1.3.0",
141 "@effect-atom/atom": "0.5.3",
142 "@effect-atom/atom-react": "0.5.0",
143 "@effect/platform": "catalog:",140 "@effect/platform": "catalog:",
144 "@executor/platform-api": "workspace:*",141 "@executor/sdk": "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",
151 "effect": "catalog:",142 "effect": "catalog:",
152 "shiki": "^4.0.1",143 "jsonc-parser": "^3.3.1",
153 "streamdown": "^2.3.0",
154 "tailwind-merge": "^3.5.0",
155 },144 },
156 "devDependencies": {145 "devDependencies": {
157 "@effect/platform-node": "catalog:",146 "@effect/platform-node": "catalog:",
158 "@effect/vitest": "catalog:",147 "@effect/vitest": "catalog:",
159 "@executor/effect-test-utils": "workspace:*",148 "typescript": "latest",
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",
168 "vitest": "catalog:",149 "vitest": "catalog:",
169 },150 },
170 "peerDependencies": {
171 "react": ">=18 <20",
172 },
173 },151 },
174 "packages/dev/effect-test-utils": {152 "packages/core/execution": {
175 "name": "@executor/effect-test-utils",153 "name": "@executor/execution",
176 "version": "0.0.0",154 "version": "1.4.0-beta.0",
177 "dependencies": {155 "dependencies": {
178 "@effect/platform": "catalog:",156 "@executor/codemode-core": "workspace:*",
179 "@effect/platform-node": "catalog:",157 "@executor/runtime-quickjs": "workspace:*",
158 "@executor/sdk": "workspace:*",
180 "effect": "catalog:",159 "effect": "catalog:",
181 },160 },
182 "devDependencies": {161 "devDependencies": {
183 "@types/node": "catalog:",162 "@types/node": "catalog:",
184 "bun-types": "catalog:",163 "bun-types": "catalog:",
185 "typescript": "^5.9.3",
186 },164 },
187 },165 },
188 "packages/dev/kitchen-sink": {166 "packages/core/sdk": {
189 "name": "@executor/kitchen-sink",167 "name": "@executor/sdk",
190 "version": "0.0.0",168 "version": "1.4.0-beta.0",
191 "dependencies": {169 "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:*",
197 "effect": "catalog:",170 "effect": "catalog:",
198 },171 },
199 "devDependencies": {172 "devDependencies": {
200 "@effect/vitest": "catalog:",173 "@effect/vitest": "catalog:",
201 "@types/node": "catalog:",174 "typescript": "latest",
202 "bun-types": "catalog:",
203 "vitest": "catalog:",175 "vitest": "catalog:",
204 },176 },
205 },177 },
206 "packages/hosts/ai-sdk": {178 "packages/core/storage-file": {
207 "name": "@executor/ai-sdk-adapter",179 "name": "@executor/storage-file",
208 "version": "0.0.0",180 "version": "1.4.0-beta.0",
209 "dependencies": {181 "dependencies": {
210 "@executor/codemode-core": "workspace:*",182 "@effect/sql": "catalog:",
211 "@executor/runtime-ses": "workspace:*",183 "@executor/sdk": "workspace:*",
212 "ai": "^6.0.0",
213 "effect": "catalog:",184 "effect": "catalog:",
214 "zod": "catalog:",
215 },185 },
216 "devDependencies": {186 "devDependencies": {
217 "@types/node": "catalog:",187 "@effect/experimental": "catalog:",
218 "bun-types": "catalog:",188 "@effect/sql-sqlite-node": "catalog:",
189 "@effect/vitest": "catalog:",
190 "typescript": "^5.9.3",
191 "vitest": "catalog:",
219 },192 },
220 },193 },
221 "packages/hosts/mcp": {194 "packages/hosts/mcp": {
222 "name": "@executor/executor-mcp",195 "name": "@executor/host-mcp",
223 "version": "0.0.0",196 "version": "1.4.0-beta.0",
224 "dependencies": {197 "dependencies": {
225 "@executor/platform-sdk": "workspace:*",198 "@executor/execution": "workspace:*",
226 "@modelcontextprotocol/sdk": "^1.26.0",199 "@executor/sdk": "workspace:*",
200 "@modelcontextprotocol/sdk": "^1.12.1",
227 "effect": "catalog:",201 "effect": "catalog:",
228 "zod": "catalog:",202 "zod": "^4.3.0",
229 },203 },
230 "devDependencies": {204 "devDependencies": {
231 "@effect/vitest": "catalog:",
232 "@types/node": "catalog:",205 "@types/node": "catalog:",
233 "bun-types": "catalog:",206 "bun-types": "catalog:",
234 "vitest": "catalog:",
235 },207 },
236 },208 },
237 "packages/kernel/core": {209 "packages/kernel/core": {
238 "name": "@executor/codemode-core",210 "name": "@executor/codemode-core",
239 "version": "0.0.0",211 "version": "1.4.0-beta.0",
240 "dependencies": {212 "dependencies": {
241 "@standard-schema/spec": "^1.0.0",213 "@standard-schema/spec": "^1.0.0",
242 "ajv": "^8.17.1",214 "ajv": "^8.17.1",
@@ -252,9 +224,8 @@ · 9 unmodified lines
252 },224 },
253 "packages/kernel/ir": {225 "packages/kernel/ir": {
254 "name": "@executor/ir",226 "name": "@executor/ir",
255 "version": "0.0.0",227 "version": "1.4.0-beta.0",
256 "dependencies": {228 "dependencies": {
257 "@executor/codemode-core": "workspace:*",
258 "effect": "catalog:",229 "effect": "catalog:",
259 },230 },
260 "devDependencies": {231 "devDependencies": {
@@ -280,7 +251,7 @@ · 19 unmodified lines
280 },251 },
281 "packages/kernel/runtime-quickjs": {252 "packages/kernel/runtime-quickjs": {
282 "name": "@executor/runtime-quickjs",253 "name": "@executor/runtime-quickjs",
283 "version": "0.0.0",254 "version": "1.4.0-beta.0",
284 "dependencies": {255 "dependencies": {
285 "@executor/codemode-core": "workspace:*",256 "@executor/codemode-core": "workspace:*",
286 "effect": "catalog:",257 "effect": "catalog:",
@@ -293,199 +264,99 @@ · 6 unmodified lines
293 "vitest": "catalog:",264 "vitest": "catalog:",
294 },265 },
295 },266 },
296 "packages/kernel/runtime-ses": {267 "packages/plugins/file-secrets": {
297 "name": "@executor/runtime-ses",268 "name": "@executor/plugin-file-secrets",
298 "version": "0.0.0",269 "version": "1.4.0-beta.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",
327 "dependencies": {270 "dependencies": {
328 "@effect/platform": "catalog:",271 "@executor/sdk": "workspace:*",
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:*",
336 "effect": "catalog:",272 "effect": "catalog:",
337 },273 },
338 "devDependencies": {274 "devDependencies": {
339 "@effect/vitest": "catalog:",275 "@effect/vitest": "catalog:",
340 "@executor/effect-test-utils": "workspace:*",
341 "@modelcontextprotocol/sdk": "^1.26.0",
342 "@types/node": "catalog:",276 "@types/node": "catalog:",
343 "bun-types": "catalog:",277 "bun-types": "catalog:",
344 "jsonc-parser": "3.3.1",
345 "prettier": "^3.8.1",
346 "typescript": "^5.9.3",
347 "vitest": "catalog:",278 "vitest": "catalog:",
348 "zod": "catalog:",
349 },279 },
350 },280 },
351 "packages/platform/sdk-file": {281 "packages/plugins/google-discovery": {
352 "name": "@executor/platform-sdk-file",282 "name": "@executor/plugin-google-discovery",
353 "version": "0.0.0",283 "version": "1.4.0-beta.0",
354 "dependencies": {284 "dependencies": {
355 "@effect/platform": "catalog:",285 "@effect/platform": "catalog:",
356 "@effect/platform-node": "catalog:",286 "@executor/api": "workspace:*",
357 "@executor/codemode-core": "workspace:*",287 "@executor/sdk": "workspace:*",
358 "@executor/ir": "workspace:*",
359 "@executor/platform-sdk": "workspace:*",
360 "@executor/source-core": "workspace:*",
361 "effect": "catalog:",288 "effect": "catalog:",
362 "jsonc-parser": "3.3.1",
363 },289 },
364 "devDependencies": {290 "devDependencies": {
291 "@effect-atom/atom-react": "^0.5.0",
365 "@effect/vitest": "catalog:",292 "@effect/vitest": "catalog:",
293 "@executor/react": "workspace:*",
294 "@executor/ui": "workspace:*",
366 "@types/node": "catalog:",295 "@types/node": "catalog:",
296 "@types/react": "^19.1.0",
367 "bun-types": "catalog:",297 "bun-types": "catalog:",
368 "typescript": "^5.9.3",298 "react": "^19.1.0",
369 "vitest": "catalog:",299 "vitest": "catalog:",
370 },300 },
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 ],
371 },315 },
372 "packages/platform/server": {316 "packages/plugins/graphql": {
373 "name": "@executor/server",317 "name": "@executor/plugin-graphql",
374 "version": "0.0.0",318 "version": "1.4.0-beta.0",
375 "dependencies": {319 "dependencies": {
376 "@effect/opentelemetry": "^0.61.0",
377 "@effect/platform": "catalog:",320 "@effect/platform": "catalog:",
378 "@effect/platform-node": "catalog:",321 "@effect/platform-node": "catalog:",
379 "@executor/executor-mcp": "workspace:*",322 "@executor/sdk": "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",
407 "effect": "catalog:",323 "effect": "catalog:",
408 },324 },
409 "devDependencies": {325 "devDependencies": {
326 "@effect-atom/atom-react": "^0.5.0",
410 "@effect/vitest": "catalog:",327 "@effect/vitest": "catalog:",
411 "@executor/effect-test-utils": "workspace:*",328 "@executor/api": "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": {
440 "@executor/react": "workspace:*",329 "@executor/react": "workspace:*",
441 "react": "^19.2.0",330 "@executor/ui": "workspace:*",
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": {
460 "@types/node": "catalog:",331 "@types/node": "catalog:",
332 "@types/react": "^19.1.0",
461 "bun-types": "catalog:",333 "bun-types": "catalog:",
334 "react": "^19.1.0",
335 "vitest": "catalog:",
462 },336 },
463 },337 "peerDependencies": {
464 "plugins/google-discovery/react": {338 "@effect-atom/atom-react": "^0.5.0",
465 "name": "@executor/plugin-google-discovery-react",339 "@executor/api": "workspace:*",
466 "version": "0.0.0",
467 "dependencies": {
468 "@executor/plugin-google-discovery-http": "workspace:*",
469 "@executor/plugin-google-discovery-shared": "workspace:*",
470 "@executor/react": "workspace:*",340 "@executor/react": "workspace:*",
471 "react": "^19.2.0",341 "@executor/ui": "workspace:*",
472 },342 "@tanstack/react-router": "^1.168.10",
473 "devDependencies": {343 "react": "^19.1.0",
474 "@types/node": "catalog:",344 },
475 "@types/react": "^19.2.10",345 "optionalPeers": [
476 "bun-types": "catalog:",346 "@effect-atom/atom-react",
477 },347 "@executor/api",
348 "@executor/react",
349 "@executor/ui",
350 "@tanstack/react-router",
351 "react",
352 ],
478 },353 },
479 "plugins/google-discovery/sdk": {354 "packages/plugins/keychain": {
480 "name": "@executor/plugin-google-discovery-sdk",355 "name": "@executor/plugin-keychain",
481 "version": "0.0.0",356 "version": "1.4.0-beta.0",
482 "dependencies": {357 "dependencies": {
483 "@effect/platform": "catalog:",358 "@executor/sdk": "workspace:*",
484 "@executor/codemode-core": "workspace:*",359 "@napi-rs/keyring": "^1.2.0",
485 "@executor/ir": "workspace:*",
486 "@executor/platform-sdk": "workspace:*",
487 "@executor/plugin-google-discovery-shared": "workspace:*",
488 "@executor/source-core": "workspace:*",
489 "effect": "catalog:",360 "effect": "catalog:",
490 },361 },
491 "devDependencies": {362 "devDependencies": {
@@ -495,345 +366,186 @@ · 3 unmodified lines
495 "vitest": "catalog:",366 "vitest": "catalog:",
496 },367 },
497 },368 },
498 "plugins/google-discovery/shared": {369 "packages/plugins/mcp": {
499 "name": "@executor/plugin-google-discovery-shared",370 "name": "@executor/plugin-mcp",
500 "version": "0.0.0",371 "version": "1.4.0-beta.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",
514 "dependencies": {372 "dependencies": {
515 "@effect/platform": "catalog:",373 "@effect/platform": "catalog:",
516 "@executor/platform-api": "workspace:*",374 "@effect/platform-node": "catalog:",
517 "@executor/platform-sdk": "workspace:*",375 "@executor/sdk": "workspace:*",
518 "@executor/plugin-graphql-shared": "workspace:*",376 "@modelcontextprotocol/sdk": "^1.29.0",
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:*",
550 "effect": "catalog:",377 "effect": "catalog:",
551 "graphql": "^16.12.0",
552 },378 },
553 "devDependencies": {379 "devDependencies": {
380 "@effect-atom/atom-react": "^0.5.0",
554 "@effect/vitest": "catalog:",381 "@effect/vitest": "catalog:",
382 "@executor/api": "workspace:*",
383 "@executor/react": "workspace:*",
384 "@executor/ui": "workspace:*",
555 "@types/node": "catalog:",385 "@types/node": "catalog:",
386 "@types/react": "^19.1.0",
556 "bun-types": "catalog:",387 "bun-types": "catalog:",
388 "react": "^19.1.0",
557 "vitest": "catalog:",389 "vitest": "catalog:",
558 },390 },
559 },391 "peerDependencies": {
560 "plugins/graphql/shared": {392 "@effect-atom/atom-react": "^0.5.0",
561 "name": "@executor/plugin-graphql-shared",393 "@executor/api": "workspace:*",
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": {
602 "@executor/react": "workspace:*",394 "@executor/react": "workspace:*",
603 "react": "^19.2.0",395 "@executor/ui": "workspace:*",
604 },396 "@tanstack/react-router": "^1.168.10",
605 "devDependencies": {397 "react": "^19.1.0",
606 "@types/node": "catalog:",398 },
607 "@types/react": "^19.2.10",399 "optionalPeers": [
608 "bun-types": "catalog:",400 "@effect-atom/atom-react",
609 },401 "@executor/api",
610 },402 "@executor/react",
611 "plugins/local-tools/sdk": {403 "@executor/ui",
612 "name": "@executor/plugin-local-tools-sdk",404 "@tanstack/react-router",
613 "version": "0.0.0",405 "react",
614 "dependencies": {406 ],
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 },
625 },407 },
626 "plugins/mcp/http": {408 "packages/plugins/onepassword": {
627 "name": "@executor/plugin-mcp-http",409 "name": "@executor/plugin-onepassword",
628 "version": "0.0.0",410 "version": "1.4.0-beta.0",
629 "dependencies": {411 "dependencies": {
412 "@1password/op-js": "^0.1.13",
413 "@1password/sdk": "^0.4.1-beta.1",
414 "@effect-atom/atom-react": "^0.5.0",
630 "@effect/platform": "catalog:",415 "@effect/platform": "catalog:",
631 "@executor/platform-api": "workspace:*",416 "@executor/api": "workspace:*",
632 "@executor/platform-sdk": "workspace:*",417 "@executor/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",
666 "effect": "catalog:",418 "effect": "catalog:",
667 },419 },
668 "devDependencies": {420 "devDependencies": {
669 "@effect/vitest": "catalog:",421 "@effect/vitest": "catalog:",
670 "@executor/runtime-ses": "workspace:*",
671 "@types/node": "catalog:",422 "@types/node": "catalog:",
672 "bun-types": "catalog:",423 "bun-types": "catalog:",
673 "vitest": "catalog:",424 "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:",
688 },425 },
689 },426 "peerDependencies": {
690 "plugins/onepassword/http": {427 "@effect-atom/atom-react": "^0.5.0",
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:*",
710 "@executor/react": "workspace:*",428 "@executor/react": "workspace:*",
711 "react": "^19.2.0",429 "@executor/ui": "workspace:*",
712 },430 "react": ">=18",
713 "devDependencies": {431 },
714 "@types/node": "catalog:",432 "optionalPeers": [
715 "@types/react": "^19.2.10",433 "@effect-atom/atom-react",
716 "bun-types": "catalog:",434 "@executor/react",
717 },435 "@executor/ui",
718 },436 "react",
719 "plugins/onepassword/sdk": {437 ],
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 },
732 },438 },
733 "plugins/onepassword/shared": {439 "packages/plugins/openapi": {
734 "name": "@executor/plugin-onepassword-shared",440 "name": "@executor/plugin-openapi",
735 "version": "0.0.0",441 "version": "1.4.0-beta.0",
736 "dependencies": {442 "dependencies": {
443 "@apidevtools/swagger-parser": "^12.1.0",
737 "@effect/platform": "catalog:",444 "@effect/platform": "catalog:",
738 "@executor/platform-sdk": "workspace:*",445 "@effect/platform-node": "catalog:",
739 "effect": "catalog:",446 "@executor/sdk": "workspace:*",
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:*",
754 "effect": "catalog:",447 "effect": "catalog:",
448 "openapi-types": "^12.1.3",
449 "yaml": "^2.7.1",
755 },450 },
756 "devDependencies": {451 "devDependencies": {
757 "@types/node": "catalog:",452 "@effect-atom/atom-react": "^0.5.0",
758 "bun-types": "catalog:",453 "@effect/vitest": "catalog:",
759 },454 "@executor/api": "workspace:*",
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:*",
767 "@executor/react": "workspace:*",455 "@executor/react": "workspace:*",
768 "react": "^19.2.0",456 "@executor/ui": "workspace:*",
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:*",
792 "@types/node": "catalog:",457 "@types/node": "catalog:",
458 "@types/react": "^19.1.0",
793 "bun-types": "catalog:",459 "bun-types": "catalog:",
460 "react": "^19.1.0",
794 "vitest": "catalog:",461 "vitest": "catalog:",
795 },462 },
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 ],
796 },479 },
797 "plugins/openapi/shared": {480 "packages/ui": {
798 "name": "@executor/plugin-openapi-shared",481 "name": "@executor/ui",
799 "version": "0.0.0",482 "version": "1.4.0-beta.0",
800 "dependencies": {483 "dependencies": {
801 "@executor/platform-sdk": "workspace:*",484 "@base-ui/react": "^1.3.0",
802 "@executor/source-core": "workspace:*",485 "@hookform/resolvers": "^5.2.2",
803 "effect": "catalog:",486 "@shikijs/langs": "^4.0.2",
804 "yaml": "^2.8.1",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",
805 },508 },
806 "devDependencies": {509 "devDependencies": {
807 "@types/node": "catalog:",510 "@types/react": "^19.1.0",
808 "bun-types": "catalog:",511 "hast-util-to-jsx-runtime": "^2.3.6",
512 "tailwindcss": "^4.1.10",
513 "typescript": "^5.9.3",
809 },514 },
810 },515 },
811 },516 },
812 "catalog": {517 "catalog": {
813 "@effect/cli": "^0.73.2",518 "@effect/cli": "^0.73.2",
814 "@effect/platform": "^0.94.5",519 "@effect/cluster": "^0.58.0",
815 "@effect/platform-node": "^0.104.1",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",
816 "@effect/vitest": "^0.27.0",527 "@effect/vitest": "^0.27.0",
817 "@types/node": "^24.3.1",528 "@types/node": "^24.3.1",
818 "bun-types": "^1.2.22",529 "bun-types": "^1.2.22",
819 "effect": "^3.19.19",530 "effect": "^3.21.0",
820 "vitest": "^3.2.4",531 "vitest": "^3.2.4",
821 "zod": "^4.3.6",
822 },532 },
823 "packages": {533 "packages": {
534 "@1password/op-js": ["@1password/op-js@0.1.13", "", { "dependencies": { "lookpath": "^1.2.2", "semver": "^7.6.2" } }, "sha512-ZZBLxVqywFdvIbLv2xWw2N1ImSi183rRKf90vV19KRMReNyLwuD0dv6IrKrIdrJU33IuV3Gz85Z4K2a1PJTBDg=="],
535
824 "@1password/sdk": ["@1password/sdk@0.4.1-beta.1", "", { "dependencies": { "@1password/sdk-core": "0.4.1-beta.1" } }, "sha512-QWY6eIIEs9at6kAFbgjZ1vVxg7ygp/MwXJ6/BoBdPkqIk8vfulXu4pjDsVQ87HhddJAD5LVGBXSbQIa+svI3bA=="],536 "@1password/sdk": ["@1password/sdk@0.4.1-beta.1", "", { "dependencies": { "@1password/sdk-core": "0.4.1-beta.1" } }, "sha512-QWY6eIIEs9at6kAFbgjZ1vVxg7ygp/MwXJ6/BoBdPkqIk8vfulXu4pjDsVQ87HhddJAD5LVGBXSbQIa+svI3bA=="],
825 537
826 "@1password/sdk-core": ["@1password/sdk-core@0.4.1-beta.1", "", {}, "sha512-/otbg1JVhsEn6oUIeReoT9TmFr8J7KBwr9UuRVfJFwwGG3bHPF8ewT+LhRimQeJtypqQ69ZVuOYkxknD4iQHxw=="],538 "@1password/sdk-core": ["@1password/sdk-core@0.4.1-beta.1", "", {}, "sha512-/otbg1JVhsEn6oUIeReoT9TmFr8J7KBwr9UuRVfJFwwGG3bHPF8ewT+LhRimQeJtypqQ69ZVuOYkxknD4iQHxw=="],
827 539
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=="],
829 541
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=="],
831 543
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=="],
833 545
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=="],
835 547
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=="],
837 549
838 "@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=="],550 "@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=="],
839 551
@@ -843,53 +555,31 @@ · 3 unmodified lines
843 555
844 "@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=="],556 "@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=="],
845 557
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
848 "@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=="],558 "@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=="],
849 559
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
852 "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],560 "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
853 561
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
856 "@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=="],562 "@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=="],
857 563
858 "@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=="],564 "@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=="],
859 565
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
862 "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="],566 "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="],
863 567
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
868 "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],568 "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
869 569
870 "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],570 "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
871 571
872 "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],572 "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
873 573
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=="],574 "@babel/helpers": ["@babel/helpers@7.29.2", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.29.0" } }, "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw=="],
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=="],
881 575
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=="],
883 577
884 "@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=="],578 "@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=="],
885 579
886 "@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=="],580 "@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=="],
887 581
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=="],582 "@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="],
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=="],
893 583
894 "@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=="],584 "@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=="],
895 585
@@ -901,6 +591,8 @@ · 5 unmodified lines
901 591
902 "@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=="],592 "@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=="],
903 593
594 "@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.2", "", {}, "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA=="],
595
904 "@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=="],596 "@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=="],
905 597
906 "@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=="],598 "@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
935 627
936 "@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=="],628 "@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=="],
937 629
938 "@csstools/color-helpers": ["@csstools/color-helpers@5.1.0", "", {}, "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA=="],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=="],
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=="],
941 631
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=="],
943 633
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=="],
945 635
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=="],
947 637
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=="],
949 639
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=="],
951 641
952 "@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=="],642 "@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=="],
953 643
@@ -955,167 +645,115 @@ · 1 unmodified line
955 645
956 "@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=="],646 "@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=="],
957 647
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=="],
959 649
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=="],
961 651
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=="],
963 653
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=="],
965 655
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=="],
967 657
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=="],
969 661
970 "@effect/printer": ["@effect/printer@0.47.0", "", { "peerDependencies": { "@effect/typeclass": "^0.38.0", "effect": "^3.19.0" } }, "sha512-VgR8e+YWWhMEAh9qFOjwiZ3OXluAbcVLIOtvp2S5di1nSrPOZxj78g8LE77JSvyfp5y5bS2gmFW+G7xD5uU+2Q=="],662 "@effect/printer": ["@effect/printer@0.47.0", "", { "peerDependencies": { "@effect/typeclass": "^0.38.0", "effect": "^3.19.0" } }, "sha512-VgR8e+YWWhMEAh9qFOjwiZ3OXluAbcVLIOtvp2S5di1nSrPOZxj78g8LE77JSvyfp5y5bS2gmFW+G7xD5uU+2Q=="],
971 663
972 "@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=="],664 "@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=="],
973 665
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=="],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=="],
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=="],
983 667
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=="],
985 669
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=="],
987 671
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=="],
989 673
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=="],
991 675
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=="],
993 677
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=="],
995 679
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=="],
997 681
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=="],
999 683
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=="],
1001 685
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=="],
1003 687
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=="],
1005 689
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=="],
1007 691
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=="],
1009 693
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=="],
1011 695
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=="],
1013 697
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=="],
1015 699
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=="],
1017 701
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=="],
1019 703
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=="],
1021 705
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=="],
1023 707
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=="],
1025 709
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=="],
1027 711
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=="],
1029 713
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=="],
1031 715
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=="],
1033 717
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=="],
1035 719
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=="],
1037 721
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=="],
1039 723
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=="],
1041 725
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=="],
1043 727
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=="],
1045 729
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=="],
1047 731
1048 "@executor/ai-sdk-adapter": ["@executor/ai-sdk-adapter@workspace:packages/hosts/ai-sdk"],732 "@executor/api": ["@executor/api@workspace:packages/core/api"],
1049 733
1050 "@executor/codemode-core": ["@executor/codemode-core@workspace:packages/kernel/core"],734 "@executor/codemode-core": ["@executor/codemode-core@workspace:packages/kernel/core"],
1051 735
1052 "@executor/docs": ["@executor/docs@workspace:apps/docs"],736 "@executor/config": ["@executor/config@workspace:packages/core/config"],
1053 737
1054 "@executor/effect-test-utils": ["@executor/effect-test-utils@workspace:packages/dev/effect-test-utils"],738 "@executor/execution": ["@executor/execution@workspace:packages/core/execution"],
1055 739
1056 "@executor/executor-mcp": ["@executor/executor-mcp@workspace:packages/hosts/mcp"],740 "@executor/host-mcp": ["@executor/host-mcp@workspace:packages/hosts/mcp"],
1057 741
1058 "@executor/ir": ["@executor/ir@workspace:packages/kernel/ir"],742 "@executor/ir": ["@executor/ir@workspace:packages/kernel/ir"],
1059 743
1060 "@executor/kitchen-sink": ["@executor/kitchen-sink@workspace:packages/dev/kitchen-sink"],744 "@executor/plugin-file-secrets": ["@executor/plugin-file-secrets@workspace:packages/plugins/file-secrets"],
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"],
1085 745
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"],
1087 747
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"],
1089 749
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"],
1091 751
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"],
1093 753
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"],
1095 755
1096 "@executor/plugin-mcp-http": ["@executor/plugin-mcp-http@workspace:plugins/mcp/http"],756 "@executor/plugin-openapi": ["@executor/plugin-openapi@workspace:packages/plugins/openapi"],
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"],
1119 757
1120 "@executor/react": ["@executor/react@workspace:packages/clients/react"],758 "@executor/react": ["@executor/react@workspace:packages/clients/react"],
1121 759
@@ -1123,15 +761,13 @@ · 1 unmodified line
1123 761
1124 "@executor/runtime-quickjs": ["@executor/runtime-quickjs@workspace:packages/kernel/runtime-quickjs"],762 "@executor/runtime-quickjs": ["@executor/runtime-quickjs@workspace:packages/kernel/runtime-quickjs"],
1125 763
1126 "@executor/runtime-ses": ["@executor/runtime-ses@workspace:packages/kernel/runtime-ses"],764 "@executor/sdk": ["@executor/sdk@workspace:packages/core/sdk"],
1127
1128 "@executor/serve-skills-via-mcp-demo": ["@executor/serve-skills-via-mcp-demo@workspace:examples/serve-skills-via-mcp"],
1129 765
1130 "@executor/server": ["@executor/server@workspace:packages/platform/server"],766 "@executor/server": ["@executor/server@workspace:apps/server"],
1131 767
1132 "@executor/source-core": ["@executor/source-core@workspace:packages/sources/core"],768 "@executor/storage-file": ["@executor/storage-file@workspace:packages/core/storage-file"],
1133 769
1134 "@executor/sqlite-sdk-consumer-example": ["@executor/sqlite-sdk-consumer-example@workspace:examples/sqlite-sdk-consumer"],770 "@executor/ui": ["@executor/ui@workspace:packages/ui"],
1135 771
1136 "@executor/web": ["@executor/web@workspace:apps/web"],772 "@executor/web": ["@executor/web@workspace:apps/web"],
1137 773
@@ -1143,26 +779,16 @@ · 5 unmodified lines
1143 779
1144 "@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="],780 "@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="],
1145 781
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=="],782 "@hono/node-server": ["@hono/node-server@1.19.12", "", { "peerDependencies": { "hono": "^4" } }, "sha512-txsUW4SQ1iilgE0l9/e9VQWmELXifEFvmdA1j6WFh/aFPj99hIntrSsq/if0UWyGVkmrRPKA1wCeP+UCr1B9Uw=="],
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=="],
1153 783
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=="],
1155 785
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=="],
1157 787
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=="],
1159 789
1160 "@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=="],790 "@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=="],
1161 791
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
1166 "@jitl/quickjs-ffi-types": ["@jitl/quickjs-ffi-types@0.31.0", "", {}, "sha512-1yrgvXlmXH2oNj3eFTrkwacGJbmM0crwipA3ohCrjv52gBeDaD7PsTvFYinlAnqU8iPME3LGP437yk05a2oejw=="],792 "@jitl/quickjs-ffi-types": ["@jitl/quickjs-ffi-types@0.31.0", "", {}, "sha512-1yrgvXlmXH2oNj3eFTrkwacGJbmM0crwipA3ohCrjv52gBeDaD7PsTvFYinlAnqU8iPME3LGP437yk05a2oejw=="],
1167 793
1168 "@jitl/quickjs-wasmfile-debug-asyncify": ["@jitl/quickjs-wasmfile-debug-asyncify@0.31.0", "", { "dependencies": { "@jitl/quickjs-ffi-types": "0.31.0" } }, "sha512-YkdzQdr1uaftFhgEnTRjTTZHk2SFZdpWO7XhOmRVbi6CEVsH9g5oNF8Ta1q3OuSJHRwwT8YsuR1YzEiEIJEk6w=="],794 "@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
1183 809
1184 "@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=="],810 "@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=="],
1185 811
1186 "@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="],
1187
1188 "@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=="],812 "@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=="],
1189 813
1190 "@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=="],814 "@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=="],
1191 815
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=="],
1193 817
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=="],
1195 819
1196 "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="],820 "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="],
1197 821
@@ -1205,8 +829,6 @@ · 7 unmodified lines
1205 829
1206 "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="],830 "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="],
1207 831
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
1210 "@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=="],832 "@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=="],
1211 833
1212 "@napi-rs/keyring-darwin-arm64": ["@napi-rs/keyring-darwin-arm64@1.2.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-CA83rDeyONDADO25JLZsh3eHY8yTEtm/RS6ecPsY+1v+dSawzT9GywBMu2r6uOp1IEhQs/xAfxgybGAFr17lSA=="],834 "@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
1233 855
1234 "@napi-rs/keyring-win32-x64-msvc": ["@napi-rs/keyring-win32-x64-msvc@1.2.0", "", { "os": "win32", "cpu": "x64" }, "sha512-xFlx/TsmqmCwNU9v+AVnEJgoEAlBYgzFF5Ihz1rMpPAt4qQWWkMd4sCyM1gMJ1A/GnRqRegDiQpwaxGUHFtFbA=="],856 "@napi-rs/keyring-win32-x64-msvc": ["@napi-rs/keyring-win32-x64-msvc@1.2.0", "", { "os": "win32", "cpu": "x64" }, "sha512-xFlx/TsmqmCwNU9v+AVnEJgoEAlBYgzFF5Ihz1rMpPAt4qQWWkMd4sCyM1gMJ1A/GnRqRegDiQpwaxGUHFtFbA=="],
1235 857
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=="],
1237 863
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=="],
1239 865
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=="],
1241 867
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=="],
1243 869
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=="],
1245 871
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=="],
1247 873
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=="],
1249 879
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=="],
1251 881
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=="],
1253 883
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=="],
1255 885
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=="],
1257 887
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=="],
1259 889
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=="],
1261 891
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=="],
1263 893
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=="],
1265 895
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=="],
1267 897
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=="],
1269 899
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=="],
1271 901
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=="],
1273 903
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=="],
1275 905
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=="],
1277 907
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=="],
1279 909
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=="],
1281 911
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=="],
1283 913
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=="],
1285 915
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=="],
1287 917
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=="],
1289 919
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=="],
1291 921
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=="],
1293 923
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=="],
1295 925
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=="],
1297 927
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=="],
1299 929
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=="],
1301 931
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=="],
1303 933
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=="],
1305 935
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=="],
1307 937
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=="],
1309 939
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=="],
1311 941
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=="],
1313 943
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=="],
1315 945
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=="],
1317 947
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=="],
1319 949
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=="],
1321 951
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=="],
1323 953
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=="],
1325 955
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=="],
1327 957
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=="],
1329 959
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=="],
1331 961
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=="],
1333 963
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=="],
1335 965
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=="],
1337 967
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=="],
1339 969
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=="],
1341 971
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=="],
1343 973
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=="],
1345 975
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=="],
1347 977
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=="],
1349 979
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=="],
1351 981
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=="],
1353 983
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=="],
1355 985
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=="],
1357 987
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=="],
1359 989
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=="],
1361 991
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=="],
1363 993
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=="],
1365 995
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=="],
1367 997
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=="],
1369 999
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=="],
1371 1001
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=="],
1373 1003
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=="],
1375 1005
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=="],
1377 1007
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=="],
1379 1051
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=="],
1381 1053
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=="],
1383 1055
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=="],
1385 1057
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=="],
1387 1059
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=="],
1389 1061
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=="],
1391 1063
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=="],
1393 1065
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=="],
1395 1067
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=="],
1397 1069
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=="],
1399 1071
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=="],
1401 1073
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=="],
1403 1075
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=="],
1405 1077
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=="],
1407 1079
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=="],
1409 1081
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=="],
1411 1083
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=="],
1413 1085
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=="],
1415 1087
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=="],
1417 1089
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=="],
1419 1091
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=="],
1421 1093
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=="],
1423 1095
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=="],
1425 1097
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=="],
1427 1099
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=="],
1429 1101
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=="],
1431 1103
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=="],
1433 1105
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=="],
1435 1107
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=="],
1437 1109
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=="],
1439 1111
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=="],
1441 1113
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=="],
1443 1115
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=="],
1445 1117
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=="],
1447 1119
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=="],
1449 1121
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=="],
1451 1123
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=="],
1453 1125
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=="],
1455 1127
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=="],
1457 1129
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=="],
1459 1131
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=="],
1461 1133
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=="],
1463 1135
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=="],
1465 1137
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=="],
1467 1139
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=="],
1469 1141
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=="],
1471 1143
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=="],
1473 1145
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=="],
1475 1147
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=="],
1477 1149
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=="],
1479 1151
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=="],
1481 1153
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=="],
1483 1155
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=="],
1485 1157
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=="],
1487 1159
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=="],
1489 1161
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=="],
1491 1163
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=="],
1493 1165
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=="],
1495 1167
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=="],
1497 1169
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=="],
1499 1171
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=="],
1501 1173
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=="],
1503 1175
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=="],
1505 1177
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=="],
1507 1179
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=="],
1509 1181
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=="],
1511 1183
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=="],
1513 1185
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=="],
1515 1187
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=="],
1517 1189
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=="],
1519 1191
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=="],
1521 1193
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=="],
1523 1195
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=="],
1525 1197
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=="],
1527 1199
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=="],
1529 1201
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=="],
1531 1203
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=="],
1533 1205
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=="],
1535 1207
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=="],
1537 1209
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=="],
1539 1211
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=="],
1541 1213
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=="],
1543 1215
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=="],
1545 1217
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=="],
1547 1219
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=="],
1549 1221
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=="],
1551 1223
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=="],
1553 1225
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=="],
1555 1227
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=="],
1557 1229
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=="],
1559 1231
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=="],
1561 1233
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=="],
1563 1235
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=="],
1565 1237
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=="],
1567 1239
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=="],
1569 1241
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=="],
1571 1243
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=="],
1573 1245
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=="],
1575 1247
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=="],
1577 1249
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=="],
1579 1251
1580 "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],1252 "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
1581 1253
@@ -1583,35 +1255,33 @@ · 1 unmodified line
1583 1255
1584 "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],1256 "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
1585 1257
1258 "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
1259
1586 "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],1260 "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
1587 1261
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=="],
1589 1263
1590 "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],1264 "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
1591 1265
1592 "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],1266 "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
1593 1267
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=="],
1595 1269
1596 "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],1270 "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
1597 1271
1598 "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],1272 "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
1599 1273
1600 "@types/react-reconciler": ["@types/react-reconciler@0.28.9", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg=="],1274 "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
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=="],
1605 1275
1606 "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],1276 "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
1607 1277
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=="],
1609 1279
1610 "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],1280 "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
1611 1281
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=="],
1613 1283
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=="],
1615 1285
1616 "@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=="],1286 "@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=="],
1617 1287
@@ -1629,20 +1299,18 @@ · 11 unmodified lines
1629 1299
1630 "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],1300 "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
1631 1301
1632 "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],1302 "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
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=="],
1635 1303
1636 "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=="],1304 "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=="],
1637 1305
1306 "ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="],
1307
1638 "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],1308 "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
1639 1309
1640 "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],1310 "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
1641 1311
1642 "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],1312 "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
1643 1313
1644 "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
1645
1646 "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],1314 "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
1647 1315
1648 "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],1316 "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
@@ -1651,29 +1319,29 @@ · 2 unmodified lines
1651 1319
1652 "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],1320 "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
1653 1321
1654 "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="],
1655
1656 "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],1322 "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
1657 1323
1658 "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],1324 "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
1659 1325
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=="],
1661 1327
1662 "better-path-resolve": ["better-path-resolve@1.0.0", "", { "dependencies": { "is-windows": "^1.0.0" } }, "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g=="],1328 "better-path-resolve": ["better-path-resolve@1.0.0", "", { "dependencies": { "is-windows": "^1.0.0" } }, "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g=="],
1663 1329
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=="],
1665 1331
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=="],
1667 1335
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=="],
1669 1337
1670 "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],1338 "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
1671 1339
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=="],
1673 1341
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=="],
1675 1343
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=="],
1677 1345
1678 "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],1346 "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
1679 1347
@@ -1683,16 +1351,14 @@ · 3 unmodified lines
1683 1351
1684 "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],1352 "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
1685 1353
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=="],
1687 1355
1688 "caniuse-lite": ["caniuse-lite@1.0.30001777", "", {}, "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ=="],1356 "caniuse-lite": ["caniuse-lite@1.0.30001784", "", {}, "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw=="],
1689 1357
1690 "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],1358 "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
1691 1359
1692 "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=="],1360 "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=="],
1693 1361
1694 "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
1695
1696 "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],1362 "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
1697 1363
1698 "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],1364 "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],
@@ -1705,29 +1371,23 @@ · 6 unmodified lines
1705 1371
1706 "check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="],1372 "check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="],
1707 1373
1708 "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],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=="],
1709
1710 "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
1711 1375
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=="],
1713 1377
1714 "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],1378 "chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
1715 1379
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=="],
1717 1381
1718 "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],1382 "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
1719 1383
1720 "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=="],1384 "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=="],
1721 1385
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
1728 "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],1386 "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
1729 1387
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=="],
1731 1391
1732 "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="],1392 "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="],
1733 1393
@@ -1743,37 +1403,103 @@ · 9 unmodified lines
1743 1403
1744 "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="],1404 "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="],
1745 1405
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=="],
1747 1407
1748 "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],1408 "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
1749 1409
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=="],
1751 1413
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=="],
1753 1415
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=="],
1755 1429
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=="],
1757 1431
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=="],
1759 1489
1760 "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],1490 "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
1761 1491
1762 "decimal.js": ["decimal.js@10.6.0", "", {}, "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="],1492 "decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="],
1763 1493
1764 "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="],1494 "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="],
1765 1495
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=="],
1767 1497
1768 "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],1498 "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
1769 1499
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=="],
1771 1501
1772 "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],1502 "delaunator": ["delaunator@5.1.0", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ=="],
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=="],
1777 1503
1778 "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],1504 "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
1779 1505
@@ -1787,38 +1513,34 @@ · 7 unmodified lines
1787 1513
1788 "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],1514 "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
1789 1515
1790 "diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
1791
1792 "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="],1516 "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="],
1793 1517
1794 "dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="],1518 "dompurify": ["dompurify@3.3.3", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA=="],
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=="],
1797 1519
1798 "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=="],1520 "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=="],
1799 1521
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
1802 "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],1522 "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
1803 1523
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=="],
1805 1527
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=="],
1807 1529
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=="],
1809 1533
1810 "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],1534 "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
1811 1535
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=="],
1813 1539
1814 "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="],1540 "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="],
1815 1541
1816 "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],1542 "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
1817 1543
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
1822 "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],1544 "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
1823 1545
1824 "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],1546 "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
@@ -1827,7 +1549,9 @@ · 2 unmodified lines
1827 1549
1828 "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],1550 "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
1829 1551
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=="],
1831 1555
1832 "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],1556 "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
1833 1557
@@ -1843,19 +1567,21 @@ · 9 unmodified lines
1843 1567
1844 "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],1568 "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
1845 1569
1570 "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="],
1571
1846 "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],1572 "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
1847 1573
1848 "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="],1574 "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="],
1849 1575
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"],
1851 1577
1852 "executor": ["executor@workspace:apps/executor"],1578 "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
1853 1579
1854 "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],1580 "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
1855 1581
1856 "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=="],1582 "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=="],
1857 1583
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=="],
1859 1585
1860 "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],1586 "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
1861 1587
@@ -1871,13 +1597,9 @@ · 9 unmodified lines
1871 1597
1872 "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],1598 "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
1873 1599
1874 "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="],
1875
1876 "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],1600 "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
1877 1601
1878 "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],1602 "file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
1879
1880 "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="],
1881 1603
1882 "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],1604 "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
1883 1605
@@ -1887,37 +1609,27 @@ · 3 unmodified lines
1887 1609
1888 "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],1610 "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
1889 1611
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
1894 "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],1612 "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
1895 1613
1896 "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],1614 "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
1897 1615
1616 "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
1617
1898 "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=="],1618 "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=="],
1899 1619
1900 "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],1620 "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
1901 1621
1902 "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],1622 "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
1903 1623
1904 "fuzzysort": ["fuzzysort@3.1.0", "", {}, "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ=="],
1905
1906 "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],1624 "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
1907 1625
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
1912 "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=="],1626 "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=="],
1913 1627
1914 "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="],1628 "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="],
1915 1629
1916 "get-own-enumerable-keys": ["get-own-enumerable-keys@1.0.0", "", {}, "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA=="],
1917
1918 "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],1630 "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
1919 1631
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=="],
1921 1633
1922 "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],1634 "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
1923 1635
@@ -1927,7 +1639,7 @@ · 3 unmodified lines
1927 1639
1928 "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],1640 "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
1929 1641
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=="],
1931 1643
1932 "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],1644 "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
1933 1645
@@ -1951,11 +1663,7 @@ · 17 unmodified lines
1951 1663
1952 "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=="],1664 "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=="],
1953 1665
1954 "headers-polyfill": ["headers-polyfill@4.0.3", "", {}, "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ=="],1666 "hono": ["hono@4.12.9", "", {}, "sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA=="],
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=="],
1959 1667
1960 "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],1668 "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],
1961 1669
@@ -1963,19 +1671,15 @@ · 1 unmodified line
1963 1671
1964 "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=="],1672 "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=="],
1965 1673
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
1970 "human-id": ["human-id@4.1.3", "", { "bin": { "human-id": "dist/cli.js" } }, "sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q=="],1674 "human-id": ["human-id@4.1.3", "", { "bin": { "human-id": "dist/cli.js" } }, "sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q=="],
1971 1675
1972 "human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="],
1973
1974 "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],1676 "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
1975 1677
1976 "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],1678 "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
1977 1679
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=="],
1979 1683
1980 "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],1684 "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
1981 1685
@@ -1983,7 +1687,11 @@ · 1 unmodified line
1983 1687
1984 "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],1688 "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
1985 1689
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=="],
1987 1695
1988 "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],1696 "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
1989 1697
@@ -1991,70 +1699,38 @@ · 1 unmodified line
1991 1699
1992 "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],1700 "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],
1993 1701
1994 "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
1995
1996 "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],1702 "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],
1997 1703
1998 "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
1999
2000 "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],1704 "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
2001 1705
2002 "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
2003
2004 "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],1706 "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
2005 1707
2006 "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="],1708 "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="],
2007 1709
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
2016 "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],1710 "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
2017 1711
2018 "is-obj": ["is-obj@3.0.0", "", {}, "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ=="],
2019
2020 "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],1712 "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
2021 1713
2022 "is-potential-custom-element-name": ["is-potential-custom-element-name@1.0.1", "", {}, "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="],
2023
2024 "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],1714 "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],
2025 1715
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
2030 "is-subdir": ["is-subdir@1.2.0", "", { "dependencies": { "better-path-resolve": "1.0.0" } }, "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw=="],1716 "is-subdir": ["is-subdir@1.2.0", "", { "dependencies": { "better-path-resolve": "1.0.0" } }, "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw=="],
2031 1717
2032 "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
2033
2034 "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="],1718 "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="],
2035 1719
2036 "is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="],1720 "isbot": ["isbot@5.1.37", "", {}, "sha512-5bcicX81xf6NlTEV8rWdg7Pk01LFizDetuYGHx6d/f6y3lR2/oo8IfxjzJqn1UdDEyCcwT9e7NRloj8DwCYujQ=="],
2037
2038 "isbot": ["isbot@5.1.35", "", {}, "sha512-waFfC72ZNfwLLuJ2iLaoVaqcNo+CAaLR7xCpAn0Y5WfGzkNHv7ZN39Vbi1y+kb+Zs46XHOX3tZNExroFUPX+Kg=="],
2039 1721
2040 "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],1722 "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
2041 1723
2042 "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],1724 "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
2043 1725
2044 "jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="],1726 "jose": ["jose@6.2.2", "", {}, "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ=="],
2045 1727
2046 "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],1728 "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
2047 1729
2048 "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],1730 "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
2049 1731
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
2052 "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],1732 "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
2053 1733
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
2058 "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],1734 "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
2059 1735
2060 "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],1736 "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],
@@ -2065,53 +1741,53 @@ · 4 unmodified lines
2065 1741
2066 "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],1742 "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
2067 1743
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=="],
2069 1745
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=="],
2071 1747
2072 "kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="],1748 "kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="],
2073 1749
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=="],
2075 1753
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=="],
2077 1755
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=="],
2079 1757
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=="],
2081 1759
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=="],
2083 1761
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=="],
2085 1763
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=="],
2087 1765
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=="],
2089 1767
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=="],
2091 1769
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=="],
2093 1771
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=="],
2095 1773
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=="],
2097 1775
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=="],
2099 1777
2100 "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],1778 "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
2101 1779
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=="],
2103 1781
2104 "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="],1782 "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="],
2105 1783
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
2110 "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],1784 "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
2111 1785
1786 "lookpath": ["lookpath@1.2.3", "", { "bin": { "lookpath": "bin/lookpath.js" } }, "sha512-kthRVhf4kH4+HW3anM4UBHxsw/XFESf13euCEldhXr6GpBdmBoa7rDd7WO5G0Mhd4G5XtKTcEy8OR0iRZXpS3Q=="],
1787
2112 "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],1788 "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
2113 1789
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=="],
2115 1791
2116 "lucide-react": ["lucide-react@1.7.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-yI7BeItCLZJTXikmK4KNUGCKoGzSvbKlfCvw44bU4fXAL6v3gYS4uHD1jzsLkfwODYwI6Drw5Tu9Z5ulDe0TSg=="],1792 "lucide-react": ["lucide-react@1.7.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-yI7BeItCLZJTXikmK4KNUGCKoGzSvbKlfCvw44bU4fXAL6v3gYS4uHD1jzsLkfwODYwI6Drw5Tu9Z5ulDe0TSg=="],
2117 1793
@@ -2119,7 +1795,7 @@ · 1 unmodified line
2119 1795
2120 "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="],1796 "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="],
2121 1797
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=="],
2123 1799
2124 "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],1800 "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
2125 1801
@@ -2157,10 +1833,10 @@ · 31 unmodified lines
2157 1833
2158 "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],1834 "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
2159 1835
2160 "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
2161
2162 "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],1836 "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
2163 1837
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
2164 "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=="],1840 "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=="],
2165 1841
2166 "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=="],1842 "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
2225 1901
2226 "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],1902 "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
2227 1903
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=="],
2229 1905
2230 "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],1906 "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
2231 1907
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=="],
2233 1909
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=="],
2235 1911
2236 "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],1912 "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
2237 1913
2238 "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],1914 "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
2239 1915
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=="],
2241 1917
2242 "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=="],1918 "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=="],
2243 1919
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
2246 "multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="],1920 "multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="],
2247 1921
2248 "mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="],
2249
2250 "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],1922 "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
2251 1923
1924 "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="],
1925
2252 "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],1926 "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
2253 1927
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=="],
2255 1929
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=="],
2257 1931
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=="],
2259 1933
2260 "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=="],1934 "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=="],
2261 1935
2262 "node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="],1936 "node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="],
2263 1937
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
2268 "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],1938 "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
2269 1939
2270 "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],1940 "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
2271 1941
2272 "object-treeify": ["object-treeify@1.1.33", "", {}, "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A=="],
2273
2274 "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],1942 "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
2275 1943
2276 "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],1944 "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
2277 1945
2278 "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
2279
2280 "oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="],1946 "oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="],
2281 1947
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=="],
2283 1949
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=="],1950 "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
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=="],
2287 1951
2288 "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="],1952 "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="],
2289 1953
2290 "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="],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=="],
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=="],
2295 1955
2296 "p-filter": ["p-filter@2.1.0", "", { "dependencies": { "p-map": "^2.0.0" } }, "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw=="],1956 "p-filter": ["p-filter@2.1.0", "", { "dependencies": { "p-map": "^2.0.0" } }, "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw=="],
2297 1957
@@ -2305,25 +1965,19 @@ · 7 unmodified lines
2305 1965
2306 "package-manager-detector": ["package-manager-detector@0.2.11", "", { "dependencies": { "quansync": "^0.2.7" } }, "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ=="],1966 "package-manager-detector": ["package-manager-detector@0.2.11", "", { "dependencies": { "quansync": "^0.2.7" } }, "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ=="],
2307 1967
2308 "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
2309
2310 "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=="],1968 "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=="],
2311 1969
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
2316 "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],1970 "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
2317 1971
2318 "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],1972 "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
2319 1973
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=="],
2321 1975
2322 "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],1976 "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
2323 1977
2324 "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],1978 "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
2325 1979
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=="],
2327 1981
2328 "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],1982 "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
2329 1983
@@ -2333,31 +1987,29 @@ · 3 unmodified lines
2333 1987
2334 "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],1988 "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
2335 1989
2336 "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],1990 "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
2337 1991
2338 "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="],1992 "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="],
2339 1993
2340 "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="],1994 "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="],
2341 1995
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=="],
2343 1997
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=="],
2345 1999
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=="],
2347 2001
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=="],
2349 2003
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=="],
2351 2005
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=="],
2353 2007
2354 "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],2008 "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
2355 2009
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
2358 "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=="],2010 "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=="],
2359 2011
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=="],
2361 2013
2362 "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],2014 "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
2363 2015
@@ -2371,27 +2023,45 @@ · 7 unmodified lines
2371 2023
2372 "quickjs-emscripten-core": ["quickjs-emscripten-core@0.31.0", "", { "dependencies": { "@jitl/quickjs-ffi-types": "0.31.0" } }, "sha512-oQz8p0SiKDBc1TC7ZBK2fr0GoSHZKA0jZIeXxsnCyCs4y32FStzCW4d1h6E1sE0uHDMbGITbk2zhNaytaoJwXQ=="],2024 "quickjs-emscripten-core": ["quickjs-emscripten-core@0.31.0", "", { "dependencies": { "@jitl/quickjs-ffi-types": "0.31.0" } }, "sha512-oQz8p0SiKDBc1TC7ZBK2fr0GoSHZKA0jZIeXxsnCyCs4y32FStzCW4d1h6E1sE0uHDMbGITbk2zhNaytaoJwXQ=="],
2373 2025
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
2374 "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],2028 "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
2375 2029
2376 "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=="],2030 "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=="],
2377 2031
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
2378 "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],2034 "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
2379 2035
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
2380 "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],2038 "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
2381 2039
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=="],
2383 2045
2384 "react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="],2046 "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="],
2385 2047
2386 "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=="],2048 "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=="],
2387 2049
2388 "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=="],2050 "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=="],
2389 2051
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
2390 "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=="],2054 "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=="],
2391 2055
2392 "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=="],2056 "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=="],
2393 2057
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=="],
2395 2065
2396 "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],2066 "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],
2397 2067
@@ -2413,9 +2083,7 @@ · 15 unmodified lines
2413 2083
2414 "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=="],2084 "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=="],
2415 2085
2416 "remend": ["remend@1.2.2", "", {}, "sha512-4ZJgIB9EG9fQE41mOJCRHMmnxDTKHWawQoJWZyUbZuj680wVyogu2ihnj8Edqm7vh2mo/TWHyEZpn2kqeDvS7w=="],2086 "remend": ["remend@1.3.0", "", {}, "sha512-iIhggPkhW3hFImKtB10w0dz4EZbs28mV/dmbcYVonWEJ6UGHHpP+bFZnTh6GNWJONg5m+U56JrL+8IxZRdgWjw=="],
2417
2418 "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
2419 2087
2420 "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],2088 "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
2421 2089
@@ -2423,49 +2091,43 @@ · 1 unmodified line
2423 2091
2424 "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],2092 "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
2425 2093
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=="],
2427 2095
2428 "rettime": ["rettime@0.10.1", "", {}, "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw=="],2096 "robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="],
2429 2097
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=="],
2431 2099
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=="],
2433 2101
2434 "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=="],2102 "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=="],
2435 2103
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=="],
2437 2105
2438 "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],2106 "rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="],
2439 2107
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=="],
2441 2109
2442 "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],2110 "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
2443 2111
2444 "saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="],
2445
2446 "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],2112 "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
2447 2113
2448 "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],2114 "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
2449 2115
2450 "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=="],2116 "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=="],
2451 2117
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=="],
2453 2119
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=="],
2455 2121
2456 "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=="],2122 "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=="],
2457 2123
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
2460 "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],2124 "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
2461 2125
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
2464 "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],2126 "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
2465 2127
2466 "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],2128 "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
2467 2129
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=="],
2469 2131
2470 "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=="],2132 "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=="],
2471 2133
@@ -2479,15 +2141,13 @@ · 7 unmodified lines
2479 2141
2480 "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],2142 "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
2481 2143
2482 "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],2144 "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
2483 2145
2484 "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],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=="],
2485
2486 "smol-toml": ["smol-toml@1.6.0", "", {}, "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw=="],
2487 2147
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=="],
2489 2149
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=="],
2491 2151
2492 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],2152 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
2493 2153
@@ -2503,25 +2163,17 @@ · 9 unmodified lines
2503 2163
2504 "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],2164 "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
2505 2165
2506 "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="],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=="],
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=="],
2509 2167
2510 "strict-event-emitter": ["strict-event-emitter@0.5.1", "", {}, "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ=="],2168 "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
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=="],
2513 2169
2514 "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=="],2170 "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=="],
2515 2171
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
2518 "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],2172 "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
2519 2173
2520 "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],2174 "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
2521 2175
2522 "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="],2176 "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
2523
2524 "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="],
2525 2177
2526 "strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="],2178 "strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="],
2527 2179
@@ -2529,24 +2181,24 @@ · 1 unmodified line
2529 2181
2530 "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],2182 "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
2531 2183
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=="],
2533 2185
2534 "tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],2186 "tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],
2535 2187
2536 "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
2537
2538 "tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="],2188 "tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="],
2539 2189
2540 "tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="],2190 "tailwindcss": ["tailwindcss@4.2.2", "", {}, "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q=="],
2541 2191
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=="],
2543 2197
2544 "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="],2198 "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="],
2545 2199
2546 "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],2200 "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
2547 2201
2548 "tiny-warning": ["tiny-warning@1.0.3", "", {}, "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="],
2549
2550 "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],2202 "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
2551 2203
2552 "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],2204 "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
@@ -2559,57 +2211,33 @@ · 6 unmodified lines
2559 2211
2560 "tinyspy": ["tinyspy@4.0.4", "", {}, "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q=="],2212 "tinyspy": ["tinyspy@4.0.4", "", {}, "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q=="],
2561 2213
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
2566 "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],2214 "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
2567 2215
2568 "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],2216 "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
2569 2217
2570 "toml": ["toml@3.0.0", "", {}, "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="],2218 "toml": ["toml@3.0.0", "", {}, "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="],
2571 2219
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
2576 "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],2220 "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
2577 2221
2578 "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],2222 "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
2579 2223
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=="],2224 "ts-dedent": ["ts-dedent@2.2.0", "", {}, "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="],
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=="],
2583 2225
2584 "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],2226 "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
2585 2227
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=="],2228 "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
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=="],
2595 2229
2596 "turbo-windows-64": ["turbo-windows-64@2.8.14", "", { "os": "win32", "cpu": "x64" }, "sha512-FTbIeQL1ycLFW2t9uQNMy+bRSzi3Xhwun/e7ZhFBdM+U0VZxxrtfYEBM9CHOejlfqomk6Jh7aRz0sJoqYn39Hg=="],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=="],
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=="],
2603 2231
2604 "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=="],2232 "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=="],
2605 2233
2606 "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],2234 "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
2607 2235
2608 "undici": ["undici@7.22.0", "", {}, "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg=="],2236 "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
2609 2237
2610 "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],2238 "undici": ["undici@7.24.6", "", {}, "sha512-Xi4agocCbRzt0yYMZGMA6ApD7gvtUFaxm4ZmeacWI4cZxaF6C+8I8QfofC20NAePiB/IcvZmzkJ7XPa471AEtA=="],
2611 2239
2612 "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],2240 "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
2613 2241
2614 "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=="],2242 "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=="],
2615 2243
@@ -2627,8 +2255,6 @@ · 11 unmodified lines
2627 2255
2628 "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],2256 "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
2629 2257
2630 "until-async": ["until-async@3.0.2", "", {}, "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw=="],
2631
2632 "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=="],2258 "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=="],
2633 2259
2634 "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=="],2260 "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
2641 2267
2642 "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],2268 "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
2643 2269
2644 "validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="],
2645
2646 "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],2270 "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
2647 2271
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
2648 "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],2274 "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
2649 2275
2650 "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],2276 "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
2651 2277
2652 "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],2278 "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
2653 2279
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=="],
2655 2283
2656 "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=="],2284 "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=="],
2657 2285
2658 "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=="],2286 "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=="],
2659 2287
2660 "w3c-xmlserializer": ["w3c-xmlserializer@5.0.0", "", { "dependencies": { "xml-name-validator": "^5.0.0" } }, "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA=="],2288 "vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="],
2661
2662 "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="],
2663 2289
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=="],
2665 2291
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=="],
2667 2293
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=="],
2669 2295
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=="],
2671 2297
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=="],
2673 2299
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=="],
2675 2301
2676 "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],2302 "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
2677 2303
2678 "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=="],2304 "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=="],
2679 2305
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
2682 "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],2306 "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
2683 2307
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=="],
2685 2309
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=="],
2687 2311
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=="],
2689 2313
2690 "xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="],2314 "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
2691 2315
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=="],
2693 2317
2694 "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],2318 "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
2695 2319
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=="],
2697 2321
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=="],
2699 2323
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=="],
2701 2325
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=="],
2703 2327
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=="],
2705 2329
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=="],
2707 2331
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=="],
2709 2333
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=="],
2711 2335
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=="],
2713 2337
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=="],
2715 2339
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=="],
2717 2341
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=="],
2719 2343
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=="],
2721 2345
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=="],
2723 2347
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=="],
2725 2349
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=="],
2727 2351
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=="],
2729 2353
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=="],
2731 2355
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=="],
2733 2357
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=="],
2735 2359
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=="],
2737 2361
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=="],
2739 2363
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=="],
2741 2367
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=="],
2743 2369
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=="],
2745 2371
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=="],
2747 2373
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=="],
2749 2375
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=="],
2751 2377
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=="],
2753 2379
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=="],
2755 2381
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=="],
2757 2383
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=="],
2759 2385
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=="],
2761 2387
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=="],
2763 2389
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=="],
2765 2391
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=="],
2767 2393
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=="],
2769 2395
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=="],
2771 2397
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=="],
2773 2399
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=="],
2775 2401
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=="],
2777 2403
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=="],
2779 2405
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=="],
2781 2407
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=="],
2783 2409
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=="],
2785 2411
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=="],
2787 2413
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=="],
2789 2415
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=="],
2791 2417
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=="],
2793 2419
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=="],
2795 2421
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=="],
2797 2423
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=="],
2799 2425
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=="],
2801 2427
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=="],
2803 2429
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=="],
2805 2431
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=="],
2807 2433
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=="],
2809 2435
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=="],
2811 2437
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=="],
2813 2439
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=="],
2815 2441
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=="],
2817 2443
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=="],
2819 2445
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=="],
2821 2447
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=="],
2823 2449
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=="],
2825 2451
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=="],
2827 2453
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=="],
2829 2455
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=="],
2831 2457
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=="],
2833 2483
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=="],
2835 2485
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=="],
2837 2487
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=="],
2839 2489
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=="],
2841 2491
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=="],
2843 2493
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=="],
2845 2495
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=="],
2847 2497
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=="],
2849 }2499 }
2850}2500}
compose.tracing.yaml+0−9
@@ -1,9 +0,0 @@
1services:
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 @@
1export {
2 startMcpElicitationDemoServer,
3 type McpElicitationDemoServer,
4} from "./server";
examples/mcp-elicitation-demo/src/main.ts+0−20
@@ -1,20 +0,0 @@
1import { startMcpElicitationDemoServer } from "./server";
2
3const host = process.env.HOST ?? "127.0.0.1";
4const port = process.env.PORT ? Number(process.env.PORT) : 58506;
5
6const server = await startMcpElicitationDemoServer({ host, port });
7console.error(`mcp-elicitation-demo listening on ${server.endpoint}`);
8
9const shutdown = async () => {
10 await server.close();
11 process.exit(0);
12};
13
14process.once("SIGINT", () => {
15 void shutdown();
16});
17
18process.once("SIGTERM", () => {
19 void shutdown();
20});
examples/mcp-elicitation-demo/src/server.ts+0−222
@@ -1,222 +0,0 @@
1import { randomUUID } from "node:crypto";
2
3import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
4import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
6import { z } from "zod/v4";
7
8export type McpElicitationDemoServer = {
9 readonly endpoint: string;
10 readonly close: () => Promise<void>;
11};
12
13const 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
55export 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
3This demo shows one practical way to distribute [Agent Skills](https://agentskills.io)
4over MCP resources.
5
6It 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
13The important boundary is that MCP resources only transport the bundle. The host still
14owns activation logic:
15
161. list resources
172. read the catalog or a manifest
183. choose a skill
194. read that skill's `SKILL.md`
205. fetch additional files from the manifest on demand
21
22## Run
23
24```bash
25bun run --filter @executor/serve-skills-via-mcp-demo start
26```
27
28The server listens on `http://127.0.0.1:<port>/mcp` and logs the final endpoint to
29stderr.
30
31## Smoke Test
32
33```bash
34bun run --filter @executor/serve-skills-via-mcp-demo smoke
35```
36
37The smoke script starts the server, connects with an MCP client, lists resources,
38reads 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---
2name: postgres-incident-triage
3description: Triage production PostgreSQL incidents involving lock contention, slow queries, or saturation. Use when the user asks for database incident diagnosis or immediate next steps.
4compatibility: Assumes SQL access to pg_stat_activity and pg_locks.
5allowed-tools: Bash(psql:*) Read
6---
7
8# Postgres Incident Triage
9
10## When to use this skill
11
12Use this skill for live operational diagnosis of PostgreSQL incidents, especially when
13latency spikes or blocked sessions appear.
14
15## Workflow
16
171. Read `references/error-codes.md` for common failure patterns.
182. Use `scripts/blocked-session-query.sql` to inspect blockers and waiters.
193. Separate symptoms from root cause: CPU saturation, I/O pressure, lock chains, or
20 connection pileups.
214. Recommend the least-destructive mitigation first.
225. 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 @@
1select
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
8from pg_stat_activity blocked
9join pg_locks blocked_locks
10 on blocked.pid = blocked_locks.pid
11join 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
22join pg_stat_activity blocking
23 on blocking.pid = blocking_locks.pid
24where 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---
2name: release-notes-writer
3description: Draft product release notes from commits, changelogs, and issue summaries. Use when the user asks for release notes, launch notes, or upgrade summaries.
4compatibility: Requires markdown output and access to bundled templates.
5allowed-tools: Read Write
6---
7
8# Release Notes Writer
9
10## When to use this skill
11
12Use this skill when the user wants polished release notes, changelog summaries, or
13customer-facing upgrade notes.
14
15## Workflow
16
171. Read the release template in `assets/release-template.md`.
182. Read the voice and structure rules in `references/style-guide.md`.
193. Group changes into user-facing themes instead of commit-by-commit narration.
204. Prefer concrete impact statements over internal implementation details.
215. 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 @@
1const requiredHeadings = [
2 "## Overview",
3 "## New",
4 "## Improved",
5 "## Fixed",
6];
7
8for (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 @@
1import { readdir, readFile, stat } from "node:fs/promises";
2import { extname, join, posix, relative } from "node:path";
3import { fileURLToPath } from "node:url";
4
5export type SkillFrontmatter = {
6 readonly name: string;
7 readonly description: string;
8 readonly compatibility?: string;
9 readonly license?: string;
10 readonly allowedTools?: string;
11};
12
13export 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
21export 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
32export 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
44const demoPublisher = "demo";
45const catalogUri = "skill://catalog/index.json";
46const fileTemplate = "skill://demo/{skill}/{version}/{+path}";
47
48const bundleVersions = {
49 "postgres-incident-triage": "1.1.0",
50 "release-notes-writer": "1.0.0",
51} as const;
52
53const skillsDir = fileURLToPath(new URL("../skills", import.meta.url));
54
55const 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
70const 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
86const 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
120const 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
141export const getCatalogUri = (): string => catalogUri;
142
143export const getFileTemplate = (): string => fileTemplate;
144
145export 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
198export 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
223export const findBundleByName = (
224 bundles: readonly DistributedSkillBundle[],
225 skillName: string,
226): DistributedSkillBundle | undefined =>
227 bundles.find((bundle) => bundle.skill.name === skillName);
228
229export 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
239export 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 @@
1export {
2 startServeSkillsViaMcpDemoServer,
3 type ServeSkillsViaMcpDemoServer,
4} from "./server";
examples/serve-skills-via-mcp/src/main.ts+0−20
@@ -1,20 +0,0 @@
1import { startServeSkillsViaMcpDemoServer } from "./server";
2
3const host = process.env.HOST ?? "127.0.0.1";
4const port = process.env.PORT ? Number(process.env.PORT) : 58507;
5
6const server = await startServeSkillsViaMcpDemoServer({ host, port });
7console.error(`serve-skills-via-mcp listening on ${server.endpoint}`);
8
9const shutdown = async () => {
10 await server.close();
11 process.exit(0);
12};
13
14process.once("SIGINT", () => {
15 void shutdown();
16});
17
18process.once("SIGTERM", () => {
19 void shutdown();
20});
examples/serve-skills-via-mcp/src/server.ts+0−346
@@ -1,346 +0,0 @@
1import { randomUUID } from "node:crypto";
2import type { Server as HttpServer } from "node:http";
3
4import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
5import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
6import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7
8import {
9 type DistributedSkillBundle,
10 findBundleByName,
11 findBundleFile,
12 getCatalogUri,
13 getFileTemplate,
14 loadDistributedSkillBundles,
15 readBundleFileText,
16 renderCatalog,
17} from "./catalog";
18
19export type ServeSkillsViaMcpDemoServer = {
20 readonly endpoint: string;
21 readonly close: () => Promise<void>;
22};
23
24const 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
182const 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
205const 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
216const 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
234export 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 @@
1import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
4import { startServeSkillsViaMcpDemoServer } from "./server";
5
6const server = await startServeSkillsViaMcpDemoServer();
7const client = new Client({
8 name: "serve-skills-via-mcp-smoke",
9 version: "1.0.0",
10});
11const transport = new StreamableHTTPClientTransport(new URL(server.endpoint));
12
13try {
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
3This example shows how an embedder can implement a custom SQLite-backed adapter
4using the public Promise-facing `@executor/platform-sdk`.
5
6The 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
14There is no direct `effect` usage in the example.
15
16## Run
17
18```sh
19bun run --cwd examples/sqlite-sdk-consumer start
20```
21
22To keep the demo ephemeral:
23
24```sh
25DATABASE_PATH=:memory: bun run --cwd examples/sqlite-sdk-consumer start
26```
27
28## Shape
29
30The important bit is the consumer-facing construction:
31
32```ts
33import { createExecutor } from "@executor/platform-sdk";
34import { createSqliteExecutorBackend } from "@executor/sqlite-sdk-consumer-example";
35
36const 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 @@
1export {
2 createSqliteExecutorBackend,
3 type CreateSqliteExecutorBackendOptions,
4} from "./sqlite-backend";
examples/sqlite-sdk-consumer/src/main.ts+0−54
@@ -1,54 +0,0 @@
1import { createExecutor } from "@executor/platform-sdk";
2
3import { createSqliteExecutorBackend } from "./sqlite-backend";
4
5const databasePath = process.env.DATABASE_PATH
6 ?? new URL("../.data/executor.sqlite", import.meta.url).pathname;
7
8const executor = await createExecutor({
9 backend: createSqliteExecutorBackend({
10 databasePath,
11 }),
12});
13
14try {
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 @@
1import { createHash, randomUUID } from "node:crypto";
2import { mkdirSync } from "node:fs";
3import { dirname, resolve as resolvePath } from "node:path";
4
5import { Database } from "bun:sqlite";
6import { and, eq } from "drizzle-orm";
7import { drizzle } from "drizzle-orm/bun-sqlite";
8import {
9 integer,
10 sqliteTable,
11 text,
12} from "drizzle-orm/sqlite-core";
13
14import {
15 createExecutorBackend,
16 type ExecutorBackend,
17 type ExecutorBackendRepositories,
18 type ExecutorWorkspaceConfigRepository,
19 type ExecutorWorkspaceStateRepository,
20 type ExecutorWorkspaceSourceArtifactRepository,
21} from "@executor/platform-sdk";
22import type {
23 Execution,
24 ExecutionInteraction,
25 ExecutionStep,
26 ExecutorScopeConfig,
27 LocalInstallation,
28 SecretMaterial,
29 SecretRef,
30 SecretStore,
31} from "@executor/platform-sdk/schema";
32import {
33 ScopeIdSchema,
34 SecretMaterialIdSchema,
35 SourceCatalogIdSchema,
36 SourceCatalogRevisionIdSchema,
37} from "@executor/platform-sdk/schema";
38import type {
39 SecretMaterialStoredDataRecord,
40} from "@executor/platform-sdk/runtime";
41import {
42 contentHash,
43 snapshotFromSourceCatalogSyncResult,
44} from "@executor/source-core";
45
46export type CreateSqliteExecutorBackendOptions = {
47 databasePath?: string;
48 scopeId?: string;
49 actorScopeId?: string;
50};
51
52type ScopeConfig = Awaited<ReturnType<ExecutorWorkspaceConfigRepository["load"]>>;
53type ScopeState = Awaited<ReturnType<ExecutorWorkspaceStateRepository["load"]>>;
54type SourceArtifact =
55 ReturnType<ExecutorWorkspaceSourceArtifactRepository["build"]>;
56type SourceArtifactBuildInput = Parameters<
57 ExecutorWorkspaceSourceArtifactRepository["build"]
58>[0];
59
60type SecretMaterialSummary = {
61 id: string;
62 storeId: string;
63 name: string | null;
64 purpose: string;
65 createdAt: number;
66 updatedAt: number;
67};
68
69type SqliteSecretStoredData = {
70 value: string;
71};
72
73const SQLITE_SECRET_STORE_KIND = "sqlite";
74const SQLITE_SECRET_STORE_ID = "sts_sqlite";
75
76const installations = sqliteTable("installations", {
77 key: text("key").primaryKey(),
78 scopeId: text("scope_id").notNull(),
79 actorScopeId: text("actor_scope_id").notNull(),
80});
81
82const scopeConfigs = sqliteTable("scope_configs", {
83 key: text("key").primaryKey(),
84 projectConfigJson: text("project_config_json").notNull(),
85});
86
87const scopeStates = sqliteTable("scope_states", {
88 key: text("key").primaryKey(),
89 stateJson: text("state_json").notNull(),
90});
91
92const sourceArtifacts = sqliteTable("source_artifacts", {
93 sourceId: text("source_id").primaryKey(),
94 artifactJson: text("artifact_json").notNull(),
95});
96
97const 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
107const secretMaterialStoredData = sqliteTable("secret_material_stored_data", {
108 secretId: text("secret_id").primaryKey(),
109 json: text("json").notNull(),
110});
111
112const executions = sqliteTable("executions", {
113 id: text("id").primaryKey(),
114 scopeId: text("scope_id").notNull(),
115 json: text("json").notNull(),
116});
117
118const 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
125const 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
132const makeHash = (value: string): string =>
133 createHash("sha256").update(value).digest("hex").slice(0, 24);
134
135const parseJson = <T>(value: string): T => JSON.parse(value) as T;
136
137const 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
171const defaultScopeState = (): ScopeState => ({
172 version: 1,
173 sources: {},
174 policies: {},
175});
176
177const 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
191const 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
266type SqliteStore = ReturnType<typeof openSqliteStore>;
267
268const 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
543export 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.