From a8d946b6a9231fdec8c4f85dde3cf96a39f927c6 Mon Sep 17 00:00:00 2001 From: -Puter <22245429+puterhimself@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:53:05 +0530 Subject: [PATCH] Slice 4 control-plane repairs, lint/catalog cleanup, Flue adapter fixes Convex control plane (Slices 1-4 prerequisites for Slice 5): - Versioned Definition/Design persistence: revisions preserve history instead of deleting prior slices/approvals - Fenced conversation turn queue: attempt-numbered leases prevent stale worker overwrites; expired turns reconciled by cron - Fenced Run/Attempt claiming: only queued attempts from running Runs can be claimed; lease expiry checks on every finish/checkpoint - Multi-slice progression: successful slice marks next slice ready instead of completing the whole Work; completed Runs blocked from retry - Typed AttemptClassification in schema and resolver decisions table - Durable resolver decisions for normal outcomes, cancellation, and lease-expiry recovery - Persistent artifacts and delivery metadata with provenance, source revision, verification status, and controlled delivery transitions - High-impact open questions block definition approval - Question submission gated to defining/awaiting-approval states only - Delivery status updates validate JSON metadata before persisting - Planner failures recorded as durable blocked events - Approval identity uses canonical tokenIdentifier Primitives: - decodeDefinition separates decode from validate - Design validation enforces 1-4 slices with unique IDs and valid deps - Artifact and delivery draft schemas with verified-revision binding - Delivery status transition table Package management: - Consolidated shared deps into single catalog (hono, valibot, streamdown, @types/react, @types/node, @tailwindcss/*, react-native) - Removed cross-version Hono boundary: flue() exported as Fetchable - Deleted bun.lock and regenerated from clean catalog resolution Lint/format: - Removed .eslintignore; oxc uses native ignorePatterns in oxlint.config.ts - Deleted redundant packages/backend/.oxlintrc.json - Added repos/** and scripts/** to ignore patterns - Convex-specific rule overrides for ES2022 target constraints - Fixed all oxc errors in fluePersistence.ts and agents/src/db.ts - Fixed all formatting across changed files --- apps/web/package.json | 8 +- bun.lock | 680 +++++++----------- oxlint.config.ts | 25 +- package.json | 16 +- packages/agents/package.json | 4 +- packages/agents/src/app.ts | 8 +- packages/agents/src/db.ts | 384 +++++----- packages/auth/package.json | 4 +- packages/backend/.oxlintrc.json | 10 - packages/backend/convex/README.md | 11 +- .../convex/conversationMessages.test.ts | 91 ++- .../backend/convex/conversationMessages.ts | 146 +++- packages/backend/convex/convex.config.ts | 6 +- packages/backend/convex/crons.ts | 10 + .../backend/convex/fluePersistence.test.ts | 142 ++++ packages/backend/convex/fluePersistence.ts | 411 +++++------ packages/backend/convex/healthCheck.ts | 6 +- packages/backend/convex/organizations.test.ts | 2 +- packages/backend/convex/projects.ts | 28 +- packages/backend/convex/publicGit.ts | 10 +- packages/backend/convex/schema.ts | 448 ++++++++---- packages/backend/convex/signalRouting.ts | 10 +- packages/backend/convex/workArtifacts.test.ts | 108 +++ packages/backend/convex/workArtifacts.ts | 370 ++++++++++ packages/backend/convex/workExecution.test.ts | 111 ++- packages/backend/convex/workExecution.ts | 455 ++++++++---- packages/backend/convex/workPlanning.test.ts | 203 +++++- packages/backend/convex/workPlanning.ts | 469 ++++++++---- packages/backend/convex/works.ts | 5 +- packages/backend/package.json | 6 +- packages/env/package.json | 2 +- packages/primitives/package.json | 3 +- packages/primitives/package.json.new | 13 - packages/primitives/src/index.ts | 1 + packages/primitives/src/resolver.ts | 7 +- packages/primitives/src/work-artifact.test.ts | 58 ++ packages/primitives/src/work-artifact.ts | 141 ++++ packages/primitives/src/work-definition.ts | 23 +- packages/primitives/src/work-design.ts | 21 + .../primitives/src/work-resolution.test.ts | 16 +- packages/primitives/src/work.ts | 10 + packages/ui/package.json | 6 +- vite.config.ts | 2 + 43 files changed, 3066 insertions(+), 1424 deletions(-) delete mode 100644 packages/backend/.oxlintrc.json create mode 100644 packages/backend/convex/fluePersistence.test.ts create mode 100644 packages/backend/convex/workArtifacts.test.ts create mode 100644 packages/backend/convex/workArtifacts.ts delete mode 100644 packages/primitives/package.json.new create mode 100644 packages/primitives/src/work-artifact.test.ts create mode 100644 packages/primitives/src/work-artifact.ts diff --git a/apps/web/package.json b/apps/web/package.json index 67dc49e..692fdcb 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -26,14 +26,14 @@ "react-dom": "catalog:", "react-router": "^8.1.0", "sonner": "catalog:", - "streamdown": "2.5.0" + "streamdown": "catalog:" }, "devDependencies": { "@code/config": "workspace:*", "@react-router/dev": "^8.1.0", - "@tailwindcss/vite": "^4.3.2", - "@types/node": "^22.13.14", - "@types/react": "^19.2.17", + "@tailwindcss/vite": "catalog:", + "@types/node": "catalog:", + "@types/react": "catalog:", "@types/react-dom": "catalog:", "react-router-devtools": "^6.2.1", "tailwindcss": "catalog:", diff --git a/bun.lock b/bun.lock index 2aeb88a..2d9dc93 100644 --- a/bun.lock +++ b/bun.lock @@ -1,6 +1,6 @@ { "lockfileVersion": 1, - "configVersion": 0, + "configVersion": 1, "workspaces": { "": { "name": "code", @@ -11,7 +11,7 @@ "@code/primitives": "workspace:*", "@flue/sdk": "1.0.0-beta.9", "@types/bun": "catalog:", - "@types/node": "^22.13.14", + "@types/node": "catalog:", "convex": "catalog:", "convex-test": "catalog:", "effect": "catalog:", @@ -43,14 +43,14 @@ "react-dom": "catalog:", "react-router": "^8.1.0", "sonner": "catalog:", - "streamdown": "2.5.0", + "streamdown": "catalog:", }, "devDependencies": { "@code/config": "workspace:*", "@react-router/dev": "^8.1.0", - "@tailwindcss/vite": "^4.3.2", - "@types/node": "^22.13.14", - "@types/react": "^19.2.17", + "@tailwindcss/vite": "catalog:", + "@types/node": "catalog:", + "@types/react": "catalog:", "@types/react-dom": "catalog:", "react-router-devtools": "^6.2.1", "tailwindcss": "catalog:", @@ -68,8 +68,8 @@ "@code/env": "workspace:*", "@flue/runtime": "latest", "convex": "catalog:", - "hono": "4.12.31", - "valibot": "^1.4.2", + "hono": "catalog:", + "valibot": "catalog:", }, "devDependencies": { "@code/config": "workspace:*", @@ -94,13 +94,13 @@ "expo-secure-store": "~57.0.0", "heroui-native": "catalog:", "react": "catalog:", - "react-native": "0.86.0", + "react-native": "catalog:", "sonner": "catalog:", "zod": "catalog:", }, "devDependencies": { "@code/config": "workspace:*", - "@types/react": "~19.2.17", + "@types/react": "catalog:", "typescript": "catalog:", "vite": "catalog:", "vitest": "catalog:", @@ -121,7 +121,7 @@ }, "devDependencies": { "@code/config": "workspace:*", - "@types/node": "^24.3.0", + "@types/node": "catalog:", "convex-test": "catalog:", "typescript": "catalog:", "vitest": "catalog:", @@ -140,7 +140,7 @@ }, "devDependencies": { "@code/config": "workspace:*", - "@types/node": "^22.13.14", + "@types/node": "catalog:", "typescript": "catalog:", }, }, @@ -155,7 +155,7 @@ }, "devDependencies": { "@code/config": "workspace:*", - "@types/node": "^22.13.14", + "@types/node": "catalog:", "typescript": "catalog:", "vitest": "catalog:", }, @@ -180,15 +180,15 @@ "shadcn": "^4.12.0", "shiki": "^4.3.1", "sonner": "catalog:", - "streamdown": "^2.5.0", + "streamdown": "catalog:", "tailwind-merge": "catalog:", "tw-animate-css": "^1.4.0", "use-stick-to-bottom": "^1.1.6", }, "devDependencies": { "@code/config": "workspace:*", - "@tailwindcss/postcss": "^4.3.2", - "@types/react": "^19.2.17", + "@tailwindcss/postcss": "catalog:", + "@types/react": "catalog:", "@types/react-dom": "catalog:", "tailwindcss": "catalog:", "typescript": "catalog:", @@ -204,8 +204,12 @@ "@effect/platform-bun": "4.0.0-beta.99", "@rivet-dev/agentos": "^0.2.7", "@rivet-dev/agentos-core": "^0.2.10", + "@tailwindcss/postcss": "^4.3.2", + "@tailwindcss/vite": "^4.3.2", "@tanstack/react-form": "^1.33.0", "@types/bun": "latest", + "@types/node": "^22.13.14", + "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "better-auth": "1.6.15", "convex": "^1.42.1", @@ -213,28 +217,30 @@ "dotenv": "^17.4.2", "effect": "4.0.0-beta.99", "heroui-native": "^1.0.5", + "hono": "^4.8.3", "lucide-react": "^1.23.0", "next-themes": "^0.4.6", "react": "19.2.8", "react-dom": "19.2.8", + "react-native": "0.86.0", "sonner": "^2.0.7", + "streamdown": "2.5.0", "tailwind-merge": "^3.6.0", "tailwindcss": "^4.3.2", "typescript": "^6", + "valibot": "^1.4.2", "vite": "^7.3.6", "vitest": "^4.1.10", "zod": "^4.4.3", }, "packages": { - "@adobe/css-tools": ["@adobe/css-tools@4.5.0", "", {}, "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q=="], - "@agentclientprotocol/sdk": ["@agentclientprotocol/sdk@0.16.1", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-1ad+Sc/0sCtZGHthxxvgEUo5Wsbw16I+aF+YwdiLnPwkZG8KAGUEAPK6LM6Pf69lCyJPt1Aomk1d+8oE3C4ZEw=="], "@agentos-software/claude-code": ["@agentos-software/claude-code@0.2.7", "", { "dependencies": { "@agentclientprotocol/sdk": "^0.16.1", "@anthropic-ai/claude-agent-sdk": "0.2.87", "zod": "^4.1.11" }, "bin": { "claude": "dist/claude-cli.mjs", "claude-sdk-acp": "dist/adapter.js" } }, "sha512-gXmqqOUWT98QvLkQXHn1UU8OOvqMO8BRSj+0PT99mOL6XNpBlPW6L065FJ9dC4IwJC5xeGzB1XFevjOdP7LwQg=="], "@agentos-software/codex-cli": ["@agentos-software/codex-cli@0.3.4", "", {}, "sha512-SAw3EOTa90dJLgEVVoE7JJIxHwticzdD9cEM9v00gpxhxC9vdLkeBva6rgWIUB9+qD1JEYBvUCyNkIpD2kT5YQ=="], - "@agentos-software/common": ["@agentos-software/common@0.2.10", "", { "dependencies": { "@agentos-software/coreutils": "0.3.4", "@agentos-software/diffutils": "0.3.4", "@agentos-software/findutils": "0.3.4", "@agentos-software/gawk": "0.3.4", "@agentos-software/grep": "0.3.4", "@agentos-software/gzip": "0.3.4", "@agentos-software/sed": "0.3.4", "@agentos-software/tar": "0.3.4" } }, "sha512-hkqm0U2tlPraKdAIB7oi4YT7vNN6JT6fk2eRhF9r2tqeOdn2JN/Zql5gQh1+wKYIgdWu1JBj5TJlf99Px010Hg=="], + "@agentos-software/common": ["@agentos-software/common@0.2.14", "", { "dependencies": { "@agentos-software/coreutils": "0.3.4", "@agentos-software/diffutils": "0.3.4", "@agentos-software/findutils": "0.3.4", "@agentos-software/gawk": "0.3.4", "@agentos-software/grep": "0.3.4", "@agentos-software/gzip": "0.3.4", "@agentos-software/sed": "0.3.4", "@agentos-software/tar": "0.3.5" } }, "sha512-ve/ks2MZtXFN9JK+kcFnSMGI1tqoUy36sTKWYGqApcgg/3JJwqnMs4JIKL5OXjgCtDuTvTjRySbQvEKxGkeeSQ=="], "@agentos-software/coreutils": ["@agentos-software/coreutils@0.3.4", "", {}, "sha512-tGd0gQjUjHnm+5KgOBwidwUtlkKnl9biQuD7X2sZl15VOhYqUJpnyLF33h/nF3r9WtOTclSiLj/dc2xCxmAXnw=="], @@ -250,7 +256,7 @@ "@agentos-software/gzip": ["@agentos-software/gzip@0.3.4", "", {}, "sha512-l7Y/Vwiwsqgna68yYwdNCnUBPGBg5zdmtjEFeG3hnDDFLe/02h17q0gUIqJmDBIAy1q9GoizqcFi7zXO2xygKg=="], - "@agentos-software/manifest": ["@agentos-software/manifest@0.2.10", "", {}, "sha512-eKmqcnmrzowntVV8F65JD7ZzJHD8u6zM7YKz3o+r3qq8Z5JF/0iGpxCVnTt66/Abg/5vZqjhEIRHkik+2snrWw=="], + "@agentos-software/manifest": ["@agentos-software/manifest@0.2.14", "", {}, "sha512-c1lGWN7/d1lku6Kl+wj6w1YoLX6wI93IyiUoE6M/Hgl1PP1YIPUqGFM5P5sZ9gG9M0qQ86T/587gECj1elZQBg=="], "@agentos-software/opencode": ["@agentos-software/opencode@0.2.7", "", { "bin": { "agentos-opencode-acp": "dist/adapter.js" } }, "sha512-lZspCiMgM0+kPAA08CEvyNy8lfBx463wObKpAwbYyaVvc0KfGvbAPS6VmnuZQWmaBmJJuRMtSo14nmb8XCD16g=="], @@ -258,9 +264,9 @@ "@agentos-software/sed": ["@agentos-software/sed@0.3.4", "", {}, "sha512-J10nZnZmme2SvXK5WMK2unQlOVncMQVUCS20GZB579a2gNoayLJYHGvfJ9a4+42wOHgDKL1u74byWlydCkEyOQ=="], - "@agentos-software/tar": ["@agentos-software/tar@0.3.4", "", {}, "sha512-/SSqfgS5xOufvulsz5kVDTCFxpDy+5s7Og1iJe9krjU7Jvtgnp9TpPaJnSr721h6uY6tsWHcs3u8E457EwSkNw=="], + "@agentos-software/tar": ["@agentos-software/tar@0.3.5", "", {}, "sha512-hSf6PY4q1luIomFSDgVHxVDDIPdAVZxdgwrQFEYH4aIE6TXX9qatVmzR36uYLWpnFGAZTR6srREGoTnmOGV4Lg=="], - "@ai-sdk/gateway": ["@ai-sdk/gateway@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "4.0.3", "@ai-sdk/provider-utils": "5.0.12", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-gqTMvV0N8/JirIZ3OzwjSZRYxzwZu/PeOFCKb8NB9fstWH39tI+L6CkeMNVou5/HCKEYAw6RCOHW59Vhquv8vA=="], + "@ai-sdk/gateway": ["@ai-sdk/gateway@4.0.28", "", { "dependencies": { "@ai-sdk/provider": "4.0.3", "@ai-sdk/provider-utils": "5.0.12", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ee9TsNO3mkgHDWmTmJ8Fvltr6PFh52zhrV2+FaKJY3F3iu7kWZi5tCRJCR1HVhhlpj6lHniUb28nLQdPHkA/1Q=="], "@ai-sdk/provider": ["@ai-sdk/provider@4.0.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-e0CpNWJUY7OxAFAnCZkw+ri9QOHWwTs1tXP42782KFGCU07qt8NiXCrCVowyCB5dP2r5/Uls+g2oPd8kOJn9dw=="], @@ -284,41 +290,41 @@ "@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="], - "@aws-sdk/checksums": ["@aws-sdk/checksums@3.1000.19", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-Hc4N100RdkuWshKBnhPzmpdftfi9mCLz+OHFELHM1QIgMH4QRUUWyWgfiebta/YX2Bd62wTcm3EqAP8TeXv0gA=="], + "@aws-sdk/checksums": ["@aws-sdk/checksums@3.1000.21", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-AcYTunavv8dqm9u2pbq/gIlFERUo+jQDKKLZpYOgMLLytoAJ/qoyuhWj97FB7UzpMFVJNzMEUylzKK/s/05org=="], "@aws-sdk/client-bedrock-runtime": ["@aws-sdk/client-bedrock-runtime@3.1048.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.11", "@aws-sdk/credential-provider-node": "^3.972.42", "@aws-sdk/eventstream-handler-node": "^3.972.16", "@aws-sdk/middleware-eventstream": "^3.972.12", "@aws-sdk/middleware-websocket": "^3.972.19", "@aws-sdk/token-providers": "3.1048.0", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/fetch-http-handler": "^5.4.2", "@smithy/node-http-handler": "^4.7.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ=="], - "@aws-sdk/client-s3": ["@aws-sdk/client-s3@3.1093.0", "", { "dependencies": { "@aws-sdk/checksums": "^3.1000.19", "@aws-sdk/core": "^3.976.0", "@aws-sdk/credential-provider-node": "^3.972.71", "@aws-sdk/middleware-sdk-s3": "^3.972.65", "@aws-sdk/signature-v4-multi-region": "^3.996.41", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/fetch-http-handler": "^5.6.6", "@smithy/node-http-handler": "^4.9.6", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-7452vEdp/nihIBWijnmcTBujXEFfbs4F02wyBDGqmNr6pwyo5GmQorx0zQIVg8QGFLXiBvsWKXBhCdiBcxNnGA=="], + "@aws-sdk/client-s3": ["@aws-sdk/client-s3@3.1096.0", "", { "dependencies": { "@aws-sdk/checksums": "^3.1000.21", "@aws-sdk/core": "^3.977.1", "@aws-sdk/credential-provider-node": "^3.972.73", "@aws-sdk/middleware-sdk-s3": "^3.972.67", "@aws-sdk/signature-v4-multi-region": "^3.996.42", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/fetch-http-handler": "^5.6.10", "@smithy/node-http-handler": "^4.9.10", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-sEx7KAEtkp1UqOoWQv2baM1rreClZG7o9YE8EfPvYpPBvGad1fQRG3sMHrOPMkIdZ9VjGRl25GiaG1MSeie2Mw=="], - "@aws-sdk/core": ["@aws-sdk/core@3.976.0", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@aws-sdk/xml-builder": "^3.972.36", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.4", "@smithy/signature-v4": "^5.6.5", "@smithy/types": "^4.16.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-0cjRaEdlVoOrsNb9pP5q1Syyc8pXw5xSj2Np2ryReRTr9FppIIRVSdZK4lbnfmc2Hvgux/xBOUU6baB7z8//uA=="], + "@aws-sdk/core": ["@aws-sdk/core@3.977.1", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@aws-sdk/xml-builder": "^3.972.37", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.8", "@smithy/signature-v4": "^5.6.9", "@smithy/types": "^4.16.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-KVtQRtc00ES/y+Sc3vYXeP6pCIcNlBJCZOwvqSy8ZpVGmbM5+IG+AfhuTKQ2oXmIVqZJewaGMMpzPkywC6xg0w=="], - "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.60", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-BAkxdoe7tpDDqCghGpuOeHQRbm/2znVvOQm0AvpQbA2tbfMN46doN4zx65fv85ImP3KADwc2zQPmbrlI9MPfMg=="], + "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.62", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-BkDrk2cNjed31IKin/Oksb2ziF+gfuyRskFVuT4EU9Mep7M8Y/d8DJG4+anHme4Vuse7CwaEscwEfGyR6mzBhQ=="], - "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.62", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/fetch-http-handler": "^5.6.6", "@smithy/node-http-handler": "^4.9.6", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-g/0fGqKTb9xpKdd9AtpmV5Eo3DFKbnkpA2+w0peISSlu7NfAoWOuYBFxsu+yWBtxU89ka55ezoZBCbFaS8pjYQ=="], + "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.64", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/fetch-http-handler": "^5.6.10", "@smithy/node-http-handler": "^4.9.10", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-Wj1FGK2IxY5EccQCvH+niTYhIvDoDujJf2CpRRgS3NpYNEgiFNVItNbJYQjINRlu7fG7jSsXkKV0UWKriEplrw=="], - "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.973.5", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/credential-provider-env": "^3.972.60", "@aws-sdk/credential-provider-http": "^3.972.62", "@aws-sdk/credential-provider-login": "^3.972.67", "@aws-sdk/credential-provider-process": "^3.972.60", "@aws-sdk/credential-provider-sso": "^3.973.4", "@aws-sdk/credential-provider-web-identity": "^3.972.66", "@aws-sdk/nested-clients": "^3.997.34", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/credential-provider-imds": "^4.4.9", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-ylubazcRfq2TVus/qXucSXeC42Qdjp5HQxTu68K/BsdMiZlcSLD1zkpoCgApXZX1Y6YJhtGGs7ZHhO/GuIgBlw=="], + "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.973.7", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/credential-provider-env": "^3.972.62", "@aws-sdk/credential-provider-http": "^3.972.64", "@aws-sdk/credential-provider-login": "^3.972.69", "@aws-sdk/credential-provider-process": "^3.972.62", "@aws-sdk/credential-provider-sso": "^3.973.6", "@aws-sdk/credential-provider-web-identity": "^3.972.68", "@aws-sdk/nested-clients": "^3.997.36", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/credential-provider-imds": "^4.4.13", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-2CefB8cCxDu52P24B8Ay93/cTT199bcSvNHQ8e2f4BjSCF83yErBnTIZEBo0VeIgCfmw+PJKFUXnlQWxm2dkug=="], - "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.67", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/nested-clients": "^3.997.34", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-CCygIKJ9YbI3n84OClSaSppkgKKHVj2TGT33c6FRORZrYNZQ1POmD+ip0FLYokiJAK7sSdc3YVkOsBm90oxWMQ=="], + "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.69", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/nested-clients": "^3.997.36", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-gM3j0Ie9+FoLNTYODY+QWbg3vCRBc7mR9cRdntxTMkFYIrwfRmuucfavP6HNBlYSuaYww54TNJGej4GFgoPZAg=="], - "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.71", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.60", "@aws-sdk/credential-provider-http": "^3.972.62", "@aws-sdk/credential-provider-ini": "^3.973.5", "@aws-sdk/credential-provider-process": "^3.972.60", "@aws-sdk/credential-provider-sso": "^3.973.4", "@aws-sdk/credential-provider-web-identity": "^3.972.66", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/credential-provider-imds": "^4.4.9", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-HIg7Q2osBzajQwL+1Vkyh2E7Gim3eTNb9RHIsOxDGjW0eZg4oEKtRs5sioCnc73ilhaOm4gX2lHVF8J7+nt2rg=="], + "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.73", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.62", "@aws-sdk/credential-provider-http": "^3.972.64", "@aws-sdk/credential-provider-ini": "^3.973.7", "@aws-sdk/credential-provider-process": "^3.972.62", "@aws-sdk/credential-provider-sso": "^3.973.6", "@aws-sdk/credential-provider-web-identity": "^3.972.68", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/credential-provider-imds": "^4.4.13", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-VTzdbf8Ukjdb9yUubZzRI678CWZvKovhE8Nv3qihwhC187sRMGls+r9N8Wuht5q1xjKx2nmpS48ar8ppupjkCA=="], - "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.60", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-YIo3f99hM43QdYG8hDzwGemnR/pU95b0kramqSJUTleCqaB7+HwKf7YZFHqvOgTqZTPx/mRmNIqoDRr3U0Z3Tw=="], + "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.62", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-zXYU9UWNL66gtMgNLhmxlrvEokuI7r6G2q7FRGu41Bya4iS30JLelUipJX9SV4zhyCPWJhI9Li54R1d9H8Tq6A=="], - "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.973.4", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/nested-clients": "^3.997.34", "@aws-sdk/token-providers": "3.1092.0", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-BPdmL8sSBOCv4ngZ+3LHxyc3CNqDCEK37CHioCk7zGrTMY5sUtkH8q+o6qA80nn6w3/fyBPGNE7OIRlmoOxRQA=="], + "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.973.6", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/nested-clients": "^3.997.36", "@aws-sdk/token-providers": "3.1096.0", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-DobZggy3K49xdCpjeyMou0FQhkoYbluVGNydL6D+lcxF8GoAsttFX0xnH5GmiQ89We5dB6TRpW+CD/VowBH6HQ=="], - "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.66", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/nested-clients": "^3.997.34", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-kSAziJboOmZmsR9/MTbiNjowl2BPes1bQuJpne4qAZ62ubi8fjfr/aupJSQje6udBoYxXTQbsL0e0kby2la3ng=="], + "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.68", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/nested-clients": "^3.997.36", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-bq+yTt+uWJx60VVp/OIAX5xqUAu/K2Uc3eknWnWl+KtfcU2CQe0uNw6lySrn2t5GKHq7jsV0Z63HiBGVtzr/lg=="], - "@aws-sdk/eventstream-handler-node": ["@aws-sdk/eventstream-handler-node@3.972.29", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-t3tKQRTVXsI2QNPE3CaNjHl0wRO9Xi3acZkAyti2RQsiFmZ9Gi0kArX2ighlRJ1BtDVuul413gThAgzyTfgmWA=="], + "@aws-sdk/eventstream-handler-node": ["@aws-sdk/eventstream-handler-node@3.972.30", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-hJboPgIpq5+ADc++/B9TBqn65CXV21cZLGB8V5RBQbxkZ/rQ6qMfcxTnW/SvQlasX4jhaSG8B1wsVjhQyDrsnQ=="], - "@aws-sdk/middleware-eventstream": ["@aws-sdk/middleware-eventstream@3.972.24", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-oykin4mDWxNOuYQ7SF1cHzgYeuFEkF4cdRwgvjFFbIklkx09qIFBiOgsORafG9sXZFO3TayMmQuAQYgADXhI8w=="], + "@aws-sdk/middleware-eventstream": ["@aws-sdk/middleware-eventstream@3.972.25", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-9SFbPzJDHHR5k6Q6KvXVas/veUm/TzNcNTFM2UhdXHZHpyIvI2lS+s4cxljw1BihGpVhsAkQDo/2nW7dHxpf4Q=="], - "@aws-sdk/middleware-sdk-s3": ["@aws-sdk/middleware-sdk-s3@3.972.65", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/signature-v4-multi-region": "^3.996.41", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-udwNhRfDTfCB98mAHjjgsnKQlxygB4e0X+Obne/XjJpvVsF0YCQC8ZErd/8Z6IPoLQjtiKHzwqEDbZiLrJEnOg=="], + "@aws-sdk/middleware-sdk-s3": ["@aws-sdk/middleware-sdk-s3@3.972.67", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/signature-v4-multi-region": "^3.996.42", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-aB1ahF9z4J5r8YK1QodwNX/P8XSKBFtnjf7h72XCs0BP3rtThOiXeA3Lm+Z+8tiN9Iwl5otsGeHaXmQoQ5MVfA=="], - "@aws-sdk/middleware-websocket": ["@aws-sdk/middleware-websocket@3.972.42", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/fetch-http-handler": "^5.6.6", "@smithy/signature-v4": "^5.6.5", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-dw+GP8DC7QC2C8tUoK7DI8BnrNAjz8tb+uBHSrD2qJvxkCf58kTtFr98pljSrk+umU4n4HDW4eU2k7C2dWMzsg=="], + "@aws-sdk/middleware-websocket": ["@aws-sdk/middleware-websocket@3.972.44", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/fetch-http-handler": "^5.6.10", "@smithy/signature-v4": "^5.6.9", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-MPjH/vT1UZc7RSdvP/bIZCJqQCOORei84D6a7dwBuvdwOIskTsQ2EczlTRFQu7yWpGMQr1x3xdpDRHjWlTH2Tw=="], - "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.34", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/signature-v4-multi-region": "^3.996.41", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/fetch-http-handler": "^5.6.6", "@smithy/node-http-handler": "^4.9.6", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-Y9REVrSwmLM+Qy6sZJ7ofMC2S3Hr3tPP/4CzL5U1olPP7OGoF+6+Px0E49cVQBtSxJtyeLJMf0UaBErfeSahAA=="], + "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.36", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/signature-v4-multi-region": "^3.996.42", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/fetch-http-handler": "^5.6.10", "@smithy/node-http-handler": "^4.9.10", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-b71Suv7L+DnhM0MsQHU4WO42I32kxLZi96PbVhZbxMYIoKnEZz3v+LSrG8fupAoA4cBSshCk1Dl/PeRz49qUSg=="], - "@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.41", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@smithy/signature-v4": "^5.6.5", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-QMUytg+FQMGouc8gHS00KoYih3+N6cqmVI/pQGOIo7Nr7OpQaiXjSYOuL+vsPZ1tymY4LAQ8MYcHJmws5LRxng=="], + "@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.42", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@smithy/signature-v4": "^5.6.9", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-DBV4naZP6HYBlAvPpoQzOP12Wvfou/5rN8yJPXjBTBylU5qwCbh/tXr2MddHoIjgoRkEl/eS+IljiUqvmwey1Q=="], "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1048.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.11", "@aws-sdk/nested-clients": "^3.997.9", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA=="], @@ -326,7 +332,7 @@ "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.8", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g=="], - "@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.36", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-RdGmS1GLrtaTOLE1ElSluMldNrpk9Emq6uYs8SS8iHlu5xTAmM9rRkM91o48+rIRryBtyO9t+uLYCoMG6jVMVA=="], + "@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.37", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-zKq4HQum8JwDyEuyfuI4bbiAcU0KxP6qy+9PR/IsR92IyE/DaBAikzAS50tjxip4bqIIANpCcG+Yyj6CVhXupg=="], "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], @@ -530,17 +536,17 @@ "@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.16.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": ">1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw=="], - "@cloudflare/vite-plugin": ["@cloudflare/vite-plugin@1.46.0", "", { "dependencies": { "@cloudflare/unenv-preset": "2.16.1", "miniflare": "4.20260721.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260721.1", "wrangler": "4.113.0", "ws": "8.21.0" }, "peerDependencies": { "vite": "^6.1.0 || ^7.0.0 || ^8.0.0" }, "bin": { "cf-vite": "bin/cf-vite" } }, "sha512-+pnxcFWo+kMozeCah9CxYI6VywMQmBBfEiGJZgYkIji+vnNWkWEC0WkL5MQWHCBIiEPIbcoZDQiKr6yruLFI2Q=="], + "@cloudflare/vite-plugin": ["@cloudflare/vite-plugin@1.47.0", "", { "dependencies": { "@cloudflare/unenv-preset": "2.16.1", "miniflare": "4.20260722.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260722.1", "wrangler": "4.114.0", "ws": "8.21.0" }, "peerDependencies": { "vite": "^6.1.0 || ^7.0.0 || ^8.0.0" }, "bin": { "cf-vite": "bin/cf-vite" } }, "sha512-WyGNYtJ2nzcJXtlwCHTO5S5+flFaYhfH5WfFfx6IpGf2Y/oNwyizEW9mNSImpg65PWmDs1715Pk/vGSKKtYJ1w=="], - "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260721.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-VivNMhiEdZIB4JBWxf1RMJGROErv53qmQ+dvhjA1evrCouvqRYW718VqDideU3PSV7Ythl5Df48NqZYWoaEHpQ=="], + "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260722.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-vZOP8vIS3NwnuaO+gz0FZ7kIGeiO3bZmxV35Ph9zOXKSREhDFlH7wQ7mkCdhW3O4jnXsew+XT7b+DNEI2CcJGQ=="], - "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260721.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-k7oye1ZiuwnnBBA2eTMduconr/ud5ZxFtRNTsYwMdmJeeeislw2+M72otrHxxvybCP7JWPPlJ38uhfajpcyhOA=="], + "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260722.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EmIQymihDq6WNdER4+LF8Qn80yqayBUpJ+tkOO7wmY8pmgfyXjIUFNXotl21AHovTeu2seR7HdVUgeN/BilCWw=="], - "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260721.1", "", { "os": "linux", "cpu": "x64" }, "sha512-hon0lW4ZQ4boAVgaw+0ZFTNS8v5MWPWvK0HZnt4tDpKYnDUviLZawtUW3KqvFmCQTipVHl1S34j3J8Eqb93hGQ=="], + "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260722.1", "", { "os": "linux", "cpu": "x64" }, "sha512-jvZ3k9fxcnEn04s80CgIYxQfpOyAiz/8qC42DP8EBa9tR27qWyg9wmm31zIobVlrgBZn/+8NfdP73avRGcQOjQ=="], - "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260721.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-nAl+HRQqpX5b7xVwWcvLPZmCk8NQ2yjI0yvJTWcHiRswbMEg1ZZckVmjJUAn0PHzZARbCSyIV7v3UjM+SPRmIQ=="], + "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260722.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-BOSB55SMNdy+DA5uj2WirgiNanpHGis5PVvXH1wSfvjRKr4JGgWK+EZzxz0RFUo6QjjQQC/NimEzNZ7va7jmKg=="], - "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260721.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9paFG5cMTKz/CRixnEEnZbe5uvFPBFSDthxJHANfCWhUtBj49GSL1FPIokIg+Q+H8DGJEExU0lL92LtxD0lTxQ=="], + "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260722.1", "", { "os": "win32", "cpu": "x64" }, "sha512-sYM8YgUpKnRz2xjvdJLX1Ojzoi4MlA4gk8WTTExhGydjYB2UTs5NIbv0ZmpKgMoK9io3ixgmiW56ZnTbcWOdiA=="], "@code/agents": ["@code/agents@workspace:packages/agents"], @@ -636,7 +642,7 @@ "@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="], - "@eslint/config-helpers": ["@eslint/config-helpers@0.6.0", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA=="], + "@eslint/config-helpers": ["@eslint/config-helpers@0.7.0", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw=="], "@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="], @@ -644,8 +650,6 @@ "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.2", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A=="], - "@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.41", "", {}, "sha512-BKNSJ6oFGWi+aXu6PF+1EdI43J8Ag+Sm7Ste1SXYmC2eYOJasyjXHkKjgkIieBB1eDZQJSPWuPv421Vg6N5tCQ=="], - "@expo/cli": ["@expo/cli@57.0.10", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~57.0.6", "@expo/config-plugins": "~57.0.6", "@expo/devcert": "^1.2.1", "@expo/env": "~2.4.2", "@expo/image-utils": "^0.11.4", "@expo/inline-modules": "^0.1.3", "@expo/json-file": "^11.0.1", "@expo/log-box": "^57.0.1", "@expo/metro": "~56.0.0", "@expo/metro-config": "~57.0.7", "@expo/metro-file-map": "^57.0.1", "@expo/osascript": "^2.7.1", "@expo/package-manager": "^1.13.1", "@expo/plist": "^0.8.1", "@expo/prebuild-config": "^57.0.9", "@expo/require-utils": "^57.0.4", "@expo/router-server": "^57.0.4", "@expo/schema-utils": "^57.0.2", "@expo/spawn-async": "^1.8.0", "@expo/ws-tunnel": "^2.0.0", "@expo/xcpretty": "^4.4.4", "@react-native/dev-middleware": "0.86.0", "accepts": "^1.3.8", "agent-cli-detector": "^0.1.2", "arg": "^5.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.4", "expo-server": "^57.0.1", "fetch-nodeshim": "^0.4.10", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.1", "multitars": "^1.0.0", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.4", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "main.js" } }, "sha512-mP+B9ZrTnRE94bxPM/kCVKPyuVuOTRvvsqbXVxdXtrAfOfF94YIZLGUtw/151cGFtdUPbsBsJ9gW02LhU+QMZA=="], "@expo/code-signing-certificates": ["@expo/code-signing-certificates@0.0.6", "", { "dependencies": { "node-forge": "^1.3.3" } }, "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w=="], @@ -684,8 +688,6 @@ "@expo/metro-file-map": ["@expo/metro-file-map@57.0.1", "", { "dependencies": { "debug": "^4.3.4", "fb-watchman": "^2.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "sha512-8JXfVstZN7QnP4NianZZnlTVboOWR0sG8trUDNajOjnbGlPln29vponXM84tY+3tAHapz5/TxE53L0ixUwqPtA=="], - "@expo/metro-runtime": ["@expo/metro-runtime@57.0.7", "", { "dependencies": { "@expo/log-box": "^57.0.1", "anser": "^1.4.9", "pretty-format": "^29.7.0", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-dom": "*", "react-native": "*" }, "optionalPeers": ["react-dom"] }, "sha512-95UeoN/YsLellvskKsFGN9vKBwNc5k70ysO3skqfL3VusWlYIiYmPY+MpEWNz8A8W2CjLg9AKwZKAGrFj6znQg=="], - "@expo/osascript": ["@expo/osascript@2.7.1", "", { "dependencies": { "@expo/spawn-async": "^1.8.0" } }, "sha512-Zn03EX6In7ts2lPUW2ESUSkEhEWQN1qqsiXjadtZMJOuZRkMiAg1ZQHuvz9DjByDWNJ2pBwAGyrts9lj9k389g=="], "@expo/package-manager": ["@expo/package-manager@1.13.1", "", { "dependencies": { "@expo/json-file": "^11.0.1", "@expo/spawn-async": "^1.8.0", "chalk": "^4.0.0", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "resolve-workspace-root": "^2.0.0" } }, "sha512-y/K+CaYYpZpNGZhSX4HyLT/vyIunFjNfyoxNysPBCefeLKI/VCx6f9LNPzrxayr3rCYO5bl9O8H+HRQK265Nkg=="], @@ -706,8 +708,6 @@ "@expo/sudo-prompt": ["@expo/sudo-prompt@9.3.2", "", {}, "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw=="], - "@expo/ui": ["@expo/ui@57.0.7", "", { "dependencies": { "sf-symbols-typescript": "^2.1.0", "vaul": "^1.1.2" }, "peerDependencies": { "@babel/core": "*", "expo": "*", "react": "*", "react-dom": "*", "react-native": "*", "react-native-worklets": "*" }, "optionalPeers": ["@babel/core", "react-dom", "react-native-worklets"] }, "sha512-WqRVabl8VpHf3+YLHVjUy7PMIuXXI6DG88Vgmavro7Nd8Ks13h9sEJH/RLSCaJE2daVnqzEKY1v797BibuY9aw=="], - "@expo/ws-tunnel": ["@expo/ws-tunnel@2.0.0", "", { "peerDependencies": { "ws": "^8.0.0" } }, "sha512-j+JfTRdCk820J9dU0sA2SqshQIKFOMo7ED84w9MJFcebfbNQgsLztEY/SABDkGnjatrW4xGqnUhVRxSBVyCkXw=="], "@expo/xcpretty": ["@expo/xcpretty@4.4.4", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw=="], @@ -728,11 +728,7 @@ "@google/genai": ["@google/genai@1.52.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q=="], - "@gorhom/bottom-sheet": ["@gorhom/bottom-sheet@5.2.14", "", { "dependencies": { "@gorhom/portal": "1.0.14", "invariant": "^2.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-native": "*", "react": "*", "react-native": "*", "react-native-gesture-handler": ">=2.16.1", "react-native-reanimated": ">=3.16.0 || >=4.0.0-" }, "optionalPeers": ["@types/react", "@types/react-native"] }, "sha512-uLQFlDjp9z+jrOFcMSEldPqL5JdaXL3vXOh+juhwoNvXgTsEorJLjHTugXu+YccAG/0KJnShzKCrb71MHBsvJg=="], - - "@gorhom/portal": ["@gorhom/portal@1.0.14", "", { "dependencies": { "nanoid": "^3.3.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A=="], - - "@hono/node-server": ["@hono/node-server@2.0.11", "", { "peerDependencies": { "hono": "^4" } }, "sha512-bjD221KPLoJTWUwso1J6fGKiTXEUFedG/s0visavY4zakFPkeGURMRNly+FhBHs7T8Dz4qHaZIMX9ZoJHSJtKA=="], + "@hono/node-server": ["@hono/node-server@2.0.12", "", { "peerDependencies": { "hono": "^4" } }, "sha512-eWpQYr67tqJLeaSUl0Q+TquuYfUdTibpOJlUMV2FfUP7+KqCC5TufnwnlXL6mobZBJbGAYRd7ZvEBDCbLInjhg=="], "@hono/standard-validator": ["@hono/standard-validator@0.2.3", "", { "peerDependencies": { "@standard-schema/spec": "^1.0.0", "hono": ">=3.9.0" } }, "sha512-bp9vHu6Va6SfMHC3D4ZLBbT/woi+AZ9CRdTXQu3kLJuLh2W/Gb9UO4hijS+BQAGFXi4EGpXdetxpzwTAawSVeg=="], @@ -756,53 +752,57 @@ "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], - "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.1" }, "os": "darwin", "cpu": "arm64" }, "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg=="], - "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.3.1" }, "os": "darwin", "cpu": "x64" }, "sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw=="], - "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="], + "@img/sharp-freebsd-wasm32": ["@img/sharp-freebsd-wasm32@0.35.2", "", { "dependencies": { "@img/sharp-wasm32": "0.35.2" }, "os": "freebsd" }, "sha512-YoAxdnd8hPUkvLHd3bWY+YA8nw3xM/RyRopYucNsWHVSan8NLVM3X2volsfoRDcXdUJPg6tXahSd7HXPK7lRnw=="], - "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="], + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.3.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g=="], - "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="], + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.3.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ=="], - "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="], + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.3.1", "", { "os": "linux", "cpu": "arm" }, "sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg=="], - "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="], + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw=="], - "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="], + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.3.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1EkwGNCZk6iWNCMWqrvdJ+r1j0PT1zIz60CNPhYnJlK/zyeWqlsPZIe+ocBVqPF8k/Ssee/NCk+tE9Ryrko6ng=="], - "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="], + "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.3.1", "", { "os": "linux", "cpu": "none" }, "sha512-Ilays+w2bXdnxzxtQdmXR62u8o8GYa3eL4+Gr+1KiE4xperMZUslRaVPJwwPkzlHEjGfXAfRVAa/7CYCtSqsBw=="], - "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="], + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.3.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-VfBwVHQTbRoj4XlpA/KLZ7ltgMpz+4WSejFzQ+GnoImjo1PtEJ59QB2qR1xQEeRPYIkNrPIm2L4cICMvz4C2ew=="], - "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="], + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A=="], - "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw=="], - "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="], + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg=="], - "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="], + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.3.1" }, "os": "linux", "cpu": "arm" }, "sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A=="], - "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="], + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.3.1" }, "os": "linux", "cpu": "arm64" }, "sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA=="], - "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="], + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.3.1" }, "os": "linux", "cpu": "ppc64" }, "sha512-hYSBm7zcNtDCozCxQHYZJiu63b/bXsgRZuOxCIBZsStMM9Vap47iFHdbX4kCvQsblPB/k+clhELpdQJHQLSHvg=="], - "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="], + "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.3.1" }, "os": "linux", "cpu": "none" }, "sha512-qQt0Kc13+Hoan/Awq/qMSQw3L+RI1NCRPgD5cUJ/1WSSmIoysLOc72jlRM3E0OHN9Yr313jgeQ2T+zW+F03QFA=="], - "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="], + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.3.1" }, "os": "linux", "cpu": "s390x" }, "sha512-E4fLLfRPzDLlEeDaTzI98OFLcv++WL5ChLLMwPoVd0CIoZQqupBSNbOisPL5am9XsbQ9T84+iiMpUvbFtkunbA=="], - "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="], + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.3.1" }, "os": "linux", "cpu": "x64" }, "sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA=="], - "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="], + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.3.1" }, "os": "linux", "cpu": "arm64" }, "sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg=="], - "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="], + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.3.1" }, "os": "linux", "cpu": "x64" }, "sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg=="], - "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="], + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.35.2", "", { "dependencies": { "@emnapi/runtime": "^1.11.1" } }, "sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw=="], - "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="], + "@img/sharp-webcontainers-wasm32": ["@img/sharp-webcontainers-wasm32@0.35.2", "", { "dependencies": { "@img/sharp-wasm32": "0.35.2" }, "cpu": "none" }, "sha512-QNV27pxs9wpApEiCfvHM1RDoP1w1+2KrUWWDPEhEwg+latvOrfuhWrHWZKwdSFwU6jh3myjw/yOCRsUIuOft3g=="], - "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.35.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.35.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-YYEhx9PImCC7T0tI8JDMi4DB9LwLCXCU5OWNYEXAxh5Q1ShKkyC6byxzoBJ3gEFDnH2lQckWuDe70G7mB2XJog=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.35.2", "", { "os": "win32", "cpu": "x64" }, "sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ=="], "@isaacs/ttlcache": ["@isaacs/ttlcache@1.4.1", "", {}, "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA=="], @@ -872,7 +872,7 @@ "@mixmark-io/domino": ["@mixmark-io/domino@2.2.0", "", {}, "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw=="], - "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="], + "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.30.0", "", { "dependencies": { "@hono/node-server": "^1.19.9 || ^2.0.5", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA=="], "@mongodb-js/zstd": ["@mongodb-js/zstd@7.0.0", "", { "dependencies": { "node-addon-api": "^8.5.0", "prebuild-install": "^7.1.3" } }, "sha512-mQ2s0pYYiav+tzCDR05Zptem8Ey2v8s11lri5RKGhTtL4COVCvVCk5vtyRYNT+9L8qSfyOqqefF9UtnW8mC5jA=="], @@ -912,43 +912,43 @@ "@oxc-project/types": ["@oxc-project/types@0.138.0", "", {}, "sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA=="], - "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.60.0", "", { "os": "android", "cpu": "arm" }, "sha512-1q4q4Jc8FlOMVojEisyFAVyl8h1yawNv6phjgmhGVEDeyeOdsSnSr9x0+D4mOnEKvpO5L4mxKZ/DP9X6U3A/Mw=="], + "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.61.0", "", { "os": "android", "cpu": "arm" }, "sha512-BaS+1OVvg9sr+Xav0+KdWedQRcAzrdoEcwMZeqoc2F6ieC1s/t5eM35YQoRPQ7vAqkZ+p3tbQb1r9I9mrV5oGA=="], - "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.60.0", "", { "os": "android", "cpu": "arm64" }, "sha512-tD41I6nCt9k8SQXft0CSjjU9jg6SwG7uMu7PxodSEHXl+GDW0868oy6tTtoJkyUze8YKFgTpz/k5LuPUnFiGLw=="], + "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.61.0", "", { "os": "android", "cpu": "arm64" }, "sha512-of8atAV0M1egGcVOMbgZCvc10sFOP3ayQBNQV5h5G3fNq8gACdEswfFk9bzGrdbM23rtg0Coxi7np7oPLcueNw=="], - "@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.60.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TTpzPug96Zxdyb46KvTyIUQDdsqbumXh2TKG9C23PCT0kF7JkW56Z/quPuG9rqOFKQIi1gpRNZ7DX18LwxXPnw=="], + "@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.61.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-7l8+5ov4BGwtAcmpzvEik/TG3bciwyw/S3e6j5GKH7pcQqcgCVxD3AuJeP6upto+SOTBKQ4wrrdbMt0gq8fHSQ=="], - "@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.60.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-CnOoWgQ7L+JL/YQaRJ+NyATciSfcftncm7y3kqyte1cGtFEGnStaCd1TAyrinkfQ7nRBfHrTs1/vTwUJr3WF2Q=="], + "@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.61.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Fnz4dDDXBb7udk+DmwelNjxbD6yptyxwCqwCH2ebo4RVLxVsRfFsn/AHJC49KIltPrVokamGv4SSOsiV50DTxQ=="], - "@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.60.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-ychJo7S3hZxdO6eDZ9zM6F2lM9fpJS3EKS5CAUSWyprdLYxTu4gbaUKV/VBPTcMJwQa2Bpo+643y3OJ537pihA=="], + "@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.61.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mddOebKNCP+AucmzfNsk3jgbr681qAUvgMqi865GW5gWLJ/AnzXbvjQRrny0e++NAN8aphav/aRSrfFxNsNjpA=="], - "@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.60.0", "", { "os": "linux", "cpu": "arm" }, "sha512-36IH5o55T2Fx7E0feDttt+mifxN6yk9pWv4KfhAIsP0dFnUq27331OwbpOsZdoXF9soOLWm7mQUz5+UUmyec4g=="], + "@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.61.0", "", { "os": "linux", "cpu": "arm" }, "sha512-svx59iYL+DbaZGZUIoice4W0CjRXGExnbz7Re+awIb60rVxBS2KrU7Hnlx+nZYanLGLpjneUEgo/VFEKkSZAyQ=="], - "@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.60.0", "", { "os": "linux", "cpu": "arm" }, "sha512-G1Ve7lAa6sFBolVI2LWHfEAqy0YKh4vnioH8uYO9kAEdgM7mR40IksIx9/Zk4+vbYew/sGa4J9Q4tZ3n9gXDHA=="], + "@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.61.0", "", { "os": "linux", "cpu": "arm" }, "sha512-BYK9MPJPCf6d+fLKMTruThmEyCtHzQ1zLcsrTlUVkmnoXIaHAbfpeLYQwX1tkjs7W11dyzoi6HFvKcdnvX1zNg=="], - "@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.60.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-LTQdRBf6uzj/h7Xk6lKzbGD2hrF/fK4YI9LIN1c0509tPUn8wRa3mCmrFQpEWJPLYGFrLFFMTYW1Ljj6VqW2Hw=="], + "@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.61.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-QUaCNLq2/EC6G5ljOuFanl9Lgw6ZWp4co7rs4+KOMUzbGfA4Lq58FHRjjF9sVIG+93XSbo343MxFATrOU1qctA=="], - "@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.60.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-2JMo3XPxMPx3hiqddSZYyaH+fKJm6cz0u8n1naYjP/CdOQOZW34i8lKBUfmbWiuFvd6KoYXLmhAyBuvojsYS7Q=="], + "@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.61.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-S6uvJ6MXnRXl+zTs0CARNDvkE+cymj0EVWEKKsyKnlLlqTyQJBjw5s4D2pSIOZc+S46cy4STefzcr/sm0VzVPA=="], - "@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.60.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-L3C+nBD13lr306tr/PjM3RMll+BVqgFrIgUyoeHuai5oueJrRLgO3j+GO5/Cbhtkf5PSlHYTI1JY7iqBd1qa6A=="], + "@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.61.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-6VDlRcytvZG6UlSIdAFKDLbppo9tvPxrWzle6vHldYFMeuDPQEfMKrkwezp7FaBq1wik9ra554ZZeRPsyIkFpg=="], - "@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.60.0", "", { "os": "linux", "cpu": "none" }, "sha512-M4MsmvqlxFiPtSRGyBYQSZxchEf463AOyd+Dh4/9xDpjWBsRtDUTDMFN5EdHinjVK1/eDJQ8MLpcYjpYayaCnA=="], + "@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.61.0", "", { "os": "linux", "cpu": "none" }, "sha512-KkBTYbzExpbmn15XjKPLu2fRV2PVlq+KWt+brad5rwIa03vdYoaDRWiS7raHII/dCTR6Ro4UpYUCH4t6lif4WQ=="], - "@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.60.0", "", { "os": "linux", "cpu": "none" }, "sha512-OH+9UskYuxRB+GxqdGkVN8f5UpwhqG8YscNo1wl8+KJ62cd7wZdGga6iGLJIf8kibF1WBwvlfDUx3cez/VXwFg=="], + "@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.61.0", "", { "os": "linux", "cpu": "none" }, "sha512-69tzIq7sJLVB9dxYYtvMzcSSsnZHSO+U2U19O2RqDqgj6+Q4O7HjSXdaszbcgqzhsUwzSH7z5kWvk8nmf6BHTg=="], - "@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.60.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-y7AAFutt9wFWBFOAn6+BHaV39usZmcr3YYH2385f+NHgPNpIF9HpqKp0jgUxPaUOCyG3oaX5VhJduL1Nw164rw=="], + "@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.61.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-Oqi/N0OvtOVXsPKAOOhKgGH3msRYF8BLJaNBbWiupRiKoKVyc8JRKPCfarkQJC+RgP9U8raUKLe+bNwd0HUMiA=="], - "@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.60.0", "", { "os": "linux", "cpu": "x64" }, "sha512-yKZ9+CXAI+1RO5nH/4Z/9M6DAsfOzd5bw/gtWk81KB4mpalMaRRSXfouc5/tHxazDmBek55HNPepNYBgaCew0Q=="], + "@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.61.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3TKwv/ed4uwJSemAA8P9XcoqETpjQI4waquF9UilhA9Mn/dhr1PdUEXWlL74mtc6ZNfmKPA9+NEJm01nRF8CVA=="], - "@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.60.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bCUGaF6hJOYnQzLJdHLZbvGsOd5oSvGAyJhPAKum2uyLYUuXmP8vqg690DWi2hqcnIoYpqSqCrjzE5aiUAgwQg=="], + "@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.61.0", "", { "os": "linux", "cpu": "x64" }, "sha512-uFso4u4nLkVSlMCpgjyvWV60Gt7GvDQHnk1mmRxHIkZTMB0ljpUKwCD9FYGgN9H97x2wYl0UwEjgRZaPIuhEhw=="], - "@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.60.0", "", { "os": "none", "cpu": "arm64" }, "sha512-GrUeZOvzP30ExxfCuQiyofuUGI+OmvAgFwOO5w5p9mGPlxcyuqI+6Sy9fAKFFfLQrqKYWFgc5sYA2Unj/29nPg=="], + "@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.61.0", "", { "os": "none", "cpu": "arm64" }, "sha512-keGLkzeOvkMpNmPp4hffXWpfoSsY6e1K8++KXD4mSSfxdvM8q9QUDsYY689TB1k6Co832DZn1MnaaVx6cIBMWQ=="], - "@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.60.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-WD4Q954kUl2TDJV/6q7UnE2rlKk047kXLJsr4bJ2mXRaAqNXcmV3nwKUsGCc3mz/jYDBnXtJEaBErJEybK8iQQ=="], + "@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.61.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-VzsAISkFxmNhJ5LBDEL9VuH6tJsVJMtqYit2LyIUf/HLnsCe4Pg9SMOjjVQzGWt0bnpyfJ94CrqTqcpNZzK+ug=="], - "@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.60.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-HqDekjr8JXzVDUP1YthDZ1Y3CBEcuZT4WX3B+1kaxj8CvZA8Y2YhcEsXqoSop3tVsgjACxjnFQFDkBo0r/jq1Q=="], + "@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.61.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-xv4t7yzwJoYaLB6Zv28B3W+j7brEjsyv50rLTAQgmxJzddce9fAMCxed8dSAkbWES0zz2J29nYK5FaTuD2YBHg=="], - "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.60.0", "", { "os": "win32", "cpu": "x64" }, "sha512-tz78yhmGPKboTMHCHSaUqXK8JrmoSejgDcWeqAtg2s07ZGKQ3rH5Jn8NuXPGNG33CDbY2e9NoQWXIVEmKO21Rw=="], + "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.61.0", "", { "os": "win32", "cpu": "x64" }, "sha512-6EZXFkqOwxdDYjIn3TSNnPk3ST5E5GiYd4FiM6UF/mCL/LZSfr6D6UygTfW3R1PCQP2quCKpCEGRlij8E3VYbg=="], "@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.24.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-C2uMmwK5Bc4ri4ysZ6sA8Rcu+A5zBQTp6ml2u0CLLbRZp4kMFPV3yWk8B5DK9Aw7y9bbjogIm75tUwGLFzlsYQ=="], @@ -962,43 +962,43 @@ "@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.24.0", "", { "os": "win32", "cpu": "x64" }, "sha512-0ZbGd9qRB6zs82moekaKdEvncRANq49EAwfNX62JpTS46feXUhKAuoyVDvZMj6Rywejylrmmu79Wo6faYCo4Ew=="], - "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.75.0", "", { "os": "android", "cpu": "arm" }, "sha512-lutovtFzJqlRaqpZrCqSSGaHZzl9nIxxpjLzhSRLunN6dCLylj0uzlCyQGaQDIys7rrv8kVXiFO+R4Zpn0bX7g=="], + "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.76.0", "", { "os": "android", "cpu": "arm" }, "sha512-ZHIE5Zt9AsPDcY4nOlofXt0YfneEeo+QrKMPcPzLf2Z6Q8VtV2W73d7SFJ920WUwyik783u/doKCs3KXdwG+7w=="], - "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.75.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hXI0hDgHkw4w5nfru72aG7y+2iQJmC4waH/KV6H/hbgA6yAP5jYNx0P9yug15Hs0tWl/+mda3Jjn/2gmDT48tw=="], + "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.76.0", "", { "os": "android", "cpu": "arm64" }, "sha512-shm/ngQilHK6bs+ElJWa4oHfNj5vL1Gl/iVEJldTQjpr0/67oSgr0KUpbmcnLig5Fo0v/l6j2567A7TOL89ONA=="], - "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.75.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-D91BWbK/dMYfCcrghspPIuKs2D9LF4Z/OabVSQjw1AO6PWxArD7teDA48bm0ySFqWDaPVqmQRl5GMWNglTXyrQ=="], + "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.76.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rvJmrAPKSQ9aWJ6wIS6CK2tJjwzfW0ApQH9qokq6sfDvmHwoyIHxHFMq7z7i7GiV6fdE6s8qvBqWKPTu8RmT6Q=="], - "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.75.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-02mpwzf12BonZ6PT0TuQoomvEh2kVl2WGBIKWezCyToIS+rYkQZ6GXnARBAl9A4Ovm2V+Xe7M4KretyqmmcnJQ=="], + "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.76.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U/zYdb7VYKGY6pA9Vd2rYl9O/HlCylcOlb5PGPvVLtg+oLGsk6H3XGKEMHKyqD3nmmtmlmwb/8SwU2vfSAtvMw=="], - "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.75.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-qZJgLnDaBsiL5YESx2t/TZ8eXkL9fEkKoXEdzegROhlz9A0lgyGnZ0dAzJrh7LJAHQl2K9RdRueN2s/9N7+odg=="], + "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.76.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-WvKG9CAriuo0XNiFzpXjDngUZcRGFNpaK2kLyMUsnJlShxkT96u+BpJQ3KqdQwGOrvI14L6V8bAwXwAYNNY6Jg=="], - "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.75.0", "", { "os": "linux", "cpu": "arm" }, "sha512-7XlaWA5BJD3XpCfrEqjEe6Zseeb14S7QGa304XfwKignRaKQ+eIj775BQ7nIslggWickl4IsPUFqJ+/gAyNHVg=="], + "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.76.0", "", { "os": "linux", "cpu": "arm" }, "sha512-qJ5+RH99TqFRq3UCDxkW0zJJu9c+OAHFY72vGlxZLEpuO+MpKo3POgqb8sYipL9KYm8XY6ofb0HsOuvY6hQNqQ=="], - "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.75.0", "", { "os": "linux", "cpu": "arm" }, "sha512-av6Tpv8yrcMMMOadOqENBhlsLRcGFXXwoQ0hzHhsmS9FJ4Wioy8we427GbcMe2XTxmL2e60T67H1Dyr3up+tAA=="], + "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.76.0", "", { "os": "linux", "cpu": "arm" }, "sha512-PvPCVptkgVARsucgIqFQQcSmJ6xc6GtnVB5bRBekRahTc9eObMtjHfMjy5M+C2tHt5UCMttWM9RuSk/H9NqYeg=="], - "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.75.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-WcUhd8fHT5plrA14lANevl+hOl815mVI5t2hU21oFWrZKFXIVV/Sr4rWQV0NzSvzBupbMLNc5ErEA6Ehxh5jMg=="], + "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.76.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-3KeFDx8Bu4HPAXbuHZOr/oHvN+QT+JQhMw/NYPz7Z071xLSsG27Jfh9PIQVEY7hk1I+jr43ExqRIeJ6VKk2yLw=="], - "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.75.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UWzp5wRHFe/ESO3+eEaxXsTkYTGLYjnTsi/I5neEacXSItQ6WNleapfOAeA4x2b8nyhJ4uQxqvtv9pHv8kWJtQ=="], + "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.76.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-oPFkkKTgl0K/EIg9fQ8oA3IGcI05/Mq1en04iFa41mmNPT+6KEiByVazTOZZJiHMBBrbsns1YJ2e1Scqwzesjw=="], - "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.75.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-XEVRwGMLKCUKrvhLAz4F6AIh8MJrQVdSZtAmPpRZt9tGPsUnamPOcl3dS/ZQzJnar/Ymgc//+xho0L60Emzuxg=="], + "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.76.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gN7yZ0eqflA5Fhf1wvHxGUltIV3FsvmB1zhNMDEK9vSHhc7E6qg9CuPeBgPZab66Tjzq6w6kHAtNEvnTHf4cyw=="], - "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.75.0", "", { "os": "linux", "cpu": "none" }, "sha512-mAG4DUXqfLC8cTjMD2kt3jDmVzFREYtDyeLNdLdsCcBc4Zbl2EMuiFektGBilQwkNjYnMvCqJs55U+Hyb+b+jw=="], + "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.76.0", "", { "os": "linux", "cpu": "none" }, "sha512-S/HqMbn22mQrjtErUxEoS/a55u8kIeXvreIxiJu5G7Le3UecEd6SQZxrDIpuhtgaFnsY/nVra3ytP+pRljDilA=="], - "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.75.0", "", { "os": "linux", "cpu": "none" }, "sha512-95hrAvriAlI+pekSomTFIn0+bawMDlDwTNVmdjsFusTHyL2JWh7TWvRNG/Lkim72uN8OiCcO9wcaC6omLP5E3w=="], + "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.76.0", "", { "os": "linux", "cpu": "none" }, "sha512-ZIga3097VJZolGZk6SrIAUokIGfRkxRlhiHDUznZptGBfwrhD7pNfD1rzEzsCwvk/1DX0A1bLz+liuNh5QKIVQ=="], - "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.75.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-4b6f2+FrtruAESrCqIKcrarzfrSx+wk2QNcp+RT91/Prc+pMQMAfyZ1rG1c3tFQNl8Bc616tx40uNXyxNBRPbQ=="], + "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.76.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-ZGiiA7pFzMJSyMWYZTVlPgbTsx+Vl8ihLGMIujPwaslUF7kIPPWAbVmAlTc+9lWDV+DCiB8Ikixu+lSHeOIIWQ=="], - "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.75.0", "", { "os": "linux", "cpu": "x64" }, "sha512-nshAhrUvXFUWOvqQ2soIw7HFNWvpvEV4o0cYSqPtzLiPF5gKyYTDOOTJ6Rn8g8K/iGvPIrbDA4v8+5MvnjJrrg=="], + "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.76.0", "", { "os": "linux", "cpu": "x64" }, "sha512-JLiy5WuvEBFTT6ErIFV35SLzi0R7Iri6MKU6dZbTxfIx8pndbbPs3Mj780nMipBFcPkti+okAPOJ9POKkHFEgg=="], - "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.75.0", "", { "os": "linux", "cpu": "x64" }, "sha512-e4jNxLKnxLC6sYBQRxrI2pgIIxnmMtF8U/VwNYcjTT/CLS+spH624cYVnj07bTKwaEWT37/e025isOs6j/0xqA=="], + "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.76.0", "", { "os": "linux", "cpu": "x64" }, "sha512-z7lgKQtbo/I1NIe8G5NHLesxJDv0tRSUWTpXKb9Pm3E9nKFKfO4IOSDtFroKgXtOYb0jQbcdH+0wzTyMXVes+A=="], - "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.75.0", "", { "os": "none", "cpu": "arm64" }, "sha512-hZ2lH+1qLf/DiEP9UWuQTK2JWj/BgvMB4jhIV4SmNU1wfEiYYX4TynQyAZXx0j9X4qRYizAL042SKaV+8ynh4w=="], + "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.76.0", "", { "os": "none", "cpu": "arm64" }, "sha512-JOjKymIpb9QcYfEhZsN6h4V9Ivd474W38cNIBRv6bg2TbIvogbMTH0Mg6YWW9TiRDqfcX+/Hyfsbo5vcSE5guQ=="], - "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.75.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Ilj6PNzGDS3bCU0MSJH7Msh0NhH+T/mRp2shwg+q+GHeVlPwP5LEboW96aW+3kVKFk6zYZy1Xi5pZkqZh6X8KQ=="], + "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.76.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-pqDWZiwcmByWUEm1NFUBNiT6aentCcaoMWJv0HbXEmuYermJ4sg8ppVrshubYP2MZ6SHccJJcpr6x469PuDFIw=="], - "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.75.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-QVit2nOEOiPhkmsrksPSkoGCdnZRNkspt8fwoYyP09te1VEbnSj4LAxua4rc8FKTmWkySVe05j8iz9GXYfF1AQ=="], + "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.76.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-Ba0O659kgMv6pwO3z9PdO+K3aMxQRaw9HnG+e6AtOfgwcKFvYilciQYBoUBmxfQvOCKZe1SwjMkuB542NkuDMQ=="], - "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.75.0", "", { "os": "win32", "cpu": "x64" }, "sha512-DSxnNkBUAYARPwJtR12Ig3deWr8w0H997xP6jy33i+e0SyYJw8FKuz4+cZtpmPEhQmvlPJE3X/2vNxDmLkd/rA=="], + "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.76.0", "", { "os": "win32", "cpu": "x64" }, "sha512-5qcirPHO8nKfkoowEVWtpAoVTcYDy6g0UT0NGic450Qv8J2NrOqg4uQ8QppRP4MDTC7Xx47lbZnmadTH03CGGA=="], "@oxlint/plugins": ["@oxlint/plugins@1.68.0", "", {}, "sha512-titLmukUt/h8ho7Svlf0xSBjoy2ccZKrXjpXpZCj+v6V4CJccC2KyP45BLSCMx8YIpifMyiDyUptM4+5sruKbQ=="], @@ -1030,59 +1030,39 @@ "@protobufjs/utf8": ["@protobufjs/utf8@1.1.2", "", {}, "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug=="], - "@radix-ui/primitive": ["@radix-ui/primitive@1.1.6", "", {}, "sha512-w9hl+724uYEgCGR3bhuRepjBtrNB/6gkhCnAf58Ke+SLbHPPQqVZZB59z60roB+5H+nh3nWTcdJhQdFMEydWmw=="], + "@radix-ui/primitive": ["@radix-ui/primitive@1.1.7", "", {}, "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q=="], - "@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.17", "", { "dependencies": { "@radix-ui/primitive": "1.1.6", "@radix-ui/react-collapsible": "1.1.17", "@radix-ui/react-collection": "1.1.12", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.2.0", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-use-controllable-state": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-l3Dmp+qPPc3SqT8+SPnxIgoWBEU2MMBxcQ7BsoRgak2UT75xY83SFvFcrUkUAWukOV3LFF+BQ9aBIFtZsIG8yQ=="], + "@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.20", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collapsible": "1.1.20", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "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-jDhG9FvAEnlhnjrsINbNXcUa4G+L1KqSkJSunkbKEzFRcAb52jvM0PjPxPRvhe1HNc5F5yc0yzzWeeqlH4yBIg=="], - "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.17", "", { "dependencies": { "@radix-ui/primitive": "1.1.6", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.2.0", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-presence": "1.1.8", "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-use-controllable-state": "1.2.4", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-DJgqGsNXa0df3ifz9PFNgvgj/bzIu5QTVWCt5nQWaUkM6y0EarUv4QG4s6mCoeQdOIyVOT/Q1osFuEGub2TDXQ=="], + "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.20", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mcGesGplBnzN2sbvJETzpCNfSMyPnb29q1GRLU+Ib7bJrpIG2ywmRoh2V5VbA2uNvKikKUlVbAPks7JDjz4A8Q=="], - "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.12", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.2.0", "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-slot": "1.3.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-nb67INpE0IahJKN7EYPp9m9YGwYeKlnzxT3MwXVkgCskaSJia97kG4T0ywpjNUSSnoJk/uvk12V8vbrEHEj+/Q=="], + "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.15", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.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-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA=="], - "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA=="], + "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.5", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA=="], - "@radix-ui/react-context": ["@radix-ui/react-context@1.2.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-fOE+JtN9rygNZkCnHRBEP0TAvLldlhyOxMsbwFvTP4nAs+nBmfnna+o/Zski2wkmY1YMrFC0aSzsHoLY47iLrg=="], + "@radix-ui/react-context": ["@radix-ui/react-context@1.2.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA=="], - "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.20", "", { "dependencies": { "@radix-ui/primitive": "1.1.6", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.2.0", "@radix-ui/react-dismissable-layer": "1.1.16", "@radix-ui/react-focus-guards": "1.1.4", "@radix-ui/react-focus-scope": "1.1.13", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-portal": "1.1.14", "@radix-ui/react-presence": "1.1.8", "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-slot": "1.3.0", "@radix-ui/react-use-controllable-state": "1.2.4", "@radix-ui/react-use-layout-effect": "1.1.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-cngVJcvK0yMvR7wICJpv+1uW3Qw4T7QM5sdbb+oE/lxOdTdvF00oaRpWUjVgmjyXe3J+xh7eZyXZlVF3g2g59g=="], + "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg=="], - "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA=="], + "@radix-ui/react-id": ["@radix-ui/react-id@1.1.4", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA=="], - "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.6", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-effect-event": "0.0.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-t45h68IjFx0ccBnPJqk0X6ecv69LkCFWd6DNCFQX56mUnVEXZbNOLCH/u9fHlAjFZ1RrFdl8/m4zev7B7NyhXQ=="], + "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.10", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw=="], - "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q=="], + "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.10", "", { "dependencies": { "@radix-ui/react-slot": "1.3.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-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg=="], - "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.13", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-use-callback-ref": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-dE04aPEuP9rvKKT0d0KjSOtTEYNg6bmCYFsoSJpfC+y91Hic28ZfDCGgv6aJ+2Kw/LBXYipMZpyqVj/OD3Z8Gg=="], + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.3.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q=="], - "@radix-ui/react-id": ["@radix-ui/react-id@1.1.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA=="], + "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ=="], - "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.14", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-REwjAGPMa3J9oyDE4cuWkZbwnCbbyky66NurquQklXMSDn67cl6oGFx2gO7KZhPtFNbNw9xTWNrti3VIhgluYw=="], + "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.5", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg=="], - "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.8", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0hhyrQdXMaATgq4ammLG9+iPqsXxzZkgTSIxdrJHdfLnXO4Uo5L7BoO3/Xf0AEaettadGZWGGJMw6ujzQvIpGA=="], - - "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.7", "", { "dependencies": { "@radix-ui/react-slot": "1.3.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bC3NiwsprbxKjuon9l7X6BUTw7FPVzEYaL92MPEY5SCd/9hUTPXVFtVwRix7778wtRsVao+zE062gL79FZleeQ=="], - - "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.6", "@radix-ui/react-collection": "1.1.12", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.2.0", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-controllable-state": "1.2.4", "@radix-ui/react-use-is-hydrated": "0.1.1", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-w7lLsTSd3940vFYEshKkHw+NGf7H0QDJPHYsy8NRjDCVbO6ZdKW1X/xoJSYHZtttnrdZiYqbN2O/2uHGB0zasw=="], - - "@radix-ui/react-slot": ["@radix-ui/react-slot@1.3.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA=="], - - "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.18", "", { "dependencies": { "@radix-ui/primitive": "1.1.6", "@radix-ui/react-context": "1.2.0", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-presence": "1.1.8", "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-roving-focus": "1.1.16", "@radix-ui/react-use-controllable-state": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-1zq2XkQkK/KfbZn84edytYpOLquhNalra5LXc3NAMKhNRSGtyXqjMv6OyC9jlSuNKpqvQtsb57WKoICNk1v/sQ=="], - - "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw=="], - - "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.4", "", { "dependencies": { "@radix-ui/primitive": "1.1.6", "@radix-ui/react-use-effect-event": "0.0.3", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-cx2DixxmSfjCcEoRvDvy1NLd6SWK94XFcEEOZUcharUlXbmahFQGKCfwdKZL2ub34iIwOPOEFVF80xb+yfLYiA=="], - - "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.3", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA=="], - - "@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-qwOiz4Tjo8CNnrOLAYUMXeZwDzXgXpvK4TKQPmWLECM9XoWvA6+0Z2/7Ag3A4ivjS4ovbLJPbskkxioFyBhr8A=="], - - "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA=="], - - "@react-native-masked-view/masked-view": ["@react-native-masked-view/masked-view@0.3.2", "", { "peerDependencies": { "react": ">=16", "react-native": ">=0.57" } }, "sha512-XwuQoW7/GEgWRMovOQtX3A4PrXhyaZm0lVUiY8qJDvdngjLms9Cpdck6SmGAUNqQwcj2EadHC1HwL0bEyoa/SQ=="], + "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw=="], "@react-native/assets-registry": ["@react-native/assets-registry@0.86.0", "", {}, "sha512-nIaXbm2jX1OTYp0qbviJ3O6KZivoE8z3BnhUQ2LsqfZSWRoOK/n1qsiAr6oALiNKWnXY3j2KPwtYORnZzp8xew=="], "@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.86.0", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@react-native/codegen": "0.86.0" } }, "sha512-qdsABWNW7uTll90l4Vh03gjeyu3WVDi2CyiiyvYGMRDcoYbjbQi6df3BMAm9lQI2yslZ1T14LlDDAsgTwNxplA=="], - "@react-native/babel-preset": ["@react-native/babel-preset@0.86.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@react-native/babel-plugin-codegen": "0.86.0", "babel-plugin-syntax-hermes-parser": "0.36.0", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-bYQcWiPySNvF4dns9Ls9gMmwgq66ohvM9Fwc/Kn8r85t66UNHxch3p1QwPiSorDelFauZwJbgo9+ReibTgvpbA=="], + "@react-native/babel-preset": ["@react-native/babel-preset@0.86.2", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@react-native/babel-plugin-codegen": "0.86.2", "babel-plugin-syntax-hermes-parser": "0.36.0", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-4XKEJ6jKW9lXMB1O5o47gBoGgolde1fbX13gLW/erlcn+1ky+MHHo5UjuM3RWGdPJHIvIzekDDumSUHhB9x5iQ=="], "@react-native/codegen": ["@react-native/codegen@0.86.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.29.0", "hermes-parser": "0.36.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "tinyglobby": "^0.2.15", "yargs": "^17.6.2" } }, "sha512-uTs9DBo3+/lUqinsGZK0FKJRBVClrwMXoZToaDxE1Q2SL2e55vs2GwyZfIKzPl5uJnbu4PfFMIp0/mLXLWUMuA=="], @@ -1098,9 +1078,9 @@ "@react-native/js-polyfills": ["@react-native/js-polyfills@0.86.0", "", {}, "sha512-zYy/Cjd1VTnZ2iCNaG9bDF9C3l2ntESiPRscjIlI5FKugu6aeTwsDSv1aI8Bc4Kp3vEdoVg+UQhLAhE4svREaQ=="], - "@react-native/metro-babel-transformer": ["@react-native/metro-babel-transformer@0.86.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@react-native/babel-preset": "0.86.0", "hermes-parser": "0.36.0", "nullthrows": "^1.1.1" } }, "sha512-SjKej3E5qIahqo/G+rSOrmJUQM44RyKtWtO+VfmKAAMoJWkBFomM22hTLKCIS5cdbIAJ9COAmU+KAi2wVSO0wQ=="], + "@react-native/metro-babel-transformer": ["@react-native/metro-babel-transformer@0.86.2", "", { "dependencies": { "@babel/core": "^7.25.2", "@react-native/babel-preset": "0.86.2", "hermes-parser": "0.36.0", "nullthrows": "^1.1.1" } }, "sha512-mX1wgLErdb2hDgXJr9zM9SWLe+ZteZTFTwRWGOQ53yEJwc9DVSnxdTlAtVdMeOj2ntycKh0R8jYdat2Am43cwQ=="], - "@react-native/metro-config": ["@react-native/metro-config@0.86.0", "", { "dependencies": { "@react-native/js-polyfills": "0.86.0", "@react-native/metro-babel-transformer": "0.86.0", "metro-config": "^0.84.3", "metro-runtime": "^0.84.3" } }, "sha512-7v+xbTeEci9ZcQ/Z1OqI4RXcqN69wSMDYL5BAMvOReZ7U04+aDQ0/SQhClYPn6x2/RxM4WzMKSAuNyLKqvYVtw=="], + "@react-native/metro-config": ["@react-native/metro-config@0.86.2", "", { "dependencies": { "@react-native/js-polyfills": "0.86.2", "@react-native/metro-babel-transformer": "0.86.2", "metro-config": "^0.84.3", "metro-runtime": "^0.84.3" } }, "sha512-hJno256j+MS0b3JD1aD3ouTGZVacKNVBuXL2atMQQ8BZ060vl1ptnZ83y569aDW+/rgFSOcqn6ydKeSz4uUKQQ=="], "@react-native/normalize-colors": ["@react-native/normalize-colors@0.86.0", "", {}, "sha512-kG0wfCGghUKlfxkJyyHCDVutWVYWK7/DG58ojA/4v9EfulgF+osuSQmlbNb3rcKX58qutm7JcldSeVLgGFha9g=="], @@ -1124,77 +1104,77 @@ "@rivet-dev/agent-os-python": ["@rivet-dev/agent-os-python@0.1.0", "", { "dependencies": { "@secure-exec/core": "^0.2.1", "pyodide": "^0.28.3" } }, "sha512-1tH1beMf1ceSpicQKwN/a6h+NmJrmfuT4GStiRDZmvN/UWfZhkxuy7HR5VPTQpE/feUZJ01FdtBS3Em/Qoxb2Q=="], - "@rivet-dev/agentos": ["@rivet-dev/agentos@0.2.10", "", { "dependencies": { "@agentclientprotocol/sdk": "0.16.1", "@agentos-software/common": "0.2.10", "@rivet-dev/agentos-core": "0.2.10", "@rivetkit/react": "2.3.7", "rivetkit": "2.3.7", "zod": "^4.1.11" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" }, "optionalPeers": ["react", "react-dom"] }, "sha512-0R/1p1iesYJtOSarHmfO5pV6BurCQx0z7V+ssIAIXtNaNs7pgMFRrooWsr9UnAJj/xWJ+lM9xIUTHe+o8dE3dw=="], + "@rivet-dev/agentos": ["@rivet-dev/agentos@0.2.14", "", { "dependencies": { "@agentclientprotocol/sdk": "0.16.1", "@agentos-software/common": "0.2.14", "@rivet-dev/agentos-core": "0.2.14", "@rivetkit/react": "2.3.9", "rivetkit": "2.3.9", "zod": "^4.1.11" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" }, "optionalPeers": ["react", "react-dom"] }, "sha512-dr7GU8AA02wB906gdQ6tyfCTyOa08KtT8djpUdtprbx7GLkaUQpq0j60BVeS/OkTUzEwYexWEKmKyGL1U/EgiQ=="], - "@rivet-dev/agentos-core": ["@rivet-dev/agentos-core@0.2.10", "", { "dependencies": { "@agentclientprotocol/sdk": "0.16.1", "@agentos-software/claude-code": "0.2.7", "@agentos-software/codex-cli": "0.3.4", "@agentos-software/common": "0.2.10", "@agentos-software/manifest": "0.2.10", "@agentos-software/opencode": "0.2.7", "@agentos-software/pi": "0.2.7", "@aws-sdk/client-s3": "^3.1019.0", "@rivet-dev/agentos-runtime-core": "0.2.10", "@rivet-dev/agentos-sidecar": "0.2.10", "@rivetkit/bare-ts": "^0.6.2", "@xterm/headless": "^6.0.0", "better-sqlite3": "^12.8.0", "croner": "^10.0.1", "googleapis": "^144.0.0", "isolated-vm": "^6.0.0", "long-timeout": "^0.1.1", "minimatch": "^10.2.4", "zod": "^4.1.11", "zod-to-json-schema": "^3.25.2" } }, "sha512-0UMQgBFOmMtiZ0UhQ3cJei44tRmY9VzTpkJh4a+g0HWjAz5thUH2OCYtmF+tGNU8qzHhyN9hBFwT744YMRV/Dg=="], + "@rivet-dev/agentos-core": ["@rivet-dev/agentos-core@0.2.14", "", { "dependencies": { "@agentclientprotocol/sdk": "0.16.1", "@agentos-software/claude-code": "0.2.7", "@agentos-software/codex-cli": "0.3.4", "@agentos-software/common": "0.2.14", "@agentos-software/manifest": "0.2.14", "@agentos-software/opencode": "0.2.7", "@agentos-software/pi": "0.2.7", "@aws-sdk/client-s3": "^3.1019.0", "@rivet-dev/agentos-runtime-core": "0.2.14", "@rivet-dev/agentos-sidecar": "0.2.14", "@rivetkit/bare-ts": "^0.6.2", "@xterm/headless": "^6.0.0", "better-sqlite3": "^12.8.0", "croner": "^10.0.1", "googleapis": "^144.0.0", "isolated-vm": "^6.0.0", "long-timeout": "^0.1.1", "minimatch": "^10.2.4", "zod": "^4.1.11", "zod-to-json-schema": "^3.25.2" } }, "sha512-YAbK0NpauQKlcuSKl0eXB95ZdNopMGmXw1dBaoSlODKVYoKTjOEKwUtSEvx/zZB0Cse2kSQ/IrJpLe183QeQPw=="], - "@rivet-dev/agentos-runtime-core": ["@rivet-dev/agentos-runtime-core@0.2.10", "", { "dependencies": { "@rivet-dev/agentos-runtime-sidecar": "0.2.10", "@rivetkit/bare-ts": "^0.6.2", "zod": "^4.1.11" } }, "sha512-qMmWhDZ/IWL0QOKnASl1STHwRQaDknX34DTX1p+fCjcWbf2QD+ScQMTLdll52oyhQl8KhXn+Tlyhp+XTdqaySQ=="], + "@rivet-dev/agentos-runtime-core": ["@rivet-dev/agentos-runtime-core@0.2.14", "", { "dependencies": { "@rivet-dev/agentos-runtime-sidecar": "0.2.14", "@rivetkit/bare-ts": "^0.6.2", "zod": "^4.1.11" } }, "sha512-mZYas5wUZXjwLLLHq6uMOaajtyc/3iLQ6vGzOH4E3OHBwCfK054YwGU8iunRqWtk+Wd7MPetzstxzdu+72nBug=="], - "@rivet-dev/agentos-runtime-sidecar": ["@rivet-dev/agentos-runtime-sidecar@0.2.10", "", { "optionalDependencies": { "@rivet-dev/agentos-runtime-sidecar-darwin-arm64": "0.2.10", "@rivet-dev/agentos-runtime-sidecar-darwin-x64": "0.2.10", "@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu": "0.2.10", "@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu": "0.2.10" } }, "sha512-v2KXHTTQYHdMpNFhBt3/wCyKajwxq9o4jKLYpaa9mYiaBdHfORuBaDI9e3WDGEly7HCIEWNnwvkNMvoQoHnXnQ=="], + "@rivet-dev/agentos-runtime-sidecar": ["@rivet-dev/agentos-runtime-sidecar@0.2.14", "", { "optionalDependencies": { "@rivet-dev/agentos-runtime-sidecar-darwin-arm64": "0.2.14", "@rivet-dev/agentos-runtime-sidecar-darwin-x64": "0.2.14", "@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu": "0.2.14", "@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu": "0.2.14" } }, "sha512-dsA1wNg+0Y6DYRB8no962k1tAQk1y5kfdAbrpKjJQJjfgfwkv0q8XZ3ybtt1hLml/thgE32CI++8F7MRWz4TFA=="], - "@rivet-dev/agentos-runtime-sidecar-darwin-arm64": ["@rivet-dev/agentos-runtime-sidecar-darwin-arm64@0.2.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-PJ5rJZmgpS/EX9Zn1UA6Z5Ol0Y31UJKfD7Fisdqy7hlJuxhQVS9cVFrp3bud2og9s3n32riEYTx1mUE1PVQKZA=="], + "@rivet-dev/agentos-runtime-sidecar-darwin-arm64": ["@rivet-dev/agentos-runtime-sidecar-darwin-arm64@0.2.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5pKvG7TC3lKbCMbQZptyXd3QPQyfiJ+wKqA+u5SqoP+Lqwim9C4PVSYMLUaxx0QqxliNuNu+VWif1xM91yECiw=="], - "@rivet-dev/agentos-runtime-sidecar-darwin-x64": ["@rivet-dev/agentos-runtime-sidecar-darwin-x64@0.2.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-+C4gEE7/pT36fclYqdUYt6bMUj6CsDDZ+2Kxuej57/q06cSa9W5Od2zIO4wxZbI6g0EoN5zVJ8qXv+jSOtTLbg=="], + "@rivet-dev/agentos-runtime-sidecar-darwin-x64": ["@rivet-dev/agentos-runtime-sidecar-darwin-x64@0.2.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-mTSDuMXKHSpMJ3SVLCb/3sBCpOaBw0fnEsnLzVSuicuSWSzhNe4yyUeAcyz4wsuT4l+M+Z5mDH1eydfpz7nltw=="], - "@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu": ["@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu@0.2.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-BSs/LkKkNxvNBD9qEmxPWHmdHQokNGkGS3dcI3LTY4D6Sgat1Vun1OQ53v1HQSGf/TuAfgYOzbQPikvOU3zkmQ=="], + "@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu": ["@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu@0.2.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-bVtITOH4sNxcq8RuBMJF+Srlwa/Rl1ARZIej+MUDBR8VM7DGnBMWCaCHvYxy3JBmdP5aTb3gCwUm6e7m4/Khgw=="], - "@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu": ["@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu@0.2.10", "", { "os": "linux", "cpu": "x64" }, "sha512-IIM0ILGdPNjettgBVOXvrNTICggo/xNtKO0V3kM7XJiQ4DkQQkjA1/Y0JBdLvsigt7HAcEJ38zQ3ahl+HOXK8w=="], + "@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu": ["@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu@0.2.14", "", { "os": "linux", "cpu": "x64" }, "sha512-NOI1m456Ev06ey4O0pVnITaYA7emeoKR2lJIFJP4j9Kv0XuXpbmaz1aigfa3/SZQ7AvqOzxbNLCcH5m22iO8ng=="], - "@rivet-dev/agentos-sidecar": ["@rivet-dev/agentos-sidecar@0.2.10", "", { "optionalDependencies": { "@rivet-dev/agentos-sidecar-darwin-arm64": "0.2.10", "@rivet-dev/agentos-sidecar-darwin-x64": "0.2.10", "@rivet-dev/agentos-sidecar-linux-arm64-gnu": "0.2.10", "@rivet-dev/agentos-sidecar-linux-x64-gnu": "0.2.10" } }, "sha512-3bq7k/OrtMffUT+aDSeXPIEDEaJLbPXzQ5oUqnjsU+6Hsmvvf+nAl/zTvHyQOMmriQiQ1BPMPqgNyXAc5BrV3w=="], + "@rivet-dev/agentos-sidecar": ["@rivet-dev/agentos-sidecar@0.2.14", "", { "optionalDependencies": { "@rivet-dev/agentos-sidecar-darwin-arm64": "0.2.14", "@rivet-dev/agentos-sidecar-darwin-x64": "0.2.14", "@rivet-dev/agentos-sidecar-linux-arm64-gnu": "0.2.14", "@rivet-dev/agentos-sidecar-linux-x64-gnu": "0.2.14" } }, "sha512-aISMeC7UY5Mjum/DiYp3idZa/EnNZ76FGke29FVQHmBfwVX6dTx2R/FHjZdEE+iOCi9APxAHIvdu8C+EVp6q2A=="], - "@rivet-dev/agentos-sidecar-darwin-arm64": ["@rivet-dev/agentos-sidecar-darwin-arm64@0.2.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q+54J8WLa/Diyn5H+TVZwIHt4kVFCBkwtco5DjUmFmG6y5ozzPl6MM0vVzIx6iNTzhWiYOFLz5PybICmy6j7BQ=="], + "@rivet-dev/agentos-sidecar-darwin-arm64": ["@rivet-dev/agentos-sidecar-darwin-arm64@0.2.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-U1R4wYvlsLCdASC5Lf6oP/6bW6ONGsiILtTQSVgxIHl/J1TrmOifrAbRgDC205kThJEZQ2op8kVzol5aEWOpbA=="], - "@rivet-dev/agentos-sidecar-darwin-x64": ["@rivet-dev/agentos-sidecar-darwin-x64@0.2.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-Q0rAxtGjddpDcaB9keicukuExtIiynwX+DqVRG6hWjki0PSYqFqqrNFCzPiUswWf0u5Pakq1iBM+RgNu19PxZA=="], + "@rivet-dev/agentos-sidecar-darwin-x64": ["@rivet-dev/agentos-sidecar-darwin-x64@0.2.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-vuij3BYGjVSCGMNB3HbS0EiDS50xG68cjH3ItuZL77GPHsw5V765TOheWDVgUOo1Q3+VWjdMaS2wNWv63qCf0w=="], - "@rivet-dev/agentos-sidecar-linux-arm64-gnu": ["@rivet-dev/agentos-sidecar-linux-arm64-gnu@0.2.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVgsnPczeT4oMoiUTrOfadAtDGoHhd30lrAU2p/xxyeCOhHAsZt1h0xo2oCteLmZ78DJm3rLcsR+4zhY6AhtOw=="], + "@rivet-dev/agentos-sidecar-linux-arm64-gnu": ["@rivet-dev/agentos-sidecar-linux-arm64-gnu@0.2.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-nauooe07/NhHb+Wn4xvJTUMNFzhOvrNoPwceiC0eGvkK7+imRyZpAgSGB4qRiaa2NRyuNRVh+d6kzp5iKzBwnA=="], - "@rivet-dev/agentos-sidecar-linux-x64-gnu": ["@rivet-dev/agentos-sidecar-linux-x64-gnu@0.2.10", "", { "os": "linux", "cpu": "x64" }, "sha512-WXKLIeZJvOo2Kxw2wPmPNc7QWM0lq69Xt/Yy2W86gYKORAFPVJ9GVag85ywP3LrjIW1oEDwzqrvMp3PGVkvVXg=="], + "@rivet-dev/agentos-sidecar-linux-x64-gnu": ["@rivet-dev/agentos-sidecar-linux-x64-gnu@0.2.14", "", { "os": "linux", "cpu": "x64" }, "sha512-PaGPXi5mS0Ef023nqS9lbMkMH6KGoOsHA3apAaOQz95lrmVx7E/z5BPzKYl3aYMYjmlo004mnNETVBZOy0VbQw=="], "@rivetkit/bare-ts": ["@rivetkit/bare-ts@0.6.2", "", {}, "sha512-3qndQUQXLdwafMEqfhz24hUtDPcsf1Bu3q52Kb8MqeH8JUh3h6R4HYW3ZJXiQsLcyYyFM68PuIwlLRlg1xDEpg=="], - "@rivetkit/engine-cli": ["@rivetkit/engine-cli@2.3.7", "", { "optionalDependencies": { "@rivetkit/engine-cli-darwin-arm64": "2.3.7", "@rivetkit/engine-cli-darwin-x64": "2.3.7", "@rivetkit/engine-cli-linux-arm64-musl": "2.3.7", "@rivetkit/engine-cli-linux-x64-musl": "2.3.7", "@rivetkit/engine-cli-win32-x64": "2.3.7" } }, "sha512-CezLwJ0B7dWDbA7qM6Aq04mwnrJAdrDActRrrcb4NBa20h7wO9KPAYBwyJz/dRnKm9EUUNcFZ6hrSDpp6T3+Rg=="], + "@rivetkit/engine-cli": ["@rivetkit/engine-cli@2.3.9", "", { "optionalDependencies": { "@rivetkit/engine-cli-darwin-arm64": "2.3.9", "@rivetkit/engine-cli-darwin-x64": "2.3.9", "@rivetkit/engine-cli-linux-arm64-musl": "2.3.9", "@rivetkit/engine-cli-linux-x64-musl": "2.3.9", "@rivetkit/engine-cli-win32-x64": "2.3.9" } }, "sha512-6sFgD0h5Z6aTioerwCNw3WF0jRysEhJhOlQHHVdnL32KzXfZoAcJLvS3dW/M1IAKydND/MsVwSQjPSYPjTy4UQ=="], - "@rivetkit/engine-cli-darwin-arm64": ["@rivetkit/engine-cli-darwin-arm64@2.3.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-F3yGSDIaW94BZzuAm3erQRT/Ki55wHJ/b6tOaE7d9tRmTAZw/XqHmjNdUYjOvFUQKLb+SSsOittM4dINrAANQQ=="], + "@rivetkit/engine-cli-darwin-arm64": ["@rivetkit/engine-cli-darwin-arm64@2.3.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4mXfCo48055pnNViS+2WjC8p57eLLzLw1ZNgL0b7AoaPpxJ4YKXJ9F8TezSHtTc5ScXtPdfZb5jH4n/e6ePSMA=="], - "@rivetkit/engine-cli-darwin-x64": ["@rivetkit/engine-cli-darwin-x64@2.3.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-P8BbQsamIvv8U/cEoJUFr+uAzwjjl9cG+ZZxjDX9OJxbuD11ESpHvDLgge54ijynO3IjoP8cIzjIXat6mr2Gkw=="], + "@rivetkit/engine-cli-darwin-x64": ["@rivetkit/engine-cli-darwin-x64@2.3.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-BiNPd5KWKFp9H3xWZqeILJ9bmz7c04fYAAwXWtqmAWfGMBCd11QAGsJFwDnoHsMQhEGpDzbYg5L0KbKUD4HIMA=="], - "@rivetkit/engine-cli-linux-arm64-musl": ["@rivetkit/engine-cli-linux-arm64-musl@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-G3s76BHfIs6R9rm6JYI13sOjPLy08+C8WvVoFwSdMqsibEaqlfo36wVkp/x1g0sEZUek/dBxVrKqMMR7c4/gug=="], + "@rivetkit/engine-cli-linux-arm64-musl": ["@rivetkit/engine-cli-linux-arm64-musl@2.3.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-xbtUVXPK9aMcJgaA9XcLnZ52J9a9YXUWAP7pk9uHY7rRYODOwC8rRReiyeD++/+7+YsciwcIDcHb4daLHrN4tg=="], - "@rivetkit/engine-cli-linux-x64-musl": ["@rivetkit/engine-cli-linux-x64-musl@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-LWhrUVzULcsZ4ufCLsx23YfrdMW2INd9g0ANBac9+PzGwL8qYfVIXnDpR3587lapu68EbSEPZcconf1tBlvJxQ=="], + "@rivetkit/engine-cli-linux-x64-musl": ["@rivetkit/engine-cli-linux-x64-musl@2.3.9", "", { "os": "linux", "cpu": "x64" }, "sha512-0OqFgoV4nvRJKtgXEELpwTLKuFJu6DaffG+l9xkDUdcTsf/tAgk5oNU1CLgGK0JsuT77JFucAqVd93pOEWSKhg=="], - "@rivetkit/engine-cli-win32-x64": ["@rivetkit/engine-cli-win32-x64@2.3.7", "", { "os": "win32", "cpu": "x64" }, "sha512-jyA5PlHivHXyyq2ehnuXwxd5TUSbB4emomnph9EovsJo7qIdmSNaaCO13NYBT483fd0uXiNI0MK/lkJa9ePY5A=="], + "@rivetkit/engine-cli-win32-x64": ["@rivetkit/engine-cli-win32-x64@2.3.9", "", { "os": "win32", "cpu": "x64" }, "sha512-Pqr6YAM49vbDUhg6olE07wvIk0AhiEhoHFDoZWxfGLnnNAbZNKEa72j7rOZa0mXMe1JPCTRfG7zG85bIH6y4tQ=="], - "@rivetkit/engine-envoy-protocol": ["@rivetkit/engine-envoy-protocol@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2" } }, "sha512-lsJM3ERwozQCebaOMKJzqIQlcLbbN3LXurRB0+7LsM6FUUL2l6hMoq5I2De/G35DJ6OWDva9AmzfvzI+5f1GPg=="], + "@rivetkit/engine-envoy-protocol": ["@rivetkit/engine-envoy-protocol@2.3.9", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2" } }, "sha512-2IK41V9U8sgMnEYd/P6u/68nCufCU2dvxuHVV3uAV0uIVCdtRV8lkjuR2fSr05bwHmzSmewdqsbiNMiC/GWt8w=="], - "@rivetkit/framework-base": ["@rivetkit/framework-base@2.3.7", "", { "dependencies": { "@tanstack/store": "^0.7.1", "fast-deep-equal": "^3.1.3", "rivetkit": "2.3.7" } }, "sha512-zxmdAzFogA3PeT3ZgFIoYlEAJVi3iCwbPBXczZKf2x2QMCl2cTZ2jswFCAgHUUMQWj+AWiX65usxq73a9Ls/qQ=="], + "@rivetkit/framework-base": ["@rivetkit/framework-base@2.3.9", "", { "dependencies": { "@tanstack/store": "^0.7.1", "fast-deep-equal": "^3.1.3", "rivetkit": "2.3.9" } }, "sha512-ZSxrclYcpmdGsLMiVE2dfWNfUB6diSx+t8k4EQgL4cN02ThzJD3BM5mhU+zQVCCwfNw42eRZVIoxydYDLl/yHw=="], "@rivetkit/on-change": ["@rivetkit/on-change@6.0.1", "", {}, "sha512-QBN/KRBXLJdCgN4gBTL3XAc/zKm58atSnieXWMOyFSPmo6F1/yIVV/LTRdvAktfCttrGx7W6c32i/lwqCHWnsQ=="], - "@rivetkit/react": ["@rivetkit/react@2.3.7", "", { "dependencies": { "@rivetkit/framework-base": "2.3.7", "@tanstack/react-store": "^0.7.1", "rivetkit": "2.3.7" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" } }, "sha512-Y3UoUYhkLKDQrJdloCmYK+fhJMlPw5BPHbRb5VutFh5L8csIRZLoCoMitzV7mjNUxuDE1+k10iGuUHYPZUP4aA=="], + "@rivetkit/react": ["@rivetkit/react@2.3.9", "", { "dependencies": { "@rivetkit/framework-base": "2.3.9", "@tanstack/react-store": "^0.7.1", "rivetkit": "2.3.9" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" } }, "sha512-j9t82h/yIqqSt17coQZeRu3F9Q5w2FgWPDUC9fCyQUJp9PTjO7ea494PR0lSWvuEiwMRqE5JpgbHdYUQ1woE9w=="], - "@rivetkit/rivetkit-napi": ["@rivetkit/rivetkit-napi@2.3.7", "", { "dependencies": { "@napi-rs/cli": "^2.18.4", "@rivetkit/engine-envoy-protocol": "2.3.7" }, "optionalDependencies": { "@rivetkit/rivetkit-napi-darwin-arm64": "2.3.7", "@rivetkit/rivetkit-napi-darwin-x64": "2.3.7", "@rivetkit/rivetkit-napi-linux-arm64-gnu": "2.3.7", "@rivetkit/rivetkit-napi-linux-arm64-musl": "2.3.7", "@rivetkit/rivetkit-napi-linux-x64-gnu": "2.3.7", "@rivetkit/rivetkit-napi-linux-x64-musl": "2.3.7", "@rivetkit/rivetkit-napi-win32-x64-msvc": "2.3.7" } }, "sha512-1d3HtNKzJwdkznWDWSpCwg1rBn+nVwUfcKrApINTfiEhfDyVeznwbVFkfHWqOBHsjU17vvWFfjjTtf8QsjLwUQ=="], + "@rivetkit/rivetkit-napi": ["@rivetkit/rivetkit-napi@2.3.9", "", { "dependencies": { "@napi-rs/cli": "^2.18.4", "@rivetkit/engine-envoy-protocol": "2.3.9" }, "optionalDependencies": { "@rivetkit/rivetkit-napi-darwin-arm64": "2.3.9", "@rivetkit/rivetkit-napi-darwin-x64": "2.3.9", "@rivetkit/rivetkit-napi-linux-arm64-gnu": "2.3.9", "@rivetkit/rivetkit-napi-linux-arm64-musl": "2.3.9", "@rivetkit/rivetkit-napi-linux-x64-gnu": "2.3.9", "@rivetkit/rivetkit-napi-linux-x64-musl": "2.3.9", "@rivetkit/rivetkit-napi-win32-x64-msvc": "2.3.9" } }, "sha512-lUuOK1ja6ZMwnNRsdtqJeXChbBEqyvHuI/1h5XQWHfBUu7DgX5zuyA/FJ+BY6YFWtwnkHnOVCBJeNx/3gj8Xhg=="], - "@rivetkit/rivetkit-napi-darwin-arm64": ["@rivetkit/rivetkit-napi-darwin-arm64@2.3.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gI1wMe6z85VDeR4K/wnzevVakXTg5UCfvjlDOp1+23nyU3NlInhN156dEWO8EsfRMrs+1bYoGdc4rcoN+4PUrw=="], + "@rivetkit/rivetkit-napi-darwin-arm64": ["@rivetkit/rivetkit-napi-darwin-arm64@2.3.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-3Ls1gHUeYs1mByNDgt1H3s3b9gZaXyyFrrCagoK2HrBAr0celfMa2zh0fH1BrjZufyF5oC/Jvk3ALPCFCNf4EQ=="], - "@rivetkit/rivetkit-napi-darwin-x64": ["@rivetkit/rivetkit-napi-darwin-x64@2.3.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-H5tUwvCbKwTIBiyQG01ikK5mdc9ISg+bv8gPUw41mYOKq8rb9nBLkcl2TKcreFHac8KaGxtnBZzYcjbUV3NcwQ=="], + "@rivetkit/rivetkit-napi-darwin-x64": ["@rivetkit/rivetkit-napi-darwin-x64@2.3.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-tsX60L7RXD9BnMU+0b8YnKfuAqYfH8sr6DnUAWk2z2Nnmc7E11RibVWSeny/+2LxD5Zib3f3G7Ea/Pt/NF+ypA=="], - "@rivetkit/rivetkit-napi-linux-arm64-gnu": ["@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-MpOeiO5M737e93hM/FjcH+zv8xBEX1tgBd/59K/Uw7qlRbWW7JGz8WGjavdxv211LRqxsn8EUlGRxcADDsXnBA=="], + "@rivetkit/rivetkit-napi-linux-arm64-gnu": ["@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-Ov1c40CgIXMiOOo8sLLDO4cCcUw3+H/8OMOYoa7a5a5snmbJlDLSi0YYACWGRcBJvCGrjeDtQGIN3JISTL8Q9Q=="], - "@rivetkit/rivetkit-napi-linux-arm64-musl": ["@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-0GsUgd/HHvIq6v92kp0H175mGm2Exvs4krBLih0MIpVAkqJk8EIcKI6wJhCwY04Fr0MS8sHkUhjuHXa7QcmlYA=="], + "@rivetkit/rivetkit-napi-linux-arm64-musl": ["@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-HgK83QYfT45HI+Ly+gWuoxWDSFzTgYJm0rFlmuOz8zweTirZ4ixHEE/lIQVU16lkHl4cO7PcRbQ1vUeQJMmVtA=="], - "@rivetkit/rivetkit-napi-linux-x64-gnu": ["@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-8wCD1FuDpM+yiKRG8ro1K8ILVpJXzCNKViJ1axq1b4Nyqgod/nyEvvKDaT4qhA5+Om+W5i6YRO1uddjC6QjJSQ=="], + "@rivetkit/rivetkit-napi-linux-x64-gnu": ["@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.9", "", { "os": "linux", "cpu": "x64" }, "sha512-GvGfGUpCpFGWzQdA5Yey5Y5ih+J6Ay/chEwa10UlzF4MC4bX0GM//0m2FXLFUXtBjNRNdhKvAAaXWdWBuZQsSw=="], - "@rivetkit/rivetkit-napi-linux-x64-musl": ["@rivetkit/rivetkit-napi-linux-x64-musl@2.3.7", "", { "os": "linux", "cpu": "x64" }, "sha512-8RGzXD33GH1/DWufFzCZRI+npF5IL/9z7Ja3pthsuYgrL+axGG0iqfAjbwj5HHnB/ceUGQVT+uCKzoLnG+odtw=="], + "@rivetkit/rivetkit-napi-linux-x64-musl": ["@rivetkit/rivetkit-napi-linux-x64-musl@2.3.9", "", { "os": "linux", "cpu": "x64" }, "sha512-J48W7iLoqE8i1n1TvhxkxFrwJTxOsdXrVf7HyXUsEyLrb+kal/aS+/ta+Bfq/veJ7wZyDw7YkOIdn0BgPinIuQ=="], - "@rivetkit/rivetkit-napi-win32-x64-msvc": ["@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.7", "", { "os": "win32", "cpu": "x64" }, "sha512-n1by/coKxWOb2FZDGLM2qmULxcLSqx8hxJuk7Hsb1gl4uNHGviUzYr+r7WAiOzonK/Dgy477u3OKf5yBie743A=="], + "@rivetkit/rivetkit-napi-win32-x64-msvc": ["@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.9", "", { "os": "win32", "cpu": "x64" }, "sha512-3oZYh56m3wTVAbipHI5Rnqw1vSTI1fzoksdm1x4a45TgKi1ULxPyl2fT2E9A/Jyn1LzfTfztazN6mX0//kxmxg=="], - "@rivetkit/rivetkit-wasm": ["@rivetkit/rivetkit-wasm@2.3.7", "", {}, "sha512-o7QBtFOJrajyPVBIDQ32k8sDNFsUc8v2ETfNpr+Ch374ydmZMzCv3XKJU9vubc9bZa7WpCHSzf5ztc8b8i/Xpg=="], + "@rivetkit/rivetkit-wasm": ["@rivetkit/rivetkit-wasm@2.3.9", "", {}, "sha512-KRCKnk0h3dvzuLHHDTKdguSCaZdDpeza4XucYi2+XZaZUJUP1zNxCHfKvQRZ1FaGhPx9rhZJTGV19+lLOWKSwA=="], - "@rivetkit/traces": ["@rivetkit/traces@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2", "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", "vbare": "^0.0.4" } }, "sha512-B7QYjFP2HPxyfPsVjfcNIV7FPLWgGWGypmlT/dZM1i1Cf1WRdeuBumPLffgs3YceiY7Pm4D/gZZVt5p0m4Cx+A=="], + "@rivetkit/traces": ["@rivetkit/traces@2.3.9", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2", "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", "vbare": "^0.0.4" } }, "sha512-T0og48gPh6RjIdwEuG7mEKOuxVA3R/Zcptf67z8dHVF78yuzHooeW0W0rvH6wlu4XGINWvYhGHMGY0uh4uyPEw=="], - "@rivetkit/virtual-websocket": ["@rivetkit/virtual-websocket@2.3.7", "", {}, "sha512-jwxDvYbr3YB6vFuxwRdB/AqUUMwdtC1rIAc4tNN6VQR3weHbE+PrDoHKbe85zrtlBtcnG89/p8tlovrj8qyQWA=="], + "@rivetkit/virtual-websocket": ["@rivetkit/virtual-websocket@2.3.9", "", {}, "sha512-exWO75dBB81w3ipXRg7twXY0SYQyDsB9ELJVhi1LtmWnmCn4FnHlzfinZKZlFAf5C9L0m9XAbJGS3WfRGRGlUg=="], - "@rivetkit/workflow-engine": ["@rivetkit/workflow-engine@2.3.7", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2", "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", "pino": "^9.6.0", "vbare": "^0.0.4" } }, "sha512-+C4kGuSNysrw2zs/LQoYxouOxufKHHMxiIXKF8Ab9GU2BCJ32RUST9dYU/gaQE/w9uM+hqAHUz0DTlOBYU6p6g=="], + "@rivetkit/workflow-engine": ["@rivetkit/workflow-engine@2.3.9", "", { "dependencies": { "@rivetkit/bare-ts": "^0.6.2", "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", "pino": "^9.6.0", "vbare": "^0.0.4" } }, "sha512-RqbXdQYc2z/PCLwOyi14iimE/+m0v7Oq7DKuzdAxs4Y1jqslUZurkn3B40pjhaNN2Kz212BJXnbmaK4YHE/q8g=="], "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.1.4", "", { "os": "android", "cpu": "arm64" }, "sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw=="], @@ -1228,9 +1208,9 @@ "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.62.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.62.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Pch2pFNOxxz1hTjypIdPyRTR6riiwRl84+VcN9djS680fw+Co1nAJINrdpqp7KV0NvyuU8ilZXZCjd7ykJl1GQ=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.62.2", "", { "os": "linux", "cpu": "x64" }, "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.62.3", "", { "os": "linux", "cpu": "x64" }, "sha512-V4KtWtQfAFMU7+9/A/VDps/VI8CHd3cYz0L8sgJzz8qK7eY7wI4ruFD82UYIYvW9Z4DtlTfhQcsl4XyPHW5uSg=="], "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="], @@ -1274,17 +1254,17 @@ "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], - "@smithy/core": ["@smithy/core@3.29.7", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-BiEE2bnnGoPKdlGe3L+gOYORDHFGPuYVRLP7iUow/Sflm0B4hC4XY3FC1MRuc7ltzpW2xNnXopKi34TTkULlKQ=="], + "@smithy/core": ["@smithy/core@3.31.0", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-sylYk2l9d7CmRv8ts8p0SDQUr3VO+HMeS1nrjL6+UtbO8ktJHTOeQ1McX+aAyvGGccp5aZX9eNtdcXrSwzoZaw=="], - "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.4.12", "", { "dependencies": { "@smithy/core": "^3.29.7", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-ZZPDbl/aRp77aycuoMlo3BTayT4CE2a3uoqETYZU5ySnVbhpl5IJiY7dCZedn+ZusyDLqVv44IvKBiXd2/nK0Q=="], + "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.4.15", "", { "dependencies": { "@smithy/core": "^3.31.0", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-xYVGrisQqTJWhOnScUhbx8s9H63TMtoxzuUoxG6mP8J+B/YbX3vZxVsgV0xDf43abJnJP0fjP7BkQh7OESwuRA=="], - "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.6.9", "", { "dependencies": { "@smithy/core": "^3.29.7", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-EJktha5m5MXCwzdXrlWyqb9UCNHNFKlg+PmTpRsdX3dncJPTiqYleM9OKj2mLgdVJHR01d2tU4alG+z2NdH5rQ=="], + "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.6.12", "", { "dependencies": { "@smithy/core": "^3.31.0", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-OpQgP6IGH4j0NJ2zjfYZLjQL85ai+Wi/q51EmZJovXsEwKSvu89qiXUq77Q6EmwZ/hSl7fKpn2Z9mhiDN6OM+Q=="], "@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], "@smithy/node-http-handler": ["@smithy/node-http-handler@4.7.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA=="], - "@smithy/signature-v4": ["@smithy/signature-v4@5.6.8", "", { "dependencies": { "@smithy/core": "^3.29.7", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-iGBm6hIwD2MGvVRSgrjVWa4FXtXDq3akxu0DCpnkmBo0xtEHZ/siMRt7ycfZAefYr2UdywUgmGtoRLaq5u56pg=="], + "@smithy/signature-v4": ["@smithy/signature-v4@5.6.11", "", { "dependencies": { "@smithy/core": "^3.31.0", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-7HsspeiNCZvZHEJ22vV5L/QYuJdTyJvPJvMrYD3AgkM3IJB0pkln4jkjPvtpTWRMkHXbO8WKwNjoVdVlBFwHmw=="], "@smithy/types": ["@smithy/types@4.16.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg=="], @@ -1380,8 +1360,6 @@ "@testing-library/dom": ["@testing-library/dom@10.4.1", "", { "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", "aria-query": "5.3.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", "picocolors": "1.1.1", "pretty-format": "^27.0.2" } }, "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg=="], - "@testing-library/jest-dom": ["@testing-library/jest-dom@6.10.0", "", { "dependencies": { "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", "css.escape": "^1.5.1", "dom-accessibility-api": "^0.6.3", "picocolors": "^1.1.1", "redent": "^3.0.0" }, "peerDependencies": { "@testing-library/dom": ">=10 <11" } }, "sha512-HQwu0KaB2zyT0iLzBL+8CLyZDL3KlZlZJ+2iyc9uCUnlJVskJU/UlPuVCyIPhtukjPQdT2QNoR5nCP5FqTmmDQ=="], - "@testing-library/user-event": ["@testing-library/user-event@14.6.1", "", { "peerDependencies": { "@testing-library/dom": ">=7.21.4" } }, "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw=="], "@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="], @@ -1594,7 +1572,7 @@ "agent-cli-detector": ["agent-cli-detector@0.1.4", "", { "bin": { "agent-cli-detector": "dist/cli.js" } }, "sha512-qPgevFvpaQoBaRJVKzr8R7h1WPvV3DtbgRIQlne4le66KBzXx5hNBwo/+NTw67LgkKBlhCzksrdautpUdlls0Q=="], - "ai": ["ai@7.0.36", "", { "dependencies": { "@ai-sdk/gateway": "4.0.27", "@ai-sdk/provider": "4.0.3", "@ai-sdk/provider-utils": "5.0.12" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-1XJjua58GVQ0CyO2Xbioyladt85x71Joup2U8qKrjHUl8tHYwrDw8iFRtav6e94AxSVCn9FVgTS17oX1OCquKA=="], + "ai": ["ai@7.0.37", "", { "dependencies": { "@ai-sdk/gateway": "4.0.28", "@ai-sdk/provider": "4.0.3", "@ai-sdk/provider-utils": "5.0.12" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-stF+SEQJgKY3Qfe3FwNzqUrehHviOp2l7LemoI8YMOa0Zk5PxKsRNgUk3cHXz0RAue9RRyCAis2fz6LSCP6EKw=="], "ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="], @@ -1618,8 +1596,6 @@ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], - "aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="], "asap": ["asap@2.0.6", "", {}, "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="], @@ -1662,7 +1638,7 @@ "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], - "baseline-browser-mapping": ["baseline-browser-mapping@2.11.1", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-HYXq73DDpCtNzOmrFsm9eSwCvWCql0RzqjpDzXN9EadiLJ4DNat0nsZ/Bzmy+Ud12mb4/zKDY0cQ805ZzN+i0A=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.11.5", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-xJo6a6YZnwZfnyGmQKWMbVOcii7XRibjOskRh+WJ9UHQoX16xrQrcIgAMQOzfvs8XiLMx6ih/fsLPF73iY2D1A=="], "basic-auth": ["basic-auth@2.0.1", "", { "dependencies": { "safe-buffer": "5.1.2" } }, "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg=="], @@ -1696,7 +1672,7 @@ "bplist-parser": ["bplist-parser@0.3.2", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ=="], - "brace-expansion": ["brace-expansion@5.0.7", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA=="], + "brace-expansion": ["brace-expansion@5.0.8", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], @@ -1796,8 +1772,6 @@ "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], - "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], - "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=="], "clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="], @@ -1806,14 +1780,10 @@ "code-block-writer": ["code-block-writer@13.0.3", "", {}, "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg=="], - "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], - "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], "commander": ["commander@15.0.0", "", {}, "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg=="], @@ -1872,22 +1842,16 @@ "croner": ["croner@10.0.1", "", {}, "sha512-ixNtAJndqh173VQ4KodSdJEI6nuioBWI0V1ITNKhZZsO0pEMoDxz539T4FTTbSZ/xIOSuDnzxLVRqBVSvPNE2g=="], - "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="], - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "crypto-browserify": ["crypto-browserify@3.12.1", "", { "dependencies": { "browserify-cipher": "^1.0.1", "browserify-sign": "^4.2.3", "create-ecdh": "^4.0.4", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", "diffie-hellman": "^5.0.3", "hash-base": "~3.0.4", "inherits": "^2.0.4", "pbkdf2": "^3.1.2", "public-encrypt": "^4.0.3", "randombytes": "^2.1.0", "randomfill": "^1.0.4" } }, "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ=="], - "css-in-js-utils": ["css-in-js-utils@3.1.0", "", { "dependencies": { "hyphenate-style-name": "^1.0.3" } }, "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A=="], - "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], "css-tree": ["css-tree@1.1.3", "", { "dependencies": { "mdn-data": "2.0.14", "source-map": "^0.6.1" } }, "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q=="], "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], - "css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="], - "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], @@ -1970,12 +1934,10 @@ "debounce-fn": ["debounce-fn@4.0.0", "", { "dependencies": { "mimic-fn": "^3.0.0" } }, "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ=="], - "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], - "decode-uri-component": ["decode-uri-component@0.2.2", "", {}, "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="], - "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], "dedent": ["dedent@1.7.2", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA=="], @@ -2014,8 +1976,6 @@ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], - "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="], @@ -2054,7 +2014,7 @@ "effect": ["effect@4.0.0-beta.99", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.9.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.4", "multipasta": "^0.2.8", "toml": "^4.1.2", "uuid": "^14.0.1", "yaml": "^2.9.0" } }, "sha512-hP1C61uzINfLl/4kKMwcqksxd34s4sQ3VSjsWjhGrkx9CRlXaqnfOK9dpTEKynQ6rA7wU9rb3c+48eDYw7uzxA=="], - "electron-to-chromium": ["electron-to-chromium@1.5.395", "", {}, "sha512-7zt9Aw+SrmxLWLN0zhaTWZQiCdryLVrYTq5R7iZakLvi2UQPYMMsROYV/2qVCzMeCiSXHwKOU+sZ4zOVVlrtKA=="], + "electron-to-chromium": ["electron-to-chromium@1.5.396", "", {}, "sha512-yHiw2Y3C3H9U6TMbOfoWK/BPreiOPXRfTWPBwQBoZG6/8TB6eOPnsy5oaRYuatR7Fw2SJ4kKforgufeo7fq0EQ=="], "elliptic": ["elliptic@6.6.1", "", { "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", "hash.js": "^1.0.0", "hmac-drbg": "^1.0.1", "inherits": "^2.0.4", "minimalistic-assert": "^1.0.1", "minimalistic-crypto-utils": "^1.0.1" } }, "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g=="], @@ -2086,7 +2046,7 @@ "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], - "es-toolkit": ["es-toolkit@1.49.0", "", {}, "sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g=="], + "es-toolkit": ["es-toolkit@1.50.0", "", {}, "sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w=="], "esbuild": ["esbuild@0.27.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.0", "@esbuild/android-arm": "0.27.0", "@esbuild/android-arm64": "0.27.0", "@esbuild/android-x64": "0.27.0", "@esbuild/darwin-arm64": "0.27.0", "@esbuild/darwin-x64": "0.27.0", "@esbuild/freebsd-arm64": "0.27.0", "@esbuild/freebsd-x64": "0.27.0", "@esbuild/linux-arm": "0.27.0", "@esbuild/linux-arm64": "0.27.0", "@esbuild/linux-ia32": "0.27.0", "@esbuild/linux-loong64": "0.27.0", "@esbuild/linux-mips64el": "0.27.0", "@esbuild/linux-ppc64": "0.27.0", "@esbuild/linux-riscv64": "0.27.0", "@esbuild/linux-s390x": "0.27.0", "@esbuild/linux-x64": "0.27.0", "@esbuild/netbsd-arm64": "0.27.0", "@esbuild/netbsd-x64": "0.27.0", "@esbuild/openbsd-arm64": "0.27.0", "@esbuild/openbsd-x64": "0.27.0", "@esbuild/openharmony-arm64": "0.27.0", "@esbuild/sunos-x64": "0.27.0", "@esbuild/win32-arm64": "0.27.0", "@esbuild/win32-ia32": "0.27.0", "@esbuild/win32-x64": "0.27.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA=="], @@ -2098,7 +2058,7 @@ "escodegen": ["escodegen@2.1.0", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w=="], - "eslint": ["eslint@10.7.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.6.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-GVTD7s1vdIl6UYvAfriOPeY1Df8LIZjfofLvHwde+erDHGGuHyuM6xoxRxmHiebhYuD2p1vN4wWh0XzPARSGDQ=="], + "eslint": ["eslint@10.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.7.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ=="], "eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="], @@ -2150,37 +2110,25 @@ "expo-font": ["expo-font@57.0.1", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-QyS9L1Kh9sKJg4gfU6rdbpxpmH+DyzBX8z6jVvXMUDoqLr1GqmkO/Wu379KCXjL///kWbhpNlbi7AgBuj4VdIQ=="], - "expo-glass-effect": ["expo-glass-effect@57.0.1", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-m/n8maxqNcHk6ZDhuqXBfD5Kt1Iz3M8xykVgdB0iSCIXvF70IqWXmQhX8Psswhrp8eZ+3r0mAD0Jh/2gFA3QaA=="], - "expo-keep-awake": ["expo-keep-awake@57.0.1", "", { "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-28lkFImeXTS+bhAjuCFV7w7tW5bXg27BJVrxv+nC/nyYa86qEa0oFeHwqol6ha5k4pdVDQgBF09GM4A1k76Ssg=="], - "expo-linking": ["expo-linking@57.0.4", "", { "dependencies": { "expo-constants": "~57.0.7", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-e1alfHNJdywIfJkCuKMc6M3hBfAGPd2gKMeF/6V7qwFWzHCS2mTBqU+KaO4FLpltA5Nt6CYEx6zmUlGfUF+8lA=="], - "expo-modules-autolinking": ["expo-modules-autolinking@57.0.9", "", { "dependencies": { "@expo/require-utils": "^57.0.4", "@expo/spawn-async": "^1.8.0", "chalk": "^4.1.0", "commander": "^7.2.0" }, "bin": { "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, "sha512-lj2nsAKMMRLXSFnGgaaQrWJ2fdSpLPc/bca6Rkiw4g8zYPn7qX4MRUJgavvzm/hBrzvMnlhXVgJtidOGuwBh+w=="], "expo-modules-core": ["expo-modules-core@57.0.7", "", { "dependencies": { "@expo/expo-modules-macros-plugin": "0.6.1", "expo-modules-jsi": "~57.0.4", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-worklets": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0" }, "optionalPeers": ["react-native-worklets"] }, "sha512-5HrbCfgYmLs0a5dzfM4GmRGelVTPIg+eYp0vmSbWnKRTOPj5DyVOfg1rHGEsuNKp07QwDxfLJfQVp8CNbuvxMQ=="], "expo-modules-jsi": ["expo-modules-jsi@57.0.4", "", { "peerDependencies": { "react-native": "*" } }, "sha512-vt7FyqUqqFXiRVnBqYD7y+GSPTgeua5Ocoy0+SYt+RSHkZEA2Fyop7If3g1TYDzQObYybPRo7TG2Rle1XLaWFw=="], - "expo-network": ["expo-network@57.0.1", "", { "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-ndg+FbDDlz6XTpQ6aVuVgyvrYQwMkpcUAvZIXbwrGBbLTSWNzYC/gawYu1BAeDN7O6JTGY98GBVJBov/JH7LgQ=="], - - "expo-router": ["expo-router@57.0.8", "", { "dependencies": { "@expo/log-box": "^57.0.1", "@expo/metro-runtime": "^57.0.7", "@expo/schema-utils": "^57.0.2", "@expo/ui": "^57.0.7", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-native-masked-view/masked-view": "^0.3.2", "@testing-library/jest-dom": "^6.9.1", "@testing-library/user-event": "^14.6.1", "client-only": "^0.0.1", "color": "^4.2.3", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "expo-glass-effect": "^57.0.1", "expo-server": "^57.0.1", "expo-symbols": "^57.0.1", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-is": "^19.1.0", "react-native-drawer-layout": "^4.2.2", "react-native-screens": "^4.26.0", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "standard-navigation": "^0.0.5", "vaul": "^1.1.2" }, "peerDependencies": { "@testing-library/react-native": ">= 13.2.0", "expo": "*", "expo-constants": "^57.0.7", "expo-linking": "^57.0.4", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-web": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-xAyTnZl597G9/r17GOuyTy6VlhjYCVmgzgmP00bhZ9b+VstPl3tTrOOhSFagVpeln47nKp7x7vgkANNheCv4eQ=="], - "expo-secure-store": ["expo-secure-store@57.0.1", "", { "peerDependencies": { "expo": "*" } }, "sha512-tLa1VmSadOq19mA/dwkl99RbHyjLE0T1qqBYMY3/OsguZTI+rlrDy/DDJjupqlVtmr95hD7o1pYqx5aL+B4YMA=="], "expo-server": ["expo-server@57.0.1", "", {}, "sha512-sBfVDH6dmKVHZxqUxbfkzS00PZELMZt1IpnHKxcOTMZtR/t7CtRAFrbXcisG+EyzeqHSVDacZT+1tbYfZt5D8w=="], - "expo-symbols": ["expo-symbols@57.0.1", "", { "dependencies": { "@expo-google-fonts/material-symbols": "^0.4.1", "sf-symbols-typescript": "^2.0.0" }, "peerDependencies": { "expo": "*", "expo-font": "*", "react": "*", "react-native": "*" } }, "sha512-8Zf+a83OywV0vf1NUtSKpNqKcULmO0GTI+zfFnGYl7SLDH9FjL5RcEZoy6CHvCgq2KDrQF21pl3r7Tb4ItPscw=="], - - "expo-web-browser": ["expo-web-browser@57.0.2", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-3vl5kvd7PB48ub6PpNIJUuPxO8xVa6D8RnIgNba6SXRwqFprOfeEZgwTgtm41kz0AAtvMOztUVNEUkwrHKjqMQ=="], - "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="], "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=="], - "express-rate-limit": ["express-rate-limit@8.6.0", "", { "dependencies": { "debug": "^4.4.3", "ip-address": "^10.2.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-XKJXDsASUOo0LLtFwW5hCcQGH0N4WQc/Rn8/Pvoia+TJFOkkFPvrtW9lZOeeNcxQJspvOIERMwiRLsVFlhHEkA=="], + "express-rate-limit": ["express-rate-limit@8.6.1", "", { "dependencies": { "debug": "^4.4.3", "ip-address": "^10.2.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-0D493aP61w0TJ2A0wy27riRsO7FMQ7FK+KUHOKCSfPvYo0R55aiC6emCVgFUeShH0fq0ICPVzNcgoS+BsbXQCA=="], - "exsolve": ["exsolve@1.1.0", "", {}, "sha512-D+42+T12DdIlJM3uepa55qGiL3sYdLBOxIl2ifQCzCHz4c7eiolaHsi3BIqEr7JxBzxv2pYZQX9kw16ziMcEmw=="], + "exsolve": ["exsolve@1.1.1", "", {}, "sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g=="], "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], @@ -2214,10 +2162,6 @@ "fb-watchman": ["fb-watchman@2.0.2", "", { "dependencies": { "bser": "2.1.1" } }, "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA=="], - "fbjs": ["fbjs@3.0.5", "", { "dependencies": { "cross-fetch": "^3.1.5", "fbjs-css-vars": "^1.0.0", "loose-envify": "^1.0.0", "object-assign": "^4.1.0", "promise": "^7.1.1", "setimmediate": "^1.0.5", "ua-parser-js": "^1.0.35" } }, "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg=="], - - "fbjs-css-vars": ["fbjs-css-vars@1.0.2", "", {}, "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="], - "fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="], "fdb-tuple": ["fdb-tuple@1.0.0", "", {}, "sha512-8jSvKPCYCgTpi9Pt87qlfTk6griyMx4Gk3Xv31Dp72Qp8b6XgIyFsMm8KzPmFJ9iJ8K4pGvRxvOS8D0XGnrkjw=="], @@ -2238,8 +2182,6 @@ "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], - "filter-obj": ["filter-obj@1.1.0", "", {}, "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="], - "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="], "find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="], @@ -2268,7 +2210,7 @@ "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], - "fs-extra": ["fs-extra@11.3.6", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA=="], + "fs-extra": ["fs-extra@11.4.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], @@ -2276,7 +2218,7 @@ "fuzzysort": ["fuzzysort@3.1.0", "", {}, "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ=="], - "gaxios": ["gaxios@7.2.0", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg=="], + "gaxios": ["gaxios@7.3.0", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA=="], "gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="], @@ -2290,8 +2232,6 @@ "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], - "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], - "get-own-enumerable-keys": ["get-own-enumerable-keys@1.0.0", "", {}, "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA=="], "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], @@ -2312,7 +2252,7 @@ "goober": ["goober@2.1.19", "", { "peerDependencies": { "csstype": "^3.0.10" } }, "sha512-U7veizMqxyKlM58+Z5j2ngJBH/r9siDmxpvNxSw0PylF6WQvrASJEZrxh1hidRBJc2jqoBVSyOban5u8m+6Rxg=="], - "google-auth-library": ["google-auth-library@10.9.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg=="], + "google-auth-library": ["google-auth-library@10.9.1", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw=="], "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], @@ -2384,7 +2324,7 @@ "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], - "hono": ["hono@4.12.31", "", {}, "sha512-zJIHFrl6bq3RDd2YusFNCDlM8qUprxKswyi/OPzPyzKDdyBXDqWx8bZlZ7R+saTdSTatUmb3O7K4SspGPaEOQg=="], + "hono": ["hono@4.12.32", "", {}, "sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg=="], "hono-openapi": ["hono-openapi@1.3.1", "", { "peerDependencies": { "@hono/standard-validator": "^0.2.0", "@standard-community/standard-json": "^0.3.5", "@standard-community/standard-openapi": "^0.2.9", "@types/json-schema": "^7.0.15", "hono": "^4.11.2", "openapi-types": "^12.1.3" }, "optionalPeers": ["@hono/standard-validator", "hono"] }, "sha512-NLVeVkhKZ3drmQNEIPac8HX8Y54uf1hJAgIM/7MfDsaeVVmB+QILWQxx5x3R3NvRHgedcbEbOCGY2uR7WQYyMw=="], @@ -2404,8 +2344,6 @@ "human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="], - "hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="], - "iconv-lite": ["iconv-lite@0.7.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ=="], "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], @@ -2420,21 +2358,17 @@ "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], - "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], "ini": ["ini@7.0.0", "", {}, "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w=="], "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="], - "inline-style-prefixer": ["inline-style-prefixer@7.0.1", "", { "dependencies": { "css-in-js-utils": "^3.1.0" } }, "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw=="], - "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], "invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="], - "ip-address": ["ip-address@10.2.0", "", {}, "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA=="], + "ip-address": ["ip-address@10.3.1", "", {}, "sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g=="], "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], @@ -2550,7 +2484,7 @@ "jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], - "just-bash": ["just-bash@3.1.0", "", { "dependencies": { "diff": "^8.0.2", "fast-xml-parser": "^5.7.3", "file-type": "^21.2.0", "ini": "^6.0.0", "minimatch": "^10.1.1", "modern-tar": "^0.7.3", "papaparse": "^5.5.3", "quickjs-emscripten": "^0.32.0", "re2js": "^1.2.1", "seek-bzip": "^2.0.0", "smol-toml": "^1.6.0", "sprintf-js": "^1.1.3", "sql.js": "^1.13.0", "turndown": "^7.2.2", "yaml": "^2.8.2" }, "optionalDependencies": { "@mongodb-js/zstd": "^7.0.0", "node-liblzma": "^2.0.3" }, "bin": { "just-bash": "dist/bin/just-bash.js", "just-bash-shell": "dist/bin/shell/shell.js" } }, "sha512-/t28X8EH3+j/zvELGkNhlFV2g6hc3oHBzy6zPBnNq2nqUN0DGS9PsD889JfQ7F6ll08gqFoutiS+VJHK30wZpg=="], + "just-bash": ["just-bash@3.2.0", "", { "dependencies": { "diff": "^8.0.2", "fast-xml-parser": "^5.7.3", "file-type": "^21.2.0", "ini": "^6.0.0", "minimatch": "^10.1.1", "modern-tar": "^0.7.3", "papaparse": "^5.5.3", "quickjs-emscripten": "^0.32.0", "re2js": "^1.2.1", "seek-bzip": "^2.0.0", "smol-toml": "^1.6.0", "sprintf-js": "^1.1.3", "sql.js": "^1.13.0", "turndown": "^7.2.2", "undici": "^7.25.0", "yaml": "^2.8.2" }, "optionalDependencies": { "@mongodb-js/zstd": "^7.0.0", "node-liblzma": "^2.0.3" }, "bin": { "just-bash": "dist/bin/just-bash.js", "just-bash-shell": "dist/bin/shell/shell.js" } }, "sha512-hRTLLWBXCKuosjaNFJR7uPYBza+T2vjG3NdPBz4wxlctlnxwrbLjtLQf6RtSKmy/jzNJ6/URCtvxrXjy6yFGeQ=="], "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=="], @@ -2632,7 +2566,7 @@ "lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="], - "lucide-react": ["lucide-react@1.25.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-/mdJTRbiwcLOQ1NZZK1amZF9rIZyvO18D6r9TngE6TG1NmqHgFuT4eE7Xrkm9UsXMbBJD1NlfwHVltCDWHrOTw=="], + "lucide-react": ["lucide-react@1.27.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-rJicGl/3Fly/E0rOH1YmPZ6e49JCnKknh1ox1vpHnkfjujAkKA6sqUZvH3MTAaXXjgexyUwgNwTJzTtYuAFYJw=="], "lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="], @@ -2688,7 +2622,7 @@ "mdn-data": ["mdn-data@2.0.14", "", {}, "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="], - "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], + "media-typer": ["media-typer@1.1.1", "", {}, "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ=="], "memoize-one": ["memoize-one@5.2.1", "", {}, "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="], @@ -2808,15 +2742,13 @@ "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], - "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="], - - "miniflare": ["miniflare@4.20260721.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.34.5", "undici": "7.28.0", "workerd": "1.20260721.1", "ws": "8.21.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-fBLaCxZ2i/nPH8iyLzvza0C8/sSF4sjD1ma1Skf+pkZVK0TlaW5ujHJlUHwcwR66v2JZt+Q28d4DCX/oaLG0cA=="], + "miniflare": ["miniflare@4.20260722.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.35.2", "undici": "7.28.0", "workerd": "1.20260722.1", "ws": "8.21.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-LW6ABMhCx/yIEFBLC/DO4yAhdm2T/G7jp7pr5T2kj895+CCIaHZqpMXdW9O6YE48LcYcCJChwWc8aEs1vpbTXw=="], "minimalistic-assert": ["minimalistic-assert@1.0.1", "", {}, "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="], "minimalistic-crypto-utils": ["minimalistic-crypto-utils@1.0.1", "", {}, "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="], - "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + "minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], @@ -2940,9 +2872,9 @@ "os-browserify": ["os-browserify@0.3.0", "", {}, "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A=="], - "oxfmt": ["oxfmt@0.60.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.60.0", "@oxfmt/binding-android-arm64": "0.60.0", "@oxfmt/binding-darwin-arm64": "0.60.0", "@oxfmt/binding-darwin-x64": "0.60.0", "@oxfmt/binding-freebsd-x64": "0.60.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.60.0", "@oxfmt/binding-linux-arm-musleabihf": "0.60.0", "@oxfmt/binding-linux-arm64-gnu": "0.60.0", "@oxfmt/binding-linux-arm64-musl": "0.60.0", "@oxfmt/binding-linux-ppc64-gnu": "0.60.0", "@oxfmt/binding-linux-riscv64-gnu": "0.60.0", "@oxfmt/binding-linux-riscv64-musl": "0.60.0", "@oxfmt/binding-linux-s390x-gnu": "0.60.0", "@oxfmt/binding-linux-x64-gnu": "0.60.0", "@oxfmt/binding-linux-x64-musl": "0.60.0", "@oxfmt/binding-openharmony-arm64": "0.60.0", "@oxfmt/binding-win32-arm64-msvc": "0.60.0", "@oxfmt/binding-win32-ia32-msvc": "0.60.0", "@oxfmt/binding-win32-x64-msvc": "0.60.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-fViX6i+gJuZWY+jI/fnR6WRbRj70GZ9RlCd30MygJrHTUNc4DxvKHWw8vBjMjffv3PgU5qWDR0AzmojQByqaZA=="], + "oxfmt": ["oxfmt@0.61.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.61.0", "@oxfmt/binding-android-arm64": "0.61.0", "@oxfmt/binding-darwin-arm64": "0.61.0", "@oxfmt/binding-darwin-x64": "0.61.0", "@oxfmt/binding-freebsd-x64": "0.61.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.61.0", "@oxfmt/binding-linux-arm-musleabihf": "0.61.0", "@oxfmt/binding-linux-arm64-gnu": "0.61.0", "@oxfmt/binding-linux-arm64-musl": "0.61.0", "@oxfmt/binding-linux-ppc64-gnu": "0.61.0", "@oxfmt/binding-linux-riscv64-gnu": "0.61.0", "@oxfmt/binding-linux-riscv64-musl": "0.61.0", "@oxfmt/binding-linux-s390x-gnu": "0.61.0", "@oxfmt/binding-linux-x64-gnu": "0.61.0", "@oxfmt/binding-linux-x64-musl": "0.61.0", "@oxfmt/binding-openharmony-arm64": "0.61.0", "@oxfmt/binding-win32-arm64-msvc": "0.61.0", "@oxfmt/binding-win32-ia32-msvc": "0.61.0", "@oxfmt/binding-win32-x64-msvc": "0.61.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-DxdHBEMYpcEnHoUHjjOigUqV2TYKsvxLwUPXnVYBjgFdqrcQ/91OtwubtZ2PUodCs3sStI8R5Qw3fKNGK4e8wQ=="], - "oxlint": ["oxlint@1.75.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.75.0", "@oxlint/binding-android-arm64": "1.75.0", "@oxlint/binding-darwin-arm64": "1.75.0", "@oxlint/binding-darwin-x64": "1.75.0", "@oxlint/binding-freebsd-x64": "1.75.0", "@oxlint/binding-linux-arm-gnueabihf": "1.75.0", "@oxlint/binding-linux-arm-musleabihf": "1.75.0", "@oxlint/binding-linux-arm64-gnu": "1.75.0", "@oxlint/binding-linux-arm64-musl": "1.75.0", "@oxlint/binding-linux-ppc64-gnu": "1.75.0", "@oxlint/binding-linux-riscv64-gnu": "1.75.0", "@oxlint/binding-linux-riscv64-musl": "1.75.0", "@oxlint/binding-linux-s390x-gnu": "1.75.0", "@oxlint/binding-linux-x64-gnu": "1.75.0", "@oxlint/binding-linux-x64-musl": "1.75.0", "@oxlint/binding-openharmony-arm64": "1.75.0", "@oxlint/binding-win32-arm64-msvc": "1.75.0", "@oxlint/binding-win32-ia32-msvc": "1.75.0", "@oxlint/binding-win32-x64-msvc": "1.75.0" }, "peerDependencies": { "oxlint-tsgolint": ">=7.0.2001", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-m9WzjRcRYA/uqIZDa9tclrieoPJ/ln1QYTKdFx6NUOs8uY5DiHlIwRQoCrHT6OM6O3ww3l2skY5gO7G7ZphE7g=="], + "oxlint": ["oxlint@1.76.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.76.0", "@oxlint/binding-android-arm64": "1.76.0", "@oxlint/binding-darwin-arm64": "1.76.0", "@oxlint/binding-darwin-x64": "1.76.0", "@oxlint/binding-freebsd-x64": "1.76.0", "@oxlint/binding-linux-arm-gnueabihf": "1.76.0", "@oxlint/binding-linux-arm-musleabihf": "1.76.0", "@oxlint/binding-linux-arm64-gnu": "1.76.0", "@oxlint/binding-linux-arm64-musl": "1.76.0", "@oxlint/binding-linux-ppc64-gnu": "1.76.0", "@oxlint/binding-linux-riscv64-gnu": "1.76.0", "@oxlint/binding-linux-riscv64-musl": "1.76.0", "@oxlint/binding-linux-s390x-gnu": "1.76.0", "@oxlint/binding-linux-x64-gnu": "1.76.0", "@oxlint/binding-linux-x64-musl": "1.76.0", "@oxlint/binding-openharmony-arm64": "1.76.0", "@oxlint/binding-win32-arm64-msvc": "1.76.0", "@oxlint/binding-win32-ia32-msvc": "1.76.0", "@oxlint/binding-win32-x64-msvc": "1.76.0" }, "peerDependencies": { "oxlint-tsgolint": ">=7.0.2001", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-6QoFioEU4fNdiUx/2Eo6TRd6NG7H7njnRCz8rhB66cZmMHDTqcm1Rjvl8Wry+ZTQMBAmyb4Mlf62Mk5X+eHSOw=="], "oxlint-tsgolint": ["oxlint-tsgolint@0.24.0", "", { "optionalDependencies": { "@oxlint-tsgolint/darwin-arm64": "0.24.0", "@oxlint-tsgolint/darwin-x64": "0.24.0", "@oxlint-tsgolint/linux-arm64": "0.24.0", "@oxlint-tsgolint/linux-x64": "0.24.0", "@oxlint-tsgolint/win32-arm64": "0.24.0", "@oxlint-tsgolint/win32-x64": "0.24.0" }, "bin": { "tsgolint": "bin/tsgolint.js" } }, "sha512-giCk5sEvG02d5tzPmFMX3hem8ndzEEu1xvGYS5OwNfO2WGl6ZVxt5LjE0yiMDoz94INI7XkXwgFAQiydPvVHDw=="], @@ -3038,12 +2970,10 @@ "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], - "postcss": ["postcss@8.5.22", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-KBDEIpLrvpv16pp3K0Fw+UCoZfopFjjgeB+0tA/aaThfEE74kKDLrgg603YvOWJyg3+WYtyq3xYsQWsIyZlPqQ=="], + "postcss": ["postcss@8.5.23", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg=="], "postcss-selector-parser": ["postcss-selector-parser@7.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg=="], - "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], - "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="], "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="], @@ -3098,8 +3028,6 @@ "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], - "query-string": ["query-string@7.1.3", "", { "dependencies": { "decode-uri-component": "^0.2.2", "filter-obj": "^1.1.0", "split-on-first": "^1.0.0", "strict-uri-encode": "^2.0.0" } }, "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg=="], - "querystring-es3": ["querystring-es3@0.2.1", "", {}, "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA=="], "queue": ["queue@6.0.2", "", { "dependencies": { "inherits": "~2.0.3" } }, "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA=="], @@ -3116,7 +3044,7 @@ "randomfill": ["randomfill@1.0.4", "", { "dependencies": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" } }, "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw=="], - "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + "range-parser": ["range-parser@1.3.0", "", {}, "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw=="], "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], @@ -3132,10 +3060,6 @@ "react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="], - "react-fast-compare": ["react-fast-compare@3.2.2", "", {}, "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="], - - "react-freeze": ["react-freeze@1.0.4", "", { "peerDependencies": { "react": ">=17.0.0" } }, "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA=="], - "react-hotkeys-hook": ["react-hotkeys-hook@5.3.3", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-aswgyWUnE25hmhzHTfKDmKzsaSE5DJ4LKaU/o6rQSXkDd/1Bh9TfAFQbHkf6fLy11HvlYkp+cDDarGdhmCDhoQ=="], "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], @@ -3144,36 +3068,24 @@ "react-native": ["react-native@0.86.0", "", { "dependencies": { "@react-native/assets-registry": "0.86.0", "@react-native/codegen": "0.86.0", "@react-native/community-cli-plugin": "0.86.0", "@react-native/gradle-plugin": "0.86.0", "@react-native/js-polyfills": "0.86.0", "@react-native/normalize-colors": "0.86.0", "@react-native/virtualized-lists": "0.86.0", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-plugin-syntax-hermes-parser": "0.36.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.14", "invariant": "^2.2.4", "memoize-one": "^5.0.0", "metro-runtime": "^0.84.3", "metro-source-map": "^0.84.3", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@react-native/jest-preset": "0.86.0", "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@react-native/jest-preset", "@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-17ALh/dd6AO4pgOVmOO5Axll5PbErEo3XFyLokyzW6usyi+OShIEPwUW26wLPlhVifgSOIfECCH0WN+0IqtJ1w=="], - "react-native-drawer-layout": ["react-native-drawer-layout@4.2.9", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*", "react-native-gesture-handler": ">= 2.0.0", "react-native-reanimated": ">= 2.0.0" } }, "sha512-ETOxvlhhb4LmuuG3RN7A3qwt9jr9AZ2it+1G2kNE4g2fTyxxay7QQkPm1HfKi/JzmMSWC5+YTepGSgZNpJIDGg=="], - "react-native-gesture-handler": ["react-native-gesture-handler@2.32.0", "", { "dependencies": { "@egjs/hammerjs": "^2.0.17", "@types/react-test-renderer": "^19.1.0", "hoist-non-react-statics": "^3.3.0", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-uYIMOKlKENORq2SABE+jIjbPU+h5I/sQKcq2v16zRq848nwEp1fWRVwML4QWqijc8UcXJC25o54S8GQd4Mf2OA=="], "react-native-is-edge-to-edge": ["react-native-is-edge-to-edge@1.3.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-NIXU/iT5+ORyCc7p0z2nnlkouYKX425vuU1OEm6bMMtWWR9yvb+Xg5AZmImTKoF9abxCPqrKC3rOZsKzUYgYZA=="], - "react-native-reanimated": ["react-native-reanimated@4.5.0", "", { "dependencies": { "react-native-is-edge-to-edge": "^1.3.1", "semver": "^7.7.3" }, "peerDependencies": { "react": "*", "react-native": "0.83 - 0.86", "react-native-worklets": "0.10.x" } }, "sha512-+iPfvK34PKKYP/p/4TaBliFkbfvjGDIvXuiiaxvISP5ip7sWegvlacwU/uAV6zNDSSmX0tDyER7PurPMKGDipA=="], + "react-native-reanimated": ["react-native-reanimated@4.5.3", "", { "dependencies": { "react-native-is-edge-to-edge": "^1.3.1", "semver": "^7.7.3" }, "peerDependencies": { "react": "*", "react-native": "0.83 - 0.86", "react-native-worklets": "0.10.x - 0.11.x" } }, "sha512-+owIckpD4sA13XKHaLrr8V1RP4paqoxKvz/jy2wl/ULjMsfcRlfIJdKJxR1kcQr4McBZ6hAoPo01NyLnmy2ycQ=="], - "react-native-safe-area-context": ["react-native-safe-area-context@5.7.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-/9/MtQz8ODphjsLdZ+GZAIcC/RtoqW9EeShf7Uvnfgm/pzYrJ75y3PV/J1wuAV1T5Dye5ygq4EAW20RoBq0ABQ=="], + "react-native-safe-area-context": ["react-native-safe-area-context@5.8.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-t+ZsAVzY/wWzzx34vqGbo3/as9EEESJdbyZNL7Yg5EYX+toYMtMqFoDDCvqZUi35eeGVsXc6pAaEk4edMwbuCQ=="], - "react-native-screens": ["react-native-screens@4.25.2", "", { "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" }, "peerDependencies": { "react": "*", "react-native": ">=0.82.0" } }, "sha512-1Nj1fusFd+rIMKU/qC9yGKVG+3ofh11d3OdBQKL1iVvQfKvcB8vhvTGQf2TkfxW3bamxN+hCZIXmNuU0mRkyDg=="], + "react-native-svg": ["react-native-svg@15.15.5", "", { "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-L4go5jA+GWutdJ/JucuN20cjAbMg1HmMtAP+wZ+3JLCf6Jd0bhXQHxciRP/AQm/FlrIEZwkMcHNZP+FXAiic0w=="], - "react-native-svg": ["react-native-svg@15.15.4", "", { "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3", "warn-once": "0.1.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-boT/vIRgj6zZKBpfTPJJiYWMbZE9duBMOwPK6kCSTgxsS947IFMOq9OgIFkpWZTB7t229H24pDRkh3W9ZK/J1A=="], - - "react-native-web": ["react-native-web@0.21.2", "", { "dependencies": { "@babel/runtime": "^7.18.6", "@react-native/normalize-colors": "^0.74.1", "fbjs": "^3.0.4", "inline-style-prefixer": "^7.0.1", "memoize-one": "^6.0.0", "nullthrows": "^1.1.1", "postcss-value-parser": "^4.2.0", "styleq": "^0.1.3" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg=="], - - "react-native-worklets": ["react-native-worklets@0.10.0", "", { "dependencies": { "@babel/plugin-transform-arrow-functions": "^7.27.1", "@babel/plugin-transform-class-properties": "^7.28.6", "@babel/plugin-transform-classes": "^7.28.6", "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", "@babel/plugin-transform-optional-chaining": "^7.28.6", "@babel/plugin-transform-shorthand-properties": "^7.27.1", "@babel/plugin-transform-template-literals": "^7.27.1", "@babel/plugin-transform-unicode-regex": "^7.27.1", "@babel/preset-typescript": "^7.28.5", "@babel/types": "^7.27.1", "convert-source-map": "^2.0.0", "semver": "^7.7.4" }, "peerDependencies": { "@babel/core": "*", "@react-native/metro-config": "*", "react": "*", "react-native": "0.83 - 0.86" } }, "sha512-JhE6IxDf6iabC0qu3+TAKA4v9RlluXmoIngPQX7/QUByf75lfrsHZ6/dQhyjEWnp1EEQiwzz8Cpew140ZcewDw=="], + "react-native-worklets": ["react-native-worklets@0.11.3", "", { "dependencies": { "@babel/generator": "^7.27.1", "@babel/plugin-transform-arrow-functions": "^7.27.1", "@babel/plugin-transform-class-properties": "^7.28.6", "@babel/plugin-transform-classes": "^7.28.6", "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", "@babel/plugin-transform-optional-chaining": "^7.28.6", "@babel/plugin-transform-shorthand-properties": "^7.27.1", "@babel/plugin-transform-template-literals": "^7.27.1", "@babel/plugin-transform-unicode-regex": "^7.27.1", "@babel/preset-typescript": "^7.28.5", "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1", "convert-source-map": "^2.0.0", "semver": "^7.7.4" }, "peerDependencies": { "@babel/core": "*", "@react-native/metro-config": "*", "react": "*", "react-native": "0.83 - 0.86" } }, "sha512-paLRlVFTrrGhkGTi37LHwtaJbrTftA54/zAx1h/ONSBw7XejZn6XUUl1KpM6EOMwsbw7TEGuxJXTAp/wkvuMqQ=="], "react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="], - "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="], - - "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], - "react-router": ["react-router@8.3.0", "", { "dependencies": { "cookie-es": "^3.1.1" }, "peerDependencies": { "react": ">=19.2.7", "react-dom": ">=19.2.7" }, "optionalPeers": ["react-dom"] }, "sha512-qyPMvW83jGIct3yiieisxdk9M745anqhpIMKN5m1t6yBMfgVPpt77aHOqs5fUlEJRMCGffg9BaQLH9oPVOL7xQ=="], "react-router-devtools": ["react-router-devtools@6.2.1", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@radix-ui/react-accordion": "^1.2.12", "@tanstack/devtools-client": "^0.0.5", "@tanstack/devtools-event-client": "^0.4.0", "@tanstack/devtools-vite": "^0.4.1", "@tanstack/react-devtools": "^0.9.1", "chalk": "5.6.2", "clsx": "2.1.1", "framer-motion": "^12.23.24", "goober": "^2.1.18", "react-d3-tree": "^3.6.6", "react-hotkeys-hook": "^5.2.1", "react-tooltip": "^5.30.0" }, "optionalDependencies": { "@biomejs/cli-darwin-arm64": "^2.3.5", "@rollup/rollup-darwin-arm64": "^4.53.2", "@rollup/rollup-linux-x64-gnu": "^4.53.2" }, "peerDependencies": { "@types/react": ">=17", "@types/react-dom": ">=17", "react": ">=17", "react-dom": ">=17", "react-router": ">=7.0.0", "vite": ">=5.0.0 || >=6.0.0" } }, "sha512-qhQg5bJvsiWQpCddehh7HUpNt/zGlxHygG3rseooky1ENDGmlNwB08w4gW4YZRzeZOPgVpgEXgw94ypBpGfpww=="], - "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=="], - "react-tooltip": ["react-tooltip@5.30.1", "", { "dependencies": { "@floating-ui/dom": "^1.6.1", "classnames": "^2.3.0" }, "peerDependencies": { "react": ">=16.14.0", "react-dom": ">=16.14.0" } }, "sha512-1lSPLQXuVooePxadUpmcwLgOsF1mIty7UZTJ9XnyfX4drOzStYs4JMXnazcDLguQr41W5OUZddOp9kfvArdpEQ=="], "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], @@ -3184,8 +3096,6 @@ "recast": ["recast@0.23.12", "", { "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-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA=="], - "redent": ["redent@3.0.0", "", { "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg=="], - "regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="], "regenerate-unicode-properties": ["regenerate-unicode-properties@10.2.2", "", { "dependencies": { "regenerate": "^1.4.2" } }, "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g=="], @@ -3250,7 +3160,7 @@ "ripemd160": ["ripemd160@2.0.3", "", { "dependencies": { "hash-base": "^3.1.2", "inherits": "^2.0.4" } }, "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA=="], - "rivetkit": ["rivetkit@2.3.7", "", { "dependencies": { "@hono/zod-openapi": "^1.1.5", "@rivet-dev/agent-os-core": "^0.1.1", "@rivetkit/bare-ts": "^0.6.2", "@rivetkit/engine-cli": "2.3.7", "@rivetkit/engine-envoy-protocol": "2.3.7", "@rivetkit/on-change": "6.0.1", "@rivetkit/rivetkit-napi": "2.3.7", "@rivetkit/rivetkit-wasm": "2.3.7", "@rivetkit/traces": "2.3.7", "@rivetkit/virtual-websocket": "2.3.7", "@rivetkit/workflow-engine": "2.3.7", "cbor-x": "^1.6.0", "drizzle-orm": "^0.44.2", "hono": "^4.7.0", "invariant": "^2.2.4", "p-retry": "^6.2.1", "pino": "^9.5.0", "uuid": "^12.0.0", "vbare": "^0.0.4", "zod": "^4.1.0" }, "peerDependencies": { "drizzle-kit": "^0.31.2", "eventsource": "^4.0.0", "ws": "^8.0.0" }, "optionalPeers": ["drizzle-kit", "eventsource", "ws"] }, "sha512-V2IWlXq9SRLJWrcYVa8WUftELCpbdsBVWZIqz2WQjhhzRK9Aan65RfMoZVx62A9k8HuIO6MH1nAPLhOuk1xePQ=="], + "rivetkit": ["rivetkit@2.3.9", "", { "dependencies": { "@hono/zod-openapi": "^1.1.5", "@rivet-dev/agent-os-core": "^0.1.1", "@rivetkit/bare-ts": "^0.6.2", "@rivetkit/engine-cli": "2.3.9", "@rivetkit/engine-envoy-protocol": "2.3.9", "@rivetkit/on-change": "6.0.1", "@rivetkit/rivetkit-napi": "2.3.9", "@rivetkit/rivetkit-wasm": "2.3.9", "@rivetkit/traces": "2.3.9", "@rivetkit/virtual-websocket": "2.3.9", "@rivetkit/workflow-engine": "2.3.9", "cbor-x": "^1.6.0", "drizzle-orm": "^0.44.2", "hono": "^4.7.0", "invariant": "^2.2.4", "p-retry": "^6.2.1", "pino": "^9.5.0", "uuid": "^12.0.0", "vbare": "^0.0.4", "zod": "^4.1.0" }, "peerDependencies": { "drizzle-kit": "^0.31.2", "eventsource": "^4.0.0", "ws": "^8.0.0" }, "optionalPeers": ["drizzle-kit", "eventsource", "ws"] }, "sha512-m8pd3+nfI81T8uxKPflOKXTvvRf6X/u5zW0vRqq6v+d/Dwh964jKAHp0pVo5R6D9PotNZQIroqy57AZvX7nc4g=="], "robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="], @@ -3276,7 +3186,7 @@ "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], - "sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], + "sax": ["sax@1.6.1", "", {}, "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q=="], "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], @@ -3296,8 +3206,6 @@ "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="], - "server-only": ["server-only@0.0.1", "", {}, "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="], - "set-cookie-parser": ["set-cookie-parser@3.1.2", "", {}, "sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw=="], "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], @@ -3306,21 +3214,17 @@ "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], - "sf-symbols-typescript": ["sf-symbols-typescript@2.2.0", "", {}, "sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw=="], - "sha.js": ["sha.js@2.4.12", "", { "dependencies": { "inherits": "^2.0.4", "safe-buffer": "^5.2.1", "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" } }, "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w=="], - "shadcn": ["shadcn@4.14.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "kleur": "^4.1.5", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "undici": "^7.27.2", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-WSSMmB9ERauwy0SQwE0NlSfeaoBANHtzgSjAfoEsIHpRQwVkQBiiLV8Y9yAYOj9Wf3mbCIdQt3oLGzkH7NQFiQ=="], + "shadcn": ["shadcn@4.16.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "kleur": "^4.1.5", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "undici": "^7.27.2", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-kPr4RrQmbbZeAjwBYeBSpFvAHV8rkTlNPUluIxkRriq5TpevfFelVO5xvcF6oguHPVn0R6wPuVer4HudfcLy/A=="], - "shallowequal": ["shallowequal@1.1.0", "", {}, "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="], - - "sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], + "sharp": ["sharp@0.35.2", "", { "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", "semver": "^7.8.4" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.35.2", "@img/sharp-darwin-x64": "0.35.2", "@img/sharp-freebsd-wasm32": "0.35.2", "@img/sharp-libvips-darwin-arm64": "1.3.1", "@img/sharp-libvips-darwin-x64": "1.3.1", "@img/sharp-libvips-linux-arm": "1.3.1", "@img/sharp-libvips-linux-arm64": "1.3.1", "@img/sharp-libvips-linux-ppc64": "1.3.1", "@img/sharp-libvips-linux-riscv64": "1.3.1", "@img/sharp-libvips-linux-s390x": "1.3.1", "@img/sharp-libvips-linux-x64": "1.3.1", "@img/sharp-libvips-linuxmusl-arm64": "1.3.1", "@img/sharp-libvips-linuxmusl-x64": "1.3.1", "@img/sharp-linux-arm": "0.35.2", "@img/sharp-linux-arm64": "0.35.2", "@img/sharp-linux-ppc64": "0.35.2", "@img/sharp-linux-riscv64": "0.35.2", "@img/sharp-linux-s390x": "0.35.2", "@img/sharp-linux-x64": "0.35.2", "@img/sharp-linuxmusl-arm64": "0.35.2", "@img/sharp-linuxmusl-x64": "0.35.2", "@img/sharp-webcontainers-wasm32": "0.35.2", "@img/sharp-win32-arm64": "0.35.2", "@img/sharp-win32-ia32": "0.35.2", "@img/sharp-win32-x64": "0.35.2" } }, "sha512-FVtFjtBCMiJS6yb5CX7Sop45WFMpeGw6oRKuJnXYgf/f1ms/D7LE/ZUSNxnW7rZ/dbslQWYkoqFHGPaDBtaK4w=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - "shell-quote": ["shell-quote@1.8.4", "", {}, "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ=="], + "shell-quote": ["shell-quote@1.10.0", "", {}, "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA=="], "shiki": ["shiki@4.3.1", "", { "dependencies": { "@shikijs/core": "4.3.1", "@shikijs/engine-javascript": "4.3.1", "@shikijs/engine-oniguruma": "4.3.1", "@shikijs/langs": "4.3.1", "@shikijs/themes": "4.3.1", "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw=="], @@ -3342,8 +3246,6 @@ "simple-plist": ["simple-plist@1.3.1", "", { "dependencies": { "bplist-creator": "0.1.0", "bplist-parser": "0.3.1", "plist": "^3.0.5" } }, "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw=="], - "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], - "sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="], "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], @@ -3352,7 +3254,7 @@ "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="], - "smol-toml": ["smol-toml@1.7.0", "", {}, "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ=="], + "smol-toml": ["smol-toml@1.7.1", "", {}, "sha512-PPlsspAZ4jbMBu5DMFhfUGDQLu/vrL4SyBROVS37x8ynnVmFIs1VPBz1Co8Xks3TvpIaZXmU85y4DrQ+UyVFoQ=="], "socks": ["socks@2.8.9", "", { "dependencies": { "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" } }, "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw=="], @@ -3372,8 +3274,6 @@ "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], - "split-on-first": ["split-on-first@1.1.0", "", {}, "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="], - "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], "sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], @@ -3386,8 +3286,6 @@ "stacktrace-parser": ["stacktrace-parser@0.1.11", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg=="], - "standard-navigation": ["standard-navigation@0.0.5", "", {}, "sha512-YAmzwAiiQVocZxO/VGPFiQHcu5pKiz09QIGC0MK6aRMoa3E0QkoTQgcqJr7ZZ3OMiNhu4DkaGElFI5htjOIDbw=="], - "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], "std-env": ["std-env@4.2.0", "", {}, "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw=="], @@ -3402,8 +3300,6 @@ "streamdown": ["streamdown@2.5.0", "", { "dependencies": { "clsx": "^2.1.1", "hast-util-to-jsx-runtime": "^2.3.6", "html-url-attributes": "^3.0.1", "marked": "^17.0.1", "mermaid": "^11.12.2", "rehype-harden": "^1.1.8", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remend": "1.3.0", "tailwind-merge": "^3.4.0", "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-/tTnURfIOxZK/pqJAxsfCvETG/XCJHoWnk3jq9xLcuz6CSpnjjuxSRBTTL4PKGhxiZQf0lqPxGhImdpwcZ2XwA=="], - "strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="], - "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=="], "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], @@ -3418,8 +3314,6 @@ "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], - "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], - "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], "strnum": ["strnum@2.4.1", "", { "dependencies": { "anynum": "^1.0.1" } }, "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg=="], @@ -3432,8 +3326,6 @@ "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="], - "styleq": ["styleq@0.1.3", "", {}, "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA=="], - "stylis": ["stylis@4.4.0", "", {}, "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA=="], "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], @@ -3442,13 +3334,13 @@ "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - "systeminformation": ["systeminformation@5.33.0", "", { "os": "!aix", "bin": { "systeminformation": "lib/cli.js" } }, "sha512-0LYSL01CCbjVeJG7iXI8fUCFU76zMjzbHd/EU3or4QpSFYCLMgslR11prwHuA3siz5jmOkqoLhjgOyDRmXBKmA=="], + "systeminformation": ["systeminformation@5.33.1", "", { "os": "!aix", "bin": { "systeminformation": "lib/cli.js" } }, "sha512-DEN6ICHk3Tk0Uf/hrAHh7xlt7iL5CJFBtPZinA0H62DrGG/KPKqq/Nzj6lCXPS4Ay/sf/14zNnk9LpqKzBIc+w=="], "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="], "tailwind-merge": ["tailwind-merge@3.6.0", "", {}, "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w=="], - "tailwind-variants": ["tailwind-variants@3.2.2", "", { "peerDependencies": { "tailwind-merge": ">=3.0.0", "tailwindcss": "*" }, "optionalPeers": ["tailwind-merge"] }, "sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg=="], + "tailwind-variants": ["tailwind-variants@3.3.0", "", { "peerDependencies": { "tailwind-merge": ">=3.0.0", "tailwindcss": "*" }, "optionalPeers": ["tailwind-merge", "tailwindcss"] }, "sha512-t1QsB42dcwUdaCEArO0tRZcP0nbCcAmJKRYCs7jmwYSFOCXlGqgO8c0TrCYm9OranYmT6i9YOi8LFo2gxmxnow=="], "tailwindcss": ["tailwindcss@4.3.3", "", {}, "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ=="], @@ -3540,15 +3432,13 @@ "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], - "ua-parser-js": ["ua-parser-js@1.0.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug=="], - "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], "ulidx": ["ulidx@2.4.1", "", { "dependencies": { "layerr": "^3.0.0" } }, "sha512-xY7c8LPyzvhvew0Fn+Ek3wBC9STZAuDI/Y5andCKi9AX6/jvfaX45PhsDX8oxgPL0YFp0Jhr8qWMbS/p9375Xg=="], "ultracite": ["ultracite@7.9.3", "", { "dependencies": { "@clack/prompts": "^1.5.1", "@typescript-eslint/utils": "^8.62.1", "commander": "^15.0.0", "cross-spawn": "^7.0.6", "deepmerge": "^4.3.1", "glob": "^13.0.6", "jsonc-parser": "^3.3.1", "nypm": "^0.6.6", "yaml": "^2.9.0", "zod": "^4.4.3" }, "peerDependencies": { "oxfmt": ">=0.1.0", "oxlint": "^1.0.0" }, "optionalPeers": ["oxfmt", "oxlint"], "bin": { "ultracite": "dist/index.js" } }, "sha512-MqF0cn5DNHy/I61+hL4aYPRVye+rrmUqfv1dhwQ0ORfoFngk1O8tTKigF+zpsh/6qA84gkl26KkrtYzoypPiaw=="], - "undici": ["undici@7.28.0", "", {}, "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA=="], + "undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="], "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], @@ -3592,12 +3482,6 @@ "url-template": ["url-template@2.0.8", "", {}, "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw=="], - "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=="], - - "use-latest-callback": ["use-latest-callback@0.2.6", "", { "peerDependencies": { "react": ">=16.8" } }, "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg=="], - - "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=="], - "use-stick-to-bottom": ["use-stick-to-bottom@1.1.6", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-z3Up8jYQGTkUCsGBnwg6/wj70KgXoW5Kz1AAc1j8MtQuYMBo6ZsdhrIXoegxa7gaMMilgQYyTohTrt3p94jHog=="], "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=="], @@ -3616,8 +3500,6 @@ "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], - "vaul": ["vaul@1.1.2", "", { "dependencies": { "@radix-ui/react-dialog": "^1.1.1" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA=="], - "vbare": ["vbare@0.0.4", "", {}, "sha512-QsxSVw76NqYUWYPVcQmOnQPX8buIVjgn+yqldTHlWISulBTB9TJ9rnzZceDu+GZmycOtzsmuPbPN1YNxvK12fg=="], "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], @@ -3640,8 +3522,6 @@ "walker": ["walker@1.0.8", "", { "dependencies": { "makeerror": "1.0.12" } }, "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ=="], - "warn-once": ["warn-once@0.1.1", "", {}, "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q=="], - "warning": ["warning@3.0.0", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ=="], "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], @@ -3668,9 +3548,9 @@ "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], - "workerd": ["workerd@1.20260721.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260721.1", "@cloudflare/workerd-darwin-arm64": "1.20260721.1", "@cloudflare/workerd-linux-64": "1.20260721.1", "@cloudflare/workerd-linux-arm64": "1.20260721.1", "@cloudflare/workerd-windows-64": "1.20260721.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-b/DWhpV0jTudzQpLhDovcOgBz233386q+3Hbari7CLCNT9UXxjQziSTZ9yCoKdT2K3TSx5jrwlOisq8hlLWXYg=="], + "workerd": ["workerd@1.20260722.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260722.1", "@cloudflare/workerd-darwin-arm64": "1.20260722.1", "@cloudflare/workerd-linux-64": "1.20260722.1", "@cloudflare/workerd-linux-arm64": "1.20260722.1", "@cloudflare/workerd-windows-64": "1.20260722.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-NycKuc1x2onvsRfGGpM093vRlLFU2zHDAM0+APpccfg4+gZxDGCH27RmdDvkeBuoZyYqgLo3oAfF6re4mvC3vQ=="], - "wrangler": ["wrangler@4.113.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.28.1", "miniflare": "4.20260721.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260721.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "@cloudflare/workers-types": "^5.20260721.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "cf-wrangler": "bin/cf-wrangler.js", "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-ROGzSloJv0y21It6Oc9LaruNcu1tdiQ/XzL3Jc3YkFjzXEMXzTqVhA8vQaGMTdZHTjFP0PVcwAHNgaw3gXu4wA=="], + "wrangler": ["wrangler@4.114.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.28.1", "miniflare": "4.20260722.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260722.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "@cloudflare/workers-types": "^5.20260722.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "cf-wrangler": "bin/cf-wrangler.js", "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-M65P25t5UHA1TIJfgZXDcj+YzVobgKdRguM2QPz0xnxLFuOcuE3ErgllDht0iaho7MS4o0g/Bb4YK2+GT+bibg=="], "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=="], @@ -3706,7 +3586,7 @@ "yocto-spinner": ["yocto-spinner@1.2.2", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-DODGl1wJjA/s5pnJFKau9lIYHT81lnhob1i3e1TjxZRxEhWRKl74nTbWE6H5KlkViQQTo/Z29YFdxzTZAMY3ng=="], - "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], + "yoctocolors": ["yoctocolors@2.2.0", "", {}, "sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg=="], "youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="], @@ -3720,15 +3600,31 @@ "@anthropic-ai/claude-agent-sdk/@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.74.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-srbJV7JKsc5cQ6eVuFzjZO7UR3xEPJqPamHFIe29bs38Ij2IripoAhC0S5NslNbaFUYqBKypmmpzMTpqfHEUDw=="], - "@aws-sdk/client-bedrock-runtime/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.9", "", { "dependencies": { "@smithy/core": "^3.29.7", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-xVBZ3hptB99iNO9XyWqEhC7KD9bP9UPXhuy3h5Y2ItCfBv160D9IIC/Fmmp3EbnWwit4C+KVqlSE+E29Nk/pPg=="], + "@anthropic-ai/claude-agent-sdk/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], - "@aws-sdk/client-s3/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.9", "", { "dependencies": { "@smithy/core": "^3.29.7", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-xVBZ3hptB99iNO9XyWqEhC7KD9bP9UPXhuy3h5Y2ItCfBv160D9IIC/Fmmp3EbnWwit4C+KVqlSE+E29Nk/pPg=="], + "@anthropic-ai/claude-agent-sdk/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], - "@aws-sdk/credential-provider-http/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.9", "", { "dependencies": { "@smithy/core": "^3.29.7", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-xVBZ3hptB99iNO9XyWqEhC7KD9bP9UPXhuy3h5Y2ItCfBv160D9IIC/Fmmp3EbnWwit4C+KVqlSE+E29Nk/pPg=="], + "@anthropic-ai/claude-agent-sdk/@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="], - "@aws-sdk/credential-provider-sso/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1092.0", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/nested-clients": "^3.997.34", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-hBYUAr6iBLNFcsiWTgtBb0stdSw39VOUq4Sp4A5caCNf66BAZplWN4FleKrVpJx5li2YgdnK2DqoFSMWC642FQ=="], + "@anthropic-ai/claude-agent-sdk/@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="], - "@aws-sdk/nested-clients/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.9", "", { "dependencies": { "@smithy/core": "^3.29.7", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-xVBZ3hptB99iNO9XyWqEhC7KD9bP9UPXhuy3h5Y2ItCfBv160D9IIC/Fmmp3EbnWwit4C+KVqlSE+E29Nk/pPg=="], + "@anthropic-ai/claude-agent-sdk/@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="], + + "@anthropic-ai/claude-agent-sdk/@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="], + + "@anthropic-ai/claude-agent-sdk/@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="], + + "@anthropic-ai/claude-agent-sdk/@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="], + + "@anthropic-ai/claude-agent-sdk/@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], + + "@aws-sdk/client-s3/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.12", "", { "dependencies": { "@smithy/core": "^3.31.0", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-dWW5KRt4mnEvjNzbGqGeCuAvgum85Y9ZoyuMQqcTEfapndyVJ1k9BEHK7kdXJZ32enyRmmwcFjMwlB/KgLKI3Q=="], + + "@aws-sdk/credential-provider-http/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.12", "", { "dependencies": { "@smithy/core": "^3.31.0", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-dWW5KRt4mnEvjNzbGqGeCuAvgum85Y9ZoyuMQqcTEfapndyVJ1k9BEHK7kdXJZ32enyRmmwcFjMwlB/KgLKI3Q=="], + + "@aws-sdk/credential-provider-sso/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1096.0", "", { "dependencies": { "@aws-sdk/core": "^3.977.1", "@aws-sdk/nested-clients": "^3.997.36", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-hdUS2hDppy3vkWeFl5y86RLNU6OWH2mQB09yOSsRefwhhGTSFPkaZvfLDD/9vFcvMzlr8QFQFw3fw2FtrurVQA=="], + + "@aws-sdk/nested-clients/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.12", "", { "dependencies": { "@smithy/core": "^3.31.0", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-dWW5KRt4mnEvjNzbGqGeCuAvgum85Y9ZoyuMQqcTEfapndyVJ1k9BEHK7kdXJZ32enyRmmwcFjMwlB/KgLKI3Q=="], "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], @@ -3742,8 +3638,6 @@ "@babel/plugin-transform-runtime/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "@code/backend/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], - "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], "@dotenvx/dotenvx/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], @@ -3764,8 +3658,6 @@ "@expo/cli/send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], - "@expo/cli/ws": ["ws@8.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], - "@expo/cli/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "@expo/config-plugins/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -3794,42 +3686,34 @@ "@google/genai/p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="], - "@google/genai/ws": ["ws@8.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], - - "@jest/types/@types/node": ["@types/node@26.1.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw=="], - "@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "@mariozechner/jiti/std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="], "@mariozechner/pi-ai/@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.73.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-URURVzhxXGJDGUGFunIOtBlSl7KWvZiAAKY/ttTkZAkXT9bTPqdk2eK0b8qqSxXpikh3QKPnPYpiyX98zf5ebw=="], - "@mariozechner/pi-ai/@aws-sdk/client-bedrock-runtime": ["@aws-sdk/client-bedrock-runtime@3.1093.0", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/credential-provider-node": "^3.972.71", "@aws-sdk/eventstream-handler-node": "^3.972.29", "@aws-sdk/middleware-eventstream": "^3.972.24", "@aws-sdk/middleware-websocket": "^3.972.42", "@aws-sdk/token-providers": "3.1093.0", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/fetch-http-handler": "^5.6.6", "@smithy/node-http-handler": "^4.9.6", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-CpXch6f8k+Cwjh/dLXwmoYc44ELmDlXFMPHAZBe6wDN4TDKNskgk9M6LUuizMvN1OHfvQcoGtvy8Oc/G3RNvLg=="], - "@mariozechner/pi-ai/@mistralai/mistralai": ["@mistralai/mistralai@1.14.1", "", { "dependencies": { "ws": "^8.18.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.24.1" } }, "sha512-IiLmmZFCCTReQgPAT33r7KQ1nYo5JPdvGkrkZqA8qQ2qB1GHgs5LoP5K2ICyrjnpw2n8oSxMM/VP+liiKcGNlQ=="], "@mariozechner/pi-ai/@sinclair/typebox": ["@sinclair/typebox@0.34.52", "", {}, "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw=="], "@mariozechner/pi-coding-agent/hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="], - "@mariozechner/pi-coding-agent/ignore": ["ignore@7.0.6", "", {}, "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw=="], - "@mariozechner/pi-coding-agent/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], "@mariozechner/pi-tui/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], - "@mistralai/mistralai/ws": ["ws@8.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], - - "@modelcontextprotocol/sdk/@hono/node-server": ["@hono/node-server@1.19.14", "", { "peerDependencies": { "hono": "^4" } }, "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw=="], - "@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], + "@react-native/babel-preset/@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.86.2", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@react-native/codegen": "0.86.2" } }, "sha512-NNDZqOlNbH5SzgPks1jFDYH3234Rpa5e/nhZymxhIiBH3NcE3uD+rGj/HWXhH7nHF2ToGK6XbUpqy7nmJPeh+g=="], + "@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="], "@react-native/dev-middleware/serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], "@react-native/dev-middleware/ws": ["ws@7.5.13", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA=="], + "@react-native/metro-config/@react-native/js-polyfills": ["@react-native/js-polyfills@0.86.2", "", {}, "sha512-bIwNcGBaQ74shB5z1mRkxOpjikimuwsnOCEkZSzL67Z1FTyK1ObpENfyd2QvcvVW9Cjl+tHuw9ynpBnb2jPoJQ=="], + "@react-router/dev/react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="], "@rivetkit/framework-base/@tanstack/store": ["@tanstack/store@0.7.7", "", {}, "sha512-xa6pTan1bcaqYDS9BDpSiS63qa6EoDkPN9RsRaxHuDdVDNntzq3xNwR5YKTU/V3SkSyC9T4YVOPh2zRQN0nhIQ=="], @@ -3860,18 +3744,10 @@ "@tanstack/devtools/@tanstack/devtools-event-bus": ["@tanstack/devtools-event-bus@0.4.1", "", { "dependencies": { "ws": "^8.18.3" } }, "sha512-cNnJ89Q021Zf883rlbBTfsaxTfi2r73/qejGtyTa7ksErF3hyDyAq1aTbo5crK9dAL7zSHh9viKY1BtMls1QOA=="], - "@tanstack/devtools-event-bus/ws": ["ws@8.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], - "@testing-library/dom/pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="], - "@testing-library/jest-dom/dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="], - - "@types/yauzl/@types/node": ["@types/node@26.1.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw=="], - "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], - "@vitest/browser/ws": ["ws@8.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], - "accepts/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], @@ -3886,14 +3762,8 @@ "browserify-sign/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], - "bun-types/@types/node": ["@types/node@26.1.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw=="], - "cbor-extract/node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.1.1", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-test": "build-test.js", "node-gyp-build-optional-packages-optional": "optional.js" } }, "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw=="], - "chrome-launcher/@types/node": ["@types/node@26.1.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw=="], - - "chromium-edge-launcher/@types/node": ["@types/node@26.1.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw=="], - "cli-highlight/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "cli-highlight/parse5": ["parse5@5.1.1", "", {}, "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug=="], @@ -3914,8 +3784,6 @@ "create-ecdh/bn.js": ["bn.js@4.12.5", "", {}, "sha512-3aRg6/JxfffFD+OlOjOFR3Vo79l39ooBTFucxx+MT3dhCtzn3EmiUPQo+6/OZuI2jbXi3YKgmiTFBgChQMwIRQ=="], - "cross-fetch/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], - "css-tree/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="], @@ -3962,14 +3830,8 @@ "expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], - "expo-router/react-is": ["react-is@19.2.8", "", {}, "sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ=="], - - "expo-router/react-native-screens": ["react-native-screens@4.26.2", "", { "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-2XnWsZToKj76trGtEZzx5ELD/qOICFEprEeUntImmitQFVUkea27fiWdUSITArI356Y1qynpXZINW+Unbhky/A=="], - "extract-zip/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], - "fbjs/promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="], - "fetch-blob/web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], "get-uri/data-uri-to-buffer": ["data-uri-to-buffer@6.0.2", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="], @@ -3992,16 +3854,12 @@ "is-inside-container/is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], - "jest-util/@types/node": ["@types/node@26.1.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw=="], - "jest-util/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "jest-util/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "jest-validate/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "jest-worker/@types/node": ["@types/node@26.1.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw=="], - "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], "just-bash/ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="], @@ -4030,6 +3888,8 @@ "miller-rabin/bn.js": ["bn.js@4.12.5", "", {}, "sha512-3aRg6/JxfffFD+OlOjOFR3Vo79l39ooBTFucxx+MT3dhCtzn3EmiUPQo+6/OZuI2jbXi3YKgmiTFBgChQMwIRQ=="], + "miniflare/undici": ["undici@7.28.0", "", {}, "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA=="], + "morgan/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "node-stdlib-browser/punycode": ["punycode@1.4.1", "", {}, "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="], @@ -4060,14 +3920,10 @@ "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - "protobufjs/@types/node": ["@types/node@26.1.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw=="], - "proxy-agent/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], "public-encrypt/bn.js": ["bn.js@4.12.5", "", {}, "sha512-3aRg6/JxfffFD+OlOjOFR3Vo79l39ooBTFucxx+MT3dhCtzn3EmiUPQo+6/OZuI2jbXi3YKgmiTFBgChQMwIRQ=="], - "pyodide/ws": ["ws@8.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], - "rc/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], "react-d3-tree/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], @@ -4078,10 +3934,6 @@ "react-native/ws": ["ws@7.5.13", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA=="], - "react-native-web/@react-native/normalize-colors": ["@react-native/normalize-colors@0.74.89", "", {}, "sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg=="], - - "react-native-web/memoize-one": ["memoize-one@6.0.0", "", {}, "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="], - "recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], @@ -4100,8 +3952,6 @@ "simple-plist/bplist-parser": ["bplist-parser@0.3.1", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA=="], - "simple-swizzle/is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="], - "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "stacktrace-parser/type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="], @@ -4152,7 +4002,19 @@ "youch/cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], - "@code/backend/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + "@anthropic-ai/claude-agent-sdk/@img/sharp-darwin-arm64/@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="], + + "@anthropic-ai/claude-agent-sdk/@img/sharp-darwin-x64/@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="], + + "@anthropic-ai/claude-agent-sdk/@img/sharp-linux-arm/@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="], + + "@anthropic-ai/claude-agent-sdk/@img/sharp-linux-arm64/@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="], + + "@anthropic-ai/claude-agent-sdk/@img/sharp-linux-x64/@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="], + + "@anthropic-ai/claude-agent-sdk/@img/sharp-linuxmusl-arm64/@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="], + + "@anthropic-ai/claude-agent-sdk/@img/sharp-linuxmusl-x64/@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], "@dotenvx/dotenvx/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], @@ -4188,6 +4050,8 @@ "@expo/cli/send/fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], + "@expo/cli/send/range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + "@expo/config-plugins/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "@expo/devtools/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], @@ -4216,15 +4080,9 @@ "@google/genai/p-retry/@types/retry": ["@types/retry@0.12.0", "", {}, "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="], - "@jest/types/@types/node/undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], - "@jest/types/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - "@mariozechner/pi-ai/@aws-sdk/client-bedrock-runtime/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1093.0", "", { "dependencies": { "@aws-sdk/core": "^3.976.0", "@aws-sdk/nested-clients": "^3.997.34", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.4", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-0TOm0RAnnsgV3eaG/xh/PlMxtmpv8hvdAjVReQvmOMhBgIKdYuc3Iz318GvnDNNgf3pUoV5zUaLVeGz4jp3shw=="], - - "@mariozechner/pi-ai/@aws-sdk/client-bedrock-runtime/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.9", "", { "dependencies": { "@smithy/core": "^3.29.7", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-xVBZ3hptB99iNO9XyWqEhC7KD9bP9UPXhuy3h5Y2ItCfBv160D9IIC/Fmmp3EbnWwit4C+KVqlSE+E29Nk/pPg=="], - - "@mariozechner/pi-ai/@mistralai/mistralai/ws": ["ws@8.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], + "@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen": ["@react-native/codegen@0.86.2", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.29.0", "hermes-parser": "0.36.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "tinyglobby": "^0.2.15", "yargs": "^17.6.2" } }, "sha512-xKkudsahUJ1n//55g4fXk5BStVqqmZlz8HQveL45ZxcfDnwvhuYe2GymksQANFsSN+slvrarjrfq8kIxJzbceA=="], "@react-native/dev-middleware/serve-static/send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], @@ -4316,22 +4174,12 @@ "@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="], - "@tanstack/devtools/@tanstack/devtools-event-bus/ws": ["ws@8.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], - "@testing-library/dom/pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="], - "@types/yauzl/@types/node/undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], - "browserify-sign/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], "browserify-sign/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], - "bun-types/@types/node/undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], - - "chrome-launcher/@types/node/undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], - - "chromium-edge-launcher/@types/node/undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], - "cli-highlight/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "cli-highlight/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], @@ -4372,14 +4220,10 @@ "gtoken/gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], - "jest-util/@types/node/undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], - "jest-util/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "jest-validate/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - "jest-worker/@types/node/undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], - "lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "md5.js/hash-base/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], @@ -4394,8 +4238,6 @@ "pkg-up/find-up/locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], - "protobufjs/@types/node/undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], - "ripemd160/hash-base/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], "vite-plus/oxfmt/@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.57.0", "", { "os": "android", "cpu": "arm" }, "sha512-qVBsEO+KugOsCmUHcO8iqNnqc65p7PCKpCs8M66mPZ+Ri+CWbcpoQOEJBg2OTu03+0qu++NK1jj6IzvQVs0Sig=="], @@ -4554,6 +4396,8 @@ "@react-native/dev-middleware/serve-static/send/fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], + "@react-native/dev-middleware/serve-static/send/range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + "cli-highlight/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "googleapis-common/google-auth-library/gcp-metadata/google-logging-utils": ["google-logging-utils@0.0.2", "", {}, "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ=="], diff --git a/oxlint.config.ts b/oxlint.config.ts index 70008b0..158b4ff 100644 --- a/oxlint.config.ts +++ b/oxlint.config.ts @@ -5,5 +5,28 @@ import remix from "ultracite/oxlint/remix"; export default defineConfig({ extends: [core, react, remix], - ignorePatterns: core.ignorePatterns, + ignorePatterns: [...core.ignorePatterns, "repos/**", "scripts/**"], + overrides: [ + { + files: ["**/convex/**/*.ts", "**/convex/**/*.test.ts"], + rules: { + "unicorn/filename-case": "off", + // Convex targets ES2022: no toSorted/at; sequential awaits ensure atomicity + "unicorn/no-array-sort": "off", + "no-await-in-loop": "off", + // Convex query builders use `any` in index callbacks + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "eslint/complexity": "off", + }, + }, + { + files: ["**/convex/**/*.test.ts"], + rules: { + "unicorn/no-await-expression-member": "off", + "eslint/require-await": "off", + "sort-keys": "off", + }, + }, + ], }); diff --git a/package.json b/package.json index 33ae6f2..7a6370f 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,15 @@ "heroui-native": "^1.0.5", "vite": "^7.3.6", "vitest": "^4.1.10", - "convex-test": "^0.0.54" + "convex-test": "^0.0.54", + "react-native": "0.86.0", + "@types/react": "^19.2.17", + "@types/node": "^22.13.14", + "hono": "^4.8.3", + "valibot": "^1.4.2", + "streamdown": "2.5.0", + "@tailwindcss/postcss": "^4.3.2", + "@tailwindcss/vite": "^4.3.2" } }, "type": "module", @@ -45,8 +53,8 @@ "dev": "vp run -r dev", "build": "vp run -r build", "check-types": "vp run -r check-types", - "check": "ultracite check package.json vite.config.ts apps/web/package.json apps/web/src/root.tsx apps/web/src/index.css apps/web/src/components/chat apps/web/src/components/slice-one apps/web/src/hooks/chat apps/web/src/hooks/slice-one apps/web/src/lib/chat apps/web/src/lib/slice-one apps/web/src/routes.ts apps/web/src/routes/app/dashboard/page.tsx apps/web/src/routes/app/mobile/page.tsx packages/agents/package.json packages/agents/src/agents/zopu.ts packages/agents/src/app.ts packages/agents/src/auth.ts packages/agents/src/tools/slice-one.ts packages/backend/package.json packages/backend/convex/conversationMessages.ts packages/backend/convex/conversationMessages.test.ts packages/backend/convex/projects.ts packages/backend/convex/schema.ts packages/backend/convex/signalRouting.ts packages/backend/convex/signalRouting.test.ts packages/backend/convex/works.ts packages/backend/convex/works.test.ts packages/backend/convex/workExecution.ts packages/backend/convex/workExecution.test.ts packages/backend/convex/workPlanning.ts packages/backend/convex/workPlanning.test.ts packages/backend/convex/crons.ts packages/primitives/src/work.ts packages/primitives/src/work.test.ts packages/primitives/src/resolver.ts packages/primitives/src/work-lifecycle.ts packages/primitives/src/work-resolution.test.ts", - "lint": "vp lint", + "check": "ultracite check package.json vite.config.ts apps/web/package.json apps/web/src/root.tsx apps/web/src/index.css apps/web/src/components/chat apps/web/src/components/slice-one apps/web/src/hooks/chat apps/web/src/hooks/slice-one apps/web/src/lib/chat apps/web/src/lib/slice-one apps/web/src/routes.ts apps/web/src/routes/app/dashboard/page.tsx apps/web/src/routes/app/mobile/page.tsx packages/agents/package.json packages/agents/src/agents/zopu.ts packages/agents/src/app.ts packages/agents/src/auth.ts packages/agents/src/tools/slice-one.ts packages/backend/package.json packages/backend/convex/conversationMessages.ts packages/backend/convex/conversationMessages.test.ts packages/backend/convex/fluePersistence.test.ts packages/backend/convex/projects.ts packages/backend/convex/schema.ts packages/backend/convex/signalRouting.ts packages/backend/convex/signalRouting.test.ts packages/backend/convex/works.ts packages/backend/convex/works.test.ts packages/backend/convex/workArtifacts.ts packages/backend/convex/workArtifacts.test.ts packages/backend/convex/workExecution.ts packages/backend/convex/workExecution.test.ts packages/backend/convex/workPlanning.ts packages/backend/convex/workPlanning.test.ts packages/backend/convex/crons.ts packages/primitives/src/work.ts packages/primitives/src/work.test.ts packages/primitives/src/work-artifact.ts packages/primitives/src/work-artifact.test.ts packages/primitives/src/resolver.ts packages/primitives/src/work-lifecycle.ts packages/primitives/src/work-resolution.test.ts", + "lint": "oxlint --disable-nested-config", "format": "vp fmt", "staged": "vp staged", "hooks:setup": "vp config", @@ -72,7 +80,7 @@ "@code/primitives": "workspace:*", "@flue/sdk": "1.0.0-beta.9", "@types/bun": "catalog:", - "@types/node": "^22.13.14", + "@types/node": "catalog:", "convex": "catalog:", "convex-test": "catalog:", "effect": "catalog:", diff --git a/packages/agents/package.json b/packages/agents/package.json index d8d37fb..d7854d9 100644 --- a/packages/agents/package.json +++ b/packages/agents/package.json @@ -17,8 +17,8 @@ "@code/env": "workspace:*", "@flue/runtime": "latest", "convex": "catalog:", - "hono": "4.12.31", - "valibot": "^1.4.2" + "hono": "catalog:", + "valibot": "catalog:" }, "devDependencies": { "@code/config": "workspace:*", diff --git a/packages/agents/src/app.ts b/packages/agents/src/app.ts index aa3cf2e..17fbe91 100644 --- a/packages/agents/src/app.ts +++ b/packages/agents/src/app.ts @@ -1,7 +1,7 @@ import { parseAgentEnv } from "@code/env/agent"; import { registerProvider } from "@flue/runtime"; +import type { Fetchable } from "@flue/runtime/routing"; import { flue } from "@flue/runtime/routing"; -import { Hono } from "hono"; const agentEnv = parseAgentEnv(process.env); @@ -24,7 +24,5 @@ registerProvider(agentEnv.AGENT_MODEL_PROVIDER, { }, }); -const app = new Hono(); -app.route("/", flue() as unknown as Hono); - -export default app; +// flue() returns a complete Hono app; the Fetchable contract accepts it. +export default flue() satisfies Fetchable; diff --git a/packages/agents/src/db.ts b/packages/agents/src/db.ts index 266bb56..472edcd 100644 --- a/packages/agents/src/db.ts +++ b/packages/agents/src/db.ts @@ -1,3 +1,4 @@ +/* eslint-disable max-classes-per-file, @typescript-eslint/no-invalid-void-type, class-methods-use-this, @typescript-eslint/parameter-properties */ /** * Convex-backed Flue {@link PersistenceAdapter} for the agents package. * @@ -25,70 +26,11 @@ */ import { env } from "@code/env/server"; -import { - type AgentAttemptMarker, - type AgentDispatchAdmission, - type AgentDispatchReceipt, - type AgentExecutionStore, - type AgentSubmission, - type AgentSubmissionStore, - AttachmentConflictError, - type AttachmentRef, - type AttachmentStore, - type ConversationProducerClaim, - type ConversationRecord, - type ConversationStreamBatch, - type ConversationStreamIdentity, - type ConversationStreamMeta, - type ConversationStreamReadResult, - type ConversationStreamStore, - type CreateRunInput, - DEFAULT_LIST_LIMIT, - DEFAULT_READ_LIMIT, - type DirectAgentSubmissionInput, - type DispatchAgentSubmissionInput, - type DispatchInput, - type EndRunInput, - type EventStreamMeta, - type EventStreamReadResult, - type EventStreamStore, - type GetAttachmentInput, - MAX_LIST_LIMIT, - MAX_READ_LIMIT, - type PersistedChunkRow, - type PersistenceAdapter, - type PersistenceStores, - type PutAttachmentInput, - type RunPointer, - type RunRecord, - type RunStore, - type RunStatus, - StreamListenerRegistry, - type StoredAttachment, - type SubmissionAttemptRef, - type SubmissionClaimRef, - type SubmissionDurability, - type SubmissionSettlementObligation, - type SubmissionSettledRecord, - assertSupportedFlueSchemaVersion, - clampLimit, - copyAttachmentBytes, - createSessionStorageKey, - decodeRunCursor, - encodeRunCursor, - formatOffset, - hydratePersistedDirectSubmission, - parseOffset, - prepareDirectSubmission, - verifyAttachmentBytes, -} from "@flue/runtime/adapter"; +import { AttachmentConflictError, DEFAULT_LIST_LIMIT, DEFAULT_READ_LIMIT, MAX_LIST_LIMIT, MAX_READ_LIMIT, StreamListenerRegistry, assertSupportedFlueSchemaVersion, clampLimit, copyAttachmentBytes, createSessionStorageKey, decodeRunCursor, encodeRunCursor, formatOffset, hydratePersistedDirectSubmission, parseOffset, prepareDirectSubmission, verifyAttachmentBytes } from '@flue/runtime/adapter'; +import type { AgentAttemptMarker, AgentDispatchAdmission, AgentDispatchReceipt, AgentExecutionStore, AgentSubmission, AgentSubmissionStore, AttachmentRef, AttachmentStore, ConversationProducerClaim, ConversationRecord, ConversationStreamBatch, ConversationStreamIdentity, ConversationStreamMeta, ConversationStreamReadResult, ConversationStreamStore, CreateRunInput, DirectAgentSubmissionInput, DispatchAgentSubmissionInput, DispatchInput, EndRunInput, EventStreamMeta, EventStreamReadResult, EventStreamStore, GetAttachmentInput, PersistedChunkRow, PersistenceAdapter, PersistenceStores, PutAttachmentInput, RunPointer, RunRecord, RunStore, RunStatus, StoredAttachment, SubmissionAttemptRef, SubmissionClaimRef, SubmissionDurability, SubmissionSettlementObligation, SubmissionSettledRecord } from '@flue/runtime/adapter'; import { ConvexHttpClient } from "convex/browser"; -import { - type FunctionArgs, - type FunctionReference, - type FunctionReturnType, - makeFunctionReference, -} from "convex/server"; +import { makeFunctionReference } from 'convex/server'; +import type { FunctionArgs, FunctionReference, FunctionReturnType } from 'convex/server'; // --------------------------------------------------------------------------- // Token + arg types @@ -100,7 +42,7 @@ import { // --------------------------------------------------------------------------- /** Auth token present on every Convex function call. */ -type TokenArgs = { readonly token: string; readonly [key: string]: unknown }; +interface TokenArgs { readonly token: string; readonly [key: string]: unknown } const TOKEN = (): string => env.FLUE_DB_TOKEN; @@ -112,7 +54,7 @@ type TraceCarrier = NonNullable; // --------------------------------------------------------------------------- /** Common fields stored for every submission row. */ -type SubmissionRow = { +interface SubmissionRow { readonly sequence: number; readonly submissionId: string; readonly sessionKey: string; @@ -134,42 +76,42 @@ type SubmissionRow = { readonly ownerId: string | null; readonly leaseExpiresAt: number; readonly traceCarrierJson: string | null; -}; +} -type SettlementObligationRow = { +interface SettlementObligationRow { readonly submissionId: string; readonly sessionKey: string; readonly attemptId: string; readonly recordId: string; readonly recordJson: string; -}; +} -type AttemptMarkerRow = { +interface AttemptMarkerRow { readonly submissionId: string; readonly attemptId: string; readonly createdAt: number; -}; +} -type ConversationStreamRow = { +interface ConversationStreamRow { readonly identity: ConversationStreamIdentity; readonly incarnation: string; readonly nextOffset: number; readonly producerId: string | null; readonly producerEpoch: number; readonly nextProducerSequence: number; -}; +} -type ConversationBatchRow = { +interface ConversationBatchRow { readonly offset: number; readonly recordsJson: string; -}; +} -type EventEntryRow = { +interface EventEntryRow { readonly offset: number; readonly dataJson: string; -}; +} -type RunRow = { +interface RunRow { readonly runId: string; readonly workflowName: string; readonly status: RunStatus; @@ -181,9 +123,9 @@ type RunRow = { readonly resultJson: string | null; readonly errorJson: string | null; readonly traceCarrierJson: string | null; -}; +} -type RunPointerRow = { +interface RunPointerRow { readonly runId: string; readonly workflowName: string; readonly status: RunStatus; @@ -191,15 +133,15 @@ type RunPointerRow = { readonly endedAt: string | null; readonly durationMs: number | null; readonly isError: boolean | null; -}; +} -type AttachmentRefWire = { +interface AttachmentRefWire { readonly id: string; readonly mimeType: string; readonly size: number; readonly digest: string; readonly filename?: string; -}; +} // --------------------------------------------------------------------------- // Typed function references @@ -263,7 +205,7 @@ const replaceSubmissionAttempt = makeFunctionReference< >("fluePersistence:replaceSubmissionAttempt"); /** Unified admission envelope — `kind` discriminates dispatch vs direct. */ -type AdmitSubmissionEnvelope = { +interface AdmitSubmissionEnvelope { readonly kind: "dispatch" | "direct"; readonly submissionId: string; readonly sessionKey: string; @@ -271,12 +213,12 @@ type AdmitSubmissionEnvelope = { readonly inputJson: string; readonly chunksJson?: string; readonly traceCarrierJson?: string; -}; -type AdmitSubmissionResponse = { +} +interface AdmitSubmissionResponse { readonly kind: "submission" | "retained_receipt" | "conflict"; readonly submission?: SubmissionRow; readonly receipt?: AgentDispatchReceipt; -}; +} const admitSubmission = makeFunctionReference< "mutation", TokenArgs & { readonly input: AdmitSubmissionEnvelope }, @@ -410,7 +352,7 @@ type AppendBatchArgs = TokenArgs & { readonly submission?: { readonly submissionId: string; readonly attemptId: string }; readonly recordsJson: string; }; -type AppendResult = { readonly offset: number; readonly appended: boolean }; +interface AppendResult { readonly offset: number; readonly appended: boolean } const appendConversationBatch = makeFunctionReference< "mutation", AppendBatchArgs, @@ -422,11 +364,11 @@ type ReadBatchesArgs = TokenArgs & { readonly afterOffset: number; readonly limit: number; }; -type ReadBatchesResult = { +interface ReadBatchesResult { readonly batches: ConversationBatchRow[]; readonly nextOffset: number; readonly upToDate: boolean; -}; +} const readConversationBatches = makeFunctionReference< "query", ReadBatchesArgs, @@ -478,12 +420,12 @@ type ReadEventsArgs = TokenArgs & { readonly afterOffset: number; readonly limit: number; }; -type ReadEventsResult = { +interface ReadEventsResult { readonly events: EventEntryRow[]; readonly nextOffset: number; readonly upToDate: boolean; readonly closed: boolean; -}; +} const readEventsFn = makeFunctionReference< "query", ReadEventsArgs, @@ -496,7 +438,7 @@ const closeEventStream = makeFunctionReference< void >("fluePersistence:closeEventStream"); -type EventStreamMetaRow = { readonly nextOffset: number; readonly closed: boolean }; +interface EventStreamMetaRow { readonly nextOffset: number; readonly closed: boolean } const getEventStreamMeta = makeFunctionReference< "query", TokenArgs & { readonly path: string }, @@ -545,10 +487,10 @@ type ListRunsArgs = TokenArgs & { readonly limit: number; readonly cursor?: { readonly startedAt: string; readonly runId: string }; }; -type ListRunsResult = { +interface ListRunsResult { readonly rows: RunPointerRow[]; readonly hasMore: boolean; -}; +} const listRuns = makeFunctionReference<"query", ListRunsArgs, ListRunsResult>( "fluePersistence:listRuns", ); @@ -571,10 +513,10 @@ type GetAttachmentArgs = TokenArgs & { readonly conversationId: string; readonly attachmentId: string; }; -type AttachmentWire = { +interface AttachmentWire { readonly attachment: AttachmentRefWire; readonly bytes: ArrayBuffer; -}; +} const getAttachment = makeFunctionReference< "query", GetAttachmentArgs, @@ -592,7 +534,7 @@ const deleteAttachmentsForInstance = makeFunctionReference< // --------------------------------------------------------------------------- const safeJsonParse = (text: string | null | undefined): T | undefined => { - if (text === null || text === undefined || text === "") return undefined; + if (text === null || text === undefined || text === "") {return undefined;} return JSON.parse(text) as T; }; @@ -601,7 +543,7 @@ const jsonStringify = (value: unknown): string => JSON.stringify(value); const parseAcceptedAt = (value: string, label: string): number => { const ms = Date.parse(value); if (!Number.isFinite(ms)) { - throw new Error( + throw new TypeError( `[flue] ${label} produced non-finite acceptedAt: ${value}`, ); } @@ -613,18 +555,18 @@ const afterOffset = (offset: string | undefined): number => offset === undefined ? -1 : parseOffset(offset); const wireRefToAttachmentRef = (wire: AttachmentRefWire): AttachmentRef => ({ + digest: wire.digest, id: wire.id, mimeType: wire.mimeType, size: wire.size, - digest: wire.digest, ...(wire.filename === undefined ? {} : { filename: wire.filename }), }); const attachmentRefToWire = (ref: AttachmentRef): AttachmentRefWire => ({ + digest: ref.digest, id: ref.id, mimeType: ref.mimeType, size: ref.size, - digest: ref.digest, ...(ref.filename === undefined ? {} : { filename: ref.filename }), }); @@ -636,17 +578,17 @@ const attachmentRefToWire = (ref: AttachmentRef): AttachmentRefWire => ({ */ const hydrateSubmission = (row: SubmissionRow): AgentSubmission => { const baseSubmission: Omit = { - sequence: row.sequence, - submissionId: row.submissionId, - sessionKey: row.sessionKey, - kind: row.kind, - status: row.status, acceptedAt: row.acceptedAt, - canonicalReadyAt: row.canonicalReadyAt, attemptCount: row.attemptCount, - maxRetry: row.maxRetry, - timeoutAt: row.timeoutAt, + canonicalReadyAt: row.canonicalReadyAt, + kind: row.kind, leaseExpiresAt: row.leaseExpiresAt, + maxRetry: row.maxRetry, + sequence: row.sequence, + sessionKey: row.sessionKey, + status: row.status, + submissionId: row.submissionId, + timeoutAt: row.timeoutAt, ...(row.attemptId === null ? {} : { attemptId: row.attemptId }), ...(row.inputAppliedAt === null ? {} @@ -699,19 +641,19 @@ const hydrateObligation = ( ); } return { - submissionId: row.submissionId, - sessionKey: row.sessionKey, attemptId: row.attemptId, - recordId: row.recordId, record, + recordId: row.recordId, + sessionKey: row.sessionKey, + submissionId: row.submissionId, }; }; const toRunRecord = (row: RunRow): RunRecord => ({ runId: row.runId, - workflowName: row.workflowName, - status: row.status, startedAt: row.startedAt, + status: row.status, + workflowName: row.workflowName, ...(row.endedAt === null ? {} : { endedAt: row.endedAt }), ...(row.isError === null ? {} : { isError: row.isError }), ...(row.durationMs === null ? {} : { durationMs: row.durationMs }), @@ -725,9 +667,9 @@ const toRunRecord = (row: RunRow): RunRecord => ({ const toRunPointer = (row: RunPointerRow): RunPointer => ({ runId: row.runId, - workflowName: row.workflowName, - status: row.status, startedAt: row.startedAt, + status: row.status, + workflowName: row.workflowName, ...(row.endedAt === null ? {} : { endedAt: row.endedAt }), ...(row.durationMs === null ? {} : { durationMs: row.durationMs }), ...(row.isError === null ? {} : { isError: row.isError }), @@ -772,13 +714,13 @@ class ConvexAgentSubmissionStore implements AgentSubmissionStore { async getSubmission(submissionId: string): Promise { const row = await this.convex.query(getSubmission, { - token: TOKEN(), submissionId, + token: TOKEN(), }); return row === null ? null : hydrateSubmission(row); } - async hasUnsettledSubmissions(): Promise { + hasUnsettledSubmissions(): Promise { return this.convex.query(hasUnsettledSubmissions, { token: TOKEN() }); } @@ -818,10 +760,10 @@ class ConvexAgentSubmissionStore implements AgentSubmissionStore { lease?: { ownerId: string; leaseExpiresAt: number }, ): Promise { const row = await this.convex.mutation(replaceSubmissionAttempt, { - token: TOKEN(), - submissionId: attempt.submissionId, attemptId: attempt.attemptId, nextAttemptId, + submissionId: attempt.submissionId, + token: TOKEN(), ...(lease === undefined ? {} : lease), }); return row === null ? null : hydrateSubmission(row); @@ -833,25 +775,25 @@ class ConvexAgentSubmissionStore implements AgentSubmissionStore { DispatchAgentSubmissionInput, "kind" | "submissionId" > = { - dispatchId: input.dispatchId, + acceptedAt: input.acceptedAt, agent: input.agent, + dispatchId: input.dispatchId, id: input.id, input: input.input, - acceptedAt: input.acceptedAt, }; const res = await this.convex.mutation(admitSubmission, { - token: TOKEN(), input: { - kind: "dispatch", - submissionId: input.dispatchId, - sessionKey, acceptedAt: parseAcceptedAt(input.acceptedAt, "admitDispatch"), inputJson: jsonStringify({ kind: "dispatch", submissionId: input.dispatchId, ...submissionInput, }), + kind: "dispatch", + sessionKey, + submissionId: input.dispatchId, }, + token: TOKEN(), }); if (res.kind === "submission" && res.submission !== undefined) { return { @@ -871,18 +813,18 @@ class ConvexAgentSubmissionStore implements AgentSubmissionStore { const sessionKey = createSessionStorageKey(input.id, "default", "default"); const extracted = prepareDirectSubmission(input); const res = await this.convex.mutation(admitSubmission, { - token: TOKEN(), input: { - kind: "direct", - submissionId: input.submissionId, - sessionKey, acceptedAt: parseAcceptedAt(input.acceptedAt, "admitDirect"), - inputJson: jsonStringify(extracted.value), chunksJson: jsonStringify(extracted.chunks), + inputJson: jsonStringify(extracted.value), + kind: "direct", + sessionKey, + submissionId: input.submissionId, ...(input.traceCarrier === undefined ? {} : { traceCarrierJson: jsonStringify(input.traceCarrier) }), }, + token: TOKEN(), }); if (res.kind === "submission" && res.submission !== undefined) { return hydrateSubmission(res.submission); @@ -899,8 +841,8 @@ class ConvexAgentSubmissionStore implements AgentSubmissionStore { submissionId: string, ): Promise { const row = await this.convex.mutation(markSubmissionCanonicalReady, { - token: TOKEN(), submissionId, + token: TOKEN(), }); return row === null ? null : hydrateSubmission(row); } @@ -909,51 +851,51 @@ class ConvexAgentSubmissionStore implements AgentSubmissionStore { claim: SubmissionClaimRef, ): Promise { const row = await this.convex.mutation(claimSubmission, { - token: TOKEN(), - submissionId: claim.submissionId, attemptId: claim.attemptId, - ownerId: claim.ownerId, leaseExpiresAt: claim.leaseExpiresAt, + ownerId: claim.ownerId, + submissionId: claim.submissionId, + token: TOKEN(), }); return row === null ? null : hydrateSubmission(row); } - async markSubmissionInputApplied( + markSubmissionInputApplied( attempt: SubmissionAttemptRef, durability?: SubmissionDurability, ): Promise { return this.convex.mutation(markSubmissionInputApplied, { - token: TOKEN(), - submissionId: attempt.submissionId, attemptId: attempt.attemptId, + submissionId: attempt.submissionId, + token: TOKEN(), ...(durability === undefined ? {} : durability), }); } - async requestSubmissionRecovery( + requestSubmissionRecovery( attempt: SubmissionAttemptRef, ): Promise { return this.convex.mutation(requestSubmissionRecovery, { - token: TOKEN(), - submissionId: attempt.submissionId, attemptId: attempt.attemptId, - }); - } - - async requestSessionAbort(sessionKey: string): Promise { - return this.convex.mutation(requestSessionAbort, { + submissionId: attempt.submissionId, token: TOKEN(), - sessionKey, }); } - async requeueSubmissionBeforeInputApplied( + requestSessionAbort(sessionKey: string): Promise { + return this.convex.mutation(requestSessionAbort, { + sessionKey, + token: TOKEN(), + }); + } + + requeueSubmissionBeforeInputApplied( attempt: SubmissionAttemptRef, ): Promise { return this.convex.mutation(requeueSubmissionBeforeInputApplied, { - token: TOKEN(), - submissionId: attempt.submissionId, attemptId: attempt.attemptId, + submissionId: attempt.submissionId, + token: TOKEN(), }); } @@ -962,62 +904,62 @@ class ConvexAgentSubmissionStore implements AgentSubmissionStore { settlement: { recordId: string; record: SubmissionSettledRecord }, ): Promise { const row = await this.convex.mutation(reserveSubmissionSettlement, { - token: TOKEN(), - submissionId: attempt.submissionId, attemptId: attempt.attemptId, recordId: settlement.recordId, recordJson: jsonStringify(settlement.record), + submissionId: attempt.submissionId, + token: TOKEN(), }); return row === null ? null : hydrateObligation(row); } - async finalizeSubmissionSettlement( + finalizeSubmissionSettlement( attempt: SubmissionAttemptRef, recordId: string, ): Promise { return this.convex.mutation(finalizeSubmissionSettlement, { - token: TOKEN(), - submissionId: attempt.submissionId, attemptId: attempt.attemptId, recordId, + submissionId: attempt.submissionId, + token: TOKEN(), }); } - async completeSubmission(attempt: SubmissionAttemptRef): Promise { + completeSubmission(attempt: SubmissionAttemptRef): Promise { return this.convex.mutation(settleSubmission, { - token: TOKEN(), - submissionId: attempt.submissionId, attemptId: attempt.attemptId, outcome: "completed", + submissionId: attempt.submissionId, + token: TOKEN(), }); } - async failSubmission( + failSubmission( attempt: SubmissionAttemptRef, error: unknown, ): Promise { return this.convex.mutation(settleSubmission, { - token: TOKEN(), - submissionId: attempt.submissionId, attemptId: attempt.attemptId, - outcome: "failed", errorJson: jsonStringify(error), + outcome: "failed", + submissionId: attempt.submissionId, + token: TOKEN(), }); } async insertAttemptMarker(attempt: SubmissionAttemptRef): Promise { await this.convex.mutation(insertAttemptMarker, { - token: TOKEN(), - submissionId: attempt.submissionId, attemptId: attempt.attemptId, + submissionId: attempt.submissionId, + token: TOKEN(), }); } async deleteAttemptMarker(attempt: SubmissionAttemptRef): Promise { await this.convex.mutation(deleteAttemptMarker, { - token: TOKEN(), - submissionId: attempt.submissionId, attemptId: attempt.attemptId, + submissionId: attempt.submissionId, + token: TOKEN(), }); } @@ -1026,17 +968,17 @@ class ConvexAgentSubmissionStore implements AgentSubmissionStore { token: TOKEN(), }); return rows.map((row) => ({ - submissionId: row.submissionId, attemptId: row.attemptId, createdAt: row.createdAt, + submissionId: row.submissionId, })); } async renewLeases(ownerId: string, submissionIds: string[]): Promise { await this.convex.mutation(renewLeases, { - token: TOKEN(), ownerId, submissionIds, + token: TOKEN(), }); } @@ -1062,20 +1004,20 @@ class ConvexConversationStreamStore implements ConversationStreamStore { identity: ConversationStreamIdentity, ): Promise { await this.convex.mutation(createConversationStream, { - token: TOKEN(), - path, identity, + path, + token: TOKEN(), }); } - async acquireProducer( + acquireProducer( path: string, producerId: string, ): Promise { return this.convex.mutation(acquireConversationProducer, { - token: TOKEN(), path, producerId, + token: TOKEN(), }); } @@ -1089,14 +1031,14 @@ class ConvexConversationStreamStore implements ConversationStreamStore { records: readonly ConversationRecord[]; }): Promise<{ offset: string }> { const result = await this.convex.mutation(appendConversationBatch, { - token: TOKEN(), - path: input.path, - producerId: input.producerId, - producerEpoch: input.producerEpoch, incarnation: input.incarnation, + path: input.path, + producerEpoch: input.producerEpoch, + producerId: input.producerId, producerSequence: input.producerSequence, - ...(input.submission === undefined ? {} : { submission: input.submission }), recordsJson: jsonStringify(input.records), + token: TOKEN(), + ...(input.submission === undefined ? {} : { submission: input.submission }), }); if (result.appended) { this.listeners.notify(input.path); @@ -1114,10 +1056,10 @@ class ConvexConversationStreamStore implements ConversationStreamStore { MAX_READ_LIMIT, ); const result = await this.convex.query(readConversationBatches, { - token: TOKEN(), - path, afterOffset: afterOffset(options?.offset), limit, + path, + token: TOKEN(), }); const batches: ConversationStreamBatch[] = result.batches.map((row) => ({ offset: formatOffset(row.offset), @@ -1132,24 +1074,24 @@ class ConvexConversationStreamStore implements ConversationStreamStore { async getMeta(path: string): Promise { const row = await this.convex.query(getConversationStreamMeta, { - token: TOKEN(), path, + token: TOKEN(), }); - if (row === null) return null; + if (row === null) {return null;} return { identity: row.identity, incarnation: row.incarnation, nextOffset: formatOffset(row.nextOffset), - producerId: row.producerId, - producerEpoch: row.producerEpoch, nextProducerSequence: row.nextProducerSequence, + producerEpoch: row.producerEpoch, + producerId: row.producerId, }; } async delete(path: string): Promise { await this.convex.mutation(deleteConversationStream, { - token: TOKEN(), path, + token: TOKEN(), }); } @@ -1169,16 +1111,16 @@ class ConvexEventStreamStore implements EventStreamStore { async createStream(path: string): Promise { await this.convex.mutation(createEventStream, { - token: TOKEN(), path, + token: TOKEN(), }); } async appendEvent(path: string, event: unknown): Promise { const result = await this.convex.mutation(appendEventFn, { - token: TOKEN(), - path, dataJson: jsonStringify(event), + path, + token: TOKEN(), }); if (result.appended) { this.listeners.notify(path); @@ -1192,10 +1134,10 @@ class ConvexEventStreamStore implements EventStreamStore { event: unknown, ): Promise { const result = await this.convex.mutation(appendEventOnce, { - token: TOKEN(), - path, - key, dataJson: jsonStringify(event), + key, + path, + token: TOKEN(), }); if (result.appended) { this.listeners.notify(path); @@ -1209,38 +1151,38 @@ class ConvexEventStreamStore implements EventStreamStore { ): Promise { const limit = clampLimit(opts?.limit, DEFAULT_READ_LIMIT, MAX_READ_LIMIT); const result = await this.convex.query(readEventsFn, { - token: TOKEN(), - path, afterOffset: afterOffset(opts?.offset), limit, + path, + token: TOKEN(), }); return { + closed: result.closed, events: result.events.map((row) => ({ - offset: formatOffset(row.offset), data: safeJsonParse(row.dataJson), + offset: formatOffset(row.offset), })), nextOffset: formatOffset(result.nextOffset), upToDate: result.upToDate, - closed: result.closed, }; } async closeStream(path: string): Promise { await this.convex.mutation(closeEventStream, { - token: TOKEN(), path, + token: TOKEN(), }); } async getStreamMeta(path: string): Promise { const row = await this.convex.query(getEventStreamMeta, { - token: TOKEN(), path, + token: TOKEN(), }); - if (row === null) return null; + if (row === null) {return null;} return { - nextOffset: formatOffset(row.nextOffset), closed: row.closed, + nextOffset: formatOffset(row.nextOffset), }; } @@ -1258,11 +1200,11 @@ class ConvexRunStore implements RunStore { async createRun(input: CreateRunInput): Promise { await this.convex.mutation(createRun, { - token: TOKEN(), - runId: input.runId, - workflowName: input.workflowName, - startedAt: input.startedAt, inputJson: jsonStringify(input.input), + runId: input.runId, + startedAt: input.startedAt, + token: TOKEN(), + workflowName: input.workflowName, ...(input.traceCarrier === undefined ? {} : { traceCarrierJson: jsonStringify(input.traceCarrier) }), @@ -1271,11 +1213,11 @@ class ConvexRunStore implements RunStore { async endRun(input: EndRunInput): Promise { await this.convex.mutation(endRun, { - token: TOKEN(), - runId: input.runId, + durationMs: input.durationMs, endedAt: input.endedAt, isError: input.isError, - durationMs: input.durationMs, + runId: input.runId, + token: TOKEN(), ...(input.result === undefined ? {} : { resultJson: jsonStringify(input.result) }), @@ -1286,14 +1228,14 @@ class ConvexRunStore implements RunStore { } async getRun(runId: string): Promise { - const row = await this.convex.query(getRun, { token: TOKEN(), runId }); + const row = await this.convex.query(getRun, { runId, token: TOKEN() }); return row === null ? null : toRunRecord(row); } - async lookupRun( + lookupRun( runId: string, ): Promise<{ runId: string; workflowName: string } | null> { - return this.convex.query(lookupRun, { token: TOKEN(), runId }); + return this.convex.query(lookupRun, { runId, token: TOKEN() }); } async listRuns(opts?: { @@ -1314,10 +1256,10 @@ class ConvexRunStore implements RunStore { ...(decoded === undefined ? {} : { cursor: decoded }), }); const runs = result.rows.map(toRunPointer); - const last = runs[runs.length - 1]; + const last = runs.at(-1); const nextCursor = result.hasMore && last !== undefined - ? encodeRunCursor({ startedAt: last.startedAt, runId: last.runId }) + ? encodeRunCursor({ runId: last.runId, startedAt: last.startedAt }) : undefined; return { runs, ...(nextCursor === undefined ? {} : { nextCursor }) }; } @@ -1336,31 +1278,31 @@ class ConvexAttachmentStore implements AttachmentStore { // payload cannot be mutated after the call returns. const bytes = copyAttachmentBytes(input.bytes); const status = await this.convex.mutation(putAttachment, { - token: TOKEN(), - streamPath: input.streamPath, - conversationId: input.conversationId, attachment: attachmentRefToWire(input.attachment), bytes: bytes.buffer.slice( bytes.byteOffset, bytes.byteOffset + bytes.byteLength, ) as ArrayBuffer, + conversationId: input.conversationId, + streamPath: input.streamPath, + token: TOKEN(), }); if (status === "conflict") { throw new AttachmentConflictError({ - path: input.streamPath, attachmentId: input.attachment.id, + path: input.streamPath, }); } } async get(input: GetAttachmentInput): Promise { const row = await this.convex.query(getAttachment, { - token: TOKEN(), - streamPath: input.streamPath, - conversationId: input.conversationId, attachmentId: input.attachmentId, + conversationId: input.conversationId, + streamPath: input.streamPath, + token: TOKEN(), }); - if (row === null) return null; + if (row === null) {return null;} const attachment = wireRefToAttachmentRef(row.attachment); const bytes = new Uint8Array(row.bytes); // Verify integrity before handing bytes back to the runtime; throws @@ -1374,8 +1316,8 @@ class ConvexAttachmentStore implements AttachmentStore { async deleteForInstance(streamPath: string): Promise { await this.convex.mutation(deleteAttachmentsForInstance, { - token: TOKEN(), streamPath, + token: TOKEN(), }); } } @@ -1409,11 +1351,11 @@ class ConvexPersistenceAdapterImpl implements PersistenceAdapter { const submissions = new ConvexAgentSubmissionStore(this.convex); const executionStore: AgentExecutionStore = { submissions }; return { + attachmentStore: new ConvexAttachmentStore(this.convex), + conversationStreamStore: new ConvexConversationStreamStore(this.convex), + eventStreamStore: new ConvexEventStreamStore(this.convex), executionStore, runStore: new ConvexRunStore(this.convex), - eventStreamStore: new ConvexEventStreamStore(this.convex), - conversationStreamStore: new ConvexConversationStreamStore(this.convex), - attachmentStore: new ConvexAttachmentStore(this.convex), }; } diff --git a/packages/auth/package.json b/packages/auth/package.json index bafb4a9..c9ebc0a 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -23,13 +23,13 @@ "expo-secure-store": "~57.0.0", "heroui-native": "catalog:", "react": "catalog:", - "react-native": "0.86.0", + "react-native": "catalog:", "sonner": "catalog:", "zod": "catalog:" }, "devDependencies": { "@code/config": "workspace:*", - "@types/react": "~19.2.17", + "@types/react": "catalog:", "typescript": "catalog:", "vite": "catalog:", "vitest": "catalog:" diff --git a/packages/backend/.oxlintrc.json b/packages/backend/.oxlintrc.json deleted file mode 100644 index a91a35c..0000000 --- a/packages/backend/.oxlintrc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "overrides": [ - { - "files": ["convex/**/*.ts"], - "rules": { - "unicorn/filename-case": "off" - } - } - ] -} diff --git a/packages/backend/convex/README.md b/packages/backend/convex/README.md index 1802962..5dd1ae8 100644 --- a/packages/backend/convex/README.md +++ b/packages/backend/convex/README.md @@ -1,8 +1,6 @@ # Convex Backend -Convex is the only application API used by web, desktop, and mobile clients. -The active Slice 1 backend is intentionally limited to tenancy, projects, -conversation turns, Signals, Work, and Flue's required persistence adapter. +Convex is the only application API used by web, desktop, and mobile clients. The active backend covers the durable control plane through Slice 4: tenancy, projects, conversation turns, Signals, Work planning, approved Design slices, simulated Runs and Attempts, artifacts/delivery metadata, and Flue persistence. ## Domain relations @@ -11,6 +9,9 @@ conversation turns, Signals, Work, and Flue's required persistence adapter. - `conversations`, `conversationTurns`, `conversationMessages`, and `conversationAttachments` own chat admission and reactive history. - `signals`, `signalConstraints`, and `signalSources` preserve structured intent and exact evidence. - `works`, `signalWorkAttachments`, and `workEvents` own proposed Work and provenance. +- `workDefinitions`, `workQuestions`, and `workApprovals` own versioned outcome contracts and approvals. +- `designPackets` and `workSlices` preserve versioned implementation intent and executable slice order. +- `workRuns`, `workAttempts`, `workAttemptEvents`, and `resolverDecisions` own bounded simulated execution and recovery. +- `workArtifacts` and `workDeliveries` preserve evidence and delivery metadata without performing Git or sandbox work. -The `flue*` tables are infrastructure tables required by Flue's persistence -contract. They are deliberately separate from the product relations. +The `flue*` tables are infrastructure tables required by Flue's persistence contract. They are deliberately separate from the product relations. diff --git a/packages/backend/convex/conversationMessages.test.ts b/packages/backend/convex/conversationMessages.test.ts index 80b9205..1389b3c 100644 --- a/packages/backend/convex/conversationMessages.test.ts +++ b/packages/backend/convex/conversationMessages.test.ts @@ -1,5 +1,5 @@ import { convexTest } from "convex-test"; -import { anyApi } from "convex/server"; +import { anyApi, makeFunctionReference } from "convex/server"; import { describe, expect, test } from "vitest"; import schema from "./schema"; @@ -15,6 +15,33 @@ const api = anyApi; const identityA = { tokenIdentifier: "https://convex.test|user-a" }; const identityB = { tokenIdentifier: "https://convex.test|user-b" }; const newTest = () => convexTest({ modules, schema }); +const markProcessingRef = makeFunctionReference< + "mutation", + { turnId: string; attempt: number; leaseOwner: string }, + boolean +>("conversationMessages:markProcessing"); +const completeTurnRef = makeFunctionReference< + "mutation", + { + turnId: string; + attempt: number; + leaseOwner: string; + submissionId: string; + text: string; + }, + boolean +>("conversationMessages:completeTurn"); +const failTurnRef = makeFunctionReference< + "mutation", + { + turnId: string; + attempt: number; + leaseOwner: string; + error: string; + retry: boolean; + }, + boolean +>("conversationMessages:failTurn"); const ensureOrg = async ( t: ReturnType, @@ -109,4 +136,66 @@ describe("conversationMessages", () => { }) ).rejects.toThrow(/Organization membership required/u); }); + + test("fences stale turn attempts from overwriting a retry", async () => { + const t = newTest(); + const organization = await ensureOrg(t, identityA); + const sent = await t + .withIdentity(identityA) + .mutation(api.conversationMessages.send, { + clientRequestId: "request-fenced", + images: [], + organizationId: organization._id, + rawText: "Keep only the current response", + }); + + expect( + await t.mutation(markProcessingRef, { + attempt: 1, + leaseOwner: "worker-1", + turnId: sent.turnId, + }) + ).toBe(true); + expect( + await t.mutation(failTurnRef, { + attempt: 1, + error: "retry", + leaseOwner: "worker-1", + retry: true, + turnId: sent.turnId, + }) + ).toBe(true); + expect( + await t.mutation(completeTurnRef, { + attempt: 1, + leaseOwner: "worker-1", + submissionId: "stale", + text: "stale response", + turnId: sent.turnId, + }) + ).toBe(false); + expect( + await t.mutation(markProcessingRef, { + attempt: 2, + leaseOwner: "worker-2", + turnId: sent.turnId, + }) + ).toBe(true); + expect( + await t.mutation(completeTurnRef, { + attempt: 2, + leaseOwner: "worker-2", + submissionId: "current", + text: "current response", + turnId: sent.turnId, + }) + ).toBe(true); + + const messages = await t + .withIdentity(identityA) + .query(api.conversationMessages.listForCurrentOrganization, { + organizationId: organization._id, + }); + expect(messages[1]?.rawText).toBe("current response"); + }); }); diff --git a/packages/backend/convex/conversationMessages.ts b/packages/backend/convex/conversationMessages.ts index 8cf24b4..f1903c1 100644 --- a/packages/backend/convex/conversationMessages.ts +++ b/packages/backend/convex/conversationMessages.ts @@ -31,18 +31,34 @@ const getTurnRef = makeFunctionReference< >("conversationMessages:getTurn"); const markProcessingRef = makeFunctionReference< "mutation", - { turnId: Id<"conversationTurns"> }, + { + turnId: Id<"conversationTurns">; + attempt: number; + leaseOwner: string; + }, boolean >("conversationMessages:markProcessing"); const completeTurnRef = makeFunctionReference< "mutation", - { turnId: Id<"conversationTurns">; submissionId: string; text: string }, - null + { + turnId: Id<"conversationTurns">; + attempt: number; + leaseOwner: string; + submissionId: string; + text: string; + }, + boolean >("conversationMessages:completeTurn"); const failTurnRef = makeFunctionReference< "mutation", - { turnId: Id<"conversationTurns">; error: string; retry: boolean }, - null + { + turnId: Id<"conversationTurns">; + attempt: number; + leaseOwner: string; + error: string; + retry: boolean; + }, + boolean >("conversationMessages:failTurn"); export const generateUploadUrl = mutation({ @@ -57,16 +73,16 @@ export const generateUploadUrl = mutation({ export const send = mutation({ args: { - organizationId: v.id("organizations"), clientRequestId: v.string(), - rawText: v.string(), images: v.array( v.object({ - storageId: v.id("_storage"), filename: v.optional(v.string()), mimeType: v.string(), + storageId: v.id("_storage"), }) ), + organizationId: v.id("organizations"), + rawText: v.string(), }, handler: async (ctx, args) => { await requireOrganizationMember(ctx, args.organizationId); @@ -115,6 +131,7 @@ export const send = mutation({ .first(); const ordinal = (lastMessage?.ordinal ?? -1) + 1; const turnId = await ctx.db.insert("conversationTurns", { + attemptNumber: 1, clientRequestId: args.clientRequestId, conversationId: conversation._id, createdAt, @@ -233,24 +250,49 @@ export const getTurn = internalQuery({ }); export const markProcessing = internalMutation({ - args: { turnId: v.id("conversationTurns") }, + args: { + attempt: v.number(), + leaseOwner: v.string(), + turnId: v.id("conversationTurns"), + }, handler: async (ctx, args): Promise => { const turn = await ctx.db.get(args.turnId); - if (!turn || turn.status === "completed") { + if ( + !turn || + turn.status !== "queued" || + (turn.attemptNumber ?? 1) !== args.attempt + ) { return false; } - await ctx.db.patch(turn._id, { error: undefined, status: "processing" }); + await ctx.db.patch(turn._id, { + error: undefined, + leaseExpiresAt: Date.now() + 60_000, + leaseOwner: args.leaseOwner, + status: "processing", + }); return true; }, }); export const completeTurn = internalMutation({ args: { - turnId: v.id("conversationTurns"), + attempt: v.number(), + leaseOwner: v.string(), submissionId: v.string(), text: v.string(), + turnId: v.id("conversationTurns"), }, - handler: async (ctx, args): Promise => { + handler: async (ctx, args): Promise => { + const turn = await ctx.db.get(args.turnId); + if ( + !turn || + turn.status !== "processing" || + (turn.attemptNumber ?? 1) !== args.attempt || + turn.leaseOwner !== args.leaseOwner || + (turn.leaseExpiresAt !== undefined && turn.leaseExpiresAt < Date.now()) + ) { + return false; + } const assistant = await ctx.db .query("conversationMessages") .withIndex("by_turnId_and_role", (q) => @@ -263,29 +305,43 @@ export const completeTurn = internalMutation({ await ctx.db.patch(args.turnId, { completedAt: Date.now(), error: undefined, + leaseExpiresAt: undefined, + leaseOwner: undefined, status: "completed", submissionId: args.submissionId, }); - return null; + return true; }, }); export const failTurn = internalMutation({ args: { - turnId: v.id("conversationTurns"), + attempt: v.number(), error: v.string(), + leaseOwner: v.string(), retry: v.boolean(), + turnId: v.id("conversationTurns"), }, - handler: async (ctx, args): Promise => { + handler: async (ctx, args): Promise => { const turn = await ctx.db.get(args.turnId); - if (turn && turn.status !== "completed") { - await ctx.db.patch(turn._id, { - completedAt: args.retry ? undefined : Date.now(), - error: args.error, - status: args.retry ? "queued" : "failed", - }); + if ( + !turn || + turn.status !== "processing" || + (turn.attemptNumber ?? 1) !== args.attempt || + turn.leaseOwner !== args.leaseOwner || + (turn.leaseExpiresAt !== undefined && turn.leaseExpiresAt < Date.now()) + ) { + return false; } - return null; + await ctx.db.patch(turn._id, { + attemptNumber: args.retry ? args.attempt + 1 : args.attempt, + completedAt: args.retry ? undefined : Date.now(), + error: args.error, + leaseExpiresAt: undefined, + leaseOwner: undefined, + status: args.retry ? "queued" : "failed", + }); + return true; }, }); @@ -298,12 +354,17 @@ const toBase64 = (buffer: ArrayBuffer): string => { }; export const runTurn = internalAction({ - args: { turnId: v.id("conversationTurns"), attempt: v.number() }, + args: { attempt: v.number(), turnId: v.id("conversationTurns") }, handler: async (ctx, args): Promise => { + const leaseOwner = `conversation:${args.turnId}:${args.attempt}`; const turn = await ctx.runQuery(getTurnRef, { turnId: args.turnId }); if ( !turn || - !(await ctx.runMutation(markProcessingRef, { turnId: args.turnId })) + !(await ctx.runMutation(markProcessingRef, { + attempt: args.attempt, + leaseOwner, + turnId: args.turnId, + })) ) { return null; } @@ -358,6 +419,8 @@ export const runTurn = internalAction({ throw new Error(`Flue turn failed (${response.status})`); } await ctx.runMutation(completeTurnRef, { + attempt: args.attempt, + leaseOwner, submissionId: payload.submissionId, text: payload.result.text, turnId: args.turnId, @@ -365,7 +428,9 @@ export const runTurn = internalAction({ } catch (error) { const retry = args.attempt < MAX_ATTEMPTS; await ctx.runMutation(failTurnRef, { + attempt: args.attempt, error: error instanceof Error ? error.message : String(error), + leaseOwner, retry, turnId: args.turnId, }); @@ -379,3 +444,34 @@ export const runTurn = internalAction({ return null; }, }); + +export const reconcileExpiredTurns = internalMutation({ + args: {}, + handler: async (ctx): Promise<{ reconciled: number }> => { + const expired = await ctx.db + .query("conversationTurns") + .withIndex("by_status_and_leaseExpiresAt", (q) => + q.eq("status", "processing").lt("leaseExpiresAt", Date.now()) + ) + .collect(); + for (const turn of expired) { + const attempt = turn.attemptNumber ?? 1; + const retry = attempt < MAX_ATTEMPTS; + await ctx.db.patch(turn._id, { + attemptNumber: retry ? attempt + 1 : attempt, + completedAt: retry ? undefined : Date.now(), + error: "Conversation worker lease expired", + leaseExpiresAt: undefined, + leaseOwner: undefined, + status: retry ? "queued" : "failed", + }); + if (retry) { + await ctx.scheduler.runAfter(0, runTurnRef, { + attempt: attempt + 1, + turnId: turn._id, + }); + } + } + return { reconciled: expired.length }; + }, +}); diff --git a/packages/backend/convex/convex.config.ts b/packages/backend/convex/convex.config.ts index da2cf3a..a6700e2 100644 --- a/packages/backend/convex/convex.config.ts +++ b/packages/backend/convex/convex.config.ts @@ -4,12 +4,12 @@ import { v } from "convex/values"; const app = defineApp({ env: { - NATIVE_APP_URL: v.optional(v.string()), - SITE_URL: v.string(), FLUE_DB_TOKEN: v.string(), FLUE_URL: v.optional(v.string()), - GITEA_URL: v.optional(v.string()), GITEA_TOKEN: v.optional(v.string()), + GITEA_URL: v.optional(v.string()), + NATIVE_APP_URL: v.optional(v.string()), + SITE_URL: v.string(), }, }); app.use(betterAuth); diff --git a/packages/backend/convex/crons.ts b/packages/backend/convex/crons.ts index 7be4c15..88eceb1 100644 --- a/packages/backend/convex/crons.ts +++ b/packages/backend/convex/crons.ts @@ -7,6 +7,11 @@ const reconcileRef = makeFunctionReference< Record, { reconciled: number } | null >("workExecution:reconcileExpiredAttempts"); +const reconcileConversationTurnsRef = makeFunctionReference< + "mutation", + Record, + { reconciled: number } +>("conversationMessages:reconcileExpiredTurns"); const crons = cronJobs(); @@ -15,5 +20,10 @@ crons.interval( { seconds: 30 }, reconcileRef ); +crons.interval( + "reconcile expired conversation turns", + { seconds: 30 }, + reconcileConversationTurnsRef +); export default crons; diff --git a/packages/backend/convex/fluePersistence.test.ts b/packages/backend/convex/fluePersistence.test.ts new file mode 100644 index 0000000..bebd4d4 --- /dev/null +++ b/packages/backend/convex/fluePersistence.test.ts @@ -0,0 +1,142 @@ +import { env } from "@code/env/convex"; +import { convexTest } from "convex-test"; +import { anyApi } from "convex/server"; +import { describe, expect, test } from "vitest"; + +import schema from "./schema"; + +declare global { + interface ImportMeta { + readonly glob: (pattern: string) => Record Promise>; + } +} + +const modules = import.meta.glob("./**/*.ts"); +const api = anyApi; +const token = env.FLUE_DB_TOKEN; + +describe("Flue Convex persistence", () => { + test("admits idempotently and claims only the session head", async () => { + const t = convexTest({ modules, schema }); + const firstInput = { + acceptedAt: 1, + inputJson: '{"message":"first"}', + kind: "dispatch" as const, + sessionKey: "agent/instance/default", + submissionId: "dispatch-1", + }; + const first = await t.mutation(api.fluePersistence.admitSubmission, { + input: firstInput, + token, + }); + const replay = await t.mutation(api.fluePersistence.admitSubmission, { + input: firstInput, + token, + }); + expect(first.kind).toBe("submission"); + expect(replay.kind).toBe("retained_receipt"); + + await t.mutation(api.fluePersistence.admitSubmission, { + input: { + ...firstInput, + acceptedAt: 2, + inputJson: '{"message":"second"}', + submissionId: "dispatch-2", + }, + token, + }); + await t.mutation(api.fluePersistence.markSubmissionCanonicalReady, { + submissionId: "dispatch-1", + token, + }); + await t.mutation(api.fluePersistence.markSubmissionCanonicalReady, { + submissionId: "dispatch-2", + token, + }); + const secondClaim = await t.mutation(api.fluePersistence.claimSubmission, { + attemptId: "attempt-2", + leaseExpiresAt: 100, + ownerId: "owner", + submissionId: "dispatch-2", + token, + }); + expect(secondClaim).toBeNull(); + const firstClaim = await t.mutation(api.fluePersistence.claimSubmission, { + attemptId: "attempt-1", + leaseExpiresAt: 100, + ownerId: "owner", + submissionId: "dispatch-1", + token, + }); + expect(firstClaim).toMatchObject({ + attemptId: "attempt-1", + status: "running", + }); + }); + + test("fences stale conversation producers and conflicting attachments", async () => { + const t = convexTest({ modules, schema }); + await t.mutation(api.fluePersistence.createConversationStream, { + identity: { agentName: "work-planner", instanceId: "org-1" }, + path: "agents/work-planner/org-1", + token, + }); + const first = await t.mutation( + api.fluePersistence.acquireConversationProducer, + { + path: "agents/work-planner/org-1", + producerId: "producer-1", + token, + } + ); + await t.mutation(api.fluePersistence.acquireConversationProducer, { + path: "agents/work-planner/org-1", + producerId: "producer-2", + token, + }); + await expect( + t.mutation(api.fluePersistence.appendConversationBatch, { + incarnation: first.incarnation, + path: "agents/work-planner/org-1", + producerEpoch: first.producerEpoch, + producerId: "producer-1", + producerSequence: 0, + recordsJson: '[{"id":"record-1","type":"message"}]', + token, + }) + ).rejects.toThrow(/producer ownership is stale/u); + + const attachment = { + digest: "digest", + id: "attachment-1", + mimeType: "text/plain", + size: 3, + }; + const inserted = await t.mutation(api.fluePersistence.putAttachment, { + attachment, + bytes: new TextEncoder().encode("one").buffer, + conversationId: "conversation-1", + streamPath: "agents/work-planner/org-1", + token, + }); + const replay = await t.mutation(api.fluePersistence.putAttachment, { + attachment, + bytes: new TextEncoder().encode("one").buffer, + conversationId: "conversation-1", + streamPath: "agents/work-planner/org-1", + token, + }); + const conflict = await t.mutation(api.fluePersistence.putAttachment, { + attachment, + bytes: new TextEncoder().encode("two").buffer, + conversationId: "conversation-1", + streamPath: "agents/work-planner/org-1", + token, + }); + expect([inserted, replay, conflict]).toEqual([ + "inserted", + "existing", + "conflict", + ]); + }); +}); diff --git a/packages/backend/convex/fluePersistence.ts b/packages/backend/convex/fluePersistence.ts index 014b8eb..4d6c1b4 100644 --- a/packages/backend/convex/fluePersistence.ts +++ b/packages/backend/convex/fluePersistence.ts @@ -1,3 +1,4 @@ +/* eslint-disable unicorn/no-array-sort, no-await-in-loop, unicorn/no-await-expression-member, unicorn/filename-case, unicorn/prefer-at, unicorn/no-array-reduce, @typescript-eslint/no-non-null-assertion */ import { env } from "@code/env/convex"; import type { Doc } from "./_generated/dataModel"; import { mutation, query } from "./_generated/server"; @@ -21,7 +22,7 @@ type EventEntryDoc = Doc<"flueEventEntries">; type RunDoc = Doc<"flueRuns">; type AttachmentDoc = Doc<"flueAttachments">; -type SubmissionRow = { +interface SubmissionRow { readonly sequence: number; readonly submissionId: string; readonly sessionKey: string; @@ -43,55 +44,55 @@ type SubmissionRow = { readonly ownerId: string | null; readonly leaseExpiresAt: number; readonly traceCarrierJson: string | null; -}; +} -type SettlementObligationRow = { +interface SettlementObligationRow { readonly submissionId: string; readonly sessionKey: string; readonly attemptId: string; readonly recordId: string; readonly recordJson: string; -}; +} -type AttemptMarkerRow = { +interface AttemptMarkerRow { readonly submissionId: string; readonly attemptId: string; readonly createdAt: number; -}; +} -type ConversationStreamIdentity = { +interface ConversationStreamIdentity { readonly agentName: string; readonly instanceId: string; -}; +} -type ConversationProducerClaim = { +interface ConversationProducerClaim { readonly producerId: string; readonly producerEpoch: number; readonly incarnation: string; readonly nextProducerSequence: number; readonly offset: string; -}; +} -type ConversationStreamRow = { +interface ConversationStreamRow { readonly identity: ConversationStreamIdentity; readonly incarnation: string; readonly nextOffset: number; readonly producerId: string | null; readonly producerEpoch: number; readonly nextProducerSequence: number; -}; +} -type ConversationBatchRow = { +interface ConversationBatchRow { readonly offset: number; readonly recordsJson: string; -}; +} -type EventEntryRow = { +interface EventEntryRow { readonly offset: number; readonly dataJson: string; -}; +} -type RunRow = { +interface RunRow { readonly runId: string; readonly workflowName: string; readonly status: RunStatus; @@ -103,9 +104,9 @@ type RunRow = { readonly resultJson: string | null; readonly errorJson: string | null; readonly traceCarrierJson: string | null; -}; +} -type RunPointerRow = { +interface RunPointerRow { readonly runId: string; readonly workflowName: string; readonly status: RunStatus; @@ -113,38 +114,38 @@ type RunPointerRow = { readonly endedAt: string | null; readonly durationMs: number | null; readonly isError: boolean | null; -}; +} -type AttachmentRefWire = { +interface AttachmentRefWire { readonly id: string; readonly mimeType: string; readonly size: number; readonly digest: string; readonly filename?: string; -}; +} -type AttachmentWire = { +interface AttachmentWire { readonly attachment: AttachmentRefWire; readonly bytes: ArrayBuffer; -}; +} -type AdmitSubmissionResponse = { +interface AdmitSubmissionResponse { readonly kind: "submission" | "retained_receipt" | "conflict"; readonly submission?: SubmissionRow; readonly receipt?: { readonly submissionId: string; readonly acceptedAt: number }; -}; +} -type AppendResult = { readonly offset: number; readonly appended: boolean }; +interface AppendResult { readonly offset: number; readonly appended: boolean } -type ListRunsCursor = { readonly startedAt: string; readonly runId: string }; +interface ListRunsCursor { readonly startedAt: string; readonly runId: string } -type OwnedConversationRecord = { +interface OwnedConversationRecord { readonly id?: string; readonly type?: string; readonly submissionId?: string; readonly attemptId?: string; -}; +} const submissionKind = v.union(v.literal("dispatch"), v.literal("direct")); const runStatus = v.union( @@ -153,11 +154,11 @@ const runStatus = v.union( v.literal("errored"), ); const attachmentRef = v.object({ + digest: v.string(), + filename: v.optional(v.string()), id: v.string(), mimeType: v.string(), size: v.number(), - digest: v.string(), - filename: v.optional(v.string()), }); const conversationIdentity = v.object({ agentName: v.string(), @@ -174,26 +175,26 @@ const assertToken = (token: string): void => { const safeJsonParse = (text: string): T => JSON.parse(text) as T; const toSubmissionRow = (doc: SubmissionDoc): SubmissionRow => ({ - sequence: doc.sequence, - submissionId: doc.submissionId, - sessionKey: doc.sessionKey, - kind: doc.kind, - inputJson: doc.inputJson, - chunksJson: doc.chunksJson, - status: doc.status, - acceptedAt: doc.acceptedAt, - canonicalReadyAt: doc.canonicalReadyAt ?? null, - attemptId: doc.attemptId ?? null, - inputAppliedAt: doc.inputAppliedAt ?? null, - recoveryRequestedAt: doc.recoveryRequestedAt ?? null, abortRequestedAt: doc.abortRequestedAt ?? null, - startedAt: doc.startedAt ?? null, - error: doc.error ?? null, + acceptedAt: doc.acceptedAt, attemptCount: doc.attemptCount, - maxRetry: doc.maxRetry, - timeoutAt: doc.timeoutAt, - ownerId: doc.ownerId ?? null, + attemptId: doc.attemptId ?? null, + canonicalReadyAt: doc.canonicalReadyAt ?? null, + chunksJson: doc.chunksJson, + error: doc.error ?? null, + inputAppliedAt: doc.inputAppliedAt ?? null, + inputJson: doc.inputJson, + kind: doc.kind, leaseExpiresAt: doc.leaseExpiresAt, + maxRetry: doc.maxRetry, + ownerId: doc.ownerId ?? null, + recoveryRequestedAt: doc.recoveryRequestedAt ?? null, + sequence: doc.sequence, + sessionKey: doc.sessionKey, + startedAt: doc.startedAt ?? null, + status: doc.status, + submissionId: doc.submissionId, + timeoutAt: doc.timeoutAt, traceCarrierJson: doc.traceCarrierJson ?? null, }); @@ -208,18 +209,18 @@ const toSettlementObligationRow = ( return null; } return { - submissionId: doc.submissionId, - sessionKey: doc.sessionKey, attemptId: doc.attemptId, recordId: doc.settlementRecordId, recordJson: doc.settlementRecordJson, + sessionKey: doc.sessionKey, + submissionId: doc.submissionId, }; }; const toAttemptMarkerRow = (doc: AttemptMarkerDoc): AttemptMarkerRow => ({ - submissionId: doc.submissionId, attemptId: doc.attemptId, createdAt: doc.createdAt, + submissionId: doc.submissionId, }); const toConversationStreamRow = ( @@ -228,9 +229,9 @@ const toConversationStreamRow = ( identity: safeJsonParse(doc.identityJson), incarnation: doc.incarnation, nextOffset: doc.nextOffset - 1, - producerId: doc.producerId ?? null, - producerEpoch: doc.producerEpoch, nextProducerSequence: doc.nextProducerSequence, + producerEpoch: doc.producerEpoch, + producerId: doc.producerId ?? null, }); const toConversationBatchRow = (doc: ConversationBatchDoc): ConversationBatchRow => ({ @@ -239,40 +240,40 @@ const toConversationBatchRow = (doc: ConversationBatchDoc): ConversationBatchRow }); const toEventEntryRow = (doc: EventEntryDoc): EventEntryRow => ({ - offset: doc.seq, dataJson: doc.dataJson, + offset: doc.seq, }); const toRunRow = (doc: RunDoc): RunRow => ({ - runId: doc.runId, - workflowName: doc.workflowName, - status: doc.status, - startedAt: doc.startedAt, - endedAt: doc.endedAt ?? null, - isError: doc.isError ?? null, durationMs: doc.durationMs ?? null, - inputJson: doc.inputJson ?? null, - resultJson: doc.resultJson ?? null, + endedAt: doc.endedAt ?? null, errorJson: doc.errorJson ?? null, + inputJson: doc.inputJson ?? null, + isError: doc.isError ?? null, + resultJson: doc.resultJson ?? null, + runId: doc.runId, + startedAt: doc.startedAt, + status: doc.status, traceCarrierJson: doc.traceCarrierJson ?? null, + workflowName: doc.workflowName, }); const toRunPointerRow = (doc: RunDoc): RunPointerRow => ({ - runId: doc.runId, - workflowName: doc.workflowName, - status: doc.status, - startedAt: doc.startedAt, - endedAt: doc.endedAt ?? null, durationMs: doc.durationMs ?? null, + endedAt: doc.endedAt ?? null, isError: doc.isError ?? null, + runId: doc.runId, + startedAt: doc.startedAt, + status: doc.status, + workflowName: doc.workflowName, }); const toAttachmentWire = (doc: AttachmentDoc): AttachmentWire => ({ attachment: { + digest: doc.digest, id: doc.attachmentId, mimeType: doc.mimeType, size: doc.size, - digest: doc.digest, ...(doc.filename === undefined ? {} : { filename: doc.filename }), }, bytes: doc.bytes, @@ -332,7 +333,9 @@ const parseSessionInstance = (sessionKey: string): string | undefined => { ) { return parsed[0]; } - } catch {} + } catch { + // JSON parse failure means the stored value is not an array + } return undefined; }; @@ -374,7 +377,7 @@ const parseSettledOutcome = (recordJson: string | undefined): SettledOutcome | u type ReadCtx = QueryCtx | MutationCtx; -const getSubmissionDoc = async ( +const getSubmissionDoc = ( ctx: ReadCtx, submissionId: string, ): Promise => @@ -383,7 +386,7 @@ const getSubmissionDoc = async ( .withIndex("by_submissionId", (q) => q.eq("submissionId", submissionId)) .unique(); -const getConversationStreamDoc = async ( +const getConversationStreamDoc = ( ctx: ReadCtx, path: string, ): Promise => @@ -416,7 +419,7 @@ const assertSubmissionAuthorization = async ( if (submission === undefined) { if (owned.length > 0) { throw new Error( - `[flue] Conversation stream \"${path}\" received submission-owned records without authorization.`, + `[flue] Conversation stream "${path}" received submission-owned records without authorization.`, ); } return; @@ -430,7 +433,7 @@ const assertSubmissionAuthorization = async ( ) ) { throw new Error( - `[flue] Conversation stream \"${path}\" record ownership does not match the authorized submission attempt.`, + `[flue] Conversation stream "${path}" record ownership does not match the authorized submission attempt.`, ); } @@ -438,7 +441,7 @@ const assertSubmissionAuthorization = async ( const stored = await getSubmissionDoc(ctx, submission.submissionId); if (stream === null || stored === null) { throw new Error( - `[flue] Submission attempt no longer owns work for agent instance \"${path}\".`, + `[flue] Submission attempt no longer owns work for agent instance "${path}".`, ); } @@ -463,7 +466,7 @@ const assertSubmissionAuthorization = async ( ) ) { throw new Error( - `[flue] Submission attempt no longer owns work for agent instance \"${path}\".`, + `[flue] Submission attempt no longer owns work for agent instance "${path}".`, ); } }; @@ -563,11 +566,11 @@ export const listPendingSubmissionSettlements = query({ export const replaceSubmissionAttempt = mutation({ args: { ...tokenArgs, - submissionId: v.string(), attemptId: v.string(), + leaseExpiresAt: v.optional(v.number()), nextAttemptId: v.string(), ownerId: v.optional(v.string()), - leaseExpiresAt: v.optional(v.number()), + submissionId: v.string(), }, handler: async (ctx, args) => { assertToken(args.token); @@ -584,10 +587,10 @@ export const replaceSubmissionAttempt = mutation({ } const now = Date.now(); await ctx.db.patch(submission._id, { + attemptCount: submission.attemptCount + 1, attemptId: args.nextAttemptId, recoveryRequestedAt: undefined, startedAt: now, - attemptCount: submission.attemptCount + 1, ...(args.ownerId === undefined ? { ownerId: undefined } : { ownerId: args.ownerId }), ...(args.leaseExpiresAt === undefined ? { leaseExpiresAt: submission.leaseExpiresAt } @@ -603,12 +606,12 @@ export const admitSubmission = mutation({ args: { ...tokenArgs, input: v.object({ - kind: submissionKind, - submissionId: v.string(), - sessionKey: v.string(), acceptedAt: v.number(), - inputJson: v.string(), chunksJson: v.optional(v.string()), + inputJson: v.string(), + kind: submissionKind, + sessionKey: v.string(), + submissionId: v.string(), traceCarrierJson: v.optional(v.string()), }), }, @@ -634,8 +637,8 @@ export const admitSubmission = mutation({ return { kind: "retained_receipt", receipt: { - submissionId: existing.submissionId, acceptedAt: existing.acceptedAt, + submissionId: existing.submissionId, }, }; } @@ -649,19 +652,19 @@ export const admitSubmission = mutation({ ) + 1; const now = Date.now(); const rowId = await ctx.db.insert("flueSubmissions", { - submissionId: args.input.submissionId, - sessionKey: args.input.sessionKey, - sequence: nextSequence, - kind: args.input.kind, - inputJson: args.input.inputJson, - chunksJson: args.input.chunksJson ?? "[]", - traceCarrierJson: args.input.traceCarrierJson, - status: "queued", acceptedAt: args.input.acceptedAt, attemptCount: 0, - maxRetry: DURABILITY_DEFAULT_MAX_ATTEMPTS, - timeoutAt: 0, + chunksJson: args.input.chunksJson ?? "[]", + inputJson: args.input.inputJson, + kind: args.input.kind, leaseExpiresAt: 0, + maxRetry: DURABILITY_DEFAULT_MAX_ATTEMPTS, + sequence: nextSequence, + sessionKey: args.input.sessionKey, + status: "queued", + submissionId: args.input.submissionId, + timeoutAt: 0, + traceCarrierJson: args.input.traceCarrierJson, updatedAt: now, }); const created = await ctx.db.get(rowId); @@ -697,10 +700,10 @@ export const markSubmissionCanonicalReady = mutation({ export const claimSubmission = mutation({ args: { ...tokenArgs, - submissionId: v.string(), attemptId: v.string(), - ownerId: v.string(), leaseExpiresAt: v.number(), + ownerId: v.string(), + submissionId: v.string(), }, handler: async (ctx, args) => { assertToken(args.token); @@ -726,20 +729,20 @@ export const claimSubmission = mutation({ } const now = Date.now(); await ctx.db.patch(submission._id, { - status: "running", - attemptId: args.attemptId, - startedAt: now, attemptCount: submission.attemptCount + 1, - ownerId: args.ownerId, + attemptId: args.attemptId, leaseExpiresAt: args.leaseExpiresAt, - timeoutAt: - submission.timeoutAt > 0 - ? submission.timeoutAt - : now + DURABILITY_DEFAULT_TIMEOUT_MS, maxRetry: submission.maxRetry > 0 ? submission.maxRetry : DURABILITY_DEFAULT_MAX_ATTEMPTS, + ownerId: args.ownerId, + startedAt: now, + status: "running", + timeoutAt: + submission.timeoutAt > 0 + ? submission.timeoutAt + : now + DURABILITY_DEFAULT_TIMEOUT_MS, updatedAt: now, }); const updated = await ctx.db.get(submission._id); @@ -750,9 +753,9 @@ export const claimSubmission = mutation({ export const markSubmissionInputApplied = mutation({ args: { ...tokenArgs, - submissionId: v.string(), attemptId: v.string(), maxRetry: v.optional(v.number()), + submissionId: v.string(), timeoutAt: v.optional(v.number()), }, handler: async (ctx, args) => { @@ -785,7 +788,7 @@ export const markSubmissionInputApplied = mutation({ }); export const requestSubmissionRecovery = mutation({ - args: { ...tokenArgs, submissionId: v.string(), attemptId: v.string() }, + args: { ...tokenArgs, attemptId: v.string(), submissionId: v.string() }, handler: async (ctx, args) => { assertToken(args.token); const submission = await ctx.db @@ -827,7 +830,7 @@ export const requestSessionAbort = mutation({ }); export const requeueSubmissionBeforeInputApplied = mutation({ - args: { ...tokenArgs, submissionId: v.string(), attemptId: v.string() }, + args: { ...tokenArgs, attemptId: v.string(), submissionId: v.string() }, handler: async (ctx, args) => { assertToken(args.token); const submission = await ctx.db @@ -843,12 +846,12 @@ export const requeueSubmissionBeforeInputApplied = mutation({ return false; } await ctx.db.patch(submission._id, { - status: "queued", attemptId: undefined, + leaseExpiresAt: 0, + ownerId: undefined, recoveryRequestedAt: undefined, startedAt: undefined, - ownerId: undefined, - leaseExpiresAt: 0, + status: "queued", updatedAt: Date.now(), }); return true; @@ -858,10 +861,10 @@ export const requeueSubmissionBeforeInputApplied = mutation({ export const reserveSubmissionSettlement = mutation({ args: { ...tokenArgs, - submissionId: v.string(), attemptId: v.string(), recordId: v.string(), recordJson: v.string(), + submissionId: v.string(), }, handler: async (ctx, args) => { assertToken(args.token); @@ -887,9 +890,9 @@ export const reserveSubmissionSettlement = mutation({ return null; } await ctx.db.patch(submission._id, { - status: "terminalizing", settlementRecordId: args.recordId, settlementRecordJson: args.recordJson, + status: "terminalizing", updatedAt: Date.now(), }); const updated = await ctx.db.get(submission._id); @@ -898,7 +901,7 @@ export const reserveSubmissionSettlement = mutation({ }); export const finalizeSubmissionSettlement = mutation({ - args: { ...tokenArgs, submissionId: v.string(), attemptId: v.string(), recordId: v.string() }, + args: { ...tokenArgs, attemptId: v.string(), recordId: v.string(), submissionId: v.string() }, handler: async (ctx, args) => { assertToken(args.token); const submission = await ctx.db @@ -914,11 +917,11 @@ export const finalizeSubmissionSettlement = mutation({ return false; } await ctx.db.patch(submission._id, { - status: "settled", + leaseExpiresAt: 0, + ownerId: undefined, settledOutcome: parseSettledOutcome(submission.settlementRecordJson) ?? "completed", - ownerId: undefined, - leaseExpiresAt: 0, + status: "settled", updatedAt: Date.now(), }); return true; @@ -928,10 +931,10 @@ export const finalizeSubmissionSettlement = mutation({ export const settleSubmission = mutation({ args: { ...tokenArgs, - submissionId: v.string(), attemptId: v.string(), - outcome: v.union(v.literal("completed"), v.literal("failed")), errorJson: v.optional(v.string()), + outcome: v.union(v.literal("completed"), v.literal("failed")), + submissionId: v.string(), }, handler: async (ctx, args) => { assertToken(args.token); @@ -947,11 +950,11 @@ export const settleSubmission = mutation({ return false; } await ctx.db.patch(submission._id, { - status: "settled", - settledOutcome: args.outcome, error: args.errorJson, - ownerId: undefined, leaseExpiresAt: 0, + ownerId: undefined, + settledOutcome: args.outcome, + status: "settled", updatedAt: Date.now(), }); return true; @@ -959,7 +962,7 @@ export const settleSubmission = mutation({ }); export const insertAttemptMarker = mutation({ - args: { ...tokenArgs, submissionId: v.string(), attemptId: v.string() }, + args: { ...tokenArgs, attemptId: v.string(), submissionId: v.string() }, handler: async (ctx, args) => { assertToken(args.token); const existing = await ctx.db @@ -972,9 +975,9 @@ export const insertAttemptMarker = mutation({ return toAttemptMarkerRow(existing); } const rowId = await ctx.db.insert("flueAttemptMarkers", { - submissionId: args.submissionId, attemptId: args.attemptId, createdAt: Date.now(), + submissionId: args.submissionId, }); const created = await ctx.db.get(rowId); if (created === null) { @@ -985,7 +988,7 @@ export const insertAttemptMarker = mutation({ }); export const deleteAttemptMarker = mutation({ - args: { ...tokenArgs, submissionId: v.string(), attemptId: v.string() }, + args: { ...tokenArgs, attemptId: v.string(), submissionId: v.string() }, handler: async (ctx, args) => { assertToken(args.token); const existing = await ctx.db @@ -1051,7 +1054,7 @@ export const listExpiredSubmissions = query({ }); export const createConversationStream = mutation({ - args: { ...tokenArgs, path: v.string(), identity: conversationIdentity }, + args: { ...tokenArgs, identity: conversationIdentity, path: v.string() }, handler: async (ctx, args) => { assertToken(args.token); const existing = await ctx.db @@ -1062,20 +1065,20 @@ export const createConversationStream = mutation({ if (existing !== null) { if (existing.identityJson !== identityJson) { throw new Error( - `[flue] Conversation stream \"${args.path}\" identity conflicts with the existing stream.`, + `[flue] Conversation stream "${args.path}" identity conflicts with the existing stream.`, ); } return; } await ctx.db.insert("flueConversationStreams", { - path: args.path, - identityJson, - incarnation: crypto.randomUUID(), - producerEpoch: 0, - nextProducerSequence: 0, - nextOffset: 0, closed: false, createdAt: Date.now(), + identityJson, + incarnation: crypto.randomUUID(), + nextOffset: 0, + nextProducerSequence: 0, + path: args.path, + producerEpoch: 0, }); }, }); @@ -1089,20 +1092,20 @@ export const acquireConversationProducer = mutation({ .withIndex("by_path", (q) => q.eq("path", args.path)) .unique(); if (stream === null) { - throw new Error(`[flue] Conversation stream \"${args.path}\" does not exist.`); + throw new Error(`[flue] Conversation stream "${args.path}" does not exist.`); } const producerEpoch = stream.producerEpoch + 1; await ctx.db.patch(stream._id, { - producerId: args.producerId, - producerEpoch, nextProducerSequence: 0, + producerEpoch, + producerId: args.producerId, }); return { - producerId: args.producerId, - producerEpoch, incarnation: stream.incarnation, nextProducerSequence: 0, offset: `${stream.nextOffset - 1}`, + producerEpoch, + producerId: args.producerId, }; }, }); @@ -1110,22 +1113,22 @@ export const acquireConversationProducer = mutation({ export const appendConversationBatch = mutation({ args: { ...tokenArgs, - path: v.string(), - producerId: v.string(), - producerEpoch: v.number(), incarnation: v.string(), + path: v.string(), + producerEpoch: v.number(), + producerId: v.string(), producerSequence: v.number(), - submission: v.optional( - v.object({ submissionId: v.string(), attemptId: v.string() }), - ), recordsJson: v.string(), + submission: v.optional( + v.object({ attemptId: v.string(), submissionId: v.string() }), + ), }, handler: async (ctx, args): Promise => { assertToken(args.token); const records = safeJsonParse(args.recordsJson); if (records.length === 0) { throw new Error( - `[flue] Conversation stream \"${args.path}\" cannot append an empty canonical batch.`, + `[flue] Conversation stream "${args.path}" cannot append an empty canonical batch.`, ); } const stream = await ctx.db @@ -1133,7 +1136,7 @@ export const appendConversationBatch = mutation({ .withIndex("by_path", (q) => q.eq("path", args.path)) .unique(); if (stream === null) { - throw new Error(`[flue] Conversation stream \"${args.path}\" does not exist.`); + throw new Error(`[flue] Conversation stream "${args.path}" does not exist.`); } if ( stream.producerId !== args.producerId || @@ -1141,7 +1144,7 @@ export const appendConversationBatch = mutation({ stream.incarnation !== args.incarnation ) { throw new Error( - `[flue] Conversation stream \"${args.path}\" producer ownership is stale.`, + `[flue] Conversation stream "${args.path}" producer ownership is stale.`, ); } const existing = await ctx.db @@ -1160,39 +1163,39 @@ export const appendConversationBatch = mutation({ existing.attemptId === args.submission?.attemptId; if (!sameSubmission || existing.recordsJson !== args.recordsJson) { throw new Error( - `[flue] Conversation stream \"${args.path}\" producer sequence has conflicting content.`, + `[flue] Conversation stream "${args.path}" producer sequence has conflicting content.`, ); } - return { offset: existing.seq, appended: false }; + return { appended: false, offset: existing.seq }; } if (stream.nextProducerSequence !== args.producerSequence) { throw new Error( - `[flue] Conversation stream \"${args.path}\" producer sequence is not the next expected value.`, + `[flue] Conversation stream "${args.path}" producer sequence is not the next expected value.`, ); } await assertSubmissionAuthorization(ctx, args.path, args.submission, args.recordsJson); const seq = stream.nextOffset; await ctx.db.insert("flueConversationBatches", { + appendedAt: Date.now(), + attemptId: args.submission?.attemptId, path: args.path, - seq, - producerId: args.producerId, producerEpoch: args.producerEpoch, + producerId: args.producerId, producerSequence: args.producerSequence, recordsJson: args.recordsJson, + seq, submissionId: args.submission?.submissionId, - attemptId: args.submission?.attemptId, - appendedAt: Date.now(), }); await ctx.db.patch(stream._id, { nextOffset: seq + 1, nextProducerSequence: stream.nextProducerSequence + 1, }); - return { offset: seq, appended: true }; + return { appended: true, offset: seq }; }, }); export const readConversationBatches = query({ - args: { ...tokenArgs, path: v.string(), afterOffset: v.number(), limit: v.number() }, + args: { ...tokenArgs, afterOffset: v.number(), limit: v.number(), path: v.string() }, handler: async (ctx, args) => { assertToken(args.token); const stream = await ctx.db @@ -1267,16 +1270,16 @@ export const createEventStream = mutation({ return; } await ctx.db.insert("flueEventStreams", { - path: args.path, - nextSeq: 0, closed: false, createdAt: Date.now(), + nextSeq: 0, + path: args.path, }); }, }); export const appendEvent = mutation({ - args: { ...tokenArgs, path: v.string(), dataJson: v.string() }, + args: { ...tokenArgs, dataJson: v.string(), path: v.string() }, handler: async (ctx, args): Promise => { assertToken(args.token); const stream = await ctx.db @@ -1284,25 +1287,25 @@ export const appendEvent = mutation({ .withIndex("by_path", (q) => q.eq("path", args.path)) .unique(); if (stream === null) { - throw new Error(`[flue] Event stream \"${args.path}\" does not exist.`); + throw new Error(`[flue] Event stream "${args.path}" does not exist.`); } if (stream.closed) { - throw new Error(`[flue] Event stream \"${args.path}\" is closed.`); + throw new Error(`[flue] Event stream "${args.path}" is closed.`); } const seq = stream.nextSeq; await ctx.db.insert("flueEventEntries", { + appendedAt: Date.now(), + dataJson: args.dataJson, path: args.path, seq, - dataJson: args.dataJson, - appendedAt: Date.now(), }); await ctx.db.patch(stream._id, { nextSeq: seq + 1 }); - return { offset: seq, appended: true }; + return { appended: true, offset: seq }; }, }); export const appendEventOnce = mutation({ - args: { ...tokenArgs, path: v.string(), key: v.string(), dataJson: v.string() }, + args: { ...tokenArgs, dataJson: v.string(), key: v.string(), path: v.string() }, handler: async (ctx, args): Promise => { assertToken(args.token); const stream = await ctx.db @@ -1310,10 +1313,10 @@ export const appendEventOnce = mutation({ .withIndex("by_path", (q) => q.eq("path", args.path)) .unique(); if (stream === null) { - throw new Error(`[flue] Event stream \"${args.path}\" does not exist.`); + throw new Error(`[flue] Event stream "${args.path}" does not exist.`); } if (stream.closed) { - throw new Error(`[flue] Event stream \"${args.path}\" is closed.`); + throw new Error(`[flue] Event stream "${args.path}" is closed.`); } const existing = await ctx.db .query("flueEventEntries") @@ -1324,26 +1327,26 @@ export const appendEventOnce = mutation({ if (existing !== null) { if (existing.dataJson !== args.dataJson) { throw new Error( - `[flue] Event key \"${args.key}\" already has a conflicting payload.`, + `[flue] Event key "${args.key}" already has a conflicting payload.`, ); } - return { offset: existing.seq, appended: false }; + return { appended: false, offset: existing.seq }; } const seq = stream.nextSeq; await ctx.db.insert("flueEventEntries", { + appendedAt: Date.now(), + dataJson: args.dataJson, + onceKey: args.key, path: args.path, seq, - onceKey: args.key, - dataJson: args.dataJson, - appendedAt: Date.now(), }); await ctx.db.patch(stream._id, { nextSeq: seq + 1 }); - return { offset: seq, appended: true }; + return { appended: true, offset: seq }; }, }); export const readEvents = query({ - args: { ...tokenArgs, path: v.string(), afterOffset: v.number(), limit: v.number() }, + args: { ...tokenArgs, afterOffset: v.number(), limit: v.number(), path: v.string() }, handler: async (ctx, args) => { assertToken(args.token); const stream = await ctx.db @@ -1352,10 +1355,10 @@ export const readEvents = query({ .unique(); if (stream === null) { return { + closed: false, events: [] as EventEntryRow[], nextOffset: -1, upToDate: true, - closed: false, }; } const rows = (await ctx.db @@ -1366,11 +1369,11 @@ export const readEvents = query({ .sort((left, right) => left.seq - right.seq); const page = rows.slice(0, args.limit); return { + closed: stream.closed, events: page.map(toEventEntryRow), nextOffset: page.length > 0 ? page[page.length - 1]!.seq : args.afterOffset, upToDate: rows.length <= args.limit, - closed: stream.closed, }; }, }); @@ -1399,18 +1402,18 @@ export const getEventStreamMeta = query({ .unique(); return stream === null ? null - : { nextOffset: stream.nextSeq - 1, closed: stream.closed }; + : { closed: stream.closed, nextOffset: stream.nextSeq - 1 }; }, }); export const createRun = mutation({ args: { ...tokenArgs, - runId: v.string(), - workflowName: v.string(), - startedAt: v.string(), inputJson: v.string(), + runId: v.string(), + startedAt: v.string(), traceCarrierJson: v.optional(v.string()), + workflowName: v.string(), }, handler: async (ctx, args) => { assertToken(args.token); @@ -1422,12 +1425,12 @@ export const createRun = mutation({ return; } await ctx.db.insert("flueRuns", { - runId: args.runId, - workflowName: args.workflowName, - status: "active", - startedAt: args.startedAt, inputJson: args.inputJson, + runId: args.runId, + startedAt: args.startedAt, + status: "active", traceCarrierJson: args.traceCarrierJson, + workflowName: args.workflowName, }); }, }); @@ -1435,12 +1438,12 @@ export const createRun = mutation({ export const endRun = mutation({ args: { ...tokenArgs, - runId: v.string(), - endedAt: v.string(), - isError: v.boolean(), durationMs: v.number(), - resultJson: v.optional(v.string()), + endedAt: v.string(), errorJson: v.optional(v.string()), + isError: v.boolean(), + resultJson: v.optional(v.string()), + runId: v.string(), }, handler: async (ctx, args) => { assertToken(args.token); @@ -1452,12 +1455,12 @@ export const endRun = mutation({ return; } await ctx.db.patch(run._id, { - status: args.isError ? "errored" : "completed", - endedAt: args.endedAt, - isError: args.isError, durationMs: args.durationMs, - resultJson: args.resultJson, + endedAt: args.endedAt, errorJson: args.errorJson, + isError: args.isError, + resultJson: args.resultJson, + status: args.isError ? "errored" : "completed", }); }, }); @@ -1491,10 +1494,10 @@ export const lookupRun = query({ export const listRuns = query({ args: { ...tokenArgs, + cursor: v.optional(v.object({ runId: v.string(), startedAt: v.string() })), + limit: v.number(), status: v.optional(runStatus), workflowName: v.optional(v.string()), - limit: v.number(), - cursor: v.optional(v.object({ startedAt: v.string(), runId: v.string() })), }, handler: async (ctx, args) => { assertToken(args.token); @@ -1518,8 +1521,8 @@ export const listRuns = query({ }); const page = rows.slice(0, args.limit + 1); return { - rows: page.slice(0, args.limit), hasMore: page.length > args.limit, + rows: page.slice(0, args.limit), }; }, }); @@ -1527,10 +1530,10 @@ export const listRuns = query({ export const putAttachment = mutation({ args: { ...tokenArgs, - streamPath: v.string(), - conversationId: v.string(), attachment: attachmentRef, bytes: v.bytes(), + conversationId: v.string(), + streamPath: v.string(), }, handler: async (ctx, args) => { assertToken(args.token); @@ -1544,15 +1547,15 @@ export const putAttachment = mutation({ return sameAttachment(existing, args) ? "existing" : "conflict"; } await ctx.db.insert("flueAttachments", { - streamPath: args.streamPath, - conversationId: args.conversationId, attachmentId: args.attachment.id, - mimeType: args.attachment.mimeType, - size: args.attachment.size, + bytes: args.bytes, + conversationId: args.conversationId, + createdAt: Date.now(), digest: args.attachment.digest, filename: args.attachment.filename, - bytes: args.bytes, - createdAt: Date.now(), + mimeType: args.attachment.mimeType, + size: args.attachment.size, + streamPath: args.streamPath, }); return "inserted"; }, @@ -1561,9 +1564,9 @@ export const putAttachment = mutation({ export const getAttachment = query({ args: { ...tokenArgs, - streamPath: v.string(), - conversationId: v.string(), attachmentId: v.string(), + conversationId: v.string(), + streamPath: v.string(), }, handler: async (ctx, args) => { assertToken(args.token); diff --git a/packages/backend/convex/healthCheck.ts b/packages/backend/convex/healthCheck.ts index b38d944..7f9919e 100644 --- a/packages/backend/convex/healthCheck.ts +++ b/packages/backend/convex/healthCheck.ts @@ -1,7 +1,7 @@ import { query } from "./_generated/server"; export const get = query({ - handler: async () => { - return "OK"; - }, + handler: () => + "OK" + , }); diff --git a/packages/backend/convex/organizations.test.ts b/packages/backend/convex/organizations.test.ts index a7b9fd6..a58d569 100644 --- a/packages/backend/convex/organizations.test.ts +++ b/packages/backend/convex/organizations.test.ts @@ -23,7 +23,7 @@ const ID_B = "https://convex.test|user-b"; const identityA = { tokenIdentifier: ID_A }; const identityB = { tokenIdentifier: ID_B }; -const newTest = () => convexTest({ schema, modules }); +const newTest = () => convexTest({ modules, schema }); describe("organizations", () => { test("first ensure creates one organization and owner membership", async () => { diff --git a/packages/backend/convex/projects.ts b/packages/backend/convex/projects.ts index 7e868cc..9d320d0 100644 --- a/packages/backend/convex/projects.ts +++ b/packages/backend/convex/projects.ts @@ -1,8 +1,10 @@ import { decodePublicGitImportResult, preparePublicGitSource, - type ProjectImportOutcome, - type ProjectView, +} from "@code/primitives/project"; +import type { + ProjectImportOutcome, + ProjectView, } from "@code/primitives/project"; import { ConvexError, v } from "convex/values"; import { Effect } from "effect"; @@ -54,18 +56,11 @@ const toProjectView = async ( export const persistPublicGitImport = internalMutation({ args: { - userId: v.string(), - source: v.object({ - host: v.string(), - projectName: v.string(), - repositoryPath: v.string(), - normalizedUrl: v.string(), - url: v.string(), - }), remote: v.object({ defaultBranch: v.optional(v.string()), documents: v.array( v.object({ + content: v.string(), kind: v.union( v.literal("readme"), v.literal("agents"), @@ -75,11 +70,18 @@ export const persistPublicGitImport = internalMutation({ v.literal("tech") ), path: v.string(), - content: v.string(), }) ), - warnings: v.array(v.object({ path: v.string(), message: v.string() })), + warnings: v.array(v.object({ message: v.string(), path: v.string() })), }), + source: v.object({ + host: v.string(), + normalizedUrl: v.string(), + projectName: v.string(), + repositoryPath: v.string(), + url: v.string(), + }), + userId: v.string(), }, handler: async (ctx, args): Promise => { const organization = await ctx.db @@ -106,9 +108,9 @@ export const persistPublicGitImport = internalMutation({ await ctx.db.patch(projectId, { defaultBranch: args.remote.defaultBranch, name: args.source.projectName, + repositoryPath: args.source.repositoryPath, sourceHost: args.source.host, sourceUrl: args.source.url, - repositoryPath: args.source.repositoryPath, updatedAt: timestamp, }); const oldDocuments = await ctx.db diff --git a/packages/backend/convex/publicGit.ts b/packages/backend/convex/publicGit.ts index a978a3f..391b8ff 100644 --- a/packages/backend/convex/publicGit.ts +++ b/packages/backend/convex/publicGit.ts @@ -1,11 +1,5 @@ -import { - CONTEXT_KINDS, - contextPathForKind, - MAX_CONTEXT_DOCUMENT_CHARACTERS, - type PreparedPublicGitSource, - type PublicGitImportResult, - type RepositoryContextDocument, -} from "@code/primitives/project"; +import { CONTEXT_KINDS, contextPathForKind, MAX_CONTEXT_DOCUMENT_CHARACTERS } from '@code/primitives/project'; +import type { PreparedPublicGitSource, PublicGitImportResult, RepositoryContextDocument } from '@code/primitives/project'; const GITHUB_HOST = "github.com"; const GITEA_HOST = "git.openputer.com"; diff --git a/packages/backend/convex/schema.ts b/packages/backend/convex/schema.ts index ed489d8..b5d7031 100644 --- a/packages/backend/convex/schema.ts +++ b/packages/backend/convex/schema.ts @@ -1,32 +1,59 @@ import { defineSchema, defineTable } from "convex/server"; import { v } from "convex/values"; +/* eslint-disable sort-keys */ + +const attemptClassification = v.union( + v.literal("Succeeded"), + v.literal("RetryableFailure"), + v.literal("NeedsInput"), + v.literal("Blocked"), + v.literal("VerificationFailed"), + v.literal("BudgetExhausted"), + v.literal("Cancelled"), + v.literal("PermanentFailure") +); +const workStatus = v.union( + v.literal("proposed"), + v.literal("defining"), + v.literal("awaiting-definition-approval"), + v.literal("designing"), + v.literal("awaiting-design-approval"), + v.literal("ready"), + v.literal("executing"), + v.literal("needs-input"), + v.literal("blocked"), + v.literal("completed"), + v.literal("failed"), + v.literal("cancelled") +); + export default defineSchema({ organizations: defineTable({ - name: v.string(), - kind: v.union(v.literal("personal"), v.literal("team")), - createdBy: v.string(), createdAt: v.number(), + createdBy: v.string(), + kind: v.union(v.literal("personal"), v.literal("team")), + name: v.string(), }).index("by_createdBy_and_kind", ["createdBy", "kind"]), organizationMembers: defineTable({ - organizationId: v.id("organizations"), - userId: v.string(), - role: v.union(v.literal("owner"), v.literal("member")), createdAt: v.number(), + organizationId: v.id("organizations"), + role: v.union(v.literal("owner"), v.literal("member")), + userId: v.string(), }) .index("by_userId", ["userId"]) .index("by_organizationId", ["organizationId"]) .index("by_organizationId_and_userId", ["organizationId", "userId"]), projects: defineTable({ - organizationId: v.id("organizations"), - name: v.string(), - description: v.optional(v.string()), - sourceUrl: v.string(), - normalizedSourceUrl: v.string(), - sourceHost: v.string(), - repositoryPath: v.string(), - defaultBranch: v.optional(v.string()), createdAt: v.number(), + defaultBranch: v.optional(v.string()), + description: v.optional(v.string()), + name: v.string(), + normalizedSourceUrl: v.string(), + organizationId: v.id("organizations"), + repositoryPath: v.string(), + sourceHost: v.string(), + sourceUrl: v.string(), updatedAt: v.number(), }) .index("by_organizationId_and_createdAt", ["organizationId", "createdAt"]) @@ -35,7 +62,8 @@ export default defineSchema({ "normalizedSourceUrl", ]), projectContextDocuments: defineTable({ - projectId: v.id("projects"), + content: v.string(), + createdAt: v.number(), kind: v.union( v.literal("readme"), v.literal("agents"), @@ -44,20 +72,25 @@ export default defineSchema({ v.literal("design"), v.literal("tech") ), - path: v.string(), - content: v.string(), origin: v.literal("repository"), + path: v.string(), + projectId: v.id("projects"), sourceUrl: v.string(), - createdAt: v.number(), updatedAt: v.number(), }).index("by_projectId_and_path", ["projectId", "path"]), conversations: defineTable({ - organizationId: v.id("organizations"), createdAt: v.number(), + organizationId: v.id("organizations"), }).index("by_organizationId", ["organizationId"]), conversationTurns: defineTable({ - conversationId: v.id("conversations"), + attemptNumber: v.optional(v.number()), clientRequestId: v.string(), + completedAt: v.optional(v.number()), + conversationId: v.id("conversations"), + createdAt: v.number(), + error: v.optional(v.string()), + leaseExpiresAt: v.optional(v.number()), + leaseOwner: v.optional(v.string()), status: v.union( v.literal("queued"), v.literal("processing"), @@ -65,100 +98,86 @@ export default defineSchema({ v.literal("failed") ), submissionId: v.optional(v.string()), - error: v.optional(v.string()), - createdAt: v.number(), - completedAt: v.optional(v.number()), - }).index("by_conversationId_and_clientRequestId", [ - "conversationId", - "clientRequestId", - ]), + }) + .index("by_conversationId_and_clientRequestId", [ + "conversationId", + "clientRequestId", + ]) + .index("by_status_and_leaseExpiresAt", ["status", "leaseExpiresAt"]), conversationMessages: defineTable({ - conversationId: v.id("conversations"), - turnId: v.id("conversationTurns"), - role: v.union(v.literal("user"), v.literal("assistant")), content: v.string(), - ordinal: v.number(), + conversationId: v.id("conversations"), createdAt: v.number(), + ordinal: v.number(), + role: v.union(v.literal("user"), v.literal("assistant")), + turnId: v.id("conversationTurns"), }) .index("by_conversationId_and_ordinal", ["conversationId", "ordinal"]) .index("by_turnId_and_role", ["turnId", "role"]), conversationAttachments: defineTable({ - messageId: v.id("conversationMessages"), - storageId: v.id("_storage"), - filename: v.optional(v.string()), - mimeType: v.string(), createdAt: v.number(), + filename: v.optional(v.string()), + messageId: v.id("conversationMessages"), + mimeType: v.string(), + storageId: v.id("_storage"), }).index("by_messageId", ["messageId"]), signals: defineTable({ - organizationId: v.id("organizations"), - projectId: v.id("projects"), conversationId: v.id("conversations"), - sourceKey: v.string(), - title: v.string(), - summary: v.string(), - desiredOutcome: v.string(), - processedByAgentName: v.string(), - processedByAgentInstanceId: v.string(), createdAt: v.number(), + desiredOutcome: v.string(), + organizationId: v.id("organizations"), + processedByAgentInstanceId: v.string(), + processedByAgentName: v.string(), + projectId: v.id("projects"), + sourceKey: v.string(), + summary: v.string(), + title: v.string(), }) .index("by_organization_and_createdAt", ["organizationId", "createdAt"]) .index("by_organization_and_sourceKey", ["organizationId", "sourceKey"]) .index("by_project_and_createdAt", ["projectId", "createdAt"]), signalConstraints: defineTable({ - signalId: v.id("signals"), ordinal: v.number(), + signalId: v.id("signals"), value: v.string(), }).index("by_signalId_and_ordinal", ["signalId", "ordinal"]), signalSources: defineTable({ - signalId: v.id("signals"), messageId: v.id("conversationMessages"), ordinal: v.number(), rawTextSnapshot: v.string(), + signalId: v.id("signals"), sourceCreatedAt: v.number(), }) .index("by_signalId_and_ordinal", ["signalId", "ordinal"]) .index("by_messageId", ["messageId"]), works: defineTable({ + createdAt: v.number(), + definitionApprovalVersion: v.optional(v.number()), + definitionVersion: v.optional(v.number()), + designApprovalVersion: v.optional(v.number()), + designVersion: v.optional(v.number()), + objective: v.string(), organizationId: v.id("organizations"), projectId: v.id("projects"), + status: workStatus, title: v.string(), - objective: v.string(), - status: v.union( - v.literal("proposed"), - v.literal("defining"), - v.literal("awaiting-definition-approval"), - v.literal("designing"), - v.literal("awaiting-design-approval"), - v.literal("ready"), - v.literal("executing"), - v.literal("needs-input"), - v.literal("blocked"), - v.literal("completed"), - v.literal("failed"), - v.literal("cancelled") - ), - definitionVersion: v.optional(v.number()), - definitionApprovalVersion: v.optional(v.number()), - designVersion: v.optional(v.number()), - designApprovalVersion: v.optional(v.number()), - createdAt: v.number(), updatedAt: v.number(), }) .index("by_project_and_createdAt", ["projectId", "createdAt"]) .index("by_organization_and_createdAt", ["organizationId", "createdAt"]), signalWorkAttachments: defineTable({ + createdAt: v.number(), signalId: v.id("signals"), workId: v.id("works"), - createdAt: v.number(), }) .index("by_signal", ["signalId"]) .index("by_work", ["workId"]) .index("by_signal_and_work", ["signalId", "workId"]), workEvents: defineTable({ - workId: v.id("works"), - signalId: v.optional(v.id("signals")), + createdAt: v.number(), + idempotencyKey: v.string(), kind: v.union( v.literal("work.proposed"), v.literal("signal.attached"), @@ -167,6 +186,7 @@ export default defineSchema({ v.literal("definition.revised"), v.literal("definition.approved"), v.literal("definition.invalidated"), + v.literal("question.created"), v.literal("question.answered"), v.literal("question.withdrawn"), v.literal("design.requested"), @@ -174,24 +194,33 @@ export default defineSchema({ v.literal("design.revised"), v.literal("design.approved"), v.literal("design.invalidated"), + v.literal("planner.failed"), + v.literal("slice.started"), + v.literal("slice.completed"), + v.literal("slice.ready"), v.literal("run.started"), + v.literal("run.completed"), v.literal("run.cancelled"), v.literal("attempt.claimed"), v.literal("attempt.event"), v.literal("attempt.completed"), - v.literal("attempt.reconciled") + v.literal("attempt.reconciled"), + v.literal("resolver.decided"), + v.literal("artifact.recorded"), + v.literal("delivery.recorded"), + v.literal("delivery.updated") ), - referenceId: v.optional(v.string()), payloadJson: v.optional(v.string()), - idempotencyKey: v.string(), - createdAt: v.number(), + referenceId: v.optional(v.string()), + signalId: v.optional(v.id("signals")), + workId: v.id("works"), }) .index("by_work_and_createdAt", ["workId", "createdAt"]) .index("by_work_and_idempotencyKey", ["workId", "idempotencyKey"]), workDefinitions: defineTable({ - workId: v.id("works"), - version: v.number(), + createdAt: v.number(), + createdBy: v.string(), payloadJson: v.string(), risk: v.union(v.literal("low"), v.literal("medium"), v.literal("high")), status: v.union( @@ -199,42 +228,55 @@ export default defineSchema({ v.literal("current"), v.literal("superseded") ), - createdBy: v.string(), - createdAt: v.number(), + version: v.number(), + workId: v.id("works"), }) .index("by_work_and_version", ["workId", "version"]) .index("by_work_and_status", ["workId", "status"]), workQuestions: defineTable({ - workId: v.id("works"), - definitionVersion: v.number(), - questionId: v.string(), - prompt: v.string(), - impact: v.union(v.literal("low"), v.literal("medium"), v.literal("high")), - recommendation: v.optional(v.string()), alternativesJson: v.string(), + answer: v.optional(v.string()), + createdAt: v.number(), + definitionVersion: v.number(), + impact: v.union(v.literal("low"), v.literal("medium"), v.literal("high")), + prompt: v.string(), + questionId: v.string(), + recommendation: v.optional(v.string()), status: v.union( v.literal("open"), v.literal("answered"), v.literal("withdrawn") ), - answer: v.optional(v.string()), - createdAt: v.number(), - }).index("by_work_and_definitionVersion", ["workId", "definitionVersion"]), + workId: v.id("works"), + }) + .index("by_workId_and_definitionVersion", ["workId", "definitionVersion"]) + .index("by_workId_and_definitionVersion_and_questionId", [ + "workId", + "definitionVersion", + "questionId", + ]), workApprovals: defineTable({ - workId: v.id("works"), - kind: v.union(v.literal("definition"), v.literal("design")), + approvedAt: v.number(), + approvedBy: v.string(), definitionVersion: v.number(), designVersion: v.optional(v.number()), - approvedBy: v.string(), - approvedAt: v.number(), + kind: v.union(v.literal("definition"), v.literal("design")), status: v.union(v.literal("active"), v.literal("invalidated")), - }).index("by_work_and_kind", ["workId", "kind"]), + workId: v.id("works"), + }) + .index("by_workId_and_kind", ["workId", "kind"]) + .index("by_workId_and_kind_and_definitionVersion_and_designVersion", [ + "workId", + "kind", + "definitionVersion", + "designVersion", + ]), designPackets: defineTable({ - workId: v.id("works"), - version: v.number(), + createdAt: v.number(), + createdBy: v.string(), definitionVersion: v.number(), payloadJson: v.string(), status: v.union( @@ -242,19 +284,18 @@ export default defineSchema({ v.literal("current"), v.literal("superseded") ), - createdBy: v.string(), - createdAt: v.number(), + version: v.number(), + workId: v.id("works"), }).index("by_work_and_version", ["workId", "version"]), workSlices: defineTable({ - workId: v.id("works"), + createdAt: v.optional(v.number()), designVersion: v.number(), - sliceId: v.string(), - ordinal: v.number(), - title: v.string(), objective: v.string(), observableBehavior: v.string(), + ordinal: v.number(), payloadJson: v.string(), + sliceId: v.string(), status: v.union( v.literal("planned"), v.literal("ready"), @@ -262,17 +303,22 @@ export default defineSchema({ v.literal("completed"), v.literal("blocked") ), - }).index("by_work_and_designVersion", ["workId", "designVersion"]), + title: v.string(), + workId: v.id("works"), + }) + .index("by_workId_and_designVersion", ["workId", "designVersion"]) + .index("by_workId_and_designVersion_and_sliceId", [ + "workId", + "designVersion", + "sliceId", + ]), workRuns: defineTable({ - workId: v.id("works"), - sliceId: v.optional(v.string()), - status: v.union( - v.literal("ready"), - v.literal("running"), - v.literal("terminal"), - v.literal("cancelled") - ), + createdAt: v.number(), + designVersion: v.optional(v.number()), + endedAt: v.optional(v.number()), + kitId: v.string(), + kitVersion: v.string(), scenario: v.union( v.literal("success"), v.literal("transient-failure-then-success"), @@ -280,42 +326,140 @@ export default defineSchema({ v.literal("permanent-failure"), v.literal("cancelled") ), - kitId: v.string(), - kitVersion: v.string(), - createdAt: v.number(), + sliceId: v.optional(v.string()), + sliceRowId: v.optional(v.id("workSlices")), startedAt: v.optional(v.number()), - endedAt: v.optional(v.number()), - terminalClassification: v.optional(v.string()), + status: v.union( + v.literal("ready"), + v.literal("running"), + v.literal("terminal"), + v.literal("cancelled") + ), + terminalClassification: v.optional(attemptClassification), terminalSummary: v.optional(v.string()), + workId: v.id("works"), }).index("by_work_and_createdAt", ["workId", "createdAt"]), workAttempts: defineTable({ - runId: v.id("workRuns"), - workId: v.id("works"), + classification: v.optional(attemptClassification), + endedAt: v.optional(v.number()), + leaseExpiresAt: v.optional(v.number()), + leaseOwner: v.optional(v.string()), number: v.number(), + runId: v.id("workRuns"), + startedAt: v.optional(v.number()), status: v.union( v.literal("queued"), v.literal("claimed"), v.literal("running"), v.literal("terminal") ), - leaseOwner: v.optional(v.string()), - leaseExpiresAt: v.optional(v.number()), - startedAt: v.optional(v.number()), - endedAt: v.optional(v.number()), - classification: v.optional(v.string()), summary: v.optional(v.string()), - }).index("by_run_and_number", ["runId", "number"]), + workId: v.id("works"), + }) + .index("by_runId_and_number", ["runId", "number"]) + .index("by_status_and_leaseExpiresAt", ["status", "leaseExpiresAt"]), workAttemptEvents: defineTable({ attemptId: v.id("workAttempts"), - sequence: v.number(), kind: v.string(), message: v.string(), metadataJson: v.string(), occurredAt: v.number(), + sequence: v.number(), }).index("by_attempt_and_sequence", ["attemptId", "sequence"]), + resolverDecisions: defineTable({ + attemptId: v.id("workAttempts"), + attemptNumber: v.number(), + classification: attemptClassification, + createdAt: v.number(), + decision: v.union(v.literal("retry"), v.literal("terminal")), + resultingWorkStatus: v.optional(workStatus), + runId: v.id("workRuns"), + summary: v.string(), + workId: v.id("works"), + }) + .index("by_runId_and_attemptNumber", ["runId", "attemptNumber"]) + .index("by_attemptId", ["attemptId"]), + + workArtifacts: defineTable({ + attemptId: v.optional(v.id("workAttempts")), + contentHash: v.optional(v.string()), + createdAt: v.number(), + designVersion: v.optional(v.number()), + environmentId: v.optional(v.string()), + idempotencyKey: v.string(), + kind: v.union( + v.literal("definition"), + v.literal("design"), + v.literal("diff"), + v.literal("test-report"), + v.literal("verification-report"), + v.literal("runtime-log"), + v.literal("screenshot"), + v.literal("video"), + v.literal("commit"), + v.literal("branch"), + v.literal("pull-request"), + v.literal("preview"), + v.literal("deployment"), + v.literal("other") + ), + metadataJson: v.string(), + organizationId: v.id("organizations"), + producer: v.string(), + projectId: v.id("projects"), + provenanceJson: v.string(), + runId: v.optional(v.id("workRuns")), + sliceId: v.optional(v.string()), + sourceRevision: v.optional(v.string()), + title: v.string(), + uri: v.optional(v.string()), + verificationStatus: v.union( + v.literal("unverified"), + v.literal("verified"), + v.literal("rejected") + ), + workId: v.id("works"), + }) + .index("by_workId_and_createdAt", ["workId", "createdAt"]) + .index("by_workId_and_idempotencyKey", ["workId", "idempotencyKey"]) + .index("by_runId_and_createdAt", ["runId", "createdAt"]), + + workDeliveries: defineTable({ + artifactId: v.optional(v.id("workArtifacts")), + createdAt: v.number(), + externalId: v.string(), + idempotencyKey: v.string(), + kind: v.union( + v.literal("branch"), + v.literal("commit"), + v.literal("pull-request"), + v.literal("preview"), + v.literal("deployment") + ), + metadataJson: v.string(), + organizationId: v.id("organizations"), + projectId: v.id("projects"), + provider: v.string(), + sourceRevision: v.string(), + status: v.union( + v.literal("recorded"), + v.literal("ready"), + v.literal("approved"), + v.literal("delivered"), + v.literal("failed"), + v.literal("cancelled") + ), + target: v.string(), + updatedAt: v.number(), + url: v.optional(v.string()), + workId: v.id("works"), + }) + .index("by_workId_and_createdAt", ["workId", "createdAt"]) + .index("by_workId_and_idempotencyKey", ["workId", "idempotencyKey"]), + // ----------------------------------------------------------------- // Flue persistence stores (schema/format version 4). // ----------------------------------------------------------------- @@ -382,38 +526,38 @@ export default defineSchema({ // Durable evidence that a submission attempt started and has not yet // settled. Append-once by (submissionId, attemptId). flueAttemptMarkers: defineTable({ - submissionId: v.string(), attemptId: v.string(), createdAt: v.number(), + submissionId: v.string(), }) .index("by_submissionId_and_attemptId", ["submissionId", "attemptId"]) .index("by_submissionId", ["submissionId"]), // Conversation-stream metadata: one row per stream path. flueConversationStreams: defineTable({ - path: v.string(), - identityJson: v.string(), - incarnation: v.string(), - producerId: v.optional(v.string()), - producerEpoch: v.number(), - nextProducerSequence: v.number(), - nextOffset: v.number(), closed: v.boolean(), createdAt: v.number(), + identityJson: v.string(), + incarnation: v.string(), + nextOffset: v.number(), + nextProducerSequence: v.number(), + path: v.string(), + producerEpoch: v.number(), + producerId: v.optional(v.string()), }).index("by_path", ["path"]), // Conversation-stream batches: one row per appended batch. Offset is // 0-based; `seq` is the row's position in the stream. flueConversationBatches: defineTable({ + appendedAt: v.number(), + attemptId: v.optional(v.string()), path: v.string(), - seq: v.number(), - producerId: v.string(), producerEpoch: v.number(), + producerId: v.string(), producerSequence: v.number(), recordsJson: v.string(), + seq: v.number(), submissionId: v.optional(v.string()), - attemptId: v.optional(v.string()), - appendedAt: v.number(), }) .index("by_path_and_seq", ["path", "seq"]) .index("by_path_producer_epoch_producerSequence", [ @@ -425,41 +569,41 @@ export default defineSchema({ // Event-stream metadata: one row per stream path. flueEventStreams: defineTable({ - path: v.string(), - nextSeq: v.number(), closed: v.boolean(), createdAt: v.number(), + nextSeq: v.number(), + path: v.string(), }).index("by_path", ["path"]), // Event-stream entries: one row per appended event. `onceKey` carries the // idempotency key for `appendEventOnce` and is null for plain appends. flueEventEntries: defineTable({ + appendedAt: v.number(), + dataJson: v.string(), + onceKey: v.optional(v.string()), path: v.string(), seq: v.number(), - onceKey: v.optional(v.string()), - dataJson: v.string(), - appendedAt: v.number(), }) .index("by_path_and_seq", ["path", "seq"]) .index("by_path_and_onceKey", ["path", "onceKey"]), // Workflow run records. flueRuns: defineTable({ + durationMs: v.optional(v.number()), + endedAt: v.optional(v.string()), + errorJson: v.optional(v.string()), + inputJson: v.optional(v.string()), + isError: v.optional(v.boolean()), + resultJson: v.optional(v.string()), runId: v.string(), - workflowName: v.string(), + startedAt: v.string(), status: v.union( v.literal("active"), v.literal("completed"), v.literal("errored") ), - startedAt: v.string(), - inputJson: v.optional(v.string()), traceCarrierJson: v.optional(v.string()), - endedAt: v.optional(v.string()), - isError: v.optional(v.boolean()), - durationMs: v.optional(v.number()), - resultJson: v.optional(v.string()), - errorJson: v.optional(v.string()), + workflowName: v.string(), }) .index("by_runId", ["runId"]) .index("by_startedAt_and_runId", ["startedAt", "runId"]) @@ -479,15 +623,15 @@ export default defineSchema({ // Immutable attachment bytes. Identity is (streamPath, attachmentId); reads // are additionally scoped by conversationId. flueAttachments: defineTable({ - streamPath: v.string(), - conversationId: v.string(), attachmentId: v.string(), - mimeType: v.string(), - size: v.number(), + bytes: v.bytes(), + conversationId: v.string(), + createdAt: v.number(), digest: v.string(), filename: v.optional(v.string()), - bytes: v.bytes(), - createdAt: v.number(), + mimeType: v.string(), + size: v.number(), + streamPath: v.string(), }) .index("by_streamPath", ["streamPath"]) .index("by_streamPath_and_attachmentId", ["streamPath", "attachmentId"]) diff --git a/packages/backend/convex/signalRouting.ts b/packages/backend/convex/signalRouting.ts index 9e22a9f..5fed257 100644 --- a/packages/backend/convex/signalRouting.ts +++ b/packages/backend/convex/signalRouting.ts @@ -82,16 +82,16 @@ export const listEvidence = query({ export const createSignal = mutation({ args: { - organizationId: v.id("organizations"), - projectId: v.id("projects"), messageIds: v.array(v.string()), + organizationId: v.id("organizations"), problemStatement: v.object({ - title: v.string(), - summary: v.string(), - desiredOutcome: v.string(), constraints: v.array(v.string()), + desiredOutcome: v.string(), + summary: v.string(), + title: v.string(), }), processedByAgentInstanceId: v.string(), + projectId: v.id("projects"), token: v.string(), }, handler: async (ctx, args) => { diff --git a/packages/backend/convex/workArtifacts.test.ts b/packages/backend/convex/workArtifacts.test.ts new file mode 100644 index 0000000..657b6ad --- /dev/null +++ b/packages/backend/convex/workArtifacts.test.ts @@ -0,0 +1,108 @@ +import { env } from "@code/env/convex"; +import { convexTest } from "convex-test"; +import { anyApi } from "convex/server"; +import { describe, expect, test } from "vitest"; + +import schema from "./schema"; + +declare global { + interface ImportMeta { + readonly glob: (pattern: string) => Record Promise>; + } +} + +const modules = import.meta.glob("./**/*.ts"); +const api = anyApi; + +describe("Work artifacts and delivery", () => { + test("records exact idempotent artifact and delivery metadata", async () => { + const t = convexTest({ modules, schema }); + const workId = await t.run(async (ctx) => { + const organizationId = await ctx.db.insert("organizations", { + createdAt: 1, + createdBy: "user", + kind: "personal", + name: "Personal", + }); + const projectId = await ctx.db.insert("projects", { + createdAt: 1, + name: "Zopu", + normalizedSourceUrl: "https://example.com/zopu", + organizationId, + repositoryPath: "puter/zopu", + sourceHost: "example.com", + sourceUrl: "https://example.com/zopu", + updatedAt: 1, + }); + return await ctx.db.insert("works", { + createdAt: 1, + objective: "Persist evidence", + organizationId, + projectId, + status: "executing", + title: "Artifact proof", + updatedAt: 1, + }); + }); + + const draft = { + idempotencyKey: "attempt-1:test-report", + kind: "test-report" as const, + metadataJson: "{}", + producer: "fake-harness", + provenanceJson: "{}", + sourceRevision: "abc123", + title: "Focused tests", + verificationStatus: "verified" as const, + }; + const first = await t.mutation(api.workArtifacts.recordArtifact, { + draft, + token: env.FLUE_DB_TOKEN, + workId, + }); + const replay = await t.mutation(api.workArtifacts.recordArtifact, { + draft, + token: env.FLUE_DB_TOKEN, + workId, + }); + expect(first.created).toBe(true); + expect(replay).toEqual({ artifactId: first.artifactId, created: false }); + + const delivery = await t.mutation(api.workArtifacts.recordDelivery, { + artifactId: first.artifactId, + draft: { + externalId: "42", + idempotencyKey: "pr:42", + kind: "pull-request", + metadataJson: "{}", + provider: "gitea", + sourceRevision: "abc123", + status: "ready", + target: "main", + url: "https://git.example/pulls/42", + }, + token: env.FLUE_DB_TOKEN, + workId, + }); + expect(delivery.created).toBe(true); + const updated = await t.mutation(api.workArtifacts.updateDeliveryStatus, { + deliveryId: delivery.deliveryId, + metadataJson: '{"approvedBy":"user"}', + status: "approved", + token: env.FLUE_DB_TOKEN, + }); + expect(updated).toEqual({ changed: true, status: "approved" }); + const stored = await t.run(async (ctx) => ({ + artifacts: await ctx.db.query("workArtifacts").collect(), + deliveries: await ctx.db.query("workDeliveries").collect(), + events: await ctx.db.query("workEvents").collect(), + })); + expect(stored.artifacts).toHaveLength(1); + expect(stored.deliveries).toHaveLength(1); + expect(stored.events.map((event) => event.kind)).toEqual([ + "artifact.recorded", + "delivery.recorded", + "delivery.updated", + ]); + }); +}); diff --git a/packages/backend/convex/workArtifacts.ts b/packages/backend/convex/workArtifacts.ts new file mode 100644 index 0000000..3e92fff --- /dev/null +++ b/packages/backend/convex/workArtifacts.ts @@ -0,0 +1,370 @@ +import { env } from "@code/env/convex"; +import { + canTransitionWorkDelivery, + decodeWorkArtifactDraft, + decodeWorkDeliveryDraft, +} from "@code/primitives/work-artifact"; +import { ConvexError, v } from "convex/values"; +import { Effect } from "effect"; + +import type { Id } from "./_generated/dataModel"; +import { mutation, query } from "./_generated/server"; +import type { MutationCtx } from "./_generated/server"; +import { requireProjectMember } from "./authz"; + +const artifactKind = v.union( + v.literal("definition"), + v.literal("design"), + v.literal("diff"), + v.literal("test-report"), + v.literal("verification-report"), + v.literal("runtime-log"), + v.literal("screenshot"), + v.literal("video"), + v.literal("commit"), + v.literal("branch"), + v.literal("pull-request"), + v.literal("preview"), + v.literal("deployment"), + v.literal("other") +); +const verificationStatus = v.union( + v.literal("unverified"), + v.literal("verified"), + v.literal("rejected") +); +const deliveryKind = v.union( + v.literal("branch"), + v.literal("commit"), + v.literal("pull-request"), + v.literal("preview"), + v.literal("deployment") +); +const deliveryStatus = v.union( + v.literal("recorded"), + v.literal("ready"), + v.literal("approved"), + v.literal("delivered"), + v.literal("failed"), + v.literal("cancelled") +); + +const requireAgent = (token: string): void => { + if (token !== env.FLUE_DB_TOKEN) { + throw new ConvexError("Invalid agent control token"); + } +}; + +const appendEvent = async ( + ctx: MutationCtx, + workId: Id<"works">, + kind: "artifact.recorded" | "delivery.recorded" | "delivery.updated", + idempotencyKey: string, + referenceId: string, + payloadJson: string +): Promise => { + const existing = await ctx.db + .query("workEvents") + .withIndex("by_work_and_idempotencyKey", (q) => + q.eq("workId", workId).eq("idempotencyKey", idempotencyKey) + ) + .unique(); + if (existing) { + return; + } + await ctx.db.insert("workEvents", { + createdAt: Date.now(), + idempotencyKey, + kind, + payloadJson, + referenceId, + workId, + }); +}; + +export const recordArtifact = mutation({ + args: { + attemptId: v.optional(v.id("workAttempts")), + designVersion: v.optional(v.number()), + draft: v.object({ + contentHash: v.optional(v.string()), + environmentId: v.optional(v.string()), + idempotencyKey: v.string(), + kind: artifactKind, + metadataJson: v.string(), + producer: v.string(), + provenanceJson: v.string(), + sourceRevision: v.optional(v.string()), + title: v.string(), + uri: v.optional(v.string()), + verificationStatus, + }), + runId: v.optional(v.id("workRuns")), + sliceId: v.optional(v.string()), + token: v.string(), + workId: v.id("works"), + }, + handler: async (ctx, args) => { + requireAgent(args.token); + const work = await ctx.db.get(args.workId); + if (!work) { + throw new ConvexError("Work not found"); + } + const draft = await Effect.runPromise( + decodeWorkArtifactDraft(args.draft) + ).catch((error: unknown) => { + throw new ConvexError( + error instanceof Error ? error.message : "Invalid Work artifact" + ); + }); + const attempt = args.attemptId ? await ctx.db.get(args.attemptId) : null; + if (args.attemptId && !attempt) { + throw new ConvexError("Attempt not found"); + } + const referencedRunId = args.runId ?? attempt?.runId; + const run = referencedRunId ? await ctx.db.get(referencedRunId) : null; + if (referencedRunId && !run) { + throw new ConvexError("Run not found"); + } + if (run && run.workId !== work._id) { + throw new ConvexError("Run does not belong to Work"); + } + if ( + attempt && + (attempt.workId !== work._id || + (run !== null && attempt.runId !== run._id)) + ) { + throw new ConvexError("Attempt does not belong to Work Run"); + } + if ( + run && + ((args.designVersion !== undefined && + args.designVersion !== run.designVersion) || + (args.sliceId !== undefined && args.sliceId !== run.sliceId)) + ) { + throw new ConvexError("Artifact provenance conflicts with Work Run"); + } + const designVersion = args.designVersion ?? run?.designVersion; + const sliceId = args.sliceId ?? run?.sliceId; + if (designVersion !== undefined && sliceId !== undefined) { + const slice = await ctx.db + .query("workSlices") + .withIndex("by_workId_and_designVersion_and_sliceId", (q) => + q + .eq("workId", work._id) + .eq("designVersion", designVersion) + .eq("sliceId", sliceId) + ) + .unique(); + if (!slice) { + throw new ConvexError("Artifact slice not found"); + } + } else if (designVersion !== undefined) { + const design = await ctx.db + .query("designPackets") + .withIndex("by_work_and_version", (q) => + q.eq("workId", work._id).eq("version", designVersion) + ) + .unique(); + if (!design) { + throw new ConvexError("Artifact Design not found"); + } + } + const existing = await ctx.db + .query("workArtifacts") + .withIndex("by_workId_and_idempotencyKey", (q) => + q.eq("workId", work._id).eq("idempotencyKey", draft.idempotencyKey) + ) + .unique(); + if (existing) { + const exactReplay = + existing.kind === draft.kind && + existing.title === draft.title && + existing.uri === draft.uri && + existing.contentHash === draft.contentHash && + existing.sourceRevision === draft.sourceRevision && + existing.environmentId === draft.environmentId && + existing.producer === draft.producer && + existing.provenanceJson === draft.provenanceJson && + existing.metadataJson === draft.metadataJson && + existing.verificationStatus === draft.verificationStatus && + existing.designVersion === designVersion && + existing.sliceId === sliceId && + existing.runId === run?._id && + existing.attemptId === attempt?._id; + if (!exactReplay) { + throw new ConvexError("Artifact idempotency key has conflicting data"); + } + return { artifactId: existing._id, created: false }; + } + const createdAt = Date.now(); + const artifactId = await ctx.db.insert("workArtifacts", { + ...draft, + attemptId: attempt?._id, + createdAt, + designVersion, + organizationId: work.organizationId, + projectId: work.projectId, + runId: run?._id, + sliceId, + workId: work._id, + }); + await appendEvent( + ctx, + work._id, + "artifact.recorded", + `artifact:${draft.idempotencyKey}`, + String(artifactId), + JSON.stringify({ kind: draft.kind, title: draft.title }) + ); + return { artifactId, created: true }; + }, +}); + +export const recordDelivery = mutation({ + args: { + artifactId: v.optional(v.id("workArtifacts")), + draft: v.object({ + externalId: v.string(), + idempotencyKey: v.string(), + kind: deliveryKind, + metadataJson: v.string(), + provider: v.string(), + sourceRevision: v.string(), + status: deliveryStatus, + target: v.string(), + url: v.optional(v.string()), + }), + token: v.string(), + workId: v.id("works"), + }, + handler: async (ctx, args) => { + requireAgent(args.token); + const work = await ctx.db.get(args.workId); + if (!work) { + throw new ConvexError("Work not found"); + } + const draft = await Effect.runPromise( + decodeWorkDeliveryDraft(args.draft) + ).catch((error: unknown) => { + throw new ConvexError( + error instanceof Error ? error.message : "Invalid Work delivery" + ); + }); + const artifact = args.artifactId ? await ctx.db.get(args.artifactId) : null; + if (args.artifactId && !artifact) { + throw new ConvexError("Artifact not found"); + } + if (artifact && artifact.workId !== work._id) { + throw new ConvexError("Artifact does not belong to Work"); + } + const existing = await ctx.db + .query("workDeliveries") + .withIndex("by_workId_and_idempotencyKey", (q) => + q.eq("workId", work._id).eq("idempotencyKey", draft.idempotencyKey) + ) + .unique(); + if (existing) { + const exactReplay = + existing.kind === draft.kind && + existing.provider === draft.provider && + existing.externalId === draft.externalId && + existing.url === draft.url && + existing.sourceRevision === draft.sourceRevision && + existing.target === draft.target && + existing.status === draft.status && + existing.metadataJson === draft.metadataJson && + existing.artifactId === artifact?._id; + if (!exactReplay) { + throw new ConvexError("Delivery idempotency key has conflicting data"); + } + return { created: false, deliveryId: existing._id }; + } + const timestamp = Date.now(); + const deliveryId = await ctx.db.insert("workDeliveries", { + ...draft, + artifactId: artifact?._id, + createdAt: timestamp, + organizationId: work.organizationId, + projectId: work.projectId, + updatedAt: timestamp, + workId: work._id, + }); + await appendEvent( + ctx, + work._id, + "delivery.recorded", + `delivery:${draft.idempotencyKey}`, + String(deliveryId), + JSON.stringify({ kind: draft.kind, sourceRevision: draft.sourceRevision }) + ); + return { created: true, deliveryId }; + }, +}); + +export const updateDeliveryStatus = mutation({ + args: { + deliveryId: v.id("workDeliveries"), + metadataJson: v.string(), + status: deliveryStatus, + token: v.string(), + }, + handler: async (ctx, args) => { + requireAgent(args.token); + // Validate JSON before persisting, matching recordDelivery's decode path. + const metadata = JSON.parse(args.metadataJson) as unknown; + if (typeof metadata !== "object" || metadata === null) { + throw new ConvexError("Delivery metadata must be a JSON object"); + } + const delivery = await ctx.db.get(args.deliveryId); + if (!delivery) { + throw new ConvexError("Delivery not found"); + } + if (delivery.status === args.status) { + return { changed: false, status: delivery.status }; + } + if (!canTransitionWorkDelivery(delivery.status, args.status)) { + throw new ConvexError( + `Invalid delivery transition: ${delivery.status} -> ${args.status}` + ); + } + await ctx.db.patch(delivery._id, { + metadataJson: args.metadataJson, + status: args.status, + updatedAt: Date.now(), + }); + await appendEvent( + ctx, + delivery.workId, + "delivery.updated", + `delivery-updated:${delivery._id}:${args.status}`, + String(delivery._id), + JSON.stringify({ from: delivery.status, to: args.status }) + ); + return { changed: true, status: args.status }; + }, +}); + +export const listForWork = query({ + args: { workId: v.id("works") }, + handler: async (ctx, args) => { + const work = await ctx.db.get(args.workId); + if (!work) { + return null; + } + await requireProjectMember(ctx, work.projectId); + const [artifacts, deliveries] = await Promise.all([ + ctx.db + .query("workArtifacts") + .withIndex("by_workId_and_createdAt", (q) => q.eq("workId", work._id)) + .order("desc") + .take(100), + ctx.db + .query("workDeliveries") + .withIndex("by_workId_and_createdAt", (q) => q.eq("workId", work._id)) + .order("desc") + .take(50), + ]); + return { artifacts, deliveries }; + }, +}); diff --git a/packages/backend/convex/workExecution.test.ts b/packages/backend/convex/workExecution.test.ts index 59b343d..dfd9fcf 100644 --- a/packages/backend/convex/workExecution.test.ts +++ b/packages/backend/convex/workExecution.test.ts @@ -1,5 +1,5 @@ import { convexTest } from "convex-test"; -import { anyApi } from "convex/server"; +import { anyApi, makeFunctionReference } from "convex/server"; import { describe, expect, test } from "vitest"; import type { Id } from "./_generated/dataModel"; @@ -15,6 +15,11 @@ const modules = { }; const identity = { tokenIdentifier: "https://convex.test|exec-user" }; const api = anyApi; +const claimAttemptRef = makeFunctionReference< + "mutation", + { attemptId: Id<"workAttempts">; leaseMs: number; owner: string }, + { number: number } | null +>("workExecution:claimAttempt"); const makeTest = () => convexTest({ modules, schema }); type TestT = ReturnType; @@ -26,7 +31,7 @@ type Scenario = | "permanent-failure" | "cancelled"; -const seedReadyWork = async () => { +const seedReadyWork = async (options: { secondSlice?: boolean } = {}) => { const t = convexTest({ modules, schema }); const { workId } = await t.withIdentity(identity).run(async (ctx) => { const organizationId = await ctx.db.insert("organizations", { @@ -74,6 +79,7 @@ const seedReadyWork = async () => { workId: id, }); await ctx.db.insert("workSlices", { + createdAt: 1, designVersion: 1, objective: "execute the slice", observableBehavior: "terminal run", @@ -84,6 +90,20 @@ const seedReadyWork = async () => { title: "first", workId: id, }); + if (options.secondSlice) { + await ctx.db.insert("workSlices", { + createdAt: 1, + designVersion: 1, + objective: "execute the second slice", + observableBehavior: "second terminal run", + ordinal: 1, + payloadJson: "{}", + sliceId: "slice-2", + status: "planned", + title: "second", + workId: id, + }); + } return { workId: id }; }); return { t, workId }; @@ -103,12 +123,14 @@ const attemptNumber = async ( const attempt = await t.run(async (ctx) => ctx.db .query("workAttempts") - .withIndex("by_run_and_number", (q) => + .withIndex("by_runId_and_number", (q) => q.eq("runId", runId).eq("number", number) ) .unique() ); - if (!attempt) throw new Error(`attempt ${number} not found`); + if (!attempt) { + throw new Error(`attempt ${number} not found`); + } return attempt._id; }; @@ -116,15 +138,21 @@ const snapshot = async (t: TestT, workId: Id<"works">, runId: Id<"workRuns">) => t.run(async (ctx) => ({ attempts: await ctx.db .query("workAttempts") - .withIndex("by_run_and_number", (q) => q.eq("runId", runId)) + .withIndex("by_runId_and_number", (q) => q.eq("runId", runId)) .collect(), run: await ctx.db.get(runId), slice: await ctx.db .query("workSlices") - .withIndex("by_work_and_designVersion", (q) => + .withIndex("by_workId_and_designVersion", (q) => q.eq("workId", workId).eq("designVersion", 1) ) .first(), + slices: await ctx.db + .query("workSlices") + .withIndex("by_workId_and_designVersion", (q) => + q.eq("workId", workId).eq("designVersion", 1) + ) + .collect(), work: await ctx.db.get(workId), })); @@ -144,6 +172,77 @@ describe("simulated execution resolver", () => { expect(state.run?.terminalClassification).toBe("Succeeded"); expect(state.attempts).toHaveLength(1); expect(state.slice?.status).toBe("completed"); + const decisions = await t.run(async (ctx) => + ctx.db.query("resolverDecisions").collect() + ); + expect(decisions).toHaveLength(1); + expect(decisions[0]).toMatchObject({ + classification: "Succeeded", + decision: "terminal", + resultingWorkStatus: "completed", + }); + }); + + test("completes Work only after every approved slice succeeds", async () => { + const { t, workId } = await seedReadyWork({ secondSlice: true }); + const first = await t + .withIdentity(identity) + .mutation(api.workExecution.startSimulatedExecution, { + scenario: "success", + workId, + }); + await runAttempt(t, first.attemptId, "success"); + const afterFirst = await snapshot(t, workId, first.runId); + expect(afterFirst.work?.status).toBe("ready"); + expect( + afterFirst.slices.find((slice) => slice.sliceId === "slice-1")?.status + ).toBe("completed"); + expect( + afterFirst.slices.find((slice) => slice.sliceId === "slice-2")?.status + ).toBe("ready"); + await expect( + t + .withIdentity(identity) + .mutation(api.workExecution.retrySimulatedExecution, { + runId: first.runId, + }) + ).rejects.toThrow(/retryable state/u); + + const second = await t + .withIdentity(identity) + .mutation(api.workExecution.startSimulatedExecution, { + scenario: "success", + sliceId: "slice-2", + workId, + }); + await runAttempt(t, second.attemptId, "success"); + const completed = await snapshot(t, workId, second.runId); + expect(completed.work?.status).toBe("completed"); + expect( + completed.slices.every((slice) => slice.status === "completed") + ).toBe(true); + }); + + test("allows only one owner to claim a queued attempt", async () => { + const { t, workId } = await seedReadyWork(); + const started = await t + .withIdentity(identity) + .mutation(api.workExecution.startSimulatedExecution, { + scenario: "success", + workId, + }); + const first = await t.mutation(claimAttemptRef, { + attemptId: started.attemptId, + leaseMs: 60_000, + owner: "worker-a", + }); + const second = await t.mutation(claimAttemptRef, { + attemptId: started.attemptId, + leaseMs: 60_000, + owner: "worker-b", + }); + expect(first?.number).toBe(1); + expect(second).toBeNull(); }); test("transient failure retries within the kit budget and then succeeds", async () => { diff --git a/packages/backend/convex/workExecution.ts b/packages/backend/convex/workExecution.ts index 4385e2f..bd14bb2 100644 --- a/packages/backend/convex/workExecution.ts +++ b/packages/backend/convex/workExecution.ts @@ -1,12 +1,7 @@ -import { - FakeHarnessLive, - type FakeScenario, -} from "@code/primitives/harness-runtime"; -import { - type AttemptClassification, - defaultCodingKitV0, - resolveOutcome, -} from "@code/primitives/resolver"; +import { FakeHarnessLive } from "@code/primitives/harness-runtime"; +import type { FakeScenario } from "@code/primitives/harness-runtime"; +import { defaultCodingKitV0, resolveOutcome } from "@code/primitives/resolver"; +import type { WorkEventKind } from "@code/primitives/work"; import { makeFunctionReference } from "convex/server"; import { ConvexError, v } from "convex/values"; import { Effect } from "effect"; @@ -18,6 +13,7 @@ import { mutation, query, } from "./_generated/server"; +import type { MutationCtx } from "./_generated/server"; import { requireProjectMember } from "./authz"; const executeRef = makeFunctionReference< @@ -53,34 +49,51 @@ const finishRef = makeFunctionReference< unknown >("workExecution:finishAttempt"); const now = () => Date.now(); +const attemptClassification = v.union( + v.literal("Succeeded"), + v.literal("RetryableFailure"), + v.literal("NeedsInput"), + v.literal("Blocked"), + v.literal("VerificationFailed"), + v.literal("BudgetExhausted"), + v.literal("Cancelled"), + v.literal("PermanentFailure") +); -const requireWorkForMember = async (ctx: any, workId: Id<"works">) => { +const requireWorkForMember = async ( + ctx: MutationCtx, + workId: Id<"works"> +): Promise> => { const work = await ctx.db.get(workId); - if (!work) throw new ConvexError("Work not found"); + if (!work) { + throw new ConvexError("Work not found"); + } await requireProjectMember(ctx, work.projectId); return work; }; const appendWorkEvent = async ( - ctx: any, + ctx: MutationCtx, workId: Id<"works">, - kind: any, + kind: WorkEventKind, idempotencyKey: string, referenceId?: string, payloadJson?: string ) => { const existing = await ctx.db .query("workEvents") - .withIndex("by_work_and_idempotencyKey", (q: any) => + .withIndex("by_work_and_idempotencyKey", (q) => q.eq("workId", workId).eq("idempotencyKey", idempotencyKey) ) .unique(); - if (existing) return; + if (existing) { + return; + } await ctx.db.insert("workEvents", { - workId, - kind, - idempotencyKey, createdAt: now(), + idempotencyKey, + kind, + workId, ...(referenceId ? { referenceId } : {}), ...(payloadJson ? { payloadJson } : {}), }); @@ -89,54 +102,64 @@ const appendWorkEvent = async ( // Slice the Run targets for the currently approved Design. `sliceId` is // optional only to let the resolver default to the first ready slice. const resolveRunSlice = async ( - ctx: any, + ctx: MutationCtx, work: Doc<"works">, sliceId?: string -) => { +): Promise> => { const currentDesignVersion = work.designVersion; - if (currentDesignVersion === undefined) + if (currentDesignVersion === undefined) { throw new ConvexError("Work has no approved Design to execute"); + } const slices = await ctx.db .query("workSlices") - .withIndex("by_work_and_designVersion", (q: any) => + .withIndex("by_workId_and_designVersion", (q) => q.eq("workId", work._id).eq("designVersion", currentDesignVersion) ) .collect(); - if (slices.length === 0) + if (slices.length === 0) { throw new ConvexError("No slices found for the current approved Design"); + } const slice = sliceId - ? slices.find((row: any) => row.sliceId === sliceId) - : slices.sort((a: any, b: any) => a.ordinal - b.ordinal)[0]; - if (!slice) + ? slices.find((row) => row.sliceId === sliceId) + : slices + .sort((a, b) => a.ordinal - b.ordinal) + .find((row) => row.status === "ready"); + if (!slice) { throw new ConvexError( "Requested slice does not belong to the current approved Design" ); - return slice as Doc<"workSlices">; + } + if (slice.status !== "ready") { + throw new ConvexError("Only the next ready slice can be executed"); + } + return slice; }; -const setSliceStatus = async ( - ctx: any, - workId: Id<"works">, - sliceId: string | undefined, - status: any -) => { - if (!sliceId) return; - const slice = ( - await ctx.db - .query("workSlices") - .withIndex("by_work_and_designVersion", (q: any) => - q.eq("workId", workId) - ) - .collect() - ).find((row: any) => row.sliceId === sliceId); - if (slice) await ctx.db.patch(slice._id, { status }); +const getRunSlice = async ( + ctx: MutationCtx, + run: Doc<"workRuns"> +): Promise | null> => { + if (run.sliceRowId) { + return await ctx.db.get(run.sliceRowId); + } + if (run.designVersion === undefined || run.sliceId === undefined) { + return null; + } + return await ctx.db + .query("workSlices") + .withIndex("by_workId_and_designVersion_and_sliceId", (q) => + q + .eq("workId", run.workId) + .eq("designVersion", run.designVersion!) + .eq("sliceId", run.sliceId!) + ) + .unique(); }; -const RETRYABLE_WORK_STATUSES = ["failed", "needs-input", "blocked", "ready"]; +const RETRYABLE_WORK_STATUSES = new Set(["failed", "needs-input", "blocked"]); export const startSimulatedExecution = mutation({ args: { - workId: v.id("works"), scenario: v.union( v.literal("success"), v.literal("transient-failure-then-success"), @@ -145,41 +168,46 @@ export const startSimulatedExecution = mutation({ v.literal("cancelled") ), sliceId: v.optional(v.string()), + workId: v.id("works"), }, handler: async (ctx, args) => { const work = await requireWorkForMember(ctx, args.workId); - if (work.status !== "ready") + if (work.status !== "ready") { throw new ConvexError("Work must be Ready before simulated execution"); + } if ( work.definitionApprovalVersion !== work.definitionVersion || work.designApprovalVersion !== work.designVersion - ) + ) { throw new ConvexError( "Execution requires exact approved Definition and Design versions" ); + } const slice = await resolveRunSlice(ctx, work, args.sliceId); const createdAt = now(); const runId = await ctx.db.insert("workRuns", { - workId: work._id, - sliceId: slice.sliceId, - status: "ready", - scenario: args.scenario, + createdAt, + designVersion: slice.designVersion, kitId: defaultCodingKitV0.id, kitVersion: defaultCodingKitV0.version, - createdAt, + scenario: args.scenario, + sliceId: slice.sliceId, + sliceRowId: slice._id, + status: "ready", + workId: work._id, }); const attemptId = await ctx.db.insert("workAttempts", { - runId, - workId: work._id, number: 1, + runId, status: "queued", + workId: work._id, }); await ctx.db.patch(work._id, { status: "executing", updatedAt: createdAt, }); await ctx.db.patch(slice._id, { status: "running" }); - await ctx.db.patch(runId, { status: "running", startedAt: createdAt }); + await ctx.db.patch(runId, { startedAt: createdAt, status: "running" }); await appendWorkEvent( ctx, work._id, @@ -187,11 +215,18 @@ export const startSimulatedExecution = mutation({ `run-started:${runId}`, String(runId) ); + await appendWorkEvent( + ctx, + work._id, + "slice.started", + `slice-started:${runId}:${slice.sliceId}`, + String(slice._id) + ); await ctx.scheduler.runAfter(0, executeRef, { attemptId, scenario: args.scenario, }); - return { runId, attemptId }; + return { attemptId, runId }; }, }); @@ -199,29 +234,56 @@ export const cancelSimulatedExecution = mutation({ args: { runId: v.id("workRuns") }, handler: async (ctx, args) => { const run = await ctx.db.get(args.runId); - if (!run) throw new ConvexError("Run not found"); + if (!run) { + throw new ConvexError("Run not found"); + } const work = await requireWorkForMember(ctx, run.workId); - if (run.status === "terminal" || run.status === "cancelled") + if (run.status === "terminal" || run.status === "cancelled") { return { cancelled: false }; + } await ctx.db.patch(run._id, { - status: "cancelled", endedAt: now(), + status: "cancelled", terminalClassification: "Cancelled", terminalSummary: "Simulation cancelled", }); const attempts = await ctx.db .query("workAttempts") - .withIndex("by_run_and_number", (q: any) => q.eq("runId", run._id)) + .withIndex("by_runId_and_number", (q) => q.eq("runId", run._id)) .collect(); - for (const attempt of attempts) - if (attempt.status !== "terminal") + for (const attempt of attempts) { + if (attempt.status !== "terminal") { await ctx.db.patch(attempt._id, { - status: "terminal", - endedAt: now(), classification: "Cancelled", + endedAt: now(), + status: "terminal", summary: "Simulation cancelled", }); - await setSliceStatus(ctx, work._id, run.sliceId, "ready"); + await ctx.db.insert("resolverDecisions", { + attemptId: attempt._id, + attemptNumber: attempt.number, + classification: "Cancelled", + createdAt: now(), + decision: "terminal", + resultingWorkStatus: "ready", + runId: run._id, + summary: "Simulation cancelled", + workId: work._id, + }); + await appendWorkEvent( + ctx, + work._id, + "resolver.decided", + `resolver-decided:${attempt._id}`, + String(attempt._id), + JSON.stringify({ classification: "Cancelled", decision: "terminal" }) + ); + } + } + const slice = await getRunSlice(ctx, run); + if (slice) { + await ctx.db.patch(slice._id, { status: "ready" }); + } await ctx.db.patch(work._id, { status: "ready", updatedAt: now() }); await appendWorkEvent( ctx, @@ -240,32 +302,40 @@ export const retrySimulatedExecution = mutation({ args: { runId: v.id("workRuns") }, handler: async (ctx, args) => { const run = await ctx.db.get(args.runId); - if (!run) throw new ConvexError("Run not found"); + if (!run) { + throw new ConvexError("Run not found"); + } const work = await requireWorkForMember(ctx, run.workId); - if (run.status !== "terminal") + if (run.status !== "terminal") { throw new ConvexError("Only terminal Runs can be retried"); - if (!RETRYABLE_WORK_STATUSES.includes(work.status)) + } + if (!RETRYABLE_WORK_STATUSES.has(work.status)) { throw new ConvexError("Work is not in a retryable state"); + } const attempts = await ctx.db .query("workAttempts") - .withIndex("by_run_and_number", (q: any) => q.eq("runId", run._id)) + .withIndex("by_runId_and_number", (q) => q.eq("runId", run._id)) .collect(); const number = attempts.length + 1; const attemptId = await ctx.db.insert("workAttempts", { - runId: run._id, - workId: work._id, number, + runId: run._id, status: "queued", + workId: work._id, }); await ctx.db.patch(run._id, { - status: "running", - startedAt: now(), endedAt: undefined, + startedAt: now(), + status: "running", terminalClassification: undefined, terminalSummary: undefined, }); await ctx.db.patch(work._id, { status: "executing", updatedAt: now() }); - await setSliceStatus(ctx, work._id, run.sliceId, "running"); + const slice = await getRunSlice(ctx, run); + if (!slice) { + throw new ConvexError("Run slice not found"); + } + await ctx.db.patch(slice._id, { status: "running" }); await ctx.scheduler.runAfter(0, executeRef, { attemptId, scenario: run.scenario, @@ -277,62 +347,71 @@ export const retrySimulatedExecution = mutation({ export const claimAttempt = internalMutation({ args: { attemptId: v.id("workAttempts"), - owner: v.string(), leaseMs: v.number(), + owner: v.string(), }, handler: async (ctx, args) => { const attempt = await ctx.db.get(args.attemptId); - if (!attempt || attempt.status === "terminal") return null; + if (!attempt || attempt.status !== "queued") { + return null; + } + const run = await ctx.db.get(attempt.runId); + if (!run || run.status !== "running") { + return null; + } const claimedAt = now(); await ctx.db.patch(attempt._id, { - status: "claimed", - leaseOwner: args.owner, leaseExpiresAt: claimedAt + args.leaseMs, + leaseOwner: args.owner, startedAt: attempt.startedAt ?? claimedAt, + status: "claimed", }); await ctx.db.patch(attempt.runId, { - status: "running", startedAt: claimedAt, + status: "running", }); - return { ...attempt, status: "claimed" as const, leaseOwner: args.owner }; + return { ...attempt, leaseOwner: args.owner, status: "claimed" as const }; }, }); export const checkpointAttempt = internalMutation({ args: { attemptId: v.id("workAttempts"), - owner: v.string(), - sequence: v.number(), kind: v.string(), message: v.string(), metadataJson: v.string(), + owner: v.string(), + sequence: v.number(), }, handler: async (ctx, args) => { const attempt = await ctx.db.get(args.attemptId); if ( !attempt || attempt.leaseOwner !== args.owner || - attempt.status === "terminal" - ) + attempt.status === "terminal" || + (attempt.leaseExpiresAt !== undefined && attempt.leaseExpiresAt < now()) + ) { return false; + } const existing = await ctx.db .query("workAttemptEvents") .withIndex("by_attempt_and_sequence", (q: any) => q.eq("attemptId", attempt._id).eq("sequence", args.sequence) ) .unique(); - if (!existing) + if (!existing) { await ctx.db.insert("workAttemptEvents", { attemptId: attempt._id, - sequence: args.sequence, kind: args.kind, message: args.message, metadataJson: args.metadataJson, occurredAt: now(), + sequence: args.sequence, }); + } await ctx.db.patch(attempt._id, { - status: "running", leaseExpiresAt: now() + 60_000, + status: "running", }); return true; }, @@ -345,8 +424,8 @@ export const checkpointAttempt = internalMutation({ export const finishAttempt = internalMutation({ args: { attemptId: v.id("workAttempts"), + classification: attemptClassification, owner: v.string(), - classification: v.string(), retryable: v.boolean(), summary: v.string(), }, @@ -355,19 +434,21 @@ export const finishAttempt = internalMutation({ if ( !attempt || attempt.leaseOwner !== args.owner || - attempt.status === "terminal" - ) + attempt.status === "terminal" || + (attempt.leaseExpiresAt !== undefined && attempt.leaseExpiresAt < now()) + ) { return null; + } const endedAt = now(); await ctx.db.patch(attempt._id, { - status: "terminal", - endedAt, classification: args.classification, - summary: args.summary, + endedAt, leaseExpiresAt: undefined, + status: "terminal", + summary: args.summary, }); const outcome = { - classification: args.classification as AttemptClassification, + classification: args.classification, retryable: args.retryable, summary: args.summary, }; @@ -377,7 +458,9 @@ export const finishAttempt = internalMutation({ defaultCodingKitV0.retryPolicy ); const run = await ctx.db.get(attempt.runId); - if (!run) return null; + if (!run) { + return null; + } await appendWorkEvent( ctx, attempt.workId, @@ -390,13 +473,34 @@ export const finishAttempt = internalMutation({ summary: args.summary, }) ); + await appendWorkEvent( + ctx, + attempt.workId, + "resolver.decided", + `resolver-decided:${attempt._id}`, + String(attempt._id), + JSON.stringify({ + classification: args.classification, + decision: resolution.kind, + }) + ); if (resolution.kind === "retry") { + await ctx.db.insert("resolverDecisions", { + attemptId: attempt._id, + attemptNumber: attempt.number, + classification: args.classification, + createdAt: endedAt, + decision: "retry", + runId: run._id, + summary: args.summary, + workId: attempt.workId, + }); // Keep Run running and Work executing; spin the next attempt. const nextAttemptId = await ctx.db.insert("workAttempts", { - runId: run._id, - workId: attempt.workId, number: attempt.number + 1, + runId: run._id, status: "queued", + workId: attempt.workId, }); await ctx.scheduler.runAfter(0, executeRef, { attemptId: nextAttemptId, @@ -405,22 +509,78 @@ export const finishAttempt = internalMutation({ return { nextAttemptId, retried: true }; } await ctx.db.patch(run._id, { - status: "terminal", endedAt, + status: "terminal", terminalClassification: args.classification, terminalSummary: args.summary, }); const work = await ctx.db.get(run.workId); - if (work) + const slice = await getRunSlice(ctx, run); + let resultingWorkStatus = resolution.workStatus; + if (args.classification === "Succeeded" && slice) { + await ctx.db.patch(slice._id, { status: "completed" }); + await appendWorkEvent( + ctx, + attempt.workId, + "slice.completed", + `slice-completed:${run._id}:${slice.sliceId}`, + String(slice._id) + ); + const slices = await ctx.db + .query("workSlices") + .withIndex("by_workId_and_designVersion", (q) => + q + .eq("workId", attempt.workId) + .eq("designVersion", slice.designVersion) + ) + .collect(); + const nextSlice = slices + .sort((left, right) => left.ordinal - right.ordinal) + .find((candidate) => candidate.status === "planned"); + if (nextSlice) { + await ctx.db.patch(nextSlice._id, { status: "ready" }); + resultingWorkStatus = "ready"; + await appendWorkEvent( + ctx, + attempt.workId, + "slice.ready", + `slice-ready:${run._id}:${nextSlice.sliceId}`, + String(nextSlice._id) + ); + } + } else if (slice) { + const blocked = ["NeedsInput", "Blocked", "VerificationFailed"].includes( + args.classification + ); + await ctx.db.patch(slice._id, { status: blocked ? "blocked" : "ready" }); + } + if (work) { await ctx.db.patch(work._id, { - status: resolution.workStatus, + status: resultingWorkStatus, updatedAt: endedAt, }); - await setSliceStatus( + } + await ctx.db.insert("resolverDecisions", { + attemptId: attempt._id, + attemptNumber: attempt.number, + classification: args.classification, + createdAt: endedAt, + decision: "terminal", + resultingWorkStatus, + runId: run._id, + summary: args.summary, + workId: attempt.workId, + }); + await appendWorkEvent( ctx, attempt.workId, - run.sliceId, - args.classification === "Succeeded" ? "completed" : "ready" + "run.completed", + `run-completed:${run._id}`, + String(run._id), + JSON.stringify({ + classification: args.classification, + workStatus: resultingWorkStatus, + }) ); return { retried: false }; }, @@ -441,17 +601,19 @@ export const executeFakeAttempt = internalAction({ const owner = `fake-worker:${args.attemptId}`; const claimed = await ctx.runMutation(claimRef, { attemptId: args.attemptId, - owner, leaseMs: 60_000, + owner, }); - if (!claimed) return null; + if (!claimed) { + return null; + } const [events, outcome] = await Effect.runPromise( FakeHarnessLive().run({ attemptNumber: claimed.number, scenario: args.scenario, }) ); - for (const item of events) + for (const item of events) { await ctx.runMutation(checkpointRef, { attemptId: args.attemptId, kind: item.kind, @@ -460,6 +622,7 @@ export const executeFakeAttempt = internalAction({ owner, sequence: item.sequence, }); + } await ctx.runMutation(finishRef, { attemptId: args.attemptId, classification: outcome.classification, @@ -477,7 +640,22 @@ export const executeFakeAttempt = internalAction({ export const reconcileExpiredAttempts = internalMutation({ args: {}, handler: async (ctx) => { - const active = await ctx.db.query("workAttempts").collect(); + const timestamp = now(); + const [claimed, running] = await Promise.all([ + ctx.db + .query("workAttempts") + .withIndex("by_status_and_leaseExpiresAt", (q) => + q.eq("status", "claimed").lt("leaseExpiresAt", timestamp) + ) + .collect(), + ctx.db + .query("workAttempts") + .withIndex("by_status_and_leaseExpiresAt", (q) => + q.eq("status", "running").lt("leaseExpiresAt", timestamp) + ) + .collect(), + ]); + const active = [...claimed, ...running]; let reconciled = 0; for (const attempt of active) { if ( @@ -486,12 +664,12 @@ export const reconcileExpiredAttempts = internalMutation({ attempt.leaseExpiresAt < now() ) { await ctx.db.patch(attempt._id, { - status: "terminal", - endedAt: now(), classification: "Blocked", - summary: "Attempt lease expired and was reconciled", - leaseOwner: undefined, + endedAt: now(), leaseExpiresAt: undefined, + leaseOwner: undefined, + status: "terminal", + summary: "Attempt lease expired and was reconciled", }); const run = await ctx.db.get(attempt.runId); await appendWorkEvent( @@ -503,19 +681,44 @@ export const reconcileExpiredAttempts = internalMutation({ JSON.stringify({ attemptNumber: attempt.number }) ); reconciled += 1; - if (!run) continue; + if (!run) { + continue; + } const attempts = await ctx.db .query("workAttempts") - .withIndex("by_run_and_number", (q: any) => q.eq("runId", run._id)) + .withIndex("by_runId_and_number", (q) => q.eq("runId", run._id)) .collect(); const withinBudget = attempts.length < defaultCodingKitV0.retryPolicy.maxAttempts; - if (run.status === "running" && withinBudget) { + const retry = run.status === "running" && withinBudget; + await ctx.db.insert("resolverDecisions", { + attemptId: attempt._id, + attemptNumber: attempt.number, + classification: "Blocked", + createdAt: now(), + decision: retry ? "retry" : "terminal", + resultingWorkStatus: retry ? undefined : "blocked", + runId: run._id, + summary: "Attempt lease expired and was reconciled", + workId: attempt.workId, + }); + await appendWorkEvent( + ctx, + attempt.workId, + "resolver.decided", + `resolver-decided:${attempt._id}`, + String(attempt._id), + JSON.stringify({ + classification: "Blocked", + decision: retry ? "retry" : "terminal", + }) + ); + if (retry) { const nextAttemptId = await ctx.db.insert("workAttempts", { - runId: run._id, - workId: attempt.workId, number: attempts.length + 1, + runId: run._id, status: "queued", + workId: attempt.workId, }); await ctx.scheduler.runAfter(0, executeRef, { attemptId: nextAttemptId, @@ -523,18 +726,22 @@ export const reconcileExpiredAttempts = internalMutation({ }); } else { await ctx.db.patch(run._id, { - status: "terminal", endedAt: now(), + status: "terminal", terminalClassification: "Blocked", terminalSummary: "Run reconciled after expired lease", }); const work = await ctx.db.get(run.workId); - if (work) + if (work) { await ctx.db.patch(work._id, { status: "blocked", updatedAt: now(), }); - await setSliceStatus(ctx, attempt.workId, run.sliceId, "ready"); + } + const slice = await getRunSlice(ctx, run); + if (slice) { + await ctx.db.patch(slice._id, { status: "blocked" }); + } } } } @@ -546,13 +753,17 @@ export const listRunEvents = query({ args: { attemptId: v.id("workAttempts") }, handler: async (ctx, args) => { const attempt = await ctx.db.get(args.attemptId); - if (!attempt) return []; + if (!attempt) { + return []; + } const work = await ctx.db.get(attempt.workId); - if (!work) return []; + if (!work) { + return []; + } await requireProjectMember(ctx, work.projectId); return await ctx.db .query("workAttemptEvents") - .withIndex("by_attempt_and_sequence", (q: any) => + .withIndex("by_attempt_and_sequence", (q) => q.eq("attemptId", args.attemptId) ) .order("asc") diff --git a/packages/backend/convex/workPlanning.test.ts b/packages/backend/convex/workPlanning.test.ts index 7cc959f..e6473db 100644 --- a/packages/backend/convex/workPlanning.test.ts +++ b/packages/backend/convex/workPlanning.test.ts @@ -30,10 +30,10 @@ describe("Work planning and execution commands", () => { name: "Personal", }); await ctx.db.insert("organizationMembers", { - organizationId, - userId: identity.tokenIdentifier, - role: "owner", createdAt: 1, + organizationId, + role: "owner", + userId: identity.tokenIdentifier, }); const projectId = await ctx.db.insert("projects", { createdAt: 1, @@ -46,12 +46,12 @@ describe("Work planning and execution commands", () => { updatedAt: 1, }); const workId = await ctx.db.insert("works", { + createdAt: 1, + objective: "Prove the flow", organizationId, projectId, - title: "Executable work", - objective: "Prove the flow", status: "proposed", - createdAt: 1, + title: "Executable work", updatedAt: 1, }); return { projectId, workId }; @@ -63,67 +63,67 @@ describe("Work planning and execution commands", () => { const definition = await t .withIdentity(identity) .mutation(api.workPlanning.saveDefinitionProposal, { - workId: fixture.workId, payloadJson: JSON.stringify({ - problem: "Need a proof", - desiredOutcome: "A terminal simulation", + acceptanceCriteria: ["terminal"], affectedUsers: ["user"], + assumptions: [], + constraints: [], + desiredOutcome: "A terminal simulation", inScope: ["fake"], outOfScope: [], - acceptanceCriteria: ["terminal"], - constraints: [], - assumptions: [], + problem: "Need a proof", questions: [], - risk: "low", requiredArtifacts: ["events"], + risk: "low", }), + workId: fixture.workId, }); await t .withIdentity(identity) .mutation(api.workPlanning.approveDefinition, { - workId: fixture.workId, version: definition.version, + workId: fixture.workId, }); const design = await t .withIdentity(identity) .mutation(api.workPlanning.saveDesignProposal, { - workId: fixture.workId, payloadJson: JSON.stringify({ - impactMap: { files: [], modules: [], risks: [], summary: "small" }, architectureSummary: "fake", - fileTreeDelta: [], callFlowDelta: [], - keyInterfaces: [], - invariants: ["terminal"], concerns: [], + evidenceRequirements: ["event"], + fileTreeDelta: [], + impactMap: { files: [], modules: [], risks: [], summary: "small" }, + invariants: ["terminal"], + keyInterfaces: [], slices: [ { + codeBoundaries: ["runtime"], + dependsOn: [], + evidenceRequirements: ["event"], id: "slice-1", - title: "fake", objective: "fake", observableBehavior: "event", - codeBoundaries: ["runtime"], - evidenceRequirements: ["event"], - verification: ["assert"], reviewRequired: false, - dependsOn: [], + title: "fake", + verification: ["assert"], }, ], - evidenceRequirements: ["event"], tradeoffs: [], }), + workId: fixture.workId, }); await t.withIdentity(identity).mutation(api.workPlanning.approveDesign, { - workId: fixture.workId, definitionVersion: definition.version, designVersion: design.version, + workId: fixture.workId, }); const started = await t .withIdentity(identity) .mutation(api.workExecution.startSimulatedExecution, { - workId: fixture.workId, scenario: "success", sliceId: "slice-1", + workId: fixture.workId, }); expect(started.runId).toBeTruthy(); const state = await t.run(async (ctx) => ctx.db.get(fixture.workId)); @@ -137,7 +137,7 @@ describe("Work planning and execution commands", () => { const completed = await t.run(async (ctx) => ({ attempt: await ctx.db .query("workAttempts") - .withIndex("by_run_and_number", (q) => q.eq("runId", started.runId)) + .withIndex("by_runId_and_number", (q) => q.eq("runId", started.runId)) .unique(), events: await ctx.db.query("workAttemptEvents").collect(), run: await ctx.db.get(started.runId as Id<"workRuns">), @@ -164,7 +164,154 @@ const validDefinitionPayload = () => ({ risk: "low", }); +const validDesignPayload = (sliceId = "slice-1") => ({ + architectureSummary: "fake", + callFlowDelta: [], + concerns: [], + evidenceRequirements: ["event"], + fileTreeDelta: [], + impactMap: { files: [], modules: [], risks: [], summary: "small" }, + invariants: ["terminal"], + keyInterfaces: [], + slices: [ + { + codeBoundaries: ["runtime"], + dependsOn: [], + evidenceRequirements: ["event"], + id: sliceId, + objective: "fake", + observableBehavior: "event", + reviewRequired: false, + title: "fake", + verification: ["assert"], + }, + ], + tradeoffs: [], +}); + describe("Work planning guards", () => { + test("persists high-impact questions but blocks approval", async () => { + const t = convexTest({ modules, schema }); + const { workId } = await t.withIdentity(identity).run(async (ctx) => { + const organizationId = await ctx.db.insert("organizations", { + createdAt: 1, + createdBy: identity.tokenIdentifier, + kind: "personal", + name: "Personal", + }); + await ctx.db.insert("organizationMembers", { + createdAt: 1, + organizationId, + role: "owner", + userId: identity.tokenIdentifier, + }); + const projectId = await ctx.db.insert("projects", { + createdAt: 1, + name: "Zopu", + normalizedSourceUrl: "https://example.com/zopu", + organizationId, + repositoryPath: "puter/zopu", + sourceHost: "example.com", + sourceUrl: "https://example.com/zopu", + updatedAt: 1, + }); + const id = await ctx.db.insert("works", { + createdAt: 1, + objective: "Resolve a critical question", + organizationId, + projectId, + status: "defining", + title: "Question gate", + updatedAt: 1, + }); + return { workId: id }; + }); + const saved = await t + .withIdentity(identity) + .mutation(api.workPlanning.saveDefinitionProposal, { + payloadJson: JSON.stringify({ + ...validDefinitionPayload(), + questions: [ + { + alternatives: ["public", "private"], + id: "visibility", + impact: "high", + prompt: "Should the endpoint be public?", + status: "open", + }, + ], + }), + workId, + }); + await expect( + t.withIdentity(identity).mutation(api.workPlanning.approveDefinition, { + version: saved.version, + workId, + }) + ).rejects.toThrow(/High-impact open questions/u); + const stored = await t.run(async (ctx) => + ctx.db.query("workQuestions").collect() + ); + expect(stored).toHaveLength(1); + expect(stored[0]?.status).toBe("open"); + }); + + test("keeps prior Design slices as versioned history", async () => { + const t = convexTest({ modules, schema }); + const { workId } = await t.withIdentity(identity).run(async (ctx) => { + const organizationId = await ctx.db.insert("organizations", { + createdAt: 1, + createdBy: identity.tokenIdentifier, + kind: "personal", + name: "Personal", + }); + await ctx.db.insert("organizationMembers", { + createdAt: 1, + organizationId, + role: "owner", + userId: identity.tokenIdentifier, + }); + const projectId = await ctx.db.insert("projects", { + createdAt: 1, + name: "Zopu", + normalizedSourceUrl: "https://example.com/zopu", + organizationId, + repositoryPath: "puter/zopu", + sourceHost: "example.com", + sourceUrl: "https://example.com/zopu", + updatedAt: 1, + }); + const id = await ctx.db.insert("works", { + createdAt: 1, + definitionApprovalVersion: 1, + definitionVersion: 1, + objective: "Preserve Design history", + organizationId, + projectId, + status: "designing", + title: "Versioned Design", + updatedAt: 1, + }); + return { workId: id }; + }); + await t + .withIdentity(identity) + .mutation(api.workPlanning.saveDesignProposal, { + payloadJson: JSON.stringify(validDesignPayload("slice-v1")), + workId, + }); + await t + .withIdentity(identity) + .mutation(api.workPlanning.saveDesignProposal, { + payloadJson: JSON.stringify(validDesignPayload("slice-v2")), + workId, + }); + const slices = await t.run(async (ctx) => + ctx.db.query("workSlices").collect() + ); + expect(slices.map((slice) => slice.designVersion).sort()).toEqual([1, 2]); + }); + test("a Definition cannot be revised while a Run is executing", async () => { const t = convexTest({ modules, schema }); const { workId } = await t.withIdentity(identity).run(async (ctx) => { diff --git a/packages/backend/convex/workPlanning.ts b/packages/backend/convex/workPlanning.ts index 2f937a2..1621692 100644 --- a/packages/backend/convex/workPlanning.ts +++ b/packages/backend/convex/workPlanning.ts @@ -1,8 +1,10 @@ +import type { WorkEventKind } from "@code/primitives/work"; import { - type WorkDefinition, + decodeDefinition, validateDefinition, WorkQuestion, } from "@code/primitives/work-definition"; +import type { WorkDefinition } from "@code/primitives/work-definition"; import { validateDesignPacket } from "@code/primitives/work-design"; import { makeFunctionReference } from "convex/server"; import { ConvexError, v } from "convex/values"; @@ -12,10 +14,12 @@ import type { Doc, Id } from "./_generated/dataModel"; import { env, internalAction, + internalMutation, internalQuery, mutation, query, } from "./_generated/server"; +import type { MutationCtx, QueryCtx } from "./_generated/server"; import { requireProjectMember } from "./authz"; const plannerRef = makeFunctionReference< @@ -27,6 +31,11 @@ const plannerContextRef = makeFunctionReference< { workId: Id<"works"> }, { objective: string; status: string; title: string } | null >("workPlanning:getPlannerContext"); +const plannerFailureRef = makeFunctionReference< + "mutation", + { workId: Id<"works">; error: string }, + null +>("workPlanning:recordPlannerFailure"); const parsePayload = (payloadJson: string): unknown => { try { @@ -38,67 +47,72 @@ const parsePayload = (payloadJson: string): unknown => { const objectPayload = (payloadJson: string): Record => { const value = parsePayload(payloadJson); - if (typeof value !== "object" || value === null || Array.isArray(value)) + if (typeof value !== "object" || value === null || Array.isArray(value)) { throw new ConvexError("Proposal payload must be an object"); + } return value as Record; }; -const requireWork = async (ctx: { db: any }, workId: Id<"works">) => { - const work = (await ctx.db.get(workId)) as Doc<"works"> | null; - if (!work) throw new ConvexError("Work not found"); +const requireWork = async ( + ctx: QueryCtx | MutationCtx, + workId: Id<"works"> +): Promise> => { + const work = await ctx.db.get(workId); + if (!work) { + throw new ConvexError("Work not found"); + } return work; }; const appendEvent = async ( - ctx: { db: any }, + ctx: MutationCtx, workId: Id<"works">, - kind: any, + kind: WorkEventKind, idempotencyKey: string, referenceId?: string, payloadJson?: string ) => { const existing = await ctx.db .query("workEvents") - .withIndex("by_work_and_idempotencyKey", (q: any) => + .withIndex("by_work_and_idempotencyKey", (q) => q.eq("workId", workId).eq("idempotencyKey", idempotencyKey) ) .unique(); - if (existing) return existing._id; + if (existing) { + return existing._id; + } return await ctx.db.insert("workEvents", { - workId, - kind, - idempotencyKey, createdAt: Date.now(), + idempotencyKey, + kind, + workId, ...(referenceId ? { referenceId } : {}), ...(payloadJson ? { payloadJson } : {}), }); }; const invalidateApprovalsAndDesign = async ( - ctx: { db: any }, + ctx: MutationCtx, workId: Id<"works"> ) => { const approvals = await ctx.db .query("workApprovals") - .withIndex("by_work_and_kind", (q: any) => q.eq("workId", workId)) + .withIndex("by_workId_and_kind", (q) => q.eq("workId", workId)) .collect(); for (const approval of approvals) { - if (approval.status === "active") + if (approval.status === "active") { await ctx.db.patch(approval._id, { status: "invalidated" }); + } } const designs = await ctx.db .query("designPackets") - .withIndex("by_work_and_version", (q: any) => q.eq("workId", workId)) + .withIndex("by_work_and_version", (q) => q.eq("workId", workId)) .collect(); for (const design of designs) { - if (design.status === "current") + if (design.status === "current") { await ctx.db.patch(design._id, { status: "superseded" }); + } } - const slices = await ctx.db - .query("workSlices") - .withIndex("by_work_and_designVersion", (q: any) => q.eq("workId", workId)) - .collect(); - for (const slice of slices) await ctx.db.delete(slice._id); }; export const requestDefinition = mutation({ @@ -106,8 +120,16 @@ export const requestDefinition = mutation({ handler: async (ctx, args) => { const work = await requireWork(ctx, args.workId); await requireProjectMember(ctx, work.projectId); - if (work.status !== "proposed" && work.status !== "defining") + if ( + work.status !== "proposed" && + work.status !== "defining" && + !( + work.status === "blocked" && + work.definitionApprovalVersion !== work.definitionVersion + ) + ) { throw new ConvexError("Work is not available for definition"); + } const now = Date.now(); await ctx.db.patch(work._id, { status: "defining", updatedAt: now }); await appendEvent( @@ -125,15 +147,16 @@ export const requestDefinition = mutation({ }); const saveDefinition = async ( - ctx: { db: any }, + ctx: MutationCtx, work: Doc<"works">, payloadJson: string, createdBy: string ) => { - if (work.status === "executing") + if (work.status === "executing") { throw new ConvexError("Cannot revise Work while a Run is executing"); + } const decoded = await Effect.runPromise( - validateDefinition({ + decodeDefinition({ ...objectPayload(payloadJson), version: (work.definitionVersion ?? 0) + 1, }) @@ -142,52 +165,45 @@ const saveDefinition = async ( error instanceof Error ? error.message : "Invalid Definition" ); }); - const version = decoded.version; + const { version } = decoded; await invalidateApprovalsAndDesign(ctx, work._id); const previous = await ctx.db .query("workDefinitions") - .withIndex("by_work_and_version", (q: any) => q.eq("workId", work._id)) + .withIndex("by_work_and_version", (q) => q.eq("workId", work._id)) .collect(); - for (const row of previous) - if (row.status === "current") + for (const row of previous) { + if (row.status === "current") { await ctx.db.patch(row._id, { status: "superseded" }); + } + } const definitionId = await ctx.db.insert("workDefinitions", { - workId: work._id, - version, + createdAt: Date.now(), + createdBy, payloadJson: JSON.stringify(decoded), risk: decoded.risk, status: "current", - createdBy, - createdAt: Date.now(), + version, + workId: work._id, }); - const questions = await ctx.db - .query("workQuestions") - .withIndex("by_work_and_definitionVersion", (q: any) => - q.eq("workId", work._id) - ) - .collect(); - for (const question of questions) - if (question.definitionVersion !== version) - await ctx.db.delete(question._id); for (const question of decoded.questions) { await ctx.db.insert("workQuestions", { - workId: work._id, - definitionVersion: version, - questionId: question.id, - prompt: question.prompt, - impact: question.impact, - recommendation: question.recommendation, alternativesJson: JSON.stringify(question.alternatives), - status: question.status, answer: question.answer, createdAt: Date.now(), + definitionVersion: version, + impact: question.impact, + prompt: question.prompt, + questionId: question.id, + recommendation: question.recommendation, + status: question.status, + workId: work._id, }); } await ctx.db.patch(work._id, { - definitionVersion: version, definitionApprovalVersion: undefined, - designVersion: undefined, + definitionVersion: version, designApprovalVersion: undefined, + designVersion: undefined, status: "awaiting-definition-approval", updatedAt: Date.now(), }); @@ -203,7 +219,7 @@ const saveDefinition = async ( }; export const saveDefinitionProposal = mutation({ - args: { workId: v.id("works"), payloadJson: v.string() }, + args: { payloadJson: v.string(), workId: v.id("works") }, handler: async (ctx, args) => { const work = await requireWork(ctx, args.workId); await requireProjectMember(ctx, work.projectId); @@ -214,22 +230,25 @@ export const saveDefinitionProposal = mutation({ export const reviseDefinition = saveDefinitionProposal; export const approveDefinition = mutation({ - args: { workId: v.id("works"), version: v.number() }, + args: { version: v.number(), workId: v.id("works") }, handler: async (ctx, args) => { const work = await requireWork(ctx, args.workId); await requireProjectMember(ctx, work.projectId); if ( work.definitionVersion !== args.version || work.status !== "awaiting-definition-approval" - ) + ) { throw new ConvexError("Definition version is not current or approvable"); + } const row = await ctx.db .query("workDefinitions") - .withIndex("by_work_and_version", (q: any) => + .withIndex("by_work_and_version", (q) => q.eq("workId", work._id).eq("version", args.version) ) .unique(); - if (!row) throw new ConvexError("Definition not found"); + if (!row) { + throw new ConvexError("Definition not found"); + } const definition = JSON.parse(row.payloadJson) as WorkDefinition; const valid = await Effect.runPromise(validateDefinition(definition)).catch( (error: unknown) => { @@ -240,19 +259,36 @@ export const approveDefinition = mutation({ ); } ); + const questions = await ctx.db + .query("workQuestions") + .withIndex("by_workId_and_definitionVersion", (q) => + q.eq("workId", work._id).eq("definitionVersion", args.version) + ) + .collect(); + if ( + questions.some( + (question) => question.status === "open" && question.impact === "high" + ) + ) { + throw new ConvexError( + "High-impact open questions must be resolved before approval" + ); + } const identity = await ctx.auth.getUserIdentity(); - if (!identity) throw new ConvexError("Authentication required"); + if (!identity) { + throw new ConvexError("Authentication required"); + } await ctx.db.insert("workApprovals", { - workId: work._id, - kind: "definition", - definitionVersion: args.version, - approvedBy: identity.subject, approvedAt: Date.now(), + approvedBy: identity.tokenIdentifier, + definitionVersion: args.version, + kind: "definition", status: "active", + workId: work._id, }); await ctx.db.patch(work._id, { - status: "designing", definitionApprovalVersion: valid.version, + status: "designing", updatedAt: Date.now(), }); await appendEvent( @@ -270,36 +306,57 @@ export const approveDefinition = mutation({ }); const reviseQuestion = async ( - ctx: { db: any }, + ctx: MutationCtx, work: Doc<"works">, questionId: string, update: { status: "answered" | "withdrawn"; answer?: string } ) => { const current = await ctx.db .query("workDefinitions") - .withIndex("by_work_and_version", (q: any) => + .withIndex("by_work_and_version", (q) => q.eq("workId", work._id).eq("version", work.definitionVersion ?? 0) ) .unique(); - if (!current) throw new ConvexError("Current Definition not found"); + if (!current) { + throw new ConvexError("Current Definition not found"); + } const definition = JSON.parse(current.payloadJson) as WorkDefinition; + const persistedQuestions = await ctx.db + .query("workQuestions") + .withIndex("by_workId_and_definitionVersion", (q) => + q.eq("workId", work._id).eq("definitionVersion", current.version) + ) + .collect(); + if ( + !persistedQuestions.some((question) => question.questionId === questionId) + ) { + throw new ConvexError("Question not found"); + } const next = { ...definition, - questions: definition.questions.map((question) => - question.id === questionId ? { ...question, ...update } : question - ), + questions: persistedQuestions.map((question) => ({ + alternatives: JSON.parse(question.alternativesJson) as string[], + answer: + question.questionId === questionId ? update.answer : question.answer, + id: question.questionId, + impact: question.impact, + prompt: question.prompt, + recommendation: question.recommendation, + status: + question.questionId === questionId ? update.status : question.status, + })), }; return await saveDefinition(ctx, work, JSON.stringify(next), "user"); }; export const answerQuestion = mutation({ - args: { workId: v.id("works"), questionId: v.string(), answer: v.string() }, + args: { answer: v.string(), questionId: v.string(), workId: v.id("works") }, handler: async (ctx, args) => { const work = await requireWork(ctx, args.workId); await requireProjectMember(ctx, work.projectId); const result = await reviseQuestion(ctx, work, args.questionId, { - status: "answered", answer: args.answer, + status: "answered", }); await appendEvent( ctx, @@ -312,7 +369,7 @@ export const answerQuestion = mutation({ }); export const withdrawQuestion = mutation({ - args: { workId: v.id("works"), questionId: v.string() }, + args: { questionId: v.string(), workId: v.id("works") }, handler: async (ctx, args) => { const work = await requireWork(ctx, args.workId); await requireProjectMember(ctx, work.projectId); @@ -335,35 +392,48 @@ export const requestDesign = mutation({ const work = await requireWork(ctx, args.workId); await requireProjectMember(ctx, work.projectId); if ( - work.status !== "designing" || + (work.status !== "designing" && work.status !== "blocked") || work.definitionApprovalVersion !== work.definitionVersion - ) + ) { throw new ConvexError("Definition must be approved before Design"); + } + if (work.status === "blocked") { + await ctx.db.patch(work._id, { + status: "designing", + updatedAt: Date.now(), + }); + } await appendEvent( ctx, work._id, "design.requested", `design-requested:${work.definitionVersion}` ); - return { status: work.status }; + await ctx.scheduler.runAfter(0, plannerRef, { + organizationId: work.organizationId, + workId: work._id, + }); + return { status: "designing" as const }; }, }); const saveDesign = async ( - ctx: { db: any }, + ctx: MutationCtx, work: Doc<"works">, payloadJson: string, createdBy: string ) => { - if (work.status === "executing") + if (work.status === "executing") { throw new ConvexError("Cannot revise Work while a Run is executing"); - if (work.definitionApprovalVersion !== work.definitionVersion) + } + if (work.definitionApprovalVersion !== work.definitionVersion) { throw new ConvexError("Design must bind an approved Definition version"); + } const decoded = await Effect.runPromise( validateDesignPacket({ ...objectPayload(payloadJson), - version: (work.designVersion ?? 0) + 1, definitionVersion: work.definitionVersion, + version: (work.designVersion ?? 0) + 1, }) ).catch((error: unknown) => { throw new ConvexError( @@ -372,51 +442,50 @@ const saveDesign = async ( }); const prior = await ctx.db .query("designPackets") - .withIndex("by_work_and_version", (q: any) => q.eq("workId", work._id)) + .withIndex("by_work_and_version", (q) => q.eq("workId", work._id)) .collect(); - for (const row of prior) - if (row.status === "current") + for (const row of prior) { + if (row.status === "current") { await ctx.db.patch(row._id, { status: "superseded" }); + } + } const designApprovals = await ctx.db .query("workApprovals") - .withIndex("by_work_and_kind", (q: any) => + .withIndex("by_workId_and_kind", (q) => q.eq("workId", work._id).eq("kind", "design") ) .collect(); - for (const approval of designApprovals) - if (approval.status === "active") + for (const approval of designApprovals) { + if (approval.status === "active") { await ctx.db.patch(approval._id, { status: "invalidated" }); + } + } const designId = await ctx.db.insert("designPackets", { - workId: work._id, - version: decoded.version, + createdAt: Date.now(), + createdBy, definitionVersion: decoded.definitionVersion, payloadJson: JSON.stringify(decoded), status: "current", - createdBy, - createdAt: Date.now(), + version: decoded.version, + workId: work._id, }); - const priorSlices = await ctx.db - .query("workSlices") - .withIndex("by_work_and_designVersion", (q: any) => - q.eq("workId", work._id) - ) - .collect(); - for (const slice of priorSlices) await ctx.db.delete(slice._id); - for (const [ordinal, slice] of decoded.slices.entries()) + for (const [ordinal, slice] of decoded.slices.entries()) { await ctx.db.insert("workSlices", { - workId: work._id, + createdAt: Date.now(), designVersion: decoded.version, - sliceId: slice.id, - ordinal, - title: slice.title, objective: slice.objective, observableBehavior: slice.observableBehavior, + ordinal, payloadJson: JSON.stringify(slice), + sliceId: slice.id, status: ordinal === 0 ? "ready" : "planned", + title: slice.title, + workId: work._id, }); + } await ctx.db.patch(work._id, { - designVersion: decoded.version, designApprovalVersion: undefined, + designVersion: decoded.version, status: "awaiting-design-approval", updatedAt: Date.now(), }); @@ -432,7 +501,7 @@ const saveDesign = async ( }; export const saveDesignProposal = mutation({ - args: { workId: v.id("works"), payloadJson: v.string() }, + args: { payloadJson: v.string(), workId: v.id("works") }, handler: async (ctx, args) => { const work = await requireWork(ctx, args.workId); await requireProjectMember(ctx, work.projectId); @@ -444,9 +513,9 @@ export const reviseDesign = saveDesignProposal; export const approveDesign = mutation({ args: { - workId: v.id("works"), definitionVersion: v.number(), designVersion: v.number(), + workId: v.id("works"), }, handler: async (ctx, args) => { const work = await requireWork(ctx, args.workId); @@ -455,24 +524,27 @@ export const approveDesign = mutation({ work.definitionApprovalVersion !== args.definitionVersion || work.designVersion !== args.designVersion || work.status !== "awaiting-design-approval" - ) + ) { throw new ConvexError( "Design approval must bind current Definition and Design versions" ); + } const identity = await ctx.auth.getUserIdentity(); - if (!identity) throw new ConvexError("Authentication required"); + if (!identity) { + throw new ConvexError("Authentication required"); + } await ctx.db.insert("workApprovals", { - workId: work._id, - kind: "design", + approvedAt: Date.now(), + approvedBy: identity.tokenIdentifier, definitionVersion: args.definitionVersion, designVersion: args.designVersion, - approvedBy: identity.subject, - approvedAt: Date.now(), + kind: "design", status: "active", + workId: work._id, }); await ctx.db.patch(work._id, { - status: "ready", designApprovalVersion: args.designVersion, + status: "ready", updatedAt: Date.now(), }); await appendEvent( @@ -486,83 +558,168 @@ export const approveDesign = mutation({ }); export const submitDefinitionProposal = mutation({ - args: { workId: v.id("works"), payloadJson: v.string(), token: v.string() }, + args: { payloadJson: v.string(), token: v.string(), workId: v.id("works") }, handler: async (ctx, args) => { - if (args.token !== env.FLUE_DB_TOKEN) + if (args.token !== env.FLUE_DB_TOKEN) { throw new ConvexError("Invalid agent control token"); + } const work = await requireWork(ctx, args.workId); return await saveDefinition(ctx, work, args.payloadJson, "work-planner"); }, }); export const submitDesignProposal = mutation({ - args: { workId: v.id("works"), payloadJson: v.string(), token: v.string() }, + args: { payloadJson: v.string(), token: v.string(), workId: v.id("works") }, handler: async (ctx, args) => { - if (args.token !== env.FLUE_DB_TOKEN) + if (args.token !== env.FLUE_DB_TOKEN) { throw new ConvexError("Invalid agent control token"); + } const work = await requireWork(ctx, args.workId); return await saveDesign(ctx, work, args.payloadJson, "work-planner"); }, }); export const submitQuestion = mutation({ - args: { workId: v.id("works"), questionJson: v.string(), token: v.string() }, + args: { questionJson: v.string(), token: v.string(), workId: v.id("works") }, handler: async (ctx, args) => { - if (args.token !== env.FLUE_DB_TOKEN) + if (args.token !== env.FLUE_DB_TOKEN) { throw new ConvexError("Invalid agent control token"); + } const work = await requireWork(ctx, args.workId); - if (work.definitionVersion === undefined) + if (work.definitionVersion === undefined) { throw new ConvexError("Work has no Definition to attach a question to"); + } + if ( + work.status !== "defining" && + work.status !== "awaiting-definition-approval" + ) { + throw new ConvexError( + "Questions can only be submitted while the Work is being defined" + ); + } const question = await Effect.runPromise( - Schema.decodeUnknownEffect(WorkQuestion)(JSON.parse(args.questionJson)) + Schema.decodeUnknownEffect(WorkQuestion)(parsePayload(args.questionJson)) ).catch((error: unknown) => { throw new ConvexError( error instanceof Error ? error.message : "Invalid question" ); }); - await ctx.db.insert("workQuestions", { - workId: work._id, - definitionVersion: work.definitionVersion, - questionId: question.id, - prompt: question.prompt, - impact: question.impact, - recommendation: question.recommendation, + const existing = await ctx.db + .query("workQuestions") + .withIndex("by_workId_and_definitionVersion_and_questionId", (q) => + q + .eq("workId", work._id) + .eq("definitionVersion", work.definitionVersion!) + .eq("questionId", question.id) + ) + .unique(); + const questionRow = { alternativesJson: JSON.stringify(question.alternatives), - status: question.status, answer: question.answer, createdAt: Date.now(), - }); + definitionVersion: work.definitionVersion, + impact: question.impact, + prompt: question.prompt, + questionId: question.id, + recommendation: question.recommendation, + status: question.status, + workId: work._id, + }; + if (existing) { + const same = + existing.prompt === questionRow.prompt && + existing.impact === questionRow.impact && + existing.recommendation === questionRow.recommendation && + existing.alternativesJson === questionRow.alternativesJson && + existing.status === questionRow.status && + existing.answer === questionRow.answer; + if (!same) { + throw new ConvexError("Question ID already has different content"); + } + return { accepted: false }; + } + await ctx.db.insert("workQuestions", questionRow); + await appendEvent( + ctx, + work._id, + "question.created", + `question-created:${work.definitionVersion}:${question.id}`, + question.id, + JSON.stringify(question) + ); return { accepted: true }; }, }); +export const recordPlannerFailure = internalMutation({ + args: { error: v.string(), workId: v.id("works") }, + handler: async (ctx, args): Promise => { + const work = await ctx.db.get(args.workId); + if (!work || (work.status !== "defining" && work.status !== "designing")) { + return null; + } + await ctx.db.patch(work._id, { status: "blocked", updatedAt: Date.now() }); + await appendEvent( + ctx, + work._id, + "planner.failed", + `planner-failed:${work._id}:${work.status}`, + undefined, + JSON.stringify({ error: args.error, phase: work.status }) + ); + return null; + }, +}); + export const runPlanner = internalAction({ args: { organizationId: v.id("organizations"), workId: v.id("works") }, handler: async (ctx, args) => { const flueUrl = (env as typeof env & { readonly FLUE_URL?: string }) .FLUE_URL; - if (!flueUrl) return null; + if (!flueUrl) { + await ctx.runMutation(plannerFailureRef, { + error: "FLUE_URL is not configured in Convex", + workId: args.workId, + }); + return null; + } const context = await ctx.runQuery(plannerContextRef, { workId: args.workId, }); - if (!context) return null; + if (!context) { + return null; + } const endpoint = new URL( `agents/work-planner/${encodeURIComponent(String(args.organizationId))}`, `${flueUrl.replace(/\/+$/u, "")}/` ); endpoint.searchParams.set("wait", "result"); - await fetch(endpoint, { - method: "POST", - headers: { - authorization: `Bearer ${env.FLUE_DB_TOKEN}`, - "content-type": "application/json", - "x-zopu-organization-id": String(args.organizationId), - "x-zopu-request-id": `work-planner:${args.workId}`, - }, - body: JSON.stringify({ - message: `Plan Work ${String(args.workId)} titled "${context.title}" with objective "${context.objective}". Current state is ${context.status}. If the Work is defining, submit only a Definition proposal and questions. If the Work is designing, submit only a Design Packet proposal bound to the approved Definition. Never approve or execute.`, - }), - }); + try { + const response = await fetch(endpoint, { + body: JSON.stringify({ + message: `Plan Work ${String(args.workId)} titled "${context.title}" with objective "${context.objective}". Current state is ${context.status}. If the Work is defining, submit only a Definition proposal and questions. If the Work is designing, submit only a Design Packet proposal bound to the approved Definition. Never approve or execute.`, + }), + headers: { + authorization: `Bearer ${env.FLUE_DB_TOKEN}`, + "content-type": "application/json", + "x-zopu-organization-id": String(args.organizationId), + "x-zopu-request-id": `work-planner:${args.workId}`, + }, + method: "POST", + }); + if (response.ok) { + return null; + } + await ctx.runMutation(plannerFailureRef, { + error: `Work Planner request failed (${response.status})`, + workId: args.workId, + }); + } catch (error) { + await ctx.runMutation(plannerFailureRef, { + error: error instanceof Error ? error.message : String(error), + workId: args.workId, + }); + } // The private worker submits typed proposals through Convex mutations; it // never approves or advances Work itself. return null; @@ -608,8 +765,10 @@ export const listForProject = query({ .take(10); const slices = await ctx.db .query("workSlices") - .withIndex("by_work_and_designVersion", (q: any) => - q.eq("workId", work._id) + .withIndex("by_workId_and_designVersion", (q) => + q + .eq("workId", work._id) + .eq("designVersion", work.designVersion ?? 0) ) .collect(); const runs = await ctx.db @@ -633,18 +792,18 @@ export const listForProject = query({ const signals = await Promise.all( attachments.map(async (attachment) => { const signal = await ctx.db.get(attachment.signalId); - if (!signal) return null; + if (!signal) { + return null; + } const sources = await ctx.db .query("signalSources") - .withIndex("by_signalId_and_ordinal", (q: any) => + .withIndex("by_signalId_and_ordinal", (q) => q.eq("signalId", signal._id) ) .collect(); return { createdAt: signal.createdAt, signalId: signal._id, - summary: signal.summary, - title: signal.title, sources: sources .sort((a, b) => a.ordinal - b.ordinal) .map((source) => ({ @@ -653,6 +812,8 @@ export const listForProject = query({ rawText: source.rawTextSnapshot, submissionId: null, })), + summary: signal.summary, + title: signal.title, }; }) ); @@ -664,16 +825,16 @@ export const listForProject = query({ ); return { ...work, - definitions, - designs, - slices: slices.sort((a, b) => a.ordinal - b.ordinal), - runs, - events, - signals: signals.filter((signal) => signal !== null), definition: currentDefinition ? JSON.parse(currentDefinition.payloadJson) : null, + definitions, design: currentDesign ? JSON.parse(currentDesign.payloadJson) : null, + designs, + events, + runs, + signals: signals.filter((signal) => signal !== null), + slices: slices.sort((a, b) => a.ordinal - b.ordinal), }; }) ); diff --git a/packages/backend/convex/works.ts b/packages/backend/convex/works.ts index 07a94b0..09c64b5 100644 --- a/packages/backend/convex/works.ts +++ b/packages/backend/convex/works.ts @@ -8,7 +8,8 @@ import { ConvexError, v } from "convex/values"; import { Effect } from "effect"; import type { Doc, Id } from "./_generated/dataModel"; -import { mutation, type MutationCtx, query } from "./_generated/server"; +import { mutation, query } from "./_generated/server"; +import type { MutationCtx } from "./_generated/server"; import { requireProjectMember } from "./authz"; const requireAgent = (token: string) => { @@ -241,7 +242,6 @@ export const listForProject = query({ return { createdAt: signal.createdAt, signalId: signal._id, - summary: signal.summary, sources: sources .sort((a, b) => a.ordinal - b.ordinal) .map((source) => ({ @@ -250,6 +250,7 @@ export const listForProject = query({ rawText: source.rawTextSnapshot, submissionId: null, })), + summary: signal.summary, title: signal.title, }; }) diff --git a/packages/backend/package.json b/packages/backend/package.json index f3bcba2..e2ccb13 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -8,8 +8,8 @@ "dev": "convex dev --env-file ../../.env", "dev:setup": "convex dev --env-file ../../.env --configure --until-success", "check-types": "tsc --noEmit -p convex/tsconfig.json", - "test": "vitest run", - "test:watch": "vitest" + "test": "CONVEX_SITE_URL=https://convex.test FLUE_DB_TOKEN=test-token SITE_URL=https://site.test vitest run", + "test:watch": "CONVEX_SITE_URL=https://convex.test FLUE_DB_TOKEN=test-token SITE_URL=https://site.test vitest" }, "dependencies": { "@better-auth/expo": "catalog:", @@ -23,7 +23,7 @@ }, "devDependencies": { "@code/config": "workspace:*", - "@types/node": "^24.3.0", + "@types/node": "catalog:", "convex-test": "catalog:", "typescript": "catalog:", "vitest": "catalog:" diff --git a/packages/env/package.json b/packages/env/package.json index b6334c9..5acdb6f 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -19,7 +19,7 @@ }, "devDependencies": { "@code/config": "workspace:*", - "@types/node": "^22.13.14", + "@types/node": "catalog:", "typescript": "catalog:" } } diff --git a/packages/primitives/package.json b/packages/primitives/package.json index b2e2cba..18c9196 100644 --- a/packages/primitives/package.json +++ b/packages/primitives/package.json @@ -16,6 +16,7 @@ "./signal": "./src/signal.ts", "./smoke": "./src/smoke.ts", "./work": "./src/work.ts", + "./work-artifact": "./src/work-artifact.ts", "./work-definition": "./src/work-definition.ts", "./work-design": "./src/work-design.ts", "./work-lifecycle": "./src/work-lifecycle.ts", @@ -35,7 +36,7 @@ }, "devDependencies": { "@code/config": "workspace:*", - "@types/node": "^22.13.14", + "@types/node": "catalog:", "typescript": "catalog:", "vitest": "catalog:" } diff --git a/packages/primitives/package.json.new b/packages/primitives/package.json.new deleted file mode 100644 index 5bd6c8b..0000000 --- a/packages/primitives/package.json.new +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "@code/primitives", - "exports": { - ".": "./src/index.ts", - "./agent-os": "./src/agent-os.ts", - "./git": "./src/git.ts", - "./project": "./src/project.ts", - "./project-issue": "./src/project-issue.ts", - "./project-workspace": "./src/project-workspace.ts", - "./project-work": "./src/project-work.ts", - "./signal": "./src/signal.ts", - "./smoke": "./src/smoke.ts" - }, diff --git a/packages/primitives/src/index.ts b/packages/primitives/src/index.ts index ab5915f..bce942f 100644 --- a/packages/primitives/src/index.ts +++ b/packages/primitives/src/index.ts @@ -10,6 +10,7 @@ export * from "./project-work"; export * from "./signal"; export * from "./smoke"; export * from "./work"; +export * from "./work-artifact"; export * from "./work-definition"; export * from "./work-design"; export * from "./work-lifecycle"; diff --git a/packages/primitives/src/resolver.ts b/packages/primitives/src/resolver.ts index 5fc014d..ea2e5c5 100644 --- a/packages/primitives/src/resolver.ts +++ b/packages/primitives/src/resolver.ts @@ -8,7 +8,12 @@ const Text = Schema.String.check( }) ); -export const RunStatus = Schema.Literals(["ready", "running", "terminal"]); +export const RunStatus = Schema.Literals([ + "ready", + "running", + "terminal", + "cancelled", +]); export type RunStatus = typeof RunStatus.Type; export const AttemptStatus = Schema.Literals([ "queued", diff --git a/packages/primitives/src/work-artifact.test.ts b/packages/primitives/src/work-artifact.test.ts new file mode 100644 index 0000000..eac438c --- /dev/null +++ b/packages/primitives/src/work-artifact.test.ts @@ -0,0 +1,58 @@ +import { Effect } from "effect"; +import { describe, expect, test } from "vitest"; + +import { + decodeWorkArtifactDraft, + decodeWorkDeliveryDraft, +} from "./work-artifact"; + +describe("Work artifact contracts", () => { + test("accepts traceable artifact and delivery metadata", async () => { + await expect( + Effect.runPromise( + decodeWorkArtifactDraft({ + idempotencyKey: "attempt:1:test-report", + kind: "test-report", + metadataJson: "{}", + producer: "fake-harness", + provenanceJson: "{}", + sourceRevision: "abc123", + title: "Focused test report", + verificationStatus: "verified", + }) + ) + ).resolves.toMatchObject({ kind: "test-report" }); + + await expect( + Effect.runPromise( + decodeWorkDeliveryDraft({ + externalId: "42", + idempotencyKey: "delivery:pr:42", + kind: "pull-request", + metadataJson: "{}", + provider: "gitea", + sourceRevision: "abc123", + status: "ready", + target: "main", + url: "https://git.example/pulls/42", + }) + ) + ).resolves.toMatchObject({ kind: "pull-request" }); + }); + + test("rejects unverifiable evidence metadata", async () => { + await expect( + Effect.runPromise( + decodeWorkArtifactDraft({ + idempotencyKey: "attempt:1:test-report", + kind: "test-report", + metadataJson: "not-json", + producer: "fake-harness", + provenanceJson: "{}", + title: "Focused test report", + verificationStatus: "verified", + }) + ) + ).rejects.toThrow(); + }); +}); diff --git a/packages/primitives/src/work-artifact.ts b/packages/primitives/src/work-artifact.ts new file mode 100644 index 0000000..4697f73 --- /dev/null +++ b/packages/primitives/src/work-artifact.ts @@ -0,0 +1,141 @@ +import { Effect, Schema } from "effect"; + +const Text = Schema.String.check( + Schema.makeFilter((value) => value.trim().length > 0, { + expected: "a non-empty string", + }) +); +const JsonText = Schema.String.check( + Schema.makeFilter( + (value) => { + try { + JSON.parse(value); + return true; + } catch { + return false; + } + }, + { expected: "valid JSON text" } + ) +); + +export const WorkArtifactKind = Schema.Literals([ + "definition", + "design", + "diff", + "test-report", + "verification-report", + "runtime-log", + "screenshot", + "video", + "commit", + "branch", + "pull-request", + "preview", + "deployment", + "other", +]); +export type WorkArtifactKind = typeof WorkArtifactKind.Type; + +export const ArtifactVerificationStatus = Schema.Literals([ + "unverified", + "verified", + "rejected", +]); +export type ArtifactVerificationStatus = typeof ArtifactVerificationStatus.Type; + +export const WorkArtifactDraft = Schema.Struct({ + contentHash: Schema.optional(Text), + environmentId: Schema.optional(Text), + idempotencyKey: Text, + kind: WorkArtifactKind, + metadataJson: JsonText, + producer: Text, + provenanceJson: JsonText, + sourceRevision: Schema.optional(Text), + title: Text, + uri: Schema.optional(Text), + verificationStatus: ArtifactVerificationStatus, +}); +export type WorkArtifactDraft = typeof WorkArtifactDraft.Type; + +export const WorkDeliveryKind = Schema.Literals([ + "branch", + "commit", + "pull-request", + "preview", + "deployment", +]); +export type WorkDeliveryKind = typeof WorkDeliveryKind.Type; + +export const WorkDeliveryStatus = Schema.Literals([ + "recorded", + "ready", + "approved", + "delivered", + "failed", + "cancelled", +]); +export type WorkDeliveryStatus = typeof WorkDeliveryStatus.Type; + +export const WorkDeliveryDraft = Schema.Struct({ + externalId: Text, + idempotencyKey: Text, + kind: WorkDeliveryKind, + metadataJson: JsonText, + provider: Text, + sourceRevision: Text, + status: WorkDeliveryStatus, + target: Text, + url: Schema.optional(Text), +}); +export type WorkDeliveryDraft = typeof WorkDeliveryDraft.Type; + +export class WorkArtifactError extends Schema.TaggedErrorClass()( + "WorkArtifactError", + { message: Schema.String } +) {} + +const decode = (schema: Schema.Codec, input: unknown) => + Schema.decodeUnknownEffect(schema)(input).pipe( + Effect.mapError( + (cause) => new WorkArtifactError({ message: cause.message }) + ) + ); + +export const decodeWorkArtifactDraft = Effect.fn("Work.decodeArtifactDraft")( + function* decodeArtifactDraft(input: unknown) { + const draft = yield* decode(WorkArtifactDraft, input); + if ( + draft.verificationStatus === "verified" && + draft.sourceRevision === undefined + ) { + return yield* Effect.fail( + new WorkArtifactError({ + message: "Verified artifacts must bind an exact source revision", + }) + ); + } + return draft; + } +); + +export const decodeWorkDeliveryDraft = Effect.fn("Work.decodeDeliveryDraft")( + (input: unknown) => decode(WorkDeliveryDraft, input) +); + +const DELIVERY_TRANSITIONS: Readonly< + Record +> = { + approved: ["delivered", "failed", "cancelled"], + cancelled: [], + delivered: [], + failed: [], + ready: ["approved", "delivered", "failed", "cancelled"], + recorded: ["ready", "failed", "cancelled"], +}; + +export const canTransitionWorkDelivery = ( + from: WorkDeliveryStatus, + to: WorkDeliveryStatus +): boolean => DELIVERY_TRANSITIONS[from].includes(to); diff --git a/packages/primitives/src/work-definition.ts b/packages/primitives/src/work-definition.ts index a2abe8d..51d81ea 100644 --- a/packages/primitives/src/work-definition.ts +++ b/packages/primitives/src/work-definition.ts @@ -59,8 +59,8 @@ export class DefinitionError extends Schema.TaggedErrorClass()( } ) {} -export const validateDefinition = Effect.fn("Work.validateDefinition")( - function* validateDefinition(input: unknown) { +export const decodeDefinition = Effect.fn("Work.decodeDefinition")( + function* decodeDefinition(input: unknown) { const definition = yield* Schema.decodeUnknownEffect(WorkDefinition)( input ).pipe( @@ -69,6 +69,25 @@ export const validateDefinition = Effect.fn("Work.validateDefinition")( new DefinitionError({ message: cause.message, reason: "Invalid" }) ) ); + const questionIds = new Set(); + for (const question of definition.questions) { + if (questionIds.has(question.id)) { + return yield* Effect.fail( + new DefinitionError({ + message: `Question ID must be unique: ${question.id}`, + reason: "Invalid", + }) + ); + } + questionIds.add(question.id); + } + return definition; + } +); + +export const validateDefinition = Effect.fn("Work.validateDefinition")( + function* validateDefinition(input: unknown) { + const definition = yield* decodeDefinition(input); const blocked = definition.questions.some( (question) => question.status === "open" && question.impact === "high" ); diff --git a/packages/primitives/src/work-design.ts b/packages/primitives/src/work-design.ts index cbd6b8a..13fa501 100644 --- a/packages/primitives/src/work-design.ts +++ b/packages/primitives/src/work-design.ts @@ -59,6 +59,7 @@ export class DesignError extends Schema.TaggedErrorClass()( "Invalid", "NoObservableSlices", "DefinitionMismatch", + "InvalidSliceGraph", ]), } ) {} @@ -73,8 +74,10 @@ export const validateDesignPacket = Effect.fn("Work.validateDesignPacket")( ); if ( design.slices.length === 0 || + design.slices.length > 4 || design.slices.some( (slice) => + slice.codeBoundaries.length === 0 || slice.observableBehavior.trim().length === 0 || slice.evidenceRequirements.length === 0 || slice.verification.length === 0 @@ -88,6 +91,24 @@ export const validateDesignPacket = Effect.fn("Work.validateDesignPacket")( }) ); } + const seen = new Set(); + for (const slice of design.slices) { + if ( + seen.has(slice.id) || + slice.dependsOn.some( + (dependency) => dependency === slice.id || !seen.has(dependency) + ) + ) { + return yield* Effect.fail( + new DesignError({ + message: + "Slice IDs must be unique and dependencies must reference earlier slices", + reason: "InvalidSliceGraph", + }) + ); + } + seen.add(slice.id); + } return design; } ); diff --git a/packages/primitives/src/work-resolution.test.ts b/packages/primitives/src/work-resolution.test.ts index 537862f..55bf862 100644 --- a/packages/primitives/src/work-resolution.test.ts +++ b/packages/primitives/src/work-resolution.test.ts @@ -3,7 +3,7 @@ import { describe, expect, test } from "vitest"; import { FakeHarnessLive } from "./harness-runtime"; import { defaultCodingKitV0, resolveOutcome, shouldRetry } from "./resolver"; -import { validateDefinition } from "./work-definition"; +import { decodeDefinition, validateDefinition } from "./work-definition"; import { validateDesignPacket } from "./work-design"; import { canTransitionWork } from "./work-lifecycle"; @@ -37,11 +37,25 @@ const probeOutcome = ( describe("work resolution contracts", () => { test("high-impact open questions block definition approval", async () => { + await expect( + Effect.runPromise(decodeDefinition(definition)) + ).resolves.toEqual(definition); await expect( Effect.runPromise(validateDefinition(definition)) ).rejects.toThrow(/High-impact/u); }); + test("question identities are unique within a Definition version", async () => { + await expect( + Effect.runPromise( + decodeDefinition({ + ...definition, + questions: [definition.questions[0], definition.questions[0]], + }) + ) + ).rejects.toThrow(/Question ID must be unique/u); + }); + test("observable slices and terminal fake outcomes are enforced", async () => { const approved = await Effect.runPromise( validateDefinition({ ...definition, questions: [] }) diff --git a/packages/primitives/src/work.ts b/packages/primitives/src/work.ts index 1133000..ee9070b 100644 --- a/packages/primitives/src/work.ts +++ b/packages/primitives/src/work.ts @@ -96,6 +96,7 @@ export const WorkEventKind = Schema.Literals([ "definition.revised", "definition.approved", "definition.invalidated", + "question.created", "question.answered", "question.withdrawn", "design.requested", @@ -103,12 +104,21 @@ export const WorkEventKind = Schema.Literals([ "design.revised", "design.approved", "design.invalidated", + "planner.failed", + "slice.started", + "slice.completed", + "slice.ready", "run.started", + "run.completed", "run.cancelled", "attempt.claimed", "attempt.event", "attempt.completed", "attempt.reconciled", + "resolver.decided", + "artifact.recorded", + "delivery.recorded", + "delivery.updated", ]); export type WorkEventKind = typeof WorkEventKind.Type; diff --git a/packages/ui/package.json b/packages/ui/package.json index 32c472a..1fb2859 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -30,15 +30,15 @@ "shadcn": "^4.12.0", "shiki": "^4.3.1", "sonner": "catalog:", - "streamdown": "^2.5.0", + "streamdown": "catalog:", "tailwind-merge": "catalog:", "tw-animate-css": "^1.4.0", "use-stick-to-bottom": "^1.1.6" }, "devDependencies": { "@code/config": "workspace:*", - "@tailwindcss/postcss": "^4.3.2", - "@types/react": "^19.2.17", + "@tailwindcss/postcss": "catalog:", + "@types/react": "catalog:", "@types/react-dom": "catalog:", "tailwindcss": "catalog:", "typescript": "catalog:" diff --git a/vite.config.ts b/vite.config.ts index d307769..3ff8a63 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,6 +7,7 @@ export default defineConfig({ "**/node_modules/**", ".agents/skills/**", "repos/**", + "scripts/**", "apps/daemon/**", "apps/desktop/**", "apps/native/**", @@ -28,6 +29,7 @@ export default defineConfig({ "**/node_modules/**", ".agents/skills/**", "repos/**", + "scripts/**", "apps/daemon/**", "apps/desktop/**", "apps/native/**",