History

Update tool explorer components and dependencies

- Added `json-schema-traverse` dependency to enhance schema handling. - Removed unused `infra` workspace from `package.json` and related scripts. - Refactored tool explorer components to improve structure and usability, including the addition of `NavGroupNode` and `ToolListItem` for better tool organization. - Updated `ToolExplorer` to streamline source management and selection. - Enhanced `TypeSignature` component for improved type display and copying functionality. - Cleaned up CSS styles for better layout and responsiveness in tool components.

Rhys Sullivan committed 8 months ago

Commit b89a9b81 parent c9631fc27 files · +2289 −2067Browse files

Unified · Split

27 files
  1. bun.lock +21 −544
  2. executor/apps/web/package.json +1 −0
  3. executor/apps/web/src/app/globals.css +2 −0
  4. executor/apps/web/src/components/tools/add/source/dialog-sections.tsx +2 −2
  5. executor/apps/web/src/components/tools/explorer-groups.tsx +215 −2
  6. executor/apps/web/src/components/tools/explorer-rows.tsx +159 −0
  7. executor/apps/web/src/components/tools/explorer-toolbar.tsx +49 −164
  8. executor/apps/web/src/components/tools/explorer.tsx +325 −340
  9. executor/apps/web/src/components/tools/explorer/source-form-panel.tsx +507 −0
  10. executor/apps/web/src/components/tools/explorer/tool-detail.tsx +344 −171
  11. executor/apps/web/src/components/tools/explorer/type-signature.tsx +43 −11
  12. executor/apps/web/src/components/tools/view.tsx +2 −19
  13. executor/apps/web/src/lib/tool/schema-traverse.ts +385 −0
  14. executor/infra/.gitignore +0 −2
  15. executor/infra/README.md +0 −122
  16. executor/infra/package.json +0 −26
  17. executor/infra/sst.config.ts +0 −572
  18. executor/infra/tsconfig.json +0 −12
  19. executor/package.json +0 −4
  20. executor/packages/core/src/mcp/server-approval.ts +48 −42
  21. executor/packages/core/src/tool-source-loaders/graphql-loader.ts +1 −7
  22. executor/packages/database/convex/_generated/api.d.ts +6 −0
  23. executor/packages/database/convex/http/mcp_service.ts +38 −5
  24. executor/packages/database/convex/runtimeCallbacks.ts +13 −0
  25. executor/packages/database/src/runtime-callbacks/handlers.ts +36 −0
  26. executor/packages/database/src/runtime-node/runtime-dispatch.ts +90 −19
  27. package.json +2 −3
bun.lock+21−544
@@ -99,6 +99,7 @@ · 98 unmodified lines
9999 "clsx": "^2.1.1",
100100 "cmdk": "^1",
101101 "convex": "^1.31.7",
102+ "json-schema-traverse": "^1.0.0",
102103 "lucide-react": "^0.563.0",
103104 "monaco-editor": "^0.55.1",
104105 "next": "16.1.6",
@@ -130,20 +131,6 @@ · 25 unmodified lines
130131 "typescript": "^5",
131132 },
132133 },
133− "executor/infra": {
134− "name": "executor-infra",
135− "dependencies": {
136− "@pulumi/command": "^1.1.3",
137− "@pulumi/pulumi": "^3.220.0",
138− "@pulumiverse/vercel": "^4.5.0",
139− "pulumi-stripe": "^0.0.26",
140− "sst": "^3.17.38",
141− },
142− "devDependencies": {
143− "@types/node": "^24.6.2",
144− "typescript": "^5.9.3",
145− },
146− },
147134 "executor/packages/core": {
148135 "name": "@executor/core",
149136 "version": "0.1.0",
@@ -509,10 +496,6 @@ · 359 unmodified lines
509496
510497 "@google/genai": ["@google/genai@1.40.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-fhIww8smT0QYRX78qWOiz/nIQhHMF5wXOrlXvj33HBrz3vKDBb+wibLcEmTA+L9dmPD4KmfNr7UF3LDQVTXNjA=="],
511498
512− "@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=="],
513−
514− "@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=="],
515−
516499 "@hono/node-server": ["@hono/node-server@1.19.9", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw=="],
517500
518501 "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
@@ -589,10 +572,6 @@ · 70 unmodified lines
589572
590573 "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
591574
592− "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
593−
594− "@isaacs/string-locale-compare": ["@isaacs/string-locale-compare@1.1.0", "", {}, "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ=="],
595−
596575 "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
597576
598577 "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
@@ -603,10 +582,6 @@ · 4 unmodified lines
603582
604583 "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
605584
606− "@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="],
607−
608− "@logdna/tail-file": ["@logdna/tail-file@2.2.0", "", {}, "sha512-XGSsWDweP80Fks16lwkAUIr54ICyBs6PsI4mpfTLQaWgEJRtY9xEV+PeyDpJ+sJEGZxqINlpmAwe/6tS1pP8Ng=="],
609−
610585 "@mariozechner/pi-ai": ["@mariozechner/pi-ai@0.52.8", "", { "dependencies": { "@anthropic-ai/sdk": "^0.73.0", "@aws-sdk/client-bedrock-runtime": "^3.983.0", "@google/genai": "^1.40.0", "@mistralai/mistralai": "1.10.0", "@sinclair/typebox": "^0.34.41", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "chalk": "^5.6.2", "openai": "6.10.0", "partial-json": "^0.1.7", "proxy-agent": "^6.5.0", "undici": "^7.19.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-+aFCUbKJcskDJhr9wPcMBTy0x/xWio5v1dkxRYXUBPWp+Zt9DSdT5Kmd/IIQ+a0TOZDF4ajt4GY/oAw37X7XTw=="],
611586
612587 "@mistralai/mistralai": ["@mistralai/mistralai@1.10.0", "", { "dependencies": { "zod": "^3.20.0", "zod-to-json-schema": "^3.24.1" } }, "sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg=="],
@@ -667,34 +642,6 @@ · 54 unmodified lines
667642
668643 "@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="],
669644
670− "@npmcli/agent": ["@npmcli/agent@4.0.0", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^11.2.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA=="],
671−
672− "@npmcli/arborist": ["@npmcli/arborist@9.3.0", "", { "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/fs": "^5.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/map-workspaces": "^5.0.0", "@npmcli/metavuln-calculator": "^9.0.2", "@npmcli/name-from-folder": "^4.0.0", "@npmcli/node-gyp": "^5.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/query": "^5.0.0", "@npmcli/redact": "^4.0.0", "@npmcli/run-script": "^10.0.0", "bin-links": "^6.0.0", "cacache": "^20.0.1", "common-ancestor-path": "^2.0.0", "hosted-git-info": "^9.0.0", "json-stringify-nice": "^1.1.4", "lru-cache": "^11.2.1", "minimatch": "^10.0.3", "nopt": "^9.0.0", "npm-install-checks": "^8.0.0", "npm-package-arg": "^13.0.0", "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "pacote": "^21.0.2", "parse-conflict-json": "^5.0.1", "proc-log": "^6.0.0", "proggy": "^4.0.0", "promise-all-reject-late": "^1.0.0", "promise-call-limit": "^3.0.1", "semver": "^7.3.7", "ssri": "^13.0.0", "treeverse": "^3.0.0", "walk-up-path": "^4.0.0" }, "bin": { "arborist": "bin/index.js" } }, "sha512-+iH0S4YZBsSgItmFWJsxbxtuFmaldGG8h9hQfCHeYHQxFZuIKD8NZB960c22OeFtQnI0FcuGLRA+sWQ3/4EEHQ=="],
673−
674− "@npmcli/fs": ["@npmcli/fs@5.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og=="],
675−
676− "@npmcli/git": ["@npmcli/git@7.0.1", "", { "dependencies": { "@npmcli/promise-spawn": "^9.0.0", "ini": "^6.0.0", "lru-cache": "^11.2.1", "npm-pick-manifest": "^11.0.1", "proc-log": "^6.0.0", "promise-retry": "^2.0.1", "semver": "^7.3.5", "which": "^6.0.0" } }, "sha512-+XTFxK2jJF/EJJ5SoAzXk3qwIDfvFc5/g+bD274LZ7uY7LE8sTfG6Z8rOanPl2ZEvZWqNvmEdtXC25cE54VcoA=="],
677−
678− "@npmcli/installed-package-contents": ["@npmcli/installed-package-contents@4.0.0", "", { "dependencies": { "npm-bundled": "^5.0.0", "npm-normalize-package-bin": "^5.0.0" }, "bin": { "installed-package-contents": "bin/index.js" } }, "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA=="],
679−
680− "@npmcli/map-workspaces": ["@npmcli/map-workspaces@5.0.3", "", { "dependencies": { "@npmcli/name-from-folder": "^4.0.0", "@npmcli/package-json": "^7.0.0", "glob": "^13.0.0", "minimatch": "^10.0.3" } }, "sha512-o2grssXo1e774E5OtEwwrgoszYRh0lqkJH+Pb9r78UcqdGJRDRfhpM8DvZPjzNLLNYeD/rNbjOKM3Ss5UABROw=="],
681−
682− "@npmcli/metavuln-calculator": ["@npmcli/metavuln-calculator@9.0.3", "", { "dependencies": { "cacache": "^20.0.0", "json-parse-even-better-errors": "^5.0.0", "pacote": "^21.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5" } }, "sha512-94GLSYhLXF2t2LAC7pDwLaM4uCARzxShyAQKsirmlNcpidH89VA4/+K1LbJmRMgz5gy65E/QBBWQdUvGLe2Frg=="],
683−
684− "@npmcli/name-from-folder": ["@npmcli/name-from-folder@4.0.0", "", {}, "sha512-qfrhVlOSqmKM8i6rkNdZzABj8MKEITGFAY+4teqBziksCQAOLutiAxM1wY2BKEd8KjUSpWmWCYxvXr0y4VTlPg=="],
685−
686− "@npmcli/node-gyp": ["@npmcli/node-gyp@5.0.0", "", {}, "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ=="],
687−
688− "@npmcli/package-json": ["@npmcli/package-json@7.0.4", "", { "dependencies": { "@npmcli/git": "^7.0.0", "glob": "^13.0.0", "hosted-git-info": "^9.0.0", "json-parse-even-better-errors": "^5.0.0", "proc-log": "^6.0.0", "semver": "^7.5.3", "validate-npm-package-license": "^3.0.4" } }, "sha512-0wInJG3j/K40OJt/33ax47WfWMzZTm6OQxB9cDhTt5huCP2a9g2GnlsxmfN+PulItNPIpPrZ+kfwwUil7eHcZQ=="],
689−
690− "@npmcli/promise-spawn": ["@npmcli/promise-spawn@9.0.1", "", { "dependencies": { "which": "^6.0.0" } }, "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q=="],
691−
692− "@npmcli/query": ["@npmcli/query@5.0.0", "", { "dependencies": { "postcss-selector-parser": "^7.0.0" } }, "sha512-8TZWfTQOsODpLqo9SVhVjHovmKXNpevHU0gO9e+y4V4fRIOneiXy0u0sMP9LmS71XivrEWfZWg50ReH4WRT4aQ=="],
693−
694− "@npmcli/redact": ["@npmcli/redact@4.0.0", "", {}, "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q=="],
695−
696− "@npmcli/run-script": ["@npmcli/run-script@10.0.3", "", { "dependencies": { "@npmcli/node-gyp": "^5.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^9.0.0", "node-gyp": "^12.1.0", "proc-log": "^6.0.0", "which": "^6.0.0" } }, "sha512-ER2N6itRkzWbbtVmZ9WKaWxVlKlOeBFF1/7xx+KA5J1xKa4JjUwBdb6tDpk0v1qA+d+VDwHI9qmLcXSWcmi+Rw=="],
697−
698645 "@open-draft/deferred-promise": ["@open-draft/deferred-promise@2.2.0", "", {}, "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA=="],
699646
700647 "@open-draft/logger": ["@open-draft/logger@0.3.0", "", { "dependencies": { "is-node-process": "^1.2.0", "outvariant": "^1.4.0" } }, "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ=="],
@@ -705,30 +652,6 @@ · 4 unmodified lines
705652
706653 "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
707654
708− "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.55.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-3cpa+qI45VHYcA5c0bHM6VHo9gicv3p5mlLHNG3rLyjQU8b7e0st1rWtrUn3JbZ3DwwCfhKop4eQ9UuYlC6Pkg=="],
709−
710− "@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@1.30.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA=="],
711−
712− "@opentelemetry/core": ["@opentelemetry/core@1.30.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "1.28.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ=="],
713−
714− "@opentelemetry/exporter-zipkin": ["@opentelemetry/exporter-zipkin@1.30.1", "", { "dependencies": { "@opentelemetry/core": "1.30.1", "@opentelemetry/resources": "1.30.1", "@opentelemetry/sdk-trace-base": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-6S2QIMJahIquvFaaxmcwpvQQRD/YFaMTNoIxrfPIPOeITN+a8lfEcPDxNxn8JDAaxkg+4EnXhz8upVDYenoQjA=="],
715−
716− "@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.55.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.55.0", "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "semver": "^7.5.2", "shimmer": "^1.2.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-YDCMlaQRZkziLL3t6TONRgmmGxDx6MyQDXRD0dknkkgUZtOK5+8MWft1OXzmNu6XfBOdT12MKN5rz+jHUkafKQ=="],
717−
718− "@opentelemetry/instrumentation-grpc": ["@opentelemetry/instrumentation-grpc@0.55.0", "", { "dependencies": { "@opentelemetry/instrumentation": "0.55.0", "@opentelemetry/semantic-conventions": "1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-n2ZH4pRwOy0Vhag/3eKqiyDBwcpUnGgJI9iiIRX7vivE0FMncaLazWphNFezRRaM/LuKwq1TD8pVUvieP68mow=="],
719−
720− "@opentelemetry/propagator-b3": ["@opentelemetry/propagator-b3@1.30.1", "", { "dependencies": { "@opentelemetry/core": "1.30.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-oATwWWDIJzybAZ4pO76ATN5N6FFbOA1otibAVlS8v90B4S1wClnhRUk7K+2CHAwN1JKYuj4jh/lpCEG5BAqFuQ=="],
721−
722− "@opentelemetry/propagator-jaeger": ["@opentelemetry/propagator-jaeger@1.30.1", "", { "dependencies": { "@opentelemetry/core": "1.30.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-Pj/BfnYEKIOImirH76M4hDaBSx6HyZ2CXUqk+Kj02m6BB80c/yo4BdWkn/1gDFfU+YPY+bPR2U0DKBfdxCKwmg=="],
723−
724− "@opentelemetry/resources": ["@opentelemetry/resources@1.30.1", "", { "dependencies": { "@opentelemetry/core": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA=="],
725−
726− "@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@1.30.1", "", { "dependencies": { "@opentelemetry/core": "1.30.1", "@opentelemetry/resources": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg=="],
727−
728− "@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@1.30.1", "", { "dependencies": { "@opentelemetry/context-async-hooks": "1.30.1", "@opentelemetry/core": "1.30.1", "@opentelemetry/propagator-b3": "1.30.1", "@opentelemetry/propagator-jaeger": "1.30.1", "@opentelemetry/sdk-trace-base": "1.30.1", "semver": "^7.5.2" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-cBjYOINt1JxXdpw1e5MlHmFRc5fgj4GW/86vsKFxJCJ8AL4PdVtYH41gWwl4qd4uQjqEL1oJVrXkSy5cnduAnQ=="],
729−
730− "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="],
731−
732655 "@oxc-project/types": ["@oxc-project/types@0.112.0", "", {}, "sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ=="],
733656
734657 "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.6.0", "", { "dependencies": { "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg=="],
@@ -767,12 +690,6 @@ · 32 unmodified lines
767690
768691 "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="],
769692
770− "@pulumi/command": ["@pulumi/command@1.1.3", "", { "dependencies": { "@pulumi/pulumi": "^3.142.0" } }, "sha512-eBzGE/BQlxMNcxrrA62N4cLaHdL0xDSRACXxB0Hjc4rJG60vhpDVO130xxb4x3cZ7HT1kvjS4KuuoH8R5JRbIQ=="],
771−
772− "@pulumi/pulumi": ["@pulumi/pulumi@3.220.0", "", { "dependencies": { "@grpc/grpc-js": "^1.10.1", "@logdna/tail-file": "^2.0.6", "@npmcli/arborist": "^9.0.0", "@opentelemetry/api": "^1.9", "@opentelemetry/exporter-zipkin": "^1.28", "@opentelemetry/instrumentation": "^0.55", "@opentelemetry/instrumentation-grpc": "^0.55", "@opentelemetry/resources": "^1.28", "@opentelemetry/sdk-trace-base": "^1.28", "@opentelemetry/sdk-trace-node": "^1.28", "@types/google-protobuf": "^3.15.5", "@types/semver": "^7.5.6", "@types/tmp": "^0.2.6", "execa": "^5.1.0", "fdir": "^6.5.0", "google-protobuf": "^3.21.4", "got": "^11.8.6", "ini": "^2.0.0", "js-yaml": "^3.14.2", "minimist": "^1.2.6", "normalize-package-data": "^6.0.0", "package-directory": "^8.1.0", "picomatch": "^3.0.1", "require-from-string": "^2.0.1", "semver": "^7.5.2", "source-map-support": "^0.5.6", "tmp": "^0.2.4", "upath": "^1.1.0" }, "peerDependencies": { "ts-node": ">= 7.0.1 < 12", "typescript": ">= 3.8.3 < 6" }, "optionalPeers": ["ts-node", "typescript"] }, "sha512-WfFu4Qv5r/9uv4bh6jxZPKLc945RtdjIq29mDa6c9sIXzQtRtv/Voo58E6u6lhA1RKaK+ocymqgykZ6QV7OnGQ=="],
773−
774− "@pulumiverse/vercel": ["@pulumiverse/vercel@4.5.0", "", { "dependencies": { "@pulumi/pulumi": "^3.142.0" } }, "sha512-WA4MN+II6ie2s2dMcve6AT+XzI16ZbthVXhT5+GK2WqamMHIg9ARexHD68kNQKHQ1Yz9jN1xnzLhggkUC2Uo0A=="],
775−
776693 "@quansync/fs": ["@quansync/fs@1.0.0", "", { "dependencies": { "quansync": "^1.0.0" } }, "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ=="],
777694
778695 "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
@@ -1003,21 +920,9 @@ · 224 unmodified lines
1003920
1004921 "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
1005922
1006− "@sigstore/bundle": ["@sigstore/bundle@4.0.0", "", { "dependencies": { "@sigstore/protobuf-specs": "^0.5.0" } }, "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A=="],
1007−
1008− "@sigstore/core": ["@sigstore/core@3.1.0", "", {}, "sha512-o5cw1QYhNQ9IroioJxpzexmPjfCe7gzafd2RY3qnMpxr4ZEja+Jad/U8sgFpaue6bOaF+z7RVkyKVV44FN+N8A=="],
1009−
1010− "@sigstore/protobuf-specs": ["@sigstore/protobuf-specs@0.5.0", "", {}, "sha512-MM8XIwUjN2bwvCg1QvrMtbBmpcSHrkhFSCu1D11NyPvDQ25HEc4oG5/OcQfd/Tlf/OxmKWERDj0zGE23jQaMwA=="],
1011−
1012− "@sigstore/sign": ["@sigstore/sign@4.1.0", "", { "dependencies": { "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0", "make-fetch-happen": "^15.0.3", "proc-log": "^6.1.0", "promise-retry": "^2.0.1" } }, "sha512-Vx1RmLxLGnSUqx/o5/VsCjkuN5L7y+vxEEwawvc7u+6WtX2W4GNa7b9HEjmcRWohw/d6BpATXmvOwc78m+Swdg=="],
1013−
1014− "@sigstore/tuf": ["@sigstore/tuf@4.0.1", "", { "dependencies": { "@sigstore/protobuf-specs": "^0.5.0", "tuf-js": "^4.1.0" } }, "sha512-OPZBg8y5Vc9yZjmWCHrlWPMBqW5yd8+wFNl+thMdtcWz3vjVSoJQutF8YkrzI0SLGnkuFof4HSsWUhXrf219Lw=="],
1015−
1016− "@sigstore/verify": ["@sigstore/verify@3.1.0", "", { "dependencies": { "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0" } }, "sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag=="],
1017−
1018923 "@sinclair/typebox": ["@sinclair/typebox@0.34.48", "", {}, "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA=="],
1019924
1020− "@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="],
925+ "@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="],
1021926
1022927 "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="],
1023928
@@ -1119,8 +1024,6 @@ · 95 unmodified lines
11191024
11201025 "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
11211026
1122− "@szmarczak/http-timer": ["@szmarczak/http-timer@4.0.6", "", { "dependencies": { "defer-to-connect": "^2.0.0" } }, "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w=="],
1123−
11241027 "@tailwindcss/node": ["@tailwindcss/node@4.1.18", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.18" } }, "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ=="],
11251028
11261029 "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.18", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.18", "@tailwindcss/oxide-darwin-arm64": "4.1.18", "@tailwindcss/oxide-darwin-x64": "4.1.18", "@tailwindcss/oxide-freebsd-x64": "4.1.18", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", "@tailwindcss/oxide-linux-x64-musl": "4.1.18", "@tailwindcss/oxide-wasm32-wasi": "4.1.18", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A=="],
@@ -1167,12 +1070,6 @@ · 40 unmodified lines
11671070
11681071 "@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=="],
11691072
1170− "@tsconfig/bun": ["@tsconfig/bun@1.0.7", "", {}, "sha512-udGrGJBNQdXGVulehc1aWT73wkR9wdaGBtB6yL70RJsqwW/yJhIg6ZbRlPOfIUiFNrnBuYLBi9CSmMKfDC7dvA=="],
1171−
1172− "@tufjs/canonical-json": ["@tufjs/canonical-json@2.0.0", "", {}, "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA=="],
1173−
1174− "@tufjs/models": ["@tufjs/models@4.1.0", "", { "dependencies": { "@tufjs/canonical-json": "2.0.0", "minimatch": "^10.1.1" } }, "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww=="],
1175−
11761073 "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
11771074
11781075 "@types/accepts": ["@types/accepts@1.3.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ=="],
@@ -1181,8 +1078,6 @@ · 2 unmodified lines
11811078
11821079 "@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="],
11831080
1184− "@types/cacheable-request": ["@types/cacheable-request@6.0.3", "", { "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", "@types/node": "*", "@types/responselike": "^1.0.0" } }, "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw=="],
1185−
11861081 "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
11871082
11881083 "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="],
@@ -1205,14 +1100,10 @@ · 16 unmodified lines
12051100
12061101 "@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.8", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA=="],
12071102
1208− "@types/google-protobuf": ["@types/google-protobuf@3.15.12", "", {}, "sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ=="],
1209−
12101103 "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
12111104
12121105 "@types/http-assert": ["@types/http-assert@1.5.6", "", {}, "sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw=="],
12131106
1214− "@types/http-cache-semantics": ["@types/http-cache-semantics@4.2.0", "", {}, "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q=="],
1215−
12161107 "@types/http-errors": ["@types/http-errors@2.0.5", "", {}, "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="],
12171108
12181109 "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
@@ -1221,8 +1112,6 @@ · 2 unmodified lines
12211112
12221113 "@types/keygrip": ["@types/keygrip@1.0.6", "", {}, "sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ=="],
12231114
1224− "@types/keyv": ["@types/keyv@3.1.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg=="],
1225−
12261115 "@types/koa": ["@types/koa@2.15.0", "", { "dependencies": { "@types/accepts": "*", "@types/content-disposition": "*", "@types/cookies": "*", "@types/http-assert": "*", "@types/http-errors": "*", "@types/keygrip": "*", "@types/koa-compose": "*", "@types/node": "*" } }, "sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g=="],
12271116
12281117 "@types/koa-compose": ["@types/koa-compose@3.2.9", "", { "dependencies": { "@types/koa": "*" } }, "sha512-BroAZ9FTvPiCy0Pi8tjD1OfJ7bgU1gQf0eR6e1Vm+JJATy9eKOG3hQMFtMciMawiSOVnLMdmUOC46s7HBhSTsA=="],
@@ -1245,20 +1134,12 @@ · 16 unmodified lines
12451134
12461135 "@types/react-reconciler": ["@types/react-reconciler@0.31.0", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-wa1KtV3SHKnWeLHfZFg/7nrPSe/Ejdn+qbanNX4V6i9I7C3ECKPfBnC1KM3ef58KFWEohLmTvoTH5XuEIKGX2g=="],
12471136
1248− "@types/responselike": ["@types/responselike@1.0.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw=="],
1249−
1250− "@types/semver": ["@types/semver@7.7.1", "", {}, "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA=="],
1251−
12521137 "@types/send": ["@types/send@0.17.6", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og=="],
12531138
12541139 "@types/serve-static": ["@types/serve-static@1.15.10", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "<1" } }, "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw=="],
12551140
1256− "@types/shimmer": ["@types/shimmer@1.2.0", "", {}, "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg=="],
1257−
12581141 "@types/statuses": ["@types/statuses@2.0.6", "", {}, "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA=="],
12591142
1260− "@types/tmp": ["@types/tmp@0.2.6", "", {}, "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA=="],
1261−
12621143 "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
12631144
12641145 "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
@@ -1367,14 +1248,10 @@ · 102 unmodified lines
13671248
13681249 "@workos-inc/node": ["@workos-inc/node@8.2.0", "", { "dependencies": { "iron-webcrypto": "^2.0.0", "jose": "~6.1.0" } }, "sha512-aAY2k7X09lQ4TaVe7Kjm3gjb+EsGRoncbwJCOou9mCmunQoEYO1lsNrJTRIMM+jKCPBQDcmMF1O3Bv8IQwQKtg=="],
13691250
1370− "abbrev": ["abbrev@4.0.0", "", {}, "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA=="],
1371−
13721251 "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
13731252
13741253 "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
13751254
1376− "acorn-import-attributes": ["acorn-import-attributes@1.9.5", "", { "peerDependencies": { "acorn": "^8" } }, "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ=="],
1377−
13781255 "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
13791256
13801257 "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
@@ -1393,7 +1270,7 @@ · 12 unmodified lines
13931270
13941271 "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="],
13951272
1396− "argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
1273+ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
13971274
13981275 "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
13991276
@@ -1431,10 +1308,6 @@ · 31 unmodified lines
14311308
14321309 "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
14331310
1434− "aws-sdk": ["aws-sdk@2.1692.0", "", { "dependencies": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", "jmespath": "0.16.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", "util": "^0.12.4", "uuid": "8.0.0", "xml2js": "0.6.2" } }, "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw=="],
1435−
1436− "aws4fetch": ["aws4fetch@1.0.18", "", {}, "sha512-3Cf+YaUl07p24MoQ46rFwulAmiyCwH2+1zw1ZyPAX5OtJ34Hh185DwB8y/qRLb6cYYYtSFJ9pthyLc0MD4e8sQ=="],
1437−
14381311 "axe-core": ["axe-core@4.11.1", "", {}, "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A=="],
14391312
14401313 "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
@@ -1453,8 +1326,6 @@ · 12 unmodified lines
14531326
14541327 "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
14551328
1456− "bin-links": ["bin-links@6.0.0", "", { "dependencies": { "cmd-shim": "^8.0.0", "npm-normalize-package-bin": "^5.0.0", "proc-log": "^6.0.0", "read-cmd-shim": "^6.0.0", "write-file-atomic": "^7.0.0" } }, "sha512-X4CiKlcV2GjnCMwnKAfbVWpHa++65th9TuzAEYtZoATiOE2DQKhSp4CJlyLoTqdhBKlXjpXjCTYPNNFS33Fi6w=="],
1457−
14581329 "birpc": ["birpc@2.9.0", "", {}, "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw=="],
14591330
14601331 "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="],
@@ -1469,12 +1340,10 @@ · 8 unmodified lines
14691340
14701341 "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=="],
14711342
1472− "buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="],
1343+ "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
14731344
14741345 "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
14751346
1476− "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
1477−
14781347 "bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="],
14791348
14801349 "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
@@ -1483,12 +1352,6 @@ · 2 unmodified lines
14831352
14841353 "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
14851354
1486− "cacache": ["cacache@20.0.3", "", { "dependencies": { "@npmcli/fs": "^5.0.0", "fs-minipass": "^3.0.0", "glob": "^13.0.0", "lru-cache": "^11.1.0", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^13.0.0", "unique-filename": "^5.0.0" } }, "sha512-3pUp4e8hv07k1QlijZu6Kn7c9+ZpWWk4j3F8N3xPuCExULobqJydKYOTj1FTq58srkJsXvO7LbGAH4C0ZU3WGw=="],
1487−
1488− "cacheable-lookup": ["cacheable-lookup@5.0.4", "", {}, "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="],
1489−
1490− "cacheable-request": ["cacheable-request@7.0.4", "", { "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", "normalize-url": "^6.0.1", "responselike": "^2.0.0" } }, "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg=="],
1491−
14921355 "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
14931356
14941357 "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
@@ -1521,10 +1384,6 @@ · 26 unmodified lines
15211384
15221385 "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
15231386
1524− "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
1525−
1526− "cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
1527−
15281387 "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
15291388
15301389 "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
@@ -1537,12 +1396,8 @@ · 6 unmodified lines
15371396
15381397 "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=="],
15391398
1540− "clone-response": ["clone-response@1.0.3", "", { "dependencies": { "mimic-response": "^1.0.0" } }, "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA=="],
1541−
15421399 "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
15431400
1544− "cmd-shim": ["cmd-shim@8.0.0", "", {}, "sha512-Jk/BK6NCapZ58BKUxlSI+ouKRbjH1NLZCgJkYoab+vEHUY3f6OzpNBN9u7HFSv9J6TRDGs4PLOHezoKGaFRSCA=="],
1545−
15461401 "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=="],
15471402
15481403 "code-block-writer": ["code-block-writer@13.0.3", "", {}, "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg=="],
@@ -1557,8 +1412,6 @@ · 8 unmodified lines
15571412
15581413 "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="],
15591414
1560− "common-ancestor-path": ["common-ancestor-path@2.0.0", "", {}, "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng=="],
1561−
15621415 "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
15631416
15641417 "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="],
@@ -1601,8 +1454,6 @@ · 36 unmodified lines
16011454
16021455 "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="],
16031456
1604− "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
1605−
16061457 "dedent": ["dedent@1.7.1", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg=="],
16071458
16081459 "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
@@ -1615,8 +1466,6 @@ · 6 unmodified lines
16151466
16161467 "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],
16171468
1618− "defer-to-connect": ["defer-to-connect@2.0.1", "", {}, "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="],
1619−
16201469 "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
16211470
16221471 "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
@@ -1673,18 +1522,12 @@ · 50 unmodified lines
16731522
16741523 "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
16751524
1676− "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="],
1677−
1678− "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
1679−
16801525 "enhanced-resolve": ["enhanced-resolve@5.19.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg=="],
16811526
16821527 "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
16831528
16841529 "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
16851530
1686− "err-code": ["err-code@2.0.3", "", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="],
1687−
16881531 "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
16891532
16901533 "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="],
@@ -1757,8 +1600,6 @@ · 66 unmodified lines
17571600
17581601 "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
17591602
1760− "events": ["events@1.1.1", "", {}, "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw=="],
1761−
17621603 "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
17631604
17641605 "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="],
@@ -1767,12 +1608,8 @@ · 2 unmodified lines
17671608
17681609 "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=="],
17691610
1770− "executor-infra": ["executor-infra@workspace:executor/infra"],
1771−
17721611 "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
17731612
1774− "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="],
1775−
17761613 "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=="],
17771614
17781615 "express-rate-limit": ["express-rate-limit@8.2.1", "", { "dependencies": { "ip-address": "10.0.1" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g=="],
@@ -1815,8 +1652,6 @@ · 36 unmodified lines
18151652
18161653 "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
18171654
1818− "find-up-simple": ["find-up-simple@1.0.1", "", {}, "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ=="],
1819−
18201655 "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
18211656
18221657 "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
@@ -1833,8 +1668,6 @@ · 10 unmodified lines
18331668
18341669 "fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="],
18351670
1836− "fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="],
1837−
18381671 "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
18391672
18401673 "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
@@ -1875,7 +1708,7 @@ · 34 unmodified lines
18751708
18761709 "get-uri": ["get-uri@6.0.5", "", { "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", "debug": "^4.3.4" } }, "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg=="],
18771710
1878− "glob": ["glob@13.0.2", "", { "dependencies": { "minimatch": "^10.1.2", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-035InabNu/c1lW0tzPhAgapKctblppqsKKG9ZaNzbr+gXwWMjXoiyGSyB9sArzrjG7jY+zntRq5ZSUYemrnWVQ=="],
1711+ "glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
18791712
18801713 "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
18811714
@@ -1887,12 +1720,8 @@ · 5 unmodified lines
18871720
18881721 "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="],
18891722
1890− "google-protobuf": ["google-protobuf@3.21.4", "", {}, "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ=="],
1891−
18921723 "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
18931724
1894− "got": ["got@11.8.6", "", { "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", "p-cancelable": "^2.0.0", "responselike": "^2.0.0" } }, "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g=="],
1895−
18961725 "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
18971726
18981727 "graphql": ["graphql@16.12.0", "", {}, "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ=="],
@@ -1941,44 +1770,32 @@ · 42 unmodified lines
19411770
19421771 "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
19431772
1944− "hosted-git-info": ["hosted-git-info@9.0.2", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg=="],
1945−
19461773 "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],
19471774
19481775 "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
19491776
1950− "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="],
1951−
19521777 "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=="],
19531778
19541779 "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
19551780
1956− "http2-wrapper": ["http2-wrapper@1.0.3", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" } }, "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg=="],
1957−
19581781 "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
19591782
19601783 "human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="],
19611784
19621785 "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
19631786
1964− "ieee754": ["ieee754@1.1.13", "", {}, "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="],
1787+ "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
19651788
19661789 "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
19671790
1968− "ignore-walk": ["ignore-walk@8.0.0", "", { "dependencies": { "minimatch": "^10.0.3" } }, "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A=="],
1969−
19701791 "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
19711792
1972− "import-in-the-middle": ["import-in-the-middle@1.15.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } }, "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA=="],
1973−
19741793 "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
19751794
19761795 "index-to-position": ["index-to-position@1.2.0", "", {}, "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw=="],
19771796
19781797 "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
19791798
1980− "ini": ["ini@2.0.0", "", {}, "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA=="],
1981−
19821799 "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
19831800
19841801 "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
@@ -1995,8 +1812,6 @@ · 10 unmodified lines
19951812
19961813 "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],
19971814
1998− "is-arguments": ["is-arguments@1.2.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA=="],
1999−
20001815 "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
20011816
20021817 "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
@@ -2081,7 +1896,7 @@ · 78 unmodified lines
20811896
20821897 "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
20831898
2084− "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
1899+ "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
20851900
20861901 "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
20871902
@@ -2091,15 +1906,13 @@ · 3 unmodified lines
20911906
20921907 "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
20931908
2094− "jmespath": ["jmespath@0.16.0", "", {}, "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw=="],
2095−
20961909 "jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="],
20971910
20981911 "js-levenshtein": ["js-levenshtein@1.1.6", "", {}, "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g=="],
20991912
21001913 "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
21011914
2102− "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=="],
1915+ "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
21031916
21041917 "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
21051918
@@ -2117,20 +1930,12 @@ · 11 unmodified lines
21171930
21181931 "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
21191932
2120− "json-stringify-nice": ["json-stringify-nice@1.1.4", "", {}, "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw=="],
2121−
21221933 "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
21231934
21241935 "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],
21251936
2126− "jsonparse": ["jsonparse@1.3.1", "", {}, "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg=="],
2127−
21281937 "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="],
21291938
2130− "just-diff": ["just-diff@6.0.2", "", {}, "sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA=="],
2131−
2132− "just-diff-apply": ["just-diff-apply@5.5.0", "", {}, "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw=="],
2133−
21341939 "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="],
21351940
21361941 "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
@@ -2177,8 +1982,6 @@ · 40 unmodified lines
21771982
21781983 "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="],
21791984
2180− "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="],
2181−
21821985 "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
21831986
21841987 "lodash.snakecase": ["lodash.snakecase@4.1.1", "", {}, "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="],
@@ -2193,8 +1996,6 @@ · 8 unmodified lines
21931996
21941997 "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
21951998
2196− "lowercase-keys": ["lowercase-keys@2.0.0", "", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="],
2197−
21981999 "lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
21992000
22002001 "lucide-react": ["lucide-react@0.563.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-8dXPB2GI4dI8jV4MgUDGBeLdGk8ekfqVZ0BdLcrRzocGgG75ltNEmWS+gE7uokKF/0oSUuczNDT+g9hFJ23FkA=="],
@@ -2203,8 +2004,6 @@ · 2 unmodified lines
22032004
22042005 "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
22052006
2206− "make-fetch-happen": ["make-fetch-happen@15.0.3", "", { "dependencies": { "@npmcli/agent": "^4.0.0", "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^6.0.0", "promise-retry": "^2.0.1", "ssri": "^13.0.0" } }, "sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw=="],
2207−
22082007 "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="],
22092008
22102009 "marked": ["marked@14.0.0", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ=="],
@@ -2317,8 +2116,6 @@ · 106 unmodified lines
23172116
23182117 "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
23192118
2320− "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
2321−
23222119 "miniflare": ["miniflare@4.20260210.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "^0.34.5", "undici": "7.18.2", "workerd": "1.20260210.0", "ws": "8.18.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-HXR6m53IOqEzq52DuGF1x7I1K6lSIqzhbCbQXv/cTmPnPJmNkr7EBtLDm4nfSkOvlDtnwDCLUjWII5fyGJI5Tw=="],
23232120
23242121 "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
@@ -2327,20 +2124,6 @@ · 2 unmodified lines
23272124
23282125 "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
23292126
2330− "minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="],
2331−
2332− "minipass-fetch": ["minipass-fetch@5.0.1", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^2.0.0", "minizlib": "^3.0.1" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-yHK8pb0iCGat0lDrs/D6RZmCdaBT64tULXjdxjSMAqoDi18Q3qKEUTHypHQZQd9+FYpIS+lkvpq6C/R6SbUeRw=="],
2333−
2334− "minipass-flush": ["minipass-flush@1.0.5", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw=="],
2335−
2336− "minipass-pipeline": ["minipass-pipeline@1.2.4", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="],
2337−
2338− "minipass-sized": ["minipass-sized@2.0.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA=="],
2339−
2340− "minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
2341−
2342− "module-details-from-path": ["module-details-from-path@1.0.4", "", {}, "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w=="],
2343−
23442127 "monaco-editor": ["monaco-editor@0.55.1", "", { "dependencies": { "dompurify": "3.2.7", "marked": "14.0.0" } }, "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A=="],
23452128
23462129 "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
@@ -2373,38 +2156,14 @@ · 26 unmodified lines
23732156
23742157 "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=="],
23752158
2376− "node-gyp": ["node-gyp@12.2.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "make-fetch-happen": "^15.0.0", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "tar": "^7.5.4", "tinyglobby": "^0.2.12", "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-q23WdzrQv48KozXlr0U1v9dwO/k59NHeSzn6loGcasyf0UnSrtzs8kRxM+mfwJSf0DkX0s43hcqgnSO4/VNthQ=="],
2377−
23782159 "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=="],
23792160
23802161 "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
23812162
2382− "nopt": ["nopt@9.0.0", "", { "dependencies": { "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw=="],
2383−
2384− "normalize-package-data": ["normalize-package-data@6.0.2", "", { "dependencies": { "hosted-git-info": "^7.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" } }, "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g=="],
2385−
2386− "normalize-url": ["normalize-url@6.1.0", "", {}, "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A=="],
2387−
2388− "npm-bundled": ["npm-bundled@5.0.0", "", { "dependencies": { "npm-normalize-package-bin": "^5.0.0" } }, "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw=="],
2389−
2390− "npm-install-checks": ["npm-install-checks@8.0.0", "", { "dependencies": { "semver": "^7.1.1" } }, "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA=="],
2391−
2392− "npm-normalize-package-bin": ["npm-normalize-package-bin@5.0.0", "", {}, "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag=="],
2393−
2394− "npm-package-arg": ["npm-package-arg@13.0.2", "", { "dependencies": { "hosted-git-info": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^7.0.0" } }, "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA=="],
2395−
2396− "npm-packlist": ["npm-packlist@10.0.3", "", { "dependencies": { "ignore-walk": "^8.0.0", "proc-log": "^6.0.0" } }, "sha512-zPukTwJMOu5X5uvm0fztwS5Zxyvmk38H/LfidkOMt3gbZVCyro2cD/ETzwzVPcWZA3JOyPznfUN/nkyFiyUbxg=="],
2397−
2398− "npm-pick-manifest": ["npm-pick-manifest@11.0.3", "", { "dependencies": { "npm-install-checks": "^8.0.0", "npm-normalize-package-bin": "^5.0.0", "npm-package-arg": "^13.0.0", "semver": "^7.3.5" } }, "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ=="],
2399−
2400− "npm-registry-fetch": ["npm-registry-fetch@19.1.1", "", { "dependencies": { "@npmcli/redact": "^4.0.0", "jsonparse": "^1.3.1", "make-fetch-happen": "^15.0.0", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minizlib": "^3.0.1", "npm-package-arg": "^13.0.0", "proc-log": "^6.0.0" } }, "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw=="],
2401−
24022163 "npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="],
24032164
24042165 "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
24052166
2406− "object-hash": ["object-hash@2.2.0", "", {}, "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw=="],
2407−
24082167 "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
24092168
24102169 "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
@@ -2421,8 +2180,6 @@ · 10 unmodified lines
24212180
24222181 "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="],
24232182
2424− "oidc-token-hash": ["oidc-token-hash@5.2.0", "", {}, "sha512-6gj2m8cJZ+iSW8bm0FXdGF0YhIQbKrfP4yWTNzxc31U6MOjfEmB1rHvlYvxI1B7t7BCi1F2vYTT6YhtQRG4hxw=="],
2425−
24262183 "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
24272184
24282185 "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
@@ -2441,10 +2198,6 @@ · 12 unmodified lines
24412198
24422199 "openapi-typescript": ["openapi-typescript@7.12.0", "", { "dependencies": { "@redocly/openapi-core": "^1.34.6", "ansi-colors": "^4.1.3", "change-case": "^5.4.4", "parse-json": "^8.3.0", "supports-color": "^10.2.2", "yargs-parser": "^21.1.1" }, "peerDependencies": { "typescript": "^5.x" }, "bin": { "openapi-typescript": "bin/cli.js" } }, "sha512-dtk3h5rbILWfDEUCNgMeBHSpvVsslM0ik1psDxxlrIAJk34SDqZIbhF+qKZy6MytW7Fp+wxynq9y5S3wgJcn0g=="],
24432200
2444− "opencontrol": ["opencontrol@0.0.6", "", { "dependencies": { "@modelcontextprotocol/sdk": "1.6.1", "@tsconfig/bun": "1.0.7", "hono": "4.7.4", "zod": "3.24.2", "zod-to-json-schema": "3.24.3" }, "bin": { "opencontrol": "bin/index.mjs" } }, "sha512-QeCrpOK5D15QV8kjnGVeD/BHFLwcVr+sn4T6KKmP0WAMs2pww56e4h+eOGHb5iPOufUQXbdbBKi6WV2kk7tefQ=="],
2445−
2446− "openid-client": ["openid-client@5.6.4", "", { "dependencies": { "jose": "^4.15.4", "lru-cache": "^6.0.0", "object-hash": "^2.2.0", "oidc-token-hash": "^5.0.3" } }, "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA=="],
2447−
24482201 "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
24492202
24502203 "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=="],
@@ -2453,30 +2206,20 @@ · 2 unmodified lines
24532206
24542207 "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
24552208
2456− "p-cancelable": ["p-cancelable@2.1.1", "", {}, "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="],
2457−
24582209 "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
24592210
24602211 "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
24612212
2462− "p-map": ["p-map@7.0.4", "", {}, "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ=="],
2463−
24642213 "pac-proxy-agent": ["pac-proxy-agent@7.2.0", "", { "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.1.2", "debug": "^4.3.4", "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.6", "pac-resolver": "^7.0.1", "socks-proxy-agent": "^8.0.5" } }, "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA=="],
24652214
24662215 "pac-resolver": ["pac-resolver@7.0.1", "", { "dependencies": { "degenerator": "^5.0.0", "netmask": "^2.0.2" } }, "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg=="],
24672216
2468− "package-directory": ["package-directory@8.2.0", "", { "dependencies": { "find-up-simple": "^1.0.0" } }, "sha512-qJSu5Mo6tHmRxCy2KCYYKYgcfBdUpy9dwReaZD/xwf608AUk/MoRtIOWzgDtUeGeC7n/55yC3MI1Q+MbSoektw=="],
2469−
24702217 "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
24712218
24722219 "package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="],
24732220
2474− "pacote": ["pacote@21.3.1", "", { "dependencies": { "@npmcli/git": "^7.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^9.0.0", "@npmcli/run-script": "^10.0.0", "cacache": "^20.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^13.0.0", "npm-packlist": "^10.0.1", "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "proc-log": "^6.0.0", "promise-retry": "^2.0.1", "sigstore": "^4.0.0", "ssri": "^13.0.0", "tar": "^7.4.3" }, "bin": { "pacote": "bin/index.js" } }, "sha512-O0EDXi85LF4AzdjG74GUwEArhdvawi/YOHcsW6IijKNj7wm8IvEWNF5GnfuxNpQ/ZpO3L37+v8hqdVh8GgWYhg=="],
2475−
24762221 "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
24772222
2478− "parse-conflict-json": ["parse-conflict-json@5.0.1", "", { "dependencies": { "json-parse-even-better-errors": "^5.0.0", "just-diff": "^6.0.0", "just-diff-apply": "^5.2.0" } }, "sha512-ZHEmNKMq1wyJXNwLxyHnluPfRAFSIliBvbK/UiOceROt4Xh9Pz0fq49NytIaeaCUf5VR86hwQ/34FCcNU5/LKQ=="],
2479−
24802223 "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=="],
24812224
24822225 "parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="],
@@ -2497,7 +2240,7 @@ · 14 unmodified lines
24972240
24982241 "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
24992242
2500− "path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="],
2243+ "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
25012244
25022245 "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
25032246
@@ -2507,7 +2250,7 @@ · 3 unmodified lines
25072250
25082251 "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
25092252
2510− "picomatch": ["picomatch@3.0.1", "", {}, "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag=="],
2253+ "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
25112254
25122255 "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="],
25132256
@@ -2527,16 +2270,6 @@ · 13 unmodified lines
25272270
25282271 "pretty-ms": ["pretty-ms@9.3.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ=="],
25292272
2530− "proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
2531−
2532− "proggy": ["proggy@4.0.0", "", {}, "sha512-MbA4R+WQT76ZBm/5JUpV9yqcJt92175+Y0Bodg3HgiXzrmKu7Ggq+bpn6y6wHH+gN9NcyKn3yg1+d47VaKwNAQ=="],
2533−
2534− "promise-all-reject-late": ["promise-all-reject-late@1.0.1", "", {}, "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw=="],
2535−
2536− "promise-call-limit": ["promise-call-limit@3.0.2", "", {}, "sha512-mRPQO2T1QQVw11E7+UdCJu7S61eJVWknzml9sC1heAdj1jxl0fWMBypIt9ZOcLFf8FkG995ZD7RnVk7HH72fZw=="],
2537−
2538− "promise-retry": ["promise-retry@2.0.1", "", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="],
2539−
25402273 "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
25412274
25422275 "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
@@ -2551,10 +2284,6 @@ · 8 unmodified lines
25512284
25522285 "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
25532286
2554− "pulumi-stripe": ["pulumi-stripe@0.0.26", "", { "dependencies": { "@pulumi/pulumi": "^3.0.0" } }, "sha512-6kwXa6Sn+JaEtv/b6Gji3tOmjxGyYG6LwavC3udJSt+HP6GwcqirF5NJKyCqpjNdm7wbwIBnz8hI3Xri9hkPqA=="],
2555−
2556− "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
2557−
25582287 "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
25592288
25602289 "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
@@ -2567,12 +2296,8 @@ · 6 unmodified lines
25672296
25682297 "quansync": ["quansync@1.0.0", "", {}, "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA=="],
25692298
2570− "querystring": ["querystring@0.2.0", "", {}, "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g=="],
2571−
25722299 "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
25732300
2574− "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="],
2575−
25762301 "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=="],
25772302
25782303 "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
@@ -2599,8 +2324,6 @@ · 20 unmodified lines
25992324
26002325 "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=="],
26012326
2602− "read-cmd-shim": ["read-cmd-shim@6.0.0", "", {}, "sha512-1zM5HuOfagXCBWMN83fuFI/x+T/UhZ7k+KIzhrHXcQoeX5+7gmaDYjELQHmmzIodumBHeByBJT4QYS7ufAgs7A=="],
2603−
26042327 "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
26052328
26062329 "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=="],
@@ -2635,22 +2358,14 @@ · 28 unmodified lines
26352358
26362359 "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
26372360
2638− "require-in-the-middle": ["require-in-the-middle@7.5.2", "", { "dependencies": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3", "resolve": "^1.22.8" } }, "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ=="],
2639−
26402361 "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
26412362
2642− "resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="],
2643−
26442363 "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
26452364
26462365 "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
26472366
2648− "responselike": ["responselike@2.0.1", "", { "dependencies": { "lowercase-keys": "^2.0.0" } }, "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw=="],
2649−
26502367 "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
26512368
2652− "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="],
2653−
26542369 "rettime": ["rettime@0.10.1", "", {}, "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw=="],
26552370
26562371 "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
@@ -2679,11 +2394,9 @@ · 22 unmodified lines
26792394
26802395 "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
26812396
2682− "sax": ["sax@1.2.1", "", {}, "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="],
2683−
26842397 "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
26852398
2686− "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
2399+ "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
26872400
26882401 "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=="],
26892402
@@ -2709,8 +2422,6 @@ · 19 unmodified lines
27092422
27102423 "shiki": ["shiki@3.22.0", "", { "dependencies": { "@shikijs/core": "3.22.0", "@shikijs/engine-javascript": "3.22.0", "@shikijs/engine-oniguruma": "3.22.0", "@shikijs/langs": "3.22.0", "@shikijs/themes": "3.22.0", "@shikijs/types": "3.22.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-LBnhsoYEe0Eou4e1VgJACes+O6S6QC0w71fCSp5Oya79inkwkm15gQ1UF6VtQ8j/taMDh79hAB49WUk8ALQW3g=="],
27112424
2712− "shimmer": ["shimmer@1.2.1", "", {}, "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="],
2713−
27142425 "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=="],
27152426
27162427 "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
@@ -2723,8 +2434,6 @@ · 6 unmodified lines
27232434
27242435 "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
27252436
2726− "sigstore": ["sigstore@4.1.0", "", { "dependencies": { "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0", "@sigstore/sign": "^4.1.0", "@sigstore/tuf": "^4.0.1", "@sigstore/verify": "^3.1.0" } }, "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA=="],
2727−
27282437 "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
27292438
27302439 "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
@@ -2739,40 +2448,8 @@ · 8 unmodified lines
27392448
27402449 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
27412450
2742− "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
2743−
27442451 "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
27452452
2746− "spdx-correct": ["spdx-correct@3.2.0", "", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA=="],
2747−
2748− "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="],
2749−
2750− "spdx-expression-parse": ["spdx-expression-parse@3.0.1", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="],
2751−
2752− "spdx-license-ids": ["spdx-license-ids@3.0.22", "", {}, "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ=="],
2753−
2754− "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
2755−
2756− "ssri": ["ssri@13.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ=="],
2757−
2758− "sst": ["sst@3.17.38", "", { "dependencies": { "aws-sdk": "2.1692.0", "aws4fetch": "1.0.18", "jose": "5.2.3", "opencontrol": "0.0.6", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "3.17.38", "sst-darwin-x64": "3.17.38", "sst-linux-arm64": "3.17.38", "sst-linux-x64": "3.17.38", "sst-linux-x86": "3.17.38", "sst-win32-arm64": "3.17.38", "sst-win32-x64": "3.17.38", "sst-win32-x86": "3.17.38" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-AshCCzogYVVTgLV7SBQ2hkmctAI0QV4pJmHwsyrX1ruSCvH18ccGgX/kux6/AFfaKrT7GmuVuQ2Zsz25GPXEiA=="],
2759−
2760− "sst-darwin-arm64": ["sst-darwin-arm64@3.17.38", "", { "os": "darwin", "cpu": "arm64" }, "sha512-2qEu/jRRBGQbMzkJKy4cypX+LdjInKtn1VrPHeggHD0/DsXLUBVdj/WyYb9ZxbsZEUcA9xZDR2+FBZ7lQzaDcw=="],
2761−
2762− "sst-darwin-x64": ["sst-darwin-x64@3.17.38", "", { "os": "darwin", "cpu": "x64" }, "sha512-um13cWbRK5rfsYuLxS97gaSkFVd6jCzI+k6wlpJaOcJ5IZiH5UdFIz+ZE/7iCfNTEiwDT+RMw2nGL9a+07Vtww=="],
2763−
2764− "sst-linux-arm64": ["sst-linux-arm64@3.17.38", "", { "os": "linux", "cpu": "arm64" }, "sha512-gMxYJmpytntqZOf9SZfMnj+v6E0vZ8dAT5XnaKQhETSwuN6WH/OWHgx4bnp7bMQfdvm1uYNB+p7GRopIRRPePQ=="],
2765−
2766− "sst-linux-x64": ["sst-linux-x64@3.17.38", "", { "os": "linux", "cpu": "x64" }, "sha512-vwzfHhCugRTWevoA2qcl339yQhc8+vVdAqA11Qcats7LvaM6KxN9SqY00SfHPZxmm2odnefDg8z4b3Qvdo2NAw=="],
2767−
2768− "sst-linux-x86": ["sst-linux-x86@3.17.38", "", { "os": "linux", "cpu": "none" }, "sha512-rxG2YsN2XnykCvJ1ZquZIXbEOWIdLdcJ1ir9hcqb31cLrH0z2EN5F/IsioH9mLRVJnbmY3JewNk+C9mMB2a8zA=="],
2769−
2770− "sst-win32-arm64": ["sst-win32-arm64@3.17.38", "", { "os": "win32", "cpu": "arm64" }, "sha512-aPTaLqJ4bEEfQwaxnteFXHAePw4Po1Be0tsdTuNUPDhhyv1CV5xSl4nppb4q/Qn1dGxaU6L4zCzZkshWskGIOg=="],
2771−
2772− "sst-win32-x64": ["sst-win32-x64@3.17.38", "", { "os": "win32", "cpu": "x64" }, "sha512-X2kx6MOK1tZ0JhMqDisB60fJCOSxot5q7NPFMna5hj7cgJaQfj0NAgQqGJkLEB8iVWyxi6e5o1oJLg+vH452HQ=="],
2773−
2774− "sst-win32-x86": ["sst-win32-x86@3.17.38", "", { "os": "win32", "cpu": "none" }, "sha512-W5PxA4uhpXMzWNT0/sMrmU27fn1DCaReGwVwJGEZapu9GKTix41uaP+pyd9fwjiAHVILIdxqe7+BkZfH+mvzbg=="],
2775−
27762453 "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="],
27772454
27782455 "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
@@ -2847,8 +2524,6 @@ · 68 unmodified lines
28472524
28482525 "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
28492526
2850− "tar": ["tar@7.5.7", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ=="],
2851−
28522527 "throttle-debounce": ["throttle-debounce@2.3.0", "", {}, "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ=="],
28532528
28542529 "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
@@ -2869,8 +2544,6 @@ · 14 unmodified lines
28692544
28702545 "tldts-core": ["tldts-core@7.0.22", "", {}, "sha512-KgbTDC5wzlL6j/x6np6wCnDSMUq4kucHNm00KXPbfNzmllCmtmvtykJHfmgdHntwIeupW04y8s1N/43S1PkQDw=="],
28712546
2872− "tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="],
2873−
28742547 "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
28752548
28762549 "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
@@ -2879,8 +2552,6 @@ · 2 unmodified lines
28792552
28802553 "tough-cookie": ["tough-cookie@6.0.0", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w=="],
28812554
2882− "treeverse": ["treeverse@3.0.0", "", {}, "sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ=="],
2883−
28842555 "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
28852556
28862557 "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
@@ -2899,8 +2570,6 @@ · 12 unmodified lines
28992570
29002571 "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
29012572
2902− "tuf-js": ["tuf-js@4.1.0", "", { "dependencies": { "@tufjs/models": "4.1.0", "debug": "^4.4.3", "make-fetch-happen": "^15.0.1" } }, "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ=="],
2903−
29042573 "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
29052574
29062575 "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
@@ -2941,10 +2610,6 @@ · 34 unmodified lines
29412610
29422611 "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=="],
29432612
2944− "unique-filename": ["unique-filename@5.0.0", "", { "dependencies": { "unique-slug": "^6.0.0" } }, "sha512-2RaJTAvAb4owyjllTfXzFClJ7WsGxlykkPvCr9pA//LD9goVq+m4PPAeBgNodGZ7nSrntT/auWpJ6Y5IFXcfjg=="],
2945−
2946− "unique-slug": ["unique-slug@6.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw=="],
2947−
29482613 "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="],
29492614
29502615 "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
@@ -2963,28 +2628,20 @@ · 12 unmodified lines
29632628
29642629 "until-async": ["until-async@3.0.2", "", {}, "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw=="],
29652630
2966− "upath": ["upath@1.2.0", "", {}, "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg=="],
2967−
29682631 "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=="],
29692632
29702633 "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
29712634
2972− "url": ["url@0.10.3", "", { "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" } }, "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ=="],
2973−
29742635 "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=="],
29752636
29762637 "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.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-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="],
29772638
29782639 "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
29792640
2980− "util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="],
2981−
29822641 "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
29832642
29842643 "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
29852644
2986− "validate-npm-package-license": ["validate-npm-package-license@3.0.4", "", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="],
2987−
29882645 "validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="],
29892646
29902647 "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
@@ -3001,8 +2658,6 @@ · 10 unmodified lines
30012658
30022659 "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=="],
30032660
3004− "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="],
3005−
30062661 "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
30072662
30082663 "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
@@ -3033,19 +2688,13 @@ · 24 unmodified lines
30332688
30342689 "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
30352690
3036− "write-file-atomic": ["write-file-atomic@7.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" } }, "sha512-YnlPC6JqnZl6aO4uRc+dx5PHguiR9S6WeoLtpxNT9wIG+BDya7ZNE1q7KOjVgaA73hKhKLpVPgJ5QA9THQ5BRg=="],
3037−
30382691 "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=="],
30392692
30402693 "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="],
30412694
3042− "xml2js": ["xml2js@0.6.2", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA=="],
3043−
3044− "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="],
3045−
30462695 "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
30472696
3048− "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
2697+ "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
30492698
30502699 "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="],
30512700
@@ -3073,8 +2722,6 @@ · 21 unmodified lines
30732722
30742723 "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
30752724
3076− "@apidevtools/json-schema-ref-parser/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
3077−
30782725 "@assistant/bot/@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="],
30792726
30802727 "@assistant/server/@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="],
@@ -3083,16 +2730,10 @@ · 2 unmodified lines
30832730
30842731 "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
30852732
3086− "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
3087−
30882733 "@babel/generator/@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=="],
30892734
30902735 "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
30912736
3092− "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
3093−
3094− "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
3095−
30962737 "@convex-dev/workos/@workos-inc/authkit-react": ["@workos-inc/authkit-react@0.11.0", "", { "dependencies": { "@workos-inc/authkit-js": "0.13.0" }, "peerDependencies": { "react": ">=17" } }, "sha512-67HFSxP4wXC8ECGyvc1yGMwuD5NGkwT2OPt8DavHoKAlO+hRaAlu9wwzqUx1EJrHht0Dcx+l20Byq8Ab0bEhlg=="],
30972738
30982739 "@convex-dev/workos-authkit/@workos-inc/node": ["@workos-inc/node@7.82.0", "", { "dependencies": { "iron-session": "~6.3.1", "jose": "~5.6.3", "leb": "^1.0.0", "qs": "6.14.1" } }, "sha512-8h6XjIJf8nqNGYQMkWsjZ72WXMtzqrb4Azz39schXWoSRmwoK6tK+GpeAviJ9slddiJdOcp0Ht9/r+L6pGQMCg=="],
@@ -3105,8 +2746,6 @@ · 6 unmodified lines
31052746
31062747 "@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=="],
31072748
3108− "@dotenvx/dotenvx/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
3109−
31102749 "@dotenvx/dotenvx/which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="],
31112750
31122751 "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
@@ -3115,8 +2754,6 @@ · 2 unmodified lines
31152754
31162755 "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
31172756
3118− "@eslint/eslintrc/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
3119−
31202757 "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
31212758
31222759 "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
@@ -3131,40 +2768,10 @@ · 8 unmodified lines
31312768
31322769 "@next/eslint-plugin-next/fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="],
31332770
3134− "@npmcli/agent/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="],
3135−
3136− "@npmcli/arborist/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="],
3137−
3138− "@npmcli/arborist/minimatch": ["minimatch@10.1.2", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.1" } }, "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw=="],
3139−
3140− "@npmcli/git/ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="],
3141−
3142− "@npmcli/git/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="],
3143−
3144− "@npmcli/git/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
3145−
3146− "@npmcli/map-workspaces/minimatch": ["minimatch@10.1.2", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.1" } }, "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw=="],
3147−
3148− "@npmcli/metavuln-calculator/json-parse-even-better-errors": ["json-parse-even-better-errors@5.0.0", "", {}, "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ=="],
3149−
3150− "@npmcli/package-json/json-parse-even-better-errors": ["json-parse-even-better-errors@5.0.0", "", {}, "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ=="],
3151−
3152− "@npmcli/promise-spawn/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
3153−
3154− "@npmcli/run-script/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
3155−
31562771 "@openassistant/reacord/react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
31572772
3158− "@opentelemetry/instrumentation-grpc/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.27.0", "", {}, "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg=="],
3159−
3160− "@poppinss/dumper/@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="],
3161−
31622773 "@proto/sources/@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="],
31632774
3164− "@pulumi/pulumi/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=="],
3165−
3166− "@redocly/openapi-core/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
3167−
31682775 "@redocly/openapi-core/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
31692776
31702777 "@rolldown/binding-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" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
@@ -3183,46 +2790,26 @@ · 12 unmodified lines
31832790
31842791 "@ts-morph/common/minimatch": ["minimatch@10.1.2", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.1" } }, "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw=="],
31852792
3186− "@tufjs/models/minimatch": ["minimatch@10.1.2", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.1" } }, "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw=="],
3187−
3188− "@types/cacheable-request/@types/node": ["@types/node@24.10.13", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg=="],
3189−
3190− "@types/keyv/@types/node": ["@types/node@24.10.13", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg=="],
3191−
3192− "@types/responselike/@types/node": ["@types/node@24.10.13", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg=="],
3193−
31942793 "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
31952794
31962795 "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
31972796
2797+ "@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
2798+
31982799 "@workos-inc/authkit-nextjs/@workos-inc/node": ["@workos-inc/node@7.82.0", "", { "dependencies": { "iron-session": "~6.3.1", "jose": "~5.6.3", "leb": "^1.0.0", "qs": "6.14.1" } }, "sha512-8h6XjIJf8nqNGYQMkWsjZ72WXMtzqrb4Azz39schXWoSRmwoK6tK+GpeAviJ9slddiJdOcp0Ht9/r+L6pGQMCg=="],
31992800
32002801 "@workos-inc/authkit-nextjs/jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="],
32012802
3202− "aws-sdk/uuid": ["uuid@8.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw=="],
3203−
3204− "buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
3205−
3206− "cacache/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="],
3207−
3208− "cacheable-request/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
3209−
32102803 "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=="],
32112804
32122805 "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
32132806
32142807 "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=="],
32152808
3216− "clone-response/mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],
3217−
3218− "cosmiconfig/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
3219−
32202809 "cosmiconfig/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=="],
32212810
32222811 "degenerator/ast-types": ["ast-types@0.13.4", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w=="],
32232812
3224− "encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
3225−
32262813 "eslint/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
32272814
32282815 "eslint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
@@ -3233,32 +2820,24 @@ · 4 unmodified lines
32332820
32342821 "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
32352822
3236− "eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
3237−
32382823 "eslint-plugin-import/tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
32392824
32402825 "eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="],
32412826
3242− "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
3243−
3244− "executor-infra/@types/node": ["@types/node@24.10.13", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg=="],
3245−
32462827 "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
32472828
32482829 "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
32492830
32502831 "get-uri/data-uri-to-buffer": ["data-uri-to-buffer@6.0.2", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="],
32512832
3252− "glob/minimatch": ["minimatch@10.1.2", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.1" } }, "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw=="],
3253−
3254− "hosted-git-info/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="],
3255−
3256− "ignore-walk/minimatch": ["minimatch@10.1.2", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.1" } }, "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw=="],
2833+ "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
32572834
32582835 "iron-session/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
32592836
32602837 "iron-session/iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="],
32612838
2839+ "is-bun-module/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
2840+
32622841 "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="],
32632842
32642843 "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
@@ -3269,37 +2848,15 @@ · 4 unmodified lines
32692848
32702849 "miniflare/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
32712850
3272− "minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
3273−
3274− "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
3275−
32762851 "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
32772852
3278− "node-gyp/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
3279−
3280− "normalize-package-data/hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="],
3281−
32822853 "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
32832854
3284− "opencontrol/@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.6.1", "", { "dependencies": { "content-type": "^1.0.5", "cors": "^2.8.5", "eventsource": "^3.0.2", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^4.1.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-oxzMzYCkZHMntzuyerehK3fV6A2Kwh5BD6CGEJSVDU2QNEhfLOptf2X7esQgaHZXHZY0oHmMsOtIDLP71UJXgA=="],
3285−
3286− "opencontrol/hono": ["hono@4.7.4", "", {}, "sha512-Pst8FuGqz3L7tFF+u9Pu70eI0xa5S3LPUmrNd5Jm8nTHze9FxLTK9Kaj5g/k4UcwuJSXTP65SyHOPLrffpcAJg=="],
3287−
3288− "opencontrol/zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="],
3289−
3290− "opencontrol/zod-to-json-schema": ["zod-to-json-schema@3.24.3", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-HIAfWdYIt1sssHfYZFCXp4rU1w2r8hVVXYIlmoa0r0gABLs5di3RCqPU5DDROogVz1pAdYBaz7HK5n9pSUNs3A=="],
3291−
3292− "openid-client/jose": ["jose@4.15.9", "", {}, "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA=="],
3293−
3294− "openid-client/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
3295−
3296− "parse-conflict-json/json-parse-even-better-errors": ["json-parse-even-better-errors@5.0.0", "", {}, "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ=="],
3297−
32982855 "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
32992856
33002857 "parse-json/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
33012858
3302− "path-scurry/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="],
2859+ "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
33032860
33042861 "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
33052862
@@ -3307,17 +2864,11 @@ · 1 unmodified line
33072864
33082865 "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
33092866
3310− "rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
3311−
33122867 "router/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="],
33132868
3314− "safe-array-concat/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
3315−
3316− "safe-push-apply/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
3317−
33182869 "shadcn/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
33192870
3320− "sst/jose": ["jose@5.2.3", "", {}, "sha512-KUXdbctm1uHVL8BYhnyHkgp3zDX5KW8ZhAKVFEfUbU2P8Alpzjb+48hHvjOdQIyPshoblhzsuqOwEEAbtHVirA=="],
2871+ "sharp/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
33212872
33222873 "streamdown/marked": ["marked@17.0.1", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg=="],
33232874
@@ -3331,22 +2882,10 @@ · 7 unmodified lines
33312882
33322883 "strip-literal/js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
33332884
3334− "tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
3335−
3336− "tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
3337−
3338− "token-types/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
3339−
3340− "url/punycode": ["punycode@1.3.2", "", {}, "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="],
3341−
3342− "vite/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
3343−
3344− "vitest/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
2885+ "tsdown/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
33452886
33462887 "vitest/tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
33472888
3348− "which-builtin-type/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
3349−
33502889 "wrangler/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=="],
33512890
33522891 "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=="],
@@ -3359,8 +2898,6 @@ · 6 unmodified lines
33592898
33602899 "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=="],
33612900
3362− "@apidevtools/json-schema-ref-parser/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
3363−
33642901 "@assistant/bot/@types/bun/bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
33652902
33662903 "@assistant/server/@types/bun/bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
@@ -3369,8 +2906,6 @@ · 2 unmodified lines
33692906
33702907 "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
33712908
3372− "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
3373−
33742909 "@convex-dev/workos-authkit/@workos-inc/node/iron-session": ["iron-session@6.3.1", "", { "dependencies": { "@peculiar/webcrypto": "^1.4.0", "@types/cookie": "^0.5.1", "@types/express": "^4.17.13", "@types/koa": "^2.13.5", "@types/node": "^17.0.41", "cookie": "^0.5.0", "iron-webcrypto": "^0.2.5" }, "peerDependencies": { "express": ">=4", "koa": ">=2", "next": ">=10" }, "optionalPeers": ["express", "koa", "next"] }, "sha512-3UJ7y2vk/WomAtEySmPgM6qtYF1cZ3tXuWX5GsVX4PJXAcs5y/sV9HuSfpjKS6HkTL/OhZcTDWJNLZ7w+Erx3A=="],
33752910
33762911 "@convex-dev/workos-authkit/@workos-inc/node/jose": ["jose@5.6.3", "", {}, "sha512-1Jh//hEEwMhNYPDDLwXHa2ePWgWiFNNUadVmguAAw2IJ6sj9mNxV5tGXJNqlMkJAybF6Lgw1mISDxTePP/187g=="],
@@ -3393,42 +2928,14 @@ · 16 unmodified lines
33932928
33942929 "@eslint/eslintrc/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
33952930
3396− "@eslint/eslintrc/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
3397−
33982931 "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
33992932
34002933 "@next/eslint-plugin-next/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
34012934
3402− "@npmcli/git/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
3403−
3404− "@npmcli/promise-spawn/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
3405−
3406− "@npmcli/run-script/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
3407−
34082935 "@proto/sources/@types/bun/bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
34092936
3410− "@pulumi/pulumi/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
3411−
3412− "@pulumi/pulumi/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
3413−
3414− "@pulumi/pulumi/execa/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
3415−
3416− "@pulumi/pulumi/execa/npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
3417−
3418− "@pulumi/pulumi/execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
3419−
3420− "@pulumi/pulumi/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
3421−
3422− "@redocly/openapi-core/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
3423−
34242937 "@redocly/openapi-core/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
34252938
3426− "@types/cacheable-request/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
3427−
3428− "@types/keyv/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
3429−
3430− "@types/responselike/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
3431−
34322939 "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
34332940
34342941 "@workos-inc/authkit-nextjs/@workos-inc/node/iron-session": ["iron-session@6.3.1", "", { "dependencies": { "@peculiar/webcrypto": "^1.4.0", "@types/cookie": "^0.5.1", "@types/express": "^4.17.13", "@types/koa": "^2.13.5", "@types/node": "^17.0.41", "cookie": "^0.5.0", "iron-webcrypto": "^0.2.5" }, "peerDependencies": { "express": ">=4", "koa": ">=2", "next": ">=10" }, "optionalPeers": ["express", "koa", "next"] }, "sha512-3UJ7y2vk/WomAtEySmPgM6qtYF1cZ3tXuWX5GsVX4PJXAcs5y/sV9HuSfpjKS6HkTL/OhZcTDWJNLZ7w+Erx3A=="],
@@ -3439,31 +2946,13 @@ · 4 unmodified lines
34392946
34402947 "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
34412948
3442− "cosmiconfig/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
3443−
34442949 "eslint-plugin-import/tsconfig-paths/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
34452950
34462951 "eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
34472952
34482953 "eslint/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
34492954
3450− "executor-infra/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
3451−
3452− "node-gyp/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
3453−
3454− "normalize-package-data/hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
3455−
3456− "opencontrol/@modelcontextprotocol/sdk/express-rate-limit": ["express-rate-limit@7.5.1", "", { "peerDependencies": { "express": ">= 4.11" } }, "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw=="],
3457−
3458− "opencontrol/@modelcontextprotocol/sdk/pkce-challenge": ["pkce-challenge@4.1.0", "", {}, "sha512-ZBmhE1C9LcPoH9XZSdwiPtbPHZROwAnMy+kIFQVrnMCxY4Cudlz3gBOpzilgc0jOgRaiT3sIWfpMomW2ar2orQ=="],
3459−
3460− "opencontrol/@modelcontextprotocol/sdk/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
3461−
3462− "opencontrol/@modelcontextprotocol/sdk/zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
3463−
3464− "rimraf/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
3465−
3466− "rimraf/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
2955+ "glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
34672956
34682957 "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
34692958
@@ -3547,18 +3036,6 @@ · 77 unmodified lines
35473036
35483037 "@workos-inc/authkit-nextjs/@workos-inc/node/iron-session/iron-webcrypto": ["iron-webcrypto@0.2.8", "", { "dependencies": { "buffer": "^6" } }, "sha512-YPdCvjFMOBjXaYuDj5tiHst5CEk6Xw84Jo8Y2+jzhMceclAnb3+vNPP/CTtb5fO2ZEuXEaO4N+w62Vfko757KA=="],
35493038
3550− "rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
3551−
3552− "rimraf/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
3553−
35543039 "yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
3555−
3556− "@convex-dev/workos-authkit/@workos-inc/node/iron-session/iron-webcrypto/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
3557−
3558− "@workos-inc/authkit-nextjs/@workos-inc/node/iron-session/iron-webcrypto/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
3559−
3560− "@convex-dev/workos-authkit/@workos-inc/node/iron-session/iron-webcrypto/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
3561−
3562− "@workos-inc/authkit-nextjs/@workos-inc/node/iron-session/iron-webcrypto/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
35633040 }
35643041 }
executor/apps/web/package.json+1−0
@@ -25,6 +25,7 @@ · 24 unmodified lines
2525 "clsx": "^2.1.1",
2626 "cmdk": "^1",
2727 "convex": "^1.31.7",
28+ "json-schema-traverse": "^1.0.0",
2829 "lucide-react": "^0.563.0",
2930 "monaco-editor": "^0.55.1",
3031 "next": "16.1.6",
executor/apps/web/src/app/globals.css+2−0
@@ -391,3 +391,5 @@ · 390 unmodified lines
391391 max-width: 100%;
392392 border-radius: 0.25rem;
393393 }
394+
395+
executor/apps/web/src/components/tools/add/source/dialog-sections.tsx+2−2
@@ -63,7 +63,7 @@ export function CatalogViewSection({ · 62 unmodified lines
6363
6464 <Separator />
6565
66− <div className="max-h-80 overflow-y-auto overflow-x-hidden space-y-1 pr-1">
66+ <div className="flex-1 min-h-0 overflow-y-auto overflow-x-hidden space-y-1 pr-1">
6767 <button
6868 type="button"
6969 onClick={onSwitchToCustom}
@@ -278,7 +278,7 @@ export function CustomViewSection({ · 208 unmodified lines
278278
279279 {/* Detecting type skeleton for remaining fields */}
280280 {detectingType && !typeResolved ? (
281− <div className="space-y-3">
281+ <div className="flex flex-col gap-3 min-h-0 flex-1">
282282 <div className="space-y-1.5">
283283 <Skeleton className="h-3 w-12 rounded" />
284284 <Skeleton className="h-8 w-full rounded-md" />
executor/apps/web/src/components/tools/explorer-groups.tsx+215−2
@@ -26,8 +26,9 @@ import { · 25 unmodified lines
2626 toolDisplaySegment,
2727 type ToolGroup,
2828 } from "@/lib/tool/explorer-grouping";
29−import type { SourceAuthProfile, ToolDescriptor, ToolSourceRecord } from "@/lib/types";
30−import { SelectableToolRow, ToolLoadingRows } from "./explorer-rows";
29+import type { ToolDescriptor, ToolSourceRecord } from "@/lib/types";
30+import type { SourceAuthProfile } from "@/lib/types";
31+import { SelectableToolRow, ToolListItem, ToolLoadingRows } from "./explorer-rows";
3132 import { DefaultSourceIcon, SourceFavicon } from "./source-favicon";
3233
3334 export function GroupNode({
@@ -214,6 +215,218 @@ export function GroupNode({ · 180 unmodified lines
214215 );
215216 }
216217
218+// ── Navigation tree node (click-to-focus, no inline detail) ─────────────────
219+
220+export function NavGroupNode({
221+ group,
222+ depth,
223+ expandedKeys,
224+ onToggle,
225+ focusedPath,
226+ focusedSource,
227+ selectedKeys,
228+ onFocusTool,
229+ onSelectTool,
230+ onSourceClick,
231+ source,
232+}: {
233+ group: ToolGroup;
234+ depth: number;
235+ expandedKeys: Set<string>;
236+ onToggle: (key: string) => void;
237+ focusedPath: string | null;
238+ focusedSource?: string | null;
239+ selectedKeys: Set<string>;
240+ onFocusTool: (tool: ToolDescriptor) => void;
241+ onSelectTool?: (path: string, e: React.MouseEvent) => void;
242+ onSourceClick?: (sourceName: string) => void;
243+ source?: ToolSourceRecord;
244+}) {
245+ const isExpanded = expandedKeys.has(group.key);
246+ const isSource = group.type === "source";
247+ const isSourceFocused = isSource && focusedSource === group.label;
248+ const isLoading =
249+ group.type === "source" &&
250+ typeof group.loadingPlaceholderCount === "number" &&
251+ group.loadingPlaceholderCount > 0;
252+ const sourceTypeFallback: ToolSourceRecord["type"] | "local" | "system" = source
253+ ? source.type
254+ : group.label === "system"
255+ ? "system"
256+ : (group.sourceType as ToolSourceRecord["type"] | "local") ?? "openapi";
257+
258+ const hasNestedGroups = group.children.some((child): child is ToolGroup => "key" in child);
259+ const displayLabel = toolDisplaySegment(group.label);
260+
261+ const handleSourceHeaderClick = () => {
262+ // Always expand when clicking a source
263+ if (!isExpanded) {
264+ onToggle(group.key);
265+ }
266+ // Show source details in the main panel
267+ if (isSource && onSourceClick) {
268+ onSourceClick(group.label);
269+ }
270+ };
271+
272+ return (
273+ <Collapsible open={isExpanded} onOpenChange={() => onToggle(group.key)}>
274+ {isSource ? (
275+ // Source headers: click shows details in main panel + expands
276+ <div
277+ onClick={handleSourceHeaderClick}
278+ className={cn(
279+ "flex items-center gap-1.5 px-2 py-1 transition-colors cursor-pointer group/source",
280+ "sticky bg-background/95 backdrop-blur-sm",
281+ isExpanded && "border-b border-border/20",
282+ isSourceFocused
283+ ? "bg-accent/40 border-l-2 border-l-primary"
284+ : "hover:bg-accent/20 border-l-2 border-l-transparent",
285+ )}
286+ style={{
287+ paddingLeft: `${depth * 14 + 6}px`,
288+ top: `${depth * 28}px`,
289+ zIndex: 20 - depth,
290+ }}
291+ >
292+ <CollapsibleTrigger asChild>
293+ <button
294+ className="h-3.5 w-3.5 flex items-center justify-center shrink-0"
295+ onClick={(e) => e.stopPropagation()}
296+ >
297+ {isExpanded ? (
298+ <ChevronDown className="h-2.5 w-2.5 text-muted-foreground/60" />
299+ ) : (
300+ <ChevronRight className="h-2.5 w-2.5 text-muted-foreground/40" />
301+ )}
302+ </button>
303+ </CollapsibleTrigger>
304+
305+ <div className="h-4 w-4 rounded bg-muted/50 flex items-center justify-center shrink-0">
306+ {source ? (
307+ <SourceFavicon
308+ source={source}
309+ iconClassName="h-2.5 w-2.5 text-muted-foreground"
310+ imageClassName="w-full h-full"
311+ />
312+ ) : (
313+ <DefaultSourceIcon type={sourceTypeFallback} className="h-2.5 w-2.5 text-muted-foreground" />
314+ )}
315+ </div>
316+
317+ <span className="font-mono text-[11px] font-semibold text-foreground/90 truncate">
318+ {displayLabel}
319+ </span>
320+
321+ <span className="text-[9px] font-mono text-muted-foreground/50 ml-auto flex items-center gap-1 shrink-0">
322+ {isLoading ? (
323+ <Loader2 className="h-2.5 w-2.5 animate-spin" />
324+ ) : (
325+ <>
326+ {group.approvalCount > 0 && (
327+ <span className="inline-flex items-center gap-0.5 text-terminal-amber">
328+ <ShieldCheck className="h-2 w-2" />
329+ {group.approvalCount}
330+ </span>
331+ )}
332+ <span className="tabular-nums">{group.childCount}</span>
333+ </>
334+ )}
335+ </span>
336+ </div>
337+ ) : (
338+ // Namespace headers: plain collapsible toggle
339+ <CollapsibleTrigger asChild>
340+ <div
341+ className={cn(
342+ "flex items-center gap-1.5 px-2 py-1 transition-colors cursor-pointer",
343+ "sticky bg-background/95 backdrop-blur-sm",
344+ isExpanded && "border-b border-border/20",
345+ "hover:bg-accent/20",
346+ )}
347+ style={{
348+ paddingLeft: `${depth * 14 + 6}px`,
349+ top: `${depth * 28}px`,
350+ zIndex: 20 - depth,
351+ }}
352+ >
353+ <div className="h-3.5 w-3.5 flex items-center justify-center shrink-0">
354+ {isExpanded ? (
355+ <ChevronDown className="h-2.5 w-2.5 text-muted-foreground/60" />
356+ ) : (
357+ <ChevronRight className="h-2.5 w-2.5 text-muted-foreground/40" />
358+ )}
359+ </div>
360+
361+ <span className="font-mono text-[11px] font-medium text-foreground/80 truncate">
362+ {displayLabel}
363+ </span>
364+
365+ <span className="text-[9px] font-mono text-muted-foreground/50 ml-auto flex items-center gap-1 shrink-0">
366+ {group.approvalCount > 0 && (
367+ <span className="inline-flex items-center gap-0.5 text-terminal-amber">
368+ <ShieldCheck className="h-2 w-2" />
369+ {group.approvalCount}
370+ </span>
371+ )}
372+ <span className="tabular-nums">{group.childCount}</span>
373+ </span>
374+ </div>
375+ </CollapsibleTrigger>
376+ )}
377+
378+ <CollapsibleContent>
379+ {hasNestedGroups || group.children.some((child) => !("key" in child))
380+ ? group.children.map((child) => {
381+ if ("key" in child) {
382+ return (
383+ <NavGroupNode
384+ key={child.key}
385+ group={child}
386+ depth={depth + 1}
387+ expandedKeys={expandedKeys}
388+ onToggle={onToggle}
389+ focusedPath={focusedPath}
390+ focusedSource={focusedSource}
391+ selectedKeys={selectedKeys}
392+ onFocusTool={onFocusTool}
393+ onSelectTool={onSelectTool}
394+ onSourceClick={onSourceClick}
395+ />
396+ );
397+ }
398+
399+ return (
400+ <ToolListItem
401+ key={child.path}
402+ tool={child}
403+ label={toolDisplayOperation(child.path)}
404+ focused={child.path === focusedPath}
405+ selected={selectedKeys.has(child.path)}
406+ onFocus={onFocusTool}
407+ onSelect={
408+ onSelectTool
409+ ? (e) => onSelectTool(child.path, e)
410+ : undefined
411+ }
412+ depth={depth + 1}
413+ />
414+ );
415+ })
416+ : null}
417+
418+ {isLoading ? (
419+ <ToolLoadingRows
420+ source={displayLabel}
421+ count={group.loadingPlaceholderCount ?? 3}
422+ depth={depth + 1}
423+ />
424+ ) : null}
425+ </CollapsibleContent>
426+ </Collapsible>
427+ );
428+}
429+
217430 export function SourceSidebar({
218431 sources,
219432 sourceCounts,
executor/apps/web/src/components/tools/explorer-rows.tsx+159−0
@@ -19,6 +19,85 @@ import type { ToolDescriptor } from "@/lib/types"; · 18 unmodified lines
1919 import { CopyButton } from "./explorer/copy-button";
2020 import { ToolDetail } from "./explorer/tool-detail";
2121
22+// ── Compact sidebar tool item (click-to-focus, no collapsible) ──────────────
23+
24+export const ToolListItem = memo(function ToolListItem({
25+ tool,
26+ label,
27+ focused,
28+ selected,
29+ onFocus,
30+ onSelect,
31+ depth = 0,
32+}: {
33+ tool: ToolDescriptor;
34+ label: string;
35+ focused: boolean;
36+ selected: boolean;
37+ onFocus: (tool: ToolDescriptor) => void;
38+ onSelect?: (e: React.MouseEvent) => void;
39+ depth?: number;
40+}) {
41+ const handleClick = useCallback(() => {
42+ onFocus(tool);
43+ }, [onFocus, tool]);
44+
45+ return (
46+ <div
47+ onClick={handleClick}
48+ className={cn(
49+ "flex items-center gap-1.5 px-2 py-1 cursor-pointer transition-colors group/item",
50+ focused
51+ ? "bg-accent/50 border-l-2 border-l-primary"
52+ : "hover:bg-accent/20 border-l-2 border-l-transparent",
53+ selected && !focused && "bg-primary/5",
54+ )}
55+ style={{ paddingLeft: `${depth * 14 + 8}px` }}
56+ >
57+ {onSelect ? (
58+ <button
59+ onClick={(e) => {
60+ e.stopPropagation();
61+ onSelect(e);
62+ }}
63+ className={cn(
64+ "h-3.5 w-3.5 rounded border flex items-center justify-center shrink-0 transition-colors",
65+ selected
66+ ? "bg-primary border-primary text-primary-foreground"
67+ : "border-border/60 opacity-0 group-hover/item:opacity-100",
68+ )}
69+ >
70+ {selected && <Check className="h-2 w-2" />}
71+ </button>
72+ ) : null}
73+
74+ <Zap className="h-2.5 w-2.5 text-primary/50 shrink-0" />
75+
76+ <span
77+ className={cn(
78+ "text-[12px] font-mono truncate",
79+ focused ? "text-foreground font-medium" : "text-foreground/75",
80+ )}
81+ >
82+ {label}
83+ </span>
84+
85+ {tool.approval === "required" ? (
86+ <ShieldCheck className="h-2.5 w-2.5 text-terminal-amber/70 shrink-0 ml-auto" />
87+ ) : null}
88+ </div>
89+ );
90+},
91+(prev, next) =>
92+ prev.tool === next.tool &&
93+ prev.label === next.label &&
94+ prev.focused === next.focused &&
95+ prev.selected === next.selected &&
96+ prev.depth === next.depth,
97+);
98+
99+// ── Original collapsible tool row (used in tree/flat views) ─────────────────
100+
22101 const ToolRow = memo(function ToolRow({
23102 tool,
24103 label,
@@ -151,6 +230,86 @@ export const SelectableToolRow = memo(function SelectableToolRow({ · 126 unmodified lines
151230 prev.selectedKeys.has(prev.tool.path) === next.selectedKeys.has(next.tool.path),
152231 );
153232
233+// ── Tool list for sidebar layout ────────────────────────────────────────────
234+
235+export function ToolListSidebar({
236+ tools,
237+ focusedPath,
238+ selectedKeys,
239+ onFocusTool,
240+ onSelectTool,
241+ loadingRows,
242+ hasMoreTools = false,
243+ loadingMoreTools = false,
244+ onLoadMoreTools,
245+ scrollContainerId,
246+ scrollContainerRef,
247+}: {
248+ tools: ToolDescriptor[];
249+ focusedPath: string | null;
250+ selectedKeys: Set<string>;
251+ onFocusTool: (tool: ToolDescriptor) => void;
252+ onSelectTool?: (path: string, e: React.MouseEvent) => void;
253+ loadingRows?: { source: string; count: number }[];
254+ hasMoreTools?: boolean;
255+ loadingMoreTools?: boolean;
256+ onLoadMoreTools?: () => Promise<void>;
257+ scrollContainerId: string;
258+ scrollContainerRef: React.RefObject<HTMLDivElement | null>;
259+}) {
260+ return (
261+ <div
262+ ref={scrollContainerRef}
263+ id={scrollContainerId}
264+ className="h-full overflow-y-auto"
265+ >
266+ <InfiniteScroll
267+ dataLength={tools.length}
268+ next={() => {
269+ void onLoadMoreTools?.();
270+ }}
271+ hasMore={hasMoreTools}
272+ scrollableTarget={scrollContainerId}
273+ style={{ overflow: "visible" }}
274+ loader={
275+ <div className="px-2 py-2 text-[10px] text-muted-foreground/60">
276+ {loadingMoreTools ? "Loading..." : ""}
277+ </div>
278+ }
279+ >
280+ <div className="py-0.5">
281+ {tools.map((tool) => (
282+ <ToolListItem
283+ key={tool.path}
284+ tool={tool}
285+ label={toolDisplayPath(tool.path)}
286+ focused={tool.path === focusedPath}
287+ selected={selectedKeys.has(tool.path)}
288+ onFocus={onFocusTool}
289+ onSelect={
290+ onSelectTool
291+ ? (e) => onSelectTool(tool.path, e)
292+ : undefined
293+ }
294+ />
295+ ))}
296+
297+ {loadingRows?.map((loadingRow) => (
298+ <ToolLoadingRows
299+ key={loadingRow.source}
300+ source={loadingRow.source}
301+ count={loadingRow.count}
302+ depth={0}
303+ />
304+ ))}
305+ </div>
306+ </InfiniteScroll>
307+ </div>
308+ );
309+}
310+
311+// ── Flat list (original, used in flat view mode) ────────────────────────────
312+
154313 export function VirtualFlatList({
155314 tools,
156315 selectedKeys,
executor/apps/web/src/components/tools/explorer-toolbar.tsx+49−164
@@ -1,13 +1,10 @@
11 import {
22 Search,
33 ShieldCheck,
4− Server,
54 Filter,
5+ Plus,
66 X,
7− FolderTree,
8− List,
97 } from "lucide-react";
10−import type { ReactNode } from "react";
118 import { Input } from "@/components/ui/input";
129 import { Button } from "@/components/ui/button";
1310 import {
@@ -30,160 +27,74 @@ interface ToolExplorerToolbarProps { · 16 unmodified lines
3027 hasSearch: boolean;
3128 resultCount: number;
3229 loadingInventory?: boolean;
33− viewMode: ViewMode;
34− groupBy: GroupBy;
3530 filterApproval: FilterApproval;
36− showSourceSidebar: boolean;
3731 activeSource: string | null;
38− sourceOptions: string[];
3932 selectedToolCount: number;
4033 onSearchChange: (value: string) => void;
4134 onClearSearch: () => void;
42− onViewModeChange: (mode: ViewMode) => void;
43− onGroupByChange: (mode: GroupBy) => void;
4435 onFilterApprovalChange: (filter: FilterApproval) => void;
45− onSourceSelect: (source: string | null) => void;
46− addSourceAction?: ReactNode;
36+ onAddSource?: () => void;
4737 onSelectAll: () => void;
4838 onClearSelection: () => void;
49− onExpandAll: () => void;
50− onCollapseAll: () => void;
5139 }
5240
5341 export function ToolExplorerToolbar({
5442 search,
5543 filteredToolCount,
5644 loadingInventory = false,
57− viewMode,
58− groupBy,
5945 filterApproval,
60− showSourceSidebar,
61− activeSource,
62− sourceOptions,
6346 selectedToolCount,
6447 onSearchChange,
6548 onClearSearch,
66− onViewModeChange,
67− onGroupByChange,
6849 onFilterApprovalChange,
69− onSourceSelect,
70− addSourceAction,
50+ onAddSource,
7151 onSelectAll,
7252 onClearSelection,
7353 }: ToolExplorerToolbarProps) {
7454 const hasSelection = selectedToolCount > 0;
7555
7656 return (
77− <div className="shrink-0 relative">
78− <div className="flex items-center gap-2 pb-3 flex-wrap">
79− <div className="relative flex-1 min-w-[200px]">
80− <Search className="absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground/50" />
81− <Input
82− value={search}
83− onChange={(e) => onSearchChange(e.target.value)}
84− placeholder={loadingInventory ? "Loading tools..." : `Search ${filteredToolCount} tools...`}
85− className="h-8 text-xs pl-8 bg-background/50 border-border/50 focus:border-primary/30"
86− />
87− {search && (
88− <button
89− onClick={onClearSearch}
90− className="absolute right-2 top-1/2 -translate-y-1/2 h-4 w-4 rounded flex items-center justify-center text-muted-foreground hover:text-foreground"
91− >
92− <X className="h-3 w-3" />
93− </button>
94− )}
95− </div>
96−
97− <div className="flex h-8 rounded-md border border-border/50 overflow-hidden">
57+ <div className="shrink-0 relative space-y-1.5">
58+ {/* Search — own row */}
59+ <div className="relative">
60+ <Search className="absolute left-2 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground/50" />
61+ <Input
62+ value={search}
63+ onChange={(e) => onSearchChange(e.target.value)}
64+ placeholder={loadingInventory ? "Loading..." : `Search ${filteredToolCount} tools...`}
65+ className="h-7 text-[11px] pl-7 bg-background/50 border-border/50 focus:border-primary/30"
66+ />
67+ {search && (
9868 <button
99− onClick={() => onViewModeChange("tree")}
100− className={cn(
101− "px-2 flex items-center gap-1 text-[11px] transition-colors",
102− viewMode === "tree"
103− ? "bg-accent/40 text-foreground"
104− : "text-muted-foreground hover:text-foreground hover:bg-accent/20",
105− )}
69+ onClick={onClearSearch}
70+ className="absolute right-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 rounded flex items-center justify-center text-muted-foreground hover:text-foreground"
10671 >
107− <FolderTree className="h-3 w-3" />
108− <span className="hidden sm:inline">Tree</span>
72+ <X className="h-2.5 w-2.5" />
10973 </button>
110− <button
111− onClick={() => onViewModeChange("flat")}
112− className={cn(
113− "px-2 flex items-center gap-1 text-[11px] transition-colors border-l border-border/50",
114− viewMode === "flat"
115− ? "bg-accent/40 text-foreground"
116− : "text-muted-foreground hover:text-foreground hover:bg-accent/20",
117− )}
118− >
119− <List className="h-3 w-3" />
120− <span className="hidden sm:inline">Flat</span>
121− </button>
122− </div>
123−
124− {viewMode === "tree" && (
125− <DropdownMenu>
126− <DropdownMenuTrigger asChild>
127− <Button
128− variant="outline"
129− size="sm"
130− className="h-8 text-[11px] border-border/50"
131− >
132− <FolderTree className="h-3 w-3 mr-1" />
133− {groupBy === "source"
134− ? "By source"
135− : groupBy === "namespace"
136− ? "By namespace"
137− : "By approval"}
138− </Button>
139− </DropdownMenuTrigger>
140− <DropdownMenuContent align="end">
141− <DropdownMenuLabel className="text-[11px]">Group by</DropdownMenuLabel>
142− <DropdownMenuSeparator />
143− <DropdownMenuCheckboxItem
144− checked={groupBy === "source"}
145− onCheckedChange={() => onGroupByChange("source")}
146− className="text-xs"
147− >
148− Source → Namespace
149− </DropdownMenuCheckboxItem>
150− <DropdownMenuCheckboxItem
151− checked={groupBy === "namespace"}
152− onCheckedChange={() => onGroupByChange("namespace")}
153− className="text-xs"
154− >
155− Namespace
156− </DropdownMenuCheckboxItem>
157− <DropdownMenuCheckboxItem
158− checked={groupBy === "approval"}
159− onCheckedChange={() => onGroupByChange("approval")}
160− className="text-xs"
161− >
162− Approval mode
163− </DropdownMenuCheckboxItem>
164− </DropdownMenuContent>
165− </DropdownMenu>
16674 )}
75+ </div>
16776
77+ {/* Filter + actions row */}
78+ <div className="flex items-center gap-1.5">
16879 <DropdownMenu>
16980 <DropdownMenuTrigger asChild>
17081 <Button
17182 variant="outline"
17283 size="sm"
17384 className={cn(
174− "h-8 text-[11px] border-border/50",
85+ "h-6 text-[10px] border-border/50 px-2",
17586 filterApproval !== "all" && "border-primary/30 text-primary",
17687 )}
17788 >
178− <Filter className="h-3 w-3 mr-1" />
89+ <Filter className="h-2.5 w-2.5 mr-1" />
17990 {filterApproval === "all"
180− ? "Filter"
91+ ? "All"
18192 : filterApproval === "required"
182− ? "Gated only"
183− : "Auto only"}
93+ ? "Gated"
94+ : "Auto"}
18495 </Button>
18596 </DropdownMenuTrigger>
186− <DropdownMenuContent align="end">
97+ <DropdownMenuContent align="start">
18798 <DropdownMenuLabel className="text-[11px]">Approval filter</DropdownMenuLabel>
18899 <DropdownMenuSeparator />
189100 <DropdownMenuCheckboxItem
@@ -210,83 +121,57 @@ export function ToolExplorerToolbar({ · 20 unmodified lines
210121 </DropdownMenuContent>
211122 </DropdownMenu>
212123
213− <DropdownMenu>
214− <DropdownMenuTrigger asChild>
215− <Button
216− variant="outline"
217− size="sm"
218− className={cn(
219− "h-8 text-[11px] border-border/50",
220− showSourceSidebar && "lg:hidden",
221− activeSource && "border-primary/30 text-primary",
222− )}
223− >
224− <Server className="h-3 w-3 mr-1" />
225− {activeSource ?? "All"}
226− </Button>
227− </DropdownMenuTrigger>
228− <DropdownMenuContent align="end">
229− <DropdownMenuLabel className="text-[11px]">Source</DropdownMenuLabel>
230− <DropdownMenuSeparator />
231− <DropdownMenuCheckboxItem
232− checked={activeSource === null}
233− onCheckedChange={() => onSourceSelect(null)}
234− className="text-xs"
235− >
236− All sources
237− </DropdownMenuCheckboxItem>
238− {sourceOptions.map((src) => (
239− <DropdownMenuCheckboxItem
240− key={src}
241− checked={activeSource === src}
242− onCheckedChange={() => onSourceSelect(activeSource === src ? null : src)}
243− className="text-xs font-mono"
244− >
245− {src}
246− </DropdownMenuCheckboxItem>
247− ))}
248− </DropdownMenuContent>
249− </DropdownMenu>
124+ <div className="flex-1" />
250125
251− {addSourceAction ? <div className="ml-auto">{addSourceAction}</div> : null}
126+ {onAddSource ? (
127+ <Button
128+ variant="default"
129+ size="sm"
130+ className="h-6 text-[10px] px-2"
131+ onClick={onAddSource}
132+ >
133+ <Plus className="h-2.5 w-2.5 mr-1" />
134+ Add Source
135+ </Button>
136+ ) : null}
252137 </div>
253138
254139 <div
255140 className={cn(
256− "absolute inset-x-0 top-full mt-2 transition-opacity duration-150 pointer-events-none",
141+ "absolute inset-x-0 top-full mt-1 z-30 transition-opacity duration-150 pointer-events-none",
257142 hasSelection ? "opacity-100 pointer-events-auto" : "opacity-0",
258143 )}
259144 aria-hidden={!hasSelection}
260145 >
261− <div className="flex items-center gap-2 px-3 py-2 rounded-md bg-primary/5 border border-primary/10">
262− <span className="text-[12px] font-mono text-primary">
263− {selectedToolCount} tool{selectedToolCount !== 1 ? "s" : ""} selected
146+ <div className="flex items-center gap-2 px-2.5 py-1.5 rounded-md bg-primary/5 border border-primary/10">
147+ <span className="text-[11px] font-mono text-primary">
148+ {selectedToolCount} selected
264149 </span>
265150 <div className="flex-1" />
266151 <Button
267152 variant="ghost"
268153 size="sm"
269− className="h-6 text-[11px] text-muted-foreground"
154+ className="h-5 text-[10px] text-muted-foreground px-1.5"
270155 onClick={onSelectAll}
271156 >
272− Select all ({filteredToolCount})
157+ All ({filteredToolCount})
273158 </Button>
274159 <Button
275160 variant="ghost"
276161 size="sm"
277− className="h-6 text-[11px] text-muted-foreground"
162+ className="h-5 text-[10px] text-muted-foreground px-1.5"
278163 onClick={onClearSelection}
279164 >
280165 Clear
281166 </Button>
282− <div className="h-4 w-px bg-border/50" />
167+ <div className="h-3 w-px bg-border/50" />
283168 <Button
284169 variant="outline"
285170 size="sm"
286− className="h-6 text-[11px] border-terminal-amber/30 text-terminal-amber hover:bg-terminal-amber/10"
171+ className="h-5 text-[10px] border-terminal-amber/30 text-terminal-amber hover:bg-terminal-amber/10 px-1.5"
287172 >
288− <ShieldCheck className="h-3 w-3 mr-1" />
289− Set approval
173+ <ShieldCheck className="h-2.5 w-2.5 mr-0.5" />
174+ Approval
290175 </Button>
291176 </div>
292177 </div>
executor/apps/web/src/components/tools/explorer.tsx+325−340
@@ -1,36 +1,36 @@
11 "use client";
22
3−import { type ReactNode, useState, useMemo, useCallback, useRef, useDeferredValue } from "react";
3+import { useState, useMemo, useCallback, useRef, useDeferredValue, useEffect } from "react";
4+import {
5+ AlertTriangle,
6+ Loader2,
7+ RefreshCcw,
8+} from "lucide-react";
49 import InfiniteScroll from "react-infinite-scroll-component";
510 import { cn } from "@/lib/utils";
6−import {
7− collectGroupKeys,
8−} from "@/lib/tool/explorer-grouping";
9−import type { SourceAuthProfile, ToolDescriptor, ToolSourceRecord } from "@/lib/types";
10−import { findToolsInGroupByKey } from "./explorer-helpers";
11+import type { ToolDescriptor, ToolSourceRecord } from "@/lib/types";
12+import type { SourceAuthProfile } from "@/lib/types";
1113 import {
1214 autoExpandedKeysForSearch,
1315 countSelectedTools,
14− expandedKeysForSource,
1516 filterToolsBySearch,
1617 filterToolsBySourceAndApproval,
17− flatToolsForView,
18− sourceOptionsFromTools,
1918 treeGroupsForView,
2019 type FilterApproval,
2120 } from "./explorer-derived";
21+import { collectGroupKeys } from "@/lib/tool/explorer-grouping";
2222 import { sourceLabel } from "@/lib/tool/source-utils";
2323 import {
2424 EmptyState,
2525 LoadingState,
26− VirtualFlatList,
26+ ToolLoadingRows,
2727 } from "./explorer-rows";
28−import { GroupNode, SourceSidebar } from "./explorer-groups";
28+import { NavGroupNode } from "./explorer-groups";
2929 import {
3030 ToolExplorerToolbar,
31− type GroupBy,
32− type ViewMode,
3331 } from "./explorer-toolbar";
32+import { ToolDetailPanel, ToolDetailEmpty } from "./explorer/tool-detail";
33+import { SourceFormPanel } from "./explorer/source-form-panel";
3434 import type { SourceDialogMeta } from "./add/source-dialog";
3535 import { warningsBySourceName } from "@/lib/tools/source-helpers";
3636
@@ -54,8 +54,9 @@ interface ToolExplorerProps { · 17 unmodified lines
5454 initialSource?: string | null;
5555 activeSource?: string | null;
5656 onActiveSourceChange?: (source: string | null) => void;
57+ /** @deprecated No longer used — source sidebar is merged into the tool list panel. */
5758 showSourceSidebar?: boolean;
58− addSourceAction?: ReactNode;
59+ onSourceAdded?: (source: ToolSourceRecord) => void;
5960 sourceDialogMeta?: Record<string, SourceDialogMeta>;
6061 sourceAuthProfiles?: Record<string, SourceAuthProfile>;
6162 existingSourceNames?: Set<string>;
@@ -70,13 +71,10 @@ export function ToolExplorer({ · 8 unmodified lines
7071 tools,
7172 sources,
7273 sourceCountsOverride,
73− totalTools,
7474 hasMoreTools = false,
7575 loadingMoreTools = false,
7676 onLoadMoreTools,
77− sourceHasMoreTools,
7877 sourceLoadingMoreTools,
79− onLoadMoreToolsForSource,
8078 loading = false,
8179 loadingSources = [],
8280 onLoadToolDetails,
@@ -84,8 +82,7 @@ export function ToolExplorer({ · 1 unmodified line
8482 initialSource = null,
8583 activeSource,
8684 onActiveSourceChange,
87− showSourceSidebar = true,
88− addSourceAction,
85+ onSourceAdded,
8986 sourceDialogMeta,
9087 sourceAuthProfiles,
9188 existingSourceNames,
@@ -111,32 +108,20 @@ export function ToolExplorer({ · 19 unmodified lines
111108
112109 const [searchInput, setSearchInput] = useState("");
113110 const search = useDeferredValue(searchInput);
114− const [viewMode, setViewMode] = useState<ViewMode>("tree");
115− const [groupBy, setGroupBy] = useState<GroupBy>("source");
116− const [internalActiveSource, setInternalActiveSource] = useState<string | null>(initialSource);
117− const [expandedKeys, setExpandedKeys] = useState<Set<string>>(
118− () => expandedKeysForSource(initialSource),
119− );
111+ const [internalActiveSource] = useState<string | null>(initialSource);
120112 const [selectedKeys, setSelectedKeys] = useState<Set<string>>(new Set());
121113 const [filterApproval, setFilterApproval] = useState<FilterApproval>("all");
122114 const [toolDetailsByPath, setToolDetailsByPath] = useState<Record<string, Pick<ToolDescriptor, "path" | "description" | "display" | "typing">>>({});
123115 const [loadingDetailPaths, setLoadingDetailPaths] = useState<Set<string>>(new Set());
124− const treeListRef = useRef<HTMLDivElement>(null);
125− const flatListRef = useRef<HTMLDivElement>(null);
126− const flatScrollContainerId = "tool-explorer-flat-scroll";
127− const treeScrollContainerId = "tool-explorer-tree-scroll";
116+ const [focusedToolPath, setFocusedToolPath] = useState<string | null>(null);
117+ const [focusedSourceName, setFocusedSourceName] = useState<string | null>(null);
118+ // "new" = add source form, ToolSourceRecord = edit/view existing source, null = no source panel
119+ const [formSource, setFormSource] = useState<"new" | ToolSourceRecord | null>(null);
120+ const toolListRef = useRef<HTMLDivElement>(null);
121+ const toolListScrollContainerId = "tool-explorer-toollist-scroll";
128122 const resolvedActiveSource =
129123 activeSource === undefined ? internalActiveSource : activeSource;
130124
131− const handleSourceSelect = useCallback((source: string | null) => {
132− if (activeSource === undefined) {
133− setInternalActiveSource(source);
134− }
135−
136− onActiveSourceChange?.(source);
137− setExpandedKeys(expandedKeysForSource(source));
138− }, [activeSource, onActiveSourceChange]);
139−
140125 const hydratedTools = useMemo(() => {
141126 if (Object.keys(toolDetailsByPath).length === 0) {
142127 return tools;
@@ -179,20 +164,6 @@ export function ToolExplorer({ · 36 unmodified lines
179164 return set;
180165 }, [filteredTools.length, loading, loadingSources, resolvedActiveSource, searchInput.length, sourceLoadingMoreTools, sources]);
181166
182− const visibleLoadingSources = useMemo(() => {
183− if (loadingSourceSet.size === 0) {
184− return [] as string[];
185− }
186−
187− if (resolvedActiveSource) {
188− return loadingSourceSet.has(resolvedActiveSource)
189− ? [resolvedActiveSource]
190− : [];
191− }
192−
193− return Array.from(loadingSourceSet);
194− }, [loadingSourceSet, resolvedActiveSource]);
195−
196167 const sourceCounts = useMemo(() => {
197168 if (sourceCountsOverride) {
198169 return sourceCountsOverride;
@@ -223,25 +194,15 @@ export function ToolExplorer({ · 24 unmodified lines
223194 return filterToolsBySearch(filteredTools, search);
224195 }, [filteredTools, search]);
225196
226− const warningsBySource = useMemo(() => warningsBySourceName(warnings), [warnings]);
197+ const selectedToolCount = useMemo(() => {
198+ return countSelectedTools(selectedKeys, filteredTools);
199+ }, [selectedKeys, filteredTools]);
227200
228201 const sidebarExistingSourceNames = useMemo(() => {
229202 return existingSourceNames ?? new Set(visibleSources.map((source) => source.name));
230203 }, [existingSourceNames, visibleSources]);
231204
232− const treeGroups = useMemo(() => {
233− const showAllSources = search.length === 0;
234− return treeGroupsForView(searchedTools, viewMode, groupBy, {
235− loadingSources: visibleLoadingSources,
236− sourceRecords: showAllSources ? visibleSources : [],
237− sourceCounts: showAllSources ? sourceCounts : {},
238− activeSource: resolvedActiveSource,
239− });
240− }, [searchedTools, viewMode, groupBy, visibleLoadingSources, visibleSources, sourceCounts, resolvedActiveSource, search]);
241−
242− const flatTools = useMemo(() => {
243− return flatToolsForView(searchedTools, viewMode);
244− }, [searchedTools, viewMode]);
205+ const warningsBySrc = useMemo(() => warningsBySourceName(warnings), [warnings]);
245206
246207 const sourceByName = useMemo(() => {
247208 const map = new Map<string, ToolSourceRecord>();
@@ -251,75 +212,6 @@ export function ToolExplorer({ · 3 unmodified lines
251212 return map;
252213 }, [visibleSources]);
253214
254− const autoExpandedKeys = useMemo(() => {
255− return autoExpandedKeysForSearch(search, filteredTools, viewMode);
256− }, [search, filteredTools, viewMode]);
257−
258− const visibleExpandedKeys = autoExpandedKeys ?? expandedKeys;
259−
260− const loadedCountsBySource = useMemo(() => {
261− const counts: Record<string, number> = {};
262− for (const tool of hydratedTools) {
263− const name = sourceLabel(tool.source);
264− counts[name] = (counts[name] ?? 0) + 1;
265− }
266− return counts;
267− }, [hydratedTools]);
268−
269− const expandedSourceNames = useMemo(() => {
270− return Array.from(visibleExpandedKeys)
271− .map((key) => /^source:([^:]+)$/.exec(key)?.[1] ?? null)
272− .filter((name): name is string => Boolean(name));
273− }, [visibleExpandedKeys]);
274−
275− const sourceHasMoreByCount = useCallback((sourceName: string) => {
276− const total = sourceCounts[sourceName] ?? 0;
277− const loaded = loadedCountsBySource[sourceName] ?? 0;
278− return loaded < total;
279− }, [loadedCountsBySource, sourceCounts]);
280−
281− const nextExpandedSourceToLoad = useMemo(() => {
282− for (const sourceName of expandedSourceNames) {
283− const explicitHasMore = sourceHasMoreTools?.[sourceName];
284− const hasMore = explicitHasMore ?? sourceHasMoreByCount(sourceName);
285− if (hasMore) {
286− return sourceName;
287− }
288− }
289− return null;
290− }, [expandedSourceNames, sourceHasMoreByCount, sourceHasMoreTools]);
291−
292− const toggleExpand = useCallback((key: string) => {
293− const sourceGroupMatch = /^source:([^:]+)$/.exec(key);
294− const isSourceGroup = Boolean(sourceGroupMatch);
295− const sourceName = sourceGroupMatch?.[1] ?? null;
296− const willExpand = !expandedKeys.has(key);
297−
298− if (isSourceGroup && sourceName && willExpand && onLoadMoreToolsForSource) {
299− const sourceRecord = sourceByName.get(sourceName);
300− if (sourceRecord) {
301− const explicitHasMore = sourceHasMoreTools?.[sourceName];
302− const hasMore = explicitHasMore ?? sourceHasMoreByCount(sourceName);
303− if (hasMore) {
304− void onLoadMoreToolsForSource({
305− source: `${sourceRecord.type}:${sourceRecord.name}`,
306− sourceName: sourceRecord.name,
307− });
308− }
309− }
310− }
311−
312− setExpandedKeys((prev) => {
313− const next = new Set(prev);
314− if (next.has(key)) {
315− next.delete(key);
316− } else {
317− next.add(key);
318− }
319− return next;
320− });
321− }, [expandedKeys, onLoadMoreToolsForSource, sourceByName, sourceHasMoreByCount, sourceHasMoreTools]);
322−
323215 const toggleSelectTool = useCallback(
324216 (path: string, e: React.MouseEvent) => {
325217 e.stopPropagation();
@@ -337,30 +229,6 @@ export function ToolExplorer({ · 11 unmodified lines
337229 [],
338230 );
339231
340− const toggleSelectGroup = useCallback(
341− (key: string, e: React.MouseEvent) => {
342− e.stopPropagation();
343− e.preventDefault();
344− setSelectedKeys((prev) => {
345− const next = new Set(prev);
346− const childTools = findToolsInGroupByKey(treeGroups, key);
347− const allSelected =
348− childTools.length > 0 &&
349− childTools.every((t) => prev.has(t.path));
350−
351− if (allSelected) {
352− for (const t of childTools) next.delete(t.path);
353− next.delete(key);
354− } else {
355− for (const t of childTools) next.add(t.path);
356− next.add(key);
357− }
358− return next;
359− });
360− },
361− [treeGroups],
362− );
363−
364232 const clearSelection = useCallback(() => {
365233 setSelectedKeys(new Set());
366234 }, []);
@@ -369,21 +237,6 @@ export function ToolExplorer({ · 2 unmodified lines
369237 setSelectedKeys(new Set(filteredTools.map((t) => t.path)));
370238 }, [filteredTools]);
371239
372− const selectedToolCount = useMemo(() => {
373− return countSelectedTools(selectedKeys, filteredTools);
374− }, [selectedKeys, filteredTools]);
375−
376− const sourceOptions = useMemo(
377− () => {
378− const optionSet = new Set(sourceOptionsFromTools(hydratedTools, loadingSources));
379− for (const source of visibleSources) {
380− optionSet.add(source.name);
381− }
382− return Array.from(optionSet).sort((a, b) => a.localeCompare(b));
383− },
384− [hydratedTools, loadingSources, visibleSources],
385− );
386−
387240 const maybeLoadToolDetails = useCallback(async (tool: ToolDescriptor, expanded: boolean) => {
388241 if (!expanded || !onLoadToolDetails) {
389242 return;
@@ -420,117 +273,261 @@ export function ToolExplorer({ · 30 unmodified lines
420273 }
421274 }, [hasRenderableToolDetails, loadingDetailPaths, onLoadToolDetails, toolDetailsByPath]);
422275
423− const flatLoadingRows = useMemo(() => {
424− if (search.length > 0 || viewMode !== "flat") {
425− return [];
276+ // ── Focus tool handler ──────────────────────────────────────────────────
277+
278+ const handleFocusTool = useCallback((tool: ToolDescriptor) => {
279+ setFocusedToolPath(tool.path);
280+ setFocusedSourceName(null);
281+ setFormSource(null);
282+ void maybeLoadToolDetails(tool, true);
283+ }, [maybeLoadToolDetails]);
284+
285+ const handleSourceClick = useCallback((sourceName: string) => {
286+ const source = sourceByName.get(sourceName);
287+ setFocusedSourceName(sourceName);
288+ setFocusedToolPath(null);
289+ // Open the source form panel directly — no separate "view" mode
290+ setFormSource(source ?? null);
291+ // Ensure the source group is expanded
292+ setExpandedKeys((prev) => {
293+ const key = `source:${sourceName}`;
294+ if (prev.has(key)) return prev;
295+ const next = new Set(prev);
296+ next.add(key);
297+ return next;
298+ });
299+ }, [sourceByName]);
300+
301+ const handleAddSource = useCallback(() => {
302+ setFormSource("new");
303+ setFocusedToolPath(null);
304+ setFocusedSourceName(null);
305+ }, []);
306+
307+ const handleSourceFormClose = useCallback(() => {
308+ setFormSource(null);
309+ }, []);
310+
311+ const handleSourceFormAdded = useCallback((source: ToolSourceRecord) => {
312+ onSourceAdded?.(source);
313+ // After adding, show the new source in the form
314+ setFormSource(null);
315+ setFocusedSourceName(source.name);
316+ setFocusedToolPath(null);
317+ }, [onSourceAdded]);
318+
319+ const focusedTool = useMemo(() => {
320+ if (!focusedToolPath) return null;
321+ return hydratedTools.find((t) => t.path === focusedToolPath) ?? null;
322+ }, [focusedToolPath, hydratedTools]);
323+
324+ const focusedSource = useMemo(() => {
325+ if (!focusedSourceName) return null;
326+ return sourceByName.get(focusedSourceName) ?? null;
327+ }, [focusedSourceName, sourceByName]);
328+
329+ // Auto-focus first tool when tools arrive
330+ useEffect(() => {
331+ if (!focusedToolPath && searchedTools.length > 0) {
332+ const first = searchedTools[0];
333+ setFocusedToolPath(first.path);
334+ void maybeLoadToolDetails(first, true);
426335 }
336+ // eslint-disable-next-line react-hooks/exhaustive-deps
337+ }, [searchedTools.length > 0]);
427338
428− return visibleLoadingSources.map((source) => ({
429− source,
430− count: 3,
431− }));
432− }, [search, viewMode, visibleLoadingSources]);
433−
434− const hasFlatRows = flatTools.length > 0 || flatLoadingRows.length > 0;
435− const canInfiniteLoad = searchInput.length === 0
436− && (viewMode === "tree" && groupBy === "source"
437− ? nextExpandedSourceToLoad !== null
438− : hasMoreTools);
439− const activeSourceLoadingMore = nextExpandedSourceToLoad
440− ? (sourceLoadingMoreTools?.[nextExpandedSourceToLoad] ?? false)
441− : false;
339+ const loadingRows = useMemo(() => {
340+ if (search.length > 0) return [];
341+ const visibleLoadingSources = loadingSourceSet.size === 0
342+ ? []
343+ : resolvedActiveSource
344+ ? loadingSourceSet.has(resolvedActiveSource) ? [resolvedActiveSource] : []
345+ : Array.from(loadingSourceSet);
346+
347+ return visibleLoadingSources.map((source) => ({ source, count: 3 }));
348+ }, [search.length, loadingSourceSet, resolvedActiveSource]);
349+
350+ const canInfiniteLoad = searchInput.length === 0 && hasMoreTools;
442351 const awaitingInitialInventory =
443352 searchInput.length === 0
444353 && filteredTools.length === 0
445354 && (loading || loadingSources.length > 0);
446355
447− const handleExpandAll = useCallback(() => {
448− setExpandedKeys(collectGroupKeys(treeGroups));
356+ // ── Tree view data ──────────────────────────────────────────────────────
357+
358+ const treeGroups = useMemo(() => {
359+ return treeGroupsForView(searchedTools, "tree", "source", {
360+ loadingSources,
361+ sourceRecords: visibleSources,
362+ sourceCounts,
363+ activeSource: resolvedActiveSource,
364+ });
365+ }, [searchedTools, loadingSources, visibleSources, sourceCounts, resolvedActiveSource]);
366+
367+ const [expandedKeys, setExpandedKeys] = useState<Set<string>>(() => {
368+ // Start with all source-level groups expanded
369+ const keys = new Set<string>();
370+ for (const group of treeGroups) {
371+ keys.add(group.key);
372+ }
373+ return keys;
374+ });
375+
376+ // Auto-expand all groups when search is active
377+ const searchAutoExpanded = useMemo(
378+ () => autoExpandedKeysForSearch(search, searchedTools, "tree"),
379+ [search, searchedTools],
380+ );
381+
382+ const effectiveExpandedKeys = searchAutoExpanded ?? expandedKeys;
383+
384+ // When new source groups appear, auto-expand them
385+ useEffect(() => {
386+ const allKeys = collectGroupKeys(treeGroups);
387+ setExpandedKeys((prev) => {
388+ const next = new Set(prev);
389+ let changed = false;
390+ for (const key of allKeys) {
391+ if (key.startsWith("source:") && !key.includes(":ns:") && !next.has(key)) {
392+ next.add(key);
393+ changed = true;
394+ }
395+ }
396+ return changed ? next : prev;
397+ });
449398 }, [treeGroups]);
450399
451− const handleCollapseAll = useCallback(() => {
452− setExpandedKeys(new Set());
400+ const toggleExpand = useCallback((key: string) => {
401+ setExpandedKeys((prev) => {
402+ const next = new Set(prev);
403+ if (next.has(key)) {
404+ next.delete(key);
405+ } else {
406+ next.add(key);
407+ }
408+ return next;
409+ });
453410 }, []);
454411
455− const handleExplorerWheel = useCallback(
456− (e: React.WheelEvent<HTMLDivElement>) => {
457− const listEl = viewMode === "flat" ? flatListRef.current : treeListRef.current;
458− if (!listEl) return;
412+ const inventoryStatus = useMemo(() => {
413+ const loadingSourceCount = loadingSourceSet.size;
459414
460− const target = e.target as HTMLElement | null;
461− if (target && listEl.contains(target)) return;
462−
463− const atTop = listEl.scrollTop <= 0;
464− const atBottom =
465− listEl.scrollTop + listEl.clientHeight >= listEl.scrollHeight - 1;
415+ if (!inventoryState) {
416+ return { label: "Checking...", tone: "muted" as const };
417+ }
418+ if (inventoryState === "initializing") {
419+ const w = loadingSourceCount === 1 ? "source" : "sources";
420+ return {
421+ label: loadingSourceCount > 0 ? `Building (${loadingSourceCount} ${w})` : "Building...",
422+ tone: "loading" as const,
423+ };
424+ }
425+ if (inventoryState === "rebuilding") {
426+ const w = loadingSourceCount === 1 ? "source" : "sources";
427+ return {
428+ label: loadingSourceCount > 0 ? `Refreshing (${loadingSourceCount} ${w})` : "Refreshing...",
429+ tone: "loading" as const,
430+ };
431+ }
432+ if (inventoryState === "stale") {
433+ return { label: "Out of date", tone: "muted" as const };
434+ }
435+ if (inventoryState === "failed") {
436+ return {
437+ label: inventoryError ? `Failed: ${inventoryError}` : "Failed",
438+ tone: "error" as const,
439+ };
440+ }
441+ return { label: "Up to date", tone: "muted" as const };
442+ }, [inventoryError, inventoryState, loadingSourceSet.size]);
466443
467− if ((e.deltaY < 0 && atTop) || (e.deltaY > 0 && atBottom)) return;
444+ const regenerationInProgress = isRebuilding;
445+ const inventoryStale = inventoryState === "stale";
468446
469− listEl.scrollTop += e.deltaY;
470− e.preventDefault();
471− },
472− [viewMode],
473− );
447+ // ── Render ──────────────────────────────────────────────────────────────
474448
475449 return (
476− <div className="flex" onWheelCapture={handleExplorerWheel}>
477− {showSourceSidebar ? (
478− <SourceSidebar
479− sources={visibleSources}
480− sourceCounts={sourceCounts}
481− loadingSources={loadingSourceSet}
482− warningsBySource={warningsBySource}
483− activeSource={resolvedActiveSource}
484− onSelectSource={handleSourceSelect}
485− sourceDialogMeta={sourceDialogMeta}
486− sourceAuthProfiles={sourceAuthProfiles}
487− existingSourceNames={sidebarExistingSourceNames}
488− onSourceDeleted={onSourceDeleted}
489− onRegenerate={onRegenerate}
490− isRebuilding={isRebuilding}
491− inventoryState={inventoryState}
492− inventoryError={inventoryError}
493− />
494− ) : null}
495−
496− <div
497− className={cn(
498− "flex-1 min-w-0 flex flex-col",
499− showSourceSidebar ? "pl-2 lg:pl-3" : "pl-0",
500− )}
501− >
502− <ToolExplorerToolbar
503− search={searchInput}
504− filteredToolCount={filteredTools.length}
505− hasSearch={searchInput.length > 0}
506− resultCount={searchedTools.length}
507− loadingInventory={awaitingInitialInventory}
508− viewMode={viewMode}
509− groupBy={groupBy}
510− filterApproval={filterApproval}
511− showSourceSidebar={showSourceSidebar}
512− activeSource={resolvedActiveSource}
513− sourceOptions={sourceOptions}
514− addSourceAction={addSourceAction}
515− selectedToolCount={selectedToolCount}
516− onSearchChange={setSearchInput}
517− onClearSearch={() => setSearchInput("")}
518− onViewModeChange={setViewMode}
519− onGroupByChange={setGroupBy}
520− onFilterApprovalChange={setFilterApproval}
521− onSourceSelect={handleSourceSelect}
522− onSelectAll={selectAll}
523− onClearSelection={clearSelection}
524− onExpandAll={handleExpandAll}
525− onCollapseAll={handleCollapseAll}
526− />
527−
528− {viewMode === "flat" ? (
529− !hasFlatRows ? (
530− <div
531− ref={flatListRef}
532− className="max-h-[calc(100vh-320px)] overflow-y-auto rounded-md border border-border/30 bg-background/30"
533− >
450+ <div className="flex h-[calc(100vh-220px)]">
451+ {/* ── Left panel: search + tree ────────────────────────────────────── */}
452+ <div className="flex flex-col w-72 lg:w-80 xl:w-[22rem] shrink-0 border-r border-border/40">
453+ {/* Header: inventory status + regenerate */}
454+ <div className="shrink-0 px-3 pt-2 pb-1.5 border-b border-border/30">
455+ <div className="flex items-center justify-between">
456+ <div className="flex items-center gap-1.5">
457+ <p className="text-[10px] font-mono uppercase tracking-widest text-muted-foreground/50">
458+ Tools
459+ </p>
460+ <span
461+ className={cn(
462+ "text-[9px] font-mono flex items-center gap-0.5",
463+ inventoryStatus.tone === "loading"
464+ ? "text-terminal-amber/80"
465+ : inventoryStatus.tone === "error"
466+ ? "text-terminal-red/80"
467+ : "text-muted-foreground/40",
468+ )}
469+ title={inventoryStatus.label}
470+ >
471+ {inventoryStatus.tone === "loading" ? (
472+ <Loader2 className="h-2.5 w-2.5 animate-spin" />
473+ ) : inventoryStatus.tone === "error" ? (
474+ <AlertTriangle className="h-2.5 w-2.5" />
475+ ) : null}
476+ {inventoryStatus.label}
477+ </span>
478+ </div>
479+ <div className="flex items-center gap-0.5">
480+ {onRegenerate ? (
481+ <button
482+ onClick={onRegenerate}
483+ disabled={regenerationInProgress}
484+ title={
485+ regenerationInProgress
486+ ? "Rebuilding..."
487+ : inventoryStale
488+ ? "Out of date — click to refresh"
489+ : "Regenerate inventory"
490+ }
491+ className={cn(
492+ "p-0.5 rounded transition-colors",
493+ regenerationInProgress
494+ ? "text-terminal-amber cursor-not-allowed"
495+ : inventoryStale
496+ ? "text-muted-foreground/70 hover:text-muted-foreground"
497+ : "text-muted-foreground/30 hover:text-muted-foreground/60",
498+ )}
499+ >
500+ <RefreshCcw className={cn("h-3 w-3", regenerationInProgress && "animate-spin")} />
501+ </button>
502+ ) : null}
503+ </div>
504+ </div>
505+ </div>
506+
507+ {/* Search toolbar (own row) */}
508+ <div className="shrink-0 px-2 py-2 border-b border-border/20">
509+ <ToolExplorerToolbar
510+ search={searchInput}
511+ filteredToolCount={filteredTools.length}
512+ hasSearch={searchInput.length > 0}
513+ resultCount={searchedTools.length}
514+ loadingInventory={awaitingInitialInventory}
515+ filterApproval={filterApproval}
516+ activeSource={resolvedActiveSource}
517+ selectedToolCount={selectedToolCount}
518+ onSearchChange={setSearchInput}
519+ onClearSearch={() => setSearchInput("")}
520+ onFilterApprovalChange={setFilterApproval}
521+ onAddSource={handleAddSource}
522+ onSelectAll={selectAll}
523+ onClearSelection={clearSelection}
524+ />
525+ </div>
526+
527+ {/* Source-grouped tree */}
528+ <div className="flex-1 min-h-0">
529+ {searchedTools.length === 0 && loadingRows.length === 0 ? (
530+ <div className="h-full overflow-y-auto">
534531 {awaitingInitialInventory ? (
535532 <LoadingState />
536533 ) : (
@@ -538,89 +535,77 @@ export function ToolExplorer({ · 1 unmodified line
538535 )}
539536 </div>
540537 ) : (
541− <VirtualFlatList
542− tools={flatTools}
543− selectedKeys={selectedKeys}
544− onSelectTool={toggleSelectTool}
545− onExpandedChange={maybeLoadToolDetails}
546− detailLoadingPaths={loadingDetailPaths}
547− scrollContainerRef={flatListRef}
548− scrollContainerId={flatScrollContainerId}
549− loadingRows={flatLoadingRows}
550− hasMoreTools={canInfiniteLoad}
551− loadingMoreTools={loadingMoreTools}
552− onLoadMoreTools={onLoadMoreTools}
553− />
554− )
555− ) : (
556− <div
557− ref={treeListRef}
558− id={treeScrollContainerId}
559− className="max-h-[calc(100vh-320px)] overflow-y-auto rounded-md border border-border/30 bg-background/30"
560− >
561− {treeGroups.length === 0 ? (
562− awaitingInitialInventory ? (
563− <LoadingState />
564− ) : (
565− <EmptyState hasSearch={!!search} onClearSearch={() => setSearchInput("")} />
566− )
567− ) : (
568− <InfiniteScroll
569− dataLength={tools.length}
570− next={() => {
571− if (
572− searchInput.length === 0
573− && viewMode === "tree"
574− && groupBy === "source"
575− && onLoadMoreToolsForSource
576− ) {
577− if (!nextExpandedSourceToLoad) {
578− return;
579− }
580− const sourceRecord = sourceByName.get(nextExpandedSourceToLoad);
581− if (sourceRecord) {
582− void onLoadMoreToolsForSource({
583− source: `${sourceRecord.type}:${sourceRecord.name}`,
584− sourceName: sourceRecord.name,
585− });
586− return;
587− }
588− }
589−
590− void onLoadMoreTools?.();
591− }}
592− hasMore={canInfiniteLoad}
593− scrollableTarget={treeScrollContainerId}
594− style={{ overflow: "visible" }}
595− loader={
596− <div className="px-2 py-2 text-[11px] text-muted-foreground">
597− {(loadingMoreTools || activeSourceLoadingMore)
598− ? `Loading more tools${totalTools ? ` (${tools.length} / ${totalTools})` : ""}...`
599− : ""}
600− </div>
601− }
538+ <div
539+ ref={toolListRef}
540+ id={toolListScrollContainerId}
541+ className="h-full overflow-y-auto"
542+ >
543+ <InfiniteScroll
544+ dataLength={searchedTools.length}
545+ next={() => {
546+ void onLoadMoreTools?.();
547+ }}
548+ hasMore={canInfiniteLoad}
549+ scrollableTarget={toolListScrollContainerId}
550+ style={{ overflow: "visible" }}
551+ loader={
552+ <div className="px-2 py-2 text-[10px] text-muted-foreground/60">
553+ {loadingMoreTools ? "Loading..." : ""}
554+ </div>
555+ }
602556 >
603− <div className="p-1">
557+ <div className="py-0.5">
604558 {treeGroups.map((group) => (
605− <GroupNode
559+ <NavGroupNode
606560 key={group.key}
607561 group={group}
608562 depth={0}
609− expandedKeys={visibleExpandedKeys}
563+ expandedKeys={effectiveExpandedKeys}
610564 onToggle={toggleExpand}
565+ focusedPath={focusedToolPath}
566+ focusedSource={focusedSourceName}
611567 selectedKeys={selectedKeys}
612− onSelectGroup={toggleSelectGroup}
568+ onFocusTool={handleFocusTool}
613569 onSelectTool={toggleSelectTool}
614− onExpandedChange={maybeLoadToolDetails}
615− detailLoadingPaths={loadingDetailPaths}
616− source={group.type === "source" ? sourceByName.get(group.label) : undefined}
617− search={search}
570+ onSourceClick={handleSourceClick}
571+ source={sourceByName.get(group.label) ?? undefined}
572+ />
573+ ))}
574+
575+ {loadingRows.map((loadingRow) => (
576+ <ToolLoadingRows
577+ key={loadingRow.source}
578+ source={loadingRow.source}
579+ count={loadingRow.count}
580+ depth={0}
618581 />
619582 ))}
620583 </div>
621584 </InfiniteScroll>
622− )}
623− </div>
585+ </div>
586+ )}
587+ </div>
588+ </div>
589+
590+ {/* ── Detail panel (right, main content) ─────────────────────────────── */}
591+ <div className="flex-1 min-w-0 bg-background/50">
592+ {formSource !== null ? (
593+ <SourceFormPanel
594+ existingSourceNames={sidebarExistingSourceNames}
595+ sourceToEdit={formSource === "new" ? undefined : formSource}
596+ sourceDialogMeta={formSource !== "new" ? sourceDialogMeta?.[formSource.name] : undefined}
597+ sourceAuthProfiles={sourceAuthProfiles}
598+ onSourceAdded={handleSourceFormAdded}
599+ onSourceDeleted={onSourceDeleted}
600+ onClose={handleSourceFormClose}
601+ />
602+ ) : focusedTool ? (
603+ <ToolDetailPanel
604+ tool={focusedTool}
605+ loading={loadingDetailPaths.has(focusedTool.path)}
606+ />
607+ ) : (
608+ <ToolDetailEmpty />
624609 )}
625610 </div>
626611 </div>
executor/apps/web/src/components/tools/explorer/source-form-panel.tsx+507−0
@@ -0,0 +1,507 @@
1+"use client";
2+
3+import { useState } from "react";
4+import { useAction, useMutation, useQuery } from "convex/react";
5+import { Result } from "better-result";
6+import { toast } from "sonner";
7+import {
8+ AlertTriangle,
9+ ArrowLeft,
10+ Loader2,
11+ Trash2,
12+} from "lucide-react";
13+import { Badge } from "@/components/ui/badge";
14+import { Button } from "@/components/ui/button";
15+import type {
16+ CredentialRecord,
17+ SourceAuthProfile,
18+ ToolSourceRecord,
19+} from "@/lib/types";
20+import type { SourceDialogMeta } from "../add/source-dialog";
21+import { SourceFavicon } from "../source-favicon";
22+import { displaySourceName } from "@/lib/tool/source-utils";
23+import {
24+ compactEndpointLabel,
25+ formatSourceAuthBadge,
26+ sourceAuthProfileForSource,
27+} from "@/lib/tools/source-helpers";
28+import { SourceQualitySummary } from "../source/quality-details";
29+import { useSession } from "@/lib/session-context";
30+import { convexApi } from "@/lib/convex-api";
31+import { normalizeSourceEndpoint } from "@/lib/tools/source-url";
32+import { createCustomSourceConfig } from "../add/source/dialog-helpers";
33+import {
34+ CatalogViewSection,
35+ CustomViewSection,
36+} from "../add/source/dialog-sections";
37+import { SourceAuthPanel } from "../add/source/auth-panel";
38+import { saveSourceWithCredentials } from "../add/source-submit";
39+import {
40+ useAddSourceFormState,
41+} from "../use/add/source/form-state";
42+import { startMcpOAuthPopup } from "@/lib/mcp/oauth-popup";
43+import { workspaceQueryArgs } from "@/lib/workspace/query-args";
44+
45+// ── Helpers ─────────────────────────────────────────────────────────────────
46+
47+function resultErrorMessage(error: unknown, fallback: string): string {
48+ const cause = typeof error === "object" && error && "cause" in error
49+ ? (error as { cause?: unknown }).cause
50+ : error;
51+ if (cause instanceof Error && cause.message.trim()) {
52+ return cause.message;
53+ }
54+ if (typeof cause === "string" && cause.trim()) {
55+ return cause;
56+ }
57+ return fallback;
58+}
59+
60+function ownerScopeBadge(scopeType: ToolSourceRecord["scopeType"] | undefined): string {
61+ return scopeType === "organization" ? "org shared" : "workspace only";
62+}
63+
64+// ── Main Panel ──────────────────────────────────────────────────────────────
65+
66+export function SourceFormPanel({
67+ existingSourceNames,
68+ sourceToEdit,
69+ sourceDialogMeta,
70+ sourceAuthProfiles,
71+ onSourceAdded,
72+ onSourceDeleted,
73+ onClose,
74+}: {
75+ existingSourceNames: Set<string>;
76+ sourceToEdit?: ToolSourceRecord;
77+ sourceDialogMeta?: SourceDialogMeta;
78+ sourceAuthProfiles?: Record<string, SourceAuthProfile>;
79+ onSourceAdded?: (source: ToolSourceRecord, options?: { connected?: boolean }) => void;
80+ onSourceDeleted?: (sourceName: string) => void;
81+ onClose: () => void;
82+}) {
83+ const { context } = useSession();
84+ const upsertToolSource = useMutation(convexApi.workspace.upsertToolSource);
85+ const deleteToolSource = useMutation(convexApi.workspace.deleteToolSource);
86+ const upsertCredential = useAction(convexApi.credentialsNode.upsertCredential);
87+ const previewOpenApiSourceUpgrade = useAction(convexApi.executorNode.previewOpenApiSourceUpgrade);
88+ const credentials = useQuery(
89+ convexApi.workspace.listCredentials,
90+ workspaceQueryArgs(context),
91+ );
92+ const credentialItems = (credentials ?? []) as CredentialRecord[];
93+ const credentialsLoading = Boolean(context) && credentials === undefined;
94+ const [submitting, setSubmitting] = useState(false);
95+ const [mcpOAuthBusy, setMcpOAuthBusy] = useState(false);
96+ const [deleting, setDeleting] = useState(false);
97+
98+ const editing = Boolean(sourceToEdit);
99+
100+ // Edit-mode metadata
101+ const editSourceMeta = sourceToEdit ? sourceDialogMeta : undefined;
102+ const editSourceWarnings = editSourceMeta?.warnings ?? [];
103+ const editSourceQuality = editSourceMeta?.quality;
104+ const editSourceQualityLoading = Boolean(editSourceMeta?.qualityLoading);
105+ const editAuthProfile = sourceToEdit && sourceAuthProfiles
106+ ? sourceAuthProfileForSource(sourceToEdit, sourceAuthProfiles)
107+ : undefined;
108+ const editAuthBadge = sourceToEdit ? formatSourceAuthBadge(sourceToEdit, editAuthProfile) : null;
109+
110+ // Form state — `open` is always true for the inline panel
111+ const form = useAddSourceFormState({
112+ open: true,
113+ sourceToEdit,
114+ existingSourceNames,
115+ credentialItems,
116+ accountId: context?.accountId,
117+ });
118+
119+ const handleCatalogAdd = (item: { specUrl: string } & Parameters<typeof form.handleCatalogAdd>[0]) => {
120+ if (!item.specUrl.trim()) {
121+ toast.error("Missing endpoint URL for this source");
122+ return;
123+ }
124+ form.handleCatalogAdd(item);
125+ };
126+
127+ const handleCustomSubmit = async () => {
128+ if (!context || !form.name.trim() || !form.endpoint.trim()) {
129+ return;
130+ }
131+
132+ if (sourceToEdit?.type === "openapi" && form.type === "openapi") {
133+ const previewConfig = createCustomSourceConfig({
134+ type: form.type,
135+ endpoint: form.endpoint.trim(),
136+ baseUrl: form.baseUrl,
137+ auth: form.buildAuthConfig(),
138+ mcpTransport: form.mcpTransport,
139+ accountId: context.accountId,
140+ });
141+
142+ const previewResult = await Result.tryPromise(() =>
143+ previewOpenApiSourceUpgrade({
144+ workspaceId: context.workspaceId,
145+ sessionId: context.sessionId,
146+ sourceId: sourceToEdit.id,
147+ name: form.name.trim(),
148+ config: previewConfig,
149+ }),
150+ );
151+
152+ if (!previewResult.isOk()) {
153+ toast.error(resultErrorMessage(previewResult.error, "Failed to preview OpenAPI changes"));
154+ return;
155+ }
156+
157+ const preview = previewResult.value;
158+ if (preview.hasChanges) {
159+ const sample = (items: string[]) => items.slice(0, 8).join("\n- ");
160+ const added = sample(preview.addedPaths);
161+ const removed = sample(preview.removedPaths);
162+ const changed = sample(preview.changedPaths);
163+
164+ const message = [
165+ `OpenAPI upgrade for \"${preview.currentSourceName}\"`,
166+ "",
167+ `Added: ${preview.addedCount}`,
168+ `Removed: ${preview.removedCount}`,
169+ `Changed: ${preview.changedCount}`,
170+ "",
171+ added ? `Added sample:\n- ${added}` : "",
172+ removed ? `Removed sample:\n- ${removed}` : "",
173+ changed ? `Changed sample:\n- ${changed}` : "",
174+ preview.truncated ? "\n(Preview truncated)" : "",
175+ "",
176+ "Apply this upgrade now?",
177+ ]
178+ .filter((line) => line.length > 0)
179+ .join("\n");
180+
181+ const approved = window.confirm(message);
182+ if (!approved) {
183+ toast.message("Upgrade cancelled");
184+ return;
185+ }
186+ }
187+ }
188+
189+ if (form.isNameTaken(form.name)) {
190+ toast.error(`Source name "${form.name.trim()}" already exists`);
191+ return;
192+ }
193+
194+ if (form.type === "openapi" && form.specStatus !== "ready") {
195+ if (form.specStatus === "detecting") {
196+ toast.error("Spec fetch is still in progress");
197+ return;
198+ }
199+ toast.error(form.specError || "OpenAPI spec is invalid or could not be fetched");
200+ return;
201+ }
202+
203+ setSubmitting(true);
204+ const saveResult = await Result.tryPromise(() =>
205+ saveSourceWithCredentials({
206+ context,
207+ sourceToEdit,
208+ credentialsLoading,
209+ upsertToolSource,
210+ upsertCredential,
211+ form: {
212+ name: form.name,
213+ endpoint: form.endpoint,
214+ type: form.type,
215+ scopeType: form.scopeType,
216+ baseUrl: form.baseUrl,
217+ mcpTransport: form.mcpTransport,
218+ authType: form.authType,
219+ authScope: form.authScope,
220+ apiKeyHeader: form.apiKeyHeader,
221+ existingScopedCredential: form.existingScopedCredential,
222+ buildAuthConfig: form.buildAuthConfig,
223+ hasCredentialInput: form.hasCredentialInput,
224+ buildSecretJson: form.buildSecretJson,
225+ },
226+ }),
227+ );
228+ setSubmitting(false);
229+
230+ if (!saveResult.isOk()) {
231+ toast.error(resultErrorMessage(
232+ saveResult.error,
233+ sourceToEdit ? "Failed to update source" : "Failed to add source",
234+ ));
235+ return;
236+ }
237+
238+ const result = saveResult.value;
239+ const needsCredentials = form.authType !== "none" && !result.connected;
240+ onSourceAdded?.(result.source, { connected: result.connected });
241+ if (needsCredentials) {
242+ toast.warning(
243+ sourceToEdit
244+ ? `Source "${form.name.trim()}" updated — credentials still needed`
245+ : `Source "${form.name.trim()}" added without credentials — edit to add them`,
246+ );
247+ } else {
248+ toast.success(
249+ sourceToEdit
250+ ? result.connected
251+ ? `Source "${form.name.trim()}" updated with credentials`
252+ : `Source "${form.name.trim()}" updated`
253+ : result.connected
254+ ? `Source "${form.name.trim()}" added with credentials — loading tools…`
255+ : `Source "${form.name.trim()}" added — loading tools…`,
256+ );
257+ }
258+ if (!sourceToEdit) {
259+ form.reserveSourceName(form.name.trim());
260+ }
261+ onClose();
262+ };
263+
264+ const handleMcpOAuthConnect = async () => {
265+ if (form.type !== "mcp") return;
266+ const endpoint = form.endpoint.trim();
267+ if (!endpoint) {
268+ toast.error("Enter an MCP endpoint URL first");
269+ return;
270+ }
271+ const initiatedEndpoint = normalizeSourceEndpoint(endpoint);
272+
273+ setMcpOAuthBusy(true);
274+ const oauthResult = await Result.tryPromise(() => startMcpOAuthPopup(endpoint));
275+ setMcpOAuthBusy(false);
276+
277+ if (!oauthResult.isOk()) {
278+ toast.error(resultErrorMessage(oauthResult.error, "Failed to connect OAuth"));
279+ return;
280+ }
281+
282+ const returnedEndpoint = normalizeSourceEndpoint(oauthResult.value.sourceUrl);
283+ if (returnedEndpoint && initiatedEndpoint && returnedEndpoint !== initiatedEndpoint) {
284+ toast.error("OAuth finished for a different endpoint. Try again.");
285+ return;
286+ }
287+
288+ const currentEndpoint = normalizeSourceEndpoint(form.endpoint);
289+ if (currentEndpoint !== initiatedEndpoint) {
290+ toast.error("Endpoint changed while OAuth was running. Please reconnect OAuth.");
291+ return;
292+ }
293+
294+ if (form.authType !== "bearer") {
295+ form.handleAuthTypeChange("bearer");
296+ }
297+ form.handleAuthFieldChange("tokenValue", oauthResult.value.accessToken);
298+ form.markMcpOAuthLinked(initiatedEndpoint);
299+ toast.success("OAuth linked successfully.");
300+ };
301+
302+ const handleDeleteSource = async () => {
303+ if (!sourceToEdit || !context) return;
304+ const scopeLabel = sourceToEdit.scopeType === "organization"
305+ ? "your organization"
306+ : "this workspace";
307+ const confirmed = window.confirm(
308+ `Remove source "${sourceToEdit.name}" and all related tools from ${scopeLabel}?`,
309+ );
310+ if (!confirmed) return;
311+
312+ setDeleting(true);
313+ try {
314+ await deleteToolSource({
315+ workspaceId: context.workspaceId,
316+ sessionId: context.sessionId,
317+ sourceId: sourceToEdit.id,
318+ });
319+ toast.success(`Removed "${sourceToEdit.name}"`);
320+ onSourceDeleted?.(sourceToEdit.name);
321+ onClose();
322+ } catch (err) {
323+ toast.error(err instanceof Error ? err.message : "Failed to remove source");
324+ } finally {
325+ setDeleting(false);
326+ }
327+ };
328+
329+ const submitLabel = editing ? "Save Source" : "Add Source";
330+ const sourceInfoLoading =
331+ (form.type === "openapi" && form.specStatus === "detecting")
332+ || (form.type === "mcp" && form.mcpOAuthStatus === "checking");
333+
334+ // ── Render ──────────────────────────────────────────────────────────────
335+
336+ return (
337+ <div className="h-full flex flex-col">
338+ {/* ── Sticky header ────────────────────────────────────────────── */}
339+ <div className="sticky top-0 z-10 bg-background/95 backdrop-blur-sm border-b border-border/40 px-5 py-3">
340+ <div className="flex items-center gap-3 min-w-0">
341+ <button
342+ onClick={onClose}
343+ className="h-7 w-7 rounded-md flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-accent/40 transition-colors shrink-0"
344+ >
345+ <ArrowLeft className="h-3.5 w-3.5" />
346+ </button>
347+ <div className="min-w-0 flex-1">
348+ <h2 className="text-[14px] font-mono font-semibold text-foreground">
349+ {editing ? "Edit source" : "Add source"}
350+ </h2>
351+ <p className="text-[10px] text-muted-foreground/60 mt-0.5">
352+ {editing
353+ ? "Update endpoint, auth, and credentials."
354+ : "Connect a source and configure credentials."}
355+ </p>
356+ </div>
357+ </div>
358+ </div>
359+
360+ {/* ── Scrollable body ──────────────────────────────────────────── */}
361+ <div className="flex-1 min-h-0 overflow-y-auto flex flex-col">
362+ <div className="px-5 py-5 flex flex-col gap-5 flex-1 min-h-0">
363+
364+ {/* Edit mode: source summary card */}
365+ {sourceToEdit ? (
366+ <div className="rounded-lg border border-border/60 bg-muted/10 p-4 space-y-3">
367+ <div className="flex items-start gap-3">
368+ <SourceFavicon
369+ source={sourceToEdit}
370+ iconClassName="h-5 w-5 text-muted-foreground"
371+ imageClassName="w-7 h-7"
372+ />
373+ <div className="min-w-0 flex-1">
374+ <p className="text-[13px] font-medium truncate">
375+ {displaySourceName(sourceToEdit.name)}
376+ </p>
377+ <p className="text-[10px] text-muted-foreground truncate mt-0.5">
378+ {compactEndpointLabel(sourceToEdit)}
379+ </p>
380+ <div className="mt-2 flex items-center gap-1.5 flex-wrap">
381+ <Badge variant="outline" className="h-5 px-2 text-[9px] uppercase tracking-wide">
382+ {sourceToEdit.type}
383+ </Badge>
384+ <Badge variant="outline" className="h-5 px-2 text-[9px] uppercase tracking-wide">
385+ {ownerScopeBadge(sourceToEdit.scopeType)}
386+ </Badge>
387+ {editAuthBadge ? (
388+ <Badge
389+ variant="outline"
390+ className="h-5 px-2 text-[9px] uppercase tracking-wide text-primary border-primary/30"
391+ >
392+ {editAuthBadge}
393+ </Badge>
394+ ) : null}
395+ {sourceToEdit.type === "openapi" && editSourceQuality ? (
396+ <SourceQualitySummary quality={editSourceQuality} qualityLoading={editSourceQualityLoading} />
397+ ) : null}
398+ </div>
399+ </div>
400+ </div>
401+
402+ {editSourceWarnings.length > 0 ? (
403+ <div className="rounded-md border border-terminal-amber/20 bg-terminal-amber/5 px-3 py-2 space-y-0.5">
404+ {editSourceWarnings.map((warning, i) => (
405+ <p key={i} className="text-[10px] text-terminal-amber/90 flex items-start gap-1.5">
406+ <AlertTriangle className="h-2.5 w-2.5 mt-0.5 shrink-0" />
407+ {warning}
408+ </p>
409+ ))}
410+ </div>
411+ ) : null}
412+ </div>
413+ ) : null}
414+
415+ {/* Form content — catalog or custom */}
416+ {form.view === "catalog" && !sourceToEdit ? (
417+ <CatalogViewSection
418+ catalogQuery={form.catalogQuery}
419+ onCatalogQueryChange={form.setCatalogQuery}
420+ catalogSort={form.catalogSort}
421+ onCatalogSortChange={form.setCatalogSort}
422+ visibleCatalogItems={form.visibleCatalogItems}
423+ onSwitchToCustom={() => form.setView("custom")}
424+ onAddCatalog={handleCatalogAdd}
425+ />
426+ ) : (
427+ <CustomViewSection
428+ type={form.type}
429+ onTypeChange={form.handleTypeChange}
430+ typeDisabled={form.editing}
431+ typeDetectionStatus={form.typeDetectionStatus}
432+ typeExplicitlySet={form.typeExplicitlySet}
433+ endpoint={form.endpoint}
434+ onEndpointChange={form.handleEndpointChange}
435+ name={form.name}
436+ onNameChange={form.handleNameChange}
437+ baseUrl={form.baseUrl}
438+ baseUrlOptions={form.openApiBaseUrlOptions}
439+ onBaseUrlChange={form.setBaseUrl}
440+ mcpTransport={form.mcpTransport}
441+ onMcpTransportChange={form.setMcpTransport}
442+ submitting={submitting}
443+ submittingLabel={editing ? "Saving..." : "Adding..."}
444+ submitDisabled={
445+ submitting
446+ || !form.name.trim()
447+ || !form.endpoint.trim()
448+ || (form.type === "openapi" && form.specStatus !== "ready")
449+ }
450+ submitLabel={submitLabel}
451+ showBackToCatalog={!form.editing}
452+ onBackToCatalog={!form.editing ? () => form.setView("catalog") : undefined}
453+ onSubmit={handleCustomSubmit}
454+ sourceInfoLoading={sourceInfoLoading}
455+ >
456+ <SourceAuthPanel
457+ model={{
458+ sourceType: form.type,
459+ specStatus: form.specStatus,
460+ inferredSpecAuth: form.inferredSpecAuth,
461+ specError: form.specError,
462+ mcpOAuthStatus: form.mcpOAuthStatus,
463+ mcpOAuthDetail: form.mcpOAuthDetail,
464+ mcpOAuthAuthorizationServers: form.mcpOAuthAuthorizationServers,
465+ mcpOAuthConnected: form.mcpOAuthConnected,
466+ authType: form.authType,
467+ scopeType: form.scopeType,
468+ authScope: form.authScope,
469+ apiKeyHeader: form.apiKeyHeader,
470+ tokenValue: form.tokenValue,
471+ apiKeyValue: form.apiKeyValue,
472+ basicUsername: form.basicUsername,
473+ basicPassword: form.basicPassword,
474+ hasExistingCredential: Boolean(form.existingScopedCredential),
475+ }}
476+ onAuthTypeChange={form.handleAuthTypeChange}
477+ onScopeChange={form.handleScopePresetChange}
478+ onFieldChange={form.handleAuthFieldChange}
479+ onMcpOAuthConnect={form.type === "mcp" ? handleMcpOAuthConnect : undefined}
480+ onOpenApiSpecRetry={form.type === "openapi" ? form.retryOpenApiSpec : undefined}
481+ openApiSpecRetrying={form.type === "openapi" && form.specStatus === "detecting"}
482+ mcpOAuthBusy={mcpOAuthBusy}
483+ sourceInfoLoading={sourceInfoLoading}
484+ />
485+ </CustomViewSection>
486+ )}
487+
488+ {/* Delete action for edit mode */}
489+ {sourceToEdit ? (
490+ <div className="pt-3 border-t border-border/30">
491+ <Button
492+ variant="outline"
493+ size="sm"
494+ className="h-8 text-[11px] border-terminal-red/30 text-terminal-red hover:bg-terminal-red/10 gap-1.5"
495+ onClick={handleDeleteSource}
496+ disabled={deleting}
497+ >
498+ <Trash2 className="h-3 w-3" />
499+ {deleting ? "Removing..." : "Remove source"}
500+ </Button>
501+ </div>
502+ ) : null}
503+ </div>
504+ </div>
505+ </div>
506+ );
507+}
executor/apps/web/src/components/tools/explorer/tool-detail.tsx+344−171
@@ -3,22 +3,19 @@ · 2 unmodified lines
33 import { useMemo } from "react";
44 import { Streamdown } from "streamdown";
55 import { createCodePlugin } from "@streamdown/code";
6+import { ShieldCheck, Zap } from "lucide-react";
67 import type { ToolDescriptor } from "@/lib/types";
78 import { Skeleton } from "@/components/ui/skeleton";
9+import { cn } from "@/lib/utils";
10+import { traverseSchema, type SchemaFieldEntry } from "@/lib/tool/schema-traverse";
811 import { TypeSignature } from "./type-signature";
12+import { CopyButton } from "./copy-button";
913
1014 const codePlugin = createCodePlugin({
1115 themes: ["github-light", "github-dark"],
1216 });
1317
14−type FieldDocEntry = {
15− path: string;
16− required?: boolean;
17− description?: string;
18− example?: string;
19− defaultValue?: string;
20− deprecated?: boolean;
21−};
18+// ── Helpers ──────────────────────────────────────────────────────────────────
2219
2320 function asRecord(value: unknown): Record<string, unknown> {
2421 return value && typeof value === "object" && !Array.isArray(value)
@@ -26,22 +23,6 @@ function asRecord(value: unknown): Record<string, unknown> { · 1 unmodified line
2623 : {};
2724 }
2825
29−function toPreviewValue(value: unknown): string | undefined {
30− if (value === undefined) return undefined;
31− if (typeof value === "string") {
32− const trimmed = value.trim();
33− if (!trimmed) return undefined;
34− return trimmed.length > 96 ? `${trimmed.slice(0, 96)}...` : trimmed;
35− }
36− try {
37− const serialized = JSON.stringify(value);
38− if (!serialized) return undefined;
39− return serialized.length > 96 ? `${serialized.slice(0, 96)}...` : serialized;
40− } catch {
41− return undefined;
42− }
43−}
44−
4526 function parseSchemaJson(value: string): Record<string, unknown> {
4627 if (!value) return {};
4728 try {
@@ -52,111 +33,248 @@ function parseSchemaJson(value: string): Record<string, unknown> { · 4 unmodified lines
5233 }
5334 }
5435
55−function collectSchemaFieldDocs(schema: Record<string, unknown>, options: { maxEntries?: number; maxDepth?: number } = {}): {
56− entries: FieldDocEntry[];
57− truncated: boolean;
58−} {
59− const maxEntries = options.maxEntries ?? 28;
60− const maxDepth = options.maxDepth ?? 4;
61− const entries: FieldDocEntry[] = [];
62− let truncated = false;
63−
64− const pushEntry = (entry: FieldDocEntry) => {
65− if (entries.length >= maxEntries) {
66− truncated = true;
67− return;
68− }
69− entries.push(entry);
70− };
71−
72− const walk = (node: unknown, prefix: string, depth: number) => {
73− if (depth > maxDepth || truncated) return;
74− const shape = asRecord(node);
75− const required = new Set(
76− Array.isArray(shape.required)
77− ? shape.required.filter((value): value is string => typeof value === "string")
78− : [],
79− );
80−
81− const properties = asRecord(shape.properties);
82− for (const [rawKey, child] of Object.entries(properties)) {
83− if (truncated) break;
84− const key = rawKey.trim();
85− if (!key) continue;
86− const childShape = asRecord(child);
87− const path = prefix ? `${prefix}.${key}` : key;
88− const description = typeof childShape.description === "string"
89− ? childShape.description.trim()
90− : "";
91− const example = toPreviewValue(childShape.example);
92− const defaultValue = toPreviewValue(childShape.default);
93− const deprecated = childShape.deprecated === true;
94− const isRequired = required.has(key);
95−
96− if (description || example || defaultValue || deprecated || isRequired) {
97− pushEntry({
98− path,
99− ...(isRequired ? { required: true } : {}),
100− ...(description ? { description } : {}),
101− ...(example ? { example } : {}),
102− ...(defaultValue ? { defaultValue } : {}),
103− ...(deprecated ? { deprecated: true } : {}),
104− });
105− }
36+// ── Type color mapping ──────────────────────────────────────────────────────
37+
38+function typeColorClasses(type: string): string {
39+ switch (type) {
40+ case "string":
41+ return "text-[oklch(0.45_0.14_155)] bg-[oklch(0.45_0.14_155_/_0.07)] border-[oklch(0.45_0.14_155_/_0.15)] dark:text-[oklch(0.75_0.14_155)] dark:bg-[oklch(0.75_0.14_155_/_0.1)] dark:border-[oklch(0.75_0.14_155_/_0.2)]";
42+ case "number":
43+ case "integer":
44+ return "text-[oklch(0.50_0.16_260)] bg-[oklch(0.50_0.16_260_/_0.07)] border-[oklch(0.50_0.16_260_/_0.15)] dark:text-[oklch(0.75_0.14_260)] dark:bg-[oklch(0.75_0.14_260_/_0.1)] dark:border-[oklch(0.75_0.14_260_/_0.2)]";
45+ case "boolean":
46+ return "text-[oklch(0.55_0.18_300)] bg-[oklch(0.55_0.18_300_/_0.07)] border-[oklch(0.55_0.18_300_/_0.15)] dark:text-[oklch(0.78_0.14_300)] dark:bg-[oklch(0.78_0.14_300_/_0.1)] dark:border-[oklch(0.78_0.14_300_/_0.2)]";
47+ case "array":
48+ return "text-[oklch(0.50_0.14_200)] bg-[oklch(0.50_0.14_200_/_0.07)] border-[oklch(0.50_0.14_200_/_0.15)] dark:text-[oklch(0.75_0.12_200)] dark:bg-[oklch(0.75_0.12_200_/_0.1)] dark:border-[oklch(0.75_0.12_200_/_0.2)]";
49+ case "object":
50+ return "text-[oklch(0.55_0.12_75)] bg-[oklch(0.55_0.12_75_/_0.07)] border-[oklch(0.55_0.12_75_/_0.15)] dark:text-[oklch(0.78_0.1_75)] dark:bg-[oklch(0.78_0.1_75_/_0.1)] dark:border-[oklch(0.78_0.1_75_/_0.2)]";
51+ case "enum":
52+ case "union":
53+ return "text-[oklch(0.50_0.16_30)] bg-[oklch(0.50_0.16_30_/_0.07)] border-[oklch(0.50_0.16_30_/_0.15)] dark:text-[oklch(0.75_0.14_30)] dark:bg-[oklch(0.75_0.14_30_/_0.1)] dark:border-[oklch(0.75_0.14_30_/_0.2)]";
54+ case "null":
55+ return "text-muted-foreground/70";
56+ default:
57+ return "text-muted-foreground/50";
58+ }
59+}
60+
61+// ── Constraint badges ───────────────────────────────────────────────────────
62+
63+function ConstraintBadges({ entry }: { entry: SchemaFieldEntry }) {
64+ const parts: string[] = [];
65+
66+ if (entry.constraints) {
67+ const c = entry.constraints;
68+ if (c.minimum !== undefined) parts.push(`>= ${c.minimum}`);
69+ if (c.maximum !== undefined) parts.push(`<= ${c.maximum}`);
70+ if (c.exclusiveMinimum !== undefined) parts.push(`> ${c.exclusiveMinimum}`);
71+ if (c.exclusiveMaximum !== undefined) parts.push(`< ${c.exclusiveMaximum}`);
72+ if (c.minLength !== undefined) parts.push(`minLen: ${c.minLength}`);
73+ if (c.maxLength !== undefined) parts.push(`maxLen: ${c.maxLength}`);
74+ if (c.pattern) parts.push(`/${c.pattern}/`);
75+ if (c.minItems !== undefined) parts.push(`minItems: ${c.minItems}`);
76+ if (c.maxItems !== undefined) parts.push(`maxItems: ${c.maxItems}`);
77+ if (c.uniqueItems) parts.push("unique");
78+ }
79+
80+ if (entry.format && !entry.typeLabel.includes(entry.format)) {
81+ parts.push(entry.format);
82+ }
83+
84+ if (parts.length === 0) return null;
85+
86+ return (
87+ <span className="inline-flex items-center gap-1 ml-0.5">
88+ {parts.map((p, i) => (
89+ <span key={i} className="font-mono text-[9px] text-muted-foreground/65 bg-muted rounded-sm px-1 leading-[1.4]">
90+ {p}
91+ </span>
92+ ))}
93+ </span>
94+ );
95+}
96+
97+// ── Field row ───────────────────────────────────────────────────────────────
98+
99+function FieldRow({ entry }: { entry: SchemaFieldEntry }) {
100+ return (
101+ <div
102+ className="flex flex-col gap-1 py-2.5 pr-3.5 border-b border-border/50 last:border-b-0"
103+ style={{ paddingLeft: `${entry.depth * 16 + 14}px` }}
104+ >
105+ {/* Name + type line */}
106+ <div className="flex items-center gap-1.5 flex-wrap">
107+ <span className="font-mono text-[11px] font-semibold text-foreground leading-tight">
108+ {entry.path.split(".").pop()}
109+ </span>
110+
111+ {entry.required ? (
112+ <span
113+ className="w-1 h-1 rounded-full bg-[oklch(0.65_0.22_25)] dark:bg-[oklch(0.72_0.2_25)] shrink-0"
114+ title="required"
115+ />
116+ ) : null}
117+
118+ <span
119+ className={cn(
120+ "font-mono text-[10px] leading-none px-1.5 py-0.5 rounded-[3px] border font-medium",
121+ typeColorClasses(entry.type),
122+ )}
123+ >
124+ {entry.typeLabel}
125+ </span>
106126
107− walk(childShape, path, depth + 1);
127+ {entry.deprecated ? (
128+ <span className="font-mono text-[9px] font-medium uppercase tracking-wide text-[oklch(0.6_0.16_75)] dark:text-[oklch(0.78_0.14_75)] bg-[oklch(0.6_0.16_75_/_0.08)] dark:bg-[oklch(0.78_0.14_75_/_0.1)] border border-[oklch(0.6_0.16_75_/_0.18)] dark:border-[oklch(0.78_0.14_75_/_0.2)] rounded-[3px] px-1.5 py-px leading-none">
129+ deprecated
130+ </span>
131+ ) : null}
132+
133+ <ConstraintBadges entry={entry} />
134+ </div>
135+
136+ {/* Description */}
137+ {entry.description ? (
138+ <div className="text-[11px] leading-relaxed text-muted-foreground [&_p]:m-0 [&_p+p]:mt-0.5 [&_code]:font-mono [&_code]:text-[10px] [&_code]:bg-muted [&_code]:border [&_code]:border-border/70 [&_code]:rounded-sm [&_code]:px-1 [&_code]:py-px [&_code]:text-terminal-cyan [&_a]:text-primary [&_a]:underline [&_a]:underline-offset-2 [&_a]:decoration-primary/25 hover:[&_a]:decoration-primary/70">
139+ <Streamdown plugins={{ code: codePlugin }} controls={false}>{entry.description}</Streamdown>
140+ </div>
141+ ) : null}
142+
143+ {/* Enum values */}
144+ {entry.enumValues && entry.enumValues.length > 0 && entry.enumValues.length <= 12 ? (
145+ <div className="flex flex-wrap gap-1 mt-0.5">
146+ {entry.enumValues.map((v, i) => (
147+ <code key={i} className="font-mono text-[10px] bg-muted border border-border/60 rounded-[3px] px-1.5 py-px text-foreground/80">
148+ {v}
149+ </code>
150+ ))}
151+ </div>
152+ ) : null}
153+
154+ {/* Example / Default */}
155+ {(entry.example || entry.defaultValue) ? (
156+ <div className="flex flex-wrap gap-2 mt-0.5">
157+ {entry.example ? (
158+ <span className="inline-flex items-center gap-1">
159+ <span className="font-mono text-[9px] uppercase tracking-wider text-muted-foreground/50">example</span>
160+ <code className="font-mono text-[10px] text-muted-foreground/85">{entry.example}</code>
161+ </span>
162+ ) : null}
163+ {entry.defaultValue ? (
164+ <span className="inline-flex items-center gap-1">
165+ <span className="font-mono text-[9px] uppercase tracking-wider text-muted-foreground/50">default</span>
166+ <code className="font-mono text-[10px] text-muted-foreground/85">{entry.defaultValue}</code>
167+ </span>
168+ ) : null}
169+ </div>
170+ ) : null}
171+ </div>
172+ );
173+}
174+
175+// ── Schema fields section ───────────────────────────────────────────────────
176+
177+/** Detect schemas that describe an empty / void result (no useful fields). */
178+function isEmptySchema(schemaJson: string | undefined): boolean {
179+ if (!schemaJson) return false;
180+ try {
181+ const parsed = JSON.parse(schemaJson) as Record<string, unknown>;
182+ if (parsed.type === "object") {
183+ const props = parsed.properties;
184+ if (!props || (typeof props === "object" && Object.keys(props as object).length === 0)) {
185+ return true;
186+ }
108187 }
109− };
110−
111− walk(schema, "", 0);
112− const ordered = [...entries].sort((a, b) => {
113− const requiredOrder = Number(Boolean(b.required)) - Number(Boolean(a.required));
114− if (requiredOrder !== 0) return requiredOrder;
115− return a.path.localeCompare(b.path);
116− });
117− return { entries: ordered, truncated };
188+ return false;
189+ } catch {
190+ return false;
191+ }
118192 }
119193
120−function FieldDocsSection({
194+function SchemaFieldsSection({
121195 label,
122196 entries,
123197 truncated,
198+ schemaJson,
124199 }: {
125200 label: string;
126− entries: FieldDocEntry[];
201+ entries: SchemaFieldEntry[];
127202 truncated: boolean;
203+ schemaJson?: string;
128204 }) {
129− if (entries.length === 0) return null;
205+ if (entries.length === 0 && !schemaJson) return null;
130206
131− const collapsedByDefault = entries.length > 8 || truncated;
207+ const hasEntries = entries.length > 0;
208+ const empty = !hasEntries && isEmptySchema(schemaJson);
209+ const collapsedByDefault = entries.length > 10 || truncated;
132210
133211 return (
134− <details className="group" open={!collapsedByDefault}>
135− <summary className="mb-1 cursor-pointer select-none text-[10px] font-mono text-muted-foreground/70 group-open:mb-1">
136− <span className="mr-2 text-[9px] uppercase tracking-wider text-muted-foreground/50">{label}</span>
137− <span>{collapsedByDefault ? `show documented fields (${entries.length})` : `documented fields (${entries.length})`}</span>
138− </summary>
139− <div className="rounded-md border border-border/50 bg-muted/30 px-2.5 py-2 space-y-1.5">
140− {entries.map((entry) => (
141− <div key={entry.path} className="text-[11px] leading-relaxed">
142− <div className="font-mono text-foreground/85">
143− {entry.path}
144− {entry.required ? <span className="ml-1 text-[10px] text-emerald-600 dark:text-emerald-400">required</span> : null}
145− </div>
146− {entry.description ? <div className="text-muted-foreground">{entry.description}</div> : null}
147− {entry.example ? <div className="font-mono text-muted-foreground/80">example: {entry.example}</div> : null}
148− {entry.defaultValue ? <div className="font-mono text-muted-foreground/80">default: {entry.defaultValue}</div> : null}
149− {entry.deprecated ? <div className="font-mono text-amber-600 dark:text-amber-400">deprecated</div> : null}
150− </div>
151− ))}
152− {truncated ? (
153− <div className="text-[10px] font-mono text-muted-foreground/70">Showing first {entries.length} documented fields...</div>
212+ <div className="flex flex-col gap-2">
213+ {/* Section header */}
214+ <div className="flex items-baseline gap-2">
215+ <span className="font-mono text-[9px] font-medium tracking-wider uppercase text-muted-foreground/60">
216+ {label}
217+ </span>
218+ {hasEntries ? (
219+ <span className="font-mono text-[10px] text-muted-foreground/50">
220+ {entries.length} field{entries.length !== 1 ? "s" : ""}
221+ {truncated ? "+" : ""}
222+ </span>
154223 ) : null}
155224 </div>
156− </details>
225+
226+ {/* Field list */}
227+ {hasEntries ? (
228+ <div className="border border-border rounded-md bg-muted/30 overflow-hidden">
229+ {collapsedByDefault ? (
230+ <details open={false}>
231+ <summary className="cursor-pointer select-none font-mono text-[10px] text-muted-foreground/60 px-3.5 py-2 block transition-opacity hover:opacity-100">
232+ Show all fields ({entries.length}{truncated ? "+" : ""})
233+ </summary>
234+ <div className="flex flex-col">
235+ {entries.map((entry, i) => (
236+ <FieldRow key={`${entry.path}-${i}`} entry={entry} />
237+ ))}
238+ {truncated ? (
239+ <p className="font-mono text-[10px] text-muted-foreground/50 px-3.5 py-2">
240+ Showing first {entries.length} fields...
241+ </p>
242+ ) : null}
243+ </div>
244+ </details>
245+ ) : (
246+ <div className="flex flex-col">
247+ {entries.map((entry, i) => (
248+ <FieldRow key={`${entry.path}-${i}`} entry={entry} />
249+ ))}
250+ </div>
251+ )}
252+ </div>
253+ ) : empty ? (
254+ <p className="text-[11px] font-mono text-muted-foreground/50 italic pl-0.5">
255+ Empty object
256+ </p>
257+ ) : schemaJson ? (
258+ <TypeSignature raw={schemaJson} label="" lang="json" />
259+ ) : null}
260+
261+ {/* Raw schema toggle */}
262+ {hasEntries && schemaJson ? (
263+ <details className="mt-1">
264+ <summary className="cursor-pointer select-none font-mono text-[9px] uppercase tracking-wider text-muted-foreground/50 transition-opacity hover:opacity-80">
265+ Raw schema
266+ </summary>
267+ <div className="mt-1.5">
268+ <TypeSignature raw={schemaJson} label="" lang="json" />
269+ </div>
270+ </details>
271+ ) : null}
272+ </div>
157273 );
158274 }
159275
276+// ── Inline detail (used inside collapsible rows in tree/flat view) ───────────
277+
160278 export function ToolDetail({
161279 tool,
162280 depth,
@@ -167,6 +285,83 @@ export function ToolDetail({ · 4 unmodified lines
167285 loading?: boolean;
168286 }) {
169287 const insetLeft = depth * 20 + 8 + 16 + 8;
288+
289+ return (
290+ <div style={{ paddingLeft: insetLeft }}>
291+ <ToolDetailContent tool={tool} loading={loading} />
292+ </div>
293+ );
294+}
295+
296+// ── Standalone detail panel (main content area in sidebar layout) ────────────
297+
298+export function ToolDetailPanel({
299+ tool,
300+ loading,
301+}: {
302+ tool: ToolDescriptor;
303+ loading?: boolean;
304+}) {
305+ return (
306+ <div className="h-full overflow-y-auto">
307+ {/* Header */}
308+ <div className="sticky top-0 z-10 bg-background/95 backdrop-blur-sm border-b border-border/40 px-5 py-3">
309+ <div className="flex items-center gap-2.5 min-w-0">
310+ <Zap className="h-3.5 w-3.5 text-primary/70 shrink-0" />
311+ <h2 className="text-[14px] font-mono font-semibold text-foreground truncate">
312+ {tool.path}
313+ </h2>
314+ {tool.approval === "required" ? (
315+ <span className="inline-flex items-center gap-0.5 text-[9px] font-mono uppercase tracking-wider text-terminal-amber bg-terminal-amber/8 px-1.5 py-0.5 rounded border border-terminal-amber/15 shrink-0">
316+ <ShieldCheck className="h-2.5 w-2.5" />
317+ gated
318+ </span>
319+ ) : null}
320+ <div className="ml-auto shrink-0">
321+ <CopyButton text={tool.path} />
322+ </div>
323+ </div>
324+ {tool.source ? (
325+ <p className="mt-0.5 text-[10px] font-mono text-muted-foreground/50 pl-6">
326+ {tool.source}
327+ </p>
328+ ) : null}
329+ </div>
330+
331+ {/* Body */}
332+ <div className="px-5 py-4">
333+ <ToolDetailContent tool={tool} loading={loading} />
334+ </div>
335+ </div>
336+ );
337+}
338+
339+// ── Empty state for detail panel ────────────────────────────────────────────
340+
341+export function ToolDetailEmpty() {
342+ return (
343+ <div className="h-full flex items-center justify-center">
344+ <div className="text-center space-y-2">
345+ <div className="h-10 w-10 rounded-full bg-muted/40 flex items-center justify-center mx-auto">
346+ <Zap className="h-5 w-5 text-muted-foreground/20" />
347+ </div>
348+ <p className="text-[13px] text-muted-foreground/50">
349+ Select a tool to view its schema
350+ </p>
351+ </div>
352+ </div>
353+ );
354+}
355+
356+// ── Shared detail content (used by both inline and panel modes) ─────────────
357+
358+function ToolDetailContent({
359+ tool,
360+ loading,
361+}: {
362+ tool: ToolDescriptor;
363+ loading?: boolean;
364+}) {
170365 const description = tool.description?.trim() ?? "";
171366 const inputHint = tool.display?.input?.trim() ?? "";
172367 const outputHint = tool.display?.output?.trim() ?? "";
@@ -178,97 +373,75 @@ export function ToolDetail({ · 5 unmodified lines
178373 const hasOutputSchema = outputSchemaJson.length > 0 && outputSchemaJson !== "{}";
179374 const showInputHint = hasInputHint && !hasInputSchema;
180375 const showOutputHint = hasOutputHint && !hasOutputSchema;
181− const inputFieldDocs = useMemo(
182− () => collectSchemaFieldDocs(parseSchemaJson(inputSchemaJson), { maxEntries: 24, maxDepth: 4 }),
376+
377+ const inputFields = useMemo(
378+ () => traverseSchema(parseSchemaJson(inputSchemaJson), { maxEntries: 30, maxDepth: 5 }),
183379 [inputSchemaJson],
184380 );
185− const outputFieldDocs = useMemo(
186− () => collectSchemaFieldDocs(parseSchemaJson(outputSchemaJson), { maxEntries: 24, maxDepth: 4 }),
381+ const outputFields = useMemo(
382+ () => traverseSchema(parseSchemaJson(outputSchemaJson), { maxEntries: 30, maxDepth: 5 }),
187383 [outputSchemaJson],
188384 );
189− const hasInputFieldDocs = inputFieldDocs.entries.length > 0;
190− const hasOutputFieldDocs = outputFieldDocs.entries.length > 0;
191− const showInputRawSchema = hasInputSchema && !hasInputFieldDocs;
192− const showOutputRawSchema = hasOutputSchema && !hasOutputFieldDocs;
385+
193386 const hasDetails = description.length > 0
194387 || showInputHint
195388 || showOutputHint
196389 || hasInputSchema
197− || hasOutputSchema
198− || inputFieldDocs.entries.length > 0
199− || outputFieldDocs.entries.length > 0;
390+ || hasOutputSchema;
200391 const showLoading = Boolean(loading);
201392
202393 return (
203− <div className="space-y-2.5 pb-3 pt-1 pr-2" style={{ paddingLeft: insetLeft }}>
394+ <div className="pt-2 pb-4 flex flex-col gap-4">
395+ {/* Loading state */}
204396 {showLoading ? (
205− <div className="space-y-2.5">
206− <Skeleton className="h-3.5 w-64" />
207−
397+ <div className="space-y-3">
398+ <Skeleton className="h-3.5 w-72" />
208399 <div>
209− <p className="mb-1 text-[9px] font-mono uppercase tracking-wider text-muted-foreground/50">
210− Arguments
211− </p>
212− <Skeleton className="h-16 w-full rounded-md" />
400+ <p className="font-mono text-[9px] font-medium tracking-wider uppercase text-muted-foreground/60">Arguments</p>
401+ <Skeleton className="h-20 w-full rounded-md mt-1" />
213402 </div>
214−
215403 <div>
216− <p className="mb-1 text-[9px] font-mono uppercase tracking-wider text-muted-foreground/50">
217− Returns
218− </p>
219− <Skeleton className="h-12 w-full rounded-md" />
404+ <p className="font-mono text-[9px] font-medium tracking-wider uppercase text-muted-foreground/60">Returns</p>
405+ <Skeleton className="h-14 w-full rounded-md mt-1" />
220406 </div>
221407 </div>
222408 ) : null}
223409
224− {description && (
225− <div className="tool-description text-[12px] leading-relaxed text-muted-foreground">
226− <Streamdown plugins={{ code: codePlugin }}>{description}</Streamdown>
410+ {/* Description */}
411+ {description ? (
412+ <div className="text-[12px] leading-relaxed text-muted-foreground">
413+ <Streamdown plugins={{ code: codePlugin }} controls={{ code: true }}>{description}</Streamdown>
227414 </div>
228− )}
415+ ) : null}
229416
230− {showInputHint && <TypeSignature raw={inputHint} label="Arguments" />}
231− {showOutputHint && <TypeSignature raw={outputHint} label="Returns" />}
417+ {/* Type hint fallbacks (when no full schema is available) */}
418+ {showInputHint ? <TypeSignature raw={inputHint} label="Arguments" /> : null}
419+ {showOutputHint ? <TypeSignature raw={outputHint} label="Returns" /> : null}
232420
233− {showInputRawSchema ? <TypeSignature raw={inputSchemaJson} label="Input Schema" /> : null}
234− {showOutputRawSchema ? <TypeSignature raw={outputSchemaJson} label="Output Schema" /> : null}
421+ {/* Structured schema rendering */}
235422 {hasInputSchema ? (
236− <FieldDocsSection
237− label="Input Field Docs"
238− entries={inputFieldDocs.entries}
239− truncated={inputFieldDocs.truncated}
423+ <SchemaFieldsSection
424+ label="Arguments"
425+ entries={inputFields.entries}
426+ truncated={inputFields.truncated}
427+ schemaJson={inputSchemaJson}
240428 />
241429 ) : null}
430+
242431 {hasOutputSchema ? (
243− <FieldDocsSection
244− label="Output Field Docs"
245− entries={outputFieldDocs.entries}
246− truncated={outputFieldDocs.truncated}
432+ <SchemaFieldsSection
433+ label="Returns"
434+ entries={outputFields.entries}
435+ truncated={outputFields.truncated}
436+ schemaJson={outputSchemaJson}
247437 />
248438 ) : null}
249− {hasInputSchema && hasInputFieldDocs ? (
250− <details>
251− <summary className="cursor-pointer select-none text-[10px] font-mono uppercase tracking-wider text-muted-foreground/60">
252− Show Raw Input Schema
253− </summary>
254− <div className="mt-1">
255− <TypeSignature raw={inputSchemaJson} label="Input Schema" />
256− </div>
257− </details>
258− ) : null}
259− {hasOutputSchema && hasOutputFieldDocs ? (
260− <details>
261− <summary className="cursor-pointer select-none text-[10px] font-mono uppercase tracking-wider text-muted-foreground/60">
262− Show Raw Output Schema
263− </summary>
264− <div className="mt-1">
265− <TypeSignature raw={outputSchemaJson} label="Output Schema" />
266− </div>
267− </details>
268− ) : null}
269439
440+ {/* Empty state */}
270441 {!showLoading && !hasDetails ? (
271− <p className="text-[11px] text-muted-foreground/60">No description or type signatures available yet.</p>
442+ <p className="text-[11px] text-muted-foreground/50 italic">
443+ No description or schema available.
444+ </p>
272445 ) : null}
273446 </div>
274447 );
executor/apps/web/src/components/tools/explorer/type-signature.tsx+43−11
@@ -2,9 +2,23 @@ · 1 unmodified line
22
33 import { useMemo } from "react";
44 import { useQuery as useTanstackQuery } from "@tanstack/react-query";
5+import { cn } from "@/lib/utils";
6+import { CopyButton } from "./copy-button";
57
6−function prettyType(raw: string): string {
8+function prettyJson(raw: string): string {
79 const trimmed = raw.trim();
10+
11+ // If it looks like JSON, try to parse + re-format
12+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
13+ try {
14+ const parsed = JSON.parse(trimmed);
15+ return JSON.stringify(parsed, null, 2);
16+ } catch {
17+ // fall through
18+ }
19+ }
20+
21+ // Otherwise use the simple TS-like formatter
822 if (trimmed.includes("\n") || trimmed.length < 50) {
923 return trimmed;
1024 }
@@ -47,15 +61,17 @@ function prettyType(raw: string): string { · 36 unmodified lines
4761 return output;
4862 }
4963
50−export function TypeSignature({ raw, label }: { raw: string; label: string }) {
51− const formatted = useMemo(() => prettyType(raw), [raw]);
64+export function TypeSignature({ raw, label, lang }: { raw: string; label: string; lang?: string }) {
65+ const isJson = raw.trim().startsWith("{") || raw.trim().startsWith("[");
66+ const effectiveLang = lang ?? (isJson ? "json" : "typescript");
67+ const formatted = useMemo(() => prettyJson(raw), [raw]);
5268
5369 const { data: highlightedHtml } = useTanstackQuery<string>({
54− queryKey: ["type-signature", formatted],
70+ queryKey: ["type-signature", formatted, effectiveLang],
5571 queryFn: async () => {
5672 const { codeToHtml } = await import("shiki");
5773 return codeToHtml(formatted, {
58− lang: "typescript",
74+ lang: effectiveLang,
5975 themes: { light: "github-light", dark: "github-dark" },
6076 });
6177 },
@@ -63,17 +79,33 @@ export function TypeSignature({ raw, label }: { raw: string; label: string }) { · 1 unmodified line
6379 });
6480
6581 return (
66− <div>
67− <p className="mb-1 text-[9px] font-mono uppercase tracking-wider text-muted-foreground/50">
68− {label}
69− </p>
82+ <div className="relative group/schema">
83+ {label ? (
84+ <div className="flex items-center justify-between mb-1">
85+ <p className="font-mono text-[9px] font-medium tracking-wider uppercase text-muted-foreground/60">
86+ {label}
87+ </p>
88+ <CopyButton
89+ text={formatted}
90+ className="opacity-0 group-hover/schema:opacity-100 transition-opacity"
91+ />
92+ </div>
93+ ) : (
94+ <CopyButton
95+ text={formatted}
96+ className="absolute right-2 top-2 opacity-0 group-hover/schema:opacity-100 transition-opacity z-10"
97+ />
98+ )}
7099 {highlightedHtml ? (
71100 <div
72− className="type-signature text-[11px] leading-relaxed bg-muted/40 border border-border/40 rounded-md px-2.5 py-2 overflow-x-auto [&_pre]:!bg-transparent [&_pre]:!m-0 [&_pre]:!p-0 [&_code]:!text-[11px] [&_code]:!leading-relaxed"
101+ className={cn(
102+ "text-[10.5px] leading-[1.65] bg-muted/40 border border-border/40 rounded-md px-3.5 py-2.5 overflow-x-auto",
103+ "[&_pre]:!bg-transparent [&_pre]:!m-0 [&_pre]:!p-0 [&_code]:!text-[10.5px] [&_code]:!leading-[1.65]",
104+ )}
73105 dangerouslySetInnerHTML={{ __html: highlightedHtml }}
74106 />
75107 ) : (
76− <pre className="text-[11px] font-mono leading-relaxed text-foreground/80 bg-muted/40 border border-border/40 rounded-md px-2.5 py-2 overflow-x-auto whitespace-pre">
108+ <pre className="font-mono text-[10.5px] leading-[1.65] bg-muted/40 border border-border/40 rounded-md px-3.5 py-2.5 overflow-x-auto text-foreground/80 whitespace-pre m-0">
77109 {formatted}
78110 </pre>
79111 )}
executor/apps/web/src/components/tools/view.tsx+2−19
@@ -1,15 +1,13 @@
11 "use client";
22
33 import { useCallback, useMemo, useRef, useState } from "react";
4−import { Plus } from "lucide-react";
54 import { Card, CardContent } from "@/components/ui/card";
6−import { Button } from "@/components/ui/button";
75 import { Skeleton } from "@/components/ui/skeleton";
86 import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
97 import { PageHeader } from "@/components/page-header";
108 import { ToolExplorer } from "@/components/tools/explorer";
119 import { TaskComposer } from "@/components/tasks/task-composer";
12−import { AddSourceDialog } from "@/components/tools/add/source-dialog";
10+
1311 import { CredentialsPanel } from "@/components/tools/credentials";
1412 import { ConnectionFormDialog } from "@/components/tools/connection/form-dialog";
1513 import { PoliciesPanel } from "@/components/tools/policies";
@@ -498,22 +496,7 @@ export function ToolsView({ · 482 unmodified lines
498496 || inventoryStatus?.state === "rebuilding"
499497 || inventoryStatus?.state === "initializing"
500498 }
501− addSourceAction={
502− <AddSourceDialog
503− existingSourceNames={existingSourceNames}
504− onSourceAdded={handleSourceAdded}
505− trigger={
506− <Button
507− variant="default"
508− size="sm"
509− className="h-8 text-[11px]"
510− >
511− <Plus className="h-3.5 w-3.5 mr-1.5" />
512− Add Source
513− </Button>
514− }
515− />
516− }
499+ onSourceAdded={handleSourceAdded}
517500 />
518501 </div>
519502 </CardContent>
executor/apps/web/src/lib/tool/schema-traverse.ts+385−0
@@ -0,0 +1,385 @@
1+/**
2+ * schema-traverse.ts
3+ *
4+ * Structured JSON Schema walker using json-schema-traverse.
5+ * Produces a flat list of documented field entries for rendering,
6+ * handling properties, items, oneOf/anyOf/allOf, enums, and nested objects.
7+ */
8+
9+import traverse from "json-schema-traverse";
10+
11+// ── Types ────────────────────────────────────────────────────────────────────
12+
13+export type SchemaFieldType =
14+ | "string"
15+ | "number"
16+ | "integer"
17+ | "boolean"
18+ | "array"
19+ | "object"
20+ | "null"
21+ | "enum"
22+ | "union"
23+ | "unknown";
24+
25+export interface SchemaFieldEntry {
26+ /** Dot-delimited path, e.g. "config.retries" */
27+ path: string;
28+ /** Resolved JSON Schema type */
29+ type: SchemaFieldType;
30+ /** Human-readable type label (e.g. "string[]", "string | number") */
31+ typeLabel: string;
32+ /** Whether this field is required by its parent */
33+ required: boolean;
34+ /** Description from the schema */
35+ description?: string;
36+ /** Example value (serialized) */
37+ example?: string;
38+ /** Default value (serialized) */
39+ defaultValue?: string;
40+ /** Whether the field is marked deprecated */
41+ deprecated: boolean;
42+ /** Enum values if present */
43+ enumValues?: string[];
44+ /** Format hint (e.g. "uri", "date-time", "email") */
45+ format?: string;
46+ /** Nesting depth (0 = top-level) */
47+ depth: number;
48+ /** If array, the item type label */
49+ itemType?: string;
50+ /** Constraints: minimum, maximum, minLength, maxLength, pattern */
51+ constraints?: SchemaConstraints;
52+}
53+
54+export interface SchemaConstraints {
55+ minimum?: number;
56+ maximum?: number;
57+ exclusiveMinimum?: number;
58+ exclusiveMaximum?: number;
59+ minLength?: number;
60+ maxLength?: number;
61+ pattern?: string;
62+ minItems?: number;
63+ maxItems?: number;
64+ uniqueItems?: boolean;
65+}
66+
67+export interface TraverseOptions {
68+ maxDepth?: number;
69+ maxEntries?: number;
70+}
71+
72+// ── Helpers ──────────────────────────────────────────────────────────────────
73+
74+function asRecord(v: unknown): Record<string, unknown> {
75+ return v && typeof v === "object" && !Array.isArray(v)
76+ ? (v as Record<string, unknown>)
77+ : {};
78+}
79+
80+function toPreview(v: unknown): string | undefined {
81+ if (v === undefined) return undefined;
82+ if (typeof v === "string") {
83+ const t = v.trim();
84+ return t ? (t.length > 120 ? `${t.slice(0, 120)}...` : t) : undefined;
85+ }
86+ try {
87+ const s = JSON.stringify(v);
88+ return s && s.length > 0
89+ ? s.length > 120
90+ ? `${s.slice(0, 120)}...`
91+ : s
92+ : undefined;
93+ } catch {
94+ return undefined;
95+ }
96+}
97+
98+function resolveTypeLabel(schema: Record<string, unknown>): {
99+ type: SchemaFieldType;
100+ label: string;
101+ itemType?: string;
102+} {
103+ // Enum
104+ if (Array.isArray(schema.enum) && schema.enum.length > 0) {
105+ return { type: "enum", label: schema.enum.map((v) => JSON.stringify(v)).join(" | ") };
106+ }
107+
108+ // Const
109+ if (schema.const !== undefined) {
110+ return { type: "enum", label: JSON.stringify(schema.const) };
111+ }
112+
113+ // oneOf / anyOf union
114+ const union = (schema.oneOf ?? schema.anyOf) as unknown[] | undefined;
115+ if (Array.isArray(union) && union.length > 0) {
116+ const parts = union.map((s) => {
117+ const sub = asRecord(s);
118+ return resolveTypeLabel(sub).label;
119+ });
120+ return { type: "union", label: parts.join(" | ") };
121+ }
122+
123+ // allOf intersection
124+ const allOf = schema.allOf as unknown[] | undefined;
125+ if (Array.isArray(allOf) && allOf.length > 0) {
126+ const parts = allOf.map((s) => {
127+ const sub = asRecord(s);
128+ return resolveTypeLabel(sub).label;
129+ });
130+ return { type: "object", label: parts.join(" & ") };
131+ }
132+
133+ // Type array (e.g. ["string", "null"])
134+ if (Array.isArray(schema.type)) {
135+ const types = schema.type as string[];
136+ if (types.length === 2 && types.includes("null")) {
137+ const nonNull = types.find((t) => t !== "null") ?? "unknown";
138+ return { type: nonNull as SchemaFieldType, label: `${nonNull} | null` };
139+ }
140+ return { type: "union", label: types.join(" | ") };
141+ }
142+
143+ const rawType = typeof schema.type === "string" ? schema.type : undefined;
144+
145+ // Array with items
146+ if (rawType === "array") {
147+ const items = asRecord(schema.items);
148+ if (Object.keys(items).length > 0) {
149+ const inner = resolveTypeLabel(items);
150+ return { type: "array", label: `${inner.label}[]`, itemType: inner.label };
151+ }
152+ return { type: "array", label: "array", itemType: undefined };
153+ }
154+
155+ // Object
156+ if (rawType === "object") {
157+ return { type: "object", label: "object" };
158+ }
159+
160+ // String with format
161+ if (rawType === "string" && typeof schema.format === "string") {
162+ return { type: "string", label: `string<${schema.format}>` };
163+ }
164+
165+ // Simple type
166+ if (rawType) {
167+ return { type: rawType as SchemaFieldType, label: rawType };
168+ }
169+
170+ return { type: "unknown", label: "unknown" };
171+}
172+
173+function extractConstraints(schema: Record<string, unknown>): SchemaConstraints | undefined {
174+ const c: SchemaConstraints = {};
175+ let hasAny = false;
176+
177+ for (const [key, field] of [
178+ ["minimum", "minimum"],
179+ ["maximum", "maximum"],
180+ ["exclusiveMinimum", "exclusiveMinimum"],
181+ ["exclusiveMaximum", "exclusiveMaximum"],
182+ ["minLength", "minLength"],
183+ ["maxLength", "maxLength"],
184+ ["minItems", "minItems"],
185+ ["maxItems", "maxItems"],
186+ ] as const) {
187+ if (typeof schema[field] === "number") {
188+ (c as Record<string, unknown>)[key] = schema[field];
189+ hasAny = true;
190+ }
191+ }
192+
193+ if (typeof schema.pattern === "string") {
194+ c.pattern = schema.pattern;
195+ hasAny = true;
196+ }
197+ if (schema.uniqueItems === true) {
198+ c.uniqueItems = true;
199+ hasAny = true;
200+ }
201+
202+ return hasAny ? c : undefined;
203+}
204+
205+// ── Main traversal ──────────────────────────────────────────────────────────
206+
207+export function traverseSchema(
208+ schema: Record<string, unknown>,
209+ options: TraverseOptions = {},
210+): { entries: SchemaFieldEntry[]; truncated: boolean } {
211+ const maxDepth = options.maxDepth ?? 5;
212+ const maxEntries = options.maxEntries ?? 40;
213+ const entries: SchemaFieldEntry[] = [];
214+ let truncated = false;
215+
216+ // Use json-schema-traverse to walk all sub-schemas
217+ // We track the JSON pointer path to compute our dot-notation path
218+ const requiredSets = new Map<string, Set<string>>();
219+
220+ // Pre-compute required sets for all object nodes
221+ traverse(schema, {
222+ cb: (subSchema, _jsonPtr, _rootSchema, _parentJsonPtr, _parentKeyword, _parentSchema, _keyIndex) => {
223+ const node = asRecord(subSchema);
224+ if (Array.isArray(node.required)) {
225+ const ptr = _jsonPtr || "";
226+ requiredSets.set(
227+ ptr,
228+ new Set(
229+ (node.required as unknown[]).filter((v): v is string => typeof v === "string"),
230+ ),
231+ );
232+ }
233+ },
234+ });
235+
236+ // Now do a targeted walk ourselves for rendering, using json-schema-traverse
237+ // for validation but our own recursive walk for the rendering entries.
238+ // This gives us more control over depth, path naming, and entry construction.
239+
240+ const walk = (
241+ node: unknown,
242+ prefix: string,
243+ depth: number,
244+ parentRequiredKeys: Set<string>,
245+ ) => {
246+ if (depth > maxDepth || truncated) return;
247+ const shape = asRecord(node);
248+
249+ // Collect required set for this node
250+ const requiredKeys = new Set(
251+ Array.isArray(shape.required)
252+ ? (shape.required as unknown[]).filter((v): v is string => typeof v === "string")
253+ : [],
254+ );
255+
256+ // Walk properties
257+ const properties = asRecord(shape.properties);
258+ for (const [rawKey, child] of Object.entries(properties)) {
259+ if (truncated) break;
260+ const key = rawKey.trim();
261+ if (!key) continue;
262+
263+ const childShape = asRecord(child);
264+ const path = prefix ? `${prefix}.${key}` : key;
265+ const { type, label, itemType } = resolveTypeLabel(childShape);
266+ const description =
267+ typeof childShape.description === "string"
268+ ? childShape.description.trim() || undefined
269+ : undefined;
270+ const example = toPreview(childShape.example);
271+ const defaultValue = toPreview(childShape.default);
272+ const deprecated = childShape.deprecated === true;
273+ const isRequired = parentRequiredKeys.has(key) || requiredKeys.has(key);
274+ const format =
275+ typeof childShape.format === "string" ? childShape.format : undefined;
276+ const enumValues = Array.isArray(childShape.enum)
277+ ? (childShape.enum as unknown[]).map((v) => JSON.stringify(v))
278+ : undefined;
279+ const constraints = extractConstraints(childShape);
280+
281+ if (entries.length >= maxEntries) {
282+ truncated = true;
283+ break;
284+ }
285+
286+ entries.push({
287+ path,
288+ type,
289+ typeLabel: label,
290+ required: isRequired,
291+ description,
292+ example,
293+ defaultValue,
294+ deprecated,
295+ enumValues,
296+ format,
297+ depth,
298+ itemType,
299+ constraints,
300+ });
301+
302+ // Recurse into nested objects
303+ if (type === "object" || asRecord(childShape.properties) && Object.keys(asRecord(childShape.properties)).length > 0) {
304+ walk(childShape, path, depth + 1, requiredKeys);
305+ }
306+
307+ // Recurse into array items if they have properties
308+ if (type === "array" && childShape.items) {
309+ const itemShape = asRecord(childShape.items);
310+ if (Object.keys(asRecord(itemShape.properties)).length > 0) {
311+ walk(itemShape, `${path}[]`, depth + 1, new Set<string>());
312+ }
313+ }
314+
315+ // Recurse into oneOf/anyOf variants that have properties
316+ const variants = (childShape.oneOf ?? childShape.anyOf) as unknown[] | undefined;
317+ if (Array.isArray(variants)) {
318+ for (const variant of variants) {
319+ const variantShape = asRecord(variant);
320+ if (Object.keys(asRecord(variantShape.properties)).length > 0) {
321+ walk(variantShape, path, depth + 1, new Set<string>());
322+ }
323+ }
324+ }
325+ }
326+
327+ // Handle top-level oneOf/anyOf/allOf at any node if there are no direct properties
328+ if (Object.keys(properties).length === 0) {
329+ const composites = [
330+ ...(Array.isArray(shape.oneOf) ? (shape.oneOf as unknown[]) : []),
331+ ...(Array.isArray(shape.anyOf) ? (shape.anyOf as unknown[]) : []),
332+ ...(Array.isArray(shape.allOf) ? (shape.allOf as unknown[]) : []),
333+ ];
334+ for (const comp of composites) {
335+ walk(comp, prefix, depth, parentRequiredKeys);
336+ }
337+ }
338+ };
339+
340+ walk(schema, "", 0, new Set<string>());
341+
342+ // Preserve schema traversal order so parent/child fields stay grouped.
343+ return { entries, truncated };
344+}
345+
346+/**
347+ * Summarize a JSON Schema into a brief one-line type signature.
348+ * e.g. "{ name: string, age?: number, tags: string[] }"
349+ */
350+export function schemaToTypeHint(schema: Record<string, unknown>, maxLength = 120): string {
351+ const properties = asRecord(schema.properties);
352+ const requiredKeys = new Set(
353+ Array.isArray(schema.required)
354+ ? (schema.required as unknown[]).filter((v): v is string => typeof v === "string")
355+ : [],
356+ );
357+
358+ const keys = Object.keys(properties);
359+ if (keys.length === 0) {
360+ const { label } = resolveTypeLabel(schema);
361+ return label;
362+ }
363+
364+ const parts: string[] = [];
365+ for (const key of keys) {
366+ const childShape = asRecord(properties[key]);
367+ const { label } = resolveTypeLabel(childShape);
368+ const optional = requiredKeys.has(key) ? "" : "?";
369+ parts.push(`${key}${optional}: ${label}`);
370+ }
371+
372+ const joined = `{ ${parts.join(", ")} }`;
373+ if (joined.length <= maxLength) return joined;
374+
375+ // Truncate to fit
376+ let result = "{ ";
377+ for (let i = 0; i < parts.length; i++) {
378+ const next = result + parts[i] + (i < parts.length - 1 ? ", " : " }");
379+ if (next.length > maxLength - 6) {
380+ return `${result}... }`;
381+ }
382+ result = i < parts.length - 1 ? result + parts[i] + ", " : next;
383+ }
384+ return result;
385+}
executor/infra/.gitignore+0−2
@@ -1,2 +0,0 @@
1−.sst
2−.pulumi
executor/infra/README.md+0−122
@@ -1,122 +0,0 @@
1−# Executor IaC (SST)
2−
3−This directory contains the production Infrastructure as Code setup for `executor/`.
4−
5−It uses SST (v3) as the deployment framework and Pulumi providers/resources under the hood.
6−
7−## What this manages
8−
9−- Cloudflare runtime wiring for sandbox execution (via `setup:prod:cloudflare` command resource)
10−- Convex production env synchronization (via `setup:prod:env` command resource)
11−- Convex production deploy (optional command resource)
12−- Production doctor verification (`doctor:prod`) after apply
13−- Stripe catalog resources (optional): product, recurring price, webhook endpoint
14−- Vercel project + environment variables (optional)
15−
16−WorkOS and Convex are managed as code through scripted command resources because they do not have first-class native Pulumi resource coverage in this repo workflow.
17−
18−## Prerequisites
19−
20−- SST CLI login/config ready for your chosen stage
21−- Cloudflare credentials configured for SST/Pulumi deployment backend
22−- Local tools available:
23− - `bun`
24− - `bunx convex`
25− - `bunx wrangler`
26−
27−## Install
28−
29−From `executor/infra`:
30−
31−```bash
32−bun install
33−```
34−
35−## Configure
36−
37−This stack resolves values in this order:
38−
39−1. SST/Pulumi stage config
40−2. Shell env (`process.env`)
41−3. Existing Convex production env (`bunx convex env list --prod`) when `IAC_USE_CONVEX_ENV_DISCOVERY` is not `0`
42−
43−So if your Convex production env is already populated, you only need minimal bootstrap values.
44−
45−Minimal bootstrap env for baseline deploy:
46−
47−```bash
48−# Convex API URL (if not already present in Convex prod env)
49−export CONVEX_URL=https://<deployment>.convex.cloud
50−```
51−
52−If Convex prod env is empty/new, also provide WorkOS + Stripe + runtime vars (or set them via SST secrets/config before deploy).
53−
54−Cloudflare auth is handled by `wrangler` when the Cloudflare setup command runs, so make sure `wrangler whoami` works in your shell.
55−
56−Optional toggles (defaults shown):
57−
58−```bash
59−export IAC_MANAGE_CLOUDFLARE_RUNTIME=true # default true
60−export IAC_MANAGE_CONVEX_ENV=true # default true
61−export IAC_DEPLOY_CONVEX_FUNCTIONS=true # default true
62−export IAC_MANAGE_VERCEL_PROJECT=false # default false
63−export IAC_MANAGE_STRIPE_CATALOG=false # default false
64−```
65−
66−If `IAC_MANAGE_STRIPE_CATALOG=true`, also set:
67−
68−```bash
69−export IAC_STRIPE_UNIT_AMOUNT=2000
70−export IAC_STRIPE_INTERVAL=month
71−export IAC_STRIPE_CURRENCY=usd
72−```
73−
74−If `IAC_MANAGE_VERCEL_PROJECT=true`, also set:
75−
76−```bash
77−export VERCEL_API_TOKEN=<value>
78−export VERCEL_TEAM=<team-id-or-slug> # optional
79−export VERCEL_PROJECT_NAME=executor-web # optional
80−export VERCEL_GIT_REPO=owner/repo # optional
81−```
82−
83−## Deploy
84−
85−```bash
86−sst install
87−bun run deploy
88−```
89−
90−From `executor/`, prefer the guided deploy runner:
91−
92−```bash
93−# Plan only (no changes)
94−bun run deploy:prod
95−
96−# Apply all steps
97−bun run deploy:prod --apply
98−
99−# Apply selected steps
100−bun run deploy:prod --apply --only cloudflare,doctor
101−```
102−
103−For first-time initialization of a fresh production deployment from `executor/`:
104−
105−```bash
106−bun run setup:prod:cloudflare --deploy
107−bun run setup:prod:env --from-env --strict
108−```
109−
110−## Helpful outputs
111−
112−The stack returns outputs including:
113−
114−- `doctorCommand`
115−- `stripePriceId`
116−- `vercelProjectId`
117−
118−## Notes
119−
120−- `doctor:prod` remains the final correctness gate.
121−- Optional billing URLs can be set as config and will be propagated to Convex env.
122−- If you disable a managed area (`manageVercelProject`, `manageStripeCatalog`, etc), ensure required values are supplied by config/secrets instead.
executor/infra/package.json+0−26
@@ -1,26 +0,0 @@
1−{
2− "name": "executor-infra",
3− "private": true,
4− "type": "module",
5− "scripts": {
6− "dev": "sst dev",
7− "deploy": "sst deploy",
8− "remove": "sst remove",
9− "diff": "sst diff",
10− "refresh": "sst refresh",
11− "typecheck": "bunx --package @typescript/native-preview tsgo --noEmit -p tsconfig.json",
12− "typecheck:slow": "bunx tsc --noEmit -p tsconfig.json",
13− "clean": "rm -rf node_modules .turbo"
14− },
15− "dependencies": {
16− "@pulumi/command": "^1.1.3",
17− "@pulumi/pulumi": "^3.220.0",
18− "@pulumiverse/vercel": "^4.5.0",
19− "pulumi-stripe": "^0.0.26",
20− "sst": "^3.17.38"
21− },
22− "devDependencies": {
23− "@types/node": "^24.6.2",
24− "typescript": "^5.9.3"
25− }
26−}
executor/infra/sst.config.ts+0−572
@@ -1,572 +0,0 @@
1−/// <reference path="./.sst/platform/config.d.ts" />
2−
3−function toSiteUrl(convexUrl: string): string {
4− if (convexUrl.includes(".convex.cloud")) {
5− return convexUrl.replace(".convex.cloud", ".convex.site");
6− }
7− return convexUrl;
8−}
9−
10−function compact<T>(values: Array<T | null | undefined>): T[] {
11− return values.filter((value): value is T => value !== null && value !== undefined);
12−}
13−
14−function parseConvexEnvList(raw: string): Map<string, string> {
15− const env = new Map<string, string>();
16− for (const line of raw.split("\n")) {
17− const trimmed = line.trim();
18− if (!trimmed || trimmed.startsWith("#")) {
19− continue;
20− }
21−
22− const eqIndex = trimmed.indexOf("=");
23− if (eqIndex <= 0) {
24− continue;
25− }
26−
27− const key = trimmed.slice(0, eqIndex).trim();
28− const value = trimmed.slice(eqIndex + 1);
29− if (key.length > 0) {
30− env.set(key, value);
31− }
32− }
33− return env;
34−}
35−
36−function loadConvexEnv(executorRoot: string, spawnSync: any): Map<string, string> {
37− if (process.env.IAC_USE_CONVEX_ENV_DISCOVERY === "0") {
38− return new Map<string, string>();
39− }
40−
41− const listed = spawnSync("bunx", ["convex", "env", "list", "--prod"], {
42− cwd: executorRoot,
43− env: process.env,
44− encoding: "utf8",
45− });
46−
47− if (listed.status !== 0) {
48− return new Map<string, string>();
49− }
50−
51− return parseConvexEnvList(listed.stdout ?? "");
52−}
53−
54−function createResolver(config: any, pulumi: any, convexEnv: Map<string, string>) {
55− const readText = (configKey: string, envKey: string): string | undefined => {
56− const cfg = config.get(configKey);
57− if (cfg && cfg.trim().length > 0) {
58− return cfg.trim();
59− }
60−
61− const env = process.env[envKey];
62− if (env && env.trim().length > 0) {
63− return env.trim();
64− }
65−
66− const discovered = convexEnv.get(envKey);
67− if (discovered && discovered.trim().length > 0) {
68− return discovered.trim();
69− }
70−
71− return undefined;
72− };
73−
74− const readSecret = (configKey: string, envKey: string): any => {
75− const cfg = config.getSecret(configKey);
76− if (cfg) {
77− return cfg;
78− }
79−
80− const text = readText(configKey, envKey);
81− return text ? pulumi.secret(text) : undefined;
82− };
83−
84− const requireText = (configKey: string, envKey: string): string => {
85− const value = readText(configKey, envKey);
86− if (!value) {
87− throw new Error(`Missing required value '${configKey}' (or env '${envKey}')`);
88− }
89− return value;
90− };
91−
92− const requireSecret = (configKey: string, envKey: string): any => {
93− const value = readSecret(configKey, envKey);
94− if (!value) {
95− throw new Error(`Missing required secret '${configKey}' (or env '${envKey}')`);
96− }
97− return value;
98− };
99−
100− const readBool = (configKey: string, envKey: string, fallback: boolean): boolean => {
101− const cfg = config.getBoolean(configKey);
102− if (cfg !== undefined) {
103− return cfg;
104− }
105−
106− const env = process.env[envKey]?.trim().toLowerCase();
107− if (!env) {
108− return fallback;
109− }
110−
111− if (["1", "true", "yes", "on"].includes(env)) {
112− return true;
113− }
114− if (["0", "false", "no", "off"].includes(env)) {
115− return false;
116− }
117− return fallback;
118− };
119−
120− return {
121− readText,
122− readSecret,
123− requireText,
124− requireSecret,
125− readBool,
126− };
127−}
128−
129−function setupStripe(args: {
130− manageStripeCatalog: boolean;
131− resolver: ReturnType<typeof createResolver>;
132− stripe: any;
133− config: any;
134− stage: string;
135− convexSiteUrl: string;
136−}) {
137− const { manageStripeCatalog, resolver, stripe, config, stage, convexSiteUrl } = args;
138−
139− let stripePriceId: any = resolver.readText("stripePriceId", "STRIPE_PRICE_ID");
140− let stripeWebhookSecret: any = resolver.readSecret("stripeWebhookSecret", "STRIPE_WEBHOOK_SECRET");
141− const stripeSecretKey = resolver.readSecret("stripeSecretKey", "STRIPE_SECRET_KEY");
142−
143− let stripeProductResource: any;
144− if (manageStripeCatalog) {
145− const stripeProvider = new stripe.Provider("stripe-provider", {
146− apiKey: resolver.requireSecret("stripeSecretKey", "STRIPE_SECRET_KEY"),
147− });
148−
149− const unitAmountRaw = resolver.requireText("stripeUnitAmount", "IAC_STRIPE_UNIT_AMOUNT");
150− const unitAmount = Number.parseInt(unitAmountRaw, 10);
151− if (!Number.isFinite(unitAmount) || unitAmount <= 0) {
152− throw new Error(`Invalid stripeUnitAmount '${unitAmountRaw}'`);
153− }
154−
155− const currency = resolver.readText("stripeCurrency", "IAC_STRIPE_CURRENCY") ?? "usd";
156− const interval = resolver.readText("stripeInterval", "IAC_STRIPE_INTERVAL") ?? "month";
157− const lookupKey = resolver.readText("stripeLookupKey", "IAC_STRIPE_LOOKUP_KEY") ?? "executor_team_seat_monthly";
158− const productName = resolver.readText("stripeProductName", "IAC_STRIPE_PRODUCT_NAME") ?? "Executor Team Seat";
159− const productDescription =
160− resolver.readText("stripeProductDescription", "IAC_STRIPE_PRODUCT_DESCRIPTION")
161− ?? "Per-seat subscription for Executor organizations.";
162−
163− stripeProductResource = new stripe.Product(
164− "executor-seat-product",
165− {
166− name: productName,
167− description: productDescription,
168− active: true,
169− metadata: { managedBy: "sst", stage },
170− },
171− { provider: stripeProvider },
172− );
173−
174− const stripePrice = new stripe.Price(
175− "executor-seat-price",
176− {
177− product: stripeProductResource.id,
178− currency,
179− unitAmount,
180− lookupKey,
181− recurring: { interval },
182− metadata: { managedBy: "sst", stage },
183− },
184− { provider: stripeProvider },
185− );
186− stripePriceId = stripePrice.id;
187−
188− const webhookUrl = resolver.readText("stripeWebhookUrl", "IAC_STRIPE_WEBHOOK_URL") ?? `${convexSiteUrl}/stripe/webhook`;
189− const webhookEvents =
190− (config.getObject("stripeWebhookEvents") as string[] | undefined)
191− ?? [
192− "checkout.session.completed",
193− "customer.subscription.created",
194− "customer.subscription.updated",
195− "customer.subscription.deleted",
196− "invoice.paid",
197− "invoice.payment_failed",
198− ];
199−
200− const webhook = new stripe.WebhookEndpoint(
201− "executor-billing-webhook",
202− {
203− url: webhookUrl,
204− enabledEvents: webhookEvents,
205− description: `Executor billing webhook (${stage})`,
206− },
207− { provider: stripeProvider },
208− );
209−
210− stripeWebhookSecret = webhook.secret;
211− }
212−
213− return {
214− stripePriceId,
215− stripeWebhookSecret,
216− stripeSecretKey,
217− stripeProductResource,
218− };
219−}
220−
221−function setupCloudflareRuntime(args: {
222− enabled: boolean;
223− resolver: ReturnType<typeof createResolver>;
224− pulumi: any;
225− command: any;
226− convexUrl: string;
227− executorRoot: string;
228−}) {
229− const { enabled, resolver, pulumi, command, convexUrl, executorRoot } = args;
230− if (!enabled) {
231− return undefined;
232− }
233−
234− const runUrl = resolver.readText("cloudflareSandboxRunUrl", "CLOUDFLARE_SANDBOX_RUN_URL");
235− const authToken = resolver.readSecret("cloudflareSandboxAuthToken", "CLOUDFLARE_SANDBOX_AUTH_TOKEN");
236− const internalToken = resolver.readSecret("executorInternalToken", "EXECUTOR_INTERNAL_TOKEN");
237−
238− const runUrlArg = runUrl ? pulumi.interpolate` --run-url ${runUrl}` : "";
239− const authArg = authToken ? pulumi.interpolate` --auth-token ${authToken}` : "";
240− const internalArg = internalToken ? pulumi.interpolate` --internal-token ${internalToken}` : "";
241−
242− const setupCmd = pulumi.interpolate`bun run setup:prod:cloudflare --deploy --no-doctor --convex-url ${convexUrl}${runUrlArg}${authArg}${internalArg}`;
243−
244− return new command.local.Command("executor-cloudflare-runtime", {
245− create: setupCmd,
246− update: setupCmd,
247− dir: executorRoot,
248− triggers: [runUrl ?? "", convexUrl, authToken ?? "", internalToken ?? ""],
249− });
250−}
251−
252−function setupConvexEnvSync(args: {
253− enabled: boolean;
254− resolver: ReturnType<typeof createResolver>;
255− command: any;
256− executorRoot: string;
257− cloudflareSetup: any;
258− stripeSecretKey: any;
259− stripeWebhookSecret: any;
260− stripePriceId: any;
261−}) {
262− const {
263− enabled,
264− resolver,
265− command,
266− executorRoot,
267− cloudflareSetup,
268− stripeSecretKey,
269− stripeWebhookSecret,
270− stripePriceId,
271− } = args;
272− if (!enabled) {
273− return undefined;
274− }
275−
276− const workosClientId = resolver.requireText("workosClientId", "WORKOS_CLIENT_ID");
277− const workosApiKey = resolver.requireSecret("workosApiKey", "WORKOS_API_KEY");
278− const workosWebhookSecret = resolver.requireSecret("workosWebhookSecret", "WORKOS_WEBHOOK_SECRET");
279− const workosCookiePassword = resolver.requireSecret("workosCookiePassword", "WORKOS_COOKIE_PASSWORD");
280− const mcpAuthorizationServer =
281− resolver.readText("mcpAuthorizationServer", "MCP_AUTHORIZATION_SERVER")
282− ?? resolver.readText("mcpAuthorizationServer", "MCP_AUTHORIZATION_SERVER_URL");
283− if (!mcpAuthorizationServer) {
284− throw new Error("Missing MCP authorization server (MCP_AUTHORIZATION_SERVER or MCP_AUTHORIZATION_SERVER_URL)");
285− }
286−
287− if (!stripeSecretKey) {
288− throw new Error("Missing stripeSecretKey (or STRIPE_SECRET_KEY)");
289− }
290− if (!stripePriceId) {
291− throw new Error("Missing stripePriceId (or STRIPE_PRICE_ID)");
292− }
293− if (!stripeWebhookSecret) {
294− throw new Error("Missing stripeWebhookSecret (or STRIPE_WEBHOOK_SECRET)");
295− }
296−
297− const billingSuccessUrl = resolver.readText("billingSuccessUrl", "BILLING_SUCCESS_URL");
298− const billingCancelUrl = resolver.readText("billingCancelUrl", "BILLING_CANCEL_URL");
299− const billingReturnUrl = resolver.readText("billingReturnUrl", "BILLING_RETURN_URL");
300−
301− const envVars: Record<string, any> = {
302− WORKOS_CLIENT_ID: workosClientId,
303− WORKOS_API_KEY: workosApiKey,
304− WORKOS_WEBHOOK_SECRET: workosWebhookSecret,
305− WORKOS_COOKIE_PASSWORD: workosCookiePassword,
306− MCP_AUTHORIZATION_SERVER: mcpAuthorizationServer,
307− STRIPE_SECRET_KEY: stripeSecretKey,
308− STRIPE_WEBHOOK_SECRET: stripeWebhookSecret,
309− STRIPE_PRICE_ID: stripePriceId,
310− };
311−
312− if (billingSuccessUrl) envVars.BILLING_SUCCESS_URL = billingSuccessUrl;
313− if (billingCancelUrl) envVars.BILLING_CANCEL_URL = billingCancelUrl;
314− if (billingReturnUrl) envVars.BILLING_RETURN_URL = billingReturnUrl;
315−
316− return new command.local.Command(
317− "executor-convex-env",
318− {
319− create: "bun run setup:prod:env --from-env --strict",
320− update: "bun run setup:prod:env --from-env --strict",
321− dir: executorRoot,
322− environment: envVars,
323− triggers: [
324− workosClientId,
325− workosApiKey,
326− workosWebhookSecret,
327− workosCookiePassword,
328− mcpAuthorizationServer,
329− stripeSecretKey,
330− stripeWebhookSecret,
331− stripePriceId,
332− billingSuccessUrl ?? "",
333− billingCancelUrl ?? "",
334− billingReturnUrl ?? "",
335− ],
336− },
337− {
338− dependsOn: compact([cloudflareSetup]),
339− },
340− );
341−}
342−
343−function setupConvexDeploy(args: {
344− enabled: boolean;
345− command: any;
346− executorRoot: string;
347− stage: string;
348− convexEnvSync: any;
349− cloudflareSetup: any;
350−}) {
351− const { enabled, command, executorRoot, stage, convexEnvSync, cloudflareSetup } = args;
352− if (!enabled) {
353− return undefined;
354− }
355−
356− return new command.local.Command(
357− "executor-convex-deploy",
358− {
359− create: "bunx convex deploy --prod",
360− update: "bunx convex deploy --prod",
361− dir: executorRoot,
362− triggers: [stage],
363− },
364− {
365− dependsOn: compact([convexEnvSync, cloudflareSetup]),
366− },
367− );
368−}
369−
370−function setupDoctor(args: {
371− command: any;
372− executorRoot: string;
373− stage: string;
374− convexDeploy: any;
375− convexEnvSync: any;
376− cloudflareSetup: any;
377−}) {
378− const { command, executorRoot, stage, convexDeploy, convexEnvSync, cloudflareSetup } = args;
379− return new command.local.Command(
380− "executor-doctor-prod",
381− {
382− create: "bun run doctor:prod",
383− update: "bun run doctor:prod",
384− dir: executorRoot,
385− triggers: [stage],
386− },
387− {
388− dependsOn: compact([convexDeploy, convexEnvSync, cloudflareSetup]),
389− },
390− );
391−}
392−
393−function setupVercel(args: {
394− enabled: boolean;
395− resolver: ReturnType<typeof createResolver>;
396− vercel: any;
397− convexUrl: string;
398− convexSiteUrl: string;
399− stripePriceId: any;
400−}) {
401− const { enabled, resolver, vercel, convexUrl, convexSiteUrl, stripePriceId } = args;
402− if (!enabled) {
403− return undefined;
404− }
405−
406− const vercelApiToken = resolver.requireSecret("vercelApiToken", "VERCEL_API_TOKEN");
407− const vercelTeam = resolver.readText("vercelTeam", "VERCEL_TEAM");
408− const vercelProjectName = resolver.readText("vercelProjectName", "VERCEL_PROJECT_NAME") ?? "executor-web";
409− const vercelGitRepo = resolver.readText("vercelGitRepo", "VERCEL_GIT_REPO");
410−
411− const provider = new vercel.Provider("vercel-provider", {
412− apiToken: vercelApiToken,
413− team: vercelTeam,
414− });
415−
416− const project = new vercel.Project(
417− "executor-web-project",
418− {
419− name: vercelProjectName,
420− framework: "nextjs",
421− rootDirectory: "executor/apps/web",
422− gitRepository: vercelGitRepo
423− ? {
424− type: "github",
425− repo: vercelGitRepo,
426− }
427− : undefined,
428− },
429− { provider },
430− );
431−
432− const workosClientId = resolver.readText("workosClientId", "WORKOS_CLIENT_ID") ?? "";
433− const workosApiKey = resolver.readSecret("workosApiKey", "WORKOS_API_KEY") ?? "";
434− const workosCookiePassword = resolver.readSecret("workosCookiePassword", "WORKOS_COOKIE_PASSWORD") ?? "";
435−
436− const vercelVars: Array<{ key: string; value: any; sensitive: boolean }> = [
437− { key: "CONVEX_URL", value: convexUrl, sensitive: false },
438− { key: "CONVEX_SITE_URL", value: convexSiteUrl, sensitive: false },
439− { key: "WORKOS_CLIENT_ID", value: workosClientId, sensitive: false },
440− { key: "WORKOS_API_KEY", value: workosApiKey, sensitive: true },
441− { key: "WORKOS_COOKIE_PASSWORD", value: workosCookiePassword, sensitive: true },
442− { key: "STRIPE_PRICE_ID", value: stripePriceId ?? "", sensitive: false },
443− ];
444−
445− for (const item of vercelVars) {
446− if (!item.value) {
447− continue;
448− }
449−
450− new vercel.ProjectEnvironmentVariable(
451− `vercel-env-${item.key.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`,
452− {
453− projectId: project.id,
454− key: item.key,
455− value: item.value,
456− targets: ["production", "preview", "development"],
457− sensitive: item.sensitive,
458− },
459− { provider },
460− );
461− }
462−
463− return project;
464−}
465−
466−export default $config({
467− app(input: any) {
468− return {
469− name: "executor-infra",
470− home: "local",
471− removal: input?.stage === "production" ? "retain" : "remove",
472− };
473− },
474− async run() {
475− const path = await import("node:path");
476− const { fileURLToPath } = await import("node:url");
477− const { spawnSync } = await import("node:child_process");
478− const pulumi = await import("@pulumi/pulumi");
479− const command = await import("@pulumi/command");
480− const stripe = await import("pulumi-stripe");
481− const vercel = await import("@pulumiverse/vercel");
482−
483− const stage = $app.stage;
484− const executorRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
485− const config = new pulumi.Config();
486− const convexEnv = loadConvexEnv(executorRoot, spawnSync);
487− const resolver = createResolver(config, pulumi, convexEnv);
488−
489− const flags = {
490− manageCloudflareRuntime: resolver.readBool("manageCloudflareRuntime", "IAC_MANAGE_CLOUDFLARE_RUNTIME", true),
491− manageConvexEnv: resolver.readBool("manageConvexEnv", "IAC_MANAGE_CONVEX_ENV", true),
492− deployConvexFunctions: resolver.readBool("deployConvexFunctions", "IAC_DEPLOY_CONVEX_FUNCTIONS", true),
493− manageStripeCatalog: resolver.readBool("manageStripeCatalog", "IAC_MANAGE_STRIPE_CATALOG", false),
494− manageVercelProject: resolver.readBool("manageVercelProject", "IAC_MANAGE_VERCEL_PROJECT", false),
495− };
496−
497− const convexUrl = resolver.requireText("convexUrl", "CONVEX_URL");
498− const convexSiteUrl = resolver.readText("convexSiteUrl", "CONVEX_SITE_URL") ?? toSiteUrl(convexUrl);
499−
500− const stripeState = setupStripe({
501− manageStripeCatalog: flags.manageStripeCatalog,
502− resolver,
503− stripe,
504− config,
505− stage,
506− convexSiteUrl,
507− });
508−
509− const cloudflareSetup = setupCloudflareRuntime({
510− enabled: flags.manageCloudflareRuntime,
511− resolver,
512− pulumi,
513− command,
514− convexUrl,
515− executorRoot,
516− });
517−
518− const convexEnvSync = setupConvexEnvSync({
519− enabled: flags.manageConvexEnv,
520− resolver,
521− command,
522− executorRoot,
523− cloudflareSetup,
524− stripeSecretKey: stripeState.stripeSecretKey,
525− stripeWebhookSecret: stripeState.stripeWebhookSecret,
526− stripePriceId: stripeState.stripePriceId,
527− });
528−
529− const convexDeploy = setupConvexDeploy({
530− enabled: flags.deployConvexFunctions,
531− command,
532− executorRoot,
533− stage,
534− convexEnvSync,
535− cloudflareSetup,
536− });
537−
538− const doctor = setupDoctor({
539− command,
540− executorRoot,
541− stage,
542− convexDeploy,
543− convexEnvSync,
544− cloudflareSetup,
545− });
546−
547− const vercelProject = setupVercel({
548− enabled: flags.manageVercelProject,
549− resolver,
550− vercel,
551− convexUrl,
552− convexSiteUrl,
553− stripePriceId: stripeState.stripePriceId,
554− });
555−
556− return {
557− stage,
558− convexUrl,
559− convexSiteUrl,
560− cloudflareRuntimeManaged: flags.manageCloudflareRuntime,
561− convexEnvManaged: flags.manageConvexEnv,
562− convexDeployManaged: flags.deployConvexFunctions,
563− stripeManaged: flags.manageStripeCatalog,
564− vercelManaged: flags.manageVercelProject,
565− doctorCommand: "bun run --cwd executor doctor:prod",
566− doctorResourceId: doctor.id,
567− stripeProductId: stripeState.stripeProductResource?.id,
568− stripePriceId: stripeState.stripePriceId,
569− vercelProjectId: vercelProject?.id,
570− };
571− },
572−});
executor/infra/tsconfig.json+0−12
@@ -1,12 +0,0 @@
1−{
2− "compilerOptions": {
3− "target": "ES2022",
4− "module": "ESNext",
5− "moduleResolution": "Bundler",
6− "strict": true,
7− "esModuleInterop": true,
8− "skipLibCheck": true,
9− "types": ["node"]
10− },
11− "include": ["./sst.config.ts"]
12−}
executor/package.json+0−4
@@ -14,10 +14,6 @@ · 13 unmodified lines
1414 "setup:prod:env": "bun run scripts/prod/setup/prod-env.ts --from-env",
1515 "setup:prod:cloudflare": "bun run scripts/prod/setup/prod-cloudflare.ts",
1616 "setup:prod:all": "bun run setup:prod:cloudflare --deploy && bun run setup:prod:env && bun run doctor:prod",
17− "iac:install": "bun install --cwd infra",
18− "iac:deploy": "bun run --cwd infra deploy",
19− "iac:diff": "bun run --cwd infra diff",
20− "iac:remove": "bun run --cwd infra remove",
2117 "up": "bun run executor.ts up",
2218 "upgrade": "bun run executor.ts upgrade",
2319 "down": "bun run executor.ts down",
executor/packages/core/src/mcp/server-approval.ts+48−42
@@ -160,7 +160,7 @@ export function waitForTerminalTask( · 159 unmodified lines
160160 let loggedElicitationFallback = false;
161161 const seenApprovalIds = new Set<string>();
162162 let unsubscribe: (() => void) | undefined;
163− let interval: ReturnType<typeof setInterval> | undefined;
163+ let handlingApprovals = false;
164164
165165 const logElicitationFallback = (reason: string) => {
166166 if (loggedElicitationFallback) return;
@@ -172,38 +172,21 @@ export function waitForTerminalTask( · 5 unmodified lines
172172 if (settled) return;
173173 settled = true;
174174 clearTimeout(timeout);
175− if (interval) {
176− clearInterval(interval);
177− }
178175 unsubscribe?.();
179176 resolve(await service.getTask(taskId, workspaceId));
180177 };
181178
182179 const timeout = setTimeout(done, waitTimeoutMs);
183180
184− // Convex HTTP actions don't provide a real push subscription. To avoid hanging
185− // forever, we poll task state and pending approvals on an interval.
186− let polling = false;
187− const poll = async () => {
188− if (settled || polling) return;
189− polling = true;
190− try {
191− await maybeHandleApprovals();
192− const task = await service.getTask(taskId, workspaceId);
193− if (task && getTaskTerminalState(task.status)) {
194− await done();
195− }
196− } finally {
197− polling = false;
198− }
199− };
200−
201− interval = setInterval(() => {
202− void poll().catch(() => {});
203− }, 750);
204−
205181 const maybeHandleApprovals = async () => {
206− if (!elicitationEnabled || !service.listPendingApprovals || !service.resolveApproval || !onApprovalPrompt || !approvalContext) {
182+ if (
183+ settled
184+ || !elicitationEnabled
185+ || !service.listPendingApprovals
186+ || !service.resolveApproval
187+ || !onApprovalPrompt
188+ || !approvalContext
189+ ) {
207190 return;
208191 }
209192
@@ -239,24 +222,34 @@ export function waitForTerminalTask( · 29 unmodified lines
239222 }
240223 };
241224
225+ const maybeHandleApprovalsSafely = async () => {
226+ if (handlingApprovals || settled) {
227+ return;
228+ }
229+ handlingApprovals = true;
230+ try {
231+ await maybeHandleApprovals();
232+ } finally {
233+ handlingApprovals = false;
234+ }
235+ };
236+
242237 unsubscribe = service.subscribe(taskId, workspaceId, (event) => {
243238 const parsedPayload = subscriptionEventPayloadSchema.safeParse(event.payload);
244239 const type = parsedPayload.success ? parsedPayload.data.status : undefined;
245− const pendingApprovalCount = parsedPayload.success
246− ? (parsedPayload.data.pendingApprovalCount ?? 0)
247− : 0;
240+ const pendingApprovalCount = parsedPayload.success ? parsedPayload.data.pendingApprovalCount : undefined;
248241
249242 if (type && getTaskTerminalState(type)) {
250243 void done();
251244 return;
252245 }
253246
254− if (pendingApprovalCount > 0) {
255− void maybeHandleApprovals().catch(() => {});
247+ if ((pendingApprovalCount ?? 1) > 0) {
248+ void maybeHandleApprovalsSafely().catch(() => {});
256249 }
257250 });
258251
259− void poll().catch(() => {});
252+ void maybeHandleApprovalsSafely().catch(() => {});
260253
261254 void service.getTask(taskId, workspaceId).then((task) => {
262255 if (task && getTaskTerminalState(task.status)) {
@@ -289,6 +282,8 @@ export async function runTaskNowWithApprovalElicitation( · 26 unmodified lines
289282 let settled = false;
290283 let elicitationEnabled = true;
291284 let loggedElicitationFallback = false;
285+ let handlingApprovals = false;
286+ let unsubscribe: (() => void) | undefined;
292287 const seenApprovalIds = new Set<string>();
293288
294289 const logElicitationFallback = (reason: string) => {
@@ -298,7 +293,7 @@ export async function runTaskNowWithApprovalElicitation( · 3 unmodified lines
298293 };
299294
300295 const maybeHandleApprovals = async () => {
301− if (!elicitationEnabled) {
296+ if (settled || !elicitationEnabled) {
302297 return;
303298 }
304299
@@ -335,21 +330,32 @@ export async function runTaskNowWithApprovalElicitation( · 30 unmodified lines
335330 }
336331 };
337332
338− const pollApprovals = async () => {
339− while (!settled) {
340− await maybeHandleApprovals().catch(() => {});
341− if (settled) {
342− break;
343− }
344− await new Promise((resolve) => setTimeout(resolve, 750));
333+ const maybeHandleApprovalsSafely = async () => {
334+ if (handlingApprovals || settled) {
335+ return;
336+ }
337+ handlingApprovals = true;
338+ try {
339+ await maybeHandleApprovals();
340+ } finally {
341+ handlingApprovals = false;
345342 }
346343 };
347344
348− const approvalPoller = pollApprovals();
345+ unsubscribe = service.subscribe(taskId, approvalContext.workspaceId, (event) => {
346+ const parsedPayload = subscriptionEventPayloadSchema.safeParse(event.payload);
347+ const pendingApprovalCount = parsedPayload.success ? parsedPayload.data.pendingApprovalCount : undefined;
348+ if ((pendingApprovalCount ?? 1) > 0) {
349+ void maybeHandleApprovalsSafely().catch(() => {});
350+ }
351+ });
352+
353+ void maybeHandleApprovalsSafely().catch(() => {});
354+
349355 try {
350356 return await runTaskNow();
351357 } finally {
352358 settled = true;
353− void approvalPoller;
359+ unsubscribe?.();
354360 }
355361 }
executor/packages/core/src/tool-source-loaders/graphql-loader.ts+1−7
@@ -535,18 +535,12 @@ export async function loadGraphqlTools(config: GraphqlToolSourceConfig): Promise · 534 unmodified lines
535535 const inputHint = gqlFieldArgsTypeHint(field.args, typeMap);
536536 const outputHint = `{ data: ${gqlTypeToHint(field.type, typeMap)}; errors: unknown[] }`;
537537
538− // Build the example query for the description
539538 const exampleQuery = buildFieldQuery(operationType, field.name, field.args, field.type, typeMap);
540− const directCallExample = field.args.length === 0
541− ? `tools.${fieldPath}({})`
542− : `tools.${fieldPath}({ ${field.args.map((arg) => `${arg.name}: ...`).join(", ")} })`;
543539
544540 const fieldTool: ToolDefinition & { _pseudoTool: boolean } = {
545541 path: fieldPath,
546542 source: sourceKey,
547− description: field.description
548− ? `${field.description}\n\nPreferred: ${directCallExample}\nReturns: { data, errors }\nRaw GraphQL: ${sourceName}.graphql({ query: \`${exampleQuery}\`, variables: {...} })`
549− : `GraphQL ${operationType}: ${field.name}\n\nPreferred: ${directCallExample}\nReturns: { data, errors }\nRaw GraphQL: ${sourceName}.graphql({ query: \`${exampleQuery}\`, variables: {...} })`,
543+ description: field.description || `GraphQL ${operationType}: ${field.name}`,
550544 approval,
551545 credential: credentialSpec,
552546 typing: {
executor/packages/database/convex/_generated/api.d.ts+6−0
@@ -284,6 +284,12 @@ export declare const api: { · 283 unmodified lines
284284 { approvalId: string; internalSecret: string; runId: string },
285285 any
286286 >;
287+ getTaskWatchStatus: FunctionReference<
288+ "query",
289+ "public",
290+ { internalSecret: string; runId: string; workspaceId: Id<"workspaces"> },
291+ any
292+ >;
287293 handleToolCall: FunctionReference<
288294 "action",
289295 "public",
executor/packages/database/convex/http/mcp_service.ts+38−5
@@ -1,6 +1,5 @@
1−import type { ActionCtx } from "../_generated/server";
2−import { internal } from "../_generated/api";
3−import type { Id } from "../_generated/dataModel.d.ts";
1+import { ConvexClient } from "convex/browser";
2+import type { LiveTaskEvent } from "../../../core/src/events";
43 import type {
54 AnonymousContext,
65 PendingApprovalRecord,
@@ -8,6 +7,9 @@ import type { · 1 unmodified line
87 TaskRecord,
98 ToolDescriptor,
109 } from "../../../core/src/types";
10+import { api, internal } from "../_generated/api";
11+import type { Id } from "../_generated/dataModel.d.ts";
12+import type { ActionCtx } from "../_generated/server";
1113
1214 export function createMcpExecutorService(ctx: ActionCtx) {
1315 return {
@@ -41,8 +43,39 @@ export function createMcpExecutorService(ctx: ActionCtx) { · 27 unmodified lines
4143 }
4244 return null;
4345 },
44− subscribe: () => {
45− return () => {};
46+ subscribe: (taskId: string, workspaceId: Id<"workspaces">, listener: (event: LiveTaskEvent) => void) => {
47+ const callbackConvexUrl = process.env.CONVEX_URL ?? process.env.CONVEX_SITE_URL;
48+ const callbackInternalSecret = process.env.EXECUTOR_INTERNAL_TOKEN;
49+ if (!callbackConvexUrl || !callbackInternalSecret) {
50+ return () => {};
51+ }
52+
53+ const client = new ConvexClient(callbackConvexUrl, {
54+ skipConvexDeploymentUrlCheck: true,
55+ });
56+ let sequence = 0;
57+ const unsubscribe = client.onUpdate(
58+ api.runtimeCallbacks.getTaskWatchStatus,
59+ {
60+ internalSecret: callbackInternalSecret,
61+ runId: taskId,
62+ workspaceId,
63+ },
64+ (payload: unknown) => {
65+ sequence += 1;
66+ listener({
67+ id: sequence,
68+ eventName: "task",
69+ payload,
70+ createdAt: Date.now(),
71+ });
72+ },
73+ );
74+
75+ return () => {
76+ unsubscribe();
77+ client.close();
78+ };
4679 },
4780 bootstrapAnonymousContext: async (sessionId?: string): Promise<AnonymousContext> => {
4881 return await ctx.runMutation(internal.database.bootstrapAnonymousSession, { sessionId });
executor/packages/database/convex/runtimeCallbacks.ts+13−0
@@ -4,6 +4,7 @@ import { customAction, customMutation, customQuery } from "../../core/src/functi · 3 unmodified lines
44 import {
55 completeRunHandler,
66 getApprovalStatusHandler,
7+ getTaskWatchStatusHandler,
78 handleToolCallHandler,
89 } from "../src/runtime-callbacks/handlers";
910 import { jsonObjectValidator } from "../src/database/validators";
@@ -48,3 +49,15 @@ export const getApprovalStatus = customQuery({ · 38 unmodified lines
4849 return await getApprovalStatusHandler(ctx, internal, args);
4950 },
5051 });
52+
53+export const getTaskWatchStatus = customQuery({
54+ method: "GET",
55+ args: {
56+ internalSecret: v.string(),
57+ runId: v.string(),
58+ workspaceId: v.id("workspaces"),
59+ },
60+ handler: async (ctx, args) => {
61+ return await getTaskWatchStatusHandler(ctx, internal, args);
62+ },
63+});
executor/packages/database/src/runtime-callbacks/handlers.ts+36−0
@@ -1,4 +1,6 @@
11 import type { ActionCtx, MutationCtx, QueryCtx } from "../../convex/_generated/server";
2+import type { Id } from "../../convex/_generated/dataModel.d.ts";
3+import type { PendingApprovalRecord } from "../../../core/src/types";
24
35 type InternalApi = typeof import("../../convex/_generated/api").internal;
46
@@ -76,3 +78,37 @@ export async function getApprovalStatusHandler( · 71 unmodified lines
7678
7779 return { status: approval.status };
7880 }
81+
82+export async function getTaskWatchStatusHandler(
83+ ctx: Pick<QueryCtx, "runQuery">,
84+ internalApi: InternalApi,
85+ args: {
86+ internalSecret: string;
87+ runId: string;
88+ workspaceId: Id<"workspaces">;
89+ },
90+) {
91+ requireInternalSecret(args.internalSecret);
92+
93+ const task = await ctx.runQuery(internalApi.database.getTaskInWorkspace, {
94+ taskId: args.runId,
95+ workspaceId: args.workspaceId,
96+ });
97+
98+ if (!task) {
99+ return {
100+ pendingApprovalCount: 0,
101+ };
102+ }
103+
104+ const pendingApprovals = await ctx.runQuery(internalApi.database.listPendingApprovals, {
105+ workspaceId: args.workspaceId,
106+ });
107+
108+ const pendingApprovalCount = pendingApprovals.filter((approval: PendingApprovalRecord) => approval.taskId === args.runId).length;
109+
110+ return {
111+ status: task.status,
112+ pendingApprovalCount,
113+ };
114+}
executor/packages/database/src/runtime-node/runtime-dispatch.ts+90−19
@@ -1,4 +1,5 @@
1−import { ConvexHttpClient } from "convex/browser";
1+import { ConvexClient, ConvexHttpClient } from "convex/browser";
2+import { Result } from "better-result";
23 import { z } from "zod";
34 import { api } from "../../convex/_generated/api";
45 import { dispatchCodeWithCloudflareWorkerLoader } from "../../../core/src/runtimes/cloudflare/worker/loader-runtime";
@@ -14,6 +15,7 @@ import type { · 9 unmodified lines
1415 import { describeError } from "../../../core/src/utils";
1516
1617 const recordSchema = z.record(z.unknown());
18+const APPROVAL_SUBSCRIPTION_TIMEOUT_MS = 10 * 60 * 1000;
1719
1820 function toRecord(value: unknown): Record<string, unknown> {
1921 const parsed = recordSchema.safeParse(value);
@@ -49,28 +51,97 @@ class CallbackExecutionAdapter implements ExecutionAdapter { · 29 unmodified lines
4951 });
5052 }
5153
54+ private createRealtimeClient(): ConvexClient {
55+ return new ConvexClient(this.callbackConfig.callbackConvexUrl, {
56+ skipConvexDeploymentUrlCheck: true,
57+ });
58+ }
59+
60+ private async waitForApprovalUpdate(runId: string, approvalId: string): Promise<void> {
61+ const client = this.createRealtimeClient();
62+
63+ await new Promise<void>((resolve, reject) => {
64+ let settled = false;
65+
66+ const timer = setTimeout(() => {
67+ if (settled) return;
68+ settled = true;
69+ unsubscribe();
70+ client.close();
71+ reject(new Error(`Timed out waiting for approval update: ${approvalId}`));
72+ }, APPROVAL_SUBSCRIPTION_TIMEOUT_MS);
73+
74+ const unsubscribe = client.onUpdate(
75+ api.runtimeCallbacks.getApprovalStatus,
76+ {
77+ internalSecret: this.callbackConfig.callbackInternalSecret,
78+ runId,
79+ approvalId,
80+ },
81+ (value: { status?: "pending" | "approved" | "denied" | "missing" } | null | undefined) => {
82+ const status = value?.status;
83+ if (!status || status === "pending") {
84+ return;
85+ }
86+
87+ if (status === "missing") {
88+ if (settled) return;
89+ settled = true;
90+ clearTimeout(timer);
91+ unsubscribe();
92+ client.close();
93+ reject(new Error(`Approval not found: ${approvalId}`));
94+ return;
95+ }
96+
97+ if (settled) return;
98+ settled = true;
99+ clearTimeout(timer);
100+ unsubscribe();
101+ client.close();
102+ resolve();
103+ },
104+ );
105+ });
106+ }
107+
52108 async invokeTool(call: ToolCallRequest): Promise<ToolCallResult> {
53− const response = await this.client.action(api.runtimeCallbacks.handleToolCall, {
54− internalSecret: this.callbackConfig.callbackInternalSecret,
55− runId: call.runId,
56− callId: call.callId,
57− toolPath: call.toolPath,
58− input: toRecord(call.input),
59− }).catch((error: unknown) => ({
60− ok: false,
61− kind: "failed",
62− error: `Node runtime callback failed: ${describeError(error)}`,
63− } as const));
64−
65− const parsed = decodeToolCallResultFromTransport(response);
66− if (!parsed) {
67− return {
109+ while (true) {
110+ const response = await this.client.action(api.runtimeCallbacks.handleToolCall, {
111+ internalSecret: this.callbackConfig.callbackInternalSecret,
112+ runId: call.runId,
113+ callId: call.callId,
114+ toolPath: call.toolPath,
115+ input: toRecord(call.input),
116+ }).catch((error: unknown) => ({
68117 ok: false,
69118 kind: "failed",
70− error: "Node runtime callback returned invalid payload",
71− };
119+ error: `Node runtime callback failed: ${describeError(error)}`,
120+ } as const));
121+
122+ const parsed = decodeToolCallResultFromTransport(response);
123+ if (!parsed) {
124+ return {
125+ ok: false,
126+ kind: "failed",
127+ error: "Node runtime callback returned invalid payload",
128+ };
129+ }
130+
131+ if (!parsed.ok && parsed.kind === "pending") {
132+ const waitResult = await Result.tryPromise(() => this.waitForApprovalUpdate(call.runId, parsed.approvalId));
133+ if (waitResult.isErr()) {
134+ return {
135+ ok: false,
136+ kind: "failed",
137+ error: `Node runtime approval subscription failed: ${describeError(waitResult.error.cause)}`,
138+ };
139+ }
140+ continue;
141+ }
142+
143+ return parsed;
72144 }
73− return parsed;
74145 }
75146 }
76147
package.json+2−3
@@ -5,7 +5,6 @@ · 4 unmodified lines
55 "workspaces": [
66 "executor/apps/*",
77 "executor/packages/*",
8− "executor/infra",
98 "sources",
109 "assistant",
1110 "assistant/packages/*"
@@ -30,8 +29,8 @@ · 18 unmodified lines
3029 "test:assistant": "bun run --cwd assistant test",
3130 "typecheck": "bun run typecheck:workspaces",
3231 "typecheck:slow": "bun run typecheck:workspaces:slow",
33− "typecheck:workspaces": "bun run --filter \"@executor/*\" --filter \"executor-infra\" --filter \"@proto/sources\" --filter \"@assistant/*\" --filter \"@openassistant/reacord\" --if-present typecheck",
34− "typecheck:workspaces:slow": "bun run --filter \"@executor/*\" --filter \"executor-infra\" --filter \"@proto/sources\" --filter \"@assistant/*\" --filter \"@openassistant/reacord\" --if-present typecheck:slow",
32+ "typecheck:workspaces": "bun run --filter \"@executor/*\" --filter \"@proto/sources\" --filter \"@assistant/*\" --filter \"@openassistant/reacord\" --if-present typecheck",
33+ "typecheck:workspaces:slow": "bun run --filter \"@executor/*\" --filter \"@proto/sources\" --filter \"@assistant/*\" --filter \"@openassistant/reacord\" --if-present typecheck:slow",
3534 "typecheck:executor": "bunx --package @typescript/native-preview tsgo --noEmit -p executor/tsconfig.json",
3635 "typecheck:executor:slow": "bunx tsc --noEmit -p executor/tsconfig.json",
3736 "typecheck:assistant": "bunx --package @typescript/native-preview tsgo --noEmit -p assistant/packages/server/tsconfig.json && bunx --package @typescript/native-preview tsgo --noEmit -p assistant/packages/bot/tsconfig.json",