From 3ce58f6609cc6b15066a844fdf7a7a42f4b4baf0 Mon Sep 17 00:00:00 2001 From: James White Date: Fri, 14 Nov 2025 19:35:08 +0000 Subject: [PATCH 01/35] fix: prevent visible CMD windows when spawning Codex on Windows On Windows, the MCP SDK's StdioClientTransport only sets windowsHide: true when running in Electron environments. This causes visible CMD windows to appear every time Happy CLI interacts with the Codex subprocess when running as a daemon or background process. This commit implements a workaround by temporarily setting process.type during transport initialization, which tricks the MCP SDK into enabling windowsHide on Windows platforms. Root cause: @modelcontextprotocol/sdk only enables windowsHide when isElectron() returns true, which checks for process.type property. TODO: Submit PR to @modelcontextprotocol/sdk to always hide windows on Windows platforms, not just in Electron. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/codex/codexMcpClient.ts | 52 +++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/codex/codexMcpClient.ts b/src/codex/codexMcpClient.ts index 795bc05d..95ddd460 100644 --- a/src/codex/codexMcpClient.ts +++ b/src/codex/codexMcpClient.ts @@ -87,23 +87,43 @@ export class CodexMcpClient { const mcpCommand = getCodexMcpCommand(); logger.debug(`[CodexMCP] Connecting to Codex MCP server using command: codex ${mcpCommand}`); - this.transport = new StdioClientTransport({ - command: 'codex', - args: [mcpCommand], - env: Object.keys(process.env).reduce((acc, key) => { - const value = process.env[key]; - if (typeof value === 'string') acc[key] = value; - return acc; - }, {} as Record) - }); - - // Register request handlers for Codex permission methods - this.registerPermissionHandlers(); - - await this.client.connect(this.transport); - this.connected = true; + // WORKAROUND: Force windowsHide on Windows platforms + // The MCP SDK only sets windowsHide: true when running in Electron, + // but we need it for all Windows processes to prevent CMD windows from appearing. + // We temporarily set process.type which makes the SDK think we're in Electron. + // TODO: Submit PR to @modelcontextprotocol/sdk to always hide windows on Windows + const originalProcessType = (process as any).type; + const isWindows = process.platform === 'win32'; + if (isWindows && !originalProcessType) { + (process as any).type = 'node'; // Trick SDK into enabling windowsHide + logger.debug('[CodexMCP] Temporarily set process.type to enable windowsHide on Windows'); + } - logger.debug('[CodexMCP] Connected to Codex'); + try { + this.transport = new StdioClientTransport({ + command: 'codex', + args: [mcpCommand], + env: Object.keys(process.env).reduce((acc, key) => { + const value = process.env[key]; + if (typeof value === 'string') acc[key] = value; + return acc; + }, {} as Record) + }); + + // Register request handlers for Codex permission methods + this.registerPermissionHandlers(); + + await this.client.connect(this.transport); + this.connected = true; + + logger.debug('[CodexMCP] Connected to Codex'); + } finally { + // Restore original process.type + if (isWindows && !originalProcessType) { + delete (process as any).type; + logger.debug('[CodexMCP] Restored process.type'); + } + } } private registerPermissionHandlers(): void { From f8a1fc2a89bc2dacff4fd4984bff6fd3d9f57901 Mon Sep 17 00:00:00 2001 From: James White Date: Fri, 14 Nov 2025 19:38:42 +0000 Subject: [PATCH 02/35] fix: resolve WebSocket race condition causing missed first messages The ApiSessionClient was connecting to the WebSocket immediately in the constructor, before message handlers were registered. This created a race condition where messages could arrive before onUserMessage() callback was set, causing the first user message to be missed or delayed. Changes: - Removed auto-connect from constructor - Added ensureConnected() method that returns a Promise for connection - Updated onUserMessage() to await connection before returning - Made sendSessionEvent() async to ensure connection is established - Updated all callers of sendSessionEvent() to handle async calls This ensures: 1. Message callback is registered BEFORE WebSocket connects 2. Connection is established and verified before messages flow 3. pendingMessages queue is properly drained in correct order 4. 10-second timeout prevents infinite hangs on connection failures Fixes the primary cause of missed first messages in Codex agent integration. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/api/apiSession.ts | 59 ++++++++++++++++++++++++++++-- src/claude/claudeLocalLauncher.ts | 2 +- src/claude/claudeRemoteLauncher.ts | 8 ++-- src/claude/runClaude.ts | 2 +- src/codex/runCodex.ts | 20 ++++++---- 5 files changed, 73 insertions(+), 18 deletions(-) diff --git a/src/api/apiSession.ts b/src/api/apiSession.ts index aa4b88ae..5c4bed56 100644 --- a/src/api/apiSession.ts +++ b/src/api/apiSession.ts @@ -26,6 +26,8 @@ export class ApiSessionClient extends EventEmitter { private metadataLock = new AsyncLock(); private encryptionKey: Uint8Array; private encryptionVariant: 'legacy' | 'dataKey'; + private connectionPromise: Promise | null = null; + private connectionResolve: (() => void) | null = null; constructor(token: string, session: Session) { super() @@ -74,6 +76,11 @@ export class ApiSessionClient extends EventEmitter { this.socket.on('connect', () => { logger.debug('Socket connected successfully'); this.rpcHandlerManager.onSocketConnect(this.socket); + // Resolve the connection promise when socket connects + if (this.connectionResolve) { + this.connectionResolve(); + this.connectionResolve = null; + } }) // Set up global RPC request handler @@ -146,17 +153,59 @@ export class ApiSessionClient extends EventEmitter { }); // - // Connect (after short delay to give a time to add handlers) + // Don't auto-connect - wait for ensureConnected() to be called + // This prevents race conditions where messages arrive before handlers are registered // + } + + /** + * Ensure the socket is connected. Returns a promise that resolves when connected. + * Safe to call multiple times - subsequent calls return the same promise. + */ + async ensureConnected(): Promise { + if (this.socket.connected) { + return Promise.resolve(); + } + + if (this.connectionPromise) { + return this.connectionPromise; + } + + this.connectionPromise = new Promise((resolve, reject) => { + this.connectionResolve = resolve; - this.socket.connect(); + // Set timeout for connection + const timeout = setTimeout(() => { + this.connectionResolve = null; + this.connectionPromise = null; + reject(new Error('Socket connection timeout after 10s')); + }, 10000); + + // Clear timeout when connected + const originalResolve = this.connectionResolve; + this.connectionResolve = () => { + clearTimeout(timeout); + originalResolve?.(); + }; + + logger.debug('[API] Initiating socket connection...'); + this.socket.connect(); + }); + + return this.connectionPromise; } - onUserMessage(callback: (data: UserMessage) => void) { + async onUserMessage(callback: (data: UserMessage) => void) { + // Set callback first, before connecting this.pendingMessageCallback = callback; + + // Drain any messages that arrived during construction while (this.pendingMessages.length > 0) { callback(this.pendingMessages.shift()!); } + + // Now establish connection - messages will flow directly to callback + await this.ensureConnected(); } /** @@ -239,7 +288,7 @@ export class ApiSessionClient extends EventEmitter { }); } - sendSessionEvent(event: { + async sendSessionEvent(event: { type: 'switch', mode: 'local' | 'remote' } | { type: 'message', message: string @@ -248,6 +297,8 @@ export class ApiSessionClient extends EventEmitter { } | { type: 'ready' }, id?: string) { + await this.ensureConnected(); + let content = { role: 'agent', content: { diff --git a/src/claude/claudeLocalLauncher.ts b/src/claude/claudeLocalLauncher.ts index f2b1d958..882cd722 100644 --- a/src/claude/claudeLocalLauncher.ts +++ b/src/claude/claudeLocalLauncher.ts @@ -115,7 +115,7 @@ export async function claudeLocalLauncher(session: Session): Promise<'switch' | } catch (e) { logger.debug('[local]: launch error', e); if (!exitReason) { - session.client.sendSessionEvent({ type: 'message', message: 'Process exited unexpectedly' }); + session.client.sendSessionEvent({ type: 'message', message: 'Process exited unexpectedly' }).catch(err => logger.debug('[Claude] Failed to send exit event:', err)); continue; } else { break; diff --git a/src/claude/claudeRemoteLauncher.ts b/src/claude/claudeRemoteLauncher.ts index 735e4025..8044c234 100644 --- a/src/claude/claudeRemoteLauncher.ts +++ b/src/claude/claudeRemoteLauncher.ts @@ -373,7 +373,7 @@ export async function claudeRemoteLauncher(session: Session): Promise<'switch' | onMessage, onCompletionEvent: (message: string) => { logger.debug(`[remote]: Completion event: ${message}`); - session.client.sendSessionEvent({ type: 'message', message }); + session.client.sendSessionEvent({ type: 'message', message }).catch(err => logger.debug('[Claude] Failed to send completion event:', err)); }, onSessionReset: () => { logger.debug('[remote]: Session reset'); @@ -381,7 +381,7 @@ export async function claudeRemoteLauncher(session: Session): Promise<'switch' | }, onReady: () => { if (!pending && session.queue.size() === 0) { - session.client.sendSessionEvent({ type: 'ready' }); + session.client.sendSessionEvent({ type: 'ready' }).catch(err => logger.debug('[Claude] Failed to send ready event:', err)); session.api.push().sendToAllDevices( 'It\'s ready!', `Claude is waiting for your command`, @@ -396,12 +396,12 @@ export async function claudeRemoteLauncher(session: Session): Promise<'switch' | session.consumeOneTimeFlags(); if (!exitReason && abortController.signal.aborted) { - session.client.sendSessionEvent({ type: 'message', message: 'Aborted by user' }); + session.client.sendSessionEvent({ type: 'message', message: 'Aborted by user' }).catch(err => logger.debug('[Claude] Failed to send abort event:', err)); } } catch (e) { logger.debug('[remote]: launch error', e); if (!exitReason) { - session.client.sendSessionEvent({ type: 'message', message: 'Process exited unexpectedly' }); + session.client.sendSessionEvent({ type: 'message', message: 'Process exited unexpectedly' }).catch(err => logger.debug('[Claude] Failed to send exit event:', err)); continue; } } finally { diff --git a/src/claude/runClaude.ts b/src/claude/runClaude.ts index cd75cf7f..d7e9d547 100644 --- a/src/claude/runClaude.ts +++ b/src/claude/runClaude.ts @@ -352,7 +352,7 @@ export async function runClaude(credentials: Credentials, options: StartOptions api, allowedTools: happyServer.toolNames.map(toolName => `mcp__happy__${toolName}`), onModeChange: (newMode) => { - session.sendSessionEvent({ type: 'switch', mode: newMode }); + session.sendSessionEvent({ type: 'switch', mode: newMode }).catch(err => logger.debug('[Claude] Failed to send mode change event:', err)); session.updateAgentState((currentState) => ({ ...currentState, controlledByUser: newMode === 'local' diff --git a/src/codex/runCodex.ts b/src/codex/runCodex.ts index 62b4b5fd..86604b08 100644 --- a/src/codex/runCodex.ts +++ b/src/codex/runCodex.ts @@ -32,7 +32,7 @@ type ReadyEventOptions = { pending: unknown; queueSize: () => number; shouldExit: boolean; - sendReady: () => void; + sendReady: () => void | Promise; notify?: () => void; }; @@ -51,7 +51,11 @@ export function emitReadyIfIdle({ pending, queueSize, shouldExit, sendReady, not return false; } - sendReady(); + // sendReady might be async, handle both cases + const result = sendReady(); + if (result instanceof Promise) { + result.catch((err: Error) => logger.debug('[Codex] Failed to send ready event:', err)); + } notify?.(); return true; } @@ -184,8 +188,8 @@ export async function runCodex(opts: { session.keepAlive(thinking, 'remote'); }, 2000); - const sendReady = () => { - session.sendSessionEvent({ type: 'ready' }); + const sendReady = async () => { + await session.sendSessionEvent({ type: 'ready' }); try { api.push().sendToAllDevices( "It's ready!", @@ -413,10 +417,10 @@ export async function runCodex(opts: { messageBuffer.addMessage('Starting task...', 'status'); } else if (msg.type === 'task_complete') { messageBuffer.addMessage('Task completed', 'status'); - sendReady(); + sendReady().catch(err => logger.debug('[Codex] Failed to send ready event:', err)); } else if (msg.type === 'turn_aborted') { messageBuffer.addMessage('Turn aborted', 'status'); - sendReady(); + sendReady().catch(err => logger.debug('[Codex] Failed to send ready event:', err)); } if (msg.type === 'task_started') { @@ -689,7 +693,7 @@ export async function runCodex(opts: { if (isAbortError) { messageBuffer.addMessage('Aborted by user', 'status'); - session.sendSessionEvent({ type: 'message', message: 'Aborted by user' }); + session.sendSessionEvent({ type: 'message', message: 'Aborted by user' }).catch(err => logger.debug('[Codex] Failed to send abort event:', err)); // Session was already stored in handleAbort(), no need to store again // Mark session as not created to force proper resume on next message wasCreated = false; @@ -697,7 +701,7 @@ export async function runCodex(opts: { logger.debug('[Codex] Marked session as not created after abort for proper resume'); } else { messageBuffer.addMessage('Process exited unexpectedly', 'status'); - session.sendSessionEvent({ type: 'message', message: 'Process exited unexpectedly' }); + session.sendSessionEvent({ type: 'message', message: 'Process exited unexpectedly' }).catch(err => logger.debug('[Codex] Failed to send exit event:', err)); // For unexpected exits, try to store session for potential recovery if (client.hasActiveSession()) { storedSessionIdForResume = client.storeSessionForResume(); From 91a2801e9c1e5821f2d320ffbe3f1b8c07bd4dfd Mon Sep 17 00:00:00 2001 From: James White Date: Fri, 14 Nov 2025 19:39:59 +0000 Subject: [PATCH 03/35] docs: add comprehensive technical architecture documentation Created PROJECT.md with detailed technical overview of Happy CLI architecture, focusing on agent integration and communication flow. Contents: - System overview and component architecture - Detailed agent communication flow diagrams - Critical component documentation (apiSession, codexMcpClient, runCodex) - Analysis of 5 identified issues with status and fixes - Windows console window issue (fixed) - WebSocket race condition (fixed) - Agent disconnection/offline (pending) - Message queue timing (pending) - Missing timeouts (pending) - Code patterns, testing, and debugging tips This documentation is optimized for LLM consumption with concise, technical language and minimal prose to preserve context space. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- PROJECT.md | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 PROJECT.md diff --git a/PROJECT.md b/PROJECT.md new file mode 100644 index 00000000..9a97af94 --- /dev/null +++ b/PROJECT.md @@ -0,0 +1,281 @@ +# Happy CLI - Technical Architecture Documentation + +## System Overview + +Happy CLI is a command-line wrapper for Claude Code and OpenAI Codex CLI that enables remote control via mobile app and session sharing. It consists of three components: + +1. **handy-cli** (this project) - CLI wrapper +2. **handy** - React Native mobile client +3. **handy-server** - Node.js server at https://api.happy-servers.com/ + +## Agent Integration Architecture + +### Supported Agents + +- **Claude Code**: Integrated via `@anthropic-ai/claude-code` SDK +- **OpenAI Codex**: Integrated via Model Context Protocol (MCP) subprocess + +### Agent Communication Flow + +``` +Mobile App (user input) + ↓ WebSocket (encrypted) +Server + ↓ WebSocket 'update' event +ApiSessionClient + ↓ onUserMessage callback +MessageQueue + ↓ batch processing +Agent MCP Client (Claude/Codex) + ↓ MCP tool calls (startSession/continueSession) +Agent subprocess + ↓ MCP event notifications +Message handlers + ↓ sendCodexMessage/sendClaudeSessionMessage +Server + ↓ WebSocket broadcast +Mobile App +``` + +## Critical Components + +### /src/api/apiSession.ts - WebSocket Session Client + +**Purpose**: Manages WebSocket connection to server with end-to-end encryption + +**Key Features**: +- Lazy connection via `ensureConnected()` to prevent race conditions +- E2E encryption using TweetNaCl (NaCl crypto library) +- Optimistic concurrency control for metadata/state updates +- RPC handler registration for bidirectional communication +- Message queue buffering during initialization + +**Connection Lifecycle**: +1. Constructor creates socket with `autoConnect: false` +2. Registers event handlers for 'update', 'connect', 'disconnect' +3. `onUserMessage(callback)` sets callback and calls `ensureConnected()` +4. `ensureConnected()` initiates connection, returns Promise +5. Socket 'connect' event resolves promise +6. Messages flow directly to registered callback + +**Race Condition Prevention**: +- Old behavior: Socket connected immediately in constructor → messages arrived before callback set +- New behavior: Connection deferred until `onUserMessage()` called → callback registered BEFORE connect + +### /src/codex/codexMcpClient.ts - Codex MCP Integration + +**Purpose**: Wrapper for Codex CLI via Model Context Protocol (stdio transport) + +**Key Features**: +- Spawns Codex as subprocess using `StdioClientTransport` +- Bidirectional MCP communication over stdio +- Session ID extraction and tracking +- Permission request handling via `ElicitRequestSchema` +- Windows console window hiding workaround + +**Windows-Specific Issue**: +- MCP SDK only sets `windowsHide: true` when `isElectron()` returns true +- Workaround: Temporarily set `process.type` during transport creation +- Result: Prevents visible CMD windows on Windows platforms + +**Session Management**: +- `startSession(config)` - Creates new Codex session via 'codex' tool +- `continueSession(prompt)` - Continues existing session via 'codex-reply' tool +- `sessionId` and `conversationId` extracted from MCP responses +- Session persistence for resume functionality + +**Permission Flow**: +1. Codex requests permission via MCP `ElicitRequestSchema` +2. CodexMcpClient receives request in `setRequestHandler` +3. Delegates to `CodexPermissionHandler.handleToolCall()` +4. Handler sends RPC request to mobile app +5. Mobile app responds with approval/denial +6. Response returned to Codex via MCP + +### /src/codex/runCodex.ts - Codex Runtime Orchestrator + +**Purpose**: Main entry point for Codex agent mode, coordinates all Codex operations + +**Key Components**: +- `MessageQueue2`: Batches user messages with mode tracking (normal/direct/plan/edit) +- `MessageBuffer`: Accumulates Codex output for streaming to mobile +- `CodexMcpClient`: MCP communication with Codex subprocess +- `CodexPermissionHandler`: Handles tool approval requests via RPC +- `ApiSessionClient`: Server communication and encryption + +**Message Flow**: +1. `session.onUserMessage()` callback pushes to `messageQueue` +2. Main loop calls `messageQueue.waitForMessagesAndGetAsString()` +3. Batched messages sent to Codex via `client.startSession()` or `continueSession()` +4. Codex events flow through MCP to `client.setHandler()` +5. Handler processes events, updates `messageBuffer` +6. Buffer periodically flushed to server via `session.sendCodexMessage()` + +**Session State Management**: +- `wasCreated`: Tracks if session was successfully created +- `storedSessionIdForResume`: Preserved session ID for crash recovery +- `currentModeHash`: Detects mode changes requiring session restart +- Resume logic: On abort/error, stores session ID for next message continuation + +**Abort Handling**: +- AbortController signal passed to MCP tool calls +- On abort: Stores session ID, marks `wasCreated = false` +- Next message resumes from stored session instead of creating new one + +### /src/codex/utils/permissionHandler.ts - Permission RPC Handler + +**Purpose**: Bridges Codex permission requests to mobile app via RPC + +**Flow**: +1. `handleToolCall(callId, toolName, args)` called by CodexMcpClient +2. Creates pending request entry in Map +3. Sends RPC request via `rpcManager.sendRequest('tool-approval-request')` +4. Waits for RPC response callback +5. Returns `{ decision: 'approved' | 'denied' }` to Codex +6. Updates agent state with permission status + +**Issue**: No timeout on permission requests - will hang indefinitely if mobile doesn't respond + +### /src/api/encryption.ts - E2E Encryption + +**Purpose**: Encrypt all data before sending to server using TweetNaCl + +**Encryption Variants**: +- `legacy`: Uses session's encryption key directly (backward compatibility) +- `dataKey`: Derives per-message key from base key + nonce (more secure) + +**Key Operations**: +- `encrypt(key, variant, data)`: Encrypts JSON object → Uint8Array +- `decrypt(key, variant, encrypted)`: Decrypts Uint8Array → JSON object +- All messages encrypted before `socket.emit('message', ...)` +- All incoming messages decrypted in 'update' event handler + +## Identified Issues & Fixes + +### Issue #1: Windows Console Windows (FIXED) +**Cause**: MCP SDK only enables `windowsHide` when running in Electron +**Impact**: Visible CMD window appears for every Codex interaction on Windows +**Fix**: Temporarily set `process.type` to trick SDK into enabling windowsHide +**Location**: `/src/codex/codexMcpClient.ts:90-126` +**Status**: ✅ Committed (3ce58f6) + +### Issue #2: Missed First Messages (FIXED) +**Cause**: WebSocket connected before `onUserMessage()` callback registered +**Impact**: First user message lost in race condition +**Fix**: Defer connection until `onUserMessage()` called, await connection +**Location**: `/src/api/apiSession.ts:161-209` +**Status**: ✅ Committed (f8a1fc2) + +### Issue #3: Agent Disconnection/Offline +**Cause**: No subprocess health monitoring, no reconnection logic +**Impact**: Codex crashes silently, agent appears offline +**Fix Needed**: +- Add heartbeat mechanism to detect subprocess death +- Implement exponential backoff retry on MCP connection failure +- Monitor subprocess exit events, auto-restart +**Location**: `/src/codex/codexMcpClient.ts`, `/src/codex/runCodex.ts` +**Status**: ⏳ Pending + +### Issue #4: Message Queue Timing +**Cause**: 400+ lines between callback registration and processing loop start +**Impact**: Messages queued but not processed immediately +**Fix Needed**: +- Start message processing loop immediately after `onUserMessage()` +- Reduce initialization gap between callback and loop +**Location**: `/src/codex/runCodex.ts:148-565` +**Status**: ⏳ Pending + +### Issue #5: Missing Timeouts +**Cause**: No timeouts on MCP operations or permission requests +**Impact**: Operations hang indefinitely on failure +**Fix Needed**: +- Reduce MCP timeout from 14 days to reasonable value (e.g., 30s) +- Add timeout to permission handler RPC calls +- Add timeout to WebSocket operations +**Location**: Multiple files +**Status**: ⏳ Pending + +## Code Patterns + +### Error Handling +- Try-catch blocks with specific error logging +- AbortController for cancellable operations +- Exponential backoff for retryable operations (metadata/state updates) + +### Logging +- All debugging via file logs (`~/.happy-dev/logs/`) +- Prevents interference with agent terminal UI +- `logger.debug()` for standard logs +- `logger.debugLargeJson()` for objects (auto-truncates) + +### Type Safety +- Zod schemas for runtime validation (`UserMessageSchema`, etc.) +- Explicit TypeScript types throughout +- No `any` types except in MCP SDK interfaces + +### Async Patterns +- Promise-based async/await throughout +- Lock mechanisms for concurrent state updates (`AsyncLock`) +- Fire-and-forget for non-critical operations (notifications) + +## Testing + +### Test Structure +- Unit tests using Vitest +- Tests colocated with source (`.test.ts`) +- No mocking - tests make real API calls +- Test authentication flow, encryption, session management + +### Running Tests +```bash +npm test +``` + +## Build & Deployment + +### Build Process +```bash +npm run build +# Uses pkgroll to bundle TypeScript +# Output: dist/ directory +``` + +### Entry Points +- CLI: `bin/happy.mjs` +- Daemon: Spawns via `src/daemon/run.ts` +- Codex: `src/codex/runCodex.ts` +- Claude: `src/claude/runClaude.ts` + +## Future Improvements + +1. **Upstream MCP SDK Fix**: Submit PR to always hide windows on Windows +2. **Heartbeat Implementation**: Monitor agent subprocess health +3. **Retry Logic**: Exponential backoff for failed agent connections +4. **Timeout Configuration**: Configurable timeouts for all operations +5. **Connection Pooling**: Reuse WebSocket connections across sessions +6. **Structured Logging**: JSON-formatted logs for better parsing + +## Debug Tips + +### Enable Debug Logging +```bash +DEBUG=1 happy codex +``` + +### View Logs +```bash +tail -f ~/.happy-dev/logs/$(ls -t ~/.happy-dev/logs/ | head -1) +``` + +### Check Daemon Status +```bash +happy daemon status +``` + +### Kill Stuck Sessions +```bash +# Find process +ps aux | grep codex +# Kill by PID +kill -9 +``` From 62e70f1b90236d8d43ed4a5a44e5a12ba8f0cc0f Mon Sep 17 00:00:00 2001 From: James White Date: Fri, 14 Nov 2025 19:40:42 +0000 Subject: [PATCH 04/35] chore(deps): add package-lock.json and update yarn.lock Co-authored-by: terragon-labs[bot] --- package-lock.json | 8788 +++++++++++++++++++++++++++++++++++++++++++++ yarn.lock | 454 +-- 2 files changed, 8893 insertions(+), 349 deletions(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..1a5c2d64 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,8788 @@ +{ + "name": "happy-coder", + "version": "0.11.2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "happy-coder", + "version": "0.11.2", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@anthropic-ai/claude-code": "2.0.24", + "@anthropic-ai/sdk": "0.65.0", + "@modelcontextprotocol/sdk": "^1.15.1", + "@stablelib/base64": "^2.0.1", + "@stablelib/hex": "^2.0.1", + "@types/cross-spawn": "^6.0.6", + "@types/http-proxy": "^1.17.16", + "@types/ps-list": "^6.2.1", + "@types/qrcode-terminal": "^0.12.2", + "@types/react": "^19.1.9", + "@types/tmp": "^0.2.6", + "axios": "^1.10.0", + "chalk": "^5.4.1", + "cross-spawn": "^7.0.6", + "expo-server-sdk": "^3.15.0", + "fastify": "^5.5.0", + "fastify-type-provider-zod": "4.0.2", + "http-proxy": "^1.18.1", + "http-proxy-middleware": "^3.0.5", + "ink": "^6.1.0", + "open": "^10.2.0", + "ps-list": "^8.1.1", + "qrcode-terminal": "^0.12.0", + "react": "^19.1.1", + "socket.io-client": "^4.8.1", + "tar": "^7.4.3", + "tmp": "^0.2.5", + "tweetnacl": "^1.0.3", + "zod": "^3.23.8" + }, + "bin": { + "happy": "bin/happy.mjs", + "happy-mcp": "bin/happy-mcp.mjs" + }, + "devDependencies": { + "@eslint/compat": "^1", + "@types/node": ">=20", + "cross-env": "^10.0.0", + "dotenv": "^16.6.1", + "eslint": "^9", + "eslint-config-prettier": "^10", + "pkgroll": "^2.14.2", + "release-it": "^19.0.4", + "shx": "^0.3.3", + "ts-node": "^10", + "tsx": "^4.20.3", + "typescript": "^5", + "vitest": "^3.2.4" + } + }, + "node_modules/@alcalzone/ansi-tokenize": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@alcalzone/ansi-tokenize/-/ansi-tokenize-0.2.0.tgz", + "integrity": "sha512-qI/5TaaaCZE4yeSZ83lu0+xi1r88JSxUjnH4OP/iZF7+KKZ75u3ee5isd0LxX+6N8U0npL61YrpbthILHB6BnA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@anthropic-ai/claude-code": { + "version": "2.0.24", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.0.24.tgz", + "integrity": "sha512-6f/AXoTi3SmFYZl42l6L8brdPSkL+MDQWesRBJwgZy3enNI0LaVn1j/6RxQ7toPKnIyChCN0r6hZi61N8znzzQ==", + "license": "SEE LICENSE IN README.md", + "bin": { + "claude": "cli.js" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "^0.33.5", + "@img/sharp-darwin-x64": "^0.33.5", + "@img/sharp-linux-arm": "^0.33.5", + "@img/sharp-linux-arm64": "^0.33.5", + "@img/sharp-linux-x64": "^0.33.5", + "@img/sharp-win32-x64": "^0.33.5" + } + }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.65.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.65.0.tgz", + "integrity": "sha512-zIdPOcrCVEI8t3Di40nH4z9EoeyGZfXbYSvWdDLsB/KkaSYMnEgC7gmcgWu83g2NTn1ZTpbMvpdttWDGGIk6zw==", + "license": "MIT", + "dependencies": { + "json-schema-to-ts": "^3.1.1" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@epic-web/invariant": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", + "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.3.2.tgz", + "integrity": "sha512-jRNwzTbd6p2Rw4sZ1CgWRS8YMtqG15YyZf7zvb6gY2rB2u6n+2Z+ELW0GtL0fQgyl0pr4Y/BzBfng/BdsereRA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^8.40 || 9" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", + "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@fastify/ajv-compiler": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-4.0.2.tgz", + "integrity": "sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "fast-uri": "^3.0.0" + } + }, + "node_modules/@fastify/ajv-compiler/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@fastify/ajv-compiler/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/@fastify/error": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.2.0.tgz", + "integrity": "sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@fastify/fast-json-stringify-compiler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.0.3.tgz", + "integrity": "sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "fast-json-stringify": "^6.0.0" + } + }, + "node_modules/@fastify/forwarded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.0.tgz", + "integrity": "sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==", + "license": "MIT" + }, + "node_modules/@fastify/merge-json-schemas": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz", + "integrity": "sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@fastify/proxy-addr": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz", + "integrity": "sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==", + "license": "MIT", + "dependencies": { + "@fastify/forwarded": "^3.0.0", + "ipaddr.js": "^2.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.2.1.tgz", + "integrity": "sha512-bevKGO6kX1eM/N+pdh9leS5L7TBF4ICrzi9a+cbWkrxeAeIcwlo/7OfWGCDERdRCI2/Q6tjltX4bt07ALHDwFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/checkbox/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@inquirer/checkbox/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.15.tgz", + "integrity": "sha512-SwHMGa8Z47LawQN0rog0sT+6JpiL0B7eW9p1Bb7iCeKDGTI5Ez25TSc2l8kw52VV7hA4sX/C78CGkMrKXfuspA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.1.15", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.15.tgz", + "integrity": "sha512-8xrp836RZvKkpNbVvgWUlxjT4CraKk2q+I3Ksy+seI2zkcE+y6wNs1BVhgcv8VyImFecUhdQrYLdW32pAjwBdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@inquirer/core/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/editor": { + "version": "4.2.17", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.17.tgz", + "integrity": "sha512-r6bQLsyPSzbWrZZ9ufoWL+CztkSatnJ6uSxqd6N+o41EZC51sQeWOzI6s5jLb+xxTWxl7PlUppqm8/sow241gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/external-editor": "^1.0.1", + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.17.tgz", + "integrity": "sha512-PSqy9VmJx/VbE3CT453yOfNa+PykpKg/0SYP7odez1/NWBGuDXgPhp4AeGYYKjhLn5lUUavVS/JbeYMPdH50Mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.1.tgz", + "integrity": "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^2.1.0", + "iconv-lite": "^0.6.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.13.tgz", + "integrity": "sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.1.tgz", + "integrity": "sha512-tVC+O1rBl0lJpoUZv4xY+WGWY8V5b0zxU1XDsMsIHYregdh7bN5X5QnIONNBAl0K765FYlAfNHS2Bhn7SSOVow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.17.tgz", + "integrity": "sha512-GcvGHkyIgfZgVnnimURdOueMk0CztycfC8NZTiIY9arIAkeOgt6zG57G+7vC59Jns3UX27LMkPKnKWAOF5xEYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.17.tgz", + "integrity": "sha512-DJolTnNeZ00E1+1TW+8614F7rOJJCM4y4BAGQ3Gq6kQIG+OJ4zr3GLjIjVVJCbKsk2jmkmv6v2kQuN/vriHdZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@inquirer/password/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.8.3.tgz", + "integrity": "sha512-iHYp+JCaCRktM/ESZdpHI51yqsDgXu+dMs4semzETftOaF8u5hwlqnbIsuIR/LrWZl8Pm1/gzteK9I7MAq5HTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.2.1", + "@inquirer/confirm": "^5.1.15", + "@inquirer/editor": "^4.2.17", + "@inquirer/expand": "^4.0.17", + "@inquirer/input": "^4.2.1", + "@inquirer/number": "^3.0.17", + "@inquirer/password": "^4.0.17", + "@inquirer/rawlist": "^4.1.5", + "@inquirer/search": "^3.1.0", + "@inquirer/select": "^4.3.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.5.tgz", + "integrity": "sha512-R5qMyGJqtDdi4Ht521iAkNqyB6p2UPuZUbMifakg1sWtu24gc2Z8CJuw8rP081OckNDMgtDCuLe42Q2Kr3BolA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.1.0.tgz", + "integrity": "sha512-PMk1+O/WBcYJDq2H7foV0aAZSmDdkzZB9Mw2v/DmONRJopwA/128cS9M/TXWLKKdEQKZnKwBzqu2G4x/2Nqx8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.3.1.tgz", + "integrity": "sha512-Gfl/5sqOF5vS/LIrSndFgOh7jgoe0UXEizDqahFRkq5aJBLegZ6WjuMh/hVEJwlFQjyLq1z9fRtvUMkb7jM1LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@inquirer/select/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.8.tgz", + "integrity": "sha512-lg9Whz8onIHRthWaN1Q9EGLa/0LFJjyM8mEUbL1eTi6yMGvBf8gvyDLtxSXztQsxMvhxxNpJYrwa1YHdq+w4Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.17.3.tgz", + "integrity": "sha512-JPwUKWSsbzx+DLFznf/QZ32Qa+ptfbUlHhRLrBQBAFu9iI1iYvizM4p+zhhRDceSsPutXp4z+R/HPVphlIiclg==", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.6", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodeutils/defaults-deep": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@nodeutils/defaults-deep/-/defaults-deep-1.1.0.tgz", + "integrity": "sha512-gG44cwQovaOFdSR02jR9IhVRpnDP64VN6JdjYJTfNz4J4fWn7TQnmrf22nSjRqlwlxPcW8PL/L3KbJg3tdwvpg==", + "dev": true, + "license": "ISC", + "dependencies": { + "lodash": "^4.15.0" + } + }, + "node_modules/@octokit/auth-token": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.6.tgz", + "integrity": "sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.2.2", + "@octokit/request": "^9.2.3", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz", + "integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz", + "integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", + "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz", + "integrity": "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.10.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.5.0.tgz", + "integrity": "sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.10.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/request": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.4.tgz", + "integrity": "sha512-q8ybdytBmxa6KogWlNa818r0k1wlqzNC+yNkcQDECHvQo8Vmstrg18JwqJHdJdUiHD2sjlwBgSm9kHkOKe2iyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^10.1.4", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", + "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz", + "integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/core": "^6.1.4", + "@octokit/plugin-paginate-rest": "^11.4.2", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.3.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", + "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^25.1.0" + } + }, + "node_modules/@phun-ky/typeof": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@phun-ky/typeof/-/typeof-1.2.8.tgz", + "integrity": "sha512-7J6ca1tK0duM2BgVB+CuFMh3idlIVASOP2QvOCbNWDc6JnvjtKa9nufPoJQQ4xrwBonwgT1TIhRRcEtzdVgWsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.9.0 || >=22.0.0", + "npm": ">=10.8.2" + }, + "funding": { + "url": "https://github.com/phun-ky/typeof?sponsor=1" + } + }, + "node_modules/@rollup/plugin-alias": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-5.1.1.tgz", + "integrity": "sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "28.0.6", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz", + "integrity": "sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.2.0", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0 || 14 >= 14.17" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/plugin-dynamic-import-vars": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@rollup/plugin-dynamic-import-vars/-/plugin-dynamic-import-vars-2.1.5.tgz", + "integrity": "sha512-Mymi24fd9hlRifdZV/jYIFj1dn99F34imiYu3KzlAcgBcRi3i9SucgW/VRo5SQ9K4NuQ7dCep6pFWgNyhRdFHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "astring": "^1.8.5", + "estree-walker": "^2.0.2", + "fast-glob": "^3.2.12", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-inject": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz", + "integrity": "sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-json": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz", + "integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", + "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.3.tgz", + "integrity": "sha512-UmTdvXnLlqQNOCJnyksjPs1G4GqXNGW1LrzCe8+8QoaLhhDeTXYBgJ3k6x61WIhlHX2U+VzEJ55TtIjR/HTySA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.3.tgz", + "integrity": "sha512-8NoxqLpXm7VyeI0ocidh335D6OKT0UJ6fHdnIxf3+6oOerZZc+O7r+UhvROji6OspyPm+rrIdb1gTXtVIqn+Sg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.3.tgz", + "integrity": "sha512-csnNavqZVs1+7/hUKtgjMECsNG2cdB8F7XBHP6FfQjqhjF8rzMzb3SLyy/1BG7YSfQ+bG75Ph7DyedbUqwq1rA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.3.tgz", + "integrity": "sha512-r2MXNjbuYabSIX5yQqnT8SGSQ26XQc8fmp6UhlYJd95PZJkQD1u82fWP7HqvGUf33IsOC6qsiV+vcuD4SDP6iw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.3.tgz", + "integrity": "sha512-uluObTmgPJDuJh9xqxyr7MV61Imq+0IvVsAlWyvxAaBSNzCcmZlhfYcRhCdMaCsy46ccZa7vtDDripgs9Jkqsw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.3.tgz", + "integrity": "sha512-AVJXEq9RVHQnejdbFvh1eWEoobohUYN3nqJIPI4mNTMpsyYN01VvcAClxflyk2HIxvLpRcRggpX1m9hkXkpC/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.3.tgz", + "integrity": "sha512-byyflM+huiwHlKi7VHLAYTKr67X199+V+mt1iRgJenAI594vcmGGddWlu6eHujmcdl6TqSNnvqaXJqZdnEWRGA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.3.tgz", + "integrity": "sha512-aLm3NMIjr4Y9LklrH5cu7yybBqoVCdr4Nvnm8WB7PKCn34fMCGypVNpGK0JQWdPAzR/FnoEoFtlRqZbBBLhVoQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.3.tgz", + "integrity": "sha512-VtilE6eznJRDIoFOzaagQodUksTEfLIsvXymS+UdJiSXrPW7Ai+WG4uapAc3F7Hgs791TwdGh4xyOzbuzIZrnw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.3.tgz", + "integrity": "sha512-dG3JuS6+cRAL0GQ925Vppafi0qwZnkHdPeuZIxIPXqkCLP02l7ka+OCyBoDEv8S+nKHxfjvjW4OZ7hTdHkx8/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.3.tgz", + "integrity": "sha512-iU8DxnxEKJptf8Vcx4XvAUdpkZfaz0KWfRrnIRrOndL0SvzEte+MTM7nDH4A2Now4FvTZ01yFAgj6TX/mZl8hQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.3.tgz", + "integrity": "sha512-VrQZp9tkk0yozJoQvQcqlWiqaPnLM6uY1qPYXvukKePb0fqaiQtOdMJSxNFUZFsGw5oA5vvVokjHrx8a9Qsz2A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.3.tgz", + "integrity": "sha512-uf2eucWSUb+M7b0poZ/08LsbcRgaDYL8NCGjUeFMwCWFwOuFcZ8D9ayPl25P3pl+D2FH45EbHdfyUesQ2Lt9wA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.3.tgz", + "integrity": "sha512-7tnUcDvN8DHm/9ra+/nF7lLzYHDeODKKKrh6JmZejbh1FnCNZS8zMkZY5J4sEipy2OW1d1Ncc4gNHUd0DLqkSg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.3.tgz", + "integrity": "sha512-MUpAOallJim8CsJK+4Lc9tQzlfPbHxWDrGXZm2z6biaadNpvh3a5ewcdat478W+tXDoUiHwErX/dOql7ETcLqg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.3.tgz", + "integrity": "sha512-F42IgZI4JicE2vM2PWCe0N5mR5vR0gIdORPqhGQ32/u1S1v3kLtbZ0C/mi9FFk7C5T0PgdeyWEPajPjaUpyoKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.3.tgz", + "integrity": "sha512-oLc+JrwwvbimJUInzx56Q3ujL3Kkhxehg7O1gWAYzm8hImCd5ld1F2Gry5YDjR21MNb5WCKhC9hXgU7rRlyegQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.3.tgz", + "integrity": "sha512-lOrQ+BVRstruD1fkWg9yjmumhowR0oLAAzavB7yFSaGltY8klttmZtCLvOXCmGE9mLIn8IBV/IFrQOWz5xbFPg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.3.tgz", + "integrity": "sha512-vvrVKPRS4GduGR7VMH8EylCBqsDcw6U+/0nPDuIjXQRbHJc6xOBj+frx8ksfZAh6+Fptw5wHrN7etlMmQnPQVg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.3.tgz", + "integrity": "sha512-fi3cPxCnu3ZeM3EwKZPgXbWoGzm2XHgB/WShKI81uj8wG0+laobmqy5wbgEwzstlbLu4MyO8C19FyhhWseYKNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@stablelib/base64": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-2.0.1.tgz", + "integrity": "sha512-P2z89A7N1ETt6RxgpVdDT2xlg8cnm3n6td0lY9gyK7EiWK3wdq388yFX/hLknkCC0we05OZAD1rfxlQJUbl5VQ==", + "license": "MIT" + }, + "node_modules/@stablelib/hex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hex/-/hex-2.0.1.tgz", + "integrity": "sha512-nsAgs3109myeijRQg3HASq3vlxe/8uDKHEUuIwn9ZLxfWtXavgojAGLBjI7Sda6seOhy7rKrpmeehYo0Z5VGQA==", + "license": "MIT" + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*" + } + }, + "node_modules/@types/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.16", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz", + "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", + "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/parse-path": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/parse-path/-/parse-path-7.0.3.tgz", + "integrity": "sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ps-list": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@types/ps-list/-/ps-list-6.2.1.tgz", + "integrity": "sha512-YGrVUmLaAu89QffaehCcCp5kphlbCf72+vDxnRyP1soC9y7xaatnoB0Fgo/tEGHk8teglcLwY6b4iHcyd/UWFA==", + "deprecated": "This is a stub types definition. ps-list provides its own type definitions, so you do not need this installed.", + "license": "MIT", + "dependencies": { + "ps-list": "*" + } + }, + "node_modules/@types/qrcode-terminal": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/qrcode-terminal/-/qrcode-terminal-0.12.2.tgz", + "integrity": "sha512-v+RcIEJ+Uhd6ygSQ0u5YYY7ZM+la7GgPbs0V/7l/kFs2uO4S8BcIUEMoP7za4DNIqNnUD5npf0A/7kBhrCKG5Q==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.1.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.10.tgz", + "integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/tmp": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz", + "integrity": "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==", + "license": "MIT" + }, + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/abstract-logging": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", + "license": "MIT" + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "dev": true, + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/async-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/auto-bind": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-5.0.1.tgz", + "integrity": "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/avvio": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-9.1.0.tgz", + "integrity": "sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==", + "license": "MIT", + "dependencies": { + "@fastify/error": "^4.0.0", + "fastq": "^1.17.1" + } + }, + "node_modules/axios": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chai": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.1.tgz", + "integrity": "sha512-48af6xm9gQK8rhIcOxWwdGzIervm8BVTin+yRp9HEvU20BtVZ2lBywlIJBzwaDtvo0FvjeL7QdCADoUoqIbV3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz", + "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", + "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/code-excerpt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", + "license": "MIT", + "dependencies": { + "convert-to-spaces": "^2.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-to-spaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-env": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.0.0.tgz", + "integrity": "sha512-aU8qlEK/nHYtVuN4p7UQgAwVljzMg8hB4YK5ThRqD2l/ziSnryncPNn7bMLt5cFYsKVKBh8HqLqyCoTupEUu7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@epic-web/invariant": "^1.0.0", + "cross-spawn": "^7.0.6" + }, + "bin": { + "cross-env": "dist/bin/cross-env.js", + "cross-env-shell": "dist/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true, + "license": "MIT" + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "dev": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-toolkit": { + "version": "1.39.10", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.10.tgz", + "integrity": "sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/eslint": { + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", + "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.33.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eta": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-3.5.0.tgz", + "integrity": "sha512-e3x3FBvGzeCIHhF+zhK8FZA2vC5uFn6b4HJjegUbIWrDb4mJ7JjTGMJY9VGIbRVpmSwHopNiaJibhjIr+HfLug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.5.tgz", + "integrity": "sha512-bSRG85ZrMdmWtm7qkF9He9TNRzc/Bm99gEJMaQoHJ9E6Kv9QBbsldh2oMj7iXmYNEAVvNgvv5vPorG6W+XtBhQ==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/expo-server-sdk": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/expo-server-sdk/-/expo-server-sdk-3.15.0.tgz", + "integrity": "sha512-Y71mQ7yeDhq6miHzn4kwRQOjqvBBsWeFXvyS9PYc6uqO/+UiYvrw3vMQiQqRxg2y0qgn9jMsvjf8T+mukSH85A==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.0", + "promise-limit": "^2.7.0", + "promise-retry": "^2.0.1" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-json-stringify": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-6.0.1.tgz", + "integrity": "sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/merge-json-schemas": "^0.2.0", + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "fast-uri": "^3.0.0", + "json-schema-ref-resolver": "^2.0.0", + "rfdc": "^1.2.0" + } + }, + "node_modules/fast-json-stringify/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fast-json-stringify/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-querystring": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "license": "MIT", + "dependencies": { + "fast-decode-uri-component": "^1.0.1" + } + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastify": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.5.0.tgz", + "integrity": "sha512-ZWSWlzj3K/DcULCnCjEiC2zn2FBPdlZsSA/pnPa/dbUfLvxkD/Nqmb0XXMXLrWkeM4uQPUvjdJpwtXmTfriXqw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/ajv-compiler": "^4.0.0", + "@fastify/error": "^4.0.0", + "@fastify/fast-json-stringify-compiler": "^5.0.0", + "@fastify/proxy-addr": "^5.0.0", + "abstract-logging": "^2.0.1", + "avvio": "^9.0.0", + "fast-json-stringify": "^6.0.0", + "find-my-way": "^9.0.0", + "light-my-request": "^6.0.0", + "pino": "^9.0.0", + "process-warning": "^5.0.0", + "rfdc": "^1.3.1", + "secure-json-parse": "^4.0.0", + "semver": "^7.6.0", + "toad-cache": "^3.7.0" + } + }, + "node_modules/fastify-type-provider-zod": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fastify-type-provider-zod/-/fastify-type-provider-zod-4.0.2.tgz", + "integrity": "sha512-FDRzSL3ZuoZ+4YDevR1YOinmDKkxOdy3QB9dDR845sK+bQvDroPKhHAXLEAOObDxL7SMA0OZN/A4osrNBTdDTQ==", + "license": "MIT", + "dependencies": { + "@fastify/error": "^4.0.0", + "zod-to-json-schema": "^3.23.3" + }, + "peerDependencies": { + "fastify": "^5.0.0", + "zod": "^3.14.2" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-my-way": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.3.0.tgz", + "integrity": "sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-querystring": "^1.0.0", + "safe-regex2": "^5.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/get-uri": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/git-up": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-8.1.1.tgz", + "integrity": "sha512-FDenSF3fVqBYSaJoYy1KSc2wosx0gCvKP+c+PRBht7cAaiCeQlBtfBDX9vgnNOHmdePlSFITVcn4pFfcgNvx3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-ssh": "^1.4.0", + "parse-url": "^9.2.0" + } + }, + "node_modules/git-url-parse": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-16.1.0.tgz", + "integrity": "sha512-cPLz4HuK86wClEW7iDdeAKcCVlWXmrLpb2L+G9goW0Z1dtpNS6BXXSOckUTlJT/LDQViE1QZKstNORzHsLnobw==", + "dev": true, + "license": "MIT", + "dependencies": { + "git-up": "^8.1.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-middleware": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.5.tgz", + "integrity": "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==", + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.15", + "debug": "^4.3.6", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.3", + "is-plain-object": "^5.0.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ink": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ink/-/ink-6.2.1.tgz", + "integrity": "sha512-ZF3V9bHcWqqSrMClU9FRIBLQel1mc7H6zKSTt/MSCh2uks4T3xKq4qb9Z+aC7dOPGU4Ahy/Mw1hvUCl77F4EPg==", + "license": "MIT", + "dependencies": { + "@alcalzone/ansi-tokenize": "^0.2.0", + "ansi-escapes": "^7.0.0", + "ansi-styles": "^6.2.1", + "auto-bind": "^5.0.1", + "chalk": "^5.6.0", + "cli-boxes": "^3.0.0", + "cli-cursor": "^4.0.0", + "cli-truncate": "^4.0.0", + "code-excerpt": "^4.0.0", + "es-toolkit": "^1.39.10", + "indent-string": "^5.0.0", + "is-in-ci": "^2.0.0", + "patch-console": "^2.0.0", + "react-reconciler": "^0.32.0", + "scheduler": "^0.26.0", + "signal-exit": "^3.0.7", + "slice-ansi": "^7.1.0", + "stack-utils": "^2.0.6", + "string-width": "^7.2.0", + "type-fest": "^4.27.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0", + "ws": "^8.18.0", + "yoga-layout": "~3.2.1" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@types/react": ">=19.0.0", + "react": ">=19.0.0", + "react-devtools-core": "^4.19.1" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react-devtools-core": { + "optional": true + } + } + }, + "node_modules/inquirer": { + "version": "12.7.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.7.0.tgz", + "integrity": "sha512-KKFRc++IONSyE2UYw9CJ1V0IWx5yQKomwB+pp3cWomWs+v2+ZsG11G2OVfAjFS6WWCppKw+RfKmpqGfSzD5QBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.14", + "@inquirer/prompts": "^7.6.0", + "@inquirer/type": "^3.0.7", + "ansi-escapes": "^4.3.2", + "mute-stream": "^2.0.0", + "run-async": "^4.0.4", + "rxjs": "^7.8.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/inquirer/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-address": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-in-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-2.0.0.tgz", + "integrity": "sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w==", + "license": "MIT", + "bin": { + "is-in-ci": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/is-ssh": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.1.tgz", + "integrity": "sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "protocols": "^2.0.1" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/issue-parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-7.0.1.tgz", + "integrity": "sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.capitalize": "^4.2.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.uniqby": "^4.7.0" + }, + "engines": { + "node": "^18.17 || >=20.6.1" + } + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-ref-resolver": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-2.0.1.tgz", + "integrity": "sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/light-my-request": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.6.0.tgz", + "integrity": "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", + "dependencies": { + "cookie": "^1.0.1", + "process-warning": "^4.0.0", + "set-cookie-parser": "^2.6.0" + } + }, + "node_modules/light-my-request/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/light-my-request/node_modules/process-warning": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", + "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.capitalize": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/loupe": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.0.tgz", + "integrity": "sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/macos-release": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.4.0.tgz", + "integrity": "sha512-wpGPwyg/xrSp4H4Db4xYSeAr6+cFQGHfspHzDUdYxswDnUW0L5Ov63UuJiSr8NMSpyaChO4u1n0MXUvVPtrN6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/new-github-release-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", + "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^2.5.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/new-github-release-url/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", + "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.2.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/os-name": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-6.1.0.tgz", + "integrity": "sha512-zBd1G8HkewNd2A8oQ8c6BN/f/c9EId7rSUueOLGu28govmUctXmM+3765GwsByv9nYUdrLqHphXlYIc86saYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "macos-release": "^3.3.0", + "windows-release": "^6.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "dev": true, + "license": "MIT", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-path": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.3.tgz", + "integrity": "sha512-0R71msgRgmkcZ5CWnzS+GPXJ1Fc+lbKyPDuA83Ej0QKCpf/Feieh813bF38My3CTNBzcQhtRRqvXNpCFF6FRMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "protocols": "^2.0.0" + } + }, + "node_modules/parse-url": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-9.2.0.tgz", + "integrity": "sha512-bCgsFI+GeGWPAvAiUv63ZorMeif3/U0zaXABGJbOWt5OH2KCaPHF6S+0ok4aqM9RuIPGyZdx9tR9l13PsW4AYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-path": "^7.0.0", + "parse-path": "^7.0.0" + }, + "engines": { + "node": ">=14.13.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/patch-console": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/patch-console/-/patch-console-2.0.0.tgz", + "integrity": "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pino": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.9.0.tgz", + "integrity": "sha512-zxsRIQG9HzG+jEljmvmZupOMDUQ0Jpj0yAgE28jQvvrdYTlEaiGwelJpdndMl/MBuRr70heIj83QyqJUWaU8mQ==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "license": "MIT" + }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/pkgroll": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/pkgroll/-/pkgroll-2.15.3.tgz", + "integrity": "sha512-yEuitslh2Y2ZhH3eX61Y5gTCqxC9KDcQ4gmsjQWwtlk5R3/n8rlkPaxZFT7e4QybeAOonnlm8xlIM5HUk7Ok9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/plugin-alias": "^5.1.1", + "@rollup/plugin-commonjs": "^28.0.6", + "@rollup/plugin-dynamic-import-vars": "^2.1.5", + "@rollup/plugin-inject": "^5.0.5", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^16.0.1", + "@rollup/pluginutils": "^5.2.0", + "cjs-module-lexer": "^2.1.0", + "esbuild": "^0.25.8", + "magic-string": "^0.30.17", + "rollup": "^4.46.2", + "rollup-pluginutils": "^2.8.2" + }, + "bin": { + "pkgroll": "dist/cli.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/privatenumber/pkgroll?sponsor=1" + }, + "peerDependencies": { + "typescript": "^4.1 || ^5.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/promise-limit": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/promise-limit/-/promise-limit-2.7.0.tgz", + "integrity": "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==", + "license": "ISC" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protocols": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.2.tgz", + "integrity": "sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/ps-list": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/ps-list/-/ps-list-8.1.1.tgz", + "integrity": "sha512-OPS9kEJYVmiO48u/B9qneqhkMvgCxT+Tm28VCEJpheTpl8cJ0ffZRRNgS5mrQRTrX5yRTpaJ+hRDeefXYmmorQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qrcode-terminal": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", + "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "node_modules/react": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", + "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-reconciler": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.32.0.tgz", + "integrity": "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/release-it": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-19.0.4.tgz", + "integrity": "sha512-W9A26FW+l1wy5fDg9BeAknZ19wV+UvHUDOC4D355yIOZF/nHBOIhjDwutKd4pikkjvL7CpKeF+4zLxVP9kmVEw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/webpro" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/webpro" + } + ], + "license": "MIT", + "dependencies": { + "@nodeutils/defaults-deep": "1.1.0", + "@octokit/rest": "21.1.1", + "@phun-ky/typeof": "1.2.8", + "async-retry": "1.3.3", + "c12": "3.1.0", + "ci-info": "^4.3.0", + "eta": "3.5.0", + "git-url-parse": "16.1.0", + "inquirer": "12.7.0", + "issue-parser": "7.0.1", + "lodash.merge": "4.6.2", + "mime-types": "3.0.1", + "new-github-release-url": "2.0.0", + "open": "10.2.0", + "ora": "8.2.0", + "os-name": "6.1.0", + "proxy-agent": "6.5.0", + "semver": "7.7.2", + "tinyglobby": "0.2.14", + "undici": "6.21.3", + "url-join": "5.0.0", + "wildcard-match": "5.1.4", + "yargs-parser": "21.1.1" + }, + "bin": { + "release-it": "bin/release-it.js" + }, + "engines": { + "node": "^20.12.0 || >=22.0.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ret": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.5.0.tgz", + "integrity": "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.46.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.3.tgz", + "integrity": "sha512-RZn2XTjXb8t5g13f5YclGoilU/kwT696DIkY3sywjdZidNSi3+vseaQov7D7BZXVJCPv3pDWUN69C78GGbXsKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.46.3", + "@rollup/rollup-android-arm64": "4.46.3", + "@rollup/rollup-darwin-arm64": "4.46.3", + "@rollup/rollup-darwin-x64": "4.46.3", + "@rollup/rollup-freebsd-arm64": "4.46.3", + "@rollup/rollup-freebsd-x64": "4.46.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.46.3", + "@rollup/rollup-linux-arm-musleabihf": "4.46.3", + "@rollup/rollup-linux-arm64-gnu": "4.46.3", + "@rollup/rollup-linux-arm64-musl": "4.46.3", + "@rollup/rollup-linux-loongarch64-gnu": "4.46.3", + "@rollup/rollup-linux-ppc64-gnu": "4.46.3", + "@rollup/rollup-linux-riscv64-gnu": "4.46.3", + "@rollup/rollup-linux-riscv64-musl": "4.46.3", + "@rollup/rollup-linux-s390x-gnu": "4.46.3", + "@rollup/rollup-linux-x64-gnu": "4.46.3", + "@rollup/rollup-linux-x64-musl": "4.46.3", + "@rollup/rollup-win32-arm64-msvc": "4.46.3", + "@rollup/rollup-win32-ia32-msvc": "4.46.3", + "@rollup/rollup-win32-x64-msvc": "4.46.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/rollup-pluginutils/node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-async": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-4.0.6.tgz", + "integrity": "sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex2": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.0.0.tgz", + "integrity": "sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "ret": "~0.5.0" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/secure-json-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.0.0.tgz", + "integrity": "sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/shx": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz", + "integrity": "sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.3", + "shelljs": "^0.8.5" + }, + "bin": { + "shx": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "dev": true, + "license": "MIT" + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.3.tgz", + "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toad-cache": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", + "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "license": "MIT" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.20.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.4.tgz", + "integrity": "sha512-yyxBKfORQ7LuRt/BQKBXrpcq59ZvSW0XxwfjAt3w2/8PmdxaFzijtMhTawprSHhpzeM5BgU2hXHG3lklIERZXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "license": "Unlicense" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", + "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "license": "MIT" + }, + "node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.3.tgz", + "integrity": "sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.14" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest/node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "license": "MIT", + "dependencies": { + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wildcard-match": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/wildcard-match/-/wildcard-match-5.1.4.tgz", + "integrity": "sha512-wldeCaczs8XXq7hj+5d/F38JE2r7EXgb6WQDM84RVwxy81T/sxB5e9+uZLK9Q9oNz1mlvjut+QtvgaOQFPVq/g==", + "dev": true, + "license": "ISC" + }, + "node_modules/windows-release": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-6.1.0.tgz", + "integrity": "sha512-1lOb3qdzw6OFmOzoY0nauhLG72TpWtb5qgYPiSh/62rjc1XidBSDio2qw0pwHh17VINF217ebIkZJdFLZFn9SA==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^8.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoga-layout": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz", + "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==", + "license": "MIT" + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } + } + } +} diff --git a/yarn.lock b/yarn.lock index fe4d3171..396b81f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,10 +10,10 @@ ansi-styles "^6.2.1" is-fullwidth-code-point "^5.0.0" -"@anthropic-ai/claude-code@2.0.14": - version "2.0.14" - resolved "https://registry.yarnpkg.com/@anthropic-ai/claude-code/-/claude-code-2.0.14.tgz#c4b9d06bb34c4478fd835afb5f58ea384a54db06" - integrity sha512-Q4A4Jo7WZ4aMUIu8CUIIo2Jt66kl2vrEjRg/kYzX6syuK0DiV3WhdMZceSvLAU0BFpX1L8aERhRWxLWDxX3fYg== +"@anthropic-ai/claude-code@2.0.24": + version "2.0.24" + resolved "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.0.24.tgz" + integrity sha512-6f/AXoTi3SmFYZl42l6L8brdPSkL+MDQWesRBJwgZy3enNI0LaVn1j/6RxQ7toPKnIyChCN0r6hZi61N8znzzQ== optionalDependencies: "@img/sharp-darwin-arm64" "^0.33.5" "@img/sharp-darwin-x64" "^0.33.5" @@ -46,136 +46,11 @@ resolved "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz" integrity sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA== -"@esbuild/aix-ppc64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz#bef96351f16520055c947aba28802eede3c9e9a9" - integrity sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA== - -"@esbuild/android-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz#d2e70be7d51a529425422091e0dcb90374c1546c" - integrity sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg== - -"@esbuild/android-arm@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.9.tgz#d2a753fe2a4c73b79437d0ba1480e2d760097419" - integrity sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ== - -"@esbuild/android-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.9.tgz#5278836e3c7ae75761626962f902a0d55352e683" - integrity sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw== - -"@esbuild/darwin-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz" - integrity sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg== - -"@esbuild/darwin-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz#e27dbc3b507b3a1cea3b9280a04b8b6b725f82be" - integrity sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ== - -"@esbuild/freebsd-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz#364e3e5b7a1fd45d92be08c6cc5d890ca75908ca" - integrity sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q== - -"@esbuild/freebsd-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz#7c869b45faeb3df668e19ace07335a0711ec56ab" - integrity sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg== - -"@esbuild/linux-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz#48d42861758c940b61abea43ba9a29b186d6cb8b" - integrity sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw== - -"@esbuild/linux-arm@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz#6ce4b9cabf148274101701d112b89dc67cc52f37" - integrity sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw== - -"@esbuild/linux-ia32@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz#207e54899b79cac9c26c323fc1caa32e3143f1c4" - integrity sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A== - -"@esbuild/linux-loong64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz#0ba48a127159a8f6abb5827f21198b999ffd1fc0" - integrity sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ== - -"@esbuild/linux-mips64el@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz#a4d4cc693d185f66a6afde94f772b38ce5d64eb5" - integrity sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA== - -"@esbuild/linux-ppc64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz#0f5805c1c6d6435a1dafdc043cb07a19050357db" - integrity sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w== - -"@esbuild/linux-riscv64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz#6776edece0f8fca79f3386398b5183ff2a827547" - integrity sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg== - -"@esbuild/linux-s390x@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz#3f6f29ef036938447c2218d309dc875225861830" - integrity sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA== - "@esbuild/linux-x64@0.25.9": version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz#831fe0b0e1a80a8b8391224ea2377d5520e1527f" + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz" integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg== -"@esbuild/netbsd-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz#06f99d7eebe035fbbe43de01c9d7e98d2a0aa548" - integrity sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q== - -"@esbuild/netbsd-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz#db99858e6bed6e73911f92a88e4edd3a8c429a52" - integrity sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g== - -"@esbuild/openbsd-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz#afb886c867e36f9d86bb21e878e1185f5d5a0935" - integrity sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ== - -"@esbuild/openbsd-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz#30855c9f8381fac6a0ef5b5f31ac6e7108a66ecf" - integrity sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA== - -"@esbuild/openharmony-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz#2f2144af31e67adc2a8e3705c20c2bd97bd88314" - integrity sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg== - -"@esbuild/sunos-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz#69b99a9b5bd226c9eb9c6a73f990fddd497d732e" - integrity sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw== - -"@esbuild/win32-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz#d789330a712af916c88325f4ffe465f885719c6b" - integrity sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ== - -"@esbuild/win32-ia32@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz#52fc735406bd49688253e74e4e837ac2ba0789e3" - integrity sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww== - -"@esbuild/win32-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz#585624dc829cfb6e7c0aa6c3ca7d7e6daa87e34f" - integrity sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ== - "@eslint-community/eslint-utils@^4.2.0": version "4.7.0" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz" @@ -316,59 +191,11 @@ resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz" integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== -"@img/sharp-darwin-arm64@^0.33.5": - version "0.33.5" - resolved "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz" - integrity sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ== - optionalDependencies: - "@img/sharp-libvips-darwin-arm64" "1.0.4" - -"@img/sharp-darwin-x64@^0.33.5": - version "0.33.5" - resolved "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz" - integrity sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q== - optionalDependencies: - "@img/sharp-libvips-darwin-x64" "1.0.4" - -"@img/sharp-libvips-darwin-arm64@1.0.4": - version "1.0.4" - resolved "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz" - integrity sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg== - -"@img/sharp-libvips-darwin-x64@1.0.4": - version "1.0.4" - resolved "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz" - integrity sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ== - -"@img/sharp-libvips-linux-arm64@1.0.4": - version "1.0.4" - resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz" - integrity sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA== - -"@img/sharp-libvips-linux-arm@1.0.5": - version "1.0.5" - resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz" - integrity sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g== - "@img/sharp-libvips-linux-x64@1.0.4": version "1.0.4" resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz" integrity sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw== -"@img/sharp-linux-arm64@^0.33.5": - version "0.33.5" - resolved "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz" - integrity sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA== - optionalDependencies: - "@img/sharp-libvips-linux-arm64" "1.0.4" - -"@img/sharp-linux-arm@^0.33.5": - version "0.33.5" - resolved "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz" - integrity sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ== - optionalDependencies: - "@img/sharp-libvips-linux-arm" "1.0.5" - "@img/sharp-linux-x64@^0.33.5": version "0.33.5" resolved "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz" @@ -376,11 +203,6 @@ optionalDependencies: "@img/sharp-libvips-linux-x64" "1.0.4" -"@img/sharp-win32-x64@^0.33.5": - version "0.33.5" - resolved "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz" - integrity sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg== - "@inquirer/checkbox@^4.2.1": version "4.2.1" resolved "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.2.1.tgz" @@ -572,7 +394,7 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== @@ -597,7 +419,7 @@ resolved "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz" integrity sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw== -"@octokit/core@^6.1.4": +"@octokit/core@^6.1.4", "@octokit/core@>=6": version "6.1.6" resolved "https://registry.npmjs.org/@octokit/core/-/core-6.1.6.tgz" integrity sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA== @@ -768,106 +590,11 @@ estree-walker "^2.0.2" picomatch "^4.0.2" -"@rollup/rollup-android-arm-eabi@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.3.tgz#8d8afcc5a79a3f190c5f855facde6e0da6a5b7ea" - integrity sha512-UmTdvXnLlqQNOCJnyksjPs1G4GqXNGW1LrzCe8+8QoaLhhDeTXYBgJ3k6x61WIhlHX2U+VzEJ55TtIjR/HTySA== - -"@rollup/rollup-android-arm64@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.3.tgz#bed8ee4c2b31fd255fb91c2f52949dffef16ecf1" - integrity sha512-8NoxqLpXm7VyeI0ocidh335D6OKT0UJ6fHdnIxf3+6oOerZZc+O7r+UhvROji6OspyPm+rrIdb1gTXtVIqn+Sg== - -"@rollup/rollup-darwin-arm64@4.46.3": - version "4.46.3" - resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.3.tgz" - integrity sha512-csnNavqZVs1+7/hUKtgjMECsNG2cdB8F7XBHP6FfQjqhjF8rzMzb3SLyy/1BG7YSfQ+bG75Ph7DyedbUqwq1rA== - -"@rollup/rollup-darwin-x64@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.3.tgz#f5a01577c40830c423855492ecd8d3a7ae1b4836" - integrity sha512-r2MXNjbuYabSIX5yQqnT8SGSQ26XQc8fmp6UhlYJd95PZJkQD1u82fWP7HqvGUf33IsOC6qsiV+vcuD4SDP6iw== - -"@rollup/rollup-freebsd-arm64@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.3.tgz#d272eed9c14efc149bab316de364c04f236c544f" - integrity sha512-uluObTmgPJDuJh9xqxyr7MV61Imq+0IvVsAlWyvxAaBSNzCcmZlhfYcRhCdMaCsy46ccZa7vtDDripgs9Jkqsw== - -"@rollup/rollup-freebsd-x64@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.3.tgz#4c793f86e2dc64e725370daa2bec103f5869b5a6" - integrity sha512-AVJXEq9RVHQnejdbFvh1eWEoobohUYN3nqJIPI4mNTMpsyYN01VvcAClxflyk2HIxvLpRcRggpX1m9hkXkpC/A== - -"@rollup/rollup-linux-arm-gnueabihf@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.3.tgz#28da78d3709262f0b7ef0ba7e8e6f77c1b2f30a6" - integrity sha512-byyflM+huiwHlKi7VHLAYTKr67X199+V+mt1iRgJenAI594vcmGGddWlu6eHujmcdl6TqSNnvqaXJqZdnEWRGA== - -"@rollup/rollup-linux-arm-musleabihf@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.3.tgz#7e3309e6519eca1459038761aad44863e86fc497" - integrity sha512-aLm3NMIjr4Y9LklrH5cu7yybBqoVCdr4Nvnm8WB7PKCn34fMCGypVNpGK0JQWdPAzR/FnoEoFtlRqZbBBLhVoQ== - -"@rollup/rollup-linux-arm64-gnu@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.3.tgz#bc18efe81022baac97566cc0ace04b359eb7cd16" - integrity sha512-VtilE6eznJRDIoFOzaagQodUksTEfLIsvXymS+UdJiSXrPW7Ai+WG4uapAc3F7Hgs791TwdGh4xyOzbuzIZrnw== - -"@rollup/rollup-linux-arm64-musl@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.3.tgz#3ac849b6c42591014b0cb8e25c9ba1ace8fe19ec" - integrity sha512-dG3JuS6+cRAL0GQ925Vppafi0qwZnkHdPeuZIxIPXqkCLP02l7ka+OCyBoDEv8S+nKHxfjvjW4OZ7hTdHkx8/w== - -"@rollup/rollup-linux-loongarch64-gnu@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.3.tgz#10260ca0c3682c2904b04bb907163aca8bc5adef" - integrity sha512-iU8DxnxEKJptf8Vcx4XvAUdpkZfaz0KWfRrnIRrOndL0SvzEte+MTM7nDH4A2Now4FvTZ01yFAgj6TX/mZl8hQ== - -"@rollup/rollup-linux-ppc64-gnu@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.3.tgz#36b002a84c04f2e18093f563896c95a6e687f28f" - integrity sha512-VrQZp9tkk0yozJoQvQcqlWiqaPnLM6uY1qPYXvukKePb0fqaiQtOdMJSxNFUZFsGw5oA5vvVokjHrx8a9Qsz2A== - -"@rollup/rollup-linux-riscv64-gnu@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.3.tgz#ff1b3708624fc8b912e5341431751977b78be273" - integrity sha512-uf2eucWSUb+M7b0poZ/08LsbcRgaDYL8NCGjUeFMwCWFwOuFcZ8D9ayPl25P3pl+D2FH45EbHdfyUesQ2Lt9wA== - -"@rollup/rollup-linux-riscv64-musl@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.3.tgz#ab6f7ef69cdf812eccb318021a8f5c221bd0c048" - integrity sha512-7tnUcDvN8DHm/9ra+/nF7lLzYHDeODKKKrh6JmZejbh1FnCNZS8zMkZY5J4sEipy2OW1d1Ncc4gNHUd0DLqkSg== - -"@rollup/rollup-linux-s390x-gnu@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.3.tgz#60527b48dd84814fa5092a2eef1ac90e2b4bf825" - integrity sha512-MUpAOallJim8CsJK+4Lc9tQzlfPbHxWDrGXZm2z6biaadNpvh3a5ewcdat478W+tXDoUiHwErX/dOql7ETcLqg== - "@rollup/rollup-linux-x64-gnu@4.46.3": version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.3.tgz#c95698199820782b7420f5472e5d36b681728274" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.3.tgz" integrity sha512-F42IgZI4JicE2vM2PWCe0N5mR5vR0gIdORPqhGQ32/u1S1v3kLtbZ0C/mi9FFk7C5T0PgdeyWEPajPjaUpyoKg== -"@rollup/rollup-linux-x64-musl@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.3.tgz#226eb081be8d6698a580022448197b01cb4193a2" - integrity sha512-oLc+JrwwvbimJUInzx56Q3ujL3Kkhxehg7O1gWAYzm8hImCd5ld1F2Gry5YDjR21MNb5WCKhC9hXgU7rRlyegQ== - -"@rollup/rollup-win32-arm64-msvc@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.3.tgz#e900bd51cfc20af2a1c828d999bb49da1bd497eb" - integrity sha512-lOrQ+BVRstruD1fkWg9yjmumhowR0oLAAzavB7yFSaGltY8klttmZtCLvOXCmGE9mLIn8IBV/IFrQOWz5xbFPg== - -"@rollup/rollup-win32-ia32-msvc@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.3.tgz#94652ba771a90bf2558c0a6c553857148d7ff8f4" - integrity sha512-vvrVKPRS4GduGR7VMH8EylCBqsDcw6U+/0nPDuIjXQRbHJc6xOBj+frx8ksfZAh6+Fptw5wHrN7etlMmQnPQVg== - -"@rollup/rollup-win32-x64-msvc@4.46.3": - version "4.46.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.3.tgz#3d9ed4f8b9f2be7500565515d863c409eaceeb70" - integrity sha512-fi3cPxCnu3ZeM3EwKZPgXbWoGzm2XHgB/WShKI81uj8wG0+laobmqy5wbgEwzstlbLu4MyO8C19FyhhWseYKNQ== - "@socket.io/component-emitter@~3.1.0": version "3.1.2" resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz" @@ -927,7 +654,7 @@ resolved "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz" integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== -"@types/estree@*", "@types/estree@1.0.8", "@types/estree@^1.0.0", "@types/estree@^1.0.6": +"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.6", "@types/estree@1.0.8": version "1.0.8" resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz" integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== @@ -944,16 +671,16 @@ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== -"@types/node@*", "@types/node@>=20": +"@types/node@*", "@types/node@^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node@^20.19.0 || >=22.12.0", "@types/node@>=18", "@types/node@>=20": version "24.3.0" resolved "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz" integrity sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow== dependencies: undici-types "~7.10.0" -"@types/parse-path@7.0.3", "@types/parse-path@^7.0.0": +"@types/parse-path@^7.0.0": version "7.0.3" - resolved "https://registry.yarnpkg.com/@types/parse-path/-/parse-path-7.0.3.tgz#cec2da2834ab58eb2eb579122d9a1fc13bd7ef36" + resolved "https://registry.npmjs.org/@types/parse-path/-/parse-path-7.0.3.tgz" integrity sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg== "@types/ps-list@^6.2.1": @@ -968,7 +695,7 @@ resolved "https://registry.npmjs.org/@types/qrcode-terminal/-/qrcode-terminal-0.12.2.tgz" integrity sha512-v+RcIEJ+Uhd6ygSQ0u5YYY7ZM+la7GgPbs0V/7l/kFs2uO4S8BcIUEMoP7za4DNIqNnUD5npf0A/7kBhrCKG5Q== -"@types/react@^19.1.9": +"@types/react@^19.1.9", "@types/react@>=19.0.0": version "19.1.10" resolved "https://registry.npmjs.org/@types/react/-/react-19.1.10.tgz" integrity sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg== @@ -1005,7 +732,7 @@ estree-walker "^3.0.3" magic-string "^0.30.17" -"@vitest/pretty-format@3.2.4", "@vitest/pretty-format@^3.2.4": +"@vitest/pretty-format@^3.2.4", "@vitest/pretty-format@3.2.4": version "3.2.4" resolved "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz" integrity sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA== @@ -1071,7 +798,7 @@ acorn-walk@^8.1.1: dependencies: acorn "^8.11.0" -acorn@^8.11.0, acorn@^8.15.0, acorn@^8.4.1: +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.11.0, acorn@^8.15.0, acorn@^8.4.1: version "8.15.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz" integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== @@ -1098,7 +825,17 @@ ajv@^6.12.4, ajv@^6.12.6: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.12.0: +ajv@^8.0.0: + version "8.17.1" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ajv@^8.12.0: version "8.17.1" resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== @@ -1132,7 +869,14 @@ ansi-regex@^6.0.1: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz" integrity sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg== -ansi-styles@^4.0.0, ansi-styles@^4.1.0: +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -1262,7 +1006,7 @@ bundle-name@^4.1.0: dependencies: run-applescript "^7.0.0" -bytes@3.1.2, bytes@^3.1.2: +bytes@^3.1.2, bytes@3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== @@ -1529,14 +1273,21 @@ data-uri-to-buffer@^6.0.2: resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz" integrity sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw== -debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.6, debug@^4.4.0, debug@^4.4.1: +debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.6, debug@^4.4.0, debug@^4.4.1, debug@4: version "4.4.1" resolved "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz" integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== dependencies: ms "^2.1.3" -debug@~4.3.1, debug@~4.3.2: +debug@~4.3.1: + version "4.3.7" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +debug@~4.3.2: version "4.3.7" resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz" integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== @@ -1595,7 +1346,7 @@ delayed-stream@~1.0.0: resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -depd@2.0.0, depd@^2.0.0: +depd@^2.0.0, depd@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -1793,7 +1544,7 @@ eslint-visitor-keys@^4.2.1: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz" integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== -eslint@^9: +"eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.40 || 9", eslint@^9, eslint@>=7.0.0: version "9.33.0" resolved "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz" integrity sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA== @@ -1950,7 +1701,7 @@ express-rate-limit@^7.5.0: resolved "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz" integrity sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw== -express@^5.0.1: +express@^5.0.1, "express@>= 4.11": version "5.1.0" resolved "https://registry.npmjs.org/express/-/express-5.1.0.tgz" integrity sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA== @@ -2061,7 +1812,7 @@ fastify-type-provider-zod@4.0.2: "@fastify/error" "^4.0.0" zod-to-json-schema "^3.23.3" -fastify@^5.5.0: +fastify@^5.0.0, fastify@^5.5.0: version "5.5.0" resolved "https://registry.npmjs.org/fastify/-/fastify-5.5.0.tgz" integrity sha512-ZWSWlzj3K/DcULCnCjEiC2zn2FBPdlZsSA/pnPa/dbUfLvxkD/Nqmb0XXMXLrWkeM4uQPUvjdJpwtXmTfriXqw== @@ -2089,7 +1840,17 @@ fastq@^1.17.1, fastq@^1.6.0: dependencies: reusify "^1.0.4" -fdir@^6.2.0, fdir@^6.4.4, fdir@^6.5.0: +fdir@^6.2.0: + version "6.5.0" + resolved "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +fdir@^6.4.4: + version "6.5.0" + resolved "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +fdir@^6.5.0: version "6.5.0" resolved "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz" integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== @@ -2181,11 +1942,6 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" @@ -2328,7 +2084,7 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" -http-errors@2.0.0, http-errors@^2.0.0: +http-errors@^2.0.0, http-errors@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== @@ -2381,7 +2137,7 @@ human-signals@^5.0.0: resolved "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz" integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== -iconv-lite@0.6.3, iconv-lite@^0.6.3: +iconv-lite@^0.6.3, iconv-lite@0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -2477,16 +2233,16 @@ ip-address@^10.0.1: resolved "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz" integrity sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA== -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - ipaddr.js@^2.1.0: version "2.2.0" resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz" integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + is-core-module@^2.16.0: version "2.16.1" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz" @@ -2617,7 +2373,7 @@ issue-parser@7.0.1: lodash.isstring "^4.0.1" lodash.uniqby "^4.7.0" -jiti@^2.4.2: +jiti@*, jiti@^2.4.2, jiti@>=1.21.0: version "2.5.1" resolved "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz" integrity sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w== @@ -2720,7 +2476,7 @@ lodash.isstring@^4.0.1: resolved "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== -lodash.merge@4.6.2, lodash.merge@^4.6.2: +lodash.merge@^4.6.2, lodash.merge@4.6.2: version "4.6.2" resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== @@ -2803,22 +2559,15 @@ micromatch@^4.0.8: braces "^3.0.3" picomatch "^2.3.1" -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - mime-db@^1.54.0: version "1.54.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz" integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== -mime-types@3.0.1, mime-types@^3.0.0, mime-types@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz" - integrity sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA== - dependencies: - mime-db "^1.54.0" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.12: version "2.1.35" @@ -2827,6 +2576,13 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +mime-types@^3.0.0, mime-types@^3.0.1, mime-types@3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz" + integrity sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA== + dependencies: + mime-db "^1.54.0" + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" @@ -2993,7 +2749,7 @@ onetime@^7.0.0: dependencies: mimic-function "^5.0.0" -open@10.2.0, open@^10.2.0: +open@^10.2.0, open@10.2.0: version "10.2.0" resolved "https://registry.npmjs.org/open/-/open-10.2.0.tgz" integrity sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA== @@ -3081,9 +2837,9 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-path@7.0.3, parse-path@^7.0.0: +parse-path@^7.0.0: version "7.0.3" - resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-7.0.3.tgz#f29d8942a3562aac561a1b77de6a56cc93dca489" + resolved "https://registry.npmjs.org/parse-path/-/parse-path-7.0.3.tgz" integrity sha512-0R71msgRgmkcZ5CWnzS+GPXJ1Fc+lbKyPDuA83Ej0QKCpf/Feieh813bF38My3CTNBzcQhtRRqvXNpCFF6FRMQ== dependencies: protocols "^2.0.0" @@ -3161,7 +2917,7 @@ picomatch@^2.3.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2, picomatch@^4.0.3: +"picomatch@^3 || ^4", picomatch@^4.0.2, picomatch@^4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz" integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== @@ -3303,7 +3059,7 @@ ps-list@*, ps-list@^8.1.1: punycode@^2.1.0, punycode@^2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== qrcode-terminal@^0.12.0: @@ -3358,7 +3114,7 @@ react-reconciler@^0.32.0: dependencies: scheduler "^0.26.0" -react@^19.1.1: +react@^19.1.0, react@^19.1.1, react@>=19.0.0: version "19.1.1" resolved "https://registry.npmjs.org/react/-/react-19.1.1.tgz" integrity sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ== @@ -3459,16 +3215,16 @@ ret@~0.5.0: resolved "https://registry.npmjs.org/ret/-/ret-0.5.0.tgz" integrity sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw== -retry@0.13.1: - version "0.13.1" - resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - retry@^0.12.0: version "0.12.0" resolved "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz" integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== +retry@0.13.1: + version "0.13.1" + resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + reusify@^1.0.4: version "1.1.0" resolved "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz" @@ -3486,7 +3242,7 @@ rollup-pluginutils@^2.8.2: dependencies: estree-walker "^0.6.1" -rollup@^4.43.0, rollup@^4.46.2: +rollup@^1.20.0||^2.0.0||^3.0.0||^4.0.0, rollup@^2.68.0||^3.0.0||^4.0.0, rollup@^2.78.0||^3.0.0||^4.0.0, rollup@^4.43.0, rollup@^4.46.2: version "4.46.3" resolved "https://registry.npmjs.org/rollup/-/rollup-4.46.3.tgz" integrity sha512-RZn2XTjXb8t5g13f5YclGoilU/kwT696DIkY3sywjdZidNSi3+vseaQov7D7BZXVJCPv3pDWUN69C78GGbXsKw== @@ -3582,7 +3338,7 @@ secure-json-parse@^4.0.0: resolved "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.0.0.tgz" integrity sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA== -semver@7.7.2, semver@^7.6.0: +semver@^7.6.0, semver@7.7.2: version "7.7.2" resolved "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz" integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== @@ -3798,16 +3554,16 @@ stackback@0.0.2: resolved "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz" integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - statuses@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz" integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + std-env@^3.9.0: version "3.9.0" resolved "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz" @@ -3913,7 +3669,7 @@ tinyexec@^1.0.1: resolved "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz" integrity sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw== -tinyglobby@0.2.14, tinyglobby@^0.2.14: +tinyglobby@^0.2.14, tinyglobby@0.2.14: version "0.2.14" resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz" integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== @@ -3960,7 +3716,7 @@ toidentifier@1.0.1: tr46@^5.1.0: version "5.1.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.1.1.tgz#96ae867cddb8fdb64a49cc3059a8d428bcf238ca" + resolved "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz" integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw== dependencies: punycode "^2.3.1" @@ -3994,7 +3750,7 @@ tslib@^2.0.1, tslib@^2.1.0: resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== -tsx@^4.20.3: +tsx@^4.20.3, tsx@^4.8.1: version "4.20.4" resolved "https://registry.npmjs.org/tsx/-/tsx-4.20.4.tgz" integrity sha512-yyxBKfORQ7LuRt/BQKBXrpcq59ZvSW0XxwfjAt3w2/8PmdxaFzijtMhTawprSHhpzeM5BgU2hXHG3lklIERZXg== @@ -4040,7 +3796,7 @@ type-is@^2.0.0, type-is@^2.0.1: media-typer "^1.1.0" mime-types "^3.0.0" -typescript@^5: +"typescript@^4.1 || ^5.0", typescript@^5, typescript@>=2.7: version "5.9.2" resolved "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz" integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A== @@ -4143,12 +3899,12 @@ vitest@^3.2.4: webidl-conversions@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -whatwg-url@14.2.0, whatwg-url@^5.0.0: +whatwg-url@^5.0.0: version "14.2.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.2.0.tgz#4ee02d5d725155dae004f6ae95c73e7ef5d95663" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz" integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw== dependencies: tr46 "^5.1.0" @@ -4273,7 +4029,7 @@ zod-to-json-schema@^3.23.3, zod-to-json-schema@^3.24.1: resolved "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz" integrity sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg== -zod@^3.23.8: +zod@^3.14.2, zod@^3.23.8, zod@^3.24.1, "zod@^3.25.0 || ^4.0.0": version "3.25.76" resolved "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz" integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== From 1517b7976fb38c48102fc0a6d266ad9fbfa6b45c Mon Sep 17 00:00:00 2001 From: James White Date: Fri, 14 Nov 2025 19:50:00 +0000 Subject: [PATCH 05/35] feat: add Codex subprocess health monitoring and auto-reconnection Implements comprehensive health monitoring for the Codex subprocess to detect crashes and automatically reconnect with exponential backoff. Changes to CodexMcpClient: - Added isProcessAlive() method to check subprocess status - Added setProcessExitHandler() for exit event notifications - Added setProcessErrorHandler() for error event notifications - Hooked transport.onerror and transport.onclose for monitoring - Logs subprocess PID on successful connection Changes to runCodex: - Track subprocess health state (processUnexpectedlyExited) - Implement ensureCodexConnection() with exponential backoff (1s, 2s, 4s) - Auto-reconnect on subprocess death (max 3 attempts) - Clear session state after reconnection to force fresh session - Check connection health before processing each message - User-friendly error message when reconnection fails This prevents the "agent going offline" issue where Codex subprocess crashes silently and never recovers. The agent will now automatically reconnect and continue serving requests. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/codex/codexMcpClient.ts | 51 +++++++++++++++++++++- src/codex/runCodex.ts | 86 +++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/src/codex/codexMcpClient.ts b/src/codex/codexMcpClient.ts index 95ddd460..26cce744 100644 --- a/src/codex/codexMcpClient.ts +++ b/src/codex/codexMcpClient.ts @@ -51,6 +51,8 @@ export class CodexMcpClient { private conversationId: string | null = null; private handler: ((event: any) => void) | null = null; private permissionHandler: CodexPermissionHandler | null = null; + private processExitHandler: ((code: number | null, signal: NodeJS.Signals | null) => void) | null = null; + private processErrorHandler: ((error: Error) => void) | null = null; constructor() { this.client = new Client( @@ -81,6 +83,36 @@ export class CodexMcpClient { this.permissionHandler = handler; } + /** + * Set handler for subprocess exit events + */ + setProcessExitHandler(handler: (code: number | null, signal: NodeJS.Signals | null) => void): void { + this.processExitHandler = handler; + } + + /** + * Set handler for subprocess error events + */ + setProcessErrorHandler(handler: (error: Error) => void): void { + this.processErrorHandler = handler; + } + + /** + * Check if the subprocess is alive + */ + isProcessAlive(): boolean { + const pid = this.transport?.pid; + if (!pid) return false; + + try { + // Signal 0 checks if process exists without killing it + process.kill(pid, 0); + return true; + } catch { + return false; + } + } + async connect(): Promise { if (this.connected) return; @@ -110,13 +142,30 @@ export class CodexMcpClient { }, {} as Record) }); + // Set up subprocess health monitoring + this.transport.onerror = (error: Error) => { + logger.debug('[CodexMCP] Transport error:', error); + if (this.processErrorHandler) { + this.processErrorHandler(error); + } + }; + + this.transport.onclose = () => { + logger.debug('[CodexMCP] Transport closed'); + // Note: We can't get exit code/signal from StdioClientTransport's onclose + // but we can detect that the process has exited + if (this.processExitHandler) { + this.processExitHandler(null, null); + } + }; + // Register request handlers for Codex permission methods this.registerPermissionHandlers(); await this.client.connect(this.transport); this.connected = true; - logger.debug('[CodexMCP] Connected to Codex'); + logger.debug('[CodexMCP] Connected to Codex, subprocess PID:', this.transport.pid); } finally { // Restore original process.type if (isWindows && !originalProcessType) { diff --git a/src/codex/runCodex.ts b/src/codex/runCodex.ts index 86604b08..5b4d3afd 100644 --- a/src/codex/runCodex.ts +++ b/src/codex/runCodex.ts @@ -343,6 +343,77 @@ export async function runCodex(opts: { const client = new CodexMcpClient(); + // Track subprocess health for reconnection + let processUnexpectedlyExited = false; + let reconnectionAttempts = 0; + const MAX_RECONNECTION_ATTEMPTS = 3; + + // Set up subprocess health monitoring + client.setProcessExitHandler((code, signal) => { + logger.debug(`[Codex] Subprocess exited: code=${code}, signal=${signal}`); + processUnexpectedlyExited = true; + + // Don't reconnect if we're shutting down intentionally + if (shouldExit) { + logger.debug('[Codex] Subprocess exit expected during shutdown'); + return; + } + + logger.warn('[Codex] Subprocess exited unexpectedly, will attempt to reconnect on next message'); + }); + + client.setProcessErrorHandler((error) => { + logger.warn('[Codex] Subprocess error:', error); + processUnexpectedlyExited = true; + }); + + // Helper: Reconnect to Codex subprocess with exponential backoff + async function ensureCodexConnection(): Promise { + // Check if process is alive + if (client.isProcessAlive()) { + reconnectionAttempts = 0; // Reset on successful connection + return true; + } + + // If process died, attempt reconnection + if (processUnexpectedlyExited) { + logger.debug(`[Codex] Attempting reconnection (attempt ${reconnectionAttempts + 1}/${MAX_RECONNECTION_ATTEMPTS})`); + + if (reconnectionAttempts >= MAX_RECONNECTION_ATTEMPTS) { + logger.warn('[Codex] Max reconnection attempts reached, giving up'); + processUnexpectedlyExited = false; + reconnectionAttempts = 0; + return false; + } + + try { + // Exponential backoff: 1s, 2s, 4s + const backoffMs = Math.pow(2, reconnectionAttempts) * 1000; + logger.debug(`[Codex] Waiting ${backoffMs}ms before reconnection attempt`); + await delay(backoffMs); + + // Disconnect old transport + await client.disconnect(); + + // Reconnect + await client.connect(); + + logger.debug('[Codex] Reconnection successful'); + processUnexpectedlyExited = false; + reconnectionAttempts = 0; + + // Note: Session state will be cleared by the caller + return true; + } catch (error) { + logger.warn(`[Codex] Reconnection attempt ${reconnectionAttempts + 1} failed:`, error); + reconnectionAttempts++; + return false; + } + } + + return true; + } + // Helper: find Codex session transcript for a given sessionId function findCodexResumeFile(sessionId: string | null): string | null { if (!sessionId) return null; @@ -619,6 +690,21 @@ export async function runCodex(opts: { messageBuffer.addMessage(message.message, 'user'); currentModeHash = message.hash; + // Ensure Codex subprocess is alive and reconnect if needed + const connectionOk = await ensureCodexConnection(); + if (!connectionOk) { + messageBuffer.addMessage('Failed to connect to Codex after multiple attempts. Please try again later.', 'status'); + pending = null; + continue; + } + + // If we just reconnected, clear session state to force new session creation + if (processUnexpectedlyExited === false && reconnectionAttempts === 0 && !wasCreated) { + logger.debug('[Codex] Reconnection detected, clearing session state'); + wasCreated = false; + currentModeHash = null; + } + try { // Map permission mode to approval policy and sandbox for startSession const approvalPolicy = (() => { From 162f13b97d1a33707589b8549d6202a3fed9aa12 Mon Sep 17 00:00:00 2001 From: James White Date: Fri, 14 Nov 2025 19:52:05 +0000 Subject: [PATCH 06/35] feat: add timeout handling for MCP operations and permissions Reduces excessive timeouts and prevents indefinite hangs in Codex operations. Changes to codexMcpClient: - Reduced DEFAULT_TIMEOUT from 14 days to 5 minutes - Previous 14-day timeout could cause indefinite hangs - 5 minutes is reasonable for most Codex operations Changes to permissionHandler: - Added PERMISSION_TIMEOUT constant (2 minutes) - Implemented timeout mechanism for permission requests - Added timeoutId tracking in PendingRequest interface - Timeout handler rejects promise and updates agent state - Clear timeout when permission response received - Clear all timeouts on reset() to prevent leaks - Timeout requests marked as 'canceled' with reason Impact: - Prevents permission requests hanging forever if mobile doesn't respond - Prevents MCP operations hanging for weeks - Provides clear timeout error messages - Properly cleans up timers to prevent memory leaks This resolves Issue #5: Missing timeouts causing operations to hang indefinitely when mobile app is unresponsive or MCP operations fail. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/codex/codexMcpClient.ts | 4 ++- src/codex/utils/permissionHandler.ts | 45 ++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/codex/codexMcpClient.ts b/src/codex/codexMcpClient.ts index 26cce744..71fb4844 100644 --- a/src/codex/codexMcpClient.ts +++ b/src/codex/codexMcpClient.ts @@ -11,7 +11,9 @@ import { ElicitRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import { CodexPermissionHandler } from './utils/permissionHandler'; import { execSync } from 'child_process'; -const DEFAULT_TIMEOUT = 14 * 24 * 60 * 60 * 1000; // 14 days, which is the half of the maximum possible timeout (~28 days for int32 value in NodeJS) +// Timeout for MCP operations - 5 minutes is reasonable for most Codex operations +// Previous value was 14 days which could cause indefinite hangs +const DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes /** * Get the correct MCP subcommand based on installed codex version diff --git a/src/codex/utils/permissionHandler.ts b/src/codex/utils/permissionHandler.ts index ff7afee5..3e8aa326 100644 --- a/src/codex/utils/permissionHandler.ts +++ b/src/codex/utils/permissionHandler.ts @@ -9,6 +9,9 @@ import { logger } from "@/ui/logger"; import { ApiSessionClient } from "@/api/apiSession"; import { AgentState } from "@/api/types"; +// Timeout for permission requests - 2 minutes should be enough for user to respond +const PERMISSION_TIMEOUT = 2 * 60 * 1000; // 2 minutes + interface PermissionResponse { id: string; approved: boolean; @@ -20,6 +23,7 @@ interface PendingRequest { reject: (error: Error) => void; toolName: string; input: unknown; + timeoutId: NodeJS.Timeout; } interface PermissionResult { @@ -48,12 +52,45 @@ export class CodexPermissionHandler { input: unknown ): Promise { return new Promise((resolve, reject) => { + // Set timeout for permission request + const timeoutId = setTimeout(() => { + const pending = this.pendingRequests.get(toolCallId); + if (pending) { + this.pendingRequests.delete(toolCallId); + logger.warn(`[Codex] Permission request timed out for ${toolName} (${toolCallId})`); + + // Update agent state to mark as timed out + this.session.updateAgentState((currentState) => { + const request = currentState.requests?.[toolCallId]; + if (!request) return currentState; + + const { [toolCallId]: _, ...remainingRequests } = currentState.requests || {}; + return { + ...currentState, + requests: remainingRequests, + completedRequests: { + ...currentState.completedRequests, + [toolCallId]: { + ...request, + completedAt: Date.now(), + status: 'canceled', + reason: 'Permission request timed out' + } + } + }; + }); + + reject(new Error(`Permission request timed out after ${PERMISSION_TIMEOUT / 1000}s`)); + } + }, PERMISSION_TIMEOUT); + // Store the pending request this.pendingRequests.set(toolCallId, { resolve, reject, toolName, - input + input, + timeoutId }); // Send push notification @@ -100,6 +137,9 @@ export class CodexPermissionHandler { return; } + // Clear the timeout + clearTimeout(pending.timeoutId); + // Remove from pending this.pendingRequests.delete(response.id); @@ -145,8 +185,9 @@ export class CodexPermissionHandler { * Reset state for new sessions */ reset(): void { - // Reject all pending requests + // Reject all pending requests and clear timeouts for (const [id, pending] of this.pendingRequests.entries()) { + clearTimeout(pending.timeoutId); pending.reject(new Error('Session reset')); } this.pendingRequests.clear(); From 1155c7fa16da936745cf42975aa6bb709fa252ad Mon Sep 17 00:00:00 2001 From: James White Date: Fri, 14 Nov 2025 20:06:29 +0000 Subject: [PATCH 07/35] chore: bump version to 0.11.3-preview.1 for testing This preview release includes all Codex integration improvements: - Fixed Windows console window issue - Fixed WebSocket race condition (missed first messages) - Added subprocess health monitoring with auto-reconnection - Added timeout handling for MCP operations and permissions - Comprehensive technical documentation in PROJECT.md Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2f78437f..b21a3b2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "happy-coder", - "version": "0.11.2", + "version": "0.11.3-preview.1", "description": "Mobile and Web client for Claude Code and Codex", "author": "Kirill Dubovitskiy", "license": "MIT", From 28aa2f148116cb1fc7b407c5ec767735c6636b5b Mon Sep 17 00:00:00 2001 From: James White Date: Sat, 15 Nov 2025 15:11:07 +0000 Subject: [PATCH 08/35] fix: handle missing tar dependency during npm install from git The postinstall script (unpack-tools.cjs) was failing during npm install from GitHub because the 'tar' dependency wasn't available yet during the git package preparation phase. Changes: - Lazy load tar module with try/catch - Skip unpacking gracefully when tar not available - Add helpful message about deferred unpacking - Exit with code 0 (success) when skipping due to missing tar - Tools will unpack on first use or manual script run This fixes the error: Error: Cannot find module 'tar' npm error command failed npm error command sh -c node scripts/unpack-tools.cjs Users can now install directly from GitHub without errors. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- scripts/unpack-tools.cjs | 54 +++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/scripts/unpack-tools.cjs b/scripts/unpack-tools.cjs index 5862bd87..077d6b6e 100644 --- a/scripts/unpack-tools.cjs +++ b/scripts/unpack-tools.cjs @@ -8,9 +8,17 @@ const fs = require('fs'); const path = require('path'); const zlib = require('zlib'); -const tar = require('tar'); const os = require('os'); +// Lazy load tar - it might not be available during initial npm install +let tar; +try { + tar = require('tar'); +} catch (e) { + // tar not available yet - will be handled later + tar = null; +} + /** * Get the platform-specific directory name */ @@ -68,12 +76,16 @@ function areToolsUnpacked(toolsDir) { * Unpack a tar.gz archive to a destination directory */ async function unpackArchive(archivePath, destDir) { + if (!tar) { + throw new Error('tar module not available - dependencies may not be installed yet'); + } + return new Promise((resolve, reject) => { // Ensure destination directory exists if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }); } - + // Create read stream and extract fs.createReadStream(archivePath) .pipe(zlib.createGunzip()) @@ -110,37 +122,44 @@ async function unpackTools() { const toolsDir = getToolsDir(); const archivesDir = path.join(toolsDir, 'archives'); const unpackedPath = path.join(toolsDir, 'unpacked'); - + // Check if already unpacked if (areToolsUnpacked(toolsDir)) { console.log(`Tools already unpacked for ${platformDir}`); return { success: true, alreadyUnpacked: true }; } - + + // Check if tar module is available + if (!tar) { + console.log('Skipping tool unpacking - tar module not yet available'); + console.log('Tools will be unpacked on first use or by running: node scripts/unpack-tools.cjs'); + return { success: true, skipped: true }; + } + console.log(`Unpacking tools for ${platformDir}...`); - + // Create unpacked directory if (!fs.existsSync(unpackedPath)) { fs.mkdirSync(unpackedPath, { recursive: true }); } - + // Unpack difftastic const difftasticArchive = path.join(archivesDir, `difftastic-${platformDir}.tar.gz`); if (!fs.existsSync(difftasticArchive)) { throw new Error(`Archive not found: ${difftasticArchive}`); } await unpackArchive(difftasticArchive, unpackedPath); - + // Unpack ripgrep const ripgrepArchive = path.join(archivesDir, `ripgrep-${platformDir}.tar.gz`); if (!fs.existsSync(ripgrepArchive)) { throw new Error(`Archive not found: ${ripgrepArchive}`); } await unpackArchive(ripgrepArchive, unpackedPath); - + console.log(`Tools unpacked successfully to ${unpackedPath}`); return { success: true, alreadyUnpacked: false }; - + } catch (error) { console.error('Failed to unpack tools:', error.message); throw error; @@ -154,10 +173,21 @@ module.exports = { unpackTools, getPlatformDir, getToolsDir }; if (require.main === module) { unpackTools() .then(result => { - process.exit(0); + if (result.skipped) { + // Don't fail installation if tar is not available yet + process.exit(0); + } else { + process.exit(0); + } }) .catch(error => { - console.error('Error:', error); - process.exit(1); + // Only exit with error if it's not a tar availability issue + if (error.message && error.message.includes('tar module not available')) { + console.log('Note: Tool unpacking deferred until dependencies are installed'); + process.exit(0); + } else { + console.error('Error:', error); + process.exit(1); + } }); } \ No newline at end of file From ef0b865e097446dc2239b2a343acb5ed71dbfaf3 Mon Sep 17 00:00:00 2001 From: James White Date: Sat, 15 Nov 2025 15:11:29 +0000 Subject: [PATCH 09/35] chore: bump version to 0.11.3-preview.2 Includes fix for npm install from GitHub (postinstall script issue). Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b21a3b2a..41642c44 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "happy-coder", - "version": "0.11.3-preview.1", + "version": "0.11.3-preview.2", "description": "Mobile and Web client for Claude Code and Codex", "author": "Kirill Dubovitskiy", "license": "MIT", From 6d3d011682eb1b3c67526d85f8aef7c172417b18 Mon Sep 17 00:00:00 2001 From: James White Date: Mon, 17 Nov 2025 16:09:38 +0000 Subject: [PATCH 10/35] fix: make postinstall script more resilient to missing files Changed postinstall to use inline node -e with try/catch instead of directly calling the script file. This handles cases where: - scripts directory is not included in npm package from GitHub - unpack-tools.cjs is missing or inaccessible - Dependencies haven't been installed yet The script will now fail gracefully with a helpful message and allow installation to succeed. Tools will unpack on first use. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 41642c44..df28cbbd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "happy-coder", - "version": "0.11.3-preview.2", + "version": "0.11.3-preview.3", "description": "Mobile and Web client for Claude Code and Codex", "author": "Kirill Dubovitskiy", "license": "MIT", @@ -65,7 +65,7 @@ "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts", "prepublishOnly": "yarn build && yarn test", "release": "release-it", - "postinstall": "node scripts/unpack-tools.cjs" + "postinstall": "node -e \"try { require('./scripts/unpack-tools.cjs').unpackTools().catch(() => {}); } catch (e) { console.log('Note: Tool unpacking will happen on first use'); }\"" }, "dependencies": { "@anthropic-ai/claude-code": "2.0.24", From 7c28ba5b11bbad61dc0d258f88763bfc02808a24 Mon Sep 17 00:00:00 2001 From: James White Date: Mon, 17 Nov 2025 16:54:28 +0000 Subject: [PATCH 11/35] fix: add prepare script to ensure dist is built on npm install from git When installing from GitHub, npm runs the 'prepare' script but not 'prepublishOnly'. This ensures the dist directory is built during installation so the bin scripts can execute properly. Fixes error: Error: Cannot find module '.../node_modules/happy-coder/bin/happy.mjs' Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index df28cbbd..6ff5ae7d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "happy-coder", - "version": "0.11.3-preview.3", + "version": "0.11.3-preview.4", "description": "Mobile and Web client for Claude Code and Codex", "author": "Kirill Dubovitskiy", "license": "MIT", @@ -63,6 +63,7 @@ "dev": "tsx src/index.ts", "dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts", "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts", + "prepare": "npm run build", "prepublishOnly": "yarn build && yarn test", "release": "release-it", "postinstall": "node -e \"try { require('./scripts/unpack-tools.cjs').unpackTools().catch(() => {}); } catch (e) { console.log('Note: Tool unpacking will happen on first use'); }\"" From 1ffe9f32a465216bb7b53c768d74eb817dc4b42d Mon Sep 17 00:00:00 2001 From: James White Date: Mon, 17 Nov 2025 17:12:14 +0000 Subject: [PATCH 12/35] feat(preview-release): add preview release package 'happy-next' with scripts and docs - Introduce 'package-next.json' for preview version '0.11.3-preview.4', enabling side-by-side installation with stable 'happy-coder'. - Add 'scripts/publish-next.sh' to automate publishing 'happy-next' under npm preview tag. - Add test scripts 'scripts/test-install.sh' and 'scripts/test-installed.sh' to validate installations. - Add comprehensive 'scripts/README.md' with usage docs, workflows, and troubleshooting for dual packages. - Update dependencies and lockfiles to support preview package setup. This enables users to install and test preview features safely alongside stable releases. Co-authored-by: terragon-labs[bot] --- package-lock.json | 44 +++---- package-next.json | 126 ++++++++++++++++++++ package.json | 2 +- scripts/README.md | 241 ++++++++++++++++++++++++++++++++++++++ scripts/publish-next.sh | 98 ++++++++++++++++ scripts/test-install.sh | 167 ++++++++++++++++++++++++++ scripts/test-installed.sh | 150 ++++++++++++++++++++++++ yarn.lock | 37 +++--- 8 files changed, 819 insertions(+), 46 deletions(-) create mode 100644 package-next.json create mode 100644 scripts/README.md create mode 100755 scripts/publish-next.sh create mode 100755 scripts/test-install.sh create mode 100755 scripts/test-installed.sh diff --git a/package-lock.json b/package-lock.json index 1a5c2d64..963516bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,16 @@ { "name": "happy-coder", - "version": "0.11.2", + "version": "0.11.3-preview.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "happy-coder", - "version": "0.11.2", + "version": "0.11.3-preview.4", "hasInstallScript": true, "license": "MIT", "dependencies": { - "@anthropic-ai/claude-code": "2.0.24", + "@anthropic-ai/claude-code": "^2.0.24", "@anthropic-ai/sdk": "0.65.0", "@modelcontextprotocol/sdk": "^1.15.1", "@stablelib/base64": "^2.0.1", @@ -8100,16 +8100,10 @@ } }, "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" }, "node_modules/ts-algebra": { "version": "2.0.0", @@ -8537,25 +8531,19 @@ "license": "MIT" }, "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, "node_modules/which": { diff --git a/package-next.json b/package-next.json new file mode 100644 index 00000000..88fa55ad --- /dev/null +++ b/package-next.json @@ -0,0 +1,126 @@ +{ + "name": "happy-next", + "version": "0.11.3-preview.4", + "description": "Mobile and Web client for Claude Code and Codex - Preview Release", + "author": "Kirill Dubovitskiy", + "license": "MIT", + "type": "module", + "homepage": "https://github.com/slopus/happy-cli", + "bugs": "https://github.com/slopus/happy-cli/issues", + "repository": "slopus/happy-cli", + "bin": { + "happy-next": "./bin/happy.mjs", + "happy-next-mcp": "./bin/happy-mcp.mjs" + }, + "main": "./dist/index.cjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.cts", + "exports": { + ".": { + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + }, + "import": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + } + }, + "./lib": { + "require": { + "types": "./dist/lib.d.cts", + "default": "./dist/lib.cjs" + }, + "import": { + "types": "./dist/lib.d.mts", + "default": "./dist/lib.mjs" + } + }, + "./codex/happyMcpStdioBridge": { + "require": { + "types": "./dist/codex/happyMcpStdioBridge.d.cts", + "default": "./dist/codex/happyMcpStdioBridge.cjs" + }, + "import": { + "types": "./dist/codex/happyMcpStdioBridge.d.mts", + "default": "./dist/codex/happyMcpStdioBridge.mjs" + } + } + }, + "files": [ + "dist", + "bin", + "scripts", + "tools", + "package.json" + ], + "scripts": { + "why do we need to build before running tests / dev?": "We need the binary to be built so we run daemon commands which directly run the binary - we don't want them to go out of sync or have custom spawn logic depending how we started happy", + "typecheck": "tsc --noEmit", + "build": "shx rm -rf dist && npx tsc --noEmit && pkgroll", + "test": "yarn build && tsx --env-file .env.integration-test node_modules/.bin/vitest run", + "start": "yarn build && ./bin/happy.mjs", + "dev": "tsx src/index.ts", + "dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts", + "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts", + "prepare": "npm run build", + "prepublishOnly": "yarn build && yarn test", + "release": "release-it", + "postinstall": "node -e \"try { require('./scripts/unpack-tools.cjs').unpackTools().catch(() => {}); } catch (e) { console.log('Note: Tool unpacking will happen on first use'); }\"" + }, + "dependencies": { + "@anthropic-ai/claude-code": "^2.0.24", + "@anthropic-ai/sdk": "0.65.0", + "@modelcontextprotocol/sdk": "^1.15.1", + "@stablelib/base64": "^2.0.1", + "@stablelib/hex": "^2.0.1", + "@types/cross-spawn": "^6.0.6", + "@types/http-proxy": "^1.17.16", + "@types/ps-list": "^6.2.1", + "@types/qrcode-terminal": "^0.12.2", + "@types/react": "^19.1.9", + "@types/tmp": "^0.2.6", + "axios": "^1.10.0", + "chalk": "^5.4.1", + "cross-spawn": "^7.0.6", + "expo-server-sdk": "^3.15.0", + "fastify": "^5.5.0", + "fastify-type-provider-zod": "4.0.2", + "http-proxy": "^1.18.1", + "http-proxy-middleware": "^3.0.5", + "ink": "^6.1.0", + "open": "^10.2.0", + "ps-list": "^8.1.1", + "qrcode-terminal": "^0.12.0", + "react": "^19.1.1", + "socket.io-client": "^4.8.1", + "tar": "^7.4.3", + "tmp": "^0.2.5", + "tweetnacl": "^1.0.3", + "zod": "^3.23.8" + }, + "devDependencies": { + "@eslint/compat": "^1", + "@types/node": ">=20", + "cross-env": "^10.0.0", + "dotenv": "^16.6.1", + "eslint": "^9", + "eslint-config-prettier": "^10", + "pkgroll": "^2.14.2", + "release-it": "^19.0.4", + "shx": "^0.3.3", + "ts-node": "^10", + "tsx": "^4.20.3", + "typescript": "^5", + "vitest": "^3.2.4" + }, + "resolutions": { + "whatwg-url": "14.2.0", + "parse-path": "7.0.3", + "@types/parse-path": "7.0.3" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org" + }, + "packageManager": "yarn@1.22.22" +} diff --git a/package.json b/package.json index 6ff5ae7d..ccde346f 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "postinstall": "node -e \"try { require('./scripts/unpack-tools.cjs').unpackTools().catch(() => {}); } catch (e) { console.log('Note: Tool unpacking will happen on first use'); }\"" }, "dependencies": { - "@anthropic-ai/claude-code": "2.0.24", + "@anthropic-ai/claude-code": "^2.0.24", "@anthropic-ai/sdk": "0.65.0", "@modelcontextprotocol/sdk": "^1.15.1", "@stablelib/base64": "^2.0.1", diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 00000000..c6eedd57 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,241 @@ +# Happy CLI Scripts + +This directory contains scripts for testing, publishing, and managing happy-coder installations. + +## Dual Package Strategy + +Happy CLI is published under two package names for different use cases: + +- **`happy-coder`** (stable) - Main stable release, commands: `happy`, `happy-mcp` +- **`happy-next`** (preview) - Preview/beta releases, commands: `happy-next`, `happy-next-mcp` + +This allows users to: +1. Test preview features without affecting stable installations +2. Run both versions side-by-side for comparison +3. Gradually migrate to new features + +## Available Scripts + +### test-install.sh + +Installs happy-coder from GitHub and validates the installation works correctly. + +**Usage:** +```bash +# Install from current branch +./scripts/test-install.sh + +# Install from specific tag +./scripts/test-install.sh v0.11.3-preview.4 + +# Install from specific branch +./scripts/test-install.sh main + +# Install from commit hash +./scripts/test-install.sh abc1234 +``` + +**What it tests:** +1. happy command is available in PATH +2. `happy --version` works +3. happy-mcp command is available +4. Daemon can start and stop successfully +5. Daemon logs are created + +**Notes:** +- Uninstalls any existing happy-coder before installing +- Automatically cleans up daemon on exit +- Requires network access to GitHub + +### test-installed.sh + +Tests an already-installed happy-coder or happy-next installation without reinstalling. + +**Usage:** +```bash +# Test stable version +./scripts/test-installed.sh + +# Test preview version +./scripts/test-installed.sh happy-next +``` + +**What it tests:** +1. Command is available in PATH +2. `--version` works +3. MCP command is available +4. Daemon can start and stop successfully +5. Daemon logs are created + +**Notes:** +- Does not modify the installation +- Faster than test-install.sh +- Use this to verify an existing installation +- Supports testing both stable and preview side-by-side + +### publish-next.sh + +Publishes the project as `happy-next` for preview releases. + +**Usage:** +```bash +# Publish to npm +./scripts/publish-next.sh + +# Dry run (test without publishing) +DRY_RUN=1 ./scripts/publish-next.sh +``` + +**What it does:** +1. Backs up `package.json` +2. Replaces with `package-next.json` (changes name to `happy-next`) +3. Builds the project +4. Publishes to npm with `--tag preview` +5. Restores original `package.json` + +**Notes:** +- Requires npm publish permissions +- Published under the `preview` tag (not `latest`) +- Automatically restores package.json even if publish fails + +### unpack-tools.cjs + +Internal script called during npm install to unpack platform-specific binaries (ripgrep, etc.) from tar archives in the `tools/` directory. + +**Features:** +- Automatically detects platform and architecture +- Gracefully handles missing tar dependency during GitHub installs +- Creates `.unpacked` marker file to avoid redundant unpacking +- Lazy loads tar dependency to prevent install failures + +**Direct usage (not typically needed):** +```bash +node scripts/unpack-tools.cjs +``` + +## Common Workflows + +### Publishing a Preview Release + +```bash +# 1. Update version for preview +npm version prerelease --preid=preview + +# 2. Publish as happy-next +./scripts/publish-next.sh + +# 3. Test the published version +npm install -g happy-next +./scripts/test-installed.sh happy-next +``` + +### Testing Both Versions Side-by-Side + +```bash +# Install both packages +npm install -g happy-coder # Stable +npm install -g happy-next # Preview + +# Test stable +./scripts/test-installed.sh + +# Test preview +./scripts/test-installed.sh happy-next + +# Use either version +happy --version # Stable +happy-next --version # Preview +``` + +### Testing Local Changes + +```bash +# 1. Build locally +npm run build + +# 2. Install locally as stable +npm install -g . + +# 3. Validate the installation +./scripts/test-installed.sh +``` + +### Publishing Stable Release + +```bash +# 1. Update version +npm version patch # or minor, major + +# 2. Build and test +npm run build +npm test + +# 3. Publish to npm (as happy-coder) +npm publish + +# 4. Test the published version +npm install -g happy-coder +./scripts/test-installed.sh +``` + +## Important Notes + +### Claude Code Dependency Version + +Happy CLI currently pins `@anthropic-ai/claude-code` to version **2.0.24** because: +- Versions 2.0.25+ removed the SDK exports (`sdk.mjs`, `sdk.d.ts`) +- We depend on these SDK types for integration +- Version 2.0.24 is the latest with full SDK support + +**Do not update** to newer versions of `@anthropic-ai/claude-code` without verifying the SDK is still exported. + +### Package Names and Commands + +| Package | Commands | Use Case | +|---------|----------|----------| +| `happy-coder` | `happy`, `happy-mcp` | Stable releases | +| `happy-next` | `happy-next`, `happy-next-mcp` | Preview/beta releases | + +Both packages share the same codebase but use different command names to avoid conflicts. + +## Troubleshooting + +### "happy command not found" + +The installation may have failed. Check: +1. npm install output for errors +2. Try: `npm install -g happy-coder` +3. Verify npm global bin directory is in PATH: `npm bin -g` + +### Daemon fails to start + +1. Check if another daemon is running: `happy daemon status` +2. Stop existing daemon: `happy daemon stop` +3. Check logs in `~/.happy-dev/logs/` + +### Installation from GitHub fails + +This can happen due to: +1. Network issues downloading binaries +2. Branch/tag not pushed to remote +3. Missing dependencies (the `prepare` script should handle this) + +Try: +- Installing from npm registry instead: `npm install -g happy-coder` +- Running the install command again (sometimes transient network issues) +- Installing from a released tag instead of a branch + +### Both versions installed but want to use specific one + +If you have both `happy-coder` and `happy-next` installed: +```bash +# Use stable explicitly +command -v happy + +# Use preview explicitly +command -v happy-next + +# Uninstall one if needed +npm uninstall -g happy-coder # Remove stable +npm uninstall -g happy-next # Remove preview +``` diff --git a/scripts/publish-next.sh b/scripts/publish-next.sh new file mode 100755 index 00000000..8673e5b7 --- /dev/null +++ b/scripts/publish-next.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash + +# Script to publish preview releases as happy-next package +# This allows users to install both stable (happy) and preview (happy-next) side-by-side + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +print_step() { + echo -e "${YELLOW}==>${NC} $1" +} + +print_success() { + echo -e "${GREEN}✓${NC} $1" +} + +print_error() { + echo -e "${RED}✗${NC} $1" +} + +echo "" +print_step "Publishing happy-next preview release..." +echo "" + +# Check if we're in the right directory +if [ ! -f "package.json" ] || [ ! -f "package-next.json" ]; then + print_error "Must be run from the project root directory" + exit 1 +fi + +# Backup original package.json +print_step "Backing up package.json..." +cp package.json package.json.backup +print_success "Backup created" +echo "" + +# Cleanup function +cleanup() { + if [ -f "package.json.backup" ]; then + print_step "Restoring package.json..." + mv package.json.backup package.json + print_success "Restored" + fi +} + +trap cleanup EXIT + +# Replace package.json with package-next.json +print_step "Switching to happy-next configuration..." +cp package-next.json package.json +print_success "Switched to happy-next" +echo "" + +# Build the project +print_step "Building project..." +npm run build +print_success "Build complete" +echo "" + +# Run tests (optional - comment out if too slow) +# print_step "Running tests..." +# npm run test +# print_success "Tests passed" +# echo "" + +# Get version from package.json +VERSION=$(node -p "require('./package.json').version") + +# Publish +print_step "Publishing happy-next@$VERSION to npm..." +if [ "$DRY_RUN" = "1" ]; then + print_step "DRY RUN - would publish with: npm publish --tag preview" + npm publish --dry-run +else + npm publish --tag preview + print_success "Published happy-next@$VERSION" +fi +echo "" + +# Final message +echo "" +echo "=========================================" +print_success "Publish complete!" +echo "=========================================" +echo "" +echo "Users can now install:" +echo " npm install -g happy-next # Latest preview" +echo " npm install -g happy-next@$VERSION # Specific version" +echo "" +echo "Commands available after install:" +echo " happy-next # Preview CLI" +echo " happy-next-mcp # Preview MCP server" +echo "" diff --git a/scripts/test-install.sh b/scripts/test-install.sh new file mode 100755 index 00000000..352f2e62 --- /dev/null +++ b/scripts/test-install.sh @@ -0,0 +1,167 @@ +#!/usr/bin/env bash + +# Test script to install latest preview and validate basic functionality +# Usage: ./scripts/test-install.sh [tag|branch|commit] +# Examples: +# ./scripts/test-install.sh # Uses current branch +# ./scripts/test-install.sh v0.11.3-preview.4 # Uses specific tag +# ./scripts/test-install.sh main # Uses main branch + +set -e # Exit on error + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Function to print colored output +print_step() { + echo -e "${YELLOW}==>${NC} $1" +} + +print_success() { + echo -e "${GREEN}✓${NC} $1" +} + +print_error() { + echo -e "${RED}✗${NC} $1" +} + +# Cleanup function +cleanup() { + print_step "Cleaning up..." + if [ -f "$HOME/.happy-dev/daemon.pid" ]; then + happy daemon stop 2>/dev/null || true + fi +} + +# Set trap to cleanup on exit +trap cleanup EXIT + +# Start test +echo "" +print_step "Starting installation test for happy-coder..." +echo "" + +# Determine what to install +if [ -n "$1" ]; then + # Use provided argument (tag, branch, or commit) + REF="$1" + print_step "Installing from specified ref: $REF" +else + # Use current branch + CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + REF="$CURRENT_BRANCH" + print_step "Installing from current branch: $REF" +fi +echo "" + +# Uninstall any existing version +print_step "Uninstalling any existing version..." +npm uninstall -g happy-coder 2>/dev/null || true +print_success "Cleanup complete" +echo "" + +# Install from GitHub +print_step "Installing from GitHub: slopus/happy-cli#$REF" +if npm install -g "github:slopus/happy-cli#$REF" 2>&1 | tee /tmp/npm-install.log; then + print_success "Installation complete" +else + print_error "Installation failed" + echo "" + echo "Last 20 lines of npm install output:" + tail -20 /tmp/npm-install.log + exit 1 +fi +echo "" + +# Test 1: Check if happy command exists +print_step "Test 1: Checking if 'happy' command is available..." +if command -v happy &> /dev/null; then + print_success "'happy' command found in PATH" +else + print_error "'happy' command not found in PATH" + exit 1 +fi +echo "" + +# Test 2: Check version +print_step "Test 2: Checking 'happy --version'..." +VERSION_OUTPUT=$(happy --version 2>&1) +if [ $? -eq 0 ]; then + print_success "Version check succeeded: $VERSION_OUTPUT" +else + print_error "Version check failed" + exit 1 +fi +echo "" + +# Test 3: Check if happy-mcp exists +print_step "Test 3: Checking if 'happy-mcp' command is available..." +if command -v happy-mcp &> /dev/null; then + print_success "'happy-mcp' command found in PATH" +else + print_error "'happy-mcp' command not found in PATH" + exit 1 +fi +echo "" + +# Test 4: Start daemon (with timeout) +print_step "Test 4: Starting daemon (30 second timeout)..." +timeout 30s happy daemon start & +DAEMON_PID=$! + +# Wait a bit for daemon to start +sleep 3 + +# Check if daemon started successfully +if happy daemon status 2>&1 | grep -q "running"; then + print_success "Daemon started successfully" + + # Stop the daemon + print_step "Stopping daemon..." + happy daemon stop + sleep 2 + + if happy daemon status 2>&1 | grep -q "not running"; then + print_success "Daemon stopped successfully" + else + print_error "Daemon failed to stop cleanly" + fi +else + print_error "Daemon failed to start" + # Kill the timeout process if still running + kill $DAEMON_PID 2>/dev/null || true + exit 1 +fi +echo "" + +# Test 5: Verify daemon logs were created +print_step "Test 5: Checking daemon logs..." +if [ -d "$HOME/.happy-dev/logs" ]; then + LOG_COUNT=$(find "$HOME/.happy-dev/logs" -name "*daemon.log" -type f | wc -l) + if [ "$LOG_COUNT" -gt 0 ]; then + print_success "Found $LOG_COUNT daemon log file(s)" + else + print_error "No daemon log files found" + fi +else + print_error "Logs directory not found" +fi +echo "" + +# Final summary +echo "" +echo "=========================================" +print_success "All tests passed!" +echo "=========================================" +echo "" +echo "Installation details:" +echo " Version: $VERSION_OUTPUT" +echo " Ref: $REF" +echo " Commands: happy, happy-mcp" +echo "" +echo "To uninstall:" +echo " npm uninstall -g happy-coder" +echo "" diff --git a/scripts/test-installed.sh b/scripts/test-installed.sh new file mode 100755 index 00000000..e7d2b149 --- /dev/null +++ b/scripts/test-installed.sh @@ -0,0 +1,150 @@ +#!/usr/bin/env bash + +# Test script to validate an already-installed happy-coder or happy-next installation +# Usage: ./scripts/test-installed.sh [happy|happy-next] +# Examples: +# ./scripts/test-installed.sh # Tests 'happy' (stable) +# ./scripts/test-installed.sh happy-next # Tests 'happy-next' (preview) + +set -e # Exit on error + +# Determine which command to test +if [ "$1" = "happy-next" ]; then + HAPPY_CMD="happy-next" + HAPPY_MCP_CMD="happy-next-mcp" + PACKAGE_NAME="happy-next" +else + HAPPY_CMD="happy" + HAPPY_MCP_CMD="happy-mcp" + PACKAGE_NAME="happy-coder" +fi + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Function to print colored output +print_step() { + echo -e "${YELLOW}==>${NC} $1" +} + +print_success() { + echo -e "${GREEN}✓${NC} $1" +} + +print_error() { + echo -e "${RED}✗${NC} $1" +} + +# Cleanup function +cleanup() { + if [ -f "$HOME/.happy-dev/daemon.pid" ]; then + print_step "Stopping daemon..." + $HAPPY_CMD daemon stop 2>/dev/null || true + fi +} + +# Set trap to cleanup on exit +trap cleanup EXIT + +# Start test +echo "" +print_step "Testing installed $PACKAGE_NAME..." +echo "" + +# Test 1: Check if command exists +print_step "Test 1: Checking if '$HAPPY_CMD' command is available..." +if command -v $HAPPY_CMD &> /dev/null; then + HAPPY_PATH=$(which $HAPPY_CMD) + print_success "'$HAPPY_CMD' command found at: $HAPPY_PATH" +else + print_error "'$HAPPY_CMD' command not found in PATH" + echo "" + echo "Please install $PACKAGE_NAME first:" + echo " npm install -g $PACKAGE_NAME" + exit 1 +fi +echo "" + +# Test 2: Check version +print_step "Test 2: Checking '$HAPPY_CMD --version'..." +VERSION_OUTPUT=$($HAPPY_CMD --version 2>&1) +if [ $? -eq 0 ]; then + print_success "Version check succeeded: $VERSION_OUTPUT" +else + print_error "Version check failed" + exit 1 +fi +echo "" + +# Test 3: Check if mcp command exists +print_step "Test 3: Checking if '$HAPPY_MCP_CMD' command is available..." +if command -v $HAPPY_MCP_CMD &> /dev/null; then + HAPPY_MCP_PATH=$(which $HAPPY_MCP_CMD) + print_success "'$HAPPY_MCP_CMD' command found at: $HAPPY_MCP_PATH" +else + print_error "'$HAPPY_MCP_CMD' command not found in PATH" + exit 1 +fi +echo "" + +# Test 4: Start daemon (with timeout) +print_step "Test 4: Starting daemon (will timeout after 30s and that's expected)..." +timeout 30s $HAPPY_CMD daemon start > /dev/null 2>&1 & +DAEMON_PID=$! + +# Wait a bit for daemon to start +sleep 5 + +# Check if daemon started successfully +if $HAPPY_CMD daemon status 2>&1 | grep -q "running"; then + print_success "Daemon started successfully" + + # Stop the daemon + print_step "Stopping daemon..." + $HAPPY_CMD daemon stop + sleep 2 + + if $HAPPY_CMD daemon status 2>&1 | grep -q "not running"; then + print_success "Daemon stopped successfully" + else + print_error "Daemon failed to stop cleanly" + fi +else + print_error "Daemon failed to start" + # Kill the timeout process if still running + kill $DAEMON_PID 2>/dev/null || true + exit 1 +fi +echo "" + +# Test 5: Verify daemon logs were created +print_step "Test 5: Checking daemon logs..." +if [ -d "$HOME/.happy-dev/logs" ]; then + LOG_COUNT=$(find "$HOME/.happy-dev/logs" -name "*daemon.log" -type f 2>/dev/null | wc -l) + if [ "$LOG_COUNT" -gt 0 ]; then + LATEST_LOG=$(find "$HOME/.happy-dev/logs" -name "*daemon.log" -type f 2>/dev/null | sort | tail -1) + print_success "Found $LOG_COUNT daemon log file(s)" + echo " Latest: $LATEST_LOG" + else + print_error "No daemon log files found" + fi +else + print_error "Logs directory not found" +fi +echo "" + +# Final summary +echo "" +echo "=========================================" +print_success "All tests passed!" +echo "=========================================" +echo "" +echo "Installation details:" +echo " Package: $PACKAGE_NAME" +echo " Version: $VERSION_OUTPUT" +echo " $HAPPY_CMD: $HAPPY_PATH" +echo " $HAPPY_MCP_CMD: $HAPPY_MCP_PATH" +echo "" diff --git a/yarn.lock b/yarn.lock index 396b81f4..8f8e5410 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,7 +10,7 @@ ansi-styles "^6.2.1" is-fullwidth-code-point "^5.0.0" -"@anthropic-ai/claude-code@2.0.24": +"@anthropic-ai/claude-code@^2.0.24": version "2.0.24" resolved "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.0.24.tgz" integrity sha512-6f/AXoTi3SmFYZl42l6L8brdPSkL+MDQWesRBJwgZy3enNI0LaVn1j/6RxQ7toPKnIyChCN0r6hZi61N8znzzQ== @@ -595,6 +595,11 @@ resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.3.tgz" integrity sha512-F42IgZI4JicE2vM2PWCe0N5mR5vR0gIdORPqhGQ32/u1S1v3kLtbZ0C/mi9FFk7C5T0PgdeyWEPajPjaUpyoKg== +"@rollup/rollup-linux-x64-musl@4.46.3": + version "4.46.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.3.tgz" + integrity sha512-oLc+JrwwvbimJUInzx56Q3ujL3Kkhxehg7O1gWAYzm8hImCd5ld1F2Gry5YDjR21MNb5WCKhC9hXgU7rRlyegQ== + "@socket.io/component-emitter@~3.1.0": version "3.1.2" resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz" @@ -3057,7 +3062,7 @@ ps-list@*, ps-list@^8.1.1: resolved "https://registry.npmjs.org/ps-list/-/ps-list-8.1.1.tgz" integrity sha512-OPS9kEJYVmiO48u/B9qneqhkMvgCxT+Tm28VCEJpheTpl8cJ0ffZRRNgS5mrQRTrX5yRTpaJ+hRDeefXYmmorQ== -punycode@^2.1.0, punycode@^2.3.1: +punycode@^2.1.0: version "2.3.1" resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -3714,12 +3719,10 @@ toidentifier@1.0.1: resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -tr46@^5.1.0: - version "5.1.1" - resolved "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz" - integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw== - dependencies: - punycode "^2.3.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== ts-algebra@^2.0.0: version "2.0.0" @@ -3897,18 +3900,18 @@ vitest@^3.2.4: vite-node "3.2.4" why-is-node-running "^2.3.0" -webidl-conversions@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" - integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== whatwg-url@^5.0.0: - version "14.2.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz" - integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw== + version "5.0.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: - tr46 "^5.1.0" - webidl-conversions "^7.0.0" + tr46 "~0.0.3" + webidl-conversions "^3.0.0" which@^2.0.1: version "2.0.2" From a78f082e01c3908c5fccc5a118e1e2f7f9606310 Mon Sep 17 00:00:00 2001 From: James White Date: Mon, 17 Nov 2025 19:46:38 +0000 Subject: [PATCH 13/35] feat(sync-upstream): add automated daily sync from upstream repo - Add GitHub Actions workflow to automatically fetch, merge, and push changes from upstream slopus/happy-cli repository daily at 2 AM UTC - Implement conflict detection and create GitHub issues for manual intervention when merge conflicts occur - Add sync-upstream.sh script for manual syncing with dry-run, merge, and push support - Include documentation for installation and syncing process in INSTALL.md and scripts/README.md Co-authored-by: terragon-labs[bot] --- .github/workflows/sync-upstream.yml | 172 ++++++++++++++++++++++++++++ INSTALL.md | 133 +++++++++++++++++++++ scripts/README.md | 49 ++++++++ scripts/sync-upstream.sh | 156 +++++++++++++++++++++++++ 4 files changed, 510 insertions(+) create mode 100644 .github/workflows/sync-upstream.yml create mode 100644 INSTALL.md create mode 100755 scripts/sync-upstream.sh diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml new file mode 100644 index 00000000..51b5038f --- /dev/null +++ b/.github/workflows/sync-upstream.yml @@ -0,0 +1,172 @@ +name: Sync from Upstream + +on: + schedule: + # Run daily at 2 AM UTC + - cron: '0 2 * * *' + workflow_dispatch: # Allow manual trigger + +jobs: + sync: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Add upstream remote + run: | + git remote add upstream https://github.com/slopus/happy-cli.git || true + git fetch upstream + + - name: Check for upstream changes + id: check + run: | + # Get the latest commit from upstream main + UPSTREAM_COMMIT=$(git rev-parse upstream/main) + # Get the latest commit we've merged from upstream (if any) + LAST_SYNC=$(git log --grep="Sync from upstream" --format="%H" -n 1 || echo "") + + if [ -z "$LAST_SYNC" ]; then + echo "has_changes=true" >> $GITHUB_OUTPUT + echo "No previous sync found" + else + # Check if there are new commits + NEW_COMMITS=$(git rev-list $LAST_SYNC..upstream/main --count) + if [ "$NEW_COMMITS" -gt 0 ]; then + echo "has_changes=true" >> $GITHUB_OUTPUT + echo "Found $NEW_COMMITS new commits" + else + echo "has_changes=false" >> $GITHUB_OUTPUT + echo "No new commits" + fi + fi + + - name: Attempt automatic merge + if: steps.check.outputs.has_changes == 'true' + id: merge + run: | + # Try to merge upstream/main into current branch + if git merge upstream/main --no-edit -m "chore: sync from upstream slopus/happy-cli"; then + echo "merge_success=true" >> $GITHUB_OUTPUT + echo "Merge successful" + else + echo "merge_success=false" >> $GITHUB_OUTPUT + echo "Merge conflicts detected" + git merge --abort + fi + + - name: Push changes + if: steps.check.outputs.has_changes == 'true' && steps.merge.outputs.merge_success == 'true' + run: | + git push origin main + echo "Changes pushed successfully" + + - name: Create issue for merge conflicts + if: steps.check.outputs.has_changes == 'true' && steps.merge.outputs.merge_success == 'false' + uses: actions/github-script@v7 + with: + script: | + const { data: issues } = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: 'upstream-sync' + }); + + // Don't create duplicate issues + if (issues.length > 0) { + console.log('Issue already exists for upstream sync conflicts'); + return; + } + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: 'Manual intervention needed: Upstream sync has conflicts', + labels: ['upstream-sync', 'needs-attention'], + body: `The automatic sync from upstream (slopus/happy-cli) has merge conflicts. + +**Manual steps required:** + +\`\`\`bash +# Fetch latest from upstream +git fetch upstream + +# Attempt merge +git merge upstream/main + +# Resolve conflicts manually, then: +git add . +git commit -m "chore: sync from upstream (resolved conflicts)" +git push origin main +\`\`\` + +**Alternative - Rebase approach:** + +\`\`\`bash +# Create a new branch for the sync +git checkout -b sync-upstream-$(date +%Y%m%d) +git fetch upstream +git rebase upstream/main + +# Resolve conflicts, then: +git rebase --continue +git push origin sync-upstream-$(date +%Y%m%d) + +# Create PR to merge into main +\`\`\` + +This issue will be automatically closed when the next automatic sync succeeds. +` + }); + + - name: Close resolved sync issues + if: steps.check.outputs.has_changes == 'true' && steps.merge.outputs.merge_success == 'true' + uses: actions/github-script@v7 + with: + script: | + const { data: issues } = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: 'upstream-sync' + }); + + for (const issue of issues) { + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + state: 'closed' + }); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: 'Sync from upstream succeeded. Closing this issue.' + }); + } + + - name: Summary + if: always() + run: | + echo "## Sync Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "${{ steps.check.outputs.has_changes }}" == "false" ]; then + echo "✓ No new changes from upstream" >> $GITHUB_STEP_SUMMARY + elif [ "${{ steps.merge.outputs.merge_success }}" == "true" ]; then + echo "✓ Successfully merged changes from upstream" >> $GITHUB_STEP_SUMMARY + else + echo "⚠️ Merge conflicts detected - manual intervention required" >> $GITHUB_STEP_SUMMARY + fi diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 00000000..0775b0d4 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,133 @@ +# Installing Happy CLI + +## Quick Install (Windows) + +Install the latest preview from GitHub: + +```powershell +npm install -g github:jakenuts/happy-cli#latest-preview +``` + +This gives you: +- `happy` - Main CLI command +- `happy-mcp` - MCP server command + +## Install Specific Version + +```powershell +# Install specific preview version +npm install -g github:jakenuts/happy-cli#v0.11.3-preview.5 + +# Install from main branch +npm install -g github:jakenuts/happy-cli#main +``` + +## Verify Installation + +```powershell +# Check version +happy --version + +# Check daemon status +happy daemon status + +# Start daemon +happy daemon start +``` + +## From NPM (Once Published) + +When published to npm: + +```powershell +# Install stable +npm install -g happy-coder + +# Install preview (side-by-side with stable) +npm install -g happy-next +``` + +## Troubleshooting + +### Installation Fails with EOF Error + +This is usually a transient network issue downloading binaries. Try: +1. Run the install command again +2. Clear npm cache: `npm cache clean --force` +3. Try again + +### "happy command not found" + +Ensure npm's global bin directory is in your PATH: + +```powershell +# Check where npm installs global packages +npm bin -g + +# On Windows, should output something like: +# C:\Users\YourName\AppData\Roaming\npm + +# Verify it's in PATH +$env:PATH -split ';' | Select-String npm +``` + +If not in PATH, add it: +1. Search for "Environment Variables" in Windows +2. Edit user or system PATH +3. Add the npm bin directory +4. Restart PowerShell + +### Update to Latest Preview + +```powershell +# Uninstall current version +npm uninstall -g happy-coder + +# Install latest +npm install -g github:jakenuts/happy-cli#latest-preview +``` + +## Development Install + +If you have the repo cloned locally: + +```bash +# Build the project +npm run build + +# Install globally from local directory +npm install -g . + +# Test it works +happy --version +``` + +## Repository Information + +- **Fork (active development):** https://github.com/jakenuts/happy-cli +- **Upstream:** https://github.com/slopus/happy-cli +- **Server:** https://api.happy-servers.com + +## What's Installed + +When you install Happy CLI, you get: + +1. **Commands:** + - `happy` - Main CLI + - `happy-mcp` - MCP server for Claude integration + +2. **Config Directory:** + - `~/.happy-dev/` (or `$HAPPY_HOME_DIR`) + - Contains logs, daemon PID, access keys + +3. **Dependencies:** + - Claude Code SDK (2.0.24) + - Platform-specific binaries (ripgrep, etc.) + +## Uninstall + +```powershell +npm uninstall -g happy-coder +``` + +This removes the commands but leaves your config directory (`~/.happy-dev/`) intact. diff --git a/scripts/README.md b/scripts/README.md index c6eedd57..7a84c408 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -98,6 +98,33 @@ DRY_RUN=1 ./scripts/publish-next.sh - Published under the `preview` tag (not `latest`) - Automatically restores package.json even if publish fails +### sync-upstream.sh + +Syncs changes from upstream slopus/happy-cli repository into your fork. + +**Usage:** +```bash +# Preview what would be synced (no changes made) +./scripts/sync-upstream.sh --dry-run + +# Sync changes from upstream +./scripts/sync-upstream.sh +``` + +**What it does:** +1. Checks for uncommitted changes (blocks if found) +2. Fetches latest from upstream +3. Shows commits and files that will change +4. Attempts automatic merge +5. Prompts to push if successful +6. Provides conflict resolution instructions if needed + +**Notes:** +- Requires clean working directory +- Interactive - prompts for confirmation +- Safe to run anytime +- Also automated via GitHub Actions (daily at 2 AM UTC) + ### unpack-tools.cjs Internal script called during npm install to unpack platform-specific binaries (ripgrep, etc.) from tar archives in the `tools/` directory. @@ -115,6 +142,28 @@ node scripts/unpack-tools.cjs ## Common Workflows +### Syncing from Upstream + +Keep your fork up-to-date with slopus/happy-cli: + +```bash +# Check what would be synced (safe, no changes) +./scripts/sync-upstream.sh --dry-run + +# Sync changes +./scripts/sync-upstream.sh + +# Manual sync if needed +git fetch upstream +git merge upstream/main +``` + +**Automatic sync:** +- GitHub Actions runs daily at 2 AM UTC +- Auto-merges if no conflicts +- Creates issue if conflicts detected +- Issue auto-closes when resolved + ### Publishing a Preview Release ```bash diff --git a/scripts/sync-upstream.sh b/scripts/sync-upstream.sh new file mode 100755 index 00000000..58444279 --- /dev/null +++ b/scripts/sync-upstream.sh @@ -0,0 +1,156 @@ +#!/usr/bin/env bash + +# Manual script to sync changes from upstream slopus/happy-cli +# Usage: ./scripts/sync-upstream.sh [--dry-run] + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_step() { + echo -e "${YELLOW}==>${NC} $1" +} + +print_success() { + echo -e "${GREEN}✓${NC} $1" +} + +print_error() { + echo -e "${RED}✗${NC} $1" +} + +print_info() { + echo -e "${BLUE}ℹ${NC} $1" +} + +DRY_RUN=false +if [ "$1" = "--dry-run" ]; then + DRY_RUN=true + print_info "Running in DRY RUN mode - no changes will be made" +fi + +echo "" +print_step "Syncing from upstream slopus/happy-cli..." +echo "" + +# Check if we're in a git repo +if ! git rev-parse --git-dir > /dev/null 2>&1; then + print_error "Not in a git repository" + exit 1 +fi + +# Check for uncommitted changes +if ! git diff-index --quiet HEAD --; then + print_error "You have uncommitted changes. Please commit or stash them first." + git status --short + exit 1 +fi + +# Ensure upstream remote exists +print_step "Checking upstream remote..." +if ! git remote get-url upstream > /dev/null 2>&1; then + print_step "Adding upstream remote..." + if [ "$DRY_RUN" = false ]; then + git remote add upstream https://github.com/slopus/happy-cli.git + fi + print_success "Upstream remote added" +else + print_success "Upstream remote exists" +fi +echo "" + +# Fetch upstream +print_step "Fetching from upstream..." +if [ "$DRY_RUN" = false ]; then + git fetch upstream +fi +print_success "Fetch complete" +echo "" + +# Check current branch +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +print_info "Current branch: $CURRENT_BRANCH" +echo "" + +# Show what would be merged +print_step "Changes from upstream:" +NEW_COMMITS=$(git rev-list HEAD..upstream/main --count 2>/dev/null || echo "0") + +if [ "$NEW_COMMITS" -eq 0 ]; then + print_success "Already up to date with upstream" + exit 0 +fi + +print_info "Found $NEW_COMMITS new commit(s) from upstream" +echo "" +git log --oneline --graph HEAD..upstream/main | head -20 +echo "" + +# Show files that will be affected +print_step "Files that will be modified:" +git diff --name-status HEAD..upstream/main | head -20 +echo "" + +if [ "$DRY_RUN" = true ]; then + print_info "DRY RUN: Would attempt to merge upstream/main into $CURRENT_BRANCH" + echo "" + echo "To perform the actual merge, run:" + echo " ./scripts/sync-upstream.sh" + exit 0 +fi + +# Ask for confirmation +read -p "Merge these changes into $CURRENT_BRANCH? (y/N) " -n 1 -r +echo "" + +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_info "Sync cancelled" + exit 0 +fi + +echo "" +print_step "Attempting merge..." + +# Try to merge +if git merge upstream/main --no-edit -m "chore: sync from upstream slopus/happy-cli"; then + print_success "Merge successful!" + echo "" + + # Ask if we should push + read -p "Push changes to origin? (y/N) " -n 1 -r + echo "" + + if [[ $REPLY =~ ^[Yy]$ ]]; then + print_step "Pushing to origin..." + git push origin $CURRENT_BRANCH + print_success "Push complete" + else + print_info "Changes merged locally but not pushed" + print_info "To push later, run: git push origin $CURRENT_BRANCH" + fi +else + print_error "Merge conflicts detected!" + echo "" + echo "Conflicts in the following files:" + git diff --name-only --diff-filter=U + echo "" + echo "To resolve:" + echo " 1. Fix conflicts in the files listed above" + echo " 2. Run: git add " + echo " 3. Run: git commit" + echo " 4. Run: git push origin $CURRENT_BRANCH" + echo "" + echo "To abort the merge:" + echo " git merge --abort" + exit 1 +fi + +echo "" +echo "=========================================" +print_success "Sync complete!" +echo "=========================================" From 8962d2e8e3ce53a2c5588eb76c85961c8b5ef366 Mon Sep 17 00:00:00 2001 From: James White Date: Mon, 17 Nov 2025 19:58:32 +0000 Subject: [PATCH 14/35] feat: rename package to happy-next for side-by-side installation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change package name from happy-coder to happy-next - Update commands to happy-next and happy-next-mcp - Update repository references to jakenuts/happy-cli fork - Add comprehensive installation guide with side-by-side setup - Allow stable (happy) and preview (happy-next) to coexist This enables users to test the preview fork without affecting their stable installation from the upstream repo. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- INSTALL.md | 60 ++++++++++++++++++++++++++++++++++------------------ package.json | 16 +++++++------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 0775b0d4..e66fd283 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -9,8 +9,10 @@ npm install -g github:jakenuts/happy-cli#latest-preview ``` This gives you: -- `happy` - Main CLI command -- `happy-mcp` - MCP server command +- `happy-next` - Main CLI command +- `happy-next-mcp` - MCP server command + +**Note:** This installs as `happy-next` so it won't conflict with the stable `happy` version from the upstream repo. ## Install Specific Version @@ -18,33 +20,40 @@ This gives you: # Install specific preview version npm install -g github:jakenuts/happy-cli#v0.11.3-preview.5 -# Install from main branch -npm install -g github:jakenuts/happy-cli#main +# Install from a specific tag +npm install -g github:jakenuts/happy-cli#latest-preview ``` ## Verify Installation ```powershell # Check version -happy --version +happy-next --version # Check daemon status -happy daemon status +happy-next daemon status # Start daemon -happy daemon start +happy-next daemon start ``` -## From NPM (Once Published) +## Side-by-Side with Stable -When published to npm: +You can install both the stable upstream version and this preview fork: ```powershell -# Install stable -npm install -g happy-coder +# Install stable from upstream (slopus/happy-cli) +npm install -g github:slopus/happy-cli + +# Install preview fork (jakenuts/happy-cli) +npm install -g github:jakenuts/happy-cli#latest-preview -# Install preview (side-by-side with stable) -npm install -g happy-next +# Use either version +happy --version # Stable (upstream) +happy-next --version # Preview (fork) + +happy daemon start # Stable daemon +happy-next daemon start # Preview daemon ``` ## Troubleshooting @@ -56,7 +65,7 @@ This is usually a transient network issue downloading binaries. Try: 2. Clear npm cache: `npm cache clean --force` 3. Try again -### "happy command not found" +### "happy-next command not found" Ensure npm's global bin directory is in your PATH: @@ -81,7 +90,7 @@ If not in PATH, add it: ```powershell # Uninstall current version -npm uninstall -g happy-coder +npm uninstall -g happy-next # Install latest npm install -g github:jakenuts/happy-cli#latest-preview @@ -99,7 +108,7 @@ npm run build npm install -g . # Test it works -happy --version +happy-next --version ``` ## Repository Information @@ -110,15 +119,16 @@ happy --version ## What's Installed -When you install Happy CLI, you get: +When you install Happy CLI Next (preview fork), you get: 1. **Commands:** - - `happy` - Main CLI - - `happy-mcp` - MCP server for Claude integration + - `happy-next` - Main CLI + - `happy-next-mcp` - MCP server for Claude integration 2. **Config Directory:** - `~/.happy-dev/` (or `$HAPPY_HOME_DIR`) - Contains logs, daemon PID, access keys + - **Shared with stable version** if both are installed 3. **Dependencies:** - Claude Code SDK (2.0.24) @@ -127,7 +137,17 @@ When you install Happy CLI, you get: ## Uninstall ```powershell -npm uninstall -g happy-coder +npm uninstall -g happy-next ``` This removes the commands but leaves your config directory (`~/.happy-dev/`) intact. + +## Comparison: Stable vs Preview + +| Feature | Stable (`happy`) | Preview Fork (`happy-next`) | +|---------|------------------|---------------------------| +| Source | slopus/happy-cli | jakenuts/happy-cli | +| Install | `npm install -g github:slopus/happy-cli` | `npm install -g github:jakenuts/happy-cli#latest-preview` | +| Commands | `happy`, `happy-mcp` | `happy-next`, `happy-next-mcp` | +| Updates | Upstream releases | Daily synced + fork features | +| Use Case | Stable production use | Testing new features, Codex improvements | diff --git a/package.json b/package.json index ccde346f..270893d6 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,16 @@ { - "name": "happy-coder", - "version": "0.11.3-preview.4", - "description": "Mobile and Web client for Claude Code and Codex", + "name": "happy-next", + "version": "0.11.3-preview.5", + "description": "Mobile and Web client for Claude Code and Codex - Preview Fork", "author": "Kirill Dubovitskiy", "license": "MIT", "type": "module", - "homepage": "https://github.com/slopus/happy-cli", - "bugs": "https://github.com/slopus/happy-cli/issues", - "repository": "slopus/happy-cli", + "homepage": "https://github.com/jakenuts/happy-cli", + "bugs": "https://github.com/jakenuts/happy-cli/issues", + "repository": "jakenuts/happy-cli", "bin": { - "happy": "./bin/happy.mjs", - "happy-mcp": "./bin/happy-mcp.mjs" + "happy-next": "./bin/happy.mjs", + "happy-next-mcp": "./bin/happy-mcp.mjs" }, "main": "./dist/index.cjs", "module": "./dist/index.mjs", From 2e861a34b0ab2156ce43d321896f0e5ff2713d14 Mon Sep 17 00:00:00 2001 From: James White Date: Mon, 17 Nov 2025 20:00:07 +0000 Subject: [PATCH 15/35] docs: update README for happy-next fork MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Clarify this is a preview fork with experimental features - Update all command examples to use happy-next - Add 'What's New' section highlighting fork improvements - Include side-by-side installation instructions - Link to comprehensive documentation files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 84 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 4280c213..7d9f4343 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,44 @@ -# Happy +# Happy CLI Next - Preview Fork -Code on the go controlling claude code from your mobile device. +> Code on the go controlling Claude Code from your mobile device. +> +> Free. Open source. Code anywhere. -Free. Open source. Code anywhere. +**This is a preview fork** with experimental features and improvements. For the stable version, see [slopus/happy-cli](https://github.com/slopus/happy-cli). -## Installation +## Quick Install ```bash -npm install -g happy-coder +npm install -g github:jakenuts/happy-cli#latest-preview ``` +This installs as **`happy-next`** so it won't conflict with the stable `happy` version. + +📖 **[Complete Installation Guide](./INSTALL.md)** - Side-by-side setup, troubleshooting, etc. + +## What's New in This Fork + +### 🔧 Codex Integration Fixes +- Fixed race conditions in WebSocket connections +- Added subprocess health monitoring and auto-recovery +- Windows console window fixes +- Permission handling with timeouts +- Improved error recovery and reconnection logic + +### 📦 Installation Improvements +- GitHub install support (no npm publish needed) +- Resilient postinstall script handling +- Better missing dependency recovery + +### 🔄 Upstream Sync +- Automated daily sync from upstream (slopus/happy-cli) +- Manual sync: `./scripts/sync-upstream.sh` +- Auto-merges when no conflicts + ## Usage ```bash -happy +happy-next ``` This will: @@ -23,12 +48,12 @@ This will: ## Commands -- `happy auth` – Manage authentication -- `happy codex` – Start Codex mode -- `happy connect` – Store AI vendor API keys in Happy cloud -- `happy notify` – Send a push notification to your devices -- `happy daemon` – Manage background service -- `happy doctor` – System diagnostics & troubleshooting +- `happy-next auth` – Manage authentication +- `happy-next codex` – Start Codex mode +- `happy-next connect` – Store AI vendor API keys in Happy cloud +- `happy-next notify` – Send a push notification to your devices +- `happy-next daemon` – Manage background service +- `happy-next doctor` – System diagnostics & troubleshooting ## Options @@ -47,13 +72,42 @@ This will: - `HAPPY_DISABLE_CAFFEINATE` - Disable macOS sleep prevention (set to `true`, `1`, or `yes`) - `HAPPY_EXPERIMENTAL` - Enable experimental features (set to `true`, `1`, or `yes`) +## Side-by-Side with Stable + +Run both versions simultaneously: + +```bash +# Install stable +npm install -g github:slopus/happy-cli + +# Install preview +npm install -g github:jakenuts/happy-cli#latest-preview + +# Use either +happy --version # Stable +happy-next --version # Preview +``` + +Both share the same config directory (`~/.happy-dev/`) but use different command names. + ## Requirements - Node.js >= 20.0.0 - - Required by `eventsource-parser@3.0.5`, which is required by - `@modelcontextprotocol/sdk`, which we used to implement permission forwarding - to mobile app - Claude CLI installed & logged in (`claude` command available in PATH) +- **Claude Code SDK:** Pinned to 2.0.24 (last version with SDK exports) + +## Documentation + +- 📦 [Installation Guide](./INSTALL.md) - Complete setup instructions +- 🔧 [Scripts Documentation](./scripts/README.md) - Testing, publishing, syncing +- 📚 [Codebase Overview](./CLAUDE.md) - Architecture and code style +- 🏗️ [Technical Details](./PROJECT.md) - Deep dive into implementation + +## Repository Info + +- **Fork (active):** https://github.com/jakenuts/happy-cli +- **Upstream:** https://github.com/slopus/happy-cli +- **Server:** https://api.happy-servers.com/ ## License From 7c254149ab27515814a9d8ccbbd668e5b413d3ea Mon Sep 17 00:00:00 2001 From: James White Date: Mon, 17 Nov 2025 20:18:19 +0000 Subject: [PATCH 16/35] fix: use native Node.js APIs for cross-platform build script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace shx dependency with native fs.rmSync for dist cleanup - Create scripts/build.mjs that works without devDependencies - Fix Windows install from GitHub (shx not available during prepare) - Add build:dev script for development (still uses shx) - Update all scripts to use npm run instead of yarn This fixes the 'shx is not recognized' error on Windows when installing from GitHub, as the prepare script now uses only built-in Node.js APIs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- package-next.json | 13 +++++++------ package.json | 13 +++++++------ scripts/build.mjs | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 12 deletions(-) create mode 100755 scripts/build.mjs diff --git a/package-next.json b/package-next.json index 88fa55ad..0a7436c6 100644 --- a/package-next.json +++ b/package-next.json @@ -57,14 +57,15 @@ "scripts": { "why do we need to build before running tests / dev?": "We need the binary to be built so we run daemon commands which directly run the binary - we don't want them to go out of sync or have custom spawn logic depending how we started happy", "typecheck": "tsc --noEmit", - "build": "shx rm -rf dist && npx tsc --noEmit && pkgroll", - "test": "yarn build && tsx --env-file .env.integration-test node_modules/.bin/vitest run", - "start": "yarn build && ./bin/happy.mjs", + "build": "node scripts/build.mjs", + "build:dev": "shx rm -rf dist && npx tsc --noEmit && pkgroll", + "test": "npm run build && tsx --env-file .env.integration-test node_modules/.bin/vitest run", + "start": "npm run build && ./bin/happy.mjs", "dev": "tsx src/index.ts", - "dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts", - "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts", + "dev:local-server": "npm run build && tsx --env-file .env.dev-local-server src/index.ts", + "dev:integration-test-env": "npm run build && tsx --env-file .env.integration-test src/index.ts", "prepare": "npm run build", - "prepublishOnly": "yarn build && yarn test", + "prepublishOnly": "npm run build && npm test", "release": "release-it", "postinstall": "node -e \"try { require('./scripts/unpack-tools.cjs').unpackTools().catch(() => {}); } catch (e) { console.log('Note: Tool unpacking will happen on first use'); }\"" }, diff --git a/package.json b/package.json index 270893d6..05de4616 100644 --- a/package.json +++ b/package.json @@ -57,14 +57,15 @@ "scripts": { "why do we need to build before running tests / dev?": "We need the binary to be built so we run daemon commands which directly run the binary - we don't want them to go out of sync or have custom spawn logic depending how we started happy", "typecheck": "tsc --noEmit", - "build": "shx rm -rf dist && npx tsc --noEmit && pkgroll", - "test": "yarn build && tsx --env-file .env.integration-test node_modules/.bin/vitest run", - "start": "yarn build && ./bin/happy.mjs", + "build": "node scripts/build.mjs", + "build:dev": "shx rm -rf dist && npx tsc --noEmit && pkgroll", + "test": "npm run build && tsx --env-file .env.integration-test node_modules/.bin/vitest run", + "start": "npm run build && ./bin/happy.mjs", "dev": "tsx src/index.ts", - "dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts", - "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts", + "dev:local-server": "npm run build && tsx --env-file .env.dev-local-server src/index.ts", + "dev:integration-test-env": "npm run build && tsx --env-file .env.integration-test src/index.ts", "prepare": "npm run build", - "prepublishOnly": "yarn build && yarn test", + "prepublishOnly": "npm run build && npm test", "release": "release-it", "postinstall": "node -e \"try { require('./scripts/unpack-tools.cjs').unpackTools().catch(() => {}); } catch (e) { console.log('Note: Tool unpacking will happen on first use'); }\"" }, diff --git a/scripts/build.mjs b/scripts/build.mjs new file mode 100755 index 00000000..f1a0adac --- /dev/null +++ b/scripts/build.mjs @@ -0,0 +1,37 @@ +#!/usr/bin/env node + +/** + * Cross-platform build script that works during npm install from GitHub + * Does not depend on devDependencies like shx + */ + +import { rmSync, existsSync } from 'fs'; +import { execSync } from 'child_process'; + +const distDir = 'dist'; + +// Remove dist directory if it exists (cross-platform) +if (existsSync(distDir)) { + console.log('Cleaning dist directory...'); + rmSync(distDir, { recursive: true, force: true }); +} + +// Run TypeScript type checking +console.log('Type checking...'); +try { + execSync('npx tsc --noEmit', { stdio: 'inherit' }); +} catch (error) { + console.error('Type checking failed'); + process.exit(1); +} + +// Run pkgroll to build +console.log('Building with pkgroll...'); +try { + execSync('npx pkgroll', { stdio: 'inherit' }); +} catch (error) { + console.error('Build failed'); + process.exit(1); +} + +console.log('Build complete!'); From 35aeccdeb1e6d7973cf2c2a03f56e1f3aa4532ab Mon Sep 17 00:00:00 2001 From: James White Date: Mon, 17 Nov 2025 20:32:37 +0000 Subject: [PATCH 17/35] fix: skip type checking during GitHub install MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Detect if typescript is available in node_modules - Skip type check during prepare phase (GitHub install) - Only run pkgroll build during GitHub install - Full type check + build for local development Fixes 'tsc: not found' error during GitHub install. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- scripts/build.mjs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/scripts/build.mjs b/scripts/build.mjs index f1a0adac..74648629 100755 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -3,12 +3,21 @@ /** * Cross-platform build script that works during npm install from GitHub * Does not depend on devDependencies like shx + * + * During GitHub install (prepare phase): + * - Skips type checking (typescript not installed yet) + * - Only runs pkgroll build + * + * During local development: + * - Runs full type checking + build */ import { rmSync, existsSync } from 'fs'; import { execSync } from 'child_process'; +import { resolve } from 'path'; const distDir = 'dist'; +const isGitHubInstall = !existsSync(resolve('node_modules/typescript')); // Remove dist directory if it exists (cross-platform) if (existsSync(distDir)) { @@ -16,13 +25,17 @@ if (existsSync(distDir)) { rmSync(distDir, { recursive: true, force: true }); } -// Run TypeScript type checking -console.log('Type checking...'); -try { - execSync('npx tsc --noEmit', { stdio: 'inherit' }); -} catch (error) { - console.error('Type checking failed'); - process.exit(1); +// Run TypeScript type checking (skip during GitHub install) +if (isGitHubInstall) { + console.log('Skipping type check (GitHub install - typescript not available yet)'); +} else { + console.log('Type checking...'); + try { + execSync('npx tsc --noEmit', { stdio: 'inherit' }); + } catch (error) { + console.error('Type checking failed'); + process.exit(1); + } } // Run pkgroll to build From f22a445b48e394ff4f3f6853dcecbd62643389e4 Mon Sep 17 00:00:00 2001 From: James White Date: Mon, 17 Nov 2025 20:34:32 +0000 Subject: [PATCH 18/35] chore: commit dist folder for GitHub installs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove dist from gitignore to enable GitHub installs - Commit built artifacts so prepare script can skip build - Eliminates need for devDependencies (typescript, pkgroll) during install This allows users to install directly from GitHub without build failures. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .gitignore | 2 +- dist/codex/happyMcpStdioBridge.cjs | 80 + dist/codex/happyMcpStdioBridge.d.cts | 2 + dist/codex/happyMcpStdioBridge.d.mts | 2 + dist/codex/happyMcpStdioBridge.mjs | 78 + dist/index-CcjVa7OK.cjs | 6135 ++++++++++++++++++++++++++ dist/index-kjZLUW3I.mjs | 6105 +++++++++++++++++++++++++ dist/index.cjs | 41 + dist/index.d.cts | 1 + dist/index.d.mts | 1 + dist/index.mjs | 38 + dist/lib.cjs | 31 + dist/lib.d.cts | 823 ++++ dist/lib.d.mts | 823 ++++ dist/lib.mjs | 21 + dist/runCodex-CRpVyA_X.cjs | 1480 +++++++ dist/runCodex-DrPAcday.mjs | 1477 +++++++ dist/types-B6U1wuBR.mjs | 2182 +++++++++ dist/types-QJg7LeZh.cjs | 2228 ++++++++++ 19 files changed, 21549 insertions(+), 1 deletion(-) create mode 100644 dist/codex/happyMcpStdioBridge.cjs create mode 100644 dist/codex/happyMcpStdioBridge.d.cts create mode 100644 dist/codex/happyMcpStdioBridge.d.mts create mode 100644 dist/codex/happyMcpStdioBridge.mjs create mode 100644 dist/index-CcjVa7OK.cjs create mode 100644 dist/index-kjZLUW3I.mjs create mode 100644 dist/index.cjs create mode 100644 dist/index.d.cts create mode 100644 dist/index.d.mts create mode 100644 dist/index.mjs create mode 100644 dist/lib.cjs create mode 100644 dist/lib.d.cts create mode 100644 dist/lib.d.mts create mode 100644 dist/lib.mjs create mode 100644 dist/runCodex-CRpVyA_X.cjs create mode 100644 dist/runCodex-DrPAcday.mjs create mode 100644 dist/types-B6U1wuBR.mjs create mode 100644 dist/types-QJg7LeZh.cjs diff --git a/.gitignore b/.gitignore index f33d308c..addc6567 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ *-error.log **/.DS_Store /.idea -/dist +# /dist - Committing dist for GitHub installs /tmp /node_modules oclif.manifest.json diff --git a/dist/codex/happyMcpStdioBridge.cjs b/dist/codex/happyMcpStdioBridge.cjs new file mode 100644 index 00000000..9af5e408 --- /dev/null +++ b/dist/codex/happyMcpStdioBridge.cjs @@ -0,0 +1,80 @@ +'use strict'; + +var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js'); +var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js'); +var index_js = require('@modelcontextprotocol/sdk/client/index.js'); +var streamableHttp_js = require('@modelcontextprotocol/sdk/client/streamableHttp.js'); +var z = require('zod'); + +function parseArgs(argv) { + let url = null; + for (let i = 0; i < argv.length; i++) { + const a = argv[i]; + if (a === "--url" && i + 1 < argv.length) { + url = argv[i + 1]; + i++; + } + } + return { url }; +} +async function main() { + const { url: urlFromArgs } = parseArgs(process.argv.slice(2)); + const baseUrl = urlFromArgs || process.env.HAPPY_HTTP_MCP_URL || ""; + if (!baseUrl) { + process.stderr.write( + "[happy-mcp] Missing target URL. Set HAPPY_HTTP_MCP_URL or pass --url \n" + ); + process.exit(2); + } + let httpClient = null; + async function ensureHttpClient() { + if (httpClient) return httpClient; + const client = new index_js.Client( + { name: "happy-stdio-bridge", version: "1.0.0" }, + { capabilities: { tools: {} } } + ); + const transport = new streamableHttp_js.StreamableHTTPClientTransport(new URL(baseUrl)); + await client.connect(transport); + httpClient = client; + return client; + } + const server = new mcp_js.McpServer({ + name: "Happy MCP Bridge", + version: "1.0.0", + description: "STDIO bridge forwarding to Happy HTTP MCP" + }); + server.registerTool( + "change_title", + { + description: "Change the title of the current chat session", + title: "Change Chat Title", + inputSchema: { + title: z.z.string().describe("The new title for the chat session") + } + }, + async (args) => { + try { + const client = await ensureHttpClient(); + const response = await client.callTool({ name: "change_title", arguments: args }); + return response; + } catch (error) { + return { + content: [ + { type: "text", text: `Failed to change chat title: ${error instanceof Error ? error.message : String(error)}` } + ], + isError: true + }; + } + } + ); + const stdio = new stdio_js.StdioServerTransport(); + await server.connect(stdio); +} +main().catch((err) => { + try { + process.stderr.write(`[happy-mcp] Fatal: ${err instanceof Error ? err.message : String(err)} +`); + } finally { + process.exit(1); + } +}); diff --git a/dist/codex/happyMcpStdioBridge.d.cts b/dist/codex/happyMcpStdioBridge.d.cts new file mode 100644 index 00000000..04fa25ee --- /dev/null +++ b/dist/codex/happyMcpStdioBridge.d.cts @@ -0,0 +1,2 @@ + +export { }; diff --git a/dist/codex/happyMcpStdioBridge.d.mts b/dist/codex/happyMcpStdioBridge.d.mts new file mode 100644 index 00000000..04fa25ee --- /dev/null +++ b/dist/codex/happyMcpStdioBridge.d.mts @@ -0,0 +1,2 @@ + +export { }; diff --git a/dist/codex/happyMcpStdioBridge.mjs b/dist/codex/happyMcpStdioBridge.mjs new file mode 100644 index 00000000..d54117f4 --- /dev/null +++ b/dist/codex/happyMcpStdioBridge.mjs @@ -0,0 +1,78 @@ +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; +import { z } from 'zod'; + +function parseArgs(argv) { + let url = null; + for (let i = 0; i < argv.length; i++) { + const a = argv[i]; + if (a === "--url" && i + 1 < argv.length) { + url = argv[i + 1]; + i++; + } + } + return { url }; +} +async function main() { + const { url: urlFromArgs } = parseArgs(process.argv.slice(2)); + const baseUrl = urlFromArgs || process.env.HAPPY_HTTP_MCP_URL || ""; + if (!baseUrl) { + process.stderr.write( + "[happy-mcp] Missing target URL. Set HAPPY_HTTP_MCP_URL or pass --url \n" + ); + process.exit(2); + } + let httpClient = null; + async function ensureHttpClient() { + if (httpClient) return httpClient; + const client = new Client( + { name: "happy-stdio-bridge", version: "1.0.0" }, + { capabilities: { tools: {} } } + ); + const transport = new StreamableHTTPClientTransport(new URL(baseUrl)); + await client.connect(transport); + httpClient = client; + return client; + } + const server = new McpServer({ + name: "Happy MCP Bridge", + version: "1.0.0", + description: "STDIO bridge forwarding to Happy HTTP MCP" + }); + server.registerTool( + "change_title", + { + description: "Change the title of the current chat session", + title: "Change Chat Title", + inputSchema: { + title: z.string().describe("The new title for the chat session") + } + }, + async (args) => { + try { + const client = await ensureHttpClient(); + const response = await client.callTool({ name: "change_title", arguments: args }); + return response; + } catch (error) { + return { + content: [ + { type: "text", text: `Failed to change chat title: ${error instanceof Error ? error.message : String(error)}` } + ], + isError: true + }; + } + } + ); + const stdio = new StdioServerTransport(); + await server.connect(stdio); +} +main().catch((err) => { + try { + process.stderr.write(`[happy-mcp] Fatal: ${err instanceof Error ? err.message : String(err)} +`); + } finally { + process.exit(1); + } +}); diff --git a/dist/index-CcjVa7OK.cjs b/dist/index-CcjVa7OK.cjs new file mode 100644 index 00000000..f4df5fd8 --- /dev/null +++ b/dist/index-CcjVa7OK.cjs @@ -0,0 +1,6135 @@ +'use strict'; + +var chalk = require('chalk'); +var os = require('node:os'); +var node_crypto = require('node:crypto'); +var types = require('./types-QJg7LeZh.cjs'); +var node_child_process = require('node:child_process'); +var node_path = require('node:path'); +var node_readline = require('node:readline'); +var fs = require('node:fs'); +var promises = require('node:fs/promises'); +var fs$1 = require('fs/promises'); +var ink = require('ink'); +var React = require('react'); +var node_url = require('node:url'); +var axios = require('axios'); +require('node:events'); +require('socket.io-client'); +var tweetnacl = require('tweetnacl'); +require('expo-server-sdk'); +var crypto = require('crypto'); +var child_process = require('child_process'); +var fs$2 = require('fs'); +var path = require('path'); +var psList = require('ps-list'); +var spawn = require('cross-spawn'); +var os$1 = require('os'); +var tmp = require('tmp'); +var qrcode = require('qrcode-terminal'); +var open = require('open'); +var fastify = require('fastify'); +var z = require('zod'); +var fastifyTypeProviderZod = require('fastify-type-provider-zod'); +var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js'); +var node_http = require('node:http'); +var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js'); +var http = require('http'); +var util = require('util'); + +var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null; +function _interopNamespaceDefault(e) { + var n = Object.create(null); + if (e) { + Object.keys(e).forEach(function (k) { + if (k !== 'default') { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: function () { return e[k]; } + }); + } + }); + } + n.default = e; + return Object.freeze(n); +} + +var tmp__namespace = /*#__PURE__*/_interopNamespaceDefault(tmp); + +class Session { + path; + logPath; + api; + client; + queue; + claudeEnvVars; + claudeArgs; + // Made mutable to allow filtering + mcpServers; + allowedTools; + _onModeChange; + sessionId; + mode = "local"; + thinking = false; + constructor(opts) { + this.path = opts.path; + this.api = opts.api; + this.client = opts.client; + this.logPath = opts.logPath; + this.sessionId = opts.sessionId; + this.queue = opts.messageQueue; + this.claudeEnvVars = opts.claudeEnvVars; + this.claudeArgs = opts.claudeArgs; + this.mcpServers = opts.mcpServers; + this.allowedTools = opts.allowedTools; + this._onModeChange = opts.onModeChange; + this.client.keepAlive(this.thinking, this.mode); + setInterval(() => { + this.client.keepAlive(this.thinking, this.mode); + }, 2e3); + } + onThinkingChange = (thinking) => { + this.thinking = thinking; + this.client.keepAlive(thinking, this.mode); + }; + onModeChange = (mode) => { + this.mode = mode; + this.client.keepAlive(this.thinking, mode); + this._onModeChange(mode); + }; + onSessionFound = (sessionId) => { + this.sessionId = sessionId; + this.client.updateMetadata((metadata) => ({ + ...metadata, + claudeSessionId: sessionId + })); + types.logger.debug(`[Session] Claude Code session ID ${sessionId} added to metadata`); + }; + /** + * Clear the current session ID (used by /clear command) + */ + clearSessionId = () => { + this.sessionId = null; + types.logger.debug("[Session] Session ID cleared"); + }; + /** + * Consume one-time Claude flags from claudeArgs after Claude spawn + * Currently handles: --resume (with or without session ID) + */ + consumeOneTimeFlags = () => { + if (!this.claudeArgs) return; + const filteredArgs = []; + for (let i = 0; i < this.claudeArgs.length; i++) { + if (this.claudeArgs[i] === "--resume") { + if (i + 1 < this.claudeArgs.length) { + const nextArg = this.claudeArgs[i + 1]; + if (!nextArg.startsWith("-") && nextArg.includes("-")) { + i++; + types.logger.debug(`[Session] Consumed --resume flag with session ID: ${nextArg}`); + } else { + types.logger.debug("[Session] Consumed --resume flag (no session ID)"); + } + } else { + types.logger.debug("[Session] Consumed --resume flag (no session ID)"); + } + } else { + filteredArgs.push(this.claudeArgs[i]); + } + } + this.claudeArgs = filteredArgs.length > 0 ? filteredArgs : void 0; + types.logger.debug(`[Session] Consumed one-time flags, remaining args:`, this.claudeArgs); + }; +} + +function getProjectPath(workingDirectory) { + const projectId = node_path.resolve(workingDirectory).replace(/[\\\/\.:]/g, "-"); + const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || node_path.join(os.homedir(), ".claude"); + return node_path.join(claudeConfigDir, "projects", projectId); +} + +function claudeCheckSession(sessionId, path) { + const projectDir = getProjectPath(path); + const sessionFile = node_path.join(projectDir, `${sessionId}.jsonl`); + const sessionExists = fs.existsSync(sessionFile); + if (!sessionExists) { + types.logger.debug(`[claudeCheckSession] Path ${sessionFile} does not exist`); + return false; + } + const sessionData = fs.readFileSync(sessionFile, "utf-8").split("\n"); + const hasGoodMessage = !!sessionData.find((v) => { + try { + return typeof JSON.parse(v).uuid === "string"; + } catch (e) { + return false; + } + }); + return hasGoodMessage; +} + +function trimIdent(text) { + const lines = text.split("\n"); + while (lines.length > 0 && lines[0].trim() === "") { + lines.shift(); + } + while (lines.length > 0 && lines[lines.length - 1].trim() === "") { + lines.pop(); + } + const minSpaces = lines.reduce((min, line) => { + if (line.trim() === "") { + return min; + } + const leadingSpaces = line.match(/^\s*/)[0].length; + return Math.min(min, leadingSpaces); + }, Infinity); + const trimmedLines = lines.map((line) => line.slice(minSpaces)); + return trimmedLines.join("\n"); +} + +function getClaudeSettingsPath() { + const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || node_path.join(os.homedir(), ".claude"); + return node_path.join(claudeConfigDir, "settings.json"); +} +function readClaudeSettings() { + try { + const settingsPath = getClaudeSettingsPath(); + if (!fs.existsSync(settingsPath)) { + types.logger.debug(`[ClaudeSettings] No Claude settings file found at ${settingsPath}`); + return null; + } + const settingsContent = fs.readFileSync(settingsPath, "utf-8"); + const settings = JSON.parse(settingsContent); + types.logger.debug(`[ClaudeSettings] Successfully read Claude settings from ${settingsPath}`); + types.logger.debug(`[ClaudeSettings] includeCoAuthoredBy: ${settings.includeCoAuthoredBy}`); + return settings; + } catch (error) { + types.logger.debug(`[ClaudeSettings] Error reading Claude settings: ${error}`); + return null; + } +} +function shouldIncludeCoAuthoredBy() { + const settings = readClaudeSettings(); + if (!settings || settings.includeCoAuthoredBy === void 0) { + return true; + } + return settings.includeCoAuthoredBy; +} + +const BASE_SYSTEM_PROMPT = (() => trimIdent(` + ALWAYS when you start a new chat - you must call a tool "mcp__happy__change_title" to set a chat title. When you think chat title is not relevant anymore - call the tool again to change it. When chat name is too generic and you have a change to make it more specific - call the tool again to change it. This title is needed to easily find the chat in the future. Help human. +`))(); +const CO_AUTHORED_CREDITS = (() => trimIdent(` + When making commit messages, instead of just giving co-credit to Claude, also give credit to Happy like so: + +
+ + Generated with [Claude Code](https://claude.ai/code) + via [Happy](https://happy.engineering) + + Co-Authored-By: Claude + Co-Authored-By: Happy +`))(); +const systemPrompt = (() => { + const includeCoAuthored = shouldIncludeCoAuthoredBy(); + if (includeCoAuthored) { + return BASE_SYSTEM_PROMPT + "\n\n" + CO_AUTHORED_CREDITS; + } else { + return BASE_SYSTEM_PROMPT; + } +})(); + +const claudeCliPath = node_path.resolve(node_path.join(types.projectPath(), "scripts", "claude_local_launcher.cjs")); +async function claudeLocal(opts) { + const projectDir = getProjectPath(opts.path); + fs.mkdirSync(projectDir, { recursive: true }); + const watcher = fs.watch(projectDir); + let resolvedSessionId = null; + const detectedIdsRandomUUID = /* @__PURE__ */ new Set(); + const detectedIdsFileSystem = /* @__PURE__ */ new Set(); + watcher.on("change", (event, filename) => { + if (typeof filename === "string" && filename.toLowerCase().endsWith(".jsonl")) { + types.logger.debug("change", event, filename); + const sessionId = filename.replace(".jsonl", ""); + if (detectedIdsFileSystem.has(sessionId)) { + return; + } + detectedIdsFileSystem.add(sessionId); + if (resolvedSessionId) { + return; + } + if (detectedIdsRandomUUID.has(sessionId)) { + resolvedSessionId = sessionId; + opts.onSessionFound(sessionId); + } + } + }); + let startFrom = opts.sessionId; + if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path)) { + startFrom = null; + } + let thinking = false; + let stopThinkingTimeout = null; + const updateThinking = (newThinking) => { + if (thinking !== newThinking) { + thinking = newThinking; + types.logger.debug(`[ClaudeLocal] Thinking state changed to: ${thinking}`); + if (opts.onThinkingChange) { + opts.onThinkingChange(thinking); + } + } + }; + try { + process.stdin.pause(); + await new Promise((r, reject) => { + const args = []; + if (startFrom) { + args.push("--resume", startFrom); + } + args.push("--append-system-prompt", systemPrompt); + if (opts.mcpServers && Object.keys(opts.mcpServers).length > 0) { + args.push("--mcp-config", JSON.stringify({ mcpServers: opts.mcpServers })); + } + if (opts.allowedTools && opts.allowedTools.length > 0) { + args.push("--allowedTools", opts.allowedTools.join(",")); + } + if (opts.claudeArgs) { + args.push(...opts.claudeArgs); + } + if (!claudeCliPath || !fs.existsSync(claudeCliPath)) { + throw new Error("Claude local launcher not found. Please ensure HAPPY_PROJECT_ROOT is set correctly for development."); + } + const env = { + ...process.env, + ...opts.claudeEnvVars + }; + const child = node_child_process.spawn("node", [claudeCliPath, ...args], { + stdio: ["inherit", "inherit", "inherit", "pipe"], + signal: opts.abort, + cwd: opts.path, + env + }); + if (child.stdio[3]) { + const rl = node_readline.createInterface({ + input: child.stdio[3], + crlfDelay: Infinity + }); + const activeFetches = /* @__PURE__ */ new Map(); + rl.on("line", (line) => { + try { + const message = JSON.parse(line); + switch (message.type) { + case "uuid": + detectedIdsRandomUUID.add(message.value); + if (!resolvedSessionId && detectedIdsFileSystem.has(message.value)) { + resolvedSessionId = message.value; + opts.onSessionFound(message.value); + } + break; + case "fetch-start": + activeFetches.set(message.id, { + hostname: message.hostname, + path: message.path, + startTime: message.timestamp + }); + if (stopThinkingTimeout) { + clearTimeout(stopThinkingTimeout); + stopThinkingTimeout = null; + } + updateThinking(true); + break; + case "fetch-end": + activeFetches.delete(message.id); + if (activeFetches.size === 0 && thinking && !stopThinkingTimeout) { + stopThinkingTimeout = setTimeout(() => { + if (activeFetches.size === 0) { + updateThinking(false); + } + stopThinkingTimeout = null; + }, 500); + } + break; + default: + types.logger.debug(`[ClaudeLocal] Unknown message type: ${message.type}`); + } + } catch (e) { + types.logger.debug(`[ClaudeLocal] Non-JSON line from fd3: ${line}`); + } + }); + rl.on("error", (err) => { + console.error("Error reading from fd 3:", err); + }); + child.on("exit", () => { + if (stopThinkingTimeout) { + clearTimeout(stopThinkingTimeout); + } + updateThinking(false); + }); + } + child.on("error", (error) => { + }); + child.on("exit", (code, signal) => { + if (signal === "SIGTERM" && opts.abort.aborted) { + r(); + } else if (signal) { + reject(new Error(`Process terminated with signal: ${signal}`)); + } else { + r(); + } + }); + }); + } finally { + watcher.close(); + process.stdin.resume(); + if (stopThinkingTimeout) { + clearTimeout(stopThinkingTimeout); + stopThinkingTimeout = null; + } + updateThinking(false); + } + return resolvedSessionId; +} + +class Future { + _resolve; + _reject; + _promise; + constructor() { + this._promise = new Promise((resolve, reject) => { + this._resolve = resolve; + this._reject = reject; + }); + } + resolve(value) { + this._resolve(value); + } + reject(reason) { + this._reject(reason); + } + get promise() { + return this._promise; + } +} + +class InvalidateSync { + _invalidated = false; + _invalidatedDouble = false; + _stopped = false; + _command; + _pendings = []; + constructor(command) { + this._command = command; + } + invalidate() { + if (this._stopped) { + return; + } + if (!this._invalidated) { + this._invalidated = true; + this._invalidatedDouble = false; + this._doSync(); + } else { + if (!this._invalidatedDouble) { + this._invalidatedDouble = true; + } + } + } + async invalidateAndAwait() { + if (this._stopped) { + return; + } + await new Promise((resolve) => { + this._pendings.push(resolve); + this.invalidate(); + }); + } + stop() { + if (this._stopped) { + return; + } + this._notifyPendings(); + this._stopped = true; + } + _notifyPendings = () => { + for (let pending of this._pendings) { + pending(); + } + this._pendings = []; + }; + _doSync = async () => { + await types.backoff(async () => { + if (this._stopped) { + return; + } + await this._command(); + }); + if (this._stopped) { + this._notifyPendings(); + return; + } + if (this._invalidatedDouble) { + this._invalidatedDouble = false; + this._doSync(); + } else { + this._invalidated = false; + this._notifyPendings(); + } + }; +} + +function startFileWatcher(file, onFileChange) { + const abortController = new AbortController(); + void (async () => { + while (true) { + try { + types.logger.debug(`[FILE_WATCHER] Starting watcher for ${file}`); + const watcher = fs$1.watch(file, { persistent: true, signal: abortController.signal }); + for await (const event of watcher) { + if (abortController.signal.aborted) { + return; + } + types.logger.debug(`[FILE_WATCHER] File changed: ${file}`); + onFileChange(file); + } + } catch (e) { + if (abortController.signal.aborted) { + return; + } + types.logger.debug(`[FILE_WATCHER] Watch error: ${e.message}, restarting watcher in a second`); + await types.delay(1e3); + } + } + })(); + return () => { + abortController.abort(); + }; +} + +async function createSessionScanner(opts) { + const projectDir = getProjectPath(opts.workingDirectory); + let finishedSessions = /* @__PURE__ */ new Set(); + let pendingSessions = /* @__PURE__ */ new Set(); + let currentSessionId = null; + let watchers = /* @__PURE__ */ new Map(); + let processedMessageKeys = /* @__PURE__ */ new Set(); + if (opts.sessionId) { + let messages = await readSessionLog(projectDir, opts.sessionId); + for (let m of messages) { + processedMessageKeys.add(messageKey(m)); + } + } + const sync = new InvalidateSync(async () => { + let sessions = []; + for (let p of pendingSessions) { + sessions.push(p); + } + if (currentSessionId) { + sessions.push(currentSessionId); + } + for (let session of sessions) { + for (let file of await readSessionLog(projectDir, session)) { + let key = messageKey(file); + if (processedMessageKeys.has(key)) { + continue; + } + processedMessageKeys.add(key); + opts.onMessage(file); + } + } + for (let p of sessions) { + if (pendingSessions.has(p)) { + pendingSessions.delete(p); + finishedSessions.add(p); + } + } + for (let p of sessions) { + if (!watchers.has(p)) { + watchers.set(p, startFileWatcher(node_path.join(projectDir, `${p}.jsonl`), () => { + sync.invalidate(); + })); + } + } + }); + await sync.invalidateAndAwait(); + const intervalId = setInterval(() => { + sync.invalidate(); + }, 3e3); + return { + cleanup: async () => { + clearInterval(intervalId); + for (let w of watchers.values()) { + w(); + } + watchers.clear(); + await sync.invalidateAndAwait(); + sync.stop(); + }, + onNewSession: (sessionId) => { + if (currentSessionId === sessionId) { + types.logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is the same as the current session, skipping`); + return; + } + if (finishedSessions.has(sessionId)) { + types.logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is already finished, skipping`); + return; + } + if (pendingSessions.has(sessionId)) { + types.logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is already pending, skipping`); + return; + } + if (currentSessionId) { + pendingSessions.add(currentSessionId); + } + types.logger.debug(`[SESSION_SCANNER] New session: ${sessionId}`); + currentSessionId = sessionId; + sync.invalidate(); + } + }; +} +function messageKey(message) { + if (message.type === "user") { + return message.uuid; + } else if (message.type === "assistant") { + return message.uuid; + } else if (message.type === "summary") { + return "summary: " + message.leafUuid + ": " + message.summary; + } else if (message.type === "system") { + return message.uuid; + } else { + throw Error(); + } +} +async function readSessionLog(projectDir, sessionId) { + const expectedSessionFile = node_path.join(projectDir, `${sessionId}.jsonl`); + types.logger.debug(`[SESSION_SCANNER] Reading session file: ${expectedSessionFile}`); + let file; + try { + file = await promises.readFile(expectedSessionFile, "utf-8"); + } catch (error) { + types.logger.debug(`[SESSION_SCANNER] Session file not found: ${expectedSessionFile}`); + return []; + } + let lines = file.split("\n"); + let messages = []; + for (let l of lines) { + try { + if (l.trim() === "") { + continue; + } + let message = JSON.parse(l); + let parsed = types.RawJSONLinesSchema.safeParse(message); + if (!parsed.success) { + types.logger.debugLargeJson(`[SESSION_SCANNER] Failed to parse message`, message); + continue; + } + messages.push(parsed.data); + } catch (e) { + types.logger.debug(`[SESSION_SCANNER] Error processing message: ${e}`); + continue; + } + } + return messages; +} + +async function claudeLocalLauncher(session) { + const scanner = await createSessionScanner({ + sessionId: session.sessionId, + workingDirectory: session.path, + onMessage: (message) => { + if (message.type !== "summary") { + session.client.sendClaudeSessionMessage(message); + } + } + }); + let exitReason = null; + const processAbortController = new AbortController(); + let exutFuture = new Future(); + try { + async function abort() { + if (!processAbortController.signal.aborted) { + processAbortController.abort(); + } + await exutFuture.promise; + } + async function doAbort() { + types.logger.debug("[local]: doAbort"); + if (!exitReason) { + exitReason = "switch"; + } + session.queue.reset(); + await abort(); + } + async function doSwitch() { + types.logger.debug("[local]: doSwitch"); + if (!exitReason) { + exitReason = "switch"; + } + await abort(); + } + session.client.rpcHandlerManager.registerHandler("abort", doAbort); + session.client.rpcHandlerManager.registerHandler("switch", doSwitch); + session.queue.setOnMessage((message, mode) => { + doSwitch(); + }); + if (session.queue.size() > 0) { + return "switch"; + } + const handleSessionStart = (sessionId) => { + session.onSessionFound(sessionId); + scanner.onNewSession(sessionId); + }; + while (true) { + if (exitReason) { + return exitReason; + } + types.logger.debug("[local]: launch"); + try { + await claudeLocal({ + path: session.path, + sessionId: session.sessionId, + onSessionFound: handleSessionStart, + onThinkingChange: session.onThinkingChange, + abort: processAbortController.signal, + claudeEnvVars: session.claudeEnvVars, + claudeArgs: session.claudeArgs, + mcpServers: session.mcpServers, + allowedTools: session.allowedTools + }); + session.consumeOneTimeFlags(); + if (!exitReason) { + exitReason = "exit"; + break; + } + } catch (e) { + types.logger.debug("[local]: launch error", e); + if (!exitReason) { + session.client.sendSessionEvent({ type: "message", message: "Process exited unexpectedly" }).catch((err) => types.logger.debug("[Claude] Failed to send exit event:", err)); + continue; + } else { + break; + } + } + types.logger.debug("[local]: launch done"); + } + } finally { + exutFuture.resolve(void 0); + session.client.rpcHandlerManager.registerHandler("abort", async () => { + }); + session.client.rpcHandlerManager.registerHandler("switch", async () => { + }); + session.queue.setOnMessage(null); + await scanner.cleanup(); + } + return exitReason || "exit"; +} + +class MessageBuffer { + messages = []; + listeners = []; + nextId = 1; + addMessage(content, type = "assistant") { + const message = { + id: `msg-${this.nextId++}`, + timestamp: /* @__PURE__ */ new Date(), + content, + type + }; + this.messages.push(message); + this.notifyListeners(); + } + getMessages() { + return [...this.messages]; + } + clear() { + this.messages = []; + this.nextId = 1; + this.notifyListeners(); + } + onUpdate(listener) { + this.listeners.push(listener); + return () => { + const index = this.listeners.indexOf(listener); + if (index > -1) { + this.listeners.splice(index, 1); + } + }; + } + notifyListeners() { + const messages = this.getMessages(); + this.listeners.forEach((listener) => listener(messages)); + } +} + +const RemoteModeDisplay = ({ messageBuffer, logPath, onExit, onSwitchToLocal }) => { + const [messages, setMessages] = React.useState([]); + const [confirmationMode, setConfirmationMode] = React.useState(null); + const [actionInProgress, setActionInProgress] = React.useState(null); + const confirmationTimeoutRef = React.useRef(null); + const { stdout } = ink.useStdout(); + const terminalWidth = stdout.columns || 80; + const terminalHeight = stdout.rows || 24; + React.useEffect(() => { + setMessages(messageBuffer.getMessages()); + const unsubscribe = messageBuffer.onUpdate((newMessages) => { + setMessages(newMessages); + }); + return () => { + unsubscribe(); + if (confirmationTimeoutRef.current) { + clearTimeout(confirmationTimeoutRef.current); + } + }; + }, [messageBuffer]); + const resetConfirmation = React.useCallback(() => { + setConfirmationMode(null); + if (confirmationTimeoutRef.current) { + clearTimeout(confirmationTimeoutRef.current); + confirmationTimeoutRef.current = null; + } + }, []); + const setConfirmationWithTimeout = React.useCallback((mode) => { + setConfirmationMode(mode); + if (confirmationTimeoutRef.current) { + clearTimeout(confirmationTimeoutRef.current); + } + confirmationTimeoutRef.current = setTimeout(() => { + resetConfirmation(); + }, 15e3); + }, [resetConfirmation]); + ink.useInput(React.useCallback(async (input, key) => { + if (actionInProgress) return; + if (key.ctrl && input === "c") { + if (confirmationMode === "exit") { + resetConfirmation(); + setActionInProgress("exiting"); + await new Promise((resolve) => setTimeout(resolve, 100)); + onExit?.(); + } else { + setConfirmationWithTimeout("exit"); + } + return; + } + if (input === " ") { + if (confirmationMode === "switch") { + resetConfirmation(); + setActionInProgress("switching"); + await new Promise((resolve) => setTimeout(resolve, 100)); + onSwitchToLocal?.(); + } else { + setConfirmationWithTimeout("switch"); + } + return; + } + if (confirmationMode) { + resetConfirmation(); + } + }, [confirmationMode, actionInProgress, onExit, onSwitchToLocal, setConfirmationWithTimeout, resetConfirmation])); + const getMessageColor = (type) => { + switch (type) { + case "user": + return "magenta"; + case "assistant": + return "cyan"; + case "system": + return "blue"; + case "tool": + return "yellow"; + case "result": + return "green"; + case "status": + return "gray"; + default: + return "white"; + } + }; + const formatMessage = (msg) => { + const lines = msg.content.split("\n"); + const maxLineLength = terminalWidth - 10; + return lines.map((line) => { + if (line.length <= maxLineLength) return line; + const chunks = []; + for (let i = 0; i < line.length; i += maxLineLength) { + chunks.push(line.slice(i, i + maxLineLength)); + } + return chunks.join("\n"); + }).join("\n"); + }; + return /* @__PURE__ */ React.createElement(ink.Box, { flexDirection: "column", width: terminalWidth, height: terminalHeight }, /* @__PURE__ */ React.createElement( + ink.Box, + { + flexDirection: "column", + width: terminalWidth, + height: terminalHeight - 4, + borderStyle: "round", + borderColor: "gray", + paddingX: 1, + overflow: "hidden" + }, + /* @__PURE__ */ React.createElement(ink.Box, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", bold: true }, "\u{1F4E1} Remote Mode - Claude Messages"), /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", dimColor: true }, "\u2500".repeat(Math.min(terminalWidth - 4, 60)))), + /* @__PURE__ */ React.createElement(ink.Box, { flexDirection: "column", height: terminalHeight - 10, overflow: "hidden" }, messages.length === 0 ? /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", dimColor: true }, "Waiting for messages...") : ( + // Show only the last messages that fit in the available space + messages.slice(-Math.max(1, terminalHeight - 10)).map((msg) => /* @__PURE__ */ React.createElement(ink.Box, { key: msg.id, flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(ink.Text, { color: getMessageColor(msg.type), dimColor: true }, formatMessage(msg)))) + )) + ), /* @__PURE__ */ React.createElement( + ink.Box, + { + width: terminalWidth, + borderStyle: "round", + borderColor: actionInProgress ? "gray" : confirmationMode === "exit" ? "red" : confirmationMode === "switch" ? "yellow" : "green", + paddingX: 2, + justifyContent: "center", + alignItems: "center", + flexDirection: "column" + }, + /* @__PURE__ */ React.createElement(ink.Box, { flexDirection: "column", alignItems: "center" }, actionInProgress === "exiting" ? /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", bold: true }, "Exiting...") : actionInProgress === "switching" ? /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", bold: true }, "Switching to local mode...") : confirmationMode === "exit" ? /* @__PURE__ */ React.createElement(ink.Text, { color: "red", bold: true }, "\u26A0\uFE0F Press Ctrl-C again to exit completely") : confirmationMode === "switch" ? /* @__PURE__ */ React.createElement(ink.Text, { color: "yellow", bold: true }, "\u23F8\uFE0F Press space again to switch to local mode") : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ink.Text, { color: "green", bold: true }, "\u{1F4F1} Press space to switch to local mode \u2022 Ctrl-C to exit")), process.env.DEBUG && logPath && /* @__PURE__ */ React.createElement(ink.Text, { color: "gray", dimColor: true }, "Debug logs: ", logPath)) + )); +}; + +class Stream { + constructor(returned) { + this.returned = returned; + } + queue = []; + readResolve; + readReject; + isDone = false; + hasError; + started = false; + /** + * Implements async iterable protocol + */ + [Symbol.asyncIterator]() { + if (this.started) { + throw new Error("Stream can only be iterated once"); + } + this.started = true; + return this; + } + /** + * Gets the next value from the stream + */ + async next() { + if (this.queue.length > 0) { + return Promise.resolve({ + done: false, + value: this.queue.shift() + }); + } + if (this.isDone) { + return Promise.resolve({ done: true, value: void 0 }); + } + if (this.hasError) { + return Promise.reject(this.hasError); + } + return new Promise((resolve, reject) => { + this.readResolve = resolve; + this.readReject = reject; + }); + } + /** + * Adds a value to the stream + */ + enqueue(value) { + if (this.readResolve) { + const resolve = this.readResolve; + this.readResolve = void 0; + this.readReject = void 0; + resolve({ done: false, value }); + } else { + this.queue.push(value); + } + } + /** + * Marks the stream as complete + */ + done() { + this.isDone = true; + if (this.readResolve) { + const resolve = this.readResolve; + this.readResolve = void 0; + this.readReject = void 0; + resolve({ done: true, value: void 0 }); + } + } + /** + * Propagates an error through the stream + */ + error(error) { + this.hasError = error; + if (this.readReject) { + const reject = this.readReject; + this.readResolve = void 0; + this.readReject = void 0; + reject(error); + } + } + /** + * Implements async iterator cleanup + */ + async return() { + this.isDone = true; + if (this.returned) { + this.returned(); + } + return Promise.resolve({ done: true, value: void 0 }); + } +} + +class AbortError extends Error { + constructor(message) { + super(message); + this.name = "AbortError"; + } +} + +const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CcjVa7OK.cjs', document.baseURI).href))); +const __dirname$1 = node_path.join(__filename$1, ".."); +function getDefaultClaudeCodePath() { + return node_path.join(__dirname$1, "..", "..", "..", "node_modules", "@anthropic-ai", "claude-code", "cli.js"); +} +function logDebug(message) { + if (process.env.DEBUG) { + types.logger.debug(message); + console.log(message); + } +} +async function streamToStdin(stream, stdin, abort) { + for await (const message of stream) { + if (abort?.aborted) break; + stdin.write(JSON.stringify(message) + "\n"); + } + stdin.end(); +} + +class Query { + constructor(childStdin, childStdout, processExitPromise, canCallTool) { + this.childStdin = childStdin; + this.childStdout = childStdout; + this.processExitPromise = processExitPromise; + this.canCallTool = canCallTool; + this.readMessages(); + this.sdkMessages = this.readSdkMessages(); + } + pendingControlResponses = /* @__PURE__ */ new Map(); + cancelControllers = /* @__PURE__ */ new Map(); + sdkMessages; + inputStream = new Stream(); + canCallTool; + /** + * Set an error on the stream + */ + setError(error) { + this.inputStream.error(error); + } + /** + * AsyncIterableIterator implementation + */ + next(...args) { + return this.sdkMessages.next(...args); + } + return(value) { + if (this.sdkMessages.return) { + return this.sdkMessages.return(value); + } + return Promise.resolve({ done: true, value: void 0 }); + } + throw(e) { + if (this.sdkMessages.throw) { + return this.sdkMessages.throw(e); + } + return Promise.reject(e); + } + [Symbol.asyncIterator]() { + return this.sdkMessages; + } + /** + * Read messages from Claude process stdout + */ + async readMessages() { + const rl = node_readline.createInterface({ input: this.childStdout }); + try { + for await (const line of rl) { + if (line.trim()) { + try { + const message = JSON.parse(line); + if (message.type === "control_response") { + const controlResponse = message; + const handler = this.pendingControlResponses.get(controlResponse.response.request_id); + if (handler) { + handler(controlResponse.response); + } + continue; + } else if (message.type === "control_request") { + await this.handleControlRequest(message); + continue; + } else if (message.type === "control_cancel_request") { + this.handleControlCancelRequest(message); + continue; + } + this.inputStream.enqueue(message); + } catch (e) { + types.logger.debug(line); + } + } + } + await this.processExitPromise; + } catch (error) { + this.inputStream.error(error); + } finally { + this.inputStream.done(); + this.cleanupControllers(); + rl.close(); + } + } + /** + * Async generator for SDK messages + */ + async *readSdkMessages() { + for await (const message of this.inputStream) { + yield message; + } + } + /** + * Send interrupt request to Claude + */ + async interrupt() { + if (!this.childStdin) { + throw new Error("Interrupt requires --input-format stream-json"); + } + await this.request({ + subtype: "interrupt" + }, this.childStdin); + } + /** + * Send control request to Claude process + */ + request(request, childStdin) { + const requestId = Math.random().toString(36).substring(2, 15); + const sdkRequest = { + request_id: requestId, + type: "control_request", + request + }; + return new Promise((resolve, reject) => { + this.pendingControlResponses.set(requestId, (response) => { + if (response.subtype === "success") { + resolve(response); + } else { + reject(new Error(response.error)); + } + }); + childStdin.write(JSON.stringify(sdkRequest) + "\n"); + }); + } + /** + * Handle incoming control requests for tool permissions + * Replicates the exact logic from the SDK's handleControlRequest method + */ + async handleControlRequest(request) { + if (!this.childStdin) { + logDebug("Cannot handle control request - no stdin available"); + return; + } + const controller = new AbortController(); + this.cancelControllers.set(request.request_id, controller); + try { + const response = await this.processControlRequest(request, controller.signal); + const controlResponse = { + type: "control_response", + response: { + subtype: "success", + request_id: request.request_id, + response + } + }; + this.childStdin.write(JSON.stringify(controlResponse) + "\n"); + } catch (error) { + const controlErrorResponse = { + type: "control_response", + response: { + subtype: "error", + request_id: request.request_id, + error: error instanceof Error ? error.message : String(error) + } + }; + this.childStdin.write(JSON.stringify(controlErrorResponse) + "\n"); + } finally { + this.cancelControllers.delete(request.request_id); + } + } + /** + * Handle control cancel requests + * Replicates the exact logic from the SDK's handleControlCancelRequest method + */ + handleControlCancelRequest(request) { + const controller = this.cancelControllers.get(request.request_id); + if (controller) { + controller.abort(); + this.cancelControllers.delete(request.request_id); + } + } + /** + * Process control requests based on subtype + * Replicates the exact logic from the SDK's processControlRequest method + */ + async processControlRequest(request, signal) { + if (request.request.subtype === "can_use_tool") { + if (!this.canCallTool) { + throw new Error("canCallTool callback is not provided."); + } + return this.canCallTool(request.request.tool_name, request.request.input, { + signal + }); + } + throw new Error("Unsupported control request subtype: " + request.request.subtype); + } + /** + * Cleanup method to abort all pending control requests + */ + cleanupControllers() { + for (const [requestId, controller] of this.cancelControllers.entries()) { + controller.abort(); + this.cancelControllers.delete(requestId); + } + } +} +function query(config) { + const { + prompt, + options: { + allowedTools = [], + appendSystemPrompt, + customSystemPrompt, + cwd, + disallowedTools = [], + executable = "node", + executableArgs = [], + maxTurns, + mcpServers, + pathToClaudeCodeExecutable = getDefaultClaudeCodePath(), + permissionMode = "default", + continue: continueConversation, + resume, + model, + fallbackModel, + strictMcpConfig, + canCallTool + } = {} + } = config; + if (!process.env.CLAUDE_CODE_ENTRYPOINT) { + process.env.CLAUDE_CODE_ENTRYPOINT = "sdk-ts"; + } + const args = ["--output-format", "stream-json", "--verbose"]; + if (customSystemPrompt) args.push("--system-prompt", customSystemPrompt); + if (appendSystemPrompt) args.push("--append-system-prompt", appendSystemPrompt); + if (maxTurns) args.push("--max-turns", maxTurns.toString()); + if (model) args.push("--model", model); + if (canCallTool) { + if (typeof prompt === "string") { + throw new Error("canCallTool callback requires --input-format stream-json. Please set prompt as an AsyncIterable."); + } + args.push("--permission-prompt-tool", "stdio"); + } + if (continueConversation) args.push("--continue"); + if (resume) args.push("--resume", resume); + if (allowedTools.length > 0) args.push("--allowedTools", allowedTools.join(",")); + if (disallowedTools.length > 0) args.push("--disallowedTools", disallowedTools.join(",")); + if (mcpServers && Object.keys(mcpServers).length > 0) { + args.push("--mcp-config", JSON.stringify({ mcpServers })); + } + if (strictMcpConfig) args.push("--strict-mcp-config"); + if (permissionMode) args.push("--permission-mode", permissionMode); + if (fallbackModel) { + if (model && fallbackModel === model) { + throw new Error("Fallback model cannot be the same as the main model. Please specify a different model for fallbackModel option."); + } + args.push("--fallback-model", fallbackModel); + } + if (typeof prompt === "string") { + args.push("--print", prompt.trim()); + } else { + args.push("--input-format", "stream-json"); + } + if (!fs.existsSync(pathToClaudeCodeExecutable)) { + throw new ReferenceError(`Claude Code executable not found at ${pathToClaudeCodeExecutable}. Is options.pathToClaudeCodeExecutable set?`); + } + logDebug(`Spawning Claude Code process: ${executable} ${[...executableArgs, pathToClaudeCodeExecutable, ...args].join(" ")}`); + const child = node_child_process.spawn(executable, [...executableArgs, pathToClaudeCodeExecutable, ...args], { + cwd, + stdio: ["pipe", "pipe", "pipe"], + signal: config.options?.abort, + env: { + ...process.env + } + }); + let childStdin = null; + if (typeof prompt === "string") { + child.stdin.end(); + } else { + streamToStdin(prompt, child.stdin, config.options?.abort); + childStdin = child.stdin; + } + if (process.env.DEBUG) { + child.stderr.on("data", (data) => { + console.error("Claude Code stderr:", data.toString()); + }); + } + const cleanup = () => { + if (!child.killed) { + child.kill("SIGTERM"); + } + }; + config.options?.abort?.addEventListener("abort", cleanup); + process.on("exit", cleanup); + const processExitPromise = new Promise((resolve) => { + child.on("close", (code) => { + if (config.options?.abort?.aborted) { + query2.setError(new AbortError("Claude Code process aborted by user")); + } + if (code !== 0) { + query2.setError(new Error(`Claude Code process exited with code ${code}`)); + } else { + resolve(); + } + }); + }); + const query2 = new Query(childStdin, child.stdout, processExitPromise, canCallTool); + child.on("error", (error) => { + if (config.options?.abort?.aborted) { + query2.setError(new AbortError("Claude Code process aborted by user")); + } else { + query2.setError(new Error(`Failed to spawn Claude Code process: ${error.message}`)); + } + }); + processExitPromise.finally(() => { + cleanup(); + config.options?.abort?.removeEventListener("abort", cleanup); + if (process.env.CLAUDE_SDK_MCP_SERVERS) { + delete process.env.CLAUDE_SDK_MCP_SERVERS; + } + }); + return query2; +} + +function parseCompact(message) { + const trimmed = message.trim(); + if (trimmed === "/compact") { + return { + isCompact: true, + originalMessage: trimmed + }; + } + if (trimmed.startsWith("/compact ")) { + return { + isCompact: true, + originalMessage: trimmed + }; + } + return { + isCompact: false, + originalMessage: message + }; +} +function parseClear(message) { + const trimmed = message.trim(); + return { + isClear: trimmed === "/clear" + }; +} +function parseSpecialCommand(message) { + const compactResult = parseCompact(message); + if (compactResult.isCompact) { + return { + type: "compact", + originalMessage: compactResult.originalMessage + }; + } + const clearResult = parseClear(message); + if (clearResult.isClear) { + return { + type: "clear" + }; + } + return { + type: null + }; +} + +class PushableAsyncIterable { + queue = []; + waiters = []; + isDone = false; + error = null; + started = false; + constructor() { + } + /** + * Push a value to the iterable + */ + push(value) { + if (this.isDone) { + throw new Error("Cannot push to completed iterable"); + } + if (this.error) { + throw this.error; + } + const waiter = this.waiters.shift(); + if (waiter) { + waiter.resolve({ done: false, value }); + } else { + this.queue.push(value); + } + } + /** + * Mark the iterable as complete + */ + end() { + if (this.isDone) { + return; + } + this.isDone = true; + this.cleanup(); + } + /** + * Set an error on the iterable + */ + setError(err) { + if (this.isDone) { + return; + } + this.error = err; + this.isDone = true; + this.cleanup(); + } + /** + * Cleanup waiting consumers + */ + cleanup() { + while (this.waiters.length > 0) { + const waiter = this.waiters.shift(); + if (this.error) { + waiter.reject(this.error); + } else { + waiter.resolve({ done: true, value: void 0 }); + } + } + } + /** + * AsyncIterableIterator implementation + */ + async next() { + if (this.queue.length > 0) { + return { done: false, value: this.queue.shift() }; + } + if (this.isDone) { + if (this.error) { + throw this.error; + } + return { done: true, value: void 0 }; + } + return new Promise((resolve, reject) => { + this.waiters.push({ resolve, reject }); + }); + } + /** + * AsyncIterableIterator return implementation + */ + async return(_value) { + this.end(); + return { done: true, value: void 0 }; + } + /** + * AsyncIterableIterator throw implementation + */ + async throw(e) { + this.setError(e instanceof Error ? e : new Error(String(e))); + throw this.error; + } + /** + * Make this iterable + */ + [Symbol.asyncIterator]() { + if (this.started) { + throw new Error("PushableAsyncIterable can only be iterated once"); + } + this.started = true; + return this; + } + /** + * Check if the iterable is done + */ + get done() { + return this.isDone; + } + /** + * Check if the iterable has an error + */ + get hasError() { + return this.error !== null; + } + /** + * Get the current queue size + */ + get queueSize() { + return this.queue.length; + } + /** + * Get the number of waiting consumers + */ + get waiterCount() { + return this.waiters.length; + } +} + +async function awaitFileExist(file, timeout = 1e4) { + const startTime = Date.now(); + while (Date.now() - startTime < timeout) { + try { + await fs$1.access(file); + return true; + } catch (e) { + await types.delay(1e3); + } + } + return false; +} + +async function claudeRemote(opts) { + let startFrom = opts.sessionId; + if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path)) { + startFrom = null; + } + if (!startFrom && opts.claudeArgs) { + for (let i = 0; i < opts.claudeArgs.length; i++) { + if (opts.claudeArgs[i] === "--resume") { + if (i + 1 < opts.claudeArgs.length) { + const nextArg = opts.claudeArgs[i + 1]; + if (!nextArg.startsWith("-") && nextArg.includes("-")) { + startFrom = nextArg; + types.logger.debug(`[claudeRemote] Found --resume with session ID: ${startFrom}`); + break; + } else { + types.logger.debug("[claudeRemote] Found --resume without session ID - not supported in remote mode"); + break; + } + } else { + types.logger.debug("[claudeRemote] Found --resume without session ID - not supported in remote mode"); + break; + } + } + } + } + if (opts.claudeEnvVars) { + Object.entries(opts.claudeEnvVars).forEach(([key, value]) => { + process.env[key] = value; + }); + } + const initial = await opts.nextMessage(); + if (!initial) { + return; + } + const specialCommand = parseSpecialCommand(initial.message); + if (specialCommand.type === "clear") { + if (opts.onCompletionEvent) { + opts.onCompletionEvent("Context was reset"); + } + if (opts.onSessionReset) { + opts.onSessionReset(); + } + return; + } + let isCompactCommand = false; + if (specialCommand.type === "compact") { + types.logger.debug("[claudeRemote] /compact command detected - will process as normal but with compaction behavior"); + isCompactCommand = true; + if (opts.onCompletionEvent) { + opts.onCompletionEvent("Compaction started"); + } + } + let mode = initial.mode; + const sdkOptions = { + cwd: opts.path, + resume: startFrom ?? void 0, + mcpServers: opts.mcpServers, + permissionMode: initial.mode.permissionMode === "plan" ? "plan" : "default", + model: initial.mode.model, + fallbackModel: initial.mode.fallbackModel, + customSystemPrompt: initial.mode.customSystemPrompt ? initial.mode.customSystemPrompt + "\n\n" + systemPrompt : void 0, + appendSystemPrompt: initial.mode.appendSystemPrompt ? initial.mode.appendSystemPrompt + "\n\n" + systemPrompt : systemPrompt, + allowedTools: initial.mode.allowedTools ? initial.mode.allowedTools.concat(opts.allowedTools) : opts.allowedTools, + disallowedTools: initial.mode.disallowedTools, + canCallTool: (toolName, input, options) => opts.canCallTool(toolName, input, mode, options), + executable: "node", + abort: opts.signal, + pathToClaudeCodeExecutable: (() => { + return node_path.resolve(node_path.join(types.projectPath(), "scripts", "claude_remote_launcher.cjs")); + })() + }; + let thinking = false; + const updateThinking = (newThinking) => { + if (thinking !== newThinking) { + thinking = newThinking; + types.logger.debug(`[claudeRemote] Thinking state changed to: ${thinking}`); + if (opts.onThinkingChange) { + opts.onThinkingChange(thinking); + } + } + }; + let messages = new PushableAsyncIterable(); + messages.push({ + type: "user", + message: { + role: "user", + content: initial.message + } + }); + const response = query({ + prompt: messages, + options: sdkOptions + }); + updateThinking(true); + try { + types.logger.debug(`[claudeRemote] Starting to iterate over response`); + for await (const message of response) { + types.logger.debugLargeJson(`[claudeRemote] Message ${message.type}`, message); + opts.onMessage(message); + if (message.type === "system" && message.subtype === "init") { + updateThinking(true); + const systemInit = message; + if (systemInit.session_id) { + types.logger.debug(`[claudeRemote] Waiting for session file to be written to disk: ${systemInit.session_id}`); + const projectDir = getProjectPath(opts.path); + const found = await awaitFileExist(node_path.join(projectDir, `${systemInit.session_id}.jsonl`)); + types.logger.debug(`[claudeRemote] Session file found: ${systemInit.session_id} ${found}`); + opts.onSessionFound(systemInit.session_id); + } + } + if (message.type === "result") { + updateThinking(false); + types.logger.debug("[claudeRemote] Result received, exiting claudeRemote"); + if (isCompactCommand) { + types.logger.debug("[claudeRemote] Compaction completed"); + if (opts.onCompletionEvent) { + opts.onCompletionEvent("Compaction completed"); + } + isCompactCommand = false; + } + opts.onReady(); + const next = await opts.nextMessage(); + if (!next) { + messages.end(); + return; + } + mode = next.mode; + messages.push({ type: "user", message: { role: "user", content: next.message } }); + } + if (message.type === "user") { + const msg = message; + if (msg.message.role === "user" && Array.isArray(msg.message.content)) { + for (let c of msg.message.content) { + if (c.type === "tool_result" && c.tool_use_id && opts.isAborted(c.tool_use_id)) { + types.logger.debug("[claudeRemote] Tool aborted, exiting claudeRemote"); + return; + } + } + } + } + } + } catch (e) { + if (e instanceof AbortError) { + types.logger.debug(`[claudeRemote] Aborted`); + } else { + throw e; + } + } finally { + updateThinking(false); + } +} + +const PLAN_FAKE_REJECT = `User approved plan, but you need to be restarted. STOP IMMEDIATELY TO SWITCH FROM PLAN MODE. DO NOT REPLY TO THIS MESSAGE.`; +const PLAN_FAKE_RESTART = `PlEaZe Continue with plan.`; + +function deepEqual(a, b) { + if (a === b) return true; + if (a == null || b == null) return false; + if (typeof a !== "object" || typeof b !== "object") return false; + const keysA = Object.keys(a); + const keysB = Object.keys(b); + if (keysA.length !== keysB.length) return false; + for (const key of keysA) { + if (!keysB.includes(key)) return false; + if (!deepEqual(a[key], b[key])) return false; + } + return true; +} + +const STANDARD_TOOLS = { + // File operations + "Read": "Read File", + "Write": "Write File", + "Edit": "Edit File", + "MultiEdit": "Edit File", + "NotebookEdit": "Edit Notebook", + // Search and navigation + "Glob": "Find Files", + "Grep": "Search in Files", + "LS": "List Directory", + // Command execution + "Bash": "Run Command", + "BashOutput": "Check Command Output", + "KillBash": "Stop Command", + // Task management + "TodoWrite": "Update Tasks", + "TodoRead": "Read Tasks", + "Task": "Launch Agent", + // Web tools + "WebFetch": "Fetch Web Page", + "WebSearch": "Search Web", + // Special cases + "exit_plan_mode": "Execute Plan", + "ExitPlanMode": "Execute Plan" +}; +function toTitleCase(str) { + return str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase()); +} +function getToolName(toolName) { + if (STANDARD_TOOLS[toolName]) { + return STANDARD_TOOLS[toolName]; + } + if (toolName.startsWith("mcp__")) { + const parts = toolName.split("__"); + if (parts.length >= 3) { + const server = toTitleCase(parts[1]); + const action = toTitleCase(parts.slice(2).join("_")); + return `${server}: ${action}`; + } + } + return toTitleCase(toolName); +} + +function getToolDescriptor(toolName) { + if (toolName === "exit_plan_mode" || toolName === "ExitPlanMode") { + return { edit: false, exitPlan: true }; + } + if (toolName === "Edit" || toolName === "MultiEdit" || toolName === "Write" || toolName === "NotebookEdit") { + return { edit: true, exitPlan: false }; + } + return { edit: false, exitPlan: false }; +} + +class PermissionHandler { + toolCalls = []; + responses = /* @__PURE__ */ new Map(); + pendingRequests = /* @__PURE__ */ new Map(); + session; + allowedTools = /* @__PURE__ */ new Set(); + allowedBashLiterals = /* @__PURE__ */ new Set(); + allowedBashPrefixes = /* @__PURE__ */ new Set(); + permissionMode = "default"; + onPermissionRequestCallback; + constructor(session) { + this.session = session; + this.setupClientHandler(); + } + /** + * Set callback to trigger when permission request is made + */ + setOnPermissionRequest(callback) { + this.onPermissionRequestCallback = callback; + } + handleModeChange(mode) { + this.permissionMode = mode; + } + /** + * Handler response + */ + handlePermissionResponse(response, pending) { + if (response.allowTools && response.allowTools.length > 0) { + response.allowTools.forEach((tool) => { + if (tool.startsWith("Bash(") || tool === "Bash") { + this.parseBashPermission(tool); + } else { + this.allowedTools.add(tool); + } + }); + } + if (response.mode) { + this.permissionMode = response.mode; + } + if (pending.toolName === "exit_plan_mode" || pending.toolName === "ExitPlanMode") { + types.logger.debug("Plan mode result received", response); + if (response.approved) { + types.logger.debug("Plan approved - injecting PLAN_FAKE_RESTART"); + if (response.mode && ["default", "acceptEdits", "bypassPermissions"].includes(response.mode)) { + this.session.queue.unshift(PLAN_FAKE_RESTART, { permissionMode: response.mode }); + } else { + this.session.queue.unshift(PLAN_FAKE_RESTART, { permissionMode: "default" }); + } + pending.resolve({ behavior: "deny", message: PLAN_FAKE_REJECT }); + } else { + pending.resolve({ behavior: "deny", message: response.reason || "Plan rejected" }); + } + } else { + const result = response.approved ? { behavior: "allow", updatedInput: pending.input || {} } : { behavior: "deny", message: response.reason || `The user doesn't want to proceed with this tool use. The tool use was rejected (eg. if it was a file edit, the new_string was NOT written to the file). STOP what you are doing and wait for the user to tell you how to proceed.` }; + pending.resolve(result); + } + } + /** + * Creates the canCallTool callback for the SDK + */ + handleToolCall = async (toolName, input, mode, options) => { + if (toolName === "Bash") { + const inputObj = input; + if (inputObj?.command) { + if (this.allowedBashLiterals.has(inputObj.command)) { + return { behavior: "allow", updatedInput: input }; + } + for (const prefix of this.allowedBashPrefixes) { + if (inputObj.command.startsWith(prefix)) { + return { behavior: "allow", updatedInput: input }; + } + } + } + } else if (this.allowedTools.has(toolName)) { + return { behavior: "allow", updatedInput: input }; + } + const descriptor = getToolDescriptor(toolName); + if (this.permissionMode === "bypassPermissions") { + return { behavior: "allow", updatedInput: input }; + } + if (this.permissionMode === "acceptEdits" && descriptor.edit) { + return { behavior: "allow", updatedInput: input }; + } + let toolCallId = this.resolveToolCallId(toolName, input); + if (!toolCallId) { + await types.delay(1e3); + toolCallId = this.resolveToolCallId(toolName, input); + if (!toolCallId) { + throw new Error(`Could not resolve tool call ID for ${toolName}`); + } + } + return this.handlePermissionRequest(toolCallId, toolName, input, options.signal); + }; + /** + * Handles individual permission requests + */ + async handlePermissionRequest(id, toolName, input, signal) { + return new Promise((resolve, reject) => { + const abortHandler = () => { + this.pendingRequests.delete(id); + reject(new Error("Permission request aborted")); + }; + signal.addEventListener("abort", abortHandler, { once: true }); + this.pendingRequests.set(id, { + resolve: (result) => { + signal.removeEventListener("abort", abortHandler); + resolve(result); + }, + reject: (error) => { + signal.removeEventListener("abort", abortHandler); + reject(error); + }, + toolName, + input + }); + if (this.onPermissionRequestCallback) { + this.onPermissionRequestCallback(id); + } + this.session.api.push().sendToAllDevices( + "Permission Request", + `Claude wants to ${getToolName(toolName)}`, + { + sessionId: this.session.client.sessionId, + requestId: id, + tool: toolName, + type: "permission_request" + } + ); + this.session.client.updateAgentState((currentState) => ({ + ...currentState, + requests: { + ...currentState.requests, + [id]: { + tool: toolName, + arguments: input, + createdAt: Date.now() + } + } + })); + types.logger.debug(`Permission request sent for tool call ${id}: ${toolName}`); + }); + } + /** + * Parses Bash permission strings into literal and prefix sets + */ + parseBashPermission(permission) { + if (permission === "Bash") { + return; + } + const bashPattern = /^Bash\((.+?)\)$/; + const match = permission.match(bashPattern); + if (!match) { + return; + } + const command = match[1]; + if (command.endsWith(":*")) { + const prefix = command.slice(0, -2); + this.allowedBashPrefixes.add(prefix); + } else { + this.allowedBashLiterals.add(command); + } + } + /** + * Resolves tool call ID based on tool name and input + */ + resolveToolCallId(name, args) { + for (let i = this.toolCalls.length - 1; i >= 0; i--) { + const call = this.toolCalls[i]; + if (call.name === name && deepEqual(call.input, args)) { + if (call.used) { + return null; + } + call.used = true; + return call.id; + } + } + return null; + } + /** + * Handles messages to track tool calls + */ + onMessage(message) { + if (message.type === "assistant") { + const assistantMsg = message; + if (assistantMsg.message && assistantMsg.message.content) { + for (const block of assistantMsg.message.content) { + if (block.type === "tool_use") { + this.toolCalls.push({ + id: block.id, + name: block.name, + input: block.input, + used: false + }); + } + } + } + } + if (message.type === "user") { + const userMsg = message; + if (userMsg.message && userMsg.message.content && Array.isArray(userMsg.message.content)) { + for (const block of userMsg.message.content) { + if (block.type === "tool_result" && block.tool_use_id) { + const toolCall = this.toolCalls.find((tc) => tc.id === block.tool_use_id); + if (toolCall && !toolCall.used) { + toolCall.used = true; + } + } + } + } + } + } + /** + * Checks if a tool call is rejected + */ + isAborted(toolCallId) { + if (this.responses.get(toolCallId)?.approved === false) { + return true; + } + const toolCall = this.toolCalls.find((tc) => tc.id === toolCallId); + if (toolCall && (toolCall.name === "exit_plan_mode" || toolCall.name === "ExitPlanMode")) { + return true; + } + return false; + } + /** + * Resets all state for new sessions + */ + reset() { + this.toolCalls = []; + this.responses.clear(); + this.allowedTools.clear(); + this.allowedBashLiterals.clear(); + this.allowedBashPrefixes.clear(); + for (const [, pending] of this.pendingRequests.entries()) { + pending.reject(new Error("Session reset")); + } + this.pendingRequests.clear(); + this.session.client.updateAgentState((currentState) => { + const pendingRequests = currentState.requests || {}; + const completedRequests = { ...currentState.completedRequests }; + for (const [id, request] of Object.entries(pendingRequests)) { + completedRequests[id] = { + ...request, + completedAt: Date.now(), + status: "canceled", + reason: "Session switched to local mode" + }; + } + return { + ...currentState, + requests: {}, + // Clear all pending requests + completedRequests + }; + }); + } + /** + * Sets up the client handler for permission responses + */ + setupClientHandler() { + this.session.client.rpcHandlerManager.registerHandler("permission", async (message) => { + types.logger.debug(`Permission response: ${JSON.stringify(message)}`); + const id = message.id; + const pending = this.pendingRequests.get(id); + if (!pending) { + types.logger.debug("Permission request not found or already resolved"); + return; + } + this.responses.set(id, { ...message, receivedAt: Date.now() }); + this.pendingRequests.delete(id); + this.handlePermissionResponse(message, pending); + this.session.client.updateAgentState((currentState) => { + const request = currentState.requests?.[id]; + if (!request) return currentState; + let r = { ...currentState.requests }; + delete r[id]; + return { + ...currentState, + requests: r, + completedRequests: { + ...currentState.completedRequests, + [id]: { + ...request, + completedAt: Date.now(), + status: message.approved ? "approved" : "denied", + reason: message.reason, + mode: message.mode, + allowTools: message.allowTools + } + } + }; + }); + }); + } + /** + * Gets the responses map (for compatibility with existing code) + */ + getResponses() { + return this.responses; + } +} + +function formatClaudeMessageForInk(message, messageBuffer, onAssistantResult) { + types.logger.debugLargeJson("[CLAUDE INK] Message from remote mode:", message); + switch (message.type) { + case "system": { + const sysMsg = message; + if (sysMsg.subtype === "init") { + messageBuffer.addMessage("\u2500".repeat(40), "status"); + messageBuffer.addMessage(`\u{1F680} Session initialized: ${sysMsg.session_id}`, "system"); + messageBuffer.addMessage(` Model: ${sysMsg.model}`, "status"); + messageBuffer.addMessage(` CWD: ${sysMsg.cwd}`, "status"); + if (sysMsg.tools && sysMsg.tools.length > 0) { + messageBuffer.addMessage(` Tools: ${sysMsg.tools.join(", ")}`, "status"); + } + messageBuffer.addMessage("\u2500".repeat(40), "status"); + } + break; + } + case "user": { + const userMsg = message; + if (userMsg.message && typeof userMsg.message === "object" && "content" in userMsg.message) { + const content = userMsg.message.content; + if (typeof content === "string") { + messageBuffer.addMessage(`\u{1F464} User: ${content}`, "user"); + } else if (Array.isArray(content)) { + for (const block of content) { + if (block.type === "text") { + messageBuffer.addMessage(`\u{1F464} User: ${block.text}`, "user"); + } else if (block.type === "tool_result") { + messageBuffer.addMessage(`\u2705 Tool Result (ID: ${block.tool_use_id})`, "result"); + if (block.content) { + const outputStr = typeof block.content === "string" ? block.content : JSON.stringify(block.content, null, 2); + const maxLength = 200; + if (outputStr.length > maxLength) { + messageBuffer.addMessage(outputStr.substring(0, maxLength) + "... (truncated)", "result"); + } else { + messageBuffer.addMessage(outputStr, "result"); + } + } + } + } + } else { + messageBuffer.addMessage(`\u{1F464} User: ${JSON.stringify(content, null, 2)}`, "user"); + } + } + break; + } + case "assistant": { + const assistantMsg = message; + if (assistantMsg.message && assistantMsg.message.content) { + messageBuffer.addMessage("\u{1F916} Assistant:", "assistant"); + for (const block of assistantMsg.message.content) { + if (block.type === "text") { + messageBuffer.addMessage(block.text || "", "assistant"); + } else if (block.type === "tool_use") { + messageBuffer.addMessage(`\u{1F527} Tool: ${block.name}`, "tool"); + if (block.input) { + const inputStr = JSON.stringify(block.input, null, 2); + const maxLength = 500; + if (inputStr.length > maxLength) { + messageBuffer.addMessage(`Input: ${inputStr.substring(0, maxLength)}... (truncated)`, "tool"); + } else { + messageBuffer.addMessage(`Input: ${inputStr}`, "tool"); + } + } + } + } + } + break; + } + case "result": { + const resultMsg = message; + if (resultMsg.subtype === "success") { + if ("result" in resultMsg && resultMsg.result) { + messageBuffer.addMessage("\u2728 Summary:", "result"); + messageBuffer.addMessage(resultMsg.result || "", "result"); + } + if (resultMsg.usage) { + messageBuffer.addMessage("\u{1F4CA} Session Stats:", "status"); + messageBuffer.addMessage(` \u2022 Turns: ${resultMsg.num_turns}`, "status"); + messageBuffer.addMessage(` \u2022 Input tokens: ${resultMsg.usage.input_tokens}`, "status"); + messageBuffer.addMessage(` \u2022 Output tokens: ${resultMsg.usage.output_tokens}`, "status"); + if (resultMsg.usage.cache_read_input_tokens) { + messageBuffer.addMessage(` \u2022 Cache read tokens: ${resultMsg.usage.cache_read_input_tokens}`, "status"); + } + if (resultMsg.usage.cache_creation_input_tokens) { + messageBuffer.addMessage(` \u2022 Cache creation tokens: ${resultMsg.usage.cache_creation_input_tokens}`, "status"); + } + messageBuffer.addMessage(` \u2022 Cost: $${resultMsg.total_cost_usd.toFixed(4)}`, "status"); + messageBuffer.addMessage(` \u2022 Duration: ${resultMsg.duration_ms}ms`, "status"); + } + } else if (resultMsg.subtype === "error_max_turns") { + messageBuffer.addMessage("\u274C Error: Maximum turns reached", "result"); + messageBuffer.addMessage(`Completed ${resultMsg.num_turns} turns`, "status"); + } else if (resultMsg.subtype === "error_during_execution") { + messageBuffer.addMessage("\u274C Error during execution", "result"); + messageBuffer.addMessage(`Completed ${resultMsg.num_turns} turns before error`, "status"); + types.logger.debugLargeJson("[RESULT] Error during execution", resultMsg); + } + break; + } + default: { + if (process.env.DEBUG) { + messageBuffer.addMessage(`[Unknown message type: ${message.type}]`, "status"); + } + } + } +} + +function getGitBranch(cwd) { + try { + const branch = node_child_process.execSync("git rev-parse --abbrev-ref HEAD", { + cwd, + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"] + }).trim(); + return branch || void 0; + } catch { + return void 0; + } +} +class SDKToLogConverter { + lastUuid = null; + context; + responses; + sidechainLastUUID = /* @__PURE__ */ new Map(); + constructor(context, responses) { + this.context = { + ...context, + gitBranch: context.gitBranch ?? getGitBranch(context.cwd), + version: context.version ?? process.env.npm_package_version ?? "0.0.0", + parentUuid: null + }; + this.responses = responses; + } + /** + * Update session ID (for when session changes during resume) + */ + updateSessionId(sessionId) { + this.context.sessionId = sessionId; + } + /** + * Reset parent chain (useful when starting new conversation) + */ + resetParentChain() { + this.lastUuid = null; + this.context.parentUuid = null; + } + /** + * Convert SDK message to log format + */ + convert(sdkMessage) { + const uuid = node_crypto.randomUUID(); + const timestamp = (/* @__PURE__ */ new Date()).toISOString(); + let parentUuid = this.lastUuid; + let isSidechain = false; + if (sdkMessage.parent_tool_use_id) { + isSidechain = true; + parentUuid = this.sidechainLastUUID.get(sdkMessage.parent_tool_use_id) ?? null; + this.sidechainLastUUID.set(sdkMessage.parent_tool_use_id, uuid); + } + const baseFields = { + parentUuid, + isSidechain, + userType: "external", + cwd: this.context.cwd, + sessionId: this.context.sessionId, + version: this.context.version, + gitBranch: this.context.gitBranch, + uuid, + timestamp + }; + let logMessage = null; + switch (sdkMessage.type) { + case "user": { + const userMsg = sdkMessage; + logMessage = { + ...baseFields, + type: "user", + message: userMsg.message + }; + if (Array.isArray(userMsg.message.content)) { + for (const content of userMsg.message.content) { + if (content.type === "tool_result" && content.tool_use_id && this.responses?.has(content.tool_use_id)) { + const response = this.responses.get(content.tool_use_id); + if (response?.mode) { + logMessage.mode = response.mode; + } + } + } + } else if (typeof userMsg.message.content === "string") ; + break; + } + case "assistant": { + const assistantMsg = sdkMessage; + logMessage = { + ...baseFields, + type: "assistant", + message: assistantMsg.message, + // Assistant messages often have additional fields + requestId: assistantMsg.requestId + }; + break; + } + case "system": { + const systemMsg = sdkMessage; + if (systemMsg.subtype === "init" && systemMsg.session_id) { + this.updateSessionId(systemMsg.session_id); + } + logMessage = { + ...baseFields, + type: "system", + subtype: systemMsg.subtype, + model: systemMsg.model, + tools: systemMsg.tools, + // Include all other fields + ...systemMsg + }; + break; + } + case "result": { + break; + } + // Handle tool use results (often comes as user messages) + case "tool_result": { + const toolMsg = sdkMessage; + const baseLogMessage = { + ...baseFields, + type: "user", + message: { + role: "user", + content: [{ + type: "tool_result", + tool_use_id: toolMsg.tool_use_id, + content: toolMsg.content + }] + }, + toolUseResult: toolMsg.content + }; + if (toolMsg.tool_use_id && this.responses?.has(toolMsg.tool_use_id)) { + const response = this.responses.get(toolMsg.tool_use_id); + if (response?.mode) { + baseLogMessage.mode = response.mode; + } + } + logMessage = baseLogMessage; + break; + } + default: + logMessage = { + ...baseFields, + ...sdkMessage, + type: sdkMessage.type + // Override type last to ensure it's set + }; + } + if (logMessage && logMessage.type !== "summary") { + this.lastUuid = uuid; + } + return logMessage; + } + /** + * Convert multiple SDK messages to log format + */ + convertMany(sdkMessages) { + return sdkMessages.map((msg) => this.convert(msg)).filter((msg) => msg !== null); + } + /** + * Convert a simple string content to a sidechain user message + * Used for Task tool sub-agent prompts + */ + convertSidechainUserMessage(toolUseId, content) { + const uuid = node_crypto.randomUUID(); + const timestamp = (/* @__PURE__ */ new Date()).toISOString(); + this.sidechainLastUUID.set(toolUseId, uuid); + return { + parentUuid: null, + isSidechain: true, + userType: "external", + cwd: this.context.cwd, + sessionId: this.context.sessionId, + version: this.context.version, + gitBranch: this.context.gitBranch, + type: "user", + message: { + role: "user", + content + }, + uuid, + timestamp + }; + } + /** + * Generate an interrupted tool result message + * Used when a tool call is interrupted by the user + * @param toolUseId - The ID of the tool that was interrupted + * @param parentToolUseId - Optional parent tool ID if this is a sidechain tool + */ + generateInterruptedToolResult(toolUseId, parentToolUseId) { + const uuid = node_crypto.randomUUID(); + const timestamp = (/* @__PURE__ */ new Date()).toISOString(); + const errorMessage = "[Request interrupted by user for tool use]"; + let isSidechain = false; + let parentUuid = this.lastUuid; + if (parentToolUseId) { + isSidechain = true; + parentUuid = this.sidechainLastUUID.get(parentToolUseId) ?? null; + this.sidechainLastUUID.set(parentToolUseId, uuid); + } + const logMessage = { + type: "user", + isSidechain, + uuid, + message: { + role: "user", + content: [ + { + type: "tool_result", + content: errorMessage, + is_error: true, + tool_use_id: toolUseId + } + ] + }, + parentUuid, + userType: "external", + cwd: this.context.cwd, + sessionId: this.context.sessionId, + version: this.context.version, + gitBranch: this.context.gitBranch, + timestamp, + toolUseResult: `Error: ${errorMessage}` + }; + this.lastUuid = uuid; + return logMessage; + } +} + +class OutgoingMessageQueue { + constructor(sendFunction) { + this.sendFunction = sendFunction; + } + queue = []; + nextId = 1; + lock = new types.AsyncLock(); + processTimer; + delayTimers = /* @__PURE__ */ new Map(); + /** + * Add message to queue + */ + enqueue(logMessage, options) { + this.lock.inLock(async () => { + const item = { + id: this.nextId++, + logMessage, + delayed: !!options?.delay, + delayMs: options?.delay || 0, + toolCallIds: options?.toolCallIds, + released: !options?.delay, + // Not delayed = already released + sent: false + }; + this.queue.push(item); + if (item.delayed) { + const timer = setTimeout(() => { + this.releaseItem(item.id); + }, item.delayMs); + this.delayTimers.set(item.id, timer); + } + }); + this.scheduleProcessing(); + } + /** + * Release specific item by ID + */ + async releaseItem(itemId) { + await this.lock.inLock(async () => { + const item = this.queue.find((i) => i.id === itemId); + if (item && !item.released) { + item.released = true; + const timer = this.delayTimers.get(itemId); + if (timer) { + clearTimeout(timer); + this.delayTimers.delete(itemId); + } + } + }); + this.scheduleProcessing(); + } + /** + * Release all messages with specific tool call ID + */ + async releaseToolCall(toolCallId) { + await this.lock.inLock(async () => { + for (const item of this.queue) { + if (item.toolCallIds?.includes(toolCallId) && !item.released) { + item.released = true; + const timer = this.delayTimers.get(item.id); + if (timer) { + clearTimeout(timer); + this.delayTimers.delete(item.id); + } + } + } + }); + this.scheduleProcessing(); + } + /** + * Process queue - send messages in ID order that are released + * (Internal implementation without lock) + */ + processQueueInternal() { + this.queue.sort((a, b) => a.id - b.id); + while (this.queue.length > 0) { + const item = this.queue[0]; + if (!item.released) { + break; + } + if (!item.sent) { + if (item.logMessage.type !== "system") { + this.sendFunction(item.logMessage); + } + item.sent = true; + } + this.queue.shift(); + } + } + /** + * Process queue - send messages in ID order that are released + */ + async processQueue() { + await this.lock.inLock(async () => { + this.processQueueInternal(); + }); + } + /** + * Flush all messages immediately (for cleanup) + */ + async flush() { + await this.lock.inLock(async () => { + for (const timer of this.delayTimers.values()) { + clearTimeout(timer); + } + this.delayTimers.clear(); + for (const item of this.queue) { + item.released = true; + } + this.processQueueInternal(); + }); + } + /** + * Schedule processing on next tick + */ + scheduleProcessing() { + if (this.processTimer) { + clearTimeout(this.processTimer); + } + this.processTimer = setTimeout(() => { + this.processQueue(); + }, 0); + } + /** + * Cleanup timers and resources + */ + destroy() { + if (this.processTimer) { + clearTimeout(this.processTimer); + } + for (const timer of this.delayTimers.values()) { + clearTimeout(timer); + } + this.delayTimers.clear(); + } +} + +async function claudeRemoteLauncher(session) { + types.logger.debug("[claudeRemoteLauncher] Starting remote launcher"); + const hasTTY = process.stdout.isTTY && process.stdin.isTTY; + types.logger.debug(`[claudeRemoteLauncher] TTY available: ${hasTTY}`); + let messageBuffer = new MessageBuffer(); + let inkInstance = null; + if (hasTTY) { + console.clear(); + inkInstance = ink.render(React.createElement(RemoteModeDisplay, { + messageBuffer, + logPath: process.env.DEBUG ? session.logPath : void 0, + onExit: async () => { + types.logger.debug("[remote]: Exiting client via Ctrl-C"); + if (!exitReason) { + exitReason = "exit"; + } + await abort(); + }, + onSwitchToLocal: () => { + types.logger.debug("[remote]: Switching to local mode via double space"); + doSwitch(); + } + }), { + exitOnCtrlC: false, + patchConsole: false + }); + } + if (hasTTY) { + process.stdin.resume(); + if (process.stdin.isTTY) { + process.stdin.setRawMode(true); + } + process.stdin.setEncoding("utf8"); + } + let exitReason = null; + let abortController = null; + let abortFuture = null; + async function abort() { + if (abortController && !abortController.signal.aborted) { + abortController.abort(); + } + await abortFuture?.promise; + } + async function doAbort() { + types.logger.debug("[remote]: doAbort"); + await abort(); + } + async function doSwitch() { + types.logger.debug("[remote]: doSwitch"); + if (!exitReason) { + exitReason = "switch"; + } + await abort(); + } + session.client.rpcHandlerManager.registerHandler("abort", doAbort); + session.client.rpcHandlerManager.registerHandler("switch", doSwitch); + const permissionHandler = new PermissionHandler(session); + const messageQueue = new OutgoingMessageQueue( + (logMessage) => session.client.sendClaudeSessionMessage(logMessage) + ); + permissionHandler.setOnPermissionRequest((toolCallId) => { + messageQueue.releaseToolCall(toolCallId); + }); + const sdkToLogConverter = new SDKToLogConverter({ + sessionId: session.sessionId || "unknown", + cwd: session.path, + version: process.env.npm_package_version + }, permissionHandler.getResponses()); + let planModeToolCalls = /* @__PURE__ */ new Set(); + let ongoingToolCalls = /* @__PURE__ */ new Map(); + function onMessage(message) { + formatClaudeMessageForInk(message, messageBuffer); + permissionHandler.onMessage(message); + if (message.type === "assistant") { + let umessage = message; + if (umessage.message.content && Array.isArray(umessage.message.content)) { + for (let c of umessage.message.content) { + if (c.type === "tool_use" && (c.name === "exit_plan_mode" || c.name === "ExitPlanMode")) { + types.logger.debug("[remote]: detected plan mode tool call " + c.id); + planModeToolCalls.add(c.id); + } + } + } + } + if (message.type === "assistant") { + let umessage = message; + if (umessage.message.content && Array.isArray(umessage.message.content)) { + for (let c of umessage.message.content) { + if (c.type === "tool_use") { + types.logger.debug("[remote]: detected tool use " + c.id + " parent: " + umessage.parent_tool_use_id); + ongoingToolCalls.set(c.id, { parentToolCallId: umessage.parent_tool_use_id ?? null }); + } + } + } + } + if (message.type === "user") { + let umessage = message; + if (umessage.message.content && Array.isArray(umessage.message.content)) { + for (let c of umessage.message.content) { + if (c.type === "tool_result" && c.tool_use_id) { + ongoingToolCalls.delete(c.tool_use_id); + messageQueue.releaseToolCall(c.tool_use_id); + } + } + } + } + let msg = message; + if (message.type === "user") { + let umessage = message; + if (umessage.message.content && Array.isArray(umessage.message.content)) { + msg = { + ...umessage, + message: { + ...umessage.message, + content: umessage.message.content.map((c) => { + if (c.type === "tool_result" && c.tool_use_id && planModeToolCalls.has(c.tool_use_id)) { + if (c.content === PLAN_FAKE_REJECT) { + types.logger.debug("[remote]: hack plan mode exit"); + types.logger.debugLargeJson("[remote]: hack plan mode exit", c); + return { + ...c, + is_error: false, + content: "Plan approved", + mode: c.mode + }; + } else { + return c; + } + } + return c; + }) + } + }; + } + } + const logMessage = sdkToLogConverter.convert(msg); + if (logMessage) { + if (logMessage.type === "user" && logMessage.message?.content) { + const content = Array.isArray(logMessage.message.content) ? logMessage.message.content : []; + for (let i = 0; i < content.length; i++) { + const c = content[i]; + if (c.type === "tool_result" && c.tool_use_id) { + const responses = permissionHandler.getResponses(); + const response = responses.get(c.tool_use_id); + if (response) { + const permissions = { + date: response.receivedAt || Date.now(), + result: response.approved ? "approved" : "denied" + }; + if (response.mode) { + permissions.mode = response.mode; + } + if (response.allowTools && response.allowTools.length > 0) { + permissions.allowedTools = response.allowTools; + } + content[i] = { + ...c, + permissions + }; + } + } + } + } + if (logMessage.type === "assistant" && message.type === "assistant") { + const assistantMsg = message; + const toolCallIds = []; + if (assistantMsg.message.content && Array.isArray(assistantMsg.message.content)) { + for (const block of assistantMsg.message.content) { + if (block.type === "tool_use" && block.id) { + toolCallIds.push(block.id); + } + } + } + if (toolCallIds.length > 0) { + const isSidechain = assistantMsg.parent_tool_use_id !== void 0; + if (!isSidechain) { + messageQueue.enqueue(logMessage, { + delay: 250, + toolCallIds + }); + return; + } + } + } + messageQueue.enqueue(logMessage); + } + if (message.type === "assistant") { + let umessage = message; + if (umessage.message.content && Array.isArray(umessage.message.content)) { + for (let c of umessage.message.content) { + if (c.type === "tool_use" && c.name === "Task" && c.input && typeof c.input.prompt === "string") { + const logMessage2 = sdkToLogConverter.convertSidechainUserMessage(c.id, c.input.prompt); + if (logMessage2) { + messageQueue.enqueue(logMessage2); + } + } + } + } + } + } + try { + let pending = null; + let previousSessionId = null; + while (!exitReason) { + types.logger.debug("[remote]: launch"); + messageBuffer.addMessage("\u2550".repeat(40), "status"); + const isNewSession = session.sessionId !== previousSessionId; + if (isNewSession) { + messageBuffer.addMessage("Starting new Claude session...", "status"); + permissionHandler.reset(); + sdkToLogConverter.resetParentChain(); + types.logger.debug(`[remote]: New session detected (previous: ${previousSessionId}, current: ${session.sessionId})`); + } else { + messageBuffer.addMessage("Continuing Claude session...", "status"); + types.logger.debug(`[remote]: Continuing existing session: ${session.sessionId}`); + } + previousSessionId = session.sessionId; + const controller = new AbortController(); + abortController = controller; + abortFuture = new Future(); + let modeHash = null; + let mode = null; + try { + const remoteResult = await claudeRemote({ + sessionId: session.sessionId, + path: session.path, + allowedTools: session.allowedTools ?? [], + mcpServers: session.mcpServers, + canCallTool: permissionHandler.handleToolCall, + isAborted: (toolCallId) => { + return permissionHandler.isAborted(toolCallId); + }, + nextMessage: async () => { + if (pending) { + let p = pending; + pending = null; + permissionHandler.handleModeChange(p.mode.permissionMode); + return p; + } + let msg = await session.queue.waitForMessagesAndGetAsString(controller.signal); + if (msg) { + if (modeHash && msg.hash !== modeHash || msg.isolate) { + types.logger.debug("[remote]: mode has changed, pending message"); + pending = msg; + return null; + } + modeHash = msg.hash; + mode = msg.mode; + permissionHandler.handleModeChange(mode.permissionMode); + return { + message: msg.message, + mode: msg.mode + }; + } + return null; + }, + onSessionFound: (sessionId) => { + sdkToLogConverter.updateSessionId(sessionId); + session.onSessionFound(sessionId); + }, + onThinkingChange: session.onThinkingChange, + claudeEnvVars: session.claudeEnvVars, + claudeArgs: session.claudeArgs, + onMessage, + onCompletionEvent: (message) => { + types.logger.debug(`[remote]: Completion event: ${message}`); + session.client.sendSessionEvent({ type: "message", message }).catch((err) => types.logger.debug("[Claude] Failed to send completion event:", err)); + }, + onSessionReset: () => { + types.logger.debug("[remote]: Session reset"); + session.clearSessionId(); + }, + onReady: () => { + if (!pending && session.queue.size() === 0) { + session.client.sendSessionEvent({ type: "ready" }).catch((err) => types.logger.debug("[Claude] Failed to send ready event:", err)); + session.api.push().sendToAllDevices( + "It's ready!", + `Claude is waiting for your command`, + { sessionId: session.client.sessionId } + ); + } + }, + signal: abortController.signal + }); + session.consumeOneTimeFlags(); + if (!exitReason && abortController.signal.aborted) { + session.client.sendSessionEvent({ type: "message", message: "Aborted by user" }).catch((err) => types.logger.debug("[Claude] Failed to send abort event:", err)); + } + } catch (e) { + types.logger.debug("[remote]: launch error", e); + if (!exitReason) { + session.client.sendSessionEvent({ type: "message", message: "Process exited unexpectedly" }).catch((err) => types.logger.debug("[Claude] Failed to send exit event:", err)); + continue; + } + } finally { + types.logger.debug("[remote]: launch finally"); + for (let [toolCallId, { parentToolCallId }] of ongoingToolCalls) { + const converted = sdkToLogConverter.generateInterruptedToolResult(toolCallId, parentToolCallId); + if (converted) { + types.logger.debug("[remote]: terminating tool call " + toolCallId + " parent: " + parentToolCallId); + session.client.sendClaudeSessionMessage(converted); + } + } + ongoingToolCalls.clear(); + types.logger.debug("[remote]: flushing message queue"); + await messageQueue.flush(); + messageQueue.destroy(); + types.logger.debug("[remote]: message queue flushed"); + abortController = null; + abortFuture?.resolve(void 0); + abortFuture = null; + types.logger.debug("[remote]: launch done"); + permissionHandler.reset(); + modeHash = null; + mode = null; + } + } + } finally { + permissionHandler.reset(); + process.stdin.off("data", abort); + if (process.stdin.isTTY) { + process.stdin.setRawMode(false); + } + if (inkInstance) { + inkInstance.unmount(); + } + messageBuffer.clear(); + if (abortFuture) { + abortFuture.resolve(void 0); + } + } + return exitReason || "exit"; +} + +async function loop(opts) { + const logPath = types.logger.logFilePath; + let session = new Session({ + api: opts.api, + client: opts.session, + path: opts.path, + sessionId: null, + claudeEnvVars: opts.claudeEnvVars, + claudeArgs: opts.claudeArgs, + mcpServers: opts.mcpServers, + logPath, + messageQueue: opts.messageQueue, + allowedTools: opts.allowedTools, + onModeChange: opts.onModeChange + }); + if (opts.onSessionReady) { + opts.onSessionReady(session); + } + let mode = opts.startingMode ?? "local"; + while (true) { + types.logger.debug(`[loop] Iteration with mode: ${mode}`); + if (mode === "local") { + let reason = await claudeLocalLauncher(session); + if (reason === "exit") { + return; + } + mode = "remote"; + if (opts.onModeChange) { + opts.onModeChange(mode); + } + continue; + } + if (mode === "remote") { + let reason = await claudeRemoteLauncher(session); + if (reason === "exit") { + return; + } + mode = "local"; + if (opts.onModeChange) { + opts.onModeChange(mode); + } + continue; + } + } +} + +class MessageQueue2 { + queue = []; + // Made public for testing + waiter = null; + closed = false; + onMessageHandler = null; + modeHasher; + constructor(modeHasher, onMessageHandler = null) { + this.modeHasher = modeHasher; + this.onMessageHandler = onMessageHandler; + types.logger.debug(`[MessageQueue2] Initialized`); + } + /** + * Set a handler that will be called when a message arrives + */ + setOnMessage(handler) { + this.onMessageHandler = handler; + } + /** + * Push a message to the queue with a mode. + */ + push(message, mode) { + if (this.closed) { + throw new Error("Cannot push to closed queue"); + } + const modeHash = this.modeHasher(mode); + types.logger.debug(`[MessageQueue2] push() called with mode hash: ${modeHash}`); + this.queue.push({ + message, + mode, + modeHash, + isolate: false + }); + if (this.onMessageHandler) { + this.onMessageHandler(message, mode); + } + if (this.waiter) { + types.logger.debug(`[MessageQueue2] Notifying waiter`); + const waiter = this.waiter; + this.waiter = null; + waiter(true); + } + types.logger.debug(`[MessageQueue2] push() completed. Queue size: ${this.queue.length}`); + } + /** + * Push a message immediately without batching delay. + * Does not clear the queue or enforce isolation. + */ + pushImmediate(message, mode) { + if (this.closed) { + throw new Error("Cannot push to closed queue"); + } + const modeHash = this.modeHasher(mode); + types.logger.debug(`[MessageQueue2] pushImmediate() called with mode hash: ${modeHash}`); + this.queue.push({ + message, + mode, + modeHash, + isolate: false + }); + if (this.onMessageHandler) { + this.onMessageHandler(message, mode); + } + if (this.waiter) { + types.logger.debug(`[MessageQueue2] Notifying waiter for immediate message`); + const waiter = this.waiter; + this.waiter = null; + waiter(true); + } + types.logger.debug(`[MessageQueue2] pushImmediate() completed. Queue size: ${this.queue.length}`); + } + /** + * Push a message that must be processed in complete isolation. + * Clears any pending messages and ensures this message is never batched with others. + * Used for special commands that require dedicated processing. + */ + pushIsolateAndClear(message, mode) { + if (this.closed) { + throw new Error("Cannot push to closed queue"); + } + const modeHash = this.modeHasher(mode); + types.logger.debug(`[MessageQueue2] pushIsolateAndClear() called with mode hash: ${modeHash} - clearing ${this.queue.length} pending messages`); + this.queue = []; + this.queue.push({ + message, + mode, + modeHash, + isolate: true + }); + if (this.onMessageHandler) { + this.onMessageHandler(message, mode); + } + if (this.waiter) { + types.logger.debug(`[MessageQueue2] Notifying waiter for isolated message`); + const waiter = this.waiter; + this.waiter = null; + waiter(true); + } + types.logger.debug(`[MessageQueue2] pushIsolateAndClear() completed. Queue size: ${this.queue.length}`); + } + /** + * Push a message to the beginning of the queue with a mode. + */ + unshift(message, mode) { + if (this.closed) { + throw new Error("Cannot unshift to closed queue"); + } + const modeHash = this.modeHasher(mode); + types.logger.debug(`[MessageQueue2] unshift() called with mode hash: ${modeHash}`); + this.queue.unshift({ + message, + mode, + modeHash, + isolate: false + }); + if (this.onMessageHandler) { + this.onMessageHandler(message, mode); + } + if (this.waiter) { + types.logger.debug(`[MessageQueue2] Notifying waiter`); + const waiter = this.waiter; + this.waiter = null; + waiter(true); + } + types.logger.debug(`[MessageQueue2] unshift() completed. Queue size: ${this.queue.length}`); + } + /** + * Reset the queue - clears all messages and resets to empty state + */ + reset() { + types.logger.debug(`[MessageQueue2] reset() called. Clearing ${this.queue.length} messages`); + this.queue = []; + this.closed = false; + this.waiter = null; + } + /** + * Close the queue - no more messages can be pushed + */ + close() { + types.logger.debug(`[MessageQueue2] close() called`); + this.closed = true; + if (this.waiter) { + const waiter = this.waiter; + this.waiter = null; + waiter(false); + } + } + /** + * Check if the queue is closed + */ + isClosed() { + return this.closed; + } + /** + * Get the current queue size + */ + size() { + return this.queue.length; + } + /** + * Wait for messages and return all messages with the same mode as a single string + * Returns { message: string, mode: T } or null if aborted/closed + */ + async waitForMessagesAndGetAsString(abortSignal) { + if (this.queue.length > 0) { + return this.collectBatch(); + } + if (this.closed || abortSignal?.aborted) { + return null; + } + const hasMessages = await this.waitForMessages(abortSignal); + if (!hasMessages) { + return null; + } + return this.collectBatch(); + } + /** + * Collect a batch of messages with the same mode, respecting isolation requirements + */ + collectBatch() { + if (this.queue.length === 0) { + return null; + } + const firstItem = this.queue[0]; + const sameModeMessages = []; + let mode = firstItem.mode; + let isolate = firstItem.isolate ?? false; + const targetModeHash = firstItem.modeHash; + if (firstItem.isolate) { + const item = this.queue.shift(); + sameModeMessages.push(item.message); + types.logger.debug(`[MessageQueue2] Collected isolated message with mode hash: ${targetModeHash}`); + } else { + while (this.queue.length > 0 && this.queue[0].modeHash === targetModeHash && !this.queue[0].isolate) { + const item = this.queue.shift(); + sameModeMessages.push(item.message); + } + types.logger.debug(`[MessageQueue2] Collected batch of ${sameModeMessages.length} messages with mode hash: ${targetModeHash}`); + } + const combinedMessage = sameModeMessages.join("\n"); + return { + message: combinedMessage, + mode, + hash: targetModeHash, + isolate + }; + } + /** + * Wait for messages to arrive + */ + waitForMessages(abortSignal) { + return new Promise((resolve) => { + let abortHandler = null; + if (abortSignal) { + abortHandler = () => { + types.logger.debug("[MessageQueue2] Wait aborted"); + if (this.waiter === waiterFunc) { + this.waiter = null; + } + resolve(false); + }; + abortSignal.addEventListener("abort", abortHandler); + } + const waiterFunc = (hasMessages) => { + if (abortHandler && abortSignal) { + abortSignal.removeEventListener("abort", abortHandler); + } + resolve(hasMessages); + }; + if (this.queue.length > 0) { + if (abortHandler && abortSignal) { + abortSignal.removeEventListener("abort", abortHandler); + } + resolve(true); + return; + } + if (this.closed || abortSignal?.aborted) { + if (abortHandler && abortSignal) { + abortSignal.removeEventListener("abort", abortHandler); + } + resolve(false); + return; + } + this.waiter = waiterFunc; + types.logger.debug("[MessageQueue2] Waiting for messages..."); + }); + } +} + +function deterministicStringify(obj, options = {}) { + const { + undefinedBehavior = "omit", + sortArrays = false, + replacer, + includeSymbols = false + } = options; + const seen = /* @__PURE__ */ new WeakSet(); + function processValue(value, key) { + if (replacer && key !== void 0) { + value = replacer(key, value); + } + if (value === null) return null; + if (value === void 0) { + switch (undefinedBehavior) { + case "omit": + return void 0; + case "null": + return null; + case "throw": + throw new Error(`Undefined value at key: ${key}`); + } + } + if (typeof value === "boolean" || typeof value === "number" || typeof value === "string") { + return value; + } + if (value instanceof Date) { + return value.toISOString(); + } + if (value instanceof RegExp) { + return value.toString(); + } + if (typeof value === "function") { + return void 0; + } + if (typeof value === "symbol") { + return includeSymbols ? value.toString() : void 0; + } + if (typeof value === "bigint") { + return value.toString() + "n"; + } + if (seen.has(value)) { + throw new Error("Circular reference detected"); + } + seen.add(value); + if (Array.isArray(value)) { + const processed2 = value.map((item, index) => processValue(item, String(index))).filter((item) => item !== void 0); + if (sortArrays) { + processed2.sort((a, b) => { + const aStr = JSON.stringify(processValue(a)); + const bStr = JSON.stringify(processValue(b)); + return aStr.localeCompare(bStr); + }); + } + seen.delete(value); + return processed2; + } + if (value.constructor === Object || value.constructor === void 0) { + const processed2 = {}; + const keys = Object.keys(value).sort(); + for (const k of keys) { + const processedValue = processValue(value[k], k); + if (processedValue !== void 0) { + processed2[k] = processedValue; + } + } + seen.delete(value); + return processed2; + } + try { + const plain = { ...value }; + seen.delete(value); + return processValue(plain, key); + } catch { + seen.delete(value); + return String(value); + } + } + const processed = processValue(obj); + return JSON.stringify(processed); +} +function hashObject(obj, options, encoding = "hex") { + const jsonString = deterministicStringify(obj, options); + return crypto.createHash("sha256").update(jsonString).digest(encoding); +} + +let caffeinateProcess = null; +function startCaffeinate() { + if (types.configuration.disableCaffeinate) { + types.logger.debug("[caffeinate] Caffeinate disabled via HAPPY_DISABLE_CAFFEINATE environment variable"); + return false; + } + if (process.platform !== "darwin") { + types.logger.debug("[caffeinate] Not on macOS, skipping caffeinate"); + return false; + } + if (caffeinateProcess && !caffeinateProcess.killed) { + types.logger.debug("[caffeinate] Caffeinate already running"); + return true; + } + try { + caffeinateProcess = child_process.spawn("caffeinate", ["-im"], { + stdio: "ignore", + detached: false + }); + caffeinateProcess.on("error", (error) => { + types.logger.debug("[caffeinate] Error starting caffeinate:", error); + caffeinateProcess = null; + }); + caffeinateProcess.on("exit", (code, signal) => { + types.logger.debug(`[caffeinate] Process exited with code ${code}, signal ${signal}`); + caffeinateProcess = null; + }); + types.logger.debug(`[caffeinate] Started with PID ${caffeinateProcess.pid}`); + setupCleanupHandlers(); + return true; + } catch (error) { + types.logger.debug("[caffeinate] Failed to start caffeinate:", error); + return false; + } +} +let isStopping = false; +async function stopCaffeinate() { + if (isStopping) { + types.logger.debug("[caffeinate] Already stopping, skipping"); + return; + } + if (caffeinateProcess && !caffeinateProcess.killed) { + isStopping = true; + types.logger.debug(`[caffeinate] Stopping caffeinate process PID ${caffeinateProcess.pid}`); + try { + caffeinateProcess.kill("SIGTERM"); + await new Promise((resolve) => setTimeout(resolve, 1e3)); + if (caffeinateProcess && !caffeinateProcess.killed) { + types.logger.debug("[caffeinate] Force killing caffeinate process"); + caffeinateProcess.kill("SIGKILL"); + } + caffeinateProcess = null; + isStopping = false; + } catch (error) { + types.logger.debug("[caffeinate] Error stopping caffeinate:", error); + isStopping = false; + } + } +} +let cleanupHandlersSet = false; +function setupCleanupHandlers() { + if (cleanupHandlersSet) { + return; + } + cleanupHandlersSet = true; + const cleanup = () => { + stopCaffeinate(); + }; + process.on("exit", cleanup); + process.on("SIGINT", cleanup); + process.on("SIGTERM", cleanup); + process.on("SIGUSR1", cleanup); + process.on("SIGUSR2", cleanup); + process.on("uncaughtException", (error) => { + types.logger.debug("[caffeinate] Uncaught exception, cleaning up:", error); + cleanup(); + }); + process.on("unhandledRejection", (reason, promise) => { + types.logger.debug("[caffeinate] Unhandled rejection, cleaning up:", reason); + cleanup(); + }); +} + +async function extractSDKMetadata() { + const abortController = new AbortController(); + try { + types.logger.debug("[metadataExtractor] Starting SDK metadata extraction"); + const sdkQuery = query({ + prompt: "hello", + options: { + allowedTools: ["Bash(echo)"], + maxTurns: 1, + abort: abortController.signal + } + }); + for await (const message of sdkQuery) { + if (message.type === "system" && message.subtype === "init") { + const systemMessage = message; + const metadata = { + tools: systemMessage.tools, + slashCommands: systemMessage.slash_commands + }; + types.logger.debug("[metadataExtractor] Captured SDK metadata:", metadata); + abortController.abort(); + return metadata; + } + } + types.logger.debug("[metadataExtractor] No init message received from SDK"); + return {}; + } catch (error) { + if (error instanceof Error && error.name === "AbortError") { + types.logger.debug("[metadataExtractor] SDK query aborted after capturing metadata"); + return {}; + } + types.logger.debug("[metadataExtractor] Error extracting SDK metadata:", error); + return {}; + } +} +function extractSDKMetadataAsync(onComplete) { + extractSDKMetadata().then((metadata) => { + if (metadata.tools || metadata.slashCommands) { + onComplete(metadata); + } + }).catch((error) => { + types.logger.debug("[metadataExtractor] Async extraction failed:", error); + }); +} + +async function daemonPost(path, body) { + const state = await types.readDaemonState(); + if (!state?.httpPort) { + const errorMessage = "No daemon running, no state file found"; + types.logger.debug(`[CONTROL CLIENT] ${errorMessage}`); + return { + error: errorMessage + }; + } + try { + process.kill(state.pid, 0); + } catch (error) { + const errorMessage = "Daemon is not running, file is stale"; + types.logger.debug(`[CONTROL CLIENT] ${errorMessage}`); + return { + error: errorMessage + }; + } + try { + const timeout = process.env.HAPPY_DAEMON_HTTP_TIMEOUT ? parseInt(process.env.HAPPY_DAEMON_HTTP_TIMEOUT) : 1e4; + const response = await fetch(`http://127.0.0.1:${state.httpPort}${path}`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body || {}), + // Mostly increased for stress test + signal: AbortSignal.timeout(timeout) + }); + if (!response.ok) { + const errorMessage = `Request failed: ${path}, HTTP ${response.status}`; + types.logger.debug(`[CONTROL CLIENT] ${errorMessage}`); + return { + error: errorMessage + }; + } + return await response.json(); + } catch (error) { + const errorMessage = `Request failed: ${path}, ${error instanceof Error ? error.message : "Unknown error"}`; + types.logger.debug(`[CONTROL CLIENT] ${errorMessage}`); + return { + error: errorMessage + }; + } +} +async function notifyDaemonSessionStarted(sessionId, metadata) { + return await daemonPost("/session-started", { + sessionId, + metadata + }); +} +async function listDaemonSessions() { + const result = await daemonPost("/list"); + return result.children || []; +} +async function stopDaemonSession(sessionId) { + const result = await daemonPost("/stop-session", { sessionId }); + return result.success || false; +} +async function stopDaemonHttp() { + await daemonPost("/stop"); +} +async function checkIfDaemonRunningAndCleanupStaleState() { + const state = await types.readDaemonState(); + if (!state) { + return false; + } + try { + process.kill(state.pid, 0); + return true; + } catch { + types.logger.debug("[DAEMON RUN] Daemon PID not running, cleaning up state"); + await cleanupDaemonState(); + return false; + } +} +async function isDaemonRunningCurrentlyInstalledHappyVersion() { + types.logger.debug("[DAEMON CONTROL] Checking if daemon is running same version"); + const runningDaemon = await checkIfDaemonRunningAndCleanupStaleState(); + if (!runningDaemon) { + types.logger.debug("[DAEMON CONTROL] No daemon running, returning false"); + return false; + } + const state = await types.readDaemonState(); + if (!state) { + types.logger.debug("[DAEMON CONTROL] No daemon state found, returning false"); + return false; + } + try { + const packageJsonPath = path.join(types.projectPath(), "package.json"); + const packageJson = JSON.parse(fs$2.readFileSync(packageJsonPath, "utf-8")); + const currentCliVersion = packageJson.version; + types.logger.debug(`[DAEMON CONTROL] Current CLI version: ${currentCliVersion}, Daemon started with version: ${state.startedWithCliVersion}`); + return currentCliVersion === state.startedWithCliVersion; + } catch (error) { + types.logger.debug("[DAEMON CONTROL] Error checking daemon version", error); + return false; + } +} +async function cleanupDaemonState() { + try { + await types.clearDaemonState(); + types.logger.debug("[DAEMON RUN] Daemon state file removed"); + } catch (error) { + types.logger.debug("[DAEMON RUN] Error cleaning up daemon metadata", error); + } +} +async function stopDaemon() { + try { + const state = await types.readDaemonState(); + if (!state) { + types.logger.debug("No daemon state found"); + return; + } + types.logger.debug(`Stopping daemon with PID ${state.pid}`); + try { + await stopDaemonHttp(); + await waitForProcessDeath(state.pid, 2e3); + types.logger.debug("Daemon stopped gracefully via HTTP"); + return; + } catch (error) { + types.logger.debug("HTTP stop failed, will force kill", error); + } + try { + process.kill(state.pid, "SIGKILL"); + types.logger.debug("Force killed daemon"); + } catch (error) { + types.logger.debug("Daemon already dead"); + } + } catch (error) { + types.logger.debug("Error stopping daemon", error); + } +} +async function waitForProcessDeath(pid, timeout) { + const start = Date.now(); + while (Date.now() - start < timeout) { + try { + process.kill(pid, 0); + await new Promise((resolve) => setTimeout(resolve, 100)); + } catch { + return; + } + } + throw new Error("Process did not die within timeout"); +} + +async function findAllHappyProcesses() { + try { + const processes = await psList(); + const allProcesses = []; + for (const proc of processes) { + const cmd = proc.cmd || ""; + const name = proc.name || ""; + const isHappy = name.includes("happy") || name === "node" && (cmd.includes("happy-cli") || cmd.includes("dist/index.mjs")) || cmd.includes("happy.mjs") || cmd.includes("happy-coder") || cmd.includes("tsx") && cmd.includes("src/index.ts") && cmd.includes("happy-cli"); + if (!isHappy) continue; + let type = "unknown"; + if (proc.pid === process.pid) { + type = "current"; + } else if (cmd.includes("--version")) { + type = cmd.includes("tsx") ? "dev-daemon-version-check" : "daemon-version-check"; + } else if (cmd.includes("daemon start-sync") || cmd.includes("daemon start")) { + type = cmd.includes("tsx") ? "dev-daemon" : "daemon"; + } else if (cmd.includes("--started-by daemon")) { + type = cmd.includes("tsx") ? "dev-daemon-spawned" : "daemon-spawned-session"; + } else if (cmd.includes("doctor")) { + type = cmd.includes("tsx") ? "dev-doctor" : "doctor"; + } else if (cmd.includes("--yolo")) { + type = "dev-session"; + } else { + type = cmd.includes("tsx") ? "dev-related" : "user-session"; + } + allProcesses.push({ pid: proc.pid, command: cmd || name, type }); + } + return allProcesses; + } catch (error) { + return []; + } +} +async function findRunawayHappyProcesses() { + const allProcesses = await findAllHappyProcesses(); + return allProcesses.filter( + (p) => p.pid !== process.pid && (p.type === "daemon" || p.type === "dev-daemon" || p.type === "daemon-spawned-session" || p.type === "dev-daemon-spawned" || p.type === "daemon-version-check" || p.type === "dev-daemon-version-check") + ).map((p) => ({ pid: p.pid, command: p.command })); +} +async function killRunawayHappyProcesses() { + const runawayProcesses = await findRunawayHappyProcesses(); + const errors = []; + let killed = 0; + for (const { pid, command } of runawayProcesses) { + try { + console.log(`Killing runaway process PID ${pid}: ${command}`); + if (process.platform === "win32") { + const result = spawn.sync("taskkill", ["/F", "/PID", pid.toString()], { stdio: "pipe" }); + if (result.error) throw result.error; + if (result.status !== 0) throw new Error(`taskkill exited with code ${result.status}`); + } else { + process.kill(pid, "SIGTERM"); + await new Promise((resolve) => setTimeout(resolve, 1e3)); + const processes = await psList(); + const stillAlive = processes.find((p) => p.pid === pid); + if (stillAlive) { + console.log(`Process PID ${pid} ignored SIGTERM, using SIGKILL`); + process.kill(pid, "SIGKILL"); + } + } + console.log(`Successfully killed runaway process PID ${pid}`); + killed++; + } catch (error) { + const errorMessage = error.message; + errors.push({ pid, error: errorMessage }); + console.log(`Failed to kill process PID ${pid}: ${errorMessage}`); + } + } + return { killed, errors }; +} + +function getEnvironmentInfo() { + return { + PWD: process.env.PWD, + HAPPY_HOME_DIR: process.env.HAPPY_HOME_DIR, + HAPPY_SERVER_URL: process.env.HAPPY_SERVER_URL, + HAPPY_PROJECT_ROOT: process.env.HAPPY_PROJECT_ROOT, + DANGEROUSLY_LOG_TO_SERVER_FOR_AI_AUTO_DEBUGGING: process.env.DANGEROUSLY_LOG_TO_SERVER_FOR_AI_AUTO_DEBUGGING, + NODE_ENV: process.env.NODE_ENV, + DEBUG: process.env.DEBUG, + workingDirectory: process.cwd(), + processArgv: process.argv, + happyDir: types.configuration?.happyHomeDir, + serverUrl: types.configuration?.serverUrl, + logsDir: types.configuration?.logsDir, + processPid: process.pid, + nodeVersion: process.version, + platform: process.platform, + arch: process.arch, + user: process.env.USER, + home: process.env.HOME, + shell: process.env.SHELL, + terminal: process.env.TERM + }; +} +function getLogFiles(logDir) { + if (!fs.existsSync(logDir)) { + return []; + } + try { + return fs.readdirSync(logDir).filter((file) => file.endsWith(".log")).map((file) => { + const path = node_path.join(logDir, file); + const stats = fs.statSync(path); + return { file, path, modified: stats.mtime }; + }).sort((a, b) => b.modified.getTime() - a.modified.getTime()); + } catch { + return []; + } +} +async function runDoctorCommand(filter) { + if (!filter) { + filter = "all"; + } + console.log(chalk.bold.cyan("\n\u{1FA7A} Happy CLI Doctor\n")); + if (filter === "all") { + console.log(chalk.bold("\u{1F4CB} Basic Information")); + console.log(`Happy CLI Version: ${chalk.green(types.packageJson.version)}`); + console.log(`Platform: ${chalk.green(process.platform)} ${process.arch}`); + console.log(`Node.js Version: ${chalk.green(process.version)}`); + console.log(""); + console.log(chalk.bold("\u{1F527} Daemon Spawn Diagnostics")); + const projectRoot = types.projectPath(); + const wrapperPath = node_path.join(projectRoot, "bin", "happy.mjs"); + const cliEntrypoint = node_path.join(projectRoot, "dist", "index.mjs"); + console.log(`Project Root: ${chalk.blue(projectRoot)}`); + console.log(`Wrapper Script: ${chalk.blue(wrapperPath)}`); + console.log(`CLI Entrypoint: ${chalk.blue(cliEntrypoint)}`); + console.log(`Wrapper Exists: ${fs.existsSync(wrapperPath) ? chalk.green("\u2713 Yes") : chalk.red("\u274C No")}`); + console.log(`CLI Exists: ${fs.existsSync(cliEntrypoint) ? chalk.green("\u2713 Yes") : chalk.red("\u274C No")}`); + console.log(""); + console.log(chalk.bold("\u2699\uFE0F Configuration")); + console.log(`Happy Home: ${chalk.blue(types.configuration.happyHomeDir)}`); + console.log(`Server URL: ${chalk.blue(types.configuration.serverUrl)}`); + console.log(`Logs Dir: ${chalk.blue(types.configuration.logsDir)}`); + console.log(chalk.bold("\n\u{1F30D} Environment Variables")); + const env = getEnvironmentInfo(); + console.log(`HAPPY_HOME_DIR: ${env.HAPPY_HOME_DIR ? chalk.green(env.HAPPY_HOME_DIR) : chalk.gray("not set")}`); + console.log(`HAPPY_SERVER_URL: ${env.HAPPY_SERVER_URL ? chalk.green(env.HAPPY_SERVER_URL) : chalk.gray("not set")}`); + console.log(`DANGEROUSLY_LOG_TO_SERVER: ${env.DANGEROUSLY_LOG_TO_SERVER_FOR_AI_AUTO_DEBUGGING ? chalk.yellow("ENABLED") : chalk.gray("not set")}`); + console.log(`DEBUG: ${env.DEBUG ? chalk.green(env.DEBUG) : chalk.gray("not set")}`); + console.log(`NODE_ENV: ${env.NODE_ENV ? chalk.green(env.NODE_ENV) : chalk.gray("not set")}`); + try { + const settings = await types.readSettings(); + console.log(chalk.bold("\n\u{1F4C4} Settings (settings.json):")); + console.log(chalk.gray(JSON.stringify(settings, null, 2))); + } catch (error) { + console.log(chalk.bold("\n\u{1F4C4} Settings:")); + console.log(chalk.red("\u274C Failed to read settings")); + } + console.log(chalk.bold("\n\u{1F510} Authentication")); + try { + const credentials = await types.readCredentials(); + if (credentials) { + console.log(chalk.green("\u2713 Authenticated (credentials found)")); + } else { + console.log(chalk.yellow("\u26A0\uFE0F Not authenticated (no credentials)")); + } + } catch (error) { + console.log(chalk.red("\u274C Error reading credentials")); + } + } + console.log(chalk.bold("\n\u{1F916} Daemon Status")); + try { + const isRunning = await checkIfDaemonRunningAndCleanupStaleState(); + const state = await types.readDaemonState(); + if (isRunning && state) { + console.log(chalk.green("\u2713 Daemon is running")); + console.log(` PID: ${state.pid}`); + console.log(` Started: ${new Date(state.startTime).toLocaleString()}`); + console.log(` CLI Version: ${state.startedWithCliVersion}`); + if (state.httpPort) { + console.log(` HTTP Port: ${state.httpPort}`); + } + } else if (state && !isRunning) { + console.log(chalk.yellow("\u26A0\uFE0F Daemon state exists but process not running (stale)")); + } else { + console.log(chalk.red("\u274C Daemon is not running")); + } + if (state) { + console.log(chalk.bold("\n\u{1F4C4} Daemon State:")); + console.log(chalk.blue(`Location: ${types.configuration.daemonStateFile}`)); + console.log(chalk.gray(JSON.stringify(state, null, 2))); + } + const allProcesses = await findAllHappyProcesses(); + if (allProcesses.length > 0) { + console.log(chalk.bold("\n\u{1F50D} All Happy CLI Processes")); + const grouped = allProcesses.reduce((groups, process2) => { + if (!groups[process2.type]) groups[process2.type] = []; + groups[process2.type].push(process2); + return groups; + }, {}); + Object.entries(grouped).forEach(([type, processes]) => { + const typeLabels = { + "current": "\u{1F4CD} Current Process", + "daemon": "\u{1F916} Daemon", + "daemon-version-check": "\u{1F50D} Daemon Version Check (stuck)", + "daemon-spawned-session": "\u{1F517} Daemon-Spawned Sessions", + "user-session": "\u{1F464} User Sessions", + "dev-daemon": "\u{1F6E0}\uFE0F Dev Daemon", + "dev-daemon-version-check": "\u{1F6E0}\uFE0F Dev Daemon Version Check (stuck)", + "dev-session": "\u{1F6E0}\uFE0F Dev Sessions", + "dev-doctor": "\u{1F6E0}\uFE0F Dev Doctor", + "dev-related": "\u{1F6E0}\uFE0F Dev Related", + "doctor": "\u{1FA7A} Doctor", + "unknown": "\u2753 Unknown" + }; + console.log(chalk.blue(` +${typeLabels[type] || type}:`)); + processes.forEach(({ pid, command }) => { + const color = type === "current" ? chalk.green : type.startsWith("dev") ? chalk.cyan : type.includes("daemon") ? chalk.blue : chalk.gray; + console.log(` ${color(`PID ${pid}`)}: ${chalk.gray(command)}`); + }); + }); + } else { + console.log(chalk.red("\u274C No happy processes found")); + } + if (filter === "all" && allProcesses.length > 1) { + console.log(chalk.bold("\n\u{1F4A1} Process Management")); + console.log(chalk.gray("To clean up runaway processes: happy doctor clean")); + } + } catch (error) { + console.log(chalk.red("\u274C Error checking daemon status")); + } + if (filter === "all") { + console.log(chalk.bold("\n\u{1F4DD} Log Files")); + const allLogs = getLogFiles(types.configuration.logsDir); + if (allLogs.length > 0) { + const daemonLogs = allLogs.filter(({ file }) => file.includes("daemon")); + const regularLogs = allLogs.filter(({ file }) => !file.includes("daemon")); + if (regularLogs.length > 0) { + console.log(chalk.blue("\nRecent Logs:")); + const logsToShow = regularLogs.slice(0, 10); + logsToShow.forEach(({ file, path, modified }) => { + console.log(` ${chalk.green(file)} - ${modified.toLocaleString()}`); + console.log(chalk.gray(` ${path}`)); + }); + if (regularLogs.length > 10) { + console.log(chalk.gray(` ... and ${regularLogs.length - 10} more log files`)); + } + } + if (daemonLogs.length > 0) { + console.log(chalk.blue("\nDaemon Logs:")); + const daemonLogsToShow = daemonLogs.slice(0, 5); + daemonLogsToShow.forEach(({ file, path, modified }) => { + console.log(` ${chalk.green(file)} - ${modified.toLocaleString()}`); + console.log(chalk.gray(` ${path}`)); + }); + if (daemonLogs.length > 5) { + console.log(chalk.gray(` ... and ${daemonLogs.length - 5} more daemon log files`)); + } + } else { + console.log(chalk.yellow("\nNo daemon log files found")); + } + } else { + console.log(chalk.yellow("No log files found")); + } + console.log(chalk.bold("\n\u{1F41B} Support & Bug Reports")); + console.log(`Report issues: ${chalk.blue("https://github.com/slopus/happy-cli/issues")}`); + console.log(`Documentation: ${chalk.blue("https://happy.engineering/")}`); + } + console.log(chalk.green("\n\u2705 Doctor diagnosis complete!\n")); +} + +function displayQRCode(url) { + console.log("=".repeat(80)); + console.log("\u{1F4F1} To authenticate, scan this QR code with your mobile device:"); + console.log("=".repeat(80)); + qrcode.generate(url, { small: true }, (qr) => { + for (let l of qr.split("\n")) { + console.log(" ".repeat(10) + l); + } + }); + console.log("=".repeat(80)); +} + +function generateWebAuthUrl(publicKey) { + const publicKeyBase64 = types.encodeBase64(publicKey, "base64url"); + return `${types.configuration.webappUrl}/terminal/connect#key=${publicKeyBase64}`; +} + +async function openBrowser(url) { + try { + if (!process.stdout.isTTY || process.env.CI || process.env.HEADLESS) { + types.logger.debug("[browser] Headless environment detected, skipping browser open"); + return false; + } + types.logger.debug(`[browser] Attempting to open URL: ${url}`); + await open(url); + types.logger.debug("[browser] Browser opened successfully"); + return true; + } catch (error) { + types.logger.debug("[browser] Failed to open browser:", error); + return false; + } +} + +const AuthSelector = ({ onSelect, onCancel }) => { + const [selectedIndex, setSelectedIndex] = React.useState(0); + const options = [ + { + method: "mobile", + label: "Mobile App" + }, + { + method: "web", + label: "Web Browser" + } + ]; + ink.useInput((input, key) => { + if (key.upArrow) { + setSelectedIndex((prev) => Math.max(0, prev - 1)); + } else if (key.downArrow) { + setSelectedIndex((prev) => Math.min(options.length - 1, prev + 1)); + } else if (key.return) { + onSelect(options[selectedIndex].method); + } else if (key.escape || key.ctrl && input === "c") { + onCancel(); + } else if (input === "1") { + setSelectedIndex(0); + onSelect("mobile"); + } else if (input === "2") { + setSelectedIndex(1); + onSelect("web"); + } + }); + return /* @__PURE__ */ React.createElement(ink.Box, { flexDirection: "column", paddingY: 1 }, /* @__PURE__ */ React.createElement(ink.Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(ink.Text, null, "How would you like to authenticate?")), /* @__PURE__ */ React.createElement(ink.Box, { flexDirection: "column" }, options.map((option, index) => { + const isSelected = selectedIndex === index; + return /* @__PURE__ */ React.createElement(ink.Box, { key: option.method, marginY: 0 }, /* @__PURE__ */ React.createElement(ink.Text, { color: isSelected ? "cyan" : "gray" }, isSelected ? "\u203A " : " ", index + 1, ". ", option.label)); + })), /* @__PURE__ */ React.createElement(ink.Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(ink.Text, { dimColor: true }, "Use arrows or 1-2 to select, Enter to confirm"))); +}; + +async function doAuth() { + console.clear(); + const authMethod = await selectAuthenticationMethod(); + if (!authMethod) { + console.log("\nAuthentication cancelled.\n"); + process.exit(0); + } + const secret = new Uint8Array(node_crypto.randomBytes(32)); + const keypair = tweetnacl.box.keyPair.fromSecretKey(secret); + try { + console.log(`[AUTH DEBUG] Sending auth request to: ${types.configuration.serverUrl}/v1/auth/request`); + console.log(`[AUTH DEBUG] Public key: ${types.encodeBase64(keypair.publicKey).substring(0, 20)}...`); + await axios.post(`${types.configuration.serverUrl}/v1/auth/request`, { + publicKey: types.encodeBase64(keypair.publicKey), + supportsV2: true + }); + console.log(`[AUTH DEBUG] Auth request sent successfully`); + } catch (error) { + console.log(`[AUTH DEBUG] Failed to send auth request:`, error); + console.log("Failed to create authentication request, please try again later."); + return null; + } + if (authMethod === "mobile") { + return await doMobileAuth(keypair); + } else { + return await doWebAuth(keypair); + } +} +function selectAuthenticationMethod() { + return new Promise((resolve) => { + let hasResolved = false; + const onSelect = (method) => { + if (!hasResolved) { + hasResolved = true; + app.unmount(); + resolve(method); + } + }; + const onCancel = () => { + if (!hasResolved) { + hasResolved = true; + app.unmount(); + resolve(null); + } + }; + const app = ink.render(React.createElement(AuthSelector, { onSelect, onCancel }), { + exitOnCtrlC: false, + patchConsole: false + }); + }); +} +async function doMobileAuth(keypair) { + console.clear(); + console.log("\nMobile Authentication\n"); + console.log("Scan this QR code with your Happy mobile app:\n"); + const authUrl = "happy://terminal?" + types.encodeBase64Url(keypair.publicKey); + displayQRCode(authUrl); + console.log("\nOr manually enter this URL:"); + console.log(authUrl); + console.log(""); + return await waitForAuthentication(keypair); +} +async function doWebAuth(keypair) { + console.clear(); + console.log("\nWeb Authentication\n"); + const webUrl = generateWebAuthUrl(keypair.publicKey); + console.log("Opening your browser..."); + const browserOpened = await openBrowser(webUrl); + if (browserOpened) { + console.log("\u2713 Browser opened\n"); + console.log("Complete authentication in your browser window."); + } else { + console.log("Could not open browser automatically."); + } + console.log("\nIf the browser did not open, please copy and paste this URL:"); + console.log(webUrl); + console.log(""); + return await waitForAuthentication(keypair); +} +async function waitForAuthentication(keypair) { + process.stdout.write("Waiting for authentication"); + let dots = 0; + let cancelled = false; + const handleInterrupt = () => { + cancelled = true; + console.log("\n\nAuthentication cancelled."); + process.exit(0); + }; + process.on("SIGINT", handleInterrupt); + try { + while (!cancelled) { + try { + const response = await axios.post(`${types.configuration.serverUrl}/v1/auth/request`, { + publicKey: types.encodeBase64(keypair.publicKey), + supportsV2: true + }); + if (response.data.state === "authorized") { + let token = response.data.token; + let r = types.decodeBase64(response.data.response); + let decrypted = decryptWithEphemeralKey(r, keypair.secretKey); + if (decrypted) { + if (decrypted.length === 32) { + const credentials = { + secret: decrypted, + token + }; + await types.writeCredentialsLegacy(credentials); + console.log("\n\n\u2713 Authentication successful\n"); + return { + encryption: { + type: "legacy", + secret: decrypted + }, + token + }; + } else { + if (decrypted[0] === 0) { + const credentials = { + publicKey: decrypted.slice(1, 33), + machineKey: node_crypto.randomBytes(32), + token + }; + await types.writeCredentialsDataKey(credentials); + console.log("\n\n\u2713 Authentication successful\n"); + return { + encryption: { + type: "dataKey", + publicKey: credentials.publicKey, + machineKey: credentials.machineKey + }, + token + }; + } else { + console.log("\n\nFailed to decrypt response. Please try again."); + return null; + } + } + } else { + console.log("\n\nFailed to decrypt response. Please try again."); + return null; + } + } + } catch (error) { + console.log("\n\nFailed to check authentication status. Please try again."); + return null; + } + process.stdout.write("\rWaiting for authentication" + ".".repeat(dots % 3 + 1) + " "); + dots++; + await types.delay(1e3); + } + } finally { + process.off("SIGINT", handleInterrupt); + } + return null; +} +function decryptWithEphemeralKey(encryptedBundle, recipientSecretKey) { + const ephemeralPublicKey = encryptedBundle.slice(0, 32); + const nonce = encryptedBundle.slice(32, 32 + tweetnacl.box.nonceLength); + const encrypted = encryptedBundle.slice(32 + tweetnacl.box.nonceLength); + const decrypted = tweetnacl.box.open(encrypted, nonce, ephemeralPublicKey, recipientSecretKey); + if (!decrypted) { + return null; + } + return decrypted; +} +async function authAndSetupMachineIfNeeded() { + types.logger.debug("[AUTH] Starting auth and machine setup..."); + let credentials = await types.readCredentials(); + let newAuth = false; + if (!credentials) { + types.logger.debug("[AUTH] No credentials found, starting authentication flow..."); + const authResult = await doAuth(); + if (!authResult) { + throw new Error("Authentication failed or was cancelled"); + } + credentials = authResult; + newAuth = true; + } else { + types.logger.debug("[AUTH] Using existing credentials"); + } + const settings = await types.updateSettings(async (s) => { + if (newAuth || !s.machineId) { + return { + ...s, + machineId: node_crypto.randomUUID() + }; + } + return s; + }); + types.logger.debug(`[AUTH] Machine ID: ${settings.machineId}`); + return { credentials, machineId: settings.machineId }; +} + +function spawnHappyCLI(args, options = {}) { + const projectRoot = types.projectPath(); + const entrypoint = node_path.join(projectRoot, "dist", "index.mjs"); + let directory; + if ("cwd" in options) { + directory = options.cwd; + } else { + directory = process.cwd(); + } + const fullCommand = `happy ${args.join(" ")}`; + types.logger.debug(`[SPAWN HAPPY CLI] Spawning: ${fullCommand} in ${directory}`); + const nodeArgs = [ + "--no-warnings", + "--no-deprecation", + entrypoint, + ...args + ]; + if (!fs.existsSync(entrypoint)) { + const errorMessage = `Entrypoint ${entrypoint} does not exist`; + types.logger.debug(`[SPAWN HAPPY CLI] ${errorMessage}`); + throw new Error(errorMessage); + } + return child_process.spawn("node", nodeArgs, options); +} + +function startDaemonControlServer({ + getChildren, + stopSession, + spawnSession, + requestShutdown, + onHappySessionWebhook +}) { + return new Promise((resolve) => { + const app = fastify({ + logger: false + // We use our own logger + }); + app.setValidatorCompiler(fastifyTypeProviderZod.validatorCompiler); + app.setSerializerCompiler(fastifyTypeProviderZod.serializerCompiler); + const typed = app.withTypeProvider(); + typed.post("/session-started", { + schema: { + body: z.z.object({ + sessionId: z.z.string(), + metadata: z.z.any() + // Metadata type from API + }), + response: { + 200: z.z.object({ + status: z.z.literal("ok") + }) + } + } + }, async (request) => { + const { sessionId, metadata } = request.body; + types.logger.debug(`[CONTROL SERVER] Session started: ${sessionId}`); + onHappySessionWebhook(sessionId, metadata); + return { status: "ok" }; + }); + typed.post("/list", { + schema: { + response: { + 200: z.z.object({ + children: z.z.array(z.z.object({ + startedBy: z.z.string(), + happySessionId: z.z.string(), + pid: z.z.number() + })) + }) + } + } + }, async () => { + const children = getChildren(); + types.logger.debug(`[CONTROL SERVER] Listing ${children.length} sessions`); + return { + children: children.filter((child) => child.happySessionId !== void 0).map((child) => ({ + startedBy: child.startedBy, + happySessionId: child.happySessionId, + pid: child.pid + })) + }; + }); + typed.post("/stop-session", { + schema: { + body: z.z.object({ + sessionId: z.z.string() + }), + response: { + 200: z.z.object({ + success: z.z.boolean() + }) + } + } + }, async (request) => { + const { sessionId } = request.body; + types.logger.debug(`[CONTROL SERVER] Stop session request: ${sessionId}`); + const success = stopSession(sessionId); + return { success }; + }); + typed.post("/spawn-session", { + schema: { + body: z.z.object({ + directory: z.z.string(), + sessionId: z.z.string().optional() + }), + response: { + 200: z.z.object({ + success: z.z.boolean(), + sessionId: z.z.string().optional(), + approvedNewDirectoryCreation: z.z.boolean().optional() + }), + 409: z.z.object({ + success: z.z.boolean(), + requiresUserApproval: z.z.boolean().optional(), + actionRequired: z.z.string().optional(), + directory: z.z.string().optional() + }), + 500: z.z.object({ + success: z.z.boolean(), + error: z.z.string().optional() + }) + } + } + }, async (request, reply) => { + const { directory, sessionId } = request.body; + types.logger.debug(`[CONTROL SERVER] Spawn session request: dir=${directory}, sessionId=${sessionId || "new"}`); + const result = await spawnSession({ directory, sessionId }); + switch (result.type) { + case "success": + if (!result.sessionId) { + reply.code(500); + return { + success: false, + error: "Failed to spawn session: no session ID returned" + }; + } + return { + success: true, + sessionId: result.sessionId, + approvedNewDirectoryCreation: true + }; + case "requestToApproveDirectoryCreation": + reply.code(409); + return { + success: false, + requiresUserApproval: true, + actionRequired: "CREATE_DIRECTORY", + directory: result.directory + }; + case "error": + reply.code(500); + return { + success: false, + error: result.errorMessage + }; + } + }); + typed.post("/stop", { + schema: { + response: { + 200: z.z.object({ + status: z.z.string() + }) + } + } + }, async () => { + types.logger.debug("[CONTROL SERVER] Stop daemon request received"); + setTimeout(() => { + types.logger.debug("[CONTROL SERVER] Triggering daemon shutdown"); + requestShutdown(); + }, 50); + return { status: "stopping" }; + }); + app.listen({ port: 0, host: "127.0.0.1" }, (err, address) => { + if (err) { + types.logger.debug("[CONTROL SERVER] Failed to start:", err); + throw err; + } + const port = parseInt(address.split(":").pop()); + types.logger.debug(`[CONTROL SERVER] Started on port ${port}`); + resolve({ + port, + stop: async () => { + types.logger.debug("[CONTROL SERVER] Stopping server"); + await app.close(); + types.logger.debug("[CONTROL SERVER] Server stopped"); + } + }); + }); + }); +} + +const initialMachineMetadata = { + host: os$1.hostname(), + platform: os$1.platform(), + happyCliVersion: types.packageJson.version, + homeDir: os$1.homedir(), + happyHomeDir: types.configuration.happyHomeDir, + happyLibDir: types.projectPath() +}; +async function startDaemon() { + let requestShutdown; + let resolvesWhenShutdownRequested = new Promise((resolve) => { + requestShutdown = (source, errorMessage) => { + types.logger.debug(`[DAEMON RUN] Requesting shutdown (source: ${source}, errorMessage: ${errorMessage})`); + setTimeout(async () => { + types.logger.debug("[DAEMON RUN] Startup malfunctioned, forcing exit with code 1"); + await new Promise((resolve2) => setTimeout(resolve2, 100)); + process.exit(1); + }, 1e3); + resolve({ source, errorMessage }); + }; + }); + process.on("SIGINT", () => { + types.logger.debug("[DAEMON RUN] Received SIGINT"); + requestShutdown("os-signal"); + }); + process.on("SIGTERM", () => { + types.logger.debug("[DAEMON RUN] Received SIGTERM"); + requestShutdown("os-signal"); + }); + process.on("uncaughtException", (error) => { + types.logger.debug("[DAEMON RUN] FATAL: Uncaught exception", error); + types.logger.debug(`[DAEMON RUN] Stack trace: ${error.stack}`); + requestShutdown("exception", error.message); + }); + process.on("unhandledRejection", (reason, promise) => { + types.logger.debug("[DAEMON RUN] FATAL: Unhandled promise rejection", reason); + types.logger.debug(`[DAEMON RUN] Rejected promise:`, promise); + const error = reason instanceof Error ? reason : new Error(`Unhandled promise rejection: ${reason}`); + types.logger.debug(`[DAEMON RUN] Stack trace: ${error.stack}`); + requestShutdown("exception", error.message); + }); + process.on("exit", (code) => { + types.logger.debug(`[DAEMON RUN] Process exiting with code: ${code}`); + }); + process.on("beforeExit", (code) => { + types.logger.debug(`[DAEMON RUN] Process about to exit with code: ${code}`); + }); + types.logger.debug("[DAEMON RUN] Starting daemon process..."); + types.logger.debugLargeJson("[DAEMON RUN] Environment", getEnvironmentInfo()); + const runningDaemonVersionMatches = await isDaemonRunningCurrentlyInstalledHappyVersion(); + if (!runningDaemonVersionMatches) { + types.logger.debug("[DAEMON RUN] Daemon version mismatch detected, restarting daemon with current CLI version"); + await stopDaemon(); + } else { + types.logger.debug("[DAEMON RUN] Daemon version matches, keeping existing daemon"); + console.log("Daemon already running with matching version"); + process.exit(0); + } + const daemonLockHandle = await types.acquireDaemonLock(5, 200); + if (!daemonLockHandle) { + types.logger.debug("[DAEMON RUN] Daemon lock file already held, another daemon is running"); + process.exit(0); + } + try { + const caffeinateStarted = startCaffeinate(); + if (caffeinateStarted) { + types.logger.debug("[DAEMON RUN] Sleep prevention enabled"); + } + const { credentials, machineId } = await authAndSetupMachineIfNeeded(); + types.logger.debug("[DAEMON RUN] Auth and machine setup complete"); + const pidToTrackedSession = /* @__PURE__ */ new Map(); + const pidToAwaiter = /* @__PURE__ */ new Map(); + const getCurrentChildren = () => Array.from(pidToTrackedSession.values()); + const onHappySessionWebhook = (sessionId, sessionMetadata) => { + types.logger.debugLargeJson(`[DAEMON RUN] Session reported`, sessionMetadata); + const pid = sessionMetadata.hostPid; + if (!pid) { + types.logger.debug(`[DAEMON RUN] Session webhook missing hostPid for sessionId: ${sessionId}`); + return; + } + types.logger.debug(`[DAEMON RUN] Session webhook: ${sessionId}, PID: ${pid}, started by: ${sessionMetadata.startedBy || "unknown"}`); + types.logger.debug(`[DAEMON RUN] Current tracked sessions before webhook: ${Array.from(pidToTrackedSession.keys()).join(", ")}`); + const existingSession = pidToTrackedSession.get(pid); + if (existingSession && existingSession.startedBy === "daemon") { + existingSession.happySessionId = sessionId; + existingSession.happySessionMetadataFromLocalWebhook = sessionMetadata; + types.logger.debug(`[DAEMON RUN] Updated daemon-spawned session ${sessionId} with metadata`); + const awaiter = pidToAwaiter.get(pid); + if (awaiter) { + pidToAwaiter.delete(pid); + awaiter(existingSession); + types.logger.debug(`[DAEMON RUN] Resolved session awaiter for PID ${pid}`); + } + } else if (!existingSession) { + const trackedSession = { + startedBy: "happy directly - likely by user from terminal", + happySessionId: sessionId, + happySessionMetadataFromLocalWebhook: sessionMetadata, + pid + }; + pidToTrackedSession.set(pid, trackedSession); + types.logger.debug(`[DAEMON RUN] Registered externally-started session ${sessionId}`); + } + }; + const spawnSession = async (options) => { + types.logger.debugLargeJson("[DAEMON RUN] Spawning session", options); + const { directory, sessionId, machineId: machineId2, approvedNewDirectoryCreation = true } = options; + let directoryCreated = false; + try { + await fs$1.access(directory); + types.logger.debug(`[DAEMON RUN] Directory exists: ${directory}`); + } catch (error) { + types.logger.debug(`[DAEMON RUN] Directory doesn't exist, creating: ${directory}`); + if (!approvedNewDirectoryCreation) { + types.logger.debug(`[DAEMON RUN] Directory creation not approved for: ${directory}`); + return { + type: "requestToApproveDirectoryCreation", + directory + }; + } + try { + await fs$1.mkdir(directory, { recursive: true }); + types.logger.debug(`[DAEMON RUN] Successfully created directory: ${directory}`); + directoryCreated = true; + } catch (mkdirError) { + let errorMessage = `Unable to create directory at '${directory}'. `; + if (mkdirError.code === "EACCES") { + errorMessage += `Permission denied. You don't have write access to create a folder at this location. Try using a different path or check your permissions.`; + } else if (mkdirError.code === "ENOTDIR") { + errorMessage += `A file already exists at this path or in the parent path. Cannot create a directory here. Please choose a different location.`; + } else if (mkdirError.code === "ENOSPC") { + errorMessage += `No space left on device. Your disk is full. Please free up some space and try again.`; + } else if (mkdirError.code === "EROFS") { + errorMessage += `The file system is read-only. Cannot create directories here. Please choose a writable location.`; + } else { + errorMessage += `System error: ${mkdirError.message || mkdirError}. Please verify the path is valid and you have the necessary permissions.`; + } + types.logger.debug(`[DAEMON RUN] Directory creation failed: ${errorMessage}`); + return { + type: "error", + errorMessage + }; + } + } + try { + let extraEnv = {}; + if (options.token) { + if (options.agent === "codex") { + const codexHomeDir = tmp__namespace.dirSync(); + fs$1.writeFile(path.join(codexHomeDir.name, "auth.json"), options.token); + extraEnv = { + CODEX_HOME: codexHomeDir.name + }; + } else { + extraEnv = { + CLAUDE_CODE_OAUTH_TOKEN: options.token + }; + } + } + const args = [ + options.agent === "claude" ? "claude" : "codex", + "--happy-starting-mode", + "remote", + "--started-by", + "daemon" + ]; + const happyProcess = spawnHappyCLI(args, { + cwd: directory, + detached: true, + // Sessions stay alive when daemon stops + stdio: ["ignore", "pipe", "pipe"], + // Capture stdout/stderr for debugging + env: { + ...process.env, + ...extraEnv + } + }); + if (process.env.DEBUG) { + happyProcess.stdout?.on("data", (data) => { + types.logger.debug(`[DAEMON RUN] Child stdout: ${data.toString()}`); + }); + happyProcess.stderr?.on("data", (data) => { + types.logger.debug(`[DAEMON RUN] Child stderr: ${data.toString()}`); + }); + } + if (!happyProcess.pid) { + types.logger.debug("[DAEMON RUN] Failed to spawn process - no PID returned"); + return { + type: "error", + errorMessage: "Failed to spawn Happy process - no PID returned" + }; + } + types.logger.debug(`[DAEMON RUN] Spawned process with PID ${happyProcess.pid}`); + const trackedSession = { + startedBy: "daemon", + pid: happyProcess.pid, + childProcess: happyProcess, + directoryCreated, + message: directoryCreated ? `The path '${directory}' did not exist. We created a new folder and spawned a new session there.` : void 0 + }; + pidToTrackedSession.set(happyProcess.pid, trackedSession); + happyProcess.on("exit", (code, signal) => { + types.logger.debug(`[DAEMON RUN] Child PID ${happyProcess.pid} exited with code ${code}, signal ${signal}`); + if (happyProcess.pid) { + onChildExited(happyProcess.pid); + } + }); + happyProcess.on("error", (error) => { + types.logger.debug(`[DAEMON RUN] Child process error:`, error); + if (happyProcess.pid) { + onChildExited(happyProcess.pid); + } + }); + types.logger.debug(`[DAEMON RUN] Waiting for session webhook for PID ${happyProcess.pid}`); + return new Promise((resolve) => { + const timeout = setTimeout(() => { + pidToAwaiter.delete(happyProcess.pid); + types.logger.debug(`[DAEMON RUN] Session webhook timeout for PID ${happyProcess.pid}`); + resolve({ + type: "error", + errorMessage: `Session webhook timeout for PID ${happyProcess.pid}` + }); + }, 15e3); + pidToAwaiter.set(happyProcess.pid, (completedSession) => { + clearTimeout(timeout); + types.logger.debug(`[DAEMON RUN] Session ${completedSession.happySessionId} fully spawned with webhook`); + resolve({ + type: "success", + sessionId: completedSession.happySessionId + }); + }); + }); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + types.logger.debug("[DAEMON RUN] Failed to spawn session:", error); + return { + type: "error", + errorMessage: `Failed to spawn session: ${errorMessage}` + }; + } + }; + const stopSession = (sessionId) => { + types.logger.debug(`[DAEMON RUN] Attempting to stop session ${sessionId}`); + for (const [pid, session] of pidToTrackedSession.entries()) { + if (session.happySessionId === sessionId || sessionId.startsWith("PID-") && pid === parseInt(sessionId.replace("PID-", ""))) { + if (session.startedBy === "daemon" && session.childProcess) { + try { + session.childProcess.kill("SIGTERM"); + types.logger.debug(`[DAEMON RUN] Sent SIGTERM to daemon-spawned session ${sessionId}`); + } catch (error) { + types.logger.debug(`[DAEMON RUN] Failed to kill session ${sessionId}:`, error); + } + } else { + try { + process.kill(pid, "SIGTERM"); + types.logger.debug(`[DAEMON RUN] Sent SIGTERM to external session PID ${pid}`); + } catch (error) { + types.logger.debug(`[DAEMON RUN] Failed to kill external session PID ${pid}:`, error); + } + } + pidToTrackedSession.delete(pid); + types.logger.debug(`[DAEMON RUN] Removed session ${sessionId} from tracking`); + return true; + } + } + types.logger.debug(`[DAEMON RUN] Session ${sessionId} not found`); + return false; + }; + const onChildExited = (pid) => { + types.logger.debug(`[DAEMON RUN] Removing exited process PID ${pid} from tracking`); + pidToTrackedSession.delete(pid); + }; + const { port: controlPort, stop: stopControlServer } = await startDaemonControlServer({ + getChildren: getCurrentChildren, + stopSession, + spawnSession, + requestShutdown: () => requestShutdown("happy-cli"), + onHappySessionWebhook + }); + const fileState = { + pid: process.pid, + httpPort: controlPort, + startTime: (/* @__PURE__ */ new Date()).toLocaleString(), + startedWithCliVersion: types.packageJson.version, + daemonLogPath: types.logger.logFilePath + }; + types.writeDaemonState(fileState); + types.logger.debug("[DAEMON RUN] Daemon state written"); + const initialDaemonState = { + status: "offline", + pid: process.pid, + httpPort: controlPort, + startedAt: Date.now() + }; + const api = await types.ApiClient.create(credentials); + const machine = await api.getOrCreateMachine({ + machineId, + metadata: initialMachineMetadata, + daemonState: initialDaemonState + }); + types.logger.debug(`[DAEMON RUN] Machine registered: ${machine.id}`); + const apiMachine = api.machineSyncClient(machine); + apiMachine.setRPCHandlers({ + spawnSession, + stopSession, + requestShutdown: () => requestShutdown("happy-app") + }); + apiMachine.connect(); + const heartbeatIntervalMs = parseInt(process.env.HAPPY_DAEMON_HEARTBEAT_INTERVAL || "60000"); + let heartbeatRunning = false; + const restartOnStaleVersionAndHeartbeat = setInterval(async () => { + if (heartbeatRunning) { + return; + } + heartbeatRunning = true; + if (process.env.DEBUG) { + types.logger.debug(`[DAEMON RUN] Health check started at ${(/* @__PURE__ */ new Date()).toLocaleString()}`); + } + for (const [pid, _] of pidToTrackedSession.entries()) { + try { + process.kill(pid, 0); + } catch (error) { + types.logger.debug(`[DAEMON RUN] Removing stale session with PID ${pid} (process no longer exists)`); + pidToTrackedSession.delete(pid); + } + } + const projectVersion = JSON.parse(fs$2.readFileSync(path.join(types.projectPath(), "package.json"), "utf-8")).version; + if (projectVersion !== types.configuration.currentCliVersion) { + types.logger.debug("[DAEMON RUN] Daemon is outdated, triggering self-restart with latest version, clearing heartbeat interval"); + clearInterval(restartOnStaleVersionAndHeartbeat); + try { + spawnHappyCLI(["daemon", "start"], { + detached: true, + stdio: "ignore" + }); + } catch (error) { + types.logger.debug("[DAEMON RUN] Failed to spawn new daemon, this is quite likely to happen during integration tests as we are cleaning out dist/ directory", error); + } + types.logger.debug("[DAEMON RUN] Hanging for a bit - waiting for CLI to kill us because we are running outdated version of the code"); + await new Promise((resolve) => setTimeout(resolve, 1e4)); + process.exit(0); + } + const daemonState = await types.readDaemonState(); + if (daemonState && daemonState.pid !== process.pid) { + types.logger.debug("[DAEMON RUN] Somehow a different daemon was started without killing us. We should kill ourselves."); + requestShutdown("exception", "A different daemon was started without killing us. We should kill ourselves."); + } + try { + const updatedState = { + pid: process.pid, + httpPort: controlPort, + startTime: fileState.startTime, + startedWithCliVersion: types.packageJson.version, + lastHeartbeat: (/* @__PURE__ */ new Date()).toLocaleString(), + daemonLogPath: fileState.daemonLogPath + }; + types.writeDaemonState(updatedState); + if (process.env.DEBUG) { + types.logger.debug(`[DAEMON RUN] Health check completed at ${updatedState.lastHeartbeat}`); + } + } catch (error) { + types.logger.debug("[DAEMON RUN] Failed to write heartbeat", error); + } + heartbeatRunning = false; + }, heartbeatIntervalMs); + const cleanupAndShutdown = async (source, errorMessage) => { + types.logger.debug(`[DAEMON RUN] Starting proper cleanup (source: ${source}, errorMessage: ${errorMessage})...`); + if (restartOnStaleVersionAndHeartbeat) { + clearInterval(restartOnStaleVersionAndHeartbeat); + types.logger.debug("[DAEMON RUN] Health check interval cleared"); + } + await apiMachine.updateDaemonState((state) => ({ + ...state, + status: "shutting-down", + shutdownRequestedAt: Date.now(), + shutdownSource: source + })); + await new Promise((resolve) => setTimeout(resolve, 100)); + apiMachine.shutdown(); + await stopControlServer(); + await cleanupDaemonState(); + await stopCaffeinate(); + await types.releaseDaemonLock(daemonLockHandle); + types.logger.debug("[DAEMON RUN] Cleanup completed, exiting process"); + process.exit(0); + }; + types.logger.debug("[DAEMON RUN] Daemon started successfully, waiting for shutdown request"); + const shutdownRequest = await resolvesWhenShutdownRequested; + await cleanupAndShutdown(shutdownRequest.source, shutdownRequest.errorMessage); + } catch (error) { + types.logger.debug("[DAEMON RUN][FATAL] Failed somewhere unexpectedly - exiting with code 1", error); + process.exit(1); + } +} + +async function startHappyServer(client) { + const handler = async (title) => { + types.logger.debug("[happyMCP] Changing title to:", title); + try { + client.sendClaudeSessionMessage({ + type: "summary", + summary: title, + leafUuid: node_crypto.randomUUID() + }); + return { success: true }; + } catch (error) { + return { success: false, error: String(error) }; + } + }; + const mcp = new mcp_js.McpServer({ + name: "Happy MCP", + version: "1.0.0", + description: "Happy CLI MCP server with chat session management tools" + }); + mcp.registerTool("change_title", { + description: "Change the title of the current chat session", + title: "Change Chat Title", + inputSchema: { + title: z.z.string().describe("The new title for the chat session") + } + }, async (args) => { + const response = await handler(args.title); + types.logger.debug("[happyMCP] Response:", response); + if (response.success) { + return { + content: [ + { + type: "text", + text: `Successfully changed chat title to: "${args.title}"` + } + ], + isError: false + }; + } else { + return { + content: [ + { + type: "text", + text: `Failed to change chat title: ${response.error || "Unknown error"}` + } + ], + isError: true + }; + } + }); + const transport = new streamableHttp_js.StreamableHTTPServerTransport({ + // NOTE: Returning session id here will result in claude + // sdk spawn to fail with `Invalid Request: Server already initialized` + sessionIdGenerator: void 0 + }); + await mcp.connect(transport); + const server = node_http.createServer(async (req, res) => { + try { + await transport.handleRequest(req, res); + } catch (error) { + types.logger.debug("Error handling request:", error); + if (!res.headersSent) { + res.writeHead(500).end(); + } + } + }); + const baseUrl = await new Promise((resolve) => { + server.listen(0, "127.0.0.1", () => { + const addr = server.address(); + resolve(new URL(`http://127.0.0.1:${addr.port}`)); + }); + }); + return { + url: baseUrl.toString(), + toolNames: ["change_title"], + stop: () => { + types.logger.debug("[happyMCP] Stopping server"); + mcp.close(); + server.close(); + } + }; +} + +function registerKillSessionHandler(rpcHandlerManager, killThisHappy) { + rpcHandlerManager.registerHandler("killSession", async () => { + types.logger.debug("Kill session request received"); + void killThisHappy(); + return { + success: true, + message: "Killing happy-cli process" + }; + }); +} + +async function runClaude(credentials, options = {}) { + const workingDirectory = process.cwd(); + const sessionTag = node_crypto.randomUUID(); + types.logger.debugLargeJson("[START] Happy process started", getEnvironmentInfo()); + types.logger.debug(`[START] Options: startedBy=${options.startedBy}, startingMode=${options.startingMode}`); + if (options.startedBy === "daemon" && options.startingMode === "local") { + types.logger.debug("Daemon spawn requested with local mode - forcing remote mode"); + options.startingMode = "remote"; + } + const api = await types.ApiClient.create(credentials); + let state = {}; + const settings = await types.readSettings(); + let machineId = settings?.machineId; + if (!machineId) { + console.error(`[START] No machine ID found in settings, which is unexepcted since authAndSetupMachineIfNeeded should have created it. Please report this issue on https://github.com/slopus/happy-cli/issues`); + process.exit(1); + } + types.logger.debug(`Using machineId: ${machineId}`); + await api.getOrCreateMachine({ + machineId, + metadata: initialMachineMetadata + }); + let metadata = { + path: workingDirectory, + host: os.hostname(), + version: types.packageJson.version, + os: os.platform(), + machineId, + homeDir: os.homedir(), + happyHomeDir: types.configuration.happyHomeDir, + happyLibDir: types.projectPath(), + happyToolsDir: node_path.resolve(types.projectPath(), "tools", "unpacked"), + startedFromDaemon: options.startedBy === "daemon", + hostPid: process.pid, + startedBy: options.startedBy || "terminal", + // Initialize lifecycle state + lifecycleState: "running", + lifecycleStateSince: Date.now(), + flavor: "claude" + }; + const response = await api.getOrCreateSession({ tag: sessionTag, metadata, state }); + types.logger.debug(`Session created: ${response.id}`); + try { + types.logger.debug(`[START] Reporting session ${response.id} to daemon`); + const result = await notifyDaemonSessionStarted(response.id, metadata); + if (result.error) { + types.logger.debug(`[START] Failed to report to daemon (may not be running):`, result.error); + } else { + types.logger.debug(`[START] Reported session ${response.id} to daemon`); + } + } catch (error) { + types.logger.debug("[START] Failed to report to daemon (may not be running):", error); + } + extractSDKMetadataAsync(async (sdkMetadata) => { + types.logger.debug("[start] SDK metadata extracted, updating session:", sdkMetadata); + try { + api.sessionSyncClient(response).updateMetadata((currentMetadata) => ({ + ...currentMetadata, + tools: sdkMetadata.tools, + slashCommands: sdkMetadata.slashCommands + })); + types.logger.debug("[start] Session metadata updated with SDK capabilities"); + } catch (error) { + types.logger.debug("[start] Failed to update session metadata:", error); + } + }); + const session = api.sessionSyncClient(response); + const happyServer = await startHappyServer(session); + types.logger.debug(`[START] Happy MCP server started at ${happyServer.url}`); + const logPath = types.logger.logFilePath; + types.logger.infoDeveloper(`Session: ${response.id}`); + types.logger.infoDeveloper(`Logs: ${logPath}`); + session.updateAgentState((currentState) => ({ + ...currentState, + controlledByUser: options.startingMode !== "remote" + })); + const caffeinateStarted = startCaffeinate(); + if (caffeinateStarted) { + types.logger.infoDeveloper("Sleep prevention enabled (macOS)"); + } + const messageQueue = new MessageQueue2((mode) => hashObject({ + isPlan: mode.permissionMode === "plan", + model: mode.model, + fallbackModel: mode.fallbackModel, + customSystemPrompt: mode.customSystemPrompt, + appendSystemPrompt: mode.appendSystemPrompt, + allowedTools: mode.allowedTools, + disallowedTools: mode.disallowedTools + })); + let currentPermissionMode = options.permissionMode; + let currentModel = options.model; + let currentFallbackModel = void 0; + let currentCustomSystemPrompt = void 0; + let currentAppendSystemPrompt = void 0; + let currentAllowedTools = void 0; + let currentDisallowedTools = void 0; + session.onUserMessage((message) => { + let messagePermissionMode = currentPermissionMode; + if (message.meta?.permissionMode) { + const validModes = ["default", "acceptEdits", "bypassPermissions", "plan"]; + if (validModes.includes(message.meta.permissionMode)) { + messagePermissionMode = message.meta.permissionMode; + currentPermissionMode = messagePermissionMode; + types.logger.debug(`[loop] Permission mode updated from user message to: ${currentPermissionMode}`); + } else { + types.logger.debug(`[loop] Invalid permission mode received: ${message.meta.permissionMode}`); + } + } else { + types.logger.debug(`[loop] User message received with no permission mode override, using current: ${currentPermissionMode}`); + } + let messageModel = currentModel; + if (message.meta?.hasOwnProperty("model")) { + messageModel = message.meta.model || void 0; + currentModel = messageModel; + types.logger.debug(`[loop] Model updated from user message: ${messageModel || "reset to default"}`); + } else { + types.logger.debug(`[loop] User message received with no model override, using current: ${currentModel || "default"}`); + } + let messageCustomSystemPrompt = currentCustomSystemPrompt; + if (message.meta?.hasOwnProperty("customSystemPrompt")) { + messageCustomSystemPrompt = message.meta.customSystemPrompt || void 0; + currentCustomSystemPrompt = messageCustomSystemPrompt; + types.logger.debug(`[loop] Custom system prompt updated from user message: ${messageCustomSystemPrompt ? "set" : "reset to none"}`); + } else { + types.logger.debug(`[loop] User message received with no custom system prompt override, using current: ${currentCustomSystemPrompt ? "set" : "none"}`); + } + let messageFallbackModel = currentFallbackModel; + if (message.meta?.hasOwnProperty("fallbackModel")) { + messageFallbackModel = message.meta.fallbackModel || void 0; + currentFallbackModel = messageFallbackModel; + types.logger.debug(`[loop] Fallback model updated from user message: ${messageFallbackModel || "reset to none"}`); + } else { + types.logger.debug(`[loop] User message received with no fallback model override, using current: ${currentFallbackModel || "none"}`); + } + let messageAppendSystemPrompt = currentAppendSystemPrompt; + if (message.meta?.hasOwnProperty("appendSystemPrompt")) { + messageAppendSystemPrompt = message.meta.appendSystemPrompt || void 0; + currentAppendSystemPrompt = messageAppendSystemPrompt; + types.logger.debug(`[loop] Append system prompt updated from user message: ${messageAppendSystemPrompt ? "set" : "reset to none"}`); + } else { + types.logger.debug(`[loop] User message received with no append system prompt override, using current: ${currentAppendSystemPrompt ? "set" : "none"}`); + } + let messageAllowedTools = currentAllowedTools; + if (message.meta?.hasOwnProperty("allowedTools")) { + messageAllowedTools = message.meta.allowedTools || void 0; + currentAllowedTools = messageAllowedTools; + types.logger.debug(`[loop] Allowed tools updated from user message: ${messageAllowedTools ? messageAllowedTools.join(", ") : "reset to none"}`); + } else { + types.logger.debug(`[loop] User message received with no allowed tools override, using current: ${currentAllowedTools ? currentAllowedTools.join(", ") : "none"}`); + } + let messageDisallowedTools = currentDisallowedTools; + if (message.meta?.hasOwnProperty("disallowedTools")) { + messageDisallowedTools = message.meta.disallowedTools || void 0; + currentDisallowedTools = messageDisallowedTools; + types.logger.debug(`[loop] Disallowed tools updated from user message: ${messageDisallowedTools ? messageDisallowedTools.join(", ") : "reset to none"}`); + } else { + types.logger.debug(`[loop] User message received with no disallowed tools override, using current: ${currentDisallowedTools ? currentDisallowedTools.join(", ") : "none"}`); + } + const specialCommand = parseSpecialCommand(message.content.text); + if (specialCommand.type === "compact") { + types.logger.debug("[start] Detected /compact command"); + const enhancedMode2 = { + permissionMode: messagePermissionMode || "default", + model: messageModel, + fallbackModel: messageFallbackModel, + customSystemPrompt: messageCustomSystemPrompt, + appendSystemPrompt: messageAppendSystemPrompt, + allowedTools: messageAllowedTools, + disallowedTools: messageDisallowedTools + }; + messageQueue.pushIsolateAndClear(specialCommand.originalMessage || message.content.text, enhancedMode2); + types.logger.debugLargeJson("[start] /compact command pushed to queue:", message); + return; + } + if (specialCommand.type === "clear") { + types.logger.debug("[start] Detected /clear command"); + const enhancedMode2 = { + permissionMode: messagePermissionMode || "default", + model: messageModel, + fallbackModel: messageFallbackModel, + customSystemPrompt: messageCustomSystemPrompt, + appendSystemPrompt: messageAppendSystemPrompt, + allowedTools: messageAllowedTools, + disallowedTools: messageDisallowedTools + }; + messageQueue.pushIsolateAndClear(specialCommand.originalMessage || message.content.text, enhancedMode2); + types.logger.debugLargeJson("[start] /compact command pushed to queue:", message); + return; + } + const enhancedMode = { + permissionMode: messagePermissionMode || "default", + model: messageModel, + fallbackModel: messageFallbackModel, + customSystemPrompt: messageCustomSystemPrompt, + appendSystemPrompt: messageAppendSystemPrompt, + allowedTools: messageAllowedTools, + disallowedTools: messageDisallowedTools + }; + messageQueue.push(message.content.text, enhancedMode); + types.logger.debugLargeJson("User message pushed to queue:", message); + }); + const cleanup = async () => { + types.logger.debug("[START] Received termination signal, cleaning up..."); + try { + if (session) { + session.updateMetadata((currentMetadata) => ({ + ...currentMetadata, + lifecycleState: "archived", + lifecycleStateSince: Date.now(), + archivedBy: "cli", + archiveReason: "User terminated" + })); + session.sendSessionDeath(); + await session.flush(); + await session.close(); + } + stopCaffeinate(); + happyServer.stop(); + types.logger.debug("[START] Cleanup complete, exiting"); + process.exit(0); + } catch (error) { + types.logger.debug("[START] Error during cleanup:", error); + process.exit(1); + } + }; + process.on("SIGTERM", cleanup); + process.on("SIGINT", cleanup); + process.on("uncaughtException", (error) => { + types.logger.debug("[START] Uncaught exception:", error); + cleanup(); + }); + process.on("unhandledRejection", (reason) => { + types.logger.debug("[START] Unhandled rejection:", reason); + cleanup(); + }); + registerKillSessionHandler(session.rpcHandlerManager, cleanup); + await loop({ + path: workingDirectory, + model: options.model, + permissionMode: options.permissionMode, + startingMode: options.startingMode, + messageQueue, + api, + allowedTools: happyServer.toolNames.map((toolName) => `mcp__happy__${toolName}`), + onModeChange: (newMode) => { + session.sendSessionEvent({ type: "switch", mode: newMode }).catch((err) => types.logger.debug("[Claude] Failed to send mode change event:", err)); + session.updateAgentState((currentState) => ({ + ...currentState, + controlledByUser: newMode === "local" + })); + }, + onSessionReady: (_sessionInstance) => { + }, + mcpServers: { + "happy": { + type: "http", + url: happyServer.url + } + }, + session, + claudeEnvVars: options.claudeEnvVars, + claudeArgs: options.claudeArgs + }); + session.sendSessionDeath(); + types.logger.debug("Waiting for socket to flush..."); + await session.flush(); + types.logger.debug("Closing session..."); + await session.close(); + stopCaffeinate(); + types.logger.debug("Stopped sleep prevention"); + happyServer.stop(); + types.logger.debug("Stopped Happy MCP server"); + process.exit(0); +} + +const PLIST_LABEL$1 = "com.happy-cli.daemon"; +const PLIST_FILE$1 = `/Library/LaunchDaemons/${PLIST_LABEL$1}.plist`; +async function install$1() { + try { + if (fs$2.existsSync(PLIST_FILE$1)) { + types.logger.info("Daemon plist already exists. Uninstalling first..."); + child_process.execSync(`launchctl unload ${PLIST_FILE$1}`, { stdio: "inherit" }); + } + const happyPath = process.argv[0]; + const scriptPath = process.argv[1]; + const plistContent = trimIdent(` + + + + + Label + ${PLIST_LABEL$1} + + ProgramArguments + + ${happyPath} + ${scriptPath} + happy-daemon + + + EnvironmentVariables + + HAPPY_DAEMON_MODE + true + + + RunAtLoad + + + KeepAlive + + + StandardErrorPath + ${os$1.homedir()}/.happy/daemon.err + + StandardOutPath + ${os$1.homedir()}/.happy/daemon.log + + WorkingDirectory + /tmp + + + `); + fs$2.writeFileSync(PLIST_FILE$1, plistContent); + fs$2.chmodSync(PLIST_FILE$1, 420); + types.logger.info(`Created daemon plist at ${PLIST_FILE$1}`); + child_process.execSync(`launchctl load ${PLIST_FILE$1}`, { stdio: "inherit" }); + types.logger.info("Daemon installed and started successfully"); + types.logger.info("Check logs at ~/.happy/daemon.log"); + } catch (error) { + types.logger.debug("Failed to install daemon:", error); + throw error; + } +} + +async function install() { + if (process.platform !== "darwin") { + throw new Error("Daemon installation is currently only supported on macOS"); + } + if (process.getuid && process.getuid() !== 0) { + throw new Error("Daemon installation requires sudo privileges. Please run with sudo."); + } + types.logger.info("Installing Happy CLI daemon for macOS..."); + await install$1(); +} + +const PLIST_LABEL = "com.happy-cli.daemon"; +const PLIST_FILE = `/Library/LaunchDaemons/${PLIST_LABEL}.plist`; +async function uninstall$1() { + try { + if (!fs$2.existsSync(PLIST_FILE)) { + types.logger.info("Daemon plist not found. Nothing to uninstall."); + return; + } + try { + child_process.execSync(`launchctl unload ${PLIST_FILE}`, { stdio: "inherit" }); + types.logger.info("Daemon stopped successfully"); + } catch (error) { + types.logger.info("Failed to unload daemon (it might not be running)"); + } + fs$2.unlinkSync(PLIST_FILE); + types.logger.info(`Removed daemon plist from ${PLIST_FILE}`); + types.logger.info("Daemon uninstalled successfully"); + } catch (error) { + types.logger.debug("Failed to uninstall daemon:", error); + throw error; + } +} + +async function uninstall() { + if (process.platform !== "darwin") { + throw new Error("Daemon uninstallation is currently only supported on macOS"); + } + if (process.getuid && process.getuid() !== 0) { + throw new Error("Daemon uninstallation requires sudo privileges. Please run with sudo."); + } + types.logger.info("Uninstalling Happy CLI daemon for macOS..."); + await uninstall$1(); +} + +async function handleAuthCommand(args) { + const subcommand = args[0]; + if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") { + showAuthHelp(); + return; + } + switch (subcommand) { + case "login": + await handleAuthLogin(args.slice(1)); + break; + case "logout": + await handleAuthLogout(); + break; + // case 'backup': + // await handleAuthShowBackup(); + // break; + case "status": + await handleAuthStatus(); + break; + default: + console.error(chalk.red(`Unknown auth subcommand: ${subcommand}`)); + showAuthHelp(); + process.exit(1); + } +} +function showAuthHelp() { + console.log(` +${chalk.bold("happy auth")} - Authentication management + +${chalk.bold("Usage:")} + happy auth login [--force] Authenticate with Happy + happy auth logout Remove authentication and machine data + happy auth status Show authentication status + happy auth show-backup Display backup key for mobile/web clients + happy auth help Show this help message + +${chalk.bold("Options:")} + --force Clear credentials, machine ID, and stop daemon before re-auth +`); +} +async function handleAuthLogin(args) { + const forceAuth = args.includes("--force") || args.includes("-f"); + if (forceAuth) { + console.log(chalk.yellow("Force authentication requested.")); + console.log(chalk.gray("This will:")); + console.log(chalk.gray(" \u2022 Clear existing credentials")); + console.log(chalk.gray(" \u2022 Clear machine ID")); + console.log(chalk.gray(" \u2022 Stop daemon if running")); + console.log(chalk.gray(" \u2022 Re-authenticate and register machine\n")); + try { + types.logger.debug("Stopping daemon for force auth..."); + await stopDaemon(); + console.log(chalk.gray("\u2713 Stopped daemon")); + } catch (error) { + types.logger.debug("Daemon was not running or failed to stop:", error); + } + await types.clearCredentials(); + console.log(chalk.gray("\u2713 Cleared credentials")); + await types.clearMachineId(); + console.log(chalk.gray("\u2713 Cleared machine ID")); + console.log(""); + } + if (!forceAuth) { + const existingCreds = await types.readCredentials(); + const settings = await types.readSettings(); + if (existingCreds && settings?.machineId) { + console.log(chalk.green("\u2713 Already authenticated")); + console.log(chalk.gray(` Machine ID: ${settings.machineId}`)); + console.log(chalk.gray(` Host: ${os.hostname()}`)); + console.log(chalk.gray(` Use 'happy auth login --force' to re-authenticate`)); + return; + } else if (existingCreds && !settings?.machineId) { + console.log(chalk.yellow("\u26A0\uFE0F Credentials exist but machine ID is missing")); + console.log(chalk.gray(" This can happen if --auth flag was used previously")); + console.log(chalk.gray(" Fixing by setting up machine...\n")); + } + } + try { + const result = await authAndSetupMachineIfNeeded(); + console.log(chalk.green("\n\u2713 Authentication successful")); + console.log(chalk.gray(` Machine ID: ${result.machineId}`)); + } catch (error) { + console.error(chalk.red("Authentication failed:"), error instanceof Error ? error.message : "Unknown error"); + process.exit(1); + } +} +async function handleAuthLogout() { + const happyDir = types.configuration.happyHomeDir; + const credentials = await types.readCredentials(); + if (!credentials) { + console.log(chalk.yellow("Not currently authenticated")); + return; + } + console.log(chalk.blue("This will log you out of Happy")); + console.log(chalk.yellow("\u26A0\uFE0F You will need to re-authenticate to use Happy again")); + const rl = node_readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + const answer = await new Promise((resolve) => { + rl.question(chalk.yellow("Are you sure you want to log out? (y/N): "), resolve); + }); + rl.close(); + if (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") { + try { + try { + await stopDaemon(); + console.log(chalk.gray("Stopped daemon")); + } catch { + } + if (fs.existsSync(happyDir)) { + fs.rmSync(happyDir, { recursive: true, force: true }); + } + console.log(chalk.green("\u2713 Successfully logged out")); + console.log(chalk.gray(' Run "happy auth login" to authenticate again')); + } catch (error) { + throw new Error(`Failed to logout: ${error instanceof Error ? error.message : "Unknown error"}`); + } + } else { + console.log(chalk.blue("Logout cancelled")); + } +} +async function handleAuthStatus() { + const credentials = await types.readCredentials(); + const settings = await types.readSettings(); + console.log(chalk.bold("\nAuthentication Status\n")); + if (!credentials) { + console.log(chalk.red("\u2717 Not authenticated")); + console.log(chalk.gray(' Run "happy auth login" to authenticate')); + return; + } + console.log(chalk.green("\u2713 Authenticated")); + const tokenPreview = credentials.token.substring(0, 30) + "..."; + console.log(chalk.gray(` Token: ${tokenPreview}`)); + if (settings?.machineId) { + console.log(chalk.green("\u2713 Machine registered")); + console.log(chalk.gray(` Machine ID: ${settings.machineId}`)); + console.log(chalk.gray(` Host: ${os.hostname()}`)); + } else { + console.log(chalk.yellow("\u26A0\uFE0F Machine not registered")); + console.log(chalk.gray(' Run "happy auth login --force" to fix this')); + } + console.log(chalk.gray(` + Data directory: ${types.configuration.happyHomeDir}`)); + try { + const running = await checkIfDaemonRunningAndCleanupStaleState(); + if (running) { + console.log(chalk.green("\u2713 Daemon running")); + } else { + console.log(chalk.gray("\u2717 Daemon not running")); + } + } catch { + console.log(chalk.gray("\u2717 Daemon not running")); + } +} + +const CLIENT_ID$2 = "app_EMoamEEZ73f0CkXaXp7hrann"; +const AUTH_BASE_URL = "https://auth.openai.com"; +const DEFAULT_PORT$2 = 1455; +function generatePKCE$2() { + const verifier = crypto.randomBytes(32).toString("base64url").replace(/[^a-zA-Z0-9\-._~]/g, ""); + const challenge = crypto.createHash("sha256").update(verifier).digest("base64url").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_"); + return { verifier, challenge }; +} +function generateState$2() { + return crypto.randomBytes(16).toString("hex"); +} +function parseJWT(token) { + const parts = token.split("."); + if (parts.length !== 3) { + throw new Error("Invalid JWT format"); + } + const payload = Buffer.from(parts[1], "base64url").toString(); + return JSON.parse(payload); +} +async function findAvailablePort$2() { + return new Promise((resolve) => { + const server = http.createServer(); + server.listen(0, "127.0.0.1", () => { + const port = server.address().port; + server.close(() => resolve(port)); + }); + }); +} +async function isPortAvailable$2(port) { + return new Promise((resolve) => { + const testServer = http.createServer(); + testServer.once("error", () => { + testServer.close(); + resolve(false); + }); + testServer.listen(port, "127.0.0.1", () => { + testServer.close(() => resolve(true)); + }); + }); +} +async function exchangeCodeForTokens$2(code, verifier, port) { + const response = await fetch(`${AUTH_BASE_URL}/oauth/token`, { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded" + }, + body: new URLSearchParams({ + grant_type: "authorization_code", + client_id: CLIENT_ID$2, + code, + code_verifier: verifier, + redirect_uri: `http://localhost:${port}/auth/callback` + }) + }); + if (!response.ok) { + const error = await response.text(); + throw new Error(`Token exchange failed: ${error}`); + } + const data = await response.json(); + const idTokenPayload = parseJWT(data.id_token); + let accountId = idTokenPayload.chatgpt_account_id; + if (!accountId) { + const authClaim = idTokenPayload["https://api.openai.com/auth"]; + if (authClaim && typeof authClaim === "object") { + accountId = authClaim.chatgpt_account_id || authClaim.account_id; + } + } + return { + id_token: data.id_token, + access_token: data.access_token || data.id_token, + refresh_token: data.refresh_token, + account_id: accountId + }; +} +async function startCallbackServer$2(state, verifier, port) { + return new Promise((resolve, reject) => { + const server = http.createServer(async (req, res) => { + const url = new URL(req.url, `http://localhost:${port}`); + if (url.pathname === "/auth/callback") { + const code = url.searchParams.get("code"); + const receivedState = url.searchParams.get("state"); + if (receivedState !== state) { + res.writeHead(400); + res.end("Invalid state parameter"); + server.close(); + reject(new Error("Invalid state parameter")); + return; + } + if (!code) { + res.writeHead(400); + res.end("No authorization code received"); + server.close(); + reject(new Error("No authorization code received")); + return; + } + try { + const tokens = await exchangeCodeForTokens$2(code, verifier, port); + res.writeHead(200, { "Content-Type": "text/html" }); + res.end(` + + +

\u2705 Authentication Successful!

+

You can close this window and return to your terminal.

+