diff --git a/.github/scripts/brand-matrix.test.mjs b/.github/scripts/brand-matrix.test.mjs index beee7d5b9..340ceba67 100644 --- a/.github/scripts/brand-matrix.test.mjs +++ b/.github/scripts/brand-matrix.test.mjs @@ -26,7 +26,7 @@ const RE_MISMATCHED_PUBLICATION_SOURCE = /must equal sourceGitSha/; const RE_LEGACY_DESKTOP_UPLOAD = /"s3:\/\/\$\{R2_BUCKET\}\/\$\{R2_PREFIX\}\/"/; const RE_LEGACY_RELEASE_TAG = /must equal refs\/tags\/v1\.2\.3/; const RE_SECRETS_EXPRESSION = /secrets(?:\.|\[)/; -const ACTIONS_EXPRESSION = String.fromCodePoint(36); +const ACTIONS_EXPRESSION = String.fromCharCode(36); function sha(character) { return character.repeat(64); diff --git a/.github/scripts/release-inputs.test.mjs b/.github/scripts/release-inputs.test.mjs index 7be355065..dd2e1946d 100644 --- a/.github/scripts/release-inputs.test.mjs +++ b/.github/scripts/release-inputs.test.mjs @@ -110,25 +110,26 @@ describe('validateReleaseInputs', () => { }); it('rejects malformed desktop notarization key material', () => { - const env = Object.fromEntries( - [ - 'APPLE_API_KEY_BASE64', - 'APPLE_API_KEY_ID', - 'APPLE_API_ISSUER', - 'APPLE_TEAM_ID', - 'AZURE_CERTIFICATE_PROFILE', - 'AZURE_CLIENT_ID', - 'AZURE_CODE_SIGNING_ACCOUNT', - 'AZURE_PUBLISHER_NAME', - 'AZURE_SIGN_ENDPOINT', - 'AZURE_TENANT_ID', - 'MACOS_CSC_KEY_PASSWORD', - 'MACOS_CSC_LINK', - 'POSTHOG_HOST', - 'POSTHOG_PROJECT_TOKEN', - 'SENTRY_DSN_DESKTOP', - ].map((name) => [name, 'set']), - ); + const env = [ + 'APPLE_API_KEY_BASE64', + 'APPLE_API_KEY_ID', + 'APPLE_API_ISSUER', + 'APPLE_TEAM_ID', + 'AZURE_CERTIFICATE_PROFILE', + 'AZURE_CLIENT_ID', + 'AZURE_CODE_SIGNING_ACCOUNT', + 'AZURE_PUBLISHER_NAME', + 'AZURE_SIGN_ENDPOINT', + 'AZURE_TENANT_ID', + 'MACOS_CSC_KEY_PASSWORD', + 'MACOS_CSC_LINK', + 'POSTHOG_HOST', + 'POSTHOG_PROJECT_TOKEN', + 'SENTRY_DSN_DESKTOP', + ].reduce((acc, name) => { + acc[name] = 'set'; + return acc; + }, {}); expect(() => validateReleaseInputs({ env, phase: 'sign', platform: 'desktop' })).toThrow( RE_INVALID_KEY, ); diff --git a/apps/daemon/e2e/startup.e2e.ts b/apps/daemon/e2e/startup.e2e.ts index a843129d0..98181341b 100644 --- a/apps/daemon/e2e/startup.e2e.ts +++ b/apps/daemon/e2e/startup.e2e.ts @@ -120,7 +120,9 @@ async function main(): Promise { .map((row) => (row as { name: string }).name), ); sqlite.close(); - for (const table of ['__drizzle_migrations', 'sessions', 'workspaces', 'schedules', 'loops']) { + const expectedTables = ['__drizzle_migrations', 'sessions', 'workspaces', 'schedules', 'loops']; + for (let i = 0, len = expectedTables.length; i < len; i++) { + const table = expectedTables[i]; assert(tables.has(table), `missing migrated table ${table}`); } diff --git a/apps/daemon/package.json b/apps/daemon/package.json index 0a8331bf4..dbfb14bd9 100644 --- a/apps/daemon/package.json +++ b/apps/daemon/package.json @@ -32,7 +32,7 @@ "@sentry/node": "10.62.0", "@sentry/profiling-node": "10.62.0", "better-sqlite3": "^13.0.2", - "foxts": "^5.8.0", + "foxts": "^5.9.1", "pino": "^10.3.1", "zod": "catalog:" }, diff --git a/apps/daemon/scripts/dev-clean.mts b/apps/daemon/scripts/dev-clean.mts index ae90d3fe3..49f6deb68 100644 --- a/apps/daemon/scripts/dev-clean.mts +++ b/apps/daemon/scripts/dev-clean.mts @@ -3,4 +3,8 @@ import { databasePath, runtimeFilePath } from '../src/config'; // Resolves through config.ts so a fork's renamed state dir, the resolved channel, or an active // LINKCODE_PROFILE cleans the same universe the dev daemon will actually use. -for (const path of [databasePath(), runtimeFilePath()]) rmSync(path, { force: true }); +const devStatePaths = [databasePath(), runtimeFilePath()]; +for (let i = 0, len = devStatePaths.length; i < len; i++) { + const path = devStatePaths[i]; + rmSync(path, { force: true }); +} diff --git a/apps/daemon/scripts/package-daemon.mts b/apps/daemon/scripts/package-daemon.mts index e9b773282..01af52413 100644 --- a/apps/daemon/scripts/package-daemon.mts +++ b/apps/daemon/scripts/package-daemon.mts @@ -61,10 +61,13 @@ run('pnpm', ['--filter', '@linkcode/daemon', '--prod', 'deploy', '--legacy', out rmSync(join(outDir, 'dist'), { recursive: true, force: true }); cpSync(join(daemonDir, 'dist'), join(outDir, 'dist'), { recursive: true }); -for (const [scope, prefix] of PRUNE) { +for (let i = 0, len = PRUNE.length; i < len; i++) { + const [scope, prefix] = PRUNE[i]; const scopeDir = join(outDir, 'node_modules', scope); if (!existsSync(scopeDir)) continue; - for (const entry of readdirSync(scopeDir)) { + const scopeEntries = readdirSync(scopeDir); + for (let j = 0, entryCount = scopeEntries.length; j < entryCount; j++) { + const entry = scopeEntries[j]; if (entry.startsWith(prefix)) rmSync(join(scopeDir, entry), { recursive: true, force: true }); } } @@ -74,7 +77,9 @@ console.log(`daemon packaged at ${outDir} (${Math.round(bytes / 1e6)} MB)`); function dirSize(dir: string): number { let total = 0; - for (const entry of readdirSync(dir, { withFileTypes: true })) { + const entries = readdirSync(dir, { withFileTypes: true }); + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; const full = join(dir, entry.name); if (entry.isDirectory()) total += dirSize(full); else if (entry.isFile()) total += statSync(full).size; diff --git a/apps/daemon/src/__tests__/ai-gateway.test.ts b/apps/daemon/src/__tests__/ai-gateway.test.ts index c84e917a0..73ffe2119 100644 --- a/apps/daemon/src/__tests__/ai-gateway.test.ts +++ b/apps/daemon/src/__tests__/ai-gateway.test.ts @@ -47,13 +47,22 @@ class FakeChild implements SidecarChildProcess { this.signal = signal; } emitStdout(text: string): void { - for (const listener of this.dataListeners) listener(text); + for (let i = 0, len = this.dataListeners.length; i < len; i++) { + const listener = this.dataListeners[i]; + listener(text); + } } emitError(error: Error): void { - for (const listener of this.errorListeners) listener(error); + for (let i = 0, len = this.errorListeners.length; i < len; i++) { + const listener = this.errorListeners[i]; + listener(error); + } } emitExit(code: number | null): void { - for (const listener of this.exitListeners) listener(code); + for (let i = 0, len = this.exitListeners.length; i < len; i++) { + const listener = this.exitListeners[i]; + listener(code); + } } } diff --git a/apps/daemon/src/__tests__/secrets-vault.test.ts b/apps/daemon/src/__tests__/secrets-vault.test.ts index c3a0d655a..de4219912 100644 --- a/apps/daemon/src/__tests__/secrets-vault.test.ts +++ b/apps/daemon/src/__tests__/secrets-vault.test.ts @@ -25,8 +25,9 @@ const noKeyring = (): MasterKey | null => null; * Secrets are only reachable through a namespace, so every case goes through one. On disk the same * entry is the full `cloud:session` ref — asserting against that is what proves the prefixing. */ -const open = (file: string, loadKey: () => MasterKey | null): SecretStore => - createSecretVault(file, loadKey).namespace('cloud'); +function open(file: string, loadKey: () => MasterKey | null): SecretStore { + return createSecretVault(file, loadKey).namespace('cloud'); +} let file: string; const realPlatform = process.platform; diff --git a/apps/daemon/src/ai-gateway.ts b/apps/daemon/src/ai-gateway.ts index 7267a6777..6c43714bc 100644 --- a/apps/daemon/src/ai-gateway.ts +++ b/apps/daemon/src/ai-gateway.ts @@ -172,7 +172,10 @@ export function createAiGatewaySidecar(options: AiGatewaySidecarOptions = {}): T }, async closeAll() { const entries = [...running.values()]; - for (const entry of entries) entry.close(); + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; + entry.close(); + } await Promise.allSettled(entries.map((entry) => entry.ready)); }, }; diff --git a/apps/daemon/src/config.ts b/apps/daemon/src/config.ts index 56ad8aa0d..d7bc8b2ed 100644 --- a/apps/daemon/src/config.ts +++ b/apps/daemon/src/config.ts @@ -206,7 +206,8 @@ function parseAccounts(store: SecretStore, raw: unknown): Parsed { } const accounts: Accounts = []; let migrated = false; - for (const value of raw) { + for (let i = 0, len = raw.length; i < len; i++) { + const value = raw[i]; // The credential secret lives in the vault (CODE-371); merge it back before validating, so a // secret that is gone fails the schema and lands in the same drop-and-log path as a malformed one. const attached = withAccountSecret(store, value); @@ -267,7 +268,8 @@ function parseCustomMcpServers(store: SecretStore, raw: unknown): Parsed): unknown seen.set(value, sanitized); const cause = Reflect.get(value, 'cause'); if (cause !== undefined) sanitized.cause = sanitizeValue(cause, seen); - for (const [key, entry] of Object.entries(value)) { + const errorEntries = Object.entries(value); + for (let i = 0, len = errorEntries.length; i < len; i++) { + const [key, entry] = errorEntries[i]; sanitized[key] = SENSITIVE_KEY.test(key) ? REDACTED : sanitizeValue(entry, seen); } return sanitized; @@ -49,7 +51,10 @@ function sanitizeValue(value: unknown, seen: WeakMap): unknown if (Array.isArray(value)) { const sanitized: unknown[] = []; seen.set(value, sanitized); - for (const entry of value) sanitized.push(sanitizeValue(entry, seen)); + for (let i = 0, len = value.length; i < len; i++) { + const entry = value[i]; + sanitized.push(sanitizeValue(entry, seen)); + } return sanitized; } @@ -59,7 +64,9 @@ function sanitizeValue(value: unknown, seen: WeakMap): unknown const sanitized: Record = {}; seen.set(value, sanitized); - for (const [key, entry] of Object.entries(value)) { + const entries = Object.entries(value); + for (let i = 0, len = entries.length; i < len; i++) { + const [key, entry] = entries[i]; sanitized[key] = SENSITIVE_KEY.test(key) ? REDACTED : sanitizeValue(entry, seen); } return sanitized; diff --git a/apps/daemon/src/index.ts b/apps/daemon/src/index.ts index d65c4eb67..754052ab7 100644 --- a/apps/daemon/src/index.ts +++ b/apps/daemon/src/index.ts @@ -43,6 +43,7 @@ import { } from './config'; import { DaemonLoggerLive, logger } from './logger'; import { createLoopStore } from './loop-store'; +import type { ManagedAgentKind } from './managed-agent-refresh'; import { agentsToRefresh, consentedManagedAgents } from './managed-agent-refresh'; import { daemonStateDir } from './paths'; import { createProviderConfigStore } from './provider-store'; @@ -187,6 +188,23 @@ async function main(): Promise { ); const assets = new AssetManager(); const consentedAgents = consentedManagedAgents(assets); + const refreshAgentRuntime = (kind: ManagedAgentKind): Promise => + assets + .ensure(managedAgentAssetId(kind)) + .catch((err) => { + logger.warn( + { err, agentKind: kind, operation: 'asset.ensure' }, + 'Managed agent install failed', + ); + }) + .then((installed) => { + if (installed) { + logger.info( + { agentKind: kind, operation: 'asset.ensure' }, + 'Managed agent runtime ready', + ); + } + }); const gc = assets.gcAtBoot(); if (gc.removed.length > 0) { yield* Effect.logInfo('Removed superseded managed assets', { @@ -285,23 +303,9 @@ async function main(): Promise { const engine = yield* EngineService; void agentRuntimesReady .then((agentRuntimes) => { - for (const kind of agentsToRefresh(consentedAgents, agentRuntimes, assets)) { - void assets - .ensure(managedAgentAssetId(kind)) - .catch((err) => { - logger.warn( - { err, agentKind: kind, operation: 'asset.ensure' }, - 'Managed agent install failed', - ); - }) - .then((installed) => { - if (installed) { - logger.info( - { agentKind: kind, operation: 'asset.ensure' }, - 'Managed agent runtime ready', - ); - } - }); + const refreshable = agentsToRefresh(consentedAgents, agentRuntimes, assets); + for (let i = 0, len = refreshable.length; i < len; i++) { + void refreshAgentRuntime(refreshable[i]); } }) .catch((err) => { diff --git a/apps/daemon/src/logger.ts b/apps/daemon/src/logger.ts index b14475309..cbdf413ef 100644 --- a/apps/daemon/src/logger.ts +++ b/apps/daemon/src/logger.ts @@ -56,7 +56,7 @@ export function createDaemonLogger( name: 'linkcode-daemon', hooks: { logMethod(args, method) { - for (let index = 0; index < args.length; index += 1) { + for (let index = 0, len = args.length; index < len; index += 1) { args[index] = sanitizeDiagnostic(args[index]); } method.apply(this, args); @@ -78,9 +78,11 @@ export const logger = createDaemonLogger(); function effectBindings(messages: readonly unknown[]): Record { const bindings: Record = { source: 'effect' }; - for (const message of messages) { + for (let i = 0, len = messages.length; i < len; i++) { + const message = messages[i]; if (typeof message !== 'object' || message === null) continue; - for (const key of EFFECT_BINDING_KEYS) { + for (let j = 0, keyCount = EFFECT_BINDING_KEYS.length; j < keyCount; j++) { + const key = EFFECT_BINDING_KEYS[j]; const value = Reflect.get(message, key); if (typeof value === 'string' || typeof value === 'number') bindings[key] = value; } diff --git a/apps/daemon/src/loop-store.ts b/apps/daemon/src/loop-store.ts index 82d74949d..27f130b84 100644 --- a/apps/daemon/src/loop-store.ts +++ b/apps/daemon/src/loop-store.ts @@ -77,7 +77,8 @@ export function createLoopStore(dbPath: string): LoopStore { /** Parse each row through its schema; drop and log a row that fails rather than failing the load. */ function parseAll(rows: Row[], parse: (row: Row) => T): T[] { const parsed: T[] = []; - for (const row of rows) { + for (let i = 0, len = rows.length; i < len; i++) { + const row = rows[i]; try { parsed.push(parse(row)); } catch { diff --git a/apps/daemon/src/pty/bench-throughput.mts b/apps/daemon/src/pty/bench-throughput.mts index 874e3905d..578db3645 100644 --- a/apps/daemon/src/pty/bench-throughput.mts +++ b/apps/daemon/src/pty/bench-throughput.mts @@ -67,7 +67,9 @@ async function runLinkCodePty( const pending = new Map(); child.stdout.on('data', (chunk: Buffer) => { - for (const frame of decoder.feed(chunk)) { + const frames = decoder.feed(chunk); + for (let i = 0, len = frames.length; i < len; i++) { + const frame = frames[i]; switch (frame.type) { case OPENED: case OUTPUT: diff --git a/apps/daemon/src/pty/sidecar.ts b/apps/daemon/src/pty/sidecar.ts index 392af9381..222199a8f 100644 --- a/apps/daemon/src/pty/sidecar.ts +++ b/apps/daemon/src/pty/sidecar.ts @@ -135,7 +135,11 @@ export class SidecarPtyBackend implements PtyBackend { this.child = child; child.stdout.on('data', (chunk: Buffer) => { try { - for (const frame of this.decoder.feed(chunk)) this.handleFrame(frame); + const frames = this.decoder.feed(chunk); + for (let i = 0, len = frames.length; i < len; i++) { + const frame = frames[i]; + this.handleFrame(frame); + } } catch (err) { logger.error( { @@ -219,7 +223,10 @@ export class SidecarPtyBackend implements PtyBackend { const unsub = terminal.exited ? noop : terminal.data.add(cb); if (!terminal.dataSubscribed) { terminal.dataSubscribed = true; - for (const data of terminal.bufferedData) cb(data); + for (let i = 0, len = terminal.bufferedData.length; i < len; i++) { + const data = terminal.bufferedData[i]; + cb(data); + } terminal.bufferedData.length = 0; } return unsub; @@ -271,7 +278,10 @@ export class SidecarPtyBackend implements PtyBackend { } this.pending.clear(); const terminalIds = Array.from(this.terminals.keys()); - for (const terminalId of terminalIds) this.finish(terminalId, null, false); + for (let i = 0, len = terminalIds.length; i < len; i++) { + const terminalId = terminalIds[i]; + this.finish(terminalId, null, false); + } } } diff --git a/apps/daemon/src/schedule-store.ts b/apps/daemon/src/schedule-store.ts index d69b4fd46..c1a677604 100644 --- a/apps/daemon/src/schedule-store.ts +++ b/apps/daemon/src/schedule-store.ts @@ -92,7 +92,8 @@ export function createScheduleStore(dbPath: string): ScheduleStore { /** Parse each row through its schema; drop and log a row that fails rather than failing the load. */ function parseAll(rows: Row[], parse: (row: Row) => T): T[] { const parsed: T[] = []; - for (const row of rows) { + for (let i = 0, len = rows.length; i < len; i++) { + const row = rows[i]; try { parsed.push(parse(row)); } catch { diff --git a/apps/daemon/src/secrets/custom-mcp-credentials.ts b/apps/daemon/src/secrets/custom-mcp-credentials.ts index 1d8ae33e7..73518fb1f 100644 --- a/apps/daemon/src/secrets/custom-mcp-credentials.ts +++ b/apps/daemon/src/secrets/custom-mcp-credentials.ts @@ -28,7 +28,9 @@ export function withCustomMcpSecrets( } const values = { ...(server[field] as Record) }; let migrated = false; - for (const [key, value] of Object.entries(values)) { + const valueEntries = Object.entries(values); + for (let i = 0, len = valueEntries.length; i < len; i++) { + const [key, value] = valueEntries[i]; if (typeof value === 'string') { store.set(secretKey(generation, entry.id, field, key), value); migrated = true; @@ -52,7 +54,9 @@ export function detachCustomMcpSecrets( const values = entry.server.type === 'stdio' ? entry.server.env : entry.server.headers; if (values === undefined) return entry; const placeholders: Record = {}; - for (const [key, value] of Object.entries(values)) { + const valueEntries = Object.entries(values); + for (let i = 0, len = valueEntries.length; i < len; i++) { + const [key, value] = valueEntries[i]; secrets.set(secretKey(generation, entry.id, field, key), value); placeholders[key] = null; } diff --git a/apps/daemon/src/secrets/provider-credentials.ts b/apps/daemon/src/secrets/provider-credentials.ts index bb3acb8d2..f26c46a7a 100644 --- a/apps/daemon/src/secrets/provider-credentials.ts +++ b/apps/daemon/src/secrets/provider-credentials.ts @@ -76,7 +76,9 @@ export function detachProviderSecrets( const stripped: ProvidersConfig = {}; const secrets = new Map(); - for (const [kind, config] of Object.entries(providers)) { + const providerEntries = Object.entries(providers); + for (let i = 0, len = providerEntries.length; i < len; i++) { + const [kind, config] = providerEntries[i]; const { apiKey, ...rest } = config; if (apiKey !== undefined) secrets.set(kind, apiKey); Reflect.set(stripped, kind, rest); diff --git a/apps/daemon/src/secrets/vault.ts b/apps/daemon/src/secrets/vault.ts index 2f710caf0..afeca1c62 100644 --- a/apps/daemon/src/secrets/vault.ts +++ b/apps/daemon/src/secrets/vault.ts @@ -269,7 +269,9 @@ function parseEntries(raw: unknown, file: string): Map { return new Map(); } const secrets = new Map(); - for (const [ref, value] of Object.entries(raw)) { + const entries = Object.entries(raw); + for (let i = 0, len = entries.length; i < len; i++) { + const [ref, value] = entries[i]; if (typeof value === 'string') secrets.set(ref, value); else logger.warn({ operation: 'secrets.vault', ref }, 'Dropping a malformed stored secret'); } diff --git a/apps/daemon/src/session-store.ts b/apps/daemon/src/session-store.ts index 7aec1f69e..720c3403b 100644 --- a/apps/daemon/src/session-store.ts +++ b/apps/daemon/src/session-store.ts @@ -30,7 +30,9 @@ function reconcileMigrationLedger(sqlite: Sqlite.Database, migrationsFolder: str 'UPDATE __drizzle_migrations SET created_at = ? WHERE hash = ? AND created_at <> ?', ); sqlite.transaction(() => { - for (const migration of readMigrationFiles({ migrationsFolder })) { + const migrations = readMigrationFiles({ migrationsFolder }); + for (let i = 0, len = migrations.length; i < len; i++) { + const migration = migrations[i]; realign.run(migration.folderMillis, migration.hash, migration.folderMillis); } })(); @@ -59,7 +61,8 @@ export function createSessionStore(dbPath: string): SessionStore { .orderBy(asc(sessionRuns.sessionId), asc(sessionRuns.seq)) .all(); const runsBySession = new Map(); - for (const run of runRows) { + for (let i = 0, len = runRows.length; i < len; i++) { + const run = runRows[i]; const bucket = runsBySession.get(run.sessionId); if (bucket) bucket.push(run); else runsBySession.set(run.sessionId, [run]); diff --git a/apps/daemon/src/sim/mcp-endpoint.ts b/apps/daemon/src/sim/mcp-endpoint.ts index 313a3780a..0d18fa34b 100644 --- a/apps/daemon/src/sim/mcp-endpoint.ts +++ b/apps/daemon/src/sim/mcp-endpoint.ts @@ -15,6 +15,7 @@ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/ import { extractErrorMessage } from 'foxts/extract-error-message'; import { nullthrow } from 'foxts/guard'; import { noop } from 'foxts/noop'; +import { split0th } from 'foxts/split-nth'; import { z } from 'zod'; import { logger } from '../logger'; @@ -146,7 +147,7 @@ export class SimulatorMcpEndpoint implements SimulatorMcpProvider { /** Reached only through `create()`'s request closure — not via `this`, which the lint rule * tracks; keep it package-private by convention rather than `private`. */ async handle(req: IncomingMessage, res: ServerResponse): Promise { - const token = RE_MCP_PATH.exec(req.url?.split('?', 1)[0] ?? '')?.[1]; + const token = RE_MCP_PATH.exec(split0th(req.url ?? '', '?'))?.[1]; const sessionId = token === undefined ? undefined : this.tokens.get(token); if (sessionId === undefined) { res.writeHead(404, { 'content-type': 'application/json' }); diff --git a/apps/daemon/tests/integration/loop-store.test.ts b/apps/daemon/tests/integration/loop-store.test.ts index 105496830..26b72b7a5 100644 --- a/apps/daemon/tests/integration/loop-store.test.ts +++ b/apps/daemon/tests/integration/loop-store.test.ts @@ -5,6 +5,8 @@ import { createLoopStore } from '../../src/loop-store'; const lid = (id: string): LoopId => id as LoopId; +const collator = new Intl.Collator(); + function makeLoop(value: Record & { loopId: string }): LoopRecord { return LoopRecordSchema.parse({ spec: { @@ -61,7 +63,7 @@ describe('daemon sqlite loop store', () => { await store.save(withVerifier); await store.save(minimal); - const loaded = (await store.load()).sort((a, b) => a.loopId.localeCompare(b.loopId)); + const loaded = (await store.load()).sort((a, b) => collator.compare(a.loopId, b.loopId)); expect(loaded).toEqual([withVerifier, minimal]); }); diff --git a/apps/daemon/tests/integration/schedule-store.test.ts b/apps/daemon/tests/integration/schedule-store.test.ts index 28b06fa9f..30b88537f 100644 --- a/apps/daemon/tests/integration/schedule-store.test.ts +++ b/apps/daemon/tests/integration/schedule-store.test.ts @@ -5,6 +5,8 @@ import { createScheduleStore } from '../../src/schedule-store'; const sid = (id: string): ScheduleId => id as ScheduleId; +const collator = new Intl.Collator(); + function makeSchedule(value: Record & { scheduleId: string }): Schedule { return ScheduleSchema.parse({ spec: { @@ -53,7 +55,9 @@ describe('daemon sqlite schedule store', () => { await store.save(cronSessionTarget); await store.save(intervalNewSession); - const loaded = (await store.load()).sort((a, b) => a.scheduleId.localeCompare(b.scheduleId)); + const loaded = (await store.load()).sort((a, b) => + collator.compare(a.scheduleId, b.scheduleId), + ); expect(loaded).toEqual([cronSessionTarget, intervalNewSession]); }); diff --git a/apps/daemon/tests/integration/session-store.test.ts b/apps/daemon/tests/integration/session-store.test.ts index 872d4b337..55576337a 100644 --- a/apps/daemon/tests/integration/session-store.test.ts +++ b/apps/daemon/tests/integration/session-store.test.ts @@ -7,6 +7,8 @@ import Sqlite from 'better-sqlite3'; import { afterEach, describe, expect, it } from 'vitest'; import { createSessionStore } from '../../src/session-store'; +const collator = new Intl.Collator(); + function makeRecord(value: Record): SessionRecord { return SessionRecordSchema.parse({ sessionId: 'sess-1', @@ -41,7 +43,7 @@ describe('daemon sqlite session store', () => { await store.save(created); await store.save(imported); - const loaded = (await store.load()).sort((a, b) => a.sessionId.localeCompare(b.sessionId)); + const loaded = (await store.load()).sort((a, b) => collator.compare(a.sessionId, b.sessionId)); expect(loaded).toEqual([created, imported]); }); diff --git a/apps/daemon/tests/integration/workspace-store.test.ts b/apps/daemon/tests/integration/workspace-store.test.ts index f12106332..3769f5c3d 100644 --- a/apps/daemon/tests/integration/workspace-store.test.ts +++ b/apps/daemon/tests/integration/workspace-store.test.ts @@ -3,6 +3,8 @@ import { WorkspaceRecordSchema } from '@linkcode/schema'; import { describe, expect, it } from 'vitest'; import { createWorkspaceStore } from '../../src/workspace-store'; +const collator = new Intl.Collator(); + function makeRecord(value: Record): WorkspaceRecord { return WorkspaceRecordSchema.parse({ workspaceId: 'ws-1', @@ -22,7 +24,9 @@ describe('daemon sqlite workspace store', () => { await store.save(named); await store.save(unnamed); - const loaded = (await store.load()).sort((a, b) => a.workspaceId.localeCompare(b.workspaceId)); + const loaded = (await store.load()).sort((a, b) => + collator.compare(a.workspaceId, b.workspaceId), + ); expect(loaded).toEqual([named, unnamed]); }); diff --git a/apps/desktop/e2e/browser-broker.e2e.mts b/apps/desktop/e2e/browser-broker.e2e.mts index 13b542f3e..7777c4a81 100644 --- a/apps/desktop/e2e/browser-broker.e2e.mts +++ b/apps/desktop/e2e/browser-broker.e2e.mts @@ -61,11 +61,11 @@ function createWireClient(): { } { const socket = io(`http://127.0.0.1:${PORT}`, { transports: ['websocket'] }); let seq = 0; - const backlog: Record[] = []; - const waiters: { + const backlog: Array> = []; + const waiters: Array<{ predicate: (payload: Record) => boolean; resolve: (payload: Record) => void; - }[] = []; + }> = []; socket.on('frame', (frame: WireFrame) => { const index = waiters.findIndex((waiter) => waiter.predicate(frame.payload)); if (index === -1) { @@ -160,7 +160,7 @@ async function main(): Promise { url: 'https://example.com/', }); if (opened.ok !== true) fail(`tabs.open failed: ${JSON.stringify(opened)}`); - const tabs = opened.data as { id: string; url: string | null; active: boolean }[]; + const tabs = opened.data as Array<{ id: string; url: string | null; active: boolean }>; const active = tabs.find((tab) => tab.active); if (active?.url !== 'https://example.com/') { fail(`expected an active example.com tab, got ${JSON.stringify(tabs)}`); diff --git a/apps/desktop/e2e/browser-tabs.e2e.mts b/apps/desktop/e2e/browser-tabs.e2e.mts index 25bb0ead1..07bae3832 100644 --- a/apps/desktop/e2e/browser-tabs.e2e.mts +++ b/apps/desktop/e2e/browser-tabs.e2e.mts @@ -91,7 +91,11 @@ function logPageErrors(page: Page): void { } function watchAppErrors(app: ElectronApplication): void { - for (const page of app.windows()) logPageErrors(page); + const windows = app.windows(); + for (let i = 0, len = windows.length; i < len; i++) { + const page = windows[i]; + logPageErrors(page); + } app.on('window', logPageErrors); } diff --git a/apps/desktop/e2e/config-canary/dist-server.mts b/apps/desktop/e2e/config-canary/dist-server.mts index 78d625be0..97fdc0934 100644 --- a/apps/desktop/e2e/config-canary/dist-server.mts +++ b/apps/desktop/e2e/config-canary/dist-server.mts @@ -80,7 +80,8 @@ const pointerArtifacts: Record, PointerArtifact> }; const snapshotArtifacts = new Map(); -for (const step of fixture.steps) { +for (let i = 0, len = fixture.steps.length; i < len; i++) { + const step = fixture.steps[i]; const bytes = snapshotBytes(step); const existing = snapshotArtifacts.get(step.snapshotPath); assert(!existing || existing.equals(bytes), `conflicting fixture path ${step.snapshotPath}`); diff --git a/apps/desktop/e2e/file-tree.e2e.mts b/apps/desktop/e2e/file-tree.e2e.mts index cf7eb0a28..90999f71b 100644 --- a/apps/desktop/e2e/file-tree.e2e.mts +++ b/apps/desktop/e2e/file-tree.e2e.mts @@ -48,7 +48,7 @@ async function treeRowLabels(win: Page): Promise { return win.evaluate(() => { const host = document.querySelector('file-tree-container'); const rows = host?.shadowRoot?.querySelectorAll('button[data-type="item"]') ?? []; - return [...rows].map((row) => row.getAttribute('aria-label') ?? ''); + return Array.from(rows, (row) => row.getAttribute('aria-label') ?? ''); }); } @@ -196,7 +196,7 @@ async function run(win: Page): Promise { if (!shadow?.textContent?.includes('tree-fixture-config')) continue; const html = shadow.innerHTML; return { - // eslint-disable-next-line sukka/no-regex-in-function -- runs in the page: a hoisted module-scope regex is out of scope for the serialized closure + // eslint-disable-next-line vibe-proof/prefer-hoisted-regex -- runs in the page: a hoisted module-scope regex is out of scope for the serialized closure tokens: /color:\s*#|--shiki/.test(html), sample: html.slice(html.indexOf('tree-fixture-config') - 200, 300), }; diff --git a/apps/desktop/e2e/simulator-live.mts b/apps/desktop/e2e/simulator-live.mts index 7117f83cb..7ce51ab31 100644 --- a/apps/desktop/e2e/simulator-live.mts +++ b/apps/desktop/e2e/simulator-live.mts @@ -148,7 +148,9 @@ async function main(): Promise { await win.waitForTimeout(1200); } const plus = win.locator('button[aria-label="Open window"]:visible'); - for (const candidate of await plus.all()) { + const plusCandidates = await plus.all(); + for (let i = 0, len = plusCandidates.length; i < len; i++) { + const candidate = plusCandidates[i]; try { await candidate.click({ timeout: 2000 }); break; diff --git a/apps/desktop/e2e/simulator-panel.e2e.mts b/apps/desktop/e2e/simulator-panel.e2e.mts index af5f860f5..f5661cae8 100644 --- a/apps/desktop/e2e/simulator-panel.e2e.mts +++ b/apps/desktop/e2e/simulator-panel.e2e.mts @@ -29,6 +29,7 @@ import { createRequire } from 'node:module'; import { tmpdir } from 'node:os'; import { basename, join, resolve } from 'node:path'; import { noop } from 'foxts/noop'; +import { split0th } from 'foxts/split-nth'; import { wait } from 'foxts/wait'; import type { ElectronApplication, Page } from 'playwright-core'; import { _electron } from 'playwright-core'; @@ -243,7 +244,9 @@ async function run( let plusTarget = null as Awaited>[number] | null; const plusDeadline = Date.now() + 15000; while (plusTarget === null && Date.now() < plusDeadline) { - for (const candidate of await plus.all()) { + const candidates = await plus.all(); + for (let i = 0, len = candidates.length; i < len; i++) { + const candidate = candidates[i]; try { await candidate.click({ trial: true, timeout: 1000 }); plusTarget = candidate; @@ -259,7 +262,9 @@ async function run( await win.screenshot({ path: shot }); console.error(`screenshot: ${shot}`); console.error(`toggle aria-pressed: ${await toggle.getAttribute('aria-pressed')}`); - for (const candidate of await plus.all()) { + const candidates = await plus.all(); + for (let i = 0, len = candidates.length; i < len; i++) { + const candidate = candidates[i]; console.error(`plus box: ${JSON.stringify(await candidate.boundingBox())}`); } fail('the section strip + trigger never became clickable'); @@ -382,7 +387,7 @@ async function run( ctx.drawImage(source, 0, 0, 32, 64); const data = ctx.getImageData(0, 0, 32, 64).data; let hash = 0; - for (let i = 0; i < data.length; i += 16) { + for (let i = 0, len = data.length; i < len; i += 16) { hash = ((hash * 31 + data[i]) & 0xff_ff_ff) >>> 0; } return hash; @@ -471,9 +476,12 @@ async function run( // stream is the same wire the panel sends when a dropdown changes. const workerPid = (): string | null => { try { - return execFileSync('pgrep', ['-f', `capture-worker ${bootedUdid}`], { encoding: 'utf8' }) - .trim() - .split('\n', 1)[0]; + return split0th( + execFileSync('pgrep', ['-f', `capture-worker ${bootedUdid}`], { + encoding: 'utf8', + }).trim(), + '\n', + ); } catch { return null; } diff --git a/apps/desktop/package.json b/apps/desktop/package.json index d706e2d04..4396bdb09 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -44,7 +44,7 @@ "better-auth": "1.7.0-rc.2", "electron-log": "^5.4.4", "electron-updater": "^6.8.9", - "foxts": "^5.8.0", + "foxts": "^5.9.1", "zod": "catalog:" }, "devDependencies": { @@ -70,7 +70,7 @@ "cross-spawn": "^7.0.6", "electron": "catalog:", "electron-builder": "catalog:", - "foxact": "^0.3.8", + "foxact": "^0.3.10", "lucide-react": "catalog:", "motion": "^12.42.2", "playwright-core": "^1.62.0", diff --git a/apps/desktop/scripts/build.mts b/apps/desktop/scripts/build.mts index ee3e18a1a..d66f0bfe7 100644 --- a/apps/desktop/scripts/build.mts +++ b/apps/desktop/scripts/build.mts @@ -14,7 +14,9 @@ async function main(): Promise { // Main goes first: its closeBundle stages out/daemon + out/drizzle, matching electron-vite's // main → preload → renderer order. // main is .mts: its config imports ESM-only deps, so Vite must load it as ESM. - for (const target of ['main', 'preload', 'renderer']) { + const targets = ['main', 'preload', 'renderer']; + for (let i = 0, len = targets.length; i < len; i++) { + const target = targets[i]; const ext = target === 'main' ? 'mts' : 'ts'; await build({ configFile: resolve(desktopDir, `vite.${target}.config.${ext}`), mode }); } diff --git a/apps/desktop/scripts/config-bundle.mts b/apps/desktop/scripts/config-bundle.mts index 76d46fbed..792c8c8f6 100644 --- a/apps/desktop/scripts/config-bundle.mts +++ b/apps/desktop/scripts/config-bundle.mts @@ -8,6 +8,7 @@ import { join, resolve } from 'node:path'; import { appendArrayInPlace } from 'foxts/append-array-in-place'; // Relative on purpose: this module is inlined into the bundled Vite config, which runs under // plain Node — Node cannot resolve the package's extensionless TS source exports. +// eslint-disable-next-line import-x/no-relative-packages -- see above import { parseBrandIdentityArtifact } from '../../../packages/foundation/common/src/config/brand-identity'; import { configBuildBundleDefaults, @@ -47,13 +48,16 @@ const BUNDLE_FILE = 'config-build-bundle.json'; const BRAND_IDENTITY_FILE = 'brand-identity.json'; const BRAND_BUILDER_FILE = 'electron-builder.brand.json'; const BRAND_ICON_FILE = 'brand-assets/icon.png'; +const collator = new Intl.Collator(); function listFiles(dir: string, prefix = ''): string[] { if (!existsSync(dir)) return []; const files: string[] = []; - for (const entry of readdirSync(dir, { withFileTypes: true }).sort((a, b) => - a.name.localeCompare(b.name), - )) { + const entries = readdirSync(dir, { withFileTypes: true }).sort((a, b) => + collator.compare(a.name, b.name), + ); + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; const relative = prefix === '' ? entry.name : `${prefix}/${entry.name}`; if (entry.isDirectory()) appendArrayInPlace(files, listFiles(join(dir, entry.name), relative)); else files.push(relative); diff --git a/apps/desktop/scripts/dev.mts b/apps/desktop/scripts/dev.mts index c3f78ff9c..d1c02f64f 100644 --- a/apps/desktop/scripts/dev.mts +++ b/apps/desktop/scripts/dev.mts @@ -13,7 +13,7 @@ async function main(): Promise { const args = process.argv.slice(2); const electronArgs: string[] = []; let mode = 'development'; - for (let i = 0; i < args.length; i++) { + for (let i = 0, len = args.length; i < len; i++) { const arg = args[i]; if (arg === '--') continue; if (arg === '--mode') { @@ -31,7 +31,9 @@ async function main(): Promise { const desktopDir = resolve(import.meta.dirname, '..'); // main is .mts: its config imports ESM-only deps, so Vite must load it as ESM. - for (const target of ['main', 'preload']) { + const targets = ['main', 'preload']; + for (let i = 0, len = targets.length; i < len; i++) { + const target = targets[i]; const ext = target === 'main' ? 'mts' : 'ts'; await build({ configFile: resolve(desktopDir, `vite.${target}.config.${ext}`), mode }); } diff --git a/apps/desktop/scripts/package-app.mts b/apps/desktop/scripts/package-app.mts index 23658340b..152779ae8 100644 --- a/apps/desktop/scripts/package-app.mts +++ b/apps/desktop/scripts/package-app.mts @@ -94,7 +94,9 @@ function materializeStaging(arch: BuilderArch): string { ); // deploy's file selection skips .gitignore'd paths inconsistently across pnpm versions; sync the // build outputs in explicitly so `files: out/**` and `extraResources: sidecar/${arch}` resolve. - for (const dir of ['out', 'sidecar']) { + const syncDirs = ['out', 'sidecar']; + for (let i = 0, len = syncDirs.length; i < len; i++) { + const dir = syncDirs[i]; const dest = join(target, dir); rmSync(dest, { recursive: true, force: true }); cpSync(join(desktopDir, dir), dest, { recursive: true }); @@ -118,10 +120,12 @@ const MARKDOWN_RE = /\.(?:md|markdown)$/i; function pruneStaging(target: string): void { let files = 0; let bytes = 0; - for (const entry of readdirSync(join(target, 'node_modules'), { + const entries = readdirSync(join(target, 'node_modules'), { recursive: true, withFileTypes: true, - })) { + }); + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; if (!entry.isFile()) continue; const prunable = entry.name.endsWith('.map') || @@ -148,7 +152,8 @@ function stagedArches(): BuilderArch[] { const staged = BUILDER_ARCHES.filter((arch) => stagedNames.has(arch)); if (staged.length === 0) throw new Error('no staged sidecar arch; run stage:host-runtime first'); const arches = requestedArches.length === 0 ? staged : requestedArches; - for (const arch of arches) { + for (let i = 0, len = arches.length; i < len; i++) { + const arch = arches[i]; if (!staged.includes(arch)) throw new Error(`sidecar/${arch} is not staged`); } return arches; @@ -190,7 +195,9 @@ function build(): void { : 'electron-builder.release.yml'; const brandIcon = join(desktopDir, 'out', 'config', 'brand-assets', 'icon.png'); const feeds = new Map(); - for (const arch of stagedArches()) { + const arches = stagedArches(); + for (let i = 0, len = arches.length; i < len; i++) { + const arch = arches[i]; const target = materializeStaging(arch); pruneStaging(target); const feedName = updateFeedName(arch); diff --git a/apps/desktop/scripts/package-config.mts b/apps/desktop/scripts/package-config.mts index f79cc829b..99b6f4a3e 100644 --- a/apps/desktop/scripts/package-config.mts +++ b/apps/desktop/scripts/package-config.mts @@ -9,12 +9,16 @@ const CONFIG_FILE_PAIRS = [ ['brand-assets/icon.png', 'brand-assets/icon.png'], ] as const; +const collator = new Intl.Collator(); + function listFiles(dir: string, prefix = ''): string[] { if (!existsSync(dir)) return []; const files: string[] = []; - for (const entry of readdirSync(dir, { withFileTypes: true }).sort((a, b) => - a.name.localeCompare(b.name), - )) { + const entries = readdirSync(dir, { withFileTypes: true }).sort((a, b) => + collator.compare(a.name, b.name), + ); + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; const relative = prefix === '' ? entry.name : `${prefix}/${entry.name}`; if (entry.isDirectory()) appendArrayInPlace(files, listFiles(join(dir, entry.name), relative)); else files.push(relative); @@ -62,7 +66,8 @@ export function assertStagedConfigMatchesGenerated(desktopDir: string): boolean pairs.map(([, staged]) => staged).sort(), 'apps/desktop/out/config', ); - for (const [generated, staged] of pairs) { + for (let i = 0, len = pairs.length; i < len; i++) { + const [generated, staged] = pairs[i]; if ( !readFileSync(join(generatedDir, generated)).equals(readFileSync(join(outConfig, staged))) ) { diff --git a/apps/desktop/scripts/render-config-bundle.mts b/apps/desktop/scripts/render-config-bundle.mts index a1bbc3469..6fc05b791 100644 --- a/apps/desktop/scripts/render-config-bundle.mts +++ b/apps/desktop/scripts/render-config-bundle.mts @@ -38,6 +38,8 @@ const USAGE = String.raw`Usage: config:render \ --brand-artifacts also render the brand identity, staged assets, and builder overlay \ --check verify apps/desktop/generated is byte-identical; never rewrite`; +const collator = new Intl.Collator(); + function bail(message: string): never { console.error(`config:render: ${message}\n\n${USAGE}`); process.exit(1); @@ -106,9 +108,11 @@ async function renderInto( function listFiles(dir: string, prefix = ''): string[] { const files: string[] = []; - for (const entry of readdirSync(dir, { withFileTypes: true }).sort((a, b) => - a.name.localeCompare(b.name), - )) { + const entries = readdirSync(dir, { withFileTypes: true }).sort((a, b) => + collator.compare(a.name, b.name), + ); + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; const rel = prefix === '' ? entry.name : `${prefix}/${entry.name}`; if (entry.isDirectory()) appendArrayInPlace(files, listFiles(join(dir, entry.name), rel)); else files.push(rel); @@ -129,13 +133,15 @@ function assertNoDrift(freshDir: string, generatedDir: string): void { const fresh = listFiles(freshDir); const generated = listFiles(generatedDir); const drifted = new Set(); - for (const file of fresh) { + for (let i = 0, len = fresh.length; i < len; i++) { + const file = fresh[i]; if (!generated.includes(file)) drifted.add(`${file} (missing from generated)`); else if (digest(join(freshDir, file)) !== digest(join(generatedDir, file))) { drifted.add(`${file} (content drift)`); } } - for (const file of generated) { + for (let i = 0, len = generated.length; i < len; i++) { + const file = generated[i]; if (!fresh.includes(file)) drifted.add(`${file} (stale extra file)`); } if (drifted.size > 0) { diff --git a/apps/desktop/scripts/stage-sidecar.mts b/apps/desktop/scripts/stage-sidecar.mts index c7c9e7061..423b8172d 100644 --- a/apps/desktop/scripts/stage-sidecar.mts +++ b/apps/desktop/scripts/stage-sidecar.mts @@ -44,7 +44,8 @@ function stage(arch: string, cross?: CrossBuild): void { }); const destDir = join(desktopDir, 'sidecar', arch); mkdirSync(destDir, { recursive: true }); - for (const crate of crates) { + for (let i = 0, len = crates.length; i < len; i++) { + const crate = crates[i]; const binary = process.platform === 'win32' ? `${crate}.exe` : crate; const built = join(repoRoot, 'target', ...(cross ? [cross.target] : []), 'release', binary); cpSync(built, join(destDir, binary)); diff --git a/apps/desktop/scripts/verify-artifacts.mts b/apps/desktop/scripts/verify-artifacts.mts index 95ac5afb3..8ccb75aa0 100644 --- a/apps/desktop/scripts/verify-artifacts.mts +++ b/apps/desktop/scripts/verify-artifacts.mts @@ -197,7 +197,8 @@ function verifyNativeBindings(platform: string, resourceDir: string, problems: s if (sqlite !== null) bindings.push(['better-sqlite3', sqlite]); if (keyring !== null) bindings.push(['@napi-rs/keyring', keyring]); - for (const [label, relative] of bindings) { + for (let i = 0, len = bindings.length; i < len; i++) { + const [label, relative] = bindings[i]; const binding = join(RELEASE_DIR, resourceDir, 'app.asar.unpacked', relative); if (!existsSync(binding)) { problems.push(`${resourceDir}: missing native binding ${relative} (${label})`); @@ -251,7 +252,8 @@ function verifyConfigBundle(resourceDir: string, asarPath: string, problems: str function verifyHostRuntime(resourceDir: string, problems: string[]): void { const asarPath = join(RELEASE_DIR, resourceDir, 'app.asar'); let missing = false; - for (const inner of ASAR_HOST_RUNTIME) { + for (let i = 0, len = ASAR_HOST_RUNTIME.length; i < len; i++) { + const inner = ASAR_HOST_RUNTIME[i]; try { // asar's lookup splits on the platform separator — normalize or Windows never matches. statFile(asarPath, inner.replaceAll('/', sep)); @@ -283,7 +285,9 @@ function verifyNoAgentBinaries(resourceDir: string, asarPath: string, problems: ); } const shipped: string[] = []; - for (const raw of listPackage(asarPath, { isPack: false })) { + const packaged = listPackage(asarPath, { isPack: false }); + for (let i = 0, len = packaged.length; i < len; i++) { + const raw = packaged[i]; const normalized = raw.replaceAll('\\', '/'); const entry = normalized[0] === '/' ? normalized.slice(1) : normalized; if (EXCLUDED_MODULE_PREFIXES.some((prefix) => entry.startsWith(prefix))) shipped.push(entry); @@ -293,7 +297,8 @@ function verifyNoAgentBinaries(resourceDir: string, asarPath: string, problems: `${resourceDir}/app.asar: agent platform packages shipped: ${shipped[0]} (+${shipped.length - 1} more)`, ); } - for (const prefix of EXCLUDED_MODULE_PREFIXES) { + for (let i = 0, len = EXCLUDED_MODULE_PREFIXES.length; i < len; i++) { + const prefix = EXCLUDED_MODULE_PREFIXES[i]; const dir = join( RELEASE_DIR, resourceDir, @@ -303,7 +308,9 @@ function verifyNoAgentBinaries(resourceDir: string, asarPath: string, problems: if (!existsSync(dir)) continue; const base = prefix.split('/').at(-1)!; - for (const entry of readdirSync(dir)) { + const unpacked = readdirSync(dir); + for (let j = 0, entryCount = unpacked.length; j < entryCount; j++) { + const entry = unpacked[j]; if (entry.startsWith(base)) { problems.push(`${resourceDir}/app.asar.unpacked: agent platform package shipped: ${entry}`); } @@ -320,7 +327,9 @@ interface FeedEntry { function parseFeedEntries(text: string): FeedEntry[] { const entries: FeedEntry[] = []; let current: FeedEntry | null = null; - for (const line of text.split('\n')) { + const lines = text.split('\n'); + for (let i = 0, len = lines.length; i < len; i++) { + const line = lines[i]; const url = FEED_URL_LINE.exec(line); const sha = FEED_SHA_LINE.exec(line); if (url) entries.push((current = { url: url[1].trim(), sha512: '' })); @@ -356,7 +365,8 @@ async function verifyFeed(feed: string, archTokens: string[], problems: string[] if (!text.includes(`version: ${version}`)) problems.push(`${feed}: version is not ${version}`); const entries = parseFeedEntries(text); if (entries.length === 0) problems.push(`${feed}: no file entries parsed`); - for (const token of archTokens) { + for (let i = 0, len = archTokens.length; i < len; i++) { + const token = archTokens[i]; if (!entries.some((entry) => entry.url.includes(token))) { problems.push(`${feed}: no entry for arch "${token}"`); } @@ -387,11 +397,15 @@ async function main(): Promise { } const problems: string[] = []; - for (const name of expected.artifacts) { - let size: number; + for (let i = 0, len = expected.artifacts.length; i < len; i++) { + const name = expected.artifacts[i]; + let size: number | undefined; try { - size = statSync(join(RELEASE_DIR, name)).size; + size = statSync(join(RELEASE_DIR, name), { throwIfNoEntry: false })?.size; } catch { + size = undefined; + } + if (size === undefined) { problems.push(`missing artifact: ${name}`); continue; } @@ -406,14 +420,18 @@ async function main(): Promise { verifyFeed(feed, archTokens, problems), ), ); - for (const resourceDir of expected.resourceDirs) { + for (let i = 0, len = expected.resourceDirs.length; i < len; i++) { + const resourceDir = expected.resourceDirs[i]; verifyHostRuntime(resourceDir, problems); verifyNativeBindings(platform, resourceDir, problems); verifyConfigBundle(resourceDir, join(RELEASE_DIR, resourceDir, 'app.asar'), problems); } if (problems.length > 0) { - for (const problem of problems) console.error(`✗ ${problem}`); + for (let i = 0, len = problems.length; i < len; i++) { + const problem = problems[i]; + console.error(`✗ ${problem}`); + } return 1; } console.log( diff --git a/apps/desktop/src/main/__tests__/brand.test.ts b/apps/desktop/src/main/__tests__/brand.test.ts index aab50c1a2..0a6997874 100644 --- a/apps/desktop/src/main/__tests__/brand.test.ts +++ b/apps/desktop/src/main/__tests__/brand.test.ts @@ -86,7 +86,9 @@ describe('deriveDesktopBrandBase', () => { }), ); if (acme === null || zenith === null) throw new Error('expected identities'); - for (const channel of ['release', 'development'] as const) { + const channels = ['release', 'development'] as const; + for (let i = 0, len = channels.length; i < len; i++) { + const channel = channels[i]; const acmeBase = deriveDesktopBrandBase(acme, channel); const zenithBase = deriveDesktopBrandBase(zenith, channel); expect(zenithBase.storageDirName).not.toBe(acmeBase.storageDirName); @@ -97,7 +99,9 @@ describe('deriveDesktopBrandBase', () => { it('never derives the legacy unbranded storage location', () => { const identity = nullthrow(parseDesktopBrandIdentity(rawIdentity()), 'expected identity'); - for (const channel of ['release', 'development'] as const) { + const channels = ['release', 'development'] as const; + for (let i = 0, len = channels.length; i < len; i++) { + const channel = channels[i]; const base = deriveDesktopBrandBase(identity, channel); expect(base.storageDirName).not.toMatch(RE_DEFAULT_PRODUCT); expect(base.appId).not.toMatch(RE_DEFAULT_PRODUCT); diff --git a/apps/desktop/src/main/__tests__/daemon-supervisor.test.ts b/apps/desktop/src/main/__tests__/daemon-supervisor.test.ts index 279475973..d350c5a16 100644 --- a/apps/desktop/src/main/__tests__/daemon-supervisor.test.ts +++ b/apps/desktop/src/main/__tests__/daemon-supervisor.test.ts @@ -74,7 +74,10 @@ function fakeUtilityProcess(): FakeUtilityProcess { return this.on(event, listener); }, emitExit(code) { - for (const listener of exitListeners) listener(code); + for (let i = 0, len = exitListeners.length; i < len; i++) { + const listener = exitListeners[i]; + listener(code); + } }, }; } diff --git a/apps/desktop/src/main/__tests__/updater.test.ts b/apps/desktop/src/main/__tests__/updater.test.ts index 2efb955dd..6efca10d9 100644 --- a/apps/desktop/src/main/__tests__/updater.test.ts +++ b/apps/desktop/src/main/__tests__/updater.test.ts @@ -21,7 +21,11 @@ vi.mock('electron-updater', () => ({ autoUpdater: mocks.autoUpdater })); vi.mock('../constants', () => ({ CHANNEL: 'release' })); function emit(event: string, ...args: unknown[]): void { - for (const listener of mocks.listeners.get(event) ?? []) listener(...args); + const listeners = mocks.listeners.get(event) ?? []; + for (let i = 0, len = listeners.length; i < len; i++) { + const listener = listeners[i]; + listener(...args); + } } describe('desktop updater', () => { diff --git a/apps/desktop/src/main/config-adapters.ts b/apps/desktop/src/main/config-adapters.ts index 634e88566..f66e4c0fb 100644 --- a/apps/desktop/src/main/config-adapters.ts +++ b/apps/desktop/src/main/config-adapters.ts @@ -133,7 +133,8 @@ async function readBoundedBody(response: Response): Promise { } const body = new Uint8Array(length); let offset = 0; - for (const chunk of chunks) { + for (let i = 0, len = chunks.length; i < len; i++) { + const chunk = chunks[i]; body.set(chunk, offset); offset += chunk.byteLength; } diff --git a/apps/desktop/src/main/config-ipc.ts b/apps/desktop/src/main/config-ipc.ts index 3d217bdf1..1a7bf49be 100644 --- a/apps/desktop/src/main/config-ipc.ts +++ b/apps/desktop/src/main/config-ipc.ts @@ -26,7 +26,9 @@ export function registerDesktopConfigIpc(): () => void { return getDesktopConfig().refresh(); }); const unsubscribe = getDesktopConfig().onHotUpdate((keys) => { - for (const window of BrowserWindow.getAllWindows()) { + const windows = BrowserWindow.getAllWindows(); + for (let i = 0, len = windows.length; i < len; i++) { + const window = windows[i]; if (!window.isDestroyed()) window.webContents.send(CONFIG_HOT_UPDATE_CHANNEL, keys); } }); diff --git a/apps/desktop/src/main/config.ts b/apps/desktop/src/main/config.ts index a6b58d8ed..41909377a 100644 --- a/apps/desktop/src/main/config.ts +++ b/apps/desktop/src/main/config.ts @@ -279,9 +279,18 @@ export async function loadEffectiveDefaults( const parsed = JSON.parse(await readFile(overridePath, 'utf8')) as unknown; if (!isRecord(parsed)) throw new TypeError('Local config override must be an object'); const patched = applyConfigPatch(defaults, parsed as Readonly>); - return Object.fromEntries( - Object.entries(patched).filter((entry) => entry[1] !== null), - ) as Record; + return Object.entries(patched).reduce>((acc, [key, value]) => { + if (value !== null) { + // Own data property, never a prototype write: `acc.__proto__ = …` would mutate the object. + Object.defineProperty(acc, key, { + configurable: true, + enumerable: true, + value, + writable: true, + }); + } + return acc; + }, {}); } catch (error) { if (isNodeError(error) && error.code === 'ENOENT') return cloneSnapshot(defaults); log.warn('Ignoring invalid local config override'); @@ -367,7 +376,9 @@ function parseEndpoint(value: unknown): string | null { function parseKeyring(value: unknown): Readonly> { if (!isRecord(value)) throw new TypeError('Config keyrings must contain strings'); const keyring: Record = {}; - for (const [key, entry] of Object.entries(value)) { + const entries = Object.entries(value); + for (let i = 0, len = entries.length; i < len; i++) { + const [key, entry] = entries[i]; if (typeof entry !== 'string') throw new TypeError('Config keyrings must contain strings'); keyring[key] = entry; } @@ -376,7 +387,9 @@ function parseKeyring(value: unknown): Readonly> { function parseConfigValues(value: Record): Readonly> { const defaults: Record = {}; - for (const [key, entry] of Object.entries(value)) { + const entries = Object.entries(value); + for (let i = 0, len = entries.length; i < len; i++) { + const [key, entry] = entries[i]; if (!isConfigValue(entry)) throw new TypeError('Config defaults must contain JSON values'); defaults[key] = structuredClone(entry); } diff --git a/apps/desktop/src/main/editors.ts b/apps/desktop/src/main/editors.ts index 71695b508..2685e0edf 100644 --- a/apps/desktop/src/main/editors.ts +++ b/apps/desktop/src/main/editors.ts @@ -135,12 +135,16 @@ export function editorTargets( ): EditorTarget[] { const targets: EditorTarget[] = []; if (platform !== 'win32' && candidate.cli !== undefined) { - for (const file of executableSearchLocations(candidate.cli)) { + const files = executableSearchLocations(candidate.cli); + for (let i = 0, len = files.length; i < len; i++) { + const file = files[i]; targets.push({ kind: 'executable', file }); } } if (platform === 'darwin' && candidate.macApp !== undefined) { - for (const root of ['/Applications', join(homedir(), 'Applications')]) { + const roots = ['/Applications', join(homedir(), 'Applications')]; + for (let i = 0, len = roots.length; i < len; i++) { + const root = roots[i]; targets.push({ kind: 'mac-app', bundle: join(root, candidate.macApp), @@ -149,7 +153,9 @@ export function editorTargets( } } if (platform === 'win32' && candidate.windowsExe !== undefined) { - for (const root of windowsProgramRoots()) { + const roots = windowsProgramRoots(); + for (let i = 0, len = roots.length; i < len; i++) { + const root = roots[i]; targets.push({ kind: 'executable', file: join(root, candidate.windowsExe) }); } } diff --git a/apps/desktop/src/renderer/src/shell/browser/browser-webview-pane.tsx b/apps/desktop/src/renderer/src/shell/browser/browser-webview-pane.tsx index 9bdf07919..15348edff 100644 --- a/apps/desktop/src/renderer/src/shell/browser/browser-webview-pane.tsx +++ b/apps/desktop/src/renderer/src/shell/browser/browser-webview-pane.tsx @@ -128,6 +128,12 @@ export function BrowserWebviewPane({ const syncDocument = (): void => { ready = true; markBrowserWebviewReady(tabId); + /* `nav` mirrors an external event target (the guest webview). This setter normally runs + * from webview events, but the effect also invokes it once synchronously via the + * post-subscribe probe below, closing the race where a cached page finished loading + * before the listeners attached. There is no earlier call site: the webview element + * itself arrives via state, so the probe must live in the effect that subscribes. */ + // eslint-disable-next-line vibe-proof/react-no-use-effect-watching -- see above setNav((prev) => ({ ...prev, isLoading: webview.isLoading(), diff --git a/apps/desktop/src/renderer/src/shell/browser/webview-registry.ts b/apps/desktop/src/renderer/src/shell/browser/webview-registry.ts index f6747b785..aed68f1cd 100644 --- a/apps/desktop/src/renderer/src/shell/browser/webview-registry.ts +++ b/apps/desktop/src/renderer/src/shell/browser/webview-registry.ts @@ -31,7 +31,10 @@ export function registerBrowserWebview(tabId: string, webview: WebviewTag | null else webviews.delete(tabId); // Wake callers waiting on an entry that was removed or replaced so they can follow the map. previous?.resolveReady(); - for (const resolve of registrationWaiters.get(tabId) ?? []) resolve(entry); + const waiters = registrationWaiters.get(tabId); + if (waiters != null) { + for (const resolve of waiters) resolve(entry); + } registrationWaiters.delete(tabId); } diff --git a/apps/desktop/src/renderer/src/shell/chrome/chrome.tsx b/apps/desktop/src/renderer/src/shell/chrome/chrome.tsx index 5108b954e..82dadf397 100644 --- a/apps/desktop/src/renderer/src/shell/chrome/chrome.tsx +++ b/apps/desktop/src/renderer/src/shell/chrome/chrome.tsx @@ -459,6 +459,14 @@ function ChromeSlotTarget({ ); } +const nativeTrafficLightInsetJsx = ( +
+); + +const windowControlsInsetJsx = ( +
+); + function StableLeftChrome({ contentRef, hasNativeTrafficLights, @@ -474,7 +482,7 @@ function StableLeftChrome({ ref={contentRef} className="pointer-events-none flex h-full items-center gap-(--lc-chrome-control-gap)" > - {hasNativeTrafficLights ? : null} + {hasNativeTrafficLights ? nativeTrafficLightInsetJsx : null} {children}
@@ -573,7 +581,7 @@ function StableRightChrome({ {children} {/* Reserve the space the persistent window-controls layer (DesktopWindowControls, mounted at the app root) floats over, so the panel toggles never sit under it. */} - {showWindowControls ? : null} + {showWindowControls ? windowControlsInsetJsx : null} ); @@ -680,14 +688,6 @@ function ResourcesChromeControl({ ); } -function NativeTrafficLightInset(): React.ReactNode { - return
; -} - -function WindowControlsInset(): React.ReactNode { - return
; -} - function createChromeSlotKey( segment: DesktopChromeSegment, position: DesktopChromePosition, diff --git a/apps/desktop/src/renderer/src/shell/desktop-shell.tsx b/apps/desktop/src/renderer/src/shell/desktop-shell.tsx index b51ca143b..083bcf390 100644 --- a/apps/desktop/src/renderer/src/shell/desktop-shell.tsx +++ b/apps/desktop/src/renderer/src/shell/desktop-shell.tsx @@ -37,7 +37,6 @@ import { Card } from 'coss-ui/components/card'; import { toastManager } from 'coss-ui/components/toast'; import { useMediaQuery } from 'coss-ui/hooks/use-media-query'; import { useEffect } from 'foxact/use-abortable-effect'; -import { useLayoutEffect } from 'foxact/use-isomorphic-layout-effect'; import { useSingleton } from 'foxact/use-singleton'; import { useCallback, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; @@ -192,21 +191,24 @@ export function DesktopShell({ const sidebarShortcut = useKeyboardShortcutLabel('desktop.toggle-sidebar'); const bottomPanelShortcut = useKeyboardShortcutLabel('desktop.toggle-bottom-panel'); const rightPanelShortcut = useKeyboardShortcutLabel('desktop.toggle-right-panel'); - // Content boxes reported by the active panel-region instances (docked or maximized overlay). - const [rightContentTarget, setRightContentTarget] = useState(null); - const [bottomContentTarget, setBottomContentTarget] = useState(null); // Persistent portal hosts: React keys a portal by its container, so portaling into the reported // target directly would remount the subtree on every docked↔maximized handoff. Each side portals - // into one stable host div that a layout effect moves between targets — a same-document DOM - // move, preserving the React tree and the terminal's canvas. + // into one stable host div that the active panel-region's callback ref moves between targets — a + // same-document DOM move, preserving the React tree and the terminal's canvas. const { current: rightContentHost } = useSingleton(() => createPanelContentHost()); const { current: bottomContentHost } = useSingleton(() => createPanelContentHost()); - useLayoutEffect(() => { - if (rightContentTarget !== null) rightContentTarget.append(rightContentHost); - }, [rightContentTarget, rightContentHost]); - useLayoutEffect(() => { - if (bottomContentTarget !== null) bottomContentTarget.append(bottomContentHost); - }, [bottomContentTarget, bottomContentHost]); + const attachRightContentHost = useCallback( + (target: HTMLDivElement | null) => { + if (target !== null) target.append(rightContentHost); + }, + [rightContentHost], + ); + const attachBottomContentHost = useCallback( + (target: HTMLDivElement | null) => { + if (target !== null) target.append(bottomContentHost); + }, + [bottomContentHost], + ); // Desktop mounts below the connection gate, so the host is connected whenever this renders. const tConnection = useTranslations('workbench.connection'); const tComposer = useTranslations('workbench.composer'); @@ -510,7 +512,7 @@ export function DesktopShell({ chromeVisible={options.chromeVisible} contentHidden={options.contentHidden} chromeSurface={chromeSurface} - terminalContentTargetRef={setRightContentTarget} + terminalContentTargetRef={attachRightContentHost} onSelectSection={setActiveSection} onAddSection={addRightSection} onCloseSection={(section) => { @@ -548,7 +550,7 @@ export function DesktopShell({ chromeVisible={options.chromeVisible} contentHidden={options.contentHidden} chromeSurface={chromeSurface} - contentTargetRef={setBottomContentTarget} + contentTargetRef={attachBottomContentHost} onSelectTab={(id) => updatePanel((current) => ({ ...current, activeTabId: id }))} onCloseTab={(id) => closeTab(id)} onAddWindow={(type) => addWindow(type)} @@ -589,7 +591,8 @@ export function DesktopShell({ // Browser webviews live here permanently: unmounting or DOM-moving a webview // reloads it, so section and tab switches only toggle visibility. const activeIsBrowser = rightPanel.activeSection === 'browser'; - for (const tab of rightPanel.browser.tabs) { + for (let i = 0, len = rightPanel.browser.tabs.length; i < len; i++) { + const tab = rightPanel.browser.tabs[i]; items.push({ id: tab.id, active: activeIsBrowser && tab.id === rightPanel.browser.activeTabId, diff --git a/apps/desktop/src/renderer/src/shell/layout/sash-drag-style.ts b/apps/desktop/src/renderer/src/shell/layout/sash-drag-style.ts index 4acf3eb9d..5cc95e5c9 100644 --- a/apps/desktop/src/renderer/src/shell/layout/sash-drag-style.ts +++ b/apps/desktop/src/renderer/src/shell/layout/sash-drag-style.ts @@ -82,7 +82,10 @@ export function createSashDragStyleWriter( }; const restore = (): void => { - for (const [style, property, value] of touched) style.setProperty(property, value); + for (let i = 0, len = touched.length; i < len; i++) { + const [style, property, value] = touched[i]; + style.setProperty(property, value); + } touched.length = 0; }; diff --git a/apps/mobile/package.json b/apps/mobile/package.json index cd96dbfc4..dc9bcd36c 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -56,8 +56,8 @@ "expo-task-manager": "~57.0.2", "expo-updates": "~57.0.6", "expo-web-browser": "~57.0.0", - "foxact": "^0.3.8", - "foxts": "^5.8.0", + "foxact": "^0.3.10", + "foxts": "^5.9.1", "heroui-native": "1.0.6", "lucide-react-native": "^1.25.0", "posthog-react-native": "^4.60.0", diff --git a/apps/mobile/scripts/generate-terminal-themes.mjs b/apps/mobile/scripts/generate-terminal-themes.mjs index ce336e9f4..23c98ecdc 100644 --- a/apps/mobile/scripts/generate-terminal-themes.mjs +++ b/apps/mobile/scripts/generate-terminal-themes.mjs @@ -21,10 +21,11 @@ const SCHEMES = [ 'Gruvbox Dark', ]; -const hex = (color) => - color +function hex(color) { + return color ? `#${[color.r, color.g, color.b].map((v) => v.toString(16).padStart(2, '0')).join('')}` : undefined; +} async function main() { const require = createRequire(import.meta.url); @@ -32,24 +33,20 @@ async function main() { const resttyVersion = require(join(dirname(resttyEntry), '..', 'package.json')).version; const { getBuiltinTheme } = await import(resttyEntry); - const themes = Object.fromEntries( - SCHEMES.map((name) => { - const { colors } = getBuiltinTheme(name); - return [ - name, - { - background: hex(colors.background), - foreground: hex(colors.foreground), - cursorColor: hex(colors.cursor), - selectionBackground: hex(colors.selectionBackground), - selectionForeground: hex(colors.selectionForeground), - // ANSI 0-15 only: entries 16-255 are the standard xterm cube ghostty - // derives itself. - palette: colors.palette.slice(0, 16).map(hex), - }, - ]; - }), - ); + const themes = SCHEMES.reduce((acc, name) => { + const { colors } = getBuiltinTheme(name); + acc[name] = { + background: hex(colors.background), + foreground: hex(colors.foreground), + cursorColor: hex(colors.cursor), + selectionBackground: hex(colors.selectionBackground), + selectionForeground: hex(colors.selectionForeground), + // ANSI 0-15 only: entries 16-255 are the standard xterm cube ghostty + // derives itself. + palette: colors.palette.slice(0, 16).map(hex), + }; + return acc; + }, {}); const out = `// Generated by scripts/generate-terminal-themes.mjs from restty@${resttyVersion} // builtin themes — do not edit by hand; re-run the script after a restty bump. diff --git a/apps/mobile/scripts/render-config-bundle.mts b/apps/mobile/scripts/render-config-bundle.mts index c203128fd..aa12c8ad0 100644 --- a/apps/mobile/scripts/render-config-bundle.mts +++ b/apps/mobile/scripts/render-config-bundle.mts @@ -37,6 +37,8 @@ const USAGE = String.raw`Usage: config:render \ const MOBILE_PLATFORMS = ['ios', 'android'] as const; type MobilePlatform = (typeof MOBILE_PLATFORMS)[number]; +const collator = new Intl.Collator(); + function bail(message: string): never { console.error(`config:render: ${message}\n\n${USAGE}`); process.exit(1); @@ -83,7 +85,8 @@ async function renderInto( >; try { // Both platforms render in one invocation so they can never drift apart in source or inputs. - for (const platform of MOBILE_PLATFORMS) { + for (let i = 0, len = MOBILE_PLATFORMS.length; i < len; i++) { + const platform = MOBILE_PLATFORMS[i]; const outPath = join(workDir, `${platform}.json`); const releaseManifest = releaseManifests[platform]; // eslint-disable-next-line no-await-in-loop -- renders share pinned checkouts sequentially @@ -142,9 +145,11 @@ async function renderInto( function listFiles(dir: string, prefix = ''): string[] { const files: string[] = []; - for (const entry of readdirSync(dir, { withFileTypes: true }).sort((a, b) => - a.name.localeCompare(b.name), - )) { + const entries = readdirSync(dir, { withFileTypes: true }).sort((a, b) => + collator.compare(a.name, b.name), + ); + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; const rel = prefix === '' ? entry.name : `${prefix}/${entry.name}`; if (entry.isDirectory()) appendArrayInPlace(files, listFiles(join(dir, entry.name), rel)); else files.push(rel); @@ -171,13 +176,15 @@ function assertNoDrift( const fresh = listFiles(freshDir).filter(relevant); const real = listFiles(realDir).filter(relevant); const drifted = new Set(); - for (const file of fresh) { + for (let i = 0, len = fresh.length; i < len; i++) { + const file = fresh[i]; if (!real.includes(file)) drifted.add(`${file} (missing from ${label})`); else if (digest(join(freshDir, file)) !== digest(join(realDir, file))) { drifted.add(`${file} (content drift)`); } } - for (const file of real) { + for (let i = 0, len = real.length; i < len; i++) { + const file = real[i]; if (!fresh.includes(file)) drifted.add(`${file} (stale extra file)`); } if (drifted.size > 0) { diff --git a/apps/mobile/src/app/session/[sessionId].tsx b/apps/mobile/src/app/session/[sessionId].tsx index 9bd556c51..17d7b3043 100644 --- a/apps/mobile/src/app/session/[sessionId].tsx +++ b/apps/mobile/src/app/session/[sessionId].tsx @@ -57,7 +57,7 @@ function SessionScreen(): React.ReactNode { const sessionId: SessionId | null = parsed.success ? parsed.data : null; const { sessions, refresh } = useSessions(); - // eslint-disable-next-line sukka/react-no-performance-impacting-array-find -- one lookup against the thread list; the Map the rule asks for costs the same walk to build each render + // eslint-disable-next-line vibe-proof/react-no-performance-impacting-array-find -- one lookup against the thread list; the Map the rule asks for costs the same walk to build each render const session = sessions.find((entry) => entry.sessionId === sessionId); // A deep link or a notification can open a thread the snapshot has never listed. Without its // record there is no `kind`/`historyId`, so the seed reads nothing and the past renders as empty diff --git a/apps/mobile/src/components/conversation/prompt-dock/permission-prompt.tsx b/apps/mobile/src/components/conversation/prompt-dock/permission-prompt.tsx index 9caac004e..04419e0c6 100644 --- a/apps/mobile/src/components/conversation/prompt-dock/permission-prompt.tsx +++ b/apps/mobile/src/components/conversation/prompt-dock/permission-prompt.tsx @@ -30,18 +30,26 @@ interface DetailRow { * fields through `locations`/`content`, and the model keeps the rest. */ function detailRows(toolCall: ToolCallUpdate): DetailRow[] { const rows: DetailRow[] = []; - for (const location of toolCall.locations ?? []) { - rows.push({ key: `loc:${location.path}`, value: location.path }); + if (toolCall.locations != null) { + for (let i = 0, len = toolCall.locations.length; i < len; i++) { + const location = toolCall.locations[i]; + rows.push({ key: `loc:${location.path}`, value: location.path }); + } } - for (const content of toolCall.content ?? []) { - if (content.type === 'diff' && !rows.some((row) => row.value === content.path)) { - rows.push({ key: `diff:${content.path}`, value: content.path }); + if (toolCall.content != null) { + for (let i = 0, len = toolCall.content.length; i < len; i++) { + const content = toolCall.content[i]; + if (content.type === 'diff' && !rows.some((row) => row.value === content.path)) { + rows.push({ key: `diff:${content.path}`, value: content.path }); + } } } const input = toolCall.rawInput; if (typeof input === 'object' && input !== null && !Array.isArray(input)) { const record = input as Record; - for (const key of ['file_path', 'path', 'notebook_path', 'filePath']) { + const pathKeys = ['file_path', 'path', 'notebook_path', 'filePath']; + for (let i = 0, len = pathKeys.length; i < len; i++) { + const key = pathKeys[i]; const value = record[key]; if (typeof value === 'string' && !rows.some((row) => row.value === value)) { rows.push({ key: `path:${key}`, value }); diff --git a/apps/mobile/src/components/host/thread-list/thread-list.tsx b/apps/mobile/src/components/host/thread-list/thread-list.tsx index fa8558e50..d438a7ebc 100644 --- a/apps/mobile/src/components/host/thread-list/thread-list.tsx +++ b/apps/mobile/src/components/host/thread-list/thread-list.tsx @@ -5,7 +5,7 @@ import type { ThreadGroup } from '@linkcode/ui/native'; import { useEffect, useState } from 'react'; import { ThreadRow } from './thread-row'; -const MINUTE = 60_000; +const MINUTE = 60000; /** The thread inbox body: one collapsible section per group. Grouping is decided by the * caller — this only renders it. Collapsed keys live here because the state is presentational: diff --git a/apps/mobile/src/components/shell/host-connection-scope.tsx b/apps/mobile/src/components/shell/host-connection-scope.tsx index 98c1b3664..812d0275d 100644 --- a/apps/mobile/src/components/shell/host-connection-scope.tsx +++ b/apps/mobile/src/components/shell/host-connection-scope.tsx @@ -17,7 +17,10 @@ export function HostConnectionScope({ children }: React.PropsWithChildren): Reac const keep = new Set( keepHostsConnected ? hosts.map((entry) => entry.id) : host ? [host.id] : [], ); - for (const entry of hosts) if (keep.has(entry.id)) connectionFor(entry); + for (let i = 0, len = hosts.length; i < len; i++) { + const entry = hosts[i]; + if (keep.has(entry.id)) connectionFor(entry); + } pruneConnections(keep); }, [host, hosts, keepHostsConnected]); diff --git a/apps/mobile/src/components/terminal/terminal-renderer.native.tsx b/apps/mobile/src/components/terminal/terminal-renderer.native.tsx index ed263e315..c91a30033 100644 --- a/apps/mobile/src/components/terminal/terminal-renderer.native.tsx +++ b/apps/mobile/src/components/terminal/terminal-renderer.native.tsx @@ -41,7 +41,8 @@ export default function TerminalRenderer({ events(events) { const terminal = terminalRef.current; if (!terminal) return; - for (const event of events) { + for (let i = 0, len = events.length; i < len; i++) { + const event = events[i]; // Remote resizes are not applied: the ghostty grid derives from the // local view size, so only 'write' payloads reach the surface. if (event.type === 'write') terminal.writeText(event.data).catch(reportError); diff --git a/apps/mobile/src/runtime/config/__tests__/adapters.test.ts b/apps/mobile/src/runtime/config/__tests__/adapters.test.ts index fc635b3d2..2b47d48f5 100644 --- a/apps/mobile/src/runtime/config/__tests__/adapters.test.ts +++ b/apps/mobile/src/runtime/config/__tests__/adapters.test.ts @@ -71,7 +71,8 @@ describe('mobile configuration adapters', () => { 'ui.theme.primary': 'atomic-dotted-key', }, }); - for (const { key, value } of storage.writes) { + for (let i = 0, len = storage.writes.length; i < len; i++) { + const { key, value } = storage.writes[i]; if (!key.includes(':normal:')) continue; expect(() => JSON.parse(value)).not.toThrow(); } diff --git a/apps/mobile/src/runtime/config/__tests__/bundled.test.ts b/apps/mobile/src/runtime/config/__tests__/bundled.test.ts index 3f3365c90..21cd679b4 100644 --- a/apps/mobile/src/runtime/config/__tests__/bundled.test.ts +++ b/apps/mobile/src/runtime/config/__tests__/bundled.test.ts @@ -28,10 +28,12 @@ describe('bundledConfigFromModule', () => { }); it('derives the bootstrap and definitions from a generated platform bundle', async () => { - for (const [suffix, platform] of [ + const cases = [ ['-ios', 'ios'], ['-android', 'android'], - ] as const) { + ] as const; + for (let i = 0, len = cases.length; i < len; i++) { + const [suffix, platform] = cases[i]; const { bootstrap, defaults, definitions } = bundledConfigFromModule({ // eslint-disable-next-line no-await-in-loop -- two small fixture reads bundle: await loadFixture(suffix), diff --git a/apps/mobile/src/runtime/product-analytics.ts b/apps/mobile/src/runtime/product-analytics.ts index 25e886709..e09f51f05 100644 --- a/apps/mobile/src/runtime/product-analytics.ts +++ b/apps/mobile/src/runtime/product-analytics.ts @@ -210,10 +210,12 @@ export function sanitizeMobileProductAnalyticsEvent< const eventProperties = EVENT_PROPERTIES.get(event.event); if (!eventProperties) return null; - const properties = Object.fromEntries( - Object.entries(event.properties ?? {}).filter( - ([key]) => COMMON_PROPERTIES.has(key) || eventProperties.has(key), - ), + const properties = Object.entries(event.properties ?? {}).reduce>( + (acc, [key, value]) => { + if (COMMON_PROPERTIES.has(key) || eventProperties.has(key)) acc[key] = value; + return acc; + }, + {}, ); return { ...event, properties, $set: undefined, $set_once: undefined }; diff --git a/apps/mobile/src/runtime/use-seeded-conversation.ts b/apps/mobile/src/runtime/use-seeded-conversation.ts index 329306391..60f4068f2 100644 --- a/apps/mobile/src/runtime/use-seeded-conversation.ts +++ b/apps/mobile/src/runtime/use-seeded-conversation.ts @@ -51,7 +51,10 @@ export function useSeededConversation( cursor, forceRefresh: page === 0, }); - for (const entry of result.events) events.push({ event: entry.event, ts: entry.ts }); + for (let i = 0, len = result.events.length; i < len; i++) { + const entry = result.events[i]; + events.push({ event: entry.event, ts: entry.ts }); + } cursor = result.cursor; if (cursor === undefined) break; } diff --git a/apps/mobile/src/stores/analytics-store.ts b/apps/mobile/src/stores/analytics-store.ts index 6b083b33a..4da8f6cc2 100644 --- a/apps/mobile/src/stores/analytics-store.ts +++ b/apps/mobile/src/stores/analytics-store.ts @@ -33,7 +33,7 @@ export function useAnalyticsPreferenceHydrated(): boolean { setHydrated(true), ); if (useAnalyticsPreferenceStore.persist.hasHydrated()) { - const timer = setTimeout(() => setHydrated(true), 0); + const timer = setTimeout(setHydrated, 0, true); return () => { clearTimeout(timer); unsubscribe(); diff --git a/apps/webview/e2e/browser-smoke.e2e.mts b/apps/webview/e2e/browser-smoke.e2e.mts index 42e8d30ea..001b50b10 100644 --- a/apps/webview/e2e/browser-smoke.e2e.mts +++ b/apps/webview/e2e/browser-smoke.e2e.mts @@ -146,7 +146,7 @@ async function verifyActivityRunHierarchy(page: Page): Promise { ); if (!(body instanceof HTMLElement)) throw new Error('Missing expanded activity body'); - const children = [...body.children].map((row) => { + const children = Array.from(body.children, (row) => { const child = row.firstElementChild; if (!(child instanceof HTMLElement)) throw new Error('Missing activity child header'); return { @@ -192,7 +192,8 @@ async function verifyLongThreadVirtualization(page: Page): Promise { } }; const process = (records: MutationRecord[]): void => { - for (const record of records) { + for (let i = 0, len = records.length; i < len; i++) { + const record = records[i]; for (const node of record.addedNodes) collect(node); } }; diff --git a/apps/webview/package.json b/apps/webview/package.json index bfe924ac4..635ffa809 100644 --- a/apps/webview/package.json +++ b/apps/webview/package.json @@ -28,8 +28,8 @@ "@sentry/react": "10.62.0", "better-auth": "1.7.0-rc.2", "coss-ui": "workspace:*", - "foxact": "^0.3.8", - "foxts": "^5.8.0", + "foxact": "^0.3.10", + "foxts": "^5.9.1", "lucide-react": "catalog:", "react": "catalog:", "react-dom": "catalog:", diff --git a/apps/webview/src/components/data-table/core/use-table-sort.ts b/apps/webview/src/components/data-table/core/use-table-sort.ts index 520a3d562..ba34bc23c 100644 --- a/apps/webview/src/components/data-table/core/use-table-sort.ts +++ b/apps/webview/src/components/data-table/core/use-table-sort.ts @@ -96,7 +96,8 @@ export function useTableSort({ } else if (mode === 'single') { // activating a column replaces the current sort — evict the rest atomically const payload: TableSortsState = { [columnId]: direction }; - for (const id of prevOrder) { + for (let i = 0, len = prevOrder.length; i < len; i++) { + const id = prevOrder[i]; if (id !== columnId) payload[id] = undefined; } setSortsState(payload); @@ -135,7 +136,9 @@ export function useTableSort({ // getter reads the tracked `sorts` at access time, keeping the preview live. const nextSorts = useMemo(() => { const result: TableSortsState = {}; - for (const column of table?.columns ?? []) { + const columns = table?.columns ?? []; + for (let i = 0, len = columns.length; i < len; i++) { + const column = columns[i]; const { id } = column; Object.defineProperty(result, id, { enumerable: true, get: () => computeNextSort(id) }); } @@ -151,7 +154,11 @@ export function useTableSort({ const someOtherActive = orderState.order.some((id) => id !== columnId); if (!someOtherActive) { const reset: TableSortsState = {}; - for (const key of Object.keys(sorts)) reset[key] = undefined; + const activeKeys = Object.keys(sorts); + for (let i = 0, len = activeKeys.length; i < len; i++) { + const key = activeKeys[i]; + reset[key] = undefined; + } setSortsState({ ...reset, ...defaultSorts }); setOrderState({ order: Object.keys(defaultSorts) }); onAfterSortChange(); diff --git a/apps/webview/src/routes/settings/settings-layout.tsx b/apps/webview/src/routes/settings/settings-layout.tsx index df47593ea..540a29003 100644 --- a/apps/webview/src/routes/settings/settings-layout.tsx +++ b/apps/webview/src/routes/settings/settings-layout.tsx @@ -138,7 +138,7 @@ export function SettingsLayout(): React.ReactNode { }, ]; const visibleGroups = filterSettingsNavGroups(navGroups, searchQuery); - // eslint-disable-next-line sukka/react-no-performance-impacting-array-find -- a handful of static nav items scanned once per render; a Map would be needless ceremony + // eslint-disable-next-line vibe-proof/react-no-performance-impacting-array-find -- a handful of static nav items scanned once per render; a Map would be needless ceremony const activeLabel = navGroups.flatMap((group) => group.items).find((item) => item.active)?.label; return ( diff --git a/eslint-suppressions.json b/eslint-suppressions.json deleted file mode 100644 index b14926e27..000000000 --- a/eslint-suppressions.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "apps/desktop/src/renderer/src/shell/browser/browser-webview-pane.tsx": { - "sukka/react-no-use-effect-watching": { - "count": 1 - } - }, - "apps/desktop/src/renderer/src/shell/desktop-shell.tsx": { - "sukka/react-no-use-effect-watching": { - "count": 2 - } - }, - "apps/mobile/src/app/host/[hostId]/_layout.tsx": { - "sukka/react-no-use-effect-watching": { - "count": 1 - } - }, - "apps/mobile/src/app/host/[hostId]/session/[sessionId].tsx": { - "sukka/react-no-performance-impacting-array-find": { - "count": 1 - } - }, - "packages/client/workbench/src/simulator/panel.tsx": { - "sukka/react-detect-potential-race-condition": { - "count": 2 - }, - "sukka/react-no-performance-impacting-array-find": { - "count": 1 - } - }, - "packages/presentation/ui/src/shell/composer-editor/editor.tsx": { - "sukka/react-no-use-effect-watching": { - "count": 2 - } - } -} diff --git a/package.json b/package.json index c3f9b5893..dcf46f86c 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "license": "BUSL-1.1", "devDependencies": { "@biomejs/biome": "^2.5.5", - "@eslint-sukka/react": "^8.14.2", + "@eslint-sukka/react": "^9.0.1", "@iconify-json/material-icon-theme": "catalog:", "@iconify-json/simple-icons": "catalog:", "@proj-airi/lobe-icons": "catalog:", @@ -51,9 +51,9 @@ "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", "@typescript/native": "npm:typescript@^7.0.2", - "eslint": "^10.8.0", - "eslint-config-sukka": "^8.14.2", - "eslint-formatter-sukka": "^8.14.2", + "eslint": "^10.9.1", + "eslint-config-sukka": "^9.0.1", + "eslint-formatter-sukka": "^9.0.1", "jsdom": "^29.1.1", "react": "catalog:", "react-dom": "catalog:", @@ -63,7 +63,7 @@ "vite": "catalog:", "vitest": "catalog:" }, - "packageManager": "pnpm@11.10.0", + "packageManager": "pnpm@11.24.0", "engines": { "node": ">=24.0.0" } diff --git a/packages/client/core/package.json b/packages/client/core/package.json index 0ceb3fbb4..f9c6fd31e 100644 --- a/packages/client/core/package.json +++ b/packages/client/core/package.json @@ -14,8 +14,8 @@ "dependencies": { "@linkcode/schema": "workspace:*", "@linkcode/transport": "workspace:*", - "foxact": "^0.3.8", - "foxts": "^5.8.0" + "foxact": "^0.3.10", + "foxts": "^5.9.1" }, "devDependencies": { "@types/react": "catalog:", diff --git a/packages/client/core/src/__tests__/conversation-perf.bench.ts b/packages/client/core/src/__tests__/conversation-perf.bench.ts index d81dc42bf..d31134d89 100644 --- a/packages/client/core/src/__tests__/conversation-perf.bench.ts +++ b/packages/client/core/src/__tests__/conversation-perf.bench.ts @@ -133,15 +133,23 @@ function streamTail(shape: LoadShape): AgentEvent[] { function foldAll(events: readonly AgentEvent[]): void { const builder = createConversationBuilder(); - for (const event of events) builder.advance(event); + for (let i = 0, len = events.length; i < len; i++) { + const event = events[i]; + builder.advance(event); + } builder.snapshot(); } function foldStreamingCost(shape: LoadShape): void { const history = seedHistory(shape); const builder = createConversationBuilder(); - for (const event of history) builder.advance(event); - for (const event of streamTail(shape)) { + for (let i = 0, len = history.length; i < len; i++) { + const event = history[i]; + builder.advance(event); + } + const tail = streamTail(shape); + for (let i = 0, len = tail.length; i < len; i++) { + const event = tail[i]; builder.advance(event); // Each live chunk invalidates the cache and forces a fresh items shallow-copy. builder.snapshot(); @@ -160,14 +168,19 @@ function storeStreamingCost(shape: LoadShape): void { const sessionId = 'sess-perf' as SessionId; const history = seedHistory(shape); const buffer = new EventBuffer(); - for (const event of history) buffer.ingest(sessionId, event); + for (let i = 0, len = history.length; i < len; i++) { + const event = history[i]; + buffer.ingest(sessionId, event); + } // createConversationStore only needs the event surface used by sync(). const store = createConversationStore(bufferClient(buffer), sessionId); // Seed fold via first getSnapshot. store.getSnapshot(); - for (const event of streamTail(shape)) { + const tail = streamTail(shape); + for (let i = 0, len = tail.length; i < len; i++) { + const event = tail[i]; buffer.ingest(sessionId, event); store.getSnapshot(); } @@ -176,8 +189,16 @@ function storeStreamingCost(shape: LoadShape): void { function eventBufferSnapshotCost(shape: LoadShape): void { const sessionId = 'sess-buf' as SessionId; const buffer = new EventBuffer(); - for (const event of seedHistory(shape)) buffer.ingest(sessionId, event); - for (const event of streamTail(shape)) buffer.ingest(sessionId, event); + const history = seedHistory(shape); + for (let i = 0, len = history.length; i < len; i++) { + const event = history[i]; + buffer.ingest(sessionId, event); + } + const tail = streamTail(shape); + for (let i = 0, len = tail.length; i < len; i++) { + const event = tail[i]; + buffer.ingest(sessionId, event); + } // snapshot copies the full buffer array when the cache is cold; force cold each time. buffer.ingest(sessionId, textChunk('force', '.')); buffer.snapshot(sessionId); diff --git a/packages/client/core/src/__tests__/conversation-perf.report.test.ts b/packages/client/core/src/__tests__/conversation-perf.report.test.ts index 0a01a1be5..5461f926c 100644 --- a/packages/client/core/src/__tests__/conversation-perf.report.test.ts +++ b/packages/client/core/src/__tests__/conversation-perf.report.test.ts @@ -154,7 +154,10 @@ function fmt(ms: number): string { function foldHistory(history: readonly AgentEvent[]): Conversation { const builder = createConversationBuilder(); - for (const event of history) builder.advance(event); + for (let i = 0, len = history.length; i < len; i++) { + const event = history[i]; + builder.advance(event); + } return builder.snapshot(); } @@ -178,8 +181,12 @@ function reportShape(shape: LoadShape): string { const streamFold = measure(() => { const builder = createConversationBuilder(); - for (const event of history) builder.advance(event); - for (const event of stream) { + for (let i = 0, len = history.length; i < len; i++) { + const event = history[i]; + builder.advance(event); + } + for (let i = 0, len = stream.length; i < len; i++) { + const event = stream[i]; builder.advance(event); builder.snapshot(); } @@ -188,10 +195,14 @@ function reportShape(shape: LoadShape): string { const storeStream = measure(() => { const sessionId = 'sess-perf' as SessionId; const buffer = new EventBuffer(); - for (const event of history) buffer.ingest(sessionId, event); + for (let i = 0, len = history.length; i < len; i++) { + const event = history[i]; + buffer.ingest(sessionId, event); + } const store = createConversationStore(bufferClient(buffer), sessionId); store.getSnapshot(); - for (const event of stream) { + for (let i = 0, len = stream.length; i < len; i++) { + const event = stream[i]; buffer.ingest(sessionId, event); store.getSnapshot(); } diff --git a/packages/client/core/src/__tests__/conversation.test.ts b/packages/client/core/src/__tests__/conversation.test.ts index 2e5b32ca9..061ac44b8 100644 --- a/packages/client/core/src/__tests__/conversation.test.ts +++ b/packages/client/core/src/__tests__/conversation.test.ts @@ -808,7 +808,10 @@ describe('createConversationBuilder', () => { it('advancing event-by-event equals a single fold', () => { const builder = createConversationBuilder(); - for (const event of scenario) builder.advance(event); + for (let i = 0, len = scenario.length; i < len; i++) { + const event = scenario[i]; + builder.advance(event); + } expect(builder.snapshot()).toEqual(buildConversation(scenario)); }); @@ -823,11 +826,19 @@ describe('createConversationBuilder', () => { it('never mutates previously returned snapshots (copy-on-write)', () => { const builder = createConversationBuilder(); - for (const event of scenario.slice(0, 5)) builder.advance(event); + const firstFive = scenario.slice(0, 5); + for (let i = 0, len = firstFive.length; i < len; i++) { + const event = firstFive[i]; + builder.advance(event); + } const before = builder.snapshot(); const frozen = structuredClone(before); - for (const event of scenario.slice(5)) builder.advance(event); + const rest = scenario.slice(5); + for (let i = 0, len = rest.length; i < len; i++) { + const event = rest[i]; + builder.advance(event); + } builder.snapshot(); // The earlier snapshot still shows the pending tool call and the streaming message. expect(before).toEqual(frozen); diff --git a/packages/client/core/src/__tests__/use-sessions.test.tsx b/packages/client/core/src/__tests__/use-sessions.test.tsx index eea626c0c..52deb78e5 100644 --- a/packages/client/core/src/__tests__/use-sessions.test.tsx +++ b/packages/client/core/src/__tests__/use-sessions.test.tsx @@ -4,7 +4,6 @@ import type { Transport, Unsubscribe } from '@linkcode/transport'; import { createWireMessage, pong } from '@linkcode/transport'; import { act, renderHook, waitFor } from '@testing-library/react'; import { noop } from 'foxact/noop'; -import type * as React from 'react'; import { expect, it, vi } from 'vitest'; import { LinkCodeClient } from '../client'; import { LinkCodeProvider, useSessions } from '../react'; @@ -148,7 +147,9 @@ it('coalesces a burst of changes into one refetch behind the one in flight', asy const afterSeed = transport.listCalls; transport.sessions = [session('sess-a', 1), session('sess-b', 2)]; - for (const reason of ['created', 'updated', 'updated'] as const) { + const reasons = ['created', 'updated', 'updated'] as const; + for (let i = 0, len = reasons.length; i < len; i++) { + const reason = reasons[i]; transport.receive({ kind: 'session.changed', sessionId: 'sess-b' as SessionId, reason }); } diff --git a/packages/client/core/src/client.ts b/packages/client/core/src/client.ts index 4ffd9fa2b..af44ac1ef 100644 --- a/packages/client/core/src/client.ts +++ b/packages/client/core/src/client.ts @@ -356,7 +356,10 @@ export class LinkCodeClient { if (wasReady) { const subscribers = [...this.connectionCloseSubs]; this.connectionCloseSubs.clear(); - for (const cb of subscribers) cb(error); + for (let i = 0, len = subscribers.length; i < len; i++) { + const cb = subscribers[i]; + cb(error); + } } } @@ -483,11 +486,15 @@ export class LinkCodeClient { codec: p.codec, }); break; - case 'simulator.stream.frame': - for (const cb of this.simulatorFrameSubs.get(p.udid) ?? []) { - cb({ udid: p.udid, codec: p.codec, key: p.key, data: p.data }); + case 'simulator.stream.frame': { + const frameSubs = this.simulatorFrameSubs.get(p.udid); + if (frameSubs != null) { + for (const cb of frameSubs) { + cb({ udid: p.udid, codec: p.codec, key: p.key, data: p.data }); + } } break; + } case 'asset.listed': this.pending.resolve('assetList', p.replyTo, p.assets); break; diff --git a/packages/client/core/src/client/event-buffer.ts b/packages/client/core/src/client/event-buffer.ts index 1e8e42158..c6a43813c 100644 --- a/packages/client/core/src/client/event-buffer.ts +++ b/packages/client/core/src/client/event-buffer.ts @@ -73,7 +73,12 @@ export class EventBuffer { set.add(cb); // Replay buffered events with their original seqs so a late subscriber sees the full timeline. const buf = this.events.get(sessionId); - if (buf) for (const { event, seq } of buf) cb(event, seq); + if (buf) { + for (let i = 0, len = buf.length; i < len; i++) { + const { event, seq } = buf[i]; + cb(event, seq); + } + } return () => set.delete(cb); } diff --git a/packages/client/core/src/client/loop-log-buffer.ts b/packages/client/core/src/client/loop-log-buffer.ts index ab83b4ffc..b1a868e52 100644 --- a/packages/client/core/src/client/loop-log-buffer.ts +++ b/packages/client/core/src/client/loop-log-buffer.ts @@ -26,8 +26,15 @@ export class LoopLogBuffer { seen.add(entry.seq); merged.push(entry); }; - for (const entry of logs) add(entry); - for (const entry of this.entries.get(loopId) ?? []) add(entry); + for (let i = 0, len = logs.length; i < len; i++) { + const entry = logs[i]; + add(entry); + } + const existing = this.entries.get(loopId) ?? []; + for (let i = 0, len = existing.length; i < len; i++) { + const entry = existing[i]; + add(entry); + } merged.sort((a, b) => a.seq - b.seq); this.commit(loopId, merged, seen); } @@ -79,7 +86,10 @@ export class LoopLogBuffer { private commit(loopId: LoopId, list: LoopLogEntry[], seen: Set): void { if (list.length > MAX_LOG_ENTRIES) { const dropped = list.splice(0, list.length - MAX_LOG_ENTRIES); - for (const entry of dropped) seen.delete(entry.seq); + for (let i = 0, len = dropped.length; i < len; i++) { + const entry = dropped[i]; + seen.delete(entry.seq); + } } this.entries.set(loopId, list); this.seen.set(loopId, seen); diff --git a/packages/client/core/src/client/pending-registry.ts b/packages/client/core/src/client/pending-registry.ts index 79e7c638e..673fa935c 100644 --- a/packages/client/core/src/client/pending-registry.ts +++ b/packages/client/core/src/client/pending-registry.ts @@ -245,7 +245,9 @@ export class PendingRegistry { /** Reject a pending request by id alone — a `request.failed` reply doesn't carry which kind it was. */ reject(id: string, err: Error): boolean { - for (const map of Object.values(this.maps)) { + const maps = Object.values(this.maps); + for (let i = 0, len = maps.length; i < len; i++) { + const map = maps[i]; const pending = map.get(id); if (pending) { map.delete(id); @@ -258,7 +260,9 @@ export class PendingRegistry { /** Reject every in-flight request across every kind, so awaiters get an error instead of hanging forever. */ failAll(err: Error): void { - for (const map of Object.values(this.maps)) { + const maps = Object.values(this.maps); + for (let i = 0, len = maps.length; i < len; i++) { + const map = maps[i]; for (const pending of map.values()) pending.reject(err); map.clear(); } diff --git a/packages/client/core/src/client/terminal-channel.ts b/packages/client/core/src/client/terminal-channel.ts index b527caf0e..899738157 100644 --- a/packages/client/core/src/client/terminal-channel.ts +++ b/packages/client/core/src/client/terminal-channel.ts @@ -319,7 +319,10 @@ export class TerminalChannel { set.add(cb); const replay = this.replay.get(terminalId); if (replay) { - for (const event of replay) if (event.type === 'write') cb(event.data); + for (let i = 0, len = replay.length; i < len; i++) { + const event = replay[i]; + if (event.type === 'write') cb(event.data); + } } return () => set.delete(cb); } @@ -332,7 +335,12 @@ export class TerminalChannel { } set.add(cb); const replay = this.replay.get(terminalId); - if (replay) for (const event of replay) cb(event); + if (replay) { + for (let i = 0, len = replay.length; i < len; i++) { + const event = replay[i]; + cb(event); + } + } return () => set.delete(cb); } @@ -445,7 +453,10 @@ export class TerminalChannel { ): { terminal: TerminalMetadata; truncated: boolean } { this.adoptAttachment(terminal, state); if (truncated) this.markReplayTruncated(terminal.terminalId); - for (const event of replay) this.ingestEvent(terminal.terminalId, event); + for (let i = 0, len = replay.length; i < len; i++) { + const event = replay[i]; + this.ingestEvent(terminal.terminalId, event); + } this.lastSeq.set( terminal.terminalId, Math.max(this.lastSeq.get(terminal.terminalId) ?? 0, cutoffSeq), diff --git a/packages/client/core/src/conversation-store.ts b/packages/client/core/src/conversation-store.ts index 8ec749625..9929cb1d4 100644 --- a/packages/client/core/src/conversation-store.ts +++ b/packages/client/core/src/conversation-store.ts @@ -122,7 +122,8 @@ export function createConversationStore( const seedToolIds = new Set(); const seedUserMessages = new Map(); if (seed) { - for (const { event } of seed.events) { + for (let i = 0, len = seed.events.length; i < len; i++) { + const { event } = seed.events[i]; switch (event.type) { case 'agent-message': case 'agent-message-chunk': @@ -155,11 +156,16 @@ export function createConversationStore( const sync = (): void => { if (!seeded) { seeded = true; - if (seed) for (const entry of seed.events) builder.advance(entry.event, entry.ts); + if (seed) { + for (let i = 0, len = seed.events.length; i < len; i++) { + const entry = seed.events[i]; + builder.advance(entry.event, entry.ts); + } + } } if (client.eventSeq(sessionId) <= consumedSeq) return; const events = client.eventsSnapshot(sessionId); - for (let i = firstIndexAfter(events, consumedSeq); i < events.length; i += 1) { + for (let i = firstIndexAfter(events, consumedSeq), len = events.length; i < len; i += 1) { const { event, seq, receivedAt } = events[i]; if (seq > uptoSeq) { builder.advance(event, receivedAt); diff --git a/packages/client/core/src/conversation.ts b/packages/client/core/src/conversation.ts index 35738746c..33fc4373a 100644 --- a/packages/client/core/src/conversation.ts +++ b/packages/client/core/src/conversation.ts @@ -218,7 +218,10 @@ export function createConversationBuilder(): ConversationBuilder { if (cut < 0) return; entries = entries.slice(0, cut); projection = createConversationProjection(); - for (const entry of entries) projection.advance(entry.event, entry.receivedAt); + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; + projection.advance(entry.event, entry.receivedAt); + } }, snapshot: () => projection.snapshot(), }; @@ -741,7 +744,10 @@ function createConversationProjection(): ConversationBuilder { /** Build a structured Conversation from the flat, append-only agent event stream. Pure & deterministic. */ export function buildConversation(events: readonly AgentEvent[]): Conversation { const builder = createConversationBuilder(); - for (const event of events) builder.advance(event); + for (let i = 0, len = events.length; i < len; i++) { + const event = events[i]; + builder.advance(event); + } return builder.snapshot(); } diff --git a/packages/client/core/src/react.tsx b/packages/client/core/src/react.tsx index 090a3f982..e667fff3b 100644 --- a/packages/client/core/src/react.tsx +++ b/packages/client/core/src/react.tsx @@ -8,7 +8,6 @@ import type { import { noop } from 'foxact/noop'; import { nullthrow } from 'foxact/nullthrow'; import { useEffect } from 'foxact/use-abortable-effect'; -import type * as React from 'react'; import { createContext, useCallback, diff --git a/packages/client/sdk/package.json b/packages/client/sdk/package.json index 5fba6b381..4dd99d6b8 100644 --- a/packages/client/sdk/package.json +++ b/packages/client/sdk/package.json @@ -16,7 +16,7 @@ "@linkcode/client-core": "workspace:*", "@linkcode/schema": "workspace:*", "@linkcode/transport": "workspace:*", - "foxts": "^5.8.0" + "foxts": "^5.9.1" }, "devDependencies": { "typescript": "catalog:" diff --git a/packages/client/workbench/package.json b/packages/client/workbench/package.json index 25ef39bbc..bc9bad28b 100644 --- a/packages/client/workbench/package.json +++ b/packages/client/workbench/package.json @@ -24,8 +24,8 @@ "@linkcode/transport": "workspace:*", "@linkcode/ui": "workspace:*", "coss-ui": "workspace:*", - "foxact": "^0.3.8", - "foxts": "^5.8.0", + "foxact": "^0.3.10", + "foxts": "^5.9.1", "lucide-react": "catalog:", "motion": "^12.42.2", "pathe": "^2.0.3", diff --git a/packages/client/workbench/src/agent-runtime/onboarding.ts b/packages/client/workbench/src/agent-runtime/onboarding.ts index ffb8cec0b..e9468386e 100644 --- a/packages/client/workbench/src/agent-runtime/onboarding.ts +++ b/packages/client/workbench/src/agent-runtime/onboarding.ts @@ -60,9 +60,9 @@ export function dropConfirmedInstalls( runtimes: AgentRuntimes, ): AssetActivityMap { const next: AssetActivityMap = {}; - for (const [kind, assetId] of Object.entries(AGENT_ASSET_IDS) as Array< - [AgentKind, ManagedAssetId] - >) { + const assetEntries = Object.entries(AGENT_ASSET_IDS) as Array<[AgentKind, ManagedAssetId]>; + for (let i = 0, len = assetEntries.length; i < len; i++) { + const [kind, assetId] = assetEntries[i]; const key = managedAssetKey(assetId); const entry = activity[key]; if (!entry) continue; @@ -106,9 +106,9 @@ export function deriveAgentRuntimeCues( ): AgentRuntimeCues { const cues: AgentRuntimeCues = {}; if (!runtimes) return cues; - for (const [kind, runtime] of Object.entries(runtimes) as Array< - [AgentKind, AgentRuntimeAvailability] - >) { + const runtimeEntries = Object.entries(runtimes) as Array<[AgentKind, AgentRuntimeAvailability]>; + for (let i = 0, len = runtimeEntries.length; i < len; i++) { + const [kind, runtime] = runtimeEntries[i]; const cue = deriveCue( kind, runtime, diff --git a/packages/client/workbench/src/analytics/product-analytics.ts b/packages/client/workbench/src/analytics/product-analytics.ts index 80ea4728d..83da994ba 100644 --- a/packages/client/workbench/src/analytics/product-analytics.ts +++ b/packages/client/workbench/src/analytics/product-analytics.ts @@ -229,10 +229,12 @@ export function sanitizeProductAnalyticsEvent< const eventProperties = EVENT_PROPERTIES.get(event.event); if (!eventProperties) return null; - const properties = Object.fromEntries( - Object.entries(event.properties ?? {}).filter( - ([key]) => COMMON_PROPERTIES.has(key) || eventProperties.has(key), - ), + const properties = Object.entries(event.properties ?? {}).reduce>( + (acc, [key, value]) => { + if (COMMON_PROPERTIES.has(key) || eventProperties.has(key)) acc[key] = value; + return acc; + }, + {}, ); return { ...event, properties, $set: undefined, $set_once: undefined }; diff --git a/packages/client/workbench/src/app/app-providers.tsx b/packages/client/workbench/src/app/app-providers.tsx index 53a93ea4e..5ca3e87fc 100644 --- a/packages/client/workbench/src/app/app-providers.tsx +++ b/packages/client/workbench/src/app/app-providers.tsx @@ -3,7 +3,6 @@ import { defaultLocale, getMessages, resolveLocale } from '@linkcode/i18n'; import { useKeyboardShortcutListener } from '@linkcode/ui'; import { AnchoredToastProvider, ToastProvider } from 'coss-ui/components/toast'; import { ComposeContextProvider } from 'foxact/compose-context-provider'; -import type * as React from 'react'; import { useMemo } from 'react'; import { IntlProvider } from 'use-intl'; import { AppearanceRenderPrefsProvider } from '../settings/appearance-render-prefs'; diff --git a/packages/client/workbench/src/app/workbench-providers.tsx b/packages/client/workbench/src/app/workbench-providers.tsx index 64b8383ce..6c7bed3ef 100644 --- a/packages/client/workbench/src/app/workbench-providers.tsx +++ b/packages/client/workbench/src/app/workbench-providers.tsx @@ -1,4 +1,3 @@ -import type * as React from 'react'; import type { WorkbenchConnectionSource } from '../runtime/connection-controller'; import { DebugProvider } from '../runtime/debug'; import { WorkbenchConnectionGate, WorkbenchRuntimeProvider } from '../runtime/provider'; diff --git a/packages/client/workbench/src/files/locate.ts b/packages/client/workbench/src/files/locate.ts index 337cde94a..6272c8033 100644 --- a/packages/client/workbench/src/files/locate.ts +++ b/packages/client/workbench/src/files/locate.ts @@ -26,13 +26,17 @@ export function fileArtifactCandidates( const suffix = `/${relative}`; const exactHits: string[] = []; const touchedDirs: string[] = []; - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; if (item.kind !== 'tool') continue; const paths = (item.toolCall.locations ?? []).map((location) => location.path); - for (const content of item.toolCall.content) { + const contents = item.toolCall.content; + for (let j = 0, contentCount = contents.length; j < contentCount; j++) { + const content = contents[j]; if (content.type === 'diff') paths.push(content.path); } - for (const touched of paths) { + for (let j = 0, pathCount = paths.length; j < pathCount; j++) { + const touched = paths[j]; // Relative locations (adapter-dependent) have no reliable anchor; skip them. if (!isAbsolute(touched)) continue; const normalized = normalize(touched); @@ -64,7 +68,8 @@ export async function locateFileArtifact( ): Promise { const candidates = fileArtifactCandidates(requestPath, cwd, items); if (candidates.length > 1) { - for (const candidate of candidates) { + for (let i = 0, len = candidates.length; i < len; i++) { + const candidate = candidates[i]; try { // eslint-disable-next-line no-await-in-loop -- candidates must be probed in priority order and stop at the first readable path. await readWorkspaceFile({ cwd, path: candidate }); diff --git a/packages/client/workbench/src/history/imported.ts b/packages/client/workbench/src/history/imported.ts index 7c7ec40c0..378ac6ef4 100644 --- a/packages/client/workbench/src/history/imported.ts +++ b/packages/client/workbench/src/history/imported.ts @@ -14,7 +14,8 @@ export function importedSessionByHistoryId( sessions: readonly SessionInfo[], ): Map { const map = new Map(); - for (const session of sessions) { + for (let i = 0, len = sessions.length; i < len; i++) { + const session = sessions[i]; if (session.historyId !== undefined) { map.set(importedSessionKey(session.kind, session.historyId), session.sessionId); } diff --git a/packages/client/workbench/src/history/use-bulk-history-import.ts b/packages/client/workbench/src/history/use-bulk-history-import.ts index 3b2ac734f..12abdf401 100644 --- a/packages/client/workbench/src/history/use-bulk-history-import.ts +++ b/packages/client/workbench/src/history/use-bulk-history-import.ts @@ -70,7 +70,8 @@ export function useBulkHistoryImport(): BulkHistoryImportSurface { const result = await historyByKind[group.kind].importGroup(group.cwd, group.entries); if (!result) return null; const importedIds = new Set(result.imported); - for (const entry of group.entries) { + for (let i = 0, len = group.entries.length; i < len; i++) { + const entry = group.entries[i]; if (importedIds.has(entry.historyId)) { importedKeys.add(importedSessionKey(entry.kind, entry.historyId)); } @@ -111,13 +112,14 @@ export function useBulkHistoryImport(): BulkHistoryImportSurface { function groupByProviderDirectory(entries: readonly AgentHistorySession[]) { const groups = new Map(); - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; const key = `${entry.kind}\0${entry.cwd ?? ''}`; const group = groups.get(key); if (group) group.push(entry); else groups.set(key, [entry]); } - return [...groups.values()].map((group) => ({ + return Array.from(groups.values(), (group) => ({ kind: group[0].kind, cwd: group[0].cwd ?? '', entries: group, diff --git a/packages/client/workbench/src/history/use-history-import-surface.ts b/packages/client/workbench/src/history/use-history-import-surface.ts index 12148f13f..f711deec3 100644 --- a/packages/client/workbench/src/history/use-history-import-surface.ts +++ b/packages/client/workbench/src/history/use-history-import-surface.ts @@ -59,7 +59,8 @@ export function useHistoryImportSurface( const imported = importedSessionByHistoryId(sessions.sessions); const importErrors = new Map(); const groupImportFailures = new Map(); - for (const entry of history.entries) { + for (let i = 0, len = history.entries.length; i < len; i++) { + const entry = history.entries[i]; const entryError = importErrorsByKey.get(historyStateKey(entry.kind, entry.historyId)); if (entryError !== undefined) importErrors.set(entry.historyId, entryError); if (!entry.cwd) continue; @@ -130,7 +131,8 @@ export function useHistoryImportSurface( if (result.failures.length === 0) return; setImportErrorsByKey((current) => { const next = new Map(current); - for (const failure of result.failures) { + for (let i = 0, len = result.failures.length; i < len; i++) { + const failure = result.failures[i]; next.set(historyStateKey(kind, failure.historyId), errorMessage(failure.error)); } return next; @@ -198,7 +200,10 @@ function withoutMapKey(map: ReadonlyMap, key: K): ReadonlyMap function withoutMapKeys(map: ReadonlyMap, keys: readonly K[]): ReadonlyMap { if (!keys.some((key) => map.has(key))) return map; const next = new Map(map); - for (const key of keys) next.delete(key); + for (let i = 0, len = keys.length; i < len; i++) { + const key = keys[i]; + next.delete(key); + } return next; } diff --git a/packages/client/workbench/src/history/use-provider-history.ts b/packages/client/workbench/src/history/use-provider-history.ts index 5e14863de..a5c01da92 100644 --- a/packages/client/workbench/src/history/use-provider-history.ts +++ b/packages/client/workbench/src/history/use-provider-history.ts @@ -59,7 +59,7 @@ export async function importHistoryGroup({ inFlight.add(inFlightKey); try { const settled: Array> = []; - for (let start = 0; start < entries.length; start += GROUP_IMPORT_CONCURRENCY) { + for (let start = 0, len = entries.length; start < len; start += GROUP_IMPORT_CONCURRENCY) { const batch = entries.slice(start, start + GROUP_IMPORT_CONCURRENCY); appendArrayInPlace( settled, @@ -67,7 +67,8 @@ export async function importHistoryGroup({ ); } const result: HistoryGroupImportResult = { imported: [], failures: [] }; - for (const [index, outcome] of settled.entries()) { + for (let index = 0, len = settled.length; index < len; index++) { + const outcome = settled[index]; const entry = entries[index]; if (outcome.status === 'fulfilled') result.imported.push(entry.historyId); else result.failures.push({ historyId: entry.historyId, error: outcome.reason }); @@ -169,7 +170,8 @@ function currentImportingIds( importingKeys: ReadonlySet, ): ReadonlySet { const ids = new Set(); - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; if (importingKeys.has(importKey(entry.kind, entry.historyId))) ids.add(entry.historyId); } return ids; @@ -181,7 +183,8 @@ function currentImportingCwds( importingGroupKeys: ReadonlySet, ): ReadonlySet { const cwds = new Set(); - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; if (entry.cwd && importingGroupKeys.has(importKey(kind, entry.cwd))) cwds.add(entry.cwd); } return cwds; diff --git a/packages/client/workbench/src/mock/data/long-thread.ts b/packages/client/workbench/src/mock/data/long-thread.ts index fb7681d11..8c244ce8b 100644 --- a/packages/client/workbench/src/mock/data/long-thread.ts +++ b/packages/client/workbench/src/mock/data/long-thread.ts @@ -33,19 +33,20 @@ export function createLongThreadScript(messageId: (slug: string) => MessageId): for (let turn = 0; turn < LONG_THREAD_TURNS; turn++) { const subject = SUBJECTS[turn % SUBJECTS.length]; const ask = ASKS[turn % ASKS.length]; - script.push({ - type: 'user-message', - messageId: messageId(`mock-long-user-${turn}`), - content: [textBlock(`${ask} ${subject}.`)], - }); - script.push({ - type: 'agent-message-chunk', - messageId: messageId(`mock-long-reply-${turn}`), - content: textBlock(replyBody(turn, subject)), - }); + script.push( + { + type: 'user-message', + messageId: messageId(`mock-long-user-${turn}`), + content: [textBlock(`${ask} ${subject}.`)], + }, + { + type: 'agent-message-chunk', + messageId: messageId(`mock-long-reply-${turn}`), + content: textBlock(replyBody(turn, subject)), + }, + ); } - script.push({ type: 'stop', stopReason: 'end_turn' }); - script.push({ type: 'status', status: 'idle' }); + script.push({ type: 'stop', stopReason: 'end_turn' }, { type: 'status', status: 'idle' }); return script; } diff --git a/packages/client/workbench/src/mock/dev-mock-host.ts b/packages/client/workbench/src/mock/dev-mock-host.ts index 5d9e7111d..dd9155e0c 100644 --- a/packages/client/workbench/src/mock/dev-mock-host.ts +++ b/packages/client/workbench/src/mock/dev-mock-host.ts @@ -263,7 +263,9 @@ export class DevMockHost { /** Staged download: throttled progress → settled → correlated reply → runtime re-probe push. */ private async ensureAsset(clientReqId: string, id: ManagedAssetId): Promise { const totalBytes = 66 * 1_048_576; - for (const fraction of [0.04, 0.19, 0.42, 0.68, 0.91]) { + const fractions = [0.04, 0.19, 0.42, 0.68, 0.91]; + for (let i = 0, len = fractions.length; i < len; i++) { + const fraction = fractions[i]; this.send({ kind: 'asset.progress', id, @@ -300,7 +302,8 @@ export class DevMockHost { void this.handle(msg); }); const now = Date.now(); - for (const { ageMs, resources, workspaceKind, ...seed } of SEED_SESSIONS) { + for (let i = 0, len = SEED_SESSIONS.length; i < len; i++) { + const { ageMs, resources, workspaceKind, ...seed } = SEED_SESSIONS[i]; const createdAt = now - ageMs; const session = this.addSession({ ...seed, createdAt, updatedAt: createdAt }); this.seedResources(session.sessionId, now, resources ?? []); @@ -322,7 +325,7 @@ export class DevMockHost { this.send({ kind: 'session.listed', replyTo: p.clientReqId, - sessions: [...this.sessions.values()].map((session) => toSessionInfo(session)), + sessions: Array.from(this.sessions.values(), (session) => toSessionInfo(session)), }); // Start after the list reply so the UI can subscribe before scripted frames arrive. this.startShowcase(); @@ -443,7 +446,8 @@ export class DevMockHost { this.sendFailure(p.clientReqId, 'plugin management is not supported'); break; } - for (const installation of plugin.installations) { + for (let i = 0, len = plugin.installations.length; i < len; i++) { + const installation = plugin.installations[i]; if (p.scope === undefined || installation.scope === p.scope) { installation.enabled = p.enabled; } @@ -530,7 +534,7 @@ export class DevMockHost { ...branchList, branches: [ ...branchList.branches, - ...[...created].map((name) => ({ + ...Array.from(created, (name) => ({ name, isCurrent: false, lastCommitAt: Date.now(), @@ -705,7 +709,7 @@ export class DevMockHost { this.send({ kind: 'terminal.listed', replyTo: p.clientReqId, - terminals: [...this.terminals.values()].map((terminal) => terminal.metadata), + terminals: Array.from(this.terminals.values(), (terminal) => terminal.metadata), }); break; case 'terminal.open': @@ -780,7 +784,8 @@ export class DevMockHost { now: number, seeds: readonly SeedSessionResource[], ): void { - for (const { ageMs, ...seed } of seeds) { + for (let i = 0, len = seeds.length; i < len; i++) { + const { ageMs, ...seed } = seeds[i]; const timestamp = now - ageMs; const resource: SessionResource = { ...seed, @@ -1282,17 +1287,20 @@ export class DevMockHost { const messageId = this.nextMessageId('mock-message'); const reply = `${MOCK_REPLY}\n\nModel: ${session.model ?? 'mock-default'}\nYou said: ${text || '(empty prompt)'}`; - for (const chunk of reply.match(WORD_CHUNK_PATTERN) ?? []) { - // eslint-disable-next-line no-await-in-loop -- word-by-word streaming: chunks are paced sequentially by design. - if (await cancelledAfter(CHUNK_LATENCY_MS)) { - this.sendSuccess(replyTo); - return; + const chunks = reply.match(WORD_CHUNK_PATTERN); + if (chunks != null) { + for (let i = 0, len = chunks.length; i < len; i++) { + // eslint-disable-next-line no-await-in-loop -- word-by-word streaming: chunks are paced sequentially by design. + if (await cancelledAfter(CHUNK_LATENCY_MS)) { + this.sendSuccess(replyTo); + return; + } + this.emit(session.sessionId, { + type: 'agent-message-chunk', + messageId, + content: textBlock(chunks[i]), + }); } - this.emit(session.sessionId, { - type: 'agent-message-chunk', - messageId, - content: textBlock(chunk), - }); } this.emit(session.sessionId, { type: 'token-usage', @@ -1312,7 +1320,9 @@ export class DevMockHost { for (const session of this.sessions.values()) { if (!session.longThread || session.longThreadSeeded) continue; session.longThreadSeeded = true; - for (const event of createLongThreadScript((slug) => this.nextMessageId(slug))) { + const script = createLongThreadScript((slug) => this.nextMessageId(slug)); + for (let i = 0, len = script.length; i < len; i++) { + const event = script[i]; this.emit(session.sessionId, event); } } @@ -1428,10 +1438,10 @@ export class DevMockHost { ...toolEvents(bursts.activityRun.afterTask), ]; - for (const event of script) { + for (let i = 0, len = script.length; i < len; i++) { // eslint-disable-next-line no-await-in-loop -- the showcase script emits step by step on purpose. if (!(await waitForShowcaseStep(session, epoch))) return false; - this.emit(session.sessionId, event); + this.emit(session.sessionId, script[i]); } if (!(await waitForShowcaseStep(session, epoch))) return false; this.writeTerminal(terminalId, SHOWCASE_TERMINAL_START_OUTPUT); @@ -1440,7 +1450,8 @@ export class DevMockHost { toolCall: SHOWCASE_QUESTION.toolCall, }); if (!(await this.emitShowcaseEvent(session, epoch, SHOWCASE_QUESTION))) return false; - for (const permission of SHOWCASE_PERMISSIONS) { + for (let i = 0, len = SHOWCASE_PERMISSIONS.length; i < len; i++) { + const permission = SHOWCASE_PERMISSIONS[i]; this.permissions.set(permission.requestId, { sessionId: session.sessionId, toolCall: permission.toolCall, @@ -1509,15 +1520,18 @@ export class DevMockHost { content: SHOWCASE_STREAM_THOUGHT_CONTENT, }); - for (const chunk of SHOWCASE_STREAM_REPLY.match(WORD_CHUNK_PATTERN) ?? []) { - // eslint-disable-next-line no-await-in-loop -- word-by-word streaming: chunks are paced sequentially by design. - await wait(SHOWCASE_STREAM_CHUNK_LATENCY_MS); - if (!isRunningTurn(session, epoch)) return; - this.emit(session.sessionId, { - type: 'agent-message-chunk', - messageId, - content: textBlock(chunk), - }); + const streamChunks = SHOWCASE_STREAM_REPLY.match(WORD_CHUNK_PATTERN); + if (streamChunks != null) { + for (let i = 0, len = streamChunks.length; i < len; i++) { + // eslint-disable-next-line no-await-in-loop -- word-by-word streaming: chunks are paced sequentially by design. + await wait(SHOWCASE_STREAM_CHUNK_LATENCY_MS); + if (!isRunningTurn(session, epoch)) return; + this.emit(session.sessionId, { + type: 'agent-message-chunk', + messageId, + content: textBlock(streamChunks[i]), + }); + } } this.writeTerminal(terminalId, SHOWCASE_TERMINAL_EXIT_OUTPUT); this.emit(session.sessionId, { @@ -1759,7 +1773,8 @@ function applyCustomMcpPatches( ops: readonly CustomMcpServerPatchOp[], ): CustomMcpServer[] { let next = structuredClone(current); - for (const op of ops) { + for (let i = 0, len = ops.length; i < len; i++) { + const op = ops[i]; switch (op.op) { case 'add': next.push(structuredClone(op.server)); @@ -1797,7 +1812,9 @@ function applyMockSecretPatch( if (!patch) return current; const removed = new Set(patch.remove); const next: Record = {}; - for (const [key, value] of Object.entries({ ...current, ...patch.set })) { + const entries = Object.entries({ ...current, ...patch.set }); + for (let i = 0, len = entries.length; i < len; i++) { + const [key, value] = entries[i]; if (!removed.has(key)) next[key] = value; } return next; diff --git a/packages/client/workbench/src/palette/command-palette.tsx b/packages/client/workbench/src/palette/command-palette.tsx index 9fd6a890b..bda3825a5 100644 --- a/packages/client/workbench/src/palette/command-palette.tsx +++ b/packages/client/workbench/src/palette/command-palette.tsx @@ -97,10 +97,13 @@ function OpenCommandPalette({ sessions }: WorkbenchCommandPaletteProps): React.R : []), ]; let targetWorkspace: WorkspaceRecord | null = null; - for (const workspace of workspaces ?? []) { - if (workspaceKind(workspace) === 'project') { - targetWorkspace = workspace; - break; + if (workspaces != null) { + for (let i = 0, len = workspaces.length; i < len; i++) { + const workspace = workspaces[i]; + if (workspaceKind(workspace) === 'project') { + targetWorkspace = workspace; + break; + } } } const commands: PaletteCommand[] = targetWorkspace diff --git a/packages/client/workbench/src/palette/store.ts b/packages/client/workbench/src/palette/store.ts index 63a84901a..30d41a000 100644 --- a/packages/client/workbench/src/palette/store.ts +++ b/packages/client/workbench/src/palette/store.ts @@ -24,9 +24,12 @@ export const useCommandPaletteStore = create()((set) => ({ set((state) => ({ commandsByOwner: { ...state.commandsByOwner, [owner]: commands } })), unregisterCommands: (owner) => set((state) => ({ - commandsByOwner: Object.fromEntries( - Object.entries(state.commandsByOwner).filter(([key]) => key !== owner), - ), + commandsByOwner: Object.entries(state.commandsByOwner).reduce< + Record + >((acc, [key, commands]) => { + if (key !== owner) acc[key] = commands; + return acc; + }, {}), })), })); diff --git a/packages/client/workbench/src/runtime/debug.tsx b/packages/client/workbench/src/runtime/debug.tsx index 3ae95e9de..9e043f345 100644 --- a/packages/client/workbench/src/runtime/debug.tsx +++ b/packages/client/workbench/src/runtime/debug.tsx @@ -1,5 +1,4 @@ import { nullthrow } from 'foxact/nullthrow'; -import type * as React from 'react'; import { createContext, useContext, useMemo, useState } from 'react'; export interface DebugState { diff --git a/packages/client/workbench/src/runtime/provider.tsx b/packages/client/workbench/src/runtime/provider.tsx index bf5d1fbd5..d539ba097 100644 --- a/packages/client/workbench/src/runtime/provider.tsx +++ b/packages/client/workbench/src/runtime/provider.tsx @@ -7,7 +7,6 @@ import { useSingleton } from 'foxact/use-singleton'; import { extractErrorMessage } from 'foxts/extract-error-message'; import { trueFn } from 'foxts/noop'; import { wait } from 'foxts/wait'; -import type * as React from 'react'; import { createContext, useContext, useRef, useSyncExternalStore } from 'react'; import type { Cache, Middleware as SWRMiddleware } from 'swr'; import { SWRConfig, useSWRConfig } from 'swr'; diff --git a/packages/client/workbench/src/settings/plugins/custom-mcp-patch.ts b/packages/client/workbench/src/settings/plugins/custom-mcp-patch.ts index fc3b09ec5..b85998e28 100644 --- a/packages/client/workbench/src/settings/plugins/custom-mcp-patch.ts +++ b/packages/client/workbench/src/settings/plugins/custom-mcp-patch.ts @@ -103,7 +103,8 @@ function diffSecrets( const set: Record = {}; const remove: string[] = []; let touched = false; - for (const row of rows) { + for (let i = 0, len = rows.length; i < len; i++) { + const row = rows[i]; const key = row.key.trim(); if (!key) continue; if (row.remove) { @@ -127,7 +128,8 @@ function diffSecrets( function mintedServer(draft: CustomMcpServerDraft, mint: CustomMcpMint, enabled: boolean) { const secrets: Record = {}; - for (const row of draft.secrets) { + for (let i = 0, len = draft.secrets.length; i < len; i++) { + const row = draft.secrets[i]; const key = row.key.trim(); if (key && !row.remove && row.value !== '') secrets[key] = row.value; } diff --git a/packages/client/workbench/src/settings/plugins/mcp-settings.tsx b/packages/client/workbench/src/settings/plugins/mcp-settings.tsx index b955aca70..5f5f1acc3 100644 --- a/packages/client/workbench/src/settings/plugins/mcp-settings.tsx +++ b/packages/client/workbench/src/settings/plugins/mcp-settings.tsx @@ -179,12 +179,15 @@ function CustomServerDialog({ const submit = handleSubmit((form) => { const secretRows: Array<{ key: string; value: string; remove: boolean }> = []; - for (const row of form.secrets) { + for (let i = 0, len = form.secrets.length; i < len; i++) { + const row = form.secrets[i]; const key = row.key.trim(); if (key !== '') secretRows.push({ key, value: row.value, remove: row.remove }); } const args: string[] = []; - for (const line of form.args.split('\n')) { + const argLines = form.args.split('\n'); + for (let i = 0, len = argLines.length; i < len; i++) { + const line = argLines[i]; const trimmed = line.trim(); if (trimmed !== '') args.push(trimmed); } diff --git a/packages/client/workbench/src/settings/plugins/plugins-settings.tsx b/packages/client/workbench/src/settings/plugins/plugins-settings.tsx index fbe7a7444..32729a1ef 100644 --- a/packages/client/workbench/src/settings/plugins/plugins-settings.tsx +++ b/packages/client/workbench/src/settings/plugins/plugins-settings.tsx @@ -33,8 +33,12 @@ export function PluginsSettingsPanel(): React.ReactNode { const mutating = toggle.isMutating || install.isMutating || uninstall.isMutating; const missingRuntimes = new Set(); - for (const [kind, runtime] of Object.entries(runtimes ?? {})) { - if (runtime.status === 'missing') missingRuntimes.add(kind); + if (runtimes != null) { + const runtimeEntries = Object.entries(runtimes); + for (let i = 0, len = runtimeEntries.length; i < len; i++) { + const [kind, runtime] = runtimeEntries[i]; + if (runtime.status === 'missing') missingRuntimes.add(kind); + } } const groupsFor = (installed: boolean) => diff --git a/packages/client/workbench/src/settings/plugins/view.ts b/packages/client/workbench/src/settings/plugins/view.ts index 897c1b486..41c195f56 100644 --- a/packages/client/workbench/src/settings/plugins/view.ts +++ b/packages/client/workbench/src/settings/plugins/view.ts @@ -14,7 +14,8 @@ export type { PluginCardView, PluginMcpServerRow, PluginProviderGroup, SkillRowV export function pluginCardView(plugin: Plugin): PluginCardView { const title = plugin.displayName ?? plugin.name; const componentCounts: Partial> = {}; - for (const component of plugin.components) { + for (let i = 0, len = plugin.components.length; i < len; i++) { + const component = plugin.components[i]; componentCounts[component.kind] = (componentCounts[component.kind] ?? 0) + 1; } const available = plugin.availability === 'available'; @@ -64,7 +65,8 @@ export function pluginProviderGroups( ): PluginProviderGroup[] { return list.providerStatus.map((status) => { const plugins: PluginCardView[] = []; - for (const plugin of list.plugins) { + for (let i = 0, len = list.plugins.length; i < len; i++) { + const plugin = list.plugins[i]; if (plugin.provider !== status.provider) continue; if (plugin.installations.length > 0 !== opts.installed) continue; plugins.push(pluginCardView(plugin)); @@ -90,7 +92,8 @@ export function filterPluginCards( /** Plugin-bundled skills (installed plugins only) followed by standalone skills. */ export function skillRows(list: PluginList): SkillRowView[] { const rows: SkillRowView[] = []; - for (const plugin of list.plugins) { + for (let i = 0, len = list.plugins.length; i < len; i++) { + const plugin = list.plugins[i]; if (plugin.installations.length === 0) continue; const card = pluginCardView(plugin); const skills = plugin.components.filter((component) => component.kind === 'skill'); @@ -98,7 +101,8 @@ export function skillRows(list: PluginList): SkillRowView[] { plugin.installations.length === 1 ? plugin.installations[0].enabled : plugin.installations.some((entry) => entry.enabled); - for (const skill of skills) { + for (let j = 0, skillCount = skills.length; j < skillCount; j++) { + const skill = skills[j]; rows.push({ key: `${card.key}:${skill.name}`, provider: plugin.provider, @@ -115,7 +119,8 @@ export function skillRows(list: PluginList): SkillRowView[] { }); } } - for (const skill of list.standaloneSkills) { + for (let i = 0, len = list.standaloneSkills.length; i < len; i++) { + const skill = list.standaloneSkills[i]; rows.push(standaloneSkillRow(skill)); } return rows; @@ -141,11 +146,14 @@ function standaloneSkillRow(skill: StandaloneSkill): SkillRowView { /** Read-only projection of plugin-provided MCP servers for the MCP tab's lower section. */ export function pluginMcpServerRows(plugins: readonly Plugin[]): PluginMcpServerRow[] { const rows: PluginMcpServerRow[] = []; - for (const plugin of plugins) { + for (let i = 0, len = plugins.length; i < len; i++) { + const plugin = plugins[i]; if (plugin.installations.length === 0) continue; const title = plugin.displayName ?? plugin.name; const pluginEnabled = plugin.installations.some((entry) => entry.enabled); - for (const component of plugin.components) { + const components = plugin.components; + for (let j = 0, componentCount = components.length; j < componentCount; j++) { + const component = components[j]; if (component.kind !== 'mcp-server') continue; rows.push({ key: `${plugin.provider}:${plugin.id}:${component.name}`, diff --git a/packages/client/workbench/src/settings/providers/add-flow.tsx b/packages/client/workbench/src/settings/providers/add-flow.tsx index b83f57c8b..85e5787f9 100644 --- a/packages/client/workbench/src/settings/providers/add-flow.tsx +++ b/packages/client/workbench/src/settings/providers/add-flow.tsx @@ -45,7 +45,10 @@ const GROUPS: ServiceGroup[] = ['subscription', 'direct', 'gateway', 'custom']; const SERVICES_BY_GROUP = new Map( GROUPS.map((group) => [group, []]), ); -for (const service of SERVICE_CATALOG) SERVICES_BY_GROUP.get(service.group)?.push(service); +for (let i = 0, len = SERVICE_CATALOG.length; i < len; i++) { + const service = SERVICE_CATALOG[i]; + SERVICES_BY_GROUP.get(service.group)?.push(service); +} /** Account constructors live at module scope: `Date.now` may not run in a component body. */ function newAccountBase(label: string): Pick { @@ -69,7 +72,9 @@ function oauthAccount( * its own endpoint from those, so no protocol is chosen here. */ function catalogAccount(service: EndpointService, draft: CatalogDraft): Account { const trimmed: Record = {}; - for (const key of servicePlaceholders(service)) { + const placeholderKeys = servicePlaceholders(service); + for (let i = 0, len = placeholderKeys.length; i < len; i++) { + const key = placeholderKeys[i]; const value = Object.hasOwn(draft.placeholders, key) ? draft.placeholders[key] : ''; trimmed[key] = value.trim(); } @@ -88,8 +93,14 @@ function catalogAccount(service: EndpointService, draft: CatalogDraft): Account /** Placeholders across every variant: one secret covers them all, so the form asks once. */ function servicePlaceholders(service: EndpointService): string[] { const keys = new Set(); - for (const variant of Object.values(service.variants)) { - for (const key of templatePlaceholders(variant.baseUrl)) keys.add(key); + const variants = Object.values(service.variants); + for (let i = 0, len = variants.length; i < len; i++) { + const variant = variants[i]; + const placeholders = templatePlaceholders(variant.baseUrl); + for (let j = 0, placeholderCount = placeholders.length; j < placeholderCount; j++) { + const key = placeholders[j]; + keys.add(key); + } } return [...keys]; } @@ -536,7 +547,9 @@ type CatalogDraft = z.infer; function catalogDraftSchema(service: EndpointService): typeof CatalogDraftSchema { return CatalogDraftSchema.superRefine((draft, ctx) => { - for (const key of servicePlaceholders(service)) { + const placeholderKeys = servicePlaceholders(service); + for (let i = 0, len = placeholderKeys.length; i < len; i++) { + const key = placeholderKeys[i]; const value = Object.hasOwn(draft.placeholders, key) ? draft.placeholders[key] : ''; if (!value.trim()) { ctx.addIssue({ code: 'custom', path: ['placeholders', key], message: 'required' }); diff --git a/packages/client/workbench/src/settings/providers/model-options.ts b/packages/client/workbench/src/settings/providers/model-options.ts index f9d91fa3e..84b32fa96 100644 --- a/packages/client/workbench/src/settings/providers/model-options.ts +++ b/packages/client/workbench/src/settings/providers/model-options.ts @@ -25,7 +25,8 @@ export function accountModelOptions( ): Partial> { const pool = accounts ?? []; const options: Partial> = {}; - for (const kind of AgentKindSchema.options) { + for (let i = 0, len = AgentKindSchema.options.length; i < len; i++) { + const kind = AgentKindSchema.options[i]; const bindable = pool.some((account) => resolveBinding(account, kind).tier !== 'unavailable'); if (!bindable) continue; options[kind] = enabledAccountModels(pool, providers, kind).map(({ account, model }) => ({ diff --git a/packages/client/workbench/src/settings/providers/model-selection.tsx b/packages/client/workbench/src/settings/providers/model-selection.tsx index 41737491b..32373a321 100644 --- a/packages/client/workbench/src/settings/providers/model-selection.tsx +++ b/packages/client/workbench/src/settings/providers/model-selection.tsx @@ -150,7 +150,7 @@ export function ModelSelection({ {t('models.required')}

) : null} - {error !== undefined ?

{error}

: null} + {error === undefined ? null :

{error}

} {listed.length > 0 ? (
{listed.map((model) => { diff --git a/packages/client/workbench/src/settings/providers/view.ts b/packages/client/workbench/src/settings/providers/view.ts index 0019f2d3b..7bb01a4b4 100644 --- a/packages/client/workbench/src/settings/providers/view.ts +++ b/packages/client/workbench/src/settings/providers/view.ts @@ -54,7 +54,10 @@ export function accountConfigSnippet( ): string { const bound = boundAgentKinds(account, providers); const slice: Record = {}; - for (const kind of bound) slice[kind] = providers?.[kind]; + for (let i = 0, len = bound.length; i < len; i++) { + const kind = bound[i]; + slice[kind] = providers?.[kind]; + } return JSON.stringify({ providers: slice }, null, 2); } @@ -241,7 +244,8 @@ export function withEnabled( export function withoutAccount(providers: ProvidersConfig, accountId: string): ProvidersConfig { let changed = false; const next: ProvidersConfig = {}; - for (const kind of AGENT_KINDS) { + for (let i = 0, len = AGENT_KINDS.length; i < len; i++) { + const kind = AGENT_KINDS[i]; const entry = providers[kind]; if (entry === undefined) continue; if (entry.enabledAccountIds?.includes(accountId)) { diff --git a/packages/client/workbench/src/sidebar/ordering.ts b/packages/client/workbench/src/sidebar/ordering.ts index 83c3a4c0e..30e3f3d95 100644 --- a/packages/client/workbench/src/sidebar/ordering.ts +++ b/packages/client/workbench/src/sidebar/ordering.ts @@ -15,7 +15,8 @@ export function orderGroups( const unlisted: ThreadGroup[] = []; const fixed: ThreadGroup[] = []; - for (const group of groups) { + for (let i = 0, len = groups.length; i < len; i++) { + const group = groups[i]; if (group.isChat || group.workspace === null) fixed.push(group); else if (rank.has(group.collapseKey)) listed.push(group); else unlisted.push(group); diff --git a/packages/client/workbench/src/simulator/__tests__/agent-activity.test.ts b/packages/client/workbench/src/simulator/__tests__/agent-activity.test.ts index 8898f4013..5a2222f11 100644 --- a/packages/client/workbench/src/simulator/__tests__/agent-activity.test.ts +++ b/packages/client/workbench/src/simulator/__tests__/agent-activity.test.ts @@ -23,13 +23,16 @@ function fakeClient(): SimulatorActivityClient & { emit: (activity: Activity) => }; } -const started = ( +function started( udid: string | undefined, tool = 'sim_tap', at?: { x: number; y: number }, -): Activity => ({ sessionId: 's1', udid, tool, phase: 'started', ...at }) as Activity; -const settled = (udid: string | undefined, tool = 'sim_tap'): Activity => - ({ sessionId: 's1', udid, tool, phase: 'settled' }) as Activity; +): Activity { + return { sessionId: 's1', udid, tool, phase: 'started', ...at } as Activity; +} +function settled(udid: string | undefined, tool = 'sim_tap'): Activity { + return { sessionId: 's1', udid, tool, phase: 'settled' } as Activity; +} describe('useSimulatorAgentActivity', () => { beforeEach(() => { diff --git a/packages/client/workbench/src/simulator/__tests__/panel-store.test.ts b/packages/client/workbench/src/simulator/__tests__/panel-store.test.ts index cd4f8bbcf..ac4e91f26 100644 --- a/packages/client/workbench/src/simulator/__tests__/panel-store.test.ts +++ b/packages/client/workbench/src/simulator/__tests__/panel-store.test.ts @@ -5,10 +5,12 @@ import { selectDeviceTabs, useSimulatorPanelStore } from '../panel-store'; const A = 'thread-a'; const B = 'thread-b'; -const tabsOf = (key: string): { udids: readonly string[]; activeUdid: string | null } => - selectDeviceTabs(useSimulatorPanelStore.getState(), key); -const open = (key: string, udid: string): void => - useSimulatorPanelStore.getState().openDevice(key, udid); +function tabsOf(key: string): { udids: readonly string[]; activeUdid: string | null } { + return selectDeviceTabs(useSimulatorPanelStore.getState(), key); +} +function open(key: string, udid: string): void { + return useSimulatorPanelStore.getState().openDevice(key, udid); +} describe('simulator device tabs', () => { beforeEach(() => { diff --git a/packages/client/workbench/src/simulator/agent-activity.ts b/packages/client/workbench/src/simulator/agent-activity.ts index c02e4e371..996c1c472 100644 --- a/packages/client/workbench/src/simulator/agent-activity.ts +++ b/packages/client/workbench/src/simulator/agent-activity.ts @@ -50,7 +50,7 @@ export function useSimulatorAgentActivity( const at = { x: activity.x, y: activity.y }; setPoint(at); clearTimeout(pointTimer); - pointTimer = setTimeout(() => setPoint(null), POINTER_MS); + pointTimer = setTimeout(setPoint, POINTER_MS, null); } if (activity.phase === 'started') { inflight += 1; @@ -61,7 +61,7 @@ export function useSimulatorAgentActivity( inflight = Math.max(0, inflight - 1); if (inflight === 0) { clearTimeout(clearTimer); - clearTimer = setTimeout(() => setActive(false), LINGER_MS); + clearTimer = setTimeout(setActive, LINGER_MS, false); } }); return () => { diff --git a/packages/client/workbench/src/simulator/background-streams.ts b/packages/client/workbench/src/simulator/background-streams.ts index ac7a276a9..bb889e221 100644 --- a/packages/client/workbench/src/simulator/background-streams.ts +++ b/packages/client/workbench/src/simulator/background-streams.ts @@ -36,7 +36,10 @@ export function useBackgroundSimulatorStreams( return lease; }); return () => { - for (const lease of leases) lease.release(); + for (let i = 0, len = leases.length; i < len; i++) { + const lease = leases[i]; + lease.release(); + } }; }, [client, sessionId, key, scale, codec]); } diff --git a/packages/client/workbench/src/simulator/panel.tsx b/packages/client/workbench/src/simulator/panel.tsx index 8e5666254..a6e4b9382 100644 --- a/packages/client/workbench/src/simulator/panel.tsx +++ b/packages/client/workbench/src/simulator/panel.tsx @@ -237,6 +237,7 @@ export function SimulatorPanel({ sessionId }: { sessionId: SessionId | null }): const openUdids = tabs.udids.length > 0 ? tabs.udids : defaultUdid === null ? EMPTY_UDIDS : [defaultUdid]; const activeUdid = tabs.activeUdid ?? defaultUdid; + // eslint-disable-next-line vibe-proof/react-no-performance-impacting-array-find -- a host exposes a handful of simulators at most; a lookup Map would outweigh the scan const device = devices?.find((item) => item.udid === activeUdid) ?? null; const udid = device?.udid ?? null; const booted = device?.state === 'Booted'; @@ -249,14 +250,18 @@ export function SimulatorPanel({ sessionId }: { sessionId: SessionId | null }): // Fetch bookkeeping lives in a ref (not `masks`) so the effect never loops on its own writes; // the cache write itself is deliberately not abort-gated — a udid switch mid-fetch must still - // land the result for the next switch back. + // land the result for the next switch back. No stale-overwrite race exists: writes are keyed + // by the udid captured at fetch time (never clobbering another udid's entry), and the ref + // guarantees at most one fetch per udid, so no two writes ever target the same key. const maskFetchedRef = useRef(new Set()); useEffect(() => { if (udid === null || maskFetchedRef.current.has(udid)) return; maskFetchedRef.current.add(udid); void client .simulatorScreenMask(udid) + // eslint-disable-next-line vibe-proof/react-detect-potential-race-condition -- see above .then((data) => setMasks((prev) => ({ ...prev, [udid]: data }))) + // eslint-disable-next-line vibe-proof/react-detect-potential-race-condition -- see above .catch(() => setMasks((prev) => ({ ...prev, [udid]: null }))); }, [client, udid]); @@ -325,7 +330,7 @@ export function SimulatorPanel({ sessionId }: { sessionId: SessionId | null }): const flagBusy = useCallback(() => { setBusy(true); clearTimeout(busyTimerRef.current); - busyTimerRef.current = setTimeout(() => setBusy(false), BUSY_BANNER_MS); + busyTimerRef.current = setTimeout(setBusy, BUSY_BANNER_MS, false); }, []); const handleTouch = (phase: SimulatorScreenTouchPhase, point: SimulatorScreenPoint): void => { diff --git a/packages/client/workbench/src/surface/startup-selection.ts b/packages/client/workbench/src/surface/startup-selection.ts index 853d6c858..729d969ab 100644 --- a/packages/client/workbench/src/surface/startup-selection.ts +++ b/packages/client/workbench/src/surface/startup-selection.ts @@ -19,7 +19,8 @@ export function reflectedStartupSelection( ): NewSessionSelection { let reflectedModel: string | undefined; let reflectedEffort: EffortLevel | undefined; - for (const { event } of events) { + for (let i = 0, len = events.length; i < len; i++) { + const { event } = events[i]; if (event.type === 'model-update') reflectedModel = event.model; else if (event.type === 'effort-update') reflectedEffort = event.effort; } diff --git a/packages/client/workbench/src/surface/task-resources-panel.tsx b/packages/client/workbench/src/surface/task-resources-panel.tsx index 8a4fbb9dc..44f413677 100644 --- a/packages/client/workbench/src/surface/task-resources-panel.tsx +++ b/packages/client/workbench/src/surface/task-resources-panel.tsx @@ -18,11 +18,11 @@ function resourceItem(resource: SessionResource, localFileLabel: string): Resour kind: resource.kind, status: resource.status, source: - resource.direction !== 'source' - ? undefined - : resource.locator.type === 'url' + resource.direction === 'source' + ? resource.locator.type === 'url' ? new URL(resource.locator.url).hostname - : localFileLabel, + : localFileLabel + : undefined, updatedAt: resource.updatedAt, error: resource.error, canOpen: resource.status === 'ready', @@ -70,7 +70,8 @@ export function RuntimeTaskResourcesPanel({ } async function addSources(files: File[]): Promise { - for (const file of files) { + for (let i = 0, len = files.length; i < len; i++) { + const file = files[i]; if (file.size > MAX_ATTACHMENT_BYTES) { toastManager.add({ title: t('tooLarge', { name: file.name }), type: 'error' }); continue; diff --git a/packages/client/workbench/src/surface/use-seeded-conversation.ts b/packages/client/workbench/src/surface/use-seeded-conversation.ts index c2318c1ab..396248f30 100644 --- a/packages/client/workbench/src/surface/use-seeded-conversation.ts +++ b/packages/client/workbench/src/surface/use-seeded-conversation.ts @@ -33,7 +33,10 @@ async function readConversationSeed( cursor, forceRefresh: page === 0, }); - for (const entry of data.events) events.push({ event: entry.event, ts: entry.ts }); + for (let i = 0, len = data.events.length; i < len; i++) { + const entry = data.events[i]; + events.push({ event: entry.event, ts: entry.ts }); + } cursor = data.cursor; if (cursor === undefined) break; } diff --git a/packages/client/workbench/src/surface/use-workbench-sessions.ts b/packages/client/workbench/src/surface/use-workbench-sessions.ts index 8be491468..fef42d39c 100644 --- a/packages/client/workbench/src/surface/use-workbench-sessions.ts +++ b/packages/client/workbench/src/surface/use-workbench-sessions.ts @@ -288,7 +288,8 @@ function sessionById( sessionId: SessionId | null, ): SessionInfo | null { if (!sessionId) return null; - for (const session of sessions) { + for (let i = 0, len = sessions.length; i < len; i++) { + const session = sessions[i]; if (session.sessionId === sessionId) return session; } return null; diff --git a/packages/client/workbench/src/surface/workbench.tsx b/packages/client/workbench/src/surface/workbench.tsx index 74ac1e892..ca4183bc3 100644 --- a/packages/client/workbench/src/surface/workbench.tsx +++ b/packages/client/workbench/src/surface/workbench.tsx @@ -234,11 +234,13 @@ function WorkbenchSessionSurface({ const [respondingRequestIds, addRespondingRequest, removeRespondingRequest] = useSet(); const [responseErrors, setResponseErrors] = useState(() => new Map()); const visibleResponseErrors = new Map(); - for (const requestId of conversation.pendingPermissionIds) { + for (let i = 0, len = conversation.pendingPermissionIds.length; i < len; i++) { + const requestId = conversation.pendingPermissionIds[i]; const message = responseErrors.get(requestId); if (message) visibleResponseErrors.set(requestId, message); } - for (const requestId of conversation.pendingQuestionIds) { + for (let i = 0, len = conversation.pendingQuestionIds.length; i < len; i++) { + const requestId = conversation.pendingQuestionIds[i]; const message = responseErrors.get(requestId); if (message) visibleResponseErrors.set(requestId, message); } @@ -558,7 +560,8 @@ function WorkbenchSessionSurface({ const workspacesById = new Map(); let chatWorkspace: WorkspaceRecord | null = null; const projectWorkspaces: WorkspaceRecord[] = []; - for (const workspace of allWorkspaces) { + for (let i = 0, len = allWorkspaces.length; i < len; i++) { + const workspace = allWorkspaces[i]; const kind = workspaceKind(workspace); if (kind === 'worktree') continue; workspacesById.set(workspace.workspaceId, workspace); diff --git a/packages/client/workbench/src/terminal/panel.tsx b/packages/client/workbench/src/terminal/panel.tsx index f7c7563bc..22d619a88 100644 --- a/packages/client/workbench/src/terminal/panel.tsx +++ b/packages/client/workbench/src/terminal/panel.tsx @@ -67,7 +67,7 @@ export function TerminalPanel({ const unsubscribe = client.subscribeTerminalError(terminalId, () => { setInputLost(true); clearTimeout(inputLostTimerRef.current); - inputLostTimerRef.current = setTimeout(() => setInputLost(false), INPUT_LOST_BANNER_MS); + inputLostTimerRef.current = setTimeout(setInputLost, INPUT_LOST_BANNER_MS, false); }); return () => { clearTimeout(inputLostTimerRef.current); @@ -100,7 +100,7 @@ export function TerminalPanel({ void client.takeTerminalControl(terminalId).catch(() => { setInputLost(true); clearTimeout(inputLostTimerRef.current); - inputLostTimerRef.current = setTimeout(() => setInputLost(false), INPUT_LOST_BANNER_MS); + inputLostTimerRef.current = setTimeout(setInputLost, INPUT_LOST_BANNER_MS, false); }); }; return ( diff --git a/packages/client/workbench/tests/integration/dev-mock-transport.test.ts b/packages/client/workbench/tests/integration/dev-mock-transport.test.ts index 524b3f050..3febd842e 100644 --- a/packages/client/workbench/tests/integration/dev-mock-transport.test.ts +++ b/packages/client/workbench/tests/integration/dev-mock-transport.test.ts @@ -579,7 +579,8 @@ describe('dev mock transport', () => { }, source: 'user', }); - for (const request of permissionRequests) { + for (let i = 0, len = permissionRequests.length; i < len; i++) { + const request = permissionRequests[i]; // eslint-disable-next-line no-await-in-loop -- answer the asks in order, like a user would. await expect( client.respondPermission(showcase.sessionId, request.requestId, { @@ -711,7 +712,8 @@ describe('dev mock transport', () => { }), ).rejects.toThrow('Unknown question request'); - for (const request of permissionRequests) { + for (let i = 0, len = permissionRequests.length; i < len; i++) { + const request = permissionRequests[i]; // eslint-disable-next-line no-await-in-loop -- assert each cancelled ask reaches its own tool snapshot. const cancelledTool = await eventually(() => toolCalls(events).find( diff --git a/packages/foundation/common/package.json b/packages/foundation/common/package.json index 2593004be..d2187b9a8 100644 --- a/packages/foundation/common/package.json +++ b/packages/foundation/common/package.json @@ -19,7 +19,7 @@ "@noble/ed25519": "3.0.0", "@noble/hashes": "2.2.0", "canonicalize": "3.0.0", - "foxts": "^5.8.1", + "foxts": "^5.9.1", "zod": "catalog:", "zustand": "catalog:" }, diff --git a/packages/foundation/common/src/config/__tests__/brand-identity.test.ts b/packages/foundation/common/src/config/__tests__/brand-identity.test.ts index c471fa57b..f44b5e26c 100644 --- a/packages/foundation/common/src/config/__tests__/brand-identity.test.ts +++ b/packages/foundation/common/src/config/__tests__/brand-identity.test.ts @@ -20,7 +20,10 @@ const FIXTURE_SHA256 = { function toHex(bytes: Uint8Array): string { let hex = ''; - for (const byte of bytes) hex += byte.toString(16).padStart(2, '0'); + for (let i = 0, len = bytes.length; i < len; i++) { + const byte = bytes[i]; + hex += byte.toString(16).padStart(2, '0'); + } return hex; } @@ -34,7 +37,9 @@ function mutate(change: (artifact: Record) => void): unknown { describe('brand identity v1 vendored fixtures', () => { it('matches the frozen publisher bytes exactly', async () => { - for (const [name, digest] of Object.entries(FIXTURE_SHA256)) { + const fixtureDigests = Object.entries(FIXTURE_SHA256); + for (let i = 0, len = fixtureDigests.length; i < len; i++) { + const [name, digest] = fixtureDigests[i]; const suffix = name === 'desktop' ? '' : `-${name}`; // eslint-disable-next-line no-await-in-loop -- four small reads const bytes = await readFile( @@ -45,12 +50,14 @@ describe('brand identity v1 vendored fixtures', () => { }); it('validates every fixture and preserves its target', () => { - for (const [raw, brandId, platform, channel] of [ + const fixtureCases = [ [fixture, 'acme', 'desktop', 'stable'], [fixtureIos, 'acme', 'ios', 'stable'], [fixtureAndroid, 'acme', 'android', 'stable'], [fixtureZenithCanary, 'zenith', 'desktop', 'canary'], - ] as const) { + ] as const; + for (let i = 0, len = fixtureCases.length; i < len; i++) { + const [raw, brandId, platform, channel] = fixtureCases[i]; const identity = parseBrandIdentityArtifact(structuredClone(raw)); expect(identity.brandId).toBe(brandId); expect(identity.platform).toBe(platform); @@ -196,7 +203,8 @@ describe('parseBrandIdentityArtifact', () => { 'manifestSchemaVersion', ], ]; - for (const [change, message] of cases) { + for (let i = 0, len = cases.length; i < len; i++) { + const [change, message] = cases[i]; expect(() => parseBrandIdentityArtifact(mutate(change))).toThrow(message); } }); diff --git a/packages/foundation/common/src/config/__tests__/build-bundle.test.ts b/packages/foundation/common/src/config/__tests__/build-bundle.test.ts index 0853ab329..c88d111ed 100644 --- a/packages/foundation/common/src/config/__tests__/build-bundle.test.ts +++ b/packages/foundation/common/src/config/__tests__/build-bundle.test.ts @@ -25,7 +25,10 @@ const RE_SOURCE_GIT_SHA = /^[0-9a-f]{40}$/; function toHex(bytes: Uint8Array): string { let hex = ''; - for (const byte of bytes) hex += byte.toString(16).padStart(2, '0'); + for (let i = 0, len = bytes.length; i < len; i++) { + const byte = bytes[i]; + hex += byte.toString(16).padStart(2, '0'); + } return hex; } @@ -39,7 +42,9 @@ function mutate(change: (bundle: Record) => void): unknown { describe('build bundle v1 vendored fixtures', () => { it('matches the frozen publisher bytes exactly', async () => { - for (const [name, digest] of Object.entries(FIXTURE_SHA256)) { + const fixtureDigests = Object.entries(FIXTURE_SHA256); + for (let i = 0, len = fixtureDigests.length; i < len; i++) { + const [name, digest] = fixtureDigests[i]; const suffix = name === 'desktop' ? '' : `-${name}`; // eslint-disable-next-line no-await-in-loop -- three small reads const bytes = await readFile( @@ -50,11 +55,13 @@ describe('build bundle v1 vendored fixtures', () => { }); it('validates every platform fixture and extracts its defaults', () => { - for (const [raw, platform] of [ + const fixtureCases = [ [fixture, 'desktop'], [fixtureIos, 'ios'], [fixtureAndroid, 'android'], - ] as const) { + ] as const; + for (let i = 0, len = fixtureCases.length; i < len; i++) { + const [raw, platform] = fixtureCases[i]; const bundle = parseConfigBuildBundle(structuredClone(raw)); expect(bundle.platform).toBe(platform); expect(bundle.brandId).toBe('acme'); diff --git a/packages/foundation/common/src/config/__tests__/contract.test.ts b/packages/foundation/common/src/config/__tests__/contract.test.ts index 5685f5a42..8bf4cefa5 100644 --- a/packages/foundation/common/src/config/__tests__/contract.test.ts +++ b/packages/foundation/common/src/config/__tests__/contract.test.ts @@ -48,7 +48,9 @@ const crypto: ConfigCrypto = { describe('configuration contract v1 golden fixture', () => { it('locks exact snapshot bytes, size, and SHA-256', () => { - for (const name of ['current', 'previous'] as const) { + const snapshotNames = ['current', 'previous'] as const; + for (let i = 0, len = snapshotNames.length; i < len; i++) { + const name = snapshotNames[i]; const vector = snapshots[name]; const document = parseIJson(encoder.encode(vector.canonicalPayload)); assertConfigSnapshot(document); @@ -188,14 +190,16 @@ describe('configuration contract v1 golden fixture', () => { }); it('verifies pointer signatures while retaining additive root fields', () => { - for (const name of [ + const pointerNames = [ 'normal', 'rollback', 'rotationWithoutBump', 'rotation', 'additive', 'schemaTooNew', - ]) { + ]; + for (let i = 0, len = pointerNames.length; i < len; i++) { + const name = pointerNames[i]; const vector = pointers[name]; assertConfigPointer(vector.document); const payload = canonicalSignedPayloadBytes(vector.document); @@ -220,7 +224,9 @@ describe('configuration contract v1 golden fixture', () => { }); it('verifies independent emergency signatures and rejects tampering', () => { - for (const name of ['active', 'clear', 'equivocation']) { + const emergencyNames = ['active', 'clear', 'equivocation']; + for (let i = 0, len = emergencyNames.length; i < len; i++) { + const name = emergencyNames[i]; const vector = emergencies[name]; assertEmergencyDocument(vector.document); const payload = canonicalSignedPayloadBytes(vector.document); @@ -244,7 +250,8 @@ describe('configuration contract v1 golden fixture', () => { }); it('freezes normal and emergency anti-replay decisions', () => { - for (const entry of fixture.cases.pointerAntiReplay) { + for (let i = 0, len = fixture.cases.pointerAntiReplay.length; i < len; i++) { + const entry = fixture.cases.pointerAntiReplay[i]; const candidate = pointers[entry.candidate]; const accepted = entry.accepted === null ? null : pointers[entry.accepted]; expect( @@ -255,7 +262,8 @@ describe('configuration contract v1 golden fixture', () => { entry.name, ).toBe(entry.expectedDecision); } - for (const entry of fixture.cases.emergencyAntiReplay) { + for (let i = 0, len = fixture.cases.emergencyAntiReplay.length; i < len; i++) { + const entry = fixture.cases.emergencyAntiReplay[i]; const candidate = emergencies[entry.candidate]; const accepted = entry.accepted === null ? null : emergencies[entry.accepted]; expect( @@ -267,7 +275,8 @@ describe('configuration contract v1 golden fixture', () => { ).toBe(entry.expectedDecision); } expect(compareMonotonicVersions('9007199254740993', '9007199254740992')).toBeGreaterThan(0); - for (const value of fixture.cases.monotonicVersionErrors) { + for (let i = 0, len = fixture.cases.monotonicVersionErrors.length; i < len; i++) { + const value = fixture.cases.monotonicVersionErrors[i]; expect(() => assertMonotonicVersion(value), value).toThrow('uint64'); } }); @@ -291,7 +300,8 @@ describe('configuration contract v1 golden fixture', () => { expect( conditionMatches({ locale: 'k' }, { appVersion: '2.4.0', locale: 'K', os: 'windows' }), ).toBe(false); - for (const entry of fixture.cases.conditions) { + for (let i = 0, len = fixture.cases.conditions.length; i < len; i++) { + const entry = fixture.cases.conditions[i]; expect( conditionMatches( entry.condition as OverrideCondition, @@ -309,7 +319,8 @@ describe('configuration contract v1 golden fixture', () => { it('pins MurmurHash3 x86_32 UTF-8 and rollout boundaries', () => { expect(murmur3X86_32('', 0)).toBe(0); expect(murmur3X86_32('foo', 0)).toBe(4_138_058_784); - for (const entry of fixture.cases.rollouts) { + for (let i = 0, len = fixture.cases.rollouts.length; i < len; i++) { + const entry = fixture.cases.rollouts[i]; expect(rolloutBucket(entry.salt, entry.deviceId), entry.salt).toBe(entry.expectedBucket); expect(rolloutMatches(entry.salt, entry.deviceId, entry.expectedBucket)).toBe( entry.expectedHitAtBoundary, diff --git a/packages/foundation/common/src/config/__tests__/emergency-handoff.test.ts b/packages/foundation/common/src/config/__tests__/emergency-handoff.test.ts index 4ecb79400..6a31604c8 100644 --- a/packages/foundation/common/src/config/__tests__/emergency-handoff.test.ts +++ b/packages/foundation/common/src/config/__tests__/emergency-handoff.test.ts @@ -169,7 +169,8 @@ describe('emergency handoff signed documents', () => { describe('emergency handoff anti-replay decision table', () => { it('reproduces every frozen decision', () => { expect(fixture.antiReplayCases).toHaveLength(5); - for (const testCase of fixture.antiReplayCases) { + for (let i = 0, len = fixture.antiReplayCases.length; i < len; i++) { + const testCase = fixture.antiReplayCases[i]; expect( decideAntiReplay( replayState(testCase.candidate as DocumentName), @@ -183,7 +184,8 @@ describe('emergency handoff anti-replay decision table', () => { it.each(PLATFORMS)('holds decision-table parity on re-signed %s documents', async (platform) => { const target: ConfigTarget = { ...TARGET, platform }; const states: Record = {}; - for (const name of DOCUMENT_NAMES) { + for (let i = 0, len = DOCUMENT_NAMES.length; i < len; i++) { + const name = DOCUMENT_NAMES[i]; const signed = resignForPlatform(name, platform); // eslint-disable-next-line no-await-in-loop -- documents verify sequentially by design const verified = await verifyEmergencyBytes(encoder.encode(JSON.stringify(signed)), { @@ -201,7 +203,8 @@ describe('emergency handoff anti-replay decision table', () => { expect(verified.payloadSha256).toBe(fixture.documents[name].payloadSha256); } } - for (const testCase of fixture.antiReplayCases) { + for (let i = 0, len = fixture.antiReplayCases.length; i < len; i++) { + const testCase = fixture.antiReplayCases[i]; expect( decideAntiReplay( states[testCase.candidate], @@ -258,7 +261,7 @@ function hex(bytes: Uint8Array): string { function hexBytes(text: string): Uint8Array { const bytes = new Uint8Array(text.length / 2); - for (let index = 0; index < bytes.length; index += 1) { + for (let index = 0, len = bytes.length; index < len; index += 1) { bytes[index] = Number.parseInt(text.slice(index * 2, index * 2 + 2), 16); } return bytes; diff --git a/packages/foundation/common/src/config/__tests__/telemetry.test.ts b/packages/foundation/common/src/config/__tests__/telemetry.test.ts index 639f9daf5..b3ce86793 100644 --- a/packages/foundation/common/src/config/__tests__/telemetry.test.ts +++ b/packages/foundation/common/src/config/__tests__/telemetry.test.ts @@ -122,7 +122,9 @@ describe('classification', () => { 'unsupported-contract': 'parse_failure', 'unsupported-schema': 'parse_failure', }; - for (const [code, failureType] of Object.entries(expected)) { + const expectedEntries = Object.entries(expected); + for (let i = 0, len = expectedEntries.length; i < len; i++) { + const [code, failureType] = expectedEntries[i]; expect(configTelemetryFailureType(code as ConfigErrorCode)).toBe(failureType); } }); @@ -238,7 +240,9 @@ describe('ConfigTelemetryReporter', () => { }); it('dequeues on 202 duplicate replay and terminal 400/409 rejections without retrying', async () => { - for (const outcome of ['accepted', 'rejected'] as const) { + const outcomes = ['accepted', 'rejected'] as const; + for (let i = 0, len = outcomes.length; i < len; i++) { + const outcome = outcomes[i]; const sent: ConfigTelemetryRequest[] = []; const reporter = makeReporter({ send(request) { @@ -379,7 +383,8 @@ describe('ConfigTelemetryReporter', () => { { ...valid, rollout: { channel: 'canary', email: 'user@example.com' } }, { ...valid, clientEventId: 'not-a-uuid' }, ]; - for (const event of tampered) { + for (let i = 0, len = tampered.length; i < len; i++) { + const event = tampered[i]; storage.values.set(key, JSON.stringify({ version: 1, events: [event] })); // eslint-disable-next-line no-await-in-loop -- each corrupted queue is checked in isolation await expect(probe.snapshotQueue()).resolves.toEqual([]); @@ -412,7 +417,8 @@ describe('ConfigTelemetryReporter', () => { ]; const storage = new MemoryStorage(); const probe = makeReporter({ storage }); - for (const event of tampered) { + for (let i = 0, len = tampered.length; i < len; i++) { + const event = tampered[i]; storage.values.set(key, JSON.stringify({ version: 1, events: [event] })); // eslint-disable-next-line no-await-in-loop -- each corrupted queue is checked in isolation await expect(probe.snapshotQueue()).resolves.toEqual([]); diff --git a/packages/foundation/common/src/config/brand-identity.ts b/packages/foundation/common/src/config/brand-identity.ts index c73ecc596..cb04bc02c 100644 --- a/packages/foundation/common/src/config/brand-identity.ts +++ b/packages/foundation/common/src/config/brand-identity.ts @@ -66,7 +66,9 @@ function requireExactKeys( allowed: ReadonlySet, label: string, ): void { - for (const key of Object.keys(value)) { + const keys = Object.keys(value); + for (let i = 0, len = keys.length; i < len; i++) { + const key = keys[i]; if (!allowed.has(key)) fail(`${label} contains unsupported field ${key}`); } for (const key of allowed) { @@ -79,7 +81,8 @@ function assertApplicationId(value: string, platform: ConfigPlatform, label: str const segments = value.split('.'); if (segments.length < 2) fail(`${label} must contain at least two segments`); const segmentRule = platform === 'android' ? RE_ANDROID_ID_SEGMENT : RE_APPLE_ID_SEGMENT; - for (const segment of segments) { + for (let i = 0, len = segments.length; i < len; i++) { + const segment = segments[i]; if (!segmentRule.test(segment)) { fail(`${label} segment ${segment || '(empty)'} is invalid for ${platform}`); } @@ -108,7 +111,9 @@ function assertAssetsPath(value: string, label: string): void { if (value[0] === '/' || value.includes('\\')) { fail(`${label} must be a forward-slash relative path`); } - for (const segment of value.split('/')) { + const segments = value.split('/'); + for (let i = 0, len = segments.length; i < len; i++) { + const segment = segments[i]; if (segment === '' || segment === '.' || segment === '..') { fail(`${label} must not contain empty, dot, or parent segments`); } diff --git a/packages/foundation/common/src/config/build-bundle.ts b/packages/foundation/common/src/config/build-bundle.ts index 986d65743..c9f59a7fb 100644 --- a/packages/foundation/common/src/config/build-bundle.ts +++ b/packages/foundation/common/src/config/build-bundle.ts @@ -30,7 +30,9 @@ function fail(message: string): never { } function assertKeyring(keyring: Readonly>, label: string): void { - for (const [keyId, publicKey] of Object.entries(keyring)) { + const entries = Object.entries(keyring); + for (let i = 0, len = entries.length; i < len; i++) { + const [keyId, publicKey] = entries[i]; let decoded: Uint8Array; try { decoded = decodeBase64Url(publicKey); @@ -45,7 +47,11 @@ function assertKeyring(keyring: Readonly>, label: string) function sha256Hex(bytes: Uint8Array): string { let hex = ''; - for (const byte of sha256(bytes)) hex += byte.toString(16).padStart(2, '0'); + const digest = sha256(bytes); + for (let i = 0, len = digest.length; i < len; i++) { + const byte = digest[i]; + hex += byte.toString(16).padStart(2, '0'); + } return hex; } @@ -126,14 +132,21 @@ export function configBuildBundleDefaults( export function definitionsFromDefaults( defaults: Readonly>, ): ConfigDefinitions { - return Object.fromEntries( - Object.entries(defaults).map(([key, defaultValue]) => [ - key, - { - defaultValue, - parse: (value: ConfigValue) => parseLikeDefault(value, defaultValue), - } satisfies ConfigValueDefinition, - ]), + return Object.entries(defaults).reduce>( + (acc, [key, defaultValue]) => { + // Own data property, never a prototype write: `acc.__proto__ = …` would mutate the object. + Object.defineProperty(acc, key, { + configurable: true, + enumerable: true, + value: { + defaultValue, + parse: (value: ConfigValue) => parseLikeDefault(value, defaultValue), + } satisfies ConfigValueDefinition, + writable: true, + }); + return acc; + }, + {}, ); } diff --git a/packages/foundation/common/src/config/core.ts b/packages/foundation/common/src/config/core.ts index ccd418d23..fb119dcb1 100644 --- a/packages/foundation/common/src/config/core.ts +++ b/packages/foundation/common/src/config/core.ts @@ -22,6 +22,7 @@ import type { ConfigStorage, ConfigTarget, ConfigValue, + ConfigValueDefinition, ConfigValues, EvaluationContext, } from './types'; @@ -70,12 +71,18 @@ export class ConfigCore { throw new TypeError('maximumSchemaVersion must be a positive safe integer'); } configPointerPath(options.target); - const definitions = Object.fromEntries( - Object.entries(options.definitions).map(([key, definition]) => [ - key, - { defaultValue: cloneJson(definition.defaultValue), parse: definition.parse }, - ]), - ) as Definitions; + const definitions = Object.entries(options.definitions).reduce< + Record + >((acc, [key, definition]) => { + // Own data property, never a prototype write: `acc.__proto__ = …` would mutate the object. + Object.defineProperty(acc, key, { + configurable: true, + enumerable: true, + value: { defaultValue: cloneJson(definition.defaultValue), parse: definition.parse }, + writable: true, + }); + return acc; + }, {}) as Definitions; this.#options = { ...options, context: { ...options.context }, @@ -323,7 +330,9 @@ export class ConfigCore { const before = this.#stateIdentity(); const next: Record = {}; const staged: Array> = []; - for (const key of Object.keys(this.#options.definitions)) { + const definitionKeys = Object.keys(this.#options.definitions); + for (let i = 0, len = definitionKeys.length; i < len; i++) { + const key = definitionKeys[i]; const candidate = lkg.values[key]; const pinned = this.#coldPinned[key]; if (lkg.snapshot.document.applyModes[key] === 'hot') { diff --git a/packages/foundation/common/src/config/evaluation.ts b/packages/foundation/common/src/config/evaluation.ts index b70164f13..dd2d56d42 100644 --- a/packages/foundation/common/src/config/evaluation.ts +++ b/packages/foundation/common/src/config/evaluation.ts @@ -27,7 +27,9 @@ export function defaultValues( definitions: Definitions, ): ConfigValues { const values: Record = {}; - for (const [key, definition] of Object.entries(definitions)) { + const definitionEntries = Object.entries(definitions); + for (let i = 0, len = definitionEntries.length; i < len; i++) { + const [key, definition] = definitionEntries[i]; if (!isConfigKey(key)) throw new ConfigCoreError('schema-invalid', `Invalid known key ${key}`); values[key] = parseDefinitionValue(definition, key, definition.defaultValue, `default.${key}`); if (key.startsWith('feature.')) { @@ -56,19 +58,24 @@ export function evaluateSnapshot( } let evaluated: Record = { ...snapshot.values }; - for (const override of snapshot.overrides) { + for (let i = 0, len = snapshot.overrides.length; i < len; i++) { + const override = snapshot.overrides[i]; if (conditionMatches(override.when, context)) { evaluated = applyConfigPatch(evaluated, override.set); } } - for (const [key, rollout] of Object.entries(snapshot.rollouts)) { + const rolloutEntries = Object.entries(snapshot.rollouts); + for (let i = 0, len = rolloutEntries.length; i < len; i++) { + const [key, rollout] = rolloutEntries[i]; if (rolloutMatches(rollout.salt, deviceId, rollout.basisPoints)) { evaluated[key] = rollout.value; } } const values = defaultValues(definitions) as Record; - for (const [key, value] of Object.entries(evaluated)) { + const evaluatedEntries = Object.entries(evaluated); + for (let i = 0, len = evaluatedEntries.length; i < len; i++) { + const [key, value] = evaluatedEntries[i]; const definition = definitionFor(definitions, key); if (!definition) continue; values[key] = parseDefinitionValue(definition, key, value, key); @@ -82,7 +89,9 @@ export function applyEmergency( definitions: Definitions, ): ConfigValues { const projected = cloneJson(values as ConfigValue) as Record; - for (const key of emergency?.disabledFeatures ?? []) { + const disabledFeatures = emergency?.disabledFeatures ?? []; + for (let i = 0, len = disabledFeatures.length; i < len; i++) { + const key = disabledFeatures[i]; if (definitionFor(definitions, key)) projected[key] = false; } return projected as ConfigValues; @@ -120,7 +129,9 @@ function validateKnownValues( definitions: ConfigDefinitions, label: string, ): void { - for (const [key, value] of Object.entries(values)) { + const valueEntries = Object.entries(values); + for (let i = 0, len = valueEntries.length; i < len; i++) { + const [key, value] = valueEntries[i]; const definition = definitionFor(definitions, key); if (definition) parseDefinitionValue(definition, key, value, `${label}.${key}`); } diff --git a/packages/foundation/common/src/config/i-json.ts b/packages/foundation/common/src/config/i-json.ts index 216934b74..cef119c5e 100644 --- a/packages/foundation/common/src/config/i-json.ts +++ b/packages/foundation/common/src/config/i-json.ts @@ -7,7 +7,7 @@ const NUMBER_PATTERN = /-?(?:0|[1-9]\d*)(?:\.\d+)?(?:e[+-]?\d+)?/iy; export function encodeBase64Url(bytes: Uint8Array): string { let encoded = ''; - for (let index = 0; index < bytes.length; index += 3) { + for (let index = 0, len = bytes.length; index < len; index += 3) { const remaining = bytes.length - index; const first = bytes[index]; const second = remaining > 1 ? bytes[index + 1] : 0; @@ -47,7 +47,16 @@ export function cloneJson(value: Value): Value; export function cloneJson(value: JsonValue): JsonValue { if (Array.isArray(value)) return value.map((entry) => cloneJson(entry)); if (typeof value === 'object' && value !== null) { - return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, cloneJson(entry)])); + return Object.entries(value).reduce>((acc, [key, entry]) => { + // Own data property, never a prototype write: `acc.__proto__ = …` would mutate the clone. + Object.defineProperty(acc, key, { + configurable: true, + enumerable: true, + value: cloneJson(entry), + writable: true, + }); + return acc; + }, {}); } return value; } @@ -63,11 +72,16 @@ function assertIJsonValue(value: unknown, label: string): asserts value is JsonV } if (value === null || typeof value === 'boolean') return; if (Array.isArray(value)) { - for (const [index, entry] of value.entries()) assertIJsonValue(entry, `${label}[${index}]`); + for (let index = 0, len = value.length; index < len; index++) { + const entry = value[index]; + assertIJsonValue(entry, `${label}[${index}]`); + } return; } if (typeof value !== 'object') throw new TypeError(`${label} is not an I-JSON value`); - for (const [key, entry] of Object.entries(value)) { + const entries = Object.entries(value); + for (let i = 0, len = entries.length; i < len; i++) { + const [key, entry] = entries[i]; assertUnicodeScalarString(key, `${label} key`); assertIJsonValue(entry, `${label}.${key}`); } diff --git a/packages/foundation/common/src/config/rules.ts b/packages/foundation/common/src/config/rules.ts index 429f2a7aa..f97f85836 100644 --- a/packages/foundation/common/src/config/rules.ts +++ b/packages/foundation/common/src/config/rules.ts @@ -30,7 +30,9 @@ export function applyMergePatch( typeof target === 'object' && target !== null && !Array.isArray(target) ? cloneJson(target) : {}; - for (const [key, patchValue] of Object.entries(patch)) { + const patchEntries = Object.entries(patch); + for (let i = 0, len = patchEntries.length; i < len; i++) { + const [key, patchValue] = patchEntries[i]; const merged = applyMergePatch(result[key], patchValue); if (merged === undefined) Reflect.deleteProperty(result, key); else result[key] = merged; @@ -42,10 +44,19 @@ export function applyConfigPatch( values: Readonly>, patch: Readonly>, ): Record { - const result = Object.fromEntries( - Object.entries(values).map(([key, value]) => [key, cloneJson(value)]), - ); - for (const [key, patchValue] of Object.entries(patch)) { + const result = Object.entries(values).reduce>((acc, [key, value]) => { + // Own data property, never a prototype write: `acc.__proto__ = …` would mutate the result. + Object.defineProperty(acc, key, { + configurable: true, + enumerable: true, + value: cloneJson(value), + writable: true, + }); + return acc; + }, {}); + const patchEntries = Object.entries(patch); + for (let i = 0, len = patchEntries.length; i < len; i++) { + const [key, patchValue] = patchEntries[i]; if (!isConfigKey(key)) fail(`patch key ${key} is invalid`); const merged = applyMergePatch(result[key], patchValue); if (merged === undefined) Reflect.deleteProperty(result, key); diff --git a/packages/foundation/common/src/config/semver.ts b/packages/foundation/common/src/config/semver.ts index a23d14463..aaa761e8d 100644 --- a/packages/foundation/common/src/config/semver.ts +++ b/packages/foundation/common/src/config/semver.ts @@ -56,7 +56,9 @@ function parseSemver(value: string): ParsedSemver | null { } function compareSemver(left: ParsedSemver, right: ParsedSemver): number { - for (const field of ['major', 'minor', 'patch'] as const) { + const coreFields = ['major', 'minor', 'patch'] as const; + for (let i = 0, len = coreFields.length; i < len; i++) { + const field = coreFields[i]; const comparison = compareDecimal(left[field], right[field]); if (comparison !== 0) return comparison; } @@ -84,7 +86,8 @@ function parseVersionRange(value: string): readonly VersionComparator[] | null { const parts = value.split(' '); if (parts.some((part) => part.length === 0)) return null; const comparators: VersionComparator[] = []; - for (const part of parts) { + for (let i = 0, len = parts.length; i < len; i++) { + const part = parts[i]; const operator = (['>=', '<=', '>', '<', '='] as const).find((candidate) => part.startsWith(candidate), ); diff --git a/packages/foundation/common/src/node/__tests__/executable-locations.test.ts b/packages/foundation/common/src/node/__tests__/executable-locations.test.ts index 32171e8f1..e242dec26 100644 --- a/packages/foundation/common/src/node/__tests__/executable-locations.test.ts +++ b/packages/foundation/common/src/node/__tests__/executable-locations.test.ts @@ -32,7 +32,9 @@ describe('executableSearchLocations', () => { it('yields only absolute candidate paths', () => { vi.stubEnv('PATH', ['relative/bin', ''].join(delimiter)); - for (const location of executableSearchLocations('tool')) { + const locations = executableSearchLocations('tool'); + for (let i = 0, len = locations.length; i < len; i++) { + const location = locations[i]; expect(isAbsolute(location)).toBe(true); } }); diff --git a/packages/foundation/common/src/node/__tests__/release-artifact.test.ts b/packages/foundation/common/src/node/__tests__/release-artifact.test.ts index 67950baa7..f337fa7a0 100644 --- a/packages/foundation/common/src/node/__tests__/release-artifact.test.ts +++ b/packages/foundation/common/src/node/__tests__/release-artifact.test.ts @@ -110,13 +110,15 @@ describe('release artifact provenance', () => { 'executable code', ); - for (const [key, value, expected] of [ + const bypassCases = [ ['content.pluginUrl', 'https://example.invalid/content', 'executable'], ['modules.wasmLoader', false, 'must exactly match'], ['content.scriptPath', '/content/banner', 'executable'], ['content.inline', '
', 'executable'], ['content.source', 'data:text/javascript,alert(1)', 'executable'], - ] as const) { + ] as const; + for (let i = 0, len = bypassCases.length; i < len; i++) { + const [key, value, expected] = bypassCases[i]; const bypass = structuredClone(bundleFixture); const bypassSnapshot = JSON.parse( Buffer.from(bypass.snapshot.base64Url, 'base64url').toString(), diff --git a/packages/foundation/common/src/node/brand-assets.ts b/packages/foundation/common/src/node/brand-assets.ts index f4312ef24..3f0c7c603 100644 --- a/packages/foundation/common/src/node/brand-assets.ts +++ b/packages/foundation/common/src/node/brand-assets.ts @@ -27,10 +27,11 @@ function validatedAssetDir(structuralDir: string, assetsPath: string): string { } let dirStats; try { - dirStats = lstatSync(dir); + dirStats = lstatSync(dir, { throwIfNoEntry: false }); } catch { fail(`brand assets directory ${assetsPath} does not exist`); } + if (dirStats === undefined) fail(`brand assets directory ${assetsPath} does not exist`); if (dirStats.isSymbolicLink()) fail(`brand assets directory ${assetsPath} must not be a symlink`); if (!dirStats.isDirectory()) fail(`brand assets path ${assetsPath} is not a directory`); return dir; @@ -51,7 +52,8 @@ export function stageBrandAssets(options: { const dir = validatedAssetDir(options.structuralDir, options.assetsPath); const entries = readdirSync(dir).sort(); const label = options.assetsPath; - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; const stats = lstatSync(join(dir, entry)); if (stats.isSymbolicLink()) fail(`brand asset ${label}/${entry} must not be a symlink`); if (!stats.isFile()) { diff --git a/packages/foundation/common/src/node/config-build-render.ts b/packages/foundation/common/src/node/config-build-render.ts index 3744d5a87..fc95636d1 100644 --- a/packages/foundation/common/src/node/config-build-render.ts +++ b/packages/foundation/common/src/node/config-build-render.ts @@ -144,12 +144,15 @@ function parseReleaseManifest(value: unknown, path: string): ConfigBuildReleaseM throw new TypeError(`Release manifest at ${path} has an unsupported format version`); } const keys = version === 1 ? RELEASE_MANIFEST_V1_KEY_SET : RELEASE_MANIFEST_V2_KEY_SET; - for (const key of Object.keys(manifest)) { + const manifestKeys = Object.keys(manifest); + for (let i = 0, len = manifestKeys.length; i < len; i++) { + const key = manifestKeys[i]; if (!keys.has(key)) { throw new TypeError(`Release manifest at ${path} contains unsupported field ${key}`); } } - for (const key of RELEASE_MANIFEST_BASE_KEYS) { + for (let i = 0, len = RELEASE_MANIFEST_BASE_KEYS.length; i < len; i++) { + const key = RELEASE_MANIFEST_BASE_KEYS[i]; if (!(key in manifest)) { throw new TypeError(`Release manifest at ${path} is missing field ${key}`); } @@ -244,11 +247,13 @@ export async function assertReleaseManifestBinding( } const manifest = parseReleaseManifest(JSON.parse(manifestText), manifestPath); const digest = (bytes: Buffer): string => createHash('sha256').update(bytes).digest('hex'); - for (const field of [ + const hexDigestFields = [ 'expectedSnapshotSha256', 'publicKeyringsSha256', 'revisionSha256', - ] as const) { + ] as const; + for (let i = 0, len = hexDigestFields.length; i < len; i++) { + const field = hexDigestFields[i]; if (!RE_HEX_SHA256.test(manifest[field])) { throw new TypeError(`Release manifest ${field} must be a lowercase 64-hex SHA-256`); } @@ -269,7 +274,8 @@ export async function assertReleaseManifestBinding( ['telemetryEndpoint', manifest.telemetryEndpoint, bundle.endpoints.telemetry], ['expectedSnapshotSha256', manifest.expectedSnapshotSha256, bundle.snapshot.sha256], ]; - for (const [field, expected, got] of checks) { + for (let i = 0, len = checks.length; i < len; i++) { + const [field, expected, got] = checks[i]; if (expected !== got) { throw new Error( `Release manifest binding failed: ${field} is pinned to ${expected} but this build used ${got}`, diff --git a/packages/foundation/common/src/node/executable-locations.ts b/packages/foundation/common/src/node/executable-locations.ts index 3080f8107..0482eb21f 100644 --- a/packages/foundation/common/src/node/executable-locations.ts +++ b/packages/foundation/common/src/node/executable-locations.ts @@ -17,7 +17,9 @@ import { delimiter, isAbsolute, join } from 'node:path'; */ function pathInstallLocations(binary: string): string[] { const locations: string[] = []; - for (const entry of (process.env.PATH ?? '').split(delimiter)) { + const pathEntries = (process.env.PATH ?? '').split(delimiter); + for (let i = 0, len = pathEntries.length; i < len; i++) { + const entry = pathEntries[i]; // Windows PATH entries with spaces are conventionally double-quoted. const dir = entry.replaceAll('"', ''); if (dir.length > 0 && isAbsolute(dir)) locations.push(join(dir, binary)); diff --git a/packages/foundation/common/src/node/release-artifact-cli.mts b/packages/foundation/common/src/node/release-artifact-cli.mts index e1285ef75..7167cd8a1 100644 --- a/packages/foundation/common/src/node/release-artifact-cli.mts +++ b/packages/foundation/common/src/node/release-artifact-cli.mts @@ -85,11 +85,19 @@ function compliance(value: unknown): StoreComplianceDeclaration { bail('compliance declaration must contain checklist and disclosedFeatures'); } return { - checklist: Object.fromEntries( - Object.entries(declaration.checklist).map(([key, entry]) => { + checklist: Object.entries(declaration.checklist).reduce>( + (acc, [key, entry]) => { if (typeof entry !== 'boolean') bail(`compliance checklist field ${key} must be boolean`); - return [key, entry]; - }), + // Own data property, never a prototype write: `acc.__proto__ = …` would mutate the object. + Object.defineProperty(acc, key, { + configurable: true, + enumerable: true, + value: entry, + writable: true, + }); + return acc; + }, + {}, ), disclosedFeatures: declaration.disclosedFeatures.filter( (entry): entry is string => typeof entry === 'string', diff --git a/packages/foundation/common/src/node/release-artifact.ts b/packages/foundation/common/src/node/release-artifact.ts index 025c13145..6fc3fed84 100644 --- a/packages/foundation/common/src/node/release-artifact.ts +++ b/packages/foundation/common/src/node/release-artifact.ts @@ -76,7 +76,8 @@ function assertReleaseBinding(bundle: ConfigBuildBundle, manifest: ReleaseManife ['configRevisionId', bundle.provenance.configRevisionId, manifest.configRevisionId], ['expectedSnapshotSha256', bundle.snapshot.sha256, manifest.expectedSnapshotSha256], ] as const; - for (const [field, actual, expected] of checks) { + for (let i = 0, len = checks.length; i < len; i++) { + const [field, actual, expected] = checks[i]; if (actual !== expected) { throw new Error(`release manifest ${field} does not match the rendered bundle`); } @@ -88,7 +89,9 @@ async function artifactFile( path: string, ): Promise<{ path: string; sha256: string; sizeBytes: number }> { const absoluteRoot = await realpath(root); - const absolutePath = resolve(root, path); + // Resolve against the canonicalized root: a symlinked root (macOS /var → /private/var) + // would otherwise make every legitimate path read as an escape. + const absolutePath = resolve(absoluteRoot, path); const relativePath = relative(absoluteRoot, absolutePath); if (relativePath === '' || relativePath.startsWith('..') || relativePath.includes('\\')) { throw new TypeError(`artifact path escapes its isolated root: ${path}`); @@ -217,7 +220,8 @@ function releaseArtifactProvenance(value: unknown): ReleaseArtifactProvenance { } const paths = new Set(); const artifacts: Array = []; - for (const [index, value] of provenance.artifacts.entries()) { + for (let index = 0, len = provenance.artifacts.length; index < len; index++) { + const value = provenance.artifacts[index]; if (typeof value !== 'object' || value === null || Array.isArray(value)) { throw new TypeError(`release provenance artifact ${index} must be an object`); } @@ -354,7 +358,9 @@ export async function writeReleaseArtifactProvenance( artifactRoot: string, ): Promise { const absoluteRoot = await realpath(artifactRoot); - const absolutePath = resolve(artifactRoot, path); + // Resolve against the canonicalized root: a symlinked root (macOS /var → /private/var) + // would otherwise make every legitimate path read as an escape. + const absolutePath = resolve(absoluteRoot, path); const relativePath = relative(absoluteRoot, absolutePath); if (relativePath === '' || relativePath.startsWith('..') || relativePath.includes('\\')) { throw new TypeError(`provenance path escapes its isolated root: ${path}`); @@ -380,7 +386,16 @@ function jsonValue(value: unknown): JsonValue { if (typeof value !== 'object') { throw new TypeError('release provenance must contain only JSON values'); } - return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, jsonValue(entry)])); + return Object.entries(value).reduce>((acc, [key, entry]) => { + // Own data property, never a prototype write: `acc.__proto__ = …` would mutate the clone. + Object.defineProperty(acc, key, { + configurable: true, + enumerable: true, + value: jsonValue(entry), + writable: true, + }); + return acc; + }, {}); } export function parseReleaseArtifactInputs( diff --git a/packages/foundation/common/src/node/release-compliance.ts b/packages/foundation/common/src/node/release-compliance.ts index 21c893b52..90178bea9 100644 --- a/packages/foundation/common/src/node/release-compliance.ts +++ b/packages/foundation/common/src/node/release-compliance.ts @@ -57,13 +57,16 @@ function assertSafeConfigurationValue( throw new TypeError(`${path} looks like executable code or an executable-code URL`); } if (Array.isArray(value)) { - for (const [index, entry] of value.entries()) { + for (let index = 0, len = value.length; index < len; index++) { + const entry = value[index]; assertSafeConfigurationValue(entry, `${path}[${index}]`, disclosedFeatures); } return; } if (typeof value !== 'object' || value === null) return; - for (const [key, entry] of Object.entries(value)) { + const entries = Object.entries(value); + for (let i = 0, len = entries.length; i < len; i++) { + const [key, entry] = entries[i]; const tokens = configurationKeyTokens(key); if (tokens.some((token) => EXECUTABLE_KEY_TOKENS.has(token))) { throw new TypeError(`${path}.${key} declares an executable-code surface`); @@ -90,7 +93,8 @@ export function assertStoreCompliance( `compliance checklist must contain exactly: ${STORE_CHECKLIST_KEYS.join(', ')}`, ); } - for (const key of STORE_CHECKLIST_KEYS) { + for (let i = 0, len = STORE_CHECKLIST_KEYS.length; i < len; i++) { + const key = STORE_CHECKLIST_KEYS[i]; if (!declaration.checklist[key]) { throw new TypeError(`compliance checklist ${key} must be true`); } @@ -104,7 +108,8 @@ export function assertStoreCompliance( `disclosedFeatures must exactly match configurable feature/module keys: ${configurableFeatures.join(', ')}`, ); } - for (const key of keys) { + for (let i = 0, len = keys.length; i < len; i++) { + const key = keys[i]; if (configurationKeyTokens(key).some((token) => EXECUTABLE_KEY_TOKENS.has(token))) { throw new TypeError(`configuration key ${key} declares an executable-code surface`); } diff --git a/packages/foundation/common/src/sentry/index.ts b/packages/foundation/common/src/sentry/index.ts index 1ffe29925..5ceb992d5 100644 --- a/packages/foundation/common/src/sentry/index.ts +++ b/packages/foundation/common/src/sentry/index.ts @@ -105,9 +105,12 @@ export function sanitizeSentryTransaction( ? sanitizeProfileContext(event.contexts.profile) : undefined; const spans: TransactionSpan[] = []; - for (const span of event.spans ?? []) { - const sanitizedSpan = sanitizeSpan(span, options); - if (sanitizedSpan) spans.push(sanitizedSpan); + if (event.spans != null) { + for (let i = 0, len = event.spans.length; i < len; i++) { + const span = event.spans[i]; + const sanitizedSpan = sanitizeSpan(span, options); + if (sanitizedSpan) spans.push(sanitizedSpan); + } } const sanitized: SentryTransactionEvent = { event_id: validId(event.event_id, RE_EVENT_ID), @@ -122,7 +125,11 @@ export function sanitizeSentryTransaction( measurements: sanitizeMeasurements(event.measurements, options.safeMeasurementNames), }; - for (const key of Object.keys(event)) Reflect.deleteProperty(event, key); + const eventKeys = Object.keys(event); + for (let i = 0, len = eventKeys.length; i < len; i++) { + const key = eventKeys[i]; + Reflect.deleteProperty(event, key); + } Object.assign(event, sanitized); return event; } @@ -187,7 +194,8 @@ function sanitizeMeasurements( if (!isRecord(measurements) || !safeNames?.length) return undefined; const sanitized: Record = {}; let hasMeasurement = false; - for (const name of safeNames) { + for (let i = 0, len = safeNames.length; i < len; i++) { + const name = safeNames[i]; const measurement = measurements[name]; if (!isRecord(measurement)) continue; const value = finiteNumber(measurement.value); diff --git a/packages/foundation/common/src/telemetry-config/index.ts b/packages/foundation/common/src/telemetry-config/index.ts index bf256cab9..07eac769e 100644 --- a/packages/foundation/common/src/telemetry-config/index.ts +++ b/packages/foundation/common/src/telemetry-config/index.ts @@ -57,7 +57,7 @@ export function parseTelemetryConfig(value: unknown): TelemetryConfig | null { /** Fetches public sampling configuration without delaying telemetry initialization on failure. */ export async function fetchTelemetryConfig( - fetcher: TelemetryConfigFetcher = globalThis.fetch, + fetcher: TelemetryConfigFetcher = fetch, ): Promise { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 3000); diff --git a/packages/foundation/providers/package.json b/packages/foundation/providers/package.json index ddb3b1805..1e7e58a3b 100644 --- a/packages/foundation/providers/package.json +++ b/packages/foundation/providers/package.json @@ -11,6 +11,6 @@ }, "dependencies": { "@linkcode/schema": "workspace:*", - "foxts": "^5.8.1" + "foxts": "^5.9.1" } } diff --git a/packages/foundation/providers/src/__tests__/resolve.test.ts b/packages/foundation/providers/src/__tests__/resolve.test.ts index c06c3c48d..eb2e0af89 100644 --- a/packages/foundation/providers/src/__tests__/resolve.test.ts +++ b/packages/foundation/providers/src/__tests__/resolve.test.ts @@ -31,7 +31,9 @@ describe('resolveBinding: one explicit endpoint', () => { it('routes an anthropic endpoint natively to claude-code, opencode and pi', () => { const endpoint = { baseUrl: 'https://api.anthropic.com', protocol: 'anthropic' } as const; const anthropic = account({ endpoint }); - for (const kind of ['claude-code', 'opencode', 'pi'] as const) { + const nativeKinds = ['claude-code', 'opencode', 'pi'] as const; + for (let i = 0, len = nativeKinds.length; i < len; i++) { + const kind = nativeKinds[i]; expect(resolveBinding(anthropic, kind)).toEqual({ tier: 'native', ...endpoint }); } expect(resolveBinding(anthropic, 'codex')).toEqual({ @@ -68,7 +70,8 @@ describe('resolveBinding: one explicit endpoint', () => { it('keeps a pre-catalog bare key bindable everywhere', () => { const legacy = account({}); - for (const kind of ALL_KINDS) { + for (let i = 0, len = ALL_KINDS.length; i < len; i++) { + const kind = ALL_KINDS[i]; expect(resolveBinding(legacy, kind)).toEqual({ tier: 'native' }); } }); @@ -120,7 +123,9 @@ describe('resolveBinding: variant chosen per agent', () => { protocol: 'openai-responses', baseUrl: 'https://api.deepseek.com', }); - for (const kind of ['opencode', 'pi'] as const) { + const providerRoutedKinds = ['opencode', 'pi'] as const; + for (let i = 0, len = providerRoutedKinds.length; i < len; i++) { + const kind = providerRoutedKinds[i]; expect(resolveBinding(deepseek, kind)).toEqual({ tier: 'native', protocol: 'openai-chat', @@ -172,7 +177,8 @@ describe('resolveBinding: variant chosen per agent', () => { ['openrouter', 'https://openrouter.ai/api/v1'], ['vercel-gateway', 'https://ai-gateway.vercel.sh/v1'], ] as const; - for (const [service, baseUrl] of cases) { + for (let i = 0, len = cases.length; i < len; i++) { + const [service, baseUrl] = cases[i]; expect(resolveBinding(account({ service }), 'codex')).toEqual({ tier: 'native', protocol: 'openai-responses', @@ -201,7 +207,9 @@ describe('resolveBinding: variant chosen per agent', () => { protocol: 'openai-chat', baseUrl: 'https://gateway.linkcode.ai/v1', }); - for (const kind of ['opencode', 'pi'] as const) { + const providerRoutedKinds = ['opencode', 'pi'] as const; + for (let i = 0, len = providerRoutedKinds.length; i < len; i++) { + const kind = providerRoutedKinds[i]; expect(resolveBinding(gateway, kind)).toEqual({ tier: 'native', protocol: 'openai-chat', @@ -217,7 +225,9 @@ describe('resolveBinding: variant chosen per agent', () => { it('leaves opencode and pi on their known-provider variant when a responses one exists', () => { // The added responses variants carry no knownProvider, so provider-routed agents are untouched. - for (const kind of ['opencode', 'pi'] as const) { + const providerRoutedKinds = ['opencode', 'pi'] as const; + for (let i = 0, len = providerRoutedKinds.length; i < len; i++) { + const kind = providerRoutedKinds[i]; expect(resolveBinding(account({ service: 'xai' }), kind)).toMatchObject({ protocol: 'openai-chat', knownProvider: 'xai', @@ -355,7 +365,9 @@ describe('catalog helpers', () => { it('keeps the model-list url independent of the variant an agent resolves to', () => { // Deriving from the resolved variant is what this replaced: the anthropic variants of these two // sit on different paths, so appending would ask a route that does not exist. - for (const id of ['deepseek', 'vercel-gateway']) { + const serviceIds = ['deepseek', 'vercel-gateway']; + for (let i = 0, len = serviceIds.length; i < len; i++) { + const id = serviceIds[i]; const service = nullthrow(endpointServiceById(id), `${id} missing`); const anthropic = nullthrow(service.variants.anthropic, `${id} anthropic variant missing`); expect(nullthrow(service.models, `${id} model list missing`).url).not.toBe( diff --git a/packages/foundation/providers/src/detected-logins.ts b/packages/foundation/providers/src/detected-logins.ts index 12ba1d40d..823a0d4c1 100644 --- a/packages/foundation/providers/src/detected-logins.ts +++ b/packages/foundation/providers/src/detected-logins.ts @@ -17,7 +17,8 @@ export function detectedLogins( runtimes: AgentRuntimes | undefined, ): DetectedLogin[] { const suggestions: DetectedLogin[] = []; - for (const service of SERVICE_CATALOG) { + for (let i = 0, len = SERVICE_CATALOG.length; i < len; i++) { + const service = SERVICE_CATALOG[i]; if (service.kind !== 'oauth') continue; const auth = runtimes?.[service.agent]?.auth; if (auth?.loggedIn !== true) continue; diff --git a/packages/foundation/providers/src/resolve.ts b/packages/foundation/providers/src/resolve.ts index 945c37eaf..fc956ff74 100644 --- a/packages/foundation/providers/src/resolve.ts +++ b/packages/foundation/providers/src/resolve.ts @@ -96,7 +96,9 @@ function resolveService( account: Account, kind: AgentKind, ): ResolvedBinding { - for (const protocol of preferredProtocols(service, kind)) { + const protocols = preferredProtocols(service, kind); + for (let i = 0, len = protocols.length; i < len; i++) { + const protocol = protocols[i]; const variant = service.variants[protocol]; if (!variant) continue; const params = account.endpointParams ?? {}; @@ -191,7 +193,9 @@ function providerEnvFor( const mapping = variant.endpointEnv?.[kind]; if (!mapping) return undefined; const env: Record = {}; - for (const [param, name] of Object.entries(mapping)) { + const mappingEntries = Object.entries(mapping); + for (let i = 0, len = mappingEntries.length; i < len; i++) { + const [param, name] = mappingEntries[i]; const value = params[param]; if (value !== undefined) env[name] = value; } diff --git a/packages/foundation/providers/src/template.ts b/packages/foundation/providers/src/template.ts index e05f07401..0e5e25b64 100644 --- a/packages/foundation/providers/src/template.ts +++ b/packages/foundation/providers/src/template.ts @@ -2,7 +2,7 @@ const PLACEHOLDER_PATTERN = /\{([a-z_]+)\}/g; /** Account-specific `{placeholder}` fields a templated endpoint URL needs filled. */ export function templatePlaceholders(baseUrl: string): string[] { - return [...baseUrl.matchAll(PLACEHOLDER_PATTERN)].map((match) => match[1]); + return Array.from(baseUrl.matchAll(PLACEHOLDER_PATTERN), (match) => match[1]); } export function fillTemplate(baseUrl: string, values: Record): string { diff --git a/packages/foundation/schema/package.json b/packages/foundation/schema/package.json index dc0f951be..d9806d165 100644 --- a/packages/foundation/schema/package.json +++ b/packages/foundation/schema/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "canonicalize": "3.0.0", + "foxts": "^5.9.1", "zod": "catalog:" }, "devDependencies": { diff --git a/packages/foundation/schema/src/model/__tests__/linkcode-marketplace.test.ts b/packages/foundation/schema/src/model/__tests__/linkcode-marketplace.test.ts index 5c760c50d..360c7646a 100644 --- a/packages/foundation/schema/src/model/__tests__/linkcode-marketplace.test.ts +++ b/packages/foundation/schema/src/model/__tests__/linkcode-marketplace.test.ts @@ -58,7 +58,9 @@ describe('LinkCode marketplace contracts', () => { }); it('rejects insecure remote sources and duplicate local marketplace ids', () => { - for (const url of ['http://example.com/index.json', 'https:example.com/index.json']) { + const insecureUrls = ['http://example.com/index.json', 'https:example.com/index.json']; + for (let i = 0, len = insecureUrls.length; i < len; i++) { + const url = insecureUrls[i]; expect( LinkCodeMarketplaceConfigListSchema.safeParse([marketplace('community', url)]).success, ).toBe(false); diff --git a/packages/foundation/schema/src/model/__tests__/plugin.test.ts b/packages/foundation/schema/src/model/__tests__/plugin.test.ts index 795b9a435..a36d61cb5 100644 --- a/packages/foundation/schema/src/model/__tests__/plugin.test.ts +++ b/packages/foundation/schema/src/model/__tests__/plugin.test.ts @@ -219,7 +219,7 @@ describe('LinkCode plugin package contracts', () => { String.raw`skills\latex\SKILL.md`, 'C:/SKILL.md', 'skills/latex./SKILL.md', - `skills/latex${String.fromCodePoint(0)}/SKILL.md`, + `skills/latex${String.fromCharCode(0)}/SKILL.md`, 'skills/latex/readme.md', 'skills/latex/skill.md', ])('rejects invalid skill package entry %s', (entry) => { diff --git a/packages/foundation/schema/src/model/linkcode-marketplace.ts b/packages/foundation/schema/src/model/linkcode-marketplace.ts index f4ab15267..eff08fea1 100644 --- a/packages/foundation/schema/src/model/linkcode-marketplace.ts +++ b/packages/foundation/schema/src/model/linkcode-marketplace.ts @@ -1,3 +1,4 @@ +import { split0th } from 'foxts/split-nth'; import { z } from 'zod'; import { LinkCodeMarketplaceIdSchema, @@ -38,7 +39,8 @@ export const LinkCodeMarketplaceConfigListSchema = z .array(LinkCodeMarketplaceConfigSchema) .superRefine((marketplaces, ctx) => { const ids = new Set(); - for (const [index, marketplace] of marketplaces.entries()) { + for (let index = 0, len = marketplaces.length; index < len; index++) { + const marketplace = marketplaces[index]; if (ids.has(marketplace.id)) { ctx.addIssue({ code: 'custom', @@ -56,7 +58,8 @@ function validateMarketplacePlugin( ctx: z.RefinementCtx, ): void { const versions = new Set(); - for (const [index, release] of plugin.releases.entries()) { + for (let index = 0, len = plugin.releases.length; index < len; index++) { + const release = plugin.releases[index]; if (release.manifest.id !== plugin.id) { ctx.addIssue({ code: 'custom', @@ -64,7 +67,7 @@ function validateMarketplacePlugin( path: ['releases', index, 'manifest', 'id'], }); } - const precedenceVersion = release.manifest.version.split('+', 1)[0]; + const precedenceVersion = split0th(release.manifest.version, '+'); if (versions.has(precedenceVersion)) { ctx.addIssue({ code: 'custom', @@ -108,7 +111,8 @@ function rejectDuplicatePlugins( ctx: z.RefinementCtx, ): void { const pluginIds = new Set(); - for (const [pluginIndex, plugin] of index.plugins.entries()) { + for (let pluginIndex = 0, len = index.plugins.length; pluginIndex < len; pluginIndex++) { + const plugin = index.plugins[pluginIndex]; if (pluginIds.has(plugin.id)) { ctx.addIssue({ code: 'custom', diff --git a/packages/foundation/schema/src/model/linkcode-plugin.ts b/packages/foundation/schema/src/model/linkcode-plugin.ts index 4155f625c..157ac4f84 100644 --- a/packages/foundation/schema/src/model/linkcode-plugin.ts +++ b/packages/foundation/schema/src/model/linkcode-plugin.ts @@ -126,7 +126,8 @@ function rejectDuplicateComponents( ctx: z.RefinementCtx, ): void { const names = new Set(); - for (const component of manifest.components) { + for (let i = 0, len = manifest.components.length; i < len; i++) { + const component = manifest.components[i]; const key = `${component.kind}:${component.name}`; if (names.has(key)) { ctx.addIssue({ diff --git a/packages/foundation/schema/src/model/permission.ts b/packages/foundation/schema/src/model/permission.ts index 293e72f42..3e5d72baa 100644 --- a/packages/foundation/schema/src/model/permission.ts +++ b/packages/foundation/schema/src/model/permission.ts @@ -24,7 +24,8 @@ const PermissionOptionsSchema = z .min(1) .superRefine((options, ctx) => { const optionIds = new Set(); - for (const [index, option] of options.entries()) { + for (let index = 0, len = options.length; index < len; index++) { + const option = options[index]; if (optionIds.has(option.optionId)) { ctx.addIssue({ code: 'custom', diff --git a/packages/foundation/schema/src/model/question.ts b/packages/foundation/schema/src/model/question.ts index 53ce878aa..8ebbe4276 100644 --- a/packages/foundation/schema/src/model/question.ts +++ b/packages/foundation/schema/src/model/question.ts @@ -18,7 +18,8 @@ const QuestionOptionsSchema = z .min(1) .superRefine((options, ctx) => { const optionIds = new Set(); - for (const [index, option] of options.entries()) { + for (let index = 0, len = options.length; index < len; index++) { + const option = options[index]; if (optionIds.has(option.optionId)) { ctx.addIssue({ code: 'custom', @@ -48,7 +49,8 @@ const QuestionsSchema = z .min(1) .superRefine((questions, ctx) => { const questionIds = new Set(); - for (const [index, question] of questions.entries()) { + for (let index = 0, len = questions.length; index < len; index++) { + const question = questions[index]; if (questionIds.has(question.questionId)) { ctx.addIssue({ code: 'custom', diff --git a/packages/foundation/schema/src/remote-config.ts b/packages/foundation/schema/src/remote-config.ts index d496fc747..af25705d8 100644 --- a/packages/foundation/schema/src/remote-config.ts +++ b/packages/foundation/schema/src/remote-config.ts @@ -139,7 +139,9 @@ export const ConfigSnapshotSchema = z .catchall(JsonValueSchema) .superRefine((snapshot, context) => { const coveredKeys = new Set(); - for (const [key, value] of Object.entries(snapshot.values)) { + const valueEntries = Object.entries(snapshot.values); + for (let i = 0, len = valueEntries.length; i < len; i++) { + const [key, value] = valueEntries[i]; if (!isConfigKey(key)) { context.addIssue({ code: 'custom', @@ -156,8 +158,11 @@ export const ConfigSnapshotSchema = z } coveredKeys.add(key); } - for (const [index, override] of snapshot.overrides.entries()) { - for (const [key, value] of Object.entries(override.set)) { + for (let index = 0, len = snapshot.overrides.length; index < len; index++) { + const override = snapshot.overrides[index]; + const overrideEntries = Object.entries(override.set); + for (let j = 0, entryCount = overrideEntries.length; j < entryCount; j++) { + const [key, value] = overrideEntries[j]; if (!isConfigKey(key)) { context.addIssue({ code: 'custom', @@ -175,7 +180,9 @@ export const ConfigSnapshotSchema = z coveredKeys.add(key); } } - for (const key of Object.keys(snapshot.rollouts)) { + const rolloutKeys = Object.keys(snapshot.rollouts); + for (let i = 0, len = rolloutKeys.length; i < len; i++) { + const key = rolloutKeys[i]; if (!key.startsWith('feature.') || !isConfigKey(key)) { context.addIssue({ code: 'custom', @@ -185,7 +192,9 @@ export const ConfigSnapshotSchema = z } coveredKeys.add(key); } - for (const key of Object.keys(snapshot.applyModes)) { + const applyModeKeys = Object.keys(snapshot.applyModes); + for (let i = 0, len = applyModeKeys.length; i < len; i++) { + const key = applyModeKeys[i]; if (!isConfigKey(key)) { context.addIssue({ code: 'custom', @@ -271,7 +280,9 @@ export const ConfigBuildBundleSchema = z snapshot: ConfigBuildBundleSnapshotEnvelopeSchema, }) .superRefine((bundle, context) => { - for (const kind of ['normal', 'emergency'] as const) { + const keyringKinds = ['normal', 'emergency'] as const; + for (let i = 0, len = keyringKinds.length; i < len; i++) { + const kind = keyringKinds[i]; if ( (bundle.endpoints[kind] === null) !== (Object.keys(bundle.keyrings[kind]).at(0) === undefined) @@ -338,7 +349,8 @@ export const EmergencyDocumentSchema = z }) .catchall(SignedJsonValueSchema) .superRefine((document, context) => { - for (const [index, key] of document.disabledFeatures.entries()) { + for (let index = 0, len = document.disabledFeatures.length; index < len; index++) { + const key = document.disabledFeatures[index]; if (!key.startsWith('feature.') || !isConfigKey(key)) { context.addIssue({ code: 'custom', @@ -390,7 +402,19 @@ export function compareMonotonicVersions(left: string, right: string): number { export function canonicalSignedPayload(document: unknown): string { if (!isRecord(document)) throw new TypeError('signed envelope must be an object'); SignatureSchema.parse(document.sig); - const unsigned = Object.fromEntries(Object.entries(document).filter(([key]) => key !== 'sig')); + const unsigned = Object.entries(document).reduce>((acc, [key, value]) => { + if (key !== 'sig') { + // Own data property, never a prototype write: a JSON `__proto__` member must survive + // into the canonical payload instead of silently mutating (and vanishing from) it. + Object.defineProperty(acc, key, { + configurable: true, + enumerable: true, + value, + writable: true, + }); + } + return acc; + }, {}); assertSignedEnvelopeValue(unsigned, 'signed envelope payload'); return canonicalizeJson(unsigned); } @@ -486,13 +510,16 @@ function assertSignedEnvelopeValue(value: unknown, label: string): asserts value } if (value === null || typeof value === 'boolean' || typeof value === 'string') return; if (Array.isArray(value)) { - for (const [index, entry] of value.entries()) { + for (let index = 0, len = value.length; index < len; index++) { + const entry = value[index]; assertSignedEnvelopeValue(entry, `${label}[${index}]`); } return; } if (!isRecord(value)) throw new TypeError(`${label} must contain only JSON values`); - for (const [key, entry] of Object.entries(value)) { + const entries = Object.entries(value); + for (let i = 0, len = entries.length; i < len; i++) { + const [key, entry] = entries[i]; assertSignedEnvelopeValue(entry, `${label}.${key}`); } } diff --git a/packages/foundation/schema/tests/contract/wire/loop.test.ts b/packages/foundation/schema/tests/contract/wire/loop.test.ts index 83142a4d9..45314c260 100644 --- a/packages/foundation/schema/tests/contract/wire/loop.test.ts +++ b/packages/foundation/schema/tests/contract/wire/loop.test.ts @@ -63,7 +63,8 @@ describe('loop wire variants', () => { { kind: 'loop.iteration', iteration }, { kind: 'loop.log', loopId: loop.loopId, entry: log }, ]; - for (const payload of payloads) { + for (let i = 0, len = payloads.length; i < len; i++) { + const payload = payloads[i]; expect(parseWireMessage(envelope(payload)).ok, payload.kind).toBe(true); } }); diff --git a/packages/foundation/schema/tests/contract/wire/plugin.test.ts b/packages/foundation/schema/tests/contract/wire/plugin.test.ts index 66380b264..dc8649e33 100644 --- a/packages/foundation/schema/tests/contract/wire/plugin.test.ts +++ b/packages/foundation/schema/tests/contract/wire/plugin.test.ts @@ -134,7 +134,9 @@ describe('plugin wire schema', () => { }); it('round-trips install and uninstall requests', () => { - for (const kind of ['plugin.install', 'plugin.uninstall']) { + const kinds = ['plugin.install', 'plugin.uninstall']; + for (let i = 0, len = kinds.length; i < len; i++) { + const kind = kinds[i]; expect( parseWireMessage( envelope({ diff --git a/packages/foundation/schema/tests/contract/wire/schedule.test.ts b/packages/foundation/schema/tests/contract/wire/schedule.test.ts index 4f9db92fb..6853462d4 100644 --- a/packages/foundation/schema/tests/contract/wire/schedule.test.ts +++ b/packages/foundation/schema/tests/contract/wire/schedule.test.ts @@ -54,7 +54,8 @@ describe('schedule wire variants', () => { { kind: 'schedule.removed', scheduleId: schedule.scheduleId }, { kind: 'schedule.run', run }, ]; - for (const payload of payloads) { + for (let i = 0, len = payloads.length; i < len; i++) { + const payload = payloads[i]; expect(parseWireMessage(envelope(payload)).ok, payload.kind).toBe(true); } }); diff --git a/packages/foundation/transport/package.json b/packages/foundation/transport/package.json index 7c6a76a3f..8469f8f13 100644 --- a/packages/foundation/transport/package.json +++ b/packages/foundation/transport/package.json @@ -15,7 +15,7 @@ "dependencies": { "@linkcode/schema": "workspace:*", "@linkcode/tunnel": "^0.1.0", - "foxts": "^5.8.0", + "foxts": "^5.9.1", "socket.io": "catalog:", "socket.io-client": "catalog:", "ws": "catalog:", diff --git a/packages/foundation/transport/src/__tests__/tunnel.test.ts b/packages/foundation/transport/src/__tests__/tunnel.test.ts index f9dbab2af..2f04a685f 100644 --- a/packages/foundation/transport/src/__tests__/tunnel.test.ts +++ b/packages/foundation/transport/src/__tests__/tunnel.test.ts @@ -53,7 +53,10 @@ class FakeWebSocket { } emit(type: string, event: unknown): void { - for (const cb of this.listeners.get(type) ?? []) cb(event); + const callbacks = this.listeners.get(type); + if (callbacks != null) { + for (const cb of callbacks) cb(event); + } } } @@ -106,7 +109,9 @@ describe('TunnelTransportServer', () => { const inbound: unknown[] = []; connection.onMessage((message) => inbound.push(message)); const request = createWireMessage({ kind: 'session.list', clientReqId: 'r1' }); - for (const data of new TunnelChunkEncoder(1).encode(JSON.stringify(request))) { + const chunks = new TunnelChunkEncoder(1).encode(JSON.stringify(request)); + for (let i = 0, len = chunks.length; i < len; i++) { + const data = chunks[i]; socket.emit('message', { data: encodeTunnelPeerFrame({ kind: 'peer.data', peerId: 'peer-1', data }), }); @@ -115,7 +120,8 @@ describe('TunnelTransportServer', () => { connection.send(createWireMessage({ kind: 'request.succeeded', replyTo: 'r1' })); let outbound: TunnelPeerFrame | null = null; - for (const sent of socket.sent) { + for (let i = 0, len = socket.sent.length; i < len; i++) { + const sent = socket.sent[i]; if (!(sent instanceof ArrayBuffer)) continue; const frame = decodeTunnelPeerFrame(sent); if (frame?.kind === 'peer.data') { @@ -330,7 +336,9 @@ describe('TunnelTransportServer', () => { candidate.emit('message', { data: encodeTunnelPeerFrame({ kind: 'peer.join', peerId: 'peer-1' }), }); - for (const data of chunks.slice(1)) { + const remainingChunks = chunks.slice(1); + for (let i = 0, len = remainingChunks.length; i < len; i++) { + const data = remainingChunks[i]; candidate.emit('message', { data: encodeTunnelPeerFrame({ kind: 'peer.data', peerId: 'peer-1', data }), }); @@ -346,7 +354,8 @@ describe('TunnelTransportServer', () => { expect(inbound).toEqual([request]); await vi.waitFor(() => { let outbound = 0; - for (const sent of candidate.sent) { + for (let i = 0, len = candidate.sent.length; i < len; i++) { + const sent = candidate.sent[i]; if (!(sent instanceof ArrayBuffer)) continue; if (decodeTunnelPeerFrame(sent)?.kind === 'peer.data') outbound += 1; } @@ -401,7 +410,9 @@ describe('TunnelTransportServer', () => { candidate.emit('message', { data: encodeTunnelPeerFrame({ kind: 'peer.join', peerId: 'peer-1' }), }); - for (const data of new TunnelChunkEncoder(2).encode(JSON.stringify(request))) { + const chunks = new TunnelChunkEncoder(2).encode(JSON.stringify(request)); + for (let i = 0, len = chunks.length; i < len; i++) { + const data = chunks[i]; candidate.emit('message', { data: encodeTunnelPeerFrame({ kind: 'peer.data', peerId: 'peer-1', data }), }); diff --git a/packages/foundation/transport/src/http-server.ts b/packages/foundation/transport/src/http-server.ts index 9b68f5a0f..f7c81f3ed 100644 --- a/packages/foundation/transport/src/http-server.ts +++ b/packages/foundation/transport/src/http-server.ts @@ -2,6 +2,7 @@ import { once } from 'node:events'; import type { Server as HttpServer, IncomingMessage, ServerResponse } from 'node:http'; import type { DaemonIdentity } from '@linkcode/schema'; import { DAEMON_IDENTITY_PATH } from '@linkcode/schema'; +import { split0th } from 'foxts/split-nth'; /** Shared HTTP plumbing for the Node server transports: the `GET /linkcode` identity endpoint * (tells a linkcode daemon apart from a foreign process holding the port) and a `listen` that @@ -11,7 +12,7 @@ export function createIdentityRequestHandler( identity: DaemonIdentity | undefined, ): (req: IncomingMessage, res: ServerResponse) => void { return (req, res) => { - if (identity && req.method === 'GET' && req.url?.split('?', 1)[0] === DAEMON_IDENTITY_PATH) { + if (identity && req.method === 'GET' && split0th(req.url ?? '', '?') === DAEMON_IDENTITY_PATH) { res.writeHead(200, { 'content-type': 'application/json' }); res.end(JSON.stringify(identity)); return; diff --git a/packages/foundation/transport/src/hub.ts b/packages/foundation/transport/src/hub.ts index 8a6923d92..5c4fc3e96 100644 --- a/packages/foundation/transport/src/hub.ts +++ b/packages/foundation/transport/src/hub.ts @@ -126,14 +126,25 @@ export class Hub implements Transport { bestEffort(() => conn.send(createWireMessage(pong()))); return; } - if (p.kind === 'session.attach') subscription.attached.add(p.sessionId); - else if (p.kind === 'session.detach') subscription.attached.delete(p.sessionId); - else if (p.kind === 'terminal.detach') { - const attachments = subscription.terminals.get(p.terminalId); - if (attachments?.get(p.attachmentId) === p.attachmentSecret) { - attachments.delete(p.attachmentId); - if (attachments.size === 0) subscription.terminals.delete(p.terminalId); + switch (p.kind) { + case 'session.attach': { + subscription.attached.add(p.sessionId); + break; } + case 'session.detach': { + subscription.attached.delete(p.sessionId); + break; + } + case 'terminal.detach': { + const attachments = subscription.terminals.get(p.terminalId); + if (attachments?.get(p.attachmentId) === p.attachmentSecret) { + attachments.delete(p.attachmentId); + if (attachments.size === 0) subscription.terminals.delete(p.terminalId); + } + + break; + } + // no default } } if ('clientReqId' in p) { diff --git a/packages/foundation/transport/src/preview-proxy.ts b/packages/foundation/transport/src/preview-proxy.ts index 3cadff99c..7356be535 100644 --- a/packages/foundation/transport/src/preview-proxy.ts +++ b/packages/foundation/transport/src/preview-proxy.ts @@ -198,7 +198,7 @@ function proxyUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer, port: upstream.on('connect', () => { const lines = [`${req.method ?? 'GET'} ${req.url ?? '/'} HTTP/1.1`]; - for (let i = 0; i < req.rawHeaders.length; i += 2) { + for (let i = 0, len = req.rawHeaders.length; i < len; i += 2) { lines.push(`${req.rawHeaders[i]}: ${req.rawHeaders[i + 1]}`); } upstream.write(`${lines.join('\r\n')}\r\n\r\n`); diff --git a/packages/foundation/transport/src/tunnel-client.ts b/packages/foundation/transport/src/tunnel-client.ts index bc98d2118..e17a378c7 100644 --- a/packages/foundation/transport/src/tunnel-client.ts +++ b/packages/foundation/transport/src/tunnel-client.ts @@ -101,7 +101,11 @@ export class TunnelClient { throw new Error('TunnelClient: host messages must be sent through a peer'); } const ws = this.openSocket(); - for (const frame of this.encoder.encode(message)) ws.send(frame); + const frames = this.encoder.encode(message); + for (let i = 0, len = frames.length; i < len; i++) { + const frame = frames[i]; + ws.send(frame); + } } onMessage(cb: (message: string) => void): () => void { @@ -155,7 +159,10 @@ export class TunnelClient { throw failure; } if (this.candidateWs === ws) this.candidateWs = null; - for (const event of prepared.buffered) this.handleMessage(ws, event); + for (let i = 0, len = prepared.buffered.length; i < len; i++) { + const event = prepared.buffered[i]; + this.handleMessage(ws, event); + } if (this.closedByUser || ws !== this.ws) { throw new Error('TunnelClient: socket closed during handshake'); } @@ -277,7 +284,12 @@ export class TunnelClient { this.adopt(ws, prepared); const queued = this.handoffQueue; this.handoffQueue = null; - if (queued) for (const frame of queued) ws.send(frame); + if (queued) { + for (let i = 0, len = queued.length; i < len; i++) { + const frame = queued[i]; + ws.send(frame); + } + } if (current !== ws && current.readyState === current.OPEN) current.close(1000); } catch { if (handoffStarted) this.abortHandoff(current); @@ -288,7 +300,9 @@ export class TunnelClient { private sendToPeer(peerId: string, message: string): void { if (!this.peers.has(peerId)) throw new Error('TunnelPeer: connection closed'); const ws = this.handoffQueue ? null : this.openSocket(); - for (const data of this.encoder.encode(message)) { + const chunks = this.encoder.encode(message); + for (let i = 0, len = chunks.length; i < len; i++) { + const data = chunks[i]; const frame = encodeTunnelPeerFrame({ kind: 'peer.data', peerId, data }); if (this.handoffQueue) this.handoffQueue.push(frame); else ws?.send(frame); @@ -358,7 +372,8 @@ export class TunnelClient { private reconcilePeers(buffered: readonly MessageEvent[]): void { const successorPeers = new Set(); - for (const event of buffered) { + for (let i = 0, len = buffered.length; i < len; i++) { + const event = buffered[i]; if (!(event.data instanceof ArrayBuffer)) continue; const frame = decodeTunnelPeerFrame(event.data); if (frame?.kind === 'peer.join') successorPeers.add(frame.peerId); diff --git a/packages/foundation/transport/tests/integration/preview-proxy.test.ts b/packages/foundation/transport/tests/integration/preview-proxy.test.ts index c24f6ae6f..5806f0aca 100644 --- a/packages/foundation/transport/tests/integration/preview-proxy.test.ts +++ b/packages/foundation/transport/tests/integration/preview-proxy.test.ts @@ -9,8 +9,12 @@ import { WebSocket, WebSocketServer } from 'ws'; const cleanups: Array<() => Promise | void> = []; afterAll(async () => { - // eslint-disable-next-line no-await-in-loop -- teardown must run one at a time in LIFO order - for (const cleanup of cleanups.reverse()) await cleanup(); + const pending = cleanups.reverse(); + for (let i = 0, len = pending.length; i < len; i++) { + const cleanup = pending[i]; + // eslint-disable-next-line no-await-in-loop -- teardown must run one at a time in LIFO order + await cleanup(); + } }); /** An upstream dev-server stand-in: echoes the request path and Host, and echoes WS frames. */ diff --git a/packages/host/agent-adapter/package.json b/packages/host/agent-adapter/package.json index d364c6128..2e69f9ea9 100644 --- a/packages/host/agent-adapter/package.json +++ b/packages/host/agent-adapter/package.json @@ -20,7 +20,7 @@ "@openai/codex": "^0.144.6", "@opencode-ai/sdk": "^1.18.3", "cross-spawn": "^7.0.6", - "foxts": "^5.8.0", + "foxts": "^5.9.1", "smol-toml": "^1.7.1", "zod": "catalog:" }, diff --git a/packages/host/agent-adapter/src/__tests__/claude-code-approval.test.ts b/packages/host/agent-adapter/src/__tests__/claude-code-approval.test.ts index d1a6d5ee2..9b6569d15 100644 --- a/packages/host/agent-adapter/src/__tests__/claude-code-approval.test.ts +++ b/packages/host/agent-adapter/src/__tests__/claude-code-approval.test.ts @@ -262,7 +262,6 @@ describe('ClaudeCodeAdapter approval policy', () => { ], }, }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- AsyncMessageQueue.push takes ONE message; the merge autofix silently drops this one q.push({ type: 'system', subtype: 'permission_denied', diff --git a/packages/host/agent-adapter/src/__tests__/claude-code-commands.test.ts b/packages/host/agent-adapter/src/__tests__/claude-code-commands.test.ts index d908d8a6a..f9eb86032 100644 --- a/packages/host/agent-adapter/src/__tests__/claude-code-commands.test.ts +++ b/packages/host/agent-adapter/src/__tests__/claude-code-commands.test.ts @@ -186,7 +186,10 @@ class FakeQuery { } function pushMessages(query: FakeQuery, ...messages: WireMessage[]): void { - for (const message of messages) query.push(message); + for (let i = 0, len = messages.length; i < len; i++) { + const message = messages[i]; + query.push(message); + } } const queries: FakeQuery[] = []; diff --git a/packages/host/agent-adapter/src/__tests__/claude-code-effort.test.ts b/packages/host/agent-adapter/src/__tests__/claude-code-effort.test.ts index 683e46232..3e8331601 100644 --- a/packages/host/agent-adapter/src/__tests__/claude-code-effort.test.ts +++ b/packages/host/agent-adapter/src/__tests__/claude-code-effort.test.ts @@ -172,7 +172,6 @@ describe('ClaudeCodeAdapter session titles', () => { await adapter.start({ kind: 'claude-code', cwd: '/tmp/repo' }); await prompt(adapter); queries[0].push({ type: 'system', session_id: 'sess-title' }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- FakeQuery.push accepts one provider message at a time queries[0].push({ type: 'result', subtype: 'success', @@ -224,7 +223,6 @@ describe('ClaudeCodeAdapter session titles', () => { await adapter.start({ kind: 'claude-code', cwd: '/tmp/repo' }); await prompt(adapter); queries[0].push({ type: 'system', session_id: 'sess-rename' }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- FakeQuery.push accepts one provider message at a time queries[0].push({ type: 'result', subtype: 'success', @@ -280,7 +278,6 @@ describe('ClaudeCodeAdapter session titles', () => { await adapter.start({ kind: 'claude-code', cwd: '/tmp/repo' }); await prompt(adapter); queries[0].push({ type: 'system', session_id: 'sess-delayed' }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- FakeQuery.push accepts one provider message at a time queries[0].push({ type: 'result', subtype: 'success', diff --git a/packages/host/agent-adapter/src/__tests__/claude-code-subagent.test.ts b/packages/host/agent-adapter/src/__tests__/claude-code-subagent.test.ts index 2914aaa67..2443eb807 100644 --- a/packages/host/agent-adapter/src/__tests__/claude-code-subagent.test.ts +++ b/packages/host/agent-adapter/src/__tests__/claude-code-subagent.test.ts @@ -317,7 +317,8 @@ describe('ClaudeCodeAdapter readHistory subagent splice', () => { 'agent-message:u3', ]); - for (const e of result.events) { + for (let i = 0, len = result.events.length; i < len; i++) { + const e = result.events[i]; if (e.event.type === 'tool-call' && e.event.toolCall.toolCallId === 'toolu_sub') { expect(e.event.toolCall.parentToolCallId).toBe(TASK_ID); } @@ -416,10 +417,7 @@ describe('ClaudeCodeAdapter readHistory subagent splice', () => { message: { content: [{ type: 'tool_result', tool_use_id: EDIT_ID, content: 'updated' }] }, tool_use_result: toolUseResult, }); - const liveSettle = live - .tools() - .filter((t) => t.toolCallId === EDIT_ID) - .at(-1); + const liveSettle = live.tools().findLast((t) => t.toolCallId === EDIT_ID); // History: `getSubagentMessages` strips `tool_use_result`, so the patch has to come from the // subagent's own raw transcript instead. @@ -444,7 +442,7 @@ describe('ClaudeCodeAdapter readHistory subagent splice', () => { }), ); const result = await adapter.readHistory({ historyId: asHistoryId(SESSION) }); - const replayedSettle = result.events.filter((e) => e.itemId === EDIT_ID).at(-1)?.event; + const replayedSettle = result.events.findLast((e) => e.itemId === EDIT_ID)?.event; expect(replayedSettle?.type).toBe('tool-call'); if (replayedSettle?.type !== 'tool-call') return; diff --git a/packages/host/agent-adapter/src/__tests__/codex-app-server.test.ts b/packages/host/agent-adapter/src/__tests__/codex-app-server.test.ts index c123de333..4eac6f0ba 100644 --- a/packages/host/agent-adapter/src/__tests__/codex-app-server.test.ts +++ b/packages/host/agent-adapter/src/__tests__/codex-app-server.test.ts @@ -31,7 +31,10 @@ function fakeChild() { buffered += chunk.toString(); const lines = buffered.split('\n'); buffered = lines.pop() ?? ''; - for (const line of lines) writes.push(JSON.parse(line) as Record); + for (let i = 0, len = lines.length; i < len; i++) { + const line = lines[i]; + writes.push(JSON.parse(line) as Record); + } }); return { child, diff --git a/packages/host/agent-adapter/src/__tests__/codex-auth.test.ts b/packages/host/agent-adapter/src/__tests__/codex-auth.test.ts index 348b3f878..3a0d4ce14 100644 --- a/packages/host/agent-adapter/src/__tests__/codex-auth.test.ts +++ b/packages/host/agent-adapter/src/__tests__/codex-auth.test.ts @@ -34,7 +34,8 @@ class FakeCodexServer { close(): void { this.closed = true; const rejections = this.held.splice(0); - for (const reject of rejections) { + for (let i = 0, len = rejections.length; i < len; i++) { + const reject = rejections[i]; reject(new Error('codex: app-server connection is closed')); } } diff --git a/packages/host/agent-adapter/src/__tests__/opencode.test.ts b/packages/host/agent-adapter/src/__tests__/opencode.test.ts index 5fe9a70be..4a5faacd1 100644 --- a/packages/host/agent-adapter/src/__tests__/opencode.test.ts +++ b/packages/host/agent-adapter/src/__tests__/opencode.test.ts @@ -284,7 +284,6 @@ describe('OpenCodeAdapter.consumeEvents', () => { }, }, }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- FakeEventStream.push accepts one provider event at a time client.stream.push({ id: 'e-tool-completed', type: 'message.part.updated', @@ -354,19 +353,16 @@ describe('OpenCodeAdapter.consumeEvents', () => { type: 'message.part.updated', properties: { sessionID: 'sess-1', time: 0, part: part('prt-mcp-1', 'linear_list_issues') }, }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- FakeEventStream.push accepts one provider event at a time client.stream.push({ id: 'e-mcp-configured', type: 'message.part.updated', properties: { sessionID: 'sess-1', time: 1, part: part('prt-mcp-2', 'notion_search_pages') }, }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- FakeEventStream.push accepts one provider event at a time client.stream.push({ id: 'e-builtin', type: 'message.part.updated', properties: { sessionID: 'sess-1', time: 2, part: part('prt-builtin', 'bash') }, }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- FakeEventStream.push accepts one provider event at a time client.stream.push({ id: 'e-mcp-ambiguous', type: 'message.part.updated', @@ -412,7 +408,6 @@ describe('OpenCodeAdapter.consumeEvents', () => { }, }, }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- not array client.stream.push({ id: 'e-user-part', type: 'message.part.updated', @@ -428,7 +423,6 @@ describe('OpenCodeAdapter.consumeEvents', () => { }, }, }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- not array client.stream.push({ id: 'e-assistant-msg', type: 'message.updated', @@ -450,7 +444,6 @@ describe('OpenCodeAdapter.consumeEvents', () => { }, }, }); - // eslint-disable-next-line sukka/unicorn/prefer-single-call -- not array client.stream.push({ id: 'e-assistant-part', type: 'message.part.updated', diff --git a/packages/host/agent-adapter/src/__tests__/pi-approval.test.ts b/packages/host/agent-adapter/src/__tests__/pi-approval.test.ts index 0ad3d505d..b7fcb188b 100644 --- a/packages/host/agent-adapter/src/__tests__/pi-approval.test.ts +++ b/packages/host/agent-adapter/src/__tests__/pi-approval.test.ts @@ -38,15 +38,18 @@ vi.mock('@earendil-works/pi-coding-agent', async () => { private readonly options: { extensionFactories?: Array<(api: unknown) => void> }, ) {} reload() { - for (const factory of this.options.extensionFactories ?? []) { - factory({ - on(_name: string, handler: Gate) { - sdk.gate = handler; - }, - registerTool(tool: RegisteredTool) { - sdk.tool = tool; - }, - }); + if (this.options.extensionFactories != null) { + for (let i = 0, len = this.options.extensionFactories.length; i < len; i++) { + const factory = this.options.extensionFactories[i]; + factory({ + on(_name: string, handler: Gate) { + sdk.gate = handler; + }, + registerTool(tool: RegisteredTool) { + sdk.tool = tool; + }, + }); + } } return Promise.resolve(); } diff --git a/packages/host/agent-adapter/src/__tests__/pi-model-registry.test.ts b/packages/host/agent-adapter/src/__tests__/pi-model-registry.test.ts index 6e08b0164..ac9188b38 100644 --- a/packages/host/agent-adapter/src/__tests__/pi-model-registry.test.ts +++ b/packages/host/agent-adapter/src/__tests__/pi-model-registry.test.ts @@ -9,7 +9,11 @@ const roots: string[] = []; afterEach(() => { vi.unstubAllEnvs(); - for (const root of roots.splice(0)) rmSync(root, { force: true, recursive: true }); + const staleRoots = roots.splice(0); + for (let i = 0, len = staleRoots.length; i < len; i++) { + const root = staleRoots[i]; + rmSync(root, { force: true, recursive: true }); + } }); describe('Pi model registry integration', () => { diff --git a/packages/host/agent-adapter/src/credential.ts b/packages/host/agent-adapter/src/credential.ts index c79d34672..4b5285be9 100644 --- a/packages/host/agent-adapter/src/credential.ts +++ b/packages/host/agent-adapter/src/credential.ts @@ -96,6 +96,10 @@ function readString(value: unknown): string | undefined { function readStringRecord(value: unknown): Record | undefined { if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined; const out: Record = {}; - for (const [key, val] of Object.entries(value)) if (typeof val === 'string') out[key] = val; + const entries = Object.entries(value); + for (let i = 0, len = entries.length; i < len; i++) { + const [key, val] = entries[i]; + if (typeof val === 'string') out[key] = val; + } return isObjectEmpty(out) ? undefined : out; } diff --git a/packages/host/agent-adapter/src/history-util.ts b/packages/host/agent-adapter/src/history-util.ts index 48c9267c2..4799c05e5 100644 --- a/packages/host/agent-adapter/src/history-util.ts +++ b/packages/host/agent-adapter/src/history-util.ts @@ -52,7 +52,8 @@ export function sliceHistoryEventPage( ): { events: AgentHistoryEvent[]; cursor: string | undefined } { const page: AgentHistoryEvent[] = []; let pageByteLength = 0; - for (let index = offset; index < events.length && page.length < limit; index += 1) { + for (let index = offset, len = events.length; index < len; index += 1) { + if (page.length >= limit) break; const eventLength = eventSerializedByteLength(events[index]); if (page.length > 0 && pageByteLength + eventLength > MAX_ATTACHMENT_TOTAL_BASE64_LENGTH) { break; diff --git a/packages/host/agent-adapter/src/native/claude-code.ts b/packages/host/agent-adapter/src/native/claude-code.ts index d913128a7..b77c19372 100644 --- a/packages/host/agent-adapter/src/native/claude-code.ts +++ b/packages/host/agent-adapter/src/native/claude-code.ts @@ -171,7 +171,8 @@ async function settingsDefaultMode(cwd: string): Promise | undefined { if (!servers?.length) return undefined; const out: Record = {}; - for (const server of servers) { + for (let i = 0, len = servers.length; i < len; i++) { + const server = servers[i]; out[server.name] = server.type === 'http' ? { type: 'http', url: server.url, ...(server.headers && { headers: server.headers }) } @@ -322,13 +324,16 @@ function usageWindows( push('seven_day_oauth_apps', 10080, limits.seven_day_oauth_apps); push('seven_day_opus', 10080, limits.seven_day_opus); push('seven_day_sonnet', 10080, limits.seven_day_sonnet); - for (const bucket of limits.model_scoped ?? []) { - windows.push({ - label: bucket.display_name, - utilization: bucket.utilization, - resetsAt: bucket.resets_at, - durationMins: 10080, - }); + if (limits.model_scoped != null) { + for (let i = 0, len = limits.model_scoped.length; i < len; i++) { + const bucket = limits.model_scoped[i]; + windows.push({ + label: bucket.display_name, + utilization: bucket.utilization, + resetsAt: bucket.resets_at, + durationMins: 10080, + }); + } } return windows; } @@ -364,18 +369,34 @@ export function mapClaudeUsageReport(raw: SDKControlGetUsageResponse): UsageRepo totalDurationMs: raw.session.total_duration_ms, totalLinesAdded: raw.session.total_lines_added, totalLinesRemoved: raw.session.total_lines_removed, - modelUsage: Object.fromEntries( - Object.entries(raw.session.model_usage).map(([model, usage]) => [ - model, + modelUsage: Object.entries(raw.session.model_usage).reduce< + Record< + string, { + inputTokens: number; + outputTokens: number; + cacheReadTokens: number; + cacheCreationTokens: number; + totalCostUsd: number; + } + > + >((acc, [model, usage]) => { + // Own data property, never a prototype write: model ids come from the CLI subprocess. + // (The `UsageReportSchema.parse` below drops a `__proto__` key from the output either way.) + Object.defineProperty(acc, model, { + configurable: true, + enumerable: true, + value: { inputTokens: usage.inputTokens, outputTokens: usage.outputTokens, cacheReadTokens: usage.cacheReadInputTokens, cacheCreationTokens: usage.cacheCreationInputTokens, totalCostUsd: usage.costUSD, }, - ]), - ), + writable: true, + }); + return acc; + }, {}), }, subscriptionType: raw.subscription_type, rateLimits: limits @@ -719,7 +740,10 @@ export class ClaudeCodeAdapter extends BaseAgentAdapter { const children = subagentEvents.get(event.event.toolCall.toolCallId); if (children) { subagentEvents.delete(event.event.toolCall.toolCallId); - for (const child of children) pushWithSubagents(child); + for (let i = 0, len = children.length; i < len; i++) { + const child = children[i]; + pushWithSubagents(child); + } } } }; @@ -731,8 +755,13 @@ export class ClaudeCodeAdapter extends BaseAgentAdapter { const returned = new Set(page.map((message) => message.uuid)); const dropped = offset === 0 ? supplement.droppedRows.filter((row) => !returned.has(row.uuid)) : []; - for (const message of [...dropped, ...page]) { - for (const event of mapper(message)) pushWithSubagents(event); + const rows = [...dropped, ...page]; + for (let i = 0, len = rows.length; i < len; i++) { + const message = rows[i]; + const mapped = mapper(message); + for (let j = 0, eventCount = mapped.length; j < eventCount; j++) { + pushWithSubagents(mapped[j]); + } } return { session: info @@ -1195,12 +1224,14 @@ export class ClaudeCodeAdapter extends BaseAgentAdapter { } const byQuestionId = new Map(outcome.answers.map((answer) => [answer.questionId, answer])); const answers: Record = {}; - for (const [qi, question] of questions.entries()) { + for (let qi = 0, len = questions.length; qi < len; qi++) { + const question = questions[qi]; const answer = byQuestionId.get(`q${qi}`); if (!answer) continue; const selected = new Set(answer.selectedOptionIds); const labels: string[] = []; - for (const [oi, option] of question.options.entries()) { + for (let oi = 0, optionCount = question.options.length; oi < optionCount; oi++) { + const option = question.options[oi]; if (selected.has(`o${oi}`)) labels.push(option.label); } const value = answer.customText?.trim() || labels.join(', '); @@ -1349,7 +1380,8 @@ export class ClaudeCodeAdapter extends BaseAgentAdapter { // (`init` fires only at Query creation, so it can't catch a live `setModel`). this.syncModel(message.model); let calledTool = false; - for (const block of message.content) { + for (let i = 0, len = message.content.length; i < len; i++) { + const block = message.content[i]; if (block.type === 'tool_use') { const content = toolInputContent(block.name, block.input); // Announce the tool the moment Claude requests it; the matching tool_result settles it. @@ -1377,7 +1409,8 @@ export class ClaudeCodeAdapter extends BaseAgentAdapter { * cursors or calls `freshSegment()`, so a mid-turn subagent can't break the main streaming bubble. */ private handleSubagentAssistant(message: AssistantMessage, parent: string): void { - for (const block of message.content) { + for (let i = 0, len = message.content.length; i < len; i++) { + const block = message.content[i]; // eslint-disable-next-line sukka/unicorn/prefer-switch -- deliberately non-exhaustive (other block variants are ignored); the switch autofix then trips the error-level default-case rule if (block.type === 'tool_use') { const content = toolInputContent(block.name, block.input); @@ -1410,14 +1443,16 @@ export class ClaudeCodeAdapter extends BaseAgentAdapter { const results = content.filter((block) => block.type === 'tool_result'); const envelope = results.length === 1 ? toolUseResultEnvelope(msg.tool_use_result) : undefined; const patched = results.length === 1 ? editResultDiffContent(msg.tool_use_result) : undefined; - for (const block of content) { + for (let i = 0, len = content.length; i < len; i++) { + const block = content[i]; if (block.type !== 'tool_result') continue; // Replace (not append) so the patch-bearing diff supersedes the announce-time fragment // instead of stacking a second card, and do it before the settle below: a completed tool is // terminal, so any content emitted after it is silently dropped. if (patched) this.emitTool({ toolCallId: block.tool_use_id, content: patched }); - for (const result of toolResultContent(block.content)) { - this.appendToolContent(block.tool_use_id, result); + const resultContent = toolResultContent(block.content); + for (let j = 0, resultCount = resultContent.length; j < resultCount; j++) { + this.appendToolContent(block.tool_use_id, resultContent[j]); } this.emitTool({ toolCallId: block.tool_use_id, @@ -1681,7 +1716,9 @@ export function toolUseResultEnvelope(value: unknown): Record | if (!isRecord(value)) return undefined; const envelope: Record = {}; let fields = 0; - for (const [key, field] of Object.entries(value)) { + const valueEntries = Object.entries(value); + for (let i = 0, len = valueEntries.length; i < len; i++) { + const [key, field] = valueEntries[i]; const scalar = typeof field === 'string' ? field.length > 0 && field.length <= TOOL_USE_RESULT_SCALAR_MAX @@ -1857,7 +1894,9 @@ export function buildClaudeTranscriptSupplement( function harvestToolUses(toolUses: Map, row: Record): void { const parentToolCallId = stringField(row, 'parent_tool_use_id'); - for (const block of messageContentBlocks(row.message)) { + const blocks = messageContentBlocks(row.message); + for (let i = 0, len = blocks.length; i < len; i++) { + const block = blocks[i]; if (isToolUseBlock(block)) { toolUses.set(block.id, claudeToolCallFromUse(block, parentToolCallId)); } @@ -2062,7 +2101,8 @@ export function createClaudeHistoryEventMapper( lastModel = model; events.push({ historyId, ts, event: { type: 'model-update', model } }); } - for (const block of blocks) { + for (let i = 0, len = blocks.length; i < len; i++) { + const block = blocks[i]; if (!isThinkingBlock(block)) continue; const thought = thoughtHistoryEvent( historyId, @@ -2075,7 +2115,8 @@ export function createClaudeHistoryEventMapper( } const text = textHistoryEvent(historyId, 'assistant', messageId, message.message, ts, parent); if (text) events.push(text); - for (const block of blocks) { + for (let i = 0, len = blocks.length; i < len; i++) { + const block = blocks[i]; if (!isToolUseBlock(block)) continue; events.push(toolEvent(claudeToolCallFromUse(block, parent))); } @@ -2083,7 +2124,8 @@ export function createClaudeHistoryEventMapper( } const results = blocks.filter((block) => isToolResultBlock(block)); - for (const block of results) { + for (let i = 0, len = results.length; i < len; i++) { + const block = results[i]; const existing = announced.get(block.tool_use_id) ?? toolUses?.get(block.tool_use_id); events.push( toolEvent({ diff --git a/packages/host/agent-adapter/src/native/codex/adapter.ts b/packages/host/agent-adapter/src/native/codex/adapter.ts index d8b0ef9c3..f7c82d4a8 100644 --- a/packages/host/agent-adapter/src/native/codex/adapter.ts +++ b/packages/host/agent-adapter/src/native/codex/adapter.ts @@ -93,15 +93,20 @@ function resolveCodexEnvironment(cwd?: string): Promise { const BRAND_COLOR_RE = /^#[0-9A-F]{6}$/i; +const collator = new Intl.Collator(); + /** Map the app-server's `skills/list` response onto the normalized command catalog: only enabled * skills are invokable, and duplicate names resolve to the first provider result, like the TUI's * name-based mention lookup. */ export function codexSkillCommands(response: unknown): CodexSkillCommand[] { if (!isRecord(response) || !Array.isArray(response.data)) return []; const commands = new Map(); - for (const entry of response.data) { + for (let i = 0, len = response.data.length; i < len; i++) { + const entry = response.data[i]; if (!isRecord(entry) || !Array.isArray(entry.skills)) continue; - for (const skill of entry.skills) { + const skills = entry.skills; + for (let j = 0, skillCount = skills.length; j < skillCount; j++) { + const skill = skills[j]; if (!isRecord(skill) || skill.enabled !== true) continue; const name = stringField(skill, 'name'); const path = stringField(skill, 'path'); @@ -123,7 +128,7 @@ export function codexSkillCommands(response: unknown): CodexSkillCommand[] { }); } } - return [...commands.values()].sort((a, b) => a.name.localeCompare(b.name)); + return [...commands.values()].sort((a, b) => collator.compare(a.name, b.name)); } /** Composer icons render at chip size; anything bigger than this is not an icon. */ @@ -235,7 +240,8 @@ interface CodexModelCatalog { function codexModelCatalog(response: unknown): CodexModelCatalog { const catalog: CodexModelCatalog = { defaultModel: undefined, models: [] }; if (!isRecord(response) || !Array.isArray(response.data)) return catalog; - for (const candidate of response.data) { + for (let i = 0, len = response.data.length; i < len; i++) { + const candidate = response.data[i]; if (!isRecord(candidate)) continue; const model = stringField(candidate, 'model') ?? stringField(candidate, 'id'); if (!model) continue; @@ -243,7 +249,8 @@ function codexModelCatalog(response: unknown): CodexModelCatalog { let effortLevels: EffortLevel[] | undefined; if (Array.isArray(advertised)) { const supported = new Set(); - for (const option of advertised) { + for (let j = 0, optionCount = advertised.length; j < optionCount; j++) { + const option = advertised[j]; if (!isRecord(option)) continue; const effort = EffortLevelSchema.safeParse(stringField(option, 'reasoningEffort')); if (effort.success && effort.data !== 'ultracode') supported.add(effort.data); @@ -354,7 +361,8 @@ export function codexMcpConfigOverrides( const out: Record = {}; if (!servers?.length) return out; let hasHttp = false; - for (const server of servers) { + for (let i = 0, len = servers.length; i < len; i++) { + const server = servers[i]; const prefix = `mcp_servers.${server.name}`; if (server.type === 'http') { if (server.headers && !isObjectEmpty(server.headers)) { @@ -642,7 +650,8 @@ export class CodexAdapter extends BaseAgentAdapter { // live-verified against codex app-server 0.144.1; nothing documents it (codex has no .d.ts) — // verify again if the app-server pin moves. const input: CodexTurnInput[] = []; - for (const block of content) { + for (let i = 0, len = content.length; i < len; i++) { + const block = content[i]; if (block.type === 'text') { const previous = input.at(-1); if (previous?.type === 'text') previous.text += `\n${block.text}`; @@ -1049,7 +1058,10 @@ export class CodexAdapter extends BaseAgentAdapter { // The icon reads awaited — re-check that a newer refresh or server didn't win meanwhile. if (this.server !== server || generation !== this.skillsRefreshGeneration) return; this.skillCommands.clear(); - for (const skill of skills) this.skillCommands.set(skill.name, skill); + for (let i = 0, len = skills.length; i < len; i++) { + const skill = skills[i]; + this.skillCommands.set(skill.name, skill); + } this.emitCommands([COMPACT_COMMAND, ...capSkillIconPayload(catalog)]); } catch { if (this.server === server && generation === this.skillsRefreshGeneration) { @@ -1360,7 +1372,10 @@ export class CodexAdapter extends BaseAgentAdapter { this.emitTool(toolCall); break; } - for (const content of toolCall.content) this.appendToolContent(id, content); + for (let i = 0, len = toolCall.content.length; i < len; i++) { + const content = toolCall.content[i]; + this.appendToolContent(id, content); + } this.emitTool({ ...toolCall, content: undefined }); break; } @@ -1368,7 +1383,8 @@ export class CodexAdapter extends BaseAgentAdapter { const changes = Array.isArray(item.changes) ? item.changes.filter(isRecord) : []; const locations: Array<{ path: string }> = []; const content: ToolCallContent[] = []; - for (const change of changes) { + for (let i = 0, len = changes.length; i < len; i++) { + const change = changes[i]; const path = stringField(change, 'path'); if (!path) continue; // An update kind can carry a rename: `kind: {type:'update', move_path}` with `path` diff --git a/packages/host/agent-adapter/src/native/codex/history-tools.ts b/packages/host/agent-adapter/src/native/codex/history-tools.ts index d3f6ec155..cc433f4e7 100644 --- a/packages/host/agent-adapter/src/native/codex/history-tools.ts +++ b/packages/host/agent-adapter/src/native/codex/history-tools.ts @@ -377,7 +377,8 @@ export function applyPatchToolView(input: string): ApplyPatchView | null { const lines = input.split('\n'); // An envelope ending in '\n' splits into a trailing '' that is not a content line. if (lines.at(-1) === '') lines.pop(); - for (const line of lines) { + for (let i = 0, len = lines.length; i < len; i++) { + const line = lines[i]; if (line.startsWith('*** Update File: ')) { flush(); updatePath = line.slice('*** Update File: '.length); diff --git a/packages/host/agent-adapter/src/native/codex/history.ts b/packages/host/agent-adapter/src/native/codex/history.ts index 0f5b51f03..5e194fc9d 100644 --- a/packages/host/agent-adapter/src/native/codex/history.ts +++ b/packages/host/agent-adapter/src/native/codex/history.ts @@ -62,7 +62,7 @@ function isBase64(data: string): boolean { if (!isDigit && !isUppercase && !isLowercase && code !== 43 && code !== 47) return false; } for (let index = payloadLength; index < data.length; index += 1) { - if (data.codePointAt(index) !== 61) return false; + if (data.charCodeAt(index) !== 61) return false; } return true; } @@ -176,7 +176,8 @@ function isSyntheticCodexUserDigest( * of the rollout. */ export function collectCodexPromptFingerprints(rows: JsonRecord[]): Set { const prints = new Set(); - for (const row of rows) { + for (let i = 0, len = rows.length; i < len; i++) { + const row = rows[i]; if (stringField(row, 'type') !== 'event_msg') continue; const payload = recordField(row, 'payload'); if (!payload || stringField(payload, 'type') !== 'user_message') continue; @@ -279,7 +280,8 @@ export function codexHome(environment: NodeJS.ProcessEnv = env): string { export async function readCodexIndex(home = codexHome()): Promise> { const rows = await readJsonlFile(join(home, 'session_index.jsonl')); const index = new Map(); - for (const row of rows) { + for (let i = 0, len = rows.length; i < len; i++) { + const row = rows[i]; const id = stringField(row, 'id'); if (!id) continue; index.set(id, { @@ -354,12 +356,17 @@ async function collectJsonlFiles(root: string, depth = 8): Promise { } const files: string[] = []; const pendingDirs: Array> = []; - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; const path = join(root, entry.name); if (entry.isDirectory()) pendingDirs.push(collectJsonlFiles(path, depth - 1)); else if (entry.isFile() && entry.name.endsWith('.jsonl')) files.push(path); } - for (const nestedFiles of await Promise.all(pendingDirs)) appendArrayInPlace(files, nestedFiles); + const nested = await Promise.all(pendingDirs); + for (let i = 0, len = nested.length; i < len; i++) { + const nestedFiles = nested[i]; + appendArrayInPlace(files, nestedFiles); + } return files; } @@ -492,7 +499,8 @@ async function readCodexTranscriptSummary( const fileStat = await statOrUndefined(path); let firstUserText: string | undefined; - for (const userRow of userRows) { + for (let i = 0, len = userRows.length; i < len; i++) { + const userRow = userRows[i]; if (isSyntheticCodexUserDigest(userRow.digest, promptFingerprints) || userRow.empty) continue; messageCount += 1; if (userRow.preview !== undefined) firstUserText ??= userRow.preview; @@ -579,7 +587,8 @@ function collectRespondedToolCallIds(rows: JsonRecord[]): { } { const callIds = new Set(); const outputCallIds = new Set(); - for (const row of rows) { + for (let i = 0, len = rows.length; i < len; i++) { + const row = rows[i]; if (stringField(row, 'type') !== 'response_item') continue; const payload = recordField(row, 'payload'); if (!payload) continue; @@ -603,7 +612,8 @@ interface McpEndState { /** Precomputed so a response output that precedes its MCP end row still gets the structured verdict. */ function collectMcpEndStates(rows: JsonRecord[]): Map { const states = new Map(); - for (const row of rows) { + for (let i = 0, len = rows.length; i < len; i++) { + const row = rows[i]; if (stringField(row, 'type') !== 'event_msg') continue; const payload = recordField(row, 'payload'); if (!payload || stringField(payload, 'type') !== 'mcp_tool_call_end') continue; @@ -748,7 +758,8 @@ function collectCodexMcpIdentities( rows: JsonRecord[], ): Map { const identities = new Map(); - for (const row of rows) { + for (let i = 0, len = rows.length; i < len; i++) { + const row = rows[i]; if (stringField(row, 'type') !== 'event_msg') continue; const payload = recordField(row, 'payload'); if (!payload) continue; diff --git a/packages/host/agent-adapter/src/native/codex/unified-diff.ts b/packages/host/agent-adapter/src/native/codex/unified-diff.ts index 147532a2c..306dc87e5 100644 --- a/packages/host/agent-adapter/src/native/codex/unified-diff.ts +++ b/packages/host/agent-adapter/src/native/codex/unified-diff.ts @@ -27,7 +27,8 @@ export function diffContentFromUnified( const newLines: string[] = []; let inHunk = false; - for (const line of lines) { + for (let i = 0, len = lines.length; i < len; i++) { + const line = lines[i]; if (HUNK_HEADER_RE.test(line)) { inHunk = true; continue; diff --git a/packages/host/agent-adapter/src/native/grok-build/adapter.ts b/packages/host/agent-adapter/src/native/grok-build/adapter.ts index 626e9a698..684c8b488 100644 --- a/packages/host/agent-adapter/src/native/grok-build/adapter.ts +++ b/packages/host/agent-adapter/src/native/grok-build/adapter.ts @@ -28,7 +28,7 @@ const POLICIES = [ name: 'Bypass permissions', description: 'All tools run without approval prompts; this adapter cannot change it.', }, -] as const satisfies ReadonlyArray; +] as const satisfies readonly ApprovalPolicy[]; /** * Grok Build adapter — drives the local `grok` CLI in **headless** mode (`grok -p`), not ACP. diff --git a/packages/host/agent-adapter/src/native/opencode/adapter.ts b/packages/host/agent-adapter/src/native/opencode/adapter.ts index c654b4ce4..ba443a865 100644 --- a/packages/host/agent-adapter/src/native/opencode/adapter.ts +++ b/packages/host/agent-adapter/src/native/opencode/adapter.ts @@ -30,6 +30,7 @@ import { extractErrorMessage } from 'foxts/extract-error-message'; import { invariant, nullthrow } from 'foxts/guard'; import { isObjectEmpty } from 'foxts/is-object-empty'; import { falseFn } from 'foxts/noop'; +import { split0th } from 'foxts/split-nth'; import { wait } from 'foxts/wait'; import type { AgentHistoryReadContext, AgentStartCatalogOptions } from '../../adapter'; import { AUTH_FAILED_ERROR_CODE, nextToolCallId } from '../../adapter'; @@ -82,7 +83,8 @@ export function opencodeMcpConfig( ): Record | undefined { if (!servers?.length) return undefined; const out: Record = {}; - for (const server of servers) { + for (let i = 0, len = servers.length; i < len; i++) { + const server = servers[i]; out[server.name] = server.type === 'http' ? { @@ -180,13 +182,16 @@ function opencodeModelOptions( ): AgentModelOption[] { const connected = new Set(listed.connected); const models: AgentModelOption[] = []; - for (const provider of listed.all) { + for (let i = 0, len = listed.all.length; i < len; i++) { + const provider = listed.all[i]; if (credentialProviderId) { if (provider.id !== credentialProviderId) continue; } else if (!connected.has(provider.id) && provider.source !== 'api') { continue; } - for (const [modelId, model] of Object.entries(provider.models)) { + const modelEntries = Object.entries(provider.models); + for (let j = 0, modelCount = modelEntries.length; j < modelCount; j++) { + const [modelId, model] = modelEntries[j]; models.push({ id: `${provider.id}/${modelId}`, label: model.name || modelId, @@ -314,7 +319,7 @@ export class OpenCodeAdapter extends BaseAgentAdapter { } // The model ref decides routing (prompts carry `{providerID, modelID}`), so it wins; the // resolved known provider covers the common case of a model id typed without one. - const providerID = opts.model?.includes('/') ? opts.model.split('/', 1)[0] : cred.knownProvider; + const providerID = opts.model?.includes('/') ? split0th(opts.model, '/') : cred.knownProvider; const options: { apiKey?: string; baseURL?: string } = {}; const key = cred.apiKey ?? cred.authToken; if (key) options.apiKey = key; @@ -613,7 +618,7 @@ export class OpenCodeAdapter extends BaseAgentAdapter { const raced = await Promise.race([ abort, new Promise((resolve) => { - timer = setTimeout(() => resolve(ABORT_TIMED_OUT), ABORT_WAIT_MS); + timer = setTimeout(resolve, ABORT_WAIT_MS, ABORT_TIMED_OUT); }), ]); if (raced === ABORT_TIMED_OUT) { @@ -721,7 +726,11 @@ export class OpenCodeAdapter extends BaseAgentAdapter { if (!this.client) return; try { const config = await this.client.config.get({ directory: this.directory }); - for (const name of Object.keys(config.data?.mcp ?? {})) names.add(name); + const configuredNames = Object.keys(config.data?.mcp ?? {}); + for (let i = 0, len = configuredNames.length; i < len; i++) { + const name = configuredNames[i]; + names.add(name); + } this.mcpServerNames = [...names]; } catch { // fetch rejects on a dead server — retitling is never worth failing the session for. @@ -751,7 +760,11 @@ export class OpenCodeAdapter extends BaseAgentAdapter { const names = new Set(opts.mcpServerNames); try { const config = await client.config.get({ directory: got.data.directory }); - for (const name of Object.keys(config.data?.mcp ?? {})) names.add(name); + const configuredNames = Object.keys(config.data?.mcp ?? {}); + for (let i = 0, len = configuredNames.length; i < len; i++) { + const name = configuredNames[i]; + names.add(name); + } } catch { // fetch rejects on a dead server — the read proceeds with the caller's hint set. } @@ -1222,7 +1235,8 @@ export class OpenCodeAdapter extends BaseAgentAdapter { if (!answer) return []; const selected = new Set(answer.selectedOptionIds); const labels: string[] = []; - for (const [oi, option] of q.options.entries()) { + for (let oi = 0, len = q.options.length; oi < len; oi++) { + const option = q.options[oi]; if (selected.has(`o${oi}`)) labels.push(option.label); } const custom = answer.customText?.trim(); @@ -1255,7 +1269,10 @@ export class OpenCodeAdapter extends BaseAgentAdapter { // cumulative part updates do not retransmit an ever-growing content array. const toolCall = toolCallFromPart(part, this.mcpServerNames); if (toolCall.status === 'completed' || toolCall.status === 'failed') { - for (const content of toolCall.content) this.appendToolContent(part.id, content); + for (let i = 0, len = toolCall.content.length; i < len; i++) { + const content = toolCall.content[i]; + this.appendToolContent(part.id, content); + } this.emitTool({ ...toolCall, content: undefined }); } else { this.emitTool(toolCall); diff --git a/packages/host/agent-adapter/src/native/opencode/history.ts b/packages/host/agent-adapter/src/native/opencode/history.ts index 9bde57c5d..64b6f147e 100644 --- a/packages/host/agent-adapter/src/native/opencode/history.ts +++ b/packages/host/agent-adapter/src/native/opencode/history.ts @@ -65,8 +65,9 @@ export function opencodeMcpToolName( ): { server: string; tool: string } | undefined { let match: { server: string; tool: string } | undefined; let matchedLength = 0; - for (const server of mcpServers) { - const prefix = `${server.replace(OPENCODE_TOOL_NAME_SANITIZE_RE, '_')}_`; + for (let i = 0, len = mcpServers.length; i < len; i++) { + const server = mcpServers[i]; + const prefix = `${server.replaceAll(OPENCODE_TOOL_NAME_SANITIZE_RE, '_')}_`; if (prefix.length <= matchedLength || tool.length <= prefix.length) continue; if (tool.startsWith(prefix)) { match = { server, tool: tool.slice(prefix.length) }; @@ -146,7 +147,8 @@ export function mapOpencodeHistoryEvents( mcpServers: readonly string[] = [], ): AgentHistoryEvent[] { const events: AgentHistoryEvent[] = []; - for (const { info, parts } of messages) { + for (let i = 0, len = messages.length; i < len; i++) { + const { info, parts } = messages[i]; const ts = info.time.created; if (info.role === 'user') { const text = parts @@ -169,7 +171,8 @@ export function mapOpencodeHistoryEvents( } continue; } - for (const part of parts) { + for (let j = 0, partCount = parts.length; j < partCount; j++) { + const part = parts[j]; switch (part.type) { case 'text': { const event = textHistoryEvent(historyId, 'assistant', part.id, part.text, ts); diff --git a/packages/host/agent-adapter/src/native/pi/adapter.ts b/packages/host/agent-adapter/src/native/pi/adapter.ts index 8170a2731..9438efe50 100644 --- a/packages/host/agent-adapter/src/native/pi/adapter.ts +++ b/packages/host/agent-adapter/src/native/pi/adapter.ts @@ -166,7 +166,9 @@ function resolveModelRef( if (ref) return ref; const endpointProviders = new Set(); if (cred.baseUrl) { - for (const entry of modelRegistry.getAll()) { + const registryEntries = modelRegistry.getAll(); + for (let i = 0, len = registryEntries.length; i < len; i++) { + const entry = registryEntries[i]; if (entry.id === model && entry.baseUrl === cred.baseUrl) { endpointProviders.add(entry.provider); } @@ -297,18 +299,18 @@ export class PiAdapter extends BaseAgentAdapter { const file = await findPiSessionFile(opts.historyId); if (!file) throw new Error(`pi: history '${opts.historyId}' was not found`); const sourceManager = pi.SessionManager.open(file); - if (predecessor !== null) { - if (!sourceManager.getEntry(predecessor)) { - throw new Error(`pi: history branch predecessor '${predecessor}' was not found`); - } - sourceManager.createBranchedSession(predecessor); - this.pendingBranchManager = sourceManager; - } else { + if (predecessor === null) { this.pendingBranchManager = pi.SessionManager.create( sourceManager.getCwd(), sourceManager.getSessionDir(), { parentSession: file }, ); + } else { + if (!sourceManager.getEntry(predecessor)) { + throw new Error(`pi: history branch predecessor '${predecessor}' was not found`); + } + sourceManager.createBranchedSession(predecessor); + this.pendingBranchManager = sourceManager; } await this.start(startOpts); } diff --git a/packages/host/agent-adapter/src/native/pi/history.ts b/packages/host/agent-adapter/src/native/pi/history.ts index 9ca76bfcf..245acdaa8 100644 --- a/packages/host/agent-adapter/src/native/pi/history.ts +++ b/packages/host/agent-adapter/src/native/pi/history.ts @@ -138,7 +138,8 @@ export function mapPiHistoryEvents( event: { type: 'tool-call', toolCall: value }, }); }; - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; const ts = timestampMs(entry.timestamp); if (entry.type === 'compaction') { events.push({ @@ -166,7 +167,13 @@ export function mapPiHistoryEvents( const responseId = typeof message.responseId === 'string' ? message.responseId : undefined; const messageTimestamp = typeof message.timestamp === 'number' ? message.timestamp : undefined; - for (const [contentIndex, block] of message.content.entries()) { + const blocks = message.content; + for ( + let contentIndex = 0, blockCount = blocks.length; + contentIndex < blockCount; + contentIndex++ + ) { + const block = blocks[contentIndex]; if (!isRecord(block)) continue; if (block.type === 'text') { const id = piMessageBlockId( @@ -251,7 +258,8 @@ export function lastPiModelChange(entries: SessionEntry[]) { return null; } function firstUser(entries: SessionEntry[]): string | undefined { - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; if (entry.type === 'message' && isRecord(entry.message) && entry.message.role === 'user') { const content = entry.message.content; const text = diff --git a/packages/host/agent-adapter/src/native/pi/ui-bridge.ts b/packages/host/agent-adapter/src/native/pi/ui-bridge.ts index 220359f09..9abe1beb1 100644 --- a/packages/host/agent-adapter/src/native/pi/ui-bridge.ts +++ b/packages/host/agent-adapter/src/native/pi/ui-bridge.ts @@ -96,24 +96,20 @@ function text( placeholder?: string, opts?: ExtensionUIDialogOptions, ) { - return guarded( - opts, - undefined, - async (signal) => - ( - await ask( - host, - title, - { - questionId: 'input', - prompt: title, - multiSelect: false, - options: [{ optionId: 'skip', label: 'Skip', description: placeholder }], - }, - signal, - ) - )?.customText?.trim() || undefined, - ); + return guarded(opts, undefined, async (signal) => { + const answer = await ask( + host, + title, + { + questionId: 'input', + prompt: title, + multiSelect: false, + options: [{ optionId: 'skip', label: 'Skip', description: placeholder }], + }, + signal, + ); + return answer?.customText?.trim() || undefined; + }); } function guarded( opts: ExtensionUIDialogOptions | undefined, diff --git a/packages/host/agent-adapter/src/plugins/claude-code.ts b/packages/host/agent-adapter/src/plugins/claude-code.ts index 358925664..25220c95c 100644 --- a/packages/host/agent-adapter/src/plugins/claude-code.ts +++ b/packages/host/agent-adapter/src/plugins/claude-code.ts @@ -20,6 +20,7 @@ import type { const execFileAsync = promisify(execFile); const GIT_SOURCE_RE = /^(?:https?:\/\/|git@)/; +const collator = new Intl.Collator(); const settingsWrites = new Map>(); const ClaudeMarketplaceSchema = z.object({ @@ -169,7 +170,7 @@ export class ClaudeCodePluginAdapter implements PluginProviderAdapter { * never surfaces (verified on CLI 2.1.220) — a plain filesystem read is the only source. * Enablement comes from the merged `skillOverrides` map, keyed by skill name. */ async listStandaloneSkills(opts: PluginDiscoveryOptions = {}): Promise { - const roots: { dir: string; scope: StandaloneSkill['scope'] }[] = [ + const roots: Array<{ dir: string; scope: StandaloneSkill['scope'] }> = [ { dir: this.userSkillsDir, scope: 'user' }, ]; if (opts.cwd) roots.push({ dir: join(opts.cwd, '.claude', 'skills'), scope: 'project' }); @@ -227,9 +228,12 @@ export class ClaudeCodePluginAdapter implements PluginProviderAdapter { } const documents = await Promise.all(files.map((file) => readJsonRecord(file))); const merged: Record = {}; - for (const document of documents) { + for (let i = 0, len = documents.length; i < len; i++) { + const document = documents[i]; if (!isRecord(document.skillOverrides)) continue; - for (const [name, tier] of Object.entries(document.skillOverrides)) { + const overrideEntries = Object.entries(document.skillOverrides); + for (let j = 0, entryCount = overrideEntries.length; j < entryCount; j++) { + const [name, tier] = overrideEntries[j]; if (typeof tier === 'string') merged[name] = tier; } } @@ -301,14 +305,15 @@ async function readClaudeSkillsDirectory( return []; } const reads: Array> = []; - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; if (!entry.isDirectory() && !entry.isSymbolicLink()) continue; reads.push(readClaudeSkill(dir, entry.name, scope)); } const skills = await Promise.all(reads); return skills .filter((skill) => skill !== undefined) - .sort((left, right) => left.id.localeCompare(right.id)); + .sort((left, right) => collator.compare(left.id, right.id)); } async function readClaudeSkill( @@ -345,7 +350,9 @@ function parseSkillFrontmatter(content: string): { name?: string; description?: const match = RE_SKILL_FRONTMATTER.exec(content); if (!match) return {}; const fields: { name?: string; description?: string } = {}; - for (const line of match[1].split(RE_LINE_BREAK)) { + const lines = match[1].split(RE_LINE_BREAK); + for (let i = 0, len = lines.length; i < len; i++) { + const line = lines[i]; const separator = line.indexOf(':'); if (separator <= 0) continue; const key = line.slice(0, separator).trim(); @@ -393,14 +400,16 @@ async function normalizeClaudePlugins( marketplaces.map((marketplace) => [marketplace.name, marketplace]), ); const records = new Map(); - for (const available of catalog.available) { + for (let i = 0, len = catalog.available.length; i < len; i++) { + const available = catalog.available[i]; records.set(available.pluginId, { id: available.pluginId, available, installations: [], }); } - for (const installed of catalog.installed) { + for (let i = 0, len = catalog.installed.length; i < len; i++) { + const installed = catalog.installed[i]; const record = records.get(installed.id) ?? { id: installed.id, installations: [] }; record.installations.push(installed); records.set(installed.id, record); @@ -408,7 +417,7 @@ async function normalizeClaudePlugins( return Promise.all( [...records.values()] - .sort((left, right) => left.id.localeCompare(right.id)) + .sort((left, right) => collator.compare(left.id, right.id)) .map((record) => normalizeClaudePlugin(record, marketplaceByName)), ); } @@ -517,8 +526,8 @@ async function readClaudePackage(packagePath: string): Promise { - const kind = left.kind.localeCompare(right.kind); - return kind === 0 ? left.name.localeCompare(right.name) : kind; + const kind = collator.compare(left.kind, right.kind); + return kind === 0 ? collator.compare(left.name, right.name) : kind; }); return { manifest, components }; } diff --git a/packages/host/agent-adapter/src/plugins/codex.ts b/packages/host/agent-adapter/src/plugins/codex.ts index 17312be2c..c0f423321 100644 --- a/packages/host/agent-adapter/src/plugins/codex.ts +++ b/packages/host/agent-adapter/src/plugins/codex.ts @@ -25,6 +25,7 @@ const OptionalStringSchema = z.string().min(1).nullish(); const OptionalUrlSchema = z.url().nullish().catch(null); const OptionalHttpUrlSchema = z.httpUrl().nullish().catch(null); const DISCOVERY_TIMEOUT_MS = 30000; +const collator = new Intl.Collator(); const CodexPluginSourceSchema = z.discriminatedUnion('type', [ z.object({ type: z.literal('local'), path: z.string().min(1) }), @@ -175,7 +176,7 @@ export class CodexPluginAdapter implements PluginProviderAdapter { // 0.144.1: list 3.3s, one read ~160ms). Market entries keep the summary's own metadata and // simply carry no component list. const plugins = await Promise.all( - [...entries.values()].map(async ({ marketplace, summary }) => + Array.from(entries.values(), async ({ marketplace, summary }) => normalizeCodexPlugin( marketplace, summary, @@ -185,7 +186,7 @@ export class CodexPluginAdapter implements PluginProviderAdapter { ), ), ); - return plugins.sort((left, right) => left.id.localeCompare(right.id)); + return plugins.sort((left, right) => collator.compare(left.id, right.id)); }, opts.signal); } @@ -203,8 +204,12 @@ export class CodexPluginAdapter implements PluginProviderAdapter { ), ); const names = new Set(); - for (const detail of details) { - for (const name of detail.mcpServers) names.add(name); + for (let i = 0, len = details.length; i < len; i++) { + const detail = details[i]; + const mcpServers = detail.mcpServers; + for (let j = 0, serverCount = mcpServers.length; j < serverCount; j++) { + names.add(mcpServers[j]); + } } return [...names]; }, opts.signal); @@ -362,7 +367,9 @@ async function findCodexPlugin( ): Promise<{ marketplace: CodexMarketplace; summary: CodexPluginSummary }> { // `plugin/installed` answers the same envelope as `plugin/list`, minus the remote catalog. const value = await server.request(method, { cwds: opts.cwd ? [opts.cwd] : undefined }); - for (const marketplace of CodexPluginListSchema.parse(value).marketplaces) { + const marketplaces = CodexPluginListSchema.parse(value).marketplaces; + for (let i = 0, len = marketplaces.length; i < len; i++) { + const marketplace = marketplaces[i]; const summary = marketplace.plugins.find((plugin) => plugin.id === id); if (summary) return { marketplace, summary }; } @@ -397,8 +404,11 @@ async function readCodexPluginDetailStrict( function codexCatalogEntries(catalog: z.infer) { // The remote curated catalog can list one id twice; retain the installed copy, else the first. const entries = new Map(); - for (const marketplace of catalog.marketplaces) { - for (const summary of marketplace.plugins) { + for (let i = 0, len = catalog.marketplaces.length; i < len; i++) { + const marketplace = catalog.marketplaces[i]; + const summaries = marketplace.plugins; + for (let j = 0, summaryCount = summaries.length; j < summaryCount; j++) { + const summary = summaries[j]; const seen = entries.get(summary.id); if (seen && !summary.installed) continue; entries.set(summary.id, { marketplace, summary }); @@ -410,9 +420,11 @@ function codexCatalogEntries(catalog: z.infer) { function normalizeCodexStandaloneSkills(value: unknown): StandaloneSkill[] { const parsed = CodexSkillListSchema.parse(value); const skills = new Map(); - for (const group of parsed.data) { - for (const raw of group.skills) { - const entry = CodexSkillEntrySchema.safeParse(raw); + for (let i = 0, len = parsed.data.length; i < len; i++) { + const group = parsed.data[i]; + const rawSkills = group.skills; + for (let j = 0, skillCount = rawSkills.length; j < skillCount; j++) { + const entry = CodexSkillEntrySchema.safeParse(rawSkills[j]); if (!entry.success) continue; const { name, description, path, scope } = entry.data; // Plugin-qualified names (`plugin:skill`) belong to Plugin.components, not this list. @@ -429,7 +441,7 @@ function normalizeCodexStandaloneSkills(value: unknown): StandaloneSkill[] { }); } } - return [...skills.values()].sort((left, right) => left.id.localeCompare(right.id)); + return [...skills.values()].sort((left, right) => collator.compare(left.id, right.id)); } async function startCodexPluginServer(signal: AbortSignal): Promise { @@ -549,7 +561,7 @@ function codexComponents(detail: CodexPluginDetail): PluginComponent[] { ...detail.mcpServers.map((name) => ({ kind: 'mcp-server' as const, name })), ]; return components.sort((left, right) => { - const kind = left.kind.localeCompare(right.kind); - return kind === 0 ? left.name.localeCompare(right.name) : kind; + const kind = collator.compare(left.kind, right.kind); + return kind === 0 ? collator.compare(left.name, right.name) : kind; }); } diff --git a/packages/host/agent-adapter/src/probe/base.ts b/packages/host/agent-adapter/src/probe/base.ts index bca37f915..37a75a7df 100644 --- a/packages/host/agent-adapter/src/probe/base.ts +++ b/packages/host/agent-adapter/src/probe/base.ts @@ -6,6 +6,7 @@ import process from 'node:process'; import { promisify } from 'node:util'; import { executableSearchLocations } from '@linkcode/common/node'; import type { AgentAuthStatus } from '@linkcode/schema'; +import { split0th } from 'foxts/split-nth'; const execFileAsync = promisify(execFile); @@ -43,7 +44,7 @@ export abstract class AgentCliProbe { * because the SDKs' `exports` maps reject bare CJS resolution outright. */ sdkPlatformPackagePresent(): boolean { - const scope = this.sdkPackage.split('/', 1)[0]; + const scope = split0th(this.sdkPackage, '/'); const paths = createRequire(import.meta.url).resolve.paths(this.sdkPackage) ?? []; return paths.some((dir) => existsSync(join(dir, scope, this.platformPackageBase()))); } @@ -54,9 +55,10 @@ export abstract class AgentCliProbe { * is nested elsewhere (codex vendors under `vendor/` and resolves its own path). */ sdkPlatformBinaryPath(): string | undefined { - const scope = this.sdkPackage.split('/', 1)[0]; + const scope = split0th(this.sdkPackage, '/'); const paths = createRequire(import.meta.url).resolve.paths(this.sdkPackage) ?? []; - for (const dir of paths) { + for (let i = 0, len = paths.length; i < len; i++) { + const dir = paths[i]; const candidate = join(dir, scope, this.platformPackageBase(), this.binaryName()); if (existsSync(candidate)) return candidate; } @@ -100,7 +102,9 @@ export abstract class AgentCliProbe { /** Probe the known install locations in order; the first verified install wins. */ async detect(): Promise { - for (const location of this.knownLocations()) { + const locations = this.knownLocations(); + for (let i = 0, len = locations.length; i < len; i++) { + const location = locations[i]; // eslint-disable-next-line no-await-in-loop -- locations are a precedence list; the first verified install wins const runtime = await this.probeAt(location); if (runtime) return runtime; diff --git a/packages/host/agent-adapter/src/util.ts b/packages/host/agent-adapter/src/util.ts index 724fbce77..9692b53a6 100644 --- a/packages/host/agent-adapter/src/util.ts +++ b/packages/host/agent-adapter/src/util.ts @@ -36,7 +36,8 @@ const PATH_INPUT_KEYS = ['file_path', 'path', 'notebook_path', 'filePath'] as co export function locationsFromToolInput(input: unknown): ToolCallLocation[] | undefined { if (input === null || typeof input !== 'object') return undefined; const record = input as Record; - for (const key of PATH_INPUT_KEYS) { + for (let i = 0, len = PATH_INPUT_KEYS.length; i < len; i++) { + const key = PATH_INPUT_KEYS[i]; const value = record[key]; if (typeof value === 'string' && value.length > 0) return [{ path: value }]; } diff --git a/packages/host/assets/package.json b/packages/host/assets/package.json index 6e7fffdab..6b0d390c6 100644 --- a/packages/host/assets/package.json +++ b/packages/host/assets/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "@linkcode/schema": "workspace:*", - "foxts": "^5.8.0", + "foxts": "^5.9.1", "mac-system-proxy": "^1.0.4", "make-fetch-happen": "^16.0.1", "p-map": "^7.0.6", diff --git a/packages/host/assets/src/__tests__/catalog.test.ts b/packages/host/assets/src/__tests__/catalog.test.ts index 1bce2da7d..ac8750bd1 100644 --- a/packages/host/assets/src/__tests__/catalog.test.ts +++ b/packages/host/assets/src/__tests__/catalog.test.ts @@ -49,8 +49,11 @@ describe('CATALOG', () => { }); it('declares a verifiable baked artifact for every baked platform entry', () => { - for (const descriptor of descriptors) { - for (const source of Object.values(descriptor.artifacts)) { + for (let i = 0, len = descriptors.length; i < len; i++) { + const descriptor = descriptors[i]; + const sources = Object.values(descriptor.artifacts); + for (let j = 0, sourceCount = sources.length; j < sourceCount; j++) { + const source = sources[j]; if (source.kind !== 'baked') continue; expect(source.url).toMatch(HTTPS); expect(source.size).toBeGreaterThan(0); @@ -60,8 +63,11 @@ describe('CATALOG', () => { }); it('gives windows entries .exe members and posix entries bare members', () => { - for (const descriptor of descriptors) { - for (const [key, source] of Object.entries(descriptor.artifacts)) { + for (let i = 0, len = descriptors.length; i < len; i++) { + const descriptor = descriptors[i]; + const artifactEntries = Object.entries(descriptor.artifacts); + for (let j = 0, entryCount = artifactEntries.length; j < entryCount; j++) { + const [key, source] = artifactEntries[j]; expect(source.member.endsWith('.exe')).toBe(key.startsWith('win32')); } } @@ -77,7 +83,9 @@ describe('CATALOG', () => { }); it('ships the codex Windows sandbox helpers next to the win32 binaries only', () => { - for (const [key, source] of Object.entries(binary(CODEX_ID).artifacts)) { + const codexArtifacts = Object.entries(binary(CODEX_ID).artifacts); + for (let i = 0, len = codexArtifacts.length; i < len; i++) { + const [key, source] = codexArtifacts[i]; if (source.kind !== 'npm') throw new Error('expected npm source'); if (!key.startsWith('win32')) { expect(source.extraMembers).toBeUndefined(); diff --git a/packages/host/assets/src/__tests__/system-proxy.test.ts b/packages/host/assets/src/__tests__/system-proxy.test.ts index 98c20a191..586e0187a 100644 --- a/packages/host/assets/src/__tests__/system-proxy.test.ts +++ b/packages/host/assets/src/__tests__/system-proxy.test.ts @@ -34,7 +34,10 @@ beforeEach(() => { fetchMock.mockReset(); win32Mock.mockReset(); darwinMock.mockReset(); - for (const key of PROXY_ENV_KEYS) delete process.env[key]; + for (let i = 0, len = PROXY_ENV_KEYS.length; i < len; i++) { + const key = PROXY_ENV_KEYS[i]; + delete process.env[key]; + } setPlatform('win32'); }); @@ -43,7 +46,8 @@ afterEach(() => { }); afterAll(() => { - for (const key of PROXY_ENV_KEYS) { + for (let i = 0, len = PROXY_ENV_KEYS.length; i < len; i++) { + const key = PROXY_ENV_KEYS[i]; const value = originalProxyEnv.get(key); if (value === undefined) delete process.env[key]; else process.env[key] = value; diff --git a/packages/host/assets/src/catalog.ts b/packages/host/assets/src/catalog.ts index cfc323a7f..a3c9fa39e 100644 --- a/packages/host/assets/src/catalog.ts +++ b/packages/host/assets/src/catalog.ts @@ -84,10 +84,13 @@ function exe(key: PlatformKey): string { } function forAllPlatforms(source: (key: PlatformKey) => ArtifactSource) { - return Object.fromEntries(PLATFORM_KEYS.map((key) => [key, source(key)])) as Record< - PlatformKey, - ArtifactSource - >; + return PLATFORM_KEYS.reduce>( + (acc, key) => { + acc[key] = source(key); + return acc; + }, + {} as Record, + ); } /** Rust target triples embedded in the codex tarball's `vendor/` tree, per platform. */ diff --git a/packages/host/assets/src/closure-gen.ts b/packages/host/assets/src/closure-gen.ts index 76aacaea5..faec5f260 100644 --- a/packages/host/assets/src/closure-gen.ts +++ b/packages/host/assets/src/closure-gen.ts @@ -24,6 +24,8 @@ export interface GenerateClosureOptions { entry: string; } +const collator = new Intl.Collator(); + interface LockfileSnapshot { dependencies?: Record; optionalDependencies?: Record; @@ -79,11 +81,17 @@ function collectNodes(lockfile: Lockfile, rootKey: string): Map(); - for (const source of [snapshot.dependencies, snapshot.optionalDependencies]) { - for (const [depName, depVersion] of Object.entries(source ?? {})) { - const childKey = `${depName}@${depVersion}`; - deps.set(depName, childKey); - queue.push(childKey); + const depSources = [snapshot.dependencies, snapshot.optionalDependencies]; + for (let i = 0, len = depSources.length; i < len; i++) { + const source = depSources[i]; + if (source != null) { + const depEntries = Object.entries(source); + for (let j = 0, entryCount = depEntries.length; j < entryCount; j++) { + const [depName, depVersion] = depEntries[j]; + const childKey = `${depName}@${depVersion}`; + deps.set(depName, childKey); + queue.push(childKey); + } } } nodes.set(key, { @@ -171,7 +179,7 @@ export function generateClosure(options: GenerateClosureOptions): NpmClosure { const closure = { version: parseSnapshotKey(rootKeys[0]).version, entry: options.entry, - packages: [...placements.values()].sort((a, b) => a.path.localeCompare(b.path)), + packages: [...placements.values()].sort((a, b) => collator.compare(a.path, b.path)), }; return { ...closure, diff --git a/packages/host/assets/src/closure.ts b/packages/host/assets/src/closure.ts index cf0e35652..32eaf6fa0 100644 --- a/packages/host/assets/src/closure.ts +++ b/packages/host/assets/src/closure.ts @@ -5,6 +5,8 @@ * out; it never resolves versions, never runs install scripts, never mutates an installed tree. */ +import { split1st } from 'foxts/split-nth'; + /** One package of the closure: exact bytes (lockfile SRI) at a fixed layout position. */ export interface ClosurePackage { name: string; @@ -57,7 +59,7 @@ export function npmTarballUrls( version: string, registries: readonly string[] = CLOSURE_REGISTRIES, ): string[] { - const basename = name[0] === '@' ? name.split('/', 2)[1] : name; + const basename = name[0] === '@' ? split1st(name, '/') : name; const tail = `${name}/-/${basename}-${version}.tgz`; return registries.map((registry) => `${registry.replace(TRAILING_SLASH_RE, '')}/${tail}`); } diff --git a/packages/host/assets/src/download.ts b/packages/host/assets/src/download.ts index 5d64da1a3..5812baafe 100644 --- a/packages/host/assets/src/download.ts +++ b/packages/host/assets/src/download.ts @@ -41,7 +41,8 @@ export async function downloadVerified( ): Promise { const failures: string[] = []; let integrityFailed = false; - for (const url of artifact.urls) { + for (let i = 0, len = artifact.urls.length; i < len; i++) { + const url = artifact.urls[i]; try { // eslint-disable-next-line no-await-in-loop -- urls are an ordered fallback list await downloadFrom(url, destFile, artifact, options); diff --git a/packages/host/assets/src/gc.ts b/packages/host/assets/src/gc.ts index d6ca3cf4e..86daad049 100644 --- a/packages/host/assets/src/gc.ts +++ b/packages/host/assets/src/gc.ts @@ -36,7 +36,8 @@ export function collectGarbage( } // Version dirs publish via atomic rename, so presence = a complete install. const wantedInstalled = entries.includes(version); - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; if (entry === version) continue; if (!wantedInstalled && !entry.startsWith('.tmp-')) continue; const target = join(dir, entry); diff --git a/packages/host/assets/src/install.ts b/packages/host/assets/src/install.ts index b991ac8ec..8b721445a 100644 --- a/packages/host/assets/src/install.ts +++ b/packages/host/assets/src/install.ts @@ -121,8 +121,16 @@ async function doInstall( artifact.member, join(stage, binaryName(descriptor)), ); - for (const member of artifact.extraMembers ?? []) { - await extractMember(archive, artifact.format, member, join(stage, posix.basename(member))); + if (artifact.extraMembers != null) { + for (let i = 0, len = artifact.extraMembers.length; i < len; i++) { + const member = artifact.extraMembers[i]; + await extractMember( + archive, + artifact.format, + member, + join(stage, posix.basename(member)), + ); + } } } publish( @@ -152,7 +160,9 @@ async function stageClosure( options: InstallOptions, ): Promise { const byTarball = new Map(); - for (const pkg of closurePackagesForHost(descriptor.closure, process.platform, process.arch)) { + const hostPackages = closurePackagesForHost(descriptor.closure, process.platform, process.arch); + for (let i = 0, len = hostPackages.length; i < len; i++) { + const pkg = hostPackages[i]; const key = `${pkg.name}@${pkg.version}`; const targets = byTarball.get(key); if (targets) targets.push(pkg); @@ -181,7 +191,8 @@ async function stageClosure( }, }, ); - for (const target of targets) { + for (let i = 0, len = targets.length; i < len; i++) { + const target = targets[i]; // eslint-disable-next-line no-await-in-loop -- same archive, sequential extract targets await extractPackageTree(archive, join(stage, target.path)); } @@ -204,7 +215,8 @@ function publish(stage: string, dest: string, expected: readonly string[]): void renameSync(stage, dest); } catch (error) { if (!existsSync(dest)) throw error; - for (const file of expected) { + for (let i = 0, len = expected.length; i < len; i++) { + const file = expected[i]; const target = join(dest, file); if (existsSync(target)) continue; try { diff --git a/packages/host/assets/src/manager.ts b/packages/host/assets/src/manager.ts index cc58dd5d0..41d9d789c 100644 --- a/packages/host/assets/src/manager.ts +++ b/packages/host/assets/src/manager.ts @@ -72,7 +72,7 @@ export class AssetManager { /** Drop superseded versions and tmp orphans. Best-effort; never throws. */ gcAtBoot(): GcReport { return collectGarbage( - [...this.descriptors.values()].map((descriptor) => { + Array.from(this.descriptors.values(), (descriptor) => { const wanted = this.wanted.get(managedAssetKey(descriptor.id)); return { id: descriptor.id, @@ -101,7 +101,7 @@ export class AssetManager { /** Live snapshot for the `asset.list` wire resource. */ statuses(): ManagedAssetStatus[] { - return [...this.descriptors.values()].map((descriptor) => { + return Array.from(this.descriptors.values(), (descriptor) => { const version = this.wanted.get(managedAssetKey(descriptor.id))?.version; const path = version ? installedPath(descriptor, version) : undefined; return { diff --git a/packages/host/assets/src/pi-closure.gen.ts b/packages/host/assets/src/pi-closure.gen.ts index 8d43fd66e..a4acaa301 100644 --- a/packages/host/assets/src/pi-closure.gen.ts +++ b/packages/host/assets/src/pi-closure.gen.ts @@ -227,6 +227,13 @@ const packages: NpmClosure['packages'] = [ 'sha512-vcfD6tOk402isLl3Cm/qbn2O10TvgroMp1+/fEGM24ZdvETFCdOYv5VZ7m59EI5fPsjfSJh+CpQ5bhBrhfOg7g==', path: 'node_modules/@earendil-works/pi-coding-agent', }, + { + name: 'minimatch', + version: '10.2.5', + integrity: + 'sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==', + path: 'node_modules/@earendil-works/pi-coding-agent/node_modules/minimatch', + }, { name: '@earendil-works/pi-tui', version: '0.80.6', @@ -241,13 +248,6 @@ const packages: NpmClosure['packages'] = [ 'sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==', path: 'node_modules/@google/genai', }, - { - name: 'ws', - version: '8.21.0', - integrity: - 'sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==', - path: 'node_modules/@google/genai/node_modules/ws', - }, { name: '@hono/node-server', version: '2.0.12', @@ -358,13 +358,6 @@ const packages: NpmClosure['packages'] = [ 'sha512-W8pX7zHxjJvMIpw8JMxeJEleapXX0Q9NPszdNzqkM3MIEoIGPObdodujj+WHteXEvGfaP/AMwlNyRfEzSY6dQQ==', path: 'node_modules/@mistralai/mistralai', }, - { - name: 'ws', - version: '8.21.0', - integrity: - 'sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==', - path: 'node_modules/@mistralai/mistralai/node_modules/ws', - }, { name: '@modelcontextprotocol/sdk', version: '1.30.0', @@ -395,9 +388,9 @@ const packages: NpmClosure['packages'] = [ }, { name: '@opentelemetry/semantic-conventions', - version: '1.41.1', + version: '1.43.0', integrity: - 'sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==', + 'sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==', path: 'node_modules/@opentelemetry/semantic-conventions', }, { @@ -619,9 +612,9 @@ const packages: NpmClosure['packages'] = [ }, { name: 'brace-expansion', - version: '5.0.8', + version: '5.0.9', integrity: - 'sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==', + 'sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==', path: 'node_modules/brace-expansion', }, { @@ -974,6 +967,13 @@ const packages: NpmClosure['packages'] = [ 'sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==', path: 'node_modules/graceful-fs', }, + { + name: 'has-flag', + version: '4.0.0', + integrity: + 'sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==', + path: 'node_modules/has-flag', + }, { name: 'has-symbols', version: '1.1.0', @@ -1193,9 +1193,9 @@ const packages: NpmClosure['packages'] = [ }, { name: 'minimatch', - version: '10.2.5', + version: '10.2.6', integrity: - 'sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==', + 'sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==', path: 'node_modules/minimatch', }, { @@ -1499,6 +1499,13 @@ const packages: NpmClosure['packages'] = [ 'sha512-sHrVyWWdq28RbhjuJdZsA1SnGRJV6NiXbk6AXBxDOsgAcA+lmpUZCYjOdLBxkXMwis6RRe7dlZt4VlIWFVzkmg==', path: 'node_modules/strnum', }, + { + name: 'supports-color', + version: '8.1.1', + integrity: + 'sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==', + path: 'node_modules/supports-color', + }, { name: 'toidentifier', version: '1.0.1', @@ -1622,7 +1629,7 @@ const packages: NpmClosure['packages'] = [ export const PI_CLOSURE: NpmClosure = { version: '0.80.6', - revision: 'd6ff0228b84fa10c', + revision: '6fdb7aeb2039774d', entry: 'node_modules/@earendil-works/pi-coding-agent/dist/index.js', packages, }; diff --git a/packages/host/assets/src/registry-client.ts b/packages/host/assets/src/registry-client.ts index 36c611591..fd6f42bf9 100644 --- a/packages/host/assets/src/registry-client.ts +++ b/packages/host/assets/src/registry-client.ts @@ -43,7 +43,8 @@ export async function fetchNpmDist( const registries = options.registries ?? DEFAULT_REGISTRIES; const retry = options.retry ?? DEFAULT_RETRY; const failures: string[] = []; - for (const registry of registries) { + for (let i = 0, len = registries.length; i < len; i++) { + const registry = registries[i]; // eslint-disable-next-line no-await-in-loop -- registries are an ordered fallback list const dist = await fetchDist(`${registry}/${pkg}/${version}`, retry, failures); if (dist) return dist; diff --git a/packages/host/assets/src/system-proxy/index.ts b/packages/host/assets/src/system-proxy/index.ts index 172103abb..38fd0bd8f 100644 --- a/packages/host/assets/src/system-proxy/index.ts +++ b/packages/host/assets/src/system-proxy/index.ts @@ -84,7 +84,9 @@ function mergeEnvNoProxy(osNoProxy: string[]): string[] { ([key, value]) => key.toLowerCase() === 'no_proxy' && !!value, )?.[1]; const envNoProxy: string[] = []; - for (const host of env?.split(',') ?? []) { + const envHosts = env?.split(',') ?? []; + for (let i = 0, len = envHosts.length; i < len; i++) { + const host = envHosts[i]; const trimmed = host.trim(); if (trimmed) envNoProxy.push(trimmed); } diff --git a/packages/host/assets/src/system-proxy/win32.ts b/packages/host/assets/src/system-proxy/win32.ts index dfba1d7f9..d790940bf 100644 --- a/packages/host/assets/src/system-proxy/win32.ts +++ b/packages/host/assets/src/system-proxy/win32.ts @@ -35,7 +35,9 @@ export function getWin32SystemProxy(): SystemProxyDetection | undefined { */ export function parseRegQueryOutput(output: string): Map { const values = new Map(); - for (const line of output.split(NEWLINE)) { + const lines = output.split(NEWLINE); + for (let i = 0, len = lines.length; i < len; i++) { + const line = lines[i]; const row = VALUE_ROW.exec(line); if (!row) continue; const [, name, type, data] = row; @@ -94,7 +96,9 @@ function parseProxyServer(config: string): string { function parseProxyOverride(override: string | number | undefined): string[] { if (typeof override !== 'string') return []; const noProxy: string[] = []; - for (const entry of override.split(';')) { + const overrideEntries = override.split(';'); + for (let i = 0, len = overrideEntries.length; i < len; i++) { + const entry = overrideEntries[i]; const host = entry.trim(); if (!host) continue; if (host === '') noProxy.push('localhost', '127.0.0.1', '::1'); diff --git a/packages/host/assets/tests/integration/manager.test.ts b/packages/host/assets/tests/integration/manager.test.ts index 4a24a221f..17da71cc6 100644 --- a/packages/host/assets/tests/integration/manager.test.ts +++ b/packages/host/assets/tests/integration/manager.test.ts @@ -71,7 +71,9 @@ function closureDescriptor(sdkPackage = 'fake-pi-sdk'): NpmClosureAssetDescripto /** A pinFrom anchor whose node_modules holds the given packages. */ function anchorWith(packages: Record): string { const root = mkdtempSync(join(tmpdir(), 'closure-pin-')); - for (const [name, version] of Object.entries(packages)) { + const packageEntries = Object.entries(packages); + for (let i = 0, len = packageEntries.length; i < len; i++) { + const [name, version] = packageEntries[i]; const dir = join(root, 'node_modules', name); mkdirSync(dir, { recursive: true }); writeFileSync(join(dir, 'package.json'), JSON.stringify({ name, version })); diff --git a/packages/host/assets/tests/support/fixtures.ts b/packages/host/assets/tests/support/fixtures.ts index 3155f300d..060d7f8ba 100644 --- a/packages/host/assets/tests/support/fixtures.ts +++ b/packages/host/assets/tests/support/fixtures.ts @@ -19,7 +19,9 @@ export function makeTgz( ): TgzFixture { const root = mkdtempSync(join(tmpdir(), 'tgz-fixture-')); const members = { [member]: content, ...extraMembers }; - for (const [path, data] of Object.entries(members)) { + const memberEntries = Object.entries(members); + for (let i = 0, len = memberEntries.length; i < len; i++) { + const [path, data] = memberEntries[i]; const file = join(root, path); mkdirSync(dirname(file), { recursive: true }); writeFileSync(file, data, { mode: 0o644 }); @@ -37,7 +39,9 @@ export function makeTgz( /** Build an npm-shaped tgz: every file under the standard `package/` root. */ export function makePackageTgz(files: Record): TgzFixture { const root = mkdtempSync(join(tmpdir(), 'pkg-fixture-')); - for (const [name, content] of Object.entries(files)) { + const fileEntries = Object.entries(files); + for (let i = 0, len = fileEntries.length; i < len; i++) { + const [name, content] = fileEntries[i]; const file = join(root, 'package', name); mkdirSync(dirname(file), { recursive: true }); writeFileSync(file, content, { mode: 0o644 }); diff --git a/packages/host/engine/package.json b/packages/host/engine/package.json index 3259cf9bd..8b0001a6b 100644 --- a/packages/host/engine/package.json +++ b/packages/host/engine/package.json @@ -21,7 +21,7 @@ "acorn": "^8.17.0", "croner": "^10.0.1", "effect": "4.0.0-beta.98", - "foxts": "^5.8.0", + "foxts": "^5.9.1", "restty": "^0.2.6", "zod": "catalog:" }, diff --git a/packages/host/engine/src/__tests__/engine-file-suggest.test.ts b/packages/host/engine/src/__tests__/engine-file-suggest.test.ts index 0c476ea6a..0892ccde9 100644 --- a/packages/host/engine/src/__tests__/engine-file-suggest.test.ts +++ b/packages/host/engine/src/__tests__/engine-file-suggest.test.ts @@ -18,7 +18,10 @@ import { createTestEngine } from './fixtures/test-engine'; const tempRoots: string[] = []; afterAll(() => { - for (const dir of tempRoots) rmSync(dir, { recursive: true, force: true }); + for (let i = 0, len = tempRoots.length; i < len; i++) { + const dir = tempRoots[i]; + rmSync(dir, { recursive: true, force: true }); + } }); function fakeAdapter(): AgentAdapter { diff --git a/packages/host/engine/src/__tests__/engine-model-probe.test.ts b/packages/host/engine/src/__tests__/engine-model-probe.test.ts index a0623cbfe..2442e46be 100644 --- a/packages/host/engine/src/__tests__/engine-model-probe.test.ts +++ b/packages/host/engine/src/__tests__/engine-model-probe.test.ts @@ -52,11 +52,15 @@ const localModelProbe: typeof probeServiceModels = (service, secret) => { const localized: EndpointService = { ...service, models: localize(service.models), - variants: Object.fromEntries( - Object.entries(service.variants).map(([protocol, variant]) => [ - protocol, - variant && { ...variant, models: localize(variant.models) }, - ]), + variants: Object.entries(service.variants).reduce( + (acc, [protocol, variant]) => { + acc[protocol as keyof EndpointService['variants']] = variant && { + ...variant, + models: localize(variant.models), + }; + return acc; + }, + {}, ), }; // An unguarded agent: the relay is on loopback, which the probe policy exists to refuse. diff --git a/packages/host/engine/src/__tests__/engine-resources.test.ts b/packages/host/engine/src/__tests__/engine-resources.test.ts index 76b9e108a..d1e449199 100644 --- a/packages/host/engine/src/__tests__/engine-resources.test.ts +++ b/packages/host/engine/src/__tests__/engine-resources.test.ts @@ -94,7 +94,9 @@ describe('engine session resources', () => { ], }); const echoes: AgentEvent[] = []; - for (const payload of h.sent.slice(mark)) { + const sentSinceMark = h.sent.slice(mark); + for (let i = 0, len = sentSinceMark.length; i < len; i++) { + const payload = sentSinceMark[i]; if (payload.kind === 'agent.event' && payload.event.type === 'user-message') { echoes.push(payload.event); } diff --git a/packages/host/engine/src/__tests__/engine-sessions.test.ts b/packages/host/engine/src/__tests__/engine-sessions.test.ts index 313e346cf..c656b45b7 100644 --- a/packages/host/engine/src/__tests__/engine-sessions.test.ts +++ b/packages/host/engine/src/__tests__/engine-sessions.test.ts @@ -519,7 +519,8 @@ describe('engine interactive requests', () => { }), ), ); - for (const [index, testCase] of invalid.entries()) { + for (let index = 0, len = invalid.length; index < len; index++) { + const testCase = invalid[index]; const replyTo = `invalid-${index}`; const failure = sent.find( (payload) => payload.kind === 'request.failed' && payload.replyTo === replyTo, diff --git a/packages/host/engine/src/__tests__/file-service.test.ts b/packages/host/engine/src/__tests__/file-service.test.ts index 7b53e75b8..386818a79 100644 --- a/packages/host/engine/src/__tests__/file-service.test.ts +++ b/packages/host/engine/src/__tests__/file-service.test.ts @@ -14,7 +14,10 @@ function makeTempDir(): string { } afterAll(() => { - for (const root of roots) rmSync(root, { recursive: true, force: true }); + for (let i = 0, len = roots.length; i < len; i++) { + const root = roots[i]; + rmSync(root, { recursive: true, force: true }); + } }); function runReadWorkspaceFile(cwd: string, path: string) { diff --git a/packages/host/engine/src/__tests__/model-probe.test.ts b/packages/host/engine/src/__tests__/model-probe.test.ts index f6a2ac5c3..f816beb31 100644 --- a/packages/host/engine/src/__tests__/model-probe.test.ts +++ b/packages/host/engine/src/__tests__/model-probe.test.ts @@ -148,13 +148,17 @@ describe('model probe network boundary', () => { }); it('re-permits only the ranges a fake-IP tunnel mints from', () => { - for (const address of ['198.18.16.15', '198.19.255.255', '203.0.113.9']) { + const permitted = ['198.18.16.15', '198.19.255.255', '203.0.113.9']; + for (let i = 0, len = permitted.length; i < len; i++) { + const address = permitted[i]; expect(PROBE_POLICY.allowedAddresses.check(address, 'ipv4')).toBe(true); } expect(PROBE_POLICY.allowedAddresses.check('fc00::1', 'ipv6')).toBe(true); // Real ULA is assigned out of `fd00::/8` (Tailscale, Docker) and must stay unreachable. expect(PROBE_POLICY.allowedAddresses.check('fd00::1', 'ipv6')).toBe(false); - for (const address of ['127.0.0.1', '192.168.1.1', '169.254.169.254', '168.63.129.16']) { + const denied = ['127.0.0.1', '192.168.1.1', '169.254.169.254', '168.63.129.16']; + for (let i = 0, len = denied.length; i < len; i++) { + const address = denied[i]; expect(PROBE_POLICY.allowedAddresses.check(address, 'ipv4')).toBe(false); expect(PROBE_POLICY.deniedAddresses.check(address, 'ipv4')).toBe(true); } diff --git a/packages/host/engine/src/__tests__/plugin-service.test.ts b/packages/host/engine/src/__tests__/plugin-service.test.ts index abd708245..7af93a96b 100644 --- a/packages/host/engine/src/__tests__/plugin-service.test.ts +++ b/packages/host/engine/src/__tests__/plugin-service.test.ts @@ -229,10 +229,12 @@ describe('PluginService', () => { }); const service = new PluginService(factory); - for (const mutation of [ + const mutations = [ service.installPlugin('claude-code', 'any'), service.uninstallPlugin('claude-code', 'any'), - ]) { + ]; + for (let i = 0, len = mutations.length; i < len; i++) { + const mutation = mutations[i]; expect(await Effect.runPromise(Effect.flip(mutation))).toMatchObject({ _tag: 'RequestError', code: 'unsupported', diff --git a/packages/host/engine/src/__tests__/request-handler-effects.test.ts b/packages/host/engine/src/__tests__/request-handler-effects.test.ts index b686beaf7..b4791f288 100644 --- a/packages/host/engine/src/__tests__/request-handler-effects.test.ts +++ b/packages/host/engine/src/__tests__/request-handler-effects.test.ts @@ -18,7 +18,10 @@ import { WireResponder } from '../wire/responder'; const roots: string[] = []; afterAll(() => { - for (const root of roots) rmSync(root, { recursive: true, force: true }); + for (let i = 0, len = roots.length; i < len; i++) { + const root = roots[i]; + rmSync(root, { recursive: true, force: true }); + } }); class RejectingPtyBackend implements PtyBackend { diff --git a/packages/host/engine/src/__tests__/script-service.test.ts b/packages/host/engine/src/__tests__/script-service.test.ts index d2b3e12c1..bcb05247c 100644 --- a/packages/host/engine/src/__tests__/script-service.test.ts +++ b/packages/host/engine/src/__tests__/script-service.test.ts @@ -30,7 +30,10 @@ function makeWorkspace(config?: unknown): string { } afterAll(() => { - for (const root of roots) rmSync(root, { recursive: true, force: true }); + for (let i = 0, len = roots.length; i < len; i++) { + const root = roots[i]; + rmSync(root, { recursive: true, force: true }); + } }); class FakePtyProcess implements PtyProcess { @@ -58,7 +61,10 @@ class FakePtyProcess implements PtyProcess { this.exit(0); } exit(code: number | null): void { - for (const cb of this.exitCbs) cb(code); + for (let i = 0, len = this.exitCbs.length; i < len; i++) { + const cb = this.exitCbs[i]; + cb(code); + } } } @@ -225,9 +231,9 @@ describe('ScriptService', () => { const { service, backend, routes, sent } = makeService(); await Effect.runPromise(service.start(cwd, 'web')); - const hostname = [...sent] - .map((p) => (p.kind === 'script.status' ? p.script.hostname : undefined)) - .find(Boolean)!; + const hostname = Array.from(sent, (p) => + p.kind === 'script.status' ? p.script.hostname : undefined, + ).find(Boolean)!; await Effect.runPromise(service.stop(cwd, 'web')); expect(backend.opens[0].process.killed).toBe(true); diff --git a/packages/host/engine/src/__tests__/simulator-service.test.ts b/packages/host/engine/src/__tests__/simulator-service.test.ts index 3dcecd533..3039caf2e 100644 --- a/packages/host/engine/src/__tests__/simulator-service.test.ts +++ b/packages/host/engine/src/__tests__/simulator-service.test.ts @@ -90,7 +90,9 @@ describe('SimulatorService', () => { const backend = fakeBackend([]); const service = new SimulatorService(backend); - for (const udid of ['A', 'B', 'C', 'D']) { + const udids = ['A', 'B', 'C', 'D']; + for (let i = 0, len = udids.length; i < len; i++) { + const udid = udids[i]; await service.openUrl(S1, udid, 'https://example.com'); } await expect(service.openUrl(S1, 'E', 'https://example.com')).rejects.toMatchObject({ diff --git a/packages/host/engine/src/__tests__/start-options-mcp.test.ts b/packages/host/engine/src/__tests__/start-options-mcp.test.ts index 667835fb5..5095a3b53 100644 --- a/packages/host/engine/src/__tests__/start-options-mcp.test.ts +++ b/packages/host/engine/src/__tests__/start-options-mcp.test.ts @@ -247,7 +247,9 @@ describe('account binding at session start', () => { describe('custom MCP injection at session start', () => { it('folds enabled custom servers in for claude-code, codex, and opencode', async () => { - for (const kind of ['claude-code', 'codex', 'opencode'] as const) { + const kinds = ['claude-code', 'codex', 'opencode'] as const; + for (let i = 0, len = kinds.length; i < len; i++) { + const kind = kinds[i]; const resolver = new SessionStartOptionsResolver( new InMemoryProviderConfigStore(), undefined, diff --git a/packages/host/engine/src/__tests__/terminal-service.test.ts b/packages/host/engine/src/__tests__/terminal-service.test.ts index a2c6cb67b..70ef7216b 100644 --- a/packages/host/engine/src/__tests__/terminal-service.test.ts +++ b/packages/host/engine/src/__tests__/terminal-service.test.ts @@ -30,7 +30,10 @@ class FakePtyProcess implements PtyProcess { } write(data: string): void { this.writes.push(data); - for (const cb of this.dataCbs) cb(data); + for (let i = 0, len = this.dataCbs.length; i < len; i++) { + const cb = this.dataCbs[i]; + cb(data); + } } resize(cols: number, rows: number): void { this.resizes.push({ cols, rows }); @@ -40,15 +43,24 @@ class FakePtyProcess implements PtyProcess { } kill(): void { this.killed = true; - for (const cb of this.exitCbs) cb(0); + for (let i = 0, len = this.exitCbs.length; i < len; i++) { + const cb = this.exitCbs[i]; + cb(0); + } } emitData(data: string): void { - for (const cb of this.dataCbs) cb(data); + for (let i = 0, len = this.dataCbs.length; i < len; i++) { + const cb = this.dataCbs[i]; + cb(data); + } } emitExit(exitCode: number | null): void { - for (const cb of this.exitCbs) cb(exitCode); + for (let i = 0, len = this.exitCbs.length; i < len; i++) { + const cb = this.exitCbs[i]; + cb(exitCode); + } } } diff --git a/packages/host/engine/src/__tests__/workspace-registry.test.ts b/packages/host/engine/src/__tests__/workspace-registry.test.ts index 138fc306e..e893f7617 100644 --- a/packages/host/engine/src/__tests__/workspace-registry.test.ts +++ b/packages/host/engine/src/__tests__/workspace-registry.test.ts @@ -29,7 +29,10 @@ function makeTempDir(): string { } afterAll(() => { - for (const dir of tempRoots) rmSync(dir, { recursive: true, force: true }); + for (let i = 0, len = tempRoots.length; i < len; i++) { + const dir = tempRoots[i]; + rmSync(dir, { recursive: true, force: true }); + } }); beforeEach(() => { diff --git a/packages/host/engine/src/agent/custom-mcp-service.ts b/packages/host/engine/src/agent/custom-mcp-service.ts index d5f501cb5..3cbeb968e 100644 --- a/packages/host/engine/src/agent/custom-mcp-service.ts +++ b/packages/host/engine/src/agent/custom-mcp-service.ts @@ -44,7 +44,8 @@ export class CustomMcpServerService { applyPatch(ops: CustomMcpServerPatchOp[]): Effect.Effect { return Effect.suspend((): Effect.Effect => { let next = [...this.store.getCustomMcpServers()]; - for (const op of ops) { + for (let i = 0, len = ops.length; i < len; i++) { + const op = ops[i]; switch (op.op) { case 'add': { if (next.some((entry) => entry.id === op.server.id)) { @@ -178,7 +179,9 @@ function applySecretPatch( if (!patch) return current; const removed = new Set(patch.remove); const next: Record = {}; - for (const [key, value] of Object.entries({ ...current, ...patch.set })) { + const merged = Object.entries({ ...current, ...patch.set }); + for (let i = 0, len = merged.length; i < len; i++) { + const [key, value] = merged[i]; if (!removed.has(key)) next[key] = value; } return isObjectEmpty(next) ? undefined : next; diff --git a/packages/host/engine/src/agent/model-probe.ts b/packages/host/engine/src/agent/model-probe.ts index 423738150..18fbdc62a 100644 --- a/packages/host/engine/src/agent/model-probe.ts +++ b/packages/host/engine/src/agent/model-probe.ts @@ -230,7 +230,8 @@ export async function probeEndpointModels( if (!parsed.success) throw new Error(`${url.href} did not answer a model list`); const entries = Array.isArray(parsed.data) ? parsed.data : parsed.data.data; const byId = new Map(); - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; if (entry.id && !byId.has(entry.id)) { byId.set(entry.id, { id: entry.id, @@ -256,7 +257,8 @@ export async function probeServiceModels( request: ModelListRequest = requestPublicModelList, ): Promise { const byUrl = new Map(); - for (const protocol of AccountProtocolSchema.options) { + for (let i = 0, len = AccountProtocolSchema.options.length; i < len; i++) { + const protocol = AccountProtocolSchema.options[i]; // A protocol this service does not actually serve (no variant at all) must not fall through // to the service-level list — that would tag every model with a protocol the service never // offered. @@ -272,13 +274,15 @@ export async function probeServiceModels( const merged = new Map(); const lists = await Promise.all( - [...byUrl.values()].map(async ({ source, protocols }) => ({ + Array.from(byUrl.values(), async ({ source, protocols }) => ({ models: await probeEndpointModels(source, secret, request), protocols, })), ); - for (const { models, protocols } of lists) { - for (const model of models) { + for (let i = 0, len = lists.length; i < len; i++) { + const { models, protocols } = lists[i]; + for (let j = 0, modelCount = models.length; j < modelCount; j++) { + const model = models[j]; const known = merged.get(model.id); const combined = [...new Set([...(known?.protocols ?? []), ...protocols])]; merged.set(model.id, { ...model, protocols: combined }); diff --git a/packages/host/engine/src/automation/loop-iteration-runner.ts b/packages/host/engine/src/automation/loop-iteration-runner.ts index ac3c5f718..ab4615b62 100644 --- a/packages/host/engine/src/automation/loop-iteration-runner.ts +++ b/packages/host/engine/src/automation/loop-iteration-runner.ts @@ -151,7 +151,8 @@ export class LoopIterationRunner { const { reporter } = this; const saveEffect = this.saveEffect.bind(this); return Effect.gen(function* () { - for (const command of loop.spec.verifyChecks) { + for (let i = 0, len = loop.spec.verifyChecks.length; i < len; i++) { + const command = loop.spec.verifyChecks[i]; const result = yield* runShellCheck(command, { cwd: loop.spec.cwd, timeoutMs: loop.spec.turnTimeoutMs, diff --git a/packages/host/engine/src/automation/loop-service.ts b/packages/host/engine/src/automation/loop-service.ts index eac08cda9..045bfe29c 100644 --- a/packages/host/engine/src/automation/loop-service.ts +++ b/packages/host/engine/src/automation/loop-service.ts @@ -57,12 +57,16 @@ export class LoopService { } async start(): Promise { - for (const loop of await this.store.load()) { + const stored = await this.store.load(); + for (let i = 0, len = stored.length; i < len; i++) { + const loop = stored[i]; this.loops.set(loop.loopId, loop); } // A loop is a single bounded job; a restart cannot resume its worker sessions, so mark any that // were mid-run as stopped rather than pretending to continue. - for (const loop of await this.store.loadRunning()) { + const running = await this.store.loadRunning(); + for (let i = 0, len = running.length; i < len; i++) { + const loop = running[i]; loop.status = 'stopped'; loop.error = 'daemon restarted before the loop finished'; loop.endedAt = this.now(); @@ -183,7 +187,7 @@ export class LoopService { /** Resolves once all accepted loop fibers finish persistence, reporting, and session cleanup. */ settleAll(): Effect.Effect { return Effect.asVoid( - Effect.all([...this.handles.values()].map(({ fiber }) => Fiber.await(fiber))), + Effect.all(Array.from(this.handles.values(), ({ fiber }) => Fiber.await(fiber))), ); } diff --git a/packages/host/engine/src/automation/loop-store.ts b/packages/host/engine/src/automation/loop-store.ts index 4154243a2..356c0f4f9 100644 --- a/packages/host/engine/src/automation/loop-store.ts +++ b/packages/host/engine/src/automation/loop-store.ts @@ -24,7 +24,7 @@ export class InMemoryLoopStore implements LoopStore { private readonly iterations = new Map(); load(): Promise { - return Promise.resolve([...this.loops.values()].map((loop) => structuredClone(loop))); + return Promise.resolve(Array.from(this.loops.values(), (loop) => structuredClone(loop))); } save(loop: LoopRecord): Promise { diff --git a/packages/host/engine/src/automation/schedule-run-coordinator.ts b/packages/host/engine/src/automation/schedule-run-coordinator.ts index 433fb3f14..05104b396 100644 --- a/packages/host/engine/src/automation/schedule-run-coordinator.ts +++ b/packages/host/engine/src/automation/schedule-run-coordinator.ts @@ -92,7 +92,8 @@ export class ScheduleRunCoordinator { 'Failed to recover schedule runs', () => store.loadRunningRuns(), ); - for (const run of running) { + for (let i = 0, len = running.length; i < len; i++) { + const run = running[i]; yield* saveRun({ ...run, status: 'failed', diff --git a/packages/host/engine/src/automation/schedule-service.ts b/packages/host/engine/src/automation/schedule-service.ts index 3c45b1088..f56384524 100644 --- a/packages/host/engine/src/automation/schedule-service.ts +++ b/packages/host/engine/src/automation/schedule-service.ts @@ -405,7 +405,7 @@ export class ScheduleService { } private settleTasks(): Effect.Effect { - return Effect.asVoid(Effect.all([...this.inFlight].map((fiber) => Fiber.await(fiber)))); + return Effect.asVoid(Effect.all(Array.from(this.inFlight, (fiber) => Fiber.await(fiber)))); } /** Bookkeeping once a run settles: count scheduled runs toward maxRuns; record lastRunAt. */ diff --git a/packages/host/engine/src/automation/schedule-store.ts b/packages/host/engine/src/automation/schedule-store.ts index 3e2ee3231..f6d33212e 100644 --- a/packages/host/engine/src/automation/schedule-store.ts +++ b/packages/host/engine/src/automation/schedule-store.ts @@ -25,7 +25,7 @@ export class InMemoryScheduleStore implements ScheduleStore { private readonly runs = new Map(); load(): Promise { - return Promise.resolve([...this.schedules.values()].map((s) => structuredClone(s))); + return Promise.resolve(Array.from(this.schedules.values(), (s) => structuredClone(s))); } save(schedule: Schedule): Promise { @@ -71,7 +71,11 @@ export class InMemoryScheduleStore implements ScheduleStore { pruneRuns(scheduleId: ScheduleId, keep: number): Promise { const runs = this.runsForSchedule(scheduleId); runs.sort((a, b) => b.startedAt - a.startedAt); - for (const run of runs.slice(keep)) this.runs.delete(run.runId); + const excess = runs.slice(keep); + for (let i = 0, len = excess.length; i < len; i++) { + const run = excess[i]; + this.runs.delete(run.runId); + } return Promise.resolve(); } } diff --git a/packages/host/engine/src/browser/repl-rewrite.ts b/packages/host/engine/src/browser/repl-rewrite.ts index 4e1de5994..9a5edf09a 100644 --- a/packages/host/engine/src/browser/repl-rewrite.ts +++ b/packages/host/engine/src/browser/repl-rewrite.ts @@ -28,7 +28,8 @@ export function rewriteForPersistentRepl(code: string): string { const hoisted: string[] = []; const edits: Array<{ start: number; end: number; text: string }> = []; - for (const node of program.body) { + for (let i = 0, len = program.body.length; i < len; i++) { + const node = program.body[i]; switch (node.type) { case 'VariableDeclaration': { if (node.kind === 'using' || node.kind === 'await using') break; @@ -58,7 +59,9 @@ export function rewriteForPersistentRepl(code: string): string { } let rewritten = code; - for (const edit of edits.reverse()) { + const reversedEdits = edits.reverse(); + for (let i = 0, len = reversedEdits.length; i < len; i++) { + const edit = reversedEdits[i]; rewritten = rewritten.slice(0, edit.start) + edit.text + rewritten.slice(edit.end); } const prelude = hoisted.length > 0 ? `var ${hoisted.join(', ')};\n` : ''; @@ -75,12 +78,14 @@ function collectPatternNames(pattern: Pattern, names: string[]): void { names.push(pattern.name); break; case 'ObjectPattern': - for (const property of pattern.properties) { + for (let i = 0, len = pattern.properties.length; i < len; i++) { + const property = pattern.properties[i]; collectPatternNames(property.type === 'RestElement' ? property : property.value, names); } break; case 'ArrayPattern': - for (const element of pattern.elements) { + for (let i = 0, len = pattern.elements.length; i < len; i++) { + const element = pattern.elements[i]; if (element) collectPatternNames(element, names); } break; diff --git a/packages/host/engine/src/engine.ts b/packages/host/engine/src/engine.ts index f61ee2fbe..30b7b3628 100644 --- a/packages/host/engine/src/engine.ts +++ b/packages/host/engine/src/engine.ts @@ -285,7 +285,9 @@ export const createEngineRuntime = Effect.fn('Engine.create')(function* ( yield* tryOperation('store', 'workspaces.load', 'Failed to load workspaces', () => workspaces.start(), ); - for (const workspace of workspaces.list()) { + const workspaceList = workspaces.list(); + for (let i = 0, len = workspaceList.length; i < len; i++) { + const workspace = workspaceList[i]; if (workspace.kind === 'worktree' && !worktrees.hasPath(workspace.cwd)) { yield* tryOperation( 'store', diff --git a/packages/host/engine/src/git/branches.ts b/packages/host/engine/src/git/branches.ts index ea323b6f9..d0fa3539f 100644 --- a/packages/host/engine/src/git/branches.ts +++ b/packages/host/engine/src/git/branches.ts @@ -25,7 +25,9 @@ export const readGitBranches = Effect.fn('Git.readBranches')(function* (cwd: str if (result.exitCode !== 0) return { isRepo: false } as const; const branches: GitBranch[] = []; - for (const line of result.stdout.split('\n')) { + const lines = result.stdout.split('\n'); + for (let i = 0, len = lines.length; i < len; i++) { + const line = lines[i]; if (line.length === 0) continue; const [name, head, committedAt] = line.split(FIELD_SEPARATOR); if (!name) continue; diff --git a/packages/host/engine/src/git/diff.ts b/packages/host/engine/src/git/diff.ts index e570b8919..a6dd61fab 100644 --- a/packages/host/engine/src/git/diff.ts +++ b/packages/host/engine/src/git/diff.ts @@ -47,7 +47,9 @@ const resolveBaseRef = Effect.fn('Git.resolveBaseRef')(function* (cwd: string) { const base = symref.stdout.trim().replace(REMOTES_REF_PREFIX, ''); if (base.length > 0) return base; } - for (const candidate of ['origin/main', 'origin/master']) { + const candidates = ['origin/main', 'origin/master']; + for (let i = 0, len = candidates.length; i < len; i++) { + const candidate = candidates[i]; const verify = yield* git(cwd, 'rev-parse', '--verify', '--quiet', `refs/remotes/${candidate}`); if (verify.exitCode === 0) return candidate; } @@ -115,7 +117,9 @@ const readUntrackedDiff = Effect.fn('Git.readUntrackedDiff')(function* (cwd: str if (status.exitCode !== 0) return { patch: '', truncated: false }; const paths: string[] = []; - for (const entry of status.stdout.split('\0')) { + const entries = status.stdout.split('\0'); + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; if (entry.startsWith('?? ')) paths.push(entry.slice(3)); } const truncated = paths.length > MAX_UNTRACKED_FILES; @@ -164,7 +168,8 @@ function capToFileBoundary(patch: string, capBytes: number): { patch: string; tr const fileEnds = [...findFileBoundaries(patch).slice(1), patch.length]; let cut = 0; - for (const end of fileEnds) { + for (let i = 0, len = fileEnds.length; i < len; i++) { + const end = fileEnds[i]; if (Buffer.byteLength(patch.slice(0, end), 'utf8') > capBytes) break; cut = end; } @@ -176,7 +181,9 @@ function computeStat(patch: string): GitDiffStat { let files = 0; let additions = 0; let deletions = 0; - for (const line of patch.split('\n')) { + const lines = patch.split('\n'); + for (let i = 0, len = lines.length; i < len; i++) { + const line = lines[i]; if (line.startsWith('diff --git ')) files += 1; else if (line.startsWith('+++') || line.startsWith('---')) continue; else if (line[0] === '+') additions += 1; diff --git a/packages/host/engine/src/git/github.ts b/packages/host/engine/src/git/github.ts index ccc6f5fae..2f2b8cd8b 100644 --- a/packages/host/engine/src/git/github.ts +++ b/packages/host/engine/src/git/github.ts @@ -69,7 +69,8 @@ export function rollUpChecks(rollup: readonly GhCheck[] | null | undefined): Git if (!rollup || rollup.length === 0) return 'none'; let sawFailing = false; let sawPending = false; - for (const check of rollup) { + for (let i = 0, len = rollup.length; i < len; i++) { + const check = rollup[i]; const outcome = check.state ?? (check.status === 'COMPLETED' ? check.conclusion : null); if (outcome === 'EXPECTED' || outcome === 'PENDING' || outcome == null) sawPending = true; else if (FAILING_OUTCOMES.has(outcome)) sawFailing = true; diff --git a/packages/host/engine/src/git/mutations.ts b/packages/host/engine/src/git/mutations.ts index 56ef4b625..67c63b808 100644 --- a/packages/host/engine/src/git/mutations.ts +++ b/packages/host/engine/src/git/mutations.ts @@ -166,7 +166,7 @@ export const commitGitChanges = Effect.fn('Git.commitChanges')(function* ( function parseStatusPaths(output: string): Set { const entries = splitNul(output); const paths = new Set(); - for (let index = 0; index < entries.length; index += 1) { + for (let index = 0, len = entries.length; index < len; index += 1) { const entry = entries[index]; paths.add(entry.slice(3)); if (entry[0] === 'R' || entry[0] === 'C' || entry[1] === 'R' || entry[1] === 'C') { diff --git a/packages/host/engine/src/git/status.ts b/packages/host/engine/src/git/status.ts index c3e039ee2..bfd6fd40e 100644 --- a/packages/host/engine/src/git/status.ts +++ b/packages/host/engine/src/git/status.ts @@ -25,7 +25,9 @@ const readDirtyFileCount = Effect.fn('Git.readDirtyFileCount')(function* (cwd: s const result = yield* git(cwd, 'status', '--porcelain'); if (result.exitCode !== 0) return 0; let count = 0; - for (const line of result.stdout.split('\n')) { + const lines = result.stdout.split('\n'); + for (let i = 0, len = lines.length; i < len; i++) { + const line = lines[i]; if (line.length > 0) count += 1; } return count; diff --git a/packages/host/engine/src/json-equal.ts b/packages/host/engine/src/json-equal.ts index 64acd9c9a..b27eadc7b 100644 --- a/packages/host/engine/src/json-equal.ts +++ b/packages/host/engine/src/json-equal.ts @@ -9,10 +9,14 @@ export function jsonValueEqual(a: unknown, b: unknown): boolean { if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false; const left = a as Record; const right = b as Record; - for (const key of Object.keys(left)) { + const leftKeys = Object.keys(left); + for (let i = 0, len = leftKeys.length; i < len; i++) { + const key = leftKeys[i]; if (!jsonValueEqual(left[key], right[key])) return false; } - for (const key of Object.keys(right)) { + const rightKeys = Object.keys(right); + for (let i = 0, len = rightKeys.length; i < len; i++) { + const key = rightKeys[i]; if (!(key in left) && right[key] !== undefined) return false; } return true; diff --git a/packages/host/engine/src/resource/resource-store.ts b/packages/host/engine/src/resource/resource-store.ts index b12bd1a27..86fb19a77 100644 --- a/packages/host/engine/src/resource/resource-store.ts +++ b/packages/host/engine/src/resource/resource-store.ts @@ -59,7 +59,10 @@ export class InMemoryResourceStore implements ResourceStore { async deleteSession(sessionId: SessionId): Promise { const values = await this.list(sessionId); const removals: Array> = []; - for (const value of values) removals.push(this.remove(value.resourceId)); + for (let i = 0, len = values.length; i < len; i++) { + const value = values[i]; + removals.push(this.remove(value.resourceId)); + } await Promise.all(removals); return values; } diff --git a/packages/host/engine/src/resource/service.ts b/packages/host/engine/src/resource/service.ts index 1da809500..d7e53df3d 100644 --- a/packages/host/engine/src/resource/service.ts +++ b/packages/host/engine/src/resource/service.ts @@ -182,7 +182,8 @@ export class ResourceService { return this.list(sessionId).pipe( Effect.map((items) => { const locators: string[] = []; - for (const resource of items) { + for (let i = 0, len = items.length; i < len; i++) { + const resource = items[i]; if (resource.direction === 'source' && resource.status === 'ready') { locators.push( resource.locator.type === 'url' ? resource.locator.url : resource.locator.path, @@ -287,7 +288,8 @@ export class ResourceService { }).pipe( Effect.tap((removed) => Effect.sync(() => { - for (const resource of removed) { + for (let i = 0, len = removed.length; i < len; i++) { + const resource = removed[i]; this.transport.send( createWireMessage({ kind: 'resource.removed', diff --git a/packages/host/engine/src/scripts/config.ts b/packages/host/engine/src/scripts/config.ts index 2d514224d..f57fc62f5 100644 --- a/packages/host/engine/src/scripts/config.ts +++ b/packages/host/engine/src/scripts/config.ts @@ -35,7 +35,9 @@ export function readWorkspaceScripts(cwd: string): ScriptDeclaration[] { if (scripts === null || typeof scripts !== 'object') return []; const declarations: ScriptDeclaration[] = []; - for (const [name, raw] of Object.entries(scripts as Record)) { + const scriptEntries = Object.entries(scripts as Record); + for (let i = 0, len = scriptEntries.length; i < len; i++) { + const [name, raw] = scriptEntries[i]; const entry = ScriptEntrySchema.safeParse(raw); if (!entry.success || name.trim().length === 0) continue; const type = entry.data.type ?? 'task'; diff --git a/packages/host/engine/src/scripts/script-port-plan.ts b/packages/host/engine/src/scripts/script-port-plan.ts index de151a16b..ea8e5cedb 100644 --- a/packages/host/engine/src/scripts/script-port-plan.ts +++ b/packages/host/engine/src/scripts/script-port-plan.ts @@ -54,7 +54,8 @@ export class ScriptPortPlan { const url = proxyUrl(hostnameFor(declaration.name)); if (url) env.LINKCODE_URL = url; } - for (const sibling of declarations) { + for (let i = 0, len = declarations.length; i < len; i++) { + const sibling = declarations[i]; if (sibling.type !== 'service') continue; const port = this.ports.get(sibling.name); if (port === undefined) continue; @@ -67,7 +68,8 @@ export class ScriptPortPlan { } private async allocateMissing(declarations: ScriptDeclaration[]): Promise { - for (const declaration of declarations) { + for (let i = 0, len = declarations.length; i < len; i++) { + const declaration = declarations[i]; // eslint-disable-next-line no-await-in-loop -- ports are allocated one at a time on purpose const port = declaration.preferredPort ?? (await this.allocate()); this.ensureAccepting(); diff --git a/packages/host/engine/src/session/ask-response.ts b/packages/host/engine/src/session/ask-response.ts index 4960dd3b7..e2badbc1f 100644 --- a/packages/host/engine/src/session/ask-response.ts +++ b/packages/host/engine/src/session/ask-response.ts @@ -38,7 +38,8 @@ export function validateAskResponse(request: AskEvent, input: AskResponseInput): throw invalidRequest(`Question request ${input.requestId} has duplicate question IDs`); } const answers = new Map(); - for (const answer of input.outcome.answers) { + for (let i = 0, len = input.outcome.answers.length; i < len; i++) { + const answer = input.outcome.answers[i]; if (answers.has(answer.questionId)) { throw invalidRequest(`Duplicate answer for question: ${answer.questionId}`); } @@ -48,7 +49,8 @@ export function validateAskResponse(request: AskEvent, input: AskResponseInput): answers.set(answer.questionId, answer); } - for (const question of request.questions) { + for (let i = 0, len = request.questions.length; i < len; i++) { + const question = request.questions[i]; const answer = answers.get(question.questionId); if (!answer) throw invalidRequest(`Missing answer: ${question.questionId}`); if (answer.customText !== undefined) { diff --git a/packages/host/engine/src/session/attachment-guard.ts b/packages/host/engine/src/session/attachment-guard.ts index 22daa4528..b7c95da9d 100644 --- a/packages/host/engine/src/session/attachment-guard.ts +++ b/packages/host/engine/src/session/attachment-guard.ts @@ -24,7 +24,8 @@ function attachmentData(block: ContentBlock): string | undefined { * keeps a prompt's base64 under the transport's frame buffer, whose overflow kills the connection. */ export function assertAttachmentContentAllowed(content: ContentBlock[]): void { let totalBytes = 0; - for (const block of content) { + for (let i = 0, len = content.length; i < len; i++) { + const block = content[i]; if (block.type === 'image' && !isSupportedAttachmentImageMimeType(block.mimeType)) { throw new RequestError({ code: 'invalid_request', diff --git a/packages/host/engine/src/session/history-service.ts b/packages/host/engine/src/session/history-service.ts index 5cae16e76..1babaa14f 100644 --- a/packages/host/engine/src/session/history-service.ts +++ b/packages/host/engine/src/session/history-service.ts @@ -94,7 +94,8 @@ export class HistoryService { Effect.tap((result) => Effect.sync(() => { this.invalidateEventCacheFromList(kind, result.sessions); - for (const session of result.sessions) { + for (let i = 0, len = result.sessions.length; i < len; i++) { + const session = result.sessions[i]; const historyKey = eventCacheKey(kind, session.historyId); if (opts.cwd) this.historyCwdById.set(historyKey, opts.cwd); else this.historyCwdById.delete(historyKey); @@ -230,7 +231,8 @@ export class HistoryService { // eslint-disable-next-line no-await-in-loop -- Provider cursors require serial pagination. await adapter.readHistory({ historyId, cwd, limit: 1000, cursor }), ); - for (const entry of result.events) { + for (let i = 0, len = result.events.length; i < len; i++) { + const entry = result.events[i]; if (entry.event.type === 'user-message' && entry.event.branchCursor !== undefined) { branchablePrompts.push({ branchCursor: entry.event.branchCursor, @@ -284,7 +286,8 @@ export class HistoryService { } private invalidateEventCacheFromList(kind: AgentKind, sessions: AgentHistorySession[]): void { - for (const session of sessions) { + for (let i = 0, len = sessions.length; i < len; i++) { + const session = sessions[i]; const key = eventCacheKey(kind, session.historyId); const cached = this.eventCache.get(key); if (cached && cached.fingerprint !== sessionFingerprint(session)) this.eventCache.delete(key); diff --git a/packages/host/engine/src/session/orchestrator.ts b/packages/host/engine/src/session/orchestrator.ts index 24b093fd6..efc1bc585 100644 --- a/packages/host/engine/src/session/orchestrator.ts +++ b/packages/host/engine/src/session/orchestrator.ts @@ -258,7 +258,10 @@ export class SessionOrchestrator { { type: 'conversation-rewind', messageId: rewindMessageId }, ]); bufferEvents = false; - for (const event of startupEvents) events.handle(sessionId, session, event); + for (let i = 0, len = startupEvents.length; i < len; i++) { + const event = startupEvents[i]; + events.handle(sessionId, session, event); + } } if (initialInput !== undefined) { yield* session diff --git a/packages/host/engine/src/session/session-event-processor.ts b/packages/host/engine/src/session/session-event-processor.ts index a8e1f4554..590798c45 100644 --- a/packages/host/engine/src/session/session-event-processor.ts +++ b/packages/host/engine/src/session/session-event-processor.ts @@ -33,13 +33,15 @@ export class SessionEventProcessor { : event.type === 'agent-message-chunk' ? [event.content] : []; - for (const block of links) { + for (let i = 0, len = links.length; i < len; i++) { + const block = links[i]; if (block.type === 'resource_link') { this.registerResource(sessionId, 'output', block.uri, block.name, block.mimeType); } } if (event.type !== 'tool-call' || event.toolCall.status !== 'completed') return; - for (const item of event.toolCall.content) { + for (let i = 0, len = event.toolCall.content.length; i < len; i++) { + const item = event.toolCall.content[i]; if (item.type === 'diff' && item.change === 'add') { this.registerResource(sessionId, 'output', item.path); } diff --git a/packages/host/engine/src/session/session-record-registry.ts b/packages/host/engine/src/session/session-record-registry.ts index 2f9f00adf..991cf330e 100644 --- a/packages/host/engine/src/session/session-record-registry.ts +++ b/packages/host/engine/src/session/session-record-registry.ts @@ -51,7 +51,10 @@ export class SessionRecordRegistry { ), Effect.tap((records) => Effect.sync(() => { - for (const record of records) this.records.set(record.sessionId, record); + for (let i = 0, len = records.length; i < len; i++) { + const record = records[i]; + this.records.set(record.sessionId, record); + } }), ), Effect.asVoid, @@ -292,9 +295,10 @@ function latestRunValue( /** Spreading an explicit `undefined` would write the key into the persisted record. */ function definedFields(fields: T): Partial { - return Object.fromEntries( - Object.entries(fields).filter(([, value]) => value !== undefined), - ) as Partial; + return Object.entries(fields).reduce>((acc, [key, value]) => { + if (value !== undefined) (acc as Record)[key] = value; + return acc; + }, {}); } function latestHistoryId(record: SessionRecord): AgentHistoryId | undefined { @@ -308,7 +312,8 @@ function latestHistoryId(record: SessionRecord): AgentHistoryId | undefined { const WHITESPACE_RUN_RE = /\s+/g; function titleFromContent(content: ContentBlock[]): string | undefined { - for (const block of content) { + for (let i = 0, len = content.length; i < len; i++) { + const block = content[i]; if (block.type !== 'text') continue; const text = block.text.trim().replaceAll(WHITESPACE_RUN_RE, ' '); if (text.length === 0) continue; diff --git a/packages/host/engine/src/session/session-store.ts b/packages/host/engine/src/session/session-store.ts index 527b04d51..65741f283 100644 --- a/packages/host/engine/src/session/session-store.ts +++ b/packages/host/engine/src/session/session-store.ts @@ -12,7 +12,7 @@ export class InMemorySessionStore implements SessionStore { private readonly records = new Map(); load(): Promise { - return Promise.resolve([...this.records.values()].map((record) => structuredClone(record))); + return Promise.resolve(Array.from(this.records.values(), (record) => structuredClone(record))); } save(record: SessionRecord): Promise { diff --git a/packages/host/engine/src/session/start-options-resolver.ts b/packages/host/engine/src/session/start-options-resolver.ts index f22ac181c..a397ebc52 100644 --- a/packages/host/engine/src/session/start-options-resolver.ts +++ b/packages/host/engine/src/session/start-options-resolver.ts @@ -114,7 +114,8 @@ export class SessionStartOptionsResolver { const enabled = this.customMcp?.listEnabled() ?? []; if (enabled.length === 0) return Effect.succeed({ options, warnings }); if (!MCP_CAPABLE_AGENT_KINDS.has(options.kind)) { - for (const entry of enabled) { + for (let i = 0, len = enabled.length; i < len; i++) { + const entry = enabled[i]; warnings.push({ serverName: entry.server.name, reason: 'agent-unsupported' }); } return Effect.succeed({ options, warnings }); @@ -128,7 +129,8 @@ export class SessionStartOptionsResolver { return pluginNames.pipe( Effect.map((names) => { const servers = [...(options.mcpServers ?? [])]; - for (const entry of enabled) { + for (let i = 0, len = enabled.length; i < len; i++) { + const entry = enabled[i]; if (names === null) { warnings.push({ serverName: entry.server.name, diff --git a/packages/host/engine/src/simulator/consent.ts b/packages/host/engine/src/simulator/consent.ts index b4b53ef28..dd0309028 100644 --- a/packages/host/engine/src/simulator/consent.ts +++ b/packages/host/engine/src/simulator/consent.ts @@ -57,7 +57,10 @@ export class SimulatorConsentService { async init(): Promise { const state = await this.store.load(); this.agentToolsEnabled = state.agentToolsEnabled; - for (const entry of state.entries) this.decisions.set(entry.udid, entry.decision); + for (let i = 0, len = state.entries.length; i < len; i++) { + const entry = state.entries[i]; + this.decisions.set(entry.udid, entry.decision); + } } /** @@ -75,7 +78,7 @@ export class SimulatorConsentService { state(): SimulatorConsentState { return { - entries: [...this.decisions].map(([udid, decision]) => ({ udid, decision })), + entries: Array.from(this.decisions, ([udid, decision]) => ({ udid, decision })), agentToolsEnabled: this.agentToolsEnabled, }; } @@ -152,7 +155,7 @@ export class SimulatorConsentService { resolve(decision); }; }); - const timer = setTimeout(() => settle('denied'), this.askTimeoutMs); + const timer = setTimeout(settle, this.askTimeoutMs, 'denied'); timer.unref?.(); this.pending.set(udid, { promise, settle, timer }); return promise; diff --git a/packages/host/engine/src/terminal/replay.ts b/packages/host/engine/src/terminal/replay.ts index 0ded93a82..2a69f4f1f 100644 --- a/packages/host/engine/src/terminal/replay.ts +++ b/packages/host/engine/src/terminal/replay.ts @@ -47,7 +47,8 @@ export class TerminalReplayJournal { * everything after it reaches that attachment as ordinary live frames. */ snapshotUpTo(seq: number): TerminalReplayEvent[] { const events: TerminalReplayEvent[] = []; - for (const { event } of this.entries) { + for (let i = 0, len = this.entries.length; i < len; i++) { + const { event } = this.entries[i]; if (event.seq > seq) break; events.push(event); } diff --git a/packages/host/engine/src/workspace/file-suggest-service.ts b/packages/host/engine/src/workspace/file-suggest-service.ts index fc3157f3c..dfe243717 100644 --- a/packages/host/engine/src/workspace/file-suggest-service.ts +++ b/packages/host/engine/src/workspace/file-suggest-service.ts @@ -6,6 +6,7 @@ import { runCommand } from '../process/run-command'; export const DEFAULT_SUGGEST_LIMIT = 50; const MAX_ENUMERATED_FILES = 20000; +const collator = new Intl.Collator(); const LIST_CACHE_TTL_MS = 5000; const LIST_CACHE_CAPACITY = 256; const WALK_MAX_DEPTH = 8; @@ -44,6 +45,9 @@ const listGitFiles = Effect.fn('FileSuggestService.listGitFiles')(function* (cwd const walkFiles = Effect.fn('FileSuggestService.walkFiles')(function* (root: string) { const files: string[] = []; const queue: Array<{ dir: string; depth: number }> = [{ dir: root, depth: 0 }]; + // Both `.length` reads must stay live: the body grows `queue` (the BFS frontier) and `files` + // (the enumeration cap) on every iteration — caching either would freeze the walk. + // eslint-disable-next-line vibe-proof/prefer-indexed-array-loop -- see above for (let head = 0; head < queue.length && files.length < MAX_ENUMERATED_FILES; head++) { const { dir, depth } = queue[head]; const entries = yield* Effect.tryPromise(() => readdir(dir, { withFileTypes: true })).pipe( @@ -51,7 +55,8 @@ const walkFiles = Effect.fn('FileSuggestService.walkFiles')(function* (root: str ); // Unreadable directory (permissions, races) — skip, don't fail the search. if (!entries) continue; - for (const entry of entries) { + for (let i = 0, len = entries.length; i < len; i++) { + const entry = entries[i]; if (entry.name[0] === '.') continue; const absolute = path.join(dir, entry.name); if (entry.isDirectory()) { @@ -121,12 +126,13 @@ export class FileSuggestService { function rankFiles(files: readonly string[], query: string): string[] { const needle = query.toLowerCase(); const ranked: Array<{ file: string; tier: number; depth: number }> = []; - for (const file of files) { + for (let i = 0, len = files.length; i < len; i++) { + const file = files[i]; const tier = matchTier(file, needle); if (tier === null) continue; ranked.push({ file, tier, depth: file.split('/').length }); } - ranked.sort((a, b) => a.tier - b.tier || a.depth - b.depth || a.file.localeCompare(b.file)); + ranked.sort((a, b) => a.tier - b.tier || a.depth - b.depth || collator.compare(a.file, b.file)); return ranked.map((entry) => entry.file); } diff --git a/packages/host/engine/src/workspace/workspace-registry.ts b/packages/host/engine/src/workspace/workspace-registry.ts index 1560e0e23..166f5c535 100644 --- a/packages/host/engine/src/workspace/workspace-registry.ts +++ b/packages/host/engine/src/workspace/workspace-registry.ts @@ -26,7 +26,8 @@ export class WorkspaceRegistry { const records = await storeOperation('workspace.load', 'Failed to load workspaces', () => this.store.load(), ); - for (const record of records) { + for (let i = 0, len = records.length; i < len; i++) { + const record = records[i]; this.index(record); } } diff --git a/packages/host/engine/src/workspace/workspace-store.ts b/packages/host/engine/src/workspace/workspace-store.ts index 74202d955..04599db6c 100644 --- a/packages/host/engine/src/workspace/workspace-store.ts +++ b/packages/host/engine/src/workspace/workspace-store.ts @@ -12,7 +12,7 @@ export class InMemoryWorkspaceStore implements WorkspaceStore { private readonly records = new Map(); load(): Promise { - return Promise.resolve([...this.records.values()].map((record) => structuredClone(record))); + return Promise.resolve(Array.from(this.records.values(), (record) => structuredClone(record))); } save(record: WorkspaceRecord): Promise { diff --git a/packages/host/engine/src/worktree/worktree-service.ts b/packages/host/engine/src/worktree/worktree-service.ts index 8263320c8..15d44d766 100644 --- a/packages/host/engine/src/worktree/worktree-service.ts +++ b/packages/host/engine/src/worktree/worktree-service.ts @@ -45,7 +45,8 @@ export class WorktreeService { ).pipe( Effect.tap((records) => Effect.sync(() => { - for (const record of records) { + for (let i = 0, len = records.length; i < len; i++) { + const record = records[i]; this.bySession.set(record.sessionId, record); this.byRepoBranch.set(repoBranchKey(record.repoRoot, record.branch), record); } @@ -310,9 +311,11 @@ export class WorktreeService { const root = this.root; return Effect.gen({ self: this }, function* () { const groups = yield* readChildDirectories(root); - for (const group of groups) { + for (let i = 0, len = groups.length; i < len; i++) { + const group = groups[i]; const candidates = yield* readChildDirectories(group); - for (const candidate of candidates) { + for (let j = 0, candidateCount = candidates.length; j < candidateCount; j++) { + const candidate = candidates[j]; if (this.hasPath(candidate)) continue; const identity = yield* identifyManagedWorktree(candidate).pipe( Effect.catch((error) => diff --git a/packages/host/engine/src/worktree/worktree-store.ts b/packages/host/engine/src/worktree/worktree-store.ts index fa8c649b1..328bd1042 100644 --- a/packages/host/engine/src/worktree/worktree-store.ts +++ b/packages/host/engine/src/worktree/worktree-store.ts @@ -10,7 +10,7 @@ export class InMemoryWorktreeStore implements WorktreeStore { private readonly records = new Map(); load(): Promise { - return Promise.resolve([...this.records.values()].map((record) => structuredClone(record))); + return Promise.resolve(Array.from(this.records.values(), (record) => structuredClone(record))); } save(record: WorktreeRecord): Promise { diff --git a/packages/host/engine/tests/integration/engine-worktree.test.ts b/packages/host/engine/tests/integration/engine-worktree.test.ts index ed614602b..bbaed03d0 100644 --- a/packages/host/engine/tests/integration/engine-worktree.test.ts +++ b/packages/host/engine/tests/integration/engine-worktree.test.ts @@ -56,7 +56,11 @@ class RejectingStartAdapter extends FakeAdapter { } afterEach(() => { - for (const root of tempRoots.splice(0)) rmSync(root, { recursive: true, force: true }); + const drained = tempRoots.splice(0); + for (let i = 0, len = drained.length; i < len; i++) { + const root = drained[i]; + rmSync(root, { recursive: true, force: true }); + } }); describe('engine managed worktree sessions', () => { diff --git a/packages/host/engine/tests/integration/file-suggest-service.test.ts b/packages/host/engine/tests/integration/file-suggest-service.test.ts index 53507065f..b698aaadb 100644 --- a/packages/host/engine/tests/integration/file-suggest-service.test.ts +++ b/packages/host/engine/tests/integration/file-suggest-service.test.ts @@ -28,7 +28,10 @@ function git(cwd: string, ...args: string[]): void { } afterAll(() => { - for (const dir of roots) rmSync(dir, { recursive: true, force: true }); + for (let i = 0, len = roots.length; i < len; i++) { + const dir = roots[i]; + rmSync(dir, { recursive: true, force: true }); + } }); describe('FileSuggestService', () => { diff --git a/packages/host/engine/tests/integration/git-diff.test.ts b/packages/host/engine/tests/integration/git-diff.test.ts index f50fd7f3a..e728b10bd 100644 --- a/packages/host/engine/tests/integration/git-diff.test.ts +++ b/packages/host/engine/tests/integration/git-diff.test.ts @@ -68,7 +68,10 @@ function parseShortstat(output: string): { files: number; additions: number; del } afterAll(() => { - for (const dir of roots) rmSync(dir, { recursive: true, force: true }); + for (let i = 0, len = roots.length; i < len; i++) { + const dir = roots[i]; + rmSync(dir, { recursive: true, force: true }); + } }); describe('readGitDiff', () => { @@ -111,11 +114,17 @@ describe('readGitDiff', () => { it('truncates at the last complete file boundary once the patch exceeds the byte cap', async () => { const dir = makeRepo(); const fileNames = ['f0.txt', 'f1.txt', 'f2.txt', 'f3.txt', 'f4.txt']; - for (const name of fileNames) writeFileSync(join(dir, name), 'seed\n'); + for (let i = 0, len = fileNames.length; i < len; i++) { + const name = fileNames[i]; + writeFileSync(join(dir, name), 'seed\n'); + } git(dir, 'add', ...fileNames); commit(dir, 'init'); // ~500KB of unique content per file, ~2.5MB combined — comfortably over the 2MB cap. - for (const name of fileNames) writeFileSync(join(dir, name), bigLineBlock(500000, name)); + for (let i = 0, len = fileNames.length; i < len; i++) { + const name = fileNames[i]; + writeFileSync(join(dir, name), bigLineBlock(500000, name)); + } const diff = await Effect.runPromise(readGitDiff(dir, 'uncommitted')); expect(diff.truncated).toBe(true); diff --git a/packages/host/engine/tests/integration/git-mutations.test.ts b/packages/host/engine/tests/integration/git-mutations.test.ts index 95067fc98..0de7cf756 100644 --- a/packages/host/engine/tests/integration/git-mutations.test.ts +++ b/packages/host/engine/tests/integration/git-mutations.test.ts @@ -30,7 +30,11 @@ function makeRepo(): string { } afterEach(() => { - for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true }); + const drained = roots.splice(0); + for (let i = 0, len = drained.length; i < len; i++) { + const root = drained[i]; + rmSync(root, { recursive: true, force: true }); + } }); describe('git mutations', () => { diff --git a/packages/host/engine/tests/integration/git-status.test.ts b/packages/host/engine/tests/integration/git-status.test.ts index 49c5983f9..c21774c2e 100644 --- a/packages/host/engine/tests/integration/git-status.test.ts +++ b/packages/host/engine/tests/integration/git-status.test.ts @@ -80,7 +80,10 @@ afterAll(() => { else process.env.GIT_CONFIG_GLOBAL = previousGitConfigGlobal; if (previousGitConfigNoSystem === undefined) delete process.env.GIT_CONFIG_NOSYSTEM; else process.env.GIT_CONFIG_NOSYSTEM = previousGitConfigNoSystem; - for (const dir of roots) rmSync(dir, { recursive: true, force: true }); + for (let i = 0, len = roots.length; i < len; i++) { + const dir = roots[i]; + rmSync(dir, { recursive: true, force: true }); + } }); describe('readGitStatus', () => { diff --git a/packages/host/engine/tests/integration/worktree-service.test.ts b/packages/host/engine/tests/integration/worktree-service.test.ts index 177451e05..1921b3764 100644 --- a/packages/host/engine/tests/integration/worktree-service.test.ts +++ b/packages/host/engine/tests/integration/worktree-service.test.ts @@ -59,7 +59,11 @@ async function managedWorktree(store: WorktreeStore = new InMemoryWorktreeStore( } afterEach(() => { - for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true }); + const drained = roots.splice(0); + for (let i = 0, len = drained.length; i < len; i++) { + const root = drained[i]; + rmSync(root, { recursive: true, force: true }); + } }); describe('WorktreeService', () => { diff --git a/packages/host/sim/package.json b/packages/host/sim/package.json index f7faa1e67..48f57b16d 100644 --- a/packages/host/sim/package.json +++ b/packages/host/sim/package.json @@ -12,7 +12,7 @@ "lint": "eslint --format=sukka ." }, "dependencies": { - "foxts": "^5.8.0", + "foxts": "^5.9.1", "zod": "catalog:" }, "devDependencies": { diff --git a/packages/host/sim/src/__tests__/codec.test.ts b/packages/host/sim/src/__tests__/codec.test.ts index a79ad4cac..61c9faef7 100644 --- a/packages/host/sim/src/__tests__/codec.test.ts +++ b/packages/host/sim/src/__tests__/codec.test.ts @@ -24,7 +24,11 @@ describe('FrameDecoder', () => { ]); const frames = []; for (const byte of encoded) { - for (const decoded of decoder.feed(Buffer.from([byte]))) frames.push(decoded); + const fed = decoder.feed(Buffer.from([byte])); + for (let i = 0, len = fed.length; i < len; i++) { + const decoded = fed[i]; + frames.push(decoded); + } } expect(frames.map((f) => f.body.toString())).toEqual(['{"a":1}', '{"b":2}']); }); diff --git a/packages/host/sim/src/client.ts b/packages/host/sim/src/client.ts index 27cfddda0..96cbc6d41 100644 --- a/packages/host/sim/src/client.ts +++ b/packages/host/sim/src/client.ts @@ -331,7 +331,11 @@ export class SimSidecarClient { child.stdout.on('data', (chunk: Buffer) => { if (this.child !== child) return; try { - for (const frame of this.decoder.feed(chunk)) this.handleFrame(frame); + const decodedFrames = this.decoder.feed(chunk); + for (let i = 0, len = decodedFrames.length; i < len; i++) { + const frame = decodedFrames[i]; + this.handleFrame(frame); + } } catch { // A corrupt stream cannot be resynchronized mid-flight; drop the child and start over. child.kill(); diff --git a/packages/integrations/im-render/package.json b/packages/integrations/im-render/package.json index 79c3a94ad..f4ac0b94d 100644 --- a/packages/integrations/im-render/package.json +++ b/packages/integrations/im-render/package.json @@ -16,7 +16,7 @@ "@linkcode/client-core": "workspace:*", "@linkcode/schema": "workspace:*", "diff": "^9.0.0", - "foxts": "^5.8.0" + "foxts": "^5.9.1" }, "devDependencies": { "typescript": "catalog:" diff --git a/packages/integrations/im-render/src/blocks.ts b/packages/integrations/im-render/src/blocks.ts index 19fd0e044..f6c4caa0c 100644 --- a/packages/integrations/im-render/src/blocks.ts +++ b/packages/integrations/im-render/src/blocks.ts @@ -28,7 +28,8 @@ export function contentBlockToMarkdown(block: ContentBlock): string { export function contentToMarkdown(blocks: readonly ContentBlock[]): string { const parts: string[] = []; - for (const block of blocks) { + for (let i = 0, len = blocks.length; i < len; i++) { + const block = blocks[i]; const text = contentBlockToMarkdown(block); if (text.length > 0) parts.push(text); } diff --git a/packages/integrations/im-render/src/render.ts b/packages/integrations/im-render/src/render.ts index f45e2d20c..8d2830dcb 100644 --- a/packages/integrations/im-render/src/render.ts +++ b/packages/integrations/im-render/src/render.ts @@ -90,7 +90,8 @@ function toolContentMarkdown(content: ToolCallContent, opts: RenderOptions): str export function toolCallMarkdown(toolCall: ToolCall, opts: RenderOptions = {}): string { const parts = [`${TOOL_STATUS_ICON[toolCall.status]} *${toolCall.title || toolCall.kind}*`]; - for (const content of toolCall.content) { + for (let i = 0, len = toolCall.content.length; i < len; i++) { + const content = toolCall.content[i]; const text = toolContentMarkdown(content, opts); if (text.length > 0) parts.push(text); } @@ -121,7 +122,8 @@ export function permissionMarkdown( /** The agent's structured ask (AskUserQuestion): each question with its options as bullets. */ export function questionMarkdown(questions: readonly Question[]): string { const parts: string[] = ['❓ **Question**']; - for (const question of questions) { + for (let i = 0, len = questions.length; i < len; i++) { + const question = questions[i]; parts.push(question.prompt); appendArrayInPlace( parts, @@ -164,7 +166,8 @@ export function renderTurns( opts: RenderOptions = {}, ): RenderedTurn[] { const turns: RenderedTurn[] = []; - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; let turn = turns.at(-1); if (turn?.turnId !== item.turnId) { turn = { turnId: item.turnId, userMarkdown: null, agentMarkdown: '', items: [] }; @@ -190,7 +193,9 @@ export function renderConversation( opts: RenderOptions = {}, ): string { const parts: string[] = []; - for (const turn of renderTurns(items, opts)) { + const rendered = renderTurns(items, opts); + for (let i = 0, len = rendered.length; i < len; i++) { + const turn = rendered[i]; if (turn.userMarkdown !== null) parts.push(`👤 ${turn.userMarkdown}`); if (turn.agentMarkdown.length > 0) parts.push(turn.agentMarkdown); } diff --git a/packages/presentation/i18n/src/index.ts b/packages/presentation/i18n/src/index.ts index db2b5a2d8..a00ad50c2 100644 --- a/packages/presentation/i18n/src/index.ts +++ b/packages/presentation/i18n/src/index.ts @@ -19,7 +19,8 @@ export function getMessages(locale: Locale): Messages { export function resolveLocale(input: string | readonly string[] | undefined): Locale { const candidates = typeof input === 'string' ? [input] : (input ?? []); - for (const candidate of candidates) { + for (let i = 0, len = candidates.length; i < len; i++) { + const candidate = candidates[i]; const normalized = normalizeLocale(candidate); if (normalized) return normalized; } diff --git a/packages/presentation/ui/package.json b/packages/presentation/ui/package.json index ac7741434..56fd3476b 100644 --- a/packages/presentation/ui/package.json +++ b/packages/presentation/ui/package.json @@ -45,8 +45,8 @@ "clsx": "^2.1.1", "coss-ui": "workspace:*", "dompurify": "^3.4.12", - "foxact": "^0.3.8", - "foxts": "^5.8.0", + "foxact": "^0.3.10", + "foxts": "^5.9.1", "lexical": "^0.48.0", "lucide-react": "^1.25.0", "mermaid": "^11.16.0", diff --git a/packages/presentation/ui/src/__tests__/conversation-view-perf.bench.ts b/packages/presentation/ui/src/__tests__/conversation-view-perf.bench.ts index 48bbf52c1..b517ba212 100644 --- a/packages/presentation/ui/src/__tests__/conversation-view-perf.bench.ts +++ b/packages/presentation/ui/src/__tests__/conversation-view-perf.bench.ts @@ -183,7 +183,7 @@ function conversationViewPipeline(conversation: ConversationViewModel): number { const allSubagentChildren = partitionSubagentItems(items).childrenByParent; let entryCount = 0; - for (let index = 0; index < segments.length; index += 1) { + for (let index = 0, len = segments.length; index < len; index += 1) { const segment = segments[index]; const ended = index < segments.length - 1 || !isThinking; const { topLevel } = partitionSubagentItems(segment.items); diff --git a/packages/presentation/ui/src/__tests__/conversation-view-perf.report.test.ts b/packages/presentation/ui/src/__tests__/conversation-view-perf.report.test.ts index 8aa370578..95a33ae32 100644 --- a/packages/presentation/ui/src/__tests__/conversation-view-perf.report.test.ts +++ b/packages/presentation/ui/src/__tests__/conversation-view-perf.report.test.ts @@ -181,7 +181,7 @@ function conversationViewPipeline(conversation: ConversationViewModel): number { ); const segments = splitTurnSegments(conversationFlowItems(items)); let entryCount = 0; - for (let index = 0; index < segments.length; index += 1) { + for (let index = 0, len = segments.length; index < len; index += 1) { const segment = segments[index]; const ended = index < segments.length - 1 || !isThinking; const { topLevel } = partitionSubagentItems(segment.items); @@ -198,7 +198,8 @@ function conversationViewPipelineNoEdits(conversation: ConversationViewModel): n declinedToolCallIds(items); const segments = splitTurnSegments(conversationFlowItems(items)); let entryCount = 0; - for (const segment of segments) { + for (let i = 0, len = segments.length; i < len; i++) { + const segment = segments[i]; const { topLevel } = partitionSubagentItems(segment.items); entryCount += groupTimeline(topLevel).length + (assistantTurnText(topLevel) ? 1 : 0); } @@ -207,7 +208,8 @@ function conversationViewPipelineNoEdits(conversation: ConversationViewModel): n function allEditDiffStats(conversation: ConversationViewModel): number { let total = 0; - for (const item of conversation.items) { + for (let i = 0, len = conversation.items.length; i < len; i++) { + const item = conversation.items[i]; if (item.kind !== 'tool' || item.toolCall.kind !== 'edit') continue; const stats = toolCallDiffStats(item.toolCall); total += stats.additions + stats.deletions; diff --git a/packages/presentation/ui/src/__tests__/session-sidebar.test.ts b/packages/presentation/ui/src/__tests__/session-sidebar.test.ts index 324fae44a..ea0ad8c9d 100644 --- a/packages/presentation/ui/src/__tests__/session-sidebar.test.ts +++ b/packages/presentation/ui/src/__tests__/session-sidebar.test.ts @@ -4,7 +4,7 @@ import { relativeTimeLabel } from '../shell/relative-time'; describe('repositoryLabel', () => { it('uses the final path segment for POSIX and Windows repository labels', () => { - const backslash = String.fromCodePoint(92); + const backslash = String.fromCharCode(92); const windowsAppPath = ['C:', 'repo', 'app'].join(backslash); const windowsAppPathWithTrailingSeparator = `${windowsAppPath}${backslash}`; const windowsRoot = `C:${backslash}`; diff --git a/packages/presentation/ui/src/chat/__tests__/activity-run.test.tsx b/packages/presentation/ui/src/chat/__tests__/activity-run.test.tsx index 21dac32dc..1bbd64252 100644 --- a/packages/presentation/ui/src/chat/__tests__/activity-run.test.tsx +++ b/packages/presentation/ui/src/chat/__tests__/activity-run.test.tsx @@ -467,7 +467,9 @@ describe('ActivityRun', () => { 'Made 2 file changes', 'Explored once', ]; - for (const label of ['An action failed', ...regularLabels]) { + const allLabels = ['An action failed', ...regularLabels]; + for (let i = 0, len = allLabels.length; i < len; i++) { + const label = allLabels[i]; expect(header.textContent.split(label)).toHaveLength(2); } const failureClause = within(header).getByText(RE_FAILURE); @@ -475,7 +477,8 @@ describe('ActivityRun', () => { expect(failureClause.className).toContain('font-medium'); expect(failureClause.className).toContain('opacity-100'); const regularClauses = regularLabels.map((label) => within(header).getByText(`· ${label}`)); - for (const clause of regularClauses) { + for (let i = 0, len = regularClauses.length; i < len; i++) { + const clause = regularClauses[i]; expect(clause.className).toContain('font-medium'); expect(clause.className).toContain('opacity-80'); expect(clause.className).not.toContain('text-label-tertiary'); @@ -488,14 +491,16 @@ describe('ActivityRun', () => { expect(header.querySelector('svg.lucide-circle-x')).toBeNull(); // A settled abstract never shimmers. expect(header.querySelector('.bg-clip-text')).toBeNull(); - for (const detail of [ + const hiddenDetails = [ 'first.ts', 'second.ts', 'Linear', 'git status', 'README.md', 'Reviewed the results', - ]) { + ]; + for (let i = 0, len = hiddenDetails.length; i < len; i++) { + const detail = hiddenDetails[i]; expect(header.textContent).not.toContain(detail); expect(header.getAttribute('aria-label')).not.toContain(detail); } diff --git a/packages/presentation/ui/src/chat/__tests__/card-radius.test.tsx b/packages/presentation/ui/src/chat/__tests__/card-radius.test.tsx index a7392ae18..f1feaafaf 100644 --- a/packages/presentation/ui/src/chat/__tests__/card-radius.test.tsx +++ b/packages/presentation/ui/src/chat/__tests__/card-radius.test.tsx @@ -101,7 +101,9 @@ describe('Chat card chrome contract', () => { , ); - for (const testId of ['commit', 'stack-trace', 'step']) { + const roundedTestIds = ['commit', 'stack-trace', 'step']; + for (let i = 0, len = roundedTestIds.length; i < len; i++) { + const testId = roundedTestIds[i]; expect(screen.getByTestId(testId).classList.contains('rounded-2xl')).toBe(true); } diff --git a/packages/presentation/ui/src/chat/__tests__/file-preview-card.test.tsx b/packages/presentation/ui/src/chat/__tests__/file-preview-card.test.tsx index 2683ea39e..78239bfce 100644 --- a/packages/presentation/ui/src/chat/__tests__/file-preview-card.test.tsx +++ b/packages/presentation/ui/src/chat/__tests__/file-preview-card.test.tsx @@ -15,10 +15,12 @@ vi.mock('use-intl', () => ({ useTranslations: () => translateKey })); /** jsdom lays nothing out, so both metrics read 0 and the card can never look overflowing. * Stub the pair the overflow check reads to drive each branch deterministically. */ function stubPanelMetrics(scrollHeight: number, clientHeight: number): void { - for (const [name, value] of [ + const metrics = [ ['scrollHeight', scrollHeight], ['clientHeight', clientHeight], - ] as const) { + ] as const; + for (let i = 0, len = metrics.length; i < len; i++) { + const [name, value] = metrics[i]; vi.spyOn(HTMLElement.prototype, name, 'get').mockReturnValue(value); } } diff --git a/packages/presentation/ui/src/chat/__tests__/link-icon.test.tsx b/packages/presentation/ui/src/chat/__tests__/link-icon.test.tsx index 8e479ce7a..1ecb1e73c 100644 --- a/packages/presentation/ui/src/chat/__tests__/link-icon.test.tsx +++ b/packages/presentation/ui/src/chat/__tests__/link-icon.test.tsx @@ -18,7 +18,8 @@ it('loads the destination and Google favicon concurrently with a local fallback' 'https://internal.example.test/favicon.ico', 'https://www.google.com/s2/favicons?domain=https%3A%2F%2Finternal.example.test&sz=32', ]); - for (const image of images) { + for (let i = 0, len = images.length; i < len; i++) { + const image = images[i]; expect(image.getAttribute('alt')).toBe(''); expect(image.getAttribute('decoding')).toBe('async'); expect(image.getAttribute('draggable')).toBe('false'); @@ -51,7 +52,9 @@ it('resets the favicon when the url changes', () => { rerender(); expect(container.querySelector('svg')).not.toBeNull(); - expect([...container.querySelectorAll('img')].map((image) => image.getAttribute('src'))).toEqual([ + expect( + Array.from(container.querySelectorAll('img'), (image) => image.getAttribute('src')), + ).toEqual([ 'https://second.example/favicon.ico', 'https://www.google.com/s2/favicons?domain=https%3A%2F%2Fsecond.example&sz=32', ]); diff --git a/packages/presentation/ui/src/chat/__tests__/markdown.test.tsx b/packages/presentation/ui/src/chat/__tests__/markdown.test.tsx index 6df4d012c..0d440b328 100644 --- a/packages/presentation/ui/src/chat/__tests__/markdown.test.tsx +++ b/packages/presentation/ui/src/chat/__tests__/markdown.test.tsx @@ -313,7 +313,7 @@ it('chips source-file inline code while prose-shaped tokens stay code', () => { ); fireEvent.click(getByRole('button', { name: 'src/main.rs:7' })); expect(openFile).toHaveBeenCalledWith('src/main.rs'); - const codeTexts = [...container.querySelectorAll('code')].map((el) => el.textContent); + const codeTexts = Array.from(container.querySelectorAll('code'), (el) => el.textContent); expect(codeTexts).toEqual(['origin/main', 'foo.bar']); }); diff --git a/packages/presentation/ui/src/chat/__tests__/minimap-geometry.test.ts b/packages/presentation/ui/src/chat/__tests__/minimap-geometry.test.ts index e92bdd280..6cfe8c188 100644 --- a/packages/presentation/ui/src/chat/__tests__/minimap-geometry.test.ts +++ b/packages/presentation/ui/src/chat/__tests__/minimap-geometry.test.ts @@ -25,7 +25,9 @@ describe('fisheyeFactor', () => { it('decreases monotonically across the falloff', () => { const step = MINIMAP_FISHEYE_SPREAD / 6; const samples = createFixedArray(7).map((_, i) => fisheyeFactor(i * step)); - for (let i = 1; i < samples.length; i++) expect(samples[i]).toBeLessThan(samples[i - 1]); + for (let i = 1, len = samples.length; i < len; i++) { + expect(samples[i]).toBeLessThan(samples[i - 1]); + } }); it('eases out — the near half of the falloff keeps most of the magnification', () => { diff --git a/packages/presentation/ui/src/chat/__tests__/smooth-text-controller.test.ts b/packages/presentation/ui/src/chat/__tests__/smooth-text-controller.test.ts index 120aca908..97455cd5d 100644 --- a/packages/presentation/ui/src/chat/__tests__/smooth-text-controller.test.ts +++ b/packages/presentation/ui/src/chat/__tests__/smooth-text-controller.test.ts @@ -59,11 +59,13 @@ describe('smooth text controller', () => { expect(state.visible).toBe(source); expect(seen.every((visible) => source.startsWith(visible))).toBe(true); - for (const [initial, nextSource, firstStep] of [ + const graphemeCases = [ ['👨', '👨\u{200D}👩x', '👨\u{200D}👩'], ['🇺', '🇺🇸x', '🇺🇸'], ['e', 'éx', 'é'], - ]) { + ]; + for (let i = 0, len = graphemeCases.length; i < len; i++) { + const [initial, nextSource, firstStep] = graphemeCases[i]; const joined = reconcileSmoothText(createSmoothTextState(initial, false), nextSource, false); expect(advanceSmoothText(joined).visible).toBe(firstStep); } diff --git a/packages/presentation/ui/src/chat/__tests__/turn-diff-summary.test.tsx b/packages/presentation/ui/src/chat/__tests__/turn-diff-summary.test.tsx index 3d62bf6f1..d6a72d49a 100644 --- a/packages/presentation/ui/src/chat/__tests__/turn-diff-summary.test.tsx +++ b/packages/presentation/ui/src/chat/__tests__/turn-diff-summary.test.tsx @@ -47,8 +47,10 @@ describe('TurnDiffSummary', () => { ); expect(fileButtons).toHaveLength(FILES.length); // user-event queues pointer interactions, so these clicks must stay serial. - // eslint-disable-next-line no-await-in-loop -- preserve interaction ordering - for (const button of fileButtons) await user.click(button); + for (let i = 0, len = fileButtons.length; i < len; i++) { + // eslint-disable-next-line no-await-in-loop -- preserve interaction ordering + await user.click(fileButtons[i]); + } await user.click(screen.getByRole('button', { name: 'review' })); expect(openFile.mock.calls).toEqual(FILES.map((file) => [file.path])); diff --git a/packages/presentation/ui/src/chat/activity-groups.ts b/packages/presentation/ui/src/chat/activity-groups.ts index 405a95c08..aa10c1c1c 100644 --- a/packages/presentation/ui/src/chat/activity-groups.ts +++ b/packages/presentation/ui/src/chat/activity-groups.ts @@ -54,7 +54,8 @@ export function groupTimeline( ): TimelineEntry[] { // Policies may preserve approval-gated tools as standalone interaction points. const approvalGated = new Set(); - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; if (item.kind === 'approval') approvalGated.add(item.toolCall.toolCallId); } @@ -76,7 +77,8 @@ export function groupTimeline( runKey = null; }; - for (const [index, item] of items.entries()) { + for (let index = 0, len = items.length; index < len; index++) { + const item = items[index]; const key = policy.classify(item, { index, timeline: items, diff --git a/packages/presentation/ui/src/chat/activity-run.tsx b/packages/presentation/ui/src/chat/activity-run.tsx index 5b1853365..55a49a08d 100644 --- a/packages/presentation/ui/src/chat/activity-run.tsx +++ b/packages/presentation/ui/src/chat/activity-run.tsx @@ -243,7 +243,8 @@ function ActivityRunIcon({ function primarySettledCategory( clauses: readonly ActivitySummaryClause[], ): SettledActivityCategory | undefined { - for (const clause of clauses) { + for (let i = 0, len = clauses.length; i < len; i++) { + const clause = clauses[i]; if (clause.category !== 'failure') return clause.category; } return undefined; diff --git a/packages/presentation/ui/src/chat/activity-summary.ts b/packages/presentation/ui/src/chat/activity-summary.ts index 9ebe08dd4..8418da899 100644 --- a/packages/presentation/ui/src/chat/activity-summary.ts +++ b/packages/presentation/ui/src/chat/activity-summary.ts @@ -73,7 +73,8 @@ export function settledActivityRunDescriptor( let failureCount = 0; let hasThinking = false; - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; if (item.kind === 'tool' && item.toolCall.status === 'failed') failureCount += 1; const category = activityCategory(item); if (category === 'thinking') { @@ -85,7 +86,8 @@ export function settledActivityRunDescriptor( const clauses: ActivitySummaryClause[] = []; if (failureCount > 0) clauses.push({ category: 'failure', count: failureCount }); - for (const category of SETTLED_CATEGORY_PRIORITY) { + for (let i = 0, len = SETTLED_CATEGORY_PRIORITY.length; i < len; i++) { + const category = SETTLED_CATEGORY_PRIORITY[i]; const count = categoryCounts.get(category); if (count !== undefined) clauses.push({ category, count }); } @@ -119,7 +121,8 @@ export function activityRunBrand(items: readonly ActivityRunItem[]): Integration } let single: IntegrationBrand | undefined; - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; const brand = activityItemBrand(item); if (!brand) continue; if (single !== undefined && single !== brand) return undefined; diff --git a/packages/presentation/ui/src/chat/artifacts/__tests__/element-label.test.ts b/packages/presentation/ui/src/chat/artifacts/__tests__/element-label.test.ts index a471c7d81..ea6554ecf 100644 --- a/packages/presentation/ui/src/chat/artifacts/__tests__/element-label.test.ts +++ b/packages/presentation/ui/src/chat/artifacts/__tests__/element-label.test.ts @@ -22,7 +22,8 @@ class FakeElement implements DiagramElement { this.attrs = attrs; this.text = text ?? null; this.childElements = children.map((child) => new FakeElement(child)); - for (const [i, child] of this.childElements.entries()) { + for (let i = 0, len = this.childElements.length; i < len; i++) { + const child = this.childElements[i]; child.parentElement = this; child.nextElementSibling = this.childElements[i + 1] ?? null; } diff --git a/packages/presentation/ui/src/chat/artifacts/registry.ts b/packages/presentation/ui/src/chat/artifacts/registry.ts index 3b9b648a0..33354f469 100644 --- a/packages/presentation/ui/src/chat/artifacts/registry.ts +++ b/packages/presentation/ui/src/chat/artifacts/registry.ts @@ -65,7 +65,8 @@ export interface ResolvedInlineArtifact { /** Run detectors over a fence (first match wins). Returns null — degrade to a plain * code block — when nothing matches or the matched kind cannot render inline. */ export function resolveFencedArtifact(block: FencedBlock): ResolvedInlineArtifact | null { - for (const detector of detectors) { + for (let i = 0, len = detectors.length; i < len; i++) { + const detector = detectors[i]; const artifact = detector.detectFence(block); if (!artifact) continue; const definition = kinds.get(artifact.kind); diff --git a/packages/presentation/ui/src/chat/attachments.tsx b/packages/presentation/ui/src/chat/attachments.tsx index b97f328c2..5eedd4b06 100644 --- a/packages/presentation/ui/src/chat/attachments.tsx +++ b/packages/presentation/ui/src/chat/attachments.tsx @@ -3,6 +3,7 @@ import { Button } from 'coss-ui/components/button'; import { Card } from 'coss-ui/components/card'; import { Spinner } from 'coss-ui/components/spinner'; import { Tooltip, TooltipContent, TooltipTrigger } from 'coss-ui/components/tooltip'; +import { split1st } from 'foxts/split-nth'; import { AlertCircleIcon, FileImageIcon, XIcon } from 'lucide-react'; import { cn } from '../lib/cn'; import type { FileIconComponent } from '../lib/file-icon'; @@ -246,6 +247,7 @@ function attachmentExtensionLabel(attachment: ChatAttachment): string { if (dot > 0 && dot < attachment.name.length - 1) { return attachment.name.slice(dot + 1).toUpperCase(); } - const mimeSubtype = attachment.mimeType?.split('/', 2)[1]; + const mimeSubtype = + attachment.mimeType === undefined ? undefined : split1st(attachment.mimeType, '/'); return (mimeSubtype ?? attachment.kind).toUpperCase(); } diff --git a/packages/presentation/ui/src/chat/code-language.ts b/packages/presentation/ui/src/chat/code-language.ts index a06db24ab..eac11ed8a 100644 --- a/packages/presentation/ui/src/chat/code-language.ts +++ b/packages/presentation/ui/src/chat/code-language.ts @@ -1,3 +1,4 @@ +import { split0th } from 'foxts/split-nth'; import { fileExtension } from './artifacts/file-kind'; const LANGUAGE_BY_MIME_TYPE: Readonly> = { @@ -23,7 +24,8 @@ const RE_URI_SUFFIX = /[?#]/; /** Best-effort language hint for an embedded text resource. MIME wins because URIs may be opaque. */ export function codeLanguageForResource(uri: string, mimeType?: string): string | undefined { - const normalizedMime = mimeType?.split(';', 1)[0]?.trim().toLowerCase(); + const normalizedMime = + mimeType === undefined ? undefined : split0th(mimeType, ';').trim().toLowerCase(); if (normalizedMime) { const mimeLanguage = LANGUAGE_BY_MIME_TYPE[normalizedMime]; if (mimeLanguage) return mimeLanguage; diff --git a/packages/presentation/ui/src/chat/command-catalog.ts b/packages/presentation/ui/src/chat/command-catalog.ts index f7277654c..548283893 100644 --- a/packages/presentation/ui/src/chat/command-catalog.ts +++ b/packages/presentation/ui/src/chat/command-catalog.ts @@ -9,8 +9,11 @@ export function buildCommandLookup( commands: readonly AgentCommand[], ): ReadonlyMap { const lookup = new Map(); - for (const command of commands) { - for (const name of [command.name, ...(command.aliases ?? [])]) { + for (let i = 0, len = commands.length; i < len; i++) { + const command = commands[i]; + const names = [command.name, ...(command.aliases ?? [])]; + for (let j = 0, nameCount = names.length; j < nameCount; j++) { + const name = names[j]; if (!lookup.has(name)) lookup.set(name, command); } } diff --git a/packages/presentation/ui/src/chat/content-block-view.tsx b/packages/presentation/ui/src/chat/content-block-view.tsx index 8996f493a..477e91f50 100644 --- a/packages/presentation/ui/src/chat/content-block-view.tsx +++ b/packages/presentation/ui/src/chat/content-block-view.tsx @@ -1,4 +1,5 @@ import type { ContentBlock } from '@linkcode/schema'; +import { split0th } from 'foxts/split-nth'; import { useTranslations } from 'use-intl'; import { fileBasename } from './artifacts/file-kind'; import { codeLanguageForResource } from './code-language'; @@ -9,7 +10,7 @@ import { linkTargetForUri } from './link-target'; import { Markdown, SmoothMarkdown } from './markdown'; function resourceLabel(uri: string, fallback: string): string { - const visible = uri.split('#', 1)[0]?.split('?', 1)[0] ?? ''; + const visible = split0th(split0th(uri, '#'), '?'); if (visible.endsWith('/')) return fallback; const label = fileBasename(visible); return label && !label.includes(':') ? label : fallback; diff --git a/packages/presentation/ui/src/chat/conversation-minimap.tsx b/packages/presentation/ui/src/chat/conversation-minimap.tsx index ea541004b..cf118b9ad 100644 --- a/packages/presentation/ui/src/chat/conversation-minimap.tsx +++ b/packages/presentation/ui/src/chat/conversation-minimap.tsx @@ -92,7 +92,8 @@ export function useConversationMinimap(count: number): { } function segmentText(segment: TurnSegment, role: 'user' | 'assistant'): string { - for (const item of segment.items) { + for (let i = 0, len = segment.items.length; i < len; i++) { + const item = segment.items[i]; if (item.kind !== 'message' || item.role !== role) continue; const text = item.blocks .map((block) => (block.type === 'text' ? block.text : '')) diff --git a/packages/presentation/ui/src/chat/conversation-prompts.ts b/packages/presentation/ui/src/chat/conversation-prompts.ts index f7d0a69ef..c69ed430a 100644 --- a/packages/presentation/ui/src/chat/conversation-prompts.ts +++ b/packages/presentation/ui/src/chat/conversation-prompts.ts @@ -72,7 +72,8 @@ export function selectPendingPromptItems( /** toolCallIds whose authoritative permission resolution declined the gated action. */ export function declinedToolCallIds(items: readonly ConversationItem[]): Set { const ids = new Set(); - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; if (item.kind !== 'approval') continue; if (!item.resolution) continue; const outcome = item.resolution.outcome; diff --git a/packages/presentation/ui/src/chat/conversation-text.ts b/packages/presentation/ui/src/chat/conversation-text.ts index 89dd508c9..86a99b8bd 100644 --- a/packages/presentation/ui/src/chat/conversation-text.ts +++ b/packages/presentation/ui/src/chat/conversation-text.ts @@ -4,7 +4,8 @@ import type { ConversationItem } from './types'; /** Plain-text projection of content blocks (non-text blocks are skipped). */ export function contentBlocksText(blocks: readonly ContentBlock[]): string { const parts: string[] = []; - for (const block of blocks) { + for (let i = 0, len = blocks.length; i < len; i++) { + const block = blocks[i]; if (block.type === 'text' && block.text) parts.push(block.text); } return parts.join('\n'); @@ -13,7 +14,8 @@ export function contentBlocksText(blocks: readonly ContentBlock[]): string { /** The turn's copyable reply: every assistant message's text, in order. */ export function assistantTurnText(items: readonly ConversationItem[]): string { const parts: string[] = []; - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; if (item.kind !== 'message' || item.role !== 'assistant') continue; const text = contentBlocksText(item.blocks); if (text) parts.push(text); @@ -33,7 +35,8 @@ export function turnModel(items: readonly ConversationItem[]): string | undefine /** Best-known time of the latest-stamped item — the turn's approximate end time. */ export function latestReceivedAt(items: readonly ConversationItem[]): number | undefined { let latest: number | undefined; - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; if (item.receivedAt !== undefined && (latest === undefined || item.receivedAt > latest)) { latest = item.receivedAt; } diff --git a/packages/presentation/ui/src/chat/conversation.tsx b/packages/presentation/ui/src/chat/conversation.tsx index 618124507..967e4f4ed 100644 --- a/packages/presentation/ui/src/chat/conversation.tsx +++ b/packages/presentation/ui/src/chat/conversation.tsx @@ -40,7 +40,7 @@ export interface ConversationContentProps { /** Timeline rows, virtualized: only rows near the viewport are mounted. */ data: readonly T[]; /** Row renderer; must return a keyed element (virtua caches measured sizes per key). */ - // eslint-disable-next-line sukka/react-no-render-function-prop, @typescript-eslint/no-restricted-types -- virtua's windowing contract: only the virtualizer knows which rows are visible, and it requires a keyed ReactElement per row. + // eslint-disable-next-line vibe-proof/react-no-render-function-prop, @typescript-eslint/no-restricted-types -- virtua's windowing contract: only the virtualizer knows which rows are visible, and it requires a keyed ReactElement per row. children: (item: T, index: number) => React.ReactElement; /** Rendered after the virtualized rows, inside the scrolled column (e.g. the thinking row). */ trailing?: React.ReactNode; diff --git a/packages/presentation/ui/src/chat/file-tool-presentation.ts b/packages/presentation/ui/src/chat/file-tool-presentation.ts index 74c50aa32..496f61f45 100644 --- a/packages/presentation/ui/src/chat/file-tool-presentation.ts +++ b/packages/presentation/ui/src/chat/file-tool-presentation.ts @@ -21,7 +21,8 @@ export interface ToolCallFilePresentation { function filePaths(toolCall: ToolCall): string[] { const paths = new Set(toolCall.locations?.map((location) => location.path)); - for (const content of toolCall.content) { + for (let i = 0, len = toolCall.content.length; i < len; i++) { + const content = toolCall.content[i]; if (content.type === 'diff') paths.add(content.path); } const fallback = toolCallFilePath(toolCall); diff --git a/packages/presentation/ui/src/chat/highlighted-code.tsx b/packages/presentation/ui/src/chat/highlighted-code.tsx index 3535a2457..799afc833 100644 --- a/packages/presentation/ui/src/chat/highlighted-code.tsx +++ b/packages/presentation/ui/src/chat/highlighted-code.tsx @@ -100,7 +100,7 @@ export function HighlightedCode({ const plugin = createCodePlugin({ themes: [lightTheme, darkTheme] }); const apply = (result: HighlightResult): void => { if (signal.aborted) return; - // eslint-disable-next-line @eslint-react/set-state-in-effect, sukka/react-no-use-effect-watching -- Shiki resolves through this callback; the abort signal and tagged state reject stale results. + // eslint-disable-next-line @eslint-react/set-state-in-effect, vibe-proof/react-no-use-effect-watching -- Shiki resolves through this callback; the abort signal and tagged state reject stale results. setHighlighted({ code, language: normalizedLanguage, lightTheme, darkTheme, result }); }; const immediate = plugin.highlight( diff --git a/packages/presentation/ui/src/chat/integration-brand.tsx b/packages/presentation/ui/src/chat/integration-brand.tsx index 60c4f479f..5de719afa 100644 --- a/packages/presentation/ui/src/chat/integration-brand.tsx +++ b/packages/presentation/ui/src/chat/integration-brand.tsx @@ -69,7 +69,9 @@ const RE_SERVER_TOKEN_BOUNDARY = /[^a-z0-9]+/; /** MCP server names are user-chosen config keys (`linear`, `claude_ai_Gmail`, opaque ids) — * token-match them against the known brands; no match means no branding. */ export function integrationBrand(server: string): IntegrationBrand | undefined { - for (const token of server.toLowerCase().split(RE_SERVER_TOKEN_BOUNDARY)) { + const tokens = server.toLowerCase().split(RE_SERVER_TOKEN_BOUNDARY); + for (let i = 0, len = tokens.length; i < len; i++) { + const token = tokens[i]; // Own-key check: `in` would also match prototype keys ("constructor" is a valid token). if (Object.hasOwn(INTEGRATION_GLYPHS, token)) return token as IntegrationBrand; } diff --git a/packages/presentation/ui/src/chat/markdown.tsx b/packages/presentation/ui/src/chat/markdown.tsx index db4f8c6a5..ca15fe8dc 100644 --- a/packages/presentation/ui/src/chat/markdown.tsx +++ b/packages/presentation/ui/src/chat/markdown.tsx @@ -390,7 +390,9 @@ function allowMentionLinkProtocols(entry: RehypePlugins[number]): RehypePlugins[ // which would corrupt cwd-relative file mentions into absolute paths for openFile. const defaultRehypePluginValues: RehypePlugins = []; let rawRehypePluginIndex = -1; -for (const [name, entry] of Object.entries(defaultRehypePlugins)) { +const defaultRehypePluginEntries = Object.entries(defaultRehypePlugins); +for (let i = 0, len = defaultRehypePluginEntries.length; i < len; i++) { + const [name, entry] = defaultRehypePluginEntries[i]; if (name === 'harden') continue; if (name === 'raw') rawRehypePluginIndex = defaultRehypePluginValues.length; defaultRehypePluginValues.push(name === 'sanitize' ? allowMentionLinkProtocols(entry) : entry); diff --git a/packages/presentation/ui/src/chat/stack-trace-parser.ts b/packages/presentation/ui/src/chat/stack-trace-parser.ts index 4efec2029..da003b8f2 100644 --- a/packages/presentation/ui/src/chat/stack-trace-parser.ts +++ b/packages/presentation/ui/src/chat/stack-trace-parser.ts @@ -21,7 +21,9 @@ interface ParsedStackLocation { export function parseStackTrace(trace: string): ParsedStackTrace { const lines: string[] = []; - for (const line of trace.split('\n')) { + const rawLines = trace.split('\n'); + for (let i = 0, len = rawLines.length; i < len; i++) { + const line = rawLines[i]; const trimmed = line.trim(); if (trimmed.length > 0) lines.push(trimmed); } @@ -29,7 +31,9 @@ export function parseStackTrace(trace: string): ParsedStackTrace { const firstLine = lines[0]?.trim() ?? ''; const error = parseErrorLine(firstLine); const frames: ParsedStackFrame[] = []; - for (const line of lines.slice(1)) { + const frameLines = lines.slice(1); + for (let i = 0, len = frameLines.length; i < len; i++) { + const line = frameLines[i]; if (line.startsWith('at ')) frames.push(parseStackFrame(line)); } diff --git a/packages/presentation/ui/src/chat/subagent-viewer.tsx b/packages/presentation/ui/src/chat/subagent-viewer.tsx index e56f4d334..5f5900284 100644 --- a/packages/presentation/ui/src/chat/subagent-viewer.tsx +++ b/packages/presentation/ui/src/chat/subagent-viewer.tsx @@ -42,7 +42,7 @@ export function SubagentViewer({ }: SubagentViewerProps): React.ReactNode { const t = useTranslations('workbench.subagent'); - // eslint-disable-next-line sukka/react-no-performance-impacting-array-find -- a conversation holds a handful of subagents at most; a lookup Map would outweigh the scan + // eslint-disable-next-line vibe-proof/react-no-performance-impacting-array-find -- a conversation holds a handful of subagents at most; a lookup Map would outweigh the scan const selected = tasks.find((task) => task.toolCall.toolCallId === selectedId) ?? tasks.at(0); return ( diff --git a/packages/presentation/ui/src/chat/subagents.ts b/packages/presentation/ui/src/chat/subagents.ts index 8f4a29e65..36239c243 100644 --- a/packages/presentation/ui/src/chat/subagents.ts +++ b/packages/presentation/ui/src/chat/subagents.ts @@ -16,7 +16,8 @@ function itemParentId(item: ConversationItem): string | undefined { export function partitionSubagentItems(items: readonly ConversationItem[]): SubagentPartition { const taskIds = new Set(); - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; if (item.kind === 'tool' && item.toolCall.kind === 'task') { taskIds.add(item.toolCall.toolCallId); } @@ -24,7 +25,8 @@ export function partitionSubagentItems(items: readonly ConversationItem[]): Suba const topLevel: ConversationItem[] = []; const childrenByParent = new Map(); - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; const parent = itemParentId(item); if (parent === undefined || !taskIds.has(parent)) { topLevel.push(item); diff --git a/packages/presentation/ui/src/chat/tool-result-content.ts b/packages/presentation/ui/src/chat/tool-result-content.ts index 0ef93ced5..0e6616fae 100644 --- a/packages/presentation/ui/src/chat/tool-result-content.ts +++ b/packages/presentation/ui/src/chat/tool-result-content.ts @@ -15,7 +15,8 @@ export function stringValue( keys: readonly string[], ): string | undefined { if (!record) return undefined; - for (const key of keys) { + for (let i = 0, len = keys.length; i < len; i++) { + const key = keys[i]; const value = record[key]; if (typeof value === 'string' && value.length > 0) return value; } @@ -147,7 +148,7 @@ export function toolCallReadPreviewText(toolCall: ToolCall, text: string): strin prefixEnd += 1; } - if (prefixEnd === cursor || numberedText.codePointAt(prefixEnd) !== 9) return text; + if (prefixEnd === cursor || numberedText.charCodeAt(prefixEnd) !== 9) return text; const lineNumber = Number.parseInt(numberedText.slice(cursor, prefixEnd), 10); if (lineNumber !== expectedLine || !Number.isSafeInteger(lineNumber) || lineNumber < 1) { return text; diff --git a/packages/presentation/ui/src/chat/turn-edits.ts b/packages/presentation/ui/src/chat/turn-edits.ts index 53e0b1031..e87a6c65c 100644 --- a/packages/presentation/ui/src/chat/turn-edits.ts +++ b/packages/presentation/ui/src/chat/turn-edits.ts @@ -11,7 +11,8 @@ export function splitTurnSegments( items: readonly T[], ): Array> { const segments: Array> = []; - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; const current = segments.at(-1); // turnId is string | null, never undefined, so a match proves `current` exists. if (current?.turnId === item.turnId) current.items.push(item); @@ -43,7 +44,8 @@ export function advanceTurnSegments( const reused: Array> = []; let covered = 0; - for (const segment of prev.segments) { + for (let i = 0, len = prev.segments.length; i < len; i++) { + const segment = prev.segments[i]; if (covered + segment.items.length > stable) break; reused.push(segment); covered += segment.items.length; @@ -76,9 +78,12 @@ export interface TurnEdits { * or declined edit never landed). Null when the turn edited nothing. */ export function turnFileEdits(items: readonly ConversationItem[]): TurnEdits | null { const byPath = new Map(); - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; if (item.kind !== 'tool' || item.toolCall.status !== 'completed') continue; - for (const content of item.toolCall.content) { + const contents = item.toolCall.content; + for (let j = 0, contentCount = contents.length; j < contentCount; j++) { + const content = contents[j]; if (content.type !== 'diff') continue; const stats = diffContentStats(content); const edit = byPath.get(content.path) ?? { path: content.path, additions: 0, deletions: 0 }; diff --git a/packages/presentation/ui/src/chat/use-timeline-model.ts b/packages/presentation/ui/src/chat/use-timeline-model.ts index 6ed27c190..8a621a1c2 100644 --- a/packages/presentation/ui/src/chat/use-timeline-model.ts +++ b/packages/presentation/ui/src/chat/use-timeline-model.ts @@ -75,13 +75,16 @@ function advanceTimeline( const snapshotted = new Set(); const questions = new Map(); - for (const item of items) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i]; if (item.kind === 'tool') snapshotted.add(item.toolCall.toolCallId); if (item.kind === 'question') questions.set(item.toolCall.toolCallId, item); } const awaiting = new Set(); const answering = new Set(); - for (const item of selectPendingPromptItems(conversation)) { + const pendingPromptItems = selectPendingPromptItems(conversation); + for (let i = 0, len = pendingPromptItems.length; i < len; i++) { + const item = pendingPromptItems[i]; if (item.kind === 'approval') awaiting.add(item.toolCall.toolCallId); if (item.kind === 'question') answering.add(item.toolCall.toolCallId); } diff --git a/packages/presentation/ui/src/diff-utils.ts b/packages/presentation/ui/src/diff-utils.ts index f160d7d41..0ab4feca3 100644 --- a/packages/presentation/ui/src/diff-utils.ts +++ b/packages/presentation/ui/src/diff-utils.ts @@ -76,7 +76,9 @@ export function diffLines(oldStr: string, newStr: string): DiffRow[] { export function patchLines(patch: string): DiffRow[] { const rows: DiffRow[] = []; let inHunk = false; - for (const line of patch.split('\n')) { + const patchLineTexts = patch.split('\n'); + for (let i = 0, len = patchLineTexts.length; i < len; i++) { + const line = patchLineTexts[i]; if (line.startsWith('@@')) { inHunk = true; continue; @@ -135,7 +137,8 @@ export function diffContentStats(content: DiffToolCallContent): DiffStats { export function toolCallDiffStats(toolCall: Pick): DiffStats { let additions = 0; let deletions = 0; - for (const content of toolCall.content) { + for (let i = 0, len = toolCall.content.length; i < len; i++) { + const content = toolCall.content[i]; if (content.type !== 'diff') continue; const stats = diffContentStats(content); additions += stats.additions; diff --git a/packages/presentation/ui/src/keyboard/__tests__/registry.test.ts b/packages/presentation/ui/src/keyboard/__tests__/registry.test.ts index 2f399d62b..c520b5522 100644 --- a/packages/presentation/ui/src/keyboard/__tests__/registry.test.ts +++ b/packages/presentation/ui/src/keyboard/__tests__/registry.test.ts @@ -27,7 +27,9 @@ function keydown(overrides: Partial = {}): KeyboardEvent { stopImmediatePropagation: vi.fn(), ...overrides, }; - for (const [key, value] of Object.entries(properties)) { + const propertyEntries = Object.entries(properties); + for (let i = 0, len = propertyEntries.length; i < len; i++) { + const [key, value] = propertyEntries[i]; Object.defineProperty(event, key, { configurable: true, value }); } return event; @@ -182,7 +184,8 @@ describe('keyboard shortcut registry', () => { stopImmediatePropagation, }), ]; - for (const event of events) { + for (let i = 0, len = events.length; i < len; i++) { + const event = events[i]; expect(registry.dispatch(event, true)).toBe(false); } expect(preventDefault).not.toHaveBeenCalled(); @@ -242,7 +245,9 @@ describe('keyboard shortcut registry', () => { registry.setPlatform('mac'); expect(registry.dispatch(keydown({ code: 'KeyJ', metaKey: true }), true)).toBe(false); expect(getOwner).not.toHaveBeenCalled(); - for (currentOwner of [null, owner(false), owner(true, true)]) { + const inactiveOwners = [null, owner(false), owner(true, true)]; + for (let i = 0, len = inactiveOwners.length; i < len; i++) { + currentOwner = inactiveOwners[i]; expect(registry.dispatch(keydown({ code: 'KeyK', metaKey: true }), true)).toBe(false); } const ownerClosest = vi.fn(() => null); diff --git a/packages/presentation/ui/src/keyboard/hooks.ts b/packages/presentation/ui/src/keyboard/hooks.ts index 86a5e847d..4c1940701 100644 --- a/packages/presentation/ui/src/keyboard/hooks.ts +++ b/packages/presentation/ui/src/keyboard/hooks.ts @@ -1,6 +1,7 @@ +import { useEffect } from 'foxact/use-abortable-effect'; import { useLayoutEffect } from 'foxact/use-isomorphic-layout-effect'; import { useStableHandler } from 'foxact/use-stable-handler-only-when-you-know-what-you-are-doing-or-you-will-be-fired'; -import { useEffect, useEffectEvent, useSyncExternalStore } from 'react'; +import { useEffectEvent, useSyncExternalStore } from 'react'; import type { KeyboardPlatform, KeyboardShortcuts } from './registry'; import { createKeyboardShortcutRegistry } from './registry'; @@ -19,19 +20,15 @@ export function setKeyboardShortcutPlatform(platform: KeyboardPlatform): void { } export function useKeyboardShortcutListener(): void { - useEffect(() => { + useEffect((signal) => { const capture = (event: KeyboardEvent): void => { keyboardShortcutRegistry.dispatch(event, true); }; const bubble = (event: KeyboardEvent): void => { keyboardShortcutRegistry.dispatch(event, false); }; - window.addEventListener('keydown', capture, { capture: true }); - window.addEventListener('keydown', bubble); - return () => { - window.removeEventListener('keydown', capture, { capture: true }); - window.removeEventListener('keydown', bubble); - }; + window.addEventListener('keydown', capture, { capture: true, signal }); + window.addEventListener('keydown', bubble, { signal }); }, []); } diff --git a/packages/presentation/ui/src/keyboard/registry.ts b/packages/presentation/ui/src/keyboard/registry.ts index e3e88f9f0..0a68a10b0 100644 --- a/packages/presentation/ui/src/keyboard/registry.ts +++ b/packages/presentation/ui/src/keyboard/registry.ts @@ -65,7 +65,8 @@ function matchesShortcut( shortcuts: readonly KeyboardShortcut[], platform: KeyboardPlatform, ) { - for (const shortcut of shortcuts) { + for (let i = 0, len = shortcuts.length; i < len; i++) { + const shortcut = shortcuts[i]; if (matchesChord(event, chordForPlatform(shortcut, platform), platform)) return true; } return false; @@ -173,7 +174,8 @@ export function createKeyboardShortcutRegistry(warnOnMultipleMatches = IS_DEVELO const refreshLabels = (): void => { const nextLabels = new Map(); if (platform !== undefined) { - for (const registration of registrations) { + for (let i = 0, len = registrations.length; i < len; i++) { + const registration = registrations[i]; nextLabels.set( registration.actionId, formatKeyboardShortcut(registration.shortcut, platform), @@ -249,7 +251,8 @@ export function createKeyboardShortcutRegistry(warnOnMultipleMatches = IS_DEVELO let claimed = false; let matches: string[] | undefined; - for (const registration of registrations) { + for (let i = 0, len = registrations.length; i < len; i++) { + const registration = registrations[i]; if (!isOwnerMatch(registration, event, currentPlatform)) continue; if (warnOnMultipleMatches) (matches ??= []).push(registration.actionId); if (claimed) continue; diff --git a/packages/presentation/ui/src/lib/base-ui.ts b/packages/presentation/ui/src/lib/base-ui.ts index e206c29f2..9be3f1d5d 100644 --- a/packages/presentation/ui/src/lib/base-ui.ts +++ b/packages/presentation/ui/src/lib/base-ui.ts @@ -1,5 +1,3 @@ -import type * as React from 'react'; - /** Suppress Base UI's own handler for this event — e.g. an Autocomplete item press writing the * item's value into the input when the row's `onClick` fully owns the action. */ export function preventBaseUIHandler(event: React.SyntheticEvent): void { diff --git a/packages/presentation/ui/src/lib/file-icon.ts b/packages/presentation/ui/src/lib/file-icon.ts index ca981b3a8..b456ea759 100644 --- a/packages/presentation/ui/src/lib/file-icon.ts +++ b/packages/presentation/ui/src/lib/file-icon.ts @@ -174,7 +174,8 @@ const KNOWN_EXTENSIONS = new Set([ export function hasKnownFileIdentity(name: string): boolean { const basename = fileBasename(name).toLowerCase(); if (iconForFileName(basename) !== undefined) return true; - for (const [compoundExtension] of MATERIAL_COMPOUND_EXTENSION_ENTRIES) { + for (let i = 0, len = MATERIAL_COMPOUND_EXTENSION_ENTRIES.length; i < len; i++) { + const [compoundExtension] = MATERIAL_COMPOUND_EXTENSION_ENTRIES[i]; if (basename.endsWith(`.${compoundExtension}`)) return true; } return KNOWN_EXTENSIONS.has(fileExtension(basename)); @@ -197,7 +198,8 @@ export function fileIconFor({ kind, mimeType, name }: FileIconInput): FileIconCo const fileNameIcon = iconForFileName(basename); if (fileNameIcon) return fileNameIcon; - for (const [compoundExtension, icon] of MATERIAL_COMPOUND_EXTENSION_ENTRIES) { + for (let i = 0, len = MATERIAL_COMPOUND_EXTENSION_ENTRIES.length; i < len; i++) { + const [compoundExtension, icon] = MATERIAL_COMPOUND_EXTENSION_ENTRIES[i]; if (icon && basename.endsWith(`.${compoundExtension}`)) return icon; } @@ -214,7 +216,8 @@ function iconForFileName(basename: string): FileIconComponent | undefined { const materialIcon = MATERIAL_FILE_NAME_ICONS[basename]; if (materialIcon) return materialIcon; - for (const [prefix, icon] of MATERIAL_FILE_NAME_PREFIX_ICONS) { + for (let i = 0, len = MATERIAL_FILE_NAME_PREFIX_ICONS.length; i < len; i++) { + const [prefix, icon] = MATERIAL_FILE_NAME_PREFIX_ICONS[i]; if (basename.startsWith(prefix)) return icon; } diff --git a/packages/presentation/ui/src/shell/__tests__/composer-command-menu.test.tsx b/packages/presentation/ui/src/shell/__tests__/composer-command-menu.test.tsx index b2ae4cb5e..0b9159e76 100644 --- a/packages/presentation/ui/src/shell/__tests__/composer-command-menu.test.tsx +++ b/packages/presentation/ui/src/shell/__tests__/composer-command-menu.test.tsx @@ -191,13 +191,12 @@ describe('Composer command menu', () => { }); const initialActive = editor.getAttribute('aria-activedescendant'); - for (const key of ['ArrowDown', 'ArrowUp']) { - for (const modifier of [ - { altKey: true }, - { ctrlKey: true }, - { metaKey: true }, - { shiftKey: true }, - ]) { + const navigationKeys = ['ArrowDown', 'ArrowUp']; + const modifiers = [{ altKey: true }, { ctrlKey: true }, { metaKey: true }, { shiftKey: true }]; + for (let i = 0, len = navigationKeys.length; i < len; i++) { + const key = navigationKeys[i]; + for (let j = 0, modifierCount = modifiers.length; j < modifierCount; j++) { + const modifier = modifiers[j]; expect(fireEvent.keyDown(editor, { code: key, key, ...modifier })).toBe(true); expect(editor.getAttribute('aria-activedescendant')).toBe(initialActive); } diff --git a/packages/presentation/ui/src/shell/__tests__/composer-directive-chips.test.tsx b/packages/presentation/ui/src/shell/__tests__/composer-directive-chips.test.tsx index 4279814ab..7830e7963 100644 --- a/packages/presentation/ui/src/shell/__tests__/composer-directive-chips.test.tsx +++ b/packages/presentation/ui/src/shell/__tests__/composer-directive-chips.test.tsx @@ -291,10 +291,12 @@ describe('Composer directive chips', () => { await pressInComposer('ArrowRight'); expect(hasNodeSelection(editor, chipKey)).toBe(true); - for (const [key, modifier] of [ + const modifiedArrowKeys = [ ['ArrowLeft', { altKey: true }], ['ArrowRight', { shiftKey: true }], - ] as const) { + ] as const; + for (let i = 0, len = modifiedArrowKeys.length; i < len; i++) { + const [key, modifier] = modifiedArrowKeys[i]; expect(fireEvent.keyDown(composerTextbox(), { code: key, key, ...modifier })).toBe(true); expect(hasNodeSelection(editor, chipKey)).toBe(true); } @@ -459,9 +461,11 @@ describe('Composer directive chips', () => { rerender(composer({ disabled: true })); expect(screen.getByRole('button', { name: '/typo' }).disabled).toBe(true); - for (const action of within(screen.getByRole('status')).getAllByRole( + const statusActions = within(screen.getByRole('status')).getAllByRole( 'button', - )) { + ); + for (let i = 0, len = statusActions.length; i < len; i++) { + const action = statusActions[i]; expect(action.disabled).toBe(true); } }); diff --git a/packages/presentation/ui/src/shell/__tests__/question-prompt.test.tsx b/packages/presentation/ui/src/shell/__tests__/question-prompt.test.tsx index 5a8fd166d..d1da6741f 100644 --- a/packages/presentation/ui/src/shell/__tests__/question-prompt.test.tsx +++ b/packages/presentation/ui/src/shell/__tests__/question-prompt.test.tsx @@ -637,9 +637,10 @@ describe('ConversationPromptDock', () => { expect( permissionFrame?.querySelector('[data-slot="frame-panel"]')?.classList.contains('rounded-xl'), ).toBe(true); - const footerLabels = [ - ...(allow.closest('[data-slot="frame-panel-footer"]')?.querySelectorAll('button') ?? []), - ].map((button) => button.textContent); + const footerLabels = Array.from( + allow.closest('[data-slot="frame-panel-footer"]')?.querySelectorAll('button') ?? [], + (button) => button.textContent, + ); expect(footerLabels).toEqual(['Always allow', 'Reject', 'Allow']); await user.click(allow); diff --git a/packages/presentation/ui/src/shell/agent-models.ts b/packages/presentation/ui/src/shell/agent-models.ts index 4bf30a203..0495c7783 100644 --- a/packages/presentation/ui/src/shell/agent-models.ts +++ b/packages/presentation/ui/src/shell/agent-models.ts @@ -52,14 +52,17 @@ export function groupModelsByProvider( ): ModelProviderGroups | null { const ungrouped: ModelOption[] = []; const byProvider = new Map(); - for (const option of options ?? []) { - if (option.description === undefined) { - ungrouped.push(option); - continue; + if (options != null) { + for (let i = 0, len = options.length; i < len; i++) { + const option = options[i]; + if (option.description === undefined) { + ungrouped.push(option); + continue; + } + const group = byProvider.get(option.description); + if (group) group.push(option); + else byProvider.set(option.description, [option]); } - const group = byProvider.get(option.description); - if (group) group.push(option); - else byProvider.set(option.description, [option]); } if (byProvider.size < 2) return null; return { diff --git a/packages/presentation/ui/src/shell/composer-command.tsx b/packages/presentation/ui/src/shell/composer-command.tsx index fa7afe84f..421d666af 100644 --- a/packages/presentation/ui/src/shell/composer-command.tsx +++ b/packages/presentation/ui/src/shell/composer-command.tsx @@ -186,7 +186,8 @@ export function buildComposerCommandGroups({ ]; const commandItems: ComposerCommandEntry[] = []; if (commandSource === 'slash') { - for (const command of agentCommands) { + for (let i = 0, len = agentCommands.length; i < len; i++) { + const command = agentCommands[i]; // Aliases and display names match too (typing /cost surfaces /usage); selection inserts // the canonical name. if ( @@ -214,13 +215,15 @@ export function buildComposerCommandGroups({ }); } } - for (const item of commandItemCandidates) { + for (let i = 0, len = commandItemCandidates.length; i < len; i++) { + const item = commandItemCandidates[i]; if (commandSource === 'slash' && item.source === 'plus') continue; if (matchesQuery(item.label, item.value, item.hint, commandQuery)) commandItems.push(item); } if (commandSource === 'plus' && modesEnabled) { - for (const mode of availableModes) { + for (let i = 0, len = availableModes.length; i < len; i++) { + const mode = availableModes[i]; if (!matchesQuery(mode.name, mode.modeId, mode.description, commandQuery)) continue; commandItems.push({ active: currentModeId === mode.modeId, diff --git a/packages/presentation/ui/src/shell/composer-controls.tsx b/packages/presentation/ui/src/shell/composer-controls.tsx index 2462bf7e1..63d92e59d 100644 --- a/packages/presentation/ui/src/shell/composer-controls.tsx +++ b/packages/presentation/ui/src/shell/composer-controls.tsx @@ -43,8 +43,11 @@ function optionById( options: readonly T[] | undefined, id: string | null, ): T | undefined { - for (const option of options ?? []) { - if (option.id === id) return option; + if (options != null) { + for (let i = 0, len = options.length; i < len; i++) { + const option = options[i]; + if (option.id === id) return option; + } } return undefined; } @@ -53,7 +56,8 @@ function policyById( policies: readonly ApprovalPolicy[], policyId: string | null, ): ApprovalPolicy | undefined { - for (const policy of policies) { + for (let i = 0, len = policies.length; i < len; i++) { + const policy = policies[i]; if (policy.policyId === policyId) return policy; } return undefined; diff --git a/packages/presentation/ui/src/shell/composer-editor/__tests__/composer-editor.test.ts b/packages/presentation/ui/src/shell/composer-editor/__tests__/composer-editor.test.ts index 634bc8cc7..81d9fa130 100644 --- a/packages/presentation/ui/src/shell/composer-editor/__tests__/composer-editor.test.ts +++ b/packages/presentation/ui/src/shell/composer-editor/__tests__/composer-editor.test.ts @@ -142,13 +142,17 @@ describe('directive tokenizer', () => { it('chips a leading $ only with a horizontal separator and shell payload', () => { const editor = createEditor(); - for (const draft of ['$ ls -la', '$ pnpm test', '$\techo']) { + const shellDrafts = ['$ ls -la', '$ pnpm test', '$\techo']; + for (let i = 0, len = shellDrafts.length; i < len; i++) { + const draft = shellDrafts[i]; setDraft(editor, draft); expect(draftShape(editor)).toEqual(['composer-shell', 'text']); expect(draftText(editor)).toBe(draft); } - for (const draft of ['$ls', '$HOME', '$100', '$', '$ ']) { + const proseDrafts = ['$ls', '$HOME', '$100', '$', '$ ']; + for (let i = 0, len = proseDrafts.length; i < len; i++) { + const draft = proseDrafts[i]; setDraft(editor, draft); expect(draftShape(editor)).toEqual(['text']); } @@ -192,14 +196,16 @@ describe('directive tokenizer', () => { it('keeps mid-line slash and dollar-sign tokens as prose', () => { const editor = createEditor(); - for (const draft of [ + const midLineDrafts = [ 'run /usage now', 'run /typo now', 'run $ now', 'pay $5', 'echo $HOME', ' $ls', - ]) { + ]; + for (let i = 0, len = midLineDrafts.length; i < len; i++) { + const draft = midLineDrafts[i]; setDraft(editor, draft); expect(draftShape(editor)).toEqual(['text']); expect(draftText(editor)).toBe(draft); @@ -276,7 +282,9 @@ describe('directive tokenizer', () => { () => { const paragraph = $getRoot().getFirstChild(); if (!$isElementNode(paragraph)) throw new Error('expected paragraph'); - for (const child of paragraph.getChildren()) { + const children = paragraph.getChildren(); + for (let i = 0, len = children.length; i < len; i++) { + const child = children[i]; if (child.getType() !== 'composer-command') continue; const converted = $convertDirectiveToText(child.getKey()); if (converted) suppressed.add(converted); @@ -495,10 +503,12 @@ describe('$draftDirective', () => { it('moves a lone misplaced directive to the start without doubling separator whitespace', () => { const editor = createEditor(); - for (const [before, after, expected] of [ + const moveCases = [ ['please ', ' now', '/review please now'], [' ', ' now', '/review now'], - ]) { + ]; + for (let i = 0, len = moveCases.length; i < len; i++) { + const [before, after, expected] = moveCases[i]; setStructuredCommandDraft(editor, before, after); editor.update( () => { @@ -517,12 +527,14 @@ describe('$draftDirective', () => { it('normalizes boundary whitespace when removing a directive', () => { const editor = createEditor(); - for (const [before, after, expected] of [ + const removalCases = [ ['please ', ' now', 'please now'], ['', ' now', 'now'], ['please ', ' ', 'please'], ['', ' ', ''], - ]) { + ]; + for (let i = 0, len = removalCases.length; i < len; i++) { + const [before, after, expected] = removalCases[i]; setStructuredCommandDraft(editor, before, after); editor.update( () => { diff --git a/packages/presentation/ui/src/shell/composer-editor/editor.tsx b/packages/presentation/ui/src/shell/composer-editor/editor.tsx index d86045d2f..8e0055812 100644 --- a/packages/presentation/ui/src/shell/composer-editor/editor.tsx +++ b/packages/presentation/ui/src/shell/composer-editor/editor.tsx @@ -85,9 +85,11 @@ function DirectiveStatePlugin({ }: Pick): null { const [editor] = useLexicalComposerContext(); // Prop → external-store sync for the chip portals (they can't receive props through Lexical's - // decorator boundary); not a state watcher. + // decorator boundary); not a state watcher: `store` is a vanilla zustand store keyed by the + // Lexical editor instance, not React useState, and the chip portals subscribe to it directly. useEffect(() => { const store = directiveStateFor(editor); + // eslint-disable-next-line vibe-proof/react-no-use-effect-watching -- see above store.setState({ directiveControls, disabled }); }, [editor, directiveControls, disabled]); return null; @@ -104,7 +106,10 @@ function TokenizerPlugin(): null { function EditablePlugin({ disabled }: { disabled: boolean }): null { const [editor] = useLexicalComposerContext(); + // Prop → imperative sync: `setEditable` is the Lexical editor's own API (not React state); + // an effect is the only place to push the prop into the editor instance. useEffect(() => { + // eslint-disable-next-line vibe-proof/react-no-use-effect-watching -- see above editor.setEditable(!disabled); }, [editor, disabled]); return null; @@ -297,7 +302,10 @@ export function ComposerEditor({ const analysis = $analyzeDirectives(); const placementIssues: Partial> = {}; if (analysis.composition.kind === 'blocked') { - for (const key of analysis.blockedKeys) placementIssues[key] = analysis.composition.issue; + for (let i = 0, len = analysis.blockedKeys.length; i < len; i++) { + const key = analysis.blockedKeys[i]; + placementIssues[key] = analysis.composition.issue; + } } return { caretOffset: $caretFlatOffset(), diff --git a/packages/presentation/ui/src/shell/composer-editor/serialize.ts b/packages/presentation/ui/src/shell/composer-editor/serialize.ts index 8898a96ab..1b844232b 100644 --- a/packages/presentation/ui/src/shell/composer-editor/serialize.ts +++ b/packages/presentation/ui/src/shell/composer-editor/serialize.ts @@ -56,7 +56,7 @@ function $pointFlatOffset(point: PointType): number { if (!$isElementNode(node)) throw new Error('Element selection point must reference an element'); let offset = $flatOffsetOfNode(node); const children = node.getChildren(); - for (let i = 0; i < point.offset && i < children.length; i++) { + for (let i = 0, len = children.length; i < point.offset && i < len; i++) { offset += flatTextContribution(children[i], i < children.length - 1); } return offset; @@ -210,7 +210,11 @@ function $collectDirectives(node: LexicalNode, output: EditorDirective[]): void return; } if (!$isElementNode(node)) return; - for (const child of node.getChildren()) $collectDirectives(child, output); + const children = node.getChildren(); + for (let i = 0, len = children.length; i < len; i++) { + const child = children[i]; + $collectDirectives(child, output); + } } /** Classify directive placement independently from catalog validity. AgentInput can represent @@ -218,7 +222,11 @@ function $collectDirectives(node: LexicalNode, output: EditorDirective[]): void export function $analyzeDirectives(): DirectiveAnalysis { const root = $getRoot(); const directives: EditorDirective[] = []; - for (const child of root.getChildren()) $collectDirectives(child, directives); + const rootChildren = root.getChildren(); + for (let i = 0, len = rootChildren.length; i < len; i++) { + const child = rootChildren[i]; + $collectDirectives(child, directives); + } if (directives.length === 0) { return { blockedKeys: [], composition: { kind: 'none' }, leading: null }; diff --git a/packages/presentation/ui/src/shell/composer-editor/tokenize.ts b/packages/presentation/ui/src/shell/composer-editor/tokenize.ts index 07360df68..ed60f4b31 100644 --- a/packages/presentation/ui/src/shell/composer-editor/tokenize.ts +++ b/packages/presentation/ui/src/shell/composer-editor/tokenize.ts @@ -104,7 +104,9 @@ export function $normalizeDirectiveTokens( // `/name` inside command arguments or shell syntax as a second action. if ($hasLeadingDirective()) return; changed = false; - for (const node of $nodesOfType(TextNode)) { + const textNodes = $nodesOfType(TextNode); + for (let i = 0, len = textNodes.length; i < len; i++) { + const node = textNodes[i]; const candidate = $findDirectiveCandidate(node, state, opts.force ?? false); if (!candidate) continue; $replaceCandidate(node, candidate); diff --git a/packages/presentation/ui/src/shell/composer.tsx b/packages/presentation/ui/src/shell/composer.tsx index 6c53e6f64..4a19e75fd 100644 --- a/packages/presentation/ui/src/shell/composer.tsx +++ b/packages/presentation/ui/src/shell/composer.tsx @@ -542,7 +542,8 @@ export function Composer({ return; } let total = attachmentPayloadBytes(attachments); - for (const file of files) { + for (let i = 0, len = files.length; i < len; i++) { + const file = files[i]; const validationError = isSupportedImageFile(file) ? file.size > MAX_ATTACHMENT_BYTES ? t('attachmentTooLarge') @@ -808,7 +809,8 @@ export function Composer({ // Workflow mode and approval policy are orthogonal axes (see session-modes.ts, approval-policy.ts). // The active mode is server-reflected; a rejected switch (error banner) leaves the previous active. let matchedMode: SessionMode | null = null; - for (const mode of workflowModes) { + for (let i = 0, len = workflowModes.length; i < len; i++) { + const mode = workflowModes[i]; if (mode.modeId === currentModeId) matchedMode = mode; } const activeMode = matchedMode; diff --git a/packages/presentation/ui/src/shell/git/diff-viewer.tsx b/packages/presentation/ui/src/shell/git/diff-viewer.tsx index 7dcd0f44f..a5f1d50ec 100644 --- a/packages/presentation/ui/src/shell/git/diff-viewer.tsx +++ b/packages/presentation/ui/src/shell/git/diff-viewer.tsx @@ -23,6 +23,14 @@ export interface DiffViewerProps { className?: string; } +const diffViewerSkeletonJsx = ( +
+ {createFixedArray(4).map((i) => ( + + ))} +
+); + /** The right panel's Diff section content: a `@pierre/diffs` viewer for an already-fetched patch. */ export function DiffViewer({ patch, @@ -56,7 +64,7 @@ export function DiffViewer({
{files.length === 0 ? ( isLoading ? ( - + diffViewerSkeletonJsx ) : error ? ( ); } - -function DiffViewerSkeleton(): React.ReactNode { - return ( -
- {createFixedArray(4).map((i) => ( - - ))} -
- ); -} diff --git a/packages/presentation/ui/src/shell/history/history-browser.tsx b/packages/presentation/ui/src/shell/history/history-browser.tsx index 30eb7dead..fafc54dd4 100644 --- a/packages/presentation/ui/src/shell/history/history-browser.tsx +++ b/packages/presentation/ui/src/shell/history/history-browser.tsx @@ -153,7 +153,7 @@ export function HistoryBrowserList({ ); } - if (entries.length === 0 && loadError != null) { + if (loadError != null && entries.length === 0) { return ( diff --git a/packages/presentation/ui/src/shell/history/sort.ts b/packages/presentation/ui/src/shell/history/sort.ts index f72815ffa..0f4be6381 100644 --- a/packages/presentation/ui/src/shell/history/sort.ts +++ b/packages/presentation/ui/src/shell/history/sort.ts @@ -4,6 +4,8 @@ import type { HistoryBrowserEntry } from './history-browser'; /** How the history browser arranges entries: by project directory, or by recency. */ export type HistorySortOrder = 'project' | 'latest' | 'oldest'; +const collator = new Intl.Collator(); + export function sortHistoryBrowserEntries( entries: readonly HistoryBrowserEntry[], order: HistorySortOrder, @@ -18,8 +20,8 @@ export function sortHistoryBrowserEntries( return byTimestampDesc(a, b); } return ( - repositoryLabel(a.cwd).localeCompare(repositoryLabel(b.cwd)) || - a.cwd.localeCompare(b.cwd) || + collator.compare(repositoryLabel(a.cwd), repositoryLabel(b.cwd)) || + collator.compare(a.cwd, b.cwd) || byTimestampDesc(a, b) ); }); @@ -42,7 +44,8 @@ export function groupHistoryBrowserEntries( ): HistoryBrowserGroup[] { const groups: HistoryBrowserGroup[] = []; const byCwd = new Map(); - for (const entry of sorted) { + for (let i = 0, len = sorted.length; i < len; i++) { + const entry = sorted[i]; const existing = byCwd.get(entry.cwd); if (existing) { existing.entries.push(entry); diff --git a/packages/presentation/ui/src/shell/index.ts b/packages/presentation/ui/src/shell/index.ts index cb3031415..c6fc5e94c 100644 --- a/packages/presentation/ui/src/shell/index.ts +++ b/packages/presentation/ui/src/shell/index.ts @@ -20,7 +20,7 @@ export * from './notifications-settings-panel'; export * from './plugins'; export * from './providers/account-detail'; export * from './providers/account-master-list'; -export * from './providers/routing'; +export type * from './providers/routing'; export * from './service-icon'; export * from './session-sidebar'; export * from './session-title-menu'; diff --git a/packages/presentation/ui/src/shell/new-session-surface.tsx b/packages/presentation/ui/src/shell/new-session-surface.tsx index f97d9d8ff..15cb6d300 100644 --- a/packages/presentation/ui/src/shell/new-session-surface.tsx +++ b/packages/presentation/ui/src/shell/new-session-surface.tsx @@ -127,7 +127,8 @@ function workspaceById( workspaceId: WorkspaceId | null, ): WorkspaceRecord | null { if (workspaceId === null) return null; - for (const workspace of workspaces) { + for (let i = 0, len = workspaces.length; i < len; i++) { + const workspace = workspaces[i]; if (workspace.workspaceId === workspaceId) return workspace; } return null; diff --git a/packages/presentation/ui/src/shell/permission-prompt.tsx b/packages/presentation/ui/src/shell/permission-prompt.tsx index 14e83d4ac..9baa56432 100644 --- a/packages/presentation/ui/src/shell/permission-prompt.tsx +++ b/packages/presentation/ui/src/shell/permission-prompt.tsx @@ -157,16 +157,24 @@ function permissionDetails(item: PermissionConversationItem): PermissionDetail[] const showRawArguments = toolCall.kind === 'other' && raw !== undefined; const files = new Set(); - for (const item of toolCall.content ?? []) { - if (item.type === 'diff') files.add(item.path); + if (toolCall.content != null) { + for (let i = 0, len = toolCall.content.length; i < len; i++) { + const item = toolCall.content[i]; + if (item.type === 'diff') files.add(item.path); + } + } + if (toolCall.locations != null) { + for (let i = 0, len = toolCall.locations.length; i < len; i++) { + const location = toolCall.locations[i]; + files.add(location.path); + } } - for (const location of toolCall.locations ?? []) files.add(location.path); if (!showRawArguments) { const rawPath = stringField(raw, 'path') ?? stringField(raw, 'file_path'); if (rawPath) files.add(rawPath); } - const details: PermissionDetail[] = [...files].map((value) => ({ label: 'file', value })); + const details: PermissionDetail[] = Array.from(files, (value) => ({ label: 'file', value })); if (showRawArguments) { details.push({ label: 'arguments', value: JSON.stringify(raw, null, 2) }); } else { diff --git a/packages/presentation/ui/src/shell/plugins/plugin-card.tsx b/packages/presentation/ui/src/shell/plugins/plugin-card.tsx index 48543ad29..8cd141ab9 100644 --- a/packages/presentation/ui/src/shell/plugins/plugin-card.tsx +++ b/packages/presentation/ui/src/shell/plugins/plugin-card.tsx @@ -187,7 +187,8 @@ function ComponentSummary({ }): React.ReactNode { const t = useTranslations('settings.plugins'); const parts: string[] = []; - for (const kind of COMPONENT_KIND_ORDER) { + for (let i = 0, len = COMPONENT_KIND_ORDER.length; i < len; i++) { + const kind = COMPONENT_KIND_ORDER[i]; const count = counts[kind]; if (count !== undefined && count > 0) { parts.push(t(`componentCount.${kind}`, { count })); diff --git a/packages/presentation/ui/src/shell/simulator/device-compositor.ts b/packages/presentation/ui/src/shell/simulator/device-compositor.ts index 70ed9c0bb..604b1e48c 100644 --- a/packages/presentation/ui/src/shell/simulator/device-compositor.ts +++ b/packages/presentation/ui/src/shell/simulator/device-compositor.ts @@ -57,12 +57,14 @@ export function paintChassis( // Side buttons first, so the chassis paints over their inner halves. context.fillStyle = RIM_COLOR; const buttonWidth = buttonDepth * 3; - for (const [top, size] of LEFT_BUTTONS) { + for (let i = 0, len = LEFT_BUTTONS.length; i < len; i++) { + const [top, size] = LEFT_BUTTONS[i]; context.beginPath(); context.roundRect(0, pad + top * screenH, buttonWidth, size * screenH, buttonDepth); context.fill(); } - for (const [top, size] of RIGHT_BUTTONS) { + for (let i = 0, len = RIGHT_BUTTONS.length; i < len; i++) { + const [top, size] = RIGHT_BUTTONS[i]; context.beginPath(); context.roundRect( width - buttonWidth, diff --git a/packages/presentation/ui/src/shell/terminal/fonts.ts b/packages/presentation/ui/src/shell/terminal/fonts.ts index 3ed76cc67..91635b91a 100644 --- a/packages/presentation/ui/src/shell/terminal/fonts.ts +++ b/packages/presentation/ui/src/shell/terminal/fonts.ts @@ -56,7 +56,8 @@ const COLOR_EMOJI_FAMILIES = ['apple color emoji']; const MONO_FAMILIES = ['sf mono', 'menlo', 'monaco', 'consolas', 'dejavu sans mono']; function pickLocalFamily(fonts: readonly LocalFontData[], matchers: string[]): string | null { - for (const matcher of matchers) { + for (let i = 0, len = matchers.length; i < len; i++) { + const matcher = matchers[i]; const hit = fonts.find((font) => `${font.family} ${font.fullName} ${font.postscriptName}`.toLowerCase().includes(matcher), ); diff --git a/packages/presentation/ui/src/shell/threads-view.tsx b/packages/presentation/ui/src/shell/threads-view.tsx index d09ca8bce..3734e4d4f 100644 --- a/packages/presentation/ui/src/shell/threads-view.tsx +++ b/packages/presentation/ui/src/shell/threads-view.tsx @@ -98,7 +98,8 @@ export function ThreadsView({ const projectGroups: ThreadGroupViewModel[] = []; let pinnedGroup: ThreadGroupViewModel | undefined; let chatGroup: ThreadGroupViewModel | undefined; - for (const group of groups) { + for (let i = 0, len = groups.length; i < len; i++) { + const group = groups[i]; if (group.isPinned) pinnedGroup = group; else if (group.isChat) chatGroup = group; else projectGroups.push(group); @@ -165,7 +166,9 @@ export function ThreadsView({ className="flex flex-col gap-0.5" value={openSections} onValueChange={(next) => { - for (const section of changedAccordionValues(SIDEBAR_SECTIONS, openSections, next)) { + const changedSections = changedAccordionValues(SIDEBAR_SECTIONS, openSections, next); + for (let i = 0, len = changedSections.length; i < len; i++) { + const section = changedSections[i]; onToggleSectionCollapsed(section); } }} @@ -214,7 +217,13 @@ export function ThreadsView({ className="flex flex-col gap-0.5" value={openGroupKeys} onValueChange={(next) => { - for (const key of changedAccordionValues(projectGroupKeys, openGroupKeys, next)) { + const changedGroupKeys = changedAccordionValues( + projectGroupKeys, + openGroupKeys, + next, + ); + for (let i = 0, len = changedGroupKeys.length; i < len; i++) { + const key = changedGroupKeys[i]; onToggleGroupCollapsed(key); } }} diff --git a/packages/presentation/ui/src/thread-groups.ts b/packages/presentation/ui/src/thread-groups.ts index 66ab60cfa..631b57504 100644 --- a/packages/presentation/ui/src/thread-groups.ts +++ b/packages/presentation/ui/src/thread-groups.ts @@ -52,7 +52,8 @@ export function groupThreadsByWorkspace( const sessionsByWorkspaceId = new Map(); const unregistered: SessionInfo[] = []; - for (const session of sessions) { + for (let i = 0, len = sessions.length; i < len; i++) { + const session = sessions[i]; const matched = workspaceByCwdKey.get(normalizeCwdKey(session.cwd)); let workspace = matched; if (matched && workspaceKind(matched) === 'worktree') { diff --git a/packages/presentation/ui/src/tool-utils.ts b/packages/presentation/ui/src/tool-utils.ts index 7f95fcdfa..05ce1d584 100644 --- a/packages/presentation/ui/src/tool-utils.ts +++ b/packages/presentation/ui/src/tool-utils.ts @@ -148,7 +148,9 @@ function toolCallParamMetadata(toolCall: ToolCall): ToolMetadata[] { const input = recordValue(toolCall.rawInput); if (!input) return []; const metadata: ToolMetadata[] = []; - for (const [key, value] of Object.entries(input)) { + const inputEntries = Object.entries(input); + for (let i = 0, len = inputEntries.length; i < len; i++) { + const [key, value] = inputEntries[i]; if (metadata.length >= PARAM_BADGE_LIMIT) break; if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') { continue; diff --git a/packages/system-plane/ipc/src/electron-main.ts b/packages/system-plane/ipc/src/electron-main.ts index 85ee654cc..a76ffaed3 100644 --- a/packages/system-plane/ipc/src/electron-main.ts +++ b/packages/system-plane/ipc/src/electron-main.ts @@ -88,7 +88,11 @@ export function bindElectronSystemIpc({ const dispose = (reason?: unknown): void => { if (disposed) return; disposed = true; - for (const removeHandler of Object.values(removeHandlers)) removeHandler(); + const handlerRemovers = Object.values(removeHandlers); + for (let i = 0, len = handlerRemovers.length; i < len; i++) { + const removeHandler = handlerRemovers[i]; + removeHandler(); + } ipcMain.removeListener(SETTINGS_SNAPSHOT_CHANNEL, handleSnapshot); ipcMain.removeListener(DAEMON_URL_SNAPSHOT_CHANNEL, handleDaemonUrlSnapshot); window.off('maximize', emitMaximizedState); diff --git a/packages/vendor/coss-ui/package.json b/packages/vendor/coss-ui/package.json index f488e6720..b4a9bcc54 100644 --- a/packages/vendor/coss-ui/package.json +++ b/packages/vendor/coss-ui/package.json @@ -15,11 +15,11 @@ "lint": "biome check ." }, "dependencies": { - "@base-ui/react": "^1.6.0", + "@base-ui/react": "^1.7.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "foxact": "^0.3.8", - "input-otp": "^1.4.2", + "foxact": "^0.3.10", + "input-otp": "^1.5.0", "lucide-react": "catalog:", "react-day-picker": "^9.14.0", "tailwind-merge": "^3.6.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0d717c5d1..c9726975f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -133,8 +133,8 @@ importers: specifier: ^2.5.5 version: 2.5.6 '@eslint-sukka/react': - specifier: ^8.14.2 - version: 8.14.2(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) + specifier: ^9.0.1 + version: 9.0.1(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) '@iconify-json/material-icon-theme': specifier: 'catalog:' version: 1.2.69 @@ -146,10 +146,10 @@ importers: version: 1.0.19 '@svgr/core': specifier: 'catalog:' - version: 8.1.0(@typescript/typescript6@6.0.2) + version: 8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@svgr/plugin-jsx': specifier: 'catalog:' - version: 8.1.0(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)) + version: 8.1.0(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1))(supports-color@8.1.1) '@testing-library/react': specifier: ^16.3.2 version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) @@ -160,14 +160,14 @@ importers: specifier: npm:typescript@^7.0.2 version: typescript@7.0.2 eslint: - specifier: ^10.8.0 - version: 10.8.0(jiti@2.7.0) + specifier: ^10.9.1 + version: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) eslint-config-sukka: - specifier: ^8.14.2 - version: 8.14.2(@typescript-eslint/utils@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) + specifier: ^9.0.1 + version: 9.0.1(@typescript-eslint/utils@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) eslint-formatter-sukka: - specifier: ^8.14.2 - version: 8.14.2(eslint@10.8.0(jiti@2.7.0)) + specifier: ^9.0.1 + version: 9.0.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) jsdom: specifier: ^29.1.1 version: 29.1.1(@noble/hashes@2.2.0) @@ -185,7 +185,7 @@ importers: version: '@typescript/typescript6@6.0.2' unplugin-icons: specifier: 'catalog:' - version: 23.0.1(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)) + version: 23.0.1(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1)) vite: specifier: 'catalog:' version: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0) @@ -221,22 +221,22 @@ importers: version: link:../../packages/foundation/transport '@modelcontextprotocol/sdk': specifier: ^1.30.0 - version: 1.30.0(zod@4.4.3) + version: 1.30.0(supports-color@8.1.1)(zod@4.4.3) '@napi-rs/keyring': specifier: ^1.3.0 version: 1.3.0 '@sentry/node': specifier: 10.62.0 - version: 10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1)) + version: 10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(supports-color@8.1.1) '@sentry/profiling-node': specifier: 10.62.0 - version: 10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1)) + version: 10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(supports-color@8.1.1) better-sqlite3: specifier: ^13.0.2 version: 13.0.2 foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 pino: specifier: ^10.3.1 version: 10.3.1 @@ -249,7 +249,7 @@ importers: version: 4.0.0-beta.98(@opentelemetry/api-logs@0.214.0)(@opentelemetry/api@1.9.1)(@opentelemetry/resources@2.9.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.9.0(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.43.0)(effect@4.0.0-beta.98) '@effect/platform-node': specifier: 4.0.0-beta.98 - version: 4.0.0-beta.98(effect@4.0.0-beta.98)(ioredis@5.11.1) + version: 4.0.0-beta.98(effect@4.0.0-beta.98)(ioredis@5.11.1(supports-color@8.1.1)) '@linkcode/client-core': specifier: workspace:* version: link:../../packages/client/core @@ -276,7 +276,7 @@ importers: version: 4.0.0-beta.98 tsup: specifier: 'catalog:' - version: 8.5.1(@typescript/typescript6@6.0.2)(jiti@2.7.0)(postcss@8.5.24)(tsx@4.23.1)(yaml@2.9.0) + version: 8.5.1(@typescript/typescript6@6.0.2)(jiti@2.7.0)(postcss@8.5.24)(supports-color@8.1.1)(tsx@4.23.1)(yaml@2.9.0) tsx: specifier: 'catalog:' version: 4.23.1 @@ -291,7 +291,7 @@ importers: version: 1.7.0-rc.2(@better-auth/core@1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2))(@better-auth/utils@0.4.2)(better-auth@1.7.0-rc.2(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4))(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(happy-dom@20.10.6)(jsdom@29.1.1(@noble/hashes@2.2.0))(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))))(better-call@1.3.7(zod@4.4.3)) '@better-auth/electron': specifier: 1.7.0-rc.2 - version: 1.7.0-rc.2(@better-auth/core@1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-auth@1.7.0-rc.2(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4))(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(happy-dom@20.10.6)(jsdom@29.1.1(@noble/hashes@2.2.0))(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))))(better-call@1.3.7(zod@4.4.3))(electron@43.2.0) + version: 1.7.0-rc.2(@better-auth/core@1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-auth@1.7.0-rc.2(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4))(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(happy-dom@20.10.6)(jsdom@29.1.1(@noble/hashes@2.2.0))(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))))(better-call@1.3.7(zod@4.4.3))(electron@43.2.0(supports-color@8.1.1)) '@linkcode/cloud': specifier: file:../../packages/vendor/linkcode-cloud-0.1.0.tgz version: file:packages/vendor/linkcode-cloud-0.1.0.tgz @@ -312,7 +312,7 @@ importers: version: link:../../packages/foundation/transport '@sentry/electron': specifier: ^7.15.0 - version: 7.15.0 + version: 7.15.0(supports-color@8.1.1) better-auth: specifier: 1.7.0-rc.2 version: 1.7.0-rc.2(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4))(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(happy-dom@20.10.6)(jsdom@29.1.1(@noble/hashes@2.2.0))(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))) @@ -321,10 +321,10 @@ importers: version: 5.4.4 electron-updater: specifier: ^6.8.9 - version: 6.8.9 + version: 6.8.9(supports-color@8.1.1) foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 zod: specifier: 'catalog:' version: 4.4.3 @@ -352,16 +352,16 @@ importers: version: 1.0.19 '@rolldown/plugin-babel': specifier: 'catalog:' - version: 0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 0.2.3(@babel/core@7.29.7(supports-color@8.1.1))(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) '@sentry/react': specifier: 10.62.0 version: 10.62.0(react@19.3.0-canary-96fcba90-20260728) '@svgr/core': specifier: 'catalog:' - version: 8.1.0(@typescript/typescript6@6.0.2) + version: 8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@svgr/plugin-jsx': specifier: 'catalog:' - version: 8.1.0(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)) + version: 8.1.0(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1))(supports-color@8.1.1) '@tailwindcss/vite': specifier: 'catalog:' version: 4.3.3(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) @@ -379,7 +379,7 @@ importers: version: 19.2.3(@types/react@19.2.17) '@vitejs/plugin-react': specifier: 'catalog:' - version: 6.0.4(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)))(babel-plugin-react-compiler@1.0.0)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 6.0.4(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7(supports-color@8.1.1))(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)))(babel-plugin-react-compiler@1.0.0)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) babel-plugin-react-compiler: specifier: 'catalog:' version: 1.0.0 @@ -391,13 +391,13 @@ importers: version: 7.0.6 electron: specifier: 'catalog:' - version: 43.2.0 + version: 43.2.0(supports-color@8.1.1) electron-builder: specifier: 'catalog:' - version: 26.15.3(electron-builder-squirrel-windows@26.15.3) + version: 26.15.3(electron-builder-squirrel-windows@26.15.3)(supports-color@8.1.1) foxact: - specifier: ^0.3.8 - version: 0.3.8(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + specifier: ^0.3.10 + version: 0.3.10(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) lucide-react: specifier: 'catalog:' version: 1.27.0(react@19.3.0-canary-96fcba90-20260728) @@ -427,7 +427,7 @@ importers: version: '@typescript/typescript6@6.0.2' unplugin-icons: specifier: 'catalog:' - version: 23.0.1(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)) + version: 23.0.1(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1)) vite: specifier: 'catalog:' version: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0) @@ -442,13 +442,13 @@ importers: dependencies: '@better-auth/expo': specifier: 1.7.0-rc.2 - version: 1.7.0-rc.2(@better-auth/core@1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2))(better-auth@1.7.0-rc.2(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(happy-dom@20.10.6)(jsdom@29.1.1(@noble/hashes@2.2.0))(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))))(expo-constants@57.0.3)(expo-linking@57.0.2)(expo-network@57.0.1(expo@57.0.4)(react@19.2.3))(expo-web-browser@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))) + version: 1.7.0-rc.2(5705381685e3aee0fa9e57d39f706f20) '@expo/ui': specifier: 57.0.7 - version: 57.0.7(@babel/core@7.29.7)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.7(@babel/core@7.29.7(supports-color@8.1.1))(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) '@gorhom/bottom-sheet': specifier: ^5.2.14 - version: 5.2.14(@types/react@19.2.17)(react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 5.2.14(6e44dcb7dcfecf271936e923703300f2) '@linkcode/client-core': specifier: workspace:* version: link:../../packages/client/core @@ -469,40 +469,40 @@ importers: version: link:../../packages/presentation/ui '@react-native-community/netinfo': specifier: 12.0.1 - version: 12.0.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 12.0.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) '@sentry/react-native': specifier: ~7.11.0 - version: 7.11.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 7.11.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) better-auth: specifier: 1.7.0-rc.2 version: 1.7.0-rc.2(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(happy-dom@20.10.6)(jsdom@29.1.1(@noble/hashes@2.2.0))(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))) expo: specifier: ~57.0.4 - version: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-apple-authentication: specifier: ~57.0.1 - version: 57.0.1(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.1(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-audio: specifier: ~57.0.0 - version: 57.0.0(expo-asset@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.0(expo-asset@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-background-task: specifier: ~57.0.2 - version: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + version: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) expo-camera: specifier: ~57.0.1 - version: 57.0.1(@types/emscripten@1.41.5)(expo@57.0.4)(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.1(@types/emscripten@1.41.5)(expo@57.0.4)(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-clipboard: specifier: ~57.0.0 - version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-constants: specifier: ~57.0.3 - version: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + version: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) expo-crypto: specifier: ~57.0.1 version: 57.0.1(expo@57.0.4) expo-dev-client: specifier: ~57.0.5 - version: 57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + version: 57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) expo-device: specifier: ~57.0.0 version: 57.0.0(expo@57.0.4) @@ -511,10 +511,10 @@ importers: version: 57.0.0(expo@57.0.4) expo-file-system: specifier: ~57.0.0 - version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) expo-font: specifier: ~57.0.0 - version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-haptics: specifier: ~57.0.0 version: 57.0.0(expo@57.0.4) @@ -523,10 +523,10 @@ importers: version: 57.0.2(expo@57.0.4) expo-libghostty: specifier: ^0.8.1 - version: 0.8.1(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 0.8.1(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-linking: specifier: ~57.0.2 - version: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) expo-local-authentication: specifier: ~57.0.0 version: 57.0.0(expo@57.0.4) @@ -535,46 +535,46 @@ importers: version: 57.0.1(expo@57.0.4)(react@19.2.3) expo-notifications: specifier: ~57.0.3 - version: 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) expo-router: specifier: ~57.0.4 - version: 57.0.4(a892d21e44c1d5a25ab382e32d303fb9) + version: 57.0.4(3bc51b20989ed2c3020a920bb0eeb449) expo-secure-store: specifier: ~57.0.0 version: 57.0.0(expo@57.0.4) expo-sharing: specifier: ~57.0.3 - version: 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) expo-sqlite: specifier: ~57.0.0 - version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-status-bar: specifier: ~57.0.0 - version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-task-manager: specifier: ~57.0.2 - version: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + version: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) expo-updates: specifier: ~57.0.6 - version: 57.0.6(expo-dev-client@57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)))(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 57.0.6(expo-dev-client@57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)))(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) expo-web-browser: specifier: ~57.0.0 - version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + version: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) foxact: - specifier: ^0.3.8 - version: 0.3.8(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + specifier: ^0.3.10 + version: 0.3.10(react-dom@19.2.3(react@19.2.3))(react@19.2.3) foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 heroui-native: specifier: 1.0.6 - version: 1.0.6(e59c6d32fdb32d5fca21df2a11846d54) + version: 1.0.6(165eb86db294c7d42ce40e8c9ab66801) lucide-react-native: specifier: ^1.25.0 - version: 1.27.0(react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 1.27.0(react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) posthog-react-native: specifier: ^4.60.0 - version: 4.60.0(expo-application@57.0.2(expo@57.0.4))(expo-device@57.0.0(expo@57.0.4))(expo-file-system@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)))(expo-localization@57.0.1(expo@57.0.4)(react@19.2.3))(react-native-safe-area-context@5.7.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)) + version: 4.60.0(expo-application@57.0.2(expo@57.0.4))(expo-device@57.0.0(expo@57.0.4))(expo-file-system@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)))(expo-localization@57.0.1(expo@57.0.4)(react@19.2.3))(react-native-safe-area-context@5.7.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3))(react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)) react: specifier: 19.2.3 version: 19.2.3 @@ -583,34 +583,34 @@ importers: version: 19.2.3(react@19.2.3) react-native: specifier: 0.86.0 - version: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + version: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) react-native-gesture-handler: specifier: ~2.32.0 - version: 2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 2.32.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-native-keyboard-controller: specifier: 1.21.9 - version: 1.21.9(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 1.21.9(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-native-reanimated: specifier: 4.5.0 - version: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-native-safe-area-context: specifier: ~5.7.0 - version: 5.7.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 5.7.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-native-screens: specifier: 4.25.2 - version: 4.25.2(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 4.25.2(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-native-svg: specifier: 15.15.4 - version: 15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-native-web: specifier: ^0.21.2 version: 0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react-native-webview: specifier: 13.16.1 - version: 13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 13.16.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-native-worklets: specifier: 0.10.0 - version: 0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + version: 0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) tailwind-merge: specifier: ^3.6.0 version: 3.6.0 @@ -619,7 +619,7 @@ importers: version: 3.3.0(tailwind-merge@3.6.0)(tailwindcss@4.3.3) uniwind: specifier: 1.10.0 - version: 1.10.0(@expo/metro-config@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4))(metro-cache@0.84.4)(metro-transform-worker@0.84.4)(metro@0.84.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tailwindcss@4.3.3) + version: 1.10.0(@expo/metro-config@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(supports-color@8.1.1))(metro-cache@0.84.4(supports-color@8.1.1))(metro-transform-worker@0.84.4(supports-color@8.1.1))(metro@0.84.4(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(tailwindcss@4.3.3) use-intl: specifier: 'catalog:' version: 4.13.4(react@19.2.3) @@ -632,7 +632,7 @@ importers: devDependencies: '@bacons/apple-targets': specifier: 4.0.7 - version: 4.0.7(expo@57.0.4) + version: 4.0.7(expo@57.0.4)(supports-color@8.1.1) '@types/react': specifier: 'catalog:' version: 19.2.17 @@ -679,11 +679,11 @@ importers: specifier: workspace:* version: link:../../packages/vendor/coss-ui foxact: - specifier: ^0.3.8 - version: 0.3.8(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + specifier: ^0.3.10 + version: 0.3.10(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 lucide-react: specifier: 'catalog:' version: 1.27.0(react@19.3.0-canary-96fcba90-20260728) @@ -720,13 +720,13 @@ importers: version: 1.0.19 '@rolldown/plugin-babel': specifier: 'catalog:' - version: 0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 0.2.3(@babel/core@7.29.7(supports-color@8.1.1))(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) '@svgr/core': specifier: 'catalog:' - version: 8.1.0(@typescript/typescript6@6.0.2) + version: 8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@svgr/plugin-jsx': specifier: 'catalog:' - version: 8.1.0(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)) + version: 8.1.0(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1))(supports-color@8.1.1) '@tailwindcss/vite': specifier: 'catalog:' version: 4.3.3(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) @@ -738,7 +738,7 @@ importers: version: 19.2.3(@types/react@19.2.17) '@vitejs/plugin-react': specifier: 'catalog:' - version: 6.0.4(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)))(babel-plugin-react-compiler@1.0.0)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 6.0.4(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7(supports-color@8.1.1))(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)))(babel-plugin-react-compiler@1.0.0)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) babel-plugin-react-compiler: specifier: 'catalog:' version: 1.0.0 @@ -756,7 +756,7 @@ importers: version: '@typescript/typescript6@6.0.2' unplugin-icons: specifier: 'catalog:' - version: 23.0.1(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)) + version: 23.0.1(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1)) vite: specifier: 'catalog:' version: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0) @@ -770,11 +770,11 @@ importers: specifier: workspace:* version: link:../../foundation/transport foxact: - specifier: ^0.3.8 - version: 0.3.8(react-dom@19.2.7(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + specifier: ^0.3.10 + version: 0.3.10(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 devDependencies: '@types/react': specifier: 'catalog:' @@ -798,8 +798,8 @@ importers: specifier: workspace:* version: link:../../foundation/transport foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 devDependencies: typescript: specifier: 'catalog:' @@ -838,11 +838,11 @@ importers: specifier: workspace:* version: link:../../vendor/coss-ui foxact: - specifier: ^0.3.8 - version: 0.3.8(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + specifier: ^0.3.10 + version: 0.3.10(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 lucide-react: specifier: 'catalog:' version: 1.27.0(react@19.3.0-canary-96fcba90-20260728) @@ -908,14 +908,14 @@ importers: specifier: 3.0.0 version: 3.0.0 foxts: - specifier: ^5.8.1 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 zod: specifier: 'catalog:' version: 4.4.3 zustand: specifier: 'catalog:' - version: 5.0.14(@types/react@19.2.17)(react@19.2.7)(use-sync-external-store@1.6.0(react@19.2.7)) + version: 5.0.14(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(use-sync-external-store@1.6.0(react@19.3.0-canary-96fcba90-20260728)) devDependencies: '@types/node': specifier: 'catalog:' @@ -927,14 +927,17 @@ importers: specifier: workspace:* version: link:../schema foxts: - specifier: ^5.8.1 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 packages/foundation/schema: dependencies: canonicalize: specifier: 3.0.0 version: 3.0.0 + foxts: + specifier: ^5.9.1 + version: 5.9.1 zod: specifier: 'catalog:' version: 4.4.3 @@ -952,14 +955,14 @@ importers: specifier: ^0.1.0 version: 0.1.0 foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 socket.io: specifier: 'catalog:' - version: 4.8.3 + version: 4.8.3(supports-color@8.1.1) socket.io-client: specifier: 'catalog:' - version: 4.8.3 + version: 4.8.3(supports-color@8.1.1) ws: specifier: 'catalog:' version: 8.21.1 @@ -981,7 +984,7 @@ importers: dependencies: '@anthropic-ai/claude-agent-sdk': specifier: ^0.3.215 - version: 0.3.215(@anthropic-ai/sdk@0.115.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(zod@4.4.3) + version: 0.3.215(@anthropic-ai/sdk@0.115.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(zod@4.4.3) '@anthropic-ai/sdk': specifier: ^0.115.0 version: 0.115.0(zod@4.4.3) @@ -1004,8 +1007,8 @@ importers: specifier: ^7.0.6 version: 7.0.6 foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 smol-toml: specifier: ^1.7.1 version: 1.7.1 @@ -1015,7 +1018,7 @@ importers: devDependencies: '@earendil-works/pi-coding-agent': specifier: ^0.80.6 - version: 0.80.6(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(ws@8.21.1)(zod@4.4.3) + version: 0.80.6(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(supports-color@8.1.1)(ws@8.21.1)(zod@4.4.3) '@types/cross-spawn': specifier: ^6.0.6 version: 6.0.6 @@ -1032,14 +1035,14 @@ importers: specifier: workspace:* version: link:../../foundation/schema foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 mac-system-proxy: specifier: ^1.0.4 version: 1.0.4 make-fetch-happen: specifier: ^16.0.1 - version: 16.0.1 + version: 16.0.1(supports-color@8.1.1) p-map: specifier: ^7.0.6 version: 7.0.6 @@ -1100,7 +1103,7 @@ importers: version: 1.0.0 acorn: specifier: ^8.17.0 - version: 8.17.0 + version: 8.18.0 croner: specifier: ^10.0.1 version: 10.0.1 @@ -1108,8 +1111,8 @@ importers: specifier: 4.0.0-beta.98 version: 4.0.0-beta.98 foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 restty: specifier: ^0.2.6 version: 0.2.6 @@ -1124,8 +1127,8 @@ importers: packages/host/sim: dependencies: foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 zod: specifier: 'catalog:' version: 4.4.3 @@ -1149,8 +1152,8 @@ importers: specifier: ^9.0.0 version: 9.0.0 foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 devDependencies: typescript: specifier: 'catalog:' @@ -1166,7 +1169,7 @@ importers: dependencies: '@base-ui/react': specifier: ^1.6.0 - version: 1.6.0(@date-fns/tz@1.5.0)(@types/react@19.2.17)(date-fns@4.4.0)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + version: 1.7.0(@date-fns/tz@1.5.0)(@types/react@19.2.17)(date-fns@4.4.0)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) '@dnd-kit/dom': specifier: ^0.5.0 version: 0.5.0 @@ -1217,7 +1220,7 @@ importers: version: 4.3.1 '@streamdown/cjk': specifier: ^1.0.3 - version: 1.0.3(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(react@19.3.0-canary-96fcba90-20260728)(unified@11.0.5) + version: 1.0.3(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1)(unified@11.0.5) '@streamdown/code': specifier: ^1.1.1 version: 1.1.1(react@19.3.0-canary-96fcba90-20260728) @@ -1237,11 +1240,11 @@ importers: specifier: ^3.4.12 version: 3.4.12 foxact: - specifier: ^0.3.8 - version: 0.3.8(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + specifier: ^0.3.10 + version: 0.3.10(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) foxts: - specifier: ^5.8.0 - version: 5.8.1 + specifier: ^5.9.1 + version: 5.9.1 lexical: specifier: ^0.48.0 version: 0.48.0(@typescript/typescript6@6.0.2) @@ -1262,19 +1265,19 @@ importers: version: 9.3.0 react-native: specifier: '>=0.80' - version: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) + version: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) react-native-safe-area-context: specifier: '>=5.0.0' - version: 5.7.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + version: 5.7.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) rehype-slug: specifier: ^6.0.0 version: 6.0.0 remark-gfm: specifier: ^4.0.1 - version: 4.0.1 + version: 4.0.1(supports-color@8.1.1) remark-parse: specifier: ^11.0.0 - version: 11.0.0 + version: 11.0.0(supports-color@8.1.1) remend: specifier: ^1.3.0 version: 1.3.0 @@ -1283,7 +1286,7 @@ importers: version: 0.2.6 streamdown: specifier: ^2.5.0 - version: 2.5.0(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + version: 2.5.0(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) tailwind-merge: specifier: ^3.6.0 version: 3.6.0 @@ -1323,7 +1326,7 @@ importers: version: 19.2.3(@types/react@19.2.17) heroui-native: specifier: ^1.0.6 - version: 1.0.6(fbb89a5f802f3b19887fb8e060c8c1c4) + version: 1.0.6(63282ea4a5d8a79f137ba1bf529bfa14) react: specifier: 'catalog:' version: 19.3.0-canary-96fcba90-20260728 @@ -1332,13 +1335,13 @@ importers: version: 19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728) react-native-svg: specifier: ^15.15.4 - version: 15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + version: 15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) typescript: specifier: 'catalog:' version: '@typescript/typescript6@6.0.2' unplugin-icons: specifier: 'catalog:' - version: 23.0.1(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)) + version: 23.0.1(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1)) packages/system-plane/ipc: dependencies: @@ -1347,14 +1350,14 @@ importers: version: link:../../foundation/schema '@moeru/eventa': specifier: 1.0.0-beta.12 - version: 1.0.0-beta.12(electron@43.2.0)(hono@4.12.32) + version: 1.0.0-beta.12(electron@43.2.0(supports-color@8.1.1))(hono@4.12.32) zod: specifier: 'catalog:' version: 4.4.3 devDependencies: electron: specifier: 'catalog:' - version: 43.2.0 + version: 43.2.0(supports-color@8.1.1) typescript: specifier: 'catalog:' version: '@typescript/typescript6@6.0.2' @@ -1362,8 +1365,8 @@ importers: packages/vendor/coss-ui: dependencies: '@base-ui/react': - specifier: ^1.6.0 - version: 1.6.0(@date-fns/tz@1.5.0)(@types/react@19.2.17)(date-fns@4.4.0)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + specifier: ^1.7.0 + version: 1.7.0(@date-fns/tz@1.5.0)(@types/react@19.2.17)(date-fns@4.4.0)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -1371,11 +1374,11 @@ importers: specifier: ^2.1.1 version: 2.1.1 foxact: - specifier: ^0.3.8 - version: 0.3.8(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + specifier: ^0.3.10 + version: 0.3.10(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) input-otp: - specifier: ^1.4.2 - version: 1.4.2(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + specifier: ^1.5.0 + version: 1.5.0(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) lucide-react: specifier: 'catalog:' version: 1.27.0(react@19.3.0-canary-96fcba90-20260728) @@ -2033,8 +2036,8 @@ packages: '@bacons/xcode@1.0.0-alpha.32': resolution: {integrity: sha512-OGpH7+yMbWC2cgYZon5B+VVadH9HsB2V/abtEiplA65XnSuV4GAYAVixOCDc5k182WkfoakfdM0zW6U9cbcsbw==} - '@base-ui/react@1.6.0': - resolution: {integrity: sha512-/jzjTWJYXhRFO45Bev9lc3cHbmjzCMpUqbMZ2AgKy/z25mY9B6shGSNcXcjQar9n5doM0KYW1W8fcFv2jZBuMw==} + '@base-ui/react@1.7.0': + resolution: {integrity: sha512-j+8QjX44C32jrXD/qyEAGpFr70FRpGL2CY61mQd9nBPWN737CK0xxD1ceJ055rW4RtdvFDT1e7otzdlfxvsYug==} engines: {node: '>=14.0.0'} peerDependencies: '@date-fns/tz': ^1.2.0 @@ -2050,8 +2053,8 @@ packages: date-fns: optional: true - '@base-ui/utils@0.3.1': - resolution: {integrity: sha512-gFFiltORVmW/N6IILTGxizP3PBpVpysqML1ALY5Vk0mH+7faVkCknOU31goYHN5Aoek2dkjxva1XOD2Ce9WuIg==} + '@base-ui/utils@0.3.2': + resolution: {integrity: sha512-oWy1aq/I2GmYjpl4PhEAhzflF8VPGKgZeq0xAWTbfD5KBWyxcN0ZP2+WHSUm/5Z6lVMBDLReLcoXwSYoRc/zNQ==} peerDependencies: '@types/react': ^17 || ^18 || ^19 react: ^17 || ^18 || ^19 @@ -2796,16 +2799,16 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint-sukka/eslint-plugin-react-jsx-a11y@8.14.2': - resolution: {integrity: sha512-mybRR4Bz2WaxZRhn3h2qaB29H1KSYfacdNUtEDDKeDT5jjoSSwPRU0z4D8HcuzdFVvIB60jWKHF0Ga87PRHJwg==} + '@eslint-sukka/eslint-plugin-react-jsx-a11y@9.0.1': + resolution: {integrity: sha512-+4GybK6oECdmOJ0r+pdBpxUYR+FileN7qvS2Bor/e7VkUDelxeTnjAvRkm7cMuuoggZ6+IjpF3ZYT2MsZmfXgQ==} - '@eslint-sukka/eslint-plugin-stylistic@8.14.2': - resolution: {integrity: sha512-o8gnWoAoD8j75mVgCnCGoKlbotSvbWHP9OPZRRJ1FRrzXZu8aq6tZmBglchG0oBkh5G/qlgBdFANzqwT5nAJkA==} + '@eslint-sukka/eslint-plugin-stylistic@9.0.1': + resolution: {integrity: sha512-1e1E/G7IwSTi8GHnjy/Lcznd2BIhXseEQIFJIXmunVhINyLwrgFqeo7kG1JmSFTOkAdW8xlvuNMv8eVkNN5Sow==} peerDependencies: eslint: '*' - '@eslint-sukka/eslint-plugin-sukka-full@8.14.2': - resolution: {integrity: sha512-tqJEDN5MxRbR1JAknjPsgXv/ik8qGnNbB7qgrc6cDW8W+k69rZbrXv+x5cX6XlV59qn3dSUXbEVcw1uzl6l/Ig==} + '@eslint-sukka/eslint-plugin-sukka-full@9.0.1': + resolution: {integrity: sha512-R75DvnVuIlj5wHdaPgGTJgSlyr0/8GKuii16qOXu7Hzv4SVRw6Lam2Fd0w9kyJEcTsyvInIemJkoLfnvj0VNrA==} peerDependencies: eslint: '*' typescript: '*' @@ -2813,11 +2816,11 @@ packages: typescript: optional: true - '@eslint-sukka/react@8.14.2': - resolution: {integrity: sha512-j3tyd2GJFI3TvG7AqqLOh5RPL8haQSBOPRMz81sKPyuM8hkhj/i0YGgAoH570hN37k/t+4RumykGrkDV+nrQiQ==} + '@eslint-sukka/react@9.0.1': + resolution: {integrity: sha512-8+2lz6f9M4mK1+txCm02V+xi9RUoiopl1qvJ1LUx6A3wXxb+I/kAr5/Ju18iyDMyKKUOMAPH0/4kBpBxecoKqw==} - '@eslint-sukka/shared@8.14.2': - resolution: {integrity: sha512-BBvKJ2lXKJVojwFsrGdv6dzflZFRY6dV5caHr6qSPDA3UsojKzxS0B6LTnvA0OkwzrDAJUWRAZhC+OoEMTT5kw==} + '@eslint-sukka/shared@9.0.1': + resolution: {integrity: sha512-xSnIFeFhbqsyw0RgPSsER+ruHoxzg1afjqEl3jDQsvszT6wFZMILXtchtxiSocpDpOT1m0996OGiCnWi5WyAPg==} peerDependencies: eslint: '*' @@ -3731,8 +3734,8 @@ packages: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 - '@next/eslint-plugin-next@16.2.12': - resolution: {integrity: sha512-uF2z/qAK2q7B5/6CpnFcBRX6jOq5iCO+Uqh1UkJhXljX1JwLarLYhhoJadO6dPb6moTprOKewMXheBcbIoSbug==} + '@next/eslint-plugin-next@16.3.2': + resolution: {integrity: sha512-z+HW1cZgt8QhByw8p2EbxF94AImgsKIYUbtSkA7Zld2T9yrKAlys4jNOcAOCtv6csX2CoA/5qCVyesL5pHmJ0A==} '@noble/ciphers@2.2.0': resolution: {integrity: sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA==} @@ -3893,10 +3896,6 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/semantic-conventions@1.41.1': - resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==} - engines: {node: '>=14'} - '@opentelemetry/semantic-conventions@1.43.0': resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==} engines: {node: '>=14'} @@ -3995,15 +3994,9 @@ packages: '@posthog/browser-common@0.2.3': resolution: {integrity: sha512-LJOUcBLLjFOqw6ZZsjrCuojliJHFU/GYeOV88T+lXyePXJQnxFzuAouDtwwHFHtoaaOjfQ0OvDMR7J468Nkomw==} - '@posthog/core@1.45.1': - resolution: {integrity: sha512-tLtvzomavb2PPWdGYKsusyIzIeL2Px47v348Smibkay7sMy/83TyPk+Ptsp2NdeOgJsbuwSxWkR2+XA0aSCAaA==} - '@posthog/core@1.46.1': resolution: {integrity: sha512-EoCFduRkvrg9E5ylMi4QnZCjlAdRJCq6tJouWfngBVR79XSI4iPvIWYA+CdzokAjk+TfSVBFVJ++4Im3r+T0Dg==} - '@posthog/types@1.398.0': - resolution: {integrity: sha512-sJMkl4k+u8yS/0fjHsKqE9xTdsAh30a2WvgChiptellnVoE0e8QJKFgqOMD2sk8FaEArPdeFklAhXvmENAt3Sg==} - '@posthog/types@1.399.0': resolution: {integrity: sha512-/WDwBzqIPko8VJ1B+0rlso2XQEz9+2sqtsY9Tqy3p1GhgTqsFakcz/PmMpAnA321LTEZVRcO6x5hAwABV4yrDw==} @@ -5477,63 +5470,63 @@ packages: '@types/yargs@17.0.35': resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} - '@typescript-eslint/eslint-plugin@8.65.0': - resolution: {integrity: sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==} + '@typescript-eslint/eslint-plugin@8.68.0': + resolution: {integrity: sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.65.0 + '@typescript-eslint/parser': ^8.68.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.65.0': - resolution: {integrity: sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==} + '@typescript-eslint/parser@8.68.0': + resolution: {integrity: sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.65.0': - resolution: {integrity: sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==} + '@typescript-eslint/project-service@8.68.0': + resolution: {integrity: sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.65.0': - resolution: {integrity: sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==} + '@typescript-eslint/scope-manager@8.68.0': + resolution: {integrity: sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.65.0': - resolution: {integrity: sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==} + '@typescript-eslint/tsconfig-utils@8.68.0': + resolution: {integrity: sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.65.0': - resolution: {integrity: sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==} + '@typescript-eslint/type-utils@8.68.0': + resolution: {integrity: sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.65.0': - resolution: {integrity: sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==} + '@typescript-eslint/types@8.68.0': + resolution: {integrity: sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.65.0': - resolution: {integrity: sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==} + '@typescript-eslint/typescript-estree@8.68.0': + resolution: {integrity: sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.65.0': - resolution: {integrity: sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==} + '@typescript-eslint/utils@8.68.0': + resolution: {integrity: sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.65.0': - resolution: {integrity: sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==} + '@typescript-eslint/visitor-keys@8.68.0': + resolution: {integrity: sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript/typescript-aix-ppc64@7.0.2': @@ -5864,11 +5857,6 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.17.0: - resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} - engines: {node: '>=0.4.0'} - hasBin: true - acorn@8.18.0: resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} engines: {node: '>=0.4.0'} @@ -6222,10 +6210,6 @@ packages: brace-expansion@2.1.3: resolution: {integrity: sha512-DRdx5neNsG/QXbniLFWi2YmC/68oeOOmKz6zOjVk6ZS1ZLXgLIKqVEc6hWsmkjBbgii0SwaBTcJ5XKj5gzY/4A==} - brace-expansion@5.0.8: - resolution: {integrity: sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==} - engines: {node: 20 || >=22} - brace-expansion@5.0.9: resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} engines: {node: 20 || >=22} @@ -7110,8 +7094,8 @@ packages: resolution: {integrity: sha512-2agL3ueZhqxoVrfmntO8yuVj+uNSlIOnhykYHk3Cq0ShYPdUjjUiSJrQvXjq01I9jAuI0Zl2YO8Evv5Mqytm5g==} engines: {node: '>=10.2.0'} - enhanced-resolve@5.24.3: - resolution: {integrity: sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ==} + enhanced-resolve@5.24.5: + resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==} engines: {node: '>=10.13.0'} entities@4.5.0: @@ -7204,11 +7188,13 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} - eslint-config-sukka@8.14.2: - resolution: {integrity: sha512-Q4wgWrMr7XnmLQwSTN3qfydR/xTep0CJdgD5UOB/SxM8/WxOR+hnIAiddiM0juvbKBOKJmU0YajwcaWDLC1FWQ==} + eslint-config-sukka@9.0.1: + resolution: {integrity: sha512-crBHKRFoUR1PLj8s3fUhGb8Lf6Jkv/VdOCJi7LE65RYZF9tpYdTsXk8ZYK9fUGTClblzw73z8zRCspAzsLAbtQ==} + peerDependencies: + eslint: '>=10.8.0' - eslint-formatter-sukka@8.14.2: - resolution: {integrity: sha512-lPmhYY/MvTrvyjWISUZxdodc+yGfDvUK+/O60bZxibBnNmEPG/BO0VQLcLySSRF8Qw27xSdCq8nVyszfYWHJqw==} + eslint-formatter-sukka@9.0.1: + resolution: {integrity: sha512-c5gx//3KKp4lrCn4tWT+1xjpZ3m+6DLBVFdHHh/6bdtZMGbvpCU/SiSDIRBkfJQR3x4Xf56VRY4yBTmg5V9r4w==} peerDependencies: eslint: '*' @@ -7258,8 +7244,8 @@ packages: eslint-import-resolver-node: optional: true - eslint-plugin-jsonc@3.3.0: - resolution: {integrity: sha512-CsTR8aDcShDg6A71ZppLaWiPoSo2J1Ivjm5/c4Mnb9sxgwWq+WG2PgeoAnj7SwzDPJB75tlHvLrGy6ntooIitg==} + eslint-plugin-jsonc@3.4.2: + resolution: {integrity: sha512-q5xzjCYFQuhFomTbctXzd3STfDJ8XduvaigjQmMEbP2gzSKrc58y3Fv6D775/cIK1/sRUn+4kpljiU2iW8k0zw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} peerDependencies: eslint: '>=9.38.0' @@ -7287,8 +7273,8 @@ packages: peerDependencies: eslint: '>=0.8.0' - eslint-plugin-sukka@9.18.1: - resolution: {integrity: sha512-0h0Vv4rsGchCWivVGSyQq69KqZhjOb1FL/4EXiNgwaA3CcfFubgxGV8T/9K1brj+lYqHrxL9RxYXDKamkhMXFg==} + eslint-plugin-sukka@10.2.0: + resolution: {integrity: sha512-BbErYY/fymqL7Te5yiDeBGfSF7QMxzZrT4SQpFI2e8ecRun3oYbL5aJm4kzFfeUzNZ/hET8T7pedpaH1fuXXHg==} peerDependencies: eslint: '>=9.29.0' typescript: '*' @@ -7302,8 +7288,8 @@ packages: '@typescript-eslint/eslint-plugin': optional: true - eslint-plugin-vibe-proof@1.1.0: - resolution: {integrity: sha512-Fbewo0PLM63jH68eewOg3sgAFcCGzeLBG0Ge2a/xyeBigNGXttZn9RDwboLqLGflrjFi37l83nWNKcQHJqaU5g==} + eslint-plugin-vibe-proof@1.9.2: + resolution: {integrity: sha512-J79fxhc0zT7AhVD3PCQDjvZDIb7cdj9vnsn4Q/4hktJpDWQ6xNU0bEEnMkadB/jaBEkXTKEjpu9UPppE+kyBww==} peerDependencies: eslint: '>=9.29.0' typescript: '*' @@ -7320,8 +7306,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.8.0: - resolution: {integrity: sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ==} + eslint@10.9.1: + resolution: {integrity: sha512-9VaAkDURekixUQJy0oJYl2DcN6oKMfxay7XzaGYAWQwsb6qfKf+x76R2k1L8kb1boc+FyCAaTA9GmiKaaiaF+A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -7360,8 +7346,8 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} - event-target-bus@1.0.0: - resolution: {integrity: sha512-uPcWKbj/BJU3Tbw9XqhHqET4/LBOhvv3/SJWr7NksxA6TC5YqBpaZgawE9R+WpYFCBFSAE4Vun+xQS6w4ABdlA==} + event-target-bus@1.1.0: + resolution: {integrity: sha512-24JX34nM0qRcsj7KvtLbVpMcX8ZQYmb0+0a6viaV2GJtVFg5UGyJyDLITkBipJIG0fSscNskI2PxdhTBIMeg8g==} event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} @@ -7867,8 +7853,8 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} - foxact@0.3.8: - resolution: {integrity: sha512-lFakEG8xm6A6wMH4ycWhXvwUybq4ATnMxJfBD4hj6hm9CKo72q2M/YaiEemoWGh9sUjQqX+pPXfq8S/jxedWzA==} + foxact@0.3.10: + resolution: {integrity: sha512-5pyt7M2ngc9PyGX5soP3q/L6Z+JkNPEeGTyc5t200szvEiGofWy41bxNGUE/jpuhIDByLLyuumbc712HCdJWTg==} peerDependencies: react: '*' react-dom: '*' @@ -7878,8 +7864,8 @@ packages: react-dom: optional: true - foxts@5.8.1: - resolution: {integrity: sha512-smDA5j7LVk+dStvNTaAb4F1YAxWeMzPF0R3sRH28hIImhLgVoY76Q7doEl7EzNGP9XjAmIwPTPhPJx9pMjhFPw==} + foxts@5.9.1: + resolution: {integrity: sha512-NrIHGlf4LZGTjjGlVi3gmMbtvC4871SFUflu9yb8X91FYppAk+WMiYS6ZlaEgkPqAkgIGNeq+Y5YCL80GL6v8g==} framer-motion@12.42.2: resolution: {integrity: sha512-5XY9luDiu0oHfHBjpDthFMh0ES+122w6p/papSJBweMkO8Sn+PW2QaEgRblQBpWFnuvZS5qvarpt/hO2pjGmnw==} @@ -8226,10 +8212,6 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} - iconv-lite@0.7.2: - resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} - engines: {node: '>=0.10.0'} - iconv-lite@0.7.3: resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} engines: {node: '>=0.10.0'} @@ -8292,8 +8274,8 @@ packages: inline-style-prefixer@7.0.1: resolution: {integrity: sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==} - input-otp@1.4.2: - resolution: {integrity: sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==} + input-otp@1.5.0: + resolution: {integrity: sha512-3AcfdW1sNG0FmSA5hHMBXG7jNW5CdcdKs8ln8JOmn6S2SRkoXoJx+2UwC+ZvjflfnOdHJx0SfQ9/YjlxVYLtGQ==} peerDependencies: react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc @@ -8315,10 +8297,6 @@ packages: resolution: {integrity: sha512-ehuGcf94bQXhfagULNXrJdfnWO38v070jxSx/qE87Kjzmu2fU7ro5EFAb+OPituLqgfyuQaym5DlrNydW2sJ9A==} engines: {node: '>=12.22.0'} - ip-address@10.2.0: - resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} - engines: {node: '>= 12'} - ip-address@10.3.1: resolution: {integrity: sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==} engines: {node: '>= 12'} @@ -8511,8 +8489,8 @@ packages: engines: {node: '>=6'} hasBin: true - jsonc-eslint-parser@3.1.0: - resolution: {integrity: sha512-75EA7EWZExL/j+MDKQrRbdzcRI2HOkRlmUw8fZJc1ioqFEOvBsq7Rt+A6yCxOt9w/TYNpkt52gC6nm/g5tFIng==} + jsonc-eslint-parser@3.3.0: + resolution: {integrity: sha512-hYTGkHGNRZnXOFZ1urhINADoqDrGfpy53cjw+dxk84QE0pUDujQzeUeamNs6Mz44/TKD49z2x6/GVSu4ZrtA+Q==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} jsonfile@4.0.0: @@ -9297,11 +9275,6 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.15: - resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - nanoid@3.3.16: resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -9906,11 +9879,6 @@ packages: peerDependencies: react: ^19.2.3 - react-dom@19.2.7: - resolution: {integrity: sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==} - peerDependencies: - react: ^19.2.7 - react-dom@19.3.0-canary-96fcba90-20260728: resolution: {integrity: sha512-+T0E6Uw6VfylJAQ9pBRcfn+pdsY96ASMP8sruLJBl2DGN1wi13YrwJID0LLs4zUfG0Ls+n0e6GbM78qHXNRRjA==} peerDependencies: @@ -10077,10 +10045,6 @@ packages: resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} engines: {node: '>=0.10.0'} - react@19.2.7: - resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} - engines: {node: '>=0.10.0'} - react@19.3.0-canary-96fcba90-20260728: resolution: {integrity: sha512-c+uM1FmBEGKPZi9SqyUdH5jYonraRXV3dngqJfJzGUOwpoLIzKu9asV/vc9GqBUVWzguIdYIuMXNkqzszTwrFg==} engines: {node: '>=0.10.0'} @@ -10951,8 +10915,8 @@ packages: typebox@1.1.38: resolution: {integrity: sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==} - typescript-eslint@8.65.0: - resolution: {integrity: sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==} + typescript-eslint@8.68.0: + resolution: {integrity: sha512-MHy0Y0ynqeEbx/S45+i/bBssdy3X6KNBfmJAP35GrgtNxu2TQ5K5xsFDhAnmsq1jvpdoZOPG1LGtJo0HWqYCrQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -11178,6 +11142,10 @@ packages: react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + verkit@0.3.2: + resolution: {integrity: sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==} + engines: {node: '>=18.12.0'} + vfile-location@5.0.3: resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} @@ -11404,18 +11372,6 @@ packages: utf-8-validate: optional: true - ws@8.21.0: - resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@8.21.1: resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==} engines: {node: '>=10.0.0'} @@ -11580,10 +11536,10 @@ snapshots: '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.215': optional: true - '@anthropic-ai/claude-agent-sdk@0.3.215(@anthropic-ai/sdk@0.115.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(zod@4.4.3)': + '@anthropic-ai/claude-agent-sdk@0.3.215(@anthropic-ai/sdk@0.115.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(zod@4.4.3)': dependencies: '@anthropic-ai/sdk': 0.115.0(zod@4.4.3) - '@modelcontextprotocol/sdk': 1.30.0(zod@4.4.3) + '@modelcontextprotocol/sdk': 1.30.0(supports-color@8.1.1)(zod@4.4.3) zod: 4.4.3 optionalDependencies: '@anthropic-ai/claude-agent-sdk-darwin-arm64': 0.3.215 @@ -11624,10 +11580,10 @@ snapshots: semifies: 1.0.0 source-map: 0.6.1 - '@apm-js-collab/tracing-hooks@0.10.1': + '@apm-js-collab/tracing-hooks@0.10.1(supports-color@8.1.1)': dependencies: '@apm-js-collab/code-transformer': 0.15.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) module-details-from-path: 1.0.4 transitivePeerDependencies: - supports-color @@ -11910,20 +11866,20 @@ snapshots: '@babel/compat-data@7.29.7': {} - '@babel/core@7.29.7': + '@babel/core@7.29.7(supports-color@8.1.1)': dependencies: '@babel/code-frame': 7.29.7 '@babel/generator': 7.29.7 '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/helpers': 7.29.7 '@babel/parser': 7.29.7 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) '@babel/types': 7.29.7 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -11950,32 +11906,32 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7)': + '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-member-expression-to-functions': 7.29.7 + '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@8.1.1) '@babel/helper-optimise-call-expression': 7.29.7 - '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7) - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 - '@babel/traverse': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + '@babel/traverse': 7.29.7(supports-color@8.1.1) semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.29.7(@babel/core@7.29.7)': + '@babel/helper-create-regexp-features-plugin@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-annotate-as-pure': 7.29.7 regexpu-core: 6.4.0 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.7)': + '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.12 transitivePeerDependencies: @@ -11983,26 +11939,26 @@ snapshots: '@babel/helper-globals@7.29.7': {} - '@babel/helper-member-expression-to-functions@7.29.7': + '@babel/helper-member-expression-to-functions@7.29.7(supports-color@8.1.1)': dependencies: - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-module-imports@7.29.7': + '@babel/helper-module-imports@7.29.7(supports-color@8.1.1)': dependencies: - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-module-imports': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -12012,27 +11968,27 @@ snapshots: '@babel/helper-plugin-utils@7.29.7': {} - '@babel/helper-remap-async-to-generator@7.29.7(@babel/core@7.29.7)': + '@babel/helper-remap-async-to-generator@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-wrap-function': 7.29.7 - '@babel/traverse': 7.29.7 + '@babel/helper-wrap-function': 7.29.7(supports-color@8.1.1) + '@babel/traverse': 7.29.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7)': + '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-member-expression-to-functions': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@8.1.1) '@babel/helper-optimise-call-expression': 7.29.7 - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + '@babel/helper-skip-transparent-expression-wrappers@7.29.7(supports-color@8.1.1)': dependencies: - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color @@ -12043,10 +11999,10 @@ snapshots: '@babel/helper-validator-option@7.29.7': {} - '@babel/helper-wrap-function@7.29.7': + '@babel/helper-wrap-function@7.29.7(supports-color@8.1.1)': dependencies: '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color @@ -12060,304 +12016,304 @@ snapshots: dependencies: '@babel/types': 7.29.7 - '@babel/plugin-proposal-decorators@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-proposal-decorators@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-decorators': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-decorators': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) transitivePeerDependencies: - supports-color - '@babel/plugin-proposal-export-default-from@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-proposal-export-default-from@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-decorators@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-syntax-decorators@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.29.7)': + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-export-default-from@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-syntax-export-default-from@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-flow@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-syntax-flow@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-arrow-functions@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-arrow-functions@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-async-generator-functions@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-async-generator-functions@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7) - '@babel/traverse': 7.29.7 + '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/traverse': 7.29.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-to-generator@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-async-to-generator@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-module-imports': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7) + '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-block-scoping@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-block-scoping@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-class-properties@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-class-properties@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-static-block@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-class-static-block@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-classes@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-globals': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7) - '@babel/traverse': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/traverse': 7.29.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-destructuring@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-destructuring@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-export-namespace-from@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-export-namespace-from@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-flow-strip-types@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-flow-strip-types@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-flow': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-flow': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) - '@babel/plugin-transform-for-of@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-for-of@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-logical-assignment-operators@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-logical-assignment-operators@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-named-capturing-groups-regex@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-nullish-coalescing-operator@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-nullish-coalescing-operator@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-object-rest-spread@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-object-rest-spread@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7) - '@babel/traverse': 7.29.7 + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/traverse': 7.29.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-catch-binding@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-optional-catch-binding@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-parameters@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-parameters@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-private-methods@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-private-methods@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-private-property-in-object@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-display-name@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-react-display-name@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-react-jsx-development@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-react-jsx-development@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-react-jsx@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-react-jsx@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-module-imports': 7.29.7 + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-pure-annotations@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-react-pure-annotations@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-regenerator@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-regenerator@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-module-imports': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.7) - babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.29.7) - babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.7) + babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-shorthand-properties@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-shorthand-properties@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-template-literals@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-template-literals@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 - '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7) + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-unicode-regex@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-unicode-regex@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) '@babel/helper-plugin-utils': 7.29.7 - '@babel/preset-typescript@7.29.7(@babel/core@7.29.7)': + '@babel/preset-typescript@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-option': 7.29.7 - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -12369,7 +12325,7 @@ snapshots: '@babel/parser': 7.29.7 '@babel/types': 7.29.7 - '@babel/traverse@7.29.7': + '@babel/traverse@7.29.7(supports-color@8.1.1)': dependencies: '@babel/code-frame': 7.29.7 '@babel/generator': 7.29.7 @@ -12377,7 +12333,7 @@ snapshots: '@babel/parser': 7.29.7 '@babel/template': 7.29.7 '@babel/types': 7.29.7 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -12386,28 +12342,28 @@ snapshots: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@bacons/apple-targets@4.0.7(expo@57.0.4)': + '@bacons/apple-targets@4.0.7(expo@57.0.4)(supports-color@8.1.1)': dependencies: - '@bacons/xcode': 1.0.0-alpha.32 + '@bacons/xcode': 1.0.0-alpha.32(supports-color@8.1.1) '@react-native/normalize-colors': 0.79.7 - debug: 4.4.3 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + debug: 4.4.3(supports-color@8.1.1) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) glob: 10.5.0 transitivePeerDependencies: - supports-color - '@bacons/xcode@1.0.0-alpha.32': + '@bacons/xcode@1.0.0-alpha.32(supports-color@8.1.1)': dependencies: '@expo/plist': 0.0.18 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) uuid: 11.1.1 transitivePeerDependencies: - supports-color - '@base-ui/react@1.6.0(@date-fns/tz@1.5.0)(@types/react@19.2.17)(date-fns@4.4.0)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)': + '@base-ui/react@1.7.0(@date-fns/tz@1.5.0)(@types/react@19.2.17)(date-fns@4.4.0)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)': dependencies: '@babel/runtime': 7.29.7 - '@base-ui/utils': 0.3.1(@types/react@19.2.17)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + '@base-ui/utils': 0.3.2(@types/react@19.2.17)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) '@floating-ui/react-dom': 2.1.9(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) '@floating-ui/utils': 0.2.12 react: 19.3.0-canary-96fcba90-20260728 @@ -12418,7 +12374,7 @@ snapshots: '@types/react': 19.2.17 date-fns: 4.4.0 - '@base-ui/utils@0.3.1(@types/react@19.2.17)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)': + '@base-ui/utils@0.3.2(@types/react@19.2.17)(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)': dependencies: '@babel/runtime': 7.29.7 '@floating-ui/utils': 0.2.12 @@ -12458,7 +12414,7 @@ snapshots: optionalDependencies: drizzle-orm: 0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4) - '@better-auth/electron@1.7.0-rc.2(@better-auth/core@1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-auth@1.7.0-rc.2(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4))(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(happy-dom@20.10.6)(jsdom@29.1.1(@noble/hashes@2.2.0))(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))))(better-call@1.3.7(zod@4.4.3))(electron@43.2.0)': + '@better-auth/electron@1.7.0-rc.2(@better-auth/core@1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-auth@1.7.0-rc.2(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4))(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(happy-dom@20.10.6)(jsdom@29.1.1(@noble/hashes@2.2.0))(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))))(better-call@1.3.7(zod@4.4.3))(electron@43.2.0(supports-color@8.1.1))': dependencies: '@better-auth/core': 1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2) '@better-auth/utils': 0.4.2 @@ -12467,9 +12423,9 @@ snapshots: better-call: 1.3.7(zod@4.4.3) zod: 4.4.3 optionalDependencies: - electron: 43.2.0 + electron: 43.2.0(supports-color@8.1.1) - '@better-auth/expo@1.7.0-rc.2(@better-auth/core@1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2))(better-auth@1.7.0-rc.2(@opentelemetry/api@1.9.1)(better-sqlite3@12.11.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.11.1)(kysely@0.29.4))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(happy-dom@20.10.6)(jsdom@29.1.1(@noble/hashes@2.2.0))(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))))(expo-constants@57.0.3)(expo-linking@57.0.2)(expo-network@57.0.1(expo@57.0.4)(react@19.2.3))(expo-web-browser@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)))': + '@better-auth/expo@1.7.0-rc.2(5705381685e3aee0fa9e57d39f706f20)': dependencies: '@better-auth/core': 1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2) '@better-fetch/fetch': 1.3.1 @@ -12477,10 +12433,10 @@ snapshots: better-call: 1.3.7(zod@4.4.3) zod: 4.4.3 optionalDependencies: - expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) - expo-linking: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) + expo-linking: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) expo-network: 57.0.1(expo@57.0.4)(react@19.2.3) - expo-web-browser: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + expo-web-browser: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) '@better-auth/kysely-adapter@1.7.0-rc.2(@better-auth/core@1.7.0-rc.2(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.7)(kysely@0.29.4)(nanostores@1.4.2))(@better-auth/utils@0.4.2)(kysely@0.29.4)': dependencies: @@ -12633,9 +12589,9 @@ snapshots: '@drizzle-team/brocli@0.10.2': {} - '@earendil-works/pi-agent-core@0.80.6(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(ws@8.21.1)(zod@4.4.3)': + '@earendil-works/pi-agent-core@0.80.6(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(supports-color@8.1.1)(ws@8.21.1)(zod@4.4.3)': dependencies: - '@earendil-works/pi-ai': 0.80.6(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(ws@8.21.1)(zod@4.4.3) + '@earendil-works/pi-ai': 0.80.6(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(supports-color@8.1.1)(ws@8.21.1)(zod@4.4.3) ignore: 7.0.5 typebox: 1.1.38 yaml: 2.9.0 @@ -12647,16 +12603,16 @@ snapshots: - ws - zod - '@earendil-works/pi-ai@0.80.6(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(ws@8.21.1)(zod@4.4.3)': + '@earendil-works/pi-ai@0.80.6(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(supports-color@8.1.1)(ws@8.21.1)(zod@4.4.3)': dependencies: '@anthropic-ai/sdk': 0.91.1(zod@4.4.3) '@aws-sdk/client-bedrock-runtime': 3.1048.0 - '@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3)) + '@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(supports-color@8.1.1) '@mistralai/mistralai': 2.2.6(@opentelemetry/api@1.9.0) '@opentelemetry/api': 1.9.0 '@smithy/node-http-handler': 4.7.3 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 + http-proxy-agent: 7.0.2(supports-color@8.1.1) + https-proxy-agent: 7.0.6(supports-color@8.1.1) openai: 6.26.0(ws@8.21.1)(zod@4.4.3) partial-json: 0.1.7 typebox: 1.1.38 @@ -12668,10 +12624,10 @@ snapshots: - ws - zod - '@earendil-works/pi-coding-agent@0.80.6(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(ws@8.21.1)(zod@4.4.3)': + '@earendil-works/pi-coding-agent@0.80.6(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(supports-color@8.1.1)(ws@8.21.1)(zod@4.4.3)': dependencies: - '@earendil-works/pi-agent-core': 0.80.6(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(ws@8.21.1)(zod@4.4.3) - '@earendil-works/pi-ai': 0.80.6(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(ws@8.21.1)(zod@4.4.3) + '@earendil-works/pi-agent-core': 0.80.6(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(supports-color@8.1.1)(ws@8.21.1)(zod@4.4.3) + '@earendil-works/pi-ai': 0.80.6(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(supports-color@8.1.1)(ws@8.21.1)(zod@4.4.3) '@earendil-works/pi-tui': 0.80.6 '@silvia-odwyer/photon-node': 0.3.4 chalk: 5.6.2 @@ -12717,16 +12673,16 @@ snapshots: dependencies: '@types/ws': 8.18.1 effect: 4.0.0-beta.98 - ws: 8.21.0 + ws: 8.21.1 transitivePeerDependencies: - bufferutil - utf-8-validate - '@effect/platform-node@4.0.0-beta.98(effect@4.0.0-beta.98)(ioredis@5.11.1)': + '@effect/platform-node@4.0.0-beta.98(effect@4.0.0-beta.98)(ioredis@5.11.1(supports-color@8.1.1))': dependencies: '@effect/platform-node-shared': 4.0.0-beta.98(effect@4.0.0-beta.98) effect: 4.0.0-beta.98 - ioredis: 5.11.1 + ioredis: 5.11.1(supports-color@8.1.1) mime: 4.1.0 undici: 8.7.0 transitivePeerDependencies: @@ -12748,7 +12704,7 @@ snapshots: '@electron/asar@4.2.1': dependencies: glob: 13.0.6 - minimatch: 10.2.5 + minimatch: 10.2.6 '@electron/fuses@1.8.0': dependencies: @@ -12756,45 +12712,45 @@ snapshots: fs-extra: 9.1.0 minimist: 1.2.8 - '@electron/get@3.1.0': + '@electron/get@3.1.0(supports-color@8.1.1)': dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) env-paths: 2.2.1 fs-extra: 8.1.0 got: 11.8.6 progress: 2.0.3 semver: 6.3.1 - sumchecker: 3.0.1 + sumchecker: 3.0.1(supports-color@8.1.1) optionalDependencies: global-agent: 3.0.0 transitivePeerDependencies: - supports-color - '@electron/get@5.0.0': + '@electron/get@5.0.0(supports-color@8.1.1)': dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) env-paths: 3.0.0 graceful-fs: 4.2.11 progress: 2.0.3 semver: 7.8.5 - sumchecker: 3.0.1 + sumchecker: 3.0.1(supports-color@8.1.1) optionalDependencies: undici: 7.28.0 transitivePeerDependencies: - supports-color - '@electron/notarize@2.5.0': + '@electron/notarize@2.5.0(supports-color@8.1.1)': dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) fs-extra: 9.1.0 promise-retry: 2.0.1 transitivePeerDependencies: - supports-color - '@electron/osx-sign@1.3.3': + '@electron/osx-sign@1.3.3(supports-color@8.1.1)': dependencies: compare-version: 0.1.2 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) fs-extra: 10.1.0 isbinaryfile: 4.0.10 minimist: 1.2.8 @@ -12802,22 +12758,22 @@ snapshots: transitivePeerDependencies: - supports-color - '@electron/rebuild@4.1.0': + '@electron/rebuild@4.1.0(supports-color@8.1.1)': dependencies: '@malept/cross-spawn-promise': 2.0.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) node-abi: 4.32.0 node-api-version: 0.2.1 node-gyp: 12.4.0 - read-binary-file-arch: 1.0.6 + read-binary-file-arch: 1.0.6(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@electron/universal@2.0.3': + '@electron/universal@2.0.3(supports-color@8.1.1)': dependencies: '@electron/asar': 3.4.1 '@malept/cross-spawn-promise': 2.0.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) dir-compare: 4.2.0 fs-extra: 11.3.6 minimatch: 9.0.9 @@ -12825,10 +12781,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@electron/windows-sign@1.2.2': + '@electron/windows-sign@1.2.2(supports-color@8.1.1)': dependencies: cross-dirname: 0.1.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) fs-extra: 11.3.6 minimist: 1.2.8 postject: 1.0.0-alpha.6 @@ -13034,25 +12990,25 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@eslint-community/eslint-plugin-eslint-comments@4.7.2(eslint@10.8.0(jiti@2.7.0))': + '@eslint-community/eslint-plugin-eslint-comments@4.7.2(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))': dependencies: escape-string-regexp: 4.0.0 - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) ignore: 7.0.5 - '@eslint-community/eslint-utils@4.10.1(eslint@10.8.0(jiti@2.7.0))': + '@eslint-community/eslint-utils@4.10.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))': dependencies: - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.9.1(eslint@10.8.0(jiti@2.7.0))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))': dependencies: - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint-sukka/eslint-plugin-react-jsx-a11y@8.14.2': + '@eslint-sukka/eslint-plugin-react-jsx-a11y@9.0.1': dependencies: '@nolyfill/array-includes': 1.0.44 '@nolyfill/array.prototype.flat': 1.0.44 @@ -13062,59 +13018,60 @@ snapshots: '@nolyfill/object.fromentries': 1.0.44 '@nolyfill/object.values': 1.0.44 - '@eslint-sukka/eslint-plugin-stylistic@8.14.2(eslint@10.8.0(jiti@2.7.0))': + '@eslint-sukka/eslint-plugin-stylistic@9.0.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))': dependencies: - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) - '@eslint-sukka/eslint-plugin-sukka-full@8.14.2(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0))': + '@eslint-sukka/eslint-plugin-sukka-full@9.0.1(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@eslint-sukka/shared': 8.14.2(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - eslint: 10.8.0(jiti@2.7.0) - eslint-plugin-sukka: 9.18.1(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) + '@eslint-sukka/shared': 9.0.1(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) + eslint-plugin-sukka: 10.2.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) optionalDependencies: typescript: '@typescript/typescript6@6.0.2' transitivePeerDependencies: - supports-color - '@eslint-sukka/react@8.14.2(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0))': + '@eslint-sukka/react@9.0.1(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@eslint-sukka/eslint-plugin-react-jsx-a11y': 8.14.2 - '@eslint-sukka/eslint-plugin-stylistic': 8.14.2(eslint@10.8.0(jiti@2.7.0)) - '@eslint-sukka/shared': 8.14.2(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - '@eslint/compat': 2.1.0(eslint@10.8.0(jiti@2.7.0)) - '@next/eslint-plugin-next': 16.2.12 + '@eslint-sukka/eslint-plugin-react-jsx-a11y': 9.0.1 + '@eslint-sukka/eslint-plugin-stylistic': 9.0.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + '@eslint-sukka/shared': 9.0.1(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + '@eslint/compat': 2.1.0(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + '@next/eslint-plugin-next': 16.3.2(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) '@stylexjs/eslint-plugin': 0.19.0 - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/utils': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - eslint-plugin-react-hooks: 7.1.1(eslint@10.8.0(jiti@2.7.0)) - eslint-plugin-ssr-friendly: 1.3.0(eslint@10.8.0(jiti@2.7.0)) - foxts: 5.8.1 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/utils': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + eslint-plugin-react-hooks: 7.1.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + eslint-plugin-ssr-friendly: 1.3.0(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + eslint-plugin-vibe-proof: 1.9.2(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + foxts: 5.9.1 transitivePeerDependencies: - eslint - supports-color - typescript - '@eslint-sukka/shared@8.14.2(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0))': + '@eslint-sukka/shared@9.0.1(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@package-json/types': 0.0.13 - '@typescript-eslint/utils': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - enhanced-resolve: 5.24.3 - eslint: 10.8.0(jiti@2.7.0) - foxts: 5.8.1 + '@typescript-eslint/utils': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + enhanced-resolve: 5.24.5 + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) + foxts: 5.9.1 transitivePeerDependencies: - supports-color - typescript - '@eslint/compat@2.1.0(eslint@10.8.0(jiti@2.7.0))': + '@eslint/compat@2.1.0(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))': dependencies: '@eslint/core': 1.2.1 optionalDependencies: - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) - '@eslint/config-array@0.23.5': + '@eslint/config-array@0.23.5(supports-color@8.1.1)': dependencies: '@eslint/object-schema': 3.0.5 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) minimatch: 10.2.6 transitivePeerDependencies: - supports-color @@ -13127,9 +13084,9 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/js@10.0.1(eslint@10.8.0(jiti@2.7.0))': + '@eslint/js@10.0.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))': optionalDependencies: - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) '@eslint/object-schema@3.0.5': {} @@ -13144,31 +13101,31 @@ snapshots: '@expo-google-fonts/material-symbols@0.4.38': {} - '@expo/cli@57.0.6(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-constants@57.0.3)(expo-font@57.0.0)(expo-router@57.0.4)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@expo/cli@57.0.6(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-constants@57.0.3)(expo-font@57.0.0)(expo-router@57.0.4)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)': dependencies: '@expo/code-signing-certificates': 0.0.6 - '@expo/config': 57.0.3(@typescript/typescript6@6.0.2) - '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2) - '@expo/devcert': 1.2.1 - '@expo/env': 2.4.1 - '@expo/image-utils': 0.11.1(@typescript/typescript6@6.0.2) - '@expo/inline-modules': 0.1.2(@typescript/typescript6@6.0.2) + '@expo/config': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@expo/devcert': 1.2.1(supports-color@8.1.1) + '@expo/env': 2.4.1(supports-color@8.1.1) + '@expo/image-utils': 0.11.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@expo/inline-modules': 0.1.2(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@expo/json-file': 11.0.0 - '@expo/log-box': 57.0.0(@expo/dom-webview@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - '@expo/metro': 56.0.0 - '@expo/metro-config': 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4) - '@expo/metro-file-map': 57.0.0 + '@expo/log-box': 57.0.0(@expo/dom-webview@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/metro': 56.0.0(supports-color@8.1.1) + '@expo/metro-config': 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(supports-color@8.1.1) + '@expo/metro-file-map': 57.0.0(supports-color@8.1.1) '@expo/osascript': 2.7.0 '@expo/package-manager': 1.13.0 '@expo/plist': 0.8.0 - '@expo/prebuild-config': 57.0.5(@typescript/typescript6@6.0.2) - '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2) - '@expo/router-server': 57.0.2(@expo/metro-runtime@57.0.3)(expo-constants@57.0.3)(expo-font@57.0.0)(expo-router@57.0.4)(expo-server@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@expo/prebuild-config': 57.0.5(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@expo/router-server': 57.0.2(@expo/metro-runtime@57.0.3)(expo-constants@57.0.3)(expo-font@57.0.0)(expo-router@57.0.4)(expo-server@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(supports-color@8.1.1) '@expo/schema-utils': 57.0.1 '@expo/spawn-async': 1.8.0 - '@expo/ws-tunnel': 2.0.0(ws@8.21.0) + '@expo/ws-tunnel': 2.0.0(ws@8.21.1) '@expo/xcpretty': 4.4.4 - '@react-native/dev-middleware': 0.86.0 + '@react-native/dev-middleware': 0.86.0(supports-color@8.1.1) accepts: 1.3.8 agent-cli-detector: 0.1.2 arg: 5.0.2 @@ -13176,11 +13133,11 @@ snapshots: bplist-parser: 0.3.2 chalk: 4.1.2 ci-info: 3.9.0 - compression: 1.8.1 - connect: 3.7.0 - debug: 4.4.3 + compression: 1.8.1(supports-color@8.1.1) + connect: 3.7.0(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) dnssd-advertise: 1.1.6 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-server: 57.0.0 fetch-nodeshim: 0.4.10 getenv: 2.0.0 @@ -13196,18 +13153,18 @@ snapshots: prompts: 2.4.2 resolve-from: 5.0.0 semver: 7.8.5 - send: 0.19.2 + send: 0.19.2(supports-color@8.1.1) slugify: 1.6.9 stacktrace-parser: 0.1.11 structured-headers: 0.4.1 terminal-link: 2.1.1 toqr: 0.1.1 wrap-ansi: 7.0.0 - ws: 8.21.0 + ws: 8.21.1 zod: 3.25.76 optionalDependencies: - expo-router: 57.0.4(a892d21e44c1d5a25ab382e32d303fb9) - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + expo-router: 57.0.4(3bc51b20989ed2c3020a920bb0eeb449) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - '@expo/dom-webview' - '@expo/metro-runtime' @@ -13225,15 +13182,15 @@ snapshots: dependencies: node-forge: 1.4.0 - '@expo/config-plugins@57.0.3(@typescript/typescript6@6.0.2)': + '@expo/config-plugins@57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1)': dependencies: '@expo/config-types': 57.0.1 '@expo/json-file': 11.0.0 '@expo/plist': 0.8.0 - '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2) + '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@expo/sdk-runtime-versions': 1.0.0 chalk: 4.1.2 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) getenv: 2.0.0 glob: 13.0.6 semver: 7.8.5 @@ -13246,12 +13203,12 @@ snapshots: '@expo/config-types@57.0.1': {} - '@expo/config@57.0.3(@typescript/typescript6@6.0.2)': + '@expo/config@57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1)': dependencies: - '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2) + '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@expo/config-types': 57.0.1 '@expo/json-file': 11.0.0 - '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2) + '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1) deepmerge: 4.3.1 getenv: 2.0.0 glob: 13.0.6 @@ -13262,55 +13219,55 @@ snapshots: - supports-color - typescript - '@expo/devcert@1.2.1': + '@expo/devcert@1.2.1(supports-color@8.1.1)': dependencies: '@expo/sudo-prompt': 9.3.2 - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@expo/devtools@57.0.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@expo/devtools@57.0.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: chalk: 4.1.2 optionalDependencies: react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - '@expo/dom-webview@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@expo/dom-webview@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - '@expo/env@2.4.1': + '@expo/env@2.4.1(supports-color@8.1.1)': dependencies: chalk: 4.1.2 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) getenv: 2.0.0 transitivePeerDependencies: - supports-color '@expo/expo-modules-macros-plugin@0.3.0': {} - '@expo/fingerprint@0.20.3': + '@expo/fingerprint@0.20.3(supports-color@8.1.1)': dependencies: - '@expo/env': 2.4.1 + '@expo/env': 2.4.1(supports-color@8.1.1) '@expo/spawn-async': 1.8.0 arg: 5.0.2 chalk: 4.1.2 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) getenv: 2.0.0 glob: 13.0.6 ignore: 5.3.2 - minimatch: 10.2.5 + minimatch: 10.2.6 resolve-from: 5.0.0 semver: 7.8.5 transitivePeerDependencies: - supports-color - '@expo/image-utils@0.11.1(@typescript/typescript6@6.0.2)': + '@expo/image-utils@0.11.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1)': dependencies: - '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2) + '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@expo/spawn-async': 1.8.0 chalk: 4.1.2 getenv: 2.0.0 @@ -13321,9 +13278,9 @@ snapshots: - supports-color - typescript - '@expo/inline-modules@0.1.2(@typescript/typescript6@6.0.2)': + '@expo/inline-modules@0.1.2(@typescript/typescript6@6.0.2)(supports-color@8.1.1)': dependencies: - '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2) + '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) transitivePeerDependencies: - supports-color - typescript @@ -13333,40 +13290,40 @@ snapshots: '@babel/code-frame': 7.29.7 json5: 2.2.3 - '@expo/local-build-cache-provider@57.0.2(@typescript/typescript6@6.0.2)': + '@expo/local-build-cache-provider@57.0.2(@typescript/typescript6@6.0.2)(supports-color@8.1.1)': dependencies: - '@expo/config': 57.0.3(@typescript/typescript6@6.0.2) + '@expo/config': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) chalk: 4.1.2 transitivePeerDependencies: - supports-color - typescript - '@expo/log-box@57.0.0(@expo/dom-webview@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@expo/log-box@57.0.0(@expo/dom-webview@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: - '@expo/dom-webview': 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + '@expo/dom-webview': 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) anser: 1.4.10 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) stacktrace-parser: 0.1.11 - '@expo/metro-config@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)': + '@expo/metro-config@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(supports-color@8.1.1)': dependencies: '@babel/code-frame': 7.29.7 - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/generator': 7.29.7 - '@expo/config': 57.0.3(@typescript/typescript6@6.0.2) - '@expo/env': 2.4.1 + '@expo/config': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@expo/env': 2.4.1(supports-color@8.1.1) '@expo/json-file': 11.0.0 - '@expo/metro': 56.0.0 - '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2) + '@expo/metro': 56.0.0(supports-color@8.1.1) + '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@expo/spawn-async': 1.8.0 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 browserslist: 4.28.4 chalk: 4.1.2 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) getenv: 2.0.0 glob: 13.0.6 hermes-parser: 0.36.1 @@ -13376,16 +13333,16 @@ snapshots: postcss: 8.5.24 resolve-from: 5.0.0 optionalDependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) transitivePeerDependencies: - bufferutil - supports-color - typescript - utf-8-validate - '@expo/metro-file-map@57.0.0': + '@expo/metro-file-map@57.0.0(supports-color@8.1.1)': dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) fb-watchman: 2.0.2 invariant: 2.2.4 jest-worker: 29.7.0 @@ -13394,35 +13351,35 @@ snapshots: transitivePeerDependencies: - supports-color - '@expo/metro-runtime@57.0.3(@expo/log-box@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@expo/metro-runtime@57.0.3(@expo/log-box@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: - '@expo/log-box': 57.0.0(@expo/dom-webview@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + '@expo/log-box': 57.0.0(@expo/dom-webview@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) anser: 1.4.10 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) pretty-format: 29.7.0 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) stacktrace-parser: 0.1.11 whatwg-fetch: 3.6.20 optionalDependencies: react-dom: 19.2.3(react@19.2.3) - '@expo/metro@56.0.0': + '@expo/metro@56.0.0(supports-color@8.1.1)': dependencies: - metro: 0.84.4 - metro-babel-transformer: 0.84.4 - metro-cache: 0.84.4 + metro: 0.84.4(supports-color@8.1.1) + metro-babel-transformer: 0.84.4(supports-color@8.1.1) + metro-cache: 0.84.4(supports-color@8.1.1) metro-cache-key: 0.84.4 - metro-config: 0.84.4 + metro-config: 0.84.4(supports-color@8.1.1) metro-core: 0.84.4 - metro-file-map: 0.84.4 + metro-file-map: 0.84.4(supports-color@8.1.1) metro-minify-terser: 0.84.4 metro-resolver: 0.84.4 metro-runtime: 0.84.4 - metro-source-map: 0.84.4 - metro-symbolicate: 0.84.4 - metro-transform-plugins: 0.84.4 - metro-transform-worker: 0.84.4 + metro-source-map: 0.84.4(supports-color@8.1.1) + metro-symbolicate: 0.84.4(supports-color@8.1.1) + metro-transform-plugins: 0.84.4(supports-color@8.1.1) + metro-transform-worker: 0.84.4(supports-color@8.1.1) transitivePeerDependencies: - bufferutil - supports-color @@ -13453,43 +13410,43 @@ snapshots: base64-js: 1.5.1 xmlbuilder: 15.1.1 - '@expo/prebuild-config@57.0.5(@typescript/typescript6@6.0.2)': + '@expo/prebuild-config@57.0.5(@typescript/typescript6@6.0.2)(supports-color@8.1.1)': dependencies: - '@expo/config': 57.0.3(@typescript/typescript6@6.0.2) - '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2) + '@expo/config': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@expo/config-types': 57.0.1 - '@expo/image-utils': 0.11.1(@typescript/typescript6@6.0.2) + '@expo/image-utils': 0.11.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@expo/json-file': 11.0.0 '@react-native/normalize-colors': 0.86.0 - debug: 4.4.3 - expo-modules-autolinking: 57.0.5(@typescript/typescript6@6.0.2) + debug: 4.4.3(supports-color@8.1.1) + expo-modules-autolinking: 57.0.5(@typescript/typescript6@6.0.2)(supports-color@8.1.1) resolve-from: 5.0.0 semver: 7.8.5 transitivePeerDependencies: - supports-color - typescript - '@expo/require-utils@57.0.1(@typescript/typescript6@6.0.2)': + '@expo/require-utils@57.0.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1)': dependencies: '@babel/code-frame': 7.29.7 - '@babel/core': 7.29.7 - '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) optionalDependencies: typescript: '@typescript/typescript6@6.0.2' transitivePeerDependencies: - supports-color - '@expo/router-server@57.0.2(@expo/metro-runtime@57.0.3)(expo-constants@57.0.3)(expo-font@57.0.0)(expo-router@57.0.4)(expo-server@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@expo/router-server@57.0.2(@expo/metro-runtime@57.0.3)(expo-constants@57.0.3)(expo-font@57.0.0)(expo-router@57.0.4)(expo-server@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(supports-color@8.1.1)': dependencies: - debug: 4.4.3 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) - expo-font: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + debug: 4.4.3(supports-color@8.1.1) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) + expo-font: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-server: 57.0.0 react: 19.2.3 optionalDependencies: - '@expo/metro-runtime': 57.0.3(@expo/log-box@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-router: 57.0.4(a892d21e44c1d5a25ab382e32d303fb9) + '@expo/metro-runtime': 57.0.3(@expo/log-box@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + expo-router: 57.0.4(3bc51b20989ed2c3020a920bb0eeb449) react-dom: 19.2.3(react@19.2.3) transitivePeerDependencies: - supports-color @@ -13504,24 +13461,24 @@ snapshots: '@expo/sudo-prompt@9.3.2': {} - '@expo/ui@57.0.7(@babel/core@7.29.7)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@expo/ui@57.0.7(@babel/core@7.29.7(supports-color@8.1.1))(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) sf-symbols-typescript: 2.2.0 vaul: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) optionalDependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) react-dom: 19.2.3(react@19.2.3) - react-native-worklets: 0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native-worklets: 0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - '@types/react' - '@types/react-dom' - '@expo/ws-tunnel@2.0.0(ws@8.21.0)': + '@expo/ws-tunnel@2.0.0(ws@8.21.1)': dependencies: - ws: 8.21.0 + ws: 8.21.1 '@expo/xcpretty@4.4.4': dependencies: @@ -13570,53 +13527,53 @@ snapshots: '@gar/promise-retry@1.0.3': {} - '@google/genai@1.52.0(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))': + '@google/genai@1.52.0(@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3))(supports-color@8.1.1)': dependencies: - google-auth-library: 10.7.0 + google-auth-library: 10.7.0(supports-color@8.1.1) p-retry: 4.6.2 protobufjs: 7.6.5 - ws: 8.21.0 + ws: 8.21.1 optionalDependencies: - '@modelcontextprotocol/sdk': 1.30.0(zod@4.4.3) + '@modelcontextprotocol/sdk': 1.30.0(supports-color@8.1.1)(zod@4.4.3) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - '@gorhom/bottom-sheet@5.2.14(@types/react@19.2.17)(react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@gorhom/bottom-sheet@5.2.14(6e44dcb7dcfecf271936e923703300f2)': dependencies: - '@gorhom/portal': 1.0.14(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + '@gorhom/portal': 1.0.14(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) invariant: 2.2.4 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) - react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) + react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) optionalDependencies: '@types/react': 19.2.17 - '@gorhom/bottom-sheet@5.2.14(@types/react@19.2.17)(react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728))(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)': + '@gorhom/bottom-sheet@5.2.14(da77d43574db60c81967e07362a6f6fb)': dependencies: - '@gorhom/portal': 1.0.14(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + '@gorhom/portal': 1.0.14(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) invariant: 2.2.4 react: 19.3.0-canary-96fcba90-20260728 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) - react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) - react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) + react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) + react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) optionalDependencies: '@types/react': 19.2.17 optional: true - '@gorhom/portal@1.0.14(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@gorhom/portal@1.0.14(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: nanoid: 3.3.16 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - '@gorhom/portal@1.0.14(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)': + '@gorhom/portal@1.0.14(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728)': dependencies: nanoid: 3.3.16 react: 19.3.0-canary-96fcba90-20260728 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) optional: true '@hono/node-server@2.0.12(hono@4.12.32)': @@ -13968,9 +13925,9 @@ snapshots: dependencies: cross-spawn: 7.0.6 - '@malept/flatpak-bundler@0.4.0': + '@malept/flatpak-bundler@0.4.0(supports-color@8.1.1)': dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) fs-extra: 9.1.0 lodash: 4.18.1 tmp-promise: 3.0.3 @@ -14029,8 +13986,8 @@ snapshots: '@mistralai/mistralai@2.2.6(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/semantic-conventions': 1.41.1 - ws: 8.21.0 + '@opentelemetry/semantic-conventions': 1.43.0 + ws: 8.21.1 zod: 4.4.3 zod-to-json-schema: 3.25.2(zod@4.4.3) optionalDependencies: @@ -14039,7 +13996,7 @@ snapshots: - bufferutil - utf-8-validate - '@modelcontextprotocol/sdk@1.30.0(zod@4.4.3)': + '@modelcontextprotocol/sdk@1.30.0(supports-color@8.1.1)(zod@4.4.3)': dependencies: '@hono/node-server': 2.0.12(hono@4.12.32) ajv: 8.20.0 @@ -14049,8 +14006,8 @@ snapshots: cross-spawn: 7.0.6 eventsource: 3.0.7 eventsource-parser: 3.1.0 - express: 5.2.1 - express-rate-limit: 8.6.1(express@5.2.1) + express: 5.2.1(supports-color@8.1.1) + express-rate-limit: 8.6.1(express@5.2.1(supports-color@8.1.1))(supports-color@8.1.1) hono: 4.12.32 jose: 6.2.7 json-schema-typed: 8.0.2 @@ -14061,12 +14018,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@moeru/eventa@1.0.0-beta.12(electron@43.2.0)(hono@4.12.32)': + '@moeru/eventa@1.0.0-beta.12(electron@43.2.0(supports-color@8.1.1))(hono@4.12.32)': dependencies: nanoid: 6.0.0 picomatch: 4.0.5 optionalDependencies: - electron: 43.2.0 + electron: 43.2.0(supports-color@8.1.1) hono: 4.12.32 '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': @@ -14152,9 +14109,12 @@ snapshots: '@tybys/wasm-util': 0.10.3 optional: true - '@next/eslint-plugin-next@16.2.12': + '@next/eslint-plugin-next@16.3.2(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))': dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) fast-glob: 3.3.1 + transitivePeerDependencies: + - eslint '@noble/ciphers@2.2.0': {} @@ -14206,13 +14166,13 @@ snapshots: '@nolyfill/shared@1.0.44': {} - '@npmcli/agent@5.0.2': + '@npmcli/agent@5.0.2(supports-color@8.1.1)': dependencies: agent-base: 9.0.0 - http-proxy-agent: 9.1.0 - https-proxy-agent: 9.1.0 + http-proxy-agent: 9.1.0(supports-color@8.1.1) + https-proxy-agent: 9.1.0(supports-color@8.1.1) lru-cache: 11.5.1 - socks-proxy-agent: 10.1.0 + socks-proxy-agent: 10.1.0(supports-color@8.1.1) transitivePeerDependencies: - kerberos - supports-color @@ -14267,12 +14227,12 @@ snapshots: '@opentelemetry/api': 1.9.1 '@opentelemetry/semantic-conventions': 1.43.0 - '@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)(supports-color@8.1.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.214.0 import-in-the-middle: 3.2.0 - require-in-the-middle: 8.0.1 + require-in-the-middle: 8.0.1(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -14297,8 +14257,6 @@ snapshots: '@opentelemetry/resources': 2.9.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.43.0 - '@opentelemetry/semantic-conventions@1.41.1': {} - '@opentelemetry/semantic-conventions@1.43.0': {} '@ota-meshi/ast-token-store@0.3.0': {} @@ -14385,16 +14343,10 @@ snapshots: '@posthog/core': 1.46.1 '@posthog/types': 1.399.0 - '@posthog/core@1.45.1': - dependencies: - '@posthog/types': 1.399.0 - '@posthog/core@1.46.1': dependencies: '@posthog/types': 1.399.0 - '@posthog/types@1.398.0': {} - '@posthog/types@1.399.0': {} '@preact/signals-core@1.14.3': {} @@ -14616,67 +14568,67 @@ snapshots: optionalDependencies: '@types/react': 19.2.17 - '@react-native-community/netinfo@12.0.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@react-native-community/netinfo@12.0.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - '@react-native-masked-view/masked-view@0.3.2(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@react-native-masked-view/masked-view@0.3.2(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) '@react-native/assets-registry@0.86.0': {} - '@react-native/babel-plugin-codegen@0.86.0(@babel/core@7.29.7)': + '@react-native/babel-plugin-codegen@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/traverse': 7.29.7 - '@react-native/codegen': 0.86.0(@babel/core@7.29.7) + '@babel/traverse': 7.29.7(supports-color@8.1.1) + '@react-native/codegen': 0.86.0(@babel/core@7.29.7(supports-color@8.1.1)) transitivePeerDependencies: - '@babel/core' - supports-color - '@react-native/babel-preset@0.86.0(@babel/core@7.29.7)': - dependencies: - '@babel/core': 7.29.7 - '@babel/plugin-proposal-export-default-from': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7) - '@babel/plugin-syntax-export-default-from': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7) - '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-block-scoping': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-flow-strip-types': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-regenerator': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7) - '@react-native/babel-plugin-codegen': 0.86.0(@babel/core@7.29.7) + '@react-native/babel-preset@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/plugin-proposal-export-default-from': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-export-default-from': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-block-scoping': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-flow-strip-types': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-regenerator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@react-native/babel-plugin-codegen': 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) babel-plugin-syntax-hermes-parser: 0.36.0 - babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.7) + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.7(supports-color@8.1.1)) react-refresh: 0.14.2 transitivePeerDependencies: - supports-color - '@react-native/codegen@0.86.0(@babel/core@7.29.7)': + '@react-native/codegen@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/parser': 7.29.7 hermes-parser: 0.36.0 invariant: 2.2.4 @@ -14684,17 +14636,17 @@ snapshots: tinyglobby: 0.2.17 yargs: 17.7.3 - '@react-native/community-cli-plugin@0.86.0(@react-native/metro-config@0.86.0(@babel/core@7.29.7))': + '@react-native/community-cli-plugin@0.86.0(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@react-native/dev-middleware': 0.86.0 - debug: 4.4.3 + '@react-native/dev-middleware': 0.86.0(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) invariant: 2.2.4 - metro: 0.84.4 - metro-config: 0.84.4 + metro: 0.84.4(supports-color@8.1.1) + metro-config: 0.84.4(supports-color@8.1.1) metro-core: 0.84.4 semver: 7.8.5 optionalDependencies: - '@react-native/metro-config': 0.86.0(@babel/core@7.29.7) + '@react-native/metro-config': 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) transitivePeerDependencies: - bufferutil - supports-color @@ -14702,27 +14654,27 @@ snapshots: '@react-native/debugger-frontend@0.86.0': {} - '@react-native/debugger-shell@0.86.0': + '@react-native/debugger-shell@0.86.0(supports-color@8.1.1)': dependencies: cross-spawn: 7.0.6 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) fb-dotslash: 0.5.8 transitivePeerDependencies: - supports-color - '@react-native/dev-middleware@0.86.0': + '@react-native/dev-middleware@0.86.0(supports-color@8.1.1)': dependencies: '@isaacs/ttlcache': 1.4.1 '@react-native/debugger-frontend': 0.86.0 - '@react-native/debugger-shell': 0.86.0 - chrome-launcher: 0.15.2 - chromium-edge-launcher: 0.3.0 - connect: 3.7.0 - debug: 4.4.3 + '@react-native/debugger-shell': 0.86.0(supports-color@8.1.1) + chrome-launcher: 0.15.2(supports-color@8.1.1) + chromium-edge-launcher: 0.3.0(supports-color@8.1.1) + connect: 3.7.0(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) invariant: 2.2.4 nullthrows: 1.1.1 open: 7.4.2 - serve-static: 1.16.3 + serve-static: 1.16.3(supports-color@8.1.1) ws: 7.5.11 transitivePeerDependencies: - bufferutil @@ -14733,20 +14685,20 @@ snapshots: '@react-native/js-polyfills@0.86.0': {} - '@react-native/metro-babel-transformer@0.86.0(@babel/core@7.29.7)': + '@react-native/metro-babel-transformer@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@react-native/babel-preset': 0.86.0(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@react-native/babel-preset': 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) hermes-parser: 0.36.0 nullthrows: 1.1.1 transitivePeerDependencies: - supports-color - '@react-native/metro-config@0.86.0(@babel/core@7.29.7)': + '@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@react-native/js-polyfills': 0.86.0 - '@react-native/metro-babel-transformer': 0.86.0(@babel/core@7.29.7) - metro-config: 0.84.4 + '@react-native/metro-babel-transformer': 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + metro-config: 0.84.4(supports-color@8.1.1) metro-runtime: 0.84.4 transitivePeerDependencies: - '@babel/core' @@ -14760,21 +14712,21 @@ snapshots: '@react-native/normalize-colors@0.86.0': {} - '@react-native/virtualized-lists@0.86.0(@types/react@19.2.17)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@react-native/virtualized-lists@0.86.0(@types/react@19.2.17)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)': dependencies: invariant: 2.2.4 nullthrows: 1.1.1 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) optionalDependencies: '@types/react': 19.2.17 - '@react-native/virtualized-lists@0.86.0(@types/react@19.2.17)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)': + '@react-native/virtualized-lists@0.86.0(@types/react@19.2.17)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728)': dependencies: invariant: 2.2.4 nullthrows: 1.1.1 react: 19.3.0-canary-96fcba90-20260728 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) optionalDependencies: '@types/react': 19.2.17 @@ -14827,13 +14779,13 @@ snapshots: '@rolldown/binding-win32-x64-msvc@1.1.5': optional: true - '@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))': + '@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7(supports-color@8.1.1))(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) picomatch: 4.0.5 rolldown: 1.1.5 optionalDependencies: - '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/runtime': 7.29.7 vite: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0) @@ -14980,9 +14932,9 @@ snapshots: '@sentry/cli-win32-x64@2.58.4': optional: true - '@sentry/cli@2.58.4': + '@sentry/cli@2.58.4(supports-color@8.1.1)': dependencies: - https-proxy-agent: 5.0.1 + https-proxy-agent: 5.0.1(supports-color@8.1.1) node-fetch: 2.7.0 progress: 2.0.3 proxy-from-env: 1.1.0 @@ -15006,11 +14958,11 @@ snapshots: '@sentry/core@10.62.0': {} - '@sentry/electron@7.15.0': + '@sentry/electron@7.15.0(supports-color@8.1.1)': dependencies: '@sentry/browser': 10.62.0 '@sentry/core': 10.62.0 - '@sentry/node': 10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1)) + '@sentry/node': 10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(supports-color@8.1.1) transitivePeerDependencies: - '@opentelemetry/core' - '@opentelemetry/exporter-trace-otlp-http' @@ -15020,7 +14972,7 @@ snapshots: dependencies: '@sentry/core': 10.62.0 - '@sentry/node-core@10.62.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.9.0(@opentelemetry/api@1.9.1))': + '@sentry/node-core@10.62.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@2.9.0(@opentelemetry/api@1.9.1))': dependencies: '@sentry/conventions': 0.12.0 '@sentry/core': 10.62.0 @@ -15029,7 +14981,7 @@ snapshots: optionalDependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.9.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)(supports-color@8.1.1) '@opentelemetry/sdk-trace-base': 2.9.0(@opentelemetry/api@1.9.1) '@sentry/node-cpu-profiler@2.4.2': @@ -15037,16 +14989,16 @@ snapshots: detect-libc: 2.1.2 node-abi: 3.92.0 - '@sentry/node@10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))': + '@sentry/node@10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(supports-color@8.1.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)(supports-color@8.1.1) '@opentelemetry/sdk-trace-base': 2.9.0(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 + '@opentelemetry/semantic-conventions': 1.43.0 '@sentry/core': 10.62.0 - '@sentry/node-core': 10.62.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.9.0(@opentelemetry/api@1.9.1)) + '@sentry/node-core': 10.62.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@2.9.0(@opentelemetry/api@1.9.1)) '@sentry/opentelemetry': 10.62.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.9.0(@opentelemetry/api@1.9.1)) - '@sentry/server-utils': 10.62.0 + '@sentry/server-utils': 10.62.0(supports-color@8.1.1) import-in-the-middle: 3.2.0 transitivePeerDependencies: - '@opentelemetry/core' @@ -15061,28 +15013,28 @@ snapshots: '@sentry/conventions': 0.12.0 '@sentry/core': 10.62.0 - '@sentry/profiling-node@10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))': + '@sentry/profiling-node@10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(supports-color@8.1.1)': dependencies: '@sentry/core': 10.62.0 - '@sentry/node': 10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1)) + '@sentry/node': 10.62.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(supports-color@8.1.1) '@sentry/node-cpu-profiler': 2.4.2 transitivePeerDependencies: - '@opentelemetry/core' - '@opentelemetry/exporter-trace-otlp-http' - supports-color - '@sentry/react-native@7.11.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)': + '@sentry/react-native@7.11.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1)': dependencies: '@sentry/babel-plugin-component-annotate': 4.8.0 '@sentry/browser': 10.37.0 - '@sentry/cli': 2.58.4 + '@sentry/cli': 2.58.4(supports-color@8.1.1) '@sentry/core': 10.37.0 '@sentry/react': 10.37.0(react@19.2.3) '@sentry/types': 10.37.0 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) optionalDependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) transitivePeerDependencies: - encoding - supports-color @@ -15109,11 +15061,11 @@ snapshots: '@sentry/browser-utils': 10.62.0 '@sentry/core': 10.62.0 - '@sentry/server-utils@10.62.0': + '@sentry/server-utils@10.62.0(supports-color@8.1.1)': dependencies: '@apm-js-collab/code-transformer': 0.15.0 '@apm-js-collab/code-transformer-bundler-plugins': 0.5.0 - '@apm-js-collab/tracing-hooks': 0.10.1 + '@apm-js-collab/tracing-hooks': 0.10.1(supports-color@8.1.1) '@sentry/conventions': 0.12.0 '@sentry/core': 10.62.0 magic-string: 0.30.21 @@ -15270,11 +15222,11 @@ snapshots: '@standard-schema/utils@0.3.0': {} - '@streamdown/cjk@1.0.3(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(react@19.3.0-canary-96fcba90-20260728)(unified@11.0.5)': + '@streamdown/cjk@1.0.3(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1)(unified@11.0.5)': dependencies: react: 19.3.0-canary-96fcba90-20260728 - remark-cjk-friendly: 2.3.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(unified@11.0.5) - remark-cjk-friendly-gfm-strikethrough: 2.3.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(unified@11.0.5) + remark-cjk-friendly: 2.3.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@8.1.1))(unified@11.0.5) + remark-cjk-friendly-gfm-strikethrough: 2.3.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@8.1.1))(supports-color@8.1.1)(unified@11.0.5) unist-util-visit: 5.1.0 transitivePeerDependencies: - '@types/mdast' @@ -15297,54 +15249,54 @@ snapshots: '@stylexjs/shared@0.19.0': {} - '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.29.7)': + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) - '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.29.7)': + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) - '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.29.7)': + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) - '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.29.7)': + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) - '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.29.7)': + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) - '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.29.7)': + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) - '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.29.7)': + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) - '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.29.7)': + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) - '@svgr/babel-preset@8.1.0(@babel/core@7.29.7)': + '@svgr/babel-preset@8.1.0(@babel/core@7.29.7(supports-color@8.1.1))': dependencies: - '@babel/core': 7.29.7 - '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.29.7) - '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.29.7) - '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.29.7) - '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.29.7) - '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.29.7) - '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.29.7) - '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.29.7) - '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.29.7(supports-color@8.1.1)) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.29.7(supports-color@8.1.1)) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.29.7(supports-color@8.1.1)) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.29.7(supports-color@8.1.1)) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.29.7(supports-color@8.1.1)) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.29.7(supports-color@8.1.1)) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.29.7(supports-color@8.1.1)) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.29.7(supports-color@8.1.1)) - '@svgr/core@8.1.0(@typescript/typescript6@6.0.2)': + '@svgr/core@8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@svgr/babel-preset': 8.1.0(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@svgr/babel-preset': 8.1.0(@babel/core@7.29.7(supports-color@8.1.1)) camelcase: 6.3.0 cosmiconfig: 8.3.6(@typescript/typescript6@6.0.2) snake-case: 3.0.4 @@ -15357,11 +15309,11 @@ snapshots: '@babel/types': 7.29.7 entities: 4.5.0 - '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(@typescript/typescript6@6.0.2))': + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@babel/core': 7.29.7 - '@svgr/babel-preset': 8.1.0(@babel/core@7.29.7) - '@svgr/core': 8.1.0(@typescript/typescript6@6.0.2) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@svgr/babel-preset': 8.1.0(@babel/core@7.29.7(supports-color@8.1.1)) + '@svgr/core': 8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: @@ -15376,7 +15328,7 @@ snapshots: '@tailwindcss/node@4.3.0': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.24.3 + enhanced-resolve: 5.24.5 jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 @@ -15386,7 +15338,7 @@ snapshots: '@tailwindcss/node@4.3.3': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.24.3 + enhanced-resolve: 5.24.5 jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 @@ -15815,15 +15767,15 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0))': + '@typescript-eslint/eslint-plugin@8.68.0(@typescript-eslint/parser@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/type-utils': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - '@typescript-eslint/utils': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - '@typescript-eslint/visitor-keys': 8.65.0 - eslint: 10.8.0(jiti@2.7.0) + '@typescript-eslint/parser': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + '@typescript-eslint/scope-manager': 8.68.0 + '@typescript-eslint/type-utils': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + '@typescript-eslint/utils': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + '@typescript-eslint/visitor-keys': 8.68.0 + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(@typescript/typescript6@6.0.2) @@ -15831,57 +15783,57 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0))': + '@typescript-eslint/parser@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(@typescript/typescript6@6.0.2) - '@typescript-eslint/visitor-keys': 8.65.0 - debug: 4.4.3 - eslint: 10.8.0(jiti@2.7.0) + '@typescript-eslint/scope-manager': 8.68.0 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/typescript-estree': 8.68.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@typescript-eslint/visitor-keys': 8.68.0 + debug: 4.4.3(supports-color@8.1.1) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) typescript: '@typescript/typescript6@6.0.2' transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.65.0(@typescript/typescript6@6.0.2)': + '@typescript-eslint/project-service@8.68.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.65.0(@typescript/typescript6@6.0.2) - '@typescript-eslint/types': 8.65.0 - debug: 4.4.3 + '@typescript-eslint/tsconfig-utils': 8.68.0(@typescript/typescript6@6.0.2) + '@typescript-eslint/types': 8.68.0 + debug: 4.4.3(supports-color@8.1.1) typescript: '@typescript/typescript6@6.0.2' transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.65.0': + '@typescript-eslint/scope-manager@8.68.0': dependencies: - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/visitor-keys': 8.65.0 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/visitor-keys': 8.68.0 - '@typescript-eslint/tsconfig-utils@8.65.0(@typescript/typescript6@6.0.2)': + '@typescript-eslint/tsconfig-utils@8.68.0(@typescript/typescript6@6.0.2)': dependencies: typescript: '@typescript/typescript6@6.0.2' - '@typescript-eslint/type-utils@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0))': + '@typescript-eslint/type-utils@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(@typescript/typescript6@6.0.2) - '@typescript-eslint/utils': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - debug: 4.4.3 - eslint: 10.8.0(jiti@2.7.0) + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/typescript-estree': 8.68.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@typescript-eslint/utils': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) ts-api-utils: 2.5.0(@typescript/typescript6@6.0.2) typescript: '@typescript/typescript6@6.0.2' transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.65.0': {} + '@typescript-eslint/types@8.68.0': {} - '@typescript-eslint/typescript-estree@8.65.0(@typescript/typescript6@6.0.2)': + '@typescript-eslint/typescript-estree@8.68.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1)': dependencies: - '@typescript-eslint/project-service': 8.65.0(@typescript/typescript6@6.0.2) - '@typescript-eslint/tsconfig-utils': 8.65.0(@typescript/typescript6@6.0.2) - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/visitor-keys': 8.65.0 - debug: 4.4.3 + '@typescript-eslint/project-service': 8.68.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@typescript-eslint/tsconfig-utils': 8.68.0(@typescript/typescript6@6.0.2) + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/visitor-keys': 8.68.0 + debug: 4.4.3(supports-color@8.1.1) minimatch: 10.2.6 semver: 7.8.5 tinyglobby: 0.2.17 @@ -15890,20 +15842,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0))': + '@typescript-eslint/utils@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: - '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.0(jiti@2.7.0)) - '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(@typescript/typescript6@6.0.2) - eslint: 10.8.0(jiti@2.7.0) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + '@typescript-eslint/scope-manager': 8.68.0 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/typescript-estree': 8.68.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) typescript: '@typescript/typescript6@6.0.2' transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.65.0': + '@typescript-eslint/visitor-keys@8.68.0': dependencies: - '@typescript-eslint/types': 8.65.0 + '@typescript-eslint/types': 8.68.0 eslint-visitor-keys: 5.0.1 '@typescript/typescript-aix-ppc64@7.0.2': @@ -16047,12 +15999,12 @@ snapshots: d3-selection: 3.0.0 d3-transition: 3.0.1(d3-selection@3.0.0) - '@vitejs/plugin-react@6.0.4(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)))(babel-plugin-react-compiler@1.0.0)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))': + '@vitejs/plugin-react@6.0.4(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7(supports-color@8.1.1))(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)))(babel-plugin-react-compiler@1.0.0)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 vite: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0) optionalDependencies: - '@rolldown/plugin-babel': 0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) + '@rolldown/plugin-babel': 0.2.3(@babel/core@7.29.7(supports-color@8.1.1))(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@babel/runtime@7.29.7)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.1)(yaml@2.9.0)) babel-plugin-react-compiler: 1.0.0 '@vitest/expect@4.1.10': @@ -16116,21 +16068,19 @@ snapshots: mime-types: 3.0.2 negotiator: 1.0.0 - acorn-import-attributes@1.9.5(acorn@8.17.0): + acorn-import-attributes@1.9.5(acorn@8.18.0): dependencies: - acorn: 8.17.0 + acorn: 8.18.0 acorn-jsx@5.3.2(acorn@8.18.0): dependencies: acorn: 8.18.0 - acorn@8.17.0: {} - acorn@8.18.0: {} - agent-base@6.0.2: + agent-base@6.0.2(supports-color@8.1.1): dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -16196,33 +16146,33 @@ snapshots: anynum@1.0.0: {} - app-builder-lib@26.15.3(dmg-builder@26.15.3)(electron-builder-squirrel-windows@26.15.3): + app-builder-lib@26.15.3(dmg-builder@26.15.3)(electron-builder-squirrel-windows@26.15.3)(supports-color@8.1.1): dependencies: '@electron/asar': 3.4.1 '@electron/fuses': 1.8.0 - '@electron/get': 3.1.0 - '@electron/notarize': 2.5.0 - '@electron/osx-sign': 1.3.3 - '@electron/rebuild': 4.1.0 - '@electron/universal': 2.0.3 - '@malept/flatpak-bundler': 0.4.0 + '@electron/get': 3.1.0(supports-color@8.1.1) + '@electron/notarize': 2.5.0(supports-color@8.1.1) + '@electron/osx-sign': 1.3.3(supports-color@8.1.1) + '@electron/rebuild': 4.1.0(supports-color@8.1.1) + '@electron/universal': 2.0.3(supports-color@8.1.1) + '@malept/flatpak-bundler': 0.4.0(supports-color@8.1.1) '@noble/hashes': 2.2.0 '@peculiar/webcrypto': 1.7.1 '@types/fs-extra': 9.0.13 ajv: 8.20.0 asn1js: 3.0.10 async-exit-hook: 2.0.1 - builder-util: 26.15.3 - builder-util-runtime: 9.7.0 + builder-util: 26.15.3(supports-color@8.1.1) + builder-util-runtime: 9.7.0(supports-color@8.1.1) chromium-pickle-js: 0.2.0 ci-info: 4.3.1 - debug: 4.4.3 - dmg-builder: 26.15.3(electron-builder-squirrel-windows@26.15.3) + debug: 4.4.3(supports-color@8.1.1) + dmg-builder: 26.15.3(electron-builder-squirrel-windows@26.15.3)(supports-color@8.1.1) dotenv: 16.6.1 dotenv-expand: 11.0.7 ejs: 3.1.10 - electron-builder-squirrel-windows: 26.15.3(dmg-builder@26.15.3) - electron-publish: 26.15.3 + electron-builder-squirrel-windows: 26.15.3(dmg-builder@26.15.3)(supports-color@8.1.1) + electron-publish: 26.15.3(supports-color@8.1.1) fs-extra: 10.1.0 hosted-git-info: 4.1.0 isbinaryfile: 5.0.7 @@ -16286,27 +16236,27 @@ snapshots: aws4@1.13.2: {} - babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.29.7): + babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): dependencies: '@babel/compat-data': 7.29.7 - '@babel/core': 7.29.7 - '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.29.7): + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - '@babel/core': 7.29.7 - '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) core-js-compat: 3.49.0 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.29.7): + babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - '@babel/core': 7.29.7 - '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7) + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -16324,60 +16274,60 @@ snapshots: dependencies: hermes-parser: 0.36.1 - babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.29.7): + babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.29.7(supports-color@8.1.1)): dependencies: - '@babel/plugin-syntax-flow': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-flow': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) transitivePeerDependencies: - '@babel/core' - babel-preset-expo@57.0.2(@babel/core@7.29.7)(@babel/runtime@7.29.7)(expo@57.0.4)(react-refresh@0.14.2): + babel-preset-expo@57.0.2(@babel/core@7.29.7(supports-color@8.1.1))(@babel/runtime@7.29.7)(expo@57.0.4)(react-refresh@0.14.2)(supports-color@8.1.1): dependencies: '@babel/generator': 7.29.7 - '@babel/helper-module-imports': 7.29.7 - '@babel/plugin-proposal-decorators': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-proposal-export-default-from': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7) - '@babel/plugin-syntax-export-default-from': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7) - '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-block-scoping': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-class-static-block': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-export-namespace-from': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-flow-strip-types': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-logical-assignment-operators': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-object-rest-spread': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-jsx-development': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-pure-annotations': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7) - '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7) - '@react-native/babel-plugin-codegen': 0.86.0(@babel/core@7.29.7) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/plugin-proposal-decorators': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-proposal-export-default-from': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-export-default-from': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-block-scoping': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-class-static-block': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-export-namespace-from': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-flow-strip-types': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-logical-assignment-operators': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-object-rest-spread': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-react-jsx-development': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-react-pure-annotations': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@react-native/babel-plugin-codegen': 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) babel-plugin-react-compiler: 1.0.0 babel-plugin-react-native-web: 0.21.2 babel-plugin-syntax-hermes-parser: 0.36.1 - babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.7) - debug: 4.4.3 + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.7(supports-color@8.1.1)) + debug: 4.4.3(supports-color@8.1.1) react-refresh: 0.14.2 optionalDependencies: '@babel/runtime': 7.29.7 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) transitivePeerDependencies: - '@babel/core' - supports-color @@ -16503,11 +16453,11 @@ snapshots: bluebird@3.7.2: {} - body-parser@2.3.0: + body-parser@2.3.0(supports-color@8.1.1): dependencies: bytes: 3.1.2 content-type: 2.0.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) http-errors: 2.0.1 iconv-lite: 0.7.3 on-finished: 2.4.1 @@ -16545,10 +16495,6 @@ snapshots: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.8: - dependencies: - balanced-match: 4.0.4 - brace-expansion@5.0.9: dependencies: balanced-match: 4.0.4 @@ -16583,23 +16529,23 @@ snapshots: ieee754: 1.2.1 optional: true - builder-util-runtime@9.7.0: + builder-util-runtime@9.7.0(supports-color@8.1.1): dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) sax: 1.6.0 transitivePeerDependencies: - supports-color - builder-util@26.15.3: + builder-util@26.15.3(supports-color@8.1.1): dependencies: '@types/debug': 4.1.13 - builder-util-runtime: 9.7.0 + builder-util-runtime: 9.7.0(supports-color@8.1.1) chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) fs-extra: 10.1.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 + http-proxy-agent: 7.0.2(supports-color@8.1.1) + https-proxy-agent: 7.0.6(supports-color@8.1.1) js-yaml: 4.3.0 sanitize-filename: 1.6.4 source-map-support: 0.5.21 @@ -16697,21 +16643,21 @@ snapshots: chownr@3.0.0: {} - chrome-launcher@0.15.2: + chrome-launcher@0.15.2(supports-color@8.1.1): dependencies: '@types/node': 26.1.1 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 - lighthouse-logger: 1.4.2 + lighthouse-logger: 1.4.2(supports-color@8.1.1) transitivePeerDependencies: - supports-color - chromium-edge-launcher@0.3.0: + chromium-edge-launcher@0.3.0(supports-color@8.1.1): dependencies: '@types/node': 26.1.1 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 - lighthouse-logger: 1.4.2 + lighthouse-logger: 1.4.2(supports-color@8.1.1) mkdirp: 1.0.4 transitivePeerDependencies: - supports-color @@ -16807,11 +16753,11 @@ snapshots: dependencies: mime-db: 1.54.0 - compression@1.8.1: + compression@1.8.1(supports-color@8.1.1): dependencies: bytes: 3.1.2 compressible: 2.0.18 - debug: 2.6.9 + debug: 2.6.9(supports-color@8.1.1) negotiator: 0.6.4 on-headers: 1.1.0 safe-buffer: 5.2.1 @@ -16825,10 +16771,10 @@ snapshots: confbox@0.2.4: {} - connect@3.7.0: + connect@3.7.0(supports-color@8.1.1): dependencies: - debug: 2.6.9 - finalhandler: 1.1.2 + debug: 2.6.9(supports-color@8.1.1) + finalhandler: 1.1.2(supports-color@8.1.1) parseurl: 1.3.3 utils-merge: 1.0.1 transitivePeerDependencies: @@ -17126,17 +17072,23 @@ snapshots: dayjs@1.11.21: {} - debug@2.6.9: + debug@2.6.9(supports-color@8.1.1): dependencies: ms: 2.0.0 + optionalDependencies: + supports-color: 8.1.1 - debug@3.2.7: + debug@3.2.7(supports-color@8.1.1): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 - debug@4.4.3: + debug@4.4.3(supports-color@8.1.1): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 decimal.js@10.6.0: {} @@ -17215,10 +17167,10 @@ snapshots: minimatch: 3.1.5 p-limit: 3.1.0 - dmg-builder@26.15.3(electron-builder-squirrel-windows@26.15.3): + dmg-builder@26.15.3(electron-builder-squirrel-windows@26.15.3)(supports-color@8.1.1): dependencies: - app-builder-lib: 26.15.3(dmg-builder@26.15.3)(electron-builder-squirrel-windows@26.15.3) - builder-util: 26.15.3 + app-builder-lib: 26.15.3(dmg-builder@26.15.3)(electron-builder-squirrel-windows@26.15.3)(supports-color@8.1.1) + builder-util: 26.15.3(supports-color@8.1.1) fs-extra: 10.1.0 js-yaml: 4.3.0 transitivePeerDependencies: @@ -17321,23 +17273,23 @@ snapshots: dependencies: jake: 10.9.4 - electron-builder-squirrel-windows@26.15.3(dmg-builder@26.15.3): + electron-builder-squirrel-windows@26.15.3(dmg-builder@26.15.3)(supports-color@8.1.1): dependencies: - app-builder-lib: 26.15.3(dmg-builder@26.15.3)(electron-builder-squirrel-windows@26.15.3) - builder-util: 26.15.3 - electron-winstaller: 5.4.0 + app-builder-lib: 26.15.3(dmg-builder@26.15.3)(electron-builder-squirrel-windows@26.15.3)(supports-color@8.1.1) + builder-util: 26.15.3(supports-color@8.1.1) + electron-winstaller: 5.4.0(supports-color@8.1.1) transitivePeerDependencies: - dmg-builder - supports-color - electron-builder@26.15.3(electron-builder-squirrel-windows@26.15.3): + electron-builder@26.15.3(electron-builder-squirrel-windows@26.15.3)(supports-color@8.1.1): dependencies: - app-builder-lib: 26.15.3(dmg-builder@26.15.3)(electron-builder-squirrel-windows@26.15.3) - builder-util: 26.15.3 - builder-util-runtime: 9.7.0 + app-builder-lib: 26.15.3(dmg-builder@26.15.3)(electron-builder-squirrel-windows@26.15.3)(supports-color@8.1.1) + builder-util: 26.15.3(supports-color@8.1.1) + builder-util-runtime: 9.7.0(supports-color@8.1.1) chalk: 4.1.2 ci-info: 4.4.0 - dmg-builder: 26.15.3(electron-builder-squirrel-windows@26.15.3) + dmg-builder: 26.15.3(electron-builder-squirrel-windows@26.15.3)(supports-color@8.1.1) fs-extra: 10.1.0 lazy-val: 1.0.5 simple-update-notifier: 2.0.0 @@ -17348,12 +17300,12 @@ snapshots: electron-log@5.4.4: {} - electron-publish@26.15.3: + electron-publish@26.15.3(supports-color@8.1.1): dependencies: '@types/fs-extra': 9.0.13 aws4: 1.13.2 - builder-util: 26.15.3 - builder-util-runtime: 9.7.0 + builder-util: 26.15.3(supports-color@8.1.1) + builder-util-runtime: 9.7.0(supports-color@8.1.1) chalk: 4.1.2 form-data: 4.0.6 fs-extra: 10.1.0 @@ -17364,9 +17316,9 @@ snapshots: electron-to-chromium@1.5.383: {} - electron-updater@6.8.9: + electron-updater@6.8.9(supports-color@8.1.1): dependencies: - builder-util-runtime: 9.7.0 + builder-util-runtime: 9.7.0(supports-color@8.1.1) fs-extra: 10.1.0 js-yaml: 4.3.0 lazy-val: 1.0.5 @@ -17377,22 +17329,22 @@ snapshots: transitivePeerDependencies: - supports-color - electron-winstaller@5.4.0: + electron-winstaller@5.4.0(supports-color@8.1.1): dependencies: '@electron/asar': 3.4.1 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) fs-extra: 7.0.1 lodash: 4.18.1 temp: 0.9.4 optionalDependencies: - '@electron/windows-sign': 1.2.2 + '@electron/windows-sign': 1.2.2(supports-color@8.1.1) transitivePeerDependencies: - supports-color - electron@43.2.0: + electron@43.2.0(supports-color@8.1.1): dependencies: '@electron-internal/extract-zip': 1.0.3 - '@electron/get': 5.0.0 + '@electron/get': 5.0.0(supports-color@8.1.1) '@types/node': 24.13.2 transitivePeerDependencies: - supports-color @@ -17409,10 +17361,10 @@ snapshots: dependencies: once: 1.4.0 - engine.io-client@6.6.5: + engine.io-client@6.6.5(supports-color@8.1.1): dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) engine.io-parser: 5.2.3 ws: 8.21.1 xmlhttprequest-ssl: 2.1.2 @@ -17423,7 +17375,7 @@ snapshots: engine.io-parser@5.2.3: {} - engine.io@6.6.8: + engine.io@6.6.8(supports-color@8.1.1): dependencies: '@types/cors': 2.8.19 '@types/node': 26.1.1 @@ -17432,7 +17384,7 @@ snapshots: base64id: 2.0.0 cookie: 0.7.2 cors: 2.8.6 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) engine.io-parser: 5.2.3 ws: 8.21.1 transitivePeerDependencies: @@ -17440,7 +17392,7 @@ snapshots: - supports-color - utf-8-validate - enhanced-resolve@5.24.3: + enhanced-resolve@5.24.5: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -17559,42 +17511,43 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-sukka@8.14.2(@typescript-eslint/utils@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)): + eslint-config-sukka@9.0.1(@typescript-eslint/utils@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - '@eslint-community/eslint-plugin-eslint-comments': 4.7.2(eslint@10.8.0(jiti@2.7.0)) - '@eslint-sukka/eslint-plugin-stylistic': 8.14.2(eslint@10.8.0(jiti@2.7.0)) - '@eslint-sukka/eslint-plugin-sukka-full': 8.14.2(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - '@eslint-sukka/shared': 8.14.2(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) + '@eslint-community/eslint-plugin-eslint-comments': 4.7.2(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + '@eslint-sukka/eslint-plugin-stylistic': 9.0.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + '@eslint-sukka/eslint-plugin-sukka-full': 9.0.1(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + '@eslint-sukka/shared': 9.0.1(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) '@eslint/config-helpers': 0.7.0 - '@eslint/js': 10.0.1(eslint@10.8.0(jiti@2.7.0)) - '@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - '@typescript-eslint/parser': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) + '@eslint/js': 10.0.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + '@typescript-eslint/eslint-plugin': 8.68.0(@typescript-eslint/parser@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + '@typescript-eslint/parser': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) ci-info: 4.4.0 defu: 6.1.7 - eslint-import-resolver-typescript: 4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(eslint@10.8.0(jiti@2.7.0)))(eslint@10.8.0(jiti@2.7.0)) - eslint-plugin-import-x: 4.17.1(@typescript-eslint/utils@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(eslint@10.8.0(jiti@2.7.0)) - eslint-plugin-jsonc: 3.3.0(eslint@10.8.0(jiti@2.7.0)) - eslint-plugin-promise: 7.3.0(eslint@10.8.0(jiti@2.7.0)) - eslint-plugin-regexp: 3.1.1(eslint@10.8.0(jiti@2.7.0)) - eslint-plugin-unused-imports: 4.4.1(@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(eslint@10.8.0(jiti@2.7.0)) - foxts: 5.8.1 - jsonc-eslint-parser: 3.1.0 + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) + eslint-import-resolver-typescript: 4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + eslint-plugin-import-x: 4.17.1(@typescript-eslint/utils@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + eslint-plugin-jsonc: 3.4.2(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + eslint-plugin-promise: 7.3.0(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + eslint-plugin-regexp: 3.1.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + eslint-plugin-unused-imports: 4.4.1(@typescript-eslint/eslint-plugin@8.68.0(@typescript-eslint/parser@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + eslint-plugin-vibe-proof: 1.9.2(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + foxts: 5.9.1 + jsonc-eslint-parser: 3.3.0 picocolors: 1.1.1 - typescript-eslint: 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) + typescript-eslint: 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) transitivePeerDependencies: - '@eslint/json' - '@typescript-eslint/utils' - - eslint - eslint-import-resolver-node - eslint-plugin-import - supports-color - typescript - eslint-formatter-sukka@8.14.2(eslint@10.8.0(jiti@2.7.0)): + eslint-formatter-sukka@9.0.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)): dependencies: ci-info: 4.4.0 - eslint: 10.8.0(jiti@2.7.0) - foxts: 5.8.1 + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) + foxts: 5.9.1 picocolors: 1.1.1 eslint-import-context@0.1.9(unrs-resolver@1.12.2): @@ -17604,10 +17557,10 @@ snapshots: optionalDependencies: unrs-resolver: 1.12.2 - eslint-import-resolver-typescript@4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(eslint@10.8.0(jiti@2.7.0)))(eslint@10.8.0(jiti@2.7.0)): + eslint-import-resolver-typescript@4.4.5(eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - debug: 4.4.3 - eslint: 10.8.0(jiti@2.7.0) + debug: 4.4.3(supports-color@8.1.1) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) eslint-import-context: 0.1.9(unrs-resolver@1.12.2) get-tsconfig: 4.14.0 is-bun-module: 2.0.0 @@ -17615,103 +17568,102 @@ snapshots: tinyglobby: 0.2.17 unrs-resolver: 1.12.2 optionalDependencies: - eslint-plugin-import-x: 4.17.1(@typescript-eslint/utils@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(eslint@10.8.0(jiti@2.7.0)) + eslint-plugin-import-x: 4.17.1(@typescript-eslint/utils@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) transitivePeerDependencies: - supports-color - eslint-json-compat-utils@0.2.3(eslint@10.8.0(jiti@2.7.0))(jsonc-eslint-parser@3.1.0): + eslint-json-compat-utils@0.2.3(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(jsonc-eslint-parser@3.3.0): dependencies: - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) esquery: 1.7.0 - jsonc-eslint-parser: 3.1.0 + jsonc-eslint-parser: 3.3.0 - eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(eslint@10.8.0(jiti@2.7.0)): + eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - '@typescript-eslint/types': 8.65.0 + '@typescript-eslint/types': 8.68.0 comment-parser: 1.4.7 - debug: 4.4.3 - eslint: 10.8.0(jiti@2.7.0) + debug: 4.4.3(supports-color@8.1.1) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) eslint-import-context: 0.1.9(unrs-resolver@1.12.2) is-glob: 4.0.3 - minimatch: 10.2.5 + minimatch: 10.2.6 semver: 7.8.5 stable-hash-x: 0.2.0 unrs-resolver: 1.12.2 optionalDependencies: - '@typescript-eslint/utils': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) + '@typescript-eslint/utils': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) transitivePeerDependencies: - supports-color - eslint-plugin-jsonc@3.3.0(eslint@10.8.0(jiti@2.7.0)): + eslint-plugin-jsonc@3.4.2(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.8.0(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) '@eslint/core': 1.2.1 '@eslint/plugin-kit': 0.7.2 '@ota-meshi/ast-token-store': 0.3.0 diff-sequences: 29.6.3 - eslint: 10.8.0(jiti@2.7.0) - eslint-json-compat-utils: 0.2.3(eslint@10.8.0(jiti@2.7.0))(jsonc-eslint-parser@3.1.0) - jsonc-eslint-parser: 3.1.0 + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) + eslint-json-compat-utils: 0.2.3(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(jsonc-eslint-parser@3.3.0) + jsonc-eslint-parser: 3.3.0 natural-compare: 1.4.0 synckit: 0.11.13 transitivePeerDependencies: - '@eslint/json' - eslint-plugin-promise@7.3.0(eslint@10.8.0(jiti@2.7.0)): + eslint-plugin-promise@7.3.0(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.8.0(jiti@2.7.0)) - eslint: 10.8.0(jiti@2.7.0) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) - eslint-plugin-react-hooks@7.1.1(eslint@10.8.0(jiti@2.7.0)): + eslint-plugin-react-hooks@7.1.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/parser': 7.29.7 - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) hermes-parser: 0.25.1 zod: 4.4.3 zod-validation-error: 4.0.2(zod@4.4.3) transitivePeerDependencies: - supports-color - eslint-plugin-regexp@3.1.1(eslint@10.8.0(jiti@2.7.0)): + eslint-plugin-regexp@3.1.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.8.0(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) '@eslint-community/regexpp': 4.12.2 comment-parser: 1.4.7 - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) jsdoc-type-pratt-parser: 7.2.0 refa: 0.12.1 regexp-ast-analysis: 0.7.1 scslre: 0.3.0 - eslint-plugin-ssr-friendly@1.3.0(eslint@10.8.0(jiti@2.7.0)): + eslint-plugin-ssr-friendly@1.3.0(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)): dependencies: - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) globals: 13.24.0 - eslint-plugin-sukka@9.18.1(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)): + eslint-plugin-sukka@10.2.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/utils': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - eslint: 10.8.0(jiti@2.7.0) - eslint-plugin-vibe-proof: 1.1.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - foxts: 5.8.1 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/utils': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) + foxts: 5.9.1 typescript: '@typescript/typescript6@6.0.2' transitivePeerDependencies: - supports-color - eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(eslint@10.8.0(jiti@2.7.0)): + eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.68.0(@typescript-eslint/parser@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)): dependencies: - eslint: 10.8.0(jiti@2.7.0) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) + '@typescript-eslint/eslint-plugin': 8.68.0(@typescript-eslint/parser@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) - eslint-plugin-vibe-proof@1.1.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)): + eslint-plugin-vibe-proof@1.9.2(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/utils': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - eslint: 10.8.0(jiti@2.7.0) - foxts: 5.8.1 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/utils': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) + foxts: 5.9.1 typescript: '@typescript/typescript6@6.0.2' transitivePeerDependencies: - supports-color @@ -17727,11 +17679,11 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.8.0(jiti@2.7.0): + eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1): dependencies: - '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.0(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.5 + '@eslint/config-array': 0.23.5(supports-color@8.1.1) '@eslint/config-helpers': 0.7.0 '@eslint/core': 1.2.1 '@eslint/plugin-kit': 0.7.2 @@ -17741,7 +17693,7 @@ snapshots: '@types/estree': 1.0.9 ajv: 6.15.0 cross-spawn: 7.0.6 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) escape-string-regexp: 4.0.0 eslint-scope: 9.1.2 eslint-visitor-keys: 5.0.1 @@ -17790,7 +17742,7 @@ snapshots: etag@1.8.1: {} - event-target-bus@1.0.0: {} + event-target-bus@1.1.0: {} event-target-shim@5.0.1: {} @@ -17805,184 +17757,184 @@ snapshots: expect-type@1.3.0: {} - expo-apple-authentication@57.0.1(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-apple-authentication@57.0.1(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) expo-application@57.0.2(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) - expo-asset@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-asset@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): dependencies: - '@expo/image-utils': 0.11.1(@typescript/typescript6@6.0.2) - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + '@expo/image-utils': 0.11.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - supports-color - typescript - expo-audio@57.0.0(expo-asset@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-audio@57.0.0(expo-asset@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-asset: 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + expo-asset: 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - expo-background-task@57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)): + expo-background-task@57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-task-manager: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + expo-task-manager: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) transitivePeerDependencies: - react-native - expo-camera@57.0.1(@types/emscripten@1.41.5)(expo@57.0.4)(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-camera@57.0.1(@types/emscripten@1.41.5)(expo@57.0.4)(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: barcode-detector: 3.2.1(@types/emscripten@1.41.5) - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) optionalDependencies: react-native-web: 0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) transitivePeerDependencies: - '@types/emscripten' - expo-clipboard@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-clipboard@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - expo-constants@57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)): + expo-constants@57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - '@expo/env': 2.4.1 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + '@expo/env': 2.4.1(supports-color@8.1.1) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - supports-color expo-crypto@57.0.1(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) - expo-dev-client@57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)): + expo-dev-client@57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-dev-launcher: 57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) - expo-dev-menu: 57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + expo-dev-launcher: 57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) + expo-dev-menu: 57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) expo-dev-menu-interface: 57.0.0(expo@57.0.4) expo-manifests: 57.0.0(expo@57.0.4) expo-updates-interface: 57.0.0(expo@57.0.4) transitivePeerDependencies: - react-native - expo-dev-launcher@57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)): + expo-dev-launcher@57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)): dependencies: '@expo/schema-utils': 57.0.1 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-dev-menu: 57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + expo-dev-menu: 57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) expo-manifests: 57.0.0(expo@57.0.4) - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) expo-dev-menu-interface@57.0.0(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) - expo-dev-menu@57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)): + expo-dev-menu@57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-dev-menu-interface: 57.0.0(expo@57.0.4) - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) expo-device@57.0.0(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) ua-parser-js: 0.7.41 expo-document-picker@57.0.0(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-eas-client@57.0.0: {} - expo-file-system@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)): + expo-file-system@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - expo-font@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-font@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) fontfaceobserver: 2.3.0 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - expo-glass-effect@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-glass-effect@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) expo-haptics@57.0.0(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-image-loader@57.0.0(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-image-picker@57.0.2(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-image-loader: 57.0.0(expo@57.0.4) expo-json-utils@57.0.0: {} expo-keep-awake@57.0.0(expo@57.0.4)(react@19.2.3): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - expo-libghostty@0.8.1(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-libghostty@0.8.1(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - expo-linking@57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-linking@57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): dependencies: - expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) invariant: 2.2.4 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - expo - supports-color expo-local-authentication@57.0.0(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) invariant: 2.2.4 expo-localization@57.0.1(expo@57.0.4)(react@19.2.3): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 rtl-detect: 1.1.2 optional: true expo-manifests@57.0.0(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-json-utils: 57.0.0 - expo-modules-autolinking@57.0.5(@typescript/typescript6@6.0.2): + expo-modules-autolinking@57.0.5(@typescript/typescript6@6.0.2)(supports-color@8.1.1): dependencies: - '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2) + '@expo/require-utils': 57.0.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@expo/spawn-async': 1.8.0 chalk: 4.1.2 commander: 7.2.0 @@ -17990,71 +17942,71 @@ snapshots: - supports-color - typescript - expo-modules-core@57.0.3(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-modules-core@57.0.3(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: '@expo/expo-modules-macros-plugin': 0.3.0 - expo-modules-jsi: 57.0.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + expo-modules-jsi: 57.0.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) invariant: 2.2.4 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) optionalDependencies: - react-native-worklets: 0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native-worklets: 0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) - expo-modules-jsi@57.0.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)): + expo-modules-jsi@57.0.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)): dependencies: - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) expo-network@57.0.1(expo@57.0.4)(react@19.2.3): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - expo-notifications@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-notifications@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): dependencies: - '@expo/image-utils': 0.11.1(@typescript/typescript6@6.0.2) + '@expo/image-utils': 0.11.1(@typescript/typescript6@6.0.2)(supports-color@8.1.1) abort-controller: 3.0.0 badgin: 1.2.3 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-application: 57.0.2(expo@57.0.4) - expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - supports-color - typescript - expo-router@57.0.4(a892d21e44c1d5a25ab382e32d303fb9): + expo-router@57.0.4(3bc51b20989ed2c3020a920bb0eeb449): dependencies: - '@expo/log-box': 57.0.0(@expo/dom-webview@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - '@expo/metro-runtime': 57.0.3(@expo/log-box@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + '@expo/log-box': 57.0.0(@expo/dom-webview@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/metro-runtime': 57.0.3(@expo/log-box@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) '@expo/schema-utils': 57.0.1 - '@expo/ui': 57.0.7(@babel/core@7.29.7)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + '@expo/ui': 57.0.7(@babel/core@7.29.7(supports-color@8.1.1))(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.3) '@radix-ui/react-tabs': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@react-native-masked-view/masked-view': 0.3.2(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + '@react-native-masked-view/masked-view': 0.3.2(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) '@testing-library/jest-dom': 6.9.1 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) client-only: 0.0.1 color: 4.2.3 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) escape-string-regexp: 4.0.0 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) - expo-glass-effect: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-linking: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) + expo-glass-effect: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + expo-linking: 57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) expo-server: 57.0.0 - expo-symbols: 57.0.0(expo-font@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo-symbols: 57.0.0(expo-font@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) fast-deep-equal: 3.1.3 invariant: 2.2.4 - nanoid: 3.3.15 + nanoid: 3.3.16 query-string: 7.1.3 react: 19.2.3 react-fast-compare: 3.2.2 react-is: 19.2.7 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) - react-native-drawer-layout: 4.2.5(react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-safe-area-context: 5.7.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-screens: 4.25.2(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) + react-native-drawer-layout: 4.2.5(5192597165fff2dd7abc0f37e93a3df3) + react-native-safe-area-context: 5.7.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-screens: 4.25.2(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) server-only: 0.0.1 sf-symbols-typescript: 2.2.0 shallowequal: 1.1.0 @@ -18062,8 +18014,8 @@ snapshots: vaul: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) optionalDependencies: react-dom: 19.2.3(react@19.2.3) - react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-native-web: 0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) transitivePeerDependencies: - '@babel/core' @@ -18076,65 +18028,65 @@ snapshots: expo-secure-store@57.0.0(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-server@57.0.0: {} - expo-sharing@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-sharing@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): dependencies: - '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2) + '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) '@expo/config-types': 57.0.1 '@expo/plist': 0.8.0 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) transitivePeerDependencies: - supports-color - typescript - expo-sqlite@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-sqlite@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: await-lock: 2.2.2 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - expo-status-bar@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-status-bar@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) expo-structured-headers@57.0.0: {} - expo-symbols@57.0.0(expo-font@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-symbols@57.0.0(expo-font@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: '@expo-google-fonts/material-symbols': 0.4.38 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-font: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + expo-font: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) sf-symbols-typescript: 2.2.0 - expo-task-manager@57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)): + expo-task-manager@57.0.2(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) unimodules-app-loader: 57.0.0 expo-updates-interface@57.0.0(expo@57.0.4): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) - expo-updates@57.0.6(expo-dev-client@57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)))(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo-updates@57.0.6(expo-dev-client@57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)))(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): dependencies: '@expo/code-signing-certificates': 0.0.6 '@expo/plist': 0.8.0 '@expo/spawn-async': 1.8.0 arg: 4.1.3 chalk: 4.1.2 - debug: 4.4.3 - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + debug: 4.4.3(supports-color@8.1.1) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) expo-eas-client: 57.0.0 expo-manifests: 57.0.0(expo@57.0.4) expo-structured-headers: 57.0.0 @@ -18144,50 +18096,50 @@ snapshots: ignore: 5.3.2 nullthrows: 1.1.1 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) resolve-from: 5.0.0 optionalDependencies: - expo-dev-client: 57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + expo-dev-client: 57.0.5(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) transitivePeerDependencies: - supports-color - expo-web-browser@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)): + expo-web-browser@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)): dependencies: - expo: 57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + expo: 57.0.4(ffe90122b92e78d11051c8a0633e15fd) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - expo@57.0.4(@babel/core@7.29.7)(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-router@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + expo@57.0.4(ffe90122b92e78d11051c8a0633e15fd): dependencies: '@babel/runtime': 7.29.7 - '@expo/cli': 57.0.6(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-constants@57.0.3)(expo-font@57.0.0)(expo-router@57.0.4)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - '@expo/config': 57.0.3(@typescript/typescript6@6.0.2) - '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2) - '@expo/devtools': 57.0.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - '@expo/fingerprint': 0.20.3 - '@expo/local-build-cache-provider': 57.0.2(@typescript/typescript6@6.0.2) - '@expo/log-box': 57.0.0(@expo/dom-webview@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - '@expo/metro': 56.0.0 - '@expo/metro-config': 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4) + '@expo/cli': 57.0.6(@expo/dom-webview@57.0.0)(@expo/metro-runtime@57.0.3)(@typescript/typescript6@6.0.2)(expo-constants@57.0.3)(expo-font@57.0.0)(expo-router@57.0.4)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) + '@expo/config': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@expo/config-plugins': 57.0.3(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@expo/devtools': 57.0.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/fingerprint': 0.20.3(supports-color@8.1.1) + '@expo/local-build-cache-provider': 57.0.2(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@expo/log-box': 57.0.0(@expo/dom-webview@57.0.0)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/metro': 56.0.0(supports-color@8.1.1) + '@expo/metro-config': 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(supports-color@8.1.1) '@ungap/structured-clone': 1.3.1 - babel-preset-expo: 57.0.2(@babel/core@7.29.7)(@babel/runtime@7.29.7)(expo@57.0.4)(react-refresh@0.14.2) - expo-asset: 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) - expo-file-system: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) - expo-font: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + babel-preset-expo: 57.0.2(@babel/core@7.29.7(supports-color@8.1.1))(@babel/runtime@7.29.7)(expo@57.0.4)(react-refresh@0.14.2)(supports-color@8.1.1) + expo-asset: 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) + expo-constants: 57.0.3(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(supports-color@8.1.1) + expo-file-system: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) + expo-font: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) expo-keep-awake: 57.0.0(expo@57.0.4)(react@19.2.3) - expo-modules-autolinking: 57.0.5(@typescript/typescript6@6.0.2) - expo-modules-core: 57.0.3(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + expo-modules-autolinking: 57.0.5(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + expo-modules-core: 57.0.3(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) pretty-format: 29.7.0 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) react-refresh: 0.14.2 whatwg-url-minimum: 0.1.2 optionalDependencies: - '@expo/dom-webview': 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - '@expo/metro-runtime': 57.0.3(@expo/log-box@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + '@expo/dom-webview': 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + '@expo/metro-runtime': 57.0.3(@expo/log-box@57.0.0)(expo@57.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) react-dom: 19.2.3(react@19.2.3) react-native-web: 0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react-native-webview: 13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native-webview: 13.16.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) transitivePeerDependencies: - '@babel/core' - bufferutil @@ -18201,28 +18153,28 @@ snapshots: exponential-backoff@3.1.3: {} - express-rate-limit@8.6.1(express@5.2.1): + express-rate-limit@8.6.1(express@5.2.1(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - debug: 4.4.3 - express: 5.2.1 + debug: 4.4.3(supports-color@8.1.1) + express: 5.2.1(supports-color@8.1.1) ip-address: 10.3.1 transitivePeerDependencies: - supports-color - express@5.2.1: + express@5.2.1(supports-color@8.1.1): dependencies: accepts: 2.0.0 - body-parser: 2.3.0 + body-parser: 2.3.0(supports-color@8.1.1) content-disposition: 1.1.0 content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 2.1.1 + finalhandler: 2.1.1(supports-color@8.1.1) fresh: 2.0.0 http-errors: 2.0.1 merge-descriptors: 2.0.0 @@ -18233,9 +18185,9 @@ snapshots: proxy-addr: 2.0.7 qs: 6.15.3 range-parser: 1.3.0 - router: 2.2.0 - send: 1.2.1 - serve-static: 2.2.1 + router: 2.2.0(supports-color@8.1.1) + send: 1.2.1(supports-color@8.1.1) + serve-static: 2.2.1(supports-color@8.1.1) statuses: 2.0.2 type-is: 2.1.0 vary: 1.1.2 @@ -18336,9 +18288,9 @@ snapshots: filter-obj@1.1.0: {} - finalhandler@1.1.2: + finalhandler@1.1.2(supports-color@8.1.1): dependencies: - debug: 2.6.9 + debug: 2.6.9(supports-color@8.1.1) encodeurl: 1.0.2 escape-html: 1.0.3 on-finished: 2.3.0 @@ -18348,9 +18300,9 @@ snapshots: transitivePeerDependencies: - supports-color - finalhandler@2.1.1: + finalhandler@2.1.1(supports-color@8.1.1): dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -18404,34 +18356,25 @@ snapshots: forwarded@0.2.0: {} - foxact@0.3.8(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + foxact@0.3.10(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: client-only: 0.0.1 - event-target-bus: 1.0.0 + event-target-bus: 1.1.0 server-only: 0.0.1 optionalDependencies: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - foxact@0.3.8(react-dom@19.2.7(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): + foxact@0.3.10(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): dependencies: client-only: 0.0.1 - event-target-bus: 1.0.0 - server-only: 0.0.1 - optionalDependencies: - react: 19.3.0-canary-96fcba90-20260728 - react-dom: 19.2.7(react@19.3.0-canary-96fcba90-20260728) - - foxact@0.3.8(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): - dependencies: - client-only: 0.0.1 - event-target-bus: 1.0.0 + event-target-bus: 1.1.0 server-only: 0.0.1 optionalDependencies: react: 19.3.0-canary-96fcba90-20260728 react-dom: 19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728) - foxts@5.8.1: + foxts@5.9.1: dependencies: fast-fnv1a: 1.0.0 fnv1a52: 1.0.0 @@ -18500,17 +18443,17 @@ snapshots: function-bind@1.1.2: {} - gaxios@7.1.5: + gaxios@7.1.5(supports-color@8.1.1): dependencies: extend: 3.0.2 - https-proxy-agent: 7.0.6 + https-proxy-agent: 7.0.6(supports-color@8.1.1) node-fetch: 3.3.2 transitivePeerDependencies: - supports-color - gcp-metadata@8.1.2: + gcp-metadata@8.1.2(supports-color@8.1.1): dependencies: - gaxios: 7.1.5 + gaxios: 7.1.5(supports-color@8.1.1) google-logging-utils: 1.1.3 json-bigint: 1.0.0 transitivePeerDependencies: @@ -18576,7 +18519,7 @@ snapshots: glob@13.0.6: dependencies: - minimatch: 10.2.5 + minimatch: 10.2.6 minipass: 7.1.3 path-scurry: 2.0.2 @@ -18609,12 +18552,12 @@ snapshots: gopd: 1.2.0 optional: true - google-auth-library@10.7.0: + google-auth-library@10.7.0(supports-color@8.1.1): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.1.5 - gcp-metadata: 8.1.2 + gaxios: 7.1.5(supports-color@8.1.1) + gcp-metadata: 8.1.2(supports-color@8.1.1) google-logging-utils: 1.1.3 jws: 4.0.1 transitivePeerDependencies: @@ -18729,7 +18672,7 @@ snapshots: stringify-entities: 4.0.4 zwitch: 2.0.4 - hast-util-to-jsx-runtime@2.3.6: + hast-util-to-jsx-runtime@2.3.6(supports-color@8.1.1): dependencies: '@types/estree': 1.0.9 '@types/hast': 3.0.5 @@ -18738,9 +18681,9 @@ snapshots: devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 hast-util-whitespace: 3.0.0 - mdast-util-mdx-expression: 2.0.1 - mdast-util-mdx-jsx: 3.2.0 - mdast-util-mdxjs-esm: 2.0.1 + mdast-util-mdx-expression: 2.0.1(supports-color@8.1.1) + mdast-util-mdx-jsx: 3.2.0(supports-color@8.1.1) + mdast-util-mdxjs-esm: 2.0.1(supports-color@8.1.1) property-information: 7.2.0 space-separated-tokens: 2.0.2 style-to-js: 1.1.21 @@ -18801,35 +18744,35 @@ snapshots: dependencies: hermes-estree: 0.36.1 - heroui-native@1.0.6(e59c6d32fdb32d5fca21df2a11846d54): + heroui-native@1.0.6(165eb86db294c7d42ce40e8c9ab66801): dependencies: react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) - react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-safe-area-context: 5.7.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-svg: 15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-worklets: 0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) + react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-safe-area-context: 5.7.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-svg: 15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-worklets: 0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) tailwind-merge: 3.6.0 tailwind-variants: 3.3.0(tailwind-merge@3.6.0)(tailwindcss@4.3.3) optionalDependencies: - '@gorhom/bottom-sheet': 5.2.14(@types/react@19.2.17)(react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-screens: 4.25.2(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + '@gorhom/bottom-sheet': 5.2.14(6e44dcb7dcfecf271936e923703300f2) + react-native-screens: 4.25.2(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - heroui-native@1.0.6(fbb89a5f802f3b19887fb8e060c8c1c4): + heroui-native@1.0.6(63282ea4a5d8a79f137ba1bf529bfa14): dependencies: react: 19.3.0-canary-96fcba90-20260728 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) - react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) - react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) - react-native-safe-area-context: 5.7.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) - react-native-svg: 15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) - react-native-worklets: 0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) + react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) + react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) + react-native-safe-area-context: 5.7.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) + react-native-svg: 15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) + react-native-worklets: 0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) tailwind-merge: 3.6.0 tailwind-variants: 3.3.0(tailwind-merge@3.6.0)(tailwindcss@4.3.3) optionalDependencies: - '@gorhom/bottom-sheet': 5.2.14(@types/react@19.2.17)(react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728))(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) - react-native-screens: 4.25.2(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + '@gorhom/bottom-sheet': 5.2.14(da77d43574db60c81967e07362a6f6fb) + react-native-screens: 4.25.2(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) highlight.js@10.7.3: {} @@ -18871,17 +18814,17 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 - http-proxy-agent@7.0.2: + http-proxy-agent@7.0.2(supports-color@8.1.1): dependencies: agent-base: 7.1.4 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color - http-proxy-agent@9.1.0: + http-proxy-agent@9.1.0(supports-color@8.1.1): dependencies: agent-base: 9.0.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) proxy-agent-negotiate: 1.1.0 transitivePeerDependencies: - kerberos @@ -18892,24 +18835,24 @@ snapshots: quick-lru: 5.1.1 resolve-alpn: 1.2.1 - https-proxy-agent@5.0.1: + https-proxy-agent@5.0.1(supports-color@8.1.1): dependencies: - agent-base: 6.0.2 - debug: 4.4.3 + agent-base: 6.0.2(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color - https-proxy-agent@7.0.6: + https-proxy-agent@7.0.6(supports-color@8.1.1): dependencies: agent-base: 7.1.4 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color - https-proxy-agent@9.1.0: + https-proxy-agent@9.1.0(supports-color@8.1.1): dependencies: agent-base: 9.0.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) proxy-agent-negotiate: 1.1.0 transitivePeerDependencies: - kerberos @@ -18921,11 +18864,6 @@ snapshots: dependencies: safer-buffer: 2.1.2 - iconv-lite@0.7.2: - dependencies: - safer-buffer: 2.1.2 - optional: true - iconv-lite@0.7.3: dependencies: safer-buffer: 2.1.2 @@ -18952,8 +18890,8 @@ snapshots: import-in-the-middle@3.2.0: dependencies: - acorn: 8.17.0 - acorn-import-attributes: 1.9.5(acorn@8.17.0) + acorn: 8.18.0 + acorn-import-attributes: 1.9.5(acorn@8.18.0) cjs-module-lexer: 2.2.0 module-details-from-path: 1.0.4 @@ -18981,7 +18919,7 @@ snapshots: dependencies: css-in-js-utils: 3.1.0 - input-otp@1.4.2(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): + input-otp@1.5.0(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): dependencies: react: 19.3.0-canary-96fcba90-20260728 react-dom: 19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728) @@ -18999,11 +18937,11 @@ snapshots: dependencies: loose-envify: 1.4.0 - ioredis@5.11.1: + ioredis@5.11.1(supports-color@8.1.1): dependencies: '@ioredis/commands': 1.10.0 cluster-key-slot: 1.1.1 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) denque: 2.1.0 redis-errors: 1.2.0 redis-parser: 3.0.0 @@ -19011,8 +18949,6 @@ snapshots: transitivePeerDependencies: - supports-color - ip-address@10.2.0: {} - ip-address@10.3.1: {} ipaddr.js@1.9.1: {} @@ -19187,11 +19123,11 @@ snapshots: json5@2.2.3: {} - jsonc-eslint-parser@3.1.0: + jsonc-eslint-parser@3.3.0: dependencies: - acorn: 8.17.0 + acorn: 8.18.0 eslint-visitor-keys: 5.0.1 - semver: 7.8.5 + verkit: 0.3.2 jsonfile@4.0.0: optionalDependencies: @@ -19255,9 +19191,9 @@ snapshots: dependencies: isomorphic.js: 0.2.5 - lighthouse-logger@1.4.2: + lighthouse-logger@1.4.2(supports-color@8.1.1): dependencies: - debug: 2.6.9 + debug: 2.6.9(supports-color@8.1.1) marky: 1.3.0 transitivePeerDependencies: - supports-color @@ -19420,11 +19356,11 @@ snapshots: lru_map@0.4.1: {} - lucide-react-native@1.27.0(react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + lucide-react-native@1.27.0(react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) - react-native-svg: 15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) + react-native-svg: 15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) lucide-react@1.27.0(react@19.3.0-canary-96fcba90-20260728): dependencies: @@ -19438,10 +19374,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - make-fetch-happen@16.0.1: + make-fetch-happen@16.0.1(supports-color@8.1.1): dependencies: '@gar/promise-retry': 1.0.3 - '@npmcli/agent': 5.0.2 + '@npmcli/agent': 5.0.2(supports-color@8.1.1) '@npmcli/redact': 5.0.0 cacache: 21.0.1 http-cache-semantics: 4.2.0 @@ -19484,14 +19420,14 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 - mdast-util-from-markdown@2.0.3: + mdast-util-from-markdown@2.0.3(supports-color@8.1.1): dependencies: '@types/mdast': 4.0.4 '@types/unist': 3.0.3 decode-named-character-reference: 1.3.0 devlop: 1.1.0 mdast-util-to-string: 4.0.0 - micromark: 4.0.2 + micromark: 4.0.2(supports-color@8.1.1) micromark-util-decode-numeric-character-reference: 2.0.2 micromark-util-decode-string: 2.0.1 micromark-util-normalize-identifier: 2.0.1 @@ -19509,67 +19445,67 @@ snapshots: mdast-util-find-and-replace: 3.0.2 micromark-util-character: 2.1.1 - mdast-util-gfm-footnote@2.1.0: + mdast-util-gfm-footnote@2.1.0(supports-color@8.1.1): dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3 + mdast-util-from-markdown: 2.0.3(supports-color@8.1.1) mdast-util-to-markdown: 2.1.2 micromark-util-normalize-identifier: 2.0.1 transitivePeerDependencies: - supports-color - mdast-util-gfm-strikethrough@2.0.0: + mdast-util-gfm-strikethrough@2.0.0(supports-color@8.1.1): dependencies: '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.3 + mdast-util-from-markdown: 2.0.3(supports-color@8.1.1) mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color - mdast-util-gfm-table@2.0.0: + mdast-util-gfm-table@2.0.0(supports-color@8.1.1): dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 markdown-table: 3.0.4 - mdast-util-from-markdown: 2.0.3 + mdast-util-from-markdown: 2.0.3(supports-color@8.1.1) mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color - mdast-util-gfm-task-list-item@2.0.0: + mdast-util-gfm-task-list-item@2.0.0(supports-color@8.1.1): dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3 + mdast-util-from-markdown: 2.0.3(supports-color@8.1.1) mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color - mdast-util-gfm@3.1.0: + mdast-util-gfm@3.1.0(supports-color@8.1.1): dependencies: - mdast-util-from-markdown: 2.0.3 + mdast-util-from-markdown: 2.0.3(supports-color@8.1.1) mdast-util-gfm-autolink-literal: 2.0.1 - mdast-util-gfm-footnote: 2.1.0 - mdast-util-gfm-strikethrough: 2.0.0 - mdast-util-gfm-table: 2.0.0 - mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-gfm-footnote: 2.1.0(supports-color@8.1.1) + mdast-util-gfm-strikethrough: 2.0.0(supports-color@8.1.1) + mdast-util-gfm-table: 2.0.0(supports-color@8.1.1) + mdast-util-gfm-task-list-item: 2.0.0(supports-color@8.1.1) mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color - mdast-util-mdx-expression@2.0.1: + mdast-util-mdx-expression@2.0.1(supports-color@8.1.1): dependencies: '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.5 '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3 + mdast-util-from-markdown: 2.0.3(supports-color@8.1.1) mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color - mdast-util-mdx-jsx@3.2.0: + mdast-util-mdx-jsx@3.2.0(supports-color@8.1.1): dependencies: '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.5 @@ -19577,7 +19513,7 @@ snapshots: '@types/unist': 3.0.3 ccount: 2.0.1 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3 + mdast-util-from-markdown: 2.0.3(supports-color@8.1.1) mdast-util-to-markdown: 2.1.2 parse-entities: 4.0.2 stringify-entities: 4.0.4 @@ -19586,13 +19522,13 @@ snapshots: transitivePeerDependencies: - supports-color - mdast-util-mdxjs-esm@2.0.1: + mdast-util-mdxjs-esm@2.0.1(supports-color@8.1.1): dependencies: '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.5 '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3 + mdast-util-from-markdown: 2.0.3(supports-color@8.1.1) mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color @@ -19614,9 +19550,9 @@ snapshots: unist-util-visit: 5.1.0 vfile: 6.0.3 - mdast-util-to-markdown-cjk-friendly-gfm-strikethrough@1.0.0(@types/mdast@4.0.4)(micromark-util-types@2.0.2): + mdast-util-to-markdown-cjk-friendly-gfm-strikethrough@1.0.0(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(supports-color@8.1.1): dependencies: - mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-strikethrough: 2.0.0(supports-color@8.1.1) mdast-util-to-markdown: 2.1.2 micromark-extension-cjk-friendly-util: 3.0.1(micromark-util-types@2.0.2) micromark-util-symbol: 2.0.1 @@ -19694,9 +19630,9 @@ snapshots: ts-dedent: 2.3.0 uuid: 11.1.1 - metro-babel-transformer@0.84.4: + metro-babel-transformer@0.84.4(supports-color@8.1.1): dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) flow-enums-runtime: 0.0.6 hermes-parser: 0.35.0 metro-cache-key: 0.84.4 @@ -19708,22 +19644,22 @@ snapshots: dependencies: flow-enums-runtime: 0.0.6 - metro-cache@0.84.4: + metro-cache@0.84.4(supports-color@8.1.1): dependencies: exponential-backoff: 3.1.3 flow-enums-runtime: 0.0.6 - https-proxy-agent: 7.0.6 + https-proxy-agent: 7.0.6(supports-color@8.1.1) metro-core: 0.84.4 transitivePeerDependencies: - supports-color - metro-config@0.84.4: + metro-config@0.84.4(supports-color@8.1.1): dependencies: - connect: 3.7.0 + connect: 3.7.0(supports-color@8.1.1) flow-enums-runtime: 0.0.6 jest-validate: 29.7.0 - metro: 0.84.4 - metro-cache: 0.84.4 + metro: 0.84.4(supports-color@8.1.1) + metro-cache: 0.84.4(supports-color@8.1.1) metro-core: 0.84.4 metro-runtime: 0.84.4 yaml: 2.9.0 @@ -19738,9 +19674,9 @@ snapshots: lodash.throttle: 4.1.1 metro-resolver: 0.84.4 - metro-file-map@0.84.4: + metro-file-map@0.84.4(supports-color@8.1.1): dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) fb-watchman: 2.0.2 flow-enums-runtime: 0.0.6 graceful-fs: 4.2.11 @@ -19766,13 +19702,13 @@ snapshots: '@babel/runtime': 7.29.7 flow-enums-runtime: 0.0.6 - metro-source-map@0.84.4: + metro-source-map@0.84.4(supports-color@8.1.1): dependencies: - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) '@babel/types': 7.29.7 flow-enums-runtime: 0.0.6 invariant: 2.2.4 - metro-symbolicate: 0.84.4 + metro-symbolicate: 0.84.4(supports-color@8.1.1) nullthrows: 1.1.1 ob1: 0.84.4 source-map: 0.5.7 @@ -19780,61 +19716,61 @@ snapshots: transitivePeerDependencies: - supports-color - metro-symbolicate@0.84.4: + metro-symbolicate@0.84.4(supports-color@8.1.1): dependencies: flow-enums-runtime: 0.0.6 invariant: 2.2.4 - metro-source-map: 0.84.4 + metro-source-map: 0.84.4(supports-color@8.1.1) nullthrows: 1.1.1 source-map: 0.5.7 vlq: 1.0.1 transitivePeerDependencies: - supports-color - metro-transform-plugins@0.84.4: + metro-transform-plugins@0.84.4(supports-color@8.1.1): dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/generator': 7.29.7 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) flow-enums-runtime: 0.0.6 nullthrows: 1.1.1 transitivePeerDependencies: - supports-color - metro-transform-worker@0.84.4: + metro-transform-worker@0.84.4(supports-color@8.1.1): dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/generator': 7.29.7 '@babel/parser': 7.29.7 '@babel/types': 7.29.7 flow-enums-runtime: 0.0.6 - metro: 0.84.4 - metro-babel-transformer: 0.84.4 - metro-cache: 0.84.4 + metro: 0.84.4(supports-color@8.1.1) + metro-babel-transformer: 0.84.4(supports-color@8.1.1) + metro-cache: 0.84.4(supports-color@8.1.1) metro-cache-key: 0.84.4 metro-minify-terser: 0.84.4 - metro-source-map: 0.84.4 - metro-transform-plugins: 0.84.4 + metro-source-map: 0.84.4(supports-color@8.1.1) + metro-transform-plugins: 0.84.4(supports-color@8.1.1) nullthrows: 1.1.1 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - metro@0.84.4: + metro@0.84.4(supports-color@8.1.1): dependencies: '@babel/code-frame': 7.29.7 - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/generator': 7.29.7 '@babel/parser': 7.29.7 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@8.1.1) '@babel/types': 7.29.7 accepts: 2.0.0 ci-info: 2.0.0 - connect: 3.7.0 - debug: 4.4.3 + connect: 3.7.0(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) error-stack-parser: 2.1.4 flow-enums-runtime: 0.0.6 graceful-fs: 4.2.11 @@ -19844,18 +19780,18 @@ snapshots: jest-worker: 29.7.0 jsc-safe-url: 0.2.4 lodash.throttle: 4.1.1 - metro-babel-transformer: 0.84.4 - metro-cache: 0.84.4 + metro-babel-transformer: 0.84.4(supports-color@8.1.1) + metro-cache: 0.84.4(supports-color@8.1.1) metro-cache-key: 0.84.4 - metro-config: 0.84.4 + metro-config: 0.84.4(supports-color@8.1.1) metro-core: 0.84.4 - metro-file-map: 0.84.4 + metro-file-map: 0.84.4(supports-color@8.1.1) metro-resolver: 0.84.4 metro-runtime: 0.84.4 - metro-source-map: 0.84.4 - metro-symbolicate: 0.84.4 - metro-transform-plugins: 0.84.4 - metro-transform-worker: 0.84.4 + metro-source-map: 0.84.4(supports-color@8.1.1) + metro-symbolicate: 0.84.4(supports-color@8.1.1) + metro-transform-plugins: 0.84.4(supports-color@8.1.1) + metro-transform-worker: 0.84.4(supports-color@8.1.1) mime-types: 3.0.2 nullthrows: 1.1.1 serialize-error: 2.1.0 @@ -19887,11 +19823,11 @@ snapshots: micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 - micromark-extension-cjk-friendly-gfm-strikethrough@2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2): + micromark-extension-cjk-friendly-gfm-strikethrough@2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@8.1.1)): dependencies: devlop: 1.1.0 get-east-asian-width: 1.6.0 - micromark: 4.0.2 + micromark: 4.0.2(supports-color@8.1.1) micromark-extension-cjk-friendly-util: 3.0.1(micromark-util-types@2.0.2) micromark-util-character: 2.1.1 micromark-util-chunked: 2.0.1 @@ -19908,10 +19844,10 @@ snapshots: optionalDependencies: micromark-util-types: 2.0.2 - micromark-extension-cjk-friendly@2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2): + micromark-extension-cjk-friendly@2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@8.1.1)): dependencies: devlop: 1.1.0 - micromark: 4.0.2 + micromark: 4.0.2(supports-color@8.1.1) micromark-extension-cjk-friendly-util: 3.0.1(micromark-util-types@2.0.2) micromark-util-chunked: 2.0.1 micromark-util-resolve-all: 2.0.1 @@ -20069,10 +20005,10 @@ snapshots: micromark-util-types@2.0.2: {} - micromark@4.0.2: + micromark@4.0.2(supports-color@8.1.1): dependencies: '@types/debug': 4.1.13 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) decode-named-character-reference: 1.3.0 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 @@ -20124,7 +20060,7 @@ snapshots: minimatch@10.2.5: dependencies: - brace-expansion: 5.0.8 + brace-expansion: 5.0.9 minimatch@10.2.6: dependencies: @@ -20154,7 +20090,7 @@ snapshots: minipass-sized: 2.0.0 minizlib: 3.1.0 optionalDependencies: - iconv-lite: 0.7.2 + iconv-lite: 0.7.3 minipass-flush@1.0.7: dependencies: @@ -20189,7 +20125,7 @@ snapshots: mlly@1.8.2: dependencies: - acorn: 8.17.0 + acorn: 8.18.0 pathe: 2.0.3 pkg-types: 1.3.1 ufo: 1.6.4 @@ -20240,8 +20176,6 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nanoid@3.3.15: {} - nanoid@3.3.16: {} nanoid@6.0.0: {} @@ -20588,8 +20522,8 @@ snapshots: posthog-js@1.407.3(preact-render-to-string@6.6.5(preact@11.0.0-beta.0)): dependencies: '@posthog/browser-common': 0.2.3 - '@posthog/core': 1.45.1 - '@posthog/types': 1.398.0 + '@posthog/core': 1.46.1 + '@posthog/types': 1.399.0 core-js: 3.49.0 dompurify: 3.4.12 fflate: 0.4.9 @@ -20599,17 +20533,17 @@ snapshots: transitivePeerDependencies: - preact-render-to-string - posthog-react-native@4.60.0(expo-application@57.0.2(expo@57.0.4))(expo-device@57.0.0(expo@57.0.4))(expo-file-system@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)))(expo-localization@57.0.1(expo@57.0.4)(react@19.2.3))(react-native-safe-area-context@5.7.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)): + posthog-react-native@4.60.0(expo-application@57.0.2(expo@57.0.4))(expo-device@57.0.0(expo@57.0.4))(expo-file-system@57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)))(expo-localization@57.0.1(expo@57.0.4)(react@19.2.3))(react-native-safe-area-context@5.7.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3))(react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)): dependencies: '@posthog/core': 1.46.1 '@posthog/types': 1.399.0 optionalDependencies: expo-application: 57.0.2(expo@57.0.4) expo-device: 57.0.0(expo@57.0.4) - expo-file-system: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) + expo-file-system: 57.0.0(expo@57.0.4)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1)) expo-localization: 57.0.1(expo@57.0.4)(react@19.2.3) - react-native-safe-area-context: 5.7.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-svg: 15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native-safe-area-context: 5.7.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-svg: 15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) postject@1.0.0-alpha.6: dependencies: @@ -20804,12 +20738,6 @@ snapshots: react: 19.2.3 scheduler: 0.27.0 - react-dom@19.2.7(react@19.3.0-canary-96fcba90-20260728): - dependencies: - react: 19.3.0-canary-96fcba90-20260728 - scheduler: 0.27.0 - optional: true - react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728): dependencies: react: 19.3.0-canary-96fcba90-20260728 @@ -20838,105 +20766,105 @@ snapshots: react-is@19.2.7: {} - react-native-drawer-layout@4.2.5(react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + react-native-drawer-layout@4.2.5(5192597165fff2dd7abc0f37e93a3df3): dependencies: color: 4.2.3 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) - react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) + react-native-gesture-handler: 2.32.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) use-latest-callback: 0.2.6(react@19.2.3) - react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: '@egjs/hammerjs': 2.0.17 '@types/react-test-renderer': 19.1.0 hoist-non-react-statics: 3.3.2 invariant: 2.2.4 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): + react-native-gesture-handler@2.32.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728): dependencies: '@egjs/hammerjs': 2.0.17 '@types/react-test-renderer': 19.1.0 hoist-non-react-statics: 3.3.2 invariant: 2.2.4 react: 19.3.0-canary-96fcba90-20260728 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) - react-native-is-edge-to-edge@1.3.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + react-native-is-edge-to-edge@1.3.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - react-native-is-edge-to-edge@1.3.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): + react-native-is-edge-to-edge@1.3.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728): dependencies: react: 19.3.0-canary-96fcba90-20260728 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) - react-native-keyboard-controller@1.21.9(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + react-native-keyboard-controller@1.21.9(react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) - react-native-is-edge-to-edge: 1.3.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) + react-native-is-edge-to-edge: 1.3.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-reanimated: 4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) - react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) - react-native-is-edge-to-edge: 1.3.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) - react-native-worklets: 0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) + react-native-is-edge-to-edge: 1.3.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) + react-native-worklets: 0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1) semver: 7.8.5 - react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): + react-native-reanimated@4.5.0(react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728): dependencies: react: 19.3.0-canary-96fcba90-20260728 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) - react-native-is-edge-to-edge: 1.3.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) - react-native-worklets: 0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) + react-native-is-edge-to-edge: 1.3.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) + react-native-worklets: 0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) semver: 7.8.5 - react-native-safe-area-context@5.7.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + react-native-safe-area-context@5.7.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) - react-native-safe-area-context@5.7.0(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): + react-native-safe-area-context@5.7.0(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728): dependencies: react: 19.3.0-canary-96fcba90-20260728 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) - react-native-screens@4.25.2(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + react-native-screens@4.25.2(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: react: 19.2.3 react-freeze: 1.0.4(react@19.2.3) - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) warn-once: 0.1.1 - react-native-screens@4.25.2(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): + react-native-screens@4.25.2(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728): dependencies: react: 19.3.0-canary-96fcba90-20260728 react-freeze: 1.0.4(react@19.3.0-canary-96fcba90-20260728) - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) warn-once: 0.1.1 optional: true - react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: css-select: 5.2.2 css-tree: 1.1.3 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) warn-once: 0.1.1 - react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): + react-native-svg@15.15.4(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728): dependencies: css-select: 5.2.2 css-tree: 1.1.3 react: 19.3.0-canary-96fcba90-20260728 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) warn-once: 0.1.1 react-native-web@0.21.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3): @@ -20954,64 +20882,64 @@ snapshots: transitivePeerDependencies: - encoding - react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): + react-native-webview@13.16.1(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3): dependencies: escape-string-regexp: 4.0.0 invariant: 2.2.4 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) - - react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3): - dependencies: - '@babel/core': 7.29.7 - '@babel/plugin-transform-arrow-functions': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-shorthand-properties': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-template-literals': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7) - '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) + + react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/plugin-transform-arrow-functions': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-shorthand-properties': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-template-literals': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/types': 7.29.7 - '@react-native/metro-config': 0.86.0(@babel/core@7.29.7) + '@react-native/metro-config': 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) convert-source-map: 2.0.0 react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) semver: 7.8.5 transitivePeerDependencies: - supports-color - react-native-worklets@0.10.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): - dependencies: - '@babel/core': 7.29.7 - '@babel/plugin-transform-arrow-functions': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-shorthand-properties': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-template-literals': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7) - '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7) + react-native-worklets@0.10.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/plugin-transform-arrow-functions': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-shorthand-properties': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-template-literals': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@babel/types': 7.29.7 - '@react-native/metro-config': 0.86.0(@babel/core@7.29.7) + '@react-native/metro-config': 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) convert-source-map: 2.0.0 react: 19.3.0-canary-96fcba90-20260728 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1) semver: 7.8.5 transitivePeerDependencies: - supports-color - react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3): + react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1): dependencies: '@react-native/assets-registry': 0.86.0 - '@react-native/codegen': 0.86.0(@babel/core@7.29.7) - '@react-native/community-cli-plugin': 0.86.0(@react-native/metro-config@0.86.0(@babel/core@7.29.7)) + '@react-native/codegen': 0.86.0(@babel/core@7.29.7(supports-color@8.1.1)) + '@react-native/community-cli-plugin': 0.86.0(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(supports-color@8.1.1) '@react-native/gradle-plugin': 0.86.0 '@react-native/js-polyfills': 0.86.0 '@react-native/normalize-colors': 0.86.0 - '@react-native/virtualized-lists': 0.86.0(@types/react@19.2.17)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3) + '@react-native/virtualized-lists': 0.86.0(@types/react@19.2.17)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3) abort-controller: 3.0.0 anser: 1.4.10 ansi-regex: 5.0.1 @@ -21023,7 +20951,7 @@ snapshots: invariant: 2.2.4 memoize-one: 5.2.1 metro-runtime: 0.84.4 - metro-source-map: 0.84.4 + metro-source-map: 0.84.4(supports-color@8.1.1) nullthrows: 1.1.1 pretty-format: 29.7.0 promise: 8.3.0 @@ -21048,15 +20976,15 @@ snapshots: - supports-color - utf-8-validate - react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728): + react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1): dependencies: '@react-native/assets-registry': 0.86.0 - '@react-native/codegen': 0.86.0(@babel/core@7.29.7) - '@react-native/community-cli-plugin': 0.86.0(@react-native/metro-config@0.86.0(@babel/core@7.29.7)) + '@react-native/codegen': 0.86.0(@babel/core@7.29.7(supports-color@8.1.1)) + '@react-native/community-cli-plugin': 0.86.0(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(supports-color@8.1.1) '@react-native/gradle-plugin': 0.86.0 '@react-native/js-polyfills': 0.86.0 '@react-native/normalize-colors': 0.86.0 - '@react-native/virtualized-lists': 0.86.0(@types/react@19.2.17)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + '@react-native/virtualized-lists': 0.86.0(@types/react@19.2.17)(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1))(react@19.3.0-canary-96fcba90-20260728) abort-controller: 3.0.0 anser: 1.4.10 ansi-regex: 5.0.1 @@ -21068,7 +20996,7 @@ snapshots: invariant: 2.2.4 memoize-one: 5.2.1 metro-runtime: 0.84.4 - metro-source-map: 0.84.4 + metro-source-map: 0.84.4(supports-color@8.1.1) nullthrows: 1.1.1 pretty-format: 29.7.0 promise: 8.3.0 @@ -21131,14 +21059,11 @@ snapshots: react@19.2.3: {} - react@19.2.7: - optional: true - react@19.3.0-canary-96fcba90-20260728: {} - read-binary-file-arch@1.0.6: + read-binary-file-arch@1.0.6(supports-color@8.1.1): dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -21241,10 +21166,10 @@ snapshots: hast-util-to-string: 3.0.1 unist-util-visit: 5.1.0 - remark-cjk-friendly-gfm-strikethrough@2.3.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(unified@11.0.5): + remark-cjk-friendly-gfm-strikethrough@2.3.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@8.1.1))(supports-color@8.1.1)(unified@11.0.5): dependencies: - mdast-util-to-markdown-cjk-friendly-gfm-strikethrough: 1.0.0(@types/mdast@4.0.4)(micromark-util-types@2.0.2) - micromark-extension-cjk-friendly-gfm-strikethrough: 2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2) + mdast-util-to-markdown-cjk-friendly-gfm-strikethrough: 1.0.0(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(supports-color@8.1.1) + micromark-extension-cjk-friendly-gfm-strikethrough: 2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@8.1.1)) unified: 11.0.5 optionalDependencies: '@types/mdast': 4.0.4 @@ -21253,10 +21178,10 @@ snapshots: - micromark-util-types - supports-color - remark-cjk-friendly@2.3.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(unified@11.0.5): + remark-cjk-friendly@2.3.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@8.1.1))(unified@11.0.5): dependencies: mdast-util-to-markdown-cjk-friendly: 1.0.0(@types/mdast@4.0.4)(micromark-util-types@2.0.2) - micromark-extension-cjk-friendly: 2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2) + micromark-extension-cjk-friendly: 2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@8.1.1)) unified: 11.0.5 optionalDependencies: '@types/mdast': 4.0.4 @@ -21264,21 +21189,21 @@ snapshots: - micromark - micromark-util-types - remark-gfm@4.0.1: + remark-gfm@4.0.1(supports-color@8.1.1): dependencies: '@types/mdast': 4.0.4 - mdast-util-gfm: 3.1.0 + mdast-util-gfm: 3.1.0(supports-color@8.1.1) micromark-extension-gfm: 3.0.0 - remark-parse: 11.0.0 + remark-parse: 11.0.0(supports-color@8.1.1) remark-stringify: 11.0.0 unified: 11.0.5 transitivePeerDependencies: - supports-color - remark-parse@11.0.0: + remark-parse@11.0.0(supports-color@8.1.1): dependencies: '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.3 + mdast-util-from-markdown: 2.0.3(supports-color@8.1.1) micromark-util-types: 2.0.2 unified: 11.0.5 transitivePeerDependencies: @@ -21304,9 +21229,9 @@ snapshots: require-from-string@2.0.2: {} - require-in-the-middle@8.0.1: + require-in-the-middle@8.0.1(supports-color@8.1.1): dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) module-details-from-path: 1.0.4 transitivePeerDependencies: - supports-color @@ -21430,9 +21355,9 @@ snapshots: points-on-curve: 0.2.0 points-on-path: 0.2.1 - router@2.2.0: + router@2.2.0(supports-color@8.1.1): dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 @@ -21492,9 +21417,9 @@ snapshots: semver@7.8.5: {} - send@0.19.2: + send@0.19.2(supports-color@8.1.1): dependencies: - debug: 2.6.9 + debug: 2.6.9(supports-color@8.1.1) depd: 2.0.0 destroy: 1.2.0 encodeurl: 2.0.0 @@ -21510,9 +21435,9 @@ snapshots: transitivePeerDependencies: - supports-color - send@1.2.1: + send@1.2.1(supports-color@8.1.1): dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -21533,21 +21458,21 @@ snapshots: type-fest: 0.13.1 optional: true - serve-static@1.16.3: + serve-static@1.16.3(supports-color@8.1.1): dependencies: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 0.19.2 + send: 0.19.2(supports-color@8.1.1) transitivePeerDependencies: - supports-color - serve-static@2.2.1: + serve-static@2.2.1(supports-color@8.1.1): dependencies: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 1.2.1 + send: 1.2.1(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -21653,58 +21578,58 @@ snapshots: dot-case: 3.0.4 tslib: 2.8.1 - socket.io-adapter@2.5.7: + socket.io-adapter@2.5.7(supports-color@8.1.1): dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) ws: 8.21.1 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - socket.io-client@4.8.3: + socket.io-client@4.8.3(supports-color@8.1.1): dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3 - engine.io-client: 6.6.5 - socket.io-parser: 4.2.6 + debug: 4.4.3(supports-color@8.1.1) + engine.io-client: 6.6.5(supports-color@8.1.1) + socket.io-parser: 4.2.6(supports-color@8.1.1) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - socket.io-parser@4.2.6: + socket.io-parser@4.2.6(supports-color@8.1.1): dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color - socket.io@4.8.3: + socket.io@4.8.3(supports-color@8.1.1): dependencies: accepts: 1.3.8 base64id: 2.0.0 cors: 2.8.6 - debug: 4.4.3 - engine.io: 6.6.8 - socket.io-adapter: 2.5.7 - socket.io-parser: 4.2.6 + debug: 4.4.3(supports-color@8.1.1) + engine.io: 6.6.8(supports-color@8.1.1) + socket.io-adapter: 2.5.7(supports-color@8.1.1) + socket.io-parser: 4.2.6(supports-color@8.1.1) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - socks-proxy-agent@10.1.0: + socks-proxy-agent@10.1.0(supports-color@8.1.1): dependencies: agent-base: 9.0.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) socks: 2.8.9 transitivePeerDependencies: - supports-color socks@2.8.9: dependencies: - ip-address: 10.2.0 + ip-address: 10.3.1 smart-buffer: 4.2.0 sonic-boom@4.2.1: @@ -21768,10 +21693,10 @@ snapshots: stream-buffers@2.2.0: {} - streamdown@2.5.0(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728): + streamdown@2.5.0(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)(supports-color@8.1.1): dependencies: clsx: 2.1.1 - hast-util-to-jsx-runtime: 2.3.6 + hast-util-to-jsx-runtime: 2.3.6(supports-color@8.1.1) html-url-attributes: 3.0.1 marked: 17.0.6 mermaid: 11.16.0 @@ -21780,8 +21705,8 @@ snapshots: rehype-harden: 1.1.8 rehype-raw: 7.0.0 rehype-sanitize: 6.0.0 - remark-gfm: 4.0.1 - remark-parse: 11.0.0 + remark-gfm: 4.0.1(supports-color@8.1.1) + remark-parse: 11.0.0(supports-color@8.1.1) remark-rehype: 11.1.2 remend: 1.3.0 tailwind-merge: 3.6.0 @@ -21861,9 +21786,9 @@ snapshots: tinyglobby: 0.2.17 ts-interface-checker: 0.1.13 - sumchecker@3.0.1: + sumchecker@3.0.1(supports-color@8.1.1): dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -21944,7 +21869,7 @@ snapshots: tayori@0.3.8(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728)(swr@2.4.2(react@19.3.0-canary-96fcba90-20260728)): dependencies: - foxact: 0.3.8(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) + foxact: 0.3.10(react-dom@19.3.0-canary-96fcba90-20260728(react@19.3.0-canary-96fcba90-20260728))(react@19.3.0-canary-96fcba90-20260728) react: 19.3.0-canary-96fcba90-20260728 stable-hash: 0.0.6 swr: 2.4.2(react@19.3.0-canary-96fcba90-20260728) @@ -22064,13 +21989,13 @@ snapshots: tslib@2.8.1: {} - tsup@8.5.1(@typescript/typescript6@6.0.2)(jiti@2.7.0)(postcss@8.5.24)(tsx@4.23.1)(yaml@2.9.0): + tsup@8.5.1(@typescript/typescript6@6.0.2)(jiti@2.7.0)(postcss@8.5.24)(supports-color@8.1.1)(tsx@4.23.1)(yaml@2.9.0): dependencies: bundle-require: 5.1.0(esbuild@0.28.1) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 - debug: 4.4.3 + debug: 4.4.3(supports-color@8.1.1) esbuild: 0.28.1 fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 @@ -22139,13 +22064,13 @@ snapshots: typebox@1.1.38: {} - typescript-eslint@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)): + typescript-eslint@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1): dependencies: - '@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)))(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - '@typescript-eslint/parser': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - '@typescript-eslint/typescript-estree': 8.65.0(@typescript/typescript6@6.0.2) - '@typescript-eslint/utils': 8.65.0(@typescript/typescript6@6.0.2)(eslint@10.8.0(jiti@2.7.0)) - eslint: 10.8.0(jiti@2.7.0) + '@typescript-eslint/eslint-plugin': 8.68.0(@typescript-eslint/parser@8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1))(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + '@typescript-eslint/parser': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + '@typescript-eslint/typescript-estree': 8.68.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1) + '@typescript-eslint/utils': 8.68.0(@typescript/typescript6@6.0.2)(eslint@10.9.1(jiti@2.7.0)(supports-color@8.1.1))(supports-color@8.1.1) + eslint: 10.9.1(jiti@2.7.0)(supports-color@8.1.1) typescript: '@typescript/typescript6@6.0.2' transitivePeerDependencies: - supports-color @@ -22245,24 +22170,24 @@ snapshots: universalify@2.0.1: {} - uniwind@1.10.0(@expo/metro-config@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4))(metro-cache@0.84.4)(metro-transform-worker@0.84.4)(metro@0.84.4)(react-native@0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tailwindcss@4.3.3): + uniwind@1.10.0(@expo/metro-config@57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(supports-color@8.1.1))(metro-cache@0.84.4(supports-color@8.1.1))(metro-transform-worker@0.84.4(supports-color@8.1.1))(metro@0.84.4(supports-color@8.1.1))(react-native@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1))(react@19.2.3)(tailwindcss@4.3.3): dependencies: '@tailwindcss/node': 4.3.0 '@tailwindcss/oxide': 4.3.0 culori: 4.0.2 lightningcss: 1.30.1 - metro: 0.84.4 - metro-cache: 0.84.4 + metro: 0.84.4(supports-color@8.1.1) + metro-cache: 0.84.4(supports-color@8.1.1) react: 19.2.3 - react-native: 0.86.0(@babel/core@7.29.7)(@react-native/metro-config@0.86.0(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3) + react-native: 0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.86.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.2.17)(react@19.2.3)(supports-color@8.1.1) tailwindcss: 4.3.3 optionalDependencies: - '@expo/metro-config': 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4) - metro-transform-worker: 0.84.4 + '@expo/metro-config': 57.0.3(@typescript/typescript6@6.0.2)(expo@57.0.4)(supports-color@8.1.1) + metro-transform-worker: 0.84.4(supports-color@8.1.1) unpipe@1.0.0: {} - unplugin-icons@23.0.1(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)): + unplugin-icons@23.0.1(@svgr/core@8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1)): dependencies: '@antfu/install-pkg': 1.1.0 '@iconify/utils': 3.1.3 @@ -22270,12 +22195,12 @@ snapshots: obug: 2.1.3 unplugin: 2.3.11 optionalDependencies: - '@svgr/core': 8.1.0(@typescript/typescript6@6.0.2) + '@svgr/core': 8.1.0(@typescript/typescript6@6.0.2)(supports-color@8.1.1) unplugin@2.3.11: dependencies: '@jridgewell/remapping': 2.3.5 - acorn: 8.17.0 + acorn: 8.18.0 picomatch: 4.0.5 webpack-virtual-modules: 0.6.2 @@ -22368,11 +22293,6 @@ snapshots: react: 19.2.3 optional: true - use-sync-external-store@1.6.0(react@19.2.7): - dependencies: - react: 19.2.7 - optional: true - use-sync-external-store@1.6.0(react@19.3.0-canary-96fcba90-20260728): dependencies: react: 19.3.0-canary-96fcba90-20260728 @@ -22400,6 +22320,8 @@ snapshots: - '@types/react' - '@types/react-dom' + verkit@0.3.2: {} + vfile-location@5.0.3: dependencies: '@types/unist': 3.0.3 @@ -22558,8 +22480,6 @@ snapshots: ws@7.5.11: {} - ws@8.21.0: {} - ws@8.21.1: {} xcode@3.0.1: @@ -22636,12 +22556,6 @@ snapshots: react: 19.2.3 use-sync-external-store: 1.6.0(react@19.2.3) - zustand@5.0.14(@types/react@19.2.17)(react@19.2.7)(use-sync-external-store@1.6.0(react@19.2.7)): - optionalDependencies: - '@types/react': 19.2.17 - react: 19.2.7 - use-sync-external-store: 1.6.0(react@19.2.7) - zustand@5.0.14(@types/react@19.2.17)(react@19.3.0-canary-96fcba90-20260728)(use-sync-external-store@1.6.0(react@19.3.0-canary-96fcba90-20260728)): optionalDependencies: '@types/react': 19.2.17