diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 7516b0d2636..f494ce9a246 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -73,7 +73,6 @@ "@hono/node-server": "^1.14.1", "@hookform/resolvers": "^5.2.2", "@lezer/highlight": "^1.2.3", - "@mastra/core": "1.25.0", "@parcel/watcher": "^2.5.6", "@pierre/diffs": "1.1.3", "@radix-ui/react-dialog": "^1.1.15", @@ -201,7 +200,7 @@ "lowdb": "^7.0.1", "lowlight": "^3.3.0", "lucide-react": "^0.563.0", - "mastracode": "0.14.0", + "mastracode": "0.9.2", "nanoid": "^5.1.6", "node-addon-api": "^7.1.0", "node-pty": "1.1.0", diff --git a/apps/desktop/plans/done/20260415-v2-host-service-ai-branch-naming-test-plan.md b/apps/desktop/plans/done/20260415-v2-host-service-ai-branch-naming-test-plan.md deleted file mode 100644 index e6f2cffb604..00000000000 --- a/apps/desktop/plans/done/20260415-v2-host-service-ai-branch-naming-test-plan.md +++ /dev/null @@ -1,86 +0,0 @@ -# Manual Testing Plan — PR #3517 - -## Prerequisites -- Desktop dev running (`bun dev` from apps/desktop, or full `bun dev` from root) -- At least one project configured with a git repo - -## 1. v1 AI Branch Naming (API key path) - -**Setup**: `ANTHROPIC_API_KEY` or `OPENAI_API_KEY` set in env (or stored via Settings > Models). - -| Step | Expected | -|---|---| -| Open v1 new-workspace modal (Cmd+N) | Modal opens | -| Type a prompt: "fix dropdown alignment bug" | Text entered | -| Submit (Enter or click Create) | Modal closes, pending workspace shows "Generating branch…" briefly | -| Wait for workspace to initialize | Branch name is AI-generated kebab-case (e.g. `fix-dropdown-alignment`), not random words | -| Check worktree | Branch exists locally | - -## 2. v1 AI Branch Naming (no credentials) - -**Setup**: unset `ANTHROPIC_API_KEY` and `OPENAI_API_KEY` from env. No stored API keys in Settings > Models. - -| Step | Expected | -|---|---| -| Create workspace with prompt | Branch name falls back to random friendly name (e.g. `pickle-streetcar`) or prompt-derived slug | -| No error toast | Degradation is silent | - -## 3. v1 Workspace Auto-Rename - -**Setup**: API key available. - -| Step | Expected | -|---|---| -| Create workspace with prompt "refactor auth middleware" | Workspace title updates to AI-generated name (e.g. "Refactor Auth Middleware") after a few seconds | -| If no API key available | Title falls back to prompt text or friendly name | - -## 4. Anthropic OAuth Auto-Refresh (from #3510) - -**Setup**: Anthropic OAuth configured (Claude Max). Requires waiting for token expiry or manual simulation. - -| Step | Expected | -|---|---| -| Sign in to Anthropic via OAuth in Settings > Models | "Active" badge appears | -| Force-expire: edit `~/Library/Application Support/mastracode/auth.json`, set `anthropic.expires` to a past timestamp | — | -| Send a chat message | Chat succeeds silently (token auto-refreshed via `authStorage.getApiKey`). No "Reconnect" prompt. | -| If refresh token is also invalid | Falls to expired state, "Expired" badge + "Reconnect" button appears | -| Check terminal for `[chat-service] Anthropic OAuth refresh failed` | Logged if refresh fails | - -## 5. Settings > Models Page - -| Step | Expected | -|---|---| -| Navigate to Settings > Models | Page loads with Anthropic + OpenAI sections, each with provider icon in header | -| Each provider shows a single card with OAuth row + API Key row | OAuth row: label + badge + action. API Key row: input + contextual buttons | -| **Disconnected state** | "Not connected" badge, primary "Connect" button, no Save/Clear buttons | -| **API key flow**: type key → Save appears → click Save | "API key updated" toast, "Active" badge, "Logout" button appears | -| **API key flow**: click Clear | Key removed, badge reverts to "Not connected" | -| **OAuth flow**: click Connect → complete in browser | "Active" badge, "Logout" button | -| **OAuth flow**: click Logout | Badge reverts, Connect button returns | -| **API key + OAuth**: set API key, then connect OAuth, then disconnect OAuth | API key should survive the OAuth cycle (backup/restore workaround) | -| **OpenAI dialog** auto-opens browser on Connect | No manual "Open browser" step needed | -| **Copy URL** button shows "Copied!" feedback for 2s | — | - -## 6. Production Build - -| Step | Expected | -|---|---| -| `bun run compile:app` (from apps/desktop) | Succeeds. `get-small-model` chunk ~1.2 MB, no 20 MB chunk. | -| `bun run copy:native-modules` | Succeeds | -| `bun run validate:native-runtime` | All checks pass | -| `npx electron dist/main/index.js` | Main process boots (renderer 404 expected in non-packaged mode). No onnxruntime error. | - -## 7. Host-Service Procedure (dormant — future v2) - -Not yet wired to UI. Verify via tRPC playground or direct call if available: - -| Step | Expected | -|---|---| -| Call `workspaceCreation.generateBranchName({ projectId, prompt: "fix auth bug" })` | Returns `{ branchName: "fix-auth-bug" }` or similar (requires API key in host-service env) | -| Call with empty prompt | Returns `{ branchName: null }` | -| Call with no API key in env | Returns `{ branchName: null }` (graceful fallback) | - -## Known Regressions (documented, accepted) - -- **OAuth-only users** (Claude Max / OpenAI Codex without stored API key) get random branch names and prompt-derived workspace titles for small-model tasks. Main chat retains full OAuth. -- **Upstream dependency**: API key storage slot collision with OAuth is worked around via backup/restore. Proper fix tracked at mastra-ai/mastra#15483. diff --git a/apps/desktop/plans/done/20260415-v2-host-service-ai-branch-naming.md b/apps/desktop/plans/done/20260415-v2-host-service-ai-branch-naming.md deleted file mode 100644 index 5a88bb50813..00000000000 --- a/apps/desktop/plans/done/20260415-v2-host-service-ai-branch-naming.md +++ /dev/null @@ -1,168 +0,0 @@ -# V2 Workspace Modal — Host-Service AI Branch Naming - -Port v1's AI branch-name generation into v2's workspace modal, routed through host-service. Approach: **use upstream `mastracode`'s `resolveModel`** via a lightweight `createMastraCode({ disableMcp: true, disableHooks: true })` singleton. Delete our small-model abstraction; keep OAuth parity (Claude Max + Codex) because mastracode handles it internally. - -## Completed - -- ✅ Bumped `mastracode` 0.9.2 → **0.14.0** (+ transitive `@mastra/core` 1.16 → 1.25). Typecheck + tests green. Removed `minimumReleaseAge` from `bunfig.toml`. - -## Target architecture - -``` -v2 useSubmitWorkspace - └─> client.workspaceCreation.generateBranchName.mutate({ projectId, prompt }) - └─> generateBranchNameFromPrompt(...) [host-service] - └─> getSmallModel() [shared helper] - └─> resolveModel(modelId) from mastracode - (full auth: API-key + keychain + OAuth middleware) -``` - -Desktop v1's existing `ai-branch-name.ts` migrates to the same `getSmallModel` helper — single implementation, two consumers. - -## Shared helper - -`packages/chat/src/server/shared/small-model/get-small-model.ts`: - -```ts -import { createAuthStorage, createMastraCode } from "mastracode"; -import type { MastraLanguageModel } from "@mastra/core/llm"; - -const ANTHROPIC_SMALL = "anthropic/claude-haiku-4-5-20251001"; -const OPENAI_SMALL = "openai/gpt-4o-mini"; - -type Resolver = Awaited>["resolveModel"]; -let initPromise: Promise | null = null; - -function getResolver(): Promise { - if (!initPromise) { - initPromise = createMastraCode({ disableMcp: true, disableHooks: true }) - .then((r) => r.resolveModel); - } - return initPromise; -} - -function pickSmallModelId(): string | null { - const auth = createAuthStorage(); - auth.reload(); - if (auth.has("anthropic")) return ANTHROPIC_SMALL; - if (auth.has("openai")) return OPENAI_SMALL; - return null; -} - -export async function getSmallModel(): Promise { - const modelId = pickSmallModelId(); - if (!modelId) return null; - const resolveModel = await getResolver(); - return resolveModel(modelId) as MastraLanguageModel; -} -``` - -Module-level promise caches the mastracode init (one-time cost per process). Credential check is per-call (cheap, in-memory). - -## Code-removal budget - -| File | LOC | Fate | -|---|---|---| -| `apps/desktop/src/lib/ai/call-small-model.ts` | 184 | delete | -| `apps/desktop/src/lib/ai/call-small-model.test.ts` | 399 | delete | -| `apps/desktop/src/lib/ai/provider-diagnostics.ts` | 89 | delete if no other consumer | -| `packages/chat/src/server/desktop/small-model/small-model.ts` | 146 | delete | -| `packages/chat/src/server/desktop/small-model/small-model.test.ts` | 391 | delete | -| `packages/chat/src/server/desktop/title-generation/title-generation.ts` | 99 | trim (~50, drop streaming variant) | -| `packages/chat/src/server/desktop/auth/anthropic/anthropic.ts` | 232 | trim (~50, keep OAuth login helpers chat-service uses) | -| `packages/chat/src/server/desktop/auth/openai/openai.ts` | 99 | trim (~30) | -| `apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-branch-name.ts` | 117 | rewrite → ~60 | -| New `shared/small-model/get-small-model.ts` | — | +50 | - -Net: **~1200 lines removed**. - ---- - -## Step 1 — Shared helper + migrate v1 branch naming - -### Actionable tasks -1. Create `packages/chat/src/server/shared/small-model/{get-small-model.ts, index.ts}` with the helper above. -2. Update `packages/chat/src/server/desktop/index.ts` barrel if needed; new helper lives in `shared/` and is imported directly from `@superset/chat/server/shared/small-model` — no re-export from desktop. -3. Rewrite `apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-branch-name.ts`: - - Replace `callSmallModel` + provider branching with `getSmallModel()` + `generateText({ model, system, prompt })`. - - Keep `BRANCH_NAME_INSTRUCTIONS`, `resolveConflict`, `sanitizeBranchNameWithMaxLength`. -4. Grep for `callSmallModel`, `SmallModelProvider`, `getDefaultSmallModelProviders`, `generateTitleFromMessageWithStreamingModel`: - - Rewrite each consumer to `getSmallModel` + `generateText` (or Mastra Agent if the caller wants tracing). -5. Delete: - - `apps/desktop/src/lib/ai/call-small-model.ts` + test. - - `packages/chat/src/server/desktop/small-model/small-model.ts` + test + `index.ts`. - - `generateTitleFromMessageWithStreamingModel` from `title-generation.ts`. -6. `apps/desktop/src/lib/ai/provider-diagnostics.ts` — grep for consumers; delete if only `call-small-model.ts` uses it. Otherwise leave. -7. Audit `auth/anthropic` and `auth/openai`: keep exports chat-service uses for OAuth login UI; delete any credential-resolution helpers used only for small-model. -8. Run `bun run typecheck` + focused tests (chat-service, ai-branch-name). Fix breaks. -9. Smoke: launch desktop, create v1 workspace with a prompt, verify AI branch naming still works (both API key and OAuth paths). - -### Risks (step 1) -- **mastracode init side effects**: `createMastraCode` with disabled MCP/hooks still initializes storage, auto-detects project, etc. Confirm startup stays under ~200ms and doesn't create unwanted files. If it tries to touch a DB/libsql, pass an explicit `storage` config. -- **Second init conflict**: chat service already calls `createMastraCode` for its runtime. Running a second one for small-model might duplicate auth-storage singletons or compete for files. Mitigation: verify `createMastraCode` is side-effect-safe when called twice; if not, share the existing chat runtime's resolver. -- **Credential regression**: `authStorage.has("anthropic")` must cover all the "credential present" cases our current `getAnthropicCredentialsFromAnySource` covers (env vars, stored API keys, OAuth). Audit before replacing. - ---- - -## Step 2 — Host-service procedure - -### Actionable tasks -1. Port `sanitizeBranchNameWithMaxLength` (`apps/desktop/src/shared/utils/branch.ts`) and `resolveBranchPrefix` (`apps/desktop/src/lib/trpc/routers/workspaces/utils/branch-prefix.ts`) into `packages/host-service/src/trpc/router/workspace-creation/utils/`. -2. Create `packages/host-service/src/trpc/router/workspace-creation/utils/ai-branch-name.ts` — same helper as desktop's rewritten v1, imports `getSmallModel` from `@superset/chat/server/shared/small-model`. -3. Add to `workspace-creation.ts`: - ```ts - generateBranchName: publicProcedure - .input(z.object({ projectId: z.string(), prompt: z.string() })) - .mutation(async ({ input }) => { - const trimmed = input.prompt.trim(); - if (!trimmed) return { branchName: null }; - const project = /* existing project lookup */; - const existingBranches = /* existing branch listing */; - const prefix = await resolveBranchPrefix(project, existingBranches); - const branchName = await generateBranchNameFromPrompt(trimmed, existingBranches, prefix); - return { branchName }; - }), - ``` -4. Delete `packages/host-service/src/providers/model-providers/LocalModelProvider/utils/resolveAnthropicCredential.ts` + `resolveOpenAICredential.ts` if unused after step (LocalModelProvider no longer needs them since auth flows through mastracode). -5. Run typecheck + host-service tests. - ---- - -## Step 3 — Wire v2 - -### Actionable tasks -1. Update `apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/hooks/useSubmitWorkspace/useSubmitWorkspace.ts`: - - Compute `willGenerateAIName = !draft.branchNameEdited && !!trimmedPrompt && !draft.linkedPR`. - - Fallback via `resolveNames(draft)` (unchanged). - - Insert pending row with status `"generating-branch"` if `willGenerateAIName`. - - Close + navigate (unchanged). - - If `willGenerateAIName`, race `client.workspaceCreation.generateBranchName.mutate(...)` vs 30s timeout: - - success → update pending row `branchName` + status `"creating"`. - - auth error → toast + abort + remove pending row. - - other/timeout → toast `"Using random branch name..."`, keep fallback name. - - Call `client.workspaceCreation.create(...)` with resolved `branchName`. -2. Add `"generating-branch"` to `pendingWorkspaces` status union (`packages/local-db/src/schema/schema.ts`). Drizzle migration. -3. Update pending page UI (`apps/desktop/src/renderer/routes/_authenticated/_dashboard/pending/$pendingId/page.tsx`) to render "Naming your branch…" for that status. - ---- - -## Effort - -| Step | Effort | -|---|---| -| 0. mastracode upgrade | ✅ done | -| 1. Shared helper + v1 migration + deletions | 2–3 hrs | -| 2. Host-service procedure | 1–1.5 hrs | -| 3. v2 wiring + pending UI | 1–2 hrs | -| **Remaining** | **~4–6.5 hrs** | - -## Risks - -- **mastracode init side effects** at singleton init (see step 1). -- **Remote host-service API-key availability**: remote hosts need `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` set; otherwise v2 on remote hosts falls back to random-name. Document. -- **OAuth parity in host-service**: host-service can't do an interactive OAuth flow. `createAuthStorage().loadStoredApiKeysIntoEnv(...)` loads stored API keys but NOT OAuth tokens into env. For host-service, OAuth-only users get random names. -- **Diagnostics UI**: removing `provider-diagnostics.ts` removes mid-call `reportProviderIssue` signals. Audit settings UI for providers; they may source signals from chat-service regardless. - -## Out of scope -- Live/debounced ghost suggestion in v2 branch-name input. -- Retiring v1's desktop-tRPC `generateBranchName` procedure (it becomes a proxy over the shared helper; deleting it is a follow-up). diff --git a/apps/desktop/plans/done/20260417-fix-api-key-storage-slot.md b/apps/desktop/plans/done/20260417-fix-api-key-storage-slot.md deleted file mode 100644 index d31b76a60bb..00000000000 --- a/apps/desktop/plans/done/20260417-fix-api-key-storage-slot.md +++ /dev/null @@ -1,57 +0,0 @@ -# Fix: API keys overwritten by OAuth connect/disconnect cycle - -## Problem - -Settings > Models "API key" field writes to the same auth.json slot as OAuth. When a user: -1. Saves an API key → `authStorage.set("anthropic", { type: "api_key", key: "sk-..." })` -2. Connects OAuth → `authStorage.login("anthropic", ...)` overwrites with `{ type: "oauth", ... }` -3. Disconnects OAuth → `authStorage.remove("anthropic")` deletes everything - -The API key is lost. The model picker shows "disabled" even though the user saved a key. - -Chat still works because `createMastraCode`'s model resolution reads from env vars / external config independently of this status check. - -## Root cause - -`setApiKeyForProvider` uses `authStorage.set(providerId, credential)` which writes to the main provider slot. OAuth also writes to the same slot. They collide. - -mastracode's `AuthStorage` has **two separate storage mechanisms**: -- `set(providerId, credential)` / `get(providerId)` → main slot (`"anthropic"` in auth.json) -- `setStoredApiKey(providerId, key)` / `getStoredApiKey(providerId)` → dedicated API key slot (`"apikey:anthropic"` in auth.json) - -We're using the wrong one for API keys. - -## Fix - -### `auth-storage-utils.ts` - -**`setApiKeyForProvider`**: switch from `authStorage.set()` to `authStorage.setStoredApiKey()`. - -**`clearApiKeyForProvider`**: clear the `apikey:` slot. Use `authStorage.set("apikey:", ...)` with a removal, or check `hasStoredApiKey` and handle accordingly. Since mastracode doesn't expose `removeStoredApiKey`, use `authStorage.remove("apikey:")`. - -**`resolveAuthMethodForProvider`**: after checking the main slot, also check `authStorage.hasStoredApiKey(providerId)` as a fallback → return `"api_key"`. - -### `chat-service.ts` - -No changes needed — `getAnthropicAuthStatus` and `getOpenAIAuthStatus` already delegate to `resolveAuthMethodForProvider` which will now find stored API keys. - -The `setStoredAnthropicApiKeyFromEnvVariables` helper in `disconnectAnthropicOAuth` should also use `setStoredApiKey` for consistency, but it's less critical since it reads from the env config file. - -## Behavior after fix - -| Action | `"anthropic"` (main) | `"apikey:anthropic"` (dedicated) | -|---|---|---| -| Save API key (Settings) | unchanged | written | -| Connect OAuth | overwritten with OAuth | survives | -| Disconnect OAuth | removed | survives | -| Auth status check | reads both | ← | - -## Side effect: small-model tasks - -`getSmallModel` reads `apikey:anthropic` from auth.json directly. Currently, API keys saved via Settings go to the main `"anthropic"` slot, so `getSmallModel` doesn't find them. After this fix, saved API keys land in `apikey:anthropic` where `getSmallModel` already looks → branch naming works for Settings-saved keys without any additional change. - -## Scope - -- `packages/chat/src/server/desktop/chat-service/auth-storage-utils.ts` (~15 LOC changed) -- `packages/chat/src/server/desktop/chat-service/chat-service.ts` — `setStoredAnthropicApiKeyFromEnvVariables` updated for consistency (~2 LOC) -- Tests in `chat-service.test.ts` if any mock `setApiKeyForProvider` behavior diff --git a/apps/desktop/runtime-dependencies.ts b/apps/desktop/runtime-dependencies.ts index 8b02f1f71ec..18d5e5b2e4b 100644 --- a/apps/desktop/runtime-dependencies.ts +++ b/apps/desktop/runtime-dependencies.ts @@ -108,7 +108,7 @@ export const mainExternalizedDependencies = [ // mastracode transitively loads @mastra/fastembed → onnxruntime-node, whose // native binding is loaded via a dynamic `require` that @rollup/plugin-commonjs // can't resolve at bundle time. Externalizing lets Node handle the require at - // runtime from node_modules. Also keeps the bundle size sane (~20 MB chunk). + // runtime from node_modules. "mastracode", ]; diff --git a/apps/desktop/src/lib/ai/call-small-model.test.ts b/apps/desktop/src/lib/ai/call-small-model.test.ts new file mode 100644 index 00000000000..ff133f56a18 --- /dev/null +++ b/apps/desktop/src/lib/ai/call-small-model.test.ts @@ -0,0 +1,399 @@ +import { beforeEach, describe, expect, it, mock } from "bun:test"; +import type { SmallModelProvider } from "@superset/chat/server/desktop"; + +const getDefaultSmallModelProvidersMock = mock((): SmallModelProvider[] => []); + +mock.module("@superset/chat/server/desktop", () => ({ + getDefaultSmallModelProviders: getDefaultSmallModelProvidersMock, + generateTitleFromMessage: mock(async () => null), + generateTitleFromMessageWithStreamingModel: mock(async () => null), +})); + +const { callSmallModel } = await import("./call-small-model"); + +describe("callSmallModel", () => { + beforeEach(() => { + getDefaultSmallModelProvidersMock.mockReset(); + getDefaultSmallModelProvidersMock.mockReturnValue([]); + }); + + it("skips unsupported credentials and falls through to the next working provider", async () => { + const { result, attempts } = await callSmallModel({ + providers: [ + { + id: "openai", + name: "OpenAI", + resolveCredentials: () => ({ + apiKey: "oauth-token", + kind: "oauth", + source: "auth-storage", + }), + isSupported: () => ({ + supported: false, + reason: "unsupported oauth", + }), + createModel: () => "openai-model", + }, + { + id: "anthropic", + name: "Anthropic", + resolveCredentials: () => ({ + apiKey: "anthropic-token", + kind: "oauth", + source: "auth-storage", + }), + isSupported: () => ({ supported: true }), + createModel: () => "anthropic-model", + }, + ], + invoke: async ({ providerId, model }) => + providerId === "anthropic" && model === "anthropic-model" + ? "generated title" + : null, + }); + + expect(result).toBe("generated title"); + expect(attempts).toEqual([ + { + providerId: "openai", + providerName: "OpenAI", + credentialKind: "oauth", + credentialSource: "auth-storage", + issue: { + code: "unsupported_credentials", + capability: "small_model_tasks", + remediation: "add_api_key", + message: "unsupported oauth", + }, + outcome: "unsupported-credentials", + reason: "unsupported oauth", + }, + { + providerId: "anthropic", + providerName: "Anthropic", + credentialKind: "oauth", + credentialSource: "auth-storage", + outcome: "succeeded", + }, + ]); + }); + + it("allows OpenAI OAuth credentials on the small-model path", async () => { + const { result, attempts } = await callSmallModel({ + providers: [ + { + id: "openai", + name: "OpenAI", + resolveCredentials: () => ({ + apiKey: "oauth-token", + kind: "oauth", + source: "auth-storage", + }), + isSupported: () => ({ supported: true }), + createModel: () => "openai-model", + }, + ], + invoke: async ({ providerId, model }) => + providerId === "openai" && model === "openai-model" + ? "generated title" + : null, + }); + + expect(result).toBe("generated title"); + expect(attempts).toEqual([ + { + providerId: "openai", + providerName: "OpenAI", + credentialKind: "oauth", + credentialSource: "auth-storage", + outcome: "succeeded", + }, + ]); + }); + + it("treats empty-string results as successful model output", async () => { + const { result, attempts } = await callSmallModel({ + providers: [ + { + id: "openai", + name: "OpenAI", + resolveCredentials: () => ({ + apiKey: "oauth-token", + kind: "oauth", + source: "auth-storage", + }), + isSupported: () => ({ supported: true }), + createModel: () => "openai-model", + }, + ], + invoke: async () => "", + }); + + expect(result).toBe(""); + expect(attempts).toEqual([ + { + providerId: "openai", + providerName: "OpenAI", + credentialKind: "oauth", + credentialSource: "auth-storage", + outcome: "succeeded", + }, + ]); + }); + + it("classifies missing OpenAI scopes as a canonical provider issue", async () => { + const { result, attempts } = await callSmallModel({ + providers: [ + { + id: "openai", + name: "OpenAI", + resolveCredentials: () => ({ + apiKey: "oauth-token", + kind: "oauth", + source: "auth-storage", + }), + isSupported: () => ({ supported: true }), + createModel: () => "openai-model", + }, + ], + invoke: async () => { + throw new Error( + "You have insufficient permissions for this operation. Missing scopes: api.responses.write.", + ); + }, + }); + + expect(result).toBeNull(); + expect(attempts).toEqual([ + { + providerId: "openai", + providerName: "OpenAI", + credentialKind: "oauth", + credentialSource: "auth-storage", + issue: { + code: "missing_scope", + capability: "small_model_tasks", + remediation: "check_permissions", + scope: "api.responses.write", + message: "OpenAI needs permission api.responses.write", + }, + outcome: "failed", + reason: + "You have insufficient permissions for this operation. Missing scopes: api.responses.write.", + }, + ]); + }); + + it("returns null after exhausting providers", async () => { + const { result, attempts } = await callSmallModel({ + providers: [ + { + id: "anthropic", + name: "Anthropic", + resolveCredentials: () => null, + isSupported: () => ({ supported: true }), + createModel: () => "unused", + }, + { + id: "openai", + name: "OpenAI", + resolveCredentials: () => ({ + apiKey: "api-key", + kind: "apiKey", + source: "auth-storage", + }), + isSupported: () => ({ supported: true }), + createModel: () => "openai-model", + }, + ], + invoke: async () => null, + }); + + expect(result).toBeNull(); + expect(attempts).toEqual([ + { + providerId: "anthropic", + providerName: "Anthropic", + outcome: "missing-credentials", + }, + { + providerId: "openai", + providerName: "OpenAI", + credentialKind: "apiKey", + credentialSource: "auth-storage", + outcome: "empty-result", + }, + ]); + }); + + it("skips expired oauth credentials before attempting the request", async () => { + const { result, attempts } = await callSmallModel({ + providers: [ + { + id: "anthropic", + name: "Anthropic", + resolveCredentials: () => ({ + apiKey: "expired-oauth", + kind: "oauth", + source: "config", + expiresAt: Date.now() - 1_000, + }), + isSupported: () => ({ supported: true }), + createModel: () => "anthropic-model", + }, + ], + invoke: async () => "should-not-run", + }); + + expect(result).toBeNull(); + expect(attempts).toEqual([ + { + providerId: "anthropic", + providerName: "Anthropic", + credentialKind: "oauth", + credentialSource: "config", + issue: { + code: "expired", + capability: "small_model_tasks", + remediation: "reconnect", + message: "Anthropic session expired", + }, + outcome: "expired-credentials", + reason: "Anthropic session expired", + }, + ]); + }); + + it("continues after a provider throws and returns the next successful result", async () => { + const { result, attempts } = await callSmallModel({ + providers: [ + { + id: "openai", + name: "OpenAI", + resolveCredentials: () => ({ + apiKey: "api-key", + kind: "apiKey", + source: "auth-storage", + }), + isSupported: () => ({ supported: true }), + createModel: () => { + throw new Error("provider unavailable"); + }, + }, + { + id: "anthropic", + name: "Anthropic", + resolveCredentials: () => ({ + apiKey: "anthropic-key", + kind: "apiKey", + source: "config", + }), + isSupported: () => ({ supported: true }), + createModel: () => "anthropic-model", + }, + ], + invoke: async ({ providerId, model }) => + providerId === "anthropic" && model === "anthropic-model" + ? "fallback title" + : null, + }); + + expect(result).toBe("fallback title"); + expect(attempts).toEqual([ + { + providerId: "openai", + providerName: "OpenAI", + credentialKind: "apiKey", + credentialSource: "auth-storage", + issue: { + code: "unknown_error", + capability: "small_model_tasks", + remediation: "try_again", + message: "OpenAI could not complete this request", + }, + outcome: "failed", + reason: "provider unavailable", + }, + { + providerId: "anthropic", + providerName: "Anthropic", + credentialKind: "apiKey", + credentialSource: "config", + outcome: "succeeded", + }, + ]); + }); + + it("respects providerOrder when a caller prefers one provider first", async () => { + const visited: string[] = []; + + await callSmallModel({ + providers: [ + { + id: "anthropic", + name: "Anthropic", + resolveCredentials: () => ({ + apiKey: "anthropic-key", + kind: "apiKey", + source: "config", + }), + isSupported: () => ({ supported: true }), + createModel: () => "anthropic-model", + }, + { + id: "openai", + name: "OpenAI", + resolveCredentials: () => ({ + apiKey: "openai-key", + kind: "apiKey", + source: "auth-storage", + }), + isSupported: () => ({ supported: true }), + createModel: () => "openai-model", + }, + ], + providerOrder: ["openai", "anthropic"], + invoke: async ({ providerId }) => { + visited.push(providerId); + return "title"; + }, + }); + + expect(visited).toEqual(["openai"]); + }); + + it("uses shared default providers when none are supplied", async () => { + getDefaultSmallModelProvidersMock.mockReturnValue([ + { + id: "openai", + name: "OpenAI", + resolveCredentials: () => ({ + apiKey: "api-key", + kind: "apiKey", + source: "auth-storage", + }), + isSupported: () => ({ supported: true }), + createModel: () => "shared-openai-model", + }, + ]); + + const { result, attempts } = await callSmallModel({ + invoke: async ({ providerId, model }) => + providerId === "openai" && model === "shared-openai-model" + ? "title" + : null, + }); + + expect(result).toBe("title"); + expect(getDefaultSmallModelProvidersMock).toHaveBeenCalledTimes(1); + expect(attempts).toEqual([ + { + providerId: "openai", + providerName: "OpenAI", + credentialKind: "apiKey", + credentialSource: "auth-storage", + outcome: "succeeded", + }, + ]); + }); +}); diff --git a/apps/desktop/src/lib/ai/call-small-model.ts b/apps/desktop/src/lib/ai/call-small-model.ts index 369c548ee28..429a7a0147e 100644 --- a/apps/desktop/src/lib/ai/call-small-model.ts +++ b/apps/desktop/src/lib/ai/call-small-model.ts @@ -1,33 +1,24 @@ -// FORK NOTE: upstream #3517 removed fork's SmallModelProviders array -// and the provider-diagnostics store. Fork code (enhance-text.ts, -// git-operations.ts) still calls callSmallModel({ invoke }) expecting -// { result, attempts } with per-provider fallback. This shim restores -// that behavior on top of getSmallModelCandidates() (a fork-maintained -// replacement that returns the full priority list with OAuth / API key -// / proxy AUTH_TOKEN correctly wired via getAnthropicProviderOptions). -// -// Trade-offs vs. the pre-#3517 fork: -// - ProviderIssue reporting collapsed to generic `failed` — upstream -// removed the diagnostic classifiers when it dropped -// provider-diagnostics, and fork no longer surfaces them anywhere -// except describeEnhanceFailure's reason string. -// - Credential resolution happens synchronously (mastracode token -// refresh is not awaited in the candidate list). If an OAuth access -// token is actually expired, the next candidate in the priority -// chain is tried. -import { getSmallModelCandidates } from "@superset/chat/server/shared"; -import type { ProviderId, ProviderIssue } from "shared/ai/provider-status"; +import { + getDefaultSmallModelProviders, + type SmallModelCredential, + type SmallModelProvider, +} from "@superset/chat/server/desktop"; +import { + classifyProviderIssue, + type ProviderId, + type ProviderIssue, +} from "shared/ai/provider-status"; +import { + clearProviderIssue, + reportProviderIssue, +} from "./provider-diagnostics"; -export type SmallModelCredentialKind = "api_key" | "oauth" | "env"; -export interface SmallModelCredential { - kind: SmallModelCredentialKind; - source?: string; -} +type SmallModelProviderId = ProviderId; export interface SmallModelAttempt { - providerId: ProviderId; + providerId: SmallModelProviderId; providerName: string; - credentialKind?: SmallModelCredentialKind; + credentialKind?: SmallModelCredential["kind"]; credentialSource?: string; issue?: ProviderIssue; outcome: @@ -41,123 +32,153 @@ export interface SmallModelAttempt { } export interface SmallModelInvocationContext { - providerId: ProviderId; + providerId: SmallModelProviderId; providerName: string; model: unknown; credentials: SmallModelCredential; } -function toShimCredentialKind( - kind: "apiKey" | "oauth", -): SmallModelCredentialKind { - return kind === "oauth" ? "oauth" : "api_key"; +function orderProviders( + providers: SmallModelProvider[], + providerOrder?: SmallModelProviderId[], +): SmallModelProvider[] { + if (!providerOrder || providerOrder.length === 0) { + return providers; + } + + const rank = new Map( + providerOrder.map((providerId, index) => [providerId, index]), + ); + return [...providers].sort((left, right) => { + const leftRank = rank.get(left.id) ?? Number.MAX_SAFE_INTEGER; + const rightRank = rank.get(right.id) ?? Number.MAX_SAFE_INTEGER; + return leftRank - rightRank; + }); } export async function callSmallModel({ invoke, + providers = getDefaultSmallModelProviders(), providerOrder, }: { invoke: ( context: SmallModelInvocationContext, ) => Promise; - providerOrder?: ProviderId[]; + providers?: SmallModelProvider[]; + providerOrder?: SmallModelProviderId[]; }): Promise<{ result: TResult | null; attempts: SmallModelAttempt[]; }> { - const allCandidates = getSmallModelCandidates(); - - const ordered = providerOrder - ? [...allCandidates].sort((a, b) => { - const ai = providerOrder.indexOf(a.providerId); - const bi = providerOrder.indexOf(b.providerId); - return ( - (ai === -1 ? Number.MAX_SAFE_INTEGER : ai) - - (bi === -1 ? Number.MAX_SAFE_INTEGER : bi) - ); - }) - : allCandidates; - const attempts: SmallModelAttempt[] = []; - if (ordered.length === 0) { - // No credentials at all for either provider. Fabricate two - // missing-credentials attempts so describeEnhanceFailure's - // "every attempt is missing-credentials" branch triggers the - // correct "アカウントが接続されていません" message. - return { - result: null, - attempts: [ - { - providerId: "anthropic", - providerName: "Anthropic", - outcome: "missing-credentials", - }, - { - providerId: "openai", - providerName: "OpenAI", - outcome: "missing-credentials", - }, - ], - }; - } + for (const provider of orderProviders(providers, providerOrder)) { + const credentials = provider.resolveCredentials(); + if (!credentials) { + attempts.push({ + providerId: provider.id, + providerName: provider.name, + outcome: "missing-credentials", + }); + clearProviderIssue(provider.id, "small_model_tasks"); + continue; + } + if ( + credentials.kind === "oauth" && + typeof credentials.expiresAt === "number" && + credentials.expiresAt <= Date.now() + ) { + const issue: ProviderIssue = { + code: "expired", + capability: "small_model_tasks", + remediation: "reconnect", + message: `${provider.name} session expired`, + }; + attempts.push({ + providerId: provider.id, + providerName: provider.name, + credentialKind: credentials.kind, + credentialSource: credentials.source, + issue, + outcome: "expired-credentials", + reason: issue.message, + }); + reportProviderIssue(provider.id, issue); + continue; + } - for (const candidate of ordered) { - const credentials: SmallModelCredential = { - kind: toShimCredentialKind(candidate.credentialKind), - source: candidate.credentialSource, - }; - let model: unknown; - try { - model = candidate.createModel(); - } catch (error) { + const support = provider.isSupported(credentials); + if (!support.supported) { + const issue: ProviderIssue = { + code: "unsupported_credentials", + capability: "small_model_tasks", + remediation: "add_api_key", + message: + support.reason ?? + `${provider.name} credentials are not supported for this request`, + }; attempts.push({ - providerId: candidate.providerId, - providerName: candidate.providerName, + providerId: provider.id, + providerName: provider.name, credentialKind: credentials.kind, - credentialSource: candidate.credentialSource, - outcome: "failed", - reason: error instanceof Error ? error.message : String(error), + credentialSource: credentials.source, + issue, + outcome: "unsupported-credentials", + reason: support.reason, }); + reportProviderIssue(provider.id, issue); continue; } try { + const model = await provider.createModel(credentials); const result = await invoke({ - providerId: candidate.providerId, - providerName: candidate.providerName, + providerId: provider.id, + providerName: provider.name, model, credentials, }); - if (result === null || result === undefined) { + if (result != null) { attempts.push({ - providerId: candidate.providerId, - providerName: candidate.providerName, + providerId: provider.id, + providerName: provider.name, credentialKind: credentials.kind, - credentialSource: candidate.credentialSource, - outcome: "empty-result", + credentialSource: credentials.source, + outcome: "succeeded", }); - continue; + clearProviderIssue(provider.id, "small_model_tasks"); + return { result, attempts }; } + attempts.push({ - providerId: candidate.providerId, - providerName: candidate.providerName, + providerId: provider.id, + providerName: provider.name, credentialKind: credentials.kind, - credentialSource: candidate.credentialSource, - outcome: "succeeded", + credentialSource: credentials.source, + outcome: "empty-result", }); - return { result, attempts }; + clearProviderIssue(provider.id, "small_model_tasks"); } catch (error) { + const reason = error instanceof Error ? error.message : String(error); + const issue = classifyProviderIssue({ + providerId: provider.id, + errorMessage: reason, + }); attempts.push({ - providerId: candidate.providerId, - providerName: candidate.providerName, + providerId: provider.id, + providerName: provider.name, credentialKind: credentials.kind, - credentialSource: candidate.credentialSource, + credentialSource: credentials.source, + issue, outcome: "failed", - reason: error instanceof Error ? error.message : String(error), + reason, }); + reportProviderIssue(provider.id, issue); } } - return { result: null, attempts }; + return { + result: null, + attempts, + }; } diff --git a/apps/desktop/src/lib/ai/provider-diagnostics.ts b/apps/desktop/src/lib/ai/provider-diagnostics.ts new file mode 100644 index 00000000000..be8206edc0e --- /dev/null +++ b/apps/desktop/src/lib/ai/provider-diagnostics.ts @@ -0,0 +1,89 @@ +import type { + ProviderCapability, + ProviderDiagnostic, + ProviderId, + ProviderIssue, +} from "shared/ai/provider-status"; + +const DIAGNOSTIC_CAPABILITIES: ProviderCapability[] = [ + "chat", + "small_model_tasks", + "workspace_titles", +]; + +const diagnostics = new Map(); + +function getDiagnosticKey( + providerId: ProviderId, + capability: ProviderCapability, +): string { + return `${providerId}:${capability}`; +} + +function getEmptyDiagnostic(providerId: ProviderId): ProviderDiagnostic { + return { + providerId, + issue: null, + updatedAt: null, + }; +} + +export function getProviderDiagnostic( + providerId: ProviderId, + capability?: ProviderCapability, +): ProviderDiagnostic { + if (capability) { + return ( + diagnostics.get(getDiagnosticKey(providerId, capability)) ?? + getEmptyDiagnostic(providerId) + ); + } + + let latestDiagnostic: ProviderDiagnostic | null = null; + for (const supportedCapability of DIAGNOSTIC_CAPABILITIES) { + const diagnostic = diagnostics.get( + getDiagnosticKey(providerId, supportedCapability), + ); + if (!diagnostic) { + continue; + } + if ( + latestDiagnostic === null || + (diagnostic.updatedAt ?? 0) > (latestDiagnostic.updatedAt ?? 0) + ) { + latestDiagnostic = diagnostic; + } + } + + return latestDiagnostic ?? getEmptyDiagnostic(providerId); +} + +export function getProviderDiagnostics(): ProviderDiagnostic[] { + return [getProviderDiagnostic("anthropic"), getProviderDiagnostic("openai")]; +} + +export function reportProviderIssue( + providerId: ProviderId, + issue: ProviderIssue, +): void { + const capability = issue.capability ?? "chat"; + diagnostics.set(getDiagnosticKey(providerId, capability), { + providerId, + issue, + updatedAt: Date.now(), + }); +} + +export function clearProviderIssue( + providerId: ProviderId, + capability?: ProviderCapability, +): void { + if (capability) { + diagnostics.delete(getDiagnosticKey(providerId, capability)); + return; + } + + for (const supportedCapability of DIAGNOSTIC_CAPABILITIES) { + diagnostics.delete(getDiagnosticKey(providerId, supportedCapability)); + } +} diff --git a/apps/desktop/src/lib/trpc/routers/changes/git-operations.ts b/apps/desktop/src/lib/trpc/routers/changes/git-operations.ts index 55fc0432410..baa65db7f8e 100644 --- a/apps/desktop/src/lib/trpc/routers/changes/git-operations.ts +++ b/apps/desktop/src/lib/trpc/routers/changes/git-operations.ts @@ -1,4 +1,7 @@ -import { generateTitleFromMessage } from "@superset/chat/server/desktop"; +import { + generateTitleFromMessage, + generateTitleFromMessageWithStreamingModel, +} from "@superset/chat/server/desktop"; import { TRPCError } from "@trpc/server"; import { callSmallModel } from "lib/ai/call-small-model"; import { z } from "zod"; @@ -657,8 +660,20 @@ export const createGitOperationsRouter = () => { : f.diff; const { result } = await callSmallModel({ - invoke: async ({ model, providerId, providerName }) => - generateTitleFromMessage({ + invoke: async ({ + model, + credentials, + providerId, + providerName, + }) => { + if (providerId === "openai" && credentials.kind === "oauth") { + return generateTitleFromMessageWithStreamingModel({ + message: `File: ${f.path}\n\n${truncatedDiff}`, + model: model as never, + instructions: PHASE1_INSTRUCTIONS, + }); + } + return generateTitleFromMessage({ message: `File: ${f.path}\n\n${truncatedDiff}`, agentModel: model, agentId: `commit-file-summary-${providerId}`, @@ -668,7 +683,8 @@ export const createGitOperationsRouter = () => { surface: "commit-file-summary", provider: providerName, }, - }), + }); + }, }); return `${f.path}: ${result ?? "変更あり"}`; @@ -692,8 +708,16 @@ export const createGitOperationsRouter = () => { "日本語で簡潔なconventional commitメッセージを生成してください。コミットメッセージの行のみを返してください。"; const { result, attempts } = await callSmallModel({ - invoke: async ({ model, providerId, providerName }) => - generateTitleFromMessage({ + invoke: async ({ model, credentials, providerId, providerName }) => { + if (providerId === "openai" && credentials.kind === "oauth") { + return generateTitleFromMessageWithStreamingModel({ + message: PHASE2_PROMPT, + model: model as never, + instructions: PHASE2_INSTRUCTIONS, + }); + } + + return generateTitleFromMessage({ message: PHASE2_PROMPT, agentModel: model, agentId: `commit-message-${providerId}`, @@ -703,7 +727,8 @@ export const createGitOperationsRouter = () => { surface: "commit-message-generation", provider: providerName, }, - }), + }); + }, }); if (!result) { diff --git a/apps/desktop/src/lib/trpc/routers/index.ts b/apps/desktop/src/lib/trpc/routers/index.ts index c561e873f8c..810eedb5158 100644 --- a/apps/desktop/src/lib/trpc/routers/index.ts +++ b/apps/desktop/src/lib/trpc/routers/index.ts @@ -24,6 +24,7 @@ import { createGitHubMetricsRouter } from "./github-metrics"; import { createHostServiceCoordinatorRouter } from "./host-service-coordinator"; import { createLanguageServicesRouter } from "./language-services"; import { createMenuRouter } from "./menu"; +import { createModelProvidersRouter } from "./model-providers"; import { createNotificationsRouter } from "./notifications"; import { createPermissionsRouter } from "./permissions"; import { createPortsRouter } from "./ports"; @@ -55,6 +56,7 @@ export const createAppRouter = ( auth: createAuthRouter(), autoUpdate: createAutoUpdateRouter(), cache: createCacheRouter(), + modelProviders: createModelProvidersRouter(), window: createWindowRouter(getWindow), projects: createProjectsRouter(getWindow), workspaces: createWorkspacesRouter(), diff --git a/apps/desktop/src/lib/trpc/routers/model-providers/index.ts b/apps/desktop/src/lib/trpc/routers/model-providers/index.ts new file mode 100644 index 00000000000..511b3a4ef5c --- /dev/null +++ b/apps/desktop/src/lib/trpc/routers/model-providers/index.ts @@ -0,0 +1,51 @@ +import { + clearProviderIssue, + getProviderDiagnostic, +} from "lib/ai/provider-diagnostics"; +import { + deriveModelProviderStatus, + type ProviderId, +} from "shared/ai/provider-status"; +import { z } from "zod"; +import { publicProcedure, router } from "../.."; +import { chatService } from "../chat-service"; + +const providerIdSchema = z.enum(["anthropic", "openai"]); + +async function getProviderStatuses() { + const [anthropicAuthStatus, openAIAuthStatus] = await Promise.all([ + chatService.getAnthropicAuthStatus(), + chatService.getOpenAIAuthStatus(), + ]); + + return [ + deriveModelProviderStatus({ + providerId: "anthropic", + authStatus: anthropicAuthStatus, + diagnostic: getProviderDiagnostic("anthropic"), + }), + deriveModelProviderStatus({ + providerId: "openai", + authStatus: openAIAuthStatus, + diagnostic: getProviderDiagnostic("openai"), + }), + ]; +} + +export const createModelProvidersRouter = () => { + return router({ + getStatuses: publicProcedure.query(async () => { + return getProviderStatuses(); + }), + clearIssue: publicProcedure + .input(z.object({ providerId: providerIdSchema })) + .mutation(({ input }: { input: { providerId: ProviderId } }) => { + clearProviderIssue(input.providerId); + return { success: true }; + }), + }); +}; + +export type ModelProvidersRouter = ReturnType< + typeof createModelProvidersRouter +>; diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-branch-name.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-branch-name.ts index 7ad12334bab..6997101917e 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-branch-name.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-branch-name.ts @@ -1,12 +1,18 @@ -import { generateTitleFromMessage } from "@superset/chat/server/desktop"; -import { getSmallModel } from "@superset/chat/server/shared"; +import { + generateTitleFromMessage, + generateTitleFromMessageWithStreamingModel, +} from "@superset/chat/server/desktop"; +import { callSmallModel } from "lib/ai/call-small-model"; import { sanitizeBranchNameWithMaxLength } from "shared/utils/branch"; const BRANCH_NAME_INSTRUCTIONS = "Generate a concise git branch name (2-4 words, kebab-case, descriptive). Return ONLY the branch name, nothing else."; const MAX_CONFLICT_RESOLUTION_ATTEMPTS = 1000; -const INITIAL_CONFLICT_SUFFIX = 2; +const INITIAL_CONFLICT_SUFFIX = 2; // Start at -2 since -1 is implicit (no suffix) +/** + * Checks if a branch name conflicts with existing branches (case-insensitive) + */ function hasConflict( branchName: string, existingBranchesSet: Set, @@ -14,21 +20,29 @@ function hasConflict( return existingBranchesSet.has(branchName.toLowerCase()); } +/** + * Resolves branch name conflicts by appending a number (-2, -3, etc.) + * IMPORTANT: Checks conflicts with prefix applied to match server behavior + */ function resolveConflict( baseName: string, existingBranches: string[], branchPrefix: string | undefined, ): string { + // Apply prefix to match what the server will do const prefixedBase = branchPrefix ? `${branchPrefix}/${baseName}` : baseName; + + // Quick check without creating Set (covers 90% of cases where no conflict exists) const lowerPrefixedBase = prefixedBase.toLowerCase(); const hasInitialConflict = existingBranches.some( (b) => b.toLowerCase() === lowerPrefixedBase, ); if (!hasInitialConflict) { - return baseName; + return baseName; // Return unprefixed - server will apply prefix } + // Only create Set if we need to loop through conflicts const existingSet = new Set(existingBranches.map((b) => b.toLowerCase())); let counter = INITIAL_CONFLICT_SUFFIX; @@ -50,34 +64,54 @@ function resolveConflict( : candidate; } - return candidate; + return candidate; // Return unprefixed - server will apply prefix } +/** + * Generates an AI-powered branch name from a user prompt with automatic conflict resolution. + * + * @param prompt - User's workspace description + * @param existingBranches - List of existing branch names to check for conflicts + * @param branchPrefix - Optional prefix that will be applied by the server (e.g., "avi") + * @returns Generated branch name WITHOUT prefix (server will apply it) or null if generation fails + * @throws Error if conflict resolution exceeds max attempts + */ export async function generateBranchNameFromPrompt( prompt: string, existingBranches: string[], branchPrefix?: string, ): Promise { - const model = getSmallModel(); - if (!model) return null; + const { result } = await callSmallModel({ + invoke: async ({ credentials, providerId, providerName, model }) => { + if (providerId === "openai" && credentials.kind === "oauth") { + return generateTitleFromMessageWithStreamingModel({ + message: prompt, + model: model as never, + instructions: BRANCH_NAME_INSTRUCTIONS, + }); + } + + return generateTitleFromMessage({ + message: prompt, + agentModel: model, + agentId: `branch-namer-${providerId}`, + agentName: "Branch Namer", + instructions: BRANCH_NAME_INSTRUCTIONS, + tracingContext: { + surface: "workspace-branch-name", + provider: providerName, + }, + }); + }, + }); - let generated: string | null; - try { - generated = await generateTitleFromMessage({ - message: prompt, - agentModel: model, - agentId: "branch-namer", - agentName: "Branch Namer", - instructions: BRANCH_NAME_INSTRUCTIONS, - tracingContext: { surface: "workspace-branch-name" }, - }); - } catch (error) { - console.warn("[generateBranchNameFromPrompt] generation failed:", error); - return null; + if (result !== null && result !== undefined) { + const sanitized = sanitizeBranchNameWithMaxLength(result); + if (sanitized) { + // Resolve conflicts with prefix applied (matches server behavior) + return resolveConflict(sanitized, existingBranches, branchPrefix); + } } - if (!generated) return null; - const sanitized = sanitizeBranchNameWithMaxLength(generated); - if (!sanitized) return null; - return resolveConflict(sanitized, existingBranches, branchPrefix); + return null; } diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.test.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.test.ts index 5fa3df6dff0..0636b859f23 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.test.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.test.ts @@ -1,11 +1,19 @@ import { afterAll, beforeEach, describe, expect, it, mock } from "bun:test"; +import type { SmallModelAttempt } from "lib/ai/call-small-model"; -const getSmallModelMock = mock( - (() => null) as (...args: unknown[]) => unknown | null, -); +const callSmallModelMock = mock((async () => ({ + result: null, + attempts: [], +})) as (...args: unknown[]) => Promise<{ + result: string | null; + attempts: SmallModelAttempt[]; +}>); const generateTitleFromMessageMock = mock( (async () => null) as (...args: unknown[]) => Promise, ); +const generateTitleFromMessageWithStreamingModelMock = mock( + (async () => null) as (...args: unknown[]) => Promise, +); type SelectedWorkspace = | { @@ -23,12 +31,15 @@ type SelectedWorkspace = } | null; -mock.module("@superset/chat/server/shared", () => ({ - getSmallModel: getSmallModelMock, +mock.module("lib/ai/call-small-model", () => ({ + callSmallModel: callSmallModelMock, })); mock.module("@superset/chat/server/desktop", () => ({ + __esModule: true, generateTitleFromMessage: generateTitleFromMessageMock, + generateTitleFromMessageWithStreamingModel: + generateTitleFromMessageWithStreamingModelMock, })); mock.module("drizzle-orm", () => ({ @@ -78,72 +89,128 @@ const { describe("generateWorkspaceNameFromPrompt", () => { beforeEach(() => { - getSmallModelMock.mockClear(); - getSmallModelMock.mockReturnValue(null); - generateTitleFromMessageMock.mockClear(); - generateTitleFromMessageMock.mockResolvedValue(null); + callSmallModelMock.mockClear(); + callSmallModelMock.mockImplementation(async () => ({ + result: null, + attempts: [], + })); selectGetMock.mockReset(); selectGetMock.mockReturnValue(null); updateRunMock.mockReset(); updateRunMock.mockReturnValue({ changes: 1 }); localDbMock.select.mockClear(); localDbMock.update.mockClear(); + generateTitleFromMessageMock.mockClear(); + generateTitleFromMessageWithStreamingModelMock.mockClear(); }); - it("falls back to a prompt-derived title when no model is available", async () => { + it("falls back to a prompt-derived title when no providers are available", async () => { await expect( generateWorkspaceNameFromPrompt(" debug prod rename failure "), ).resolves.toEqual({ name: "debug prod rename failure", usedPromptFallback: true, warning: - "A prompt-based title was used because model naming was unavailable.", + "No model account was connected, so a prompt-based title was used.", }); }); - it("returns the model-generated title when a model is available", async () => { - getSmallModelMock.mockReturnValueOnce({ id: "test-model" }); - generateTitleFromMessageMock.mockResolvedValueOnce("Checking In"); + it("uses the last relevant provider issue in the fallback warning", async () => { + callSmallModelMock.mockImplementation(async () => ({ + result: null, + attempts: [ + { + providerId: "anthropic", + providerName: "Anthropic", + outcome: "failed", + issue: { + code: "unknown_error", + message: "Anthropic could not complete this request", + }, + }, + { + providerId: "openai", + providerName: "OpenAI", + outcome: "failed", + issue: { + code: "missing_scope", + message: "OpenAI needs permission model.request", + }, + }, + ], + })); await expect( - generateWorkspaceNameFromPrompt("hey boss how are you"), + generateWorkspaceNameFromPrompt("rename this workspace from prompt"), ).resolves.toEqual({ - name: "Checking In", - usedPromptFallback: false, - }); - expect(generateTitleFromMessageMock).toHaveBeenCalledWith({ - message: "hey boss how are you", - agentModel: { id: "test-model" }, - agentId: "workspace-namer", - agentName: "Workspace Namer", - instructions: "You generate concise workspace titles.", - tracingContext: { surface: "workspace-auto-name" }, + name: "rename this workspace from prompt", + usedPromptFallback: true, + warning: + "OpenAI needs permission model.request, so a prompt-based title was used.", }); }); - it("preserves empty-string model results instead of forcing fallback", async () => { - getSmallModelMock.mockReturnValueOnce({ id: "test-model" }); - generateTitleFromMessageMock.mockResolvedValueOnce(""); + it("uses streaming title generation for OpenAI OAuth naming", async () => { + generateTitleFromMessageWithStreamingModelMock.mockResolvedValue( + "Checking In", + ); + callSmallModelMock.mockImplementationOnce((async ({ + invoke, + }: { + invoke: (context: { + providerId: "openai"; + providerName: string; + model: { id: string }; + credentials: { + apiKey: string; + kind: "oauth"; + source: string; + }; + }) => Promise; + }) => ({ + result: await invoke({ + providerId: "openai", + providerName: "OpenAI", + model: { id: "openai-model" }, + credentials: { + apiKey: "oauth-token", + kind: "oauth", + source: "auth-storage", + }, + }), + attempts: [], + })) as (...args: unknown[]) => Promise<{ + result: string | null; + attempts: SmallModelAttempt[]; + }>); await expect( - generateWorkspaceNameFromPrompt("name this workspace"), + generateWorkspaceNameFromPrompt("hey boss how are you"), ).resolves.toEqual({ - name: "", + name: "Checking In", usedPromptFallback: false, }); + expect(generateTitleFromMessageWithStreamingModelMock).toHaveBeenCalledWith( + { + message: "hey boss how are you", + model: { id: "openai-model" }, + instructions: "You generate concise workspace titles.", + }, + ); + expect(generateTitleFromMessageMock).not.toHaveBeenCalled(); }); - it("falls back when generation throws", async () => { - getSmallModelMock.mockReturnValueOnce({ id: "test-model" }); - generateTitleFromMessageMock.mockRejectedValueOnce(new Error("boom")); + it("preserves empty-string model results instead of forcing fallback", async () => { + callSmallModelMock.mockImplementationOnce(async () => ({ + result: "", + attempts: [], + })); await expect( - generateWorkspaceNameFromPrompt("rename this workspace from prompt"), + generateWorkspaceNameFromPrompt("name this workspace"), ).resolves.toEqual({ - name: "rename this workspace from prompt", - usedPromptFallback: true, - warning: - "A prompt-based title was used because model naming was unavailable.", + name: "", + usedPromptFallback: false, }); }); }); @@ -154,10 +221,11 @@ afterAll(() => { describe("attemptWorkspaceAutoRenameFromPrompt", () => { beforeEach(() => { - getSmallModelMock.mockClear(); - getSmallModelMock.mockReturnValue(null); - generateTitleFromMessageMock.mockClear(); - generateTitleFromMessageMock.mockResolvedValue(null); + callSmallModelMock.mockClear(); + callSmallModelMock.mockImplementation(async () => ({ + result: null, + attempts: [], + })); selectGetMock.mockReset(); selectGetMock.mockReturnValue(null); updateRunMock.mockReset(); @@ -184,7 +252,7 @@ describe("attemptWorkspaceAutoRenameFromPrompt", () => { status: "skipped", reason: "workspace-named", }); - expect(getSmallModelMock).not.toHaveBeenCalled(); + expect(callSmallModelMock).not.toHaveBeenCalled(); expect(localDbMock.update).not.toHaveBeenCalled(); }); @@ -196,8 +264,10 @@ describe("attemptWorkspaceAutoRenameFromPrompt", () => { isUnnamed: true, deletingAt: null, }); - getSmallModelMock.mockReturnValueOnce({ id: "test-model" }); - generateTitleFromMessageMock.mockResolvedValueOnce(""); + callSmallModelMock.mockImplementationOnce(async () => ({ + result: "", + attempts: [], + })); await expect( attemptWorkspaceAutoRenameFromPrompt({ diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.ts index 1bb06606be5..02849066beb 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.ts @@ -1,7 +1,13 @@ -import { generateTitleFromMessage } from "@superset/chat/server/desktop"; -import { getSmallModel } from "@superset/chat/server/shared"; +import { + generateTitleFromMessage, + generateTitleFromMessageWithStreamingModel, +} from "@superset/chat/server/desktop"; import { workspaces } from "@superset/local-db"; import { and, eq, isNull } from "drizzle-orm"; +import { + callSmallModel, + type SmallModelAttempt, +} from "lib/ai/call-small-model"; import { localDb } from "main/lib/local-db"; import { deriveWorkspaceTitleFromPrompt } from "shared/utils/workspace-naming"; import { getWorkspaceAutoRenameDecision } from "./workspace-auto-rename"; @@ -26,39 +32,66 @@ export type WorkspaceAutoRenameResult = warning?: string; }; -const FALLBACK_WARNING = - "A prompt-based title was used because model naming was unavailable."; - export async function generateWorkspaceNameFromPrompt(prompt: string): Promise<{ name: string | null; usedPromptFallback: boolean; warning?: string; }> { - const model = getSmallModel(); - if (model) { - try { - const generated = await generateTitleFromMessage({ + const { result, attempts } = await callSmallModel({ + invoke: async ({ credentials, providerId, providerName, model }) => { + if (providerId === "openai" && credentials.kind === "oauth") { + return generateTitleFromMessageWithStreamingModel({ + message: prompt, + model: model as never, + instructions: "You generate concise workspace titles.", + }); + } + + return generateTitleFromMessage({ message: prompt, agentModel: model, - agentId: "workspace-namer", + agentId: `workspace-namer-${providerId}`, agentName: "Workspace Namer", instructions: "You generate concise workspace titles.", - tracingContext: { surface: "workspace-auto-name" }, + tracingContext: { + surface: "workspace-auto-name", + provider: providerName, + }, }); - if (generated !== null && generated !== undefined) { - return { name: generated, usedPromptFallback: false }; - } - } catch (error) { - console.error("[workspace-ai-name] title generation failed", error); + }, + }); + if (result !== null && result !== undefined) { + return { name: result, usedPromptFallback: false }; + } + + for (const attempt of attempts) { + if (attempt.outcome === "failed") { + console.error( + `[workspace-ai-name] ${attempt.providerName} title generation failed`, + { + issue: attempt.issue ?? null, + reason: attempt.reason ?? null, + }, + ); + continue; + } + if (attempt.outcome === "unsupported-credentials") { + console.info( + `[workspace-ai-name] Skipping ${attempt.providerName} for title generation`, + { + issue: attempt.issue ?? attempt.reason, + }, + ); } } const fallbackTitle = deriveWorkspaceTitleFromPrompt(prompt); if (fallbackTitle) { + console.info("[workspace-ai-name] Falling back to prompt-derived title"); return { name: fallbackTitle, usedPromptFallback: true, - warning: FALLBACK_WARNING, + warning: buildWorkspaceAutoNameFallbackWarning(attempts), }; } @@ -170,3 +203,33 @@ export async function attemptWorkspaceAutoRenameFromPrompt({ : "workspace-name-changed", }; } + +function buildWorkspaceAutoNameFallbackWarning( + attempts: SmallModelAttempt[], +): string { + if (attempts.length === 0) { + return "No model account was connected, so a prompt-based title was used."; + } + + for (let index = attempts.length - 1; index >= 0; index -= 1) { + const attempt = attempts[index]; + if (attempt.outcome === "expired-credentials") { + return `${attempt.issue?.message ?? `${attempt.providerName} needs to be reconnected`}, so a prompt-based title was used.`; + } + if (attempt.outcome === "failed") { + return `${attempt.issue?.message ?? `${attempt.providerName} couldn't generate a title`}, so a prompt-based title was used.`; + } + if (attempt.outcome === "unsupported-credentials") { + return `${attempt.issue?.message ?? "No compatible model account was available"}, so a prompt-based title was used.`; + } + } + + const missingCredentials = attempts.every( + (attempt) => attempt.outcome === "missing-credentials", + ); + if (missingCredentials) { + return "No model account was connected, so a prompt-based title was used."; + } + + return "A prompt-based title was used because model naming was unavailable."; +} diff --git a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/AnthropicOAuthDialog/AnthropicOAuthDialog.tsx b/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/AnthropicOAuthDialog/AnthropicOAuthDialog.tsx index 882e6a3d64f..2e4c508f083 100644 --- a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/AnthropicOAuthDialog/AnthropicOAuthDialog.tsx +++ b/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/AnthropicOAuthDialog/AnthropicOAuthDialog.tsx @@ -1,24 +1,157 @@ -import { OAuthDialog, type OAuthDialogProps } from "../OAuthDialog"; - -const ANTHROPIC_PROVIDER: OAuthDialogProps["provider"] = { - title: "Connect Anthropic", - description: - "Approve access in your browser, then paste the callback URL or `code#state` here.", - codeLabel: "Authorization code", - codePlaceholder: "Paste callback URL or code#state", - codeHint: - "Anthropic usually returns a full callback URL. Pasting either format works.", - preparingLabel: "Preparing Anthropic browser login...", -}; - -type AnthropicOAuthDialogProps = Omit; - -export function AnthropicOAuthDialog(props: AnthropicOAuthDialogProps) { +import { Button } from "@superset/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@superset/ui/dialog"; +import { InputGroup, InputGroupInput } from "@superset/ui/input-group"; +import { Label } from "@superset/ui/label"; + +interface AnthropicOAuthDialogProps { + open: boolean; + authUrl: string | null; + code: string; + errorMessage: string | null; + isPreparing: boolean; + isPending: boolean; + canDisconnect: boolean; + onOpenChange: (open: boolean) => void; + onCodeChange: (value: string) => void; + onOpenAuthUrl: () => void; + onCopyAuthUrl: () => void; + onDisconnect: () => void; + onRetry: () => void; + onSubmit: () => void; +} + +export function AnthropicOAuthDialog({ + open, + authUrl, + code, + errorMessage, + isPreparing, + isPending, + canDisconnect, + onOpenChange, + onCodeChange, + onOpenAuthUrl, + onCopyAuthUrl, + onDisconnect, + onRetry, + onSubmit, +}: AnthropicOAuthDialogProps) { + const hasAuthUrl = Boolean(authUrl); + const showCodeInput = hasAuthUrl || isPending; + const primaryLabel = isPending + ? "Connecting..." + : hasAuthUrl + ? "Continue" + : "Try again"; + return ( - + + + + Connect Anthropic + + Approve access in your browser, then paste the callback URL or + `code#state` here. + + + +
+ {isPreparing ? ( +
+ Preparing Anthropic browser login... +
+ ) : null} + + {showCodeInput ? ( +
+
+ + +
+ +
+ + + onCodeChange(event.target.value)} + onKeyDown={(event) => { + if (event.key === "Enter" && code.trim()) { + onSubmit(); + } + }} + disabled={isPending} + className="h-11 font-mono" + autoFocus + /> + +

+ Anthropic usually returns a full callback URL. Pasting either + format works. +

+
+
+ ) : null} + + {errorMessage ? ( +

{errorMessage}

+ ) : null} + +
+ +
+ + {canDisconnect ? ( + + ) : null} +
+
+
+
+
); } diff --git a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/OAuthDialog/OAuthDialog.tsx b/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/OAuthDialog/OAuthDialog.tsx deleted file mode 100644 index 7820f431fba..00000000000 --- a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/OAuthDialog/OAuthDialog.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import { Button } from "@superset/ui/button"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, -} from "@superset/ui/dialog"; -import { InputGroup, InputGroupInput } from "@superset/ui/input-group"; -import { Label } from "@superset/ui/label"; -import { useCallback, useState } from "react"; - -export interface OAuthDialogProps { - provider: { - title: string; - description: string; - codeLabel: string; - codePlaceholder: string; - codeHint: string; - preparingLabel: string; - }; - open: boolean; - authUrl: string | null; - code: string; - errorMessage: string | null; - isPreparing?: boolean; - isPending: boolean; - canDisconnect: boolean; - requireCodeForSubmit?: boolean; - onOpenChange: (open: boolean) => void; - onCodeChange: (value: string) => void; - onOpenAuthUrl: () => void; - onCopyAuthUrl: () => void; - onDisconnect: () => void; - onRetry?: () => void; - onSubmit: () => void; -} - -export function OAuthDialog({ - provider, - open, - authUrl, - code, - errorMessage, - isPreparing, - isPending, - canDisconnect, - requireCodeForSubmit, - onOpenChange, - onCodeChange, - onOpenAuthUrl, - onCopyAuthUrl, - onDisconnect, - onRetry, - onSubmit, -}: OAuthDialogProps) { - const hasAuthUrl = Boolean(authUrl); - const showCodeInput = hasAuthUrl || isPending; - const canSubmit = - !isPreparing && - !isPending && - (!requireCodeForSubmit || code.trim().length > 0); - const [copied, setCopied] = useState(false); - const handleCopy = useCallback(() => { - onCopyAuthUrl(); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - }, [onCopyAuthUrl]); - - return ( - - - - {provider.title} - {provider.description} - - -
- {isPreparing ? ( -
- {provider.preparingLabel} -
- ) : null} - - {showCodeInput ? ( -
-
- - -
- -
- - - onCodeChange(event.target.value)} - onKeyDown={(event) => { - if ( - event.key === "Enter" && - !event.nativeEvent.isComposing && - canSubmit - ) { - onSubmit(); - } - }} - disabled={isPending} - className="h-11 font-mono text-sm" - autoFocus - /> - -

- {provider.codeHint} -

-
-
- ) : !isPreparing ? ( -
- {provider.preparingLabel} -
- ) : null} - - {errorMessage ? ( -

{errorMessage}

- ) : null} - -
- -
- - {canDisconnect ? ( - - ) : null} -
-
-
-
-
- ); -} diff --git a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/OAuthDialog/index.ts b/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/OAuthDialog/index.ts deleted file mode 100644 index 602028a06a5..00000000000 --- a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/OAuthDialog/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { OAuthDialog, type OAuthDialogProps } from "./OAuthDialog"; diff --git a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/OpenAIOAuthDialog/OpenAIOAuthDialog.tsx b/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/OpenAIOAuthDialog/OpenAIOAuthDialog.tsx index a356da92ecc..2edd4a525b6 100644 --- a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/OpenAIOAuthDialog/OpenAIOAuthDialog.tsx +++ b/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/components/OpenAIOAuthDialog/OpenAIOAuthDialog.tsx @@ -1,17 +1,152 @@ -import { OAuthDialog, type OAuthDialogProps } from "../OAuthDialog"; - -const OPENAI_PROVIDER: OAuthDialogProps["provider"] = { - title: "Connect OpenAI", - description: - "Approve access in your browser. If the callback does not finish, paste the redirected callback URL below.", - codeLabel: "Callback URL (optional)", - codePlaceholder: "Paste callback URL", - codeHint: "Leave this empty if browser login finishes on its own.", - preparingLabel: "Preparing OpenAI browser login...", -}; - -type OpenAIOAuthDialogProps = Omit; - -export function OpenAIOAuthDialog(props: OpenAIOAuthDialogProps) { - return ; +import { Button } from "@superset/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@superset/ui/dialog"; +import { InputGroup, InputGroupInput } from "@superset/ui/input-group"; +import { Label } from "@superset/ui/label"; + +const OPENAI_OAUTH_CALLBACK_URL = "http://localhost:1455/auth/callback"; + +interface OpenAIOAuthDialogProps { + open: boolean; + authUrl: string | null; + code: string; + errorMessage: string | null; + isPending: boolean; + canDisconnect: boolean; + onOpenChange: (open: boolean) => void; + onCodeChange: (value: string) => void; + onOpenAuthUrl: () => void; + onCopyAuthUrl: () => void; + onDisconnect: () => void; + onSubmit: () => void; +} + +export function OpenAIOAuthDialog({ + open, + authUrl, + code, + errorMessage, + isPending, + canDisconnect, + onOpenChange, + onCodeChange, + onOpenAuthUrl, + onCopyAuthUrl, + onDisconnect, + onSubmit, +}: OpenAIOAuthDialogProps) { + const hasAuthUrl = Boolean(authUrl); + + return ( + + + + Connect OpenAI + + Approve access in your browser. If the callback does not finish, + paste the redirected callback URL below. + + + +
+
+ Tip: OpenAI + OAuth usually completes automatically after browser approval. If you + land on {`${OPENAI_OAUTH_CALLBACK_URL}?...`}, copy that + full URL and paste it below. +
+ +
+ + +
+ + {hasAuthUrl ? ( +
+

OAuth URL

+

+ {authUrl} +

+
+ ) : ( +
+ OAuth URL not ready yet. +
+ )} + +
+ + + onCodeChange(event.target.value)} + onKeyDown={(event) => { + if (event.key === "Enter" && !event.nativeEvent.isComposing) { + onSubmit(); + } + }} + disabled={isPending} + className="h-11 font-mono text-xs sm:text-sm" + autoFocus + /> + +

+ Leave this empty if browser login finishes on its own. +

+
+ + {errorMessage ? ( +

{errorMessage}

+ ) : null} + +
+ +
+ + {canDisconnect ? ( + + ) : null} +
+
+
+
+
+ ); } diff --git a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/hooks/useAnthropicOAuth/useAnthropicOAuth.ts b/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/hooks/useAnthropicOAuth/useAnthropicOAuth.ts index 313dc58829e..967c84413af 100644 --- a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/hooks/useAnthropicOAuth/useAnthropicOAuth.ts +++ b/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/hooks/useAnthropicOAuth/useAnthropicOAuth.ts @@ -1,6 +1,7 @@ import { chatServiceTrpc } from "@superset/chat/client"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useCopyToClipboard } from "renderer/hooks/useCopyToClipboard"; +import { electronTrpc } from "renderer/lib/electron-trpc"; import { electronTrpcClient } from "renderer/lib/trpc-client"; function getErrorMessage(error: unknown, fallback: string): string { @@ -74,6 +75,7 @@ export function useAnthropicOAuth({ const autoSubmitTimeoutRef = useRef | null>( null, ); + const electronUtils = electronTrpc.useUtils(); const { data: anthropicStatus, refetch: refetchAnthropicStatus } = chatServiceTrpc.auth.getAnthropicStatus.useQuery(); @@ -175,6 +177,10 @@ export function useAnthropicOAuth({ onModelSelectorOpenChange(true); try { + await electronTrpcClient.modelProviders.clearIssue.mutate({ + providerId: "anthropic", + }); + await electronUtils.modelProviders.getStatuses.invalidate(); await refetchAnthropicStatus(); await onAuthStateChange?.(); } catch (error) { @@ -187,6 +193,7 @@ export function useAnthropicOAuth({ [ clearAutoSubmitTimeout, completeAnthropicOAuthMutation, + electronUtils.modelProviders.getStatuses.invalidate, onAuthStateChange, onModelSelectorOpenChange, refetchAnthropicStatus, @@ -216,6 +223,10 @@ export function useAnthropicOAuth({ onModelSelectorOpenChange(true); try { + await electronTrpcClient.modelProviders.clearIssue.mutate({ + providerId: "anthropic", + }); + await electronUtils.modelProviders.getStatuses.invalidate(); await refetchAnthropicStatus(); await onAuthStateChange?.(); } catch (error) { @@ -226,6 +237,7 @@ export function useAnthropicOAuth({ } }, [ disconnectAnthropicOAuthMutation, + electronUtils.modelProviders.getStatuses.invalidate, onAuthStateChange, onModelSelectorOpenChange, refetchAnthropicStatus, diff --git a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/hooks/useOpenAIOAuth/useOpenAIOAuth.ts b/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/hooks/useOpenAIOAuth/useOpenAIOAuth.ts index 2506adbbc6b..59a74b5c903 100644 --- a/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/hooks/useOpenAIOAuth/useOpenAIOAuth.ts +++ b/apps/desktop/src/renderer/components/Chat/ChatInterface/components/ModelPicker/hooks/useOpenAIOAuth/useOpenAIOAuth.ts @@ -1,6 +1,7 @@ import { chatServiceTrpc } from "@superset/chat/client"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useCopyToClipboard } from "renderer/hooks/useCopyToClipboard"; +import { electronTrpc } from "renderer/lib/electron-trpc"; import { electronTrpcClient } from "renderer/lib/trpc-client"; function getErrorMessage(error: unknown, fallback: string): string { @@ -46,6 +47,7 @@ export function useOpenAIOAuth({ const [oauthCode, setOauthCode] = useState(""); const [oauthError, setOauthError] = useState(null); const [hasPendingOAuthSession, setHasPendingOAuthSession] = useState(false); + const electronUtils = electronTrpc.useUtils(); const { data: openAIStatus, refetch: refetchOpenAIStatus } = chatServiceTrpc.auth.getOpenAIStatus.useQuery(); @@ -90,14 +92,13 @@ export function useOpenAIOAuth({ setOauthCode(""); setHasPendingOAuthSession(true); setOauthDialogOpen(true); - await openExternalUrl(result.url); } catch (error) { setOauthDialogOpen(true); setOauthError( getErrorMessage(error, "Failed to start OpenAI OAuth flow"), ); } - }, [openExternalUrl, startOpenAIOAuthMutation]); + }, [startOpenAIOAuthMutation]); const { copyToClipboard } = useCopyToClipboard(); const copyOAuthUrl = useCallback(() => { @@ -109,6 +110,10 @@ export function useOpenAIOAuth({ const syncOpenAIAuthUi = useCallback( async (action: "complete" | "disconnect") => { try { + await electronTrpcClient.modelProviders.clearIssue.mutate({ + providerId: "openai", + }); + await electronUtils.modelProviders.getStatuses.invalidate(); await refetchOpenAIStatus(); } catch (error) { console.error( @@ -117,7 +122,7 @@ export function useOpenAIOAuth({ ); } }, - [refetchOpenAIStatus], + [electronUtils.modelProviders.getStatuses.invalidate, refetchOpenAIStatus], ); const completeOpenAIOAuth = useCallback(async () => { diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/ModelsSettings.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/ModelsSettings.tsx index df9cb02305a..eb0c5b319a0 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/ModelsSettings.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/ModelsSettings.tsx @@ -1,12 +1,10 @@ import { chatServiceTrpc } from "@superset/chat/client"; -import { Badge } from "@superset/ui/badge"; import { Button } from "@superset/ui/button"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@superset/ui/collapsible"; -import { claudeIcon } from "@superset/ui/icons/preset-icons"; import { Input } from "@superset/ui/input"; import { toast } from "@superset/ui/sonner"; import { Switch } from "@superset/ui/switch"; @@ -17,17 +15,19 @@ import { AnthropicOAuthDialog } from "renderer/components/Chat/ChatInterface/com import { OpenAIOAuthDialog } from "renderer/components/Chat/ChatInterface/components/ModelPicker/components/OpenAIOAuthDialog"; import { useAnthropicOAuth } from "renderer/components/Chat/ChatInterface/components/ModelPicker/hooks/useAnthropicOAuth"; import { useOpenAIOAuth } from "renderer/components/Chat/ChatInterface/components/ModelPicker/hooks/useOpenAIOAuth"; +import { electronTrpc } from "renderer/lib/electron-trpc"; import { isItemVisible, SETTING_ITEM_ID, type SettingItemId, } from "../../../utils/settings-search"; +import { AccountCard } from "./components/AccountCard"; import { ConfigRow } from "./components/ConfigRow"; import { SettingsSection } from "./components/SettingsSection"; import { buildAnthropicEnvText, EMPTY_ANTHROPIC_FORM, - getProviderAction, + getProviderSubtitle, getStatusBadge, parseAnthropicForm, resolveProviderStatus, @@ -52,6 +52,7 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { SETTING_ITEM_ID.MODELS_NEXT_EDIT, visibleItems, ); + const [apiKeysOpen, setApiKeysOpen] = useState(true); const [overrideOpen, setOverrideOpen] = useState(true); const [nextEditAdvancedOpen, setNextEditAdvancedOpen] = useState(true); const [openAIApiKeyInput, setOpenAIApiKeyInput] = useState(""); @@ -67,6 +68,14 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { stopText: "", }); + const { data: providerStatuses, refetch: refetchProviderStatuses } = + electronTrpc.modelProviders.getStatuses.useQuery(); + const anthropicDiagnosticStatus = providerStatuses?.find( + (status) => status.providerId === "anthropic", + ); + const openAIDiagnosticStatus = providerStatuses?.find( + (status) => status.providerId === "openai", + ); const { data: anthropicAuthStatus, refetch: refetchAnthropicAuthStatus } = chatServiceTrpc.auth.getAnthropicStatus.useQuery(); const { data: openAIAuthStatus, refetch: refetchOpenAIAuthStatus } = @@ -97,6 +106,8 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { chatServiceTrpc.auth.clearInceptionApiKey.useMutation(); const setNextEditConfigMutation = chatServiceTrpc.nextEdit.setConfig.useMutation(); + const clearProviderIssueMutation = + electronTrpc.modelProviders.clearIssue.useMutation(); const { isStartingOAuth: isStartingAnthropicOAuth, @@ -105,7 +116,10 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { } = useAnthropicOAuth({ ...DIALOG_CONTEXT, onAuthStateChange: async () => { - await refetchAnthropicAuthStatus(); + await Promise.all([ + refetchAnthropicAuthStatus(), + refetchProviderStatuses(), + ]); }, }); const { @@ -153,8 +167,9 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { resolveProviderStatus({ providerId: "anthropic", authStatus: anthropicAuthStatus, + diagnosticStatus: anthropicDiagnosticStatus, }), - [anthropicAuthStatus], + [anthropicAuthStatus, anthropicDiagnosticStatus], ); const openAIStatus = useMemo( @@ -162,10 +177,19 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { resolveProviderStatus({ providerId: "openai", authStatus: openAIAuthStatus, + diagnosticStatus: openAIDiagnosticStatus, }), - [openAIAuthStatus], + [openAIAuthStatus, openAIDiagnosticStatus], ); + const anthropicSubtitle = useMemo( + () => getProviderSubtitle("anthropic", anthropicStatus), + [anthropicStatus], + ); + const openAISubtitle = useMemo( + () => getProviderSubtitle("openai", openAIStatus), + [openAIStatus], + ); const anthropicBadge = useMemo( () => getStatusBadge(anthropicStatus), [anthropicStatus], @@ -175,6 +199,9 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { [openAIStatus], ); + const clearProviderIssue = (providerId: "anthropic" | "openai") => + clearProviderIssueMutation.mutateAsync({ providerId }); + const formatTokenCount = (value: number) => { return new Intl.NumberFormat("en-US").format(value); }; @@ -199,6 +226,8 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { await Promise.all([ refetchAnthropicEnvConfig(), refetchAnthropicAuthStatus(), + clearProviderIssue("anthropic"), + refetchProviderStatuses(), ]); toast.success("Anthropic settings updated"); return true; @@ -214,7 +243,11 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { try { await setAnthropicApiKeyMutation.mutateAsync({ apiKey }); setAnthropicApiKeyInput(""); - await refetchAnthropicAuthStatus(); + await Promise.all([ + refetchAnthropicAuthStatus(), + clearProviderIssue("anthropic"), + refetchProviderStatuses(), + ]); toast.success("Anthropic API key updated"); } catch (error) { toast.error(error instanceof Error ? error.message : "Failed to save"); @@ -227,7 +260,11 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { try { await setOpenAIApiKeyMutation.mutateAsync({ apiKey }); setOpenAIApiKeyInput(""); - await refetchOpenAIAuthStatus(); + await Promise.all([ + refetchOpenAIAuthStatus(), + clearProviderIssue("openai"), + refetchProviderStatuses(), + ]); toast.success("OpenAI API key updated"); } catch (error) { toast.error(error instanceof Error ? error.message : "Failed to save"); @@ -310,29 +347,63 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { status, startOAuth, isStartingOAuth, + canDisconnect, onDisconnect, }: { status: typeof anthropicStatus | typeof openAIStatus; startOAuth: () => Promise; isStartingOAuth: boolean; + canDisconnect: boolean; onDisconnect: () => void; }) => { - const action = getProviderAction(status); - if (!action) return null; - if (action.kind === "logout") { + if (!status || status.connectionState === "disconnected") { + return ( + + ); + } + + if (status.issue?.remediation === "reconnect") { + return ( + + ); + } + + if (canDisconnect) { return ( ); } + return ( ); }; @@ -349,165 +420,167 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) {
{showAnthropic ? ( - } - > -
-
-
-

OAuth

- {anthropicBadge ? ( - - {anthropicBadge.label} - - ) : null} -
- {renderProviderAction({ - status: anthropicStatus, - startOAuth: startAnthropicOAuth, - isStartingOAuth: isStartingAnthropicOAuth, - onDisconnect: async () => { - if (anthropicStatus?.authMethod === "oauth") { - anthropicOAuthDialog.onDisconnect(); - } else { - await clearAnthropicApiKeyMutation.mutateAsync(); - setAnthropicApiKeyInput(""); - } - await refetchAnthropicAuthStatus(); - }, - })} -
- { - setAnthropicApiKeyInput(event.target.value); - }} - placeholder={ - anthropicStatus?.authMethod === "api_key" - ? "Saved Anthropic API key" - : "sk-ant-..." - } - className="font-mono" - disabled={isSavingAnthropicApiKey} - /> - } - onSave={() => { - void saveAnthropicApiKey(); - }} - onClear={() => { - const nextForm = { ...anthropicForm, apiKey: "" }; - void (async () => { - try { - await clearAnthropicApiKeyMutation.mutateAsync(); - setAnthropicApiKeyInput(""); - setAnthropicForm(nextForm); - await refetchAnthropicAuthStatus(); - toast.success("Anthropic API key cleared"); - } catch (error) { - toast.error( - error instanceof Error - ? error.message - : "Failed to clear", - ); - } - })(); - }} - showSave={anthropicApiKeyInput.trim().length > 0} - disableSave={isSavingAnthropicApiKey} - showClear={anthropicStatus?.authMethod === "api_key"} - disableClear={isSavingAnthropicApiKey} - /> -
+ + ) : null} {showOpenAI ? ( - - } - > -
-
-
-

OAuth

- {openAIBadge ? ( - - {openAIBadge.label} - - ) : null} -
- {renderProviderAction({ - status: openAIStatus, - startOAuth: startOpenAIOAuth, - isStartingOAuth: isStartingOpenAIOAuth, - onDisconnect: async () => { - if (openAIStatus?.authMethod === "oauth") { - openAIOAuthDialog.onDisconnect(); - } else { - await clearOpenAIApiKeyMutation.mutateAsync(); - setOpenAIApiKeyInput(""); - } - await refetchOpenAIAuthStatus(); - }, - })} -
- { - setOpenAIApiKeyInput(event.target.value); - }} - placeholder={ - openAIStatus?.authMethod === "api_key" - ? "Saved OpenAI API key" - : "sk-..." - } - className="font-mono" - disabled={isSavingOpenAIConfig} - /> - } - onSave={() => { - void saveOpenAIApiKey(); - }} - onClear={() => { - void (async () => { - try { - await clearOpenAIApiKeyMutation.mutateAsync(); - setOpenAIApiKeyInput(""); - await refetchOpenAIAuthStatus(); - toast.success("OpenAI API key cleared"); - } catch (error) { - toast.error( - error instanceof Error - ? error.message - : "Failed to clear", - ); - } - })(); - }} - showSave={openAIApiKeyInput.trim().length > 0} - disableSave={isSavingOpenAIConfig} - showClear={openAIStatus?.authMethod === "api_key"} - disableClear={isSavingOpenAIConfig} - /> -
+ + ) : null} + +
+ + + + + {showAnthropic ? ( + { + setAnthropicApiKeyInput(event.target.value); + }} + placeholder={ + anthropicStatus?.authMethod === "api_key" + ? "Saved Anthropic API key" + : "sk-ant-..." + } + className="font-mono" + disabled={isSavingAnthropicApiKey} + /> + } + onSave={() => { + void saveAnthropicApiKey(); + }} + onClear={() => { + const nextForm = { ...anthropicForm, apiKey: "" }; + void (async () => { + try { + await clearAnthropicApiKeyMutation.mutateAsync(); + setAnthropicApiKeyInput(""); + setAnthropicForm(nextForm); + await Promise.all([ + refetchAnthropicAuthStatus(), + clearProviderIssue("anthropic"), + refetchProviderStatuses(), + ]); + toast.success("Anthropic API key cleared"); + } catch (error) { + toast.error( + error instanceof Error + ? error.message + : "Failed to clear", + ); + } + })(); + }} + disableSave={ + isSavingAnthropicApiKey || + anthropicApiKeyInput.trim().length === 0 + } + disableClear={ + isSavingAnthropicApiKey || + anthropicStatus?.authMethod !== "api_key" + } + /> + ) : null} + {showOpenAI ? ( + { + setOpenAIApiKeyInput(event.target.value); + }} + placeholder={ + openAIStatus?.authMethod === "api_key" + ? "Saved OpenAI API key" + : "sk-..." + } + className="font-mono" + disabled={isSavingOpenAIConfig} + /> + } + onSave={() => { + void saveOpenAIApiKey(); + }} + onClear={() => { + void (async () => { + try { + await clearOpenAIApiKeyMutation.mutateAsync(); + setOpenAIApiKeyInput(""); + await Promise.all([ + refetchOpenAIAuthStatus(), + clearProviderIssue("openai"), + refetchProviderStatuses(), + ]); + toast.success("OpenAI API key cleared"); + } catch (error) { + toast.error( + error instanceof Error + ? error.message + : "Failed to clear", + ); + } + })(); + }} + disableSave={ + isSavingOpenAIConfig || + openAIApiKeyInput.trim().length === 0 + } + disableClear={ + isSavingOpenAIConfig || + openAIStatus?.authMethod !== "api_key" + } + /> + ) : null} + +
+
+ {showAnthropic ? (
@@ -522,113 +595,111 @@ export function ModelsSettings({ visibleItems }: ModelsSettingsProps) { Override Provider - -
- { - setAnthropicForm((current) => ({ - ...current, - authToken: event.target.value, - })); - }} - placeholder="sk-ant-..." - className="font-mono" - disabled={isSavingAnthropicConfig} - /> - } - onSave={() => { - void saveAnthropicForm(); - }} - onClear={() => { - const nextForm = { ...anthropicForm, authToken: "" }; - setAnthropicForm(nextForm); - void saveAnthropicForm(nextForm); - }} - disableSave={isSavingAnthropicConfig} - disableClear={ - isSavingAnthropicConfig || - anthropicForm.authToken.length === 0 - } - /> - { - setAnthropicForm((current) => ({ - ...current, - baseUrl: event.target.value, - })); - }} - placeholder="https://api.anthropic.com" - className="font-mono" - disabled={isSavingAnthropicConfig} - /> - } - onSave={() => { - void saveAnthropicForm(); - }} - onClear={() => { - const nextForm = { ...anthropicForm, baseUrl: "" }; - setAnthropicForm(nextForm); - void saveAnthropicForm(nextForm); - }} - disableSave={isSavingAnthropicConfig} - disableClear={ - isSavingAnthropicConfig || - anthropicForm.baseUrl.length === 0 - } - /> - { - setAnthropicForm((current) => ({ - ...current, - extraEnv: event.target.value, - })); - }} - placeholder={ - "CLAUDE_CODE_USE_BEDROCK=1\nAWS_REGION=us-east-1" + + { + setAnthropicForm((current) => ({ + ...current, + authToken: event.target.value, + })); + }} + placeholder="sk-ant-..." + className="font-mono" + disabled={isSavingAnthropicConfig} + /> + } + onSave={() => { + void saveAnthropicForm(); + }} + onClear={() => { + const nextForm = { ...anthropicForm, authToken: "" }; + setAnthropicForm(nextForm); + void saveAnthropicForm(nextForm); + }} + disableSave={isSavingAnthropicConfig} + disableClear={ + isSavingAnthropicConfig || + anthropicForm.authToken.length === 0 + } + /> + { + setAnthropicForm((current) => ({ + ...current, + baseUrl: event.target.value, + })); + }} + placeholder="https://api.anthropic.com" + className="font-mono" + disabled={isSavingAnthropicConfig} + /> + } + onSave={() => { + void saveAnthropicForm(); + }} + onClear={() => { + const nextForm = { ...anthropicForm, baseUrl: "" }; + setAnthropicForm(nextForm); + void saveAnthropicForm(nextForm); + }} + disableSave={isSavingAnthropicConfig} + disableClear={ + isSavingAnthropicConfig || + anthropicForm.baseUrl.length === 0 + } + /> + { + setAnthropicForm((current) => ({ + ...current, + extraEnv: event.target.value, + })); + }} + placeholder={ + "CLAUDE_CODE_USE_BEDROCK=1\nAWS_REGION=us-east-1" + } + className="min-h-24 font-mono text-xs" + disabled={isSavingAnthropicConfig} + /> + } + onSave={() => { + void saveAnthropicForm(); + }} + onClear={ + hasAnthropicConfig + ? () => { + const nextForm = { + ...anthropicForm, + extraEnv: "", + }; + setAnthropicForm(nextForm); + void saveAnthropicForm(nextForm); } - className="min-h-24 font-mono text-xs" - disabled={isSavingAnthropicConfig} - /> - } - onSave={() => { - void saveAnthropicForm(); - }} - onClear={ - hasAnthropicConfig - ? () => { - const nextForm = { - ...anthropicForm, - extraEnv: "", - }; - setAnthropicForm(nextForm); - void saveAnthropicForm(nextForm); - } - : undefined - } - clearLabel="Clear" - disableSave={isSavingAnthropicConfig} - disableClear={ - isSavingAnthropicConfig || - anthropicForm.extraEnv.length === 0 - } - /> -
+ : undefined + } + clearLabel="Clear" + disableSave={isSavingAnthropicConfig} + disableClear={ + isSavingAnthropicConfig || + anthropicForm.extraEnv.length === 0 + } + />
diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/AccountCard/AccountCard.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/AccountCard/AccountCard.tsx new file mode 100644 index 00000000000..98e49024db8 --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/AccountCard/AccountCard.tsx @@ -0,0 +1,41 @@ +import { Badge } from "@superset/ui/badge"; +import { cn } from "@superset/ui/utils"; +import type { ReactNode } from "react"; + +interface AccountCardProps { + title: string; + subtitle: string; + badge?: string; + badgeVariant?: "secondary" | "outline" | "destructive"; + actions?: ReactNode; + muted?: boolean; +} + +export function AccountCard({ + title, + subtitle, + badge, + badgeVariant = "secondary", + actions, + muted = false, +}: AccountCardProps) { + return ( +
+
+
+

{title}

+

{subtitle}

+
+
+ {badge ? {badge} : null} + {actions} +
+
+
+ ); +} diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/AccountCard/index.ts b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/AccountCard/index.ts new file mode 100644 index 00000000000..88333bd623e --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/AccountCard/index.ts @@ -0,0 +1 @@ +export { AccountCard } from "./AccountCard"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/ConfigRow/ConfigRow.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/ConfigRow/ConfigRow.tsx index 953ca4dd156..d0e0b24c61c 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/ConfigRow/ConfigRow.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/ConfigRow/ConfigRow.tsx @@ -1,5 +1,4 @@ import { Button } from "@superset/ui/button"; -import { cn } from "@superset/ui/utils"; import type { ReactNode } from "react"; interface ConfigRowProps { @@ -10,11 +9,8 @@ interface ConfigRowProps { onClear?: () => void; saveLabel?: string; clearLabel?: string; - showSave?: boolean; - showClear?: boolean; disableSave?: boolean; disableClear?: boolean; - className?: string; } export function ConfigRow({ @@ -25,14 +21,11 @@ export function ConfigRow({ onClear, saveLabel = "Save", clearLabel = "Clear", - showSave = true, - showClear = true, disableSave, disableClear, - className, }: ConfigRowProps) { return ( -
+

{title}

@@ -43,7 +36,7 @@ export function ConfigRow({
{field}
- {onClear && showClear ? ( + {onClear ? ( diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/SettingsSection/SettingsSection.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/SettingsSection/SettingsSection.tsx index 19d4c485c0e..508ec0eabd9 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/SettingsSection/SettingsSection.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/components/SettingsSection/SettingsSection.tsx @@ -2,7 +2,6 @@ import type { ReactNode } from "react"; interface SettingsSectionProps { title: string; - icon?: ReactNode; description?: string; action?: ReactNode; children: ReactNode; @@ -10,7 +9,6 @@ interface SettingsSectionProps { export function SettingsSection({ title, - icon, description, action, children, @@ -19,10 +17,7 @@ export function SettingsSection({
-

- {icon} - {title} -

+

{title}

{description ? (

{description}

) : null} diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/utils.ts b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/utils.ts index b77b5b0bf75..b14c60c63d2 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/utils.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/models/components/ModelsSettings/utils.ts @@ -84,7 +84,7 @@ export function getProviderSubtitle( return status.issue.message; } if (!status || status.connectionState === "disconnected") { - return ""; + return "No account connected"; } if (status.source === "external" && status.authMethod === "oauth") { return EXTERNAL_OAUTH_LABELS[providerId]; @@ -101,8 +101,8 @@ export function getProviderSubtitle( export function getStatusBadge( status: ModelProviderStatus | undefined, ): { label: string; variant: "secondary" | "outline" | "destructive" } | null { - if (!status || status.connectionState === "disconnected") { - return { label: "Not connected", variant: "outline" }; + if (!status) { + return null; } if (status.issue?.code === "expired") { return { label: "Expired", variant: "destructive" }; @@ -119,32 +119,22 @@ export function getStatusBadge( export function resolveProviderStatus(params: { providerId: ProviderId; authStatus?: AuthStatusLike; + diagnosticStatus?: ModelProviderStatus; }): ModelProviderStatus | undefined { - const { providerId, authStatus } = params; - if (!authStatus) return undefined; - return deriveModelProviderStatus({ providerId, authStatus }); -} - -export type ProviderAction = - | { kind: "connect" } - | { kind: "reconnect" } - | { kind: "logout" } - | null; - -/** - * Single source of truth for the provider action button. - */ -export function getProviderAction( - status: ModelProviderStatus | undefined, -): ProviderAction { - if (!status || status.connectionState === "disconnected") { - return { kind: "connect" }; - } - if (status.issue?.remediation === "reconnect") { - return { kind: "reconnect" }; + const { providerId, authStatus, diagnosticStatus } = params; + if (!authStatus) { + return diagnosticStatus; } - if (status.connectionState === "connected") { - return { kind: "logout" }; - } - return { kind: "connect" }; + + return deriveModelProviderStatus({ + providerId, + authStatus, + diagnostic: { + providerId, + issue: authStatus.authenticated + ? (diagnosticStatus?.issue ?? null) + : null, + updatedAt: null, + }, + }); } diff --git a/apps/desktop/src/shared/ai/provider-status.test.ts b/apps/desktop/src/shared/ai/provider-status.test.ts index 4c0e1e99267..4a2ed63d85e 100644 --- a/apps/desktop/src/shared/ai/provider-status.test.ts +++ b/apps/desktop/src/shared/ai/provider-status.test.ts @@ -1,8 +1,23 @@ import { describe, expect, it } from "bun:test"; -import { deriveModelProviderStatus } from "./provider-status"; +import { + deriveModelProviderStatus, + type ProviderDiagnostic, +} from "./provider-status"; describe("deriveModelProviderStatus", () => { - it("marks an authenticated provider without issues as connected", () => { + it("keeps a connected provider connected when only capability diagnostics fail", () => { + const diagnostic: ProviderDiagnostic = { + providerId: "openai", + issue: { + code: "missing_scope", + capability: "small_model_tasks", + remediation: "check_permissions", + scope: "api.responses.write", + message: "OpenAI needs permission api.responses.write", + }, + updatedAt: Date.now(), + }; + const status = deriveModelProviderStatus({ providerId: "openai", authStatus: { @@ -11,15 +26,14 @@ describe("deriveModelProviderStatus", () => { source: "managed", issue: null, }, + diagnostic, }); expect(status.connectionState).toBe("connected"); - expect(status.issue).toBeNull(); - expect(status.capabilities).toEqual({ - canUseChat: true, - canGenerateWorkspaceTitle: true, - canUseSmallModelTasks: true, - }); + expect(status.issue?.code).toBe("missing_scope"); + expect(status.capabilities.canUseChat).toBe(true); + expect(status.capabilities.canGenerateWorkspaceTitle).toBe(false); + expect(status.capabilities.canUseSmallModelTasks).toBe(false); }); it("treats expired auth as needs attention and disables all capabilities", () => { @@ -41,20 +55,4 @@ describe("deriveModelProviderStatus", () => { canUseSmallModelTasks: false, }); }); - - it("reports disconnected for providers with no source and no auth", () => { - const status = deriveModelProviderStatus({ - providerId: "openai", - authStatus: { - authenticated: false, - method: null, - source: null, - issue: null, - }, - }); - - expect(status.connectionState).toBe("disconnected"); - expect(status.issue).toBeNull(); - expect(status.capabilities.canUseChat).toBe(false); - }); }); diff --git a/apps/desktop/src/shared/ai/provider-status.ts b/apps/desktop/src/shared/ai/provider-status.ts index 910ebc2f659..c74e27088af 100644 --- a/apps/desktop/src/shared/ai/provider-status.ts +++ b/apps/desktop/src/shared/ai/provider-status.ts @@ -5,14 +5,40 @@ export type ProviderConnectionState = | "disconnected" | "needs_attention"; -export type ProviderRemediation = "reconnect" | "add_api_key"; +export type ProviderCapability = + | "chat" + | "workspace_titles" + | "small_model_tasks"; -export type ProviderIssueCode = "expired"; +export type ProviderRemediation = + | "reconnect" + | "check_permissions" + | "check_billing" + | "add_api_key" + | "try_again"; + +export type ProviderIssueCode = + | "expired" + | "missing_scope" + | "forbidden" + | "quota_exceeded" + | "network_error" + | "unsupported_credentials" + | "empty_result" + | "unknown_error"; export interface ProviderIssue { code: ProviderIssueCode; message: string; + capability?: ProviderCapability; remediation?: ProviderRemediation; + scope?: string | null; +} + +export interface ProviderDiagnostic { + providerId: ProviderId; + issue: ProviderIssue | null; + updatedAt: number | null; } export interface AuthStatusLike { @@ -43,6 +69,72 @@ export function getProviderName(providerId: ProviderId): string { return providerId === "anthropic" ? "Anthropic" : "OpenAI"; } +export function classifyProviderIssue(params: { + providerId: ProviderId; + errorMessage: string; +}): ProviderIssue { + const { providerId, errorMessage } = params; + const normalized = errorMessage.trim(); + const lower = normalized.toLowerCase(); + + const missingScopeMatch = normalized.match( + /Missing scopes:\s*([A-Za-z0-9._,\s-]+)/i, + ); + if (missingScopeMatch || lower.includes("insufficient permissions")) { + const scope = + missingScopeMatch?.[1]?.trim().replace(/[.,;:]+$/, "") ?? null; + const providerName = getProviderName(providerId); + return { + code: "missing_scope", + capability: "small_model_tasks", + remediation: "check_permissions", + scope, + message: scope + ? `${providerName} needs permission ${scope}` + : `${providerName} is missing permission for this action`, + }; + } + + if (lower.includes("quota") || lower.includes("insufficient_quota")) { + return { + code: "quota_exceeded", + capability: "small_model_tasks", + remediation: "check_billing", + message: `${getProviderName(providerId)} quota or billing needs attention`, + }; + } + + if (lower.includes("forbidden") || lower.includes("status: 403")) { + return { + code: "forbidden", + capability: "small_model_tasks", + remediation: "check_permissions", + message: `${getProviderName(providerId)} denied this request`, + }; + } + + if ( + lower.includes("timed out") || + lower.includes("network") || + lower.includes("econn") || + lower.includes("fetch failed") + ) { + return { + code: "network_error", + capability: "small_model_tasks", + remediation: "try_again", + message: `${getProviderName(providerId)} request failed due to a network error`, + }; + } + + return { + code: "unknown_error", + capability: "small_model_tasks", + remediation: "try_again", + message: `${getProviderName(providerId)} could not complete this request`, + }; +} + function getIssueFromAuthStatus( providerId: ProviderId, authStatus: AuthStatusLike, @@ -50,6 +142,7 @@ function getIssueFromAuthStatus( if (authStatus.issue === "expired") { return { code: "expired", + capability: "chat", remediation: "reconnect", message: `${getProviderName(providerId)} session expired`, }; @@ -61,24 +154,53 @@ function getIssueFromAuthStatus( export function deriveModelProviderStatus(params: { providerId: ProviderId; authStatus: AuthStatusLike; + diagnostic?: ProviderDiagnostic | null; }): ModelProviderStatus { - const { providerId, authStatus } = params; - const issue = getIssueFromAuthStatus(providerId, authStatus); + const { providerId, authStatus, diagnostic } = params; + const authIssue = getIssueFromAuthStatus(providerId, authStatus); + const issue = authIssue ?? diagnostic?.issue ?? null; let connectionState: ProviderConnectionState = "disconnected"; if (authStatus.authenticated) { - connectionState = issue ? "needs_attention" : "connected"; - } else if (issue || authStatus.source !== null) { + connectionState = authIssue ? "needs_attention" : "connected"; + } else if (authIssue || authStatus.source !== null) { connectionState = "needs_attention"; } - const canUse = authStatus.authenticated && !issue; const capabilities: ProviderCapabilities = { - canUseChat: canUse, - canGenerateWorkspaceTitle: canUse, - canUseSmallModelTasks: canUse, + canUseChat: authStatus.authenticated, + canGenerateWorkspaceTitle: authStatus.authenticated, + canUseSmallModelTasks: authStatus.authenticated, }; + if (issue) { + switch (issue.code) { + case "expired": + capabilities.canUseChat = false; + capabilities.canGenerateWorkspaceTitle = false; + capabilities.canUseSmallModelTasks = false; + break; + case "missing_scope": + case "forbidden": + case "quota_exceeded": + case "network_error": + case "unsupported_credentials": + case "empty_result": + case "unknown_error": + if (issue.capability === "chat") { + capabilities.canUseChat = false; + } + if ( + issue.capability === "small_model_tasks" || + issue.capability === "workspace_titles" + ) { + capabilities.canGenerateWorkspaceTitle = false; + capabilities.canUseSmallModelTasks = false; + } + break; + } + } + return { providerId, connectionState, diff --git a/bun.lock b/bun.lock index 61b4aeca4a7..d61c15ce5b2 100644 --- a/bun.lock +++ b/bun.lock @@ -150,7 +150,6 @@ "@hono/node-server": "^1.14.1", "@hookform/resolvers": "^5.2.2", "@lezer/highlight": "^1.2.3", - "@mastra/core": "1.25.0", "@parcel/watcher": "^2.5.6", "@pierre/diffs": "1.1.3", "@radix-ui/react-dialog": "^1.1.15", @@ -278,7 +277,7 @@ "lowdb": "^7.0.1", "lowlight": "^3.3.0", "lucide-react": "^0.563.0", - "mastracode": "0.14.0", + "mastracode": "0.9.2", "nanoid": "^5.1.6", "node-addon-api": "^7.1.0", "node-pty": "1.1.0", @@ -676,7 +675,7 @@ "dependencies": { "@ai-sdk/anthropic": "^3.0.43", "@ai-sdk/openai": "3.0.36", - "@mastra/core": "1.25.0", + "@mastra/core": "1.16.0", "@mastra/mcp": "1.3.1", "@superset/trpc": "workspace:*", "@superset/workspace-fs": "workspace:*", @@ -684,7 +683,7 @@ "@trpc/server": "^11.7.1", "ai": "^6.0.0", "hono": "^4.8.5", - "mastracode": "0.14.0", + "mastracode": "0.9.2", "superjson": "^2.2.5", "zod": "^4.3.5", }, @@ -797,7 +796,6 @@ "@hono/node-ws": "^1.3.0", "@hono/trpc-server": "^0.3.4", "@octokit/rest": "^22.0.1", - "@superset/chat": "workspace:*", "@superset/shared": "workspace:*", "@superset/trpc": "workspace:*", "@superset/workspace-fs": "workspace:*", @@ -807,7 +805,7 @@ "better-sqlite3": "12.6.2", "drizzle-orm": "0.45.1", "hono": "^4.8.5", - "mastracode": "0.14.0", + "mastracode": "0.9.2", "node-pty": "1.1.0", "simple-git": "^3.30.0", "superjson": "^2.2.5", @@ -1064,52 +1062,28 @@ "@a2a-js/sdk": ["@a2a-js/sdk@0.2.5", "", { "dependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.23", "body-parser": "^2.2.0", "cors": "^2.8.5", "express": "^4.21.2", "uuid": "^11.1.0" } }, "sha512-VTDuRS5V0ATbJ/LkaQlisMnTAeYKXAK6scMguVBstf+KIBQ7HIuKhiXLv+G/hvejkV+THoXzoNifInAkU81P1g=="], - "@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@3.0.97", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.77", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-EUkR9ovQQY9dHVo67bchi9Qa+05FlSee6hTNZ6X1Rz1SJQKIIR2jt9rN7glRTvrYd+70zU7Xl993RKE3JtqT9w=="], - "@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.71", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bUWOzrzR0gJKJO/PLGMR4uH2dqEgqGhrsCV+sSpk4KtOEnUQlfjZI/F7BFlqSvVpFbjdgYRRLysAeEZpJ6S1lg=="], - "@ai-sdk/azure": ["@ai-sdk/azure@2.0.105", "", { "dependencies": { "@ai-sdk/openai": "2.0.103", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-pdYOtsFNJvNARbNxHORBIS6gwvU6yHdmgB3ZAzGdt89TiVtWiO1/quJeJ7Y3KUVLbjdpbVsTAWlL/J70XQxV5A=="], - - "@ai-sdk/cerebras": ["@ai-sdk/cerebras@1.0.41", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.36", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-UeBaOMXOcfkzHZE8TfbWRe9OMDkwB1NpHe837A+mRGWFabgdpJFTDnNrqCQVc3kGdDVhYBiDFh0lOEd8QRwJHQ=="], - - "@ai-sdk/deepseek": ["@ai-sdk/deepseek@1.0.37", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-GXSsA1wz0r9LdtEa7uxSB3ynaLHzKP7WmExrl5v5QgNVCmjmv/P4RhEMa1T6JFVdqG2sK1Nud/VWJ38LlnxkGg=="], - "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.104", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZKX5n74io8VIRlhIMSLWVlvT3sXC8Z7cZ9GHuWBWZDVi96+62AIsWuLGvMfcBA1STYuSoDrp6rIziZmvrTq0TA=="], - "@ai-sdk/google": ["@ai-sdk/google@2.0.70", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-NDMTvMo6vnPHDTA94FBOh3YMv0lxWDohYmFSGYhg0IimHMcOcC1ZV7E2KMLjzHOz5S7uasTITW7V3X5T+ozInQ=="], - - "@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.132", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.77", "@ai-sdk/google": "2.0.70", "@ai-sdk/openai-compatible": "1.0.36", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-IZfAutGNrHPk7VsziwtBVsNBnXTS2y5qZpI1tT9MdN+O6z0UFv6LVBDIpAFAZcQOec9M22j+5uc4ukB6BfC/0A=="], - - "@ai-sdk/groq": ["@ai-sdk/groq@2.0.38", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-qw6OB9RTYy1JO1//FK/bE4o12sl6s6uff7+C2L0AlskRbqOw0oWNh1FjeQU9bqHdObL5P6/UU1Cnq0FcQ7OT3g=="], - - "@ai-sdk/mistral": ["@ai-sdk/mistral@2.0.31", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ii+06f4Vzt3OH7/FNCj/QVms65VaZxqfat9GvMZ03ZdxlhO8yWzw83j3OqgdQ8pRL5qkABNepf06YUwfeNz6XQ=="], - "@ai-sdk/openai": ["@ai-sdk/openai@3.0.36", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.15" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-foY3onGY8l3q9niMw0Cwe9xrYnm46keIWL57NRw6F3DKzSW9TYTfx0cQJs/j8lXJ8lPzqNxpMO/zXOkqCUt3IQ=="], - "@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.36", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ePJ1nj1Wv2QcG9m8zA3zT20WBInFqEfwV17KT0JBeRyQucmiJBwIhzLkOq95O0sBwUutJJJrQNG8pEYxGf6w3w=="], - - "@ai-sdk/perplexity": ["@ai-sdk/perplexity@2.0.28", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-6KUdU+ccJEX+Y9xx8wKjEXIrELZINZg6NiZf2w9ZCcd96hC+8hkcq9TC4g3PDbtoA51ITfYXqwOer7UOx1nrZg=="], - "@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.23", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z8GlDaCmRSDlqkMF2f4/RFgWxdarvIbyuk+m6WXT1LYgsnGiXRJGTD2Z1+SDl3LqtFuRtGX1aghYvQLoHL/9pg=="], - "@ai-sdk/provider-utils-v5": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], + "@ai-sdk/provider-utils-v5": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], - "@ai-sdk/provider-utils-v6": ["@ai-sdk/provider-utils@4.0.23", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z8GlDaCmRSDlqkMF2f4/RFgWxdarvIbyuk+m6WXT1LYgsnGiXRJGTD2Z1+SDl3LqtFuRtGX1aghYvQLoHL/9pg=="], + "@ai-sdk/provider-utils-v6": ["@ai-sdk/provider-utils@4.0.0", "", { "dependencies": { "@ai-sdk/provider": "3.0.0", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-HyCyOls9I3a3e38+gtvOJOEjuw9KRcvbBnCL5GBuSmJvS9Jh9v3fz7pRC6ha1EUo/ZH1zwvLWYXBMtic8MTguA=="], "@ai-sdk/provider-v5": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - "@ai-sdk/provider-v6": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + "@ai-sdk/provider-v6": ["@ai-sdk/provider@3.0.5", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-2Xmoq6DBJqmSl80U6V9z5jJSJP7ehaJJQMy2iFUqTay06wdCqTnPVBBQbtEL8RCChenL+q5DC5H5WzU3vV3v8w=="], "@ai-sdk/react": ["@ai-sdk/react@3.0.170", "", { "dependencies": { "@ai-sdk/provider-utils": "4.0.23", "ai": "6.0.168", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" } }, "sha512-YUDn+mK0c8iUz14rCBf1A0zg6SV5b5aSVUz+azF1bdBd1SFXVI19dKYR+PQSpZY+0+z+zs252AAsacUqiO98Kw=="], - "@ai-sdk/togetherai": ["@ai-sdk/togetherai@1.0.39", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.36", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-RUKl8FD8WVnEHV//HnsNcV9r6lQGdfjYF2ypMON3eZZja2cGKdk/qrJnX9KBApkPjVmm2AiB1YBgkuVDWv8WTg=="], - "@ai-sdk/ui-utils-v5": ["@ai-sdk/ui-utils@1.2.11", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w=="], - "@ai-sdk/xai": ["@ai-sdk/xai@2.0.68", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.36", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-LqjizlypsbFcjVS/0BqGCPgvz4V5MaWCk+H7Tj7bZFQ1Ca8hby2Q0wGJ6u1ypR4Z8rRLHmfyrZ0mAEm/vd/d/A=="], - "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], @@ -1118,18 +1092,8 @@ "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.78.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-PzQhR715td/m1UaaN5hHXjYB8Gl2lF9UVhrrGrZeysiF6Rb74Wc9GCB8hzLdzmQtBd1qe89F9OptgB9Za1Ib5w=="], - "@anush008/tokenizers": ["@anush008/tokenizers@0.0.0", "", { "optionalDependencies": { "@anush008/tokenizers-darwin-universal": "0.0.0", "@anush008/tokenizers-linux-x64-gnu": "0.0.0", "@anush008/tokenizers-win32-x64-msvc": "0.0.0" } }, "sha512-IQD9wkVReKAhsEAbDjh/0KrBGTEXelqZLpOBRDaIRvlzZ9sjmUP+gKbpvzyJnei2JHQiE8JAgj7YcNloINbGBw=="], - - "@anush008/tokenizers-darwin-universal": ["@anush008/tokenizers-darwin-universal@0.0.0", "", { "os": "darwin" }, "sha512-SACpWEooTjFX89dFKRVUhivMxxcZRtA3nJGVepdLyrwTkQ1TZQ8581B5JoXp0TcTMHfgnDaagifvVoBiFEdNCQ=="], - - "@anush008/tokenizers-linux-x64-gnu": ["@anush008/tokenizers-linux-x64-gnu@0.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-TLjByOPWUEq51L3EJkS+slyH57HKJ7lAz/aBtEt7TIPq4QsE2owOPGovByOLIq1x5Wgh9b+a4q2JasrEFSDDhg=="], - - "@anush008/tokenizers-win32-x64-msvc": ["@anush008/tokenizers-win32-x64-msvc@0.0.0", "", { "os": "win32", "cpu": "x64" }, "sha512-/5kP0G96+Cr6947F0ZetXnmL31YCaN15dbNbh2NHg7TXXRwfqk95+JtPP5Q7v4jbR2xxAmuseBqB4H/V7zKWuw=="], - "@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@14.2.1", "", { "dependencies": { "js-yaml": "^4.1.0" }, "peerDependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-HmdFw9CDYqM6B25pqGBpNeLCKvGPlIx1EbLrVL0zPvj50CJQUHyBNBw45Muk0kEIkogo1VZvOKHajdMuAzSxRg=="], - "@appium/logger": ["@appium/logger@1.7.1", "", { "dependencies": { "console-control-strings": "1.1.0", "lodash": "4.17.21", "lru-cache": "10.4.3", "set-blocking": "2.0.0" } }, "sha512-9C2o9X/lBEDBUnKfAi3mRo9oG7Z03nmISLwsGkWxIWjMAvBdJD0RRSJMekWVKzfXN3byrI1WlCXTITzN4LAoLw=="], - "@ast-grep/napi": ["@ast-grep/napi@0.41.1", "", { "optionalDependencies": { "@ast-grep/napi-darwin-arm64": "0.41.1", "@ast-grep/napi-darwin-x64": "0.41.1", "@ast-grep/napi-linux-arm64-gnu": "0.41.1", "@ast-grep/napi-linux-arm64-musl": "0.41.1", "@ast-grep/napi-linux-x64-gnu": "0.41.1", "@ast-grep/napi-linux-x64-musl": "0.41.1", "@ast-grep/napi-win32-arm64-msvc": "0.41.1", "@ast-grep/napi-win32-ia32-msvc": "0.41.1", "@ast-grep/napi-win32-x64-msvc": "0.41.1" } }, "sha512-OYQVWBbb43af2lTSCayMS7wsZ20nl+fw6LGVl/5zSuHTZRNfANknKLk3wMA4y7RIaAiIwrldAmI6GNZeIDRTkQ=="], "@ast-grep/napi-darwin-arm64": ["@ast-grep/napi-darwin-arm64@0.41.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-sZHwg/oD6YB2y4VD8ZMeMHBq/ONil+mx+bB61YAiGQB+8UCMSFxJupvtNICB/BnIFqcPCVz/jCaSdbASLrbXQQ=="], @@ -1152,12 +1116,6 @@ "@astrojs/compiler": ["@astrojs/compiler@2.13.1", "", {}, "sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg=="], - "@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="], - - "@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/types": ["@aws-sdk/types@3.973.8", "", { "dependencies": { "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw=="], - "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], "@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="], @@ -1392,10 +1350,6 @@ "@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.2", "", {}, "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA=="], - "@browserbasehq/sdk": ["@browserbasehq/sdk@2.10.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-pOL4yW8P8AI2+N5y6zEP6XXKqIXtYyKunr1JXppqQDOyKLxxvZEDqQCHJXWUzqgx3R1tGWpn7m9AjXN7MeYInA=="], - - "@browserbasehq/stagehand": ["@browserbasehq/stagehand@3.2.1", "", { "dependencies": { "@ai-sdk/provider": "^2.0.0", "@anthropic-ai/sdk": "0.39.0", "@browserbasehq/sdk": "^2.7.0", "@google/genai": "^1.22.0", "@langchain/openai": "^0.4.4", "@modelcontextprotocol/sdk": "^1.17.2", "ai": "^5.0.133", "devtools-protocol": "^0.0.1464554", "fetch-cookie": "^3.1.0", "openai": "^4.87.1", "pino": "^9.6.0", "pino-pretty": "^13.0.0", "uuid": "^11.1.0", "ws": "^8.18.0", "zod-to-json-schema": "^3.25.0" }, "optionalDependencies": { "@ai-sdk/amazon-bedrock": "^3.0.73", "@ai-sdk/anthropic": "^2.0.34", "@ai-sdk/azure": "^2.0.54", "@ai-sdk/cerebras": "^1.0.25", "@ai-sdk/deepseek": "^1.0.23", "@ai-sdk/google": "^2.0.53", "@ai-sdk/google-vertex": "^3.0.70", "@ai-sdk/groq": "^2.0.24", "@ai-sdk/mistral": "^2.0.19", "@ai-sdk/openai": "^2.0.53", "@ai-sdk/perplexity": "^2.0.13", "@ai-sdk/togetherai": "^1.0.23", "@ai-sdk/xai": "^2.0.26", "@langchain/core": "^0.3.80", "bufferutil": "^4.0.9", "chrome-launcher": "^1.2.0", "ollama-ai-provider-v2": "^1.5.0", "patchright-core": "^1.55.2", "playwright": "^1.52.0", "playwright-core": "^1.54.1", "puppeteer-core": "^22.8.0" }, "peerDependencies": { "deepmerge": "^4.3.1", "zod": "^3.25.76 || ^4.2.0" } }, "sha512-h7KAAaNK7JUMw97w7sj0CBsBVtjLXyEorbUoYmCwLYYWrL2IUd9WFS7gRFspCp0ww2hpVPJEKMxHumwFCPEC8g=="], - "@cfworker/json-schema": ["@cfworker/json-schema@4.1.1", "", {}, "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og=="], "@chevrotain/cst-dts-gen": ["@chevrotain/cst-dts-gen@12.0.0", "", { "dependencies": { "@chevrotain/gast": "12.0.0", "@chevrotain/types": "12.0.0" } }, "sha512-fSL4KXjTl7cDgf0B5Rip9Q05BOrYvkJV/RrBTE/bKDN096E4hN/ySpcBK5B24T76dlQ2i32Zc3PAE27jFnFrKg=="], @@ -1680,8 +1634,6 @@ "@fumadocs/ui": ["@fumadocs/ui@16.4.7", "", { "dependencies": { "next-themes": "^0.4.6", "postcss-selector-parser": "^7.1.1", "tailwind-merge": "^3.4.0" }, "peerDependencies": { "@types/react": "*", "fumadocs-core": "16.4.7", "next": "16.x.x", "react": "^19.2.0", "react-dom": "^19.2.0", "tailwindcss": "^4.0.0" }, "optionalPeers": ["@types/react", "next", "tailwindcss"] }, "sha512-NnkMIN5BzBRh2OzA9rp2SgbGEkEwfCfq0sE4vq2n+GkIDIggicGYUNgSl2gtIBQsKYKP/a4/0wrkQKdq4eUJlw=="], - "@google/genai": ["@google/genai@1.50.1", "", { "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-YbkX7H9+1Pt8wOt7DDREy8XSoiL6fRDzZQRyaVBarFf8MR3zHGqVdvM4cLbDXqPhxqvegZShgfxb8kw9C7YhAQ=="], - "@graphql-hive/signal": ["@graphql-hive/signal@1.0.0", "", {}, "sha512-RiwLMc89lTjvyLEivZ/qxAC5nBHoS2CtsWFSOsN35sxG9zoo5Z+JsFHM8MlvmO9yt+MJNIyC5MLE1rsbOphlag=="], "@graphql-tools/batch-execute": ["@graphql-tools/batch-execute@9.0.19", "", { "dependencies": { "@graphql-tools/utils": "^10.9.1", "@whatwg-node/promise-helpers": "^1.3.0", "dataloader": "^2.2.3", "tslib": "^2.8.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-VGamgY4PLzSx48IHPoblRw0oTaBa7S26RpZXt0Y4NN90ytoE0LutlpB2484RbkfcTjv9wa64QD474+YP1kEgGA=="], @@ -1734,10 +1686,6 @@ "@hookform/resolvers": ["@hookform/resolvers@5.2.2", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.55.0" } }, "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA=="], - "@huggingface/hub": ["@huggingface/hub@2.11.0", "", { "dependencies": { "@huggingface/tasks": "^0.19.90" }, "optionalDependencies": { "cli-progress": "^3.12.0" }, "bin": { "hfjs": "dist/cli.js" } }, "sha512-WS6QGaXYeBVFlaB4SOn6z4LGUpLB5kRZNL08uUni4izX353KxiwwZMK5+/AWX86MJh8SMZNa/JFcvFCcQsbszQ=="], - - "@huggingface/tasks": ["@huggingface/tasks@0.19.90", "", {}, "sha512-nfV9luJbvwGQ/5oKXkKhCV9h4X7mwh1YaGG3ORd6UMLDSwr1OFSSatcBX0O9OtBtmNK19aGSjbLFqqgcIR6+IA=="], - "@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="], "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], @@ -1834,10 +1782,6 @@ "@kwsites/promise-deferred": ["@kwsites/promise-deferred@1.1.1", "", {}, "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="], - "@langchain/core": ["@langchain/core@0.3.80", "", { "dependencies": { "@cfworker/json-schema": "^4.0.2", "ansi-styles": "^5.0.0", "camelcase": "6", "decamelize": "1.2.0", "js-tiktoken": "^1.0.12", "langsmith": "^0.3.67", "mustache": "^4.2.0", "p-queue": "^6.6.2", "p-retry": "4", "uuid": "^10.0.0", "zod": "^3.25.32", "zod-to-json-schema": "^3.22.3" } }, "sha512-vcJDV2vk1AlCwSh3aBm/urQ1ZrlXFFBocv11bz/NBUfLWD5/UDNMzwPdaAd2dKvNmTWa9FM2lirLU3+JCf4cRA=="], - - "@langchain/openai": ["@langchain/openai@0.4.9", "", { "dependencies": { "js-tiktoken": "^1.0.12", "openai": "^4.87.3", "zod": "^3.22.4", "zod-to-json-schema": "^3.22.3" }, "peerDependencies": { "@langchain/core": ">=0.3.39 <0.4.0" } }, "sha512-NAsaionRHNdqaMjVLPkFCyjUDze+OqRHghA1Cn4fPoAafz+FXcl9c7LlEl9Xo0FH6/8yiCl7Rw2t780C/SBVxQ=="], - "@lezer/common": ["@lezer/common@1.5.2", "", {}, "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ=="], "@lezer/cpp": ["@lezer/cpp@1.1.5", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-DIhSXmYtJKLehrjzDFN+2cPt547ySQ41nA8yqcDf/GxMc+YM736xqltFkvADL2M0VebU5I+3+4ks2Vv+Kyq3Aw=="], @@ -1912,23 +1856,17 @@ "@mariozechner/pi-tui": ["@mariozechner/pi-tui@0.60.0", "", { "dependencies": { "@types/mime-types": "^2.1.4", "chalk": "^5.5.0", "get-east-asian-width": "^1.3.0", "marked": "^15.0.12", "mime-types": "^3.0.1" }, "optionalDependencies": { "koffi": "^2.9.0" } }, "sha512-ZAK5gxYhGmfJqMjfWcRBjB8glITltDbTrYJXvcDtfengbKTZN0p39p5uO5pvUB8/PiAWKTRS06yaNMhf/LG26g=="], - "@mastra/agent-browser": ["@mastra/agent-browser@0.2.0", "", { "dependencies": { "agent-browser": "0.19.0", "typed-emitter": "^2.1.0" }, "peerDependencies": { "@mastra/core": ">=1.22.0-0 <2.0.0-0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-JAOvfY9U8VLVo46qMmAqhbi8oMVSbto1g7V43JIeVWTBc4IL7R7UBEEpYzgCZ6KblxN038atvP8McMchO76uGQ=="], + "@mastra/core": ["@mastra/core@1.16.0", "", { "dependencies": { "@a2a-js/sdk": "~0.2.5", "@ai-sdk/provider-utils-v5": "npm:@ai-sdk/provider-utils@3.0.20", "@ai-sdk/provider-utils-v6": "npm:@ai-sdk/provider-utils@4.0.0", "@ai-sdk/provider-v5": "npm:@ai-sdk/provider@2.0.1", "@ai-sdk/provider-v6": "npm:@ai-sdk/provider@3.0.5", "@ai-sdk/ui-utils-v5": "npm:@ai-sdk/ui-utils@1.2.11", "@isaacs/ttlcache": "^2.1.4", "@lukeed/uuid": "^2.0.1", "@mastra/schema-compat": "1.2.7", "@modelcontextprotocol/sdk": "^1.27.1", "@sindresorhus/slugify": "^2.2.1", "@standard-schema/spec": "^1.1.0", "ajv": "^8.18.0", "dotenv": "^17.3.1", "execa": "^9.6.1", "gray-matter": "^4.0.3", "hono": "^4.12.8", "hono-openapi": "^1.3.0", "ignore": "^7.0.5", "js-tiktoken": "^1.0.21", "json-schema": "^0.4.0", "lru-cache": "^11.2.7", "p-map": "^7.0.4", "p-retry": "^7.1.1", "picomatch": "^4.0.3", "radash": "^12.1.1", "ws": "^8.19.0", "xxhash-wasm": "^1.1.0" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-8CuVN1/oIByJMydOkQwBSEa8jGHEUNg5EMB4ydovGbqDg1tSfIbVIO1EDOMXK6sS6RllkFbC+jsNuw6AP5o0Eg=="], - "@mastra/core": ["@mastra/core@1.25.0", "", { "dependencies": { "@a2a-js/sdk": "~0.2.5", "@ai-sdk/provider-utils-v5": "npm:@ai-sdk/provider-utils@3.0.23", "@ai-sdk/provider-utils-v6": "npm:@ai-sdk/provider-utils@4.0.23", "@ai-sdk/provider-v5": "npm:@ai-sdk/provider@2.0.1", "@ai-sdk/provider-v6": "npm:@ai-sdk/provider@3.0.8", "@ai-sdk/ui-utils-v5": "npm:@ai-sdk/ui-utils@1.2.11", "@isaacs/ttlcache": "^2.1.4", "@lukeed/uuid": "^2.0.1", "@mastra/schema-compat": "1.2.8", "@modelcontextprotocol/sdk": "^1.27.1", "@sindresorhus/slugify": "^2.2.1", "@standard-schema/spec": "^1.1.0", "ajv": "^8.18.0", "chat": "^4.24.0", "dotenv": "^17.3.1", "execa": "^9.6.1", "gray-matter": "^4.0.3", "hono": "^4.12.8", "hono-openapi": "^1.3.0", "ignore": "^7.0.5", "js-tiktoken": "^1.0.21", "json-schema": "^0.4.0", "lru-cache": "^11.2.7", "p-map": "^7.0.4", "p-retry": "^7.1.1", "picomatch": "^4.0.3", "radash": "^12.1.1", "tokenx": "^1.3.0", "ws": "^8.19.0", "xxhash-wasm": "^1.1.0" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-4dkDXtufKWRO5Y7ic2JIgHpSSty5uYhqjiS2JfbKb3uV7rNpty8Fp5vSKC1ept08UudKAd5CcZWLNeKSP5816A=="], - - "@mastra/fastembed": ["@mastra/fastembed@1.0.1", "", { "dependencies": { "fastembed": "^2.1.0" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-ApR905nHLLm+9fsaeYep/NhC5dk9i1tTLVH/JLZt9sIp1OohFCNn95kNEPalqm8ula2jX1A0rnJaOyM/v/jhBA=="], - - "@mastra/libsql": ["@mastra/libsql@1.8.1", "", { "dependencies": { "@libsql/client": "^0.15.15" }, "peerDependencies": { "@mastra/core": ">=1.0.0-0 <2.0.0-0" } }, "sha512-BQPXck6eckeCOWK83G7a455dsgqtKYTmUfaSv8py86fw4/XfQlemGfxv5KyzqruRW8Z+l037FibHCMO8PZuKpw=="], + "@mastra/libsql": ["@mastra/libsql@1.7.2", "", { "dependencies": { "@libsql/client": "^0.15.15" }, "peerDependencies": { "@mastra/core": ">=1.0.0-0 <2.0.0-0" } }, "sha512-BW4wYChvg2Yxci7RfRerCis36ox2EnXXkvlYY1wtnww+5dQSNS5Y+TDrqBxYMi0V2TFWKm5Gs8W0V7HFRhLUPw=="], "@mastra/mcp": ["@mastra/mcp@1.3.1", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^14.2.1", "@modelcontextprotocol/sdk": "^1.27.1", "exit-hook": "^5.1.0", "fast-deep-equal": "^3.1.3", "uuid": "^13.0.0" }, "peerDependencies": { "@mastra/core": ">=1.0.0-0 <2.0.0-0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-eCbOm9Hu15UFOwPTJ4bvn/wJP0gUZdjoQkOIcq5CGWo/WIM6afCo7rXSNYg2k4gN2vR0u9ZwJHXwzXjcTHFcjQ=="], - "@mastra/memory": ["@mastra/memory@1.15.1", "", { "dependencies": { "@mastra/schema-compat": "1.2.8", "async-mutex": "^0.5.0", "image-size": "^2.0.2", "json-schema": "^0.4.0", "lru-cache": "^11.2.7", "probe-image-size": "^7.2.3", "tokenx": "^1.3.0", "xxhash-wasm": "^1.1.0" }, "peerDependencies": { "@mastra/core": ">=1.4.1-0 <2.0.0-0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-OdUeEMAVpYrZx6FquziF3I48P1SlVEQagM6e7b770KIl6E5RhRJLWgbBYZT/HJFqvzyb5b7Iahd2MadTzHxkwQ=="], - - "@mastra/pg": ["@mastra/pg@1.9.1", "", { "dependencies": { "async-mutex": "^0.5.0", "pg": "^8.20.0", "xxhash-wasm": "^1.1.0" }, "peerDependencies": { "@mastra/core": ">=1.4.0-0 <2.0.0-0" } }, "sha512-i2Vjx3KGhiFFMIjKSoDzXZuyDBsKgMvxNjGSPUVwQnasbkchdqbzC6bDolaiziRSL1gaByxyLK1V7CXD4T6bIQ=="], + "@mastra/memory": ["@mastra/memory@1.10.0", "", { "dependencies": { "@mastra/schema-compat": "1.2.7", "async-mutex": "^0.5.0", "image-size": "^2.0.2", "json-schema": "^0.4.0", "lru-cache": "^11.2.7", "probe-image-size": "^7.2.3", "tokenx": "^1.3.0", "xxhash-wasm": "^1.1.0" }, "peerDependencies": { "@mastra/core": ">=1.4.1-0 <2.0.0-0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Vn27u6pOT5PjEI4IqDZGdmKfw2n+fvEjkuL6W56+CRNBitTWgI9tkjtVlAnYO7hviLmMCDb7HDQ7mHOVjim39Q=="], - "@mastra/schema-compat": ["@mastra/schema-compat@1.2.8", "", { "dependencies": { "json-schema-to-zod": "^2.7.0", "zod-from-json-schema": "^0.5.2", "zod-from-json-schema-v3": "npm:zod-from-json-schema@^0.0.5", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-XoFCtk2+wEY3ciQsuAcMF4/VvyPEZyA5mepC+nVBw5y4099e/oBUCUB/lu6/Zi9mrm99peFNwk60+iWV/C4FHA=="], + "@mastra/pg": ["@mastra/pg@1.8.3", "", { "dependencies": { "async-mutex": "^0.5.0", "pg": "^8.20.0", "xxhash-wasm": "^1.1.0" }, "peerDependencies": { "@mastra/core": ">=1.4.0-0 <2.0.0-0" } }, "sha512-PIpLZY0u5B2w41/HYP31yIvrABFWndVCLqEk237BsMPw2UixhN9XSZwiXwmaaQEtwrqosKCCr7sR+tPi4/p+hA=="], - "@mastra/stagehand": ["@mastra/stagehand@0.2.0", "", { "dependencies": { "@browserbasehq/stagehand": "^3.2.1" }, "peerDependencies": { "@mastra/core": ">=1.22.0-0 <2.0.0-0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-qZTHN3SbPx9VedVRsEZ3wPsJ+zf/wkEtXn7FZsEd+Q2/pVJ2BNgo8rccQMJ1WGId2FZIAl2EYnZBFe7yGihpag=="], + "@mastra/schema-compat": ["@mastra/schema-compat@1.2.7", "", { "dependencies": { "json-schema-to-zod": "^2.7.0", "zod-from-json-schema": "^0.5.2", "zod-from-json-schema-v3": "npm:zod-from-json-schema@^0.0.5", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-t63E0f5HcH8neXPfs3D5x4qqQM6Pf/pbhFUVk0cTC0bFo6609sT/+189I+2HY4sbAF3uzurOgy2fXIS4vfMkOA=="], "@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="], @@ -1970,8 +1908,6 @@ "@noble/hashes": ["@noble/hashes@2.2.0", "", {}, "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg=="], - "@nodable/entities": ["@nodable/entities@2.1.0", "", {}, "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA=="], - "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], @@ -2128,8 +2064,6 @@ "@pierre/theme": ["@pierre/theme@0.0.22", "", {}, "sha512-ePUIdQRNGjrveELTU7fY89Xa7YGHHEy5Po5jQy/18lm32eRn96+tnYJEtFooGdffrx55KBUtOXfvVy/7LDFFhA=="], - "@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="], - "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], "@popperjs/core": ["@popperjs/core@2.11.8", "", {}, "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="], @@ -2144,28 +2078,6 @@ "@prisma/instrumentation": ["@prisma/instrumentation@7.6.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.207.0" }, "peerDependencies": { "@opentelemetry/api": "^1.8" } }, "sha512-ZPW2gRiwpPzEfgeZgaekhqXrbW+Y2RJKHVqUmlhZhKzRNCcvR6DykzylDrynpArKKRQtLxoZy36fK7U0p3pdgQ=="], - "@promptbook/utils": ["@promptbook/utils@0.69.5", "", { "dependencies": { "spacetrim": "0.11.59" } }, "sha512-xm5Ti/Hp3o4xHrsK9Yy3MS6KbDxYbq485hDsFvxqaNA7equHLPdo8H8faTitTeb14QCDfLW4iwCxdVYu5sn6YQ=="], - - "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], - - "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], - - "@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="], - - "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="], - - "@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="], - - "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="], - - "@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="], - - "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="], - - "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="], - - "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="], - "@puppeteer/browsers": ["@puppeteer/browsers@2.13.0", "", { "dependencies": { "debug": "^4.4.3", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", "semver": "^7.7.4", "tar-fs": "^3.1.1", "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" } }, "sha512-46BZJYJjc/WwmKjsvDFykHtXrtomsCIrwYQPOP7VfMJoZY2bsDF9oROBABR3paDjDcmkUye1Pb1BqdcdiipaWA=="], "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="], @@ -2582,18 +2494,6 @@ "@slack/web-api": ["@slack/web-api@7.15.1", "", { "dependencies": { "@slack/logger": "^4.0.1", "@slack/types": "^2.20.1", "@types/node": ">=18", "@types/retry": "0.12.0", "axios": "^1.15.0", "eventemitter3": "^5.0.1", "form-data": "^4.0.4", "is-electron": "2.2.2", "is-stream": "^2", "p-queue": "^6", "p-retry": "^4", "retry": "^0.13.1" } }, "sha512-y+TAF7TszcmFzbVtBkFqAdBwKSoD+8shkNxhp4WIfFwXmCKdFje9WD6evROApPa2FTy1v1uc9yBaJs3609PPgg=="], - "@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.14", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.1", "@smithy/util-hex-encoding": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-erZq0nOIpzfeZdCyzZjdJb4nVSKLUmSkaQUVkRGQTXs30gyUGeKnrYEg+Xe1W5gE3aReS7IgsvANwVPxSzY6Pw=="], - - "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow=="], - - "@smithy/types": ["@smithy/types@4.14.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg=="], - - "@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.2", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q=="], - - "@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg=="], - - "@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], - "@socket.io/component-emitter": ["@socket.io/component-emitter@3.1.2", "", {}, "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="], "@speed-highlight/core": ["@speed-highlight/core@1.2.15", "", {}, "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw=="], @@ -3014,8 +2914,6 @@ "@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], - "@types/node-fetch": ["@types/node-fetch@2.6.13", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw=="], - "@types/offscreencanvas": ["@types/offscreencanvas@2019.7.3", "", {}, "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A=="], "@types/pg": ["@types/pg@8.15.6", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ=="], @@ -3052,8 +2950,6 @@ "@types/shell-quote": ["@types/shell-quote@1.7.5", "", {}, "sha512-+UE8GAGRPbJVQDdxi16dgadcBfQ+KG2vgZhV1+3A1XmHbmwcdwhCUwIdy+d3pAGrbvgRoVSjeI9vOWyq376Yzw=="], - "@types/sinonjs__fake-timers": ["@types/sinonjs__fake-timers@8.1.5", "", {}, "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ=="], - "@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="], "@types/stats.js": ["@types/stats.js@0.17.4", "", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="], @@ -3078,8 +2974,6 @@ "@types/webxr": ["@types/webxr@0.5.24", "", {}, "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg=="], - "@types/which": ["@types/which@2.0.2", "", {}, "sha512-113D3mDkZDjo+EeUEHCFy0qniNc1ZpecGiAU7WSo7YDoSzolZIQKpYFHrPpjkB2nuyahcKfrmLXeQlh7gqJYdw=="], - "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], "@types/yargs": ["@types/yargs@16.0.5", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ=="], @@ -3138,18 +3032,6 @@ "@vue/shared": ["@vue/shared@3.5.32", "", {}, "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg=="], - "@wdio/config": ["@wdio/config@9.27.0", "", { "dependencies": { "@wdio/logger": "9.18.0", "@wdio/types": "9.27.0", "@wdio/utils": "9.27.0", "deepmerge-ts": "^7.0.3", "glob": "^10.2.2", "import-meta-resolve": "^4.0.0", "jiti": "^2.6.1" } }, "sha512-9y8z7ugIbU6ycKrA2SqCpKh1/hobut2rDq9CLt/BNVzSlebBBVOTMiAt1XroZzcPnA7/ZqpbkpOsbpPUaAQuNQ=="], - - "@wdio/logger": ["@wdio/logger@9.18.0", "", { "dependencies": { "chalk": "^5.1.2", "loglevel": "^1.6.0", "loglevel-plugin-prefix": "^0.8.4", "safe-regex2": "^5.0.0", "strip-ansi": "^7.1.0" } }, "sha512-HdzDrRs+ywAqbXGKqe1i/bLtCv47plz4TvsHFH3j729OooT5VH38ctFn5aLXgECmiAKDkmH/A6kOq2Zh5DIxww=="], - - "@wdio/protocols": ["@wdio/protocols@9.27.0", "", {}, "sha512-rIk69BsY1+6uU2PEN5FiRpI6K7HJ86YHzZRFBe4iRzKXQgGNk1zWzbdVJIuNFoOWsnmYUkK42KSSOT4Le6EmiQ=="], - - "@wdio/repl": ["@wdio/repl@9.16.2", "", { "dependencies": { "@types/node": "^20.1.0" } }, "sha512-FLTF0VL6+o5BSTCO7yLSXocm3kUnu31zYwzdsz4n9s5YWt83sCtzGZlZpt7TaTzb3jVUfxuHNQDTb8UMkCu0lQ=="], - - "@wdio/types": ["@wdio/types@9.27.0", "", { "dependencies": { "@types/node": "^20.1.0" } }, "sha512-DQJ+OdRBqUBcQ30DN2Z651hEVh3OoxnlDUSRqlWy9An2AY6v9rYWTj825B6zsj5pLLEToYO1tfwWq0ab183pXg=="], - - "@wdio/utils": ["@wdio/utils@9.27.0", "", { "dependencies": { "@puppeteer/browsers": "^2.2.0", "@wdio/logger": "9.18.0", "@wdio/types": "9.27.0", "decamelize": "^6.0.0", "deepmerge-ts": "^7.0.3", "edgedriver": "^6.1.2", "geckodriver": "^6.1.0", "get-port": "^7.0.0", "import-meta-resolve": "^4.0.0", "locate-app": "^2.2.24", "mitt": "^3.0.1", "safaridriver": "^1.0.0", "split2": "^4.2.0", "wait-port": "^1.1.0" } }, "sha512-fUasd5OKJTy2seJfWnYZ9xlxTtY0p/Kyeuh7Tbb8kcofBqmBi2fTvM3sfZlo1tGQX9yCh+IS2N7hlfyFMmuZ+w=="], - "@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="], "@webassemblyjs/floating-point-hex-parser": ["@webassemblyjs/floating-point-hex-parser@1.13.2", "", {}, "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="], @@ -3190,8 +3072,6 @@ "@whatwg-node/promise-helpers": ["@whatwg-node/promise-helpers@1.3.2", "", { "dependencies": { "tslib": "^2.6.3" } }, "sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA=="], - "@workflow/serde": ["@workflow/serde@4.1.0-beta.2", "", {}, "sha512-8kkeoQKLDaKXefjV5dbhBj2aErfKp1Mc4pb6tj8144cF+Em5SPbyMbyLCHp+BVrFfFVCBluCtMx+jjvaFVZGww=="], - "@xmldom/xmldom": ["@xmldom/xmldom@0.8.12", "", {}, "sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg=="], "@xterm/addon-clipboard": ["@xterm/addon-clipboard@0.3.0-beta.195", "", { "dependencies": { "js-base64": "^3.7.5" }, "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.195" } }, "sha512-V266O7m5wtLCcnXGUbi70cl96vyBcwaVTImftBEBXAo6X+Pn5NpG48QgP+svtt0gB7Sc0FDA/TBVeXuFyoX+kA=="], @@ -3224,8 +3104,6 @@ "@xyflow/system": ["@xyflow/system@0.0.76", "", { "dependencies": { "@types/d3-drag": "^3.0.7", "@types/d3-interpolate": "^3.0.4", "@types/d3-selection": "^3.0.10", "@types/d3-transition": "^3.0.8", "@types/d3-zoom": "^3.0.8", "d3-drag": "^3.0.0", "d3-interpolate": "^3.0.1", "d3-selection": "^3.0.0", "d3-zoom": "^3.0.0" } }, "sha512-hvwvnRS1B3REwVDlWexsq7YQaPZeG3/mKo1jv38UmnpWmxihp14bW6VtEOuHEwJX2FvzFw8k77LyKSk/wiZVNA=="], - "@zip.js/zip.js": ["@zip.js/zip.js@2.8.26", "", {}, "sha512-RQ4h9F6DOiHxpdocUDrOl6xBM+yOtz+LkUol47AVWcfebGBDpZ7w7Xvz9PS24JgXvLGiXXzSAfdCdVy1tPlaFA=="], - "abbrev": ["abbrev@3.0.1", "", {}, "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg=="], "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], @@ -3244,10 +3122,6 @@ "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], - "agent-browser": ["agent-browser@0.19.0", "", { "dependencies": { "node-simctl": "^7.4.0", "playwright-core": "^1.57.0", "webdriverio": "^9.15.0", "ws": "^8.19.0", "zod": "^3.22.4" }, "bin": { "agent-browser": "bin/agent-browser.js" } }, "sha512-Ull7jF/OO4P+Zm/SHKCOyJPRcPIGe0nvHPM+/E611qzYIyKGoSMfv2UozIs878uB4bI++cHeAUzitOXyjiawBQ=="], - - "agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="], - "aggregate-error": ["aggregate-error@4.0.1", "", { "dependencies": { "clean-stack": "^4.0.0", "indent-string": "^5.0.0" } }, "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w=="], "ai": ["ai@6.0.168", "", { "dependencies": { "@ai-sdk/gateway": "3.0.104", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-2HqCJuO+1V2aV7vfYs5LFEUfxbkGX+5oa54q/gCCTL7KLTdbxcCu5D7TdLA5kwsrs3Szgjah9q6D9tpjHM3hUQ=="], @@ -3320,20 +3194,14 @@ "async-retry": ["async-retry@1.3.3", "", { "dependencies": { "retry": "0.13.1" } }, "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw=="], - "asyncbox": ["asyncbox@3.0.0", "", { "dependencies": { "bluebird": "^3.5.1", "lodash": "^4.17.4", "source-map-support": "^0.x" } }, "sha512-X7U0nedUMKV3nn9c4R0Zgvdvv6cw97tbDlHSZicq1snGPi/oX9DgGmFSURWtxDdnBWd3V0YviKhqAYAVvoWQ/A=="], - "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], "at-least-node": ["at-least-node@1.0.0", "", {}, "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="], - "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], - "atomically": ["atomically@2.1.1", "", { "dependencies": { "stubborn-fs": "^2.0.0", "when-exit": "^2.1.4" } }, "sha512-P4w9o2dqARji6P7MHprklbfiArZAWvo07yW7qs3pdljb3BWr12FIB7W+p0zJiuiVsUpRO0iZn1kFFcpPegg0tQ=="], "ava": ["ava@5.3.1", "", { "dependencies": { "acorn": "^8.8.2", "acorn-walk": "^8.2.0", "ansi-styles": "^6.2.1", "arrgv": "^1.0.2", "arrify": "^3.0.0", "callsites": "^4.0.0", "cbor": "^8.1.0", "chalk": "^5.2.0", "chokidar": "^3.5.3", "chunkd": "^2.0.1", "ci-info": "^3.8.0", "ci-parallel-vars": "^1.0.1", "clean-yaml-object": "^0.1.0", "cli-truncate": "^3.1.0", "code-excerpt": "^4.0.0", "common-path-prefix": "^3.0.0", "concordance": "^5.0.4", "currently-unhandled": "^0.4.1", "debug": "^4.3.4", "emittery": "^1.0.1", "figures": "^5.0.0", "globby": "^13.1.4", "ignore-by-default": "^2.1.0", "indent-string": "^5.0.0", "is-error": "^2.2.2", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", "matcher": "^5.0.0", "mem": "^9.0.2", "ms": "^2.1.3", "p-event": "^5.0.1", "p-map": "^5.5.0", "picomatch": "^2.3.1", "pkg-conf": "^4.0.0", "plur": "^5.1.0", "pretty-ms": "^8.0.0", "resolve-cwd": "^3.0.0", "stack-utils": "^2.0.6", "strip-ansi": "^7.0.1", "supertap": "^3.0.1", "temp-dir": "^3.0.0", "write-file-atomic": "^5.0.1", "yargs": "^17.7.2" }, "peerDependencies": { "@ava/typescript": "*" }, "optionalPeers": ["@ava/typescript"], "bin": { "ava": "entrypoints/cli.mjs" } }, "sha512-Scv9a4gMOXB6+ni4toLuhAm9KYWEjsgBglJl+kMGI5+IVDt120CCDZyB5HNU9DjmLI2t4I0GbnxGLmmRfGTJGg=="], - "aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="], - "axios": ["axios@1.14.0", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } }, "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ=="], "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], @@ -3408,8 +3276,6 @@ "big-integer": ["big-integer@1.6.52", "", {}, "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="], - "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], - "binary": ["binary@0.3.0", "", { "dependencies": { "buffers": "~0.1.1", "chainsaw": "~0.1.0" } }, "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg=="], "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], @@ -3446,8 +3312,6 @@ "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], - "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], - "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], "buffer-indexof-polyfill": ["buffer-indexof-polyfill@1.0.2", "", {}, "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A=="], @@ -3500,12 +3364,6 @@ "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], - "chat": ["chat@4.26.0", "", { "dependencies": { "@workflow/serde": "4.1.0-beta.2", "mdast-util-to-string": "^4.0.0", "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "remend": "^1.2.1", "unified": "^11.0.5" } }, "sha512-QToDnIEGpyb8yQA6YLMHOSRK30YVk4RtsyFyuWFYyB2c4jQlyIrSWtwVK7qyvmvqzQp9uDwCdJRAhS8GtCHAGQ=="], - - "cheerio": ["cheerio@1.2.0", "", { "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "encoding-sniffer": "^0.2.1", "htmlparser2": "^10.1.0", "parse5": "^7.3.0", "parse5-htmlparser2-tree-adapter": "^7.1.0", "parse5-parser-stream": "^7.1.2", "undici": "^7.19.0", "whatwg-mimetype": "^4.0.0" } }, "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg=="], - - "cheerio-select": ["cheerio-select@2.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" } }, "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g=="], - "chevrotain": ["chevrotain@12.0.0", "", { "dependencies": { "@chevrotain/cst-dts-gen": "12.0.0", "@chevrotain/gast": "12.0.0", "@chevrotain/regexp-to-ast": "12.0.0", "@chevrotain/types": "12.0.0", "@chevrotain/utils": "12.0.0" } }, "sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ=="], "chevrotain-allstar": ["chevrotain-allstar@0.4.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^12.0.0" } }, "sha512-PvVJm3oGqrveUVW2Vt/eZGeiAIsJszYweUcYwcskg9e+IubNYKKD+rHHem7A6XVO22eDAL+inxNIGAzZ/VIWlA=="], @@ -3516,7 +3374,7 @@ "chroma-js": ["chroma-js@3.2.0", "", {}, "sha512-os/OippSlX1RlWWr+QDPcGUZs0uoqr32urfxESG9U93lhUfbnlyckte84Q8P1UQY/qth983AS1JONKmLS4T0nw=="], - "chrome-launcher": ["chrome-launcher@1.2.1", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^2.0.1" }, "bin": { "print-chrome-path": "bin/print-chrome-path.cjs" } }, "sha512-qmFR5PLMzHyuNJHwOloHPAHhbaNglkfeV/xDtt5b7xiFFyU1I+AZZX0PYseMuhenJSSirgxELYIbswcoc+5H4A=="], + "chrome-launcher": ["chrome-launcher@0.15.2", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0" }, "bin": { "print-chrome-path": "bin/print-chrome-path.js" } }, "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ=="], "chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="], @@ -3550,8 +3408,6 @@ "cli-highlight": ["cli-highlight@2.1.11", "", { "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", "mz": "^2.4.0", "parse5": "^5.1.1", "parse5-htmlparser2-tree-adapter": "^6.0.0", "yargs": "^16.0.0" }, "bin": { "highlight": "bin/highlight" } }, "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg=="], - "cli-progress": ["cli-progress@3.12.0", "", { "dependencies": { "string-width": "^4.2.3" } }, "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A=="], - "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], "cli-truncate": ["cli-truncate@3.1.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^5.0.0" } }, "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA=="], @@ -3584,8 +3440,6 @@ "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], - "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], - "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], @@ -3618,10 +3472,6 @@ "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], - "console-control-strings": ["console-control-strings@1.1.0", "", {}, "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="], - - "console-table-printer": ["console-table-printer@2.15.0", "", { "dependencies": { "simple-wcswidth": "^1.1.2" } }, "sha512-SrhBq4hYVjLCkBVOWaTzceJalvn5K1Zq5aQA6wXC/cYjI3frKWNPEMK3sZsJfNNQApvCQmgBcc13ZKmFj8qExw=="], - "content-disposition": ["content-disposition@1.1.0", "", {}, "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], @@ -3678,12 +3528,8 @@ "css-selector-parser": ["css-selector-parser@3.3.0", "", {}, "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g=="], - "css-shorthand-properties": ["css-shorthand-properties@1.1.2", "", {}, "sha512-C2AugXIpRGQTxaCW0N7n5jD/p5irUmCrwl03TrnMFBHDbdq44CFWR2zO7rK9xPN4Eo3pUxC4vQzQgbIpzrD1PQ=="], - "css-tree": ["css-tree@1.1.3", "", { "dependencies": { "mdn-data": "2.0.14", "source-map": "^0.6.1" } }, "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q=="], - "css-value": ["css-value@0.0.1", "", {}, "sha512-FUV3xaJ63buRLgHrLQVlVgQnQdR4yqdLGaDu7g8CQcWjInDfM9plBTPI9FRfpahju1UBSaMckeb2/46ApS/V1Q=="], - "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], @@ -3776,8 +3622,6 @@ "date-time": ["date-time@3.1.0", "", { "dependencies": { "time-zone": "^1.0.0" } }, "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg=="], - "dateformat": ["dateformat@4.6.3", "", {}, "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA=="], - "dayjs": ["dayjs@1.11.20", "", {}, "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="], "debounce": ["debounce@2.2.0", "", {}, "sha512-Xks6RUDLZFdz8LIdR6q0MTH44k7FikOmnh5xkSjMig6ch45afc8sjTjRQf3P6ax8dMgcQrYO/AR2RGWURrruqw=="], @@ -3788,8 +3632,6 @@ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - "decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="], - "decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="], "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], @@ -3806,8 +3648,6 @@ "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], - "deepmerge-ts": ["deepmerge-ts@7.1.5", "", {}, "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw=="], - "default-shell": ["default-shell@2.2.0", "", {}, "sha512-sPpMZcVhRQ0nEMDtuMJ+RtCxt7iHPAMBU+I4tAlo5dU1sjRpNax0crj6nR3qKpvVnckaQ9U38enXcwW9nZJeCw=="], "defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="], @@ -3910,12 +3750,6 @@ "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], - "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], - - "edge-paths": ["edge-paths@3.0.5", "", { "dependencies": { "@types/which": "^2.0.1", "which": "^2.0.2" } }, "sha512-sB7vSrDnFa4ezWQk9nZ/n0FdpdUuC6R1EOrlU3DL+bovcNFK28rqu2emmAUjujYEJTWIgQGqgVVWUZXMnc8iWg=="], - - "edgedriver": ["edgedriver@6.3.0", "", { "dependencies": { "@wdio/logger": "^9.18.0", "@zip.js/zip.js": "^2.8.11", "decamelize": "^6.0.1", "edge-paths": "^3.0.5", "fast-xml-parser": "^5.3.3", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", "which": "^6.0.0" }, "bin": { "edgedriver": "bin/edgedriver.js" } }, "sha512-ggEQL+oEyIcM4nP2QC3AtCQ04o4kDNefRM3hja0odvlPSnsaxiruMxEZ93v3gDCKWYW6BXUr51PPradb+3nffw=="], - "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], @@ -3954,8 +3788,6 @@ "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="], - "encoding-sniffer": ["encoding-sniffer@0.2.1", "", { "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" } }, "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw=="], - "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], "engine.io": ["engine.io@6.6.6", "", { "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "@types/ws": "^8.5.12", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.4.1", "engine.io-parser": "~5.2.1", "ws": "~8.18.3" } }, "sha512-U2SN0w3OpjFRVlrc17E6TMDmH58Xl9rai1MblNjAdwWp07Kk+llmzX0hjDpQdrDGzwmvOtgM5yI+meYX6iZ2xA=="], @@ -4134,8 +3966,6 @@ "fast-content-type-parse": ["fast-content-type-parse@3.0.0", "", {}, "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg=="], - "fast-copy": ["fast-copy@4.0.3", "", {}, "sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw=="], - "fast-csv": ["fast-csv@4.3.6", "", { "dependencies": { "@fast-csv/format": "4.3.5", "@fast-csv/parse": "4.3.6" } }, "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], @@ -4150,16 +3980,8 @@ "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - "fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="], - "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], - "fast-xml-builder": ["fast-xml-builder@1.1.5", "", { "dependencies": { "path-expression-matcher": "^1.1.3" } }, "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA=="], - - "fast-xml-parser": ["fast-xml-parser@5.7.1", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.5", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-8Cc3f8GUGUULg34pBch/KGyPLglS+OFs05deyOlY7fL2MTagYPKrVQNmR1fLF/yJ9PH5ZSTd3YDF6pnmeZU+zA=="], - - "fastembed": ["fastembed@2.1.0", "", { "dependencies": { "@anush008/tokenizers": "^0.0.0", "@huggingface/hub": "^2.7.1", "onnxruntime-node": "1.21.0", "progress": "^2.0.3", "tar": "^6.2.0" } }, "sha512-oQkpcRHBppJ3+a3w9dU0uytSY0N1cnEa/iVMc8AXEd+tvT529GekOEFhNviJy89R3lvQXF6cdIMTXHj1Gi00xQ=="], - "fastest-levenshtein": ["fastest-levenshtein@1.0.16", "", {}, "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg=="], "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], @@ -4176,8 +3998,6 @@ "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], - "fetch-cookie": ["fetch-cookie@3.2.0", "", { "dependencies": { "set-cookie-parser": "^2.4.8", "tough-cookie": "^6.0.0" } }, "sha512-n61pQIxP25C6DRhcJxn7BDzgHP/+S56Urowb5WFxtcRMpU6drqXD90xjyAsVQYsNSNNVbaCcYY1DuHsdkZLuiA=="], - "fetch-nodeshim": ["fetch-nodeshim@0.4.10", "", {}, "sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w=="], "fflate": ["fflate@0.4.8", "", {}, "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="], @@ -4206,12 +4026,8 @@ "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], - "form-data-encoder": ["form-data-encoder@1.7.2", "", {}, "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="], - "format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="], - "formdata-node": ["formdata-node@4.4.1", "", { "dependencies": { "node-domexception": "1.0.0", "web-streams-polyfill": "4.0.0-beta.3" } }, "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ=="], - "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], @@ -4230,7 +4046,7 @@ "fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], - "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], + "fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="], "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], @@ -4248,12 +4064,6 @@ "fuse.js": ["fuse.js@7.3.0", "", {}, "sha512-plz8RVjfcDedTGfVngWH1jmJvBvAwi1v2jecfDerbEnMcmOYUEEwKFTHbNoCiYyzaK2Ws8lABkTCcRSqCY1q4w=="], - "gaxios": ["gaxios@7.1.4", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA=="], - - "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=="], - - "geckodriver": ["geckodriver@6.1.0", "", { "dependencies": { "@wdio/logger": "^9.18.0", "@zip.js/zip.js": "^2.8.11", "decamelize": "^6.0.1", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", "modern-tar": "^0.7.2" }, "bin": { "geckodriver": "bin/geckodriver.js" } }, "sha512-ZRXLa4ZaYTTgUO4Eefw+RsQCleugU2QLb1ME7qTYxxuRj51yAhfnXaItXNs5/vUzfIaDHuZ+YnSF005hfp07nQ=="], - "geist": ["geist@1.7.0", "", { "peerDependencies": { "next": ">=13.2.0" } }, "sha512-ZaoiZwkSf0DwwB1ncdLKp+ggAldqxl5L1+SXaNIBGkPAqcu+xjVJLxlf3/S8vLt9UHx1xu5fz3lbzKCj5iOVdQ=="], "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], @@ -4268,8 +4078,6 @@ "get-package-type": ["get-package-type@0.1.0", "", {}, "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q=="], - "get-port": ["get-port@7.2.0", "", {}, "sha512-afP4W205ONCuMoPBqcR6PSXnzX35KTcJygfJfcp+QY+uwm3p20p1YczWXhlICIzGMCxYBQcySEcOgsJcrkyobg=="], - "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], @@ -4300,18 +4108,12 @@ "glsl-noise": ["glsl-noise@0.0.0", "", {}, "sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w=="], - "google-auth-library": ["google-auth-library@10.6.2", "", { "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-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw=="], - - "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], - "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], "got": ["got@11.8.6", "", { "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", "p-cancelable": "^2.0.0", "responselike": "^2.0.0" } }, "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g=="], "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - "grapheme-splitter": ["grapheme-splitter@1.0.4", "", {}, "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ=="], - "graphql": ["graphql@16.13.2", "", {}, "sha512-5bJ+nf/UCpAjHM8i06fl7eLyVC9iuNAjm9qzkiu2ZGhM0VscSvS6WDPfAwkdkBuoXGM9FJSbKl6wylMwP9Ktig=="], "graphql-config": ["graphql-config@5.0.3", "", { "dependencies": { "@graphql-tools/graphql-file-loader": "^8.0.0", "@graphql-tools/json-file-loader": "^8.0.0", "@graphql-tools/load": "^8.0.0", "@graphql-tools/merge": "^9.0.0", "@graphql-tools/url-loader": "^8.0.0", "@graphql-tools/utils": "^10.0.0", "cosmiconfig": "^8.1.0", "jiti": "^1.18.2", "minimatch": "^4.2.3", "string-env-interpolation": "^1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "cosmiconfig-toml-loader": "^1.0.0", "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" }, "optionalPeers": ["cosmiconfig-toml-loader"] }, "sha512-BNGZaoxIBkv9yy6Y7omvsaBUHOzfFcII3UN++tpH8MGOKFPFkCPZuwx09ggANMt8FgyWP1Od8SWPmrUEZca4NQ=="], @@ -4372,8 +4174,6 @@ "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], - "help-me": ["help-me@5.0.0", "", {}, "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="], - "hermes-compiler": ["hermes-compiler@0.14.0", "", {}, "sha512-clxa193o+GYYwykWVFfpHduCATz8fR5jvU7ngXpfKHj+E9hr9vjLNtdLSEe8MUbObvVexV3wcyxQ00xTPIrB1Q=="], "hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="], @@ -4402,8 +4202,6 @@ "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], - "htmlfy": ["htmlfy@0.8.1", "", {}, "sha512-xWROBw9+MEGwxpotll0h672KCaLrKKiCYzsyN8ZgL9cQbVumFnyvsk2JqiB9ELAV1GLj1GG/jxZUjV9OZZi/yQ=="], - "htmlparser2": ["htmlparser2@8.0.2", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "entities": "^4.4.0" } }, "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA=="], "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], @@ -4420,8 +4218,6 @@ "human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="], - "humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="], - "iconv-corefoundation": ["iconv-corefoundation@1.1.7", "", { "dependencies": { "cli-truncate": "^2.1.0", "node-addon-api": "^1.6.3" }, "os": "darwin" }, "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ=="], "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], @@ -4444,8 +4240,6 @@ "import-in-the-middle": ["import-in-the-middle@2.0.1", "", { "dependencies": { "acorn": "^8.14.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } }, "sha512-bruMpJ7xz+9jwGzrwEhWgvRrlKRYCRDBrfU+ur3FcasYXLJDxTruJ//8g2Noj+QFyRBeqbpj8Bhn4Fbw6HjvhA=="], - "import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="], - "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], "indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="], @@ -4572,8 +4366,6 @@ "jose": ["jose@6.2.2", "", {}, "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ=="], - "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="], - "js-base64": ["js-base64@3.7.8", "", {}, "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow=="], "js-string-escape": ["js-string-escape@1.0.1", "", {}, "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg=="], @@ -4588,8 +4380,6 @@ "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], - "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], - "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], @@ -4616,10 +4406,6 @@ "jszip": ["jszip@3.10.1", "", { "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", "readable-stream": "~2.3.6", "setimmediate": "^1.0.5" } }, "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g=="], - "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=="], - - "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], - "katex": ["katex@0.16.45", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA=="], "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], @@ -4638,8 +4424,6 @@ "langium": ["langium@4.2.2", "", { "dependencies": { "@chevrotain/regexp-to-ast": "~12.0.0", "chevrotain": "~12.0.0", "chevrotain-allstar": "~0.4.1", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", "vscode-uri": "~3.1.0" } }, "sha512-JUshTRAfHI4/MF9dH2WupvjSXyn8JBuUEWazB8ZVJUtXutT0doDlAv1XKbZ1Pb5sMexa8FF4CFBc0iiul7gbUQ=="], - "langsmith": ["langsmith@0.3.87", "", { "dependencies": { "@types/uuid": "^10.0.0", "chalk": "^4.1.2", "console-table-printer": "^2.12.1", "p-queue": "^6.6.2", "semver": "^7.6.3", "uuid": "^10.0.0" }, "peerDependencies": { "@opentelemetry/api": "*", "@opentelemetry/exporter-trace-otlp-proto": "*", "@opentelemetry/sdk-trace-base": "*", "openai": "*" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/exporter-trace-otlp-proto", "@opentelemetry/sdk-trace-base", "openai"] }, "sha512-XXR1+9INH8YX96FKWc5tie0QixWz6tOqAsAKfcJyPkE0xPep+NDz0IQLR32q4bn10QK3LqD2HN6T3n6z1YLW7Q=="], - "launch-ide": ["launch-ide@1.4.3", "", { "dependencies": { "chalk": "^4.1.1", "dotenv": "^16.1.4" } }, "sha512-v2xMAarJOFy51kuesYEIIx5r4WHvsV+VLMU49K24bdiRZGUpo1ZulO1DRrLozM5BMbXUfRfrUTM2PbBfYCeA4Q=="], "layout-base": ["layout-base@1.0.2", "", {}, "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="], @@ -4658,7 +4442,7 @@ "lie": ["lie@3.3.0", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ=="], - "lighthouse-logger": ["lighthouse-logger@2.0.2", "", { "dependencies": { "debug": "^4.4.1", "marky": "^1.2.2" } }, "sha512-vWl2+u5jgOQuZR55Z1WM0XDdrJT6mzMP8zHUct7xTlWhuQs+eV0g+QL0RQdFjT54zVmbhLCP8vIVpy1wGn/gCg=="], + "lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="], "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="], @@ -4698,8 +4482,6 @@ "loader-runner": ["loader-runner@4.3.1", "", {}, "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q=="], - "locate-app": ["locate-app@2.5.0", "", { "dependencies": { "@promptbook/utils": "0.69.5", "type-fest": "4.26.0", "userhome": "1.0.1" } }, "sha512-xIqbzPMBYArJRmPGUZD9CzV9wOqmVtQnaAn3wrj3s6WYW0bQvPI7x+sPYUGmDTYMHefVK//zc6HEYZ1qnxIK+Q=="], - "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], @@ -4710,8 +4492,6 @@ "lodash.chunk": ["lodash.chunk@4.2.0", "", {}, "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="], - "lodash.clonedeep": ["lodash.clonedeep@4.5.0", "", {}, "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="], - "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="], @@ -4746,16 +4526,8 @@ "lodash.uniq": ["lodash.uniq@4.5.0", "", {}, "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="], - "lodash.zip": ["lodash.zip@4.2.0", "", {}, "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg=="], - "log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="], - "loglevel": ["loglevel@1.9.2", "", {}, "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg=="], - - "loglevel-plugin-prefix": ["loglevel-plugin-prefix@0.8.4", "", {}, "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g=="], - - "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], - "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], @@ -4798,7 +4570,7 @@ "marky": ["marky@1.3.0", "", {}, "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ=="], - "mastracode": ["mastracode@0.14.0", "", { "dependencies": { "@ai-sdk/anthropic": "^3.0.58", "@ai-sdk/openai": "^3.0.41", "@ast-grep/napi": "^0.42.0", "@mariozechner/pi-tui": "^0.60.0", "@mastra/agent-browser": "0.2.0", "@mastra/core": "1.25.0", "@mastra/fastembed": "1.0.1", "@mastra/libsql": "1.8.1", "@mastra/mcp": "1.5.0", "@mastra/memory": "1.15.1", "@mastra/pg": "1.9.1", "@mastra/stagehand": "0.2.0", "@tavily/core": "^0.7.2", "ai": "^6.0.116", "chalk": "^5.5.0", "cli-highlight": "^2.1.11", "execa": "^9.6.1", "fastest-levenshtein": "^1.0.16", "js-tiktoken": "^1.0.21", "partial-json": "^0.1.7", "strip-ansi": "^7.2.0", "tree-kill": "^1.2.2", "vscode-jsonrpc": "^8.2.1", "vscode-languageserver-protocol": "^3.17.5", "yaml": "^2.7.1", "zod": "^4.3.6" }, "bin": { "mastracode": "dist/cli.js" } }, "sha512-QVJGm7NPjMormBm76QfpLD175RtCj/ZFiXtQrfvqSv8LxVxkQ+I1dTVnlbV4xp8ah1Qgc0xeE9OOOJ08ppRtiw=="], + "mastracode": ["mastracode@0.9.2", "", { "dependencies": { "@ai-sdk/anthropic": "^3.0.58", "@ai-sdk/openai": "^3.0.41", "@ast-grep/napi": "^0.42.0", "@mariozechner/pi-tui": "^0.60.0", "@mastra/core": "1.16.0", "@mastra/libsql": "1.7.2", "@mastra/mcp": "1.3.1", "@mastra/memory": "1.10.0", "@mastra/pg": "1.8.3", "@tavily/core": "^0.7.2", "ai": "^6.0.116", "chalk": "^5.5.0", "cli-highlight": "^2.1.11", "execa": "^9.6.1", "fastest-levenshtein": "^1.0.16", "js-tiktoken": "^1.0.21", "js-yaml": "^3.14.2", "partial-json": "^0.1.7", "strip-ansi": "^7.2.0", "tree-kill": "^1.2.2", "vscode-jsonrpc": "^8.2.1", "vscode-languageserver-protocol": "^3.17.5", "zod": "^4.3.6" }, "bin": { "mastracode": "dist/cli.js" } }, "sha512-YGnAHIp4ucBoNsGacRRSLvqoZ6mO8RIki//XDxXIdJ1dcedhfITmsBwIRzSiJFhFu63M4FppLfkVCi1/bUT5AQ=="], "matcher": ["matcher@5.0.0", "", { "dependencies": { "escape-string-regexp": "^5.0.0" } }, "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw=="], @@ -5008,8 +4780,6 @@ "mlly": ["mlly@1.8.2", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="], - "modern-tar": ["modern-tar@0.7.6", "", {}, "sha512-sweCIVXzx1aIGTCdzcMlSZt1h8k5Tmk08VNAuRk3IU28XamGiOH5ypi11g6De2CH7PhYqSSnGy2A/EFhbWnVKg=="], - "module-details-from-path": ["module-details-from-path@1.0.4", "", {}, "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w=="], "motion": ["motion@12.38.0", "", { "dependencies": { "framer-motion": "^12.38.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w=="], @@ -5022,8 +4792,6 @@ "multitars": ["multitars@0.2.5", "", {}, "sha512-T/i4uZOzd4j2VnS28eAOJS0MgeAbcsFIijRPeLRhVv54hP9OqsC/FjYK0JmMTWxGhF2fv34oH1mtR6XLBKkNlw=="], - "mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="], - "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], "nanoid": ["nanoid@5.1.9", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-ZUvP7KeBLe3OZ1ypw6dI/TzYJuvHP77IM4Ry73waSQTLn8/g8rpdjfyVAh7t1/+FjBtG4lCP42MEbDxOsRpBMw=="], @@ -5074,8 +4842,6 @@ "node-releases": ["node-releases@2.0.37", "", {}, "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg=="], - "node-simctl": ["node-simctl@7.7.5", "", { "dependencies": { "@appium/logger": "^1.3.0", "asyncbox": "^3.0.0", "bluebird": "^3.5.1", "lodash": "^4.2.1", "rimraf": "^5.0.0", "semver": "^7.0.0", "source-map-support": "^0.x", "teen_process": "^2.2.0", "uuid": "^11.0.1", "which": "^5.0.0" } }, "sha512-lWflzDW9xLuOOvR6mTJ9efbDtO/iSCH6rEGjxFxTV0vGgz5XjoZlW2BkNCCZib0B6Y23tCOiYhYJaMQYB8FKIQ=="], - "nofilter": ["nofilter@3.1.0", "", {}, "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g=="], "nopt": ["nopt@8.1.0", "", { "dependencies": { "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A=="], @@ -5104,10 +4870,6 @@ "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], - "ollama-ai-provider-v2": ["ollama-ai-provider-v2@1.5.5", "", { "dependencies": { "@ai-sdk/provider": "^2.0.0", "@ai-sdk/provider-utils": "^3.0.17" }, "peerDependencies": { "zod": "^4.0.16" } }, "sha512-1YwTFdPjhPNHny/DrOHO+s8oVGGIE5Jib61/KnnjPRNWQhVVimrJJdaAX3e6nNRRDXrY5zbb9cfm2+yVvgsrqw=="], - - "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], - "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], "on-headers": ["on-headers@1.1.0", "", {}, "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A=="], @@ -5120,14 +4882,8 @@ "oniguruma-to-es": ["oniguruma-to-es@4.3.5", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.1.0", "regex-recursion": "^6.0.2" } }, "sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ=="], - "onnxruntime-common": ["onnxruntime-common@1.21.0", "", {}, "sha512-Q632iLLrtCAVOTO65dh2+mNbQir/QNTVBG3h/QdZBpns7mZ0RYbLRBgGABPbpU9351AgYy7SJf1WaeVwMrBFPQ=="], - - "onnxruntime-node": ["onnxruntime-node@1.21.0", "", { "dependencies": { "global-agent": "^3.0.0", "onnxruntime-common": "1.21.0", "tar": "^7.0.1" }, "os": [ "linux", "win32", "darwin", ] }, "sha512-NeaCX6WW2L8cRCSqy3bInlo5ojjQqu2fD3D+9W5qb5irwxhEyWKXeH2vZ8W9r6VxaMPUan+4/7NDwZMtouZxEw=="], - "open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="], - "openai": ["openai@4.104.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" }, "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA=="], - "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], "opentype.js": ["opentype.js@0.8.0", "", { "dependencies": { "tiny-inflate": "^1.0.2" }, "bin": { "ot": "./bin/ot" } }, "sha512-FQHR4oGP+a0m/f6yHoRpBOIbn/5ZWxKd4D/djHVJu8+KpBTYrJda0b7mLcgDEMWXE9xBCJm+qb0yv6FcvPjukg=="], @@ -5186,22 +4942,16 @@ "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@6.0.1", "", { "dependencies": { "parse5": "^6.0.1" } }, "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA=="], - "parse5-parser-stream": ["parse5-parser-stream@7.1.2", "", { "dependencies": { "parse5": "^7.0.0" } }, "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow=="], - "parseley": ["parseley@0.12.1", "", { "dependencies": { "leac": "^0.6.0", "peberminta": "^0.9.0" } }, "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw=="], "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], "partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="], - "patchright-core": ["patchright-core@1.59.4", "", { "bin": { "patchright-core": "cli.js" } }, "sha512-7/vyX0XK0cpGKlcnUD+Rhjv5o9rrmZQl4v/NI+EUBed+VaU5EORpkOF0Gdi+fP698fLhY0tXwacKBUqKE38jQA=="], - "path-data-parser": ["path-data-parser@0.1.0", "", {}, "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w=="], "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - "path-expression-matcher": ["path-expression-matcher@1.5.0", "", {}, "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ=="], - "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], @@ -5248,14 +4998,6 @@ "pidusage": ["pidusage@4.0.1", "", { "dependencies": { "safe-buffer": "^5.2.1" } }, "sha512-yCH2dtLHfEBnzlHUJymR/Z1nN2ePG3m392Mv8TFlTP1B0xkpMQNHAnfkY0n2tAi6ceKO6YWhxYfZ96V4vVkh/g=="], - "pino": ["pino@9.14.0", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w=="], - - "pino-abstract-transport": ["pino-abstract-transport@2.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw=="], - - "pino-pretty": ["pino-pretty@13.1.3", "", { "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", "fast-copy": "^4.0.0", "fast-safe-stringify": "^2.1.1", "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^3.0.0", "pump": "^3.0.0", "secure-json-parse": "^4.0.0", "sonic-boom": "^4.0.1", "strip-json-comments": "^5.0.2" }, "bin": { "pino-pretty": "bin.js" } }, "sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg=="], - - "pino-std-serializers": ["pino-std-serializers@7.1.0", "", {}, "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw=="], - "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="], @@ -5264,10 +5006,6 @@ "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], - "playwright": ["playwright@1.59.1", "", { "dependencies": { "playwright-core": "1.59.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw=="], - - "playwright-core": ["playwright-core@1.59.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg=="], - "plist": ["plist@3.1.0", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ=="], "plur": ["plur@5.1.0", "", { "dependencies": { "irregular-plurals": "^3.3.0" } }, "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg=="], @@ -5318,12 +5056,8 @@ "proc-log": ["proc-log@4.2.0", "", {}, "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA=="], - "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], - "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], - "process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="], - "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="], "promise": ["promise@8.3.0", "", { "dependencies": { "asap": "~2.0.6" } }, "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg=="], @@ -5378,8 +5112,6 @@ "prosemirror-view": ["prosemirror-view@1.41.8", "", { "dependencies": { "prosemirror-model": "^1.20.0", "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0" } }, "sha512-TnKDdohEatgyZNGCDWIdccOHXhYloJwbwU+phw/a23KBvJIR9lWQWW7WHHK3vBdOLDNuF7TaX98GObUZOWkOnA=="], - "protobufjs": ["protobufjs@7.5.5", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg=="], - "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], "proxy-agent": ["proxy-agent@6.5.0", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "http-proxy-agent": "^7.0.1", "https-proxy-agent": "^7.0.6", "lru-cache": "^7.14.1", "pac-proxy-agent": "^7.1.0", "proxy-from-env": "^1.1.0", "socks-proxy-agent": "^8.0.5" } }, "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A=="], @@ -5400,16 +5132,12 @@ "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], - "query-selector-shadow-dom": ["query-selector-shadow-dom@1.0.1", "", {}, "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw=="], - "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=="], "queue": ["queue@6.0.2", "", { "dependencies": { "inherits": "~2.0.3" } }, "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA=="], "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="], - "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="], "radash": ["radash@12.1.1", "", {}, "sha512-h36JMxKRqrAxVD8201FrCpyeNuUY9Y5zZwujr20fFO77tpUtGa6EZzfKw/3WaiBX95fq7+MpsuMLNdSnORAwSA=="], @@ -5508,8 +5236,6 @@ "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], - "recharts": ["recharts@2.15.4", "", { "dependencies": { "clsx": "^2.0.0", "eventemitter3": "^4.0.1", "lodash": "^4.17.21", "react-is": "^18.3.1", "react-smooth": "^4.0.4", "recharts-scale": "^0.4.4", "tiny-invariant": "^1.3.1", "victory-vendor": "^36.6.8" }, "peerDependencies": { "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw=="], "recharts-scale": ["recharts-scale@0.4.5", "", { "dependencies": { "decimal.js-light": "^2.4.1" } }, "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w=="], @@ -5618,18 +5344,12 @@ "responselike": ["responselike@2.0.1", "", { "dependencies": { "lowercase-keys": "^2.0.0" } }, "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw=="], - "resq": ["resq@1.11.0", "", { "dependencies": { "fast-deep-equal": "^2.0.1" } }, "sha512-G10EBz+zAAy3zUd/CDoBbXRL6ia9kOo3xRHrMDsHljI0GDkhYlyjwoCx5+3eCC4swi1uCoZQhskuJkj7Gp57Bw=="], - "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], - "ret": ["ret@0.5.0", "", {}, "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw=="], - "retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - "rgb2hex": ["rgb2hex@0.2.5", "", {}, "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw=="], - "rimraf": ["rimraf@6.1.3", "", { "dependencies": { "glob": "^13.0.3", "package-json-from-dist": "^1.0.1" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA=="], "roarr": ["roarr@2.15.4", "", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="], @@ -5656,14 +5376,8 @@ "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], - "safaridriver": ["safaridriver@1.0.1", "", {}, "sha512-jkg4434cYgtrIF2AeY/X0Wmd2W73cK5qIEFE3hDrrQenJH/2SDJIXGvPAigfvQTcE9+H31zkiNHbUqcihEiMRA=="], - "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], - "safe-regex2": ["safe-regex2@5.1.0", "", { "dependencies": { "ret": "~0.5.0" }, "bin": { "safe-regex2": "bin/safe-regex2.js" } }, "sha512-pNHAuBW7TrcleFHsxBr5QMi/Iyp0ENjUKz7GCcX1UO7cMh+NmVK6HxQckNL1tJp1XAJVjG6B8OKIPqodqj9rtw=="], - - "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], - "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], "sanitize-filename": ["sanitize-filename@1.6.4", "", { "dependencies": { "truncate-utf8-bytes": "^1.0.0" } }, "sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg=="], @@ -5702,8 +5416,6 @@ "server-only": ["server-only@0.0.1", "", {}, "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="], - "set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="], - "set-cookie-parser": ["set-cookie-parser@3.1.0", "", {}, "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw=="], "setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="], @@ -5766,8 +5478,6 @@ "simple-update-notifier": ["simple-update-notifier@2.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w=="], - "simple-wcswidth": ["simple-wcswidth@1.1.2", "", {}, "sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw=="], - "simplex-noise": ["simplex-noise@4.0.3", "", {}, "sha512-qSE2I4AngLQG7BXqoZj51jokT4WUXe8mOBrvfOXpci8+6Yu44+/dD5zqDpOx3Ux792eamTd2lLcI8jqFntk/lg=="], "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], @@ -5790,8 +5500,6 @@ "socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="], - "sonic-boom": ["sonic-boom@4.2.1", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q=="], - "sonner": ["sonner@2.0.7", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w=="], "sorted-btree": ["sorted-btree@1.8.1", "", {}, "sha512-395+XIP+wqNn3USkFSrNz7G3Ss/MXlZEqesxvzCRFwL14h6e8LukDHdLBePn5pwbm5OQ9vGu8mDyz2lLDIqamQ=="], @@ -5806,8 +5514,6 @@ "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], - "spacetrim": ["spacetrim@0.11.59", "", {}, "sha512-lLYsktklSRKprreOm7NXReW8YiX2VBjbgmXYEziOoGf/qsJqAEACaDvoTtUOycwjpaSh+bT8eu0KrJn7UNxiCg=="], - "split-on-first": ["split-on-first@1.1.0", "", {}, "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="], "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], @@ -5872,8 +5578,6 @@ "stripe-gradient": ["stripe-gradient@1.0.1", "", {}, "sha512-ttxSoPcJDXoYBPF7yG2TPC9ZZC1bc/ITxP8g0Yx5jo07dFT/wMcGn6CbjbHOtC0NBu8zZgJwJulCpK21WyRJEg=="], - "strnum": ["strnum@2.2.3", "", {}, "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg=="], - "structured-headers": ["structured-headers@0.4.1", "", {}, "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg=="], "stubborn-fs": ["stubborn-fs@2.0.0", "", { "dependencies": { "stubborn-utils": "^1.0.1" } }, "sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA=="], @@ -5930,8 +5634,6 @@ "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], - "teen_process": ["teen_process@2.3.3", "", { "dependencies": { "bluebird": "^3.7.2", "lodash": "^4.17.21", "shell-quote": "^1.8.1", "source-map-support": "^0.x" } }, "sha512-NIdeetf/6gyEqLjnzvfgQe7PfipSceq2xDQM2Py2BkBnIIeWh3HRD3vNhulyO5WppfCv9z4mtsEHyq8kdiULTA=="], - "teex": ["teex@1.0.1", "", { "dependencies": { "streamx": "^2.12.5" } }, "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg=="], "temp": ["temp@0.9.4", "", { "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" } }, "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA=="], @@ -5954,8 +5656,6 @@ "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], - "thread-stream": ["thread-stream@3.1.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A=="], - "three": ["three@0.181.2", "", {}, "sha512-k/CjiZ80bYss6Qs7/ex1TBlPD11whT9oKfT8oTGiHa34W4JRd1NiH/Tr1DbHWQ2/vMUypxksLnF2CfmlmM5XFQ=="], "three-mesh-bvh": ["three-mesh-bvh@0.8.3", "", { "peerDependencies": { "three": ">= 0.159.0" } }, "sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg=="], @@ -5966,8 +5666,6 @@ "throttleit": ["throttleit@2.1.0", "", {}, "sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw=="], - "through": ["through@2.3.8", "", {}, "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="], - "time-zone": ["time-zone@1.0.0", "", {}, "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA=="], "timeout-signal": ["timeout-signal@2.0.0", "", {}, "sha512-YBGpG4bWsHoPvofT6y/5iqulfXIiIErl5B0LdtHT1mGXDFTAhhRrbUpTvBgYbovr+3cKblya2WAOcpoy90XguA=="], @@ -5988,10 +5686,6 @@ "tiptap-markdown": ["tiptap-markdown@0.9.0", "", { "dependencies": { "@types/markdown-it": "^13.0.7", "markdown-it": "^14.1.0", "markdown-it-task-lists": "^2.1.1", "prosemirror-markdown": "^1.11.1" }, "peerDependencies": { "@tiptap/core": "^3.0.1" } }, "sha512-dKLQ9iiuGNgrlGVjrNauF/UBzWu4LYOx5pkD0jNkmQt/GOwfCJsBuzZTsf1jZ204ANHOm572mZ9PYvGh1S7tpQ=="], - "tldts": ["tldts@7.0.28", "", { "dependencies": { "tldts-core": "^7.0.28" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-+Zg3vWhRUv8B1maGSTFdev9mjoo8Etn2Ayfs4cnjlD3CsGkxXX4QyW3j2WJ0wdjYcYmy7Lx2RDsZMhgCWafKIw=="], - - "tldts-core": ["tldts-core@7.0.28", "", {}, "sha512-7W5Efjhsc3chVdFhqtaU0KtK32J37Zcr9RKtID54nG+tIpcY79CQK/veYPODxtD/LJ4Lue66jvrQzIX2Z2/pUQ=="], - "tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="], "tmp-promise": ["tmp-promise@3.0.3", "", { "dependencies": { "tmp": "^0.2.0" } }, "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ=="], @@ -6010,8 +5704,6 @@ "toqr": ["toqr@0.1.1", "", {}, "sha512-FWAPzCIHZHnrE/5/w9MPk0kK25hSQSH2IKhYh9PyjS3SG/+IEMvlwIHbhz+oF7xl54I+ueZlVnMjyzdSwLmAwA=="], - "tough-cookie": ["tough-cookie@6.0.1", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw=="], - "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], "traverse": ["traverse@0.3.9", "", {}, "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ=="], @@ -6070,8 +5762,6 @@ "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="], - "typed-emitter": ["typed-emitter@2.1.0", "", { "optionalDependencies": { "rxjs": "*" } }, "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA=="], - "typed-query-selector": ["typed-query-selector@2.12.1", "", {}, "sha512-uzR+FzI8qrUEIu96oaeBJmd9E7CFEiQ3goA5qCVgc4s5llSubcfGHq9yUstZx/k4s9dXHVKsE35YWoFyvEqEHA=="], "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], @@ -6086,8 +5776,6 @@ "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], - "unbzip2-stream": ["unbzip2-stream@1.4.3", "", { "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" } }, "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg=="], - "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], "undici": ["undici@6.25.0", "", {}, "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg=="], @@ -6164,8 +5852,6 @@ "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=="], - "userhome": ["userhome@1.0.1", "", {}, "sha512-5cnLm4gseXjAclKowC4IjByaGsjtAoV6PrOQOljplNB54ReUYJP8HdAFq2muHinSDAh09PPX/uXDPfdxRHvuSA=="], - "utf-8-validate": ["utf-8-validate@6.0.6", "", { "dependencies": { "node-gyp-build": "^4.3.0" } }, "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA=="], "utf8-byte-length": ["utf8-byte-length@1.0.5", "", {}, "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA=="], @@ -6230,8 +5916,6 @@ "w3c-keyname": ["w3c-keyname@2.2.8", "", {}, "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="], - "wait-port": ["wait-port@1.1.0", "", { "dependencies": { "chalk": "^4.1.2", "commander": "^9.3.0", "debug": "^4.3.4" }, "bin": { "wait-port": "bin/wait-port.js" } }, "sha512-3e04qkoN3LxTMLakdqeWth8nih8usyg+sf1Bgdf9wwUkp05iuK1eSY/QpLvscT/+F/gA89+LpUmmgBtesbqI2Q=="], - "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=="], @@ -6246,12 +5930,8 @@ "web-vitals": ["web-vitals@4.2.4", "", {}, "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw=="], - "webdriver": ["webdriver@9.27.0", "", { "dependencies": { "@types/node": "^20.1.0", "@types/ws": "^8.5.3", "@wdio/config": "9.27.0", "@wdio/logger": "9.18.0", "@wdio/protocols": "9.27.0", "@wdio/types": "9.27.0", "@wdio/utils": "9.27.0", "deepmerge-ts": "^7.0.3", "https-proxy-agent": "^7.0.6", "undici": "^6.21.3", "ws": "^8.8.0" } }, "sha512-w07ThZND48SIr0b4S7eFougYUyclmoUwdmju8yXvEJiXYjDjeYUpl8wZrYPEYRBylxpSx+sBHfEUBrPQkcTTRQ=="], - "webdriver-bidi-protocol": ["webdriver-bidi-protocol@0.4.1", "", {}, "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw=="], - "webdriverio": ["webdriverio@9.27.0", "", { "dependencies": { "@types/node": "^20.11.30", "@types/sinonjs__fake-timers": "^8.1.5", "@wdio/config": "9.27.0", "@wdio/logger": "9.18.0", "@wdio/protocols": "9.27.0", "@wdio/repl": "9.16.2", "@wdio/types": "9.27.0", "@wdio/utils": "9.27.0", "archiver": "^7.0.1", "aria-query": "^5.3.0", "cheerio": "^1.0.0-rc.12", "css-shorthand-properties": "^1.1.1", "css-value": "^0.0.1", "grapheme-splitter": "^1.0.4", "htmlfy": "^0.8.1", "is-plain-obj": "^4.1.0", "jszip": "^3.10.1", "lodash.clonedeep": "^4.5.0", "lodash.zip": "^4.2.0", "query-selector-shadow-dom": "^1.0.1", "resq": "^1.11.0", "rgb2hex": "0.2.5", "serialize-error": "^12.0.0", "urlpattern-polyfill": "^10.0.0", "webdriver": "9.27.0" }, "peerDependencies": { "puppeteer-core": ">=22.x || <=24.x" }, "optionalPeers": ["puppeteer-core"] }, "sha512-Y4FbMf4bKBXpPB0lYpglzQ2GfDDe6uojmMZl85uPyrDx18NW7mqN84ZawGoIg/FRvcLaVhcOzc98WOPo725Rag=="], - "webgl-constants": ["webgl-constants@1.1.1", "", {}, "sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg=="], "webgl-sdf-generator": ["webgl-sdf-generator@1.1.1", "", {}, "sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA=="], @@ -6266,8 +5946,6 @@ "well-known-symbols": ["well-known-symbols@2.0.0", "", {}, "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q=="], - "whatwg-encoding": ["whatwg-encoding@3.1.1", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="], - "whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="], "whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="], @@ -6354,59 +6032,11 @@ "@a2a-js/sdk/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], - "@ai-sdk/amazon-bedrock/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.77", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8n7ApEzFOxqVvT3HyqLrEQlgUx/2nUmPFLTGY3fNKwUA8KVNU3Ovd2C66Qh1Y93Iq5NkHsOWuLiTyAZpRKQhgw=="], - - "@ai-sdk/amazon-bedrock/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@ai-sdk/azure/@ai-sdk/openai": ["@ai-sdk/openai@2.0.103", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-FDwY060LV/D5th+LeaxpSKcot5eXjzNzHguDf0NU1K+v7rxYZFWbldQPZarNo/IpD/WJE9RojgrFAcZ1e8KyvQ=="], - - "@ai-sdk/azure/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/azure/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@ai-sdk/cerebras/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/cerebras/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@ai-sdk/deepseek/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/deepseek/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@ai-sdk/google/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/google/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.77", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8n7ApEzFOxqVvT3HyqLrEQlgUx/2nUmPFLTGY3fNKwUA8KVNU3Ovd2C66Qh1Y93Iq5NkHsOWuLiTyAZpRKQhgw=="], - - "@ai-sdk/google-vertex/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@ai-sdk/groq/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/groq/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@ai-sdk/mistral/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/mistral/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - "@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.15", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8XiKWbemmCbvNN0CLR9u3PQiet4gtEVIrX4zzLxnCj06AwsEDJwJVBbKrEI4t6qE8XRSIvU2irka0dcpziKW6w=="], - "@ai-sdk/openai-compatible/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@ai-sdk/perplexity/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/perplexity/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - "@ai-sdk/provider-utils-v5/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - "@ai-sdk/togetherai/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/togetherai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], + "@ai-sdk/provider-utils-v6/@ai-sdk/provider": ["@ai-sdk/provider@3.0.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-m9ka3ptkPQbaHHZHqDXDF9C9B5/Mav0KTdky1k2HZ3/nrW2t1AgObxIVPyGDWQNS9FXT/FS6PIoSjpcP/No8rQ=="], "@ai-sdk/ui-utils-v5/@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="], @@ -6414,16 +6044,6 @@ "@ai-sdk/ui-utils-v5/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "@ai-sdk/xai/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@ai-sdk/xai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@appium/logger/lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], - - "@appium/logger/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], - "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], @@ -6438,24 +6058,6 @@ "@babel/polyfill/core-js": ["core-js@2.6.12", "", {}, "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="], - "@browserbasehq/sdk/@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="], - - "@browserbasehq/stagehand/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.77", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8n7ApEzFOxqVvT3HyqLrEQlgUx/2nUmPFLTGY3fNKwUA8KVNU3Ovd2C66Qh1Y93Iq5NkHsOWuLiTyAZpRKQhgw=="], - - "@browserbasehq/stagehand/@ai-sdk/openai": ["@ai-sdk/openai@2.0.103", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-FDwY060LV/D5th+LeaxpSKcot5eXjzNzHguDf0NU1K+v7rxYZFWbldQPZarNo/IpD/WJE9RojgrFAcZ1e8KyvQ=="], - - "@browserbasehq/stagehand/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "@browserbasehq/stagehand/@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.39.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-eMyDIPRZbt1CCLErRCi3exlAvNkBtRe+kW5vvJyef93PmNr/clstYgHhtvmkxN82nlKgzyGPCyGxrm0JQ1ZIdg=="], - - "@browserbasehq/stagehand/ai": ["ai@5.0.179", "", { "dependencies": { "@ai-sdk/gateway": "2.0.82", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tuq/r2FH/pBuY3jo0yHF3UglDV73WONGLhW80DuwgO6w0ftPIqRsAm5p9cE3Bu4LfEuCkMXpiUG/pQRzqKRRaA=="], - - "@browserbasehq/stagehand/devtools-protocol": ["devtools-protocol@0.0.1464554", "", {}, "sha512-CAoP3lYfwAGQTaAXYvA6JZR0fjGUb7qec1qf4mToyoH2TZgUFeIqYcjh6f9jNuhHfuZiEdH+PONHYrLhRQX6aw=="], - - "@browserbasehq/stagehand/puppeteer-core": ["puppeteer-core@22.15.0", "", { "dependencies": { "@puppeteer/browsers": "2.3.0", "chromium-bidi": "0.6.3", "debug": "^4.3.6", "devtools-protocol": "0.0.1312386", "ws": "^8.18.0" } }, "sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA=="], - - "@browserbasehq/stagehand/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], - "@code-inspector/core/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "@code-inspector/core/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], @@ -6598,14 +6200,6 @@ "@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "@langchain/core/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], - - "@langchain/core/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], - - "@langchain/core/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "@langchain/openai/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "@libsql/hrana-client/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], "@linear/sdk/graphql": ["graphql@15.10.2", "", {}, "sha512-1PRqdDPAmViWr4h1GVBT8RoPZfWSGZa7kDzleTilOfVIslsgf+cia3Nl95v1KDmR4iERPaT7WzQ+tN4MJmbg3w=="], @@ -6692,8 +6286,6 @@ "@react-native/dev-middleware/@isaacs/ttlcache": ["@isaacs/ttlcache@1.4.1", "", {}, "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA=="], - "@react-native/dev-middleware/chrome-launcher": ["chrome-launcher@0.15.2", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0" }, "bin": { "print-chrome-path": "bin/print-chrome-path.js" } }, "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ=="], - "@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.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], @@ -6778,22 +6370,10 @@ "@vue/compiler-core/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], - "@wdio/config/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - - "@wdio/config/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], - - "@wdio/repl/@types/node": ["@types/node@20.19.39", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw=="], - - "@wdio/types/@types/node": ["@types/node@20.19.39", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw=="], - - "@wdio/utils/decamelize": ["decamelize@6.0.1", "", {}, "sha512-G7Cqgaelq68XHJNGlZ7lrNQyhZGsFqpwtGFexqUv4IQdjKoSYF7ipZ9UuTJZUSQXFj/XaoBLuEVIVqr8EJngEQ=="], - "@xterm/addon-ligatures/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], "@xyflow/react/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], - "agent-browser/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "ai/@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], @@ -6816,8 +6396,6 @@ "archiver-utils/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=="], - "asyncbox/bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="], - "ava/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "ava/ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], @@ -6840,26 +6418,14 @@ "builder-util/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "cacache/fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="], - "cacache/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "cacache/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "cacheable-request/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], - "cheerio/htmlparser2": ["htmlparser2@10.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "entities": "^7.0.1" } }, "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ=="], - - "cheerio/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], - - "cheerio/parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@7.1.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" } }, "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g=="], - - "cheerio/undici": ["undici@7.24.8", "", {}, "sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ=="], - "chromium-bidi/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "chromium-edge-launcher/lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="], - "chromium-edge-launcher/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], "clean-stack/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -6922,10 +6488,6 @@ "duplexer2/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=="], - "edgedriver/decamelize": ["decamelize@6.0.1", "", {}, "sha512-G7Cqgaelq68XHJNGlZ7lrNQyhZGsFqpwtGFexqUv4IQdjKoSYF7ipZ9UuTJZUSQXFj/XaoBLuEVIVqr8EJngEQ=="], - - "edgedriver/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="], - "electron-builder/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "electron-publish/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -6934,8 +6496,6 @@ "encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - "encoding-sniffer/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - "engine.io/accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], "engine.io/ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], @@ -6972,20 +6532,12 @@ "extract-zip/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], - "fastembed/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], - - "fetch-cookie/set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="], - "filelist/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "formdata-node/web-streams-polyfill": ["web-streams-polyfill@4.0.0-beta.3", "", {}, "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="], - "friendly-words/express": ["express@4.22.1", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "~1.20.3", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.3.1", "fresh": "~0.5.2", "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", "serve-static": "~1.16.2", "setprototypeof": "1.2.0", "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g=="], - "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - "fstream/rimraf": ["rimraf@2.7.1", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w=="], "fumadocs-mdx/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], @@ -6994,10 +6546,6 @@ "fumadocs-ui/lucide-react": ["lucide-react@0.562.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw=="], - "gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], - - "geckodriver/decamelize": ["decamelize@6.0.1", "", {}, "sha512-G7Cqgaelq68XHJNGlZ7lrNQyhZGsFqpwtGFexqUv4IQdjKoSYF7ipZ9UuTJZUSQXFj/XaoBLuEVIVqr8EJngEQ=="], - "get-stream/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], "get-uri/data-uri-to-buffer": ["data-uri-to-buffer@6.0.2", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="], @@ -7064,12 +6612,6 @@ "langium/vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="], - "langsmith/@types/uuid": ["@types/uuid@10.0.0", "", {}, "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ=="], - - "langsmith/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "langsmith/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], - "launch-ide/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "launch-ide/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], @@ -7078,9 +6620,9 @@ "libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], - "lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "locate-app/type-fest": ["type-fest@4.26.0", "", {}, "sha512-OduNjVJsFbifKb57UqZ2EMP1i4u64Xwow3NYXUtBbD4vIwJdQd4+xl8YDou1dlm4DVrtwT/7Ky8z8WyCULVfxw=="], + "lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "make-fetch-happen/proc-log": ["proc-log@5.0.0", "", {}, "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ=="], @@ -7088,7 +6630,7 @@ "mastracode/@ast-grep/napi": ["@ast-grep/napi@0.42.1", "", { "optionalDependencies": { "@ast-grep/napi-darwin-arm64": "0.42.1", "@ast-grep/napi-darwin-x64": "0.42.1", "@ast-grep/napi-linux-arm64-gnu": "0.42.1", "@ast-grep/napi-linux-arm64-musl": "0.42.1", "@ast-grep/napi-linux-x64-gnu": "0.42.1", "@ast-grep/napi-linux-x64-musl": "0.42.1", "@ast-grep/napi-win32-arm64-msvc": "0.42.1", "@ast-grep/napi-win32-ia32-msvc": "0.42.1", "@ast-grep/napi-win32-x64-msvc": "0.42.1" } }, "sha512-+YEv9ElJi9azr8AYII79NxYXQRJsrUy1kUqZfxZfvPM7rhs3174mzB+qEE9Pl3sVKAJS5cevyT4lgLNV0AZK6A=="], - "mastracode/@mastra/mcp": ["@mastra/mcp@1.5.0", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^14.2.1", "@modelcontextprotocol/sdk": "^1.27.1", "exit-hook": "^5.1.0", "fast-deep-equal": "^3.1.3", "uuid": "^13.0.0" }, "peerDependencies": { "@mastra/core": ">=1.0.0-0 <2.0.0-0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-I+YtghjjkKdlTtqVc1TTChnRTZ0HiMKq6o5UCjZGuGdK2oHlkTYLYd2rRZI9tIcEIXjG2bQz9OzlQhAaDd+TJw=="], + "mastracode/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], "matcher/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -7160,28 +6702,14 @@ "node-gyp/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], - "node-simctl/bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="], - - "node-simctl/rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], - - "node-simctl/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], - - "node-simctl/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], - "npm-package-arg/hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="], "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], "nypm/tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], - "ollama-ai-provider-v2/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], - - "ollama-ai-provider-v2/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - "onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], - "openai/@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="], - "ora/log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="], "ora/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], @@ -7194,22 +6722,12 @@ "parse5-htmlparser2-tree-adapter/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="], - "parse5-parser-stream/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], - "periscopic/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], "periscopic/is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], - "pino-pretty/pino-abstract-transport": ["pino-abstract-transport@3.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg=="], - - "pino-pretty/secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="], - - "pino-pretty/strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="], - "pkg-conf/find-up": ["find-up@6.3.0", "", { "dependencies": { "locate-path": "^7.1.0", "path-exists": "^5.0.0" } }, "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw=="], - "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], - "plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], @@ -7272,8 +6790,6 @@ "rehype-attr/unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="], - "resq/fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="], - "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], "roarr/sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], @@ -7330,8 +6846,6 @@ "tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], - "teen_process/bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="], - "temp/mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], "temp/rimraf": ["rimraf@2.6.3", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA=="], @@ -7350,8 +6864,6 @@ "tunnel-rat/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], - "unbzip2-stream/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], - "uniwind/@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="], "uniwind/@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="], @@ -7386,20 +6898,6 @@ "vscode-markdown-languageservice/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], - "wait-port/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "wait-port/commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="], - - "webdriver/@types/node": ["@types/node@20.19.39", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw=="], - - "webdriverio/@types/node": ["@types/node@20.19.39", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw=="], - - "webdriverio/archiver": ["archiver@7.0.1", "", { "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", "buffer-crc32": "^1.0.0", "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", "zip-stream": "^6.0.1" } }, "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ=="], - - "webdriverio/serialize-error": ["serialize-error@12.0.0", "", { "dependencies": { "type-fest": "^4.31.0" } }, "sha512-ZYkZLAvKTKQXWuh5XpBw7CdbSzagarX39WyZ2H07CDLC5/KfsRGlIXV8d4+tfqX1M7916mRqR1QfNHSij+c9Pw=="], - - "whatwg-encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - "wrangler/esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], "wrangler/path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], @@ -7460,30 +6958,8 @@ "@ai-sdk/ui-utils-v5/@ai-sdk/provider-utils/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], - "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], - "@browserbasehq/sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], - - "@browserbasehq/stagehand/@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@browserbasehq/stagehand/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@browserbasehq/stagehand/@anthropic-ai/sdk/@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="], - - "@browserbasehq/stagehand/ai/@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.82", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-vtoCSEBGPcxzChI3eqe9C9AJSlc/WUZp92tzpOqVd4B6Tnu4583S+qR7TknB0tPta15TEoOIkK0ENW6D/DgRJQ=="], - - "@browserbasehq/stagehand/ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - - "@browserbasehq/stagehand/ai/@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], - - "@browserbasehq/stagehand/puppeteer-core/@puppeteer/browsers": ["@puppeteer/browsers@2.3.0", "", { "dependencies": { "debug": "^4.3.5", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.4.0", "semver": "^7.6.3", "tar-fs": "^3.0.6", "unbzip2-stream": "^1.4.3", "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" } }, "sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA=="], - - "@browserbasehq/stagehand/puppeteer-core/chromium-bidi": ["chromium-bidi@0.6.3", "", { "dependencies": { "mitt": "3.0.1", "urlpattern-polyfill": "10.0.0", "zod": "3.23.8" }, "peerDependencies": { "devtools-protocol": "*" } }, "sha512-qXlsCmpCZJAnoTYI83Iu6EdYQpMYdVkCfq08KDh2pmlVqK5t5IA9mGs4/LwCwp4fqisSOMXZxP3HIh8w8aRn0A=="], - - "@browserbasehq/stagehand/puppeteer-core/devtools-protocol": ["devtools-protocol@0.0.1312386", "", {}, "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA=="], - "@develar/schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], "@electron/asar/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], @@ -7658,8 +7134,6 @@ "@react-native/community-cli-plugin/@react-native/dev-middleware/@react-native/debugger-shell": ["@react-native/debugger-shell@0.83.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "fb-dotslash": "0.5.8" } }, "sha512-d+0w446Hxth5OP/cBHSSxOEpbj13p2zToUy6e5e3tTERNJ8ueGlW7iGwGTrSymNDgXXFjErX+dY4P4/3WokPIQ=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware/chrome-launcher": ["chrome-launcher@0.15.2", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0" }, "bin": { "print-chrome-path": "bin/print-chrome-path.js" } }, "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ=="], - "@react-native/community-cli-plugin/@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/community-cli-plugin/@react-native/dev-middleware/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], @@ -7700,8 +7174,6 @@ "@react-native/community-cli-plugin/metro-core/metro-resolver": ["metro-resolver@0.83.6", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-lAwR/FsT1uJ5iCt4AIsN3boKfJ88aN8bjvDT5FwBS0tKeKw4/sbdSTWlFxc7W/MUTN5RekJ3nQkJRIWsvs28tA=="], - "@react-native/dev-middleware/chrome-launcher/lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="], - "@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=="], "@sentry/cli/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], @@ -7754,16 +7226,6 @@ "@tanstack/router-plugin/unplugin/webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], - "@wdio/config/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - - "@wdio/config/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - - "@wdio/config/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - - "@wdio/repl/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - - "@wdio/types/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - "app-builder-lib/@electron/get/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], "app-builder-lib/@electron/get/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], @@ -7786,12 +7248,6 @@ "cacache/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - "cheerio/htmlparser2/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], - - "cheerio/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], - - "chromium-edge-launcher/lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "chromium-edge-launcher/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], "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=="], @@ -7826,8 +7282,6 @@ "duplexer2/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - "edgedriver/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="], - "electron-winstaller/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], "electron-winstaller/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], @@ -7836,12 +7290,6 @@ "engine.io/accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], - "fastembed/tar/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], - - "fastembed/tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], - - "fastembed/tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], - "filelist/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -7950,6 +7398,8 @@ "lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + "lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "mastracode/@ast-grep/napi/@ast-grep/napi-darwin-arm64": ["@ast-grep/napi-darwin-arm64@0.42.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VtO4DX20ODCfRBwv1I71lZx+qlrhlMbt9Rpo3LozoaUpHnLmyFMBSgpUal5KTd1SCKUK8ekJGgxpKWo27H4AVQ=="], "mastracode/@ast-grep/napi/@ast-grep/napi-darwin-x64": ["@ast-grep/napi-darwin-x64@0.42.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-V2uaKP6QZLb60iFHK0IiXAcwSoUliiDJ3c1zLLzHnBFyCbTKC4b3L3XtkiyKsnpET+uzY7hQLpTIAhW5aOCX4w=="], @@ -7968,6 +7418,8 @@ "mastracode/@ast-grep/napi/@ast-grep/napi-win32-x64-msvc": ["@ast-grep/napi-win32-x64-msvc@0.42.1", "", { "os": "win32", "cpu": "x64" }, "sha512-NAeA2Q6jp7F9uXtSuG12c1xjTzipXFCTvuAcEBnsTwBXq0kdPV6H6Y4GZJVcDhsHk3TX4sGlQGkuV/6FT2Ngig=="], + "mastracode/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + "metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.33.3", "", {}, "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg=="], "metro-file-map/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], @@ -7990,20 +7442,12 @@ "node-gyp/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="], - "node-simctl/rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - - "node-simctl/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="], - "npm-package-arg/hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "openai/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], - "ora/log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], "ora/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], - "parse5-parser-stream/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], - "pkg-conf/find-up/locate-path": ["locate-path@7.2.0", "", { "dependencies": { "p-locate": "^6.0.0" } }, "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA=="], "pkg-conf/find-up/path-exists": ["path-exists@5.0.0", "", {}, "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ=="], @@ -8188,22 +7632,6 @@ "vscode-languageserver/vscode-languageserver-protocol/vscode-languageserver-types": ["vscode-languageserver-types@3.17.2", "", {}, "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA=="], - "webdriver/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - - "webdriverio/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - - "webdriverio/archiver/archiver-utils": ["archiver-utils@5.0.2", "", { "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA=="], - - "webdriverio/archiver/buffer-crc32": ["buffer-crc32@1.0.0", "", {}, "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w=="], - - "webdriverio/archiver/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], - - "webdriverio/archiver/tar-stream": ["tar-stream@3.1.8", "", { "dependencies": { "b4a": "^1.6.4", "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ=="], - - "webdriverio/archiver/zip-stream": ["zip-stream@6.0.1", "", { "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" } }, "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA=="], - - "webdriverio/serialize-error/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], - "wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], "wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], @@ -8278,16 +7706,6 @@ "@a2a-js/sdk/express/type-is/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], - - "@browserbasehq/stagehand/@anthropic-ai/sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], - - "@browserbasehq/stagehand/ai/@ai-sdk/gateway/@vercel/oidc": ["@vercel/oidc@3.1.0", "", {}, "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w=="], - - "@browserbasehq/stagehand/puppeteer-core/@puppeteer/browsers/tar-fs": ["tar-fs@3.1.2", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw=="], - - "@browserbasehq/stagehand/puppeteer-core/chromium-bidi/zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="], - "@electron/asar/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "@electron/rebuild/ora/cli-cursor/restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="], @@ -8330,8 +7748,6 @@ "@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware/chrome-launcher/lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="], - "@react-native/community-cli-plugin/@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=="], "@react-native/community-cli-plugin/metro/hermes-parser/hermes-estree": ["hermes-estree@0.35.0", "", {}, "sha512-xVx5Opwy8Oo1I5yGpVRhCvWL/iV3M+ylksSKVNlxxD90cpDpR/AR1jLYqK8HWihm065a6UI3HeyAmYzwS8NOOg=="], @@ -8340,8 +7756,6 @@ "@react-native/community-cli-plugin/metro/metro-transform-worker/metro-minify-terser": ["metro-minify-terser@0.83.6", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-Vx3/Ne9Q+EIEDLfKzZUOtn/rxSNa/QjlYxc42nvK4Mg8mB6XUgd3LXX5ZZVq7lzQgehgEqLrbgShJPGfeF8PnQ=="], - "@react-native/dev-middleware/chrome-launcher/lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "@react-native/dev-middleware/serve-static/send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "@react-native/dev-middleware/serve-static/send/fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], @@ -8356,12 +7770,6 @@ "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - "@wdio/config/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - - "@wdio/config/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], - - "@wdio/config/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "app-builder-lib/@electron/get/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], "app-builder-lib/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], @@ -8372,8 +7780,6 @@ "cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], - "chromium-edge-launcher/lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "chromium-edge-launcher/rimraf/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], "cli-highlight/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -8382,8 +7788,6 @@ "engine.io/accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "fastembed/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - "filelist/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "friendly-words/express/accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], @@ -8410,12 +7814,6 @@ "graphql-language-service-server/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], - "node-simctl/rimraf/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - - "node-simctl/rimraf/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - - "node-simctl/rimraf/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - "pkg-conf/find-up/locate-path/p-locate": ["p-locate@6.0.0", "", { "dependencies": { "p-limit": "^4.0.0" } }, "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw=="], "react-native/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], @@ -8468,20 +7866,12 @@ "vscode-langservers-extracted/vscode-languageserver/vscode-languageserver-protocol/vscode-languageserver-types": ["vscode-languageserver-types@3.17.6-next.6", "", {}, "sha512-aiJY5/yW+xzw7KPNlwi3gQtddq/3EIn5z8X8nCgJfaiAij2R1APKePngv+MUdLdYJBVTLu+Qa0ODsT+pHgYguQ=="], - "webdriverio/archiver/archiver-utils/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - - "webdriverio/archiver/readable-stream/string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], - - "webdriverio/archiver/zip-stream/compress-commons": ["compress-commons@6.0.2", "", { "dependencies": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", "is-stream": "^2.0.1", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg=="], - "zip-stream/archiver-utils/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], "@a2a-js/sdk/express/accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "@a2a-js/sdk/express/type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "@browserbasehq/stagehand/puppeteer-core/@puppeteer/browsers/tar-fs/tar-stream": ["tar-stream@3.1.8", "", { "dependencies": { "b4a": "^1.6.4", "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ=="], - "@electron/rebuild/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], "@expo/cli/ora/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], @@ -8506,16 +7896,12 @@ "@react-native/codegen/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware/chrome-launcher/lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware/serve-static/send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "@react-native/community-cli-plugin/@react-native/dev-middleware/serve-static/send/fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], "@react-native/community-cli-plugin/@react-native/dev-middleware/serve-static/send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], - "@react-native/dev-middleware/chrome-launcher/lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "@react-native/dev-middleware/serve-static/send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], @@ -8524,12 +7910,6 @@ "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "@wdio/config/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], - - "@wdio/config/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], - - "@wdio/config/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "archiver-utils/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "cacache/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], @@ -8552,26 +7932,12 @@ "graphql-language-service-server/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "node-simctl/rimraf/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - - "node-simctl/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], - - "node-simctl/rimraf/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "pkg-conf/find-up/locate-path/p-locate/p-limit": ["p-limit@4.0.0", "", { "dependencies": { "yocto-queue": "^1.0.0" } }, "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ=="], "react-native/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "temp/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], - "webdriverio/archiver/archiver-utils/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - - "webdriverio/archiver/archiver-utils/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - - "webdriverio/archiver/archiver-utils/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - - "webdriverio/archiver/zip-stream/compress-commons/crc32-stream": ["crc32-stream@6.0.0", "", { "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" } }, "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g=="], - "zip-stream/archiver-utils/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], "@expo/cli/ora/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], @@ -8584,8 +7950,6 @@ "@react-native/babel-plugin-codegen/@react-native/codegen/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware/chrome-launcher/lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware/serve-static/send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], @@ -8594,10 +7958,6 @@ "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "@wdio/config/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - - "@wdio/config/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - "cacache/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "cacache/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], @@ -8606,40 +7966,14 @@ "fstream/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "node-simctl/rimraf/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], - - "node-simctl/rimraf/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], - - "node-simctl/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "pkg-conf/find-up/locate-path/p-locate/p-limit/yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="], "temp/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "webdriverio/archiver/archiver-utils/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - - "webdriverio/archiver/archiver-utils/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], - - "webdriverio/archiver/archiver-utils/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "zip-stream/archiver-utils/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "node-simctl/rimraf/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - - "node-simctl/rimraf/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "webdriverio/archiver/archiver-utils/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], - - "webdriverio/archiver/archiver-utils/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], - - "webdriverio/archiver/archiver-utils/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "webdriverio/archiver/archiver-utils/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - - "webdriverio/archiver/archiver-utils/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], } } diff --git a/packages/chat/package.json b/packages/chat/package.json index 610bf047928..91806e673ef 100644 --- a/packages/chat/package.json +++ b/packages/chat/package.json @@ -23,10 +23,6 @@ "./server/hono": { "types": "./src/server/hono/index.ts", "default": "./src/server/hono/index.ts" - }, - "./server/shared": { - "types": "./src/server/shared/index.ts", - "default": "./src/server/shared/index.ts" } }, "scripts": { @@ -36,7 +32,7 @@ "dependencies": { "@ai-sdk/anthropic": "^3.0.43", "@ai-sdk/openai": "3.0.36", - "@mastra/core": "1.25.0", + "@mastra/core": "1.16.0", "@mastra/mcp": "1.3.1", "@superset/trpc": "workspace:*", "@superset/workspace-fs": "workspace:*", @@ -44,7 +40,7 @@ "@trpc/server": "^11.7.1", "ai": "^6.0.0", "hono": "^4.8.5", - "mastracode": "0.14.0", + "mastracode": "0.9.2", "superjson": "^2.2.5", "zod": "^4.3.5" }, diff --git a/packages/chat/src/server/desktop/auth/anthropic/anthropic.ts b/packages/chat/src/server/desktop/auth/anthropic/anthropic.ts index 75c5fff8209..b28ef85d5cc 100644 --- a/packages/chat/src/server/desktop/auth/anthropic/anthropic.ts +++ b/packages/chat/src/server/desktop/auth/anthropic/anthropic.ts @@ -168,7 +168,7 @@ export function getCredentialsFromKeychain(): ClaudeCredentials | null { return null; } -export async function getCredentialsFromAuthStorage(): Promise { +export function getCredentialsFromAuthStorage(): ClaudeCredentials | null { try { const authStorage = createAuthStorage(); authStorage.reload(); @@ -187,22 +187,18 @@ export async function getCredentialsFromAuthStorage(): Promise 0 + ) { return { - apiKey: accessToken.trim(), + apiKey: credential.access.trim(), source: "auth-storage", kind: "oauth", expiresAt: - refreshed?.type === "oauth" && typeof refreshed.expires === "number" - ? refreshed.expires + typeof credential.expires === "number" + ? credential.expires : undefined, }; } @@ -213,22 +209,24 @@ export async function getCredentialsFromAuthStorage(): Promise { - const syncResolvers = [getCredentialsFromConfig, getCredentialsFromKeychain]; +export function getCredentialsFromAnySource(): ClaudeCredentials | null { + const resolvers = [ + getCredentialsFromConfig, + getCredentialsFromKeychain, + getCredentialsFromAuthStorage, + ]; let firstExpired: ClaudeCredentials | null = null; - for (const resolve of syncResolvers) { + for (const resolve of resolvers) { const credential = resolve(); - if (!credential) continue; - if (!isClaudeCredentialExpired(credential)) return credential; + if (!credential) { + continue; + } + if (!isClaudeCredentialExpired(credential)) { + return credential; + } firstExpired ??= credential; } - const storageCredential = await getCredentialsFromAuthStorage(); - if (storageCredential && !isClaudeCredentialExpired(storageCredential)) { - return storageCredential; - } - firstExpired ??= storageCredential ?? null; - return firstExpired; } diff --git a/packages/chat/src/server/desktop/chat-service/auth-storage-utils.ts b/packages/chat/src/server/desktop/chat-service/auth-storage-utils.ts index 065e8226c25..bcdff698c59 100644 --- a/packages/chat/src/server/desktop/chat-service/auth-storage-utils.ts +++ b/packages/chat/src/server/desktop/chat-service/auth-storage-utils.ts @@ -1,8 +1,3 @@ -// WORKAROUND: backup/restore API keys across OAuth connect/disconnect. -// mastracode's resolveModel only reads API keys from the main authStorage -// slot, which OAuth login overwrites and disconnect clears. We back up to -// the dedicated apikey: slot before OAuth and restore after disconnect. -// Remove once mastra-ai/mastra#15483 lands and we bump mastracode. import type { AuthMethod, AuthStorageLike, @@ -21,14 +16,10 @@ export function setApiKeyForProvider( } authStorage.reload(); - // Store in main slot (mastracode's resolveModel reads from here). authStorage.set(providerId, { type: "api_key", key: trimmedApiKey, }); - // Also store in dedicated apikey: slot as a backup that survives - // OAuth connect/disconnect cycles. - authStorage.setStoredApiKey(providerId, trimmedApiKey); } export function clearApiKeyForProvider( @@ -36,54 +27,12 @@ export function clearApiKeyForProvider( providerId: string, ): void { authStorage.reload(); - - // Clear the dedicated backup slot. - if (authStorage.hasStoredApiKey(providerId)) { - authStorage.remove(`apikey:${providerId}`); - } - - // Clear the main slot if it holds an api_key. - const credential = authStorage.get(providerId); - if (credential?.type === "api_key") { - authStorage.remove(providerId); - } -} - -/** - * Save the current API key to the backup slot before OAuth overwrites - * the main slot. Call this BEFORE authStorage.login(). - */ -export function backupApiKeyBeforeOAuth( - authStorage: AuthStorageLike, - providerId: string, -): void { - authStorage.reload(); const credential = authStorage.get(providerId); - if ( - credential?.type === "api_key" && - credential.key.trim().length > 0 && - !authStorage.hasStoredApiKey(providerId) - ) { - authStorage.setStoredApiKey(providerId, credential.key.trim()); + if (credential?.type !== "api_key") { + return; } -} -/** - * Restore the API key from the backup slot after OAuth is disconnected. - * Call this AFTER removing the OAuth credential from the main slot. - */ -export function restoreApiKeyAfterOAuthDisconnect( - authStorage: AuthStorageLike, - providerId: string, -): void { - authStorage.reload(); - const storedApiKey = authStorage.getStoredApiKey(providerId); - if (storedApiKey && storedApiKey.trim().length > 0) { - authStorage.set(providerId, { - type: "api_key", - key: storedApiKey.trim(), - }); - } + authStorage.remove(providerId); } export function clearCredentialForProvider( @@ -111,9 +60,5 @@ export function resolveAuthMethodForProvider( if (credential?.type === "api_key" && credential.key.trim().length > 0) { return "api_key"; } - // Check the backup slot — API key may have been displaced by OAuth. - if (authStorage.hasStoredApiKey(providerId)) { - return "api_key"; - } return null; } diff --git a/packages/chat/src/server/desktop/chat-service/chat-service.test.ts b/packages/chat/src/server/desktop/chat-service/chat-service.test.ts index 9f42658e9ff..41f71244718 100644 --- a/packages/chat/src/server/desktop/chat-service/chat-service.test.ts +++ b/packages/chat/src/server/desktop/chat-service/chat-service.test.ts @@ -26,16 +26,6 @@ type FakeAuthStorage = { (providerId: string, callbacks: OAuthCallbacks) => Promise > >; - setStoredApiKey: ReturnType< - typeof mock<(providerId: string, key: string) => void> - >; - hasStoredApiKey: ReturnType boolean>>; - getStoredApiKey: ReturnType< - typeof mock<(providerId: string) => string | undefined> - >; - getApiKey: ReturnType< - typeof mock<(providerId: string) => Promise> - >; clear: () => void; }; @@ -51,27 +41,6 @@ function createFakeAuthStorage(): FakeAuthStorage { credentials.delete(providerId); }), login: mock(async () => {}), - setStoredApiKey: mock((providerId: string, key: string) => { - credentials.set(`apikey:${providerId}`, { - type: "api_key", - key, - } as Credential); - }), - hasStoredApiKey: mock((providerId: string) => - credentials.has(`apikey:${providerId}`), - ), - getStoredApiKey: mock((providerId: string) => { - const cred = credentials.get(`apikey:${providerId}`); - return cred?.type === "api_key" ? cred.key : undefined; - }), - getApiKey: mock(async (providerId: string) => { - const cred = credentials.get(providerId); - if (cred?.type === "oauth" && "access" in cred) { - return (cred as Record).access as string; - } - const stored = credentials.get(`apikey:${providerId}`); - return stored?.type === "api_key" ? stored.key : undefined; - }), clear: () => { credentials.clear(); }, @@ -133,8 +102,8 @@ mock.module("mastracode", () => ({ mock.module("../auth/anthropic", () => ({ getCredentialsFromConfig: () => anthropicConfigCredential, getCredentialsFromKeychain: () => anthropicKeychainCredential, - getCredentialsFromAnySource: async () => null, - getCredentialsFromAuthStorage: async () => null, + getCredentialsFromAnySource: () => null, + getCredentialsFromAuthStorage: () => null, getAnthropicProviderOptions: () => ({}), isClaudeCredentialExpired: (credential: { kind: "apiKey" | "oauth"; @@ -158,10 +127,6 @@ describe("ChatService OpenAI auth storage", () => { fakeAuthStorage.set.mockClear(); fakeAuthStorage.remove.mockClear(); fakeAuthStorage.login.mockClear(); - fakeAuthStorage.setStoredApiKey.mockClear(); - fakeAuthStorage.hasStoredApiKey.mockClear(); - fakeAuthStorage.getStoredApiKey.mockClear(); - fakeAuthStorage.getApiKey.mockClear(); anthropicConfigCredential = null; anthropicKeychainCredential = null; testSupersetHomeDir = mkdtempSync(join(tmpdir(), "chat-service-test-")); @@ -210,11 +175,11 @@ describe("ChatService OpenAI auth storage", () => { await chatService.clearOpenAIApiKey(); expect(createAuthStorageMock).toHaveBeenCalledTimes(1); - expect(fakeAuthStorage.setStoredApiKey).toHaveBeenCalledWith( - "openai-codex", - "test-key", - ); - expect(fakeAuthStorage.remove).toHaveBeenCalledWith("apikey:openai-codex"); + expect(fakeAuthStorage.set).toHaveBeenCalledWith("openai-codex", { + type: "api_key", + key: "test-key", + }); + expect(fakeAuthStorage.remove).toHaveBeenCalledWith("openai-codex"); }); it("stores and clears Anthropic API key in standalone auth storage", async () => { @@ -228,11 +193,11 @@ describe("ChatService OpenAI auth storage", () => { await chatService.clearAnthropicApiKey(); expect(createAuthStorageMock).toHaveBeenCalledTimes(1); - expect(fakeAuthStorage.setStoredApiKey).toHaveBeenCalledWith( - "anthropic", - "test-anthropic-key", - ); - expect(fakeAuthStorage.remove).toHaveBeenCalledWith("apikey:anthropic"); + expect(fakeAuthStorage.set).toHaveBeenCalledWith("anthropic", { + type: "api_key", + key: "test-anthropic-key", + }); + expect(fakeAuthStorage.remove).toHaveBeenCalledWith("anthropic"); }); it("persists Anthropic OAuth credentials to auth storage on completion", async () => { @@ -278,7 +243,31 @@ describe("ChatService OpenAI auth storage", () => { }), ); expect(result.expiresAt).toBe(oauthExpiresAt); - expect((await chatService.getAnthropicAuthStatus()).method).toBe("oauth"); + expect(chatService.getAnthropicAuthStatus().method).toBe("oauth"); + }); + + it("switches Anthropic status from oauth to api key when api key is saved", async () => { + const chatService = new ChatService(); + + fakeAuthStorage.login.mockImplementation( + async (providerId: string, callbacks: OAuthCallbacks) => { + callbacks.onAuth({ url: "https://claude.ai/oauth/authorize?foo=bar" }); + const code = await callbacks.onPrompt({ message: "Paste code" }); + expect(code).toBe("auth-code#state"); + fakeAuthStorage.set(providerId, { + type: "oauth", + access: "oauth-access-token", + expires: Date.now() + 60 * 60 * 1000, + }); + }, + ); + + await chatService.startAnthropicOAuth(); + await chatService.completeAnthropicOAuth({ code: "auth-code#state" }); + expect(chatService.getAnthropicAuthStatus().method).toBe("oauth"); + + await chatService.setAnthropicApiKey({ apiKey: " api-key " }); + expect(chatService.getAnthropicAuthStatus().method).toBe("api_key"); }); it("prefers a managed Anthropic API key over env-config credentials", async () => { @@ -295,7 +284,7 @@ describe("ChatService OpenAI auth storage", () => { ); expect(process.env.ANTHROPIC_API_KEY).toBeUndefined(); expect(process.env.ANTHROPIC_AUTH_TOKEN).toBeUndefined(); - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: true, method: "api_key", source: "managed", @@ -303,12 +292,12 @@ describe("ChatService OpenAI auth storage", () => { }); }); - it("ignores Anthropic runtime env credentials without managed auth", async () => { + it("ignores Anthropic runtime env credentials without managed auth", () => { const chatService = new ChatService(); process.env.ANTHROPIC_AUTH_TOKEN = "external-oauth-token"; - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: false, method: null, source: null, @@ -316,7 +305,7 @@ describe("ChatService OpenAI auth storage", () => { }); }); - it("prefers external Anthropic credentials over managed auth", async () => { + it("prefers external Anthropic credentials over managed auth", () => { const chatService = new ChatService(); anthropicConfigCredential = { @@ -324,9 +313,12 @@ describe("ChatService OpenAI auth storage", () => { source: "config", kind: "oauth", }; - fakeAuthStorage.setStoredApiKey("anthropic", "managed-api-key"); + fakeAuthStorage.set("anthropic", { + type: "api_key", + key: "managed-api-key", + }); - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: true, method: "oauth", source: "external", @@ -334,7 +326,7 @@ describe("ChatService OpenAI auth storage", () => { }); }); - it("surfaces hidden managed Anthropic OAuth when external Claude auth wins", async () => { + it("surfaces hidden managed Anthropic OAuth when external Claude auth wins", () => { const chatService = new ChatService(); anthropicConfigCredential = { @@ -348,7 +340,7 @@ describe("ChatService OpenAI auth storage", () => { expires: Date.now() + 60 * 60 * 1000, }); - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: true, method: "oauth", source: "external", @@ -357,13 +349,16 @@ describe("ChatService OpenAI auth storage", () => { }); }); - it("prefers managed Anthropic auth over runtime env credentials", async () => { + it("prefers managed Anthropic auth over runtime env credentials", () => { const chatService = new ChatService(); process.env.ANTHROPIC_AUTH_TOKEN = "external-oauth-token"; - fakeAuthStorage.setStoredApiKey("anthropic", "managed-api-key"); + fakeAuthStorage.set("anthropic", { + type: "api_key", + key: "managed-api-key", + }); - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: true, method: "api_key", source: "managed", @@ -371,7 +366,7 @@ describe("ChatService OpenAI auth storage", () => { }); }); - it("marks expired external Anthropic OAuth as expired", async () => { + it("marks expired external Anthropic OAuth as expired", () => { const chatService = new ChatService(); anthropicConfigCredential = { @@ -381,7 +376,7 @@ describe("ChatService OpenAI auth storage", () => { expiresAt: Date.now() - 1_000, }; - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: false, method: "oauth", source: "external", @@ -389,7 +384,7 @@ describe("ChatService OpenAI auth storage", () => { }); }); - it("falls back to managed Anthropic auth when external OAuth is expired", async () => { + it("falls back to managed Anthropic auth when external OAuth is expired", () => { const chatService = new ChatService(); anthropicConfigCredential = { @@ -398,9 +393,12 @@ describe("ChatService OpenAI auth storage", () => { kind: "oauth", expiresAt: Date.now() - 1_000, }; - fakeAuthStorage.setStoredApiKey("anthropic", "managed-api-key"); + fakeAuthStorage.set("anthropic", { + type: "api_key", + key: "managed-api-key", + }); - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: true, method: "api_key", source: "managed", @@ -417,7 +415,7 @@ describe("ChatService OpenAI auth storage", () => { expires: Date.now() + 60 * 60 * 1000, }); - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: true, method: "oauth", source: "managed", @@ -428,7 +426,7 @@ describe("ChatService OpenAI auth storage", () => { await chatService.disconnectAnthropicOAuth(); expect(fakeAuthStorage.remove).toHaveBeenCalledWith("anthropic"); - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: false, method: null, source: null, @@ -449,10 +447,10 @@ describe("ChatService OpenAI auth storage", () => { ); expect(process.env.ANTHROPIC_AUTH_TOKEN).toBeUndefined(); expect(process.env.ANTHROPIC_API_KEY).toBeUndefined(); - expect(fakeAuthStorage.setStoredApiKey).toHaveBeenCalledWith( - "anthropic", - "gateway-token", - ); + expect(fakeAuthStorage.set).toHaveBeenCalledWith("anthropic", { + type: "api_key", + key: "gateway-token", + }); expect(chatService.getAnthropicEnvConfig()).toEqual({ envText: "ANTHROPIC_BASE_URL=https://ai-gateway.vercel.sh\nANTHROPIC_AUTH_TOKEN=gateway-token", @@ -461,7 +459,7 @@ describe("ChatService OpenAI auth storage", () => { ANTHROPIC_AUTH_TOKEN: "gateway-token", }, }); - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: true, method: "api_key", source: "managed", @@ -476,7 +474,7 @@ describe("ChatService OpenAI auth storage", () => { access: "oauth-access-token", expires: Date.now() + 60 * 60 * 1000, }); - expect((await chatService.getAnthropicAuthStatus()).method).toBe("oauth"); + expect(chatService.getAnthropicAuthStatus().method).toBe("oauth"); await chatService.setAnthropicEnvConfig({ envText: @@ -484,7 +482,7 @@ describe("ChatService OpenAI auth storage", () => { }); expect(fakeAuthStorage.remove).toHaveBeenCalledWith("anthropic"); - expect((await chatService.getAnthropicAuthStatus()).method).toBe("api_key"); + expect(chatService.getAnthropicAuthStatus().method).toBe("api_key"); }); it("persists Anthropic env config without API key/token", async () => { @@ -500,7 +498,7 @@ describe("ChatService OpenAI auth storage", () => { ANTHROPIC_BASE_URL: "https://ai-gateway.vercel.sh", }, }); - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: false, method: null, source: null, @@ -524,11 +522,11 @@ describe("ChatService OpenAI auth storage", () => { await chatService.disconnectAnthropicOAuth(); expect(fakeAuthStorage.remove).toHaveBeenCalledWith("anthropic"); - expect(fakeAuthStorage.setStoredApiKey).toHaveBeenCalledWith( - "anthropic", - "gateway-token", - ); - expect(await chatService.getAnthropicAuthStatus()).toEqual({ + expect(fakeAuthStorage.set).toHaveBeenLastCalledWith("anthropic", { + type: "api_key", + key: "gateway-token", + }); + expect(chatService.getAnthropicAuthStatus()).toEqual({ authenticated: true, method: "api_key", source: "managed", @@ -547,10 +545,10 @@ describe("ChatService OpenAI auth storage", () => { expect(process.env.ANTHROPIC_AUTH_TOKEN).toBeUndefined(); expect(process.env.CLAUDE_CODE_USE_BEDROCK).toBe("1"); expect(process.env.AWS_REGION).toBe("us-east-1"); - expect(fakeAuthStorage.setStoredApiKey).toHaveBeenCalledWith( - "anthropic", - "env-key", - ); + expect(fakeAuthStorage.set).toHaveBeenCalledWith("anthropic", { + type: "api_key", + key: "env-key", + }); expect(chatService.getAnthropicEnvConfig()).toEqual({ envText: "ANTHROPIC_API_KEY=env-key\nCLAUDE_CODE_USE_BEDROCK=1\nAWS_REGION=us-east-1", @@ -574,12 +572,12 @@ describe("ChatService OpenAI auth storage", () => { expect(process.env.ANTHROPIC_BASE_URL).toBeUndefined(); expect(process.env.ANTHROPIC_AUTH_TOKEN).toBeUndefined(); expect(process.env.ANTHROPIC_API_KEY).toBeUndefined(); - expect(fakeAuthStorage.remove).toHaveBeenCalledWith("apikey:anthropic"); + expect(fakeAuthStorage.remove).toHaveBeenCalledWith("anthropic"); expect(chatService.getAnthropicEnvConfig()).toEqual({ envText: "", variables: {}, }); - expect((await chatService.getAnthropicAuthStatus()).method).toBeNull(); + expect(chatService.getAnthropicAuthStatus().method).toBeNull(); }); it("deletes previously applied pass-through env keys when settings change", async () => { diff --git a/packages/chat/src/server/desktop/chat-service/chat-service.ts b/packages/chat/src/server/desktop/chat-service/chat-service.ts index 449071bcef8..c6a2cacc808 100644 --- a/packages/chat/src/server/desktop/chat-service/chat-service.ts +++ b/packages/chat/src/server/desktop/chat-service/chat-service.ts @@ -27,11 +27,9 @@ import { } from "./anthropic-env-config"; import type { AuthStatus } from "./auth-storage-types"; import { - backupApiKeyBeforeOAuth, clearApiKeyForProvider, clearCredentialForProvider, resolveAuthMethodForProvider, - restoreApiKeyAfterOAuthDisconnect, setApiKeyForProvider, } from "./auth-storage-utils"; import { @@ -105,32 +103,11 @@ export class ChatService { ); } - async getAnthropicAuthStatus(): Promise { + getAnthropicAuthStatus(): AuthStatus { const authStorage = this.getAuthStorage(); authStorage.reload(); - let storedCredential = authStorage.get(ANTHROPIC_AUTH_PROVIDER_ID); + const storedCredential = authStorage.get(ANTHROPIC_AUTH_PROVIDER_ID); const hasManagedOAuth = storedCredential?.type === "oauth"; - - // If managed OAuth is past its expiry, give mastracode a chance to - // refresh it before downgrading status to "expired". Mastracode's - // getApiKey uses the stored refresh token via the anthropic provider. - if ( - storedCredential?.type === "oauth" && - typeof storedCredential.expires === "number" && - storedCredential.expires <= Date.now() - ) { - try { - await authStorage.getApiKey(ANTHROPIC_AUTH_PROVIDER_ID); - authStorage.reload(); - storedCredential = authStorage.get(ANTHROPIC_AUTH_PROVIDER_ID); - } catch (error) { - // Refresh failed; fall through to expired-state handling below. - console.warn( - "[chat-service] Anthropic OAuth refresh failed, falling back to expired state:", - error, - ); - } - } const configCredential = getAnthropicCredentialsFromConfig(); const keychainCredential = getAnthropicCredentialsFromKeychain(); const externalCandidates = [configCredential, keychainCredential].filter( @@ -617,7 +594,6 @@ export class ChatService { } clearCredentialForProvider(authStorage, providerId); - restoreApiKeyAfterOAuthDisconnect(authStorage, providerId); removedProviderIds.push(providerId); } this.logAuthResolution("openai", { @@ -631,9 +607,6 @@ export class ChatService { async completeOpenAIOAuth(input: { code?: string; }): Promise<{ success: true }> { - for (const providerId of OPENAI_AUTH_PROVIDER_IDS) { - backupApiKeyBeforeOAuth(this.getAuthStorage(), providerId); - } await this.oauthFlowController.complete( this.getOpenAIOAuthFlowOptions(), input.code, @@ -723,11 +696,6 @@ export class ChatService { const credential = authStorage.get(ANTHROPIC_AUTH_PROVIDER_ID); if (credential?.type === "oauth") { clearCredentialForProvider(authStorage, ANTHROPIC_AUTH_PROVIDER_ID); - // Restore API key from backup slot if one was saved before OAuth connect. - restoreApiKeyAfterOAuthDisconnect( - authStorage, - ANTHROPIC_AUTH_PROVIDER_ID, - ); const config = getAnthropicEnvConfigFromDisk({ configPath: this.anthropicEnvConfigPath, }); @@ -747,8 +715,6 @@ export class ChatService { async completeAnthropicOAuth(input: { code?: string; }): Promise<{ success: true; expiresAt: number }> { - // Save API key to backup slot before OAuth overwrites the main slot. - backupApiKeyBeforeOAuth(this.getAuthStorage(), ANTHROPIC_AUTH_PROVIDER_ID); const credential = await this.oauthFlowController.complete( this.getAnthropicOAuthFlowOptions(), input.code, @@ -813,7 +779,10 @@ export class ChatService { const authStorage = this.getAuthStorage(); authStorage.reload(); - authStorage.setStoredApiKey(ANTHROPIC_AUTH_PROVIDER_ID, apiKey); + authStorage.set(ANTHROPIC_AUTH_PROVIDER_ID, { + type: "api_key", + key: apiKey, + }); } private applyAnthropicRuntimeEnv(variables: AnthropicEnvVariables): void { diff --git a/packages/chat/src/server/desktop/index.ts b/packages/chat/src/server/desktop/index.ts index 06df62dddd6..39ee5ab0fb3 100644 --- a/packages/chat/src/server/desktop/index.ts +++ b/packages/chat/src/server/desktop/index.ts @@ -16,4 +16,13 @@ export { export { ChatService } from "./chat-service"; export type { ChatServiceRouter } from "./router"; export { createChatServiceRouter } from "./router"; -export { generateTitleFromMessage } from "./title-generation"; +export type { + SmallModelCredential, + SmallModelProvider, + SmallModelProviderId, +} from "./small-model"; +export { getDefaultSmallModelProviders } from "./small-model"; +export { + generateTitleFromMessage, + generateTitleFromMessageWithStreamingModel, +} from "./title-generation"; diff --git a/packages/chat/src/server/desktop/small-model/index.ts b/packages/chat/src/server/desktop/small-model/index.ts new file mode 100644 index 00000000000..70228ebbe29 --- /dev/null +++ b/packages/chat/src/server/desktop/small-model/index.ts @@ -0,0 +1,6 @@ +export type { + SmallModelCredential, + SmallModelProvider, + SmallModelProviderId, +} from "./small-model"; +export { getDefaultSmallModelProviders } from "./small-model"; diff --git a/packages/chat/src/server/desktop/small-model/small-model.test.ts b/packages/chat/src/server/desktop/small-model/small-model.test.ts new file mode 100644 index 00000000000..182d1468dea --- /dev/null +++ b/packages/chat/src/server/desktop/small-model/small-model.test.ts @@ -0,0 +1,391 @@ +import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test"; + +type MockOpenAICredentials = { + apiKey: string; + kind: "apiKey" | "oauth"; + source: string; + expiresAt?: number; + accountId?: string; + providerId?: string; +}; + +const createAnthropicModelMock = mock(() => "anthropic-default-model"); +let lastCreateOpenAIOptions: { fetch?: typeof fetch } | undefined; +const createOpenAIMock = mock((options?: { fetch?: typeof fetch }) => { + lastCreateOpenAIOptions = options; + return Object.assign(createOpenAIResponsesModelMock, { + chat: createOpenAIChatModelMock, + responses: createOpenAIResponsesModelMock, + }); +}); +const createOpenAIResponsesModelMock = mock( + () => "openai-default-responses-model", +); +const createOpenAIChatModelMock = mock(() => "openai-default-chat-model"); +const getAnthropicCredentialsFromAnySourceMock = mock(() => null); +const getAnthropicProviderOptionsMock = mock(() => ({ apiKey: "unused" })); +const getOpenAICredentialsFromAnySourceMock = mock( + (() => null) as () => MockOpenAICredentials | null, +); +const getOpenAICredentialsFromAuthStorageMock = mock( + (authStorage?: { + reload: () => void; + get: (providerId: string) => + | { + type: "api_key"; + key: string; + } + | { + type: "oauth"; + access: string; + expires?: number; + accountId?: string; + } + | undefined; + }): MockOpenAICredentials | null => { + const storage = authStorage ?? fakeAuthStorage; + storage.reload(); + + const credentials = ["openai-codex", "openai"] + .map((providerId) => { + const credential = storage.get(providerId); + if (!credential) { + return null; + } + + if (credential.type === "api_key" && credential.key.trim()) { + return { + apiKey: credential.key.trim(), + kind: "apiKey" as const, + source: "auth-storage", + providerId, + }; + } + + if (credential.type === "oauth" && credential.access.trim()) { + return { + apiKey: credential.access.trim(), + kind: "oauth" as const, + source: "auth-storage", + expiresAt: credential.expires, + accountId: credential.accountId?.trim() || undefined, + providerId, + }; + } + + return null; + }) + .filter( + (credential): credential is MockOpenAICredentials => + credential !== null, + ); + + return ( + credentials.find( + (credential) => + credential.kind !== "oauth" || + typeof credential.expiresAt !== "number" || + Date.now() < credential.expiresAt, + ) ?? + credentials[0] ?? + null + ); + }, +); +const fakeAuthStorage = { + reload: mock(() => {}), + get: mock(() => undefined), + getApiKey: mock(async () => null), +}; +const originalFetch = globalThis.fetch; +const fetchMock = mock(async () => new Response(null, { status: 200 })); + +mock.module("@ai-sdk/anthropic", () => ({ + createAnthropic: mock(() => createAnthropicModelMock), +})); + +mock.module("@ai-sdk/openai", () => ({ + createOpenAI: createOpenAIMock, +})); + +mock.module("mastracode", () => ({ + createAuthStorage: mock(() => fakeAuthStorage), + createMastraCode: mock(async () => ({ + harness: {}, + mcpManager: null, + hookManager: null, + authStorage: null, + storageWarning: undefined, + })), +})); + +mock.module("../auth/anthropic", () => ({ + getCredentialsFromAnySource: getAnthropicCredentialsFromAnySourceMock, + getCredentialsFromAuthStorage: () => null, + getCredentialsFromConfig: () => null, + getCredentialsFromKeychain: () => null, + getAnthropicProviderOptions: getAnthropicProviderOptionsMock, + isClaudeCredentialExpired: () => false, + createAnthropicOAuthSession: () => {}, + exchangeAnthropicAuthorizationCode: () => {}, +})); + +mock.module("../auth/openai", () => ({ + getOpenAICredentialsFromAnySource: getOpenAICredentialsFromAnySourceMock, + getOpenAICredentialsFromAuthStorage: getOpenAICredentialsFromAuthStorageMock, + isOpenAICredentialExpired: (credential: { + kind: "apiKey" | "oauth"; + expiresAt?: number; + }) => + credential.kind === "oauth" && + typeof credential.expiresAt === "number" && + Date.now() >= credential.expiresAt, +})); + +const { getDefaultSmallModelProviders } = await import("./small-model"); + +describe("getDefaultSmallModelProviders", () => { + beforeEach(() => { + getAnthropicCredentialsFromAnySourceMock.mockReturnValue(null); + getOpenAICredentialsFromAnySourceMock.mockReturnValue(null); + getAnthropicProviderOptionsMock.mockClear(); + createAnthropicModelMock.mockClear(); + createOpenAIMock.mockClear(); + getOpenAICredentialsFromAuthStorageMock.mockClear(); + lastCreateOpenAIOptions = undefined; + createOpenAIResponsesModelMock.mockClear(); + createOpenAIChatModelMock.mockClear(); + fakeAuthStorage.reload.mockClear(); + fakeAuthStorage.get.mockClear(); + fakeAuthStorage.getApiKey.mockClear(); + fakeAuthStorage.get.mockReturnValue(undefined); + fakeAuthStorage.getApiKey.mockResolvedValue(null); + fetchMock.mockClear(); + globalThis.fetch = fetchMock as typeof fetch; + }); + + afterEach(() => { + globalThis.fetch = originalFetch; + }); + + it("uses the OpenAI Codex OAuth model path for OAuth credentials", async () => { + getOpenAICredentialsFromAnySourceMock.mockReturnValue({ + apiKey: "openai-key", + kind: "oauth", + source: "auth-storage", + accountId: "chatgpt-account", + providerId: "openai-codex", + }); + fakeAuthStorage.get.mockReturnValue({ + type: "oauth", + access: "oauth-access-token", + accountId: "chatgpt-account", + }); + + const openAIProvider = getDefaultSmallModelProviders().find( + (provider) => provider.id === "openai", + ); + + expect(openAIProvider).toBeDefined(); + const credentials = openAIProvider?.resolveCredentials(); + expect(credentials).toEqual({ + apiKey: "openai-key", + kind: "oauth", + source: "auth-storage", + accountId: "chatgpt-account", + providerId: "openai-codex", + }); + if (!openAIProvider || !credentials) { + throw new Error("OpenAI provider should resolve OAuth credentials"); + } + + const model = await openAIProvider.createModel(credentials); + + expect(model).toBe("openai-default-responses-model"); + expect(createOpenAIResponsesModelMock).toHaveBeenCalledWith( + "gpt-5.1-codex-mini", + ); + expect(createOpenAIChatModelMock).not.toHaveBeenCalled(); + }); + + it("uses the resolved OpenAI provider id for the OAuth transport", async () => { + getOpenAICredentialsFromAnySourceMock.mockReturnValue({ + apiKey: "legacy-openai-key", + kind: "oauth", + source: "auth-storage", + providerId: "openai", + }); + fakeAuthStorage.get.mockImplementation((providerId: string) => { + if (providerId !== "openai") { + return undefined; + } + + return { + type: "oauth", + access: "legacy-openai-access", + }; + }); + + const openAIProvider = getDefaultSmallModelProviders().find( + (provider) => provider.id === "openai", + ); + if (!openAIProvider) { + throw new Error("OpenAI provider should exist"); + } + + const credentials = openAIProvider.resolveCredentials(); + if (!credentials) { + throw new Error("OpenAI provider should resolve OAuth credentials"); + } + + await openAIProvider.createModel(credentials); + + const oauthFetch = lastCreateOpenAIOptions?.fetch; + if (!oauthFetch) { + throw new Error("OpenAI OAuth provider should pass a fetch override"); + } + await oauthFetch("https://api.openai.com/v1/responses", { + headers: { + Authorization: "Bearer should-be-replaced", + }, + }); + + expect(fakeAuthStorage.get).toHaveBeenCalledWith("openai"); + expect(fakeAuthStorage.get).not.toHaveBeenCalledWith("openai-codex"); + }); + + it("preserves Request details when rewriting the OpenAI OAuth transport", async () => { + getOpenAICredentialsFromAnySourceMock.mockReturnValue({ + apiKey: "openai-key", + kind: "oauth", + source: "auth-storage", + accountId: "chatgpt-account", + providerId: "openai-codex", + }); + fakeAuthStorage.get.mockReturnValue({ + type: "oauth", + access: "oauth-access-token", + accountId: "chatgpt-account", + }); + + const openAIProvider = getDefaultSmallModelProviders().find( + (provider) => provider.id === "openai", + ); + if (!openAIProvider) { + throw new Error("OpenAI provider should exist"); + } + + const credentials = openAIProvider.resolveCredentials(); + if (!credentials) { + throw new Error("OpenAI provider should resolve OAuth credentials"); + } + + await openAIProvider.createModel(credentials); + + const oauthFetch = lastCreateOpenAIOptions?.fetch; + if (!oauthFetch) { + throw new Error("OpenAI OAuth provider should pass a fetch override"); + } + + const abortController = new AbortController(); + const request = new Request("https://api.openai.com/v1/responses", { + method: "POST", + body: JSON.stringify({ prompt: "name this workspace" }), + headers: { + "Content-Type": "application/json", + "X-Test-Header": "present", + Authorization: "Bearer should-be-replaced", + }, + signal: abortController.signal, + }); + + await oauthFetch(request); + + const [forwardedRequest] = fetchMock.mock.calls.at(-1) ?? []; + expect(forwardedRequest).toBeInstanceOf(Request); + if (!(forwardedRequest instanceof Request)) { + throw new Error("fetch should receive a rewritten Request"); + } + + expect(forwardedRequest.url).toBe( + "https://chatgpt.com/backend-api/codex/responses", + ); + expect(forwardedRequest.method).toBe("POST"); + expect(await forwardedRequest.clone().text()).toBe( + JSON.stringify({ prompt: "name this workspace" }), + ); + expect(forwardedRequest.headers.get("content-type")).toBe( + "application/json", + ); + expect(forwardedRequest.headers.get("x-test-header")).toBe("present"); + expect(forwardedRequest.headers.get("authorization")).toBe( + "Bearer oauth-access-token", + ); + expect(forwardedRequest.headers.get("chatgpt-account-id")).toBe( + "chatgpt-account", + ); + expect(forwardedRequest.signal).toBe(abortController.signal); + }); + + it("uses the OpenAI chat model path for API key credentials", async () => { + getOpenAICredentialsFromAnySourceMock.mockReturnValue({ + apiKey: "openai-key", + kind: "apiKey", + source: "auth-storage", + providerId: "openai-codex", + }); + + const openAIProvider = getDefaultSmallModelProviders().find( + (provider) => provider.id === "openai", + ); + + expect(openAIProvider).toBeDefined(); + const credentials = openAIProvider?.resolveCredentials(); + expect(credentials).toEqual({ + apiKey: "openai-key", + kind: "apiKey", + source: "auth-storage", + providerId: "openai-codex", + }); + if (!openAIProvider || !credentials) { + throw new Error("OpenAI provider should resolve API key credentials"); + } + + const model = await openAIProvider.createModel(credentials); + + expect(model).toBe("openai-default-chat-model"); + expect(createOpenAIChatModelMock).toHaveBeenCalledWith("gpt-4o-mini"); + expect(createOpenAIResponsesModelMock).not.toHaveBeenCalled(); + }); + + it("uses the Anthropic provider path for supported credentials", async () => { + getAnthropicCredentialsFromAnySourceMock.mockReturnValue({ + apiKey: "anthropic-key", + kind: "apiKey", + source: "config", + }); + + const anthropicProvider = getDefaultSmallModelProviders().find( + (provider) => provider.id === "anthropic", + ); + + expect(anthropicProvider).toBeDefined(); + const credentials = anthropicProvider?.resolveCredentials(); + expect(credentials).toEqual({ + apiKey: "anthropic-key", + kind: "apiKey", + source: "config", + }); + if (!anthropicProvider || !credentials) { + throw new Error("Anthropic provider should resolve credentials"); + } + + const model = await anthropicProvider.createModel(credentials); + + expect(model).toBe("anthropic-default-model"); + expect(getAnthropicProviderOptionsMock).toHaveBeenCalledWith(credentials); + expect(createAnthropicModelMock).toHaveBeenCalledWith( + "claude-haiku-4-5-20251001", + ); + }); +}); diff --git a/packages/chat/src/server/desktop/small-model/small-model.ts b/packages/chat/src/server/desktop/small-model/small-model.ts new file mode 100644 index 00000000000..43434cbef51 --- /dev/null +++ b/packages/chat/src/server/desktop/small-model/small-model.ts @@ -0,0 +1,146 @@ +import { createAnthropic } from "@ai-sdk/anthropic"; +import { createOpenAI } from "@ai-sdk/openai"; +import { createAuthStorage } from "mastracode"; +import { + type ClaudeCredentials, + getCredentialsFromAnySource as getAnthropicCredentialsFromAnySource, + getAnthropicProviderOptions, +} from "../auth/anthropic"; +import { + getOpenAICredentialsFromAnySource, + type OpenAICredentials, +} from "../auth/openai"; +import { OPENAI_AUTH_PROVIDER_ID } from "../auth/provider-ids"; + +export type SmallModelProviderId = "anthropic" | "openai"; + +export interface SmallModelCredential { + apiKey: string; + kind: "apiKey" | "oauth"; + source: string; + expiresAt?: number; + accountId?: string; + providerId?: string; +} + +export interface SmallModelProvider { + id: SmallModelProviderId; + name: string; + resolveCredentials: () => SmallModelCredential | null; + isSupported: (credentials: SmallModelCredential) => { + supported: boolean; + reason?: string; + }; + createModel: ( + credentials: SmallModelCredential, + ) => unknown | Promise; +} + +const OPENAI_CODEX_API_ENDPOINT = + "https://chatgpt.com/backend-api/codex/responses"; +const OPENAI_CODEX_SMALL_MODEL_ID = "gpt-5.1-codex-mini"; +const OPENAI_API_SMALL_MODEL_ID = "gpt-4o-mini"; + +function createOpenAICodexOAuthModel(credentials: OpenAICredentials) { + const authStorage = createAuthStorage(); + const openAIAuthProviderId = + credentials.providerId ?? OPENAI_AUTH_PROVIDER_ID; + const oauthFetchImpl = async ( + url: Parameters[0], + init?: Parameters[1], + ): Promise => { + authStorage.reload(); + const storedCredential = authStorage.get(openAIAuthProviderId); + if (!storedCredential || storedCredential.type !== "oauth") { + throw new Error("Not logged in to OpenAI Codex. Reconnect OpenAI."); + } + + let accessToken = storedCredential.access; + if ( + typeof storedCredential.expires === "number" && + Date.now() >= storedCredential.expires + ) { + const refreshedToken = await authStorage.getApiKey(openAIAuthProviderId); + if (!refreshedToken) { + throw new Error( + "Failed to refresh OpenAI Codex token. Please reconnect OpenAI.", + ); + } + accessToken = refreshedToken; + authStorage.reload(); + } + + const refreshedCredential = authStorage.get(openAIAuthProviderId); + const accountId = + refreshedCredential && + typeof refreshedCredential === "object" && + "accountId" in refreshedCredential && + typeof refreshedCredential.accountId === "string" && + refreshedCredential.accountId.trim().length > 0 + ? refreshedCredential.accountId.trim() + : credentials.accountId?.trim() || undefined; + + const baseRequest = new Request(url, init); + const parsedUrl = new URL(baseRequest.url); + const shouldRewrite = + parsedUrl.pathname.includes("/v1/responses") || + parsedUrl.pathname.includes("/chat/completions"); + const outgoingRequest = new Request( + shouldRewrite ? OPENAI_CODEX_API_ENDPOINT : baseRequest.url, + baseRequest, + ); + const headers = new Headers(outgoingRequest.headers); + headers.delete("authorization"); + headers.set("Authorization", `Bearer ${accessToken}`); + if (accountId) { + headers.set("ChatGPT-Account-Id", accountId); + } + + return fetch( + new Request(outgoingRequest, { + headers, + }), + ); + }; + const bunFetch = globalThis.fetch as typeof fetch & { + preconnect?: typeof globalThis.fetch; + }; + const oauthFetch = Object.assign( + oauthFetchImpl, + typeof bunFetch.preconnect === "function" + ? { preconnect: bunFetch.preconnect.bind(globalThis.fetch) } + : {}, + ) as typeof fetch; + + return createOpenAI({ + apiKey: "oauth-dummy-key", + fetch: oauthFetch, + }).responses(OPENAI_CODEX_SMALL_MODEL_ID); +} + +export function getDefaultSmallModelProviders(): SmallModelProvider[] { + return [ + { + id: "anthropic", + name: "Anthropic", + resolveCredentials: () => getAnthropicCredentialsFromAnySource(), + isSupported: () => ({ supported: true }), + createModel: (credentials) => + createAnthropic( + getAnthropicProviderOptions(credentials as ClaudeCredentials), + )("claude-haiku-4-5-20251001"), + }, + { + id: "openai", + name: "OpenAI", + resolveCredentials: () => getOpenAICredentialsFromAnySource(), + isSupported: () => ({ supported: true }), + createModel: (credentials) => + credentials.kind === "oauth" + ? createOpenAICodexOAuthModel(credentials as OpenAICredentials) + : createOpenAI({ apiKey: credentials.apiKey }).chat( + OPENAI_API_SMALL_MODEL_ID, + ), + }, + ]; +} diff --git a/packages/chat/src/server/desktop/title-generation/index.ts b/packages/chat/src/server/desktop/title-generation/index.ts index 5dcc0b3bf42..9a47fa5ef81 100644 --- a/packages/chat/src/server/desktop/title-generation/index.ts +++ b/packages/chat/src/server/desktop/title-generation/index.ts @@ -1 +1,4 @@ -export { generateTitleFromMessage } from "./title-generation"; +export { + generateTitleFromMessage, + generateTitleFromMessageWithStreamingModel, +} from "./title-generation"; diff --git a/packages/chat/src/server/desktop/title-generation/title-generation.test.ts b/packages/chat/src/server/desktop/title-generation/title-generation.test.ts new file mode 100644 index 00000000000..f58d11b8206 --- /dev/null +++ b/packages/chat/src/server/desktop/title-generation/title-generation.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, it, mock } from "bun:test"; + +const streamTextMock = mock(() => ({ + text: Promise.resolve(" Checking In "), +})); + +mock.module("ai", () => ({ + streamText: streamTextMock, +})); + +const { generateTitleFromMessageWithStreamingModel } = await import( + "./title-generation" +); + +describe("generateTitleFromMessageWithStreamingModel", () => { + it("streams a title with Codex-compatible provider options", async () => { + const title = await generateTitleFromMessageWithStreamingModel({ + message: " hey boss how are you ", + model: { id: "test-model" } as never, + instructions: "You generate concise workspace titles.", + }); + + expect(title).toBe("Checking In"); + expect(streamTextMock).toHaveBeenCalledWith({ + model: { id: "test-model" }, + system: "You generate concise workspace titles.", + prompt: + "Return only a short title for this user message:\nhey boss how are you", + providerOptions: { + openai: { + instructions: "You generate concise workspace titles.", + store: false, + }, + }, + }); + }); +}); diff --git a/packages/chat/src/server/desktop/title-generation/title-generation.ts b/packages/chat/src/server/desktop/title-generation/title-generation.ts index 94f3ab23dfe..25073636d2c 100644 --- a/packages/chat/src/server/desktop/title-generation/title-generation.ts +++ b/packages/chat/src/server/desktop/title-generation/title-generation.ts @@ -1,3 +1,5 @@ +import { type LanguageModel, streamText } from "ai"; + type TitleModel = unknown; type TitleAgent = { generateTitleFromUserMessage: (args: { @@ -69,3 +71,29 @@ export async function generateTitleFromMessage( return title?.trim() || null; } + +export async function generateTitleFromMessageWithStreamingModel(params: { + message: string; + model: LanguageModel; + instructions?: string; +}): Promise { + const cleanedMessage = params.message.trim(); + if (!cleanedMessage) { + return null; + } + + const instructions = params.instructions ?? "You generate concise titles."; + const result = streamText({ + model: params.model, + system: instructions, + prompt: `Return only a short title for this user message:\n${cleanedMessage}`, + providerOptions: { + openai: { + instructions, + store: false, + }, + }, + }); + + return (await result.text).trim() || null; +} diff --git a/packages/chat/src/server/shared/index.ts b/packages/chat/src/server/shared/index.ts deleted file mode 100644 index c54241172f5..00000000000 --- a/packages/chat/src/server/shared/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { - getSmallModel, - getSmallModelCandidates, - type SmallModelCandidate, - type SmallModelProviderId, -} from "./small-model"; diff --git a/packages/chat/src/server/shared/small-model/get-small-model.ts b/packages/chat/src/server/shared/small-model/get-small-model.ts deleted file mode 100644 index 8810b06fe95..00000000000 --- a/packages/chat/src/server/shared/small-model/get-small-model.ts +++ /dev/null @@ -1,349 +0,0 @@ -import { existsSync, readFileSync } from "node:fs"; -import { homedir } from "node:os"; -import { join } from "node:path"; -import { createAnthropic } from "@ai-sdk/anthropic"; -import { createOpenAI } from "@ai-sdk/openai"; -import { createAuthStorage } from "mastracode"; -import { - type ClaudeCredentials, - getCredentialsFromConfig as getAnthropicCredentialsFromConfig, - getCredentialsFromKeychain as getAnthropicCredentialsFromKeychain, - getAnthropicProviderOptions, - isClaudeCredentialExpired, -} from "../../desktop/auth/anthropic"; -import { - getOpenAICredentialsFromAnySource, - isOpenAICredentialExpired, - type OpenAICredentials, -} from "../../desktop/auth/openai"; -import { OPENAI_AUTH_PROVIDER_ID } from "../../desktop/auth/provider-ids"; -import { parseAnthropicEnvText } from "../../desktop/chat-service/anthropic-env-config"; - -const ANTHROPIC_SMALL_MODEL_ID = "claude-haiku-4-5-20251001"; -const OPENAI_API_SMALL_MODEL_ID = "gpt-4o-mini"; -const OPENAI_CODEX_SMALL_MODEL_ID = "gpt-5.1-codex-mini"; -const OPENAI_CODEX_API_ENDPOINT = - "https://chatgpt.com/backend-api/codex/responses"; - -export type SmallModelProviderId = "anthropic" | "openai"; - -export interface SmallModelCandidate { - providerId: SmallModelProviderId; - providerName: string; - credentialKind: "apiKey" | "oauth"; - credentialSource: string; - createModel: () => unknown; -} - -/** - * FORK NOTE: ported from upstream #3517's `getSmallModel()` but rebuilt - * on top of fork's credential resolvers so it still honors: - * - Anthropic OAuth (claude-code-20250219 / oauth-2025-04-20 headers via - * getAnthropicProviderOptions — upstream lost this when it switched to - * apiKey-only resolution) - * - Anthropic managed env config (~/.superset/chat-anthropic-env.json - * with ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN; AUTH_TOKEN is - * routed through the OAuth header path, not apiKey) - * - OpenAI Codex OAuth (custom fetch that rewrites to the Codex - * backend endpoint and refreshes access tokens via mastracode) - * - OpenAI API key in mastracode AuthStorage's `openai-codex` slot - * - * Upstream's version collapsed credentials to apiKey-only. We keep the - * simpler `getSmallModel()` export for upstream-compatible callers - * (runtime.ts title generation) and add `getSmallModelCandidates()` so - * the fork callSmallModel shim can iterate providers in order and - * record attempts properly (restoring provider fallback behavior). - */ -function buildCandidates(): SmallModelCandidate[] { - const candidates: SmallModelCandidate[] = []; - - const envApiKey = process.env.ANTHROPIC_API_KEY?.trim(); - if (envApiKey) { - candidates.push({ - providerId: "anthropic", - providerName: "Anthropic", - credentialKind: "apiKey", - credentialSource: "env:ANTHROPIC_API_KEY", - createModel: () => - createAnthropic({ apiKey: envApiKey })(ANTHROPIC_SMALL_MODEL_ID), - }); - } - - const anthropicStored = resolveAnthropicCredentialsSync(); - if (anthropicStored) { - candidates.push({ - providerId: "anthropic", - providerName: "Anthropic", - credentialKind: anthropicStored.kind === "oauth" ? "oauth" : "apiKey", - credentialSource: anthropicStored.source, - createModel: () => - createAnthropic(getAnthropicProviderOptions(anthropicStored))( - ANTHROPIC_SMALL_MODEL_ID, - ), - }); - } - - const anthropicEnvConfigCred = resolveAnthropicEnvConfigCredential(); - if (anthropicEnvConfigCred) { - candidates.push({ - providerId: "anthropic", - providerName: "Anthropic", - credentialKind: - anthropicEnvConfigCred.kind === "oauth" ? "oauth" : "apiKey", - credentialSource: anthropicEnvConfigCred.source, - createModel: () => - createAnthropic(getAnthropicProviderOptions(anthropicEnvConfigCred))( - ANTHROPIC_SMALL_MODEL_ID, - ), - }); - } - - const envOpenAIKey = process.env.OPENAI_API_KEY?.trim(); - if (envOpenAIKey) { - candidates.push({ - providerId: "openai", - providerName: "OpenAI", - credentialKind: "apiKey", - credentialSource: "env:OPENAI_API_KEY", - createModel: () => - createOpenAI({ apiKey: envOpenAIKey }).chat(OPENAI_API_SMALL_MODEL_ID), - }); - } - - const openaiCreds = getOpenAICredentialsFromAnySource(); - if (openaiCreds && !isOpenAICredentialExpired(openaiCreds)) { - candidates.push({ - providerId: "openai", - providerName: "OpenAI", - credentialKind: openaiCreds.kind === "oauth" ? "oauth" : "apiKey", - credentialSource: openaiCreds.source, - createModel: () => - openaiCreds.kind === "oauth" - ? createOpenAICodexOAuthModel(openaiCreds) - : createOpenAI({ apiKey: openaiCreds.apiKey }).chat( - OPENAI_API_SMALL_MODEL_ID, - ), - }); - } - - return candidates; -} - -export function getSmallModelCandidates(): SmallModelCandidate[] { - return buildCandidates(); -} - -/** - * Returns the first viable small-model AI-SDK LanguageModel or null. - * Upstream-compatible surface for simple single-model callers - * (runtime.ts title generation, ai-name.ts workspace naming). - * - * Iterates every candidate and returns the first one whose - * `createModel()` does not throw, so a broken-but-listed credential - * (e.g. stale cached account id) doesn't block the next provider. - * Runtime-level failures (expired OAuth 401, rate limits) still need - * to be handled by the caller — those surface when the returned - * model is actually invoked, not when it's constructed. - */ -export function getSmallModel(): unknown | null { - for (const candidate of buildCandidates()) { - try { - return candidate.createModel(); - } catch { - // Try the next candidate. - } - } - return null; -} - -// ---- Anthropic credential resolution helpers ------------------------------- - -/** - * Synchronous Anthropic credential resolver. Fork's - * `getCredentialsFromAnySource` is async because it may kick a - * mastracode token refresh. For the small-model candidate list we need - * a sync decision, so we stick to synchronous sources (config file, - * keychain, auth-storage main slot). If the resulting OAuth token is - * actually expired, createAnthropic will 401 and the shim falls - * through to the next candidate. - */ -function resolveAnthropicCredentialsSync(): ClaudeCredentials | null { - // Walk the sync sources in priority order and return the first - // non-expired credential. Unlike getCredentialsFromAnySource() we do - // NOT fall back to a known-expired credential at the end — expired - // OAuth tokens would poison buildCandidates() and block the later - // env-config / OpenAI candidates, which matter for getSmallModel()'s - // direct callers where we can't retry after a 401. - const sources: Array<() => ClaudeCredentials | null> = [ - () => { - try { - return getAnthropicCredentialsFromConfig(); - } catch { - return null; - } - }, - () => { - try { - return getAnthropicCredentialsFromKeychain(); - } catch { - return null; - } - }, - () => resolveAnthropicFromStoreSync(), - ]; - for (const resolve of sources) { - const credential = resolve(); - if (!credential) continue; - if (!isClaudeCredentialExpired(credential)) return credential; - } - return null; -} - -function resolveAnthropicFromStoreSync(): ClaudeCredentials | null { - try { - const storage = createAuthStorage(); - storage.reload(); - const raw = storage.get("anthropic"); - if (!raw || typeof raw !== "object") return null; - const value = raw as Record; - if ( - value.type === "api_key" && - typeof value.key === "string" && - value.key.trim().length > 0 - ) { - return { - apiKey: value.key.trim(), - source: "auth-storage", - kind: "apiKey", - }; - } - if ( - value.type === "oauth" && - typeof value.access === "string" && - value.access.trim().length > 0 - ) { - return { - apiKey: value.access.trim(), - source: "auth-storage", - kind: "oauth", - expiresAt: - typeof value.expires === "number" ? value.expires : undefined, - }; - } - } catch { - // Fall through to null. - } - return null; -} - -function resolveAnthropicEnvConfigCredential(): ClaudeCredentials | null { - try { - const supersetHome = - process.env.SUPERSET_HOME_DIR?.trim() || join(homedir(), ".superset"); - const path = join(supersetHome, "chat-anthropic-env.json"); - if (!existsSync(path)) return null; - const parsed = JSON.parse(readFileSync(path, "utf-8")) as { - envText?: string; - }; - if (typeof parsed.envText !== "string") return null; - const variables = parseAnthropicEnvText(parsed.envText); - const apiKey = variables.ANTHROPIC_API_KEY?.trim(); - if (apiKey) { - // `source: "config"` keeps us inside fork's ClaudeCredentials - // union; the actual display label comes from - // SmallModelCandidate.credentialSource below. - return { apiKey, source: "config", kind: "apiKey" }; - } - const authToken = variables.ANTHROPIC_AUTH_TOKEN?.trim(); - if (authToken) { - // FORK NOTE: AUTH_TOKEN must flow through the OAuth path - // (authToken + anthropic-beta / x-app headers) — routing it - // through `apiKey` was the original PR #313 regression. - return { apiKey: authToken, source: "config", kind: "oauth" }; - } - } catch { - // Swallow — missing / malformed config falls back to other sources. - } - return null; -} - -// ---- OpenAI Codex OAuth model ---------------------------------------------- - -function createOpenAICodexOAuthModel(credentials: OpenAICredentials) { - const authStorage = createAuthStorage(); - const openAIAuthProviderId = - credentials.providerId ?? OPENAI_AUTH_PROVIDER_ID; - const oauthFetchImpl = async ( - url: Parameters[0], - init?: Parameters[1], - ): Promise => { - authStorage.reload(); - const storedCredential = authStorage.get(openAIAuthProviderId); - if (!storedCredential || storedCredential.type !== "oauth") { - throw new Error("Not logged in to OpenAI Codex. Reconnect OpenAI."); - } - - let accessToken = storedCredential.access; - if ( - typeof storedCredential.expires === "number" && - Date.now() >= storedCredential.expires - ) { - const refreshedToken = await authStorage.getApiKey(openAIAuthProviderId); - if (!refreshedToken) { - throw new Error( - "Failed to refresh OpenAI Codex token. Please reconnect OpenAI.", - ); - } - accessToken = refreshedToken; - authStorage.reload(); - } - - const refreshedCredential = authStorage.get(openAIAuthProviderId); - const accountId = - refreshedCredential && - typeof refreshedCredential === "object" && - "accountId" in refreshedCredential && - typeof refreshedCredential.accountId === "string" && - refreshedCredential.accountId.trim().length > 0 - ? refreshedCredential.accountId.trim() - : credentials.accountId?.trim() || undefined; - - // biome-ignore-start lint/suspicious/noExplicitAny: fetch signature varies across runtimes (bun vs. node vs. electron) and the cross-package typecheck context loses the DOM Request type overloads. - const baseRequest = new Request(url as any, init as any); - // biome-ignore-end lint/suspicious/noExplicitAny: matching pair - const parsedUrl = new URL(baseRequest.url); - const shouldRewrite = - parsedUrl.pathname.includes("/v1/responses") || - parsedUrl.pathname.includes("/chat/completions"); - const outgoingRequest = new Request( - shouldRewrite ? OPENAI_CODEX_API_ENDPOINT : baseRequest.url, - baseRequest, - ); - const headers = new Headers(outgoingRequest.headers); - headers.delete("authorization"); - headers.set("Authorization", `Bearer ${accessToken}`); - if (accountId) { - headers.set("ChatGPT-Account-Id", accountId); - } - - return fetch( - new Request(outgoingRequest, { - headers, - }), - ); - }; - const bunFetch = globalThis.fetch as typeof fetch & { - preconnect?: typeof globalThis.fetch; - }; - const oauthFetch = Object.assign( - oauthFetchImpl, - typeof bunFetch.preconnect === "function" - ? { preconnect: bunFetch.preconnect.bind(globalThis.fetch) } - : {}, - ) as typeof fetch; - - return createOpenAI({ - apiKey: "oauth-dummy-key", - fetch: oauthFetch, - }).responses(OPENAI_CODEX_SMALL_MODEL_ID); -} diff --git a/packages/chat/src/server/shared/small-model/index.ts b/packages/chat/src/server/shared/small-model/index.ts deleted file mode 100644 index d2b53f46e8e..00000000000 --- a/packages/chat/src/server/shared/small-model/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { - getSmallModel, - getSmallModelCandidates, - type SmallModelCandidate, - type SmallModelProviderId, -} from "./get-small-model"; diff --git a/packages/chat/src/server/trpc/utils/runtime/runtime.test.ts b/packages/chat/src/server/trpc/utils/runtime/runtime.test.ts index fdac90bd49b..5a15c0534bf 100644 --- a/packages/chat/src/server/trpc/utils/runtime/runtime.test.ts +++ b/packages/chat/src/server/trpc/utils/runtime/runtime.test.ts @@ -1,27 +1,33 @@ import { describe, expect, it, mock } from "bun:test"; import type { RuntimeSession } from "./runtime"; -let generateTitleFromMessageResult = ""; - -const generateTitleFromMessageMock = mock( - (async (_params: { - message: string; - agentModel?: unknown; - agent?: unknown; - modelId?: string; - }) => generateTitleFromMessageResult) as ( +let generateTitleFromMessageWithStreamingModelResult = ""; + +const generateTitleFromMessageWithStreamingModelMock = mock( + (async (_params: { message: string; model: unknown }) => + generateTitleFromMessageWithStreamingModelResult) as ( args: unknown, - ) => Promise, + ) => Promise, ); -const getSmallModelMock = mock(() => ({}) as unknown); +const getDefaultSmallModelProvidersMock = mock(() => [ + { + id: "mock", + name: "Mock", + resolveCredentials: () => ({ + apiKey: "test", + kind: "apiKey", + source: "test", + }), + isSupported: () => ({ supported: true }), + createModel: () => ({}), + }, +]); mock.module("../../../desktop", () => ({ - generateTitleFromMessage: generateTitleFromMessageMock, -})); - -mock.module("../../../shared/small-model", () => ({ - getSmallModel: getSmallModelMock, + generateTitleFromMessageWithStreamingModel: + generateTitleFromMessageWithStreamingModelMock, + getDefaultSmallModelProviders: getDefaultSmallModelProvidersMock, })); const { @@ -90,7 +96,7 @@ function createRuntimeForTitleTest(options?: { const generatedTitle = options?.generatedTitle ?? ""; // Set the mock return value for this test - generateTitleFromMessageResult = generatedTitle; + generateTitleFromMessageWithStreamingModelResult = generatedTitle; const runtime: RuntimeSession = { sessionId: "11111111-1111-1111-1111-111111111111", diff --git a/packages/chat/src/server/trpc/utils/runtime/runtime.ts b/packages/chat/src/server/trpc/utils/runtime/runtime.ts index e4a012ed135..b32b1aea23e 100644 --- a/packages/chat/src/server/trpc/utils/runtime/runtime.ts +++ b/packages/chat/src/server/trpc/utils/runtime/runtime.ts @@ -1,8 +1,10 @@ import type { AppRouter } from "@superset/trpc"; import type { createTRPCClient } from "@trpc/client"; import type { createMastraCode } from "mastracode"; -import { generateTitleFromMessage } from "../../../desktop"; -import { getSmallModel } from "../../../shared/small-model"; +import { + generateTitleFromMessageWithStreamingModel, + getDefaultSmallModelProviders, +} from "../../../desktop"; import type { ThinkingLevel } from "../../zod"; const SUBAGENT_AGENT_TYPES = ["explore", "plan", "execute"] as const; @@ -510,21 +512,31 @@ export async function generateAndSetTitle( // Use a small model for title generation instead of the chat model, // because the chat model may use OAuth auth that isn't accessible via // process.env API keys (e.g. OpenAI Codex OAuth). - const model = getSmallModel(); - if (!model) return; - try { - const title = await generateTitleFromMessage({ - message: text, - agentModel: model, - }); - if (!title?.trim()) return; - - await apiClient.chat.updateTitle.mutate({ - sessionId: runtime.sessionId, - title: title.trim(), - }); - } catch (error) { - console.warn("[chat] Title generation failed:", error); + const providers = getDefaultSmallModelProviders(); + for (const provider of providers) { + const creds = provider.resolveCredentials(); + if (!creds) continue; + const { supported } = provider.isSupported(creds); + if (!supported) continue; + try { + const model = await provider.createModel(creds); + const title = await generateTitleFromMessageWithStreamingModel({ + message: text, + model: model as import("ai").LanguageModel, + }); + if (!title?.trim()) return; + + await apiClient.chat.updateTitle.mutate({ + sessionId: runtime.sessionId, + title: title.trim(), + }); + return; + } catch (error) { + console.warn( + `[chat] Title generation failed with ${provider.id}, trying next provider:`, + error, + ); + } } } catch (error) { console.warn("[chat] Title generation failed:", error); diff --git a/packages/host-service/package.json b/packages/host-service/package.json index 79d5371e02a..f3c646681e4 100644 --- a/packages/host-service/package.json +++ b/packages/host-service/package.json @@ -45,7 +45,6 @@ "@hono/node-ws": "^1.3.0", "@hono/trpc-server": "^0.3.4", "@octokit/rest": "^22.0.1", - "@superset/chat": "workspace:*", "@superset/shared": "workspace:*", "@superset/trpc": "workspace:*", "@superset/workspace-fs": "workspace:*", @@ -55,7 +54,7 @@ "better-sqlite3": "12.6.2", "drizzle-orm": "0.45.1", "hono": "^4.8.5", - "mastracode": "0.14.0", + "mastracode": "0.9.2", "node-pty": "1.1.0", "simple-git": "^3.30.0", "superjson": "^2.2.5", diff --git a/packages/host-service/src/providers/model-providers/LocalModelProvider/LocalModelProvider.ts b/packages/host-service/src/providers/model-providers/LocalModelProvider/LocalModelProvider.ts index e57bceef5ee..a620b6b4277 100644 --- a/packages/host-service/src/providers/model-providers/LocalModelProvider/LocalModelProvider.ts +++ b/packages/host-service/src/providers/model-providers/LocalModelProvider/LocalModelProvider.ts @@ -30,12 +30,12 @@ export class LocalModelProvider implements ModelProviderRuntimeResolver { this.anthropicEnvConfigPath = options?.anthropicEnvConfigPath; } - private async resolveRuntimeEnv(): Promise<{ + private resolveRuntimeEnv(): { env: Record; cleanupKeys: string[]; hasUsableRuntimeEnv: boolean; - }> { - const anthropicCredential = await resolveAnthropicCredential(); + } { + const anthropicCredential = resolveAnthropicCredential(); const openaiCredential = resolveOpenAICredential(); const anthropicEnvConfig = getAnthropicEnvConfig({ configPath: this.anthropicEnvConfigPath, @@ -54,11 +54,11 @@ export class LocalModelProvider implements ModelProviderRuntimeResolver { } async hasUsableRuntimeEnv(): Promise { - return (await this.resolveRuntimeEnv()).hasUsableRuntimeEnv; + return this.resolveRuntimeEnv().hasUsableRuntimeEnv; } async prepareRuntimeEnv(): Promise { - const runtimeEnv = await this.resolveRuntimeEnv(); + const runtimeEnv = this.resolveRuntimeEnv(); this.currentRuntimeEnv = applyRuntimeEnv( runtimeEnv.env, runtimeEnv.cleanupKeys, diff --git a/packages/host-service/src/providers/model-providers/LocalModelProvider/utils/resolveAnthropicCredential.ts b/packages/host-service/src/providers/model-providers/LocalModelProvider/utils/resolveAnthropicCredential.ts index 354ce598f82..96cdb2c68c6 100644 --- a/packages/host-service/src/providers/model-providers/LocalModelProvider/utils/resolveAnthropicCredential.ts +++ b/packages/host-service/src/providers/model-providers/LocalModelProvider/utils/resolveAnthropicCredential.ts @@ -82,7 +82,7 @@ function getAnthropicCredentialFromKeychain(): LocalResolvedCredential | null { return null; } -async function getAnthropicCredentialFromAuthStorage(): Promise { +function getAnthropicCredentialFromAuthStorage(): LocalResolvedCredential | null { try { const authStorage = createAuthStorage(); authStorage.reload(); @@ -97,45 +97,18 @@ async function getAnthropicCredentialFromAuthStorage(): Promise= expiresAt) { - try { - await authStorage.getApiKey(ANTHROPIC_PROVIDER_ID); - authStorage.reload(); - const refreshed = authStorage.get(ANTHROPIC_PROVIDER_ID); - if ( - isObjectRecord(refreshed) && - refreshed.type === "oauth" && - typeof refreshed.access === "string" && - refreshed.access.trim().length > 0 - ) { - return { - kind: "oauth", - expiresAt: - typeof refreshed.expires === "number" - ? refreshed.expires - : undefined, - }; - } - // Refresh returned no usable access token — callers must - // fall back rather than proxying an expired credential. - return null; - } catch (error) { - console.warn( - "[LocalModelProvider] Anthropic OAuth refresh failed:", - error, - ); - return null; - } - } - if ( - typeof credential.access === "string" && - credential.access.trim().length > 0 - ) { - return { kind: "oauth", expiresAt }; - } + if ( + credential.type === "oauth" && + typeof credential.access === "string" && + credential.access.trim().length > 0 + ) { + return { + kind: "oauth", + expiresAt: + typeof credential.expires === "number" + ? credential.expires + : undefined, + }; } } catch { // Ignore auth storage read failures for now. @@ -144,10 +117,10 @@ async function getAnthropicCredentialFromAuthStorage(): Promise { +export function resolveAnthropicCredential(): LocalResolvedCredential | null { return ( getAnthropicCredentialFromConfig() ?? getAnthropicCredentialFromKeychain() ?? - (await getAnthropicCredentialFromAuthStorage()) + getAnthropicCredentialFromAuthStorage() ); } diff --git a/packages/host-service/src/trpc/router/workspace-creation/utils/ai-branch-name.ts b/packages/host-service/src/trpc/router/workspace-creation/utils/ai-branch-name.ts deleted file mode 100644 index b2bbec615af..00000000000 --- a/packages/host-service/src/trpc/router/workspace-creation/utils/ai-branch-name.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { generateTitleFromMessage } from "@superset/chat/server/desktop"; -import { getSmallModel } from "@superset/chat/server/shared"; -import { deduplicateBranchName } from "./sanitize-branch"; - -const BRANCH_NAME_INSTRUCTIONS = - "Generate a concise git branch name (2-4 words, kebab-case, descriptive). Return ONLY the branch name, nothing else."; - -const MAX_BRANCH_LENGTH = 100; - -/** - * Light sanitizer for AI-generated branch names — lowercase, kebab-case, - * restricted character set. Differs from desktop's full sanitizer: no - * multi-segment support (AI generates a single segment) and no preserve-case - * options. - */ -function sanitizeGeneratedBranchName(raw: string): string { - return raw - .toLowerCase() - .trim() - .replace(/\s+/g, "-") - .replace(/[^a-z0-9._+@-]/g, "") - .replace(/\.{2,}/g, ".") - .replace(/-+/g, "-") - .replace(/\.lock$/g, "") - .slice(0, MAX_BRANCH_LENGTH) - .replace(/^[-.]+|[-.]+$/g, ""); -} - -export async function generateBranchNameFromPrompt( - prompt: string, - existingBranches: string[], -): Promise { - const model = getSmallModel(); - if (!model) return null; - - let generated: string | null; - try { - generated = await generateTitleFromMessage({ - message: prompt, - agentModel: model, - agentId: "branch-namer", - agentName: "Branch Namer", - instructions: BRANCH_NAME_INSTRUCTIONS, - tracingContext: { surface: "host-service-branch-name" }, - }); - } catch (error) { - console.warn("[generateBranchNameFromPrompt] generation failed:", error); - return null; - } - - if (!generated) return null; - const sanitized = sanitizeGeneratedBranchName(generated); - if (!sanitized) return null; - return deduplicateBranchName(sanitized, existingBranches); -} diff --git a/packages/host-service/src/trpc/router/workspace-creation/workspace-creation.ts b/packages/host-service/src/trpc/router/workspace-creation/workspace-creation.ts index 1f00c99608f..480b7126a15 100644 --- a/packages/host-service/src/trpc/router/workspace-creation/workspace-creation.ts +++ b/packages/host-service/src/trpc/router/workspace-creation/workspace-creation.ts @@ -16,7 +16,6 @@ import { createSimpleGitWithEnv } from "../../../runtime/git/simple-git"; import { createTerminalSessionInternal } from "../../../terminal/terminal"; import type { HostServiceContext } from "../../../types"; import { protectedProcedure, router } from "../../index"; -import { generateBranchNameFromPrompt } from "./utils/ai-branch-name"; import { execGh } from "./utils/exec-gh"; import { derivePrLocalBranchName } from "./utils/pr-branch-name"; import { resolveStartPoint } from "./utils/resolve-start-point"; @@ -632,28 +631,6 @@ export const workspaceCreationRouter = router({ return { defaultBranch, items, nextCursor }; }), - generateBranchName: protectedProcedure - .input(z.object({ projectId: z.string(), prompt: z.string() })) - .mutation(async ({ ctx, input }) => { - const trimmed = input.prompt.trim(); - if (!trimmed) return { branchName: null }; - - const localProject = ctx.db.query.projects - .findFirst({ where: eq(projects.id, input.projectId) }) - .sync(); - if (!localProject) return { branchName: null }; - - const existingBranches = await listBranchNames( - ctx, - localProject.repoPath, - ); - const branchName = await generateBranchNameFromPrompt( - trimmed, - existingBranches, - ); - return { branchName }; - }), - /** * Create a new workspace. Always creates — never opens an existing one. * Branch name is sanitized and deduplicated server-side.