release: playwriter@0.0.58

This commit is contained in:
Tommy D. Rossi
2026-02-11 16:51:47 +01:00
parent e9e9c2de08
commit b60bbdd052
8 changed files with 198 additions and 139 deletions
+11
View File
@@ -1,5 +1,16 @@
# Changelog # Changelog
## 0.0.58
### Bug Fixes
- **Fix `bunx playwriter@latest` relay restarts**: Replaced `kill-port-process` with a vendored cross-platform port killer to avoid runtime crashes during version-mismatch restart flows.
- **Harden relay port cleanup behavior**: Unified relay/test/serve port termination through local `killPortProcess({ port })` helper with Windows/macOS/Linux support.
### Internal
- **Removed `kill-port-process` dependency**: Dropped external dependency and updated lockfile to reduce transitive process-management packages.
## 0.0.57 ## 0.0.57
### Features ### Features
+2 -3
View File
@@ -1,7 +1,7 @@
{ {
"name": "playwriter", "name": "playwriter",
"description": "", "description": "",
"version": "0.0.57", "version": "0.0.58",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
@@ -46,14 +46,13 @@
"@hono/node-ws": "^1.2.0", "@hono/node-ws": "^1.2.0",
"@modelcontextprotocol/sdk": "^1.25.2", "@modelcontextprotocol/sdk": "^1.25.2",
"@xmorse/cac": "^6.0.7", "@xmorse/cac": "^6.0.7",
"@xmorse/playwright-core": "workspace:*",
"acorn": "^8.15.0", "acorn": "^8.15.0",
"async-sema": "^3.1.1", "async-sema": "^3.1.1",
"diff": "^8.0.2", "diff": "^8.0.2",
"dom-accessibility-api": "^0.7.1", "dom-accessibility-api": "^0.7.1",
"hono": "^4.10.6", "hono": "^4.10.6",
"kill-port-process": "^3.2.1",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
"@xmorse/playwright-core": "workspace:*",
"posthtml": "^0.16.7", "posthtml": "^0.16.7",
"posthtml-beautify": "^0.7.0", "posthtml-beautify": "^0.7.0",
"string-dedent": "^3.0.2", "string-dedent": "^3.0.2",
+2 -2
View File
@@ -4,6 +4,7 @@ import fs from 'node:fs'
import path from 'node:path' import path from 'node:path'
import { fileURLToPath } from 'node:url' import { fileURLToPath } from 'node:url'
import { cac } from '@xmorse/cac' import { cac } from '@xmorse/cac'
import { killPortProcess } from './kill-port.js'
import { VERSION, LOG_FILE_PATH, LOG_CDP_FILE_PATH } from './utils.js' import { VERSION, LOG_FILE_PATH, LOG_CDP_FILE_PATH } from './utils.js'
import { ensureRelayServer, RELAY_PORT, waitForExtension } from './relay-client.js' import { ensureRelayServer, RELAY_PORT, waitForExtension } from './relay-client.js'
@@ -433,8 +434,7 @@ cli
// Kill existing process on the port // Kill existing process on the port
console.log(`Killing existing server on port ${RELAY_PORT}...`) console.log(`Killing existing server on port ${RELAY_PORT}...`)
const { killPortProcess } = await import('kill-port-process') await killPortProcess({ port: RELAY_PORT })
await killPortProcess(RELAY_PORT)
} }
// Lazy-load heavy dependencies only when serve command is used // Lazy-load heavy dependencies only when serve command is used
+167
View File
@@ -0,0 +1,167 @@
/**
* Cross-platform process termination for a TCP port.
* Replaces external kill-port-process dependency for bunx/runtime stability.
*/
import { execFile } from 'node:child_process'
import os from 'node:os'
import { promisify } from 'node:util'
const execFileAsync = promisify(execFile)
function isValidPort(port: number): boolean {
return Number.isInteger(port) && port > 0 && port <= 65535
}
function parsePids(output: string): number[] {
const pids = output
.split(/\r?\n/g)
.map((line) => {
return line.trim()
})
.filter((line) => {
return Boolean(line)
})
.map((line) => {
return Number(line)
})
.filter((pid) => {
return Number.isInteger(pid) && pid > 0
})
return [...new Set(pids)]
}
function parseWindowsNetstatPids(output: string, port: number): number[] {
const rows = output
.split(/\r?\n/g)
.map((line) => {
return line.trim()
})
.filter((line) => {
return line.startsWith('TCP')
})
const pids = rows
.map((row) => {
const columns = row.split(/\s+/g)
const localAddress = columns[1] || ''
const state = columns[3] || ''
const pid = columns[4] || ''
const endsWithPort = localAddress.endsWith(`:${port}`)
if (!endsWithPort || state !== 'LISTENING') {
return NaN
}
return Number(pid)
})
.filter((pid) => {
return Number.isInteger(pid) && pid > 0
})
return [...new Set(pids)]
}
async function getPidsForPortWindows(port: number): Promise<number[]> {
const powerShellScript = [
"$ErrorActionPreference='SilentlyContinue'",
`@(Get-NetTCPConnection -LocalPort ${port} -State Listen | Select-Object -ExpandProperty OwningProcess -Unique) -join [Environment]::NewLine`,
].join('; ')
try {
const { stdout } = await execFileAsync('powershell', ['-NoProfile', '-Command', powerShellScript])
const pids = parsePids(stdout)
if (pids.length > 0) {
return pids
}
} catch {}
try {
const { stdout } = await execFileAsync('cmd', ['/d', '/s', '/c', 'netstat -ano -p tcp'])
return parseWindowsNetstatPids(stdout, port)
} catch {
return []
}
}
async function getPidsForPortUnix(port: number): Promise<number[]> {
try {
const { stdout } = await execFileAsync('lsof', ['-nP', '-iTCP:' + String(port), '-sTCP:LISTEN', '-t'])
const pids = parsePids(stdout)
if (pids.length > 0) {
return pids
}
} catch {}
try {
const { stdout } = await execFileAsync('fuser', [`${port}/tcp`])
return parsePids(stdout)
} catch {
return []
}
}
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}
function isProcessAlive(pid: number): boolean {
try {
process.kill(pid, 0)
return true
} catch {
return false
}
}
async function terminatePidWindows(pid: number): Promise<void> {
try {
await execFileAsync('taskkill', ['/PID', String(pid), '/T', '/F'])
} catch {}
}
async function terminatePidUnix(pid: number): Promise<void> {
try {
process.kill(pid, 'SIGTERM')
} catch {
return
}
await sleep(200)
if (!isProcessAlive(pid)) {
return
}
try {
process.kill(pid, 'SIGKILL')
} catch {}
}
/**
* Kill any listening process bound to the provided TCP port.
*/
export async function killPortProcess({ port }: { port: number }): Promise<void> {
if (!isValidPort(port)) {
throw new Error(`Invalid port: ${port}`)
}
const pids = os.platform() === 'win32'
? await getPidsForPortWindows(port)
: await getPidsForPortUnix(port)
const currentPid = process.pid
const targetPids = pids.filter((pid) => {
return pid !== currentPid
})
await Promise.all(
targetPids.map(async (pid) => {
if (os.platform() === 'win32') {
await terminatePidWindows(pid)
return
}
await terminatePidUnix(pid)
}),
)
}
+2 -2
View File
@@ -6,8 +6,8 @@
import { spawn } from 'node:child_process' import { spawn } from 'node:child_process'
import path from 'node:path' import path from 'node:path'
import { fileURLToPath } from 'node:url' import { fileURLToPath } from 'node:url'
import { killPortProcess } from 'kill-port-process'
import pc from 'picocolors' import pc from 'picocolors'
import { killPortProcess } from './kill-port.js'
import { VERSION, sleep, LOG_FILE_PATH } from './utils.js' import { VERSION, sleep, LOG_FILE_PATH } from './utils.js'
const __filename = fileURLToPath(import.meta.url) const __filename = fileURLToPath(import.meta.url)
@@ -73,7 +73,7 @@ export async function waitForExtension(options: {
async function killRelayServer(port: number): Promise<void> { async function killRelayServer(port: number): Promise<void> {
try { try {
await killPortProcess(port) await killPortProcess({ port })
await sleep(500) await sleep(500)
} catch {} } catch {}
} }
+2 -2
View File
@@ -8,7 +8,7 @@ import fs from 'node:fs'
import os from 'node:os' import os from 'node:os'
import { startPlayWriterCDPRelayServer, type RelayServer } from './cdp-relay.js' import { startPlayWriterCDPRelayServer, type RelayServer } from './cdp-relay.js'
import { createFileLogger } from './create-logger.js' import { createFileLogger } from './create-logger.js'
import { killPortProcess } from 'kill-port-process' import { killPortProcess } from './kill-port.js'
const execAsync = promisify(exec) const execAsync = promisify(exec)
const extensionBuildQueues: Map<string, Promise<void>> = new Map() const extensionBuildQueues: Map<string, Promise<void>> = new Map()
@@ -67,7 +67,7 @@ export async function setupTestContext({
/** Create initial page and toggle extension on it */ /** Create initial page and toggle extension on it */
toggleExtension?: boolean toggleExtension?: boolean
}): Promise<TestContext> { }): Promise<TestContext> {
await killPortProcess(port).catch(() => {}) await killPortProcess({ port }).catch(() => {})
// Use a port-scoped dist folder so parallel tests don't replace each other's extension builds. // Use a port-scoped dist folder so parallel tests don't replace each other's extension builds.
const distDir = `dist-${port}` const distDir = `dist-${port}`
+2 -2
View File
@@ -2,14 +2,14 @@
import { describe, it, expect, afterEach } from 'vitest' import { describe, it, expect, afterEach } from 'vitest'
import { startPlayWriterCDPRelayServer } from '../src/cdp-relay.js' import { startPlayWriterCDPRelayServer } from '../src/cdp-relay.js'
import { WebSocket } from 'ws' import { WebSocket } from 'ws'
import { killPortProcess } from 'kill-port-process'
import { createFileLogger } from '../src/create-logger.js' import { createFileLogger } from '../src/create-logger.js'
import { killPortProcess } from '../src/kill-port.js'
const TEST_PORT = 19999 const TEST_PORT = 19999
async function killProcessOnPort(port: number): Promise<void> { async function killProcessOnPort(port: number): Promise<void> {
try { try {
await killPortProcess(port) await killPortProcess({ port })
} catch (err) { } catch (err) {
// Ignore if no process is running // Ignore if no process is running
} }
+10 -128
View File
@@ -332,9 +332,6 @@ importers:
hono: hono:
specifier: ^4.10.6 specifier: ^4.10.6
version: 4.10.6 version: 4.10.6
kill-port-process:
specifier: ^3.2.1
version: 3.2.1
picocolors: picocolors:
specifier: ^1.1.1 specifier: ^1.1.1
version: 1.1.1 version: 1.1.1
@@ -3489,9 +3486,6 @@ packages:
engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
hasBin: true hasBin: true
cross-spawn@5.1.0:
resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==}
cross-spawn@7.0.6: cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@@ -3978,10 +3972,6 @@ packages:
resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==}
engines: {node: '>=18.0.0'} engines: {node: '>=18.0.0'}
execa@0.9.0:
resolution: {integrity: sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA==}
engines: {node: '>=4'}
exit-hook@2.2.1: exit-hook@2.2.1:
resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -4227,10 +4217,6 @@ packages:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
get-stream@3.0.0:
resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
engines: {node: '>=4'}
get-stream@5.2.0: get-stream@5.2.0:
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -4243,9 +4229,6 @@ packages:
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
get-them-args@1.3.2:
resolution: {integrity: sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==}
get-tsconfig@4.13.0: get-tsconfig@4.13.0:
resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}
@@ -4573,10 +4556,6 @@ packages:
resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
is-stream@1.1.0:
resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==}
engines: {node: '>=0.10.0'}
is-stream@4.0.1: is-stream@4.0.1:
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -4743,11 +4722,6 @@ packages:
keyv@4.5.4: keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
kill-port-process@3.2.1:
resolution: {integrity: sha512-9rRL5uivhIaW82ES0xTeciG5dfHUVQ0MqUycyf6Y1GBzDNB/fHxKStFUqnL4hCwGp89AcrKIjJWEVZHhSUi9LQ==}
engines: {node: '>=14'}
hasBin: true
langsmith@0.3.82: langsmith@0.3.82:
resolution: {integrity: sha512-RTcxtRm0zp2lV+pMesMW7EZSsIlqN7OmR2F6sZ/sOFQwmcLVl+VErMPV4VkX4Sycs4/EIAFT5hpr36EqiHoikQ==} resolution: {integrity: sha512-RTcxtRm0zp2lV+pMesMW7EZSsIlqN7OmR2F6sZ/sOFQwmcLVl+VErMPV4VkX4Sycs4/EIAFT5hpr36EqiHoikQ==}
peerDependencies: peerDependencies:
@@ -4882,9 +4856,6 @@ packages:
resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==} resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==}
engines: {node: 20 || >=22} engines: {node: 20 || >=22}
lru-cache@4.1.5:
resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==}
lru-cache@5.1.1: lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
@@ -5114,10 +5085,6 @@ packages:
npm-normalize-package-bin@1.0.1: npm-normalize-package-bin@1.0.1:
resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==} resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==}
npm-run-path@2.0.2:
resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==}
engines: {node: '>=4'}
object-assign@4.1.1: object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -5322,10 +5289,6 @@ packages:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
path-key@2.0.1:
resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==}
engines: {node: '>=4'}
path-key@3.1.1: path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -5378,10 +5341,6 @@ packages:
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
engines: {node: '>=12'} engines: {node: '>=12'}
pid-from-port@1.1.3:
resolution: {integrity: sha512-OlE82n3yMOE5dY9RMOwxhoWefeMlxwk5IVxoj0sSzSFIlmvhN4obzTvO3s/d/b5JhcgXikjaspsy/HuUDTqbBg==}
engines: {node: '>=4'}
pify@4.0.1: pify@4.0.1:
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -5523,9 +5482,6 @@ packages:
proxy-from-env@1.1.0: proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
pseudomap@1.0.2:
resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
pump@3.0.3: pump@3.0.3:
resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==}
@@ -5821,18 +5777,10 @@ packages:
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
shebang-command@1.2.0:
resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==}
engines: {node: '>=0.10.0'}
shebang-command@2.0.0: shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'} engines: {node: '>=8'}
shebang-regex@1.0.0:
resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==}
engines: {node: '>=0.10.0'}
shebang-regex@3.0.0: shebang-regex@3.0.0:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -5863,9 +5811,6 @@ packages:
siginfo@2.0.0: siginfo@2.0.0:
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
signal-exit@3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
signal-exit@4.1.0: signal-exit@4.1.0:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'} engines: {node: '>=14'}
@@ -6010,10 +5955,6 @@ packages:
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'} engines: {node: '>=4'}
strip-eof@1.0.0:
resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==}
engines: {node: '>=0.10.0'}
strip-json-comments@3.1.1: strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -6625,10 +6566,6 @@ packages:
resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
which@1.3.1:
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
hasBin: true
which@2.0.2: which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@@ -6713,9 +6650,6 @@ packages:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'} engines: {node: '>=10'}
yallist@2.1.2:
resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==}
yallist@3.1.1: yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
@@ -9530,6 +9464,14 @@ snapshots:
optionalDependencies: optionalDependencies:
vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0) vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0)
'@vitest/mocker@4.0.8(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0))':
dependencies:
'@vitest/spy': 4.0.8
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
vite: 7.2.2(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0)
'@vitest/mocker@4.0.8(vite@7.2.2(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0))': '@vitest/mocker@4.0.8(vite@7.2.2(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0))':
dependencies: dependencies:
'@vitest/spy': 4.0.8 '@vitest/spy': 4.0.8
@@ -9581,7 +9523,7 @@ snapshots:
sirv: 3.0.2 sirv: 3.0.2
tinyglobby: 0.2.15 tinyglobby: 0.2.15
tinyrainbow: 3.0.3 tinyrainbow: 3.0.3
vitest: 4.0.8(@types/node@25.2.0)(@vitest/ui@4.0.8)(jiti@2.6.1)(jsdom@27.2.0(bufferutil@4.0.9))(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0) vitest: 4.0.8(@types/node@24.10.1)(@vitest/ui@4.0.8)(jiti@2.6.1)(jsdom@27.2.0(bufferutil@4.0.9))(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0)
'@vitest/utils@4.0.16': '@vitest/utils@4.0.16':
dependencies: dependencies:
@@ -10189,12 +10131,6 @@ snapshots:
dependencies: dependencies:
cross-spawn: 7.0.6 cross-spawn: 7.0.6
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: cross-spawn@7.0.6:
dependencies: dependencies:
path-key: 3.1.1 path-key: 3.1.1
@@ -10831,16 +10767,6 @@ snapshots:
dependencies: dependencies:
eventsource-parser: 3.0.6 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
exit-hook@2.2.1: {} exit-hook@2.2.1: {}
expect-type@1.2.2: {} expect-type@1.2.2: {}
@@ -11182,8 +11108,6 @@ snapshots:
dunder-proto: 1.0.1 dunder-proto: 1.0.1
es-object-atoms: 1.1.1 es-object-atoms: 1.1.1
get-stream@3.0.0: {}
get-stream@5.2.0: get-stream@5.2.0:
dependencies: dependencies:
pump: 3.0.3 pump: 3.0.3
@@ -11199,8 +11123,6 @@ snapshots:
es-errors: 1.3.0 es-errors: 1.3.0
get-intrinsic: 1.3.0 get-intrinsic: 1.3.0
get-them-args@1.3.2: {}
get-tsconfig@4.13.0: get-tsconfig@4.13.0:
dependencies: dependencies:
resolve-pkg-maps: 1.0.0 resolve-pkg-maps: 1.0.0
@@ -11580,8 +11502,6 @@ snapshots:
dependencies: dependencies:
call-bound: 1.0.4 call-bound: 1.0.4
is-stream@1.1.0: {}
is-stream@4.0.1: {} is-stream@4.0.1: {}
is-string@1.1.1: is-string@1.1.1:
@@ -11768,11 +11688,6 @@ snapshots:
dependencies: dependencies:
json-buffer: 3.0.1 json-buffer: 3.0.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)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@4.104.0(ws@8.19.0(bufferutil@4.0.9))(zod@4.3.5)): langsmith@0.3.82(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@4.104.0(ws@8.19.0(bufferutil@4.0.9))(zod@4.3.5)):
dependencies: dependencies:
'@types/uuid': 10.0.0 '@types/uuid': 10.0.0
@@ -11892,11 +11807,6 @@ snapshots:
lru-cache@11.2.5: lru-cache@11.2.5:
optional: true optional: true
lru-cache@4.1.5:
dependencies:
pseudomap: 1.0.2
yallist: 2.1.2
lru-cache@5.1.1: lru-cache@5.1.1:
dependencies: dependencies:
yallist: 3.1.1 yallist: 3.1.1
@@ -12068,10 +11978,6 @@ snapshots:
npm-normalize-package-bin@1.0.1: {} npm-normalize-package-bin@1.0.1: {}
npm-run-path@2.0.2:
dependencies:
path-key: 2.0.1
object-assign@4.1.1: {} object-assign@4.1.1: {}
object-inspect@1.13.4: {} object-inspect@1.13.4: {}
@@ -12301,8 +12207,6 @@ snapshots:
path-is-absolute@1.0.1: {} path-is-absolute@1.0.1: {}
path-key@2.0.1: {}
path-key@3.1.1: {} path-key@3.1.1: {}
path-parse@1.0.7: {} path-parse@1.0.7: {}
@@ -12342,10 +12246,6 @@ snapshots:
picomatch@4.0.3: {} picomatch@4.0.3: {}
pid-from-port@1.1.3:
dependencies:
execa: 0.9.0
pify@4.0.1: {} pify@4.0.1: {}
pino-abstract-transport@2.0.0: pino-abstract-transport@2.0.0:
@@ -12500,8 +12400,6 @@ snapshots:
proxy-from-env@1.1.0: {} proxy-from-env@1.1.0: {}
pseudomap@1.0.2: {}
pump@3.0.3: pump@3.0.3:
dependencies: dependencies:
end-of-stream: 1.4.5 end-of-stream: 1.4.5
@@ -12952,16 +12850,10 @@ snapshots:
'@img/sharp-win32-x64': 0.34.5 '@img/sharp-win32-x64': 0.34.5
optional: true optional: true
shebang-command@1.2.0:
dependencies:
shebang-regex: 1.0.0
shebang-command@2.0.0: shebang-command@2.0.0:
dependencies: dependencies:
shebang-regex: 3.0.0 shebang-regex: 3.0.0
shebang-regex@1.0.0: {}
shebang-regex@3.0.0: {} shebang-regex@3.0.0: {}
shell-quote@1.8.3: {} shell-quote@1.8.3: {}
@@ -12998,8 +12890,6 @@ snapshots:
siginfo@2.0.0: {} siginfo@2.0.0: {}
signal-exit@3.0.7: {}
signal-exit@4.1.0: {} signal-exit@4.1.0: {}
simple-wcswidth@1.1.2: {} simple-wcswidth@1.1.2: {}
@@ -13175,8 +13065,6 @@ snapshots:
strip-bom@3.0.0: {} strip-bom@3.0.0: {}
strip-eof@1.0.0: {}
strip-json-comments@3.1.1: {} strip-json-comments@3.1.1: {}
strip-json-comments@5.0.3: {} strip-json-comments@5.0.3: {}
@@ -13670,7 +13558,7 @@ snapshots:
vitest@4.0.8(@types/node@24.10.1)(@vitest/ui@4.0.8)(jiti@2.6.1)(jsdom@27.2.0(bufferutil@4.0.9))(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0): vitest@4.0.8(@types/node@24.10.1)(@vitest/ui@4.0.8)(jiti@2.6.1)(jsdom@27.2.0(bufferutil@4.0.9))(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0):
dependencies: dependencies:
'@vitest/expect': 4.0.8 '@vitest/expect': 4.0.8
'@vitest/mocker': 4.0.8(vite@7.2.2(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0)) '@vitest/mocker': 4.0.8(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.6.0))
'@vitest/pretty-format': 4.0.8 '@vitest/pretty-format': 4.0.8
'@vitest/runner': 4.0.8 '@vitest/runner': 4.0.8
'@vitest/snapshot': 4.0.8 '@vitest/snapshot': 4.0.8
@@ -13826,10 +13714,6 @@ snapshots:
gopd: 1.2.0 gopd: 1.2.0
has-tostringtag: 1.0.2 has-tostringtag: 1.0.2
which@1.3.1:
dependencies:
isexe: 2.0.0
which@2.0.2: which@2.0.2:
dependencies: dependencies:
isexe: 2.0.0 isexe: 2.0.0
@@ -13884,8 +13768,6 @@ snapshots:
y18n@5.0.8: {} y18n@5.0.8: {}
yallist@2.1.2: {}
yallist@3.1.1: {} yallist@3.1.1: {}
yaml@2.6.0: {} yaml@2.6.0: {}