mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
node dependency updates (#2259)
chore: node dependency updates (#2259 — thanks @backryun)
This commit is contained in:
10
.env.example
10
.env.example
@@ -92,7 +92,7 @@ OMNIROUTE_USE_TURBOPACK=1
|
||||
# OMNIROUTE_PORT=20128
|
||||
|
||||
# Hostname/bind address for the Next.js server.
|
||||
# Used by: scripts/run-next.mjs (HOST), Playwright runner (HOSTNAME).
|
||||
# Used by: scripts/dev/run-next.mjs (HOST), Playwright runner (HOSTNAME).
|
||||
# Default: 0.0.0.0 (HOST) / 127.0.0.1 (HOSTNAME inside tests).
|
||||
#HOST=0.0.0.0
|
||||
#HOSTNAME=127.0.0.1
|
||||
@@ -955,7 +955,7 @@ APP_LOG_TO_FILE=true
|
||||
# Used by: open-sse/utils/cursorVersionDetector.ts. Default: probed automatically.
|
||||
# CURSOR_STATE_DB_PATH=
|
||||
|
||||
# Direct Cursor bearer token used by scripts/cursor-tap.cjs (developer tooling).
|
||||
# Direct Cursor bearer token used by scripts/ad-hoc/cursor-tap.cjs (developer tooling).
|
||||
# CURSOR_TOKEN=
|
||||
|
||||
# Log Responses API SSE-to-JSON translation details.
|
||||
@@ -1073,8 +1073,8 @@ APP_LOG_TO_FILE=true
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 25. TEST & E2E
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Used by scripts/run-next-playwright.mjs, scripts/smoke-electron-packaged.mjs,
|
||||
# scripts/run-ecosystem-tests.mjs and scripts/uninstall.mjs.
|
||||
# Used by scripts/dev/run-next-playwright.mjs, scripts/dev/smoke-electron-packaged.mjs,
|
||||
# scripts/dev/run-ecosystem-tests.mjs and scripts/build/uninstall.mjs.
|
||||
# Production deployments should leave every value below unset.
|
||||
|
||||
# E2E bootstrap mode for the Playwright runner. Accepted: auth | fresh | reuse.
|
||||
@@ -1116,7 +1116,7 @@ APP_LOG_TO_FILE=true
|
||||
# Number of parallel translation requests (default 4).
|
||||
# OMNIROUTE_TRANSLATION_CONCURRENCY=4
|
||||
|
||||
# Electron smoke harness (used by scripts/smoke-electron-packaged.mjs).
|
||||
# Electron smoke harness (used by scripts/dev/smoke-electron-packaged.mjs).
|
||||
# ELECTRON_SMOKE_URL=http://127.0.0.1:20128/login
|
||||
# ELECTRON_SMOKE_TIMEOUT_MS=45000
|
||||
# ELECTRON_SMOKE_SETTLE_MS=2000
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -165,7 +165,7 @@ body:
|
||||
description: "Which commands or tests should prove this bug is fixed?"
|
||||
placeholder: |
|
||||
Example:
|
||||
- node --import tsx/esm --test tests/unit/my-file.test.ts
|
||||
- node --import tsx --test tests/unit/my-file.test.ts
|
||||
- npm run test:coverage
|
||||
validations:
|
||||
required: false
|
||||
|
||||
@@ -59,7 +59,7 @@ body:
|
||||
description: "List the commands that must pass before this issue can be closed."
|
||||
placeholder: |
|
||||
Example:
|
||||
- node --import tsx/esm --test tests/unit/my-suite.test.ts
|
||||
- node --import tsx --test tests/unit/my-suite.test.ts
|
||||
- npm run test:coverage
|
||||
validations:
|
||||
required: true
|
||||
|
||||
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@@ -207,7 +207,7 @@ jobs:
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm run check:node-runtime
|
||||
- run: node --import tsx/esm --test --test-concurrency=1 --test-shard=${{ matrix.shard }}/2 tests/unit/*.test.ts
|
||||
- run: node --import tsx --test --test-concurrency=1 --test-shard=${{ matrix.shard }}/2 tests/unit/*.test.ts
|
||||
|
||||
node-24-compat:
|
||||
name: Node 24 Compatibility (${{ matrix.shard }}/2)
|
||||
@@ -231,7 +231,7 @@ jobs:
|
||||
- run: npm ci
|
||||
- run: npm run check:node-runtime
|
||||
- run: npm run build
|
||||
- run: node --import tsx/esm --test --test-concurrency=1 --test-shard=${{ matrix.shard }}/2 tests/unit/*.test.ts
|
||||
- run: node --import tsx --test --test-concurrency=1 --test-shard=${{ matrix.shard }}/2 tests/unit/*.test.ts
|
||||
|
||||
node-26-compat:
|
||||
name: Node 26 Compatibility (${{ matrix.shard }}/2)
|
||||
@@ -255,7 +255,7 @@ jobs:
|
||||
- run: npm ci
|
||||
- run: npm run check:node-runtime
|
||||
- run: npm run build
|
||||
- run: node --import tsx/esm --test --test-concurrency=1 --test-shard=${{ matrix.shard }}/2 tests/unit/*.test.ts
|
||||
- run: node --import tsx --test --test-concurrency=1 --test-shard=${{ matrix.shard }}/2 tests/unit/*.test.ts
|
||||
|
||||
test-coverage:
|
||||
name: Coverage
|
||||
@@ -462,7 +462,7 @@ jobs:
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm run check:node-runtime
|
||||
- run: node --import tsx/esm --test --test-force-exit --test-concurrency=1 --test-shard=${{ matrix.shard }}/2 tests/integration/*.test.ts
|
||||
- run: node --import tsx --test --test-force-exit --test-concurrency=1 --test-shard=${{ matrix.shard }}/2 tests/integration/*.test.ts
|
||||
|
||||
test-security:
|
||||
name: Security Tests
|
||||
|
||||
@@ -360,7 +360,7 @@ async function checkNativeBinary(rootDir) {
|
||||
|
||||
try {
|
||||
const { isNativeBinaryCompatible } = await import(
|
||||
pathToFileURL(path.join(rootDir, "scripts", "native-binary-compat.mjs")).href
|
||||
pathToFileURL(path.join(rootDir, "scripts", "build", "native-binary-compat.mjs")).href
|
||||
);
|
||||
const compatible = isNativeBinaryCompatible(binaryPath);
|
||||
if (!compatible) {
|
||||
|
||||
@@ -37,7 +37,7 @@ export async function startMcpCli(rootDir = ROOT) {
|
||||
}
|
||||
|
||||
// `tsx` loader is only required for local `.ts` fallback; JS entry works without it.
|
||||
const loaderArgs = mcpEntry.endsWith(".ts") ? ["--import", "tsx/esm"] : [];
|
||||
const loaderArgs = mcpEntry.endsWith(".ts") ? ["--import", "tsx"] : [];
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const child = spawn(process.execPath, [...loaderArgs, mcpEntry], {
|
||||
|
||||
@@ -22,7 +22,7 @@ import { existsSync, readFileSync } from "node:fs";
|
||||
import { join, dirname } from "node:path";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import { homedir, platform } from "node:os";
|
||||
import { isNativeBinaryCompatible } from "../scripts/native-binary-compat.mjs";
|
||||
import { isNativeBinaryCompatible } from "../scripts/build/native-binary-compat.mjs";
|
||||
import { getNodeRuntimeSupport, getNodeRuntimeWarning } from "./nodeRuntimeSupport.mjs";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
|
||||
@@ -105,19 +105,19 @@ OmniRoute uses **SQLite** (via `better-sqlite3`) for all persistence. These vari
|
||||
|
||||
## 3. Network & Ports
|
||||
|
||||
| Variable | Default | Source File | Description |
|
||||
| ------------------------- | ------------------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `PORT` | `20128` | `src/lib/runtime/ports.ts` | Primary port for both Dashboard UI and API endpoints (single-port mode). |
|
||||
| `API_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | When set, serves the `/v1/*` proxy API on this separate port. |
|
||||
| `API_HOST` | `0.0.0.0` | `src/lib/runtime/ports.ts` | Bind address for the API port. |
|
||||
| `DASHBOARD_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | When set, serves the Dashboard UI on this separate port. |
|
||||
| `PROD_DASHBOARD_PORT` | `20130` | `docker-compose.prod.yml` | Host-side published port for the Dashboard in Docker production mode. |
|
||||
| `PROD_API_PORT` | `20131` | `docker-compose.prod.yml` | Host-side published port for the API in Docker production mode. |
|
||||
| `OMNIROUTE_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | Takes precedence over `PORT` when running inside Electron or other wrappers. |
|
||||
| `NODE_ENV` | `production` | Next.js core | Controls logging verbosity, caching, error detail exposure, and Next.js optimizations. |
|
||||
| `OMNIROUTE_USE_TURBOPACK` | `1` (default in `.env.example`) | `package.json` / Next.js 16 | Toggles the Next.js 16 Turbopack bundler in `npm run dev` and `npm run build`. Set to `0` on Windows or when running into native binding incompatibilities. |
|
||||
| `HOST` | `0.0.0.0` | `scripts/run-next.mjs` | Bind address for the Next.js dev/start server. Overrides the default `0.0.0.0` when set. |
|
||||
| `HOSTNAME` | `127.0.0.1` | `scripts/run-next-playwright.mjs` | Bind address used by the Playwright runner when launching Next.js. Defaults to `127.0.0.1` for hermetic tests. |
|
||||
| Variable | Default | Source File | Description |
|
||||
| ------------------------- | ------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `PORT` | `20128` | `src/lib/runtime/ports.ts` | Primary port for both Dashboard UI and API endpoints (single-port mode). |
|
||||
| `API_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | When set, serves the `/v1/*` proxy API on this separate port. |
|
||||
| `API_HOST` | `0.0.0.0` | `src/lib/runtime/ports.ts` | Bind address for the API port. |
|
||||
| `DASHBOARD_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | When set, serves the Dashboard UI on this separate port. |
|
||||
| `PROD_DASHBOARD_PORT` | `20130` | `docker-compose.prod.yml` | Host-side published port for the Dashboard in Docker production mode. |
|
||||
| `PROD_API_PORT` | `20131` | `docker-compose.prod.yml` | Host-side published port for the API in Docker production mode. |
|
||||
| `OMNIROUTE_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | Takes precedence over `PORT` when running inside Electron or other wrappers. |
|
||||
| `NODE_ENV` | `production` | Next.js core | Controls logging verbosity, caching, error detail exposure, and Next.js optimizations. |
|
||||
| `OMNIROUTE_USE_TURBOPACK` | `1` (default in `.env.example`) | `package.json` / Next.js 16 | Toggles the Next.js 16 Turbopack bundler in `npm run dev` and `npm run build`. Set to `0` on Windows or when running into native binding incompatibilities. |
|
||||
| `HOST` | `0.0.0.0` | `scripts/dev/run-next.mjs` | Bind address for the Next.js dev/start server. Overrides the default `0.0.0.0` when set. |
|
||||
| `HOSTNAME` | `127.0.0.1` | `scripts/dev/run-next-playwright.mjs` | Bind address used by the Playwright runner when launching Next.js. Defaults to `127.0.0.1` for hermetic tests. |
|
||||
|
||||
### Port Modes
|
||||
|
||||
@@ -666,7 +666,7 @@ Anthropic-compatible provider instead.
|
||||
| `CURSOR_DUMP_FILE` | _(unset)_ | `open-sse/executors/cursor.ts` | Optional file path that receives raw decoded Cursor chunks when `CURSOR_DEBUG=1`. |
|
||||
| `CURSOR_STREAM_TIMEOUT_MS` | `300000` | `open-sse/executors/cursor.ts` | Stream idle timeout (ms) for the Cursor executor. |
|
||||
| `CURSOR_STATE_DB_PATH` | _(probed)_ | `open-sse/utils/cursorVersionDetector.ts` | Override the Cursor state DB lookup used for version detection. |
|
||||
| `CURSOR_TOKEN` | _(unset)_ | `scripts/cursor-tap.cjs` | Direct Cursor bearer token used by developer tooling. |
|
||||
| `CURSOR_TOKEN` | _(unset)_ | `scripts/ad-hoc/cursor-tap.cjs` | Direct Cursor bearer token used by developer tooling. |
|
||||
| `OMNIROUTE_LOG_REQUEST_SHAPE` | enabled (`!== "0"`) | `src/app/api/v1/chat/completions/route.ts` | Log content-type/length markers for large chat payloads. Set `"0"` to silence. |
|
||||
| `DEBUG_RESPONSES_SSE_TO_JSON` | _(unset)_ | `open-sse/handlers/responseTranslator.ts` | Set `true` to log Responses API SSE→JSON translation details. |
|
||||
| `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` | _(unset)_ | E2E test harness | Set `true` to enable E2E test mode (relaxed auth, test hooks). |
|
||||
@@ -794,28 +794,28 @@ Provider quota endpoints, network tunnels (Tailscale, Ngrok, MITM debug proxy),
|
||||
|
||||
## 26. Test & E2E Harness
|
||||
|
||||
Used by `scripts/run-next-playwright.mjs`, `scripts/smoke-electron-packaged.mjs`,
|
||||
`scripts/run-ecosystem-tests.mjs`, and `scripts/uninstall.mjs`. Leave every
|
||||
Used by `scripts/dev/run-next-playwright.mjs`, `scripts/dev/smoke-electron-packaged.mjs`,
|
||||
`scripts/dev/run-ecosystem-tests.mjs`, and `scripts/build/uninstall.mjs`. Leave every
|
||||
value below unset in production deployments.
|
||||
|
||||
| Variable | Default | Source File | Description |
|
||||
| ------------------------------------- | -------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------- |
|
||||
| `OMNIROUTE_E2E_BOOTSTRAP_MODE` | `auth` | `scripts/run-next-playwright.mjs` | E2E bootstrap mode (`auth`, `fresh`, `reuse`) for the Playwright runner. |
|
||||
| `OMNIROUTE_E2E_PASSWORD` | falls back to `INITIAL_PASSWORD` | `scripts/run-next-playwright.mjs` | Admin password injected into the Playwright environment. |
|
||||
| `OMNIROUTE_DISABLE_LOCAL_HEALTHCHECK` | `true` | `scripts/run-next-playwright.mjs` | Disable the local healthcheck poll during Playwright runs. |
|
||||
| `OMNIROUTE_DISABLE_TOKEN_HEALTHCHECK` | `true` | `scripts/run-next-playwright.mjs` | Disable the OAuth token healthcheck loop during tests. |
|
||||
| `OMNIROUTE_HIDE_HEALTHCHECK_LOGS` | `true` | `scripts/run-next-playwright.mjs` | Silence healthcheck noise in Playwright stdout. |
|
||||
| `OMNIROUTE_PLAYWRIGHT_SKIP_BUILD` | `0` | `scripts/run-next-playwright.mjs` | Skip the Next.js production build before Playwright starts (CI optimization). |
|
||||
| `OMNIROUTE_SKIP_UNINSTALL_HOOK` | `0` | `scripts/uninstall.mjs` | Skip the OmniRoute uninstall hook (used by CI to keep `node_modules` intact). |
|
||||
| `ECOSYSTEM_SERVER_WAIT_MS` | `180000` | `scripts/run-ecosystem-tests.mjs` | Wait time (ms) for the server to become healthy before running ecosystem/protocol tests. |
|
||||
| `ELECTRON_SMOKE_URL` | `http://127.0.0.1:20128/login` | `scripts/smoke-electron-packaged.mjs` | URL the Electron smoke harness expects the packaged app to serve. |
|
||||
| `ELECTRON_SMOKE_TIMEOUT_MS` | `45000` | `scripts/smoke-electron-packaged.mjs` | Total timeout (ms) before the smoke harness gives up. |
|
||||
| `ELECTRON_SMOKE_SETTLE_MS` | `2000` | `scripts/smoke-electron-packaged.mjs` | Settle window (ms) after the page loads. |
|
||||
| `ELECTRON_SMOKE_APP_EXECUTABLE` | _(auto)_ | `scripts/smoke-electron-packaged.mjs` | Explicit path to the packaged Electron executable. |
|
||||
| `ELECTRON_SMOKE_DATA_DIR` | _(tmpdir)_ | `scripts/smoke-electron-packaged.mjs` | Data directory for the Electron smoke run. |
|
||||
| `ELECTRON_SMOKE_KEEP_DATA` | `0` | `scripts/smoke-electron-packaged.mjs` | Set `1` to preserve the smoke data directory after the run. |
|
||||
| `ELECTRON_SMOKE_STREAM_LOGS` | `0` | `scripts/smoke-electron-packaged.mjs` | Set `1` to stream Electron logs to stdout during the run. |
|
||||
| `CLI_DEVIN_BIN` | _(PATH lookup)_ | `open-sse/executors/devin-cli.ts` | Override the Devin CLI binary path. |
|
||||
| Variable | Default | Source File | Description |
|
||||
| ------------------------------------- | -------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------- |
|
||||
| `OMNIROUTE_E2E_BOOTSTRAP_MODE` | `auth` | `scripts/dev/run-next-playwright.mjs` | E2E bootstrap mode (`auth`, `fresh`, `reuse`) for the Playwright runner. |
|
||||
| `OMNIROUTE_E2E_PASSWORD` | falls back to `INITIAL_PASSWORD` | `scripts/dev/run-next-playwright.mjs` | Admin password injected into the Playwright environment. |
|
||||
| `OMNIROUTE_DISABLE_LOCAL_HEALTHCHECK` | `true` | `scripts/dev/run-next-playwright.mjs` | Disable the local healthcheck poll during Playwright runs. |
|
||||
| `OMNIROUTE_DISABLE_TOKEN_HEALTHCHECK` | `true` | `scripts/dev/run-next-playwright.mjs` | Disable the OAuth token healthcheck loop during tests. |
|
||||
| `OMNIROUTE_HIDE_HEALTHCHECK_LOGS` | `true` | `scripts/dev/run-next-playwright.mjs` | Silence healthcheck noise in Playwright stdout. |
|
||||
| `OMNIROUTE_PLAYWRIGHT_SKIP_BUILD` | `0` | `scripts/dev/run-next-playwright.mjs` | Skip the Next.js production build before Playwright starts (CI optimization). |
|
||||
| `OMNIROUTE_SKIP_UNINSTALL_HOOK` | `0` | `scripts/build/uninstall.mjs` | Skip the OmniRoute uninstall hook (used by CI to keep `node_modules` intact). |
|
||||
| `ECOSYSTEM_SERVER_WAIT_MS` | `180000` | `scripts/dev/run-ecosystem-tests.mjs` | Wait time (ms) for the server to become healthy before running ecosystem/protocol tests. |
|
||||
| `ELECTRON_SMOKE_URL` | `http://127.0.0.1:20128/login` | `scripts/dev/smoke-electron-packaged.mjs` | URL the Electron smoke harness expects the packaged app to serve. |
|
||||
| `ELECTRON_SMOKE_TIMEOUT_MS` | `45000` | `scripts/dev/smoke-electron-packaged.mjs` | Total timeout (ms) before the smoke harness gives up. |
|
||||
| `ELECTRON_SMOKE_SETTLE_MS` | `2000` | `scripts/dev/smoke-electron-packaged.mjs` | Settle window (ms) after the page loads. |
|
||||
| `ELECTRON_SMOKE_APP_EXECUTABLE` | _(auto)_ | `scripts/dev/smoke-electron-packaged.mjs` | Explicit path to the packaged Electron executable. |
|
||||
| `ELECTRON_SMOKE_DATA_DIR` | _(tmpdir)_ | `scripts/dev/smoke-electron-packaged.mjs` | Data directory for the Electron smoke run. |
|
||||
| `ELECTRON_SMOKE_KEEP_DATA` | `0` | `scripts/dev/smoke-electron-packaged.mjs` | Set `1` to preserve the smoke data directory after the run. |
|
||||
| `ELECTRON_SMOKE_STREAM_LOGS` | `0` | `scripts/dev/smoke-electron-packaged.mjs` | Set `1` to stream Electron logs to stdout during the run. |
|
||||
| `CLI_DEVIN_BIN` | _(PATH lookup)_ | `open-sse/executors/devin-cli.ts` | Override the Devin CLI binary path. |
|
||||
|
||||
### Docs translation pipeline
|
||||
|
||||
|
||||
1598
electron/package-lock.json
generated
1598
electron/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@
|
||||
"pack": "npm run prepare:bundle && electron-builder --dir"
|
||||
},
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^12.9.0",
|
||||
"better-sqlite3": "^12.10.0",
|
||||
"electron-updater": "^6.8.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -33,7 +33,6 @@
|
||||
"electron-builder": "^26.10.0"
|
||||
},
|
||||
"overrides": {
|
||||
"@xmldom/xmldom": "^0.9.10",
|
||||
"plist": "^4.0.0"
|
||||
},
|
||||
"build": {
|
||||
|
||||
@@ -142,7 +142,7 @@ function clampMaxTokens(value: unknown): number {
|
||||
return Math.max(1, Math.min(Math.floor(numeric), MAX_COMMAND_CODE_TOKENS));
|
||||
}
|
||||
|
||||
function buildCommandCodeBody(model: string, body: unknown): JsonRecord {
|
||||
function buildCommandCodeBody(model: string, body: unknown, stream: boolean): JsonRecord {
|
||||
const input = isRecord(body) ? body : {};
|
||||
const converted = convertMessages(input.messages);
|
||||
const explicitSystem = typeof input.system === "string" ? input.system : "";
|
||||
@@ -169,7 +169,7 @@ function buildCommandCodeBody(model: string, body: unknown): JsonRecord {
|
||||
tools: convertTools(input.tools),
|
||||
system,
|
||||
max_tokens: clampMaxTokens(input.max_tokens ?? input.max_completion_tokens),
|
||||
stream: false,
|
||||
stream,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -512,7 +512,7 @@ export class CommandCodeExecutor extends BaseExecutor {
|
||||
};
|
||||
mergeUpstreamExtraHeaders(headers, upstreamExtraHeaders);
|
||||
|
||||
const transformedBody = buildCommandCodeBody(model, body);
|
||||
const transformedBody = buildCommandCodeBody(model, body, stream);
|
||||
const url = this.buildUrl();
|
||||
const upstream = await fetch(url, {
|
||||
method: "POST",
|
||||
|
||||
169
package-lock.json
generated
169
package-lock.json
generated
@@ -18,9 +18,9 @@
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@ngrok/ngrok": "^1.7.0",
|
||||
"@swc/helpers": "0.5.21",
|
||||
"axios": "^1.16.0",
|
||||
"axios": "^1.16.1",
|
||||
"bcryptjs": "^3.0.3",
|
||||
"better-sqlite3": "^12.9.0",
|
||||
"better-sqlite3": "^12.10.0",
|
||||
"bottleneck": "^2.19.5",
|
||||
"express": "^5.2.1",
|
||||
"fetch-socks": "^1.3.3",
|
||||
@@ -29,17 +29,17 @@
|
||||
"http-proxy-middleware": "^4.0.0",
|
||||
"https-proxy-agent": "^9.0.0",
|
||||
"ioredis": "^5.10.1",
|
||||
"isomorphic-dompurify": "^3.12.0",
|
||||
"isomorphic-dompurify": "^3.13.0",
|
||||
"jose": "^6.2.3",
|
||||
"js-yaml": "^4.1.1",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"lowdb": "^7.0.1",
|
||||
"lucide-react": "^1.14.0",
|
||||
"lucide-react": "^1.16.0",
|
||||
"marked": "^18.0.3",
|
||||
"mermaid": "^11.14.0",
|
||||
"mermaid": "^11.15.0",
|
||||
"monaco-editor": "^0.55.1",
|
||||
"next": "^16.2.6",
|
||||
"next-intl": "^4.11.1",
|
||||
"next-intl": "^4.12.0",
|
||||
"node-machine-id": "^1.1.12",
|
||||
"open": "^11.0.0",
|
||||
"ora": "^9.4.0",
|
||||
@@ -53,7 +53,7 @@
|
||||
"recharts": "^3.8.1",
|
||||
"selfsigned": "^5.5.0",
|
||||
"tls-client-node": "^0.1.13",
|
||||
"tsx": "^4.21.0",
|
||||
"tsx": "^4.21.1",
|
||||
"undici": "^8.2.0",
|
||||
"uuid": "^14.0.0",
|
||||
"wreq-js": "^2.3.0",
|
||||
@@ -67,14 +67,14 @@
|
||||
"omniroute-reset-password": "bin/reset-password.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@playwright/test": "^1.60.0",
|
||||
"@tailwindcss/postcss": "^4.3.0",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@types/bcryptjs": "^3.0.0",
|
||||
"@types/better-sqlite3": "^7.6.13",
|
||||
"@types/keytar": "^4.4.2",
|
||||
"@types/node": "^25.6.2",
|
||||
"@types/node": "^25.7.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
@@ -91,9 +91,9 @@
|
||||
"prettier": "^3.8.3",
|
||||
"tailwindcss": "^4.3.0",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.59.2",
|
||||
"vitest": "^4.1.5",
|
||||
"wait-on": "^9.0.5",
|
||||
"typescript-eslint": "^8.59.3",
|
||||
"vitest": "^4.1.6",
|
||||
"wait-on": "^9.0.10",
|
||||
"wtfnode": "^0.10.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1430,18 +1430,18 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/icu-messageformat-parser": {
|
||||
"version": "3.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.7.tgz",
|
||||
"integrity": "sha512-wJxRZ+SiUCIMTL86bQlZU9bEKDQqqvgk2ezQ1BySUdWRfHqOzj4IKUVFeUZKS9w58M4e7wMSG0Sl86LAPb7Qww==",
|
||||
"version": "3.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.8.tgz",
|
||||
"integrity": "sha512-uZLvzLFN7iV2l8cbDdROwgKGtdELeLI4bpnsuz1DnyscHDxn8TdDE0anHzcfjtWK66XYCllGLV3Mi3CYcEPg/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/icu-skeleton-parser": "2.1.7"
|
||||
"@formatjs/icu-skeleton-parser": "2.1.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/icu-skeleton-parser": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.7.tgz",
|
||||
"integrity": "sha512-cIw1SFP0bi0CUBiJ2jzp99ws3OJNQDfStcHq9Z0iHWzItmiIikihFO+npR8C80yDlp7ZuBCLXCcKjgWjHicksA==",
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.8.tgz",
|
||||
"integrity": "sha512-iX5i0O15gPf69l1WqmLFYwn7wq53lauvytvWFnHamIfX/5Ta56gpFj6fdeHRcKTV58IhrKv8QOvWfTYZYm7f+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/intl-localematcher": {
|
||||
@@ -5626,16 +5626,42 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz",
|
||||
"integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==",
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz",
|
||||
"integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.16.0",
|
||||
"form-data": "^4.0.5",
|
||||
"https-proxy-agent": "^5.0.1",
|
||||
"proxy-from-env": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios/node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios/node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/axobject-query": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||
@@ -5720,9 +5746,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/better-sqlite3": {
|
||||
"version": "12.9.0",
|
||||
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.9.0.tgz",
|
||||
"integrity": "sha512-wqUv4Gm3toFpHDQmaKD4QhZm3g1DjUBI0yzS4UBl6lElUmXFYdTQmmEDpAFa5o8FiFiymURypEnfVHzILKaxqQ==",
|
||||
"version": "12.10.0",
|
||||
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.10.0.tgz",
|
||||
"integrity": "sha512-CyzaZRQKyHkB2ZInfTTl2nvT33EbDpjkLEbE8/Zck3Ll6O0qqvuGdrJ45HgtH+HykRg88ITY3AdreBGN70aBSQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -5730,7 +5756,7 @@
|
||||
"prebuild-install": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20.x || 22.x || 23.x || 24.x || 25.x"
|
||||
"node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x"
|
||||
}
|
||||
},
|
||||
"node_modules/bidi-js": {
|
||||
@@ -7358,9 +7384,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.2.tgz",
|
||||
"integrity": "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==",
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.3.tgz",
|
||||
"integrity": "sha512-VVwJidIJcp1hpg2OMXML3ZVRPYSZiq4aX7qBh83BSIpOaRDqI+qxhXjjIWnpzkOXhmp0L81lnoME1mnCc9H48A==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
@@ -8895,6 +8921,7 @@
|
||||
"version": "4.13.7",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz",
|
||||
"integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"resolve-pkg-maps": "^1.0.0"
|
||||
@@ -9366,9 +9393,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/icu-minify": {
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.11.1.tgz",
|
||||
"integrity": "sha512-C0tsPVuvyNp+++qWJP+mty/KLLStjerOZqu3W1xWLJkChEDbDi9Taoj6blK7L/onxbuVzwgH6k9Sf+rOV6lOvw==",
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.12.0.tgz",
|
||||
"integrity": "sha512-zDmM05uav3t3+kxSfRrNlmyXOdj2b+uHA+p04CG32eJabtaHbugXujuL+YfRkwP9joAnf0Uh+RMGCKD5NLa5rQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -9499,19 +9526,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/intl-messageformat": {
|
||||
"version": "11.2.4",
|
||||
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.4.tgz",
|
||||
"integrity": "sha512-iKP6+uJXn+XcfRgYfGPE3+mqCoODV2vATrXDLo/YkYgIdelJHJPBEbc0GZThipAYPuk+8QJFiPgOfblU085ABg==",
|
||||
"version": "11.2.5",
|
||||
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.5.tgz",
|
||||
"integrity": "sha512-zaROHiUsnlSFXVypU54AsQuAm3DLmmSH8KfDhiUuG1XZ9NTQ4o3xlxIJYVNmeWAklyp3CWg0lhexNUnee8PsYQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "3.1.4",
|
||||
"@formatjs/icu-messageformat-parser": "3.5.7"
|
||||
"@formatjs/fast-memoize": "3.1.5",
|
||||
"@formatjs/icu-messageformat-parser": "3.5.8"
|
||||
}
|
||||
},
|
||||
"node_modules/intl-messageformat/node_modules/@formatjs/fast-memoize": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.4.tgz",
|
||||
"integrity": "sha512-Lbke1aOrsygKKR09Ux0NrZgbTqpDmiwXOgzyDOJ8Owr1zd5qOKTauf62hH+Seeku3ju77rHWH9I5SfX2CN0vuA==",
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.5.tgz",
|
||||
"integrity": "sha512-KLi3fan6WnCHmigd9pmEEN8Hid0v4wiFBW576M/d07KMWYecf1CvyMI3n34vCmHT4AoVqG2n702kiHbXjzZX2A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ioredis": {
|
||||
@@ -9539,9 +9566,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ip-address": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.1.tgz",
|
||||
"integrity": "sha512-1FMu8/N15Ck1BL551Jf42NYIoin2unWjLQ2Fze/DXryJRl5twqtwNHlO39qERGbIOcKYWHdgRryhOC+NG4eaLw==",
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
|
||||
"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
@@ -10170,12 +10197,12 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/isomorphic-dompurify": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-dompurify/-/isomorphic-dompurify-3.12.0.tgz",
|
||||
"integrity": "sha512-8n+j+6ypTHvriJwFOQ2qusQ6bzGjZVcR3jbe1pBpLcGI1dn4WIl0ctLBngqE5QttquQBAlKXwJeTMw+X7x7qKw==",
|
||||
"version": "3.13.0",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-dompurify/-/isomorphic-dompurify-3.13.0.tgz",
|
||||
"integrity": "sha512-QzgzjAGJN0QoOpLWx7mkMhhTQvQXsBpS6oEi2Wy58mEWwrvaRJrx5hrVEdsM70nNKOwHCHj3bwYkwI+HFd3Khg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dompurify": "^3.4.2",
|
||||
"dompurify": "^3.4.3",
|
||||
"jsdom": "^29.1.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -11088,9 +11115,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lucide-react": {
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.14.0.tgz",
|
||||
"integrity": "sha512-+1mdWcfSJVUsaTIjN9zoezmUhfXo5l0vP7ekBMPo3jcS/aIkxHnXqAPsByszMZx/Y8oQBRJxJx5xg+RH3urzxA==",
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.16.0.tgz",
|
||||
"integrity": "sha512-dYwyPzb4MEKpGUmNYk3WKWPnMrHs3FKM+q94kAnJrcDIqqn1hq2xY8scaS2ovsOCM5D51ey2gaRG3PBb1vgoYQ==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
@@ -12101,9 +12128,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/next-intl": {
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.11.1.tgz",
|
||||
"integrity": "sha512-s32lFFLXkxrW6fy+4IVaGD5J8xPpbEDFLfBbXV73CTbHAGhOGMjYN4/rftdsKOQ44AnPhnZ5Et+ZNMr5tRpsqA==",
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.12.0.tgz",
|
||||
"integrity": "sha512-v8KpppWG0yLLlChJ3Of6uoPew9LeRDBAtY6vpJmF7YJmBZlHEzzoEL4w1g1dAU+VleEPNoXNm9hg1eEsKWV5hw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -12115,11 +12142,11 @@
|
||||
"@formatjs/intl-localematcher": "^0.8.1",
|
||||
"@parcel/watcher": "^2.4.1",
|
||||
"@swc/core": "^1.15.2",
|
||||
"icu-minify": "^4.11.1",
|
||||
"icu-minify": "^4.12.0",
|
||||
"negotiator": "^1.0.0",
|
||||
"next-intl-swc-plugin-extractor": "^4.11.1",
|
||||
"next-intl-swc-plugin-extractor": "^4.12.0",
|
||||
"po-parser": "^2.1.1",
|
||||
"use-intl": "^4.11.1"
|
||||
"use-intl": "^4.12.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
|
||||
@@ -12132,9 +12159,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/next-intl-swc-plugin-extractor": {
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.11.1.tgz",
|
||||
"integrity": "sha512-jHKGij7NoYccy2y54+e/wHVMoRgNt4h/Kn0XS9c4GbKu3KgJyANLUN8sFcDixv6sqz4V2kh6CTWgrkIidQksUg==",
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.12.0.tgz",
|
||||
"integrity": "sha512-jUxVEu1Nryjt4YgaDktSys7ioOgQfcNPF/SF2dbPNxbVb6U+P1INRgHeCVN+EC59H2rnTFIQwbddmOCrUWFr3g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/next/node_modules/@swc/helpers": {
|
||||
@@ -12910,9 +12937,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz",
|
||||
"integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",
|
||||
"version": "8.5.14",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz",
|
||||
"integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -13527,6 +13554,7 @@
|
||||
"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"
|
||||
@@ -15003,13 +15031,12 @@
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
|
||||
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.1.tgz",
|
||||
"integrity": "sha512-5QE2Q04cN1u0993w0LT5rPw3faZqZU1fFn1mGE0pV53N1Dn7c+QFFxQu1mBeSgeOXwFyTicZw02wVgp3Tb5cAQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "~0.27.0",
|
||||
"get-tsconfig": "^4.7.5"
|
||||
"esbuild": "~0.27.0"
|
||||
},
|
||||
"bin": {
|
||||
"tsx": "dist/cli.mjs"
|
||||
@@ -15422,9 +15449,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/use-intl": {
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.11.1.tgz",
|
||||
"integrity": "sha512-/dqWSqUSbVMzC+fdy7io8enhGYHeGeHK1bFhTLrp0ZblqdzY4FkE+tkffW6IfCauqaIA2/z4DQae4XEn93+raw==",
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.12.0.tgz",
|
||||
"integrity": "sha512-r+qVb7UI1+kiOhjYsmsNUCY+jrnjVopwGeFlmMyQj4YInlwZzgMeMSv9n8MqnWWy77HL5BVM8K2WgX50SbtcpA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -15435,7 +15462,7 @@
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "^3.1.0",
|
||||
"@schummar/icu-type-parser": "1.21.5",
|
||||
"icu-minify": "^4.11.1",
|
||||
"icu-minify": "^4.12.0",
|
||||
"intl-messageformat": "^11.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
62
package.json
62
package.json
@@ -65,9 +65,9 @@
|
||||
"scripts": {
|
||||
"dev": "node scripts/dev/run-next.mjs dev",
|
||||
"prebuild:docs": "node scripts/docs/generate-docs-index.mjs && node scripts/docs/gen-openapi-module.mjs",
|
||||
"gen:provider-reference": "node --import tsx/esm scripts/docs/gen-provider-reference.ts",
|
||||
"gen:provider-reference": "node --import tsx scripts/docs/gen-provider-reference.ts",
|
||||
"build": "node scripts/build/build-next-isolated.mjs",
|
||||
"build:cli": "node --import tsx/esm scripts/build/prepublish.ts",
|
||||
"build:cli": "node --import tsx scripts/build/prepublish.ts",
|
||||
"start": "node scripts/dev/run-next.mjs start",
|
||||
"lint": "eslint .",
|
||||
"electron:dev": "concurrently \"npm run dev\" \"wait-on http://localhost:20128 && cd electron && npm run dev\"",
|
||||
@@ -76,11 +76,11 @@
|
||||
"electron:build:mac": "npm run build && cd electron && npm run build:mac",
|
||||
"electron:build:linux": "npm run build && cd electron && npm run build:linux",
|
||||
"electron:smoke:packaged": "node scripts/dev/smoke-electron-packaged.mjs",
|
||||
"test": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test --test-concurrency=10 tests/unit/*.test.ts",
|
||||
"test:unit": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test --test-concurrency=10 tests/unit/*.test.ts",
|
||||
"test:plan3": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/plan3-p0.test.ts",
|
||||
"test:fixes": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/fixes-p1.test.ts",
|
||||
"test:security": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/security-fase01.test.ts",
|
||||
"test": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test --test-concurrency=10 tests/unit/*.test.ts",
|
||||
"test:unit": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test --test-concurrency=10 tests/unit/*.test.ts",
|
||||
"test:plan3": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test tests/unit/plan3-p0.test.ts",
|
||||
"test:fixes": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test tests/unit/fixes-p1.test.ts",
|
||||
"test:security": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test tests/unit/security-fase01.test.ts",
|
||||
"check:cycles": "node scripts/check/check-cycles.mjs",
|
||||
"check:route-validation:t06": "node scripts/check/check-route-validation.mjs",
|
||||
"check:any-budget:t11": "node scripts/check/check-t11-any-budget.mjs",
|
||||
@@ -97,21 +97,21 @@
|
||||
"i18n:sync-ui": "node scripts/i18n/sync-ui-keys.mjs",
|
||||
"i18n:sync-ui:dry": "node scripts/i18n/sync-ui-keys.mjs --dry-run",
|
||||
"i18n:check-ui-coverage": "node scripts/i18n/check-ui-keys-coverage.mjs",
|
||||
"check:node-runtime": "node --import tsx/esm scripts/check/check-supported-node-runtime.ts",
|
||||
"check:pack-artifact": "node --import tsx/esm scripts/build/validate-pack-artifact.ts",
|
||||
"check:node-runtime": "node --import tsx scripts/check/check-supported-node-runtime.ts",
|
||||
"check:pack-artifact": "node --import tsx scripts/build/validate-pack-artifact.ts",
|
||||
"audit:deps": "npm audit --audit-level=moderate && npm run audit:electron",
|
||||
"audit:electron": "npm --prefix electron audit --audit-level=moderate",
|
||||
"typecheck:core": "tsc --pretty false -p tsconfig.typecheck-core.json",
|
||||
"typecheck:noimplicit:core": "tsc --pretty false -p tsconfig.typecheck-noimplicit-core.json",
|
||||
"backfill-aggregation": "node --import tsx/esm src/scripts/backfillAggregation.ts",
|
||||
"backfill-aggregation": "node --import tsx src/scripts/backfillAggregation.ts",
|
||||
"env:sync": "node scripts/dev/sync-env.mjs",
|
||||
"test:integration": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test --test-force-exit --test-concurrency=1 tests/integration/*.test.ts",
|
||||
"test:integration": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test --test-force-exit --test-concurrency=1 tests/integration/*.test.ts",
|
||||
"test:e2e": "node scripts/dev/run-playwright-tests.mjs test tests/e2e/*.spec.ts",
|
||||
"test:protocols:e2e": "node scripts/dev/run-protocol-clients-tests.mjs",
|
||||
"test:vitest": "vitest run --config vitest.mcp.config.ts",
|
||||
"test:ecosystem": "node scripts/dev/run-ecosystem-tests.mjs",
|
||||
"test:coverage": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true c8 --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 75 --lines 75 --functions 75 --branches 70 node --import tsx/esm --test --test-concurrency=1 tests/unit/*.test.ts",
|
||||
"test:coverage:legacy": "c8 --output-dir coverage --exclude=open-sse --check-coverage --lines 50 --functions 50 --branches 50 node --import tsx/esm --test tests/unit/*.test.ts",
|
||||
"test:coverage": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true c8 --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 75 --lines 75 --functions 75 --branches 70 node --import tsx --test --test-concurrency=1 tests/unit/*.test.ts",
|
||||
"test:coverage:legacy": "c8 --output-dir coverage --exclude=open-sse --check-coverage --lines 50 --functions 50 --branches 50 node --import tsx --test tests/unit/*.test.ts",
|
||||
"coverage:report": "c8 report --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov",
|
||||
"coverage:summary": "node scripts/check/test-report-summary.mjs --input coverage/coverage-summary.json --output coverage/coverage-report.md --threshold 60",
|
||||
"check:pr-test-policy": "node scripts/check/check-pr-test-policy.mjs",
|
||||
@@ -131,9 +131,9 @@
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@ngrok/ngrok": "^1.7.0",
|
||||
"@swc/helpers": "0.5.21",
|
||||
"axios": "^1.16.0",
|
||||
"axios": "^1.16.1",
|
||||
"bcryptjs": "^3.0.3",
|
||||
"better-sqlite3": "^12.9.0",
|
||||
"better-sqlite3": "^12.10.0",
|
||||
"bottleneck": "^2.19.5",
|
||||
"express": "^5.2.1",
|
||||
"fetch-socks": "^1.3.3",
|
||||
@@ -142,17 +142,17 @@
|
||||
"http-proxy-middleware": "^4.0.0",
|
||||
"https-proxy-agent": "^9.0.0",
|
||||
"ioredis": "^5.10.1",
|
||||
"isomorphic-dompurify": "^3.12.0",
|
||||
"isomorphic-dompurify": "^3.13.0",
|
||||
"jose": "^6.2.3",
|
||||
"js-yaml": "^4.1.1",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"lowdb": "^7.0.1",
|
||||
"lucide-react": "^1.14.0",
|
||||
"lucide-react": "^1.16.0",
|
||||
"marked": "^18.0.3",
|
||||
"mermaid": "^11.14.0",
|
||||
"mermaid": "^11.15.0",
|
||||
"monaco-editor": "^0.55.1",
|
||||
"next": "^16.2.6",
|
||||
"next-intl": "^4.11.1",
|
||||
"next-intl": "^4.12.0",
|
||||
"node-machine-id": "^1.1.12",
|
||||
"open": "^11.0.0",
|
||||
"ora": "^9.4.0",
|
||||
@@ -166,7 +166,7 @@
|
||||
"recharts": "^3.8.1",
|
||||
"selfsigned": "^5.5.0",
|
||||
"tls-client-node": "^0.1.13",
|
||||
"tsx": "^4.21.0",
|
||||
"tsx": "^4.21.1",
|
||||
"undici": "^8.2.0",
|
||||
"uuid": "^14.0.0",
|
||||
"wreq-js": "^2.3.0",
|
||||
@@ -179,14 +179,14 @@
|
||||
"keytar": "^7.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@playwright/test": "^1.60.0",
|
||||
"@tailwindcss/postcss": "^4.3.0",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@types/bcryptjs": "^3.0.0",
|
||||
"@types/better-sqlite3": "^7.6.13",
|
||||
"@types/keytar": "^4.4.2",
|
||||
"@types/node": "^25.6.2",
|
||||
"@types/node": "^25.7.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
@@ -203,9 +203,9 @@
|
||||
"prettier": "^3.8.3",
|
||||
"tailwindcss": "^4.3.0",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.59.2",
|
||||
"vitest": "^4.1.5",
|
||||
"wait-on": "^9.0.5",
|
||||
"typescript-eslint": "^8.59.3",
|
||||
"vitest": "^4.1.6",
|
||||
"wait-on": "^9.0.10",
|
||||
"wtfnode": "^0.10.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
@@ -228,14 +228,8 @@
|
||||
]
|
||||
},
|
||||
"overrides": {
|
||||
"lodash-es": "^4.18.1",
|
||||
"dompurify": "^3.4.2",
|
||||
"path-to-regexp": "^8.4.0",
|
||||
"postcss": "^8.5.10",
|
||||
"ip-address": "10.1.1",
|
||||
"hono": "^4.12.18",
|
||||
"@hono/node-server": "^1.19.13",
|
||||
"react": "$react",
|
||||
"react-dom": "$react-dom"
|
||||
"dompurify": "^3.4.3",
|
||||
"postcss": "^8.5.14",
|
||||
"ip-address": "10.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
"src/shared/contracts/",
|
||||
"src/shared/utils/nodeRuntimeSupport.ts",
|
||||
".env.example",
|
||||
"scripts/postinstall.mjs",
|
||||
"scripts/postinstallSupport.mjs",
|
||||
"scripts/responses-ws-proxy.mjs",
|
||||
"scripts/check-supported-node-runtime.ts",
|
||||
"scripts/sync-env.mjs",
|
||||
"scripts/native-binary-compat.mjs",
|
||||
"scripts/build-next-isolated.mjs",
|
||||
"scripts/build/postinstall.mjs",
|
||||
"scripts/build/postinstallSupport.mjs",
|
||||
"scripts/dev/responses-ws-proxy.mjs",
|
||||
"scripts/check/check-supported-node-runtime.ts",
|
||||
"scripts/dev/sync-env.mjs",
|
||||
"scripts/build/native-binary-compat.mjs",
|
||||
"scripts/build/build-next-isolated.mjs",
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
],
|
||||
@@ -61,54 +61,54 @@
|
||||
},
|
||||
"homepage": "https://omniroute.online",
|
||||
"scripts": {
|
||||
"dev": "node scripts/run-next.mjs dev",
|
||||
"prebuild:docs": "node scripts/generate-docs-index.mjs",
|
||||
"build": "node scripts/build-next-isolated.mjs",
|
||||
"build:cli": "node --import tsx/esm scripts/prepublish.ts",
|
||||
"start": "node scripts/run-next.mjs start",
|
||||
"dev": "node scripts/dev/run-next.mjs dev",
|
||||
"prebuild:docs": "node scripts/docs/generate-docs-index.mjs",
|
||||
"build": "node scripts/build/build-next-isolated.mjs",
|
||||
"build:cli": "node --import tsx scripts/build/prepublish.ts",
|
||||
"start": "node scripts/dev/run-next.mjs start",
|
||||
"lint": "eslint .",
|
||||
"electron:dev": "concurrently \"npm run dev\" \"wait-on http://localhost:20128 && cd electron && npm run dev\"",
|
||||
"electron:build": "npm run build && cd electron && npm run build",
|
||||
"electron:build:win": "npm run build && cd electron && npm run build:win",
|
||||
"electron:build:mac": "npm run build && cd electron && npm run build:mac",
|
||||
"electron:build:linux": "npm run build && cd electron && npm run build:linux",
|
||||
"electron:smoke:packaged": "node scripts/smoke-electron-packaged.mjs",
|
||||
"test": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test --test-concurrency=10 tests/unit/*.test.ts",
|
||||
"test:unit": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test --test-concurrency=10 tests/unit/*.test.ts",
|
||||
"test:plan3": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/plan3-p0.test.ts",
|
||||
"test:fixes": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/fixes-p1.test.ts",
|
||||
"test:security": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/security-fase01.test.ts",
|
||||
"check:cycles": "node scripts/check-cycles.mjs",
|
||||
"check:route-validation:t06": "node scripts/check-route-validation.mjs",
|
||||
"check:any-budget:t11": "node scripts/check-t11-any-budget.mjs",
|
||||
"check:docs-sync": "node scripts/check-docs-sync.mjs",
|
||||
"check:node-runtime": "node --import tsx/esm scripts/check-supported-node-runtime.ts",
|
||||
"check:pack-artifact": "node --import tsx/esm scripts/validate-pack-artifact.ts",
|
||||
"electron:smoke:packaged": "node scripts/dev/smoke-electron-packaged.mjs",
|
||||
"test": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test --test-concurrency=10 tests/unit/*.test.ts",
|
||||
"test:unit": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test --test-concurrency=10 tests/unit/*.test.ts",
|
||||
"test:plan3": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test tests/unit/plan3-p0.test.ts",
|
||||
"test:fixes": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test tests/unit/fixes-p1.test.ts",
|
||||
"test:security": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test tests/unit/security-fase01.test.ts",
|
||||
"check:cycles": "node scripts/check/check-cycles.mjs",
|
||||
"check:route-validation:t06": "node scripts/check/check-route-validation.mjs",
|
||||
"check:any-budget:t11": "node scripts/check/check-t11-any-budget.mjs",
|
||||
"check:docs-sync": "node scripts/check/check-docs-sync.mjs",
|
||||
"check:node-runtime": "node --import tsx scripts/check/check-supported-node-runtime.ts",
|
||||
"check:pack-artifact": "node --import tsx scripts/build/validate-pack-artifact.ts",
|
||||
"audit:deps": "npm audit --audit-level=moderate && npm run audit:electron",
|
||||
"audit:electron": "npm --prefix electron audit --audit-level=moderate",
|
||||
"typecheck:core": "tsc --pretty false -p tsconfig.typecheck-core.json",
|
||||
"typecheck:noimplicit:core": "tsc --pretty false -p tsconfig.typecheck-noimplicit-core.json",
|
||||
"backfill-aggregation": "node --import tsx/esm src/scripts/backfillAggregation.ts",
|
||||
"env:sync": "node scripts/sync-env.mjs",
|
||||
"test:integration": "node --import tsx/esm --test tests/integration/*.test.ts",
|
||||
"test:e2e": "node scripts/run-playwright-tests.mjs test tests/e2e/*.spec.ts",
|
||||
"test:protocols:e2e": "node scripts/run-protocol-clients-tests.mjs",
|
||||
"backfill-aggregation": "node --import tsx src/scripts/backfillAggregation.ts",
|
||||
"env:sync": "node scripts/dev/sync-env.mjs",
|
||||
"test:integration": "node --import tsx --test tests/integration/*.test.ts",
|
||||
"test:e2e": "node scripts/dev/run-playwright-tests.mjs test tests/e2e/*.spec.ts",
|
||||
"test:protocols:e2e": "node scripts/dev/run-protocol-clients-tests.mjs",
|
||||
"test:vitest": "vitest run --config vitest.mcp.config.ts",
|
||||
"test:ecosystem": "node scripts/run-ecosystem-tests.mjs",
|
||||
"test:coverage": "c8 --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 60 --lines 60 --functions 60 --branches 60 node --import tsx/esm --test --test-concurrency=10 tests/unit/*.test.ts",
|
||||
"test:coverage:legacy": "c8 --output-dir coverage --exclude=open-sse --check-coverage --lines 50 --functions 50 --branches 50 node --import tsx/esm --test tests/unit/*.test.ts",
|
||||
"test:ecosystem": "node scripts/dev/run-ecosystem-tests.mjs",
|
||||
"test:coverage": "c8 --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 60 --lines 60 --functions 60 --branches 60 node --import tsx --test --test-concurrency=10 tests/unit/*.test.ts",
|
||||
"test:coverage:legacy": "c8 --output-dir coverage --exclude=open-sse --check-coverage --lines 50 --functions 50 --branches 50 node --import tsx --test tests/unit/*.test.ts",
|
||||
"coverage:report": "c8 report --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov",
|
||||
"coverage:summary": "node scripts/test-report-summary.mjs --input coverage/coverage-summary.json --output coverage/coverage-report.md --threshold 60",
|
||||
"check:pr-test-policy": "node scripts/check-pr-test-policy.mjs",
|
||||
"coverage:summary": "node scripts/check/test-report-summary.mjs --input coverage/coverage-summary.json --output coverage/coverage-report.md --threshold 60",
|
||||
"check:pr-test-policy": "node scripts/check/check-pr-test-policy.mjs",
|
||||
"coverage:report:legacy": "c8 report --output-dir coverage --exclude=open-sse --reporter=text --reporter=text-summary",
|
||||
"test:all": "npm run test:unit && npm run test:vitest && npm run test:ecosystem && npm run test:e2e",
|
||||
"check": "npm run lint && npm run test",
|
||||
"prepublishOnly": "npm run build:cli && npm run check:pack-artifact",
|
||||
"postinstall": "node scripts/postinstall.mjs",
|
||||
"uninstall": "node scripts/uninstall.mjs",
|
||||
"uninstall:full": "node scripts/uninstall.mjs --full",
|
||||
"postinstall": "node scripts/build/postinstall.mjs",
|
||||
"uninstall": "node scripts/build/uninstall.mjs",
|
||||
"uninstall:full": "node scripts/build/uninstall.mjs --full",
|
||||
"prepare": "husky",
|
||||
"system-info": "node scripts/system-info.mjs"
|
||||
"system-info": "node scripts/dev/system-info.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lobehub/icons": "^5.8.0",
|
||||
@@ -116,26 +116,26 @@
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@ngrok/ngrok": "^1.7.0",
|
||||
"@swc/helpers": "0.5.21",
|
||||
"axios": "^1.16.0",
|
||||
"axios": "^1.16.1",
|
||||
"bcryptjs": "^3.0.3",
|
||||
"better-sqlite3": "^12.9.0",
|
||||
"better-sqlite3": "^12.10.0",
|
||||
"bottleneck": "^2.19.5",
|
||||
"express": "^5.2.1",
|
||||
"fetch-socks": "^1.3.3",
|
||||
"fuse.js": "^7.3.0",
|
||||
"http-proxy-middleware": "^3.0.5",
|
||||
"https-proxy-agent": "^9.0.0",
|
||||
"isomorphic-dompurify": "^3.12.0",
|
||||
"isomorphic-dompurify": "^3.13.0",
|
||||
"jose": "^6.2.3",
|
||||
"js-yaml": "^4.1.1",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"lowdb": "^7.0.1",
|
||||
"lucide-react": "^1.14.0",
|
||||
"lucide-react": "^1.16.0",
|
||||
"marked": "^18.0.3",
|
||||
"mermaid": "^11.14.0",
|
||||
"mermaid": "^11.15.0",
|
||||
"monaco-editor": "^0.55.1",
|
||||
"next": "^16.2.6",
|
||||
"next-intl": "^4.11.1",
|
||||
"next-intl": "^4.12.0",
|
||||
"node-machine-id": "^1.1.12",
|
||||
"open": "^11.0.0",
|
||||
"ora": "^9.4.0",
|
||||
@@ -149,7 +149,7 @@
|
||||
"recharts": "^3.8.1",
|
||||
"selfsigned": "^5.5.0",
|
||||
"tls-client-node": "^0.1.13",
|
||||
"tsx": "^4.21.0",
|
||||
"tsx": "^4.21.1",
|
||||
"undici": "^8.2.0",
|
||||
"uuid": "^14.0.0",
|
||||
"wreq-js": "^2.3.0",
|
||||
@@ -162,14 +162,14 @@
|
||||
"keytar": "^7.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@playwright/test": "^1.60.0",
|
||||
"@tailwindcss/postcss": "^4.3.0",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@types/bcryptjs": "^3.0.0",
|
||||
"@types/better-sqlite3": "^7.6.13",
|
||||
"@types/keytar": "^4.4.2",
|
||||
"@types/node": "^25.6.2",
|
||||
"@types/node": "^25.7.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
@@ -187,9 +187,9 @@
|
||||
"prettier": "^3.8.3",
|
||||
"tailwindcss": "^4.3.0",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.59.2",
|
||||
"vitest": "^4.1.5",
|
||||
"wait-on": "^9.0.5",
|
||||
"typescript-eslint": "^8.59.3",
|
||||
"vitest": "^4.1.6",
|
||||
"wait-on": "^9.0.10",
|
||||
"wtfnode": "^0.10.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
@@ -212,14 +212,8 @@
|
||||
]
|
||||
},
|
||||
"overrides": {
|
||||
"lodash-es": "^4.18.1",
|
||||
"dompurify": "^3.4.2",
|
||||
"path-to-regexp": "^8.4.0",
|
||||
"postcss": "^8.5.10",
|
||||
"ip-address": "10.1.1",
|
||||
"hono": "^4.12.18",
|
||||
"@hono/node-server": "^1.19.13",
|
||||
"react": "$react",
|
||||
"react-dom": "$react-dom"
|
||||
"dompurify": "^3.4.3",
|
||||
"postcss": "^8.5.14",
|
||||
"ip-address": "10.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
* cursor-tap — capture cursor agent.v1.AgentService/Run wire bytes for tests.
|
||||
*
|
||||
* Usage:
|
||||
* CURSOR_TOKEN=... node scripts/cursor-tap.cjs <fixture-name> <prompt>
|
||||
* CURSOR_TOKEN=... node scripts/ad-hoc/cursor-tap.cjs <fixture-name> <prompt>
|
||||
*
|
||||
* Examples:
|
||||
* node scripts/cursor-tap.cjs single-turn-chat "say only PING"
|
||||
* node scripts/cursor-tap.cjs system-prompt "be brief|hi" # split on first '|'
|
||||
* node scripts/cursor-tap.cjs tool-call "weather in Paris" --tools=get_weather
|
||||
* node scripts/cursor-tap.cjs composer-2-fast "hi" --model=composer-2-fast
|
||||
* node scripts/ad-hoc/cursor-tap.cjs single-turn-chat "say only PING"
|
||||
* node scripts/ad-hoc/cursor-tap.cjs system-prompt "be brief|hi" # split on first '|'
|
||||
* node scripts/ad-hoc/cursor-tap.cjs tool-call "weather in Paris" --tools=get_weather
|
||||
* node scripts/ad-hoc/cursor-tap.cjs composer-2-fast "hi" --model=composer-2-fast
|
||||
*
|
||||
* Writes the upstream response bytes to tests/fixtures/cursor/<fixture-name>.bin
|
||||
* and prints decoded summary to stdout. Use these fixtures in unit tests to
|
||||
@@ -27,7 +27,9 @@ const crypto = require("crypto");
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length < 2) {
|
||||
console.error("Usage: cursor-tap.cjs <fixture-name> <prompt> [--model=...] [--tools=name1,name2]");
|
||||
console.error(
|
||||
"Usage: cursor-tap.cjs <fixture-name> <prompt> [--model=...] [--tools=name1,name2]"
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ async function main() {
|
||||
};
|
||||
|
||||
if (!(await isServerReady())) {
|
||||
serverProcess = spawn(process.execPath, ["scripts/run-next-playwright.mjs", "dev"], {
|
||||
serverProcess = spawn(process.execPath, ["scripts/dev/run-next-playwright.mjs", "dev"], {
|
||||
stdio: "inherit",
|
||||
env: testEnv,
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ const backupDir = resolvePlaywrightAppBackupDir({
|
||||
appDirExists: existsSync(appDir),
|
||||
});
|
||||
const usingAlternativeBackupDir = backupDir !== defaultBackupDir;
|
||||
const buildScript = join(cwd, "scripts", "build-next-isolated.mjs");
|
||||
const buildScript = join(cwd, "scripts", "build", "build-next-isolated.mjs");
|
||||
const standaloneServer = join(cwd, testDistDir(), "standalone", "server.js");
|
||||
const rootStaticDir = join(cwd, testDistDir(), "static");
|
||||
const rootPublicDir = join(cwd, "public");
|
||||
|
||||
@@ -60,7 +60,7 @@ async function main() {
|
||||
};
|
||||
|
||||
if (!(await isServerReady())) {
|
||||
serverProcess = spawn(process.execPath, ["scripts/run-next-playwright.mjs", "dev"], {
|
||||
serverProcess = spawn(process.execPath, ["scripts/dev/run-next-playwright.mjs", "dev"], {
|
||||
stdio: "inherit",
|
||||
env: testEnv,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
// Generates docs/reference/PROVIDER_REFERENCE.md from src/shared/constants/providers.ts.
|
||||
// Run: node --import tsx/esm scripts/docs/gen-provider-reference.ts
|
||||
// Run: node --import tsx scripts/docs/gen-provider-reference.ts
|
||||
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import matter from "gray-matter";
|
||||
import { format } from "prettier";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
@@ -36,6 +37,12 @@ const SECTION_ORDER = [
|
||||
|
||||
const SECTION_INDEX = Object.fromEntries(SECTION_ORDER.map((s, i) => [s.title, i + 1]));
|
||||
|
||||
async function writeGeneratedFile(content) {
|
||||
fs.mkdirSync(path.dirname(OUT_FILE), { recursive: true });
|
||||
const formatted = await format(content, { parser: "typescript", printWidth: 100 });
|
||||
fs.writeFileSync(OUT_FILE, formatted, "utf8");
|
||||
}
|
||||
|
||||
function extractTitleFromContent(content) {
|
||||
const match = content.match(/^#\s+(.+)$/m);
|
||||
if (match) {
|
||||
@@ -72,10 +79,8 @@ function extractContentPreview(content) {
|
||||
return stripped.slice(0, 300);
|
||||
}
|
||||
|
||||
function emitEmpty(reason) {
|
||||
fs.mkdirSync(path.dirname(OUT_FILE), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
OUT_FILE,
|
||||
async function emitEmpty(reason) {
|
||||
await writeGeneratedFile(
|
||||
`// AUTO-GENERATED by scripts/docs/generate-docs-index.mjs — DO NOT EDIT MANUALLY
|
||||
// Regenerate with: node scripts/docs/generate-docs-index.mjs
|
||||
|
||||
@@ -104,8 +109,7 @@ export const autoNavSections: AutoGenNavSection[] = [];
|
||||
export const autoSearchIndex: AutoGenSearchItem[] = [];
|
||||
|
||||
export const autoAllSlugs: string[] = [];
|
||||
`,
|
||||
"utf8"
|
||||
`
|
||||
);
|
||||
console.warn(`[generate-docs-index] ${reason}; generated empty docs index.`);
|
||||
}
|
||||
@@ -119,7 +123,7 @@ if (!fs.existsSync(DOCS_DIR)) {
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
emitEmpty(`${DOCS_DIR} not found`);
|
||||
await emitEmpty(`${DOCS_DIR} not found`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -168,7 +172,7 @@ for (const { dir, title } of SECTION_ORDER) {
|
||||
}
|
||||
|
||||
if (docs.length === 0) {
|
||||
emitEmpty("no docs discovered in subfolders");
|
||||
await emitEmpty("no docs discovered in subfolders");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -258,5 +262,5 @@ export const autoAllSlugs: string[] = ${JSON.stringify(
|
||||
)};
|
||||
`;
|
||||
|
||||
fs.writeFileSync(OUT_FILE, output, "utf8");
|
||||
await writeGeneratedFile(output);
|
||||
console.log(`✅ Generated ${OUT_FILE} with ${docs.length} docs, ${navSections.length} sections`);
|
||||
|
||||
@@ -357,7 +357,7 @@ function ConnectionCooldownCard({
|
||||
/>
|
||||
<BooleanField
|
||||
label="Use upstream retry hints"
|
||||
description="Usa valores de retry-after/reset do upstream quando disponíveis."
|
||||
description="Use upstream retry-after/reset values when available."
|
||||
checked={current.useUpstreamRetryHints}
|
||||
onChange={(useUpstreamRetryHints) =>
|
||||
setDraft((prev) => ({
|
||||
@@ -409,7 +409,7 @@ function ConnectionCooldownCard({
|
||||
</p>
|
||||
</div>
|
||||
<NumberField
|
||||
label="Máximo de passos de backoff"
|
||||
label="Max backoff steps"
|
||||
value={current.maxBackoffSteps}
|
||||
min={0}
|
||||
onChange={(maxBackoffSteps) =>
|
||||
@@ -424,9 +424,9 @@ function ConnectionCooldownCard({
|
||||
<span className="font-mono text-text-main">{formatMs(current.baseCooldownMs)}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-sm">
|
||||
<span className="text-text-muted">Usar dicas de retry do upstream</span>
|
||||
<span className="text-text-muted">Use upstream retry hints</span>
|
||||
<span className="font-mono text-text-main">
|
||||
{current.useUpstreamRetryHints ? "Sim" : "Não"}
|
||||
{current.useUpstreamRetryHints ? "Yes" : "No"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-sm">
|
||||
@@ -440,7 +440,7 @@ function ConnectionCooldownCard({
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-sm">
|
||||
<span className="text-text-muted">Máximo de passos de backoff</span>
|
||||
<span className="text-text-muted">Max backoff steps</span>
|
||||
<span className="font-mono text-text-main">{current.maxBackoffSteps}</span>
|
||||
</div>
|
||||
</>
|
||||
@@ -455,12 +455,12 @@ function ConnectionCooldownCard({
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="material-symbols-outlined text-xl text-primary">timer_off</span>
|
||||
<h2 className="text-lg font-bold">Cooldown de Conexão</h2>
|
||||
<h2 className="text-lg font-bold">Connection Cooldown</h2>
|
||||
</div>
|
||||
<SectionDescription
|
||||
scope="Conexão individual"
|
||||
trigger="Quando uma conexão retorna falha transitória no upstream"
|
||||
effect="Pula temporariamente essa conexão e aumenta backoff em falhas repetidas"
|
||||
scope="Individual connection"
|
||||
trigger="When a connection returns a transient upstream failure"
|
||||
effect="Temporarily skips that connection and increases backoff after repeated failures"
|
||||
/>
|
||||
</div>
|
||||
<ActionRow
|
||||
@@ -498,13 +498,13 @@ function ConnectionCooldownCard({
|
||||
</div>
|
||||
|
||||
<p className="mb-4 text-sm text-text-muted">
|
||||
O cooldown base cobre falhas transitórias de conexão. Quando as dicas de retry do upstream
|
||||
estão ativas, a janela explícita do provedor sobrescreve o cooldown local.
|
||||
Base cooldown covers transient connection failures. When upstream retry hints are enabled,
|
||||
the provider's explicit retry window overrides the local cooldown.
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
{renderProfile("oauth", "Provedores OAuth", "lock")}
|
||||
{renderProfile("apikey", "Provedores API Key", "key")}
|
||||
{renderProfile("oauth", "OAuth Providers", "lock")}
|
||||
{renderProfile("apikey", "API Key Providers", "key")}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import path from "node:path";
|
||||
import os from "node:os";
|
||||
|
||||
import { generateClaudeConfig } from "./claude";
|
||||
import { generateClineConfig } from "./cline";
|
||||
import { generateCodexConfig } from "./codex";
|
||||
import { generateContinueConfig } from "./continue";
|
||||
import { generateKilocodeConfig } from "./kilocode";
|
||||
import { generateOpencodeConfig } from "./opencode";
|
||||
|
||||
export interface GenerateOptions {
|
||||
baseUrl: string;
|
||||
apiKey: string;
|
||||
@@ -37,21 +44,16 @@ const TOOL_CONFIG_PATHS: Record<string, string> = {
|
||||
continue: path.join(os.homedir(), ".continue", "config.yaml"),
|
||||
};
|
||||
|
||||
async function importGenerator(toolId: string) {
|
||||
const generators: Record<string, { module: string; export: string }> = {
|
||||
claude: { module: "./claude.js", export: "generateClaudeConfig" },
|
||||
codex: { module: "./codex.js", export: "generateCodexConfig" },
|
||||
opencode: { module: "./opencode.js", export: "generateOpencodeConfig" },
|
||||
cline: { module: "./cline.js", export: "generateClineConfig" },
|
||||
kilocode: { module: "./kilocode.js", export: "generateKilocodeConfig" },
|
||||
continue: { module: "./continue.js", export: "generateContinueConfig" },
|
||||
};
|
||||
type ConfigGenerator = (options: GenerateOptions) => string | Promise<string>;
|
||||
|
||||
const gen = generators[toolId];
|
||||
if (!gen) return null;
|
||||
const mod = await import(gen.module);
|
||||
return { generate: mod[gen.export] };
|
||||
}
|
||||
const GENERATORS: Record<string, ConfigGenerator> = {
|
||||
claude: generateClaudeConfig,
|
||||
codex: generateCodexConfig,
|
||||
opencode: generateOpencodeConfig,
|
||||
cline: generateClineConfig,
|
||||
kilocode: generateKilocodeConfig,
|
||||
continue: generateContinueConfig,
|
||||
};
|
||||
|
||||
export async function generateConfig(
|
||||
toolId: string,
|
||||
@@ -70,11 +72,11 @@ export async function generateConfig(
|
||||
}
|
||||
|
||||
try {
|
||||
const mod = await importGenerator(toolId);
|
||||
if (!mod) {
|
||||
const generate = GENERATORS[toolId];
|
||||
if (!generate) {
|
||||
return { success: false, configPath: "", error: `Unknown tool: ${toolId}` };
|
||||
}
|
||||
const content = await mod.generate(options);
|
||||
const content = await generate(options);
|
||||
const configPath = TOOL_CONFIG_PATHS[toolId] || "";
|
||||
return { success: true, configPath, content };
|
||||
} catch (err) {
|
||||
|
||||
@@ -2,10 +2,28 @@
|
||||
import React from "react";
|
||||
import { act } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const cleanupCallbacks: Array<() => void> = [];
|
||||
|
||||
function createTestStorage(): Storage {
|
||||
const entries = new Map<string, string>();
|
||||
return {
|
||||
get length() {
|
||||
return entries.size;
|
||||
},
|
||||
clear: () => entries.clear(),
|
||||
getItem: (key) => entries.get(key) ?? null,
|
||||
key: (index) => Array.from(entries.keys())[index] ?? null,
|
||||
removeItem: (key) => {
|
||||
entries.delete(key);
|
||||
},
|
||||
setItem: (key, value) => {
|
||||
entries.set(key, value);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function makeContainer(): HTMLElement {
|
||||
const container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
@@ -20,6 +38,7 @@ describe("AutoRoutingBanner", () => {
|
||||
(
|
||||
globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
|
||||
).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
vi.stubGlobal("localStorage", createTestStorage());
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
@@ -29,6 +48,7 @@ describe("AutoRoutingBanner", () => {
|
||||
}
|
||||
document.body.innerHTML = "";
|
||||
localStorage.clear();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it("renders banner on first mount", async () => {
|
||||
|
||||
@@ -100,7 +100,7 @@ describe("Protocol clients E2E", () => {
|
||||
async () => {
|
||||
const transport = new StdioClientTransport({
|
||||
command: process.execPath,
|
||||
args: ["--import", "tsx/esm", "open-sse/mcp-server/server.ts"],
|
||||
args: ["--import", "tsx", "open-sse/mcp-server/server.ts"],
|
||||
env: {
|
||||
...process.env,
|
||||
OMNIROUTE_BASE_URL: BASE_URL,
|
||||
|
||||
@@ -305,13 +305,14 @@ test.describe("Resilience Plan Alignment", () => {
|
||||
await mockResilienceSettings(page);
|
||||
|
||||
await gotoDashboardRoute(page, "/dashboard/settings?tab=resilience");
|
||||
const resiliencePanel = page.getByRole("tabpanel", { name: "Resilience" });
|
||||
await expect(
|
||||
page.getByRole("heading", { name: "Connection Cooldown", exact: true })
|
||||
resiliencePanel.getByRole("heading", { name: "Connection Cooldown", exact: true })
|
||||
).toBeVisible({ timeout: 15000 });
|
||||
await expect(page.getByText("Base cooldown", { exact: true }).first()).toBeVisible();
|
||||
await expect(page.getByText("Use upstream retry hints", { exact: true }).first()).toBeVisible();
|
||||
await expect(page.getByText("Max backoff steps", { exact: true }).first()).toBeVisible();
|
||||
await expect(page.getByText(/Rate-limit fallback/i)).toHaveCount(0);
|
||||
await expect(resiliencePanel.getByText(/Cooldown base\s*60000ms/)).toBeVisible();
|
||||
await expect(resiliencePanel.getByText(/Use upstream retry hints\s*No/)).toBeVisible();
|
||||
await expect(resiliencePanel.getByText(/Max backoff steps\s*8/)).toBeVisible();
|
||||
await expect(resiliencePanel.getByText(/Rate-limit fallback/i)).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("health page renders provider breaker runtime state for multiple providers", async ({
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* To run:
|
||||
* CURSOR_E2E_TOKEN=$(cat ~/.cursor/access-token) \
|
||||
* node --import tsx/esm --test tests/integration/cursor-e2e.test.ts
|
||||
* node --import tsx --test tests/integration/cursor-e2e.test.ts
|
||||
*
|
||||
* Capturing wire fixtures (separate workflow):
|
||||
* CURSOR_TOKEN=... node scripts/ad-hoc/cursor-tap.cjs single-turn-chat "say PING"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Tests bulk data operations against acceptable time thresholds.
|
||||
* Thresholds are 2x the expected target to account for slow CI machines.
|
||||
*
|
||||
* Run: node --import tsx/esm --test tests/integration/performance-regression.test.ts
|
||||
* Run: node --import tsx --test tests/integration/performance-regression.test.ts
|
||||
*/
|
||||
|
||||
import { describe, it, before, after } from "node:test";
|
||||
|
||||
@@ -4,6 +4,7 @@ import assert from "node:assert/strict";
|
||||
import { createChatPipelineHarness } from "../integration/_chatPipelineHarness.ts";
|
||||
|
||||
process.env.STREAM_IDLE_TIMEOUT_MS = "50";
|
||||
process.env.STREAM_READINESS_TIMEOUT_MS = "50";
|
||||
|
||||
const harness = await createChatPipelineHarness("chat-cooldown-aware-retry");
|
||||
const auth = await import("../../src/sse/services/auth.ts");
|
||||
@@ -241,53 +242,41 @@ test("handleChat returns model_cooldown when every credential for the requested
|
||||
assert.ok(Number(response.headers.get("Retry-After")) >= 1);
|
||||
});
|
||||
|
||||
test("handleChat returns stream readiness timeout without entering cooldown-aware retry or account lockout", async (t) => {
|
||||
t.mock.timers.enable({ apis: ["setTimeout"] });
|
||||
try {
|
||||
const connection = await seedConnection("openai", {
|
||||
apiKey: "sk-openai-stream-readiness-timeout",
|
||||
});
|
||||
await settingsDb.updateSettings({
|
||||
requestRetry: 1,
|
||||
maxRetryIntervalSec: 10,
|
||||
});
|
||||
test("handleChat returns stream readiness timeout without entering cooldown-aware retry or account lockout", async () => {
|
||||
const connection = await seedConnection("openai", {
|
||||
apiKey: "sk-openai-stream-readiness-timeout",
|
||||
});
|
||||
await settingsDb.updateSettings({
|
||||
requestRetry: 1,
|
||||
maxRetryIntervalSec: 10,
|
||||
});
|
||||
|
||||
let fetchCalls = 0;
|
||||
globalThis.fetch = async () => {
|
||||
fetchCalls += 1;
|
||||
return buildZombieSseResponse();
|
||||
};
|
||||
let fetchCalls = 0;
|
||||
globalThis.fetch = async () => {
|
||||
fetchCalls += 1;
|
||||
return buildZombieSseResponse();
|
||||
};
|
||||
|
||||
const responsePromise = handleChat(
|
||||
buildRequest({
|
||||
body: {
|
||||
model: "openai/gpt-4o-mini",
|
||||
stream: true,
|
||||
messages: [{ role: "user", content: "trigger zombie stream" }],
|
||||
},
|
||||
})
|
||||
);
|
||||
const response = await handleChat(
|
||||
buildRequest({
|
||||
body: {
|
||||
model: "openai/gpt-4o-mini",
|
||||
stream: true,
|
||||
messages: [{ role: "user", content: "trigger zombie stream" }],
|
||||
},
|
||||
})
|
||||
);
|
||||
const body = (await response.json()) as any;
|
||||
|
||||
// Give the async pipeline a chance to settle and start the fetch
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
// Fast-forward past the default 30s stream readiness timeout
|
||||
t.mock.timers.tick(30500);
|
||||
assert.equal(response.status, 504);
|
||||
assert.equal(fetchCalls, 1);
|
||||
assert.equal(body.error.code, "STREAM_READINESS_TIMEOUT");
|
||||
|
||||
const response = await responsePromise;
|
||||
const body = (await response.json()) as any;
|
||||
|
||||
assert.equal(response.status, 504);
|
||||
assert.equal(fetchCalls, 1);
|
||||
assert.equal(body.error.code, "STREAM_READINESS_TIMEOUT");
|
||||
|
||||
const refreshedConnection = (await getProviderConnectionById((connection as any).id)) as any;
|
||||
assert.equal(refreshedConnection.testStatus, "active");
|
||||
assert.ok(refreshedConnection.rateLimitedUntil == null);
|
||||
assert.ok(refreshedConnection.errorCode == null);
|
||||
assert.equal(refreshedConnection.backoffLevel, 0);
|
||||
} finally {
|
||||
t.mock.timers.reset();
|
||||
}
|
||||
const refreshedConnection = (await getProviderConnectionById((connection as any).id)) as any;
|
||||
assert.equal(refreshedConnection.testStatus, "active");
|
||||
assert.ok(refreshedConnection.rateLimitedUntil == null);
|
||||
assert.ok(refreshedConnection.errorCode == null);
|
||||
assert.equal(refreshedConnection.backoffLevel, 0);
|
||||
});
|
||||
|
||||
test("handleChat aborts the pending cooldown wait when the client disconnects", async () => {
|
||||
|
||||
@@ -140,13 +140,16 @@ test("Command Code executor posts wrapped body and required headers to alpha/gen
|
||||
});
|
||||
|
||||
test("Command Code raw NDJSON stream becomes OpenAI chat SSE chunks", async () => {
|
||||
globalThis.fetch = async () =>
|
||||
commandCodeStream([
|
||||
const calls: any[] = [];
|
||||
globalThis.fetch = async (url, init = {}) => {
|
||||
calls.push({ url: String(url), init, body: JSON.parse(String(init.body)) });
|
||||
return commandCodeStream([
|
||||
{ type: "text-delta", text: "Hello" },
|
||||
{ type: "reasoning-delta", text: "thinking" },
|
||||
{ type: "tool-call", toolCallId: "call_1", toolName: "search", input: { q: "docs" } },
|
||||
{ type: "finish", finishReason: "tool-calls" },
|
||||
]);
|
||||
};
|
||||
|
||||
const { response } = await getExecutor("command-code").execute({
|
||||
model: "gpt-5.4",
|
||||
@@ -155,6 +158,7 @@ test("Command Code raw NDJSON stream becomes OpenAI chat SSE chunks", async () =
|
||||
body: { messages: [{ role: "user", content: "Hi" }] },
|
||||
});
|
||||
|
||||
assert.equal(calls[0].body.params.stream, true);
|
||||
assert.equal(response.headers.get("Content-Type"), "text/event-stream; charset=utf-8");
|
||||
const sse = await response.text();
|
||||
assert.match(sse, /data: \[DONE\]/);
|
||||
|
||||
@@ -85,6 +85,9 @@ test("machineId: falls back to Linux machine-id files before hostname", async ()
|
||||
|
||||
fs.existsSync = () => false;
|
||||
fs.readFileSync = (filePath, encoding) => {
|
||||
if (filePath !== "/etc/machine-id") {
|
||||
return originalReadFileSync(filePath, encoding);
|
||||
}
|
||||
assert.equal(filePath, "/etc/machine-id");
|
||||
assert.equal(encoding, "utf8");
|
||||
return "LINUX-MACHINE-ID\n";
|
||||
|
||||
@@ -2,10 +2,28 @@
|
||||
import React from "react";
|
||||
import { act } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const cleanupCallbacks: Array<() => void> = [];
|
||||
|
||||
function createTestStorage(): Storage {
|
||||
const entries = new Map<string, string>();
|
||||
return {
|
||||
get length() {
|
||||
return entries.size;
|
||||
},
|
||||
clear: () => entries.clear(),
|
||||
getItem: (key) => entries.get(key) ?? null,
|
||||
key: (index) => Array.from(entries.keys())[index] ?? null,
|
||||
removeItem: (key) => {
|
||||
entries.delete(key);
|
||||
},
|
||||
setItem: (key, value) => {
|
||||
entries.set(key, value);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function makeContainer(): HTMLElement {
|
||||
const container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
@@ -20,6 +38,7 @@ describe("AutoRoutingBanner", () => {
|
||||
(
|
||||
globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
|
||||
).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
vi.stubGlobal("localStorage", createTestStorage());
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
@@ -29,6 +48,7 @@ describe("AutoRoutingBanner", () => {
|
||||
}
|
||||
document.body.innerHTML = "";
|
||||
localStorage.clear();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it("renders banner on first mount", async () => {
|
||||
|
||||
@@ -10,6 +10,23 @@ function decodeChunk(value) {
|
||||
return typeof value === "string" ? value : new TextDecoder().decode(value);
|
||||
}
|
||||
|
||||
async function readWithTimeout(reader, timeoutMs = 250) {
|
||||
let timeout;
|
||||
try {
|
||||
return await Promise.race([
|
||||
reader.read(),
|
||||
new Promise((_, reject) => {
|
||||
timeout = setTimeout(
|
||||
() => reject(new Error("Timed out waiting for SSE heartbeat")),
|
||||
timeoutMs
|
||||
);
|
||||
}),
|
||||
]);
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
test("integration: anthropic-ping heartbeat reaches downstream and does NOT trigger stream.ts strip", async () => {
|
||||
// Build a fake upstream that emits one chunk then idles indefinitely
|
||||
let cancelled = false;
|
||||
@@ -39,7 +56,7 @@ test("integration: anthropic-ping heartbeat reaches downstream and does NOT trig
|
||||
const startedAt = Date.now();
|
||||
let sawPing = false;
|
||||
while (Date.now() - startedAt < 200) {
|
||||
const { value, done } = await reader.read();
|
||||
const { value, done } = await readWithTimeout(reader);
|
||||
if (done) break;
|
||||
const chunk = decodeChunk(value);
|
||||
if (/^event: ping\b/m.test(chunk)) {
|
||||
@@ -83,7 +100,7 @@ test("integration: openai-chunk heartbeat is valid JSON parseable by SDKs", asyn
|
||||
const startedAt = Date.now();
|
||||
let sawValidChunk = false;
|
||||
while (Date.now() - startedAt < 200) {
|
||||
const { value, done } = await reader.read();
|
||||
const { value, done } = await readWithTimeout(reader);
|
||||
if (done) break;
|
||||
const chunk = decodeChunk(value);
|
||||
if (chunk.startsWith("data: ") && chunk.includes("omniroute-keepalive")) {
|
||||
@@ -118,7 +135,7 @@ test("integration: shapeForClientFormat + createSseHeartbeatTransform pipeline (
|
||||
|
||||
const reader = upstream.pipeThrough(transform).getReader();
|
||||
await reader.read(); // first real
|
||||
const { value } = await reader.read();
|
||||
const { value } = await readWithTimeout(reader);
|
||||
assert.match(decodeChunk(value), /^event: ping\ndata: \{\}\n\n$/);
|
||||
await reader.cancel();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user