diff --git a/apps/mana/apps/web/package.json b/apps/mana/apps/web/package.json index 27d67bd15..5a710da19 100644 --- a/apps/mana/apps/web/package.json +++ b/apps/mana/apps/web/package.json @@ -53,6 +53,7 @@ "@mana/local-store": "workspace:*", "@mana/local-stt": "workspace:^", "@mana/qr-export": "workspace:*", + "@mana/shared-ai": "workspace:*", "@mana/shared-auth": "workspace:*", "@mana/shared-auth-ui": "workspace:*", "@mana/shared-branding": "workspace:*", diff --git a/apps/mana/apps/web/src/lib/data/ai/missions/planner/parser.ts b/apps/mana/apps/web/src/lib/data/ai/missions/planner/parser.ts index 5226bee6a..edf8f019e 100644 --- a/apps/mana/apps/web/src/lib/data/ai/missions/planner/parser.ts +++ b/apps/mana/apps/web/src/lib/data/ai/missions/planner/parser.ts @@ -1,99 +1,7 @@ /** - * Parser for Planner LLM output. - * - * Strict: we only accept the fenced `json` block the system prompt - * prescribes, validate shape, and surface errors so the Runner can - * record them on the iteration instead of silently producing a bad plan. + * Re-export of the Planner response parser from @mana/shared-ai. + * Kept here so existing webapp imports (and tests) keep working. */ -import type { AiPlanOutput, PlannedStep } from './types'; - -export type ParseResult = - | { readonly ok: true; readonly value: AiPlanOutput } - | { readonly ok: false; readonly reason: string; readonly raw?: string }; - -/** Extract and validate the Planner JSON from the LLM's raw response. */ -export function parsePlannerResponse(text: string, knownToolNames: Set): ParseResult { - const block = extractJsonBlock(text); - if (!block) return { ok: false, reason: 'no JSON block found', raw: text }; - - let parsed: unknown; - try { - parsed = JSON.parse(block); - } catch (err) { - return { - ok: false, - reason: `JSON parse failed: ${err instanceof Error ? err.message : String(err)}`, - raw: block, - }; - } - - if (typeof parsed !== 'object' || parsed === null) { - return { ok: false, reason: 'top-level value is not an object', raw: block }; - } - - const obj = parsed as Record; - const summary = typeof obj.summary === 'string' ? obj.summary : ''; - const rawSteps = obj.steps; - if (!Array.isArray(rawSteps)) { - return { ok: false, reason: '`steps` must be an array', raw: block }; - } - - const steps: PlannedStep[] = []; - for (let i = 0; i < rawSteps.length; i++) { - const step = rawSteps[i]; - const validation = validateStep(step, knownToolNames, i); - if (!validation.ok) { - return { ok: false, reason: validation.reason, raw: block }; - } - steps.push(validation.value); - } - - return { ok: true, value: { summary, steps } }; -} - -function extractJsonBlock(text: string): string | null { - // Prefer a ```json fenced block - const fenced = /```(?:json)?\s*\n?([\s\S]*?)\n?```/; - const m = text.match(fenced); - if (m) return m[1].trim(); - // Fallback: the whole response might BE a JSON object - const trimmed = text.trim(); - if (trimmed.startsWith('{') && trimmed.endsWith('}')) return trimmed; - return null; -} - -function validateStep( - raw: unknown, - knownToolNames: Set, - index: number -): { ok: true; value: PlannedStep } | { ok: false; reason: string } { - if (typeof raw !== 'object' || raw === null) { - return { ok: false, reason: `step[${index}] is not an object` }; - } - const obj = raw as Record; - const toolName = obj.toolName; - if (typeof toolName !== 'string' || toolName.length === 0) { - return { ok: false, reason: `step[${index}].toolName missing or not a string` }; - } - if (!knownToolNames.has(toolName)) { - return { - ok: false, - reason: `step[${index}].toolName "${toolName}" is not in the allowed tool set`, - }; - } - const summary = typeof obj.summary === 'string' ? obj.summary : ''; - const rationale = typeof obj.rationale === 'string' ? obj.rationale : ''; - if (rationale.length === 0) { - return { ok: false, reason: `step[${index}].rationale is required (user will see this)` }; - } - const params = - typeof obj.params === 'object' && obj.params !== null - ? (obj.params as Record) - : {}; - - return { - ok: true, - value: { summary, toolName, rationale, params }, - }; -} +export { parsePlannerResponse } from '@mana/shared-ai'; +export type { ParseResult } from '@mana/shared-ai'; diff --git a/apps/mana/apps/web/src/lib/data/ai/missions/planner/prompt.ts b/apps/mana/apps/web/src/lib/data/ai/missions/planner/prompt.ts index 5e5ae54d0..56911bcc0 100644 --- a/apps/mana/apps/web/src/lib/data/ai/missions/planner/prompt.ts +++ b/apps/mana/apps/web/src/lib/data/ai/missions/planner/prompt.ts @@ -1,112 +1,7 @@ /** - * Prompt builder for the Mission Planner. - * - * Produces a system + user message pair the LLM backend can consume. The - * grammar we ask the model to return is deliberately small (JSON in a - * fenced block, one shape) — the parser is strict, and we'd rather the - * LLM mess up in a detectable way than produce half-valid output. - * - * Keeps everything the Planner sees inside the prompt, nothing ambient — - * makes the task reproducible and unit-testable without a live LLM. + * Re-export of the Planner prompt builder from @mana/shared-ai. + * Kept here so existing webapp imports (and tests) keep working. */ -import type { AiPlanInput } from './types'; - -export interface PlannerMessages { - readonly system: string; - readonly user: string; -} - -export function buildPlannerPrompt(input: AiPlanInput): PlannerMessages { - return { - system: buildSystemPrompt(input), - user: buildUserPrompt(input), - }; -} - -function buildSystemPrompt(input: AiPlanInput): string { - const toolBlock = input.availableTools - .map((t) => { - const params = t.parameters - .map((p) => { - const req = p.required ? ' (required)' : ''; - const enumeration = p.enum ? ` [${p.enum.join('|')}]` : ''; - return ` - ${p.name}: ${p.type}${enumeration}${req} — ${p.description}`; - }) - .join('\n'); - return ` • ${t.name} (${t.module}) — ${t.description}\n${params || ' (no parameters)'}`; - }) - .join('\n'); - - return `Du bist eine KI, die im Auftrag des Nutzers an einer langlebigen Mission arbeitet. - -Dein Job: aus dem aktuellen Mission-Kontext einen kurzen, konkreten Plan ableiten — 1 bis 5 Schritte, jeder ein Tool-Aufruf auf Nutzerdaten. Jeder Schritt MUSS eine Begründung haben (rationale), die der Nutzer in der Review-UI sieht. - -Wichtige Regeln: -1. Nutze NUR Tools aus der Liste unten. Unbekannte Tools → Plan invalide. -2. Jeder Step wird als Proposal gestaged — der Nutzer approved oder rejected. Du schreibst nie direkt. -3. Berücksichtige das Feedback aus vorherigen Iterationen (unten im User-Prompt). Wenn ein Vorschlag rejected wurde, wiederhole ihn nicht ohne Änderung. -4. Antworte AUSSCHLIESSLICH mit einem JSON-Block in folgendem Format, keine Prosa davor/danach: - -\`\`\`json -{ - "summary": "Ein Satz was du in dieser Iteration tust.", - "steps": [ - { - "summary": "Kurzer Schritt-Titel", - "toolName": "create_task", - "params": { "title": "…" }, - "rationale": "Warum genau jetzt, auf Basis welchen Inputs." - } - ] -} -\`\`\` - -Verfügbare Tools: -${toolBlock || ' (keine Tools verfügbar — gib leeren steps zurück)'}`; -} - -function buildUserPrompt(input: AiPlanInput): string { - const { mission, resolvedInputs } = input; - - const inputsBlock = - resolvedInputs.length === 0 - ? '_(keine verlinkten Inputs)_' - : resolvedInputs - .map((r) => { - const header = `### ${r.module}/${r.table}: ${r.title ?? r.id}`; - return `${header}\n${r.content}`; - }) - .join('\n\n'); - - const iterationHistory = - mission.iterations.length === 0 - ? '_(erste Iteration)_' - : mission.iterations - .slice(-3) // only the last 3 to keep the prompt tight - .map((it) => { - const steps = it.plan.map((s) => ` - [${s.status}] ${s.summary}`).join('\n'); - const feedback = it.userFeedback ? `\n Nutzer-Feedback: ${it.userFeedback}` : ''; - const summary = it.summary ? `\n Summary: ${it.summary}` : ''; - return `**${it.startedAt}** (${it.overallStatus}):${summary}\n${steps}${feedback}`; - }) - .join('\n\n'); - - return `# Mission: ${mission.title} - -## Konzept -${mission.conceptMarkdown || '_(leer)_'} - -## Konkretes Ziel -${mission.objective} - -## Verlinkte Inputs -${inputsBlock} - -## Letzte Iterationen (max. 3) -${iterationHistory} - ---- - -Erzeuge jetzt einen Plan für die nächste Iteration.`; -} +export { buildPlannerPrompt } from '@mana/shared-ai'; +export type { PlannerMessages } from '@mana/shared-ai'; diff --git a/apps/mana/apps/web/src/lib/data/ai/missions/planner/types.ts b/apps/mana/apps/web/src/lib/data/ai/missions/planner/types.ts index d6822de2c..353ac813e 100644 --- a/apps/mana/apps/web/src/lib/data/ai/missions/planner/types.ts +++ b/apps/mana/apps/web/src/lib/data/ai/missions/planner/types.ts @@ -1,56 +1,12 @@ /** - * Planner contract — shared input / output shape used by prompt builder, - * parser, and the `aiPlanTask` LLM wrapper. + * Re-export of Planner types from @mana/shared-ai. The shared package is + * the source of truth — webapp and mana-ai service both import from it. */ -import type { Mission } from '../types'; - -/** Resolved content for one {@link MissionInputRef}. */ -export interface ResolvedInput { - readonly id: string; - readonly module: string; - readonly table: string; - readonly title?: string; - readonly content: string; -} - -/** Tool definition the Planner is allowed to propose. */ -export interface AvailableTool { - readonly name: string; - readonly module: string; - readonly description: string; - readonly parameters: ReadonlyArray<{ - readonly name: string; - readonly type: string; - readonly required: boolean; - readonly description: string; - readonly enum?: readonly string[]; - }>; -} - -export interface AiPlanInput { - readonly mission: Mission; - /** Content of every MissionInputRef, pre-fetched by the caller (Runner). */ - readonly resolvedInputs: readonly ResolvedInput[]; - /** Tools the policy has whitelisted for AI proposals in this run. */ - readonly availableTools: readonly AvailableTool[]; -} - -/** - * One step in the Planner's output. The Runner turns each step into a - * Proposal by calling `executeTool(toolName, params, aiActor)` — the - * policy routes it to `propose`, and the Proposal carries the rationale. - */ -export interface PlannedStep { - readonly summary: string; - readonly toolName: string; - readonly params: Record; - readonly rationale: string; -} - -export interface AiPlanOutput { - /** 1–N steps the AI wants to take this iteration. May be empty (no-op run). */ - readonly steps: readonly PlannedStep[]; - /** The AI's one-line summary of the plan, stored on `MissionIteration.summary`. */ - readonly summary: string; -} +export type { + AiPlanInput, + AiPlanOutput, + AvailableTool, + PlannedStep, + ResolvedInput, +} from '@mana/shared-ai'; diff --git a/apps/mana/apps/web/src/lib/data/ai/missions/types.ts b/apps/mana/apps/web/src/lib/data/ai/missions/types.ts index e6feb2526..38aa93cf2 100644 --- a/apps/mana/apps/web/src/lib/data/ai/missions/types.ts +++ b/apps/mana/apps/web/src/lib/data/ai/missions/types.ts @@ -1,106 +1,22 @@ /** - * Missions — long-lived AI work items. + * Webapp-local re-export of Mission types from @mana/shared-ai plus + * storage-layer concerns (Dexie table name, proposal-status bridge). * - * A Mission is the user's standing instruction to the AI ("review my goals - * every Monday and propose three concrete actions"). The AI plans, stages - * proposals (via `pendingProposals`), collects feedback, and iterates. - * - * This file is data-model only. The Planner and Runner live elsewhere and - * operate on Missions — see `COMPANION_BRAIN_ARCHITECTURE.md §20` for the - * full pipeline. - * - * Missions sync (unlike proposals) — they are long-lived user-authored - * artifacts and should be available cross-device. Sensitive user-typed - * text (conceptMarkdown, objective, rationale strings in iterations) is - * encryption-eligible; IDs, timestamps, state enums stay plaintext. + * The runtime types themselves live in the shared package so the + * mana-ai Bun service parses identical rows. */ import type { ProposalStatus } from '../proposals/types'; +import type { PlanStep } from '@mana/shared-ai'; -/** Lifecycle of a Mission. */ -export type MissionState = 'active' | 'paused' | 'done' | 'archived'; - -/** How often the Runner should pick this Mission up. */ -export type MissionCadence = - | { readonly kind: 'manual' } - | { readonly kind: 'interval'; readonly everyMinutes: number } - | { readonly kind: 'daily'; readonly atHour: number; readonly atMinute: number } - | { - readonly kind: 'weekly'; - readonly dayOfWeek: 0 | 1 | 2 | 3 | 4 | 5 | 6; - readonly atHour: number; - } - | { readonly kind: 'cron'; readonly expression: string }; - -/** Reference to a record in another module this Mission draws context from. */ -export interface MissionInputRef { - /** Source module — e.g. `'notes'`, `'goals'`, `'kontext'`. */ - readonly module: string; - /** Dexie table name (needed because some modules have multiple). */ - readonly table: string; - /** Record id. */ - readonly id: string; -} - -/** A single step the Planner proposed for the current iteration. */ -export interface PlanStep { - readonly id: string; - /** Human-readable summary shown in the Workbench. */ - readonly summary: string; - /** What runs — today only toolCalls; later: sub-missions, text-generation, etc. */ - readonly intent: - | { - readonly kind: 'toolCall'; - readonly toolName: string; - readonly params: Record; - } - | { readonly kind: 'note'; readonly body: string }; - /** Proposal id if this step was staged; undefined before execution. */ - readonly proposalId?: string; - /** Outcome of this step. */ - readonly status: 'planned' | 'staged' | 'approved' | 'rejected' | 'skipped' | 'failed'; -} - -/** One autonomous run of the Mission, produced by the Runner invoking the Planner. */ -export interface MissionIteration { - readonly id: string; - readonly startedAt: string; - readonly finishedAt?: string; - /** Plan the Planner generated this run. */ - readonly plan: readonly PlanStep[]; - /** AI's own notes on what it did and why (for the next iteration's context). */ - readonly summary?: string; - /** Free-text feedback the user attached on review. */ - readonly userFeedback?: string; - /** Shortcut derived from step proposal statuses — used by queries / UI. */ - readonly overallStatus: 'running' | 'awaiting-review' | 'approved' | 'rejected' | 'failed'; -} - -export interface Mission { - readonly id: string; - readonly createdAt: string; - readonly updatedAt: string; - /** Short user-facing name. */ - title: string; - /** Markdown doc describing the concept / rules of engagement. */ - conceptMarkdown: string; - /** One-sentence concrete objective. */ - objective: string; - /** Module records this Mission reads from for context. */ - inputs: readonly MissionInputRef[]; - /** Cadence the Runner honours. */ - cadence: MissionCadence; - /** Lifecycle. */ - state: MissionState; - /** ISO timestamp of the next scheduled run, or undefined if not scheduled. */ - nextRunAt?: string; - /** All past iterations, newest last. */ - iterations: readonly MissionIteration[]; - - // ── Bookkeeping ────────────────────────── - userId?: string; - deletedAt?: string; -} +export type { + Mission, + MissionCadence, + MissionInputRef, + MissionIteration, + MissionState, + PlanStep, +} from '@mana/shared-ai'; export const MISSIONS_TABLE = 'aiMissions'; diff --git a/packages/shared-ai/package.json b/packages/shared-ai/package.json new file mode 100644 index 000000000..7a2657f3e --- /dev/null +++ b/packages/shared-ai/package.json @@ -0,0 +1,23 @@ +{ + "name": "@mana/shared-ai", + "version": "0.1.0", + "private": true, + "type": "module", + "sideEffects": false, + "description": "Shared AI Workbench code: actor types, planner prompt + parser, mission types", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts", + "./planner": "./src/planner/index.ts", + "./missions": "./src/missions/index.ts" + }, + "scripts": { + "type-check": "tsc --noEmit", + "test": "vitest run" + }, + "devDependencies": { + "typescript": "^5.9.3", + "vitest": "^4.1.3" + } +} diff --git a/packages/shared-ai/src/actor.ts b/packages/shared-ai/src/actor.ts new file mode 100644 index 000000000..abfe834a3 --- /dev/null +++ b/packages/shared-ai/src/actor.ts @@ -0,0 +1,32 @@ +/** + * Actor attribution type — the discriminated union stamped on every + * event, record, and sync-change row in the Mana system. + * + * Runtime helpers (runAs, runAsAsync, ambient context) stay in the webapp + * because they rely on browser single-threaded semantics and module-level + * mutable state. The *type* is shared so server-side consumers can parse + * incoming actors without re-declaring the union. + */ + +export type Actor = + | { readonly kind: 'user' } + | { + readonly kind: 'ai'; + readonly missionId: string; + readonly iterationId: string; + readonly rationale: string; + } + | { + readonly kind: 'system'; + readonly source: 'projection' | 'rule' | 'migration'; + }; + +export const USER_ACTOR: Actor = Object.freeze({ kind: 'user' }); + +export function isAiActor(actor: Actor | undefined): boolean { + return actor?.kind === 'ai'; +} + +export function isSystemActor(actor: Actor | undefined): boolean { + return actor?.kind === 'system'; +} diff --git a/packages/shared-ai/src/index.ts b/packages/shared-ai/src/index.ts new file mode 100644 index 000000000..fa43875c4 --- /dev/null +++ b/packages/shared-ai/src/index.ts @@ -0,0 +1,31 @@ +/** + * @mana/shared-ai + * + * AI Workbench code that both the webapp (SvelteKit/Vite) and the + * server-side mana-ai service (Bun) import. Keep this package free of + * runtime imports from storage layers (Dexie, Postgres) — the types + + * pure functions here must work in both environments. + */ + +export type { Actor } from './actor'; +export { USER_ACTOR, isAiActor, isSystemActor } from './actor'; + +export type { + Mission, + MissionCadence, + MissionInputRef, + MissionIteration, + MissionState, + PlanStep, +} from './missions'; + +export type { + AiPlanInput, + AiPlanOutput, + AvailableTool, + ParseResult, + PlannedStep, + PlannerMessages, + ResolvedInput, +} from './planner'; +export { buildPlannerPrompt, parsePlannerResponse } from './planner'; diff --git a/packages/shared-ai/src/missions/index.ts b/packages/shared-ai/src/missions/index.ts new file mode 100644 index 000000000..3cb4bd29c --- /dev/null +++ b/packages/shared-ai/src/missions/index.ts @@ -0,0 +1,8 @@ +export type { + Mission, + MissionCadence, + MissionInputRef, + MissionIteration, + MissionState, + PlanStep, +} from './types'; diff --git a/packages/shared-ai/src/missions/types.ts b/packages/shared-ai/src/missions/types.ts new file mode 100644 index 000000000..8dbe77f1e --- /dev/null +++ b/packages/shared-ai/src/missions/types.ts @@ -0,0 +1,78 @@ +/** + * AI Workbench Mission types — the stable contract shared between the + * webapp Runner and the server-side mana-ai service. + * + * Mirrors `apps/mana/apps/web/src/lib/data/ai/missions/types.ts` for the + * runtime shape; the webapp's file re-exports these and adds storage + * concerns (Dexie table name, encryption helpers). Don't diverge without + * a migration — both runtimes deserialize the same rows. + */ + +export type MissionState = 'active' | 'paused' | 'done' | 'archived'; + +export type MissionCadence = + | { readonly kind: 'manual' } + | { readonly kind: 'interval'; readonly everyMinutes: number } + | { readonly kind: 'daily'; readonly atHour: number; readonly atMinute: number } + | { + readonly kind: 'weekly'; + readonly dayOfWeek: 0 | 1 | 2 | 3 | 4 | 5 | 6; + readonly atHour: number; + } + | { readonly kind: 'cron'; readonly expression: string }; + +export interface MissionInputRef { + readonly module: string; + readonly table: string; + readonly id: string; +} + +export interface PlanStep { + readonly id: string; + readonly summary: string; + readonly intent: + | { + readonly kind: 'toolCall'; + readonly toolName: string; + readonly params: Record; + } + | { readonly kind: 'note'; readonly body: string }; + readonly proposalId?: string; + readonly status: 'planned' | 'staged' | 'approved' | 'rejected' | 'skipped' | 'failed'; +} + +export interface MissionIteration { + readonly id: string; + readonly startedAt: string; + readonly finishedAt?: string; + readonly plan: readonly PlanStep[]; + readonly summary?: string; + readonly userFeedback?: string; + readonly overallStatus: 'running' | 'awaiting-review' | 'approved' | 'rejected' | 'failed'; + /** + * Where this iteration was produced. + * 'browser' — the foreground Runner in the user's tab (default). + * 'server' — produced by the mana-ai background service; + * on sync, the webapp translates PlanStep[] into local + * Proposals via its staging effect. + * Missing/undefined is treated as 'browser' for back-compat with + * pre-server iterations. + */ + readonly source?: 'browser' | 'server'; +} + +export interface Mission { + readonly id: string; + readonly createdAt: string; + readonly updatedAt: string; + title: string; + conceptMarkdown: string; + objective: string; + inputs: readonly MissionInputRef[]; + cadence: MissionCadence; + state: MissionState; + nextRunAt?: string; + iterations: readonly MissionIteration[]; + userId?: string; + deletedAt?: string; +} diff --git a/packages/shared-ai/src/planner/index.ts b/packages/shared-ai/src/planner/index.ts new file mode 100644 index 000000000..5f70819f8 --- /dev/null +++ b/packages/shared-ai/src/planner/index.ts @@ -0,0 +1,5 @@ +export { buildPlannerPrompt } from './prompt'; +export type { PlannerMessages } from './prompt'; +export { parsePlannerResponse } from './parser'; +export type { ParseResult } from './parser'; +export type { AiPlanInput, AiPlanOutput, AvailableTool, PlannedStep, ResolvedInput } from './types'; diff --git a/packages/shared-ai/src/planner/parser.test.ts b/packages/shared-ai/src/planner/parser.test.ts new file mode 100644 index 000000000..c19beb186 --- /dev/null +++ b/packages/shared-ai/src/planner/parser.test.ts @@ -0,0 +1,60 @@ +import { describe, it, expect } from 'vitest'; +import { parsePlannerResponse } from './parser'; +import { buildPlannerPrompt } from './prompt'; +import type { AiPlanInput } from './types'; +import type { Mission } from '../missions/types'; + +const TOOLS = new Set(['create_task']); + +function mission(): Mission { + return { + id: 'm', + createdAt: '2026-04-14T00:00:00Z', + updatedAt: '2026-04-14T00:00:00Z', + title: 'Test', + conceptMarkdown: '', + objective: 'x', + inputs: [], + cadence: { kind: 'manual' }, + state: 'active', + iterations: [], + }; +} + +describe('shared-ai planner', () => { + it('prompt + parser round-trip a valid plan', () => { + const input: AiPlanInput = { + mission: mission(), + resolvedInputs: [], + availableTools: [ + { + name: 'create_task', + module: 'todo', + description: 'Creates a task', + parameters: [{ name: 'title', type: 'string', required: true, description: 'Title' }], + }, + ], + }; + const { system } = buildPlannerPrompt(input); + expect(system).toContain('create_task'); + + const response = `\`\`\`json +{ + "summary": "test", + "steps": [ + { "summary": "s", "toolName": "create_task", "params": { "title": "x" }, "rationale": "why" } + ] +} +\`\`\``; + const r = parsePlannerResponse(response, TOOLS); + expect(r.ok).toBe(true); + }); + + it('rejects unknown tool names', () => { + const r = parsePlannerResponse( + `{"summary":"","steps":[{"toolName":"delete_everything","params":{},"rationale":"lol"}]}`, + TOOLS + ); + expect(r.ok).toBe(false); + }); +}); diff --git a/packages/shared-ai/src/planner/parser.ts b/packages/shared-ai/src/planner/parser.ts new file mode 100644 index 000000000..cd6efb9dd --- /dev/null +++ b/packages/shared-ai/src/planner/parser.ts @@ -0,0 +1,96 @@ +/** + * Parser for Planner LLM output. + * + * Strict: we only accept the fenced `json` block the system prompt + * prescribes, validate shape, and surface errors so the Runner can + * record them on the iteration instead of silently producing a bad plan. + */ + +import type { AiPlanOutput, PlannedStep } from './types'; + +export type ParseResult = + | { readonly ok: true; readonly value: AiPlanOutput } + | { readonly ok: false; readonly reason: string; readonly raw?: string }; + +export function parsePlannerResponse(text: string, knownToolNames: Set): ParseResult { + const block = extractJsonBlock(text); + if (!block) return { ok: false, reason: 'no JSON block found', raw: text }; + + let parsed: unknown; + try { + parsed = JSON.parse(block); + } catch (err) { + return { + ok: false, + reason: `JSON parse failed: ${err instanceof Error ? err.message : String(err)}`, + raw: block, + }; + } + + if (typeof parsed !== 'object' || parsed === null) { + return { ok: false, reason: 'top-level value is not an object', raw: block }; + } + + const obj = parsed as Record; + const summary = typeof obj.summary === 'string' ? obj.summary : ''; + const rawSteps = obj.steps; + if (!Array.isArray(rawSteps)) { + return { ok: false, reason: '`steps` must be an array', raw: block }; + } + + const steps: PlannedStep[] = []; + for (let i = 0; i < rawSteps.length; i++) { + const step = rawSteps[i]; + const validation = validateStep(step, knownToolNames, i); + if (!validation.ok) { + return { ok: false, reason: validation.reason, raw: block }; + } + steps.push(validation.value); + } + + return { ok: true, value: { summary, steps } }; +} + +function extractJsonBlock(text: string): string | null { + const fenced = /```(?:json)?\s*\n?([\s\S]*?)\n?```/; + const m = text.match(fenced); + if (m) return m[1].trim(); + const trimmed = text.trim(); + if (trimmed.startsWith('{') && trimmed.endsWith('}')) return trimmed; + return null; +} + +function validateStep( + raw: unknown, + knownToolNames: Set, + index: number +): { ok: true; value: PlannedStep } | { ok: false; reason: string } { + if (typeof raw !== 'object' || raw === null) { + return { ok: false, reason: `step[${index}] is not an object` }; + } + const obj = raw as Record; + const toolName = obj.toolName; + if (typeof toolName !== 'string' || toolName.length === 0) { + return { ok: false, reason: `step[${index}].toolName missing or not a string` }; + } + if (!knownToolNames.has(toolName)) { + return { + ok: false, + reason: `step[${index}].toolName "${toolName}" is not in the allowed tool set`, + }; + } + const summary = typeof obj.summary === 'string' ? obj.summary : ''; + const rationale = typeof obj.rationale === 'string' ? obj.rationale : ''; + if (rationale.length === 0) { + return { ok: false, reason: `step[${index}].rationale is required (user will see this)` }; + } + const params = + typeof obj.params === 'object' && obj.params !== null + ? (obj.params as Record) + : {}; + + return { + ok: true, + value: { summary, toolName, rationale, params }, + }; +} diff --git a/packages/shared-ai/src/planner/prompt.ts b/packages/shared-ai/src/planner/prompt.ts new file mode 100644 index 000000000..319a112d9 --- /dev/null +++ b/packages/shared-ai/src/planner/prompt.ts @@ -0,0 +1,112 @@ +/** + * Prompt builder for the Mission Planner. + * + * Produces a system + user message pair. The grammar we ask the model to + * return is deliberately small (JSON in a fenced block, one shape) — the + * parser is strict, and we'd rather the LLM mess up in a detectable way + * than produce half-valid output. + * + * Pure function: no ambient state. Used identically from the browser and + * the mana-ai Bun service. + */ + +import type { AiPlanInput } from './types'; + +export interface PlannerMessages { + readonly system: string; + readonly user: string; +} + +export function buildPlannerPrompt(input: AiPlanInput): PlannerMessages { + return { + system: buildSystemPrompt(input), + user: buildUserPrompt(input), + }; +} + +function buildSystemPrompt(input: AiPlanInput): string { + const toolBlock = input.availableTools + .map((t) => { + const params = t.parameters + .map((p) => { + const req = p.required ? ' (required)' : ''; + const enumeration = p.enum ? ` [${p.enum.join('|')}]` : ''; + return ` - ${p.name}: ${p.type}${enumeration}${req} — ${p.description}`; + }) + .join('\n'); + return ` • ${t.name} (${t.module}) — ${t.description}\n${params || ' (no parameters)'}`; + }) + .join('\n'); + + return `Du bist eine KI, die im Auftrag des Nutzers an einer langlebigen Mission arbeitet. + +Dein Job: aus dem aktuellen Mission-Kontext einen kurzen, konkreten Plan ableiten — 1 bis 5 Schritte, jeder ein Tool-Aufruf auf Nutzerdaten. Jeder Schritt MUSS eine Begründung haben (rationale), die der Nutzer in der Review-UI sieht. + +Wichtige Regeln: +1. Nutze NUR Tools aus der Liste unten. Unbekannte Tools → Plan invalide. +2. Jeder Step wird als Proposal gestaged — der Nutzer approved oder rejected. Du schreibst nie direkt. +3. Berücksichtige das Feedback aus vorherigen Iterationen (unten im User-Prompt). Wenn ein Vorschlag rejected wurde, wiederhole ihn nicht ohne Änderung. +4. Antworte AUSSCHLIESSLICH mit einem JSON-Block in folgendem Format, keine Prosa davor/danach: + +\`\`\`json +{ + "summary": "Ein Satz was du in dieser Iteration tust.", + "steps": [ + { + "summary": "Kurzer Schritt-Titel", + "toolName": "create_task", + "params": { "title": "…" }, + "rationale": "Warum genau jetzt, auf Basis welchen Inputs." + } + ] +} +\`\`\` + +Verfügbare Tools: +${toolBlock || ' (keine Tools verfügbar — gib leeren steps zurück)'}`; +} + +function buildUserPrompt(input: AiPlanInput): string { + const { mission, resolvedInputs } = input; + + const inputsBlock = + resolvedInputs.length === 0 + ? '_(keine verlinkten Inputs)_' + : resolvedInputs + .map((r) => { + const header = `### ${r.module}/${r.table}: ${r.title ?? r.id}`; + return `${header}\n${r.content}`; + }) + .join('\n\n'); + + const iterationHistory = + mission.iterations.length === 0 + ? '_(erste Iteration)_' + : mission.iterations + .slice(-3) + .map((it) => { + const steps = it.plan.map((s) => ` - [${s.status}] ${s.summary}`).join('\n'); + const feedback = it.userFeedback ? `\n Nutzer-Feedback: ${it.userFeedback}` : ''; + const summary = it.summary ? `\n Summary: ${it.summary}` : ''; + return `**${it.startedAt}** (${it.overallStatus}):${summary}\n${steps}${feedback}`; + }) + .join('\n\n'); + + return `# Mission: ${mission.title} + +## Konzept +${mission.conceptMarkdown || '_(leer)_'} + +## Konkretes Ziel +${mission.objective} + +## Verlinkte Inputs +${inputsBlock} + +## Letzte Iterationen (max. 3) +${iterationHistory} + +--- + +Erzeuge jetzt einen Plan für die nächste Iteration.`; +} diff --git a/packages/shared-ai/src/planner/types.ts b/packages/shared-ai/src/planner/types.ts new file mode 100644 index 000000000..895f2fa1d --- /dev/null +++ b/packages/shared-ai/src/planner/types.ts @@ -0,0 +1,45 @@ +/** + * Planner contract — input/output shape consumed by the prompt builder + * and parser. Identical between browser and server runtimes. + */ + +import type { Mission } from '../missions/types'; + +export interface ResolvedInput { + readonly id: string; + readonly module: string; + readonly table: string; + readonly title?: string; + readonly content: string; +} + +export interface AvailableTool { + readonly name: string; + readonly module: string; + readonly description: string; + readonly parameters: ReadonlyArray<{ + readonly name: string; + readonly type: string; + readonly required: boolean; + readonly description: string; + readonly enum?: readonly string[]; + }>; +} + +export interface AiPlanInput { + readonly mission: Mission; + readonly resolvedInputs: readonly ResolvedInput[]; + readonly availableTools: readonly AvailableTool[]; +} + +export interface PlannedStep { + readonly summary: string; + readonly toolName: string; + readonly params: Record; + readonly rationale: string; +} + +export interface AiPlanOutput { + readonly steps: readonly PlannedStep[]; + readonly summary: string; +} diff --git a/packages/shared-ai/tsconfig.json b/packages/shared-ai/tsconfig.json new file mode 100644 index 000000000..c828b6630 --- /dev/null +++ b/packages/shared-ai/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ES2022"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "noEmit": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index abadbf9d6..e9fb27715 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -138,14 +138,14 @@ importers: version: link:../../../../packages/shared-landing-ui astro: specifier: ^5.16.0 - version: 5.18.1(@azure/storage-blob@12.31.0)(@types/node@20.19.39)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3) + version: 5.18.1(@azure/storage-blob@12.31.0)(@types/node@20.19.39)(ioredis@5.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3) typescript: specifier: ^5.9.2 version: 5.9.3 devDependencies: '@astrojs/tailwind': specifier: ^6.0.2 - version: 6.0.2(astro@5.18.1(@azure/storage-blob@12.31.0)(@types/node@20.19.39)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.3)) + version: 6.0.2(astro@5.18.1(@azure/storage-blob@12.31.0)(@types/node@20.19.39)(ioredis@5.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.3)) '@tailwindcss/typography': specifier: ^0.5.18 version: 0.5.19(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.3)) @@ -154,13 +154,13 @@ importers: version: 20.19.39 eslint: specifier: ^9.0.0 - version: 9.39.4(jiti@1.21.7) + version: 9.39.4(jiti@2.6.1) eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.2(eslint@9.39.4(jiti@1.21.7)) + version: 9.1.2(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-astro: specifier: ^1.0.0 - version: 1.6.0(eslint@9.39.4(jiti@1.21.7)) + version: 1.6.0(eslint@9.39.4(jiti@2.6.1)) prettier: specifier: ^3.6.2 version: 3.8.1 @@ -484,19 +484,19 @@ importers: version: 19.1.17 '@typescript-eslint/eslint-plugin': specifier: ^7.7.0 - version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) '@typescript-eslint/parser': specifier: ^7.7.0 - version: 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) + version: 7.18.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) dotenv: specifier: ^16.4.7 version: 16.6.1 eslint: specifier: ^9.39.1 - version: 9.39.4(jiti@2.6.1) + version: 9.39.4(jiti@1.21.7) eslint-config-universe: specifier: ^12.0.1 - version: 12.1.0(@types/eslint@9.6.1)(eslint@9.39.4(jiti@2.6.1))(prettier@3.8.1)(typescript@5.3.3) + version: 12.1.0(@types/eslint@9.6.1)(eslint@9.39.4(jiti@1.21.7))(prettier@3.8.1)(typescript@5.3.3) prettier: specifier: ^3.2.5 version: 3.8.1 @@ -1027,6 +1027,9 @@ importers: '@mana/qr-export': specifier: workspace:* version: link:../../../../packages/qr-export + '@mana/shared-ai': + specifier: workspace:* + version: link:../../../../packages/shared-ai '@mana/shared-auth': specifier: workspace:* version: link:../../../../packages/shared-auth @@ -2756,6 +2759,15 @@ importers: specifier: ^4.1.2 version: 4.1.3(@opentelemetry/api@1.9.1)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(jsdom@29.0.2(@noble/hashes@2.0.1))(vite@6.4.2(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + packages/shared-ai: + devDependencies: + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vitest: + specifier: ^4.1.3 + version: 4.1.3(@opentelemetry/api@1.9.1)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(jsdom@29.0.2(@noble/hashes@2.0.1))(vite@6.4.2(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + packages/shared-auth: dependencies: '@mana/shared-types': @@ -3271,6 +3283,25 @@ importers: specifier: ^4.1.2 version: 4.1.3(@opentelemetry/api@1.9.1)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(jsdom@29.0.2(@noble/hashes@2.0.1))(vite@6.4.2(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + services/mana-ai: + dependencies: + '@mana/shared-hono': + specifier: workspace:* + version: link:../../packages/shared-hono + hono: + specifier: ^4.7.0 + version: 4.12.12 + postgres: + specifier: ^3.4.5 + version: 3.4.9 + devDependencies: + '@types/bun': + specifier: latest + version: 1.3.12 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + services/mana-analytics: dependencies: '@mana/shared-hono': @@ -17995,16 +18026,6 @@ snapshots: transitivePeerDependencies: - ts-node - '@astrojs/tailwind@6.0.2(astro@5.18.1(@azure/storage-blob@12.31.0)(@types/node@20.19.39)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.3))': - dependencies: - astro: 5.18.1(@azure/storage-blob@12.31.0)(@types/node@20.19.39)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3) - autoprefixer: 10.4.27(postcss@8.5.8) - postcss: 8.5.8 - postcss-load-config: 4.0.2(postcss@8.5.8) - tailwindcss: 3.4.19(tsx@4.21.0)(yaml@2.8.3) - transitivePeerDependencies: - - ts-node - '@astrojs/tailwind@6.0.2(astro@5.18.1(@azure/storage-blob@12.31.0)(@types/node@20.19.39)(ioredis@5.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.3))': dependencies: astro: 5.18.1(@azure/storage-blob@12.31.0)(@types/node@20.19.39)(ioredis@5.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3) @@ -20353,82 +20374,6 @@ snapshots: - supports-color - utf-8-validate - '@expo/cli@55.0.22(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-constants@55.0.12)(expo-font@55.0.6(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0))(expo-router@55.0.11)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3)': - dependencies: - '@expo/code-signing-certificates': 0.0.6 - '@expo/config': 55.0.13(typescript@5.9.3) - '@expo/config-plugins': 55.0.8 - '@expo/devcert': 1.2.1 - '@expo/env': 2.1.1 - '@expo/image-utils': 0.8.12 - '@expo/json-file': 10.0.13 - '@expo/log-box': 55.0.10(@expo/dom-webview@55.0.5)(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0) - '@expo/metro': 55.0.0 - '@expo/metro-config': 55.0.14(expo@55.0.12)(typescript@5.9.3) - '@expo/osascript': 2.4.2 - '@expo/package-manager': 1.10.4 - '@expo/plist': 0.5.2 - '@expo/prebuild-config': 55.0.13(expo@55.0.12)(typescript@5.9.3) - '@expo/require-utils': 55.0.3(typescript@5.9.3) - '@expo/router-server': 55.0.13(@expo/metro-runtime@55.0.9)(expo-constants@55.0.12)(expo-font@55.0.6(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0))(expo-router@55.0.11)(expo-server@55.0.7)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@expo/schema-utils': 55.0.3 - '@expo/spawn-async': 1.7.2 - '@expo/ws-tunnel': 1.0.6 - '@expo/xcpretty': 4.4.1 - '@react-native/dev-middleware': 0.83.4 - accepts: 1.3.8 - arg: 5.0.2 - better-opn: 3.0.2 - bplist-creator: 0.1.0 - 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 - dnssd-advertise: 1.1.4 - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) - expo-server: 55.0.7 - fetch-nodeshim: 0.4.10 - getenv: 2.0.0 - glob: 13.0.6 - lan-network: 0.2.1 - multitars: 0.2.4 - node-forge: 1.4.0 - npm-package-arg: 11.0.3 - ora: 3.4.0 - picomatch: 4.0.4 - pretty-format: 29.7.0 - progress: 2.0.3 - prompts: 2.4.2 - resolve-from: 5.0.0 - semver: 7.7.4 - send: 0.19.2 - slugify: 1.6.9 - source-map-support: 0.5.21 - 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.20.0 - zod: 3.25.76 - optionalDependencies: - expo-router: 55.0.11(pdj77jcnw7u2taeri5ruj5t4mi) - react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) - transitivePeerDependencies: - - '@expo/dom-webview' - - '@expo/metro-runtime' - - bufferutil - - expo-constants - - expo-font - - react - - react-dom - - react-server-dom-webpack - - supports-color - - typescript - - utf-8-validate - '@expo/cli@55.0.22(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-constants@55.0.12)(expo-font@55.0.6)(expo-router@55.0.11)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3)': dependencies: '@expo/code-signing-certificates': 0.0.6 @@ -20581,6 +20526,82 @@ snapshots: - typescript - utf-8-validate + '@expo/cli@55.0.22(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-constants@55.0.12)(expo-font@55.0.6)(expo-router@55.0.11)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3)': + dependencies: + '@expo/code-signing-certificates': 0.0.6 + '@expo/config': 55.0.13(typescript@5.9.3) + '@expo/config-plugins': 55.0.8 + '@expo/devcert': 1.2.1 + '@expo/env': 2.1.1 + '@expo/image-utils': 0.8.12 + '@expo/json-file': 10.0.13 + '@expo/log-box': 55.0.10(@expo/dom-webview@55.0.5)(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0) + '@expo/metro': 55.0.0 + '@expo/metro-config': 55.0.14(expo@55.0.12)(typescript@5.9.3) + '@expo/osascript': 2.4.2 + '@expo/package-manager': 1.10.4 + '@expo/plist': 0.5.2 + '@expo/prebuild-config': 55.0.13(expo@55.0.12)(typescript@5.9.3) + '@expo/require-utils': 55.0.3(typescript@5.9.3) + '@expo/router-server': 55.0.13(@expo/metro-runtime@55.0.9)(expo-constants@55.0.12)(expo-font@55.0.6)(expo-router@55.0.11)(expo-server@55.0.7)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@expo/schema-utils': 55.0.3 + '@expo/spawn-async': 1.7.2 + '@expo/ws-tunnel': 1.0.6 + '@expo/xcpretty': 4.4.1 + '@react-native/dev-middleware': 0.83.4 + accepts: 1.3.8 + arg: 5.0.2 + better-opn: 3.0.2 + bplist-creator: 0.1.0 + 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 + dnssd-advertise: 1.1.4 + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo-server: 55.0.7 + fetch-nodeshim: 0.4.10 + getenv: 2.0.0 + glob: 13.0.6 + lan-network: 0.2.1 + multitars: 0.2.4 + node-forge: 1.4.0 + npm-package-arg: 11.0.3 + ora: 3.4.0 + picomatch: 4.0.4 + pretty-format: 29.7.0 + progress: 2.0.3 + prompts: 2.4.2 + resolve-from: 5.0.0 + semver: 7.7.4 + send: 0.19.2 + slugify: 1.6.9 + source-map-support: 0.5.21 + 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.20.0 + zod: 3.25.76 + optionalDependencies: + expo-router: 55.0.11(eq6waxwbjtmotercssqwfwfcim) + react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) + transitivePeerDependencies: + - '@expo/dom-webview' + - '@expo/metro-runtime' + - bufferutil + - expo-constants + - expo-font + - react + - react-dom + - react-server-dom-webpack + - supports-color + - typescript + - utf-8-validate + '@expo/cli@55.0.22(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-constants@55.0.12)(expo-font@55.0.6)(expo-router@55.0.11)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)(typescript@5.9.3)': dependencies: '@expo/code-signing-certificates': 0.0.6 @@ -20808,7 +20829,7 @@ snapshots: '@expo/dom-webview@55.0.5(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)': dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) react: 19.2.0 react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) @@ -20921,7 +20942,7 @@ snapshots: dependencies: '@expo/dom-webview': 55.0.5(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0) anser: 1.4.10 - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) react: 19.2.0 react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) stacktrace-parser: 0.1.11 @@ -21045,7 +21066,7 @@ snapshots: postcss: 8.4.49 resolve-from: 5.0.0 optionalDependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) transitivePeerDependencies: - bufferutil - supports-color @@ -21072,7 +21093,7 @@ snapshots: dependencies: '@expo/log-box': 55.0.10(@expo/dom-webview@55.0.5)(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0) anser: 1.4.10 - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) pretty-format: 29.7.0 react: 19.2.0 react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) @@ -21224,7 +21245,7 @@ snapshots: '@expo/json-file': 10.0.13 '@react-native/normalize-colors': 0.83.4 debug: 4.4.3 - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) resolve-from: 5.0.0 semver: 7.7.4 xml2js: 0.6.0 @@ -21270,21 +21291,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@expo/router-server@55.0.13(@expo/metro-runtime@55.0.9)(expo-constants@55.0.12)(expo-font@55.0.6(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0))(expo-router@55.0.11)(expo-server@55.0.7)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': - dependencies: - debug: 4.4.3 - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) - expo-constants: 55.0.12(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(typescript@5.9.3) - expo-font: 55.0.6(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0) - expo-server: 55.0.7 - react: 19.2.0 - optionalDependencies: - '@expo/metro-runtime': 55.0.9(@expo/dom-webview@55.0.5)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0) - expo-router: 55.0.11(pdj77jcnw7u2taeri5ruj5t4mi) - react-dom: 19.2.0(react@19.2.0) - transitivePeerDependencies: - - supports-color - '@expo/router-server@55.0.13(@expo/metro-runtime@55.0.9)(expo-constants@55.0.12)(expo-font@55.0.6)(expo-router@55.0.11)(expo-server@55.0.7)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: debug: 4.4.3 @@ -25119,16 +25125,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/parser': 6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) - '@typescript-eslint/utils': 6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/type-utils': 6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) + '@typescript-eslint/utils': 6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.4.3 - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@1.21.7) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -25177,15 +25183,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/parser': 7.18.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/type-utils': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) - '@typescript-eslint/utils': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/type-utils': 7.18.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) + '@typescript-eslint/utils': 7.18.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) '@typescript-eslint/visitor-keys': 7.18.0 - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@1.21.7) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -25258,14 +25264,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.4.3 - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@1.21.7) optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: @@ -25297,14 +25303,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3) '@typescript-eslint/visitor-keys': 7.18.0 debug: 4.4.3 - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@1.21.7) optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: @@ -25400,12 +25406,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/type-utils@6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) - '@typescript-eslint/utils': 6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/utils': 6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) debug: 4.4.3 - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@1.21.7) ts-api-utils: 1.4.3(typescript@5.3.3) optionalDependencies: typescript: 5.3.3 @@ -25436,12 +25442,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/type-utils@7.18.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3) - '@typescript-eslint/utils': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/utils': 7.18.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) debug: 4.4.3 - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@1.21.7) ts-api-utils: 1.4.3(typescript@5.3.3) optionalDependencies: typescript: 5.3.3 @@ -25594,15 +25600,15 @@ snapshots: - supports-color - typescript - '@typescript-eslint/utils@6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/utils@6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@1.21.7)) '@types/json-schema': 7.0.15 '@types/semver': 7.7.1 '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@1.21.7) semver: 7.7.4 transitivePeerDependencies: - supports-color @@ -25633,13 +25639,13 @@ snapshots: - supports-color - typescript - '@typescript-eslint/utils@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/utils@7.18.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@1.21.7)) '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3) - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@1.21.7) transitivePeerDependencies: - supports-color - typescript @@ -25830,7 +25836,7 @@ snapshots: obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.3(@opentelemetry/api@1.9.1)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(jsdom@29.0.2(@noble/hashes@2.0.1))(vite@6.4.2(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.3(@opentelemetry/api@1.9.1)(@types/node@22.19.17)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(jsdom@29.0.2(@noble/hashes@2.0.1))(vite@6.4.2(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/expect@4.1.3': dependencies: @@ -25892,7 +25898,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.1.0 - vitest: 4.1.3(@opentelemetry/api@1.9.1)(@types/node@24.12.2)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(jsdom@29.0.2(@noble/hashes@2.0.1))(vite@6.4.2(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.3(@opentelemetry/api@1.9.1)(@types/node@22.19.17)(@vitest/coverage-v8@4.1.3)(@vitest/ui@4.1.3)(jsdom@29.0.2(@noble/hashes@2.0.1))(vite@6.4.2(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/utils@4.1.3': dependencies: @@ -26323,108 +26329,6 @@ snapshots: transitivePeerDependencies: - supports-color - astro@5.18.1(@azure/storage-blob@12.31.0)(@types/node@20.19.39)(ioredis@5.10.1)(jiti@1.21.7)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3): - dependencies: - '@astrojs/compiler': 2.13.1 - '@astrojs/internal-helpers': 0.7.6 - '@astrojs/markdown-remark': 6.3.11 - '@astrojs/telemetry': 3.3.0 - '@capsizecss/unpack': 4.0.0 - '@oslojs/encoding': 1.1.0 - '@rollup/pluginutils': 5.3.0(rollup@4.60.1) - acorn: 8.16.0 - aria-query: 5.3.2 - axobject-query: 4.1.0 - boxen: 8.0.1 - ci-info: 4.4.0 - clsx: 2.1.1 - common-ancestor-path: 1.0.1 - cookie: 1.1.1 - cssesc: 3.0.0 - debug: 4.4.3 - deterministic-object-hash: 2.0.2 - devalue: 5.7.0 - diff: 8.0.4 - dlv: 1.1.3 - dset: 3.1.4 - es-module-lexer: 1.7.0 - esbuild: 0.27.7 - estree-walker: 3.0.3 - flattie: 1.1.1 - fontace: 0.4.1 - github-slugger: 2.0.0 - html-escaper: 3.0.3 - http-cache-semantics: 4.2.0 - import-meta-resolve: 4.2.0 - js-yaml: 4.1.1 - magic-string: 0.30.21 - magicast: 0.5.2 - mrmime: 2.0.1 - neotraverse: 0.6.18 - p-limit: 6.2.0 - p-queue: 8.1.1 - package-manager-detector: 1.6.0 - piccolore: 0.1.3 - picomatch: 4.0.4 - prompts: 2.4.2 - rehype: 13.0.2 - semver: 7.7.4 - shiki: 3.23.0 - smol-toml: 1.6.1 - svgo: 4.0.1 - tinyexec: 1.0.4 - tinyglobby: 0.2.15 - tsconfck: 3.1.6(typescript@5.9.3) - ultrahtml: 1.6.0 - unifont: 0.7.4 - unist-util-visit: 5.1.0 - unstorage: 1.17.5(@azure/storage-blob@12.31.0)(ioredis@5.10.1) - vfile: 6.0.3 - vite: 6.4.2(@types/node@20.19.39)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) - vitefu: 1.1.3(vite@6.4.2(@types/node@20.19.39)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) - xxhash-wasm: 1.1.0 - yargs-parser: 21.1.1 - yocto-spinner: 0.2.3 - zod: 3.25.76 - zod-to-json-schema: 3.25.2(zod@3.25.76) - zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76) - optionalDependencies: - sharp: 0.34.5 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@types/node' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' - - aws4fetch - - db0 - - idb-keyval - - ioredis - - jiti - - less - - lightningcss - - rollup - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - typescript - - uploadthing - - yaml - astro@5.18.1(@azure/storage-blob@12.31.0)(@types/node@20.19.39)(ioredis@5.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.1)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3): dependencies: '@astrojs/compiler': 2.13.1 @@ -26938,7 +26842,7 @@ snapshots: resolve-from: 5.0.0 optionalDependencies: '@babel/runtime': 7.29.2 - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) transitivePeerDependencies: - '@babel/core' - supports-color @@ -28440,11 +28344,6 @@ snapshots: eslint: 9.39.4(jiti@2.6.1) semver: 7.7.4 - eslint-compat-utils@0.6.5(eslint@9.39.4(jiti@1.21.7)): - dependencies: - eslint: 9.39.4(jiti@1.21.7) - semver: 7.7.4 - eslint-compat-utils@0.6.5(eslint@9.39.4(jiti@2.6.1)): dependencies: eslint: 9.39.4(jiti@2.6.1) @@ -28492,14 +28391,14 @@ snapshots: dependencies: eslint: 8.57.1 + eslint-config-prettier@8.10.2(eslint@9.39.4(jiti@1.21.7)): + dependencies: + eslint: 9.39.4(jiti@1.21.7) + eslint-config-prettier@8.10.2(eslint@9.39.4(jiti@2.6.1)): dependencies: eslint: 9.39.4(jiti@2.6.1) - eslint-config-prettier@9.1.2(eslint@9.39.4(jiti@1.21.7)): - dependencies: - eslint: 9.39.4(jiti@1.21.7) - eslint-config-prettier@9.1.2(eslint@9.39.4(jiti@2.6.1)): dependencies: eslint: 9.39.4(jiti@2.6.1) @@ -28524,17 +28423,17 @@ snapshots: - supports-color - typescript - eslint-config-universe@12.1.0(@types/eslint@9.6.1)(eslint@9.39.4(jiti@2.6.1))(prettier@3.8.1)(typescript@5.3.3): + eslint-config-universe@12.1.0(@types/eslint@9.6.1)(eslint@9.39.4(jiti@1.21.7))(prettier@3.8.1)(typescript@5.3.3): dependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) - '@typescript-eslint/parser': 6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) - eslint: 9.39.4(jiti@2.6.1) - eslint-config-prettier: 8.10.2(eslint@9.39.4(jiti@2.6.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.4(jiti@2.6.1)) - eslint-plugin-node: 11.1.0(eslint@9.39.4(jiti@2.6.1)) - eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1))(prettier@3.8.1) - eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@2.6.1)) - eslint-plugin-react-hooks: 4.6.2(eslint@9.39.4(jiti@2.6.1)) + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) + '@typescript-eslint/parser': 6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) + eslint: 9.39.4(jiti@1.21.7) + eslint-config-prettier: 8.10.2(eslint@9.39.4(jiti@1.21.7)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.4(jiti@1.21.7)) + eslint-plugin-node: 11.1.0(eslint@9.39.4(jiti@1.21.7)) + eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.4(jiti@1.21.7)))(eslint@9.39.4(jiti@1.21.7))(prettier@3.8.1) + eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@1.21.7)) + eslint-plugin-react-hooks: 4.6.2(eslint@9.39.4(jiti@1.21.7)) optionalDependencies: prettier: 3.8.1 transitivePeerDependencies: @@ -28641,12 +28540,12 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@1.21.7)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) - eslint: 9.39.4(jiti@2.6.1) + '@typescript-eslint/parser': 6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) + eslint: 9.39.4(jiti@1.21.7) eslint-import-resolver-node: 0.3.10 transitivePeerDependencies: - supports-color @@ -28683,20 +28582,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-astro@1.6.0(eslint@9.39.4(jiti@1.21.7)): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@1.21.7)) - '@jridgewell/sourcemap-codec': 1.5.5 - '@typescript-eslint/types': 8.58.0 - astro-eslint-parser: 1.4.0 - eslint: 9.39.4(jiti@1.21.7) - eslint-compat-utils: 0.6.5(eslint@9.39.4(jiti@1.21.7)) - globals: 16.5.0 - postcss: 8.5.8 - postcss-selector-parser: 7.1.1 - transitivePeerDependencies: - - supports-color - eslint-plugin-astro@1.6.0(eslint@9.39.4(jiti@2.6.1)): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) @@ -28724,6 +28609,12 @@ snapshots: eslint-utils: 2.1.0 regexpp: 3.2.0 + eslint-plugin-es@3.0.1(eslint@9.39.4(jiti@1.21.7)): + dependencies: + eslint: 9.39.4(jiti@1.21.7) + eslint-utils: 2.1.0 + regexpp: 3.2.0 + eslint-plugin-es@3.0.1(eslint@9.39.4(jiti@2.6.1)): dependencies: eslint: 9.39.4(jiti@2.6.1) @@ -28777,7 +28668,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.4(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.4(jiti@1.21.7)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -28786,9 +28677,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@1.21.7) eslint-import-resolver-node: 0.3.10 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@1.21.7)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -28800,7 +28691,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/parser': 6.21.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.3.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -28918,6 +28809,16 @@ snapshots: resolve: 1.22.11 semver: 6.3.1 + eslint-plugin-node@11.1.0(eslint@9.39.4(jiti@1.21.7)): + dependencies: + eslint: 9.39.4(jiti@1.21.7) + eslint-plugin-es: 3.0.1(eslint@9.39.4(jiti@1.21.7)) + eslint-utils: 2.1.0 + ignore: 5.3.2 + minimatch: 3.1.5 + resolve: 1.22.11 + semver: 6.3.1 + eslint-plugin-node@11.1.0(eslint@9.39.4(jiti@2.6.1)): dependencies: eslint: 9.39.4(jiti@2.6.1) @@ -28948,6 +28849,16 @@ snapshots: '@types/eslint': 9.6.1 eslint-config-prettier: 8.10.2(eslint@8.57.1) + eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.4(jiti@1.21.7)))(eslint@9.39.4(jiti@1.21.7))(prettier@3.8.1): + dependencies: + eslint: 9.39.4(jiti@1.21.7) + prettier: 3.8.1 + prettier-linter-helpers: 1.0.1 + synckit: 0.11.12 + optionalDependencies: + '@types/eslint': 9.6.1 + eslint-config-prettier: 8.10.2(eslint@9.39.4(jiti@1.21.7)) + eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1))(prettier@3.8.1): dependencies: eslint: 9.39.4(jiti@2.6.1) @@ -28972,6 +28883,10 @@ snapshots: dependencies: eslint: 8.57.1 + eslint-plugin-react-hooks@4.6.2(eslint@9.39.4(jiti@1.21.7)): + dependencies: + eslint: 9.39.4(jiti@1.21.7) + eslint-plugin-react-hooks@4.6.2(eslint@9.39.4(jiti@2.6.1)): dependencies: eslint: 9.39.4(jiti@2.6.1) @@ -29002,6 +28917,28 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@1.21.7)): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.3.1 + eslint: 9.39.4(jiti@1.21.7) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.5 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.6 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)): dependencies: array-includes: 3.1.9 @@ -29505,7 +29442,7 @@ snapshots: expo-dev-client@6.0.20(expo@55.0.12): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) expo-dev-launcher: 6.0.20(expo@55.0.12) expo-dev-menu: 7.0.18(expo@55.0.12) expo-dev-menu-interface: 2.0.0(expo@55.0.12) @@ -29527,7 +29464,7 @@ snapshots: expo-dev-launcher@6.0.20(expo@55.0.12): dependencies: ajv: 8.18.0 - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) expo-dev-menu: 7.0.18(expo@55.0.12) expo-manifests: 1.0.10(expo@55.0.12) transitivePeerDependencies: @@ -29535,7 +29472,7 @@ snapshots: expo-dev-menu-interface@2.0.0(expo@55.0.12): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) expo-dev-menu-interface@55.0.2(expo@55.0.12): dependencies: @@ -29548,7 +29485,7 @@ snapshots: expo-dev-menu@7.0.18(expo@55.0.12): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) expo-dev-menu-interface: 2.0.0(expo@55.0.12) expo-device@55.0.13(expo@55.0.12): @@ -29574,7 +29511,7 @@ snapshots: expo-file-system@55.0.15(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0)): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) expo-file-system@55.0.15(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0)): @@ -29598,7 +29535,7 @@ snapshots: expo-font@55.0.6(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) fontfaceobserver: 2.3.0 react: 19.2.0 react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) @@ -29619,7 +29556,7 @@ snapshots: expo-glass-effect@55.0.10(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) react: 19.2.0 react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) @@ -29635,11 +29572,11 @@ snapshots: expo-image-loader@55.0.0(expo@55.0.12): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) expo-image-picker@55.0.17(expo@55.0.12): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) expo-image-loader: 55.0.0(expo@55.0.12) expo-image@55.0.8(expo@54.0.33)(react-native-web@0.21.2(react-dom@19.2.0(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0): @@ -29654,7 +29591,7 @@ snapshots: expo-image@55.0.8(expo@55.0.12)(react-native-web@0.21.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) react: 19.2.0 react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) sf-symbols-typescript: 2.2.0 @@ -29681,7 +29618,7 @@ snapshots: expo-keep-awake@55.0.6(expo@55.0.12)(react@19.2.0): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) react: 19.2.0 expo-linear-gradient@15.0.8(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0): @@ -29777,7 +29714,7 @@ snapshots: expo-manifests@1.0.10(expo@55.0.12): dependencies: '@expo/config': 12.0.13 - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) expo-json-utils: 0.15.0 transitivePeerDependencies: - supports-color @@ -30149,7 +30086,7 @@ snapshots: expo-secure-store@55.0.12(expo@55.0.12): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) expo-server@1.0.5: {} @@ -30244,7 +30181,7 @@ snapshots: dependencies: '@react-native/normalize-colors': 0.83.4 debug: 4.4.3 - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) optionalDependencies: react-native-web: 0.21.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -30270,7 +30207,7 @@ snapshots: expo-updates-interface@2.0.0(expo@55.0.12): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) expo-updates-interface@55.1.5(expo@55.0.12): dependencies: @@ -30300,7 +30237,7 @@ snapshots: expo-web-browser@55.0.13(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0)): dependencies: - expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.3.3) react-native: 0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0) expo@54.0.33(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-native@0.81.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0): @@ -30424,7 +30361,7 @@ snapshots: expo@55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3): dependencies: '@babel/runtime': 7.29.2 - '@expo/cli': 55.0.22(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-constants@55.0.12)(expo-font@55.0.6(expo@55.0.12)(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0))(expo-router@55.0.11)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) + '@expo/cli': 55.0.22(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-constants@55.0.12)(expo-font@55.0.6)(expo-router@55.0.11)(expo@55.0.12)(react-dom@19.2.0(react@19.2.0))(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)(typescript@5.9.3) '@expo/config': 55.0.13(typescript@5.9.3) '@expo/config-plugins': 55.0.8 '@expo/devtools': 55.0.2(react-native@0.83.2(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0) @@ -37216,23 +37153,6 @@ snapshots: lightningcss: 1.32.0 terser: 5.46.1 - vite@6.4.2(@types/node@20.19.39)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3): - dependencies: - esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - postcss: 8.5.8 - rollup: 4.60.1 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 20.19.39 - fsevents: 2.3.3 - jiti: 1.21.7 - lightningcss: 1.32.0 - terser: 5.46.1 - tsx: 4.21.0 - yaml: 2.8.3 - vite@6.4.2(@types/node@20.19.39)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3): dependencies: esbuild: 0.25.12 @@ -37284,10 +37204,6 @@ snapshots: tsx: 4.21.0 yaml: 2.8.3 - vitefu@1.1.3(vite@6.4.2(@types/node@20.19.39)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)): - optionalDependencies: - vite: 6.4.2(@types/node@20.19.39)(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) - vitefu@1.1.3(vite@6.4.2(@types/node@20.19.39)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)): optionalDependencies: vite: 6.4.2(@types/node@20.19.39)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)