zidane 4.1.6 → 4.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-context-MungM3SY.js","names":["ensureDir","BUILTIN_PRESET"],"sources":["../src/chat/providers.ts","../src/chat/credentials.ts","../src/chat/auth.ts","../src/chat/store.ts","../src/chat/config.ts","../src/chat/config-context.tsx","../src/chat/format.ts","../src/chat/oauth.ts","../src/chat/safe-mode.ts","../src/chat/safe-mode-context.tsx","../src/chat/themes/catppuccin.ts","../src/chat/themes/vaporwave.ts","../src/chat/theme.ts","../src/chat/settings-context.tsx","../src/chat/streaming.ts","../src/chat/theme-context.tsx"],"sourcesContent":["/**\n * Provider registry — the customization seam for the TUI.\n *\n * A {@link ProviderDescriptor} carries everything the TUI needs to know about\n * a provider in one place: how to instantiate it, what to show in the UI,\n * how to detect credentials, how to OAuth (if applicable), and where to look\n * up its models. Hosts can ship their own descriptors instead of the built-in\n * four — see {@link BUILTIN_PROVIDERS}.\n */\n\nimport type { OAuthProviderInterface } from '@mariozechner/pi-ai/oauth'\nimport type { Provider } from '../providers'\nimport { getModel, getModels } from '@mariozechner/pi-ai'\nimport { anthropicOAuthProvider, openaiCodexOAuthProvider } from '@mariozechner/pi-ai/oauth'\nimport { anthropic, cerebras, openai, openrouter } from '../providers'\n\n/**\n * Structural model metadata — compatible with pi-ai's `Model` interface but\n * not coupled to it, so hosts can pass either pi-ai-shaped objects or a\n * custom registry of their own.\n *\n * Deliberately a structural duplicate of pi-ai's `Model` rather than a\n * re-export: keeps the public API stable when pi-ai bumps shape, and lets\n * hosts implement their own registry without depending on pi-ai's types.\n *\n * Lives here (rather than `./config`) because `ProviderDescriptor.models`\n * needs it — pushing it to `config.tsx` created an import cycle.\n */\nexport interface ModelInfo {\n id: string\n name?: string\n contextWindow: number\n maxTokens?: number\n reasoning?: boolean\n input?: readonly ('text' | 'image')[]\n cost?: { input: number, output: number, cacheRead?: number, cacheWrite?: number }\n provider?: string\n}\n\nexport interface ProviderDescriptor {\n /**\n * Unique identifier. Used as the registry key, persisted in `state.json`\n * as the resumed provider, and (by default) as the credential-file key.\n */\n key: string\n /** Display name shown in the TUI's provider picker and labels. */\n label: string\n /**\n * Factory that builds a fresh `Provider` instance. Called on every session\n * activation. Some factories (e.g. zidane's built-in `anthropic`) eagerly\n * resolve credentials at construction time and throw when none are\n * configured — set {@link defaultModel} on the descriptor to avoid the TUI\n * calling the factory before the user has picked + authed a provider.\n */\n factory: () => Provider\n /**\n * Default model id to seed the picker with. When omitted, the TUI falls\n * back to `descriptor.factory().meta.defaultModel`, which constructs the\n * provider — fine for lazy-credential factories, but breaks for factories\n * that throw on missing credentials before the wizard runs. Setting this\n * eagerly lets the TUI render the auth wizard without ever instantiating\n * the provider.\n */\n defaultModel?: string\n /**\n * Env var checked when detecting whether the user has an API key\n * configured for this provider. Optional — set to `undefined` when the\n * provider only supports OAuth (or only credentials via a custom path).\n */\n envKey?: string\n /**\n * Key under which credentials live in `credentials.json`. Defaults to\n * `key`. The only built-in that overrides this is OpenAI Codex\n * (`openai` → `openai-codex`) to stay compatible with the harness\n * provider's existing lookup.\n */\n credentialFileKey?: string\n /** Placeholder shown in the wizard's API-key input. */\n apiKeyPlaceholder?: string\n /**\n * pi-ai (or compat) OAuth provider. When present, the wizard offers an\n * OAuth option in addition to API key.\n */\n oauthProvider?: OAuthProviderInterface\n /**\n * Optional copy appended to the wizard's \"OAuth\" method description.\n * Use to communicate why a user might pick OAuth (e.g. subscription tier,\n * org-wide SSO). Shown after `browser-based sign-in`. Skip the leading\n * space — the wizard adds it. Example: `'Claude Pro/Max subscription'`.\n */\n oauthHint?: string\n /**\n * pi-ai provider id used to look up models in pi-ai's built-in registry.\n * Defaults to `key`. Only Codex differs (`openai` → `openai-codex`).\n */\n piProviderId?: string\n /**\n * Override the model list returned for this provider's picker. When set,\n * skips pi-ai's registry entirely. Useful for hosts maintaining their\n * own model catalogue or for custom providers pi-ai doesn't know about.\n */\n models?: readonly ModelInfo[]\n}\n\n/** Convenience accessor — returns `credentialFileKey ?? key`. */\nexport function credKeyOf(desc: ProviderDescriptor): string {\n return desc.credentialFileKey ?? desc.key\n}\n\n/** Convenience accessor — returns `piProviderId ?? key`. */\nexport function piIdOf(desc: ProviderDescriptor): string {\n return desc.piProviderId ?? desc.key\n}\n\n// ---------------------------------------------------------------------------\n// Built-in descriptors\n// ---------------------------------------------------------------------------\n\nexport const anthropicDescriptor: ProviderDescriptor = {\n key: 'anthropic',\n label: 'Anthropic',\n factory: anthropic,\n defaultModel: 'claude-opus-4-7',\n envKey: 'ANTHROPIC_API_KEY',\n apiKeyPlaceholder: 'sk-ant-…',\n oauthProvider: anthropicOAuthProvider,\n oauthHint: 'Claude Pro/Max subscription',\n}\n\nexport const openaiDescriptor: ProviderDescriptor = {\n key: 'openai',\n label: 'OpenAI Codex',\n factory: openai,\n defaultModel: 'gpt-5.4',\n envKey: 'OPENAI_CODEX_API_KEY',\n credentialFileKey: 'openai-codex',\n piProviderId: 'openai-codex',\n apiKeyPlaceholder: 'sk-… or eyJ… (Codex)',\n oauthProvider: openaiCodexOAuthProvider,\n}\n\nexport const openrouterDescriptor: ProviderDescriptor = {\n key: 'openrouter',\n label: 'OpenRouter',\n factory: openrouter,\n defaultModel: 'anthropic/claude-sonnet-4-6',\n envKey: 'OPENROUTER_API_KEY',\n apiKeyPlaceholder: 'sk-or-…',\n}\n\nexport const cerebrasDescriptor: ProviderDescriptor = {\n key: 'cerebras',\n label: 'Cerebras',\n factory: cerebras,\n defaultModel: 'zai-glm-4.7',\n envKey: 'CEREBRAS_API_KEY',\n apiKeyPlaceholder: 'csk-…',\n}\n\n/**\n * Default provider registry. Passed verbatim when `runTui` is invoked without\n * an explicit `providers` option. Hosts that want to override per-provider\n * metadata can spread this and replace specific entries:\n *\n * ```ts\n * runTui({ providers: { ...BUILTIN_PROVIDERS, anthropic: myOwnAnthropicDescriptor } })\n * ```\n */\nexport const BUILTIN_PROVIDERS: Readonly<Record<string, ProviderDescriptor>> = {\n anthropic: anthropicDescriptor,\n openai: openaiDescriptor,\n openrouter: openrouterDescriptor,\n cerebras: cerebrasDescriptor,\n}\n\n// ---------------------------------------------------------------------------\n// Model registry helper\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the model list for a given provider. Honors `descriptor.models`\n * when set; otherwise queries pi-ai via `descriptor.piProviderId`. Returns\n * `[]` for descriptors with no known mapping (custom providers without a\n * model list) — callers should hide the model picker in that case.\n */\nexport function modelsForDescriptor(descriptor: ProviderDescriptor): readonly ModelInfo[] {\n if (descriptor.models)\n return descriptor.models\n try {\n return getModels(piIdOf(descriptor) as never) as readonly ModelInfo[]\n }\n catch {\n return []\n }\n}\n\n/**\n * Look up the model's max context window via the descriptor's model source.\n * Returns `null` when the model isn't known (custom slugs, providers without\n * a registry); callers should hide the context indicator in that case.\n */\nexport function getContextWindow(descriptor: ProviderDescriptor, modelId: string): number | null {\n // Prefer the descriptor's own list — host overrides win.\n if (descriptor.models) {\n const found = descriptor.models.find(m => m.id === modelId)\n return found?.contextWindow ?? null\n }\n try {\n const model = getModel(piIdOf(descriptor) as never, modelId as never)\n return model?.contextWindow ?? null\n }\n catch {\n return null\n }\n}\n","/**\n * Credential storage for the TUI.\n *\n * Lives at `<dataDir>/credentials.json` (default `~/.zidane/credentials.json`,\n * overridable via `ZIDANE_STORAGE_DIR`). Owner-only (0o600) so refresh tokens\n * and API keys don't leak on shared boxes.\n *\n * Two credential kinds:\n * - `apikey` — a plain API key entered by the user (e.g. via the setup wizard).\n * - `oauth` — tokens obtained via a provider's OAuth flow (refresh-aware).\n *\n * **Schema note.** File keys come from {@link ProviderDescriptor.credentialFileKey}\n * (falling back to `descriptor.key`). They must match what the harness providers\n * look up at runtime — for built-ins this is `anthropic`, `openai-codex`,\n * `openrouter`, `cerebras`. Hosts that ship custom providers control the file\n * key via the descriptor.\n *\n * The legacy `cwd/.credentials.json` (written by `bun run auth` in older\n * versions) is migrated on first read if the new file doesn't exist yet. The\n * legacy file is left in place — we don't delete user data behind their back.\n */\n\nimport type { ProviderDescriptor } from './providers'\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { credKeyOf } from './providers'\n\n/** POSIX mode for the credentials file. Ignored on Windows. */\nconst FILE_MODE = 0o600\n\nexport interface ApiKeyCredential {\n kind: 'apikey'\n value: string\n}\nexport interface OAuthCredential {\n kind: 'oauth'\n access: string\n refresh?: string\n expires?: number\n /** Provider-specific extras (e.g. OpenAI Codex `accountId`). */\n [extra: string]: unknown\n}\nexport type ProviderCredential = ApiKeyCredential | OAuthCredential\n\n/** Top-level shape of `credentials.json` — keys are credential-file keys. */\nexport type CredentialsFile = Record<string, ProviderCredential>\n\n/**\n * Resolve the credentials file path given the resolved TUI data directory\n * (typically `~/.zidane`, i.e. `config.paths.dir`).\n *\n * Matches the convention used elsewhere in the TUI (sessions.db, state.json)\n * so a single `ZIDANE_STORAGE_DIR` override moves the entire data root.\n */\nexport function credentialsPath(dataDir: string): string {\n return resolve(dataDir, 'credentials.json')\n}\n\n/**\n * Read credentials from disk.\n *\n * Returns `{}` when the file is missing or corrupt (last-ditch tolerance —\n * a hand-edit gone wrong shouldn't lock the user out of re-authing). On first\n * call with no file present, attempts a migration from `cwd/.credentials.json`\n * (the legacy location used by `bun run auth`).\n */\nexport function readCredentials(dataDir: string): CredentialsFile {\n const path = credentialsPath(dataDir)\n\n if (!existsSync(path)) {\n const migrated = migrateLegacyFile(path)\n if (migrated)\n return migrated\n return {}\n }\n\n try {\n const raw = readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw)\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))\n return {}\n return parsed as CredentialsFile\n }\n catch {\n return {}\n }\n}\n\n/** Read a single provider's credential (translating via the descriptor). */\nexport function readProviderCredential(dataDir: string, descriptor: ProviderDescriptor): ProviderCredential | undefined {\n return readCredentials(dataDir)[credKeyOf(descriptor)]\n}\n\n/**\n * Write credentials atomically (write-then-rename) with mode 0o600.\n *\n * Atomic on the same filesystem — readers either see the previous file or the\n * new one, never a half-written intermediate. Creates the parent dir if needed\n * (first launch on a fresh machine: `~/.zidane/` may not exist yet).\n */\nexport function writeCredentials(dataDir: string, creds: CredentialsFile): void {\n const path = credentialsPath(dataDir)\n mkdirSync(dirname(path), { recursive: true })\n const tmp = `${path}.${process.pid}.${Date.now()}.tmp`\n writeFileSync(tmp, `${JSON.stringify(creds, null, 2)}\\n`, { mode: FILE_MODE })\n renameSync(tmp, path)\n}\n\nexport function setProviderCredential(\n dataDir: string,\n descriptor: ProviderDescriptor,\n cred: ProviderCredential,\n): void {\n const all = readCredentials(dataDir)\n all[credKeyOf(descriptor)] = cred\n writeCredentials(dataDir, all)\n}\n\nexport function removeProviderCredential(dataDir: string, descriptor: ProviderDescriptor): void {\n const all = readCredentials(dataDir)\n const fileKey = credKeyOf(descriptor)\n if (!(fileKey in all))\n return\n delete all[fileKey]\n writeCredentials(dataDir, all)\n}\n\n/**\n * Inject API-key credentials into `process.env` so the harness providers pick\n * them up via their existing env-var resolution. Called once at TUI launch\n * after the credentials file has been resolved. OAuth credentials are NOT\n * injected — those reach providers via `ZIDANE_CREDENTIALS_PATH` + the file\n * reader in `src/providers/oauth.ts`.\n *\n * Does not overwrite env vars that are already set — explicit user-provided\n * env values win over stored API keys.\n *\n * Descriptors without an `envKey` (OAuth-only providers, custom providers\n * that bypass env-var resolution) are skipped silently.\n */\nexport function applyApiKeyEnv(\n dataDir: string,\n registry: Readonly<Record<string, ProviderDescriptor>>,\n): void {\n const creds = readCredentials(dataDir)\n for (const descriptor of Object.values(registry)) {\n if (!descriptor.envKey || process.env[descriptor.envKey])\n continue\n const cred = creds[credKeyOf(descriptor)]\n if (cred?.kind === 'apikey' && cred.value)\n process.env[descriptor.envKey] = cred.value\n }\n}\n\n// ---------------------------------------------------------------------------\n// Legacy migration\n// ---------------------------------------------------------------------------\n\n/**\n * `bun run auth` (pre-TUI) wrote `cwd/.credentials.json` with an entry per\n * provider mapping directly to an OAuthCredentials payload, e.g.:\n *\n * {\n * \"anthropic\": { \"access\": \"...\", \"refresh\": \"...\", \"expires\": 123 },\n * \"openai-codex\": { \"access\": \"...\", \"refresh\": \"...\", \"expires\": 123, \"accountId\": \"...\" }\n * }\n *\n * We don't delete the legacy file — it might still be used by a host that\n * imports the harness directly. We just copy its contents into the new\n * location under the kind-tagged shape so the TUI picks them up.\n *\n * Migration is provider-agnostic: any top-level entry with an `access` field\n * is preserved verbatim (extras included), under the same key. The TUI's\n * detection then looks them up via the matching descriptor's `credentialFileKey`.\n *\n * Returns the migrated credentials when the migration ran, or `null` when\n * there's no legacy file to migrate.\n */\nfunction migrateLegacyFile(targetPath: string): CredentialsFile | null {\n const legacyPath = resolve(process.cwd(), '.credentials.json')\n if (!existsSync(legacyPath))\n return null\n\n let legacy: Record<string, unknown>\n try {\n legacy = JSON.parse(readFileSync(legacyPath, 'utf-8'))\n }\n catch {\n return null\n }\n if (!legacy || typeof legacy !== 'object' || Array.isArray(legacy))\n return null\n\n const migrated: CredentialsFile = {}\n for (const [fileKey, value] of Object.entries(legacy)) {\n if (!isOAuthLegacy(value))\n continue\n const { access, refresh, expires, ...extras } = value\n migrated[fileKey] = {\n kind: 'oauth',\n access,\n ...(typeof refresh === 'string' ? { refresh } : {}),\n ...(typeof expires === 'number' ? { expires } : {}),\n ...extras,\n }\n }\n\n if (Object.keys(migrated).length === 0)\n return null\n\n // Persist immediately so subsequent reads use the new file directly.\n mkdirSync(dirname(targetPath), { recursive: true })\n const tmp = `${targetPath}.${process.pid}.${Date.now()}.tmp`\n writeFileSync(tmp, `${JSON.stringify(migrated, null, 2)}\\n`, { mode: FILE_MODE })\n renameSync(tmp, targetPath)\n\n return migrated\n}\n\nfunction isOAuthLegacy(value: unknown): value is { access: string, refresh?: string, expires?: number, [extra: string]: unknown } {\n return (\n typeof value === 'object'\n && value !== null\n && 'access' in value\n && typeof (value as { access: unknown }).access === 'string'\n )\n}\n","import type { ProviderCredential } from './credentials'\nimport type { ProviderDescriptor } from './providers'\nimport { readCredentials } from './credentials'\nimport { credKeyOf } from './providers'\n\n/**\n * Provider identifier as known to the TUI. Built-in keys are `anthropic`,\n * `openai`, `openrouter`, `cerebras`, but hosts can register additional\n * keys via {@link ProviderDescriptor} — so the type is open.\n */\nexport type ProviderKey = string\n\nexport interface AuthMethod {\n source: 'env' | 'oauth' | 'apikey'\n /** Human-readable detail (env var name, expiry timestamp, …). */\n detail: string\n}\n\nexport interface ProviderAuth {\n key: ProviderKey\n label: string\n /** True when at least one credential source is present. */\n available: boolean\n methods: AuthMethod[]\n}\n\n/**\n * Detect available auth for every registered provider.\n *\n * Resolution order per provider (a method appears in `methods` for each\n * layer that has a credential — the agent itself resolves them in the same\n * order via its provider factories):\n *\n * 1. `kind: 'apikey'` from `credentials.json` (injected into env at TUI launch)\n * 2. explicit env var (descriptor's `envKey`)\n * 3. `kind: 'oauth'` from `credentials.json` (or legacy `cwd/.credentials.json`)\n *\n * Pure read — never refreshes or rewrites the credentials file.\n */\nexport function detectAuth(\n dataDir: string,\n registry: Readonly<Record<string, ProviderDescriptor>>,\n env: Record<string, string | undefined> = process.env,\n): ProviderAuth[] {\n const creds = readCredentials(dataDir)\n\n return Object.values(registry).map((descriptor) => {\n const methods: AuthMethod[] = []\n const fileEntry = creds[credKeyOf(descriptor)] as ProviderCredential | undefined\n\n // 1. Stored API key\n if (fileEntry?.kind === 'apikey' && fileEntry.value)\n methods.push({ source: 'apikey', detail: 'credentials.json' })\n\n // 2. Env var (may be set by `applyApiKeyEnv` from a stored key, or by the\n // user's shell. Either way, treated as the same observable signal.)\n if (descriptor.envKey && env[descriptor.envKey])\n methods.push({ source: 'env', detail: descriptor.envKey })\n\n // 3. Stored OAuth\n if (fileEntry?.kind === 'oauth' && fileEntry.access) {\n const detail = typeof fileEntry.expires === 'number'\n ? `oauth · expires ${new Date(fileEntry.expires).toLocaleString()}`\n : 'oauth · credentials.json'\n methods.push({ source: 'oauth', detail })\n }\n\n return {\n key: descriptor.key,\n label: descriptor.label,\n available: methods.length > 0,\n methods,\n }\n })\n}\n","import type { SessionRun, SessionStore } from '../session'\nimport type { SessionTurn, ToolResultContent } from '../types'\nimport type { ProviderKey } from './auth'\nimport type { SessionMeta, Settings, StreamEvent } from './types'\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { createSqliteStore } from '../session/sqlite'\nimport { formatTokenUsage } from '../stats'\nimport { toolResultToText } from '../types'\n\nfunction ensureDir(path: string): void {\n const dir = dirname(path)\n if (existsSync(dir))\n return\n try {\n mkdirSync(dir, { recursive: true })\n }\n catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(\n `Could not create TUI storage directory at \"${dir}\". `\n + `Override the location via \\`runTui({ storageDir, prefix })\\` or the `\n + `\\`ZIDANE_STORAGE_DIR\\` env var. Original error: ${message}`,\n )\n }\n}\n\n// ---------------------------------------------------------------------------\n// Session store — thin SQLite wrapper at a caller-supplied path.\n// ---------------------------------------------------------------------------\n\nexport function createTuiStore(dbPath: string): SessionStore {\n ensureDir(dbPath)\n return createSqliteStore({ path: dbPath })\n}\n\n// ---------------------------------------------------------------------------\n// Persisted UI state — what to resume on next launch.\n//\n// `StateStoreApi` is a thin facade that binds load/save to a specific JSON\n// path, so the rest of the UI can persist state without knowing the layout.\n// ---------------------------------------------------------------------------\n\nexport interface TuiState {\n lastProvider?: ProviderKey\n lastSessionId?: string\n /** Per-provider last-used model id. */\n lastModelByProvider?: Partial<Record<ProviderKey, string>>\n /** User-toggled transcript filters. Persisted so they outlive a launch. */\n settings?: Partial<Settings>\n}\n\nexport interface StateStoreApi {\n load: () => TuiState\n save: (state: TuiState) => void\n}\n\nexport function createStateStore(path: string): StateStoreApi {\n return {\n load: () => loadState(path),\n save: state => saveState(path, state),\n }\n}\n\nexport function loadState(path: string): TuiState {\n if (!existsSync(path))\n return {}\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf-8'))\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))\n return parsed as TuiState\n }\n catch {\n // Corrupt state file → treat as absent so the user can reach the auth screen.\n }\n return {}\n}\n\nexport function saveState(path: string, state: TuiState): void {\n ensureDir(path)\n // Atomic write via tmp + rename so a crash mid-write never leaves a half file.\n const tmp = `${path}.${process.pid}.tmp`\n writeFileSync(tmp, JSON.stringify(state, null, 2))\n renameSync(tmp, path)\n}\n\n// Re-export the model-info shape used by views below so callers don't have to\n// pull from `./config` for transcript helpers alone.\nexport type { ModelInfo } from './config'\n\n// ---------------------------------------------------------------------------\n// Session view helpers — derive UI-friendly shapes from persisted turns.\n// ---------------------------------------------------------------------------\n\n/**\n * Load every session and project it to the compact `SessionMeta` shape used by\n * the picker. Sorted by recency via the underlying store's `list()` contract\n * (sqlite store returns by `updated_at DESC`).\n */\nexport async function listSessionMeta(store: SessionStore): Promise<SessionMeta[]> {\n const ids = await store.list()\n const metas = await Promise.all(ids.map(async (id) => {\n const data = await store.load(id)\n if (!data)\n return null\n return {\n id,\n title: titleFromTurns(data.turns) ?? 'untitled',\n turnCount: data.turns.length,\n updatedAt: data.updatedAt,\n }\n }))\n return metas.filter((m): m is SessionMeta => m !== null)\n}\n\n/** Derive a short title from the first user message — returns null when empty. */\nexport function titleFromTurns(turns: SessionTurn[]): string | null {\n const first = turns.find(t => t.role === 'user')\n if (!first)\n return null\n for (const block of first.content) {\n if (block.type === 'text' && block.text.trim()) {\n const oneLine = block.text.replace(/\\s+/g, ' ').trim()\n return oneLine.length > 60 ? `${oneLine.slice(0, 60)}…` : oneLine\n }\n }\n return null\n}\n\n/**\n * Replay persisted turns as a viewable transcript. Mirrors the event shape\n * produced live by the agent hooks so loaded and streaming history render\n * identically — including subagent ancestry when `runs` is supplied.\n *\n * Subagent reconstruction:\n * - Every turn carries a `runId`. We look that up in `runs` to get the\n * run's `depth` and tag the resulting events with `{ depth, childId }`\n * — the same shape the live `child:*` bubble hooks produce.\n * - We synthesize `spawn-start` / `spawn-end` markers at each child-run\n * boundary so the transcript reads the same as a live run did\n * (`🌱 [run-id] task` … child events … `🌳 [run-id] done · tokens`).\n * - For child runs (`depth > 0`), the user-role \"task\" text is suppressed\n * because `spawn-start` already shows it.\n *\n * Without `runs` (legacy callers / tests), the function falls back to the\n * old behavior: depth-0 events with no subagent grouping.\n */\nexport function eventsFromTurns(\n turns: SessionTurn[],\n runs: readonly SessionRun[] = [],\n): StreamEvent[] {\n const runById = new Map<string, SessionRun>()\n for (const run of runs)\n runById.set(run.id, run)\n\n // Build a chronological mapping from the persisted `runId` (e.g. `run_2`) to\n // a friendly `child-N` label that mirrors what the spawn tool emits live\n // (see `src/tools/spawn.ts`'s local counter). Without this the reloaded\n // transcript labels its subagent block `[run_2]` while the persisted tool\n // result text inside that very block says `[sub-agent child-1]`.\n const childLabelByRunId = new Map<string, string>()\n const childRuns = runs\n .filter(r => (r.depth ?? 0) > 0)\n .slice()\n .sort((a, b) => a.startedAt - b.startedAt)\n childRuns.forEach((r, i) => childLabelByRunId.set(r.id, `child-${i + 1}`))\n const labelFor = (runId: string) => childLabelByRunId.get(runId) ?? runId\n\n // Build a `callId → toolName` map from the assistant `tool_call` blocks so\n // we can tag each user-role `tool_result` event with the tool it answers.\n // The renderer uses this for tool-aware filters (e.g. hiding the spawn\n // tool's result when `hideSubagentOutput` is on).\n const toolByCallId = new Map<string, string>()\n for (const turn of turns) {\n if (turn.role !== 'assistant')\n continue\n for (const block of turn.content) {\n if (block.type === 'tool_call')\n toolByCallId.set(block.id, block.name)\n }\n }\n\n const events: StreamEvent[] = []\n let lastRunId: string | undefined\n let lastDepth = 0\n\n const closeRun = (runId: string | undefined, depth: number) => {\n if (!runId || depth <= 0)\n return\n const run = runById.get(runId)\n if (!run)\n return\n const tag = run.status === 'aborted' || run.status === 'error' ? run.status : 'done'\n // Same caching gotcha as the live path: `tokensIn` mirrors `AgentStats.totalIn`\n // (new uncached only). `formatTokenUsage` folds cache reads/creations\n // into the headline `in` number and surfaces the cached portion in parens.\n const usage = formatTokenUsage({\n totalIn: run.tokensIn ?? run.totalUsage?.input ?? 0,\n totalOut: run.tokensOut ?? run.totalUsage?.output ?? 0,\n totalCacheRead: run.totalUsage?.cacheRead ?? 0,\n totalCacheCreation: run.totalUsage?.cacheCreation ?? 0,\n })\n events.push({\n kind: 'spawn-end',\n text: `${tag} ${usage}`,\n childId: labelFor(runId),\n depth,\n })\n }\n\n const openRun = (runId: string, depth: number) => {\n if (depth <= 0)\n return\n const run = runById.get(runId)\n if (!run)\n return\n const taskPreview = run.prompt.length > 80 ? `${run.prompt.slice(0, 80)}…` : run.prompt\n events.push({\n kind: 'spawn-start',\n text: taskPreview,\n childId: labelFor(runId),\n depth,\n })\n }\n\n for (let i = 0; i < turns.length; i++) {\n const turn = turns[i]\n const run = turn.runId ? runById.get(turn.runId) : undefined\n const depth = run?.depth ?? 0\n const tag = depth > 0 && turn.runId ? { childId: labelFor(turn.runId), depth } : undefined\n\n // Run transitions — close the old child run, open the new one. Only\n // emit a top-level separator when we're staying at parent depth, so\n // the transcript reads as one tight subagent block without internal\n // turn-boundary lines.\n if (turn.runId !== lastRunId) {\n closeRun(lastRunId, lastDepth)\n if (depth === 0 && lastDepth === 0 && i > 0)\n events.push({ kind: 'separator', text: '' })\n if (turn.runId)\n openRun(turn.runId, depth)\n lastRunId = turn.runId\n lastDepth = depth\n }\n else if (i > 0 && depth === 0) {\n // Same parent run, new turn pair — keep the original separator.\n events.push({ kind: 'separator', text: '' })\n }\n\n if (turn.role === 'user') {\n for (const block of turn.content) {\n if (block.type === 'text' && block.text.trim()) {\n // For child runs the \"user\" text is the spawn task itself, already\n // rendered as the `spawn-start` marker above. Drop the duplicate.\n if (depth === 0)\n events.push({ kind: 'info', text: `❯ ${block.text}` })\n }\n else if (block.type === 'tool_result') {\n const tool = toolByCallId.get(block.callId)\n // Spawn tool-results duplicate the spawn-end marker's `Tokens: …`\n // line — and on pre-fix sessions the legacy \"N in / M out\" shape\n // disagrees with the cache-aware spawn-end. Strip it at the\n // display layer; the persisted output stays intact.\n const raw = toolResultText(block.output)\n const text = tool === 'spawn' ? stripSpawnTokensLine(raw) : raw\n events.push({\n kind: 'tool-result',\n text,\n ...(tool ? { tool } : {}),\n ...tag,\n })\n }\n }\n continue\n }\n\n if (turn.role === 'assistant') {\n for (const block of turn.content) {\n if (block.type === 'text' && block.text.trim()) {\n // Persisted turns are finalized — `streaming: false` so the markdown\n // renderer commits to the final layout (no heal pass needed).\n events.push({ kind: 'markdown', text: block.text, streaming: false, ...tag })\n }\n else if (block.type === 'tool_call') {\n events.push({\n kind: 'tool',\n text: toolCallPreview(block.name, block.input),\n tool: block.name,\n ...tag,\n })\n }\n }\n }\n }\n\n // Flush a trailing open child run (e.g., last turn was a subagent's).\n closeRun(lastRunId, lastDepth)\n\n return events\n}\n\n/** Shared formatter for the `↳ name(args)` line shown on tool calls. */\nexport function toolCallPreview(name: string, input: Record<string, unknown>): string {\n const args = JSON.stringify(input)\n return args && args !== '{}' ? `${name}(${args})` : name\n}\n\n/** Render tool output as plain text, whether it's a string or structured content. */\nexport function toolResultText(output: string | ToolResultContent[]): string {\n return typeof output === 'string' ? output : toolResultToText(output)\n}\n\n/**\n * Strip the `Tokens: …` line from a spawn tool-result. The spawn-end marker\n * displayed right above already shows the same stats; keeping the line in the\n * rendered tool-result body just produces a visible duplicate (and, on\n * reloaded pre-fix sessions, an *inconsistent* duplicate — the persisted line\n * uses the old `13 in / 4075 out` shape while the freshly synthesized\n * spawn-end uses the cache-aware `in 92615 (cache 92602) / 4075 out` shape).\n *\n * Display-only: the persisted tool_result content is untouched, so the LLM\n * still sees the full string in its context window. Anchored to start-of-line\n * and matches both `Tokens: 13 in / 4075 out` (legacy) and `Tokens: in 13 …`\n * (post-`formatTokenUsage`) shapes.\n */\nexport function stripSpawnTokensLine(text: string): string {\n return text.replace(/^Tokens:[^\\n]*\\n?/m, '')\n}\n\n/** Effective context size of the most recent assistant turn — drives the footer indicator. */\nexport function lastContextSizeFromTurns(turns: SessionTurn[]): number {\n for (let i = turns.length - 1; i >= 0; i--) {\n const turn = turns[i]\n if (turn.role === 'assistant' && turn.usage) {\n return (turn.usage.input ?? 0)\n + (turn.usage.cacheRead ?? 0)\n + (turn.usage.cacheCreation ?? 0)\n }\n }\n return 0\n}\n","import type { Preset } from '../presets'\nimport type { SessionStore } from '../session'\nimport type { ProviderAuth, ProviderKey } from './auth'\nimport type { ModelInfo, ProviderDescriptor } from './providers'\nimport type { StateStoreApi, TuiState } from './store'\nimport type { Picked, Settings } from './types'\nimport { homedir } from 'node:os'\nimport { resolve } from 'node:path'\nimport BUILTIN_PRESET from '../presets/basic'\nimport { detectAuth } from './auth'\nimport { applyApiKeyEnv, credentialsPath } from './credentials'\nimport { BUILTIN_PROVIDERS, modelsForDescriptor } from './providers'\nimport { createStateStore, createTuiStore } from './store'\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/** Re-exported for callers who want `ModelInfo` from the same module as `ChatOptions`. */\nexport type { ModelInfo }\n\n/**\n * Provider registry — a map keyed by `descriptor.key`. Passed verbatim to the\n * chat engine; there is no implicit merge with built-ins. Hosts that want the\n * four default providers spread {@link BUILTIN_PROVIDERS}; hosts that only\n * want their own pass exactly their own.\n */\nexport type ProviderRegistry = Readonly<Record<string, ProviderDescriptor>>\n\n/**\n * Options accepted by `resolveConfig()` (and, transitively, by `runTui()` and\n * any future GUI launcher). Every field is optional — defaults boot a working\n * chat against the built-in providers with sessions stored under `~/.zidane/`.\n */\nexport interface ChatOptions {\n /**\n * Directory name used under `storageDir` for sessions + state.\n * Default: `'.zidane'` → `~/.zidane/sessions.db` + `~/.zidane/state.json`.\n * Pass e.g. `'.myapp'` for `~/.myapp/...`, or `'myapp'` for a visible dir.\n */\n prefix?: string\n /**\n * Storage root. Defaults to the user's home directory. Combined with\n * `prefix` to form the data directory.\n */\n storageDir?: string\n /**\n * Provider registry. Each value is a {@link ProviderDescriptor} carrying\n * label + factory + credential metadata. **No automatic merge** — hosts\n * pass exactly what they want.\n *\n * - Omitted → {@link BUILTIN_PROVIDERS} (anthropic + openai + openrouter + cerebras).\n * - `providers: BUILTIN_PROVIDERS` → same as omitted, but explicit.\n * - `providers: { anthropic: anthropicDescriptor }` → only Anthropic.\n * - `providers: { ...BUILTIN_PROVIDERS, mine: customDescriptor }` → built-ins + custom.\n * - `providers: { mine: customDescriptor }` → custom-only, **no built-ins**.\n */\n providers?: ProviderRegistry\n /**\n * Agent preset (tools, system prompt, behavior). Default: `basic`.\n */\n preset?: Preset\n /**\n * Bring your own session store. Default: a SQLite store at\n * `<storageDir>/<prefix>/sessions.db`.\n */\n store?: SessionStore\n}\n\n// ---------------------------------------------------------------------------\n// Resolved config\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedConfig {\n prefix: string\n storageDir: string\n paths: { dir: string, db: string, state: string }\n providers: ProviderRegistry\n preset: Preset\n store: SessionStore\n stateStore: StateStoreApi\n /** Lookup by `ProviderKey` returning the available models for the picker. */\n modelsFor: (key: ProviderKey) => readonly ModelInfo[]\n initialState: TuiState\n initialSettings: Partial<Settings>\n resumeProvider: ProviderAuth | null\n initialPicked: Picked | null\n}\n\n/** Resolve user options into a fully-bound runtime config. Pure aside from disk reads. */\nexport function resolveConfig(options: ChatOptions = {}): ResolvedConfig {\n const prefix = options.prefix ?? process.env.ZIDANE_PREFIX ?? '.zidane'\n const storageDir = options.storageDir ?? process.env.ZIDANE_STORAGE_DIR ?? homedir()\n const dir = resolve(storageDir, prefix)\n const paths = {\n dir,\n db: resolve(dir, 'sessions.db'),\n state: resolve(dir, 'state.json'),\n }\n\n const store: SessionStore = options.store ?? createTuiStore(paths.db)\n const stateStore = createStateStore(paths.state)\n const initialState = stateStore.load()\n\n // No implicit merge — host controls the registry entirely. Default is the\n // four built-ins; an explicit empty `{}` would mean \"no providers\" (the\n // wizard would have nothing to offer and the AuthScreen would refuse).\n const providers: ProviderRegistry = options.providers ?? BUILTIN_PROVIDERS\n const preset = options.preset ?? BUILTIN_PRESET\n\n // Wire credentials *before* anything that might read them (resume detection,\n // any factory call). Sets `ZIDANE_CREDENTIALS_PATH` so the harness providers\n // find the file the chat engine manages, and injects stored API keys into\n // env so factories that resolve credentials eagerly (like `anthropic()`)\n // see them.\n process.env.ZIDANE_CREDENTIALS_PATH = credentialsPath(dir)\n applyApiKeyEnv(dir, providers)\n\n const modelsFor = makeModelsResolver(providers)\n\n const resumeProvider = resolveResumeProvider(initialState, providers, dir)\n const initialPicked = resumeProvider ? pickInitial(resumeProvider, providers, initialState) : null\n\n return {\n prefix,\n storageDir,\n paths,\n providers,\n preset,\n store,\n stateStore,\n modelsFor,\n initialState,\n initialSettings: initialState.settings ?? {},\n resumeProvider,\n initialPicked,\n }\n}\n\nfunction makeModelsResolver(registry: ProviderRegistry): (key: ProviderKey) => readonly ModelInfo[] {\n return (key) => {\n const descriptor = registry[key]\n return descriptor ? modelsForDescriptor(descriptor) : []\n }\n}\n\nfunction resolveResumeProvider(\n state: TuiState,\n providers: ProviderRegistry,\n storageDir: string,\n): ProviderAuth | null {\n if (!state.lastProvider)\n return null\n if (!providers[state.lastProvider])\n return null\n return detectAuth(storageDir, providers).find(p => p.key === state.lastProvider && p.available) ?? null\n}\n\nfunction pickInitial(auth: ProviderAuth, providers: ProviderRegistry, state: TuiState): Picked | null {\n const descriptor = providers[auth.key]\n if (!descriptor)\n return null\n const remembered = state.lastModelByProvider?.[auth.key]\n // Prefer the remembered model, then the descriptor's declared default.\n // Only construct the provider as a last resort — some factories throw on\n // missing credentials, and we never want that to block the wizard.\n const model = remembered ?? descriptor.defaultModel ?? safeFactoryDefault(descriptor)\n return model ? { provider: auth, model } : null\n}\n\nfunction safeFactoryDefault(descriptor: ProviderDescriptor): string | undefined {\n try {\n return descriptor.factory().meta.defaultModel\n }\n catch {\n return undefined\n }\n}\n","import type { ReactNode } from 'react'\nimport type { ResolvedConfig } from './config'\nimport { createContext, useContext } from 'react'\n\n// ---------------------------------------------------------------------------\n// ConfigContext — renderer-agnostic React context that hands a fully-resolved\n// chat config down to deep consumers (modals, pickers, screens). Kept in its\n// own file so callers that only want `resolveConfig()` don't pay the\n// `import 'react'` cost.\n// ---------------------------------------------------------------------------\n\nconst ConfigContext = createContext<ResolvedConfig | null>(null)\n\nexport function ConfigProvider({ config, children }: { config: ResolvedConfig, children: ReactNode }) {\n return <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>\n}\n\nexport function useConfig(): ResolvedConfig {\n const ctx = useContext(ConfigContext)\n if (!ctx)\n throw new Error('useConfig must be used inside <ConfigProvider>')\n return ctx\n}\n","/** Compact token formatter — 12_415 → \"12.4k\", 1_234_567 → \"1.23M\". */\nexport function fmtTokens(n: number): string {\n if (n < 1000)\n return String(n)\n if (n < 1_000_000)\n return `${(n / 1000).toFixed(n < 10_000 ? 2 : 1)}k`\n return `${(n / 1_000_000).toFixed(2)}M`\n}\n\n/** Compact relative-time formatter — \"just now / 5m / 3h / 2d\". */\nexport function ageString(ts: number, now: number = Date.now()): string {\n const m = Math.floor((now - ts) / 60_000)\n if (m < 1)\n return 'just now'\n if (m < 60)\n return `${m}m ago`\n const h = Math.floor(m / 60)\n if (h < 24)\n return `${h}h ago`\n return `${Math.floor(h / 24)}d ago`\n}\n\n/** Six-char short form of a session id for headers and lists. */\nexport function shortId(id: string): string {\n return id.replace(/-/g, '').slice(0, 6)\n}\n","/**\n * OAuth login flow exposed to the TUI.\n *\n * Driven by each {@link ProviderDescriptor}'s `oauthProvider` field. Built-in\n * descriptors wire pi-ai's `anthropicOAuthProvider` and `openaiCodexOAuthProvider`,\n * but hosts can pass any object conforming to `OAuthProviderInterface` — the\n * TUI is implementation-agnostic past the descriptor boundary.\n */\n\nimport type { OAuthCredentials, OAuthLoginCallbacks } from '@mariozechner/pi-ai/oauth'\nimport type { ProviderDescriptor } from './providers'\nimport { spawn } from 'node:child_process'\n\nexport function supportsOAuth(descriptor: ProviderDescriptor): boolean {\n return descriptor.oauthProvider !== undefined\n}\n\nexport interface OAuthFlowOptions {\n /** Called when the provider emits its login URL — typically right after the callback server starts. */\n onUrl: (url: string, instructions?: string) => void\n /** Called when the provider needs a code entered manually (rare; only when callback server fails). */\n onCodeRequest?: () => Promise<string>\n /** Called with each progress message from the OAuth flow (token exchange, etc.). */\n onProgress?: (message: string) => void\n /** Abort the in-flight login (e.g. user pressed esc). */\n signal?: AbortSignal\n}\n\n/**\n * Run the OAuth login flow for a provider.\n *\n * Returns the OAuth credentials on success; caller persists them via\n * `setProviderCredential(dataDir, descriptor, { kind: 'oauth', ...credentials })`.\n * Throws when the descriptor has no `oauthProvider` configured.\n */\nexport async function runOAuthLogin(\n descriptor: ProviderDescriptor,\n options: OAuthFlowOptions,\n): Promise<OAuthCredentials> {\n if (!descriptor.oauthProvider) {\n throw new Error(\n `OAuth not supported for ${descriptor.label} (${descriptor.key}) — use an API key instead.`,\n )\n }\n\n const callbacks: OAuthLoginCallbacks = {\n onAuth: (info) => {\n options.onUrl(info.url, info.instructions)\n // Best-effort browser launch. If `open`/`xdg-open` isn't available, the\n // user can still click the URL from the TUI — the callback server is\n // already listening either way.\n void tryOpenBrowser(info.url)\n },\n onPrompt: async () => {\n if (!options.onCodeRequest)\n throw new Error('OAuth flow requires manual code input but no handler is wired.')\n return options.onCodeRequest()\n },\n onProgress: options.onProgress,\n signal: options.signal,\n }\n\n return descriptor.oauthProvider.login(callbacks)\n}\n\n/**\n * Best-effort cross-platform browser open. macOS uses `open`, Linux uses\n * `xdg-open`, Windows uses `start`. Failures are swallowed — the callback\n * server is already listening, and the URL is displayed in the TUI for\n * manual click.\n *\n * Uses `spawn` (not `exec`) so the URL is passed as an argv element rather\n * than interpolated into a shell command — no need to think about quoting\n * URLs that contain `&`, `?`, `\"` or other shell metacharacters.\n */\nfunction tryOpenBrowser(url: string): void {\n const [cmd, ...args] = (() => {\n if (process.platform === 'darwin')\n return ['open', url]\n if (process.platform === 'win32')\n return ['cmd', '/c', 'start', '', url]\n return ['xdg-open', url]\n })()\n try {\n const child = spawn(cmd, args, { stdio: 'ignore', detached: true })\n child.on('error', () => {}) // ENOENT etc. — silently fall through\n child.unref()\n }\n catch {\n // spawn() itself failed (e.g. invalid binary path). Swallow.\n }\n}\n","/**\n * Safe-mode storage + matching for the TUI.\n *\n * Lives at `<dataDir>/projects.json` (default `~/.zidane/projects.json`). Each\n * top-level key is an absolute project directory; the value carries that\n * project's persisted tool-call `safelist`.\n *\n * ```json\n * {\n * \"/Users/me/proj-a\": { \"safelist\": [\"read_file\", \"shell:git:*\"] }\n * }\n * ```\n *\n * Two granularities for safelist entries:\n * - **bare tool name** — `\"read_file\"` matches every `read_file` call.\n * - **tool + first-arg token + wildcard** — `\"shell:git:*\"` matches `shell`\n * calls whose primary string argument starts with the token `git`\n * (followed by whitespace or end-of-string). Modelled on Claude Code's\n * `Bash(git:*)` syntax.\n *\n * A short list of read-only tools is **implicitly safe** without being\n * persisted — see {@link IMPLICITLY_SAFE_TOOLS}.\n */\n\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\n\n// ---------------------------------------------------------------------------\n// Persistence\n// ---------------------------------------------------------------------------\n\nexport interface ProjectEntry {\n safelist?: string[]\n}\n\nexport type ProjectsFile = Record<string, ProjectEntry>\n\n/** Resolve `projects.json`'s on-disk path given the TUI data directory. */\nexport function projectsFilePath(dataDir: string): string {\n return resolve(dataDir, 'projects.json')\n}\n\nexport function readProjects(dataDir: string): ProjectsFile {\n const path = projectsFilePath(dataDir)\n if (!existsSync(path))\n return {}\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf-8'))\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))\n return parsed as ProjectsFile\n }\n catch {\n // Corrupt file → treat as empty so the user can re-bootstrap.\n }\n return {}\n}\n\nfunction ensureDir(path: string): void {\n const dir = dirname(path)\n if (!existsSync(dir))\n mkdirSync(dir, { recursive: true })\n}\n\n/** Atomic write — tmp + rename so a crash never leaves a half-file. */\nexport function writeProjects(dataDir: string, file: ProjectsFile): void {\n const path = projectsFilePath(dataDir)\n ensureDir(path)\n const tmp = `${path}.${process.pid}.tmp`\n writeFileSync(tmp, JSON.stringify(file, null, 2))\n renameSync(tmp, path)\n}\n\n/**\n * Append `entry` to the safelist for `projectDir`, dedup-aware. Returns the\n * updated entry list (post-write) so callers can render it without re-reading.\n */\nexport function addToSafelist(\n dataDir: string,\n projectDir: string,\n entry: string,\n): readonly string[] {\n const file = readProjects(dataDir)\n const existing = file[projectDir]?.safelist ?? []\n if (existing.includes(entry))\n return existing\n const next = [...existing, entry]\n file[projectDir] = { ...file[projectDir], safelist: next }\n writeProjects(dataDir, file)\n return next\n}\n\n/** Read the safelist for one project. Returns `[]` for unknown projects. */\nexport function getSafelist(dataDir: string, projectDir: string): readonly string[] {\n return readProjects(dataDir)[projectDir]?.safelist ?? []\n}\n\n// ---------------------------------------------------------------------------\n// Matching\n// ---------------------------------------------------------------------------\n\n/**\n * Tools that always pass without prompting — pure file/dir reads with no\n * side effects. Users who want to gate them must disable safe-mode entirely\n * (or fork this list in their own embedding).\n */\nexport const IMPLICITLY_SAFE_TOOLS: readonly string[] = [\n 'read_file',\n 'list_files',\n 'glob',\n 'grep',\n]\n\n/** Common input keys carrying the \"primary argument\" we scope safelists on. */\nconst PRIMARY_ARG_KEYS = ['command', 'path', 'pattern', 'query'] as const\n\nfunction primaryArgValue(input: Record<string, unknown>): string {\n for (const key of PRIMARY_ARG_KEYS) {\n const v = input[key]\n if (typeof v === 'string' && v.length > 0)\n return v\n }\n return ''\n}\n\n/** Extract the first whitespace-delimited token of the primary arg. */\nfunction primaryArgToken(input: Record<string, unknown>): string {\n return primaryArgValue(input).split(/\\s+/)[0] ?? ''\n}\n\n/**\n * Shell metacharacters that turn a single command into a compound: pipes,\n * sequencing, redirects, substitutions, line breaks, subshells. A `shell:git:*`\n * entry is meant to greenlight \"any git invocation\" — without this guard,\n * `git status && rm -rf /` would tokenize to `git` and pass the safelist\n * unchallenged. Reject any command that's not a single program call.\n *\n * The regex is intentionally generous: false positives (e.g. `echo \"hi & bye\"`)\n * just prompt the user again, which is the safe failure mode.\n */\nconst SHELL_COMPOUND_RE = /[;&|<>`$\\n\\r()]/\n\nfunction isCompoundShellCommand(command: string): boolean {\n return SHELL_COMPOUND_RE.test(command)\n}\n\n/**\n * Test whether a `{ tool, input }` pair is covered by one safelist entry.\n *\n * Supported entry shapes:\n * - `\"<tool>\"` — broad match on tool name. For `shell` this still requires\n * a single-program command (compound forms always prompt).\n * - `\"<tool>:<token>:*\"` — match when the primary arg's first token equals\n * `<token>`. For `shell`, also requires the command to be free of\n * metacharacters (`;`, `&&`, `||`, `|`, `$(`, backticks, `>`, `<`,\n * newlines, subshells) — otherwise a `shell:git:*` entry would silently\n * greenlight `git status && rm -rf /`.\n *\n * Entries that don't fit either shape are ignored (forward-compat for future\n * pattern syntax — readers shouldn't choke on entries written by a newer\n * version of the TUI).\n */\nexport function matchesSafelistEntry(\n entry: string,\n tool: string,\n input: Record<string, unknown>,\n): boolean {\n // Shell entries — bare or scoped — only match single-program commands. We\n // refuse to interpret the safelist for any command containing chaining or\n // redirection metacharacters.\n if (tool === 'shell') {\n const cmd = typeof input.command === 'string' ? input.command : ''\n if (isCompoundShellCommand(cmd))\n return false\n }\n if (entry === tool)\n return true\n const sep = entry.indexOf(':')\n if (sep <= 0)\n return false\n if (entry.slice(0, sep) !== tool)\n return false\n const scope = entry.slice(sep + 1)\n if (scope.endsWith(':*'))\n return primaryArgToken(input) === scope.slice(0, -2)\n return false\n}\n\n/** True when a call matches ANY entry in the project's safelist (or is implicitly safe). */\nexport function isOnSafelist(\n entries: readonly string[],\n tool: string,\n input: Record<string, unknown>,\n): boolean {\n if (IMPLICITLY_SAFE_TOOLS.includes(tool))\n return true\n return entries.some(e => matchesSafelistEntry(e, tool, input))\n}\n\n/**\n * Suggest the safelist entry to write when the user picks \"accept and\n * remember\" for a `{ tool, input }`. Heuristic:\n *\n * - `shell` → scope by first command token (`shell:git:*`).\n * - anything else → bare tool name (broad).\n *\n * Returning a string ensures the UI always has a concrete entry to display\n * as the button label.\n */\nexport function suggestSafelistEntry(\n tool: string,\n input: Record<string, unknown>,\n): string {\n if (tool === 'shell') {\n const token = primaryArgToken(input)\n if (token)\n return `${tool}:${token}:*`\n }\n return tool\n}\n","/**\n * Safe-mode React context — bridges the agent's `tool:gate` / `mcp:tool:gate`\n * hooks (which run inside the harness loop) with the TUI's React tree (which\n * renders the approval picker).\n *\n * Flow:\n * 1. Hook handler in `app.tsx` calls `requestApproval(tool, input)`.\n * 2. Context appends a pending entry to the queue, returns a Promise.\n * 3. Picker renders the queue's head, calls `resolve(decision)` on pick.\n * 4. Head is shifted off the queue; hook handler proceeds with the decision.\n *\n * The queue is FIFO so parallel tool calls prompt in arrival order.\n *\n * Two contexts on purpose:\n * - `SafeModeQueueContext` carries the live queue. Consumers re-render on\n * every push/pop.\n * - `SafeModeActionsContext` carries `{ requestApproval, resolveHead,\n * denyAll }` and never changes identity, so callbacks that depend on\n * these don't re-bind every time a tool call enters or leaves the queue.\n */\n\nimport type { ReactNode } from 'react'\nimport { createContext, useCallback, useContext, useRef, useState } from 'react'\n\nexport type ApprovalDecision = 'accept-once' | 'accept-safelist' | 'deny'\n\nexport interface ApprovalRequest {\n id: string\n tool: string\n input: Record<string, unknown>\n resolve: (decision: ApprovalDecision) => void\n}\n\n/** Function signature consumed by `tool:gate` handlers + the child-tool wrap. */\nexport type RequestApproval = (tool: string, input: Record<string, unknown>) => Promise<ApprovalDecision>\n\nexport interface SafeModeActions {\n /** Request a decision; resolves once the user picks. */\n requestApproval: RequestApproval\n /** Resolve the head and shift the queue forward. */\n resolveHead: (decision: ApprovalDecision) => void\n /** Resolve all pending with `deny`. Used on abort / hard exit. */\n denyAll: () => void\n}\n\nconst SafeModeQueueContext = createContext<readonly ApprovalRequest[]>([])\nconst SafeModeActionsContext = createContext<SafeModeActions | null>(null)\n\nlet approvalIdCounter = 0\nfunction nextApprovalId(): string {\n // Monotonic id is enough — uniqueness is scoped to a single TUI session\n // and the value never leaves the React tree. Avoids Date.now/Math.random\n // collisions inside tight parallel-tool batches.\n approvalIdCounter += 1\n return `approval-${approvalIdCounter}`\n}\n\n/**\n * Owns the queue + actions. Splits the value across two contexts so a queue\n * change doesn't invalidate every callback memo that closes over the actions.\n */\nexport function SafeModeProvider({ children }: { children: ReactNode }) {\n const [queue, setQueue] = useState<readonly ApprovalRequest[]>([])\n\n // `setQueue` is stable, so `useCallback([])` here gives genuine identity\n // stability — `requestApproval` is the same function reference for the\n // lifetime of the provider, which is what hook handlers need.\n const requestApproval = useCallback<RequestApproval>(\n (tool, input) => new Promise<ApprovalDecision>((resolve) => {\n setQueue(prev => [...prev, { id: nextApprovalId(), tool, input, resolve }])\n }),\n [],\n )\n\n const resolveHead = useCallback((decision: ApprovalDecision) => {\n setQueue((prev) => {\n const [head, ...rest] = prev\n if (head)\n head.resolve(decision)\n return rest\n })\n }, [])\n\n const denyAll = useCallback(() => {\n setQueue((prev) => {\n for (const p of prev) p.resolve('deny')\n return []\n })\n }, [])\n\n // Actions object is stable across renders — its members are all `useCallback`'d\n // with `[]` deps. `useRef` captures the first-render identity and we hand the\n // same object out forever, so consumers calling `useSafeModeActions()` never\n // re-render purely because of safe-mode state.\n const actionsRef = useRef<SafeModeActions | null>(null)\n if (!actionsRef.current)\n actionsRef.current = { requestApproval, resolveHead, denyAll }\n\n return (\n <SafeModeActionsContext.Provider value={actionsRef.current}>\n <SafeModeQueueContext.Provider value={queue}>\n {children}\n </SafeModeQueueContext.Provider>\n </SafeModeActionsContext.Provider>\n )\n}\n\nexport function useSafeModeQueue(): readonly ApprovalRequest[] {\n return useContext(SafeModeQueueContext)\n}\n\nexport function useSafeModeActions(): SafeModeActions {\n const ctx = useContext(SafeModeActionsContext)\n if (!ctx)\n throw new Error('useSafeModeActions must be used inside <SafeModeProvider>')\n return ctx\n}\n","import type { Theme } from '../theme'\n\n// ---------------------------------------------------------------------------\n// Catppuccin — four flavors built from the official palette.\n//\n// Hex values mirror catppuccin/palette v1.8.0 verbatim. The palette is the\n// data; `catppuccinTheme()` is the mapping into our `Theme` shape — accent\n// → role colors, semantic UI tokens (mantle = modal), and Tree-sitter syntax\n// token mappings that line up with the official Catppuccin styleguide.\n//\n// `Latte` is a light flavor (`base = #eff1f5`, `text = #4c4f69`) and only\n// looks correct in a light terminal — same caveat as the upstream VSCode\n// theme. The other three are dark.\n// ---------------------------------------------------------------------------\n\n/**\n * One Catppuccin flavor as a flat hex map. Mirrors the structure of\n * `catppuccin/palette` so the builder below maps named colors → roles\n * without any per-flavor branching.\n */\ninterface CatppuccinPalette {\n rosewater: string\n flamingo: string\n pink: string\n mauve: string\n red: string\n maroon: string\n peach: string\n yellow: string\n green: string\n teal: string\n sky: string\n sapphire: string\n blue: string\n lavender: string\n text: string\n subtext1: string\n subtext0: string\n overlay2: string\n overlay1: string\n overlay0: string\n surface2: string\n surface1: string\n surface0: string\n base: string\n mantle: string\n crust: string\n}\n\nconst LATTE: CatppuccinPalette = {\n rosewater: '#dc8a78',\n flamingo: '#dd7878',\n pink: '#ea76cb',\n mauve: '#8839ef',\n red: '#d20f39',\n maroon: '#e64553',\n peach: '#fe640b',\n yellow: '#df8e1d',\n green: '#40a02b',\n teal: '#179299',\n sky: '#04a5e5',\n sapphire: '#209fb5',\n blue: '#1e66f5',\n lavender: '#7287fd',\n text: '#4c4f69',\n subtext1: '#5c5f77',\n subtext0: '#6c6f85',\n overlay2: '#7c7f93',\n overlay1: '#8c8fa1',\n overlay0: '#9ca0b0',\n surface2: '#acb0be',\n surface1: '#bcc0cc',\n surface0: '#ccd0da',\n base: '#eff1f5',\n mantle: '#e6e9ef',\n crust: '#dce0e8',\n}\n\nconst FRAPPE: CatppuccinPalette = {\n rosewater: '#f2d5cf',\n flamingo: '#eebebe',\n pink: '#f4b8e4',\n mauve: '#ca9ee6',\n red: '#e78284',\n maroon: '#ea999c',\n peach: '#ef9f76',\n yellow: '#e5c890',\n green: '#a6d189',\n teal: '#81c8be',\n sky: '#99d1db',\n sapphire: '#85c1dc',\n blue: '#8caaee',\n lavender: '#babbf1',\n text: '#c6d0f5',\n subtext1: '#b5bfe2',\n subtext0: '#a5adce',\n overlay2: '#949cbb',\n overlay1: '#838ba7',\n overlay0: '#737994',\n surface2: '#626880',\n surface1: '#51576d',\n surface0: '#414559',\n base: '#303446',\n mantle: '#292c3c',\n crust: '#232634',\n}\n\nconst MACCHIATO: CatppuccinPalette = {\n rosewater: '#f4dbd6',\n flamingo: '#f0c6c6',\n pink: '#f5bde6',\n mauve: '#c6a0f6',\n red: '#ed8796',\n maroon: '#ee99a0',\n peach: '#f5a97f',\n yellow: '#eed49f',\n green: '#a6da95',\n teal: '#8bd5ca',\n sky: '#91d7e3',\n sapphire: '#7dc4e4',\n blue: '#8aadf4',\n lavender: '#b7bdf8',\n text: '#cad3f5',\n subtext1: '#b8c0e0',\n subtext0: '#a5adcb',\n overlay2: '#939ab7',\n overlay1: '#8087a2',\n overlay0: '#6e738d',\n surface2: '#5b6078',\n surface1: '#494d64',\n surface0: '#363a4f',\n base: '#24273a',\n mantle: '#1e2030',\n crust: '#181926',\n}\n\nconst MOCHA: CatppuccinPalette = {\n rosewater: '#f5e0dc',\n flamingo: '#f2cdcd',\n pink: '#f5c2e7',\n mauve: '#cba6f7',\n red: '#f38ba8',\n maroon: '#eba0ac',\n peach: '#fab387',\n yellow: '#f9e2af',\n green: '#a6e3a1',\n teal: '#94e2d5',\n sky: '#89dceb',\n sapphire: '#74c7ec',\n blue: '#89b4fa',\n lavender: '#b4befe',\n text: '#cdd6f4',\n subtext1: '#bac2de',\n subtext0: '#a6adc8',\n overlay2: '#9399b2',\n overlay1: '#7f849c',\n overlay0: '#6c7086',\n surface2: '#585b70',\n surface1: '#45475a',\n surface0: '#313244',\n base: '#1e1e2e',\n mantle: '#181825',\n crust: '#11111b',\n}\n\n/**\n * Compose a `Theme` from a Catppuccin palette flavor.\n *\n * Role-color picks follow the upstream Catppuccin styleguide:\n * - `mauve` is the canonical accent — used here as the brand color.\n * - `green` / `red` / `yellow` keep their universal semantic meaning.\n * - `blue` carries function / model identity (matches the VSCode plugin's\n * `support.function` mapping).\n * - `subtext1` / `overlay0` form the dim/mute pair (one step apart so the\n * two tiers stay visually distinct on every flavor).\n * - `surface1` / `overlay0` give the resting/active border pair.\n *\n * Syntax token mappings line up with the official Catppuccin token rules\n * (keyword = mauve, string = green, function = blue, type = yellow, …) so\n * code fences match what users see in their editor.\n */\nfunction catppuccinTheme(id: string, label: string, p: CatppuccinPalette): Theme {\n return {\n id,\n label,\n colors: {\n brand: p.mauve,\n accent: p.green,\n model: p.blue,\n warn: p.yellow,\n error: p.red,\n dim: p.subtext1,\n mute: p.overlay0,\n border: p.surface1,\n borderActive: p.overlay0,\n },\n select: {\n backgroundColor: 'transparent',\n focusedBackgroundColor: 'transparent',\n selectedBackgroundColor: 'transparent',\n selectedTextColor: p.mauve,\n textColor: p.subtext1,\n descriptionColor: p.overlay0,\n selectedDescriptionColor: p.subtext0,\n },\n surfaces: {\n // `mantle` is one shade darker than `base`, mirroring how the upstream\n // VSCode theme paints the sidebar against the editor — a subtle but\n // present elevation cue for the modal panel.\n modal: p.mantle,\n },\n syntax: {\n 'default': { fg: p.text },\n\n // ---- markdown structure ----\n 'markup.heading': { fg: p.mauve, bold: true },\n 'markup.heading.1': { fg: p.mauve, bold: true },\n 'markup.heading.2': { fg: p.lavender, bold: true },\n 'markup.heading.3': { fg: p.blue, bold: true },\n 'markup.bold': { fg: p.text, bold: true },\n 'markup.strong': { fg: p.text, bold: true },\n 'markup.italic': { fg: p.text, italic: true },\n 'markup.link': { fg: p.sky, underline: true },\n 'markup.link.url': { fg: p.sky, underline: true },\n 'markup.list': { fg: p.peach },\n 'markup.raw': { fg: p.green },\n 'markup.raw.block': { fg: p.green },\n 'markup.quote': { fg: p.overlay2, italic: true },\n\n // ---- code ----\n 'keyword': { fg: p.mauve, bold: true },\n 'keyword.import': { fg: p.pink, bold: true },\n 'keyword.operator': { fg: p.sky },\n 'string': { fg: p.green },\n 'string.escape': { fg: p.pink, bold: true },\n 'character': { fg: p.teal },\n 'comment': { fg: p.overlay1, italic: true },\n 'number': { fg: p.peach },\n 'boolean': { fg: p.peach },\n 'constant': { fg: p.peach },\n 'constant.builtin': { fg: p.peach },\n 'function': { fg: p.blue },\n 'function.call': { fg: p.blue },\n 'function.method': { fg: p.blue },\n 'function.method.call': { fg: p.blue },\n 'function.builtin': { fg: p.blue },\n 'function.macro': { fg: p.teal },\n 'type': { fg: p.yellow },\n 'type.builtin': { fg: p.yellow },\n 'constructor': { fg: p.yellow },\n 'attribute': { fg: p.yellow },\n 'tag': { fg: p.lavender },\n 'variable': { fg: p.text },\n 'variable.builtin': { fg: p.red },\n 'variable.parameter': { fg: p.maroon, italic: true },\n 'variable.member': { fg: p.text },\n 'property': { fg: p.lavender },\n 'operator': { fg: p.sky },\n 'punctuation': { fg: p.overlay2 },\n 'punctuation.bracket': { fg: p.overlay2 },\n 'punctuation.delimiter': { fg: p.overlay2 },\n 'label': { fg: p.sapphire },\n },\n }\n}\n\nexport const CATPPUCCIN_MOCHA = catppuccinTheme('catppuccin-mocha', 'Catppuccin Mocha', MOCHA)\nexport const CATPPUCCIN_MACCHIATO = catppuccinTheme('catppuccin-macchiato', 'Catppuccin Macchiato', MACCHIATO)\nexport const CATPPUCCIN_FRAPPE = catppuccinTheme('catppuccin-frappe', 'Catppuccin Frappé', FRAPPE)\nexport const CATPPUCCIN_LATTE = catppuccinTheme('catppuccin-latte', 'Catppuccin Latte', LATTE)\n","import type { Theme } from '../theme'\n\n// ---------------------------------------------------------------------------\n// Vaporwave — neon-on-dark, ported from this-fifo/vaporwave-theme-vscode.\n//\n// Hex values come straight from the upstream `vaporwave-color-theme.json`\n// (terminal ANSI table + tokenColors). The signature pink (#E95378) carries\n// the brand role; the bright pink (#FF71CE) is reserved for the keyword\n// token so headings and keywords visually rhyme without competing.\n// ---------------------------------------------------------------------------\n\nconst PALETTE = {\n pink: '#E95378',\n pinkBright: '#FF71CE',\n cyan: '#01CDFE',\n cyanBright: '#59E1E3',\n blue: '#94D0FF',\n green: '#29D398',\n greenBright: '#09F7A0',\n yellow: '#FFFB96',\n red: '#F43E5C',\n text: '#D5D8DA',\n textBright: '#EEFFFF',\n comment: '#BBBBBB',\n muted: '#6C6F93',\n surface: '#2E303E',\n panel: '#232530',\n}\n\nexport const VAPORWAVE_THEME: Theme = {\n id: 'vaporwave',\n label: 'Vaporwave',\n colors: {\n brand: PALETTE.pink,\n accent: PALETTE.greenBright,\n model: PALETTE.blue,\n warn: PALETTE.yellow,\n error: PALETTE.red,\n dim: PALETTE.text,\n mute: PALETTE.muted,\n border: PALETTE.surface,\n borderActive: PALETTE.muted,\n },\n select: {\n backgroundColor: 'transparent',\n focusedBackgroundColor: 'transparent',\n selectedBackgroundColor: 'transparent',\n selectedTextColor: PALETTE.pink,\n textColor: PALETTE.text,\n descriptionColor: PALETTE.muted,\n selectedDescriptionColor: PALETTE.text,\n },\n surfaces: {\n // Upstream uses `#232530` for editor widgets / dropdowns — same elevation\n // role as our modal panels.\n modal: PALETTE.panel,\n },\n syntax: {\n 'default': { fg: PALETTE.text },\n\n // ---- markdown structure ----\n 'markup.heading': { fg: PALETTE.pink, bold: true },\n 'markup.heading.1': { fg: PALETTE.pink, bold: true },\n 'markup.heading.2': { fg: PALETTE.pinkBright, bold: true },\n 'markup.heading.3': { fg: PALETTE.blue, bold: true },\n 'markup.bold': { fg: PALETTE.textBright, bold: true },\n 'markup.strong': { fg: PALETTE.textBright, bold: true },\n 'markup.italic': { fg: PALETTE.greenBright, italic: true },\n 'markup.link': { fg: PALETTE.yellow, underline: true },\n 'markup.link.url': { fg: PALETTE.yellow, underline: true },\n 'markup.list': { fg: PALETTE.textBright },\n 'markup.raw': { fg: PALETTE.yellow },\n 'markup.raw.block': { fg: PALETTE.yellow },\n 'markup.quote': { fg: PALETTE.yellow, italic: true },\n\n // ---- code (mirrors the upstream tokenColors mapping) ----\n 'keyword': { fg: PALETTE.pinkBright, bold: true },\n 'keyword.import': { fg: PALETTE.pinkBright, bold: true },\n 'keyword.operator': { fg: PALETTE.comment },\n 'string': { fg: PALETTE.yellow },\n 'string.escape': { fg: PALETTE.greenBright, bold: true },\n 'character': { fg: PALETTE.yellow },\n 'comment': { fg: PALETTE.comment, italic: true },\n 'number': { fg: PALETTE.textBright },\n 'boolean': { fg: PALETTE.textBright },\n 'constant': { fg: PALETTE.textBright },\n 'constant.builtin': { fg: PALETTE.textBright },\n 'function': { fg: PALETTE.greenBright },\n 'function.call': { fg: PALETTE.greenBright },\n 'function.method': { fg: PALETTE.greenBright },\n 'function.method.call': { fg: PALETTE.greenBright },\n 'function.builtin': { fg: PALETTE.greenBright },\n 'function.macro': { fg: PALETTE.greenBright },\n 'type': { fg: PALETTE.greenBright },\n 'type.builtin': { fg: PALETTE.greenBright },\n 'constructor': { fg: PALETTE.greenBright },\n 'attribute': { fg: PALETTE.yellow },\n 'tag': { fg: PALETTE.blue },\n 'variable': { fg: PALETTE.blue },\n 'variable.builtin': { fg: PALETTE.cyanBright },\n 'variable.parameter': { fg: PALETTE.text },\n 'variable.member': { fg: PALETTE.blue },\n 'property': { fg: PALETTE.blue },\n 'operator': { fg: PALETTE.comment },\n 'punctuation': { fg: PALETTE.comment },\n 'punctuation.bracket': { fg: PALETTE.textBright },\n 'punctuation.delimiter': { fg: PALETTE.comment },\n 'label': { fg: PALETTE.cyan },\n },\n}\n","/**\n * Renderer-agnostic theme system.\n *\n * A `Theme` bundles every variable that can change visually between\n * \"themes\" — colors, select-row styling, code/markdown syntax highlight\n * tokens, panel backgrounds. Plain JSON: no OpenTUI dependency, no React,\n * no functions. The TUI consumes the theme by reading from `useTheme()`\n * and converting hex strings into OpenTUI's `RGBA`/`SyntaxStyle`; a future\n * GUI consumes the same theme by converting into CSS variables or Tailwind\n * tokens.\n *\n * Components should always read theme values through `useTheme()` /\n * `useColors()` so a runtime theme switch (Settings → Theme) re-paints\n * the whole tree. Importing a raw theme object directly bypasses the\n * context and pins the component to a single look.\n *\n * Built-in flavors (Catppuccin, Vaporwave) live in `./themes/`. This file\n * just defines the shape + the default theme + the registry.\n */\n\nimport {\n CATPPUCCIN_FRAPPE,\n CATPPUCCIN_LATTE,\n CATPPUCCIN_MACCHIATO,\n CATPPUCCIN_MOCHA,\n} from './themes/catppuccin'\nimport { VAPORWAVE_THEME } from './themes/vaporwave'\n\n/** Role-named color palette. Reused throughout the UI for text, borders, accents. */\nexport interface ThemeColors {\n /** Primary accent — selected text, brand emphasis (e.g. `▶` markers). */\n brand: string\n /** Success / progress accent — used sparingly. */\n accent: string\n /** Model badge accent (provider/model name in the footer, links). */\n model: string\n /** Warnings — busy spinner, approval picker border, esc hints. */\n warn: string\n /** Errors — `✗` prefix on error events, validation messages. */\n error: string\n /** Secondary text — captions, helper text, dim transcript lines. */\n dim: string\n /** Tertiary text — separators, descriptions, the `┃` tool-result bar. */\n mute: string\n /** Resting border color. */\n border: string\n /** Border color on focused / active elements. */\n borderActive: string\n}\n\n/** Select-component styling. Plain prop shape; both OpenTUI's `<select>` and any GUI equivalent can consume this. */\nexport interface ThemeSelect {\n backgroundColor: string\n focusedBackgroundColor: string\n selectedBackgroundColor: string\n selectedTextColor: string\n textColor: string\n descriptionColor: string\n selectedDescriptionColor: string\n}\n\n/** Panel / surface backgrounds. Currently just the modal overlay. */\nexport interface ThemeSurfaces {\n /** Background of an overlaid modal panel (settings, model picker, …). */\n modal: string\n}\n\n/**\n * One entry in a `SyntaxStyles` map — what OpenTUI's `SyntaxStyle.fromStyles`\n * accepts, minus the `RGBA` conversion. Renderer-agnostic JSON.\n */\nexport interface SyntaxTokenStyle {\n fg?: string\n bg?: string\n bold?: boolean\n italic?: boolean\n underline?: boolean\n dim?: boolean\n}\n\n/**\n * Map of Tree-sitter / markdown capture group → token style.\n *\n * Two flavours of keys live in the same table:\n * - `markup.*` — the markdown structure captures (heading, bold, italic,\n * list, quote, raw inline + block, link). OpenTUI's markdown parser\n * emits these for the markdown text itself.\n * - bare token names (`keyword`, `string`, `function`, …) — emitted by\n * the embedded language Tree-sitter grammars when a code fence\n * declares a language. OpenTUI passes the same `SyntaxStyle` down to\n * the fenced-code renderable, so this map drives both surfaces.\n */\nexport type SyntaxStyles = Record<string, SyntaxTokenStyle>\n\n/** Full theme bundle. */\nexport interface Theme {\n /** Stable identifier, used as the key in `BUILTIN_THEMES` and `Settings.theme`. */\n id: string\n /** Human-readable label shown in the settings picker. */\n label: string\n colors: ThemeColors\n select: ThemeSelect\n surfaces: ThemeSurfaces\n syntax: SyntaxStyles\n}\n\n// ---------------------------------------------------------------------------\n// Default theme\n//\n// Yellow-brand + GitHub-dark syntax. Reads well on dark terminal backgrounds.\n// Defined as a local constant first so `BUILTIN_THEMES` references it by\n// name, and so the markdown-structure entries can interpolate the role-named\n// colors without redeclaring them.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_COLORS: ThemeColors = {\n brand: '#FFCC00',\n accent: '#00FF88',\n model: '#88CCFF',\n warn: '#FFAA66',\n error: '#FF6666',\n dim: '#888888',\n mute: '#555555',\n border: '#333333',\n borderActive: '#555555',\n}\n\nexport const DEFAULT_THEME: Theme = {\n id: 'default',\n label: 'Default',\n colors: DEFAULT_COLORS,\n select: {\n // Transparent backgrounds keep the highlight bar from filling with a\n // different color than the surrounding box. The `▶` marker + brand-\n // colored selected text carry the focus affordance instead.\n backgroundColor: 'transparent',\n focusedBackgroundColor: 'transparent',\n selectedBackgroundColor: 'transparent',\n selectedTextColor: DEFAULT_COLORS.brand,\n textColor: DEFAULT_COLORS.dim,\n descriptionColor: DEFAULT_COLORS.mute,\n selectedDescriptionColor: DEFAULT_COLORS.dim,\n },\n surfaces: {\n modal: '#101010',\n },\n syntax: {\n // ---- markdown structure ----\n 'default': { fg: '#E6EDF3' },\n 'markup.heading': { fg: DEFAULT_COLORS.brand, bold: true },\n 'markup.heading.1': { fg: DEFAULT_COLORS.brand, bold: true },\n 'markup.heading.2': { fg: '#FFD84D', bold: true },\n 'markup.heading.3': { fg: '#FFE680', bold: true },\n 'markup.bold': { fg: '#FFFFFF', bold: true },\n 'markup.strong': { fg: '#FFFFFF', bold: true },\n 'markup.italic': { fg: '#E6EDF3', italic: true },\n 'markup.link': { fg: DEFAULT_COLORS.model, underline: true },\n 'markup.link.url': { fg: DEFAULT_COLORS.model, underline: true },\n 'markup.list': { fg: DEFAULT_COLORS.warn },\n 'markup.raw': { fg: '#A5D6FF' },\n 'markup.raw.block': { fg: '#A5D6FF' },\n 'markup.quote': { fg: DEFAULT_COLORS.dim, italic: true },\n\n // ---- code (Tree-sitter language tokens inside fenced blocks) ----\n 'keyword': { fg: '#FF7B72', bold: true },\n 'keyword.import': { fg: '#FF7B72', bold: true },\n 'keyword.operator': { fg: '#FF7B72' },\n 'string': { fg: '#A5D6FF' },\n 'string.escape': { fg: '#A5D6FF', bold: true },\n 'character': { fg: '#A5D6FF' },\n 'comment': { fg: '#8B949E', italic: true },\n 'number': { fg: '#79C0FF' },\n 'boolean': { fg: '#79C0FF' },\n 'constant': { fg: '#79C0FF' },\n 'constant.builtin': { fg: '#79C0FF' },\n 'function': { fg: '#D2A8FF' },\n 'function.call': { fg: '#D2A8FF' },\n 'function.method': { fg: '#D2A8FF' },\n 'function.method.call': { fg: '#D2A8FF' },\n 'function.builtin': { fg: '#D2A8FF' },\n 'function.macro': { fg: '#D2A8FF' },\n 'type': { fg: '#FFA657' },\n 'type.builtin': { fg: '#FFA657' },\n 'constructor': { fg: '#FFA657' },\n 'attribute': { fg: '#FFA657' },\n 'tag': { fg: '#7EE787' },\n 'variable': { fg: '#E6EDF3' },\n 'variable.builtin': { fg: '#79C0FF' },\n 'variable.parameter': { fg: '#FFA657' },\n 'variable.member': { fg: '#79C0FF' },\n 'property': { fg: '#79C0FF' },\n 'operator': { fg: '#FF7B72' },\n 'punctuation': { fg: DEFAULT_COLORS.mute },\n 'punctuation.bracket': { fg: '#F0F6FC' },\n 'punctuation.delimiter': { fg: '#C9D1D9' },\n 'label': { fg: '#79C0FF' },\n },\n}\n\n/**\n * Built-in theme registry, keyed by `theme.id`. The TUI looks up the active\n * theme here using `Settings.theme`; unknown ids fall back to\n * `DEFAULT_THEME`. Hosts can extend this by passing additional themes to a\n * future `runTui({ themes })` option (not yet wired).\n *\n * Insertion order is the picker cycle order — keep `default` first so a\n * fresh install (no `theme` in `state.json`) sees the familiar yellow theme\n * before the others.\n */\nexport const BUILTIN_THEMES: Readonly<Record<string, Theme>> = {\n [DEFAULT_THEME.id]: DEFAULT_THEME,\n [CATPPUCCIN_MOCHA.id]: CATPPUCCIN_MOCHA,\n [CATPPUCCIN_MACCHIATO.id]: CATPPUCCIN_MACCHIATO,\n [CATPPUCCIN_FRAPPE.id]: CATPPUCCIN_FRAPPE,\n [CATPPUCCIN_LATTE.id]: CATPPUCCIN_LATTE,\n [VAPORWAVE_THEME.id]: VAPORWAVE_THEME,\n}\n\n/** Resolve a theme id to its full `Theme`, falling back to default on unknown ids. */\nexport function resolveTheme(id: string | undefined): Theme {\n if (id && BUILTIN_THEMES[id])\n return BUILTIN_THEMES[id]\n return DEFAULT_THEME\n}\n","import type { ReactNode } from 'react'\nimport type { Settings } from './types'\nimport { createContext, useCallback, useContext, useMemo, useState } from 'react'\nimport { BUILTIN_THEMES, DEFAULT_THEME } from './theme'\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nexport const DEFAULT_SETTINGS: Settings = {\n showThinking: true,\n showToolCalls: true,\n showToolResults: true,\n safeMode: true,\n hideSubagentOutput: true,\n theme: DEFAULT_THEME.id,\n}\n\n// ---------------------------------------------------------------------------\n// SettingsProvider — single source of truth for the transcript filters.\n//\n// `onChange` is called with the latest settings whenever a row toggles, so\n// the host can persist them. Persistence pathing lives outside this module\n// to keep the settings layer portable across renderers (TUI, GUI, …).\n// ---------------------------------------------------------------------------\n\ninterface SettingsContextValue {\n settings: Settings\n /** Flip a boolean setting in place. Restricted at the type level to boolean-valued keys. */\n toggle: (key: BooleanSettingKey) => void\n /** Write any setting key to a new value. Used by string-valued choice rows. */\n setSetting: <K extends keyof Settings>(key: K, value: Settings[K]) => void\n}\n\nconst SettingsContext = createContext<SettingsContextValue | null>(null)\n\nexport function SettingsProvider({\n initial,\n onChange,\n children,\n}: {\n initial: Settings\n onChange?: (settings: Settings) => void\n children: ReactNode\n}) {\n const [settings, setSettings] = useState<Settings>(initial)\n\n const toggle = useCallback((key: BooleanSettingKey) => {\n setSettings((prev) => {\n const next = { ...prev, [key]: !prev[key] }\n onChange?.(next)\n return next\n })\n }, [onChange])\n\n const setSetting = useCallback(<K extends keyof Settings>(key: K, value: Settings[K]) => {\n setSettings((prev) => {\n if (prev[key] === value)\n return prev\n const next = { ...prev, [key]: value }\n onChange?.(next)\n return next\n })\n }, [onChange])\n\n const value = useMemo<SettingsContextValue>(\n () => ({ settings, toggle, setSetting }),\n [settings, toggle, setSetting],\n )\n\n return <SettingsContext.Provider value={value}>{children}</SettingsContext.Provider>\n}\n\nexport function useSettings(): SettingsContextValue {\n const ctx = useContext(SettingsContext)\n if (!ctx)\n throw new Error('useSettings must be used inside <SettingsProvider>')\n return ctx\n}\n\n/**\n * Keys of `Settings` whose value type is exactly `boolean`. Used to type\n * the toggle table so `SETTINGS_TOGGLES.key` only ever points to a\n * boolean-valued setting — string-valued settings like `theme` live in\n * `SETTINGS_CHOICES`.\n */\nexport type BooleanSettingKey = {\n [K in keyof Settings]: Settings[K] extends boolean ? K : never\n}[keyof Settings]\n\n/**\n * Static description of every togglable setting, in display order. The TUI's\n * `SettingsModal` and any future GUI settings panel build their row list\n * from this so labels/descriptions stay in one place.\n */\nexport interface SettingsToggle {\n key: BooleanSettingKey\n label: string\n description: string\n}\n\nexport const SETTINGS_TOGGLES: readonly SettingsToggle[] = [\n { key: 'safeMode', label: 'Safe mode', description: 'prompt before each tool call (unless safelisted)' },\n { key: 'hideSubagentOutput', label: 'Hide subagent output', description: 'collapse subagent runs to start/done markers' },\n { key: 'showThinking', label: 'Thinking blocks', description: 'agent reasoning shown inline' },\n { key: 'showToolCalls', label: 'Tool calls', description: 'the ↳ name(args) lines' },\n { key: 'showToolResults', label: 'Tool outputs', description: 'the ┃ result blocks under tool calls' },\n]\n\n/**\n * String-valued settings that pick between a known set of options. The\n * `SettingsModal` renders these as one row showing the active label, where\n * `enter` cycles to the next option (wrapping back to the first). Same\n * shape any GUI settings panel can consume — render the options array as a\n * dropdown or segmented control.\n *\n * Keep `options` in stable display order; cycling depends on it.\n */\nexport interface SettingsChoice<K extends keyof Settings = keyof Settings> {\n key: K\n label: string\n description: string\n options: readonly { value: Settings[K], label: string }[]\n}\n\nexport const SETTINGS_CHOICES: readonly SettingsChoice[] = [\n {\n key: 'theme',\n label: 'Theme',\n description: 'colors + markdown / syntax styles',\n options: Object.values(BUILTIN_THEMES).map(t => ({ value: t.id, label: t.label })),\n },\n]\n","import type { Dispatch, SetStateAction } from 'react'\nimport type { TurnUsage } from '../types'\nimport type { Owner, StreamEvent } from './types'\nimport { useCallback, useMemo, useRef } from 'react'\n\n/** Target one flush per ~33ms (one frame at the default renderer targetFps=30). */\nconst FLUSH_INTERVAL_MS = 33\n\nconst PARENT_OWNER: Owner = 'parent'\n\n// ---------------------------------------------------------------------------\n// Streaming-delta merging\n//\n// Each event is owned by either the parent agent or a specific subagent\n// (`childId`). Same-owner same-kind text/thinking chunks coalesce into one\n// growing event so React allocates one renderable per stream, not per delta.\n// ---------------------------------------------------------------------------\n\ninterface DeltaBucket {\n markdown: string\n thinking: string\n owner: Owner\n depth: number\n}\n\nfunction emptyBucket(owner: Owner, depth: number): DeltaBucket {\n return { markdown: '', thinking: '', owner, depth }\n}\n\nfunction applyBucket(prev: StreamEvent[], bucket: DeltaBucket): StreamEvent[] {\n let result = prev\n if (bucket.thinking)\n result = appendThinkingLines(result, bucket.thinking, bucket.owner, bucket.depth)\n if (bucket.markdown)\n result = appendMarkdownDelta(result, bucket.markdown, bucket.owner, bucket.depth)\n return result\n}\n\nfunction appendMarkdownDelta(prev: StreamEvent[], delta: string, owner: Owner, depth: number): StreamEvent[] {\n const last = prev[prev.length - 1]\n if (last && last.kind === 'markdown' && last.streaming && ownerOf(last) === owner) {\n const next = prev.slice(0, -1)\n next.push({ ...last, text: last.text + delta })\n return next\n }\n return [\n ...prev,\n eventWithOwner({ kind: 'markdown', text: delta, streaming: true }, owner, depth),\n ]\n}\n\nfunction appendThinkingLines(prev: StreamEvent[], delta: string, owner: Owner, depth: number): StreamEvent[] {\n const lines = delta.split('\\n')\n const result = [...prev]\n const last = result[result.length - 1]\n\n if (last && last.kind === 'thinking' && ownerOf(last) === owner) {\n result[result.length - 1] = { ...last, text: last.text + lines[0] }\n }\n else if (lines[0] || lines.length > 1) {\n result.push(eventWithOwner({ kind: 'thinking', text: lines[0] }, owner, depth))\n }\n\n for (let i = 1; i < lines.length; i++)\n result.push(eventWithOwner({ kind: 'thinking', text: lines[i] }, owner, depth))\n\n return result\n}\n\nfunction ownerOf(evt: StreamEvent): Owner {\n return evt.childId ?? PARENT_OWNER\n}\n\nfunction eventWithOwner(evt: StreamEvent, owner: Owner, depth: number): StreamEvent {\n if (owner === PARENT_OWNER)\n return evt\n return { ...evt, childId: owner, depth }\n}\n\n/** Flip any trailing streaming markdown blocks (any owner) to finalized. */\nexport function finalizeStreamingMarkdown(events: StreamEvent[]): StreamEvent[] {\n let changed = false\n const next = events.map((e) => {\n if (e.kind === 'markdown' && e.streaming) {\n changed = true\n return { ...e, streaming: false }\n }\n return e\n })\n return changed ? next : events\n}\n\n/** Flip the trailing streaming markdown block for one specific owner. */\nexport function finalizeStreamingMarkdownForOwner(events: StreamEvent[], owner: Owner): StreamEvent[] {\n for (let i = events.length - 1; i >= 0; i--) {\n const e = events[i]\n if (e.kind !== 'markdown')\n continue\n if (!e.streaming)\n continue\n if (ownerOf(e) !== owner)\n continue\n const next = events.slice()\n next[i] = { ...e, streaming: false }\n return next\n }\n return events\n}\n\n// ---------------------------------------------------------------------------\n// Context-window math.\n// ---------------------------------------------------------------------------\n\n/**\n * Effective context size for a single turn.\n *\n * `usage.input` is misleading on its own when prompt caching is active: providers\n * (Anthropic, OpenRouter→Anthropic, Gemini) report `input` as the *new uncached*\n * tokens only — the cached prefix shows up in `cacheRead`, and newly-cached\n * tokens in `cacheCreation`. The model still saw all three buckets, so the real\n * context-window utilization is their sum.\n *\n * Non-caching providers leave `cacheRead`/`cacheCreation` undefined, so this\n * collapses to plain `input` for them.\n */\nexport function turnContextSize(usage: TurnUsage | undefined): number {\n if (!usage)\n return 0\n return (usage.input ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheCreation ?? 0)\n}\n\n// ---------------------------------------------------------------------------\n// useStreamBuffer — throttled stream-event accumulator with per-owner lanes.\n//\n// Provider deltas arrive at ~50Hz; flushing each one through React causes the\n// ScrollBox to recompute layout faster than the terminal can clear and\n// repaint, producing overdraw artifacts during scroll. We buffer per owner\n// (parent + each active subagent) and flush at most once per ~33ms.\n// ---------------------------------------------------------------------------\n\nexport interface StreamSource {\n /** Pass `undefined` / omit for parent-agent events. */\n childId?: string\n /** Nesting depth — 0 for parent, ≥ 1 for subagents. */\n depth?: number\n}\n\nexport interface StreamBuffer {\n /** Queue a streaming delta for the next flush tick. */\n queueStreamDelta: (kind: 'markdown' | 'thinking', delta: string, source?: StreamSource) => void\n /** Drain pending deltas immediately, then append a non-streaming event. */\n appendImmediate: (evt: StreamEvent) => void\n /** Drain pending deltas immediately, then transform the event list. */\n flushAndUpdate: (update: (events: StreamEvent[]) => StreamEvent[]) => void\n /** Drain pending deltas without further transformation. */\n flush: () => void\n /** Cancel any pending flush and drop buffered deltas (on session teardown). */\n reset: () => void\n}\n\nexport function useStreamBuffer(setEvents: Dispatch<SetStateAction<StreamEvent[]>>): StreamBuffer {\n const bucketsRef = useRef<Map<Owner, DeltaBucket>>(new Map())\n const flushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const drainPendingInto = useCallback((updater?: (events: StreamEvent[]) => StreamEvent[]) => {\n if (flushTimerRef.current) {\n clearTimeout(flushTimerRef.current)\n flushTimerRef.current = null\n }\n const buckets = Array.from(bucketsRef.current.values())\n bucketsRef.current.clear()\n const hasDeltas = buckets.some(b => b.markdown.length > 0 || b.thinking.length > 0)\n if (!hasDeltas && !updater)\n return\n setEvents((prev) => {\n let merged = prev\n for (const bucket of buckets)\n merged = applyBucket(merged, bucket)\n return updater ? updater(merged) : merged\n })\n }, [setEvents])\n\n const flush = useCallback(() => drainPendingInto(), [drainPendingInto])\n\n const flushAndUpdate = useCallback(\n (update: (events: StreamEvent[]) => StreamEvent[]) => drainPendingInto(update),\n [drainPendingInto],\n )\n\n const appendImmediate = useCallback(\n (evt: StreamEvent) => drainPendingInto(events => [...events, evt]),\n [drainPendingInto],\n )\n\n const queueStreamDelta = useCallback((\n kind: 'markdown' | 'thinking',\n delta: string,\n source?: StreamSource,\n ) => {\n if (!delta)\n return\n const owner: Owner = source?.childId ?? PARENT_OWNER\n const depth = source?.depth ?? 0\n let bucket = bucketsRef.current.get(owner)\n if (!bucket) {\n bucket = emptyBucket(owner, depth)\n bucketsRef.current.set(owner, bucket)\n }\n bucket[kind] += delta\n if (!flushTimerRef.current)\n flushTimerRef.current = setTimeout(flush, FLUSH_INTERVAL_MS)\n }, [flush])\n\n const reset = useCallback(() => {\n if (flushTimerRef.current) {\n clearTimeout(flushTimerRef.current)\n flushTimerRef.current = null\n }\n bucketsRef.current.clear()\n }, [])\n\n // CRITICAL: stabilize the returned object. All five callbacks are useCallback'd\n // (stable across renders), but a bare object-literal return would be a fresh\n // reference every call, which cascades through every `useCallback`/`useEffect`\n // that depends on `stream` and turns the resume effect into an unbounded\n // destroy/rebuild loop — the exact source of the terminal-host memory leak.\n return useMemo(\n () => ({ queueStreamDelta, appendImmediate, flushAndUpdate, flush, reset }),\n [queueStreamDelta, appendImmediate, flushAndUpdate, flush, reset],\n )\n}\n","import type { ReactNode } from 'react'\nimport type { SyntaxStyles, Theme, ThemeColors, ThemeSelect, ThemeSurfaces } from './theme'\nimport { createContext, useContext } from 'react'\nimport { DEFAULT_THEME } from './theme'\n\n// ---------------------------------------------------------------------------\n// ThemeContext\n//\n// The TUI / GUI mounts `<ThemeProvider theme={…}>` near the root of its tree,\n// resolving the active theme from `Settings.theme`. Every component reads\n// theme values through a hook so a runtime theme switch (Settings → Theme)\n// triggers an immediate re-paint of the whole tree.\n//\n// Sub-hooks (`useColors`, `useSelectStyle`, …) exist so consumers can grab\n// just the slice they need — the rename-friendly shape lets a component\n// keep its body unchanged when migrating from the static `COLOR.brand`\n// pattern to `const COLOR = useColors(); COLOR.brand`.\n// ---------------------------------------------------------------------------\n\nconst ThemeContext = createContext<Theme>(DEFAULT_THEME)\n\nexport function ThemeProvider({ theme, children }: { theme: Theme, children: ReactNode }) {\n return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>\n}\n\nexport function useTheme(): Theme {\n return useContext(ThemeContext)\n}\n\n/** Color palette only — equivalent to `useTheme().colors`. */\nexport function useColors(): ThemeColors {\n return useContext(ThemeContext).colors\n}\n\n/** Select-row styling — equivalent to `useTheme().select`. */\nexport function useSelectStyle(): ThemeSelect {\n return useContext(ThemeContext).select\n}\n\n/** Panel / surface backgrounds — equivalent to `useTheme().surfaces`. */\nexport function useSurfaces(): ThemeSurfaces {\n return useContext(ThemeContext).surfaces\n}\n\n/** Raw syntax style table — `useTheme().syntax`. Renderer converts to its native style type. */\nexport function useSyntaxStyles(): SyntaxStyles {\n return useContext(ThemeContext).syntax\n}\n"],"mappings":";;;;;;;;;;;;;;;AAyGA,SAAgB,UAAU,MAAkC;CAC1D,OAAO,KAAK,qBAAqB,KAAK;;;AAIxC,SAAgB,OAAO,MAAkC;CACvD,OAAO,KAAK,gBAAgB,KAAK;;AAOnC,MAAa,sBAA0C;CACrD,KAAK;CACL,OAAO;CACP,SAAS;CACT,cAAc;CACd,QAAQ;CACR,mBAAmB;CACnB,eAAe;CACf,WAAW;CACZ;AAED,MAAa,mBAAuC;CAClD,KAAK;CACL,OAAO;CACP,SAAS;CACT,cAAc;CACd,QAAQ;CACR,mBAAmB;CACnB,cAAc;CACd,mBAAmB;CACnB,eAAe;CAChB;AAED,MAAa,uBAA2C;CACtD,KAAK;CACL,OAAO;CACP,SAAS;CACT,cAAc;CACd,QAAQ;CACR,mBAAmB;CACpB;AAED,MAAa,qBAAyC;CACpD,KAAK;CACL,OAAO;CACP,SAAS;CACT,cAAc;CACd,QAAQ;CACR,mBAAmB;CACpB;;;;;;;;;;AAWD,MAAa,oBAAkE;CAC7E,WAAW;CACX,QAAQ;CACR,YAAY;CACZ,UAAU;CACX;;;;;;;AAYD,SAAgB,oBAAoB,YAAsD;CACxF,IAAI,WAAW,QACb,OAAO,WAAW;CACpB,IAAI;EACF,OAAO,UAAU,OAAO,WAAW,CAAU;SAEzC;EACJ,OAAO,EAAE;;;;;;;;AASb,SAAgB,iBAAiB,YAAgC,SAAgC;CAE/F,IAAI,WAAW,QAEb,OADc,WAAW,OAAO,MAAK,MAAK,EAAE,OAAO,QACvC,EAAE,iBAAiB;CAEjC,IAAI;EAEF,OADc,SAAS,OAAO,WAAW,EAAW,QACxC,EAAE,iBAAiB;SAE3B;EACJ,OAAO;;;;;;ACxLX,MAAM,YAAY;;;;;;;;AA0BlB,SAAgB,gBAAgB,SAAyB;CACvD,OAAO,QAAQ,SAAS,mBAAmB;;;;;;;;;;AAW7C,SAAgB,gBAAgB,SAAkC;CAChE,MAAM,OAAO,gBAAgB,QAAQ;CAErC,IAAI,CAAC,WAAW,KAAK,EAAE;EACrB,MAAM,WAAW,kBAAkB,KAAK;EACxC,IAAI,UACF,OAAO;EACT,OAAO,EAAE;;CAGX,IAAI;EACF,MAAM,MAAM,aAAa,MAAM,QAAQ;EACvC,MAAM,SAAS,KAAK,MAAM,IAAI;EAC9B,IAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,EAChE,OAAO,EAAE;EACX,OAAO;SAEH;EACJ,OAAO,EAAE;;;;AAKb,SAAgB,uBAAuB,SAAiB,YAAgE;CACtH,OAAO,gBAAgB,QAAQ,CAAC,UAAU,WAAW;;;;;;;;;AAUvD,SAAgB,iBAAiB,SAAiB,OAA8B;CAC9E,MAAM,OAAO,gBAAgB,QAAQ;CACrC,UAAU,QAAQ,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;CAC7C,MAAM,MAAM,GAAG,KAAK,GAAG,QAAQ,IAAI,GAAG,KAAK,KAAK,CAAC;CACjD,cAAc,KAAK,GAAG,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,WAAW,CAAC;CAC9E,WAAW,KAAK,KAAK;;AAGvB,SAAgB,sBACd,SACA,YACA,MACM;CACN,MAAM,MAAM,gBAAgB,QAAQ;CACpC,IAAI,UAAU,WAAW,IAAI;CAC7B,iBAAiB,SAAS,IAAI;;AAGhC,SAAgB,yBAAyB,SAAiB,YAAsC;CAC9F,MAAM,MAAM,gBAAgB,QAAQ;CACpC,MAAM,UAAU,UAAU,WAAW;CACrC,IAAI,EAAE,WAAW,MACf;CACF,OAAO,IAAI;CACX,iBAAiB,SAAS,IAAI;;;;;;;;;;;;;;;AAgBhC,SAAgB,eACd,SACA,UACM;CACN,MAAM,QAAQ,gBAAgB,QAAQ;CACtC,KAAK,MAAM,cAAc,OAAO,OAAO,SAAS,EAAE;EAChD,IAAI,CAAC,WAAW,UAAU,QAAQ,IAAI,WAAW,SAC/C;EACF,MAAM,OAAO,MAAM,UAAU,WAAW;EACxC,IAAI,MAAM,SAAS,YAAY,KAAK,OAClC,QAAQ,IAAI,WAAW,UAAU,KAAK;;;;;;;;;;;;;;;;;;;;;;;AA4B5C,SAAS,kBAAkB,YAA4C;CACrE,MAAM,aAAa,QAAQ,QAAQ,KAAK,EAAE,oBAAoB;CAC9D,IAAI,CAAC,WAAW,WAAW,EACzB,OAAO;CAET,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,aAAa,YAAY,QAAQ,CAAC;SAElD;EACJ,OAAO;;CAET,IAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,EAChE,OAAO;CAET,MAAM,WAA4B,EAAE;CACpC,KAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,OAAO,EAAE;EACrD,IAAI,CAAC,cAAc,MAAM,EACvB;EACF,MAAM,EAAE,QAAQ,SAAS,SAAS,GAAG,WAAW;EAChD,SAAS,WAAW;GAClB,MAAM;GACN;GACA,GAAI,OAAO,YAAY,WAAW,EAAE,SAAS,GAAG,EAAE;GAClD,GAAI,OAAO,YAAY,WAAW,EAAE,SAAS,GAAG,EAAE;GAClD,GAAG;GACJ;;CAGH,IAAI,OAAO,KAAK,SAAS,CAAC,WAAW,GACnC,OAAO;CAGT,UAAU,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;CACnD,MAAM,MAAM,GAAG,WAAW,GAAG,QAAQ,IAAI,GAAG,KAAK,KAAK,CAAC;CACvD,cAAc,KAAK,GAAG,KAAK,UAAU,UAAU,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,WAAW,CAAC;CACjF,WAAW,KAAK,WAAW;CAE3B,OAAO;;AAGT,SAAS,cAAc,OAA2G;CAChI,OACE,OAAO,UAAU,YACd,UAAU,QACV,YAAY,SACZ,OAAQ,MAA8B,WAAW;;;;;;;;;;;;;;;;;ACzLxD,SAAgB,WACd,SACA,UACA,MAA0C,QAAQ,KAClC;CAChB,MAAM,QAAQ,gBAAgB,QAAQ;CAEtC,OAAO,OAAO,OAAO,SAAS,CAAC,KAAK,eAAe;EACjD,MAAM,UAAwB,EAAE;EAChC,MAAM,YAAY,MAAM,UAAU,WAAW;EAG7C,IAAI,WAAW,SAAS,YAAY,UAAU,OAC5C,QAAQ,KAAK;GAAE,QAAQ;GAAU,QAAQ;GAAoB,CAAC;EAIhE,IAAI,WAAW,UAAU,IAAI,WAAW,SACtC,QAAQ,KAAK;GAAE,QAAQ;GAAO,QAAQ,WAAW;GAAQ,CAAC;EAG5D,IAAI,WAAW,SAAS,WAAW,UAAU,QAAQ;GACnD,MAAM,SAAS,OAAO,UAAU,YAAY,WACxC,mBAAmB,IAAI,KAAK,UAAU,QAAQ,CAAC,gBAAgB,KAC/D;GACJ,QAAQ,KAAK;IAAE,QAAQ;IAAS;IAAQ,CAAC;;EAG3C,OAAO;GACL,KAAK,WAAW;GAChB,OAAO,WAAW;GAClB,WAAW,QAAQ,SAAS;GAC5B;GACD;GACD;;;;AC/DJ,SAASA,YAAU,MAAoB;CACrC,MAAM,MAAM,QAAQ,KAAK;CACzB,IAAI,WAAW,IAAI,EACjB;CACF,IAAI;EACF,UAAU,KAAK,EAAE,WAAW,MAAM,CAAC;UAE9B,KAAK;EACV,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;EAChE,MAAM,IAAI,MACR,8CAA8C,IAAI,yHAEG,UACtD;;;AAQL,SAAgB,eAAe,QAA8B;CAC3D,YAAU,OAAO;CACjB,OAAO,kBAAkB,EAAE,MAAM,QAAQ,CAAC;;AAwB5C,SAAgB,iBAAiB,MAA6B;CAC5D,OAAO;EACL,YAAY,UAAU,KAAK;EAC3B,OAAM,UAAS,UAAU,MAAM,MAAM;EACtC;;AAGH,SAAgB,UAAU,MAAwB;CAChD,IAAI,CAAC,WAAW,KAAK,EACnB,OAAO,EAAE;CACX,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,aAAa,MAAM,QAAQ,CAAC;EACtD,IAAI,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,OAAO,EAChE,OAAO;SAEL;CAGN,OAAO,EAAE;;AAGX,SAAgB,UAAU,MAAc,OAAuB;CAC7D,YAAU,KAAK;CAEf,MAAM,MAAM,GAAG,KAAK,GAAG,QAAQ,IAAI;CACnC,cAAc,KAAK,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;CAClD,WAAW,KAAK,KAAK;;;;;;;AAgBvB,eAAsB,gBAAgB,OAA6C;CACjF,MAAM,MAAM,MAAM,MAAM,MAAM;CAY9B,QAAO,MAXa,QAAQ,IAAI,IAAI,IAAI,OAAO,OAAO;EACpD,MAAM,OAAO,MAAM,MAAM,KAAK,GAAG;EACjC,IAAI,CAAC,MACH,OAAO;EACT,OAAO;GACL;GACA,OAAO,eAAe,KAAK,MAAM,IAAI;GACrC,WAAW,KAAK,MAAM;GACtB,WAAW,KAAK;GACjB;GACD,CAAC,EACU,QAAQ,MAAwB,MAAM,KAAK;;;AAI1D,SAAgB,eAAe,OAAqC;CAClE,MAAM,QAAQ,MAAM,MAAK,MAAK,EAAE,SAAS,OAAO;CAChD,IAAI,CAAC,OACH,OAAO;CACT,KAAK,MAAM,SAAS,MAAM,SACxB,IAAI,MAAM,SAAS,UAAU,MAAM,KAAK,MAAM,EAAE;EAC9C,MAAM,UAAU,MAAM,KAAK,QAAQ,QAAQ,IAAI,CAAC,MAAM;EACtD,OAAO,QAAQ,SAAS,KAAK,GAAG,QAAQ,MAAM,GAAG,GAAG,CAAC,KAAK;;CAG9D,OAAO;;;;;;;;;;;;;;;;;;;;AAqBT,SAAgB,gBACd,OACA,OAA8B,EAAE,EACjB;CACf,MAAM,0BAAU,IAAI,KAAyB;CAC7C,KAAK,MAAM,OAAO,MAChB,QAAQ,IAAI,IAAI,IAAI,IAAI;CAO1B,MAAM,oCAAoB,IAAI,KAAqB;CAKnD,KAHG,QAAO,OAAM,EAAE,SAAS,KAAK,EAAE,CAC/B,OAAO,CACP,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,UACzB,CAAC,SAAS,GAAG,MAAM,kBAAkB,IAAI,EAAE,IAAI,SAAS,IAAI,IAAI,CAAC;CAC1E,MAAM,YAAY,UAAkB,kBAAkB,IAAI,MAAM,IAAI;CAMpE,MAAM,+BAAe,IAAI,KAAqB;CAC9C,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,KAAK,SAAS,aAChB;EACF,KAAK,MAAM,SAAS,KAAK,SACvB,IAAI,MAAM,SAAS,aACjB,aAAa,IAAI,MAAM,IAAI,MAAM,KAAK;;CAI5C,MAAM,SAAwB,EAAE;CAChC,IAAI;CACJ,IAAI,YAAY;CAEhB,MAAM,YAAY,OAA2B,UAAkB;EAC7D,IAAI,CAAC,SAAS,SAAS,GACrB;EACF,MAAM,MAAM,QAAQ,IAAI,MAAM;EAC9B,IAAI,CAAC,KACH;EACF,MAAM,MAAM,IAAI,WAAW,aAAa,IAAI,WAAW,UAAU,IAAI,SAAS;EAI9E,MAAM,QAAQ,iBAAiB;GAC7B,SAAS,IAAI,YAAY,IAAI,YAAY,SAAS;GAClD,UAAU,IAAI,aAAa,IAAI,YAAY,UAAU;GACrD,gBAAgB,IAAI,YAAY,aAAa;GAC7C,oBAAoB,IAAI,YAAY,iBAAiB;GACtD,CAAC;EACF,OAAO,KAAK;GACV,MAAM;GACN,MAAM,GAAG,IAAI,GAAG;GAChB,SAAS,SAAS,MAAM;GACxB;GACD,CAAC;;CAGJ,MAAM,WAAW,OAAe,UAAkB;EAChD,IAAI,SAAS,GACX;EACF,MAAM,MAAM,QAAQ,IAAI,MAAM;EAC9B,IAAI,CAAC,KACH;EACF,MAAM,cAAc,IAAI,OAAO,SAAS,KAAK,GAAG,IAAI,OAAO,MAAM,GAAG,GAAG,CAAC,KAAK,IAAI;EACjF,OAAO,KAAK;GACV,MAAM;GACN,MAAM;GACN,SAAS,SAAS,MAAM;GACxB;GACD,CAAC;;CAGJ,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,OAAO,MAAM;EAEnB,MAAM,SADM,KAAK,QAAQ,QAAQ,IAAI,KAAK,MAAM,GAAG,KAAA,IAChC,SAAS;EAC5B,MAAM,MAAM,QAAQ,KAAK,KAAK,QAAQ;GAAE,SAAS,SAAS,KAAK,MAAM;GAAE;GAAO,GAAG,KAAA;EAMjF,IAAI,KAAK,UAAU,WAAW;GAC5B,SAAS,WAAW,UAAU;GAC9B,IAAI,UAAU,KAAK,cAAc,KAAK,IAAI,GACxC,OAAO,KAAK;IAAE,MAAM;IAAa,MAAM;IAAI,CAAC;GAC9C,IAAI,KAAK,OACP,QAAQ,KAAK,OAAO,MAAM;GAC5B,YAAY,KAAK;GACjB,YAAY;SAET,IAAI,IAAI,KAAK,UAAU,GAE1B,OAAO,KAAK;GAAE,MAAM;GAAa,MAAM;GAAI,CAAC;EAG9C,IAAI,KAAK,SAAS,QAAQ;GACxB,KAAK,MAAM,SAAS,KAAK,SACvB,IAAI,MAAM,SAAS,UAAU,MAAM,KAAK,MAAM;QAGxC,UAAU,GACZ,OAAO,KAAK;KAAE,MAAM;KAAQ,MAAM,KAAK,MAAM;KAAQ,CAAC;UAErD,IAAI,MAAM,SAAS,eAAe;IACrC,MAAM,OAAO,aAAa,IAAI,MAAM,OAAO;IAK3C,MAAM,MAAM,eAAe,MAAM,OAAO;IACxC,MAAM,OAAO,SAAS,UAAU,qBAAqB,IAAI,GAAG;IAC5D,OAAO,KAAK;KACV,MAAM;KACN;KACA,GAAI,OAAO,EAAE,MAAM,GAAG,EAAE;KACxB,GAAG;KACJ,CAAC;;GAGN;;EAGF,IAAI,KAAK,SAAS;QACX,MAAM,SAAS,KAAK,SACvB,IAAI,MAAM,SAAS,UAAU,MAAM,KAAK,MAAM,EAG5C,OAAO,KAAK;IAAE,MAAM;IAAY,MAAM,MAAM;IAAM,WAAW;IAAO,GAAG;IAAK,CAAC;QAE1E,IAAI,MAAM,SAAS,aACtB,OAAO,KAAK;IACV,MAAM;IACN,MAAM,gBAAgB,MAAM,MAAM,MAAM,MAAM;IAC9C,MAAM,MAAM;IACZ,GAAG;IACJ,CAAC;;;CAOV,SAAS,WAAW,UAAU;CAE9B,OAAO;;;AAIT,SAAgB,gBAAgB,MAAc,OAAwC;CACpF,MAAM,OAAO,KAAK,UAAU,MAAM;CAClC,OAAO,QAAQ,SAAS,OAAO,GAAG,KAAK,GAAG,KAAK,KAAK;;;AAItD,SAAgB,eAAe,QAA8C;CAC3E,OAAO,OAAO,WAAW,WAAW,SAAS,iBAAiB,OAAO;;;;;;;;;;;;;;;AAgBvE,SAAgB,qBAAqB,MAAsB;CACzD,OAAO,KAAK,QAAQ,sBAAsB,GAAG;;;AAI/C,SAAgB,yBAAyB,OAA8B;CACrE,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;EAC1C,MAAM,OAAO,MAAM;EACnB,IAAI,KAAK,SAAS,eAAe,KAAK,OACpC,QAAQ,KAAK,MAAM,SAAS,MACvB,KAAK,MAAM,aAAa,MACxB,KAAK,MAAM,iBAAiB;;CAGrC,OAAO;;;;;ACzPT,SAAgB,cAAc,UAAuB,EAAE,EAAkB;CACvE,MAAM,SAAS,QAAQ,UAAU,QAAQ,IAAI,iBAAiB;CAC9D,MAAM,aAAa,QAAQ,cAAc,QAAQ,IAAI,sBAAsB,SAAS;CACpF,MAAM,MAAM,QAAQ,YAAY,OAAO;CACvC,MAAM,QAAQ;EACZ;EACA,IAAI,QAAQ,KAAK,cAAc;EAC/B,OAAO,QAAQ,KAAK,aAAa;EAClC;CAED,MAAM,QAAsB,QAAQ,SAAS,eAAe,MAAM,GAAG;CACrE,MAAM,aAAa,iBAAiB,MAAM,MAAM;CAChD,MAAM,eAAe,WAAW,MAAM;CAKtC,MAAM,YAA8B,QAAQ,aAAa;CACzD,MAAM,SAAS,QAAQ,UAAUC;CAOjC,QAAQ,IAAI,0BAA0B,gBAAgB,IAAI;CAC1D,eAAe,KAAK,UAAU;CAE9B,MAAM,YAAY,mBAAmB,UAAU;CAE/C,MAAM,iBAAiB,sBAAsB,cAAc,WAAW,IAAI;CAC1E,MAAM,gBAAgB,iBAAiB,YAAY,gBAAgB,WAAW,aAAa,GAAG;CAE9F,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,iBAAiB,aAAa,YAAY,EAAE;EAC5C;EACA;EACD;;AAGH,SAAS,mBAAmB,UAAwE;CAClG,QAAQ,QAAQ;EACd,MAAM,aAAa,SAAS;EAC5B,OAAO,aAAa,oBAAoB,WAAW,GAAG,EAAE;;;AAI5D,SAAS,sBACP,OACA,WACA,YACqB;CACrB,IAAI,CAAC,MAAM,cACT,OAAO;CACT,IAAI,CAAC,UAAU,MAAM,eACnB,OAAO;CACT,OAAO,WAAW,YAAY,UAAU,CAAC,MAAK,MAAK,EAAE,QAAQ,MAAM,gBAAgB,EAAE,UAAU,IAAI;;AAGrG,SAAS,YAAY,MAAoB,WAA6B,OAAgC;CACpG,MAAM,aAAa,UAAU,KAAK;CAClC,IAAI,CAAC,YACH,OAAO;CAKT,MAAM,QAJa,MAAM,sBAAsB,KAAK,QAIxB,WAAW,gBAAgB,mBAAmB,WAAW;CACrF,OAAO,QAAQ;EAAE,UAAU;EAAM;EAAO,GAAG;;AAG7C,SAAS,mBAAmB,YAAoD;CAC9E,IAAI;EACF,OAAO,WAAW,SAAS,CAAC,KAAK;SAE7B;EACJ;;;;;ACpKJ,MAAM,gBAAgB,cAAqC,KAAK;AAEhE,SAAgB,eAAe,EAAE,QAAQ,YAA6D;CACpG,OAAO,oBAAC,cAAc,UAAf;EAAwB,OAAO;EAAS;EAAkC,CAAA;;AAGnF,SAAgB,YAA4B;CAC1C,MAAM,MAAM,WAAW,cAAc;CACrC,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,iDAAiD;CACnE,OAAO;;;;;ACpBT,SAAgB,UAAU,GAAmB;CAC3C,IAAI,IAAI,KACN,OAAO,OAAO,EAAE;CAClB,IAAI,IAAI,KACN,OAAO,IAAI,IAAI,KAAM,QAAQ,IAAI,MAAS,IAAI,EAAE,CAAC;CACnD,OAAO,IAAI,IAAI,KAAW,QAAQ,EAAE,CAAC;;;AAIvC,SAAgB,UAAU,IAAY,MAAc,KAAK,KAAK,EAAU;CACtE,MAAM,IAAI,KAAK,OAAO,MAAM,MAAM,IAAO;CACzC,IAAI,IAAI,GACN,OAAO;CACT,IAAI,IAAI,IACN,OAAO,GAAG,EAAE;CACd,MAAM,IAAI,KAAK,MAAM,IAAI,GAAG;CAC5B,IAAI,IAAI,IACN,OAAO,GAAG,EAAE;CACd,OAAO,GAAG,KAAK,MAAM,IAAI,GAAG,CAAC;;;AAI/B,SAAgB,QAAQ,IAAoB;CAC1C,OAAO,GAAG,QAAQ,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE;;;;ACXzC,SAAgB,cAAc,YAAyC;CACrE,OAAO,WAAW,kBAAkB,KAAA;;;;;;;;;AAqBtC,eAAsB,cACpB,YACA,SAC2B;CAC3B,IAAI,CAAC,WAAW,eACd,MAAM,IAAI,MACR,2BAA2B,WAAW,MAAM,IAAI,WAAW,IAAI,6BAChE;CAGH,MAAM,YAAiC;EACrC,SAAS,SAAS;GAChB,QAAQ,MAAM,KAAK,KAAK,KAAK,aAAa;GAI1C,eAAoB,KAAK,IAAI;;EAE/B,UAAU,YAAY;GACpB,IAAI,CAAC,QAAQ,eACX,MAAM,IAAI,MAAM,iEAAiE;GACnF,OAAO,QAAQ,eAAe;;EAEhC,YAAY,QAAQ;EACpB,QAAQ,QAAQ;EACjB;CAED,OAAO,WAAW,cAAc,MAAM,UAAU;;;;;;;;;;;;AAalD,SAAS,eAAe,KAAmB;CACzC,MAAM,CAAC,KAAK,GAAG,eAAe;EAC5B,IAAI,QAAQ,aAAa,UACvB,OAAO,CAAC,QAAQ,IAAI;EACtB,IAAI,QAAQ,aAAa,SACvB,OAAO;GAAC;GAAO;GAAM;GAAS;GAAI;GAAI;EACxC,OAAO,CAAC,YAAY,IAAI;KACtB;CACJ,IAAI;EACF,MAAM,QAAQ,MAAM,KAAK,MAAM;GAAE,OAAO;GAAU,UAAU;GAAM,CAAC;EACnE,MAAM,GAAG,eAAe,GAAG;EAC3B,MAAM,OAAO;SAET;;;;;;;;;;;;;;;;;;;;;;;;;;;;AClDR,SAAgB,iBAAiB,SAAyB;CACxD,OAAO,QAAQ,SAAS,gBAAgB;;AAG1C,SAAgB,aAAa,SAA+B;CAC1D,MAAM,OAAO,iBAAiB,QAAQ;CACtC,IAAI,CAAC,WAAW,KAAK,EACnB,OAAO,EAAE;CACX,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,aAAa,MAAM,QAAQ,CAAC;EACtD,IAAI,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,OAAO,EAChE,OAAO;SAEL;CAGN,OAAO,EAAE;;AAGX,SAAS,UAAU,MAAoB;CACrC,MAAM,MAAM,QAAQ,KAAK;CACzB,IAAI,CAAC,WAAW,IAAI,EAClB,UAAU,KAAK,EAAE,WAAW,MAAM,CAAC;;;AAIvC,SAAgB,cAAc,SAAiB,MAA0B;CACvE,MAAM,OAAO,iBAAiB,QAAQ;CACtC,UAAU,KAAK;CACf,MAAM,MAAM,GAAG,KAAK,GAAG,QAAQ,IAAI;CACnC,cAAc,KAAK,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;CACjD,WAAW,KAAK,KAAK;;;;;;AAOvB,SAAgB,cACd,SACA,YACA,OACmB;CACnB,MAAM,OAAO,aAAa,QAAQ;CAClC,MAAM,WAAW,KAAK,aAAa,YAAY,EAAE;CACjD,IAAI,SAAS,SAAS,MAAM,EAC1B,OAAO;CACT,MAAM,OAAO,CAAC,GAAG,UAAU,MAAM;CACjC,KAAK,cAAc;EAAE,GAAG,KAAK;EAAa,UAAU;EAAM;CAC1D,cAAc,SAAS,KAAK;CAC5B,OAAO;;;AAIT,SAAgB,YAAY,SAAiB,YAAuC;CAClF,OAAO,aAAa,QAAQ,CAAC,aAAa,YAAY,EAAE;;;;;;;AAY1D,MAAa,wBAA2C;CACtD;CACA;CACA;CACA;CACD;;AAGD,MAAM,mBAAmB;CAAC;CAAW;CAAQ;CAAW;CAAQ;AAEhE,SAAS,gBAAgB,OAAwC;CAC/D,KAAK,MAAM,OAAO,kBAAkB;EAClC,MAAM,IAAI,MAAM;EAChB,IAAI,OAAO,MAAM,YAAY,EAAE,SAAS,GACtC,OAAO;;CAEX,OAAO;;;AAIT,SAAS,gBAAgB,OAAwC;CAC/D,OAAO,gBAAgB,MAAM,CAAC,MAAM,MAAM,CAAC,MAAM;;;;;;;;;;;;AAanD,MAAM,oBAAoB;AAE1B,SAAS,uBAAuB,SAA0B;CACxD,OAAO,kBAAkB,KAAK,QAAQ;;;;;;;;;;;;;;;;;;AAmBxC,SAAgB,qBACd,OACA,MACA,OACS;CAIT,IAAI,SAAS;MAEP,uBADQ,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU,GACjC,EAC7B,OAAO;;CAEX,IAAI,UAAU,MACZ,OAAO;CACT,MAAM,MAAM,MAAM,QAAQ,IAAI;CAC9B,IAAI,OAAO,GACT,OAAO;CACT,IAAI,MAAM,MAAM,GAAG,IAAI,KAAK,MAC1B,OAAO;CACT,MAAM,QAAQ,MAAM,MAAM,MAAM,EAAE;CAClC,IAAI,MAAM,SAAS,KAAK,EACtB,OAAO,gBAAgB,MAAM,KAAK,MAAM,MAAM,GAAG,GAAG;CACtD,OAAO;;;AAIT,SAAgB,aACd,SACA,MACA,OACS;CACT,IAAI,sBAAsB,SAAS,KAAK,EACtC,OAAO;CACT,OAAO,QAAQ,MAAK,MAAK,qBAAqB,GAAG,MAAM,MAAM,CAAC;;;;;;;;;;;;AAahE,SAAgB,qBACd,MACA,OACQ;CACR,IAAI,SAAS,SAAS;EACpB,MAAM,QAAQ,gBAAgB,MAAM;EACpC,IAAI,OACF,OAAO,GAAG,KAAK,GAAG,MAAM;;CAE5B,OAAO;;;;AC5KT,MAAM,uBAAuB,cAA0C,EAAE,CAAC;AAC1E,MAAM,yBAAyB,cAAsC,KAAK;AAE1E,IAAI,oBAAoB;AACxB,SAAS,iBAAyB;CAIhC,qBAAqB;CACrB,OAAO,YAAY;;;;;;AAOrB,SAAgB,iBAAiB,EAAE,YAAqC;CACtE,MAAM,CAAC,OAAO,YAAY,SAAqC,EAAE,CAAC;CAKlE,MAAM,kBAAkB,aACrB,MAAM,UAAU,IAAI,SAA2B,YAAY;EAC1D,UAAS,SAAQ,CAAC,GAAG,MAAM;GAAE,IAAI,gBAAgB;GAAE;GAAM;GAAO;GAAS,CAAC,CAAC;GAC3E,EACF,EAAE,CACH;CAED,MAAM,cAAc,aAAa,aAA+B;EAC9D,UAAU,SAAS;GACjB,MAAM,CAAC,MAAM,GAAG,QAAQ;GACxB,IAAI,MACF,KAAK,QAAQ,SAAS;GACxB,OAAO;IACP;IACD,EAAE,CAAC;CAEN,MAAM,UAAU,kBAAkB;EAChC,UAAU,SAAS;GACjB,KAAK,MAAM,KAAK,MAAM,EAAE,QAAQ,OAAO;GACvC,OAAO,EAAE;IACT;IACD,EAAE,CAAC;CAMN,MAAM,aAAa,OAA+B,KAAK;CACvD,IAAI,CAAC,WAAW,SACd,WAAW,UAAU;EAAE;EAAiB;EAAa;EAAS;CAEhE,OACE,oBAAC,uBAAuB,UAAxB;EAAiC,OAAO,WAAW;YACjD,oBAAC,qBAAqB,UAAtB;GAA+B,OAAO;GACnC;GAC6B,CAAA;EACA,CAAA;;AAItC,SAAgB,mBAA+C;CAC7D,OAAO,WAAW,qBAAqB;;AAGzC,SAAgB,qBAAsC;CACpD,MAAM,MAAM,WAAW,uBAAuB;CAC9C,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,4DAA4D;CAC9E,OAAO;;;;AClET,MAAM,QAA2B;CAC/B,WAAW;CACX,UAAU;CACV,MAAM;CACN,OAAO;CACP,KAAK;CACL,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACN,KAAK;CACL,UAAU;CACV,MAAM;CACN,UAAU;CACV,MAAM;CACN,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,MAAM;CACN,QAAQ;CACR,OAAO;CACR;AAED,MAAM,SAA4B;CAChC,WAAW;CACX,UAAU;CACV,MAAM;CACN,OAAO;CACP,KAAK;CACL,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACN,KAAK;CACL,UAAU;CACV,MAAM;CACN,UAAU;CACV,MAAM;CACN,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,MAAM;CACN,QAAQ;CACR,OAAO;CACR;AAED,MAAM,YAA+B;CACnC,WAAW;CACX,UAAU;CACV,MAAM;CACN,OAAO;CACP,KAAK;CACL,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACN,KAAK;CACL,UAAU;CACV,MAAM;CACN,UAAU;CACV,MAAM;CACN,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,MAAM;CACN,QAAQ;CACR,OAAO;CACR;AAED,MAAM,QAA2B;CAC/B,WAAW;CACX,UAAU;CACV,MAAM;CACN,OAAO;CACP,KAAK;CACL,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACN,KAAK;CACL,UAAU;CACV,MAAM;CACN,UAAU;CACV,MAAM;CACN,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,MAAM;CACN,QAAQ;CACR,OAAO;CACR;;;;;;;;;;;;;;;;;AAkBD,SAAS,gBAAgB,IAAY,OAAe,GAA6B;CAC/E,OAAO;EACL;EACA;EACA,QAAQ;GACN,OAAO,EAAE;GACT,QAAQ,EAAE;GACV,OAAO,EAAE;GACT,MAAM,EAAE;GACR,OAAO,EAAE;GACT,KAAK,EAAE;GACP,MAAM,EAAE;GACR,QAAQ,EAAE;GACV,cAAc,EAAE;GACjB;EACD,QAAQ;GACN,iBAAiB;GACjB,wBAAwB;GACxB,yBAAyB;GACzB,mBAAmB,EAAE;GACrB,WAAW,EAAE;GACb,kBAAkB,EAAE;GACpB,0BAA0B,EAAE;GAC7B;EACD,UAAU,EAIR,OAAO,EAAE,QACV;EACD,QAAQ;GACN,WAAW,EAAE,IAAI,EAAE,MAAM;GAGzB,kBAAkB;IAAE,IAAI,EAAE;IAAO,MAAM;IAAM;GAC7C,oBAAoB;IAAE,IAAI,EAAE;IAAO,MAAM;IAAM;GAC/C,oBAAoB;IAAE,IAAI,EAAE;IAAU,MAAM;IAAM;GAClD,oBAAoB;IAAE,IAAI,EAAE;IAAM,MAAM;IAAM;GAC9C,eAAe;IAAE,IAAI,EAAE;IAAM,MAAM;IAAM;GACzC,iBAAiB;IAAE,IAAI,EAAE;IAAM,MAAM;IAAM;GAC3C,iBAAiB;IAAE,IAAI,EAAE;IAAM,QAAQ;IAAM;GAC7C,eAAe;IAAE,IAAI,EAAE;IAAK,WAAW;IAAM;GAC7C,mBAAmB;IAAE,IAAI,EAAE;IAAK,WAAW;IAAM;GACjD,eAAe,EAAE,IAAI,EAAE,OAAO;GAC9B,cAAc,EAAE,IAAI,EAAE,OAAO;GAC7B,oBAAoB,EAAE,IAAI,EAAE,OAAO;GACnC,gBAAgB;IAAE,IAAI,EAAE;IAAU,QAAQ;IAAM;GAGhD,WAAW;IAAE,IAAI,EAAE;IAAO,MAAM;IAAM;GACtC,kBAAkB;IAAE,IAAI,EAAE;IAAM,MAAM;IAAM;GAC5C,oBAAoB,EAAE,IAAI,EAAE,KAAK;GACjC,UAAU,EAAE,IAAI,EAAE,OAAO;GACzB,iBAAiB;IAAE,IAAI,EAAE;IAAM,MAAM;IAAM;GAC3C,aAAa,EAAE,IAAI,EAAE,MAAM;GAC3B,WAAW;IAAE,IAAI,EAAE;IAAU,QAAQ;IAAM;GAC3C,UAAU,EAAE,IAAI,EAAE,OAAO;GACzB,WAAW,EAAE,IAAI,EAAE,OAAO;GAC1B,YAAY,EAAE,IAAI,EAAE,OAAO;GAC3B,oBAAoB,EAAE,IAAI,EAAE,OAAO;GACnC,YAAY,EAAE,IAAI,EAAE,MAAM;GAC1B,iBAAiB,EAAE,IAAI,EAAE,MAAM;GAC/B,mBAAmB,EAAE,IAAI,EAAE,MAAM;GACjC,wBAAwB,EAAE,IAAI,EAAE,MAAM;GACtC,oBAAoB,EAAE,IAAI,EAAE,MAAM;GAClC,kBAAkB,EAAE,IAAI,EAAE,MAAM;GAChC,QAAQ,EAAE,IAAI,EAAE,QAAQ;GACxB,gBAAgB,EAAE,IAAI,EAAE,QAAQ;GAChC,eAAe,EAAE,IAAI,EAAE,QAAQ;GAC/B,aAAa,EAAE,IAAI,EAAE,QAAQ;GAC7B,OAAO,EAAE,IAAI,EAAE,UAAU;GACzB,YAAY,EAAE,IAAI,EAAE,MAAM;GAC1B,oBAAoB,EAAE,IAAI,EAAE,KAAK;GACjC,sBAAsB;IAAE,IAAI,EAAE;IAAQ,QAAQ;IAAM;GACpD,mBAAmB,EAAE,IAAI,EAAE,MAAM;GACjC,YAAY,EAAE,IAAI,EAAE,UAAU;GAC9B,YAAY,EAAE,IAAI,EAAE,KAAK;GACzB,eAAe,EAAE,IAAI,EAAE,UAAU;GACjC,uBAAuB,EAAE,IAAI,EAAE,UAAU;GACzC,yBAAyB,EAAE,IAAI,EAAE,UAAU;GAC3C,SAAS,EAAE,IAAI,EAAE,UAAU;GAC5B;EACF;;AAGH,MAAa,mBAAmB,gBAAgB,oBAAoB,oBAAoB,MAAM;AAC9F,MAAa,uBAAuB,gBAAgB,wBAAwB,wBAAwB,UAAU;AAC9G,MAAa,oBAAoB,gBAAgB,qBAAqB,qBAAqB,OAAO;AAClG,MAAa,mBAAmB,gBAAgB,oBAAoB,oBAAoB,MAAM;;;AClQ9F,MAAM,UAAU;CACd,MAAM;CACN,YAAY;CACZ,MAAM;CACN,YAAY;CACZ,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,KAAK;CACL,MAAM;CACN,YAAY;CACZ,SAAS;CACT,OAAO;CACP,SAAS;CACT,OAAO;CACR;AAED,MAAa,kBAAyB;CACpC,IAAI;CACJ,OAAO;CACP,QAAQ;EACN,OAAO,QAAQ;EACf,QAAQ,QAAQ;EAChB,OAAO,QAAQ;EACf,MAAM,QAAQ;EACd,OAAO,QAAQ;EACf,KAAK,QAAQ;EACb,MAAM,QAAQ;EACd,QAAQ,QAAQ;EAChB,cAAc,QAAQ;EACvB;CACD,QAAQ;EACN,iBAAiB;EACjB,wBAAwB;EACxB,yBAAyB;EACzB,mBAAmB,QAAQ;EAC3B,WAAW,QAAQ;EACnB,kBAAkB,QAAQ;EAC1B,0BAA0B,QAAQ;EACnC;CACD,UAAU,EAGR,OAAO,QAAQ,OAChB;CACD,QAAQ;EACN,WAAW,EAAE,IAAI,QAAQ,MAAM;EAG/B,kBAAkB;GAAE,IAAI,QAAQ;GAAM,MAAM;GAAM;EAClD,oBAAoB;GAAE,IAAI,QAAQ;GAAM,MAAM;GAAM;EACpD,oBAAoB;GAAE,IAAI,QAAQ;GAAY,MAAM;GAAM;EAC1D,oBAAoB;GAAE,IAAI,QAAQ;GAAM,MAAM;GAAM;EACpD,eAAe;GAAE,IAAI,QAAQ;GAAY,MAAM;GAAM;EACrD,iBAAiB;GAAE,IAAI,QAAQ;GAAY,MAAM;GAAM;EACvD,iBAAiB;GAAE,IAAI,QAAQ;GAAa,QAAQ;GAAM;EAC1D,eAAe;GAAE,IAAI,QAAQ;GAAQ,WAAW;GAAM;EACtD,mBAAmB;GAAE,IAAI,QAAQ;GAAQ,WAAW;GAAM;EAC1D,eAAe,EAAE,IAAI,QAAQ,YAAY;EACzC,cAAc,EAAE,IAAI,QAAQ,QAAQ;EACpC,oBAAoB,EAAE,IAAI,QAAQ,QAAQ;EAC1C,gBAAgB;GAAE,IAAI,QAAQ;GAAQ,QAAQ;GAAM;EAGpD,WAAW;GAAE,IAAI,QAAQ;GAAY,MAAM;GAAM;EACjD,kBAAkB;GAAE,IAAI,QAAQ;GAAY,MAAM;GAAM;EACxD,oBAAoB,EAAE,IAAI,QAAQ,SAAS;EAC3C,UAAU,EAAE,IAAI,QAAQ,QAAQ;EAChC,iBAAiB;GAAE,IAAI,QAAQ;GAAa,MAAM;GAAM;EACxD,aAAa,EAAE,IAAI,QAAQ,QAAQ;EACnC,WAAW;GAAE,IAAI,QAAQ;GAAS,QAAQ;GAAM;EAChD,UAAU,EAAE,IAAI,QAAQ,YAAY;EACpC,WAAW,EAAE,IAAI,QAAQ,YAAY;EACrC,YAAY,EAAE,IAAI,QAAQ,YAAY;EACtC,oBAAoB,EAAE,IAAI,QAAQ,YAAY;EAC9C,YAAY,EAAE,IAAI,QAAQ,aAAa;EACvC,iBAAiB,EAAE,IAAI,QAAQ,aAAa;EAC5C,mBAAmB,EAAE,IAAI,QAAQ,aAAa;EAC9C,wBAAwB,EAAE,IAAI,QAAQ,aAAa;EACnD,oBAAoB,EAAE,IAAI,QAAQ,aAAa;EAC/C,kBAAkB,EAAE,IAAI,QAAQ,aAAa;EAC7C,QAAQ,EAAE,IAAI,QAAQ,aAAa;EACnC,gBAAgB,EAAE,IAAI,QAAQ,aAAa;EAC3C,eAAe,EAAE,IAAI,QAAQ,aAAa;EAC1C,aAAa,EAAE,IAAI,QAAQ,QAAQ;EACnC,OAAO,EAAE,IAAI,QAAQ,MAAM;EAC3B,YAAY,EAAE,IAAI,QAAQ,MAAM;EAChC,oBAAoB,EAAE,IAAI,QAAQ,YAAY;EAC9C,sBAAsB,EAAE,IAAI,QAAQ,MAAM;EAC1C,mBAAmB,EAAE,IAAI,QAAQ,MAAM;EACvC,YAAY,EAAE,IAAI,QAAQ,MAAM;EAChC,YAAY,EAAE,IAAI,QAAQ,SAAS;EACnC,eAAe,EAAE,IAAI,QAAQ,SAAS;EACtC,uBAAuB,EAAE,IAAI,QAAQ,YAAY;EACjD,yBAAyB,EAAE,IAAI,QAAQ,SAAS;EAChD,SAAS,EAAE,IAAI,QAAQ,MAAM;EAC9B;CACF;;;;;;;;;;;;;;;;;;;;;;ACMD,MAAM,iBAA8B;CAClC,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACN,OAAO;CACP,KAAK;CACL,MAAM;CACN,QAAQ;CACR,cAAc;CACf;AAED,MAAa,gBAAuB;CAClC,IAAI;CACJ,OAAO;CACP,QAAQ;CACR,QAAQ;EAIN,iBAAiB;EACjB,wBAAwB;EACxB,yBAAyB;EACzB,mBAAmB,eAAe;EAClC,WAAW,eAAe;EAC1B,kBAAkB,eAAe;EACjC,0BAA0B,eAAe;EAC1C;CACD,UAAU,EACR,OAAO,WACR;CACD,QAAQ;EAEN,WAAW,EAAE,IAAI,WAAW;EAC5B,kBAAkB;GAAE,IAAI,eAAe;GAAO,MAAM;GAAM;EAC1D,oBAAoB;GAAE,IAAI,eAAe;GAAO,MAAM;GAAM;EAC5D,oBAAoB;GAAE,IAAI;GAAW,MAAM;GAAM;EACjD,oBAAoB;GAAE,IAAI;GAAW,MAAM;GAAM;EACjD,eAAe;GAAE,IAAI;GAAW,MAAM;GAAM;EAC5C,iBAAiB;GAAE,IAAI;GAAW,MAAM;GAAM;EAC9C,iBAAiB;GAAE,IAAI;GAAW,QAAQ;GAAM;EAChD,eAAe;GAAE,IAAI,eAAe;GAAO,WAAW;GAAM;EAC5D,mBAAmB;GAAE,IAAI,eAAe;GAAO,WAAW;GAAM;EAChE,eAAe,EAAE,IAAI,eAAe,MAAM;EAC1C,cAAc,EAAE,IAAI,WAAW;EAC/B,oBAAoB,EAAE,IAAI,WAAW;EACrC,gBAAgB;GAAE,IAAI,eAAe;GAAK,QAAQ;GAAM;EAGxD,WAAW;GAAE,IAAI;GAAW,MAAM;GAAM;EACxC,kBAAkB;GAAE,IAAI;GAAW,MAAM;GAAM;EAC/C,oBAAoB,EAAE,IAAI,WAAW;EACrC,UAAU,EAAE,IAAI,WAAW;EAC3B,iBAAiB;GAAE,IAAI;GAAW,MAAM;GAAM;EAC9C,aAAa,EAAE,IAAI,WAAW;EAC9B,WAAW;GAAE,IAAI;GAAW,QAAQ;GAAM;EAC1C,UAAU,EAAE,IAAI,WAAW;EAC3B,WAAW,EAAE,IAAI,WAAW;EAC5B,YAAY,EAAE,IAAI,WAAW;EAC7B,oBAAoB,EAAE,IAAI,WAAW;EACrC,YAAY,EAAE,IAAI,WAAW;EAC7B,iBAAiB,EAAE,IAAI,WAAW;EAClC,mBAAmB,EAAE,IAAI,WAAW;EACpC,wBAAwB,EAAE,IAAI,WAAW;EACzC,oBAAoB,EAAE,IAAI,WAAW;EACrC,kBAAkB,EAAE,IAAI,WAAW;EACnC,QAAQ,EAAE,IAAI,WAAW;EACzB,gBAAgB,EAAE,IAAI,WAAW;EACjC,eAAe,EAAE,IAAI,WAAW;EAChC,aAAa,EAAE,IAAI,WAAW;EAC9B,OAAO,EAAE,IAAI,WAAW;EACxB,YAAY,EAAE,IAAI,WAAW;EAC7B,oBAAoB,EAAE,IAAI,WAAW;EACrC,sBAAsB,EAAE,IAAI,WAAW;EACvC,mBAAmB,EAAE,IAAI,WAAW;EACpC,YAAY,EAAE,IAAI,WAAW;EAC7B,YAAY,EAAE,IAAI,WAAW;EAC7B,eAAe,EAAE,IAAI,eAAe,MAAM;EAC1C,uBAAuB,EAAE,IAAI,WAAW;EACxC,yBAAyB,EAAE,IAAI,WAAW;EAC1C,SAAS,EAAE,IAAI,WAAW;EAC3B;CACF;;;;;;;;;;;AAYD,MAAa,iBAAkD;EAC5D,cAAc,KAAK;EACnB,iBAAiB,KAAK;EACtB,qBAAqB,KAAK;EAC1B,kBAAkB,KAAK;EACvB,iBAAiB,KAAK;EACtB,gBAAgB,KAAK;CACvB;;AAGD,SAAgB,aAAa,IAA+B;CAC1D,IAAI,MAAM,eAAe,KACvB,OAAO,eAAe;CACxB,OAAO;;;;ACrNT,MAAa,mBAA6B;CACxC,cAAc;CACd,eAAe;CACf,iBAAiB;CACjB,UAAU;CACV,oBAAoB;CACpB,OAAO,cAAc;CACtB;AAkBD,MAAM,kBAAkB,cAA2C,KAAK;AAExE,SAAgB,iBAAiB,EAC/B,SACA,UACA,YAKC;CACD,MAAM,CAAC,UAAU,eAAe,SAAmB,QAAQ;CAE3D,MAAM,SAAS,aAAa,QAA2B;EACrD,aAAa,SAAS;GACpB,MAAM,OAAO;IAAE,GAAG;KAAO,MAAM,CAAC,KAAK;IAAM;GAC3C,WAAW,KAAK;GAChB,OAAO;IACP;IACD,CAAC,SAAS,CAAC;CAEd,MAAM,aAAa,aAAuC,KAAQ,UAAuB;EACvF,aAAa,SAAS;GACpB,IAAI,KAAK,SAAS,OAChB,OAAO;GACT,MAAM,OAAO;IAAE,GAAG;KAAO,MAAM;IAAO;GACtC,WAAW,KAAK;GAChB,OAAO;IACP;IACD,CAAC,SAAS,CAAC;CAEd,MAAM,QAAQ,eACL;EAAE;EAAU;EAAQ;EAAY,GACvC;EAAC;EAAU;EAAQ;EAAW,CAC/B;CAED,OAAO,oBAAC,gBAAgB,UAAjB;EAAiC;EAAQ;EAAoC,CAAA;;AAGtF,SAAgB,cAAoC;CAClD,MAAM,MAAM,WAAW,gBAAgB;CACvC,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,qDAAqD;CACvE,OAAO;;AAwBT,MAAa,mBAA8C;CACzD;EAAE,KAAK;EAAY,OAAO;EAAa,aAAa;EAAoD;CACxG;EAAE,KAAK;EAAsB,OAAO;EAAwB,aAAa;EAAgD;CACzH;EAAE,KAAK;EAAgB,OAAO;EAAmB,aAAa;EAAgC;CAC9F;EAAE,KAAK;EAAiB,OAAO;EAAc,aAAa;EAA0B;CACpF;EAAE,KAAK;EAAmB,OAAO;EAAgB,aAAa;EAAwC;CACvG;AAkBD,MAAa,mBAA8C,CACzD;CACE,KAAK;CACL,OAAO;CACP,aAAa;CACb,SAAS,OAAO,OAAO,eAAe,CAAC,KAAI,OAAM;EAAE,OAAO,EAAE;EAAI,OAAO,EAAE;EAAO,EAAE;CACnF,CACF;;;;AC9HD,MAAM,oBAAoB;AAE1B,MAAM,eAAsB;AAiB5B,SAAS,YAAY,OAAc,OAA4B;CAC7D,OAAO;EAAE,UAAU;EAAI,UAAU;EAAI;EAAO;EAAO;;AAGrD,SAAS,YAAY,MAAqB,QAAoC;CAC5E,IAAI,SAAS;CACb,IAAI,OAAO,UACT,SAAS,oBAAoB,QAAQ,OAAO,UAAU,OAAO,OAAO,OAAO,MAAM;CACnF,IAAI,OAAO,UACT,SAAS,oBAAoB,QAAQ,OAAO,UAAU,OAAO,OAAO,OAAO,MAAM;CACnF,OAAO;;AAGT,SAAS,oBAAoB,MAAqB,OAAe,OAAc,OAA8B;CAC3G,MAAM,OAAO,KAAK,KAAK,SAAS;CAChC,IAAI,QAAQ,KAAK,SAAS,cAAc,KAAK,aAAa,QAAQ,KAAK,KAAK,OAAO;EACjF,MAAM,OAAO,KAAK,MAAM,GAAG,GAAG;EAC9B,KAAK,KAAK;GAAE,GAAG;GAAM,MAAM,KAAK,OAAO;GAAO,CAAC;EAC/C,OAAO;;CAET,OAAO,CACL,GAAG,MACH,eAAe;EAAE,MAAM;EAAY,MAAM;EAAO,WAAW;EAAM,EAAE,OAAO,MAAM,CACjF;;AAGH,SAAS,oBAAoB,MAAqB,OAAe,OAAc,OAA8B;CAC3G,MAAM,QAAQ,MAAM,MAAM,KAAK;CAC/B,MAAM,SAAS,CAAC,GAAG,KAAK;CACxB,MAAM,OAAO,OAAO,OAAO,SAAS;CAEpC,IAAI,QAAQ,KAAK,SAAS,cAAc,QAAQ,KAAK,KAAK,OACxD,OAAO,OAAO,SAAS,KAAK;EAAE,GAAG;EAAM,MAAM,KAAK,OAAO,MAAM;EAAI;MAEhE,IAAI,MAAM,MAAM,MAAM,SAAS,GAClC,OAAO,KAAK,eAAe;EAAE,MAAM;EAAY,MAAM,MAAM;EAAI,EAAE,OAAO,MAAM,CAAC;CAGjF,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAChC,OAAO,KAAK,eAAe;EAAE,MAAM;EAAY,MAAM,MAAM;EAAI,EAAE,OAAO,MAAM,CAAC;CAEjF,OAAO;;AAGT,SAAS,QAAQ,KAAyB;CACxC,OAAO,IAAI,WAAW;;AAGxB,SAAS,eAAe,KAAkB,OAAc,OAA4B;CAClF,IAAI,UAAU,cACZ,OAAO;CACT,OAAO;EAAE,GAAG;EAAK,SAAS;EAAO;EAAO;;;AAI1C,SAAgB,0BAA0B,QAAsC;CAC9E,IAAI,UAAU;CACd,MAAM,OAAO,OAAO,KAAK,MAAM;EAC7B,IAAI,EAAE,SAAS,cAAc,EAAE,WAAW;GACxC,UAAU;GACV,OAAO;IAAE,GAAG;IAAG,WAAW;IAAO;;EAEnC,OAAO;GACP;CACF,OAAO,UAAU,OAAO;;;AAI1B,SAAgB,kCAAkC,QAAuB,OAA6B;CACpG,KAAK,IAAI,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;EAC3C,MAAM,IAAI,OAAO;EACjB,IAAI,EAAE,SAAS,YACb;EACF,IAAI,CAAC,EAAE,WACL;EACF,IAAI,QAAQ,EAAE,KAAK,OACjB;EACF,MAAM,OAAO,OAAO,OAAO;EAC3B,KAAK,KAAK;GAAE,GAAG;GAAG,WAAW;GAAO;EACpC,OAAO;;CAET,OAAO;;;;;;;;;;;;;;AAmBT,SAAgB,gBAAgB,OAAsC;CACpE,IAAI,CAAC,OACH,OAAO;CACT,QAAQ,MAAM,SAAS,MAAM,MAAM,aAAa,MAAM,MAAM,iBAAiB;;AAgC/E,SAAgB,gBAAgB,WAAkE;CAChG,MAAM,aAAa,uBAAgC,IAAI,KAAK,CAAC;CAC7D,MAAM,gBAAgB,OAA6C,KAAK;CAExE,MAAM,mBAAmB,aAAa,YAAuD;EAC3F,IAAI,cAAc,SAAS;GACzB,aAAa,cAAc,QAAQ;GACnC,cAAc,UAAU;;EAE1B,MAAM,UAAU,MAAM,KAAK,WAAW,QAAQ,QAAQ,CAAC;EACvD,WAAW,QAAQ,OAAO;EAE1B,IAAI,CADc,QAAQ,MAAK,MAAK,EAAE,SAAS,SAAS,KAAK,EAAE,SAAS,SAAS,EACnE,IAAI,CAAC,SACjB;EACF,WAAW,SAAS;GAClB,IAAI,SAAS;GACb,KAAK,MAAM,UAAU,SACnB,SAAS,YAAY,QAAQ,OAAO;GACtC,OAAO,UAAU,QAAQ,OAAO,GAAG;IACnC;IACD,CAAC,UAAU,CAAC;CAEf,MAAM,QAAQ,kBAAkB,kBAAkB,EAAE,CAAC,iBAAiB,CAAC;CAEvE,MAAM,iBAAiB,aACpB,WAAqD,iBAAiB,OAAO,EAC9E,CAAC,iBAAiB,CACnB;CAED,MAAM,kBAAkB,aACrB,QAAqB,kBAAiB,WAAU,CAAC,GAAG,QAAQ,IAAI,CAAC,EAClE,CAAC,iBAAiB,CACnB;CAED,MAAM,mBAAmB,aACvB,MACA,OACA,WACG;EACH,IAAI,CAAC,OACH;EACF,MAAM,QAAe,QAAQ,WAAW;EACxC,MAAM,QAAQ,QAAQ,SAAS;EAC/B,IAAI,SAAS,WAAW,QAAQ,IAAI,MAAM;EAC1C,IAAI,CAAC,QAAQ;GACX,SAAS,YAAY,OAAO,MAAM;GAClC,WAAW,QAAQ,IAAI,OAAO,OAAO;;EAEvC,OAAO,SAAS;EAChB,IAAI,CAAC,cAAc,SACjB,cAAc,UAAU,WAAW,OAAO,kBAAkB;IAC7D,CAAC,MAAM,CAAC;CAEX,MAAM,QAAQ,kBAAkB;EAC9B,IAAI,cAAc,SAAS;GACzB,aAAa,cAAc,QAAQ;GACnC,cAAc,UAAU;;EAE1B,WAAW,QAAQ,OAAO;IACzB,EAAE,CAAC;CAON,OAAO,eACE;EAAE;EAAkB;EAAiB;EAAgB;EAAO;EAAO,GAC1E;EAAC;EAAkB;EAAiB;EAAgB;EAAO;EAAM,CAClE;;;;AClNH,MAAM,eAAe,cAAqB,cAAc;AAExD,SAAgB,cAAc,EAAE,OAAO,YAAmD;CACxF,OAAO,oBAAC,aAAa,UAAd;EAAuB,OAAO;EAAQ;EAAiC,CAAA;;AAGhF,SAAgB,WAAkB;CAChC,OAAO,WAAW,aAAa;;;AAIjC,SAAgB,YAAyB;CACvC,OAAO,WAAW,aAAa,CAAC;;;AAIlC,SAAgB,iBAA8B;CAC5C,OAAO,WAAW,aAAa,CAAC;;;AAIlC,SAAgB,cAA6B;CAC3C,OAAO,WAAW,aAAa,CAAC;;;AAIlC,SAAgB,kBAAgC;CAC9C,OAAO,WAAW,aAAa,CAAC"}
package/dist/tools.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { _ as ToolDef, g as ToolContext, v as ToolMap } from "./agent-BAoqUvwA.js";
2
- import { A as edit, C as readFile, D as createInteractionTool, E as InteractionToolOptions, O as grep, S as shell, T as listFiles, _ as createSkillsUseTool, b as SkillsReadToolOptions, c as validateToolArgs, d as createToolSearchTool, f as ChildAgent, g as SkillsUseToolOptions, h as createSpawnTool, k as glob, l as LazyToolEntry, m as SpawnToolState, o as writeFile, p as SpawnToolOptions, s as ValidationResult, u as ToolSearchToolOptions, v as SkillsRunScriptToolOptions, w as multiEdit, x as createSkillsReadTool, y as createSkillsRunScriptTool } from "./index-B8-yNSsk.js";
1
+ import { $ as ToolDef, Q as ToolContext, et as ToolMap } from "./index-bgh-k8Mv.js";
2
+ import { A as InteractionToolOptions, C as createSkillsRunScriptTool, D as readFile, E as shell, M as grep, N as glob, O as multiEdit, P as edit, S as SkillsRunScriptToolOptions, T as createSkillsReadTool, _ as SpawnToolOptions, b as SkillsUseToolOptions, d as ValidationResult, f as validateToolArgs, g as ChildAgent, h as createToolSearchTool, j as createInteractionTool, k as listFiles, m as ToolSearchToolOptions, p as LazyToolEntry, u as writeFile, v as SpawnToolState, w as SkillsReadToolOptions, x as createSkillsUseTool, y as createSpawnTool } from "./index-DRoG_udt.js";
3
3
  export { ChildAgent, InteractionToolOptions, LazyToolEntry, SkillsReadToolOptions, SkillsRunScriptToolOptions, SkillsUseToolOptions, SpawnToolOptions, SpawnToolState, ToolContext, ToolDef, ToolMap, ToolSearchToolOptions, ValidationResult, createInteractionTool, createSkillsReadTool, createSkillsRunScriptTool, createSkillsUseTool, createSpawnTool, createToolSearchTool, edit, glob, grep, listFiles, multiEdit, readFile, shell, validateToolArgs, writeFile };