diff --git a/extension/src/background.ts b/extension/src/background.ts index 894b83d..3a95ab2 100644 --- a/extension/src/background.ts +++ b/extension/src/background.ts @@ -328,6 +328,7 @@ function onDebuggerDetach(source: chrome.debugger.Debuggee, reason: `${chrome.de }) if (reason === chrome.debugger.DetachReason.CANCELED_BY_USER) { + // Chrome's debugger info bar cancellation detaches ALL debugger sessions, not just one tab store.setState({ connectionState: 'disconnected', errorText: undefined }) } } @@ -451,6 +452,7 @@ function handleConnectionClose(reason: string, code: number): void { if (reason === 'Extension Replaced' || code === 4001) { logger.debug('Connection replaced by another extension instance') store.setState({ + tabs: new Map(), connectionState: 'error', errorText: 'Disconnected: Replaced by another extension', }) diff --git a/playwriter/package.json b/playwriter/package.json index 1269d47..58e0256 100644 --- a/playwriter/package.json +++ b/playwriter/package.json @@ -45,6 +45,7 @@ "devtools-protocol": "^0.0.1543509", "diff": "^8.0.2", "hono": "^4.10.6", + "kill-port-process": "^3.2.1", "playwright-core": "^1.56.1", "string-dedent": "^3.0.2", "user-agents": "^1.1.669", diff --git a/playwriter/src/create-logger.ts b/playwriter/src/create-logger.ts index cc7c40c..74e1b49 100644 --- a/playwriter/src/create-logger.ts +++ b/playwriter/src/create-logger.ts @@ -9,33 +9,12 @@ export type Logger = { logFilePath: string } -function cleanupOldLogs(logsDir: string): void { - if (!fs.existsSync(logsDir)) { - return - } - const files = fs.readdirSync(logsDir) - .filter((f) => f.startsWith('relay-server-') && f.endsWith('.log')) - .map((f) => ({ - name: f, - path: path.join(logsDir, f), - mtime: fs.statSync(path.join(logsDir, f)).mtime.getTime(), - })) - .sort((a, b) => b.mtime - a.mtime) - - if (files.length > 10) { - files.slice(10).forEach((f) => { - fs.unlinkSync(f.path) - }) - } -} - export function createFileLogger({ logFilePath }: { logFilePath?: string } = {}): Logger { const resolvedLogFilePath = logFilePath || LOG_FILE_PATH const logDir = path.dirname(resolvedLogFilePath) if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }) } - cleanupOldLogs(logDir) fs.writeFileSync(resolvedLogFilePath, '') let queue: Promise = Promise.resolve() diff --git a/playwriter/src/extension/cdp-relay.ts b/playwriter/src/extension/cdp-relay.ts index 89b900a..45b2bbf 100644 --- a/playwriter/src/extension/cdp-relay.ts +++ b/playwriter/src/extension/cdp-relay.ts @@ -7,6 +7,7 @@ import type { CDPCommand, CDPResponseBase, CDPEventBase, CDPEventFor, RelayServe import type { ExtensionMessage, ExtensionEventMessage } from './protocol.js' import chalk from 'chalk' import { EventEmitter } from 'node:events' +import { VERSION } from '../utils.js' type ConnectedTarget = { sessionId: string @@ -276,6 +277,10 @@ export async function startPlayWriterCDPRelayServer({ port = 19988, host = '127. return c.text('OK') }) + app.get('/version', (c) => { + return c.json({ version: VERSION }) + }) + app.post('/mcp-log', async (c) => { try { const { level, args } = await c.req.json() diff --git a/playwriter/src/mcp.test.ts b/playwriter/src/mcp.test.ts index 71d9f40..7dda624 100644 --- a/playwriter/src/mcp.test.ts +++ b/playwriter/src/mcp.test.ts @@ -14,6 +14,7 @@ import { getCDPSessionForPage } from './cdp-session.js' import { startPlayWriterCDPRelayServer, type RelayServer } from './extension/cdp-relay.js' import { createFileLogger } from './create-logger.js' import type { CDPCommand } from './cdp-types.js' +import { killPortProcess } from 'kill-port-process' declare const window: any declare const document: any @@ -51,15 +52,10 @@ function js(strings: TemplateStringsArray, ...values: any[]): string { async function killProcessOnPort(port: number): Promise { try { - const { stdout } = await execAsync(`lsof -ti:${port}`) - const pids = stdout.trim().split('\n').filter(Boolean) - if (pids.length > 0) { - await execAsync(`kill -9 ${pids.join(' ')}`) - console.log(`Killed processes ${pids.join(', ')} on port ${port}`) - await new Promise((resolve) => setTimeout(resolve, 1000)) - } - } catch (error) { - // No process running on port or already killed + await killPortProcess(port) + console.log(`Killed processes on port ${port}`) + } catch (err) { + console.error('Error killing process on port:', err) } } @@ -1635,7 +1631,7 @@ describe('MCP Server Tests', () => { const wsUrl = getCdpUrl() const client = await getCDPSessionForPage({ page: cdpPage!, wsUrl }) - + const layoutMetrics = await client.send('Page.getLayoutMetrics') expect(layoutMetrics.cssVisualViewport).toBeDefined() expect(layoutMetrics.cssVisualViewport.clientWidth).toBeGreaterThan(0) @@ -1968,14 +1964,20 @@ describe('CDP Session Tests', () => { sampleFunctionNames: functionNames, }).toMatchInlineSnapshot(` { - "durationMicroseconds": 15772, + "durationMicroseconds": 7398, "hasNodes": true, - "nodeCount": 7, + "nodeCount": 21, "sampleFunctionNames": [ "(root)", "(program)", "(idle)", "evaluate", + "fibonacci", + "fibonacci", + "fibonacci", + "fibonacci", + "fibonacci", + "fibonacci", ], } `) diff --git a/playwriter/src/mcp.ts b/playwriter/src/mcp.ts index 68ac7b6..5888383 100644 --- a/playwriter/src/mcp.ts +++ b/playwriter/src/mcp.ts @@ -11,7 +11,8 @@ import { fileURLToPath } from 'node:url' import vm from 'node:vm' import dedent from 'string-dedent' import { createPatch } from 'diff' -import { getCdpUrl, LOG_FILE_PATH } from './utils.js' +import { getCdpUrl, LOG_FILE_PATH, VERSION } from './utils.js' +import { killPortProcess } from 'kill-port-process' import { waitForPageLoad, WaitForPageLoadOptions, WaitForPageLoadResult } from './wait-for-page-load.js' import { getCDPSessionForPage, CDPSession } from './cdp-session.js' @@ -152,7 +153,7 @@ function clearConnectionState() { async function sendLogToRelayServer(level: string, ...args: any[]) { try { - await fetch(`http://localhost:${RELAY_PORT}/mcp-log`, { + await fetch(`http://127.0.0.1:${RELAY_PORT}/mcp-log`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ level, args }), @@ -163,25 +164,41 @@ async function sendLogToRelayServer(level: string, ...args: any[]) { } } -async function isPortTaken(port: number): Promise { +async function getServerVersion(port: number): Promise { try { - const response = await fetch(`http://localhost:${port}/`, { - signal: AbortSignal.timeout(100), + const response = await fetch(`http://127.0.0.1:${port}/version`, { + signal: AbortSignal.timeout(500), }) - return response.ok - } catch { - return false + if (!response.ok) { + return null + } + const data = (await response.json()) as { version: string } + return data.version + } catch (error) { + return null } } -async function ensureRelayServer(): Promise { - const portTaken = await isPortTaken(RELAY_PORT) +async function killRelayServer(port: number): Promise { + try { + await killPortProcess(port) + await new Promise((resolve) => setTimeout(resolve, 500)) + } catch {} +} - if (portTaken) { +async function ensureRelayServer(): Promise { + const serverVersion = await getServerVersion(RELAY_PORT) + + if (serverVersion === VERSION) { return } - console.error('CDP relay server not running, starting it...') + if (serverVersion !== null) { + console.error(`CDP relay server version mismatch (server: ${serverVersion}, mcp: ${VERSION}), restarting...`) + await killRelayServer(RELAY_PORT) + } else { + console.error('CDP relay server not running, starting it...') + } const scriptPath = require.resolve('../dist/start-relay-server.js') @@ -194,8 +211,8 @@ async function ensureRelayServer(): Promise { for (let i = 0; i < 10; i++) { await new Promise((resolve) => setTimeout(resolve, 500)) - const isRunning = await isPortTaken(RELAY_PORT) - if (isRunning) { + const newVersion = await getServerVersion(RELAY_PORT) + if (newVersion === VERSION) { console.error('CDP relay server started successfully') return } @@ -622,9 +639,7 @@ server.tool( timeout, displayErrors: true, }), - new Promise((_, reject) => - setTimeout(() => reject(new CodeExecutionTimeoutError(timeout)), timeout), - ), + new Promise((_, reject) => setTimeout(() => reject(new CodeExecutionTimeoutError(timeout)), timeout)), ]) let responseText = formatConsoleLogs(consoleLogs) diff --git a/playwriter/src/snapshots/shadcn-ui-accessibility.md b/playwriter/src/snapshots/shadcn-ui-accessibility.md index f0c9c50..a615484 100644 --- a/playwriter/src/snapshots/shadcn-ui-accessibility.md +++ b/playwriter/src/snapshots/shadcn-ui-accessibility.md @@ -69,76 +69,76 @@ Return value: - generic [ref=e50]: Theme - combobox "Theme" [ref=e51]: - generic [ref=e52]: "Theme:" - - generic: Neutral - img - - button "Copy Code" [ref=e53]: + - combobox [ref=e53] + - button "Copy Code" [ref=e54]: - img - - generic [ref=e54]: Copy Code - - generic [ref=e58]: - - generic [ref=e62]: - - group "Payment Method" [ref=e63]: - - generic [ref=e64]: Payment Method - - paragraph [ref=e65]: All transactions are secure and encrypted - - generic [ref=e66]: - - group [ref=e67]: - - generic [ref=e68]: Name on Card - - textbox "Name on Card" [ref=e69]: + - generic [ref=e55]: Copy Code + - generic [ref=e59]: + - generic [ref=e63]: + - group "Payment Method" [ref=e64]: + - generic [ref=e65]: Payment Method + - paragraph [ref=e66]: All transactions are secure and encrypted + - generic [ref=e67]: + - group [ref=e68]: + - generic [ref=e69]: Name on Card + - textbox "Name on Card" [ref=e70]: - /placeholder: John Doe - - generic [ref=e70]: - - group [ref=e71]: - - generic [ref=e72]: Card Number - - textbox "Card Number" [ref=e73]: + - generic [ref=e71]: + - group [ref=e72]: + - generic [ref=e73]: Card Number + - textbox "Card Number" [ref=e74]: - /placeholder: 1234 5678 9012 3456 - - paragraph [ref=e74]: Enter your 16-digit number. - - group [ref=e75]: - - generic [ref=e76]: CVV - - textbox "CVV" [ref=e77]: + - paragraph [ref=e75]: Enter your 16-digit number. + - group [ref=e76]: + - generic [ref=e77]: CVV + - textbox "CVV" [ref=e78]: - /placeholder: "123" - - generic [ref=e78]: - - group [ref=e79]: - - generic [ref=e80]: Month - - combobox "Month" [ref=e81]: + - generic [ref=e79]: + - group [ref=e80]: + - generic [ref=e81]: Month + - combobox "Month" [ref=e82]: - generic: MM - img - - combobox [ref=e82] - - group [ref=e83]: - - generic [ref=e84]: Year - - combobox "Year" [ref=e85]: + - combobox [ref=e83] + - group [ref=e84]: + - generic [ref=e85]: Year + - combobox "Year" [ref=e86]: - generic: YYYY - img - - combobox [ref=e86] - - group "Billing Address" [ref=e88]: - - generic [ref=e89]: Billing Address - - paragraph [ref=e90]: The billing address associated with your payment method - - group [ref=e92]: - - checkbox "Same as shipping address" [checked] [ref=e93]: + - combobox [ref=e87] + - group "Billing Address" [ref=e89]: + - generic [ref=e90]: Billing Address + - paragraph [ref=e91]: The billing address associated with your payment method + - group [ref=e93]: + - checkbox "Same as shipping address" [checked] [ref=e94]: - generic: - img - checkbox [checked] - - generic [ref=e94]: Same as shipping address - - group [ref=e96]: - - group [ref=e98]: - - generic [ref=e99]: Comments - - textbox "Comments" [ref=e100]: + - generic [ref=e95]: Same as shipping address + - group [ref=e97]: + - group [ref=e99]: + - generic [ref=e100]: Comments + - textbox "Comments" [ref=e101]: - /placeholder: Add any additional comments - - group [ref=e101]: - - button "Submit" [ref=e102] - - button "Cancel" [ref=e103] - - generic [ref=e104]: - - generic [ref=e105]: - - generic [ref=e106]: - - generic [ref=e108]: - - img "@shadcn" [ref=e110] - - img "@maxleiter" [ref=e112] - - img "@evilrabbit" [ref=e114] - - generic [ref=e115]: No Team Members - - generic [ref=e116]: Invite your team to collaborate on this project. - - button "Invite Members" [ref=e118]: + - group [ref=e102]: + - button "Submit" [ref=e103] + - button "Cancel" [ref=e104] + - generic [ref=e105]: + - generic [ref=e106]: + - generic [ref=e107]: + - generic [ref=e109]: + - generic [ref=e111]: CN + - generic [ref=e113]: LR + - generic [ref=e115]: ER + - generic [ref=e116]: No Team Members + - generic [ref=e117]: Invite your team to collaborate on this project. + - button "Invite Members" [ref=e119]: - img - text: Invite Members - - generic [ref=e119]: - - generic [ref=e120]: + - generic [ref=e120]: + - generic [ref=e121]: - status "Loading" - + - tex [Truncated to 6000 characters. Better manage your logs or paginate them to read the full logs] \ No newline at end of file diff --git a/playwriter/src/utils.ts b/playwriter/src/utils.ts index a3753ee..00f85ea 100644 --- a/playwriter/src/utils.ts +++ b/playwriter/src/utils.ts @@ -1,22 +1,14 @@ import fs from 'node:fs' import os from 'node:os' import path from 'node:path' +import { fileURLToPath } from 'node:url' export function getCdpUrl({ port = 19988, host = '127.0.0.1' }: { port?: number; host?: string } = {}) { const id = `${Math.random().toString(36).substring(2, 15)}_${Date.now()}` return `ws://${host}:${port}/cdp/${id}` } -function getLogFilePath(): string { - if (process.env.PLAYWRITER_LOG_PATH) { - return process.env.PLAYWRITER_LOG_PATH - } - const logsDir = path.join(os.tmpdir(), 'playwriter') - if (!fs.existsSync(logsDir)) { - fs.mkdirSync(logsDir, { recursive: true }) - } - const timestamp = new Date().toISOString().replace(/[:.]/g, '-') - return path.join(logsDir, `relay-server-${timestamp}.log`) -} +export const LOG_FILE_PATH = path.join(os.tmpdir(), 'playwriter', 'relay-server.log') -export const LOG_FILE_PATH = getLogFilePath() +const packageJsonPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'package.json') +export const VERSION = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')).version as string diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9455178..cdfeaea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,6 +81,9 @@ importers: hono: specifier: ^4.10.6 version: 4.10.6 + kill-port-process: + specifier: ^3.2.1 + version: 3.2.1 playwright-core: specifier: ^1.56.1 version: 1.56.1 @@ -1204,6 +1207,9 @@ packages: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} + cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1409,6 +1415,10 @@ packages: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} engines: {node: '>=18.0.0'} + execa@0.9.0: + resolution: {integrity: sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA==} + engines: {node: '>=4'} + expect-type@1.2.2: resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} engines: {node: '>=12.0.0'} @@ -1561,10 +1571,17 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} + get-stream@3.0.0: + resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} + engines: {node: '>=4'} + get-stream@5.2.0: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} engines: {node: '>=8'} + get-them-args@1.3.2: + resolution: {integrity: sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==} + get-tsconfig@4.13.0: resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} @@ -1711,6 +1728,10 @@ packages: is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + is-subdir@1.2.0: resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} engines: {node: '>=4'} @@ -1767,6 +1788,11 @@ packages: jws@4.0.1: resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + kill-port-process@3.2.1: + resolution: {integrity: sha512-9rRL5uivhIaW82ES0xTeciG5dfHUVQ0MqUycyf6Y1GBzDNB/fHxKStFUqnL4hCwGp89AcrKIjJWEVZHhSUi9LQ==} + engines: {node: '>=14'} + hasBin: true + langsmith@0.3.82: resolution: {integrity: sha512-RTcxtRm0zp2lV+pMesMW7EZSsIlqN7OmR2F6sZ/sOFQwmcLVl+VErMPV4VkX4Sycs4/EIAFT5hpr36EqiHoikQ==} peerDependencies: @@ -1807,6 +1833,9 @@ packages: resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} engines: {node: 20 || >=22} + lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + lru-cache@7.18.3: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} @@ -1924,6 +1953,10 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + npm-run-path@2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -2034,6 +2067,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2066,6 +2103,10 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + pid-from-port@1.1.3: + resolution: {integrity: sha512-OlE82n3yMOE5dY9RMOwxhoWefeMlxwk5IVxoj0sSzSFIlmvhN4obzTvO3s/d/b5JhcgXikjaspsy/HuUDTqbBg==} + engines: {node: '>=4'} + pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -2138,6 +2179,9 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + pump@3.0.3: resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} @@ -2260,10 +2304,18 @@ packages: setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} + shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} @@ -2291,6 +2343,9 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -2383,6 +2438,10 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} + strip-eof@1.0.0: + resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} + engines: {node: '>=0.10.0'} + strip-json-comments@5.0.3: resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} engines: {node: '>=14.16'} @@ -2674,6 +2733,10 @@ packages: whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -2718,6 +2781,9 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -3892,6 +3958,12 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 + cross-spawn@5.1.0: + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -4118,6 +4190,16 @@ snapshots: dependencies: eventsource-parser: 3.0.6 + execa@0.9.0: + dependencies: + cross-spawn: 5.1.0 + get-stream: 3.0.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + expect-type@1.2.2: {} express-rate-limit@7.5.1(express@5.1.0): @@ -4322,11 +4404,15 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-stream@3.0.0: {} + get-stream@5.2.0: dependencies: pump: 3.0.3 optional: true + get-them-args@1.3.2: {} + get-tsconfig@4.13.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -4481,6 +4567,8 @@ snapshots: is-promise@4.0.0: {} + is-stream@1.1.0: {} + is-subdir@1.2.0: dependencies: better-path-resolve: 1.0.0 @@ -4562,6 +4650,11 @@ snapshots: jwa: 2.0.1 safe-buffer: 5.2.1 + kill-port-process@3.2.1: + dependencies: + get-them-args: 1.3.2 + pid-from-port: 1.1.3 + langsmith@0.3.82(@opentelemetry/api@1.9.0)(openai@4.104.0(ws@8.18.3(bufferutil@4.0.9))(zod@3.25.76)): dependencies: '@types/uuid': 10.0.0 @@ -4597,6 +4690,11 @@ snapshots: lru-cache@11.2.2: optional: true + lru-cache@4.1.5: + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + lru-cache@7.18.3: optional: true @@ -4678,6 +4776,10 @@ snapshots: normalize-path@3.0.0: {} + npm-run-path@2.0.2: + dependencies: + path-key: 2.0.1 + object-assign@4.1.1: {} object-inspect@1.13.4: {} @@ -4788,6 +4890,8 @@ snapshots: path-exists@4.0.0: {} + path-key@2.0.1: {} + path-key@3.1.1: {} path-scurry@1.11.1: @@ -4810,6 +4914,10 @@ snapshots: picomatch@4.0.3: {} + pid-from-port@1.1.3: + dependencies: + execa: 0.9.0 + pify@4.0.1: {} pino-abstract-transport@2.0.0: @@ -4901,6 +5009,8 @@ snapshots: proxy-from-env@1.1.0: optional: true + pseudomap@1.0.2: {} + pump@3.0.3: dependencies: end-of-stream: 1.4.5 @@ -5063,10 +5173,16 @@ snapshots: setprototypeof@1.2.0: {} + shebang-command@1.2.0: + dependencies: + shebang-regex: 1.0.0 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 + shebang-regex@1.0.0: {} + shebang-regex@3.0.0: {} shell-quote@1.8.3: {} @@ -5101,6 +5217,8 @@ snapshots: siginfo@2.0.0: {} + signal-exit@3.0.7: {} + signal-exit@4.1.0: {} simple-wcswidth@1.1.2: {} @@ -5193,6 +5311,8 @@ snapshots: strip-bom@3.0.0: {} + strip-eof@1.0.0: {} + strip-json-comments@5.0.3: {} supports-color@7.2.0: @@ -5462,6 +5582,10 @@ snapshots: tr46: 0.0.3 webidl-conversions: 3.0.1 + which@1.3.1: + dependencies: + isexe: 2.0.0 + which@2.0.2: dependencies: isexe: 2.0.0 @@ -5497,6 +5621,8 @@ snapshots: y18n@5.0.8: {} + yallist@2.1.2: {} + yargs-parser@21.1.1: {} yargs@17.7.2: